diff --git a/plugins/webpresence/CMakeLists.txt b/plugins/webpresence/CMakeLists.txt index 7fae3e7ee..ee2cdc234 100644 --- a/plugins/webpresence/CMakeLists.txt +++ b/plugins/webpresence/CMakeLists.txt @@ -1,36 +1,49 @@ include_directories(${KOPETE_INCLUDES} ${LIBXML2_INCLUDE_DIR} ${LIBXSLT_INCLUDE_DIR}) ########### next target ############### set(kopete_webpresence_PART_SRCS webpresenceplugin.cpp ) kconfig_add_kcfg_files(kopete_webpresence_PART_SRCS webpresenceconfig.kcfgc ) add_library(kopete_webpresence MODULE ${kopete_webpresence_PART_SRCS}) -target_link_libraries(kopete_webpresence KF5::KIOCore kopete ${LIBXML2_LIBRARIES} ${LIBXSLT_LIBRARIES} Qt5::Xml) +target_link_libraries( + kopete_webpresence + KF5::KIOCore + kopete + ${LIBXML2_LIBRARIES} + ${LIBXSLT_LIBRARIES} + Qt5::Xml + KF5::I18n +) install(TARGETS kopete_webpresence DESTINATION ${KDE_INSTALL_PLUGINDIR}) ########### next target ############### set(kcm_kopete_webpresence_PART_SRCS webpresencepreferences.cpp ) ki18n_wrap_ui(kcm_kopete_webpresence_PART_SRCS webpresenceprefs.ui ) kconfig_add_kcfg_files(kcm_kopete_webpresence_PART_SRCS webpresenceconfig.kcfgc ) add_library(kcm_kopete_webpresence MODULE ${kcm_kopete_webpresence_PART_SRCS}) -target_link_libraries(kcm_kopete_webpresence KF5::KIOCore kopete ) +target_link_libraries( + kcm_kopete_webpresence + KF5::I18n + KF5::KIOCore + kopete +) install(TARGETS kcm_kopete_webpresence DESTINATION ${KDE_INSTALL_PLUGINDIR}) ########### install files ############### install(FILES webpresenceconfig.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) install(FILES kopete_webpresence.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) install(FILES webpresence_html.xsl webpresence_html_images.xsl webpresence_xhtml.xsl webpresence_xhtml_images.xsl DESTINATION ${KDE_INSTALL_DATADIR}/kopete/webpresence) install(FILES kopete_webpresence_config.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}/kconfiguredialog) diff --git a/plugins/webpresence/webpresenceplugin.cpp b/plugins/webpresence/webpresenceplugin.cpp index 7fc44a6f3..ca4c2e7ac 100644 --- a/plugins/webpresence/webpresenceplugin.cpp +++ b/plugins/webpresence/webpresenceplugin.cpp @@ -1,468 +1,455 @@ /* webpresenceplugin.cpp Kopete Web Presence plugin Copyright 2005-2006 by Tommi Rantala Copyright (c) 2002,2003 by Will Stephenson Kopete (c) 2002-2006 by the Kopete developers ************************************************************************* * * * 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 "webpresenceplugin.h" #include #include #include #include #include #include #include +#include #include #include #include #include -#include +#include #include #include #include #include #include #include #include #include "kopetepluginmanager.h" #include "kopeteprotocol.h" #include "kopeteaccountmanager.h" #include "kopeteaccount.h" #include "kopetecontact.h" #include "webpresenceconfig.h" K_PLUGIN_FACTORY(WebPresencePluginFactory, registerPlugin(); ) K_EXPORT_PLUGIN(WebPresencePluginFactory("kopete_webpresence")) WebPresencePlugin::WebPresencePlugin(QObject *parent, const QVariantList & /*args*/) : Kopete::Plugin(parent) , shuttingDown(false) , resultFormatting(WEB_HTML) , m_output(0) { m_writeScheduler = new QTimer(this); - connect(m_writeScheduler, SIGNAL(timeout()), this, SLOT(slotWriteFile())); - connect(Kopete::AccountManager::self(), SIGNAL(accountRegistered(Kopete::Account *)), - this, SLOT(listenToAllAccounts())); - connect(Kopete::AccountManager::self(), SIGNAL(accountUnregistered(const Kopete::Account *)), - this, SLOT(listenToAllAccounts())); + connect(m_writeScheduler, &QTimer::timeout, this, &WebPresencePlugin::slotWriteFile); + connect(Kopete::AccountManager::self(), &Kopete::AccountManager::accountRegistered, this, &WebPresencePlugin::listenToAllAccounts); + connect(Kopete::AccountManager::self(), &Kopete::AccountManager::accountUnregistered, this, &WebPresencePlugin::listenToAllAccounts); - connect(this, SIGNAL(settingsChanged()), this, SLOT(slotSettingsChanged())); + connect(this, &WebPresencePlugin::settingsChanged, this, &WebPresencePlugin::slotSettingsChanged); slotSettingsChanged(); listenToAllAccounts(); } WebPresencePlugin::~WebPresencePlugin() { delete m_output; } void WebPresencePlugin::slotSettingsChanged() { // Force reading config WebPresenceConfig::self()->load(); resultFormatting = WEB_UNDEFINED; if (WebPresenceConfig::self()->formatHTML()) { resultFormatting = WEB_HTML; } else if (WebPresenceConfig::self()->formatXHTML()) { resultFormatting = WEB_XHTML; } else if (WebPresenceConfig::self()->formatXML()) { resultFormatting = WEB_XML; } else if (WebPresenceConfig::self()->formatStylesheet()) { resultFormatting = WEB_CUSTOM; userStyleSheet = WebPresenceConfig::self()->formatStylesheetURL(); } // Default to HTML, if we don't get anything useful from config file. if (resultFormatting == WEB_UNDEFINED) { resultFormatting = WEB_HTML; } // Update file slotWriteFile(); } void WebPresencePlugin::listenToAllAccounts() { // Connect to signals notifying of all accounts' status changes. ProtocolList protocols = allProtocols(); for (ProtocolList::Iterator it = protocols.begin(); it != protocols.end(); ++it) { QList accounts = Kopete::AccountManager::self()->accounts(*it); foreach (Kopete::Account *account, accounts) { listenToAccount(account); } } slotWaitMoreStatusChanges(); } void WebPresencePlugin::listenToAccount(Kopete::Account *account) { if (account && account->myself()) { // Connect to the account's status changed signal // because we can't know if the account has already connected - QObject::disconnect(account->myself(), - SIGNAL(onlineStatusChanged(Kopete::Contact *, - const Kopete::OnlineStatus&, - const Kopete::OnlineStatus&)), - this, - SLOT(slotWaitMoreStatusChanges())); - QObject::connect(account->myself(), - SIGNAL(onlineStatusChanged(Kopete::Contact *, - const Kopete::OnlineStatus&, - const Kopete::OnlineStatus&)), - this, - SLOT(slotWaitMoreStatusChanges())); + QObject::disconnect(account->myself(), SIGNAL(onlineStatusChanged(Kopete::Contact *, const Kopete::OnlineStatus&, const Kopete::OnlineStatus&)), this, SLOT(slotWaitMoreStatusChanges())); + QObject::connect(account->myself(), SIGNAL(onlineStatusChanged(Kopete::Contact *, const Kopete::OnlineStatus&, const Kopete::OnlineStatus&)), this, SLOT(slotWaitMoreStatusChanges())); } } void WebPresencePlugin::slotWaitMoreStatusChanges() { if (!m_writeScheduler->isActive()) { m_writeScheduler->start(WebPresenceConfig::self()->uploadFrequency() * 1000); } } void WebPresencePlugin::slotWriteFile() { m_writeScheduler->stop(); // generate the (temporary) XML file representing the current contact list - const KUrl dest = WebPresenceConfig::self()->uploadURL(); + const QUrl dest = WebPresenceConfig::self()->uploadURL(); if (dest.isEmpty() || !dest.isValid()) { kDebug(14309) << "url is empty or not valid. NOT UPDATING!"; return; } - KTemporaryFile *xml = generateFile(); + QTemporaryFile *xml = generateFile(); xml->setAutoRemove(true); switch (resultFormatting) { case WEB_XML: m_output = xml; xml = nullptr; break; case WEB_HTML: case WEB_XHTML: case WEB_CUSTOM: - m_output = new KTemporaryFile(); + m_output = new QTemporaryFile(); m_output->open(); if (!transform(xml, m_output)) { //TODO: give some error to user, even better if shown only once delete m_output; m_output = nullptr; delete xml; return; } delete xml; // might make debugging harder! break; default: return; } // upload it to the specified URL - KUrl src(m_output->fileName()); + QUrl src(m_output->fileName()); KIO::FileCopyJob *job = KIO::file_move(src, dest, -1, KIO::Overwrite | KIO::HideProgressInfo); - connect(job, SIGNAL(result(KJob *)), - SLOT(slotUploadJobResult(KJob *))); + connect(job, &KIO::FileCopyJob::result, this, &WebPresencePlugin::slotUploadJobResult); } void WebPresencePlugin::slotUploadJobResult(KJob *job) { if (job->error()) { kDebug(14309) << "Error uploading presence info."; KMessageBox::detailedError(0, i18n("An error occurred when uploading your presence page.\nCheck the path and write permissions of the destination."), 0, displayName()); delete m_output; m_output = nullptr; } } -KTemporaryFile *WebPresencePlugin::generateFile() +QTemporaryFile *WebPresencePlugin::generateFile() { // generate the (temporary) XML file representing the current contact list kDebug(14309); QString notKnown = i18n("Not yet known"); QDomDocument doc; doc.appendChild(doc.createProcessingInstruction(QStringLiteral("xml"), QStringLiteral("version=\"1.0\" encoding=\"UTF-8\""))); QDomElement root = doc.createElement(QStringLiteral("webpresence")); doc.appendChild(root); // insert the current date/time QDomElement date = doc.createElement(QStringLiteral("listdate")); - QDomText t = doc.createTextNode( - KLocale::global()->formatDateTime(QDateTime::currentDateTime())); + QDomText t = doc.createTextNode(QLocale().toString(QDateTime::currentDateTime())); date.appendChild(t); root.appendChild(date); // insert the user's name QDomElement name = doc.createElement(QStringLiteral("name")); QDomText nameText; const QString userName = WebPresenceConfig::self()->showThisName(); if (!WebPresenceConfig::self()->showName() && !userName.isEmpty()) { nameText = doc.createTextNode(userName); } else { nameText = doc.createTextNode(notKnown); } name.appendChild(nameText); root.appendChild(name); // insert the list of the user's accounts QDomElement accounts = doc.createElement(QStringLiteral("accounts")); root.appendChild(accounts); QList list = Kopete::AccountManager::self()->accounts(); // If no accounts, stop here if (!list.isEmpty()) { foreach (Kopete::Account *account, list) { QDomElement acc = doc.createElement(QStringLiteral("account")); //output += h.openTag( "account" ); QDomElement protoName = doc.createElement(QStringLiteral("protocol")); QDomText protoNameText = doc.createTextNode( account->protocol()->pluginId()); protoName.appendChild(protoNameText); acc.appendChild(protoName); Kopete::Contact *me = account->myself(); QString displayName = me->displayName(); QDomElement accName = doc.createElement(QStringLiteral("accountname")); QDomText accNameText = doc.createTextNode((me) ? displayName : notKnown); accName.appendChild(accNameText); acc.appendChild(accName); QDomElement accStatus = doc.createElement(QStringLiteral("accountstatus")); QDomText statusText = doc.createTextNode((me) ? statusAsString(me->onlineStatus()) : notKnown); accStatus.appendChild(statusText); // Do not add these if we're shutting down, because the result // would be quite weird. if (!shuttingDown) { // Add away message as an attribute, if one exists. if ((me->onlineStatus().status() == Kopete::OnlineStatus::Away || me->onlineStatus().status() == Kopete::OnlineStatus::Busy) && !me->property(QStringLiteral("awayMessage")).value().toString().isEmpty()) { accStatus.setAttribute(QStringLiteral("awayreason"), me->property(QStringLiteral("awayMessage")).value().toString()); } // Add the online status description as an attribute, if one exits. if (!me->onlineStatus().description().isEmpty()) { accStatus.setAttribute(QStringLiteral("statusdescription"), me->onlineStatus().description()); } } acc.appendChild(accStatus); if (WebPresenceConfig::self()->includeIMAddress()) { QDomElement accAddress = doc.createElement(QStringLiteral("accountaddress")); QDomText addressText = doc.createTextNode((me) ? me->contactId() : notKnown); accAddress.appendChild(addressText); acc.appendChild(accAddress); } accounts.appendChild(acc); } } // write the XML to a temporary file - KTemporaryFile *file = new KTemporaryFile(); + QTemporaryFile *file = new QTemporaryFile(); file->setAutoRemove(false); file->open(); QString buf; QTextStream stream(&buf, QIODevice::WriteOnly); stream.setCodec("UTF-16"); // QtXML works only with UTF-16 doc.documentElement().save(stream, 4); // QDomDocument::save() override stream codec to UTF-8 file->write(buf.toUtf8()); file->flush(); return file; } -bool WebPresencePlugin::transform(KTemporaryFile *src, KTemporaryFile *dest) +bool WebPresencePlugin::transform(QTemporaryFile *src, QTemporaryFile *dest) { bool retval = true; xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; QFile sheet; switch (resultFormatting) { case WEB_XML: // Oops! We tried to call transform() but XML was requested. return false; case WEB_HTML: if (WebPresenceConfig::self()->useImagesHTML()) { sheet.setFileName(QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("/webpresence/webpresence_html_images.xsl"))); } else { sheet.setFileName(QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("/webpresence/webpresence_html.xsl"))); } break; case WEB_XHTML: if (WebPresenceConfig::self()->useImagesHTML()) { sheet.setFileName(QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("/webpresence/webpresence_xhtml_images.xsl"))); } else { sheet.setFileName(QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("/webpresence/webpresence_xhtml.xsl"))); } break; case WEB_CUSTOM: sheet.setFileName(userStyleSheet.path()); break; default: // Shouldn't ever reach here. return false; } // TODO: auto / smart pointers would be useful here xsltStylesheetPtr cur = 0; xmlDocPtr doc = 0; xmlDocPtr res = 0; if (!sheet.exists()) { kDebug(14309) << "ERROR: Style sheet not found"; retval = false; goto end; } // is the cast safe? cur = xsltParseStylesheetFile((const xmlChar *)sheet.fileName().toLatin1().data()); if (!cur) { kDebug(14309) << "ERROR: Style sheet parsing failed"; retval = false; goto end; } doc = xmlParseFile(QFile::encodeName(src->fileName())); if (!doc) { kDebug(14309) << "ERROR: XML parsing failed"; retval = false; goto end; } res = xsltApplyStylesheet(cur, doc, 0); if (!res) { kDebug(14309) << "ERROR: Style sheet apply failed"; retval = false; goto end; } if (xsltSaveResultToFd(dest->handle(), res, cur) == -1) { kDebug(14309) << "ERROR: Style sheet apply failed"; retval = false; goto end; } // then it all worked! end: xsltCleanupGlobals(); xmlCleanupParser(); if (doc) { xmlFreeDoc(doc); } if (res) { xmlFreeDoc(res); } if (cur) { xsltFreeStylesheet(cur); } return retval; } ProtocolList WebPresencePlugin::allProtocols() { kDebug(14309); Kopete::PluginList plugins = Kopete::PluginManager::self()->loadedPlugins(QStringLiteral("Protocols")); Kopete::PluginList::ConstIterator it; ProtocolList result; for (it = plugins.constBegin(); it != plugins.constEnd(); ++it) { result.append(static_cast(*it)); } return result; } QString WebPresencePlugin::statusAsString(const Kopete::OnlineStatus &newStatus) { if (shuttingDown) { return QStringLiteral("OFFLINE"); } QString status; switch (newStatus.status()) { case Kopete::OnlineStatus::Online: status = QStringLiteral("ONLINE"); break; case Kopete::OnlineStatus::Away: status = QStringLiteral("AWAY"); break; case Kopete::OnlineStatus::Busy: status = QStringLiteral("BUSY"); break; case Kopete::OnlineStatus::Offline: case Kopete::OnlineStatus::Invisible: status = QStringLiteral("OFFLINE"); break; default: status = QStringLiteral("UNKNOWN"); } return status; } void WebPresencePlugin::aboutToUnload() { // Stop timer. Do not need it anymore. m_writeScheduler->stop(); // Force statusAsString() report all accounts as OFFLINE. shuttingDown = true; // Do final update of webpresence file. slotWriteFile(); emit readyForUnload(); } // vim: set noet ts=4 sts=4 sw=4: #include "webpresenceplugin.moc" diff --git a/plugins/webpresence/webpresenceplugin.h b/plugins/webpresence/webpresenceplugin.h index 4e168fb51..682a5eff3 100644 --- a/plugins/webpresence/webpresenceplugin.h +++ b/plugins/webpresence/webpresenceplugin.h @@ -1,126 +1,126 @@ /* webpresenceplugin.h Kopete Web Presence plugin Copyright (c) 2002,2003 by Will Stephenson Kopete (c) 2002,2003 by the Kopete developers ************************************************************************* * * * 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. * * * ************************************************************************* */ #ifndef WEBPRESENCEPLUGIN_H #define WEBPRESENCEPLUGIN_H #include -#include +#include #include "kopeteplugin.h" class QTimer; -class KTemporaryFile; +class QTemporaryFile; class KJob; namespace Kopete { } namespace Kopete { class Protocol; } namespace Kopete { class Account; } namespace Kopete { class OnlineStatus; } typedef QList ProtocolList; class WebPresencePlugin : public Kopete::Plugin { Q_OBJECT private: - KUrl userStyleSheet; + QUrl userStyleSheet; // Is set to true when Kopete has notified us // that we're about to be unloaded. bool shuttingDown; enum { WEB_HTML, WEB_XHTML, WEB_XML, WEB_CUSTOM, WEB_UNDEFINED } resultFormatting; public: WebPresencePlugin(QObject *parent, const QVariantList &args); virtual ~WebPresencePlugin(); void aboutToUnload() Q_DECL_OVERRIDE; protected Q_SLOTS: /** * Called when settings were changed */ void slotSettingsChanged(); /** * Write a file to the specified location, */ void slotWriteFile(); /** * Called when an upload finished, displays error if needed */ void slotUploadJobResult(KJob *); /** * Called to schedule a write, after waiting to see if more changes * occur (accounts tend to change status together) */ void slotWaitMoreStatusChanges(); /** * Sets us up to respond to account status changes */ void listenToAllAccounts(); /** * Sets us up to respond to a new account */ void listenToAccount(Kopete::Account *account); protected: /** * Generate the file (HTML, text) to be uploaded */ - KTemporaryFile *generateFile(); + QTemporaryFile *generateFile(); /** * Apply named stylesheet to get content and presentation */ - bool transform(KTemporaryFile *src, KTemporaryFile *dest); + bool transform(QTemporaryFile *src, QTemporaryFile *dest); /** * Helper method, generates list of all IM protocols */ ProtocolList allProtocols(); /** * Converts numeric status to a string */ QString statusAsString(const Kopete::OnlineStatus &newStatus); /** * Schedules writes */ QTimer *m_writeScheduler; // The file to be uploaded to the WWW - KTemporaryFile *m_output; + QTemporaryFile *m_output; }; #endif // vim: set noet ts=4 sts=4 sw=4: