|
|
|
/***************************************************************************
|
|
|
|
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(TQT_TQIODEVICE(&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(Qt::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;
|
|
|
|
}
|