You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tderadio/src/stationlist.cpp

495 lines
14 KiB

/***************************************************************************
stationlist.cpp - description
-------------------
begin : Sat March 29 2003
copyright : (C) 2003 by Klas Kalass, Ernst Martin Witte
email : klas@kde.org, witte@kawo1.rwth-aachen.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "include/radiostation.h"
#include "include/errorlog-interfaces.h"
#include "include/utils.h"
#include "include/stationlist.h"
#include "include/stationlistxmlhandler.h"
#include "include/tderadioversion.h"
#include <tqstring.h>
#include <tqfile.h>
#include <tqiodevice.h>
#include <tqmessagebox.h>
#include <tdeio/netaccess.h>
#include <tdetempfile.h>
#include <tdelocale.h>
//////////////////////////////////////////////////////////////////////////////
const KDE_EXPORT StationList emptyStationList;
//////////////////////////////////////////////////////////////////////////////
RawStationList::RawStationList ()
{
setAutoDelete(true);
}
RawStationList::RawStationList (const RawStationList &sl)
: TQPtrList<RadioStation>(sl)
{
setAutoDelete(true);
}
RawStationList::~RawStationList ()
{
clear();
}
TQPtrCollection::Item RawStationList::newItem (TQPtrCollection::Item s)
{
if (s)
return ((RadioStation*)s)->copy();
else
return NULL;
}
void RawStationList::deleteItem (TQPtrCollection::Item s)
{
if (autoDelete())
delete (RadioStation*)s;
}
int RawStationList::compareItems(TQPtrCollection::Item a, TQPtrCollection::Item b)
{
if (!a && !b)
return 0;
if (!a)
return -1;
if (!b)
return 1;
return ((RadioStation*)a)->compare(*(RadioStation*)b);
}
bool RawStationList::insert (uint index, const RadioStation * item )
{
if (!item) return false;
RadioStation *rs = &stationWithID(item->stationID());
bool r = true;
if (rs != item) {
r = BaseClass::insert(index, item);
removeRef(rs);
}
return r;
}
bool RawStationList::insert (const RadioStation * item )
{
if (!item) return false;
int idx = idxWithID(item->stationID());
if (idx >= 0) {
return replace(idx, item);
} else {
append(item);
return true;
}
}
void RawStationList::inSort ( const RadioStation * item )
{
if (!item) return;
RadioStation *rs = &stationWithID(item->stationID());
if (rs != item) {
removeRef(rs);
}
BaseClass::inSort(item);
}
void RawStationList::prepend ( const RadioStation * item )
{
if (!item) return;
RadioStation *rs = &stationWithID(item->stationID());
if (rs != item) {
removeRef(rs);
}
BaseClass::prepend(item);
}
void RawStationList::append ( const RadioStation * item )
{
if (!item) return;
RadioStation *rs = &stationWithID(item->stationID());
if (rs != item) {
removeRef(rs);
}
BaseClass::append(item);
}
bool RawStationList::replace ( uint index, const RadioStation * item )
{
bool r = true;
RadioStation *rs = &stationWithID(item->stationID());
r = BaseClass::replace(index, item);
if (rs != item) {
BaseClass::removeRef(rs);
}
return r;
}
const RadioStation &RawStationList::stationWithID(const TQString &sid) const
{
Iterator it(*this);
for (; const RadioStation *s = it.current(); ++it) {
if (s->stationID() == sid)
return *s;
}
return (RadioStation &) undefinedRadioStation;
}
RadioStation &RawStationList::stationWithID(const TQString &sid)
{
Iterator it(*this);
for (; RadioStation *s = it.current(); ++it) {
if (s->stationID() == sid)
return *s;
}
return (RadioStation &) undefinedRadioStation;
}
int RawStationList::idxWithID(const TQString &sid) const
{
int i = 0;
Iterator it(*this);
for (; const RadioStation *s = it.current(); ++it, ++i) {
if (s->stationID() == sid)
return i;
}
return -1;
}
bool RawStationList::operator == (const RawStationList &l) const
{
TQPtrListIterator<RadioStation> it1(*this);
TQPtrListIterator<RadioStation> it2(l);
if (count() != l.count())
return false;
for (; it1.current() && it2.current(); ++it1, ++it2) {
if (**it1 != **it2)
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////////
StationList::StationList()
{
m_all.setAutoDelete(true);
}
StationList::StationList(const StationList &sl)
: m_all (sl.m_all),
m_metaData (sl.m_metaData)
{
m_all.setAutoDelete(true);
}
StationList::~StationList()
{
}
void StationList::merge(const StationList & other)
{
// merge meta information: honor merge in comment
StationListMetaData const & metaData = other.metaData();
if (! m_metaData.comment.isEmpty())
m_metaData.comment += "\n";
m_metaData.lastChange = TQDateTime::currentDateTime();
if (!metaData.maintainer.isEmpty())
m_metaData.maintainer += (count() ? TQString(" / ") : TQString()) + metaData.maintainer;
if (!metaData.country.isEmpty())
m_metaData.country += (count() ? TQString(" / ") : TQString()) + metaData.country;
if (!metaData.city.isEmpty())
m_metaData.city = (count() ? TQString(" / ") : TQString()) + metaData.city;
if (!metaData.media.isEmpty())
m_metaData.media += (count() ? TQString(" / ") : TQString()) + metaData.media;
if (!metaData.comment.isEmpty())
m_metaData.comment += (count() ? TQString(" / ") : TQString()) + metaData.comment;
if (count() && other.count())
m_metaData.comment += " " + i18n("Contains merged Data");
// merge stations
TQPtrListIterator<RadioStation> it(other.all());
for (RadioStation *s = it.current(); s; s = ++it) {
m_all.insert(s);
}
}
StationList &StationList::operator = (const StationList &other)
{
m_metaData = other.metaData();
m_all = other.all();
return *this;
}
const RadioStation &StationList::at(int idx) const
{
RawStationList::Iterator it(m_all);
it += idx;
return it.current() ? *it.current() : (const RadioStation &) undefinedRadioStation;
}
RadioStation &StationList::at(int idx)
{
RawStationList::Iterator it(m_all);
it += idx;
return it.current() ? *it.current() : (RadioStation &) undefinedRadioStation;
}
const RadioStation &StationList::stationWithID(const TQString &sid) const
{
return m_all.stationWithID(sid);
}
RadioStation &StationList::stationWithID(const TQString &sid)
{
return m_all.stationWithID(sid);
}
bool StationList::readXML (const TQString &dat, const IErrorLogClient &logger, bool enableMessageBox)
{
// FIXME: TODO: error handling
TQXmlInputSource source;
source.setData(dat);
TQXmlSimpleReader reader;
StationListXmlHandler handler(logger);
reader.setContentHandler (&handler);
if (reader.parse(source)) {
if (handler.wasCompatMode() && enableMessageBox) {
TQMessageBox::information(NULL, "TDERadio",
i18n("Probably an old station preset file was read.\n"
"You have to rebuild your station selections for "
"the quickbar and the docking menu.")
);
}
m_all = handler.getStations();
m_metaData = handler.getMetaData();
return true;
} else {
logger.logError("StationList::readXML: " + i18n("parsing failed"));
if (enableMessageBox) {
TQMessageBox::warning(NULL, "TDERadio",
i18n("Parsing the station preset file failed.\n"
"See console output for more details."));
}
return false;
}
}
bool StationList::readXML (const KURL &url, const IErrorLogClient &logger, bool enableMessageBox)
{
TQString tmpfile;
if (!TDEIO::NetAccess::download(url, tmpfile, NULL)) {
if (enableMessageBox) {
logger.logError("StationList::readXML: " +
i18n("error downloading preset file %1").arg(url.url()));
TQMessageBox::warning(NULL, "TDERadio",
i18n("Download of the station preset file at %1 failed.")
.arg(url.url()));
} else {
logger.logWarning("StationList::readXML: " +
i18n("error downloading preset file %1").arg(url.url()));
}
return false;
}
logger.logDebug("StationList::readXML: " +
i18n("temporary file: ") + tmpfile);
TQFile presetFile (tmpfile);
if (! presetFile.open(IO_ReadOnly)) {
logger.logError("StationList::readXML: " +
i18n("error opening preset file %1").arg(tmpfile));
if (enableMessageBox) {
TQMessageBox::warning(NULL, "TDERadio",
i18n("Opening of the station preset file at %1 failed.")
.arg(tmpfile));
}
return false;
}
TQString xmlData;
// make sure that qtextstream is gone when we close presetFile
TQString tmp;
{
TQTextStream ins(&presetFile);
tmp = ins.read();
}
presetFile.reset();
// preset file written with tderadio <= 0.2.x
if (tmp.find("<format>") < 0) {
logger.logInfo(i18n("Old Preset File Format detected"));
TQTextStream ins(&presetFile);
ins.setEncoding(TQTextStream::Locale);
xmlData = ins.read();
}
// preset file written with tderadio >= 0.3.0
else {
TQXmlInputSource tmp(&presetFile);
xmlData = tmp.data();
}
presetFile.close();
TDEIO::NetAccess::removeTempFile(tmpfile);
return readXML(xmlData, logger, enableMessageBox);
}
TQString StationList::writeXML (const IErrorLogClient &/*logger*/) const
{
TQString data = TQString();
// write station list
TQString t = "\t";
TQString tt = "\t\t";
TQString ttt = "\t\t\t";
data += xmlOpenTag(TDERadioConfigElement) +
t + xmlOpenTag(StationListElement) +
tt + xmlTag(StationListFormat, STATION_LIST_FORMAT) +
tt + xmlOpenTag(StationListInfo) +
ttt + xmlTag(StationListInfoCreator, "tderadio-" TDERADIO_VERSION) +
ttt + xmlTag(StationListInfoMaintainer, m_metaData.maintainer) +
ttt + xmlTag(StationListInfoChanged, m_metaData.lastChange.toString(TQt::ISODate)) +
ttt + xmlTag(StationListInfoCountry, m_metaData.country) +
ttt + xmlTag(StationListInfoCity, m_metaData.city) +
ttt + xmlTag(StationListInfoMedia, m_metaData.media) +
ttt + xmlTag(StationListInfoComments, m_metaData.comment) +
tt + xmlCloseTag (StationListInfo);
for (RawStationList::Iterator it(m_all); it.current(); ++it) {
RadioStation *s = it.current();
data += tt + xmlOpenTag (s->getClassName());
TQStringList properties = s->getPropertyNames();
TQStringList::iterator end = properties.end();
for (TQStringList::iterator sit = properties.begin(); sit != end; ++sit) {
data += ttt + xmlTag (*sit, s->getProperty(*sit));
}
data += tt + xmlCloseTag(s->getClassName());
}
data += t + xmlCloseTag(StationListElement) +
xmlCloseTag(TDERadioConfigElement);
return data;
}
bool StationList::writeXML (const KURL &url, const IErrorLogClient &logger, bool enableMessageBox) const
{
KTempFile tmpFile;
tmpFile.setAutoDelete(true);
TQFile *outf = tmpFile.file();
TQTextStream outs(outf);
outs.setEncoding(TQTextStream::UnicodeUTF8);
outs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
TQString output = writeXML(logger);
outs << output;
if (outf->status() != IO_Ok) {
logger.logError("StationList::writeXML: " +
i18n("error writing to tempfile %1").arg(tmpFile.name()));
if (enableMessageBox) {
TQMessageBox::warning(NULL, "TDERadio",
i18n("Writing station preset file %1 failed.")
.arg(tmpFile.name()));
}
return false;
}
// close hopefully flushes buffers ;)
outf->close();
if (count() <= 1) {
logger.logWarning("StationList::writeXML: " +
i18n("uploading preset file %1: ").arg(url.url()));
logger.logWarning("StationList::writeXML: " +
i18n("something strange happend, station list has only %1 entries. Writing station preset file skipped").arg(count()));
} else {
if (!TDEIO::NetAccess::upload(tmpFile.name(), url, NULL)) {
logger.logError("StationList::writeXML: " +
i18n("error uploading preset file %1").arg(url.url()));
if (enableMessageBox) {
TQMessageBox::warning(NULL, "TDERadio",
i18n("Upload of station preset file to %1 failed.")
.arg(url.url()));
}
return false;
}
}
return true;
}