From 0fe6b3e686f094768d83364b154bc48bfc0eb595 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Tue, 19 Sep 2017 10:18:21 +0200 Subject: [PATCH] Uncrustify reformat. --- resources/scripts/astyle/.astylerc | 27 - .../uncrustify-format-all.sh} | 12 +- src/core/feeddownloader.cpp | 188 +- src/core/feeddownloader.h | 101 +- src/core/feedsproxymodel.cpp | 353 +-- src/core/feedsproxymodel.h | 66 +- src/core/message.cpp | 119 +- src/core/message.h | 77 +- src/core/messagesmodel.cpp | 767 +++--- src/core/messagesmodel.h | 132 +- src/core/messagesmodelcache.cpp | 18 +- src/core/messagesmodelcache.h | 39 +- src/core/messagesmodelsqllayer.cpp | 117 +- src/core/messagesmodelsqllayer.h | 43 +- src/core/messagesproxymodel.cpp | 246 +- src/core/messagesproxymodel.h | 41 +- src/definitions/definitions.h | 7 +- src/dynamic-shortcuts/dynamicshortcuts.cpp | 28 +- src/dynamic-shortcuts/dynamicshortcuts.h | 24 +- .../dynamicshortcutswidget.cpp | 129 +- .../dynamicshortcutswidget.h | 54 +- src/dynamic-shortcuts/shortcutbutton.cpp | 167 +- src/dynamic-shortcuts/shortcutbutton.h | 59 +- src/dynamic-shortcuts/shortcutcatcher.cpp | 199 +- src/dynamic-shortcuts/shortcutcatcher.h | 97 +- src/exceptions/applicationexception.cpp | 10 +- src/exceptions/applicationexception.h | 14 +- src/exceptions/ioexception.cpp | 8 +- src/exceptions/ioexception.h | 8 +- src/gui/baselineedit.cpp | 23 +- src/gui/baselineedit.h | 28 +- src/gui/basetoolbar.cpp | 27 +- src/gui/basetoolbar.h | 49 +- src/gui/colorlabel.cpp | 17 +- src/gui/colorlabel.h | 22 +- src/gui/comboboxwithstatus.cpp | 24 +- src/gui/comboboxwithstatus.h | 20 +- src/gui/dialogs/formabout.h | 21 +- src/gui/dialogs/formaddaccount.cpp | 76 +- src/gui/dialogs/formaddaccount.h | 30 +- .../dialogs/formbackupdatabasesettings.cpp | 103 +- src/gui/dialogs/formbackupdatabasesettings.h | 28 +- src/gui/dialogs/formdatabasecleanup.cpp | 137 +- src/gui/dialogs/formdatabasecleanup.h | 47 +- src/gui/dialogs/formmain.cpp | 1148 ++++---- src/gui/dialogs/formmain.h | 119 +- .../dialogs/formrestoredatabasesettings.cpp | 14 +- src/gui/dialogs/formrestoredatabasesettings.h | 36 +- src/gui/dialogs/formsettings.cpp | 170 +- src/gui/dialogs/formsettings.h | 36 +- src/gui/dialogs/formupdate.cpp | 345 +-- src/gui/dialogs/formupdate.h | 53 +- src/gui/discoverfeedsbutton.cpp | 92 +- src/gui/discoverfeedsbutton.h | 32 +- src/gui/edittableview.cpp | 62 +- src/gui/edittableview.h | 18 +- src/gui/feedstoolbar.cpp | 99 +- src/gui/feedstoolbar.h | 27 +- src/gui/feedsview.cpp | 698 ++--- src/gui/feedsview.h | 158 +- src/gui/guiutilities.cpp | 26 +- src/gui/guiutilities.h | 14 +- src/gui/labelwithstatus.cpp | 28 +- src/gui/labelwithstatus.h | 24 +- src/gui/lineeditwithstatus.cpp | 28 +- src/gui/lineeditwithstatus.h | 22 +- src/gui/locationlineedit.cpp | 39 +- src/gui/locationlineedit.h | 25 +- src/gui/messagebox.cpp | 14 +- src/gui/messagebox.h | 42 +- src/gui/messagepreviewer.cpp | 295 +-- src/gui/messagepreviewer.h | 66 +- src/gui/messagessearchlineedit.cpp | 8 +- src/gui/messagessearchlineedit.h | 13 +- src/gui/messagestoolbar.cpp | 195 +- src/gui/messagestoolbar.h | 76 +- src/gui/messagesview.cpp | 21 +- src/gui/messagetextbrowser.cpp | 34 +- src/gui/messagetextbrowser.h | 20 +- src/gui/newspaperpreviewer.cpp | 62 +- src/gui/newspaperpreviewer.h | 28 +- src/gui/plaintoolbutton.cpp | 69 +- src/gui/plaintoolbutton.h | 38 +- src/gui/settings/settingsbrowsermail.cpp | 246 +- src/gui/settings/settingsbrowsermail.h | 37 +- src/gui/settings/settingsdatabase.cpp | 290 ++- src/gui/settings/settingsdatabase.h | 39 +- src/gui/settings/settingsdownloads.cpp | 62 +- src/gui/settings/settingsdownloads.h | 29 +- src/gui/settings/settingsfeedsmessages.cpp | 189 +- src/gui/settings/settingsfeedsmessages.h | 31 +- src/gui/settings/settingsgeneral.cpp | 81 +- src/gui/settings/settingsgeneral.h | 25 +- src/gui/settings/settingsgui.cpp | 390 +-- src/gui/settings/settingsgui.h | 32 +- src/gui/settings/settingslocalization.cpp | 92 +- src/gui/settings/settingslocalization.h | 25 +- src/gui/settings/settingspanel.cpp | 38 +- src/gui/settings/settingspanel.h | 60 +- src/gui/settings/settingsshortcuts.cpp | 26 +- src/gui/settings/settingsshortcuts.h | 25 +- src/gui/squeezelabel.cpp | 21 +- src/gui/squeezelabel.h | 16 +- src/gui/statusbar.cpp | 10 +- src/gui/styleditemdelegatewithoutfocus.cpp | 18 +- src/gui/styleditemdelegatewithoutfocus.h | 15 +- src/gui/systemtrayicon.cpp | 207 +- src/gui/systemtrayicon.h | 82 +- src/gui/tabbar.cpp | 183 +- src/gui/tabbar.h | 59 +- src/gui/tabcontent.cpp | 8 +- src/gui/tabcontent.h | 41 +- src/gui/tabwidget.cpp | 403 +-- src/gui/tabwidget.h | 156 +- src/gui/timespinbox.cpp | 88 +- src/gui/timespinbox.h | 18 +- src/gui/toolbareditor.cpp | 357 +-- src/gui/toolbareditor.h | 71 +- src/gui/treeviewcolumnsmenu.cpp | 32 +- src/gui/treeviewcolumnsmenu.h | 18 +- src/gui/treewidget.cpp | 213 +- src/gui/treewidget.h | 74 +- src/gui/webbrowser.cpp | 358 +-- src/gui/webbrowser.h | 117 +- src/gui/webviewer.cpp | 203 +- src/gui/webviewer.h | 56 +- src/gui/widgetwithstatus.cpp | 76 +- src/gui/widgetwithstatus.h | 60 +- src/main.cpp | 231 +- src/miscellaneous/application.cpp | 414 +-- src/miscellaneous/application.h | 198 +- src/miscellaneous/autosaver.cpp | 62 +- src/miscellaneous/autosaver.h | 28 +- src/miscellaneous/databasecleaner.cpp | 101 +- src/miscellaneous/databasecleaner.h | 47 +- src/miscellaneous/databasefactory.cpp | 1225 ++++----- src/miscellaneous/databasefactory.h | 232 +- src/miscellaneous/databasequeries.cpp | 2301 +++++++++-------- src/miscellaneous/databasequeries.h | 178 +- src/miscellaneous/debugging.cpp | 69 +- src/miscellaneous/debugging.h | 22 +- src/miscellaneous/externaltool.cpp | 13 +- src/miscellaneous/externaltool.h | 5 +- src/miscellaneous/feedreader.cpp | 325 +-- src/miscellaneous/feedreader.h | 111 +- src/miscellaneous/iconfactory.cpp | 168 +- src/miscellaneous/iconfactory.h | 69 +- src/miscellaneous/iofactory.cpp | 134 +- src/miscellaneous/iofactory.h | 39 +- src/miscellaneous/localization.cpp | 102 +- src/miscellaneous/localization.h | 66 +- src/miscellaneous/mutex.cpp | 47 +- src/miscellaneous/mutex.h | 52 +- src/miscellaneous/settings.cpp | 506 ++-- src/miscellaneous/settings.h | 480 ++-- src/miscellaneous/settingsproperties.h | 18 +- src/miscellaneous/simplecrypt/simplecrypt.cpp | 363 +-- src/miscellaneous/simplecrypt/simplecrypt.h | 396 +-- src/miscellaneous/simpleregexp.cpp | 70 +- src/miscellaneous/simpleregexp.h | 24 +- src/miscellaneous/skinfactory.cpp | 237 +- src/miscellaneous/skinfactory.h | 81 +- src/miscellaneous/systemfactory.cpp | 382 +-- src/miscellaneous/systemfactory.h | 92 +- src/miscellaneous/textfactory.cpp | 182 +- src/miscellaneous/textfactory.h | 52 +- .../adblock/adblockaddsubscriptiondialog.cpp | 108 +- .../adblock/adblockaddsubscriptiondialog.h | 47 +- src/network-web/adblock/adblockdialog.cpp | 178 +- src/network-web/adblock/adblockdialog.h | 55 +- src/network-web/adblock/adblockicon.cpp | 220 +- src/network-web/adblock/adblockicon.h | 40 +- src/network-web/adblock/adblockmanager.cpp | 429 +-- src/network-web/adblock/adblockmanager.h | 90 +- src/network-web/adblock/adblockmatcher.cpp | 313 +-- src/network-web/adblock/adblockmatcher.h | 48 +- src/network-web/adblock/adblockrule.cpp | 930 +++---- src/network-web/adblock/adblockrule.h | 195 +- src/network-web/adblock/adblocksearchtree.cpp | 143 +- src/network-web/adblock/adblocksearchtree.h | 37 +- .../adblock/adblocksubscription.cpp | 435 ++-- src/network-web/adblock/adblocksubscription.h | 106 +- src/network-web/adblock/adblocktreewidget.cpp | 318 +-- src/network-web/adblock/adblocktreewidget.h | 47 +- .../adblock/adblockurlinterceptor.cpp | 7 +- .../adblock/adblockurlinterceptor.h | 14 +- src/network-web/basenetworkaccessmanager.cpp | 77 +- src/network-web/basenetworkaccessmanager.h | 36 +- src/network-web/downloader.cpp | 257 +- src/network-web/downloader.h | 105 +- src/network-web/downloadmanager.cpp | 1032 ++++---- src/network-web/downloadmanager.h | 224 +- src/network-web/googlesuggest.cpp | 215 +- src/network-web/googlesuggest.h | 38 +- src/network-web/networkfactory.cpp | 262 +- src/network-web/networkfactory.h | 45 +- src/network-web/networkurlinterceptor.cpp | 31 +- src/network-web/networkurlinterceptor.h | 22 +- src/network-web/rssguardschemehandler.cpp | 50 +- src/network-web/rssguardschemehandler.h | 16 +- .../silentnetworkaccessmanager.cpp | 39 +- src/network-web/silentnetworkaccessmanager.h | 24 +- src/network-web/urlinterceptor.h | 12 +- src/network-web/webfactory.cpp | 274 +- src/network-web/webfactory.h | 64 +- src/network-web/webpage.cpp | 68 +- src/network-web/webpage.h | 32 +- src/qtsingleapplication/qtlocalpeer.cpp | 245 +- src/qtsingleapplication/qtlocalpeer.h | 43 +- src/qtsingleapplication/qtlockedfile.cpp | 66 +- src/qtsingleapplication/qtlockedfile.h | 45 +- src/qtsingleapplication/qtlockedfile_unix.cpp | 107 +- src/qtsingleapplication/qtlockedfile_win.cpp | 288 +-- .../qtsingleapplication.cpp | 173 +- src/qtsingleapplication/qtsingleapplication.h | 56 +- .../qtsinglecoreapplication.cpp | 40 +- .../qtsinglecoreapplication.h | 26 +- src/services/abstract/accountcheckmodel.cpp | 363 +-- src/services/abstract/accountcheckmodel.h | 64 +- src/services/abstract/cacheforserviceroot.cpp | 90 +- src/services/abstract/cacheforserviceroot.h | 27 +- src/services/abstract/category.cpp | 65 +- src/services/abstract/category.h | 12 +- src/services/abstract/feed.cpp | 280 +- src/services/abstract/feed.h | 120 +- src/services/abstract/gui/formfeeddetails.cpp | 611 ++--- src/services/abstract/gui/formfeeddetails.h | 101 +- src/services/abstract/label.cpp | 5 +- src/services/abstract/label.h | 6 +- src/services/abstract/labelsrootitem.cpp | 8 +- src/services/abstract/labelsrootitem.h | 8 +- src/services/abstract/recyclebin.cpp | 156 +- src/services/abstract/recyclebin.h | 61 +- src/services/abstract/rootitem.cpp | 517 ++-- src/services/abstract/rootitem.h | 316 ++- src/services/abstract/serviceentrypoint.cpp | 5 +- src/services/abstract/serviceentrypoint.h | 77 +- src/services/abstract/serviceroot.cpp | 630 ++--- src/services/abstract/serviceroot.h | 278 +- src/services/owncloud/definitions.h | 2 +- .../owncloud/gui/formeditowncloudaccount.cpp | 247 +- .../owncloud/gui/formeditowncloudaccount.h | 43 +- .../owncloud/gui/formowncloudfeeddetails.cpp | 125 +- .../owncloud/gui/formowncloudfeeddetails.h | 16 +- .../network/owncloudnetworkfactory.cpp | 103 +- .../owncloud/network/owncloudnetworkfactory.h | 5 +- src/services/owncloud/owncloudcategory.cpp | 25 +- src/services/owncloud/owncloudcategory.h | 18 +- src/services/owncloud/owncloudfeed.cpp | 113 +- src/services/owncloud/owncloudfeed.h | 34 +- src/services/owncloud/owncloudrecyclebin.cpp | 16 +- src/services/owncloud/owncloudrecyclebin.h | 15 +- .../owncloud/owncloudserviceentrypoint.cpp | 38 +- .../owncloud/owncloudserviceentrypoint.h | 27 +- src/services/owncloud/owncloudserviceroot.cpp | 340 +-- src/services/owncloud/owncloudserviceroot.h | 73 +- src/services/standard/atomparser.cpp | 155 +- src/services/standard/atomparser.h | 24 +- src/services/standard/feedparser.cpp | 104 +- src/services/standard/feedparser.h | 26 +- .../gui/formstandardcategorydetails.cpp | 353 +-- .../gui/formstandardcategorydetails.h | 81 +- .../standard/gui/formstandardfeeddetails.cpp | 117 +- .../standard/gui/formstandardfeeddetails.h | 16 +- .../standard/gui/formstandardimportexport.cpp | 423 +-- .../standard/gui/formstandardimportexport.h | 59 +- src/services/standard/rdfparser.cpp | 120 +- src/services/standard/rdfparser.h | 10 +- src/services/standard/rssparser.cpp | 149 +- src/services/standard/rssparser.h | 14 +- src/services/standard/standardcategory.cpp | 232 +- src/services/standard/standardcategory.h | 59 +- src/services/standard/standardfeed.cpp | 704 ++--- src/services/standard/standardfeed.h | 195 +- .../standardfeedsimportexportmodel.cpp | 512 ++-- .../standard/standardfeedsimportexportmodel.h | 57 +- .../standard/standardserviceentrypoint.cpp | 55 +- .../standard/standardserviceentrypoint.h | 27 +- src/services/standard/standardserviceroot.cpp | 454 ++-- src/services/standard/standardserviceroot.h | 89 +- src/services/tt-rss/definitions.h | 1 + .../tt-rss/gui/formeditttrssaccount.cpp | 379 +-- .../tt-rss/gui/formeditttrssaccount.h | 49 +- .../tt-rss/gui/formttrssfeeddetails.cpp | 117 +- .../tt-rss/gui/formttrssfeeddetails.h | 19 +- .../tt-rss/network/ttrssnetworkfactory.cpp | 875 ++++--- .../tt-rss/network/ttrssnetworkfactory.h | 210 +- src/services/tt-rss/ttrsscategory.cpp | 43 +- src/services/tt-rss/ttrsscategory.h | 19 +- src/services/tt-rss/ttrssfeed.cpp | 210 +- src/services/tt-rss/ttrssfeed.h | 37 +- src/services/tt-rss/ttrssrecyclebin.cpp | 14 +- src/services/tt-rss/ttrssrecyclebin.h | 15 +- .../tt-rss/ttrssserviceentrypoint.cpp | 44 +- src/services/tt-rss/ttrssserviceentrypoint.h | 28 +- src/services/tt-rss/ttrssserviceroot.cpp | 398 +-- src/services/tt-rss/ttrssserviceroot.h | 79 +- 297 files changed, 21045 insertions(+), 20234 deletions(-) delete mode 100755 resources/scripts/astyle/.astylerc rename resources/scripts/{astyle/astyle-format-all.sh => uncrustify/uncrustify-format-all.sh} (82%) mode change 100644 => 100755 src/miscellaneous/externaltool.cpp mode change 100644 => 100755 src/miscellaneous/externaltool.h diff --git a/resources/scripts/astyle/.astylerc b/resources/scripts/astyle/.astylerc deleted file mode 100755 index 3bfdf0990..000000000 --- a/resources/scripts/astyle/.astylerc +++ /dev/null @@ -1,27 +0,0 @@ ---style=java ---indent=spaces=2 ---indent-classes ---indent-namespaces ---indent-switches ---indent-labels ---indent-preproc-define ---indent-col1-comments ---max-continuation-indent=100 ---break-blocks ---unpad-paren ---pad-oper ---pad-comma ---pad-header ---align-pointer=type ---align-reference=type ---break-closing-braces ---break-one-line-headers ---add-braces ---convert-tabs ---close-templates ---max-code-length=140 ---lineend=linux -#--delete-empty-lines ---mode=c --t -p --M60Ucv \ No newline at end of file diff --git a/resources/scripts/astyle/astyle-format-all.sh b/resources/scripts/uncrustify/uncrustify-format-all.sh similarity index 82% rename from resources/scripts/astyle/astyle-format-all.sh rename to resources/scripts/uncrustify/uncrustify-format-all.sh index 5d30079c4..c07fb3e3b 100755 --- a/resources/scripts/astyle/astyle-format-all.sh +++ b/resources/scripts/uncrustify/uncrustify-format-all.sh @@ -27,16 +27,14 @@ if [ $# -eq 0 ]; then usage fi -ASTYLE_CMD="astyle" +ASTYLE_CMD="uncrustify" if [[ "$(uname -o)" == "Cygwin" ]]; then - ASTYLE_RC="$(cygpath -w $(realpath $(dirname $0)))/.astylerc" + ASTYLE_RC="$(cygpath -w $(realpath $(dirname $0)))/uncrustify.cfg" else - ASTYLE_RC="$(realpath $(dirname $0))/.astylerc" + ASTYLE_RC="$(realpath $(dirname $0))/uncrustify.cfg" fi -ASTYLE_RC="$(cygpath -w $(realpath $(dirname $0)))/.astylerc" - echo "ASTYLE config file: $ASTYLE_RC" # Check all args. @@ -58,11 +56,11 @@ for dir in "$@"; do -o -name '*.h' \ -o -name '*.hh' \ -o -name '*.hpp'); do - "${ASTYLE_CMD}" --options="$ASTYLE_RC" "${f}" + "${ASTYLE_CMD}" -c "$ASTYLE_RC" --replace "${f}" done # Remove backup files. - find . -name "*.orig" | xargs --no-run-if-empty rm -v + find . -name "*-backup*~*" | xargs --no-run-if-empty rm -v popd done diff --git a/src/core/feeddownloader.cpp b/src/core/feeddownloader.cpp index d4a27d234..1e44514a0 100755 --- a/src/core/feeddownloader.cpp +++ b/src/core/feeddownloader.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,152 +18,157 @@ #include "core/feeddownloader.h" -#include "services/abstract/feed.h" #include "definitions/definitions.h" +#include "services/abstract/feed.h" -#include #include -#include #include #include - +#include +#include FeedDownloader::FeedDownloader(QObject* parent) - : QObject(parent), m_feeds(QList()), m_mutex(new QMutex()), m_threadPool(new QThreadPool(this)), - m_results(FeedDownloadResults()), m_feedsUpdated(0), - m_feedsUpdating(0), m_feedsOriginalCount(0) { - qRegisterMetaType("FeedDownloadResults"); - m_threadPool->setMaxThreadCount(FEED_DOWNLOADER_MAX_THREADS); + : QObject(parent), m_feeds(QList()), m_mutex(new QMutex()), m_threadPool(new QThreadPool(this)), + m_results(FeedDownloadResults()), m_feedsUpdated(0), + m_feedsUpdating(0), m_feedsOriginalCount(0) { + qRegisterMetaType("FeedDownloadResults"); + m_threadPool->setMaxThreadCount(FEED_DOWNLOADER_MAX_THREADS); } FeedDownloader::~FeedDownloader() { - m_mutex->tryLock(); - m_mutex->unlock(); - delete m_mutex; - qDebug("Destroying FeedDownloader instance."); + m_mutex->tryLock(); + m_mutex->unlock(); + delete m_mutex; + qDebug("Destroying FeedDownloader instance."); } bool FeedDownloader::isUpdateRunning() const { - return !m_feeds.isEmpty() || m_feedsUpdating > 0; + return !m_feeds.isEmpty() || m_feedsUpdating > 0; } void FeedDownloader::updateAvailableFeeds() { - while (!m_feeds.isEmpty()) { - connect(m_feeds.first(), &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished, - (Qt::ConnectionType)(Qt::UniqueConnection | Qt::AutoConnection)); + while (!m_feeds.isEmpty()) { + connect(m_feeds.first(), &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished, + (Qt::ConnectionType)(Qt::UniqueConnection | Qt::AutoConnection)); - if (m_threadPool->tryStart(m_feeds.first())) { - m_feeds.removeFirst(); - m_feedsUpdating++; - } - else { - // We want to start update of some feeds but all working threads are occupied. - break; - } - } + if (m_threadPool->tryStart(m_feeds.first())) { + m_feeds.removeFirst(); + m_feedsUpdating++; + } + else { + // We want to start update of some feeds but all working threads are occupied. + break; + } + } } void FeedDownloader::updateFeeds(const QList& feeds) { - QMutexLocker locker(m_mutex); + QMutexLocker locker(m_mutex); - if (feeds.isEmpty()) { - qDebug("No feeds to update in worker thread, aborting update."); - finalizeUpdate(); - } - else { - qDebug().nospace() << "Starting feed updates from worker in thread: \'" << QThread::currentThreadId() << "\'."; - m_feeds = feeds; - m_feedsOriginalCount = m_feeds.size(); - m_results.clear(); - m_feedsUpdated = m_feedsUpdating = 0; - // Job starts now. - emit updateStarted(); - updateAvailableFeeds(); - } + if (feeds.isEmpty()) { + qDebug("No feeds to update in worker thread, aborting update."); + finalizeUpdate(); + } + else { + qDebug().nospace() << "Starting feed updates from worker in thread: \'" << QThread::currentThreadId() << "\'."; + m_feeds = feeds; + m_feedsOriginalCount = m_feeds.size(); + m_results.clear(); + m_feedsUpdated = m_feedsUpdating = 0; + + // Job starts now. + emit updateStarted(); + + updateAvailableFeeds(); + } } void FeedDownloader::stopRunningUpdate() { - m_threadPool->clear(); - m_feeds.clear(); + m_threadPool->clear(); + m_feeds.clear(); } void FeedDownloader::oneFeedUpdateFinished(const QList& messages, bool error_during_obtaining) { - QMutexLocker locker(m_mutex); - m_feedsUpdated++; - m_feedsUpdating--; - Feed* feed = qobject_cast(sender()); - disconnect(feed, &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished); - // Now, we check if there are any feeds we would like to update too. - updateAvailableFeeds(); - // Now make sure, that messages are actually stored to SQL in a locked state. - qDebug().nospace() << "Saving messages of feed " - << feed->id() << " in thread: \'" - << QThread::currentThreadId() << "\'."; - int updated_messages = feed->updateMessages(messages, error_during_obtaining); + QMutexLocker locker(m_mutex); - /* - QMetaObject::invokeMethod(feed, "updateMessages", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(int, updated_messages), - Q_ARG(QList, messages)); - */ + m_feedsUpdated++; + m_feedsUpdating--; + Feed* feed = qobject_cast(sender()); - if (updated_messages > 0) { - m_results.appendUpdatedFeed(QPair(feed->title(), updated_messages)); - } + disconnect(feed, &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished); - qDebug("Made progress in feed updates, total feeds count %d/%d (id of feed is %d).", m_feedsUpdated, m_feedsOriginalCount, feed->id()); - emit updateProgress(feed, m_feedsUpdated, m_feedsOriginalCount); + // Now, we check if there are any feeds we would like to update too. + updateAvailableFeeds(); - if (m_feeds.isEmpty() && m_feedsUpdating <= 0) { - finalizeUpdate(); - } + // Now make sure, that messages are actually stored to SQL in a locked state. + qDebug().nospace() << "Saving messages of feed " + << feed->id() << " in thread: \'" + << QThread::currentThreadId() << "\'."; + int updated_messages = feed->updateMessages(messages, error_during_obtaining); + + /* + QMetaObject::invokeMethod(feed, "updateMessages", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(int, updated_messages), + Q_ARG(QList, messages)); + */ + + if (updated_messages > 0) { + m_results.appendUpdatedFeed(QPair(feed->title(), updated_messages)); + } + + qDebug("Made progress in feed updates, total feeds count %d/%d (id of feed is %d).", m_feedsUpdated, m_feedsOriginalCount, feed->id()); + emit updateProgress(feed, m_feedsUpdated, m_feedsOriginalCount); + + if (m_feeds.isEmpty() && m_feedsUpdating <= 0) { + finalizeUpdate(); + } } void FeedDownloader::finalizeUpdate() { - qDebug().nospace() << "Finished feed updates in thread: \'" << QThread::currentThreadId() << "\'."; - m_results.sort(); - // Update of feeds has finished. - // NOTE: This means that now "update lock" can be unlocked - // and feeds can be added/edited/deleted and application - // can eventually quit. - emit updateFinished(m_results); + qDebug().nospace() << "Finished feed updates in thread: \'" << QThread::currentThreadId() << "\'."; + m_results.sort(); + + // Update of feeds has finished. + // NOTE: This means that now "update lock" can be unlocked + // and feeds can be added/edited/deleted and application + // can eventually quit. + emit updateFinished(m_results); } -FeedDownloadResults::FeedDownloadResults() : m_updatedFeeds(QList>()) { -} +FeedDownloadResults::FeedDownloadResults() : m_updatedFeeds(QList>()) {} QString FeedDownloadResults::overview(int how_many_feeds) const { - QStringList result; + QStringList result; - for (int i = 0, number_items_output = qMin(how_many_feeds, m_updatedFeeds.size()); i < number_items_output; i++) { - result.append(m_updatedFeeds.at(i).first + QSL(": ") + QString::number(m_updatedFeeds.at(i).second)); - } + for (int i = 0, number_items_output = qMin(how_many_feeds, m_updatedFeeds.size()); i < number_items_output; i++) { + result.append(m_updatedFeeds.at(i).first + QSL(": ") + QString::number(m_updatedFeeds.at(i).second)); + } - QString res_str = result.join(QSL("\n")); + QString res_str = result.join(QSL("\n")); - if (m_updatedFeeds.size() > how_many_feeds) { - res_str += QObject::tr("\n\n+ %n other feeds.", 0, m_updatedFeeds.size() - how_many_feeds); - } + if (m_updatedFeeds.size() > how_many_feeds) { + res_str += QObject::tr("\n\n+ %n other feeds.", 0, m_updatedFeeds.size() - how_many_feeds); + } - return res_str; + return res_str; } void FeedDownloadResults::appendUpdatedFeed(const QPair& feed) { - m_updatedFeeds.append(feed); + m_updatedFeeds.append(feed); } void FeedDownloadResults::sort() { - qSort(m_updatedFeeds.begin(), m_updatedFeeds.end(), FeedDownloadResults::lessThan); + qSort(m_updatedFeeds.begin(), m_updatedFeeds.end(), FeedDownloadResults::lessThan); } bool FeedDownloadResults::lessThan(const QPair& lhs, const QPair& rhs) { - return lhs.second > rhs.second; + return lhs.second > rhs.second; } void FeedDownloadResults::clear() { - m_updatedFeeds.clear(); + m_updatedFeeds.clear(); } QList> FeedDownloadResults::updatedFeeds() const { - return m_updatedFeeds; + return m_updatedFeeds; } diff --git a/src/core/feeddownloader.h b/src/core/feeddownloader.h index ddb1e64ee..5779d1035 100755 --- a/src/core/feeddownloader.h +++ b/src/core/feeddownloader.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -24,81 +25,83 @@ #include "core/message.h" - class Feed; class QThreadPool; class QMutex; // Represents results of batch feed updates. class FeedDownloadResults { - public: - explicit FeedDownloadResults(); + public: + explicit FeedDownloadResults(); - QList> updatedFeeds() const; - QString overview(int how_many_feeds) const; + QList> updatedFeeds() const; + QString overview(int how_many_feeds) const; - void appendUpdatedFeed(const QPair& feed); - void sort(); - void clear(); + void appendUpdatedFeed(const QPair& feed); + void sort(); + void clear(); - static bool lessThan(const QPair& lhs, const QPair& rhs); + static bool lessThan(const QPair& lhs, const QPair& rhs); - private: - // QString represents title if the feed, int represents count of newly downloaded messages. - QList> m_updatedFeeds; + private: + + // QString represents title if the feed, int represents count of newly downloaded messages. + QList> m_updatedFeeds; }; // This class offers means to "update" feeds and "special" categories. // NOTE: This class is used within separate thread. class FeedDownloader : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit FeedDownloader(QObject* parent = 0); - virtual ~FeedDownloader(); + public: - bool isUpdateRunning() const; + // Constructors and destructors. + explicit FeedDownloader(QObject* parent = 0); + virtual ~FeedDownloader(); - public slots: - // Performs update of all feeds from the "feeds" parameter. - // New messages are downloaded for each feed and they - // are stored persistently in the database. - // Appropriate signals are emitted. - void updateFeeds(const QList& feeds); + bool isUpdateRunning() const; - // Stops running update. - void stopRunningUpdate(); + public slots: - private slots: - void oneFeedUpdateFinished(const QList& messages, bool error_during_obtaining); + // Performs update of all feeds from the "feeds" parameter. + // New messages are downloaded for each feed and they + // are stored persistently in the database. + // Appropriate signals are emitted. + void updateFeeds(const QList& feeds); - signals: - // Emitted if feed updates started. - void updateStarted(); + // Stops running update. + void stopRunningUpdate(); - // Emitted if all items from update queue are - // processed. - void updateFinished(FeedDownloadResults updated_feeds); + private slots: + void oneFeedUpdateFinished(const QList& messages, bool error_during_obtaining); - // Emitted if any item is processed. - // "Current" number indicates count of processed feeds - // and "total" number indicates total number of feeds - // which were in the initial queue. - void updateProgress(const Feed* feed, int current, int total); + signals: - private: - void updateAvailableFeeds(); - void finalizeUpdate(); + // Emitted if feed updates started. + void updateStarted(); - QList m_feeds; - QMutex* m_mutex; - QThreadPool* m_threadPool; - FeedDownloadResults m_results; + // Emitted if all items from update queue are + // processed. + void updateFinished(FeedDownloadResults updated_feeds); - int m_feedsUpdated; - int m_feedsUpdating; - int m_feedsOriginalCount; + // Emitted if any item is processed. + // "Current" number indicates count of processed feeds + // and "total" number indicates total number of feeds + // which were in the initial queue. + void updateProgress(const Feed* feed, int current, int total); + + private: + void updateAvailableFeeds(); + void finalizeUpdate(); + + QList m_feeds; + QMutex* m_mutex; + QThreadPool* m_threadPool; + FeedDownloadResults m_results; + int m_feedsUpdated; + int m_feedsUpdating; + int m_feedsOriginalCount; }; #endif // FEEDDOWNLOADER_H diff --git a/src/core/feedsproxymodel.cpp b/src/core/feedsproxymodel.cpp index 40c223490..feffec249 100755 --- a/src/core/feedsproxymodel.cpp +++ b/src/core/feedsproxymodel.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,254 +18,256 @@ #include "core/feedsproxymodel.h" +#include "core/feedsmodel.h" #include "definitions/definitions.h" #include "miscellaneous/application.h" -#include "core/feedsmodel.h" #include "services/abstract/rootitem.h" #include - FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent) - : QSortFilterProxyModel(parent), m_sourceModel(source_model), m_selectedItem(nullptr), - m_showUnreadOnly(false), m_hiddenIndices(QList>()) { - setObjectName(QSL("FeedsProxyModel")); - setSortRole(Qt::EditRole); - setSortCaseSensitivity(Qt::CaseInsensitive); - setFilterCaseSensitivity(Qt::CaseInsensitive); - setFilterKeyColumn(-1); - setFilterRole(Qt::EditRole); - setDynamicSortFilter(true); - setSourceModel(m_sourceModel); + : QSortFilterProxyModel(parent), m_sourceModel(source_model), m_selectedItem(nullptr), + m_showUnreadOnly(false), m_hiddenIndices(QList>()) { + setObjectName(QSL("FeedsProxyModel")); + setSortRole(Qt::EditRole); + setSortCaseSensitivity(Qt::CaseInsensitive); + setFilterCaseSensitivity(Qt::CaseInsensitive); + setFilterKeyColumn(-1); + setFilterRole(Qt::EditRole); + setDynamicSortFilter(true); + setSourceModel(m_sourceModel); } FeedsProxyModel::~FeedsProxyModel() { - qDebug("Destroying FeedsProxyModel instance"); + qDebug("Destroying FeedsProxyModel instance"); } QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const { - QModelIndexList result; - const uint match_type = flags & 0x0F; - const Qt::CaseSensitivity cs = Qt::CaseInsensitive; - const bool recurse = flags & Qt::MatchRecursive; - const bool wrap = flags & Qt::MatchWrap; - const bool all_hits = (hits == -1); - QString entered_text; - const QModelIndex p = parent(start); - int from = start.row(); - int to = rowCount(p); + QModelIndexList result; + const uint match_type = flags & 0x0F; + const Qt::CaseSensitivity cs = Qt::CaseInsensitive; + const bool recurse = flags & Qt::MatchRecursive; + const bool wrap = flags & Qt::MatchWrap; + const bool all_hits = (hits == -1); + QString entered_text; + const QModelIndex p = parent(start); + int from = start.row(); + int to = rowCount(p); - for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) { - for (int r = from; (r < to) && (all_hits || result.count() < hits); ++r) { - QModelIndex idx = index(r, start.column(), p); + for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) { + for (int r = from; (r < to) && (all_hits || result.count() < hits); ++r) { + QModelIndex idx = index(r, start.column(), p); - if (!idx.isValid()) { - continue; - } + if (!idx.isValid()) { + continue; + } - QModelIndex mapped_idx = mapToSource(idx); - QVariant item_value = m_sourceModel->itemForIndex(mapped_idx)->title(); + QModelIndex mapped_idx = mapToSource(idx); + QVariant item_value = m_sourceModel->itemForIndex(mapped_idx)->title(); - // QVariant based matching. - if (match_type == Qt::MatchExactly) { - if (value == item_value) { - result.append(idx); - } - } - // QString based matching. - else { - if (entered_text.isEmpty()) { - entered_text = value.toString(); - } + // QVariant based matching. + if (match_type == Qt::MatchExactly) { + if (value == item_value) { + result.append(idx); + } + } - QString item_text = item_value.toString(); + // QString based matching. + else { + if (entered_text.isEmpty()) { + entered_text = value.toString(); + } - switch (match_type) { - case Qt::MatchRegExp: - if (QRegExp(entered_text, cs).exactMatch(item_text)) { - result.append(idx); - } + QString item_text = item_value.toString(); - break; + switch (match_type) { + case Qt::MatchRegExp: + if (QRegExp(entered_text, cs).exactMatch(item_text)) { + result.append(idx); + } - case Qt::MatchWildcard: - if (QRegExp(entered_text, cs, QRegExp::Wildcard).exactMatch(item_text)) { - result.append(idx); - } + break; - break; + case Qt::MatchWildcard: + if (QRegExp(entered_text, cs, QRegExp::Wildcard).exactMatch(item_text)) { + result.append(idx); + } - case Qt::MatchStartsWith: - if (item_text.startsWith(entered_text, cs)) { - result.append(idx); - } + break; - break; + case Qt::MatchStartsWith: + if (item_text.startsWith(entered_text, cs)) { + result.append(idx); + } - case Qt::MatchEndsWith: - if (item_text.endsWith(entered_text, cs)) { - result.append(idx); - } + break; - break; + case Qt::MatchEndsWith: + if (item_text.endsWith(entered_text, cs)) { + result.append(idx); + } - case Qt::MatchFixedString: - if (item_text.compare(entered_text, cs) == 0) { - result.append(idx); - } + break; - break; + case Qt::MatchFixedString: + if (item_text.compare(entered_text, cs) == 0) { + result.append(idx); + } - case Qt::MatchContains: - default: - if (item_text.contains(entered_text, cs)) { - result.append(idx); - } + break; - break; - } - } + case Qt::MatchContains: + default: + if (item_text.contains(entered_text, cs)) { + result.append(idx); + } - if (recurse && hasChildren(idx)) { - result += match(index(0, idx.column(), idx), role, (entered_text.isEmpty() ? value : entered_text), (all_hits ? -1 : hits - result.count()), - flags); - } - } + break; + } + } - from = 0; - to = start.row(); - } + if (recurse && hasChildren(idx)) { + result += + match(index(0, idx.column(), idx), role, (entered_text.isEmpty() ? value : entered_text), (all_hits ? -1 : hits - result.count()), + flags); + } + } - return result; + from = 0; + to = start.row(); + } + + return result; } bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const { - if (left.isValid() && right.isValid()) { - // Make necessary castings. - const RootItem* left_item = m_sourceModel->itemForIndex(left); - const RootItem* right_item = m_sourceModel->itemForIndex(right); + if (left.isValid() && right.isValid()) { + // Make necessary castings. + const RootItem* left_item = m_sourceModel->itemForIndex(left); + const RootItem* right_item = m_sourceModel->itemForIndex(right); - // NOTE: Here we want to accomplish that ALL - // categories are queued one after another and all - // feeds are queued one after another too. - // Moreover, sort everything alphabetically or - // by item counts, depending on the sort column. + // NOTE: Here we want to accomplish that ALL + // categories are queued one after another and all + // feeds are queued one after another too. + // Moreover, sort everything alphabetically or + // by item counts, depending on the sort column. - if (left_item->kind() == right_item->kind()) { - // Both items are feeds or both items are categories. - if (left.column() == FDS_MODEL_COUNTS_INDEX) { - // User wants to sort according to counts. - return left_item->countOfUnreadMessages() < right_item->countOfUnreadMessages(); - } - else { - // In other cases, sort by title. - return QString::localeAwareCompare(left_item->title(), right_item->title()) < 0; - } - } - else if (left_item->kind() == RootItemKind::Bin) { - // Left item is recycle bin. Make sure it is "biggest" item if we have selected ascending order. - return sortOrder() == Qt::DescendingOrder; - } - else if (right_item->kind() == RootItemKind::Bin) { - // Right item is recycle bin. Make sure it is "smallest" item if we have selected descending order. - return sortOrder() == Qt::AscendingOrder; - } - else if (left_item->kind() == RootItemKind::Feed) { - // Left item is feed, right item is category. - return false; - } - else { - // Left item is category, right item is feed. - // NOTE: Category is in fact "more" than feed but we consider it to be "less" because it should be "placed" - // above the "smalles" feed when ascending sort is used. - // NOTE: We need to keep recycle bin in first position. - return true; - } - } - else { - return false; - } + if (left_item->kind() == right_item->kind()) { + // Both items are feeds or both items are categories. + if (left.column() == FDS_MODEL_COUNTS_INDEX) { + // User wants to sort according to counts. + return left_item->countOfUnreadMessages() < right_item->countOfUnreadMessages(); + } + else { + // In other cases, sort by title. + return QString::localeAwareCompare(left_item->title(), right_item->title()) < 0; + } + } + else if (left_item->kind() == RootItemKind::Bin) { + // Left item is recycle bin. Make sure it is "biggest" item if we have selected ascending order. + return sortOrder() == Qt::DescendingOrder; + } + else if (right_item->kind() == RootItemKind::Bin) { + // Right item is recycle bin. Make sure it is "smallest" item if we have selected descending order. + return sortOrder() == Qt::AscendingOrder; + } + else if (left_item->kind() == RootItemKind::Feed) { + // Left item is feed, right item is category. + return false; + } + else { + // Left item is category, right item is feed. + // NOTE: Category is in fact "more" than feed but we consider it to be "less" because it should be "placed" + // above the "smalles" feed when ascending sort is used. + // NOTE: We need to keep recycle bin in first position. + return true; + } + } + else { + return false; + } } bool FeedsProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const { - bool should_show = filterAcceptsRowInternal(source_row, source_parent); + bool should_show = filterAcceptsRowInternal(source_row, source_parent); - if (should_show && m_hiddenIndices.contains(QPair(source_row, source_parent))) { - const_cast(this)->m_hiddenIndices.removeAll(QPair(source_row, source_parent)); - // Load status. - emit expandAfterFilterIn(m_sourceModel->index(source_row, 0, source_parent)); - } + if (should_show && m_hiddenIndices.contains(QPair(source_row, source_parent))) { + const_cast(this)->m_hiddenIndices.removeAll(QPair(source_row, source_parent)); - if (!should_show) { - const_cast(this)->m_hiddenIndices.append(QPair(source_row, source_parent)); - } + // Load status. + emit expandAfterFilterIn(m_sourceModel->index(source_row, 0, source_parent)); + } - return should_show; + if (!should_show) { + const_cast(this)->m_hiddenIndices.append(QPair(source_row, source_parent)); + } + + return should_show; } bool FeedsProxyModel::filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const { - if (!m_showUnreadOnly) { - return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); - } + if (!m_showUnreadOnly) { + return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); + } - const QModelIndex idx = m_sourceModel->index(source_row, 0, source_parent); + const QModelIndex idx = m_sourceModel->index(source_row, 0, source_parent); - if (!idx.isValid()) { - return false; - } + if (!idx.isValid()) { + return false; + } - const RootItem* item = m_sourceModel->itemForIndex(idx); + const RootItem* item = m_sourceModel->itemForIndex(idx); - if (item->kind() == RootItemKind::Bin || item->kind() == RootItemKind::ServiceRoot) { - // Recycle bin is always displayed. - return true; - } - else if (item->isParentOf(m_selectedItem)/* || item->isChildOf(m_selectedItem)*/ || m_selectedItem == item) { - // Currently selected item and all its parents and children must be displayed. - return true; - } - else { - // NOTE: If item has < 0 of unread message it may mean, that the count - // of unread messages is not (yet) known, display that item too. - return item->countOfUnreadMessages() != 0; - } + if (item->kind() == RootItemKind::Bin || item->kind() == RootItemKind::ServiceRoot) { + // Recycle bin is always displayed. + return true; + } + else if (item->isParentOf(m_selectedItem) /* || item->isChildOf(m_selectedItem)*/ || m_selectedItem == item) { + // Currently selected item and all its parents and children must be displayed. + return true; + } + else { + // NOTE: If item has < 0 of unread message it may mean, that the count + // of unread messages is not (yet) known, display that item too. + return item->countOfUnreadMessages() != 0; + } } const RootItem* FeedsProxyModel::selectedItem() const { - return m_selectedItem; + return m_selectedItem; } void FeedsProxyModel::setSelectedItem(const RootItem* selected_item) { - m_selectedItem = selected_item; + m_selectedItem = selected_item; } bool FeedsProxyModel::showUnreadOnly() const { - return m_showUnreadOnly; + return m_showUnreadOnly; } void FeedsProxyModel::invalidateReadFeedsFilter(bool set_new_value, bool show_unread_only) { - if (set_new_value) { - setShowUnreadOnly(show_unread_only); - } + if (set_new_value) { + setShowUnreadOnly(show_unread_only); + } - QTimer::singleShot(0, this, &FeedsProxyModel::invalidateFilter); + QTimer::singleShot(0, this, &FeedsProxyModel::invalidateFilter); } void FeedsProxyModel::setShowUnreadOnly(bool show_unread_only) { - m_showUnreadOnly = show_unread_only; - qApp->settings()->setValue(GROUP(Feeds), Feeds::ShowOnlyUnreadFeeds, show_unread_only); + m_showUnreadOnly = show_unread_only; + qApp->settings()->setValue(GROUP(Feeds), Feeds::ShowOnlyUnreadFeeds, show_unread_only); } QModelIndexList FeedsProxyModel::mapListToSource(const QModelIndexList& indexes) const { - QModelIndexList source_indexes; + QModelIndexList source_indexes; - foreach (const QModelIndex& index, indexes) { - source_indexes << mapToSource(index); - } + foreach (const QModelIndex& index, indexes) { + source_indexes << mapToSource(index); + } - return source_indexes; + return source_indexes; } void FeedsProxyModel::invalidateFilter() { - QSortFilterProxyModel::invalidateFilter(); + QSortFilterProxyModel::invalidateFilter(); } diff --git a/src/core/feedsproxymodel.h b/src/core/feedsproxymodel.h index cce824e4d..c468c92fa 100755 --- a/src/core/feedsproxymodel.h +++ b/src/core/feedsproxymodel.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,51 +21,54 @@ #include - class FeedsModel; class RootItem; class FeedsProxyModel : public QSortFilterProxyModel { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = 0); - virtual ~FeedsProxyModel(); + public: - // Returns index list of items which "match" given value. - // Used for finding items according to entered title text. - QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const; + // Constructors and destructors. + explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = 0); + virtual ~FeedsProxyModel(); - // Maps list of indexes. - QModelIndexList mapListToSource(const QModelIndexList& indexes) const; + // Returns index list of items which "match" given value. + // Used for finding items according to entered title text. + QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const; - bool showUnreadOnly() const; - void setShowUnreadOnly(bool show_unread_only); + // Maps list of indexes. + QModelIndexList mapListToSource(const QModelIndexList& indexes) const; - const RootItem* selectedItem() const; - void setSelectedItem(const RootItem* selected_item); + bool showUnreadOnly() const; + void setShowUnreadOnly(bool show_unread_only); - public slots: - void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false); + const RootItem* selectedItem() const; - private slots: - void invalidateFilter(); + void setSelectedItem(const RootItem* selected_item); - signals: - void expandAfterFilterIn(QModelIndex idx) const; + public slots: + void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false); - private: - // Compares two rows of data. - bool lessThan(const QModelIndex& left, const QModelIndex& right) const; - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; - bool filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const; + private slots: + void invalidateFilter(); - // Source model pointer. - FeedsModel* m_sourceModel; - const RootItem* m_selectedItem; - bool m_showUnreadOnly; - QList> m_hiddenIndices; + signals: + void expandAfterFilterIn(QModelIndex idx) const; + + private: + + // Compares two rows of data. + bool lessThan(const QModelIndex& left, const QModelIndex& right) const; + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; + bool filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const; + + // Source model pointer. + FeedsModel* m_sourceModel; + const RootItem* m_selectedItem; + bool m_showUnreadOnly; + + QList> m_hiddenIndices; }; #endif // FEEDSPROXYMODEL_H diff --git a/src/core/message.cpp b/src/core/message.cpp index 18e897e88..4008267da 100755 --- a/src/core/message.cpp +++ b/src/core/message.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,81 +22,81 @@ #include - -Enclosure::Enclosure(const QString& url, const QString& mime) : m_url(url), m_mimeType(mime) { -} +Enclosure::Enclosure(const QString& url, const QString& mime) : m_url(url), m_mimeType(mime) {} QList Enclosures::decodeEnclosuresFromString(const QString& enclosures_data) { - QList enclosures; + QList enclosures; - foreach (const QString& single_enclosure, enclosures_data.split(ENCLOSURES_OUTER_SEPARATOR, QString::SkipEmptyParts)) { - Enclosure enclosure; + foreach (const QString& single_enclosure, enclosures_data.split(ENCLOSURES_OUTER_SEPARATOR, QString::SkipEmptyParts)) { + Enclosure enclosure; - if (single_enclosure.contains(ECNLOSURES_INNER_SEPARATOR)) { - QStringList mime_url = single_enclosure.split(ECNLOSURES_INNER_SEPARATOR); - enclosure.m_mimeType = QByteArray::fromBase64(mime_url.at(0).toLocal8Bit()); - enclosure.m_url = QByteArray::fromBase64(mime_url.at(1).toLocal8Bit()); - } - else { - enclosure.m_url = QByteArray::fromBase64(single_enclosure.toLocal8Bit()); - } + if (single_enclosure.contains(ECNLOSURES_INNER_SEPARATOR)) { + QStringList mime_url = single_enclosure.split(ECNLOSURES_INNER_SEPARATOR); - enclosures.append(enclosure); - } + enclosure.m_mimeType = QByteArray::fromBase64(mime_url.at(0).toLocal8Bit()); + enclosure.m_url = QByteArray::fromBase64(mime_url.at(1).toLocal8Bit()); + } + else { + enclosure.m_url = QByteArray::fromBase64(single_enclosure.toLocal8Bit()); + } - return enclosures; + enclosures.append(enclosure); + } + + return enclosures; } QString Enclosures::encodeEnclosuresToString(const QList& enclosures) { - QStringList enclosures_str; + QStringList enclosures_str; - foreach (const Enclosure& enclosure, enclosures) { - if (enclosure.m_mimeType.isEmpty()) { - enclosures_str.append(enclosure.m_url.toLocal8Bit().toBase64()); - } - else { - enclosures_str.append(QString(enclosure.m_mimeType.toLocal8Bit().toBase64()) + - ECNLOSURES_INNER_SEPARATOR + - enclosure.m_url.toLocal8Bit().toBase64()); - } - } + foreach (const Enclosure& enclosure, enclosures) { + if (enclosure.m_mimeType.isEmpty()) { + enclosures_str.append(enclosure.m_url.toLocal8Bit().toBase64()); + } + else { + enclosures_str.append(QString(enclosure.m_mimeType.toLocal8Bit().toBase64()) + + ECNLOSURES_INNER_SEPARATOR + + enclosure.m_url.toLocal8Bit().toBase64()); + } + } - return enclosures_str.join(QString(ENCLOSURES_OUTER_SEPARATOR)); + return enclosures_str.join(QString(ENCLOSURES_OUTER_SEPARATOR)); } Message::Message() { - m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = QSL(""); - m_enclosures = QList(); - m_accountId = m_id = 0; - m_isRead = m_isImportant = false; + m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = QSL(""); + m_enclosures = QList(); + m_accountId = m_id = 0; + m_isRead = m_isImportant = false; } Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) { - if (record.count() != MSG_DB_CUSTOM_HASH_INDEX + 1) { - if (result != nullptr) { - *result = false; - return Message(); - } - } + if (record.count() != MSG_DB_CUSTOM_HASH_INDEX + 1) { + if (result != nullptr) { + *result = false; + return Message(); + } + } - Message message; - message.m_id = record.value(MSG_DB_ID_INDEX).toInt(); - message.m_isRead = record.value(MSG_DB_READ_INDEX).toBool(); - message.m_isImportant = record.value(MSG_DB_IMPORTANT_INDEX).toBool(); - message.m_feedId = record.value(MSG_DB_FEED_CUSTOM_ID_INDEX).toString(); - message.m_title = record.value(MSG_DB_TITLE_INDEX).toString(); - message.m_url = record.value(MSG_DB_URL_INDEX).toString(); - message.m_author = record.value(MSG_DB_AUTHOR_INDEX).toString(); - message.m_created = TextFactory::parseDateTime(record.value(MSG_DB_DCREATED_INDEX).value()); - message.m_contents = record.value(MSG_DB_CONTENTS_INDEX).toString(); - message.m_enclosures = Enclosures::decodeEnclosuresFromString(record.value(MSG_DB_ENCLOSURES_INDEX).toString()); - message.m_accountId = record.value(MSG_DB_ACCOUNT_ID_INDEX).toInt(); - message.m_customId = record.value(MSG_DB_CUSTOM_ID_INDEX).toString(); - message.m_customHash = record.value(MSG_DB_CUSTOM_HASH_INDEX).toString(); + Message message; - if (result != nullptr) { - *result = true; - } + message.m_id = record.value(MSG_DB_ID_INDEX).toInt(); + message.m_isRead = record.value(MSG_DB_READ_INDEX).toBool(); + message.m_isImportant = record.value(MSG_DB_IMPORTANT_INDEX).toBool(); + message.m_feedId = record.value(MSG_DB_FEED_CUSTOM_ID_INDEX).toString(); + message.m_title = record.value(MSG_DB_TITLE_INDEX).toString(); + message.m_url = record.value(MSG_DB_URL_INDEX).toString(); + message.m_author = record.value(MSG_DB_AUTHOR_INDEX).toString(); + message.m_created = TextFactory::parseDateTime(record.value(MSG_DB_DCREATED_INDEX).value()); + message.m_contents = record.value(MSG_DB_CONTENTS_INDEX).toString(); + message.m_enclosures = Enclosures::decodeEnclosuresFromString(record.value(MSG_DB_ENCLOSURES_INDEX).toString()); + message.m_accountId = record.value(MSG_DB_ACCOUNT_ID_INDEX).toInt(); + message.m_customId = record.value(MSG_DB_CUSTOM_ID_INDEX).toString(); + message.m_customHash = record.value(MSG_DB_CUSTOM_HASH_INDEX).toString(); + + if (result != nullptr) { + *result = true; + } return message; } @@ -135,10 +136,10 @@ QDataStream& operator>>(QDataStream& in, Message& myObj) { } uint qHash(Message key, uint seed) { - Q_UNUSED(seed) - return (key.m_accountId * 10000) + key.m_id; + Q_UNUSED(seed) + return (key.m_accountId * 10000) + key.m_id; } uint qHash(const Message& key) { - return (key.m_accountId * 10000) + key.m_id; + return (key.m_accountId * 10000) + key.m_id; } diff --git a/src/core/message.h b/src/core/message.h index d65084afa..2f5c0bef1 100755 --- a/src/core/message.h +++ b/src/core/message.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,64 +21,62 @@ #include "definitions/definitions.h" -#include -#include -#include #include - +#include +#include +#include // Represents single enclosure. struct Enclosure { - public: - explicit Enclosure(const QString& url = QString(), const QString& mime = QString()); + public: + explicit Enclosure(const QString& url = QString(), const QString& mime = QString()); - QString m_url; - QString m_mimeType; + QString m_url; + QString m_mimeType; }; // Represents single enclosure. class Enclosures { - public: - static QList decodeEnclosuresFromString(const QString& enclosures_data); - static QString encodeEnclosuresToString(const QList& enclosures); + public: + static QList decodeEnclosuresFromString(const QString& enclosures_data); + static QString encodeEnclosuresToString(const QList& enclosures); }; // Represents single message. class Message { - public: - explicit Message(); + public: + explicit Message(); - // Creates Message from given record, which contains - // row from query SELECT * FROM Messages WHERE ....; - static Message fromSqlRecord(const QSqlRecord& record, bool* result = nullptr); + // Creates Message from given record, which contains + // row from query SELECT * FROM Messages WHERE ....; + static Message fromSqlRecord(const QSqlRecord& record, bool* result = nullptr); + QString m_title; + QString m_url; + QString m_author; + QString m_contents; + QDateTime m_created; + QString m_feedId; + int m_accountId; + int m_id; + QString m_customId; + QString m_customHash; + bool m_isRead; + bool m_isImportant; - QString m_title; - QString m_url; - QString m_author; - QString m_contents; - QDateTime m_created; - QString m_feedId; - int m_accountId; - int m_id; - QString m_customId; - QString m_customHash; + QList m_enclosures; - bool m_isRead; - bool m_isImportant; + // Is true if "created" date was obtained directly + // from the feed, otherwise is false + bool m_createdFromFeed; - QList m_enclosures; + friend inline bool operator==(const Message& lhs, const Message& rhs) { + return lhs.m_accountId == rhs.m_accountId && lhs.m_id == rhs.m_id; + } - // Is true if "created" date was obtained directly - // from the feed, otherwise is false - bool m_createdFromFeed; + friend inline bool operator!=(const Message& lhs, const Message& rhs) { + return !(lhs == rhs); + } - friend inline bool operator==(const Message& lhs, const Message& rhs) { - return lhs.m_accountId == rhs.m_accountId && lhs.m_id == rhs.m_id; - } - - friend inline bool operator!=(const Message& lhs, const Message& rhs) { - return !(lhs == rhs); - } }; // Serialize message state. diff --git a/src/core/messagesmodel.cpp b/src/core/messagesmodel.cpp index 473201441..7a3610cd0 100755 --- a/src/core/messagesmodel.cpp +++ b/src/core/messagesmodel.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,519 +18,549 @@ #include "core/messagesmodel.h" +#include "core/messagesmodelcache.h" #include "definitions/definitions.h" #include "miscellaneous/application.h" -#include "miscellaneous/textfactory.h" #include "miscellaneous/databasefactory.h" -#include "miscellaneous/iconfactory.h" #include "miscellaneous/databasequeries.h" -#include "services/abstract/serviceroot.h" -#include "core/messagesmodelcache.h" +#include "miscellaneous/iconfactory.h" +#include "miscellaneous/textfactory.h" #include "services/abstract/recyclebin.h" +#include "services/abstract/serviceroot.h" #include - MessagesModel::MessagesModel(QObject* parent) - : QSqlQueryModel(parent), MessagesModelSqlLayer(), - m_cache(new MessagesModelCache(this)), m_messageHighlighter(NoHighlighting), m_customDateFormat(QString()) { - setupFonts(); - setupIcons(); - setupHeaderData(); - updateDateFormat(); - loadMessages(nullptr); + : QSqlQueryModel(parent), MessagesModelSqlLayer(), + m_cache(new MessagesModelCache(this)), m_messageHighlighter(NoHighlighting), m_customDateFormat(QString()) { + setupFonts(); + setupIcons(); + setupHeaderData(); + updateDateFormat(); + loadMessages(nullptr); } MessagesModel::~MessagesModel() { - qDebug("Destroying MessagesModel instance."); + qDebug("Destroying MessagesModel instance."); } void MessagesModel::setupIcons() { - m_favoriteIcon = qApp->icons()->fromTheme(QSL("mail-mark-important")); - m_readIcon = qApp->icons()->fromTheme(QSL("mail-mark-read")); - m_unreadIcon = qApp->icons()->fromTheme(QSL("mail-mark-unread")); + m_favoriteIcon = qApp->icons()->fromTheme(QSL("mail-mark-important")); + m_readIcon = qApp->icons()->fromTheme(QSL("mail-mark-read")); + m_unreadIcon = qApp->icons()->fromTheme(QSL("mail-mark-unread")); } void MessagesModel::repopulate() { - m_cache->clear(); - setQuery(selectStatement(), m_db); + m_cache->clear(); + setQuery(selectStatement(), m_db); - while (canFetchMore()) { - fetchMore(); - } + while (canFetchMore()) { + fetchMore(); + } } bool MessagesModel::setData(const QModelIndex& index, const QVariant& value, int role) { - Q_UNUSED(role) - m_cache->setData(index, value, record(index.row())); - return true; + Q_UNUSED(role) + m_cache->setData(index, value, record(index.row())); + return true; } - void MessagesModel::setupFonts() { - m_normalFont = Application::font("MessagesView"); - m_boldFont = m_normalFont; - m_boldFont.setBold(true); - m_normalStrikedFont = m_normalFont; - m_boldStrikedFont = m_boldFont; - m_normalStrikedFont.setStrikeOut(true); - m_boldStrikedFont.setStrikeOut(true); + m_normalFont = Application::font("MessagesView"); + m_boldFont = m_normalFont; + m_boldFont.setBold(true); + m_normalStrikedFont = m_normalFont; + m_boldStrikedFont = m_boldFont; + m_normalStrikedFont.setStrikeOut(true); + m_boldStrikedFont.setStrikeOut(true); } void MessagesModel::loadMessages(RootItem* item) { - m_selectedItem = item; + m_selectedItem = item; - if (item == nullptr) { - setFilter(QSL(DEFAULT_SQL_MESSAGES_FILTER)); - } - else { - if (!item->getParentServiceRoot()->loadMessagesForItem(item, this)) { - setFilter(QSL("true != true")); - qWarning("Loading of messages from item '%s' failed.", qPrintable(item->title())); - qApp->showGuiMessage(tr("Loading of messages from item '%1' failed.").arg(item->title()), - tr("Loading of messages failed, maybe messages could not be downloaded."), - QSystemTrayIcon::Critical, - qApp->mainFormWidget(), - true); - } - } + if (item == nullptr) { + setFilter(QSL(DEFAULT_SQL_MESSAGES_FILTER)); + } + else { + if (!item->getParentServiceRoot()->loadMessagesForItem(item, this)) { + setFilter(QSL("true != true")); + qWarning("Loading of messages from item '%s' failed.", qPrintable(item->title())); + qApp->showGuiMessage(tr("Loading of messages from item '%1' failed.").arg(item->title()), + tr("Loading of messages failed, maybe messages could not be downloaded."), + QSystemTrayIcon::Critical, + qApp->mainFormWidget(), + true); + } + } - repopulate(); + repopulate(); } bool MessagesModel::setMessageImportantById(int id, RootItem::Importance important) { - for (int i = 0; i < rowCount(); i++) { - int found_id = data(i, MSG_DB_ID_INDEX, Qt::EditRole).toInt(); + for (int i = 0; i < rowCount(); i++) { + int found_id = data(i, MSG_DB_ID_INDEX, Qt::EditRole).toInt(); - if (found_id == id) { - bool set = setData(index(i, MSG_DB_IMPORTANT_INDEX), important); + if (found_id == id) { + bool set = setData(index(i, MSG_DB_IMPORTANT_INDEX), important); - if (set) { - emit dataChanged(index(i, 0), index(i, MSG_DB_CUSTOM_HASH_INDEX)); - } + if (set) { + emit dataChanged(index(i, 0), index(i, MSG_DB_CUSTOM_HASH_INDEX)); + } - return set; - } - } + return set; + } + } - return false; + return false; } void MessagesModel::highlightMessages(MessagesModel::MessageHighlighter highlight) { - m_messageHighlighter = highlight; - emit layoutAboutToBeChanged(); - emit layoutChanged(); + m_messageHighlighter = highlight; + emit layoutAboutToBeChanged(); + emit layoutChanged(); } int MessagesModel::messageId(int row_index) const { - return data(row_index, MSG_DB_ID_INDEX, Qt::EditRole).toInt(); + return data(row_index, MSG_DB_ID_INDEX, Qt::EditRole).toInt(); } RootItem::Importance MessagesModel::messageImportance(int row_index) const { - return (RootItem::Importance) data(row_index, MSG_DB_IMPORTANT_INDEX, Qt::EditRole).toInt(); + return (RootItem::Importance) data(row_index, MSG_DB_IMPORTANT_INDEX, Qt::EditRole).toInt(); } RootItem* MessagesModel::loadedItem() const { - return m_selectedItem; + return m_selectedItem; } void MessagesModel::updateDateFormat() { - if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool()) { - m_customDateFormat = qApp->settings()->value(GROUP(Messages), SETTING(Messages::CustomDateFormat)).toString(); - } - else { - m_customDateFormat = QString(); - } + if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool()) { + m_customDateFormat = qApp->settings()->value(GROUP(Messages), SETTING(Messages::CustomDateFormat)).toString(); + } + else { + m_customDateFormat = QString(); + } } void MessagesModel::reloadWholeLayout() { - emit layoutAboutToBeChanged(); - emit layoutChanged(); + emit layoutAboutToBeChanged(); + emit layoutChanged(); } Message MessagesModel::messageAt(int row_index) const { - return Message::fromSqlRecord(m_cache->containsData(row_index) ? m_cache->record(row_index) : record(row_index)); + return Message::fromSqlRecord(m_cache->containsData(row_index) ? m_cache->record(row_index) : record(row_index)); } void MessagesModel::setupHeaderData() { - m_headerData << /*: Tooltip for ID of message.*/ tr("Id") << - /*: Tooltip for "read" column in msg list.*/ tr("Read") << - /*: Tooltip for "deleted" column in msg list.*/ tr("Deleted") << - /*: Tooltip for "important" column in msg list.*/ tr("Important") << - /*: Tooltip for name of feed for message.*/ tr("Feed") << - /*: Tooltip for title of message.*/ tr("Title") << - /*: Tooltip for url of message.*/ tr("Url") << - /*: Tooltip for author of message.*/ tr("Author") << - /*: Tooltip for creation date of message.*/ tr("Created on") << - /*: Tooltip for contents of message.*/ tr("Contents") << - /*: Tooltip for "pdeleted" column in msg list.*/ tr("Permanently deleted") << - /*: Tooltip for attachments of message.*/ tr("Attachments") << - /*: Tooltip for account ID of message.*/ tr("Account ID") << - /*: Tooltip for custom ID of message.*/ tr("Custom ID") << - /*: Tooltip for custom hash string of message.*/ tr("Custom hash") << - /*: Tooltip for custom ID of feed of message.*/ tr("Feed ID");; - m_tooltipData << tr("Id of the message.") << tr("Is message read?") << - tr("Is message deleted?") << tr("Is message important?") << - tr("Id of feed which this message belongs to.") << - tr("Title of the message.") << tr("Url of the message.") << - tr("Author of the message.") << tr("Creation date of the message.") << - tr("Contents of the message.") << tr("Is message permanently deleted from recycle bin?") << - tr("List of attachments.") << tr("Account ID of the message.") << tr("Custom ID of the message") << - tr("Custom hash of the message.") << tr("Custom ID of feed of the message."); + m_headerData << /*: Tooltip for ID of message.*/ tr("Id") << + + /*: Tooltip for "read" column in msg list.*/ tr("Read") << + + /*: Tooltip for "deleted" column in msg list.*/ tr("Deleted") << + + /*: Tooltip for "important" column in msg list.*/ tr("Important") << + + /*: Tooltip for name of feed for message.*/ tr("Feed") << + + /*: Tooltip for title of message.*/ tr("Title") << + + /*: Tooltip for url of message.*/ tr("Url") << + + /*: Tooltip for author of message.*/ tr("Author") << + + /*: Tooltip for creation date of message.*/ tr("Created on") << + + /*: Tooltip for contents of message.*/ tr("Contents") << + + /*: Tooltip for "pdeleted" column in msg list.*/ tr("Permanently deleted") << + + /*: Tooltip for attachments of message.*/ tr("Attachments") << + + /*: Tooltip for account ID of message.*/ tr("Account ID") << + + /*: Tooltip for custom ID of message.*/ tr("Custom ID") << + + /*: Tooltip for custom hash string of message.*/ tr("Custom hash") << + + /*: Tooltip for custom ID of feed of message.*/ tr("Feed ID");; + m_tooltipData << tr("Id of the message.") << tr("Is message read?") << + tr("Is message deleted?") << tr("Is message important?") << + tr("Id of feed which this message belongs to.") << + tr("Title of the message.") << tr("Url of the message.") << + tr("Author of the message.") << tr("Creation date of the message.") << + tr("Contents of the message.") << tr("Is message permanently deleted from recycle bin?") << + tr("List of attachments.") << tr("Account ID of the message.") << tr("Custom ID of the message") << + tr("Custom hash of the message.") << tr("Custom ID of feed of the message."); } Qt::ItemFlags MessagesModel::flags(const QModelIndex& index) const { - Q_UNUSED(index) - return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemNeverHasChildren; + Q_UNUSED(index) + return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemNeverHasChildren; } QVariant MessagesModel::data(int row, int column, int role) const { - return data(index(row, column), role); + return data(index(row, column), role); } QVariant MessagesModel::data(const QModelIndex& idx, int role) const { - // This message is not in cache, return real data from live query. - switch (role) { - // Human readable data for viewing. - case Qt::DisplayRole: { - int index_column = idx.column(); + // This message is not in cache, return real data from live query. + switch (role) { + // Human readable data for viewing. + case Qt::DisplayRole: { + int index_column = idx.column(); - if (index_column == MSG_DB_DCREATED_INDEX) { - QDateTime dt = TextFactory::parseDateTime(QSqlQueryModel::data(idx, role).value()).toLocalTime(); + if (index_column == MSG_DB_DCREATED_INDEX) { + QDateTime dt = TextFactory::parseDateTime(QSqlQueryModel::data(idx, role).value()).toLocalTime(); - if (m_customDateFormat.isEmpty()) { - return dt.toString(Qt::DefaultLocaleShortDate); - } - else { - return dt.toString(m_customDateFormat); - } - } - else if (index_column == MSG_DB_AUTHOR_INDEX) { - const QString author_name = QSqlQueryModel::data(idx, role).toString(); - return author_name.isEmpty() ? QSL("-") : author_name; - } - else if (index_column != MSG_DB_IMPORTANT_INDEX && index_column != MSG_DB_READ_INDEX) { - return QSqlQueryModel::data(idx, role); - } - else { - return QVariant(); - } - } + if (m_customDateFormat.isEmpty()) { + return dt.toString(Qt::DefaultLocaleShortDate); + } + else { + return dt.toString(m_customDateFormat); + } + } + else if (index_column == MSG_DB_AUTHOR_INDEX) { + const QString author_name = QSqlQueryModel::data(idx, role).toString(); - case Qt::EditRole: - return m_cache->containsData(idx.row()) ? m_cache->data(idx) : QSqlQueryModel::data(idx, role); + return author_name.isEmpty() ? QSL("-") : author_name; + } + else if (index_column != MSG_DB_IMPORTANT_INDEX && index_column != MSG_DB_READ_INDEX) { + return QSqlQueryModel::data(idx, role); + } + else { + return QVariant(); + } + } - case Qt::FontRole: { - QModelIndex idx_read = index(idx.row(), MSG_DB_READ_INDEX); - QVariant data_read = data(idx_read, Qt::EditRole); - const bool is_bin = qobject_cast(loadedItem()) != nullptr; - bool is_deleted; + case Qt::EditRole: + return m_cache->containsData(idx.row()) ? m_cache->data(idx) : QSqlQueryModel::data(idx, role); - if (is_bin) { - QModelIndex idx_del = index(idx.row(), MSG_DB_PDELETED_INDEX); - is_deleted = data(idx_del, Qt::EditRole).toBool(); - } - else { - QModelIndex idx_del = index(idx.row(), MSG_DB_DELETED_INDEX); - is_deleted = data(idx_del, Qt::EditRole).toBool(); - } + case Qt::FontRole: { + QModelIndex idx_read = index(idx.row(), MSG_DB_READ_INDEX); + QVariant data_read = data(idx_read, Qt::EditRole); + const bool is_bin = qobject_cast(loadedItem()) != nullptr; + bool is_deleted; - const bool striked = is_deleted; + if (is_bin) { + QModelIndex idx_del = index(idx.row(), MSG_DB_PDELETED_INDEX); - if (data_read.toBool()) { - return striked ? m_normalStrikedFont : m_normalFont; - } - else { - return striked ? m_boldStrikedFont : m_boldFont; - } - } + is_deleted = data(idx_del, Qt::EditRole).toBool(); + } + else { + QModelIndex idx_del = index(idx.row(), MSG_DB_DELETED_INDEX); - case Qt::ForegroundRole: - switch (m_messageHighlighter) { - case HighlightImportant: { - QModelIndex idx_important = index(idx.row(), MSG_DB_IMPORTANT_INDEX); - QVariant dta = m_cache->containsData(idx_important.row()) ? m_cache->data(idx_important) : QSqlQueryModel::data(idx_important); - return dta.toInt() == 1 ? QColor(Qt::blue) : QVariant(); - } + is_deleted = data(idx_del, Qt::EditRole).toBool(); + } - case HighlightUnread: { - QModelIndex idx_read = index(idx.row(), MSG_DB_READ_INDEX); - QVariant dta = m_cache->containsData(idx_read.row()) ? m_cache->data(idx_read) : QSqlQueryModel::data(idx_read); - return dta.toInt() == 0 ? QColor(Qt::blue) : QVariant(); - } + const bool striked = is_deleted; - case NoHighlighting: - default: - return QVariant(); - } + if (data_read.toBool()) { + return striked ? m_normalStrikedFont : m_normalFont; + } + else { + return striked ? m_boldStrikedFont : m_boldFont; + } + } - case Qt::DecorationRole: { - const int index_column = idx.column(); + case Qt::ForegroundRole: + switch (m_messageHighlighter) { + case HighlightImportant: { + QModelIndex idx_important = index(idx.row(), MSG_DB_IMPORTANT_INDEX); + QVariant dta = m_cache->containsData(idx_important.row()) ? m_cache->data(idx_important) : QSqlQueryModel::data(idx_important); - if (index_column == MSG_DB_READ_INDEX) { - QModelIndex idx_read = index(idx.row(), MSG_DB_READ_INDEX); - QVariant dta = m_cache->containsData(idx_read.row()) ? m_cache->data(idx_read) : QSqlQueryModel::data(idx_read); - return dta.toInt() == 1 ? m_readIcon : m_unreadIcon; - } - else if (index_column == MSG_DB_IMPORTANT_INDEX) { - QModelIndex idx_important = index(idx.row(), MSG_DB_IMPORTANT_INDEX); - QVariant dta = m_cache->containsData(idx_important.row()) ? m_cache->data(idx_important) : QSqlQueryModel::data(idx_important); - return dta.toInt() == 1 ? m_favoriteIcon : QVariant(); - } - else { - return QVariant(); - } - } + return dta.toInt() == 1 ? QColor(Qt::blue) : QVariant(); + } - default: - return QVariant(); - } + case HighlightUnread: { + QModelIndex idx_read = index(idx.row(), MSG_DB_READ_INDEX); + QVariant dta = m_cache->containsData(idx_read.row()) ? m_cache->data(idx_read) : QSqlQueryModel::data(idx_read); + + return dta.toInt() == 0 ? QColor(Qt::blue) : QVariant(); + } + + case NoHighlighting: + default: + return QVariant(); + } + + case Qt::DecorationRole: { + const int index_column = idx.column(); + + if (index_column == MSG_DB_READ_INDEX) { + QModelIndex idx_read = index(idx.row(), MSG_DB_READ_INDEX); + QVariant dta = m_cache->containsData(idx_read.row()) ? m_cache->data(idx_read) : QSqlQueryModel::data(idx_read); + + return dta.toInt() == 1 ? m_readIcon : m_unreadIcon; + } + else if (index_column == MSG_DB_IMPORTANT_INDEX) { + QModelIndex idx_important = index(idx.row(), MSG_DB_IMPORTANT_INDEX); + QVariant dta = m_cache->containsData(idx_important.row()) ? m_cache->data(idx_important) : QSqlQueryModel::data(idx_important); + + return dta.toInt() == 1 ? m_favoriteIcon : QVariant(); + } + else { + return QVariant(); + } + } + + default: + return QVariant(); + } } bool MessagesModel::setMessageRead(int row_index, RootItem::ReadStatus read) { - if (data(row_index, MSG_DB_READ_INDEX, Qt::EditRole).toInt() == read) { - // Read status is the same is the one currently set. - // In that case, no extra work is needed. - return true; - } + if (data(row_index, MSG_DB_READ_INDEX, Qt::EditRole).toInt() == read) { + // Read status is the same is the one currently set. + // In that case, no extra work is needed. + return true; + } - Message message = messageAt(row_index); + Message message = messageAt(row_index); - if (!m_selectedItem->getParentServiceRoot()->onBeforeSetMessagesRead(m_selectedItem, QList() << message, read)) { - // Cannot change read status of the item. Abort. - return false; - } + if (!m_selectedItem->getParentServiceRoot()->onBeforeSetMessagesRead(m_selectedItem, QList() << message, read)) { + // Cannot change read status of the item. Abort. + return false; + } - // Rewrite "visible" data in the model. - bool working_change = setData(index(row_index, MSG_DB_READ_INDEX), read); + // Rewrite "visible" data in the model. + bool working_change = setData(index(row_index, MSG_DB_READ_INDEX), read); - if (!working_change) { - // If rewriting in the model failed, then cancel all actions. - qDebug("Setting of new data to the model failed for message read change."); - return false; - } + if (!working_change) { + // If rewriting in the model failed, then cancel all actions. + qDebug("Setting of new data to the model failed for message read change."); + return false; + } - if (DatabaseQueries::markMessagesReadUnread(m_db, QStringList() << QString::number(message.m_id), read)) { - return m_selectedItem->getParentServiceRoot()->onAfterSetMessagesRead(m_selectedItem, QList() << message, read); - } - else { - return false; - } + if (DatabaseQueries::markMessagesReadUnread(m_db, QStringList() << QString::number(message.m_id), read)) { + return m_selectedItem->getParentServiceRoot()->onAfterSetMessagesRead(m_selectedItem, QList() << message, read); + } + else { + return false; + } } bool MessagesModel::setMessageReadById(int id, RootItem::ReadStatus read) { - for (int i = 0; i < rowCount(); i++) { - int found_id = data(i, MSG_DB_ID_INDEX, Qt::EditRole).toInt(); + for (int i = 0; i < rowCount(); i++) { + int found_id = data(i, MSG_DB_ID_INDEX, Qt::EditRole).toInt(); - if (found_id == id) { - bool set = setData(index(i, MSG_DB_READ_INDEX), read); + if (found_id == id) { + bool set = setData(index(i, MSG_DB_READ_INDEX), read); - if (set) { - emit dataChanged(index(i, 0), index(i, MSG_DB_CUSTOM_HASH_INDEX)); - } + if (set) { + emit dataChanged(index(i, 0), index(i, MSG_DB_CUSTOM_HASH_INDEX)); + } - return set; - } - } + return set; + } + } - return false; + return false; } bool MessagesModel::switchMessageImportance(int row_index) { - const QModelIndex target_index = index(row_index, MSG_DB_IMPORTANT_INDEX); - const RootItem::Importance current_importance = (RootItem::Importance) data(target_index, Qt::EditRole).toInt(); - const RootItem::Importance next_importance = current_importance == RootItem::Important ? - RootItem::NotImportant : RootItem::Important; - const Message message = messageAt(row_index); - const QPair pair(message, next_importance); + const QModelIndex target_index = index(row_index, MSG_DB_IMPORTANT_INDEX); + const RootItem::Importance current_importance = (RootItem::Importance) data(target_index, Qt::EditRole).toInt(); + const RootItem::Importance next_importance = current_importance == RootItem::Important ? + RootItem::NotImportant : RootItem::Important; + const Message message = messageAt(row_index); + const QPair pair(message, next_importance); - if (!m_selectedItem->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_selectedItem, - QList>() << pair)) { - return false; - } + if (!m_selectedItem->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_selectedItem, + QList>() << pair)) { + return false; + } - // Rewrite "visible" data in the model. - const bool working_change = setData(target_index, next_importance); + // Rewrite "visible" data in the model. + const bool working_change = setData(target_index, next_importance); - if (!working_change) { - // If rewriting in the model failed, then cancel all actions. - qDebug("Setting of new data to the model failed for message importance change."); - return false; - } + if (!working_change) { + // If rewriting in the model failed, then cancel all actions. + qDebug("Setting of new data to the model failed for message importance change."); + return false; + } - // Commit changes. - if (DatabaseQueries::markMessageImportant(m_db, message.m_id, next_importance)) { - emit dataChanged(index(row_index, 0), index(row_index, MSG_DB_FEED_CUSTOM_ID_INDEX), QVector() << Qt::FontRole); - return m_selectedItem->getParentServiceRoot()->onAfterSwitchMessageImportance(m_selectedItem, - QList>() << pair); - } - else { - return false; - } + // Commit changes. + if (DatabaseQueries::markMessageImportant(m_db, message.m_id, next_importance)) { + emit dataChanged(index(row_index, 0), index(row_index, MSG_DB_FEED_CUSTOM_ID_INDEX), QVector() << Qt::FontRole); + + return m_selectedItem->getParentServiceRoot()->onAfterSwitchMessageImportance(m_selectedItem, + QList>() << pair); + } + else { + return false; + } } bool MessagesModel::switchBatchMessageImportance(const QModelIndexList& messages) { - QStringList message_ids; - QList> message_states; + QStringList message_ids; - // Obtain IDs of all desired messages. - foreach (const QModelIndex& message, messages) { - const Message msg = messageAt(message.row()); - RootItem::Importance message_importance = messageImportance((message.row())); - message_states.append(QPair(msg, message_importance == RootItem::Important ? - RootItem::NotImportant : - RootItem::Important)); - message_ids.append(QString::number(msg.m_id)); - QModelIndex idx_msg_imp = index(message.row(), MSG_DB_IMPORTANT_INDEX); - setData(idx_msg_imp, message_importance == RootItem::Important ? - (int) RootItem::NotImportant : - (int) RootItem::Important); - } + QList> message_states; - reloadWholeLayout(); + // Obtain IDs of all desired messages. + foreach (const QModelIndex& message, messages) { + const Message msg = messageAt(message.row()); - if (!m_selectedItem->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_selectedItem, message_states)) { - return false; - } + RootItem::Importance message_importance = messageImportance((message.row())); + message_states.append(QPair(msg, message_importance == RootItem::Important ? + RootItem::NotImportant : + RootItem::Important)); + message_ids.append(QString::number(msg.m_id)); + QModelIndex idx_msg_imp = index(message.row(), MSG_DB_IMPORTANT_INDEX); - if (DatabaseQueries::switchMessagesImportance(m_db, message_ids)) { - return m_selectedItem->getParentServiceRoot()->onAfterSwitchMessageImportance(m_selectedItem, message_states); - } - else { - return false; - } + setData(idx_msg_imp, message_importance == RootItem::Important ? + (int) RootItem::NotImportant : + (int) RootItem::Important); + } + + reloadWholeLayout(); + + if (!m_selectedItem->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_selectedItem, message_states)) { + return false; + } + + if (DatabaseQueries::switchMessagesImportance(m_db, message_ids)) { + return m_selectedItem->getParentServiceRoot()->onAfterSwitchMessageImportance(m_selectedItem, message_states); + } + else { + return false; + } } bool MessagesModel::setBatchMessagesDeleted(const QModelIndexList& messages) { - QStringList message_ids; - QList msgs; + QStringList message_ids; - // Obtain IDs of all desired messages. - foreach (const QModelIndex& message, messages) { - const Message msg = messageAt(message.row()); - msgs.append(msg); - message_ids.append(QString::number(msg.m_id)); + QList msgs; - if (qobject_cast(m_selectedItem) != nullptr) { - setData(index(message.row(), MSG_DB_PDELETED_INDEX), 1); - } - else { - setData(index(message.row(), MSG_DB_DELETED_INDEX), 1); - } - } + // Obtain IDs of all desired messages. + foreach (const QModelIndex& message, messages) { + const Message msg = messageAt(message.row()); - reloadWholeLayout(); + msgs.append(msg); + message_ids.append(QString::number(msg.m_id)); - if (!m_selectedItem->getParentServiceRoot()->onBeforeMessagesDelete(m_selectedItem, msgs)) { - return false; - } + if (qobject_cast(m_selectedItem) != nullptr) { + setData(index(message.row(), MSG_DB_PDELETED_INDEX), 1); + } + else { + setData(index(message.row(), MSG_DB_DELETED_INDEX), 1); + } + } - bool deleted; + reloadWholeLayout(); - if (m_selectedItem->kind() != RootItemKind::Bin) { - deleted = DatabaseQueries::deleteOrRestoreMessagesToFromBin(m_db, message_ids, true); - } - else { - deleted = DatabaseQueries::permanentlyDeleteMessages(m_db, message_ids); - } + if (!m_selectedItem->getParentServiceRoot()->onBeforeMessagesDelete(m_selectedItem, msgs)) { + return false; + } - if (deleted) { - return m_selectedItem->getParentServiceRoot()->onAfterMessagesDelete(m_selectedItem, msgs); - } - else { - return false; - } + bool deleted; + + if (m_selectedItem->kind() != RootItemKind::Bin) { + deleted = DatabaseQueries::deleteOrRestoreMessagesToFromBin(m_db, message_ids, true); + } + else { + deleted = DatabaseQueries::permanentlyDeleteMessages(m_db, message_ids); + } + + if (deleted) { + return m_selectedItem->getParentServiceRoot()->onAfterMessagesDelete(m_selectedItem, msgs); + } + else { + return false; + } } bool MessagesModel::setBatchMessagesRead(const QModelIndexList& messages, RootItem::ReadStatus read) { - QStringList message_ids; - QList msgs; + QStringList message_ids; - // Obtain IDs of all desired messages. - foreach (const QModelIndex& message, messages) { - Message msg = messageAt(message.row()); - msgs.append(msg); - message_ids.append(QString::number(msg.m_id)); - setData(index(message.row(), MSG_DB_READ_INDEX), (int) read); - } + QList msgs; - reloadWholeLayout(); + // Obtain IDs of all desired messages. + foreach (const QModelIndex& message, messages) { + Message msg = messageAt(message.row()); - if (!m_selectedItem->getParentServiceRoot()->onBeforeSetMessagesRead(m_selectedItem, msgs, read)) { - return false; - } + msgs.append(msg); + message_ids.append(QString::number(msg.m_id)); + setData(index(message.row(), MSG_DB_READ_INDEX), (int) read); + } - if (DatabaseQueries::markMessagesReadUnread(m_db, message_ids, read)) { - return m_selectedItem->getParentServiceRoot()->onAfterSetMessagesRead(m_selectedItem, msgs, read); - } - else { - return false; - } + reloadWholeLayout(); + + if (!m_selectedItem->getParentServiceRoot()->onBeforeSetMessagesRead(m_selectedItem, msgs, read)) { + return false; + } + + if (DatabaseQueries::markMessagesReadUnread(m_db, message_ids, read)) { + return m_selectedItem->getParentServiceRoot()->onAfterSetMessagesRead(m_selectedItem, msgs, read); + } + else { + return false; + } } bool MessagesModel::setBatchMessagesRestored(const QModelIndexList& messages) { - QStringList message_ids; - QList msgs; + QStringList message_ids; - // Obtain IDs of all desired messages. - foreach (const QModelIndex& message, messages) { - const Message msg = messageAt(message.row()); - msgs.append(msg); - message_ids.append(QString::number(msg.m_id)); - setData(index(message.row(), MSG_DB_PDELETED_INDEX), 0); - setData(index(message.row(), MSG_DB_DELETED_INDEX), 0); - } + QList msgs; - reloadWholeLayout(); + // Obtain IDs of all desired messages. + foreach (const QModelIndex& message, messages) { + const Message msg = messageAt(message.row()); - if (!m_selectedItem->getParentServiceRoot()->onBeforeMessagesRestoredFromBin(m_selectedItem, msgs)) { - return false; - } + msgs.append(msg); + message_ids.append(QString::number(msg.m_id)); + setData(index(message.row(), MSG_DB_PDELETED_INDEX), 0); + setData(index(message.row(), MSG_DB_DELETED_INDEX), 0); + } - if (DatabaseQueries::deleteOrRestoreMessagesToFromBin(m_db, message_ids, false)) { - return m_selectedItem->getParentServiceRoot()->onAfterMessagesRestoredFromBin(m_selectedItem, msgs); - } - else { - return false; - } + reloadWholeLayout(); + + if (!m_selectedItem->getParentServiceRoot()->onBeforeMessagesRestoredFromBin(m_selectedItem, msgs)) { + return false; + } + + if (DatabaseQueries::deleteOrRestoreMessagesToFromBin(m_db, message_ids, false)) { + return m_selectedItem->getParentServiceRoot()->onAfterMessagesRestoredFromBin(m_selectedItem, msgs); + } + else { + return false; + } } QVariant MessagesModel::headerData(int section, Qt::Orientation orientation, int role) const { - Q_UNUSED(orientation) + Q_UNUSED(orientation) - switch (role) { - case Qt::DisplayRole: + switch (role) { + case Qt::DisplayRole: - // Display textual headers for all columns except "read" and - // "important" columns. - if (section != MSG_DB_READ_INDEX && section != MSG_DB_IMPORTANT_INDEX) { - return m_headerData.at(section); - } - else { - return QVariant(); - } + // Display textual headers for all columns except "read" and + // "important" columns. + if (section != MSG_DB_READ_INDEX && section != MSG_DB_IMPORTANT_INDEX) { + return m_headerData.at(section); + } + else { + return QVariant(); + } - case Qt::ToolTipRole: - return m_tooltipData.at(section); + case Qt::ToolTipRole: + return m_tooltipData.at(section); - case Qt::EditRole: - return m_headerData.at(section); + case Qt::EditRole: + return m_headerData.at(section); - // Display icons for "read" and "important" columns. - case Qt::DecorationRole: { - switch (section) { - case MSG_DB_READ_INDEX: - return m_readIcon; + // Display icons for "read" and "important" columns. + case Qt::DecorationRole: { + switch (section) { + case MSG_DB_READ_INDEX: + return m_readIcon; - case MSG_DB_IMPORTANT_INDEX: - return m_favoriteIcon; + case MSG_DB_IMPORTANT_INDEX: + return m_favoriteIcon; - default: - return QVariant(); - } - } + default: + return QVariant(); + } + } - default: - return QVariant(); - } + default: + return QVariant(); + } } diff --git a/src/core/messagesmodel.h b/src/core/messagesmodel.h index dacd390cd..279b0ab04 100755 --- a/src/core/messagesmodel.h +++ b/src/core/messagesmodel.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,98 +19,99 @@ #ifndef MESSAGESMODEL_H #define MESSAGESMODEL_H -#include #include "core/messagesmodelsqllayer.h" +#include -#include "definitions/definitions.h" #include "core/message.h" +#include "definitions/definitions.h" #include "services/abstract/rootitem.h" #include #include - class MessagesModelCache; class MessagesModel : public QSqlQueryModel, public MessagesModelSqlLayer { - Q_OBJECT + Q_OBJECT - public: - // Enum which describes basic filtering schemes - // for messages. - enum MessageHighlighter { - NoHighlighting = 100, - HighlightUnread = 101, - HighlightImportant = 102 - }; + public: - // Constructors and destructors. - explicit MessagesModel(QObject* parent = 0); - virtual ~MessagesModel(); + // Enum which describes basic filtering schemes + // for messages. + enum MessageHighlighter { + NoHighlighting = 100, + HighlightUnread = 101, + HighlightImportant = 102 + }; - // Fetches ALL available data to the model. - // NOTE: This activates the SQL query and populates the model with new data. - void repopulate(); + // Constructors and destructors. + explicit MessagesModel(QObject* parent = 0); + virtual ~MessagesModel(); - // Model implementation. - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - QVariant data(int row, int column, int role = Qt::DisplayRole) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - Qt::ItemFlags flags(const QModelIndex& index) const; + // Fetches ALL available data to the model. + // NOTE: This activates the SQL query and populates the model with new data. + void repopulate(); - // Returns message at given index. - Message messageAt(int row_index) const; - int messageId(int row_index) const; - RootItem::Importance messageImportance(int row_index) const; + // Model implementation. + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + QVariant data(int row, int column, int role = Qt::DisplayRole) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + Qt::ItemFlags flags(const QModelIndex& index) const; - RootItem* loadedItem() const; - void updateDateFormat(); - void reloadWholeLayout(); + // Returns message at given index. + Message messageAt(int row_index) const; + int messageId(int row_index) const; + RootItem::Importance messageImportance(int row_index) const; - // SINGLE message manipulators. - bool switchMessageImportance(int row_index); - bool setMessageRead(int row_index, RootItem::ReadStatus read); + RootItem* loadedItem() const; - // BATCH messages manipulators. - bool switchBatchMessageImportance(const QModelIndexList& messages); - bool setBatchMessagesDeleted(const QModelIndexList& messages); - bool setBatchMessagesRead(const QModelIndexList& messages, RootItem::ReadStatus read); - bool setBatchMessagesRestored(const QModelIndexList& messages); + void updateDateFormat(); + void reloadWholeLayout(); - // Highlights messages. - void highlightMessages(MessageHighlighter highlight); + // SINGLE message manipulators. + bool switchMessageImportance(int row_index); + bool setMessageRead(int row_index, RootItem::ReadStatus read); - // Loads messages of given feeds. - void loadMessages(RootItem* item); + // BATCH messages manipulators. + bool switchBatchMessageImportance(const QModelIndexList& messages); + bool setBatchMessagesDeleted(const QModelIndexList& messages); + bool setBatchMessagesRead(const QModelIndexList& messages, RootItem::ReadStatus read); + bool setBatchMessagesRestored(const QModelIndexList& messages); - public slots: - // NOTE: These methods DO NOT actually change data in the DB, just in the model. - // These are particularly used by msg browser. - bool setMessageImportantById(int id, RootItem::Importance important); - bool setMessageReadById(int id, RootItem::ReadStatus read); + // Highlights messages. + void highlightMessages(MessageHighlighter highlight); - private: - void setupHeaderData(); - void setupFonts(); - void setupIcons(); + // Loads messages of given feeds. + void loadMessages(RootItem* item); - MessagesModelCache* m_cache; - MessageHighlighter m_messageHighlighter; + public slots: - QString m_customDateFormat; - RootItem* m_selectedItem; - QList m_headerData; - QList m_tooltipData; + // NOTE: These methods DO NOT actually change data in the DB, just in the model. + // These are particularly used by msg browser. + bool setMessageImportantById(int id, RootItem::Importance important); + bool setMessageReadById(int id, RootItem::ReadStatus read); - QFont m_normalFont; - QFont m_boldFont; - QFont m_normalStrikedFont; - QFont m_boldStrikedFont; + private: + void setupHeaderData(); + void setupFonts(); + void setupIcons(); - QIcon m_favoriteIcon; - QIcon m_readIcon; - QIcon m_unreadIcon; + MessagesModelCache* m_cache; + MessageHighlighter m_messageHighlighter; + QString m_customDateFormat; + RootItem* m_selectedItem; + + QList m_headerData; + QList m_tooltipData; + + QFont m_normalFont; + QFont m_boldFont; + QFont m_normalStrikedFont; + QFont m_boldStrikedFont; + QIcon m_favoriteIcon; + QIcon m_readIcon; + QIcon m_unreadIcon; }; Q_DECLARE_METATYPE(MessagesModel::MessageHighlighter) diff --git a/src/core/messagesmodelcache.cpp b/src/core/messagesmodelcache.cpp index 98e7135b1..c7391c825 100755 --- a/src/core/messagesmodelcache.cpp +++ b/src/core/messagesmodelcache.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,21 +20,18 @@ #include "miscellaneous/textfactory.h" +MessagesModelCache::MessagesModelCache(QObject* parent) : QObject(parent), m_msgCache(QHash()) {} -MessagesModelCache::MessagesModelCache(QObject* parent) : QObject(parent), m_msgCache(QHash()) { -} - -MessagesModelCache::~MessagesModelCache() { -} +MessagesModelCache::~MessagesModelCache() {} void MessagesModelCache::setData(const QModelIndex& index, const QVariant& value, const QSqlRecord& record) { - if (!m_msgCache.contains(index.row())) { - m_msgCache[index.row()] = record; - } + if (!m_msgCache.contains(index.row())) { + m_msgCache[index.row()] = record; + } - m_msgCache[index.row()].setValue(index.column(), value); + m_msgCache[index.row()].setValue(index.column(), value); } QVariant MessagesModelCache::data(const QModelIndex& idx) { - return m_msgCache[idx.row()].value(idx.column()); + return m_msgCache[idx.row()].value(idx.column()); } diff --git a/src/core/messagesmodelcache.h b/src/core/messagesmodelcache.h index 7b799e8e8..51eb0ff85 100755 --- a/src/core/messagesmodelcache.h +++ b/src/core/messagesmodelcache.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,34 +23,34 @@ #include "core/message.h" -#include #include - +#include class MessagesModelCache : public QObject { - Q_OBJECT + Q_OBJECT - public: - explicit MessagesModelCache(QObject* parent = nullptr); - virtual ~MessagesModelCache(); + public: + explicit MessagesModelCache(QObject* parent = nullptr); + virtual ~MessagesModelCache(); - inline bool containsData(int row_idx) const { - return m_msgCache.contains(row_idx); - } + inline bool containsData(int row_idx) const { + return m_msgCache.contains(row_idx); + } - inline QSqlRecord record(int row_idx) const { - return m_msgCache.value(row_idx); - } + inline QSqlRecord record(int row_idx) const { + return m_msgCache.value(row_idx); + } - inline void clear() { - m_msgCache.clear(); - } + inline void clear() { + m_msgCache.clear(); + } - void setData(const QModelIndex& index, const QVariant& value, const QSqlRecord& record); - QVariant data(const QModelIndex& idx); + void setData(const QModelIndex& index, const QVariant& value, const QSqlRecord& record); - private: - QHash m_msgCache; + QVariant data(const QModelIndex& idx); + + private: + QHash m_msgCache; }; #endif // MESSAGESMODELCACHE_H diff --git a/src/core/messagesmodelsqllayer.cpp b/src/core/messagesmodelsqllayer.cpp index 6ba71bc79..be7f95a05 100755 --- a/src/core/messagesmodelsqllayer.cpp +++ b/src/core/messagesmodelsqllayer.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,84 +21,84 @@ #include "definitions/definitions.h" #include "miscellaneous/application.h" - MessagesModelSqlLayer::MessagesModelSqlLayer() - : m_filter(QSL(DEFAULT_SQL_MESSAGES_FILTER)), m_fieldNames(QMap()), - m_sortColumns(QList()), m_sortOrders(QList()) { - m_db = qApp->database()->connection(QSL("MessagesModel"), DatabaseFactory::FromSettings); - m_fieldNames[MSG_DB_ID_INDEX] = "Messages.id"; - m_fieldNames[MSG_DB_READ_INDEX] = "Messages.is_read"; - m_fieldNames[MSG_DB_DELETED_INDEX] = "Messages.is_deleted"; - m_fieldNames[MSG_DB_IMPORTANT_INDEX] = "Messages.is_important"; - m_fieldNames[MSG_DB_FEED_TITLE_INDEX] = "Feeds.title"; - m_fieldNames[MSG_DB_TITLE_INDEX] = "Messages.title"; - m_fieldNames[MSG_DB_URL_INDEX] = "Messages.url"; - m_fieldNames[MSG_DB_AUTHOR_INDEX] = "Messages.author"; - m_fieldNames[MSG_DB_DCREATED_INDEX] = "Messages.date_created"; - m_fieldNames[MSG_DB_CONTENTS_INDEX] = "Messages.contents"; - m_fieldNames[MSG_DB_PDELETED_INDEX] = "Messages.is_pdeleted"; - m_fieldNames[MSG_DB_ENCLOSURES_INDEX] = "Messages.enclosures"; - m_fieldNames[MSG_DB_ACCOUNT_ID_INDEX] = "Messages.account_id"; - m_fieldNames[MSG_DB_CUSTOM_ID_INDEX] = "Messages.custom_id"; - m_fieldNames[MSG_DB_CUSTOM_HASH_INDEX] = "Messages.custom_hash"; - m_fieldNames[MSG_DB_FEED_CUSTOM_ID_INDEX] = "Messages.feed"; + : m_filter(QSL(DEFAULT_SQL_MESSAGES_FILTER)), m_fieldNames(QMap()), + m_sortColumns(QList()), m_sortOrders(QList()) { + m_db = qApp->database()->connection(QSL("MessagesModel"), DatabaseFactory::FromSettings); + m_fieldNames[MSG_DB_ID_INDEX] = "Messages.id"; + m_fieldNames[MSG_DB_READ_INDEX] = "Messages.is_read"; + m_fieldNames[MSG_DB_DELETED_INDEX] = "Messages.is_deleted"; + m_fieldNames[MSG_DB_IMPORTANT_INDEX] = "Messages.is_important"; + m_fieldNames[MSG_DB_FEED_TITLE_INDEX] = "Feeds.title"; + m_fieldNames[MSG_DB_TITLE_INDEX] = "Messages.title"; + m_fieldNames[MSG_DB_URL_INDEX] = "Messages.url"; + m_fieldNames[MSG_DB_AUTHOR_INDEX] = "Messages.author"; + m_fieldNames[MSG_DB_DCREATED_INDEX] = "Messages.date_created"; + m_fieldNames[MSG_DB_CONTENTS_INDEX] = "Messages.contents"; + m_fieldNames[MSG_DB_PDELETED_INDEX] = "Messages.is_pdeleted"; + m_fieldNames[MSG_DB_ENCLOSURES_INDEX] = "Messages.enclosures"; + m_fieldNames[MSG_DB_ACCOUNT_ID_INDEX] = "Messages.account_id"; + m_fieldNames[MSG_DB_CUSTOM_ID_INDEX] = "Messages.custom_id"; + m_fieldNames[MSG_DB_CUSTOM_HASH_INDEX] = "Messages.custom_hash"; + m_fieldNames[MSG_DB_FEED_CUSTOM_ID_INDEX] = "Messages.feed"; } void MessagesModelSqlLayer::addSortState(int column, Qt::SortOrder order) { - int existing = m_sortColumns.indexOf(column); - bool is_ctrl_pressed = (QApplication::queryKeyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier; + int existing = m_sortColumns.indexOf(column); + bool is_ctrl_pressed = (QApplication::queryKeyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier; - if (existing >= 0) { - m_sortColumns.removeAt(existing); - m_sortOrders.removeAt(existing); - } + if (existing >= 0) { + m_sortColumns.removeAt(existing); + m_sortOrders.removeAt(existing); + } - if (m_sortColumns.size() > MAX_MULTICOLUMN_SORT_STATES) { - // We support only limited number of sort states - // due to DB performance. - m_sortColumns.removeAt(0); - m_sortOrders.removeAt(0); - } + if (m_sortColumns.size() > MAX_MULTICOLUMN_SORT_STATES) { + // We support only limited number of sort states + // due to DB performance. + m_sortColumns.removeAt(0); + m_sortOrders.removeAt(0); + } - if (is_ctrl_pressed) { - // User is activating the multicolumn sort mode. - m_sortColumns.append(column); - m_sortOrders.append(order); - } - else { - m_sortColumns.prepend(column); - m_sortOrders.prepend(order); - } + if (is_ctrl_pressed) { + // User is activating the multicolumn sort mode. + m_sortColumns.append(column); + m_sortOrders.append(order); + } + else { + m_sortColumns.prepend(column); + m_sortOrders.prepend(order); + } - qDebug("Added sort state, select statement is now:\n'%s'", qPrintable(selectStatement())); + qDebug("Added sort state, select statement is now:\n'%s'", qPrintable(selectStatement())); } void MessagesModelSqlLayer::setFilter(const QString& filter) { - m_filter = filter; + m_filter = filter; } QString MessagesModelSqlLayer::formatFields() const { - return m_fieldNames.values().join(QSL(", ")); + return m_fieldNames.values().join(QSL(", ")); } QString MessagesModelSqlLayer::selectStatement() const { - return QL1S("SELECT ") + formatFields() + - QSL(" FROM Messages LEFT JOIN Feeds ON Messages.feed = Feeds.custom_id AND Messages.account_id = Feeds.account_id WHERE ") + - m_filter + orderByClause() + QL1C(';'); + return QL1S("SELECT ") + formatFields() + + QSL(" FROM Messages LEFT JOIN Feeds ON Messages.feed = Feeds.custom_id AND Messages.account_id = Feeds.account_id WHERE ") + + m_filter + orderByClause() + QL1C(';'); } QString MessagesModelSqlLayer::orderByClause() const { - if (m_sortColumns.isEmpty()) { - return QString(); - } - else { - QStringList sorts; + if (m_sortColumns.isEmpty()) { + return QString(); + } + else { + QStringList sorts; - for (int i = 0; i < m_sortColumns.size(); i++) { - QString field_name(m_fieldNames[m_sortColumns[i]]); - sorts.append(field_name + (m_sortOrders[i] == Qt::AscendingOrder ? QSL(" ASC") : QSL(" DESC"))); - } + for (int i = 0; i < m_sortColumns.size(); i++) { + QString field_name(m_fieldNames[m_sortColumns[i]]); - return QL1S(" ORDER BY ") + sorts.join(QSL(", ")); - } + sorts.append(field_name + (m_sortOrders[i] == Qt::AscendingOrder ? QSL(" ASC") : QSL(" DESC"))); + } + + return QL1S(" ORDER BY ") + sorts.join(QSL(", ")); + } } diff --git a/src/core/messagesmodelsqllayer.h b/src/core/messagesmodelsqllayer.h index f2a3de13f..3a53ac171 100755 --- a/src/core/messagesmodelsqllayer.h +++ b/src/core/messagesmodelsqllayer.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -15,42 +16,40 @@ // You should have received a copy of the GNU General Public License // along with RSS Guard. If not, see . - #ifndef MESSAGESMODELSQLLAYER_H #define MESSAGESMODELSQLLAYER_H #include -#include #include - +#include class MessagesModelSqlLayer { - public: - explicit MessagesModelSqlLayer(); + public: + explicit MessagesModelSqlLayer(); - // Adds this new state to queue of sort states. - void addSortState(int column, Qt::SortOrder order); + // Adds this new state to queue of sort states. + void addSortState(int column, Qt::SortOrder order); - // Sets SQL WHERE clause, without "WHERE" keyword. - void setFilter(const QString& filter); + // Sets SQL WHERE clause, without "WHERE" keyword. + void setFilter(const QString& filter); - protected: - QString orderByClause() const; - QString selectStatement() const; - QString formatFields() const; + protected: + QString orderByClause() const; + QString selectStatement() const; + QString formatFields() const; - QSqlDatabase m_db; + QSqlDatabase m_db; - private: - QString m_filter; + private: + QString m_filter; - // NOTE: These two lists contain data for multicolumn sorting. - // They are always same length. Most important sort column/order - // are located at the start of lists; - QMap m_fieldNames; - QList m_sortColumns; - QList m_sortOrders; + // NOTE: These two lists contain data for multicolumn sorting. + // They are always same length. Most important sort column/order + // are located at the start of lists; + QMap m_fieldNames; + QList m_sortColumns; + QList m_sortOrders; }; #endif // MESSAGESMODELSQLLAYER_H diff --git a/src/core/messagesproxymodel.cpp b/src/core/messagesproxymodel.cpp index 12b0e1595..51398ac20 100755 --- a/src/core/messagesproxymodel.cpp +++ b/src/core/messagesproxymodel.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,179 +20,180 @@ #include "core/messagesmodel.h" - MessagesProxyModel::MessagesProxyModel(MessagesModel* source_model, QObject* parent) - : QSortFilterProxyModel(parent), m_sourceModel(source_model) { - setObjectName(QSL("MessagesProxyModel")); - setSortRole(Qt::EditRole); - setSortCaseSensitivity(Qt::CaseInsensitive); - setFilterCaseSensitivity(Qt::CaseInsensitive); - setFilterKeyColumn(-1); - setFilterRole(Qt::EditRole); - setDynamicSortFilter(false); - setSourceModel(m_sourceModel); + : QSortFilterProxyModel(parent), m_sourceModel(source_model) { + setObjectName(QSL("MessagesProxyModel")); + setSortRole(Qt::EditRole); + setSortCaseSensitivity(Qt::CaseInsensitive); + setFilterCaseSensitivity(Qt::CaseInsensitive); + setFilterKeyColumn(-1); + setFilterRole(Qt::EditRole); + setDynamicSortFilter(false); + setSourceModel(m_sourceModel); } MessagesProxyModel::~MessagesProxyModel() { - qDebug("Destroying MessagesProxyModel instance."); + qDebug("Destroying MessagesProxyModel instance."); } QModelIndex MessagesProxyModel::getNextPreviousUnreadItemIndex(int default_row) { - const bool started_from_zero = default_row == 0; - QModelIndex next_index = getNextUnreadItemIndex(default_row, rowCount() - 1); + const bool started_from_zero = default_row == 0; + QModelIndex next_index = getNextUnreadItemIndex(default_row, rowCount() - 1); - // There is no next message, check previous. - if (!next_index.isValid() && !started_from_zero) { - next_index = getNextUnreadItemIndex(0, default_row - 1); - } + // There is no next message, check previous. + if (!next_index.isValid() && !started_from_zero) { + next_index = getNextUnreadItemIndex(0, default_row - 1); + } - return next_index; + return next_index; } QModelIndex MessagesProxyModel::getNextUnreadItemIndex(int default_row, int max_row) const { - while (default_row <= max_row) { - // Get info if the message is read or not. - const QModelIndex proxy_index = index(default_row, MSG_DB_READ_INDEX); - const bool is_read = m_sourceModel->data(mapToSource(proxy_index).row(), - MSG_DB_READ_INDEX, Qt::EditRole).toInt() == 1; + while (default_row <= max_row) { + // Get info if the message is read or not. + const QModelIndex proxy_index = index(default_row, MSG_DB_READ_INDEX); + const bool is_read = m_sourceModel->data(mapToSource(proxy_index).row(), + MSG_DB_READ_INDEX, Qt::EditRole).toInt() == 1; - if (!is_read) { - // We found unread message, mark it. - return proxy_index; - } - else { - default_row++; - } - } + if (!is_read) { + // We found unread message, mark it. + return proxy_index; + } + else { + default_row++; + } + } - return QModelIndex(); + return QModelIndex(); } bool MessagesProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const { - Q_UNUSED(left) - Q_UNUSED(right) - // NOTE: Comparisons are done by SQL servers itself, not client-side. - return false; + Q_UNUSED(left) + Q_UNUSED(right) + + // NOTE: Comparisons are done by SQL servers itself, not client-side. + return false; } QModelIndexList MessagesProxyModel::mapListFromSource(const QModelIndexList& indexes, bool deep) const { - QModelIndexList mapped_indexes; + QModelIndexList mapped_indexes; - foreach (const QModelIndex& index, indexes) { - if (deep) { - // Construct new source index. - mapped_indexes << mapFromSource(m_sourceModel->index(index.row(), index.column())); - } - else { - mapped_indexes << mapFromSource(index); - } - } + foreach (const QModelIndex& index, indexes) { + if (deep) { + // Construct new source index. + mapped_indexes << mapFromSource(m_sourceModel->index(index.row(), index.column())); + } + else { + mapped_indexes << mapFromSource(index); + } + } - return mapped_indexes; + return mapped_indexes; } QModelIndexList MessagesProxyModel::match(const QModelIndex& start, int role, const QVariant& entered_value, int hits, Qt::MatchFlags flags) const { - QModelIndexList result; - const uint match_type = flags & 0x0F; - const Qt::CaseSensitivity case_sensitivity = Qt::CaseInsensitive; - const bool wrap = flags & Qt::MatchWrap; - const bool all_hits = (hits == -1); - QString entered_text; - int from = start.row(); - int to = rowCount(); + QModelIndexList result; + const uint match_type = flags & 0x0F; + const Qt::CaseSensitivity case_sensitivity = Qt::CaseInsensitive; + const bool wrap = flags & Qt::MatchWrap; + const bool all_hits = (hits == -1); + QString entered_text; + int from = start.row(); + int to = rowCount(); - for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); i++) { - for (int r = from; (r < to) && (all_hits || result.count() < hits); r++) { - QModelIndex idx = index(r, start.column()); + for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); i++) { + for (int r = from; (r < to) && (all_hits || result.count() < hits); r++) { + QModelIndex idx = index(r, start.column()); - if (!idx.isValid()) { - continue; - } + if (!idx.isValid()) { + continue; + } - QVariant item_value = m_sourceModel->data(mapToSource(idx).row(), MSG_DB_TITLE_INDEX, role); + QVariant item_value = m_sourceModel->data(mapToSource(idx).row(), MSG_DB_TITLE_INDEX, role); - // QVariant based matching. - if (match_type == Qt::MatchExactly) { - if (entered_value == item_value) { - result.append(idx); - } - } - // QString based matching. - else { - if (entered_text.isEmpty()) { - entered_text = entered_value.toString(); - } + // QVariant based matching. + if (match_type == Qt::MatchExactly) { + if (entered_value == item_value) { + result.append(idx); + } + } - QString item_text = item_value.toString(); + // QString based matching. + else { + if (entered_text.isEmpty()) { + entered_text = entered_value.toString(); + } - switch (match_type) { - case Qt::MatchRegExp: - if (QRegExp(entered_text, case_sensitivity).exactMatch(item_text)) { - result.append(idx); - } + QString item_text = item_value.toString(); - break; + switch (match_type) { + case Qt::MatchRegExp: + if (QRegExp(entered_text, case_sensitivity).exactMatch(item_text)) { + result.append(idx); + } - case Qt::MatchWildcard: - if (QRegExp(entered_text, case_sensitivity, QRegExp::Wildcard).exactMatch(item_text)) { - result.append(idx); - } + break; - break; + case Qt::MatchWildcard: + if (QRegExp(entered_text, case_sensitivity, QRegExp::Wildcard).exactMatch(item_text)) { + result.append(idx); + } - case Qt::MatchStartsWith: - if (item_text.startsWith(entered_text, case_sensitivity)) { - result.append(idx); - } + break; - break; + case Qt::MatchStartsWith: + if (item_text.startsWith(entered_text, case_sensitivity)) { + result.append(idx); + } - case Qt::MatchEndsWith: - if (item_text.endsWith(entered_text, case_sensitivity)) { - result.append(idx); - } + break; - break; + case Qt::MatchEndsWith: + if (item_text.endsWith(entered_text, case_sensitivity)) { + result.append(idx); + } - case Qt::MatchFixedString: - if (item_text.compare(entered_text, case_sensitivity) == 0) { - result.append(idx); - } + break; - break; + case Qt::MatchFixedString: + if (item_text.compare(entered_text, case_sensitivity) == 0) { + result.append(idx); + } - case Qt::MatchContains: - default: - if (item_text.contains(entered_text, case_sensitivity)) { - result.append(idx); - } + break; - break; - } - } - } + case Qt::MatchContains: + default: + if (item_text.contains(entered_text, case_sensitivity)) { + result.append(idx); + } - // Prepare for the next iteration. - from = 0; - to = start.row(); - } + break; + } + } + } - return result; + // Prepare for the next iteration. + from = 0; + to = start.row(); + } + + return result; } void MessagesProxyModel::sort(int column, Qt::SortOrder order) { - // NOTE: Ignore here, sort is done elsewhere (server-side). - Q_UNUSED(column) - Q_UNUSED(order) + // NOTE: Ignore here, sort is done elsewhere (server-side). + Q_UNUSED(column) + Q_UNUSED(order) } QModelIndexList MessagesProxyModel::mapListToSource(const QModelIndexList& indexes) const { - QModelIndexList source_indexes; + QModelIndexList source_indexes; - foreach (const QModelIndex& index, indexes) { - source_indexes << mapToSource(index); - } + foreach (const QModelIndex& index, indexes) { + source_indexes << mapToSource(index); + } - return source_indexes; + return source_indexes; } diff --git a/src/core/messagesproxymodel.h b/src/core/messagesproxymodel.h index 1d221ad7e..bb03b9f02 100755 --- a/src/core/messagesproxymodel.h +++ b/src/core/messagesproxymodel.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,37 +21,37 @@ #include - class MessagesModel; class MessagesProxyModel : public QSortFilterProxyModel { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit MessagesProxyModel(MessagesModel* source_model, QObject* parent = 0); - virtual ~MessagesProxyModel(); + public: - QModelIndex getNextPreviousUnreadItemIndex(int default_row); + // Constructors and destructors. + explicit MessagesProxyModel(MessagesModel* source_model, QObject* parent = 0); + virtual ~MessagesProxyModel(); - // Maps list of indexes. - QModelIndexList mapListToSource(const QModelIndexList& indexes) const; - QModelIndexList mapListFromSource(const QModelIndexList& indexes, bool deep = false) const; + QModelIndex getNextPreviousUnreadItemIndex(int default_row); - // Fix for matching indexes with respect to specifics of the message model. - QModelIndexList match(const QModelIndex& start, int role, const QVariant& entered_value, int hits, Qt::MatchFlags flags) const; + // Maps list of indexes. + QModelIndexList mapListToSource(const QModelIndexList& indexes) const; + QModelIndexList mapListFromSource(const QModelIndexList& indexes, bool deep = false) const; - // Performs sort of items. - void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); + // Fix for matching indexes with respect to specifics of the message model. + QModelIndexList match(const QModelIndex& start, int role, const QVariant& entered_value, int hits, Qt::MatchFlags flags) const; - private: - QModelIndex getNextUnreadItemIndex(int default_row, int max_row) const; + // Performs sort of items. + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); - // Compares two rows of data. - bool lessThan(const QModelIndex& left, const QModelIndex& right) const; + private: + QModelIndex getNextUnreadItemIndex(int default_row, int max_row) const; - // Source model pointer. - MessagesModel* m_sourceModel; + // Compares two rows of data. + bool lessThan(const QModelIndex& left, const QModelIndex& right) const; + + // Source model pointer. + MessagesModel* m_sourceModel; }; #endif // MESSAGESPROXYMODEL_H diff --git a/src/definitions/definitions.h b/src/definitions/definitions.h index 1a6a0ff21..84296fb44 100755 --- a/src/definitions/definitions.h +++ b/src/definitions/definitions.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -46,7 +47,8 @@ #define DEFAULT_LOCALE "en" #define DEFAULT_FEED_ENCODING "UTF-8" #define DEFAULT_FEED_TYPE "RSS" -#define URL_REGEXP "^(http|https|feed|ftp):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?$" +#define URL_REGEXP \ + "^(http|https|feed|ftp):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?$" #define USER_AGENT_HTTP_HEADER "User-Agent" #define TEXT_TITLE_LIMIT 30 #define RESELECT_MESSAGE_THRESSHOLD 500 @@ -140,6 +142,7 @@ #define APP_THEME_SUFFIX ".png" #ifndef QSL + // Thin macro wrapper for literal strings. // They are much more memory efficient and faster. // Use it for all literals except for two cases: @@ -149,12 +152,14 @@ #endif #ifndef QL1S + // Macro for latin strings. Latin strings are // faster than QStrings created from literals. #define QL1S(x) QLatin1String(x) #endif #ifndef QL1C + // Macro for latin chars. #define QL1C(x) QLatin1Char(x) #endif diff --git a/src/dynamic-shortcuts/dynamicshortcuts.cpp b/src/dynamic-shortcuts/dynamicshortcuts.cpp index 7898e1308..b751cca1a 100755 --- a/src/dynamic-shortcuts/dynamicshortcuts.cpp +++ b/src/dynamic-shortcuts/dynamicshortcuts.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,25 +24,24 @@ #include - -DynamicShortcuts::DynamicShortcuts() { -} +DynamicShortcuts::DynamicShortcuts() {} void DynamicShortcuts::save(const QList& actions) { - Settings* settings = qApp->settings(); + Settings* settings = qApp->settings(); - foreach (const QAction* action, actions) { - settings->setValue(GROUP(Keyboard), action->objectName(), action->shortcut().toString(QKeySequence::PortableText)); - } + foreach (const QAction* action, actions) { + settings->setValue(GROUP(Keyboard), action->objectName(), action->shortcut().toString(QKeySequence::PortableText)); + } } void DynamicShortcuts::load(const QList& actions) { - Settings* settings = qApp->settings(); + Settings* settings = qApp->settings(); - foreach (QAction* action, actions) { - QString shortcut_for_action = settings->value(GROUP(Keyboard), - action->objectName(), - action->shortcut().toString(QKeySequence::PortableText)).toString(); - action->setShortcut(QKeySequence::fromString(shortcut_for_action, QKeySequence::PortableText)); - } + foreach (QAction* action, actions) { + QString shortcut_for_action = settings->value(GROUP(Keyboard), + action->objectName(), + action->shortcut().toString(QKeySequence::PortableText)).toString(); + + action->setShortcut(QKeySequence::fromString(shortcut_for_action, QKeySequence::PortableText)); + } } diff --git a/src/dynamic-shortcuts/dynamicshortcuts.h b/src/dynamic-shortcuts/dynamicshortcuts.h index 23026399c..e03c34ff9 100755 --- a/src/dynamic-shortcuts/dynamicshortcuts.h +++ b/src/dynamic-shortcuts/dynamicshortcuts.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,22 +21,23 @@ #include - class QAction; class DynamicShortcuts { - public: - // Checks the application settings and then initializes shortcut of - // each action from actions from the settings. - static void load(const QList& actions); + public: - // Stores shortcut of each action from actions into the application - // settings. - static void save(const QList& actions); + // Checks the application settings and then initializes shortcut of + // each action from actions from the settings. + static void load(const QList& actions); - private: - // Constructor. - explicit DynamicShortcuts(); + // Stores shortcut of each action from actions into the application + // settings. + static void save(const QList& actions); + + private: + + // Constructor. + explicit DynamicShortcuts(); }; #endif // DYNAMICSHORTCUTS_H diff --git a/src/dynamic-shortcuts/dynamicshortcutswidget.cpp b/src/dynamic-shortcuts/dynamicshortcutswidget.cpp index 39f526665..0e0ff5950 100755 --- a/src/dynamic-shortcuts/dynamicshortcutswidget.cpp +++ b/src/dynamic-shortcuts/dynamicshortcutswidget.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,93 +18,97 @@ #include "dynamic-shortcuts/dynamicshortcutswidget.h" -#include "dynamic-shortcuts/shortcutcatcher.h" -#include "dynamic-shortcuts/shortcutbutton.h" #include "definitions/definitions.h" +#include "dynamic-shortcuts/shortcutbutton.h" +#include "dynamic-shortcuts/shortcutcatcher.h" -#include #include +#include #include - DynamicShortcutsWidget::DynamicShortcutsWidget(QWidget* parent) : QWidget(parent) { - // Create layout for this control and set is as active. - m_layout = new QGridLayout(this); - m_layout->setMargin(0); - setLayout(m_layout); + // Create layout for this control and set is as active. + m_layout = new QGridLayout(this); + m_layout->setMargin(0); + setLayout(m_layout); } DynamicShortcutsWidget::~DynamicShortcutsWidget() { - delete m_layout; + delete m_layout; } bool DynamicShortcutsWidget::areShortcutsUnique() const { - QList all_shortcuts; + QList all_shortcuts; - // Obtain all shortcuts. - foreach (const ActionBinding& binding, m_actionBindings) { - const QKeySequence new_shortcut = binding.second->shortcut(); + // Obtain all shortcuts. + foreach (const ActionBinding& binding, m_actionBindings) { + const QKeySequence new_shortcut = binding.second->shortcut(); - if (!new_shortcut.isEmpty() && all_shortcuts.contains(new_shortcut)) { - // Problem, two identical non-empty shortcuts found. - return false; - } - else { - all_shortcuts.append(binding.second->shortcut()); - } - } + if (!new_shortcut.isEmpty() && all_shortcuts.contains(new_shortcut)) { + // Problem, two identical non-empty shortcuts found. + return false; + } + else { + all_shortcuts.append(binding.second->shortcut()); + } + } - return true; + return true; } void DynamicShortcutsWidget::updateShortcuts() { - foreach (const ActionBinding& binding, m_actionBindings) { - binding.first->setShortcut(binding.second->shortcut()); - } + foreach (const ActionBinding& binding, m_actionBindings) { + binding.first->setShortcut(binding.second->shortcut()); + } } void DynamicShortcutsWidget::populate(QList actions) { - m_actionBindings.clear(); - qSort(actions.begin(), actions.end(), DynamicShortcutsWidget::lessThan); - int row_id = 0; + m_actionBindings.clear(); + qSort(actions.begin(), actions.end(), DynamicShortcutsWidget::lessThan); + int row_id = 0; - // FIXME: Maybe separate actions into "categories". Each category will start with label. - // I will assign each QAaction a property called "category" with some enum value. - // Like: - // File, FeedsCategories, Messages, Tools, WebBrowser, Help - // This will be setup in FormMain::allActions(). - // Then here I will process actions into categories. + // FIXME: Maybe separate actions into "categories". Each category will start with label. + // I will assign each QAaction a property called "category" with some enum value. + // Like: + // File, FeedsCategories, Messages, Tools, WebBrowser, Help + // This will be setup in FormMain::allActions(). + // Then here I will process actions into categories. - foreach (QAction* action, actions) { - // Create shortcut catcher for this action and set default shortcut. - ShortcutCatcher* catcher = new ShortcutCatcher(this); - catcher->setDefaultShortcut(action->shortcut()); - // Store information for re-initialization of shortcuts - // of actions when widget gets "confirmed". - QPair new_binding; - new_binding.first = action; - new_binding.second = catcher; - m_actionBindings << new_binding; - // Add new catcher to our control. - QLabel* action_label = new QLabel(this); - action_label->setText(action->text().remove(QSL("&"))); - action_label->setToolTip(action->toolTip()); - action_label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); - QLabel* action_icon = new QLabel(this); - action_icon->setPixmap(action->icon().pixmap(ICON_SIZE_SETTINGS, ICON_SIZE_SETTINGS)); - action_icon->setToolTip(action->toolTip()); - m_layout->addWidget(action_icon, row_id, 0); - m_layout->addWidget(action_label, row_id, 1); - m_layout->addWidget(catcher, row_id, 2); - row_id++; - connect(catcher, &ShortcutCatcher::shortcutChanged, this, &DynamicShortcutsWidget::setupChanged); - } + foreach (QAction* action, actions) { + // Create shortcut catcher for this action and set default shortcut. + ShortcutCatcher* catcher = new ShortcutCatcher(this); - // Make sure that "spacer" is added. - m_layout->setRowStretch(row_id, 1); - m_layout->setColumnStretch(1, 1); + catcher->setDefaultShortcut(action->shortcut()); + + // Store information for re-initialization of shortcuts + // of actions when widget gets "confirmed". + QPair new_binding; + new_binding.first = action; + new_binding.second = catcher; + m_actionBindings << new_binding; + + // Add new catcher to our control. + QLabel* action_label = new QLabel(this); + + action_label->setText(action->text().remove(QSL("&"))); + action_label->setToolTip(action->toolTip()); + action_label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + QLabel* action_icon = new QLabel(this); + + action_icon->setPixmap(action->icon().pixmap(ICON_SIZE_SETTINGS, ICON_SIZE_SETTINGS)); + action_icon->setToolTip(action->toolTip()); + m_layout->addWidget(action_icon, row_id, 0); + m_layout->addWidget(action_label, row_id, 1); + m_layout->addWidget(catcher, row_id, 2); + row_id++; + connect(catcher, &ShortcutCatcher::shortcutChanged, this, &DynamicShortcutsWidget::setupChanged); + } + + // Make sure that "spacer" is added. + m_layout->setRowStretch(row_id, 1); + m_layout->setColumnStretch(1, 1); } bool DynamicShortcutsWidget::lessThan(QAction* lhs, QAction* rhs) { - return QString::localeAwareCompare(lhs->text().replace(QL1S("&"), QString()), rhs->text().replace(QL1S("&"), QString())) < 0; + return QString::localeAwareCompare(lhs->text().replace(QL1S("&"), QString()), rhs->text().replace(QL1S("&"), QString())) < 0; } diff --git a/src/dynamic-shortcuts/dynamicshortcutswidget.h b/src/dynamic-shortcuts/dynamicshortcutswidget.h index 9beb77b90..1fc37ae3b 100755 --- a/src/dynamic-shortcuts/dynamicshortcutswidget.h +++ b/src/dynamic-shortcuts/dynamicshortcutswidget.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,45 +21,46 @@ #include - class QGridLayout; class ShortcutCatcher; typedef QPair ActionBinding; class DynamicShortcutsWidget : public QWidget { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit DynamicShortcutsWidget(QWidget* parent = 0); - virtual ~DynamicShortcutsWidget(); + public: - // Updates shortcuts of all actions according to changes. - // NOTE: No access to settings is done here. - // Shortcuts are fetched from settings when applications starts - // and stored back to settings when application quits. - void updateShortcuts(); + // Constructors and destructors. + explicit DynamicShortcutsWidget(QWidget* parent = 0); + virtual ~DynamicShortcutsWidget(); - // Returns true if all shortcuts are unique, - // otherwise false. - bool areShortcutsUnique() const; + // Updates shortcuts of all actions according to changes. + // NOTE: No access to settings is done here. + // Shortcuts are fetched from settings when applications starts + // and stored back to settings when application quits. + void updateShortcuts(); - // Populates this widget with shortcut widgets for given actions. - // NOTE: This gets initial shortcut for each action from its properties, NOT from - // the application settings, so shortcuts from settings need to be - // assigned to actions before calling this method. - void populate(QList actions); + // Returns true if all shortcuts are unique, + // otherwise false. + bool areShortcutsUnique() const; - signals: - void setupChanged(); + // Populates this widget with shortcut widgets for given actions. + // NOTE: This gets initial shortcut for each action from its properties, NOT from + // the application settings, so shortcuts from settings need to be + // assigned to actions before calling this method. + void populate(QList actions); - private: - static bool lessThan(QAction* lhs, QAction* rhs); + signals: + void setupChanged(); - private: - QGridLayout* m_layout; - QList m_actionBindings; + private: + static bool lessThan(QAction* lhs, QAction* rhs); + + private: + QGridLayout* m_layout; + + QList m_actionBindings; }; #endif // DYNAMICSHORTCUTSOVERVIEW_H diff --git a/src/dynamic-shortcuts/shortcutbutton.cpp b/src/dynamic-shortcuts/shortcutbutton.cpp index 1b3f82182..6488082dd 100755 --- a/src/dynamic-shortcuts/shortcutbutton.cpp +++ b/src/dynamic-shortcuts/shortcutbutton.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -16,32 +17,32 @@ // along with RSS Guard. If not, see . /****************************************************************************** -Copyright (c) 2010, Artem Galichkin -All rights reserved. + Copyright (c) 2010, Artem Galichkin + All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of the nor the + * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************/ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ #include "dynamic-shortcuts/shortcutbutton.h" @@ -49,94 +50,92 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include - ShortcutButton::ShortcutButton(ShortcutCatcher* catcher, QWidget* parent) - : QPushButton(parent), m_catcher(catcher) { - setMinimumWidth(100); + : QPushButton(parent), m_catcher(catcher) { + setMinimumWidth(100); } -ShortcutButton::~ShortcutButton() { -} +ShortcutButton::~ShortcutButton() {} void ShortcutButton::keyPressEvent(QKeyEvent* event) { - int pressed_key = event->key(); + int pressed_key = event->key(); - if (pressed_key == -1) { - m_catcher->doneRecording(); - } + if (pressed_key == -1) { + m_catcher->doneRecording(); + } - const Qt::KeyboardModifiers new_modifiers = event->modifiers() & (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META); + const Qt::KeyboardModifiers new_modifiers = event->modifiers() & (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META); - if (!m_catcher->m_isRecording && (pressed_key == Qt::Key_Return || pressed_key == Qt::Key_Space)) { - return; - } + if (!m_catcher->m_isRecording && (pressed_key == Qt::Key_Return || pressed_key == Qt::Key_Space)) { + return; + } - if (!m_catcher->m_isRecording) { - QPushButton::keyPressEvent(event); - return; - } + if (!m_catcher->m_isRecording) { + QPushButton::keyPressEvent(event); + return; + } - event->accept(); - m_catcher->m_modifierKeys = new_modifiers; + event->accept(); + m_catcher->m_modifierKeys = new_modifiers; - switch (pressed_key) { - case Qt::Key_AltGr: - return; + switch (pressed_key) { + case Qt::Key_AltGr: + return; - case Qt::Key_Shift: - case Qt::Key_Control: - case Qt::Key_Alt: - case Qt::Key_Meta: - case Qt::Key_Menu: - m_catcher->controlModifierlessTimout(); - m_catcher->updateDisplayShortcut(); - break; + case Qt::Key_Shift: + case Qt::Key_Control: + case Qt::Key_Alt: + case Qt::Key_Meta: + case Qt::Key_Menu: + m_catcher->controlModifierlessTimout(); + m_catcher->updateDisplayShortcut(); + break; - default: + default: - // We now have a valid key press. - if (pressed_key) { - if ((pressed_key == Qt::Key_Backtab) && (m_catcher->m_modifierKeys & Qt::SHIFT)) { - pressed_key = Qt::Key_Tab | m_catcher->m_modifierKeys; - } - else { - pressed_key |= m_catcher->m_modifierKeys; - } + // We now have a valid key press. + if (pressed_key) { + if ((pressed_key == Qt::Key_Backtab) && (m_catcher->m_modifierKeys & Qt::SHIFT)) { + pressed_key = Qt::Key_Tab | m_catcher->m_modifierKeys; + } + else { + pressed_key |= m_catcher->m_modifierKeys; + } - if (m_catcher->m_numKey == 0) { - m_catcher->m_currentSequence = QKeySequence(pressed_key); - } + if (m_catcher->m_numKey == 0) { + m_catcher->m_currentSequence = QKeySequence(pressed_key); + } - m_catcher->m_numKey++; + m_catcher->m_numKey++; - if (m_catcher->m_numKey >= 4) { - m_catcher->doneRecording(); - return; - } + if (m_catcher->m_numKey >= 4) { + m_catcher->doneRecording(); + return; + } - m_catcher->controlModifierlessTimout(); - m_catcher->updateDisplayShortcut(); - } - } + m_catcher->controlModifierlessTimout(); + m_catcher->updateDisplayShortcut(); + } + } } void ShortcutButton::keyReleaseEvent(QKeyEvent* event) { - if (event->key() == -1) { - return; - } + if (event->key() == -1) { + return; + } - if (!m_catcher->m_isRecording) { - QPushButton::keyReleaseEvent(event); - return; - } + if (!m_catcher->m_isRecording) { + QPushButton::keyReleaseEvent(event); + return; + } - event->accept(); - const Qt::KeyboardModifiers new_modifiers = event->modifiers() & - (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META); + event->accept(); + const Qt::KeyboardModifiers new_modifiers = event->modifiers() & + (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META); - if (((uint) new_modifiers & m_catcher->m_modifierKeys) < m_catcher->m_modifierKeys) { - m_catcher->m_modifierKeys = new_modifiers; - m_catcher->controlModifierlessTimout(); - m_catcher->updateDisplayShortcut(); - } + if (((uint) new_modifiers & m_catcher->m_modifierKeys) < m_catcher->m_modifierKeys) { + m_catcher->m_modifierKeys = new_modifiers; + m_catcher->controlModifierlessTimout(); + m_catcher->updateDisplayShortcut(); + } } diff --git a/src/dynamic-shortcuts/shortcutbutton.h b/src/dynamic-shortcuts/shortcutbutton.h index 328ab3399..6a031b4e8 100755 --- a/src/dynamic-shortcuts/shortcutbutton.h +++ b/src/dynamic-shortcuts/shortcutbutton.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -16,55 +17,55 @@ // along with RSS Guard. If not, see . /****************************************************************************** -Copyright (c) 2010, Artem Galichkin -All rights reserved. + Copyright (c) 2010, Artem Galichkin + All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of the nor the + * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************/ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ #ifndef SHORTCUTBUTTON_H #define SHORTCUTBUTTON_H #include - class ShortcutCatcher; class ShortcutButton : public QPushButton { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit ShortcutButton(ShortcutCatcher* catcher, QWidget* parent = 0); - virtual ~ShortcutButton(); + public: - protected: - void keyPressEvent(QKeyEvent* event); - void keyReleaseEvent(QKeyEvent* event); + // Constructors and destructors. + explicit ShortcutButton(ShortcutCatcher* catcher, QWidget* parent = 0); + virtual ~ShortcutButton(); - private: - ShortcutCatcher* m_catcher; + protected: + void keyPressEvent(QKeyEvent* event); + void keyReleaseEvent(QKeyEvent* event); + + private: + ShortcutCatcher* m_catcher; }; #endif // SHORTCUTBUTTON_H diff --git a/src/dynamic-shortcuts/shortcutcatcher.cpp b/src/dynamic-shortcuts/shortcutcatcher.cpp index 261468fc8..767be6faf 100755 --- a/src/dynamic-shortcuts/shortcutcatcher.cpp +++ b/src/dynamic-shortcuts/shortcutcatcher.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -16,32 +17,32 @@ // along with RSS Guard. If not, see . /****************************************************************************** -Copyright (c) 2010, Artem Galichkin -All rights reserved. + Copyright (c) 2010, Artem Galichkin + All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of the nor the + * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************/ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ #include "dynamic-shortcuts/shortcutcatcher.h" @@ -51,119 +52,125 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include - ShortcutCatcher::ShortcutCatcher(QWidget* parent) - : QWidget(parent) { - // Setup layout of the control - m_layout = new QHBoxLayout(this); - m_layout->setMargin(0); - m_layout->setSpacing(1); - // Create reset button. - m_btnReset = new PlainToolButton(this); - m_btnReset->setIcon(qApp->icons()->fromTheme(QSL("document-revert"))); - m_btnReset->setFocusPolicy(Qt::NoFocus); - m_btnReset->setToolTip(tr("Reset to original shortcut.")); - // Create clear button. - m_btnClear = new PlainToolButton(this); - m_btnClear->setIcon(qApp->icons()->fromTheme(QSL("list-remove"))); - m_btnClear->setFocusPolicy(Qt::NoFocus); - m_btnClear->setToolTip(tr("Clear current shortcut.")); - // Clear main shortcut catching button. - m_btnChange = new ShortcutButton(this); - m_btnChange->setFocusPolicy(Qt::StrongFocus); - m_btnChange->setToolTip(tr("Click and hit new shortcut.")); - // Add both buttons to the layout. - m_layout->addWidget(m_btnChange); - m_layout->addWidget(m_btnReset); - m_layout->addWidget(m_btnClear); - // Establish needed connections. - connect(m_btnReset, &QToolButton::clicked, this, &ShortcutCatcher::resetShortcut); - connect(m_btnClear, &QToolButton::clicked, this, &ShortcutCatcher::clearShortcut); - connect(m_btnChange, &QToolButton::clicked, this, &ShortcutCatcher::startRecording); - // Prepare initial state of the control. - updateDisplayShortcut(); + : QWidget(parent) { + // Setup layout of the control + m_layout = new QHBoxLayout(this); + m_layout->setMargin(0); + m_layout->setSpacing(1); + + // Create reset button. + m_btnReset = new PlainToolButton(this); + m_btnReset->setIcon(qApp->icons()->fromTheme(QSL("document-revert"))); + m_btnReset->setFocusPolicy(Qt::NoFocus); + m_btnReset->setToolTip(tr("Reset to original shortcut.")); + + // Create clear button. + m_btnClear = new PlainToolButton(this); + m_btnClear->setIcon(qApp->icons()->fromTheme(QSL("list-remove"))); + m_btnClear->setFocusPolicy(Qt::NoFocus); + m_btnClear->setToolTip(tr("Clear current shortcut.")); + + // Clear main shortcut catching button. + m_btnChange = new ShortcutButton(this); + m_btnChange->setFocusPolicy(Qt::StrongFocus); + m_btnChange->setToolTip(tr("Click and hit new shortcut.")); + + // Add both buttons to the layout. + m_layout->addWidget(m_btnChange); + m_layout->addWidget(m_btnReset); + m_layout->addWidget(m_btnClear); + + // Establish needed connections. + connect(m_btnReset, &QToolButton::clicked, this, &ShortcutCatcher::resetShortcut); + connect(m_btnClear, &QToolButton::clicked, this, &ShortcutCatcher::clearShortcut); + connect(m_btnChange, &QToolButton::clicked, this, &ShortcutCatcher::startRecording); + + // Prepare initial state of the control. + updateDisplayShortcut(); } ShortcutCatcher::~ShortcutCatcher() { - delete m_btnReset; - delete m_btnChange; - delete m_btnClear; - delete m_layout; + delete m_btnReset; + delete m_btnChange; + delete m_btnClear; + delete m_layout; } void ShortcutCatcher::startRecording() { - m_numKey = 0; - m_modifierKeys = 0; - m_currentSequence = QKeySequence(); - m_isRecording = true; - m_btnChange->setDown(true); - m_btnChange->grabKeyboard(); - updateDisplayShortcut(); + m_numKey = 0; + m_modifierKeys = 0; + m_currentSequence = QKeySequence(); + m_isRecording = true; + m_btnChange->setDown(true); + m_btnChange->grabKeyboard(); + updateDisplayShortcut(); } void ShortcutCatcher::doneRecording() { - m_isRecording = false; - m_btnChange->releaseKeyboard(); - m_btnChange->setDown(false); - updateDisplayShortcut(); - emit shortcutChanged(m_currentSequence); + m_isRecording = false; + m_btnChange->releaseKeyboard(); + m_btnChange->setDown(false); + updateDisplayShortcut(); + emit shortcutChanged(m_currentSequence); } void ShortcutCatcher::controlModifierlessTimout() { - if (m_numKey && !m_modifierKeys) { - doneRecording(); - } + if (m_numKey && !m_modifierKeys) { + doneRecording(); + } } void ShortcutCatcher::updateDisplayShortcut() { - QString str = m_currentSequence.toString(QKeySequence::NativeText); - str.replace(QL1S("&"), QL1S("&&")); + QString str = m_currentSequence.toString(QKeySequence::NativeText); - if (m_isRecording) { - if (m_modifierKeys) { - if (!str.isEmpty()) { - str.append(QSL(",")); - } + str.replace(QL1S("&"), QL1S("&&")); - if (m_modifierKeys & Qt::META) { - str += QL1S("Meta + "); - } + if (m_isRecording) { + if (m_modifierKeys) { + if (!str.isEmpty()) { + str.append(QSL(",")); + } - if (m_modifierKeys & Qt::CTRL) { - str += QL1S("Ctrl + "); - } + if (m_modifierKeys & Qt::META) { + str += QL1S("Meta + "); + } - if (m_modifierKeys & Qt::ALT) { - str += QL1S("Alt + "); - } + if (m_modifierKeys & Qt::CTRL) { + str += QL1S("Ctrl + "); + } - if (m_modifierKeys & Qt::SHIFT) { - str += QL1S("Shift + "); - } - } - } + if (m_modifierKeys & Qt::ALT) { + str += QL1S("Alt + "); + } - m_btnChange->setText(str); + if (m_modifierKeys & Qt::SHIFT) { + str += QL1S("Shift + "); + } + } + } + + m_btnChange->setText(str); } QKeySequence ShortcutCatcher::shortcut() const { - return m_currentSequence; + return m_currentSequence; } void ShortcutCatcher::setDefaultShortcut(const QKeySequence& key) { - m_defaultSequence = key; - setShortcut(key); + m_defaultSequence = key; + setShortcut(key); } void ShortcutCatcher::setShortcut(const QKeySequence& key) { - m_currentSequence = key; - doneRecording(); + m_currentSequence = key; + doneRecording(); } void ShortcutCatcher::resetShortcut() { - setShortcut(m_defaultSequence); + setShortcut(m_defaultSequence); } void ShortcutCatcher::clearShortcut() { - setShortcut(QKeySequence()); + setShortcut(QKeySequence()); } diff --git a/src/dynamic-shortcuts/shortcutcatcher.h b/src/dynamic-shortcuts/shortcutcatcher.h index f1f80b2eb..8b4432ad5 100755 --- a/src/dynamic-shortcuts/shortcutcatcher.h +++ b/src/dynamic-shortcuts/shortcutcatcher.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -16,83 +17,81 @@ // along with RSS Guard. If not, see . /****************************************************************************** -Copyright (c) 2010, Artem Galichkin -All rights reserved. + Copyright (c) 2010, Artem Galichkin + All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of the nor the + * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************/ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ #ifndef SHORTCUTCATCHER_H #define SHORTCUTCATCHER_H #include - class QHBoxLayout; class QToolButton; class ShortcutButton; class ShortcutCatcher : public QWidget { - Q_OBJECT + Q_OBJECT - friend class ShortcutButton; + friend class ShortcutButton; - public: - // Constructors and destructors. - explicit ShortcutCatcher(QWidget* parent = 0); - virtual ~ShortcutCatcher(); + public: - void controlModifierlessTimout(); - void updateDisplayShortcut(); + // Constructors and destructors. + explicit ShortcutCatcher(QWidget* parent = 0); + virtual ~ShortcutCatcher(); - QKeySequence shortcut() const; - void setDefaultShortcut(const QKeySequence& key); - void setShortcut(const QKeySequence& key); + void controlModifierlessTimout(); + void updateDisplayShortcut(); - public slots: - void resetShortcut(); - void clearShortcut(); + QKeySequence shortcut() const; + void setDefaultShortcut(const QKeySequence& key); + void setShortcut(const QKeySequence& key); - private slots: - void startRecording(); - void doneRecording(); + public slots: + void resetShortcut(); + void clearShortcut(); - signals: - void shortcutChanged(const QKeySequence& seguence); + private slots: + void startRecording(); + void doneRecording(); - private: - QToolButton* m_btnReset; - QToolButton* m_btnClear; - ShortcutButton* m_btnChange; - QHBoxLayout* m_layout; + signals: + void shortcutChanged(const QKeySequence& seguence); - QKeySequence m_currentSequence; - QKeySequence m_defaultSequence; - - bool m_isRecording; - int m_numKey; - uint m_modifierKeys; + private: + QToolButton* m_btnReset; + QToolButton* m_btnClear; + ShortcutButton* m_btnChange; + QHBoxLayout* m_layout; + QKeySequence m_currentSequence; + QKeySequence m_defaultSequence; + bool m_isRecording; + int m_numKey; + uint m_modifierKeys; }; #endif // KEYSEQUENCECATCHER_H diff --git a/src/exceptions/applicationexception.cpp b/src/exceptions/applicationexception.cpp index e7cd17a24..b2d1133a6 100755 --- a/src/exceptions/applicationexception.cpp +++ b/src/exceptions/applicationexception.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,13 +18,10 @@ #include "exceptions/applicationexception.h" +ApplicationException::ApplicationException(const QString& message) : m_message(message) {} -ApplicationException::ApplicationException(const QString& message) : m_message(message) { -} - -ApplicationException::~ApplicationException() { -} +ApplicationException::~ApplicationException() {} QString ApplicationException::message() const { - return m_message; + return m_message; } diff --git a/src/exceptions/applicationexception.h b/src/exceptions/applicationexception.h index c5371ae83..9d238ea6a 100755 --- a/src/exceptions/applicationexception.h +++ b/src/exceptions/applicationexception.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,16 +21,15 @@ #include - class ApplicationException { - public: - explicit ApplicationException(const QString& message = QString()); - virtual ~ApplicationException(); + public: + explicit ApplicationException(const QString& message = QString()); + virtual ~ApplicationException(); - QString message() const; + QString message() const; - private: - QString m_message; + private: + QString m_message; }; #endif // APPLICATIONEXCEPTION_H diff --git a/src/exceptions/ioexception.cpp b/src/exceptions/ioexception.cpp index 6b093f50e..ee60fc2dd 100755 --- a/src/exceptions/ioexception.cpp +++ b/src/exceptions/ioexception.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,9 +18,6 @@ #include "exceptions/ioexception.h" +IOException::IOException(const QString& message) : ApplicationException(message) {} -IOException::IOException(const QString& message) : ApplicationException(message) { -} - -IOException::~IOException() { -} +IOException::~IOException() {} diff --git a/src/exceptions/ioexception.h b/src/exceptions/ioexception.h index 213086992..b2af0c4a1 100755 --- a/src/exceptions/ioexception.h +++ b/src/exceptions/ioexception.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,11 +21,10 @@ #include "exceptions/applicationexception.h" - class IOException : public ApplicationException { - public: - explicit IOException(const QString& message = QString()); - virtual ~IOException(); + public: + explicit IOException(const QString& message = QString()); + virtual ~IOException(); }; #endif // IOEXCEPTION_H diff --git a/src/gui/baselineedit.cpp b/src/gui/baselineedit.cpp index 07d05c29c..58410dedb 100755 --- a/src/gui/baselineedit.cpp +++ b/src/gui/baselineedit.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,23 +20,21 @@ #include +BaseLineEdit::BaseLineEdit(QWidget* parent) : QLineEdit(parent) {} -BaseLineEdit::BaseLineEdit(QWidget* parent) : QLineEdit(parent) { -} - -BaseLineEdit::~BaseLineEdit() { -} +BaseLineEdit::~BaseLineEdit() {} void BaseLineEdit::submit(const QString& text) { - setText(text); - emit submitted(text); + setText(text); + emit submitted(text); } void BaseLineEdit::keyPressEvent(QKeyEvent* event) { - if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { - emit submitted(text()); - event->accept(); - } + if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { + emit submitted(text()); - QLineEdit::keyPressEvent(event); + event->accept(); + } + + QLineEdit::keyPressEvent(event); } diff --git a/src/gui/baselineedit.h b/src/gui/baselineedit.h index 67fe8a9f5..aff4b64f8 100755 --- a/src/gui/baselineedit.h +++ b/src/gui/baselineedit.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,24 +21,25 @@ #include - class BaseLineEdit : public QLineEdit { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit BaseLineEdit(QWidget* parent = 0); - virtual ~BaseLineEdit(); + public: - public slots: - void submit(const QString& text); + // Constructors and destructors. + explicit BaseLineEdit(QWidget* parent = 0); + virtual ~BaseLineEdit(); - protected: - void keyPressEvent(QKeyEvent* event); + public slots: + void submit(const QString& text); - signals: - // Emitted if user hits ENTER button. - void submitted(const QString& text); + protected: + void keyPressEvent(QKeyEvent* event); + + signals: + + // Emitted if user hits ENTER button. + void submitted(const QString& text); }; #endif // BASELINEEDIT_H diff --git a/src/gui/basetoolbar.cpp b/src/gui/basetoolbar.cpp index e2300367e..eb7bd8c25 100755 --- a/src/gui/basetoolbar.cpp +++ b/src/gui/basetoolbar.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,28 +24,28 @@ #include - BaseToolBar::BaseToolBar(const QString& title, QWidget* parent) : QToolBar(title, parent) { - // Update right margin of filter textbox. - QMargins margins = contentsMargins(); - margins.setRight(margins.right() + FILTER_RIGHT_MARGIN); - setContentsMargins(margins); + // Update right margin of filter textbox. + QMargins margins = contentsMargins(); + + margins.setRight(margins.right() + FILTER_RIGHT_MARGIN); + setContentsMargins(margins); } BaseToolBar::~BaseToolBar() { - qDebug("Destroying BaseToolBar instance."); + qDebug("Destroying BaseToolBar instance."); } void BaseBar::loadSavedActions() { - loadSpecificActions(getSpecificActions(savedActions())); + loadSpecificActions(getSpecificActions(savedActions())); } QAction* BaseBar::findMatchingAction(const QString& action, const QList& actions) const { - foreach (QAction* act, actions) { - if (act->objectName() == action) { - return act; - } - } + foreach (QAction* act, actions) { + if (act->objectName() == action) { + return act; + } + } - return nullptr; + return nullptr; } diff --git a/src/gui/basetoolbar.h b/src/gui/basetoolbar.h index 8a52aff92..1ac120041 100755 --- a/src/gui/basetoolbar.h +++ b/src/gui/basetoolbar.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,41 +21,41 @@ #include - class BaseBar { - public: - // Returns all actions which can be added to the toolbar. - virtual QList availableActions() const = 0; + public: - // Returns all changeable actions which are currently included - // in the toolbar. - virtual QList changeableActions() const = 0; + // Returns all actions which can be added to the toolbar. + virtual QList availableActions() const = 0; - // Sets new "actions" to the toolbar and perhaps saves the toolbar - // state into the settings. - virtual void saveChangeableActions(const QStringList& actions) = 0; + // Returns all changeable actions which are currently included + // in the toolbar. + virtual QList changeableActions() const = 0; - // Returns list of default actions. - virtual QStringList defaultActions() const = 0; - virtual QStringList savedActions() const = 0; + // Sets new "actions" to the toolbar and perhaps saves the toolbar + // state into the settings. + virtual void saveChangeableActions(const QStringList& actions) = 0; - // Loads the toolbar state from settings. - virtual void loadSavedActions(); + // Returns list of default actions. + virtual QStringList defaultActions() const = 0; + virtual QStringList savedActions() const = 0; - virtual QList getSpecificActions(const QStringList& actions) = 0; - virtual void loadSpecificActions(const QList& actions) = 0; + // Loads the toolbar state from settings. + virtual void loadSavedActions(); + virtual QList getSpecificActions(const QStringList& actions) = 0; + virtual void loadSpecificActions(const QList& actions) = 0; - protected: - QAction* findMatchingAction(const QString& action, const QList& actions) const; + protected: + QAction* findMatchingAction(const QString& action, const QList& actions) const; }; class BaseToolBar : public QToolBar, public BaseBar { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit BaseToolBar(const QString& title, QWidget* parent = 0); - virtual ~BaseToolBar(); + public: + + // Constructors and destructors. + explicit BaseToolBar(const QString& title, QWidget* parent = 0); + virtual ~BaseToolBar(); }; #endif // TOOLBAR_H diff --git a/src/gui/colorlabel.cpp b/src/gui/colorlabel.cpp index 61816125e..9347f1e02 100755 --- a/src/gui/colorlabel.cpp +++ b/src/gui/colorlabel.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,26 +18,24 @@ #include "gui/colorlabel.h" -#include #include - +#include ColorLabel::ColorLabel(QWidget* parent) : QLabel(parent), m_color(QColor()) { - setFixedWidth(20); + setFixedWidth(20); } -ColorLabel::~ColorLabel() { -} +ColorLabel::~ColorLabel() {} QColor ColorLabel::color() const { - return m_color; + return m_color; } void ColorLabel::setColor(const QColor& color) { - m_color = color; - repaint(); + m_color = color; + repaint(); } void ColorLabel::paintEvent(QPaintEvent* event) { - QPainter(this).fillRect(event->rect(), m_color); + QPainter(this).fillRect(event->rect(), m_color); } diff --git a/src/gui/colorlabel.h b/src/gui/colorlabel.h index 9cda8e774..a64636ecc 100755 --- a/src/gui/colorlabel.h +++ b/src/gui/colorlabel.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,22 +21,21 @@ #include - class ColorLabel : public QLabel { - Q_OBJECT + Q_OBJECT - public: - explicit ColorLabel(QWidget* parent = 0); - virtual ~ColorLabel(); + public: + explicit ColorLabel(QWidget* parent = 0); + virtual ~ColorLabel(); - QColor color() const; - void setColor(const QColor& color); + QColor color() const; + void setColor(const QColor& color); - protected: - void paintEvent(QPaintEvent* event); + protected: + void paintEvent(QPaintEvent* event); - private: - QColor m_color; + private: + QColor m_color; }; #endif // COLORLABEL_H diff --git a/src/gui/comboboxwithstatus.cpp b/src/gui/comboboxwithstatus.cpp index d50cb20d2..5883375f6 100755 --- a/src/gui/comboboxwithstatus.cpp +++ b/src/gui/comboboxwithstatus.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,17 +22,18 @@ #include - ComboBoxWithStatus::ComboBoxWithStatus(QWidget* parent) - : WidgetWithStatus(parent) { - m_wdgInput = new QComboBox(this); - // Set correct size for the tool button. - const int txt_input_height = m_wdgInput->sizeHint().height(); - m_btnStatus->setFixedSize(txt_input_height, txt_input_height); - // Compose the layout. - m_layout->addWidget(m_wdgInput); - m_layout->addWidget(m_btnStatus); + : WidgetWithStatus(parent) { + m_wdgInput = new QComboBox(this); + + // Set correct size for the tool button. + const int txt_input_height = m_wdgInput->sizeHint().height(); + + m_btnStatus->setFixedSize(txt_input_height, txt_input_height); + + // Compose the layout. + m_layout->addWidget(m_wdgInput); + m_layout->addWidget(m_btnStatus); } -ComboBoxWithStatus::~ComboBoxWithStatus() { -} +ComboBoxWithStatus::~ComboBoxWithStatus() {} diff --git a/src/gui/comboboxwithstatus.h b/src/gui/comboboxwithstatus.h index a81cdb262..9f75c4e1b 100755 --- a/src/gui/comboboxwithstatus.h +++ b/src/gui/comboboxwithstatus.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,18 +23,19 @@ #include - class ComboBoxWithStatus : public WidgetWithStatus { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit ComboBoxWithStatus(QWidget* parent = 0); - virtual ~ComboBoxWithStatus(); + public: + + // Constructors and destructors. + explicit ComboBoxWithStatus(QWidget* parent = 0); + virtual ~ComboBoxWithStatus(); + + inline QComboBox* comboBox() const { + return static_cast(m_wdgInput); + } - inline QComboBox* comboBox() const { - return static_cast(m_wdgInput); - } }; #endif // COMBOBOXWITHSTATUS_H diff --git a/src/gui/dialogs/formabout.h b/src/gui/dialogs/formabout.h index b4b9fbbf0..ec6df583a 100755 --- a/src/gui/dialogs/formabout.h +++ b/src/gui/dialogs/formabout.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -24,20 +25,20 @@ #include "definitions/definitions.h" - class FormAbout : public QDialog { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit FormAbout(QWidget* parent); - virtual ~FormAbout(); + public: - private: - void loadLicenseAndInformation(); - void loadSettingsAndPaths(); + // Constructors and destructors. + explicit FormAbout(QWidget* parent); + virtual ~FormAbout(); - Ui::FormAbout m_ui; + private: + void loadLicenseAndInformation(); + void loadSettingsAndPaths(); + + Ui::FormAbout m_ui; }; #endif // FORMABOUT_H diff --git a/src/gui/dialogs/formaddaccount.cpp b/src/gui/dialogs/formaddaccount.cpp index 5adad3841..54ee2cfc2 100755 --- a/src/gui/dialogs/formaddaccount.cpp +++ b/src/gui/dialogs/formaddaccount.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,66 +18,67 @@ #include "gui/dialogs/formaddaccount.h" +#include "core/feedsmodel.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" -#include "core/feedsmodel.h" #include "services/standard/standardserviceentrypoint.h" -#include #include - +#include FormAddAccount::FormAddAccount(const QList& entry_points, FeedsModel* model, QWidget* parent) - : QDialog(parent), m_ui(new Ui::FormAddAccount), m_model(model), m_entryPoints(entry_points) { - m_ui->setupUi(this); - // Set flags and attributes. - setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); - setWindowIcon(qApp->icons()->fromTheme(QSL("document-new"))); - connect(m_ui->m_listEntryPoints, &QListWidget::itemDoubleClicked, this, &FormAddAccount::addSelectedAccount); - connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormAddAccount::addSelectedAccount); - connect(m_ui->m_listEntryPoints, &QListWidget::itemSelectionChanged, this, &FormAddAccount::displayActiveEntryPointDetails); - loadEntryPoints(); + : QDialog(parent), m_ui(new Ui::FormAddAccount), m_model(model), m_entryPoints(entry_points) { + m_ui->setupUi(this); + + // Set flags and attributes. + setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); + setWindowIcon(qApp->icons()->fromTheme(QSL("document-new"))); + connect(m_ui->m_listEntryPoints, &QListWidget::itemDoubleClicked, this, &FormAddAccount::addSelectedAccount); + connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormAddAccount::addSelectedAccount); + connect(m_ui->m_listEntryPoints, &QListWidget::itemSelectionChanged, this, &FormAddAccount::displayActiveEntryPointDetails); + loadEntryPoints(); } FormAddAccount::~FormAddAccount() { - qDebug("Destroying FormAddAccount instance."); + qDebug("Destroying FormAddAccount instance."); } void FormAddAccount::addSelectedAccount() { - accept(); - ServiceEntryPoint* point = selectedEntryPoint(); - ServiceRoot* new_root = point->createNewRoot(); + accept(); + ServiceEntryPoint* point = selectedEntryPoint(); + ServiceRoot* new_root = point->createNewRoot(); - if (new_root != nullptr) { - m_model->addServiceAccount(new_root, true); - } - else { - qCritical("Cannot create new account."); - } + if (new_root != nullptr) { + m_model->addServiceAccount(new_root, true); + } + else { + qCritical("Cannot create new account."); + } } void FormAddAccount::displayActiveEntryPointDetails() { - const ServiceEntryPoint* point = selectedEntryPoint(); - m_ui->m_txtAuthor->setText(point->author()); - m_ui->m_txtDescription->setText(point->description()); - m_ui->m_txtName->setText(point->name()); - m_ui->m_txtVersion->setText(point->version()); + const ServiceEntryPoint* point = selectedEntryPoint(); + + m_ui->m_txtAuthor->setText(point->author()); + m_ui->m_txtDescription->setText(point->description()); + m_ui->m_txtName->setText(point->name()); + m_ui->m_txtVersion->setText(point->version()); } ServiceEntryPoint* FormAddAccount::selectedEntryPoint() const { - return m_entryPoints.at(m_ui->m_listEntryPoints->currentRow()); + return m_entryPoints.at(m_ui->m_listEntryPoints->currentRow()); } void FormAddAccount::loadEntryPoints() { - foreach (const ServiceEntryPoint* entry_point, m_entryPoints) { - QListWidgetItem* item = new QListWidgetItem(entry_point->icon(), entry_point->name(), m_ui->m_listEntryPoints); + foreach (const ServiceEntryPoint* entry_point, m_entryPoints) { + QListWidgetItem* item = new QListWidgetItem(entry_point->icon(), entry_point->name(), m_ui->m_listEntryPoints); - if (entry_point->isSingleInstanceService() && m_model->containsServiceRootFromEntryPoint(entry_point)) { - // Oops, this item cannot be added, it is single instance and is already added. - item->setFlags(Qt::NoItemFlags); - item->setToolTip(tr("This account can be added only once.")); - } - } + if (entry_point->isSingleInstanceService() && m_model->containsServiceRootFromEntryPoint(entry_point)) { + // Oops, this item cannot be added, it is single instance and is already added. + item->setFlags(Qt::NoItemFlags); + item->setToolTip(tr("This account can be added only once.")); + } + } - m_ui->m_listEntryPoints->setCurrentRow(m_entryPoints.size() - 1); + m_ui->m_listEntryPoints->setCurrentRow(m_entryPoints.size() - 1); } diff --git a/src/gui/dialogs/formaddaccount.h b/src/gui/dialogs/formaddaccount.h index 3a9faa359..746856a9d 100755 --- a/src/gui/dialogs/formaddaccount.h +++ b/src/gui/dialogs/formaddaccount.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,28 +23,29 @@ #include "ui_formaddaccount.h" - class ServiceEntryPoint; class FeedsModel; class FormAddAccount : public QDialog { - Q_OBJECT + Q_OBJECT - public: - explicit FormAddAccount(const QList& entry_points, FeedsModel* model, QWidget* parent = 0); - virtual ~FormAddAccount(); + public: + explicit FormAddAccount(const QList& entry_points, FeedsModel* model, QWidget* parent = 0); + virtual ~FormAddAccount(); - private slots: - void addSelectedAccount(); - void displayActiveEntryPointDetails(); + private slots: + void addSelectedAccount(); + void displayActiveEntryPointDetails(); - private: - ServiceEntryPoint* selectedEntryPoint() const; - void loadEntryPoints(); + private: + ServiceEntryPoint* selectedEntryPoint() const; - QScopedPointer m_ui; - FeedsModel* m_model; - QList m_entryPoints; + void loadEntryPoints(); + + QScopedPointer m_ui; + FeedsModel* m_model; + + QList m_entryPoints; }; #endif // FORMADDACCOUNT_H diff --git a/src/gui/dialogs/formbackupdatabasesettings.cpp b/src/gui/dialogs/formbackupdatabasesettings.cpp index d49b7eb9e..2122632d3 100755 --- a/src/gui/dialogs/formbackupdatabasesettings.cpp +++ b/src/gui/dialogs/formbackupdatabasesettings.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,82 +18,82 @@ #include "gui/dialogs/formbackupdatabasesettings.h" +#include "exceptions/applicationexception.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" -#include "exceptions/applicationexception.h" -#include -#include #include -#include #include - +#include +#include +#include FormBackupDatabaseSettings::FormBackupDatabaseSettings(QWidget* parent) : QDialog(parent), m_ui(new Ui::FormBackupDatabaseSettings) { - m_ui->setupUi(this); - m_ui->m_txtBackupName->lineEdit()->setPlaceholderText(tr("Common name for backup files")); - setWindowIcon(qApp->icons()->fromTheme(QSL("document-export"))); - setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); - connect(m_ui->m_checkBackupDatabase, &QCheckBox::toggled, this, &FormBackupDatabaseSettings::checkOkButton); - connect(m_ui->m_checkBackupSettings, &QCheckBox::toggled, this, &FormBackupDatabaseSettings::checkOkButton); - connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormBackupDatabaseSettings::performBackup); - connect(m_ui->m_txtBackupName->lineEdit(), &BaseLineEdit::textChanged, this, &FormBackupDatabaseSettings::checkBackupNames); - connect(m_ui->m_txtBackupName->lineEdit(), &BaseLineEdit::textChanged, this, &FormBackupDatabaseSettings::checkOkButton); - connect(m_ui->m_btnSelectFolder, &QPushButton::clicked, this, &FormBackupDatabaseSettings::selectFolderInitial); - selectFolder(qApp->documentsFolder()); - m_ui->m_txtBackupName->lineEdit()->setText(QString(APP_LOW_NAME) + QL1S("_") + QDateTime::currentDateTime().toString(QSL("yyyyMMddHHmm"))); - m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet.")); + m_ui->setupUi(this); + m_ui->m_txtBackupName->lineEdit()->setPlaceholderText(tr("Common name for backup files")); + setWindowIcon(qApp->icons()->fromTheme(QSL("document-export"))); + setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); + connect(m_ui->m_checkBackupDatabase, &QCheckBox::toggled, this, &FormBackupDatabaseSettings::checkOkButton); + connect(m_ui->m_checkBackupSettings, &QCheckBox::toggled, this, &FormBackupDatabaseSettings::checkOkButton); + connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormBackupDatabaseSettings::performBackup); + connect(m_ui->m_txtBackupName->lineEdit(), &BaseLineEdit::textChanged, this, &FormBackupDatabaseSettings::checkBackupNames); + connect(m_ui->m_txtBackupName->lineEdit(), &BaseLineEdit::textChanged, this, &FormBackupDatabaseSettings::checkOkButton); + connect(m_ui->m_btnSelectFolder, &QPushButton::clicked, this, &FormBackupDatabaseSettings::selectFolderInitial); + selectFolder(qApp->documentsFolder()); + m_ui->m_txtBackupName->lineEdit()->setText(QString(APP_LOW_NAME) + QL1S("_") + + QDateTime::currentDateTime().toString(QSL("yyyyMMddHHmm"))); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet.")); - if (qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE && - qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE_MEMORY) { - m_ui->m_checkBackupDatabase->setDisabled(true); - } + if (qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE && + qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE_MEMORY) { + m_ui->m_checkBackupDatabase->setDisabled(true); + } } FormBackupDatabaseSettings::~FormBackupDatabaseSettings() { - qDebug("Destroying FormBackupDatabaseSettings instance."); + qDebug("Destroying FormBackupDatabaseSettings instance."); } void FormBackupDatabaseSettings::performBackup() { - try { - qApp->backupDatabaseSettings(m_ui->m_checkBackupDatabase->isChecked(), m_ui->m_checkBackupSettings->isChecked(), - m_ui->m_lblSelectFolder->label()->text(), m_ui->m_txtBackupName->lineEdit()->text()); - m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, - tr("Backup was created successfully and stored in target directory."), - tr("Backup was created successfully.")); - } - catch (const ApplicationException& ex) { - m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(), tr("Backup failed.")); - } + try { + qApp->backupDatabaseSettings(m_ui->m_checkBackupDatabase->isChecked(), m_ui->m_checkBackupSettings->isChecked(), + m_ui->m_lblSelectFolder->label()->text(), m_ui->m_txtBackupName->lineEdit()->text()); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, + tr("Backup was created successfully and stored in target directory."), + tr("Backup was created successfully.")); + } + catch (const ApplicationException& ex) { + m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(), tr("Backup failed.")); + } } void FormBackupDatabaseSettings::selectFolderInitial() { - selectFolder(); + selectFolder(); } void FormBackupDatabaseSettings::selectFolder(QString path) { - if (path.isEmpty()) { - path = QFileDialog::getExistingDirectory(this, tr("Select destination directory"), m_ui->m_lblSelectFolder->label()->text()); - } + if (path.isEmpty()) { + path = QFileDialog::getExistingDirectory(this, tr("Select destination directory"), m_ui->m_lblSelectFolder->label()->text()); + } - if (!path.isEmpty()) { - m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(path), - tr("Good destination directory is specified.")); - } + if (!path.isEmpty()) { + m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(path), + tr("Good destination directory is specified.")); + } } void FormBackupDatabaseSettings::checkBackupNames(const QString& name) { - if (name.simplified().isEmpty()) { - m_ui->m_txtBackupName->setStatus(WidgetWithStatus::Error, tr("Backup name cannot be empty.")); - } - else { - m_ui->m_txtBackupName->setStatus(WidgetWithStatus::Ok, tr("Backup name looks okay.")); - } + if (name.simplified().isEmpty()) { + m_ui->m_txtBackupName->setStatus(WidgetWithStatus::Error, tr("Backup name cannot be empty.")); + } + else { + m_ui->m_txtBackupName->setStatus(WidgetWithStatus::Ok, tr("Backup name looks okay.")); + } } void FormBackupDatabaseSettings::checkOkButton() { - m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setDisabled(m_ui->m_txtBackupName->lineEdit()->text().simplified().isEmpty() || - m_ui->m_lblSelectFolder->label()->text().simplified().isEmpty() || - (!m_ui->m_checkBackupDatabase->isChecked() && - !m_ui->m_checkBackupSettings->isChecked())); + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setDisabled(m_ui->m_txtBackupName->lineEdit()->text().simplified().isEmpty() || + m_ui->m_lblSelectFolder->label()->text().simplified().isEmpty() || + (!m_ui->m_checkBackupDatabase->isChecked() && + !m_ui->m_checkBackupSettings->isChecked())); } diff --git a/src/gui/dialogs/formbackupdatabasesettings.h b/src/gui/dialogs/formbackupdatabasesettings.h index 5f73059a3..f670b4b5a 100755 --- a/src/gui/dialogs/formbackupdatabasesettings.h +++ b/src/gui/dialogs/formbackupdatabasesettings.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,25 +23,24 @@ #include "ui_formbackupdatabasesettings.h" - class FormBackupDatabaseSettings : public QDialog { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors - explicit FormBackupDatabaseSettings(QWidget* parent = 0); - virtual ~FormBackupDatabaseSettings(); + public: + // Constructors and destructors + explicit FormBackupDatabaseSettings(QWidget* parent = 0); + virtual ~FormBackupDatabaseSettings(); - private slots: - void performBackup(); - void selectFolderInitial(); - void selectFolder(QString path = QString()); - void checkBackupNames(const QString& name); - void checkOkButton(); + private slots: + void performBackup(); + void selectFolderInitial(); + void selectFolder(QString path = QString()); + void checkBackupNames(const QString& name); + void checkOkButton(); - private: - QScopedPointer m_ui; + private: + QScopedPointer m_ui; }; #endif // FORMBACKUPDATABASECONFIG_H diff --git a/src/gui/dialogs/formdatabasecleanup.cpp b/src/gui/dialogs/formdatabasecleanup.cpp index 1092134f9..8d95d4e3d 100755 --- a/src/gui/dialogs/formdatabasecleanup.cpp +++ b/src/gui/dialogs/formdatabasecleanup.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,111 +19,113 @@ #include "gui/dialogs/formdatabasecleanup.h" #include "miscellaneous/application.h" -#include "miscellaneous/iconfactory.h" #include "miscellaneous/databasefactory.h" +#include "miscellaneous/iconfactory.h" #include #include #include - FormDatabaseCleanup::FormDatabaseCleanup(QWidget* parent) : QDialog(parent), m_ui(new Ui::FormDatabaseCleanup), m_cleaner(nullptr) { - m_ui->setupUi(this); - // Set flags and attributes. - setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); - setWindowIcon(qApp->icons()->fromTheme(QSL("edit-clear"))); - connect(m_ui->m_spinDays, static_cast(&QSpinBox::valueChanged), this, &FormDatabaseCleanup::updateDaysSuffix); - m_ui->m_spinDays->setValue(DEFAULT_DAYS_TO_DELETE_MSG); - m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("I am ready."), tr("I am ready.")); - loadDatabaseInfo(); + m_ui->setupUi(this); + + // Set flags and attributes. + setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); + setWindowIcon(qApp->icons()->fromTheme(QSL("edit-clear"))); + connect(m_ui->m_spinDays, static_cast(&QSpinBox::valueChanged), this, &FormDatabaseCleanup::updateDaysSuffix); + m_ui->m_spinDays->setValue(DEFAULT_DAYS_TO_DELETE_MSG); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("I am ready."), tr("I am ready.")); + loadDatabaseInfo(); } FormDatabaseCleanup::~FormDatabaseCleanup() { - qDebug("Destroying FormDatabaseCleanup instance."); + qDebug("Destroying FormDatabaseCleanup instance."); } void FormDatabaseCleanup::setCleaner(DatabaseCleaner* cleaner) { - if (m_cleaner != nullptr) { - disconnect(this, 0, m_cleaner, 0); - disconnect(m_cleaner, 0, this, 0); - } + if (m_cleaner != nullptr) { + disconnect(this, 0, m_cleaner, 0); + disconnect(m_cleaner, 0, this, 0); + } - m_cleaner = cleaner; - connect(m_ui->m_btnBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormDatabaseCleanup::startPurging); - connect(this, &FormDatabaseCleanup::purgeRequested, m_cleaner, &DatabaseCleaner::purgeDatabaseData); - connect(m_cleaner, &DatabaseCleaner::purgeStarted, this, &FormDatabaseCleanup::onPurgeStarted); - connect(m_cleaner, &DatabaseCleaner::purgeProgress, this, &FormDatabaseCleanup::onPurgeProgress); - connect(m_cleaner, &DatabaseCleaner::purgeFinished, this, &FormDatabaseCleanup::onPurgeFinished); + m_cleaner = cleaner; + connect(m_ui->m_btnBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormDatabaseCleanup::startPurging); + connect(this, &FormDatabaseCleanup::purgeRequested, m_cleaner, &DatabaseCleaner::purgeDatabaseData); + connect(m_cleaner, &DatabaseCleaner::purgeStarted, this, &FormDatabaseCleanup::onPurgeStarted); + connect(m_cleaner, &DatabaseCleaner::purgeProgress, this, &FormDatabaseCleanup::onPurgeProgress); + connect(m_cleaner, &DatabaseCleaner::purgeFinished, this, &FormDatabaseCleanup::onPurgeFinished); } void FormDatabaseCleanup::closeEvent(QCloseEvent* event) { - if (m_ui->m_progressBar->isEnabled()) { - event->ignore(); - } - else { - QDialog::closeEvent(event); - } + if (m_ui->m_progressBar->isEnabled()) { + event->ignore(); + } + else { + QDialog::closeEvent(event); + } } void FormDatabaseCleanup::keyPressEvent(QKeyEvent* event) { - if (m_ui->m_progressBar->isEnabled()) { - event->ignore(); - } - else { - QDialog::keyPressEvent(event); - } + if (m_ui->m_progressBar->isEnabled()) { + event->ignore(); + } + else { + QDialog::keyPressEvent(event); + } } void FormDatabaseCleanup::updateDaysSuffix(int number) { - m_ui->m_spinDays->setSuffix(tr(" day(s)", 0, number)); + m_ui->m_spinDays->setSuffix(tr(" day(s)", 0, number)); } void FormDatabaseCleanup::startPurging() { - CleanerOrders orders; - orders.m_removeRecycleBin = m_ui->m_checkRemoveRecycleBin->isChecked(); - orders.m_removeOldMessages = m_ui->m_checkRemoveOldMessages->isChecked(); - orders.m_barrierForRemovingOldMessagesInDays = m_ui->m_spinDays->value(); - orders.m_removeReadMessages = m_ui->m_checkRemoveReadMessages->isChecked(); - orders.m_shrinkDatabase = m_ui->m_checkShrink->isEnabled() && m_ui->m_checkShrink->isChecked(); - orders.m_removeStarredMessages = m_ui->m_checkRemoveStarredMessages->isChecked(); - emit purgeRequested(orders); + CleanerOrders orders; + + orders.m_removeRecycleBin = m_ui->m_checkRemoveRecycleBin->isChecked(); + orders.m_removeOldMessages = m_ui->m_checkRemoveOldMessages->isChecked(); + orders.m_barrierForRemovingOldMessagesInDays = m_ui->m_spinDays->value(); + orders.m_removeReadMessages = m_ui->m_checkRemoveReadMessages->isChecked(); + orders.m_shrinkDatabase = m_ui->m_checkShrink->isEnabled() && m_ui->m_checkShrink->isChecked(); + orders.m_removeStarredMessages = m_ui->m_checkRemoveStarredMessages->isChecked(); + emit purgeRequested(orders); } void FormDatabaseCleanup::onPurgeStarted() { - m_ui->m_progressBar->setValue(0); - m_ui->m_progressBar->setEnabled(true); - m_ui->m_btnBox->setEnabled(false); - m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("Database cleanup is running."), tr("Database cleanup is running.")); + m_ui->m_progressBar->setValue(0); + m_ui->m_progressBar->setEnabled(true); + m_ui->m_btnBox->setEnabled(false); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("Database cleanup is running."), tr("Database cleanup is running.")); } void FormDatabaseCleanup::onPurgeProgress(int progress, const QString& description) { - m_ui->m_progressBar->setValue(progress); - m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, description, description); + m_ui->m_progressBar->setValue(progress); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, description, description); } void FormDatabaseCleanup::onPurgeFinished(bool finished) { - m_ui->m_progressBar->setEnabled(false); - m_ui->m_progressBar->setValue(0); - m_ui->m_btnBox->setEnabled(true); + m_ui->m_progressBar->setEnabled(false); + m_ui->m_progressBar->setValue(0); + m_ui->m_btnBox->setEnabled(true); - if (finished) { - m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Database cleanup is completed."), tr("Database cleanup is completed.")); - } - else { - m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Database cleanup failed."), tr("Database cleanup failed.")); - } + if (finished) { + m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Database cleanup is completed."), tr("Database cleanup is completed.")); + } + else { + m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Database cleanup failed."), tr("Database cleanup failed.")); + } - loadDatabaseInfo(); + loadDatabaseInfo(); } void FormDatabaseCleanup::loadDatabaseInfo() { - qint64 file_size = qApp->database()->getDatabaseFileSize(); - qint64 data_size = qApp->database()->getDatabaseDataSize(); - QString file_size_str = file_size > 0 ? QString::number(file_size / 1000000.0) + QL1S(" MB") : tr("unknown"); - QString data_size_str = data_size > 0 ? QString::number(data_size / 1000000.0) + QL1S(" MB") : tr("unknown"); - m_ui->m_txtFileSize->setText(tr("file: %1, data: %2").arg(file_size_str, data_size_str)); - m_ui->m_txtDatabaseType->setText(qApp->database()->humanDriverName(qApp->database()->activeDatabaseDriver())); - m_ui->m_checkShrink->setEnabled(qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE || - qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE_MEMORY); - m_ui->m_checkShrink->setChecked(m_ui->m_checkShrink->isEnabled()); + qint64 file_size = qApp->database()->getDatabaseFileSize(); + qint64 data_size = qApp->database()->getDatabaseDataSize(); + QString file_size_str = file_size > 0 ? QString::number(file_size / 1000000.0) + QL1S(" MB") : tr("unknown"); + QString data_size_str = data_size > 0 ? QString::number(data_size / 1000000.0) + QL1S(" MB") : tr("unknown"); + + m_ui->m_txtFileSize->setText(tr("file: %1, data: %2").arg(file_size_str, data_size_str)); + m_ui->m_txtDatabaseType->setText(qApp->database()->humanDriverName(qApp->database()->activeDatabaseDriver())); + m_ui->m_checkShrink->setEnabled(qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE || + qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE_MEMORY); + m_ui->m_checkShrink->setChecked(m_ui->m_checkShrink->isEnabled()); } diff --git a/src/gui/dialogs/formdatabasecleanup.h b/src/gui/dialogs/formdatabasecleanup.h index 8bacda633..5e800898d 100755 --- a/src/gui/dialogs/formdatabasecleanup.h +++ b/src/gui/dialogs/formdatabasecleanup.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -24,37 +25,37 @@ #include "miscellaneous/databasecleaner.h" - class FormDatabaseCleanup : public QDialog { - Q_OBJECT + Q_OBJECT - public: - // Constructors. - explicit FormDatabaseCleanup(QWidget* parent = 0); - virtual ~FormDatabaseCleanup(); + public: - void setCleaner(DatabaseCleaner* cleaner); + // Constructors. + explicit FormDatabaseCleanup(QWidget* parent = 0); + virtual ~FormDatabaseCleanup(); - protected: - void closeEvent(QCloseEvent* event); - void keyPressEvent(QKeyEvent* event); + void setCleaner(DatabaseCleaner* cleaner); - private slots: - void updateDaysSuffix(int number); - void startPurging(); - void onPurgeStarted(); - void onPurgeProgress(int progress, const QString& description); - void onPurgeFinished(bool finished); + protected: + void closeEvent(QCloseEvent* event); + void keyPressEvent(QKeyEvent* event); - signals: - void purgeRequested(const CleanerOrders& which_data); + private slots: + void updateDaysSuffix(int number); + void startPurging(); + void onPurgeStarted(); + void onPurgeProgress(int progress, const QString& description); + void onPurgeFinished(bool finished); - private: - void loadDatabaseInfo(); + signals: + void purgeRequested(const CleanerOrders& which_data); - private: - QScopedPointer m_ui; - DatabaseCleaner* m_cleaner; + private: + void loadDatabaseInfo(); + + private: + QScopedPointer m_ui; + DatabaseCleaner* m_cleaner; }; #endif // FORMDATABASECLEANUP_H diff --git a/src/gui/dialogs/formmain.cpp b/src/gui/dialogs/formmain.cpp index 44849773b..18ad2a68b 100755 --- a/src/gui/dialogs/formmain.cpp +++ b/src/gui/dialogs/formmain.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,757 +19,782 @@ #include "gui/dialogs/formmain.h" #include "definitions/definitions.h" -#include "miscellaneous/settings.h" -#include "miscellaneous/application.h" -#include "miscellaneous/systemfactory.h" -#include "miscellaneous/mutex.h" -#include "miscellaneous/databasefactory.h" -#include "miscellaneous/iconfactory.h" -#include "miscellaneous/feedreader.h" -#include "network-web/webfactory.h" -#include "gui/feedsview.h" -#include "gui/messagebox.h" -#include "gui/systemtrayicon.h" -#include "gui/tabbar.h" -#include "gui/statusbar.h" -#include "gui/messagesview.h" -#include "gui/feedmessageviewer.h" -#include "gui/plaintoolbutton.h" -#include "gui/feedstoolbar.h" -#include "gui/messagestoolbar.h" #include "gui/dialogs/formabout.h" +#include "gui/dialogs/formaddaccount.h" +#include "gui/dialogs/formbackupdatabasesettings.h" +#include "gui/dialogs/formdatabasecleanup.h" +#include "gui/dialogs/formrestoredatabasesettings.h" #include "gui/dialogs/formsettings.h" #include "gui/dialogs/formupdate.h" -#include "gui/dialogs/formdatabasecleanup.h" -#include "gui/dialogs/formbackupdatabasesettings.h" -#include "gui/dialogs/formrestoredatabasesettings.h" -#include "gui/dialogs/formaddaccount.h" -#include "services/abstract/serviceroot.h" +#include "gui/feedmessageviewer.h" +#include "gui/feedstoolbar.h" +#include "gui/feedsview.h" +#include "gui/messagebox.h" +#include "gui/messagestoolbar.h" +#include "gui/messagesview.h" +#include "gui/plaintoolbutton.h" +#include "gui/statusbar.h" +#include "gui/systemtrayicon.h" +#include "gui/tabbar.h" +#include "miscellaneous/application.h" +#include "miscellaneous/databasefactory.h" +#include "miscellaneous/feedreader.h" +#include "miscellaneous/iconfactory.h" +#include "miscellaneous/mutex.h" +#include "miscellaneous/settings.h" +#include "miscellaneous/systemfactory.h" +#include "network-web/webfactory.h" #include "services/abstract/recyclebin.h" -#include "services/standard/gui/formstandardimportexport.h" +#include "services/abstract/serviceroot.h" #include "services/owncloud/network/owncloudnetworkfactory.h" +#include "services/standard/gui/formstandardimportexport.h" #include +#include +#include #include #include -#include #include -#include #if defined (USE_WEBENGINE) -#include "network-web/adblock/adblockmanager.h" #include "network-web/adblock/adblockicon.h" +#include "network-web/adblock/adblockmanager.h" #endif - FormMain::FormMain(QWidget* parent, Qt::WindowFlags f) - : QMainWindow(parent, f), m_ui(new Ui::FormMain) { - m_ui->setupUi(this); - qApp->setMainForm(this); + : QMainWindow(parent, f), m_ui(new Ui::FormMain) { + m_ui->setupUi(this); + qApp->setMainForm(this); #if defined (USE_WEBENGINE) - m_ui->m_menuWebBrowserTabs->addAction(AdBlockManager::instance()->adBlockIcon()); - m_ui->m_menuWebBrowserTabs->addAction(qApp->web()->engineSettingsAction()); + m_ui->m_menuWebBrowserTabs->addAction(AdBlockManager::instance()->adBlockIcon()); + m_ui->m_menuWebBrowserTabs->addAction(qApp->web()->engineSettingsAction()); #endif - // Add these actions to the list of actions of the main window. - // This allows to use actions via shortcuts - // even if main menu is not visible. - addActions(qApp->userActions()); - setStatusBar(m_statusBar = new StatusBar(this)); + // Add these actions to the list of actions of the main window. + // This allows to use actions via shortcuts + // even if main menu is not visible. + addActions(qApp->userActions()); + setStatusBar(m_statusBar = new StatusBar(this)); - // Prepare main window and tabs. - prepareMenus(); + // Prepare main window and tabs. + prepareMenus(); - // Prepare tabs. - tabWidget()->feedMessageViewer()->feedsToolBar()->loadSavedActions(); - tabWidget()->feedMessageViewer()->messagesToolBar()->loadSavedActions(); + // Prepare tabs. + tabWidget()->feedMessageViewer()->feedsToolBar()->loadSavedActions(); + tabWidget()->feedMessageViewer()->messagesToolBar()->loadSavedActions(); // Establish connections. - createConnections(); - updateMessageButtonsAvailability(); - updateFeedButtonsAvailability(); + createConnections(); + updateMessageButtonsAvailability(); + updateFeedButtonsAvailability(); // Setup some appearance of the window. - setupIcons(); - loadSize(); - m_statusBar->loadSavedActions(); + setupIcons(); + loadSize(); + m_statusBar->loadSavedActions(); } FormMain::~FormMain() { - qDebug("Destroying FormMain instance."); + qDebug("Destroying FormMain instance."); } QMenu* FormMain::trayMenu() const { - return m_trayMenu; + return m_trayMenu; } TabWidget* FormMain::tabWidget() const { - return m_ui->m_tabWidget; + return m_ui->m_tabWidget; } StatusBar* FormMain::statusBar() const { - return m_statusBar; + return m_statusBar; } void FormMain::showDbCleanupAssistant() { - if (qApp->feedUpdateLock()->tryLock()) { + if (qApp->feedUpdateLock()->tryLock()) { FormDatabaseCleanup form(this); + form.setCleaner(qApp->feedReader()->databaseCleaner()); form.exec(); // Reload needed stuff. - qApp->feedUpdateLock()->unlock(); - tabWidget()->feedMessageViewer()->messagesView()->reloadSelections(); - qApp->feedReader()->feedsModel()->reloadCountsOfWholeModel(); - } - else { - qApp->showGuiMessage(tr("Cannot cleanup database"), - tr("Cannot cleanup database, because another critical action is running."), - QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - } + qApp->feedUpdateLock()->unlock(); + tabWidget()->feedMessageViewer()->messagesView()->reloadSelections(); + qApp->feedReader()->feedsModel()->reloadCountsOfWholeModel(); + } + else { + qApp->showGuiMessage(tr("Cannot cleanup database"), + tr("Cannot cleanup database, because another critical action is running."), + QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); + } } QList FormMain::allActions() const { - QList actions; - // Add basic actions. - actions << m_ui->m_actionSettings; - actions << m_ui->m_actionDownloadManager; - actions << m_ui->m_actionRestoreDatabaseSettings; - actions << m_ui->m_actionBackupDatabaseSettings; - actions << m_ui->m_actionRestart; - actions << m_ui->m_actionQuit; + QList actions; + + // Add basic actions. + actions << m_ui->m_actionSettings; + actions << m_ui->m_actionDownloadManager; + actions << m_ui->m_actionRestoreDatabaseSettings; + actions << m_ui->m_actionBackupDatabaseSettings; + actions << m_ui->m_actionRestart; + actions << m_ui->m_actionQuit; #if !defined(Q_OS_MAC) - actions << m_ui->m_actionFullscreen; + actions << m_ui->m_actionFullscreen; #endif - actions << m_ui->m_actionAboutGuard; - actions << m_ui->m_actionSwitchFeedsList; - actions << m_ui->m_actionSwitchMainWindow; + actions << m_ui->m_actionAboutGuard; + actions << m_ui->m_actionSwitchFeedsList; + actions << m_ui->m_actionSwitchMainWindow; #if !defined(Q_OS_MAC) - actions << m_ui->m_actionSwitchMainMenu; + actions << m_ui->m_actionSwitchMainMenu; #endif - actions << m_ui->m_actionSwitchToolBars; - actions << m_ui->m_actionSwitchListHeaders; - actions << m_ui->m_actionSwitchStatusBar; - actions << m_ui->m_actionSwitchMessageListOrientation; + actions << m_ui->m_actionSwitchToolBars; + actions << m_ui->m_actionSwitchListHeaders; + actions << m_ui->m_actionSwitchStatusBar; + actions << m_ui->m_actionSwitchMessageListOrientation; actions << m_ui->m_actionTabsNext; actions << m_ui->m_actionTabsPrevious; actions << m_ui->m_actionOpenSelectedSourceArticlesExternally; - actions << m_ui->m_actionOpenSelectedMessagesInternally; - actions << m_ui->m_actionMarkAllItemsRead; - actions << m_ui->m_actionMarkSelectedItemsAsRead; - actions << m_ui->m_actionMarkSelectedItemsAsUnread; - actions << m_ui->m_actionClearSelectedItems; - actions << m_ui->m_actionClearAllItems; - actions << m_ui->m_actionShowOnlyUnreadItems; - actions << m_ui->m_actionMarkSelectedMessagesAsRead; - actions << m_ui->m_actionMarkSelectedMessagesAsUnread; - actions << m_ui->m_actionSwitchImportanceOfSelectedMessages; - actions << m_ui->m_actionDeleteSelectedMessages; - actions << m_ui->m_actionUpdateAllItems; - actions << m_ui->m_actionUpdateSelectedItems; - actions << m_ui->m_actionStopRunningItemsUpdate; - actions << m_ui->m_actionEditSelectedItem; - actions << m_ui->m_actionDeleteSelectedItem; - actions << m_ui->m_actionServiceAdd; - actions << m_ui->m_actionServiceEdit; - actions << m_ui->m_actionServiceDelete; - actions << m_ui->m_actionCleanupDatabase; - actions << m_ui->m_actionAddFeedIntoSelectedAccount; - actions << m_ui->m_actionAddCategoryIntoSelectedAccount; - actions << m_ui->m_actionViewSelectedItemsNewspaperMode; - actions << m_ui->m_actionSelectNextItem; - actions << m_ui->m_actionSelectPreviousItem; - actions << m_ui->m_actionSelectNextMessage; - actions << m_ui->m_actionSelectPreviousMessage; - actions << m_ui->m_actionSelectNextUnreadMessage; - actions << m_ui->m_actionExpandCollapseItem; + actions << m_ui->m_actionOpenSelectedMessagesInternally; + actions << m_ui->m_actionMarkAllItemsRead; + actions << m_ui->m_actionMarkSelectedItemsAsRead; + actions << m_ui->m_actionMarkSelectedItemsAsUnread; + actions << m_ui->m_actionClearSelectedItems; + actions << m_ui->m_actionClearAllItems; + actions << m_ui->m_actionShowOnlyUnreadItems; + actions << m_ui->m_actionMarkSelectedMessagesAsRead; + actions << m_ui->m_actionMarkSelectedMessagesAsUnread; + actions << m_ui->m_actionSwitchImportanceOfSelectedMessages; + actions << m_ui->m_actionDeleteSelectedMessages; + actions << m_ui->m_actionUpdateAllItems; + actions << m_ui->m_actionUpdateSelectedItems; + actions << m_ui->m_actionStopRunningItemsUpdate; + actions << m_ui->m_actionEditSelectedItem; + actions << m_ui->m_actionDeleteSelectedItem; + actions << m_ui->m_actionServiceAdd; + actions << m_ui->m_actionServiceEdit; + actions << m_ui->m_actionServiceDelete; + actions << m_ui->m_actionCleanupDatabase; + actions << m_ui->m_actionAddFeedIntoSelectedAccount; + actions << m_ui->m_actionAddCategoryIntoSelectedAccount; + actions << m_ui->m_actionViewSelectedItemsNewspaperMode; + actions << m_ui->m_actionSelectNextItem; + actions << m_ui->m_actionSelectPreviousItem; + actions << m_ui->m_actionSelectNextMessage; + actions << m_ui->m_actionSelectPreviousMessage; + actions << m_ui->m_actionSelectNextUnreadMessage; + actions << m_ui->m_actionExpandCollapseItem; #if defined(USE_WEBENGINE) - actions << m_ui->m_actionTabNewWebBrowser; + actions << m_ui->m_actionTabNewWebBrowser; #endif - actions << m_ui->m_actionTabsCloseAll; - actions << m_ui->m_actionTabsCloseAllExceptCurrent; - return actions; + actions << m_ui->m_actionTabsCloseAll; + actions << m_ui->m_actionTabsCloseAllExceptCurrent; + return actions; } void FormMain::prepareMenus() { - // Setup menu for tray icon. - if (SystemTrayIcon::isSystemTrayAvailable()) { + // Setup menu for tray icon. + if (SystemTrayIcon::isSystemTrayAvailable()) { #if defined(Q_OS_WIN) - m_trayMenu = new TrayIconMenu(APP_NAME, this); + m_trayMenu = new TrayIconMenu(APP_NAME, this); #else - m_trayMenu = new QMenu(QSL(APP_NAME), this); + m_trayMenu = new QMenu(QSL(APP_NAME), this); #endif - // Add needed items to the menu. - m_trayMenu->addAction(m_ui->m_actionSwitchMainWindow); - m_trayMenu->addSeparator(); - m_trayMenu->addAction(m_ui->m_actionUpdateAllItems); - m_trayMenu->addAction(m_ui->m_actionMarkAllItemsRead); - m_trayMenu->addSeparator(); - m_trayMenu->addAction(m_ui->m_actionSettings); - m_trayMenu->addAction(m_ui->m_actionQuit); - qDebug("Creating tray icon menu."); - } + + // Add needed items to the menu. + m_trayMenu->addAction(m_ui->m_actionSwitchMainWindow); + m_trayMenu->addSeparator(); + m_trayMenu->addAction(m_ui->m_actionUpdateAllItems); + m_trayMenu->addAction(m_ui->m_actionMarkAllItemsRead); + m_trayMenu->addSeparator(); + m_trayMenu->addAction(m_ui->m_actionSettings); + m_trayMenu->addAction(m_ui->m_actionQuit); + qDebug("Creating tray icon menu."); + } #if !defined(USE_WEBENGINE) - m_ui->m_menuWebBrowserTabs->removeAction(m_ui->m_actionTabNewWebBrowser); - m_ui->m_menuWebBrowserTabs->setTitle(tr("Tabs")); + m_ui->m_menuWebBrowserTabs->removeAction(m_ui->m_actionTabNewWebBrowser); + m_ui->m_menuWebBrowserTabs->setTitle(tr("Tabs")); #endif #if defined(Q_OS_MAC) - m_ui->m_actionSwitchMainMenu->setVisible(false); - m_ui->m_actionFullscreen->setVisible(false); + m_ui->m_actionSwitchMainMenu->setVisible(false); + m_ui->m_actionFullscreen->setVisible(false); #endif } void FormMain::switchFullscreenMode() { - if (!isFullScreen()) { - qApp->settings()->setValue(GROUP(GUI), GUI::IsMainWindowMaximizedBeforeFullscreen, isMaximized()); - showFullScreen(); - } - else { - if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::IsMainWindowMaximizedBeforeFullscreen)).toBool()) { - setWindowState((windowState() & ~Qt::WindowFullScreen) | Qt::WindowMaximized); - } - else { - showNormal(); - } - } + if (!isFullScreen()) { + qApp->settings()->setValue(GROUP(GUI), GUI::IsMainWindowMaximizedBeforeFullscreen, isMaximized()); + showFullScreen(); + } + else { + if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::IsMainWindowMaximizedBeforeFullscreen)).toBool()) { + setWindowState((windowState() & ~Qt::WindowFullScreen) | Qt::WindowMaximized); + } + else { + showNormal(); + } + } } void FormMain::updateAddItemMenu() { - // NOTE: Clear here deletes items from memory but only those OWNED by the menu. - m_ui->m_menuAddItem->clear(); + // NOTE: Clear here deletes items from memory but only those OWNED by the menu. + m_ui->m_menuAddItem->clear(); - foreach (ServiceRoot* activated_root, qApp->feedReader()->feedsModel()->serviceRoots()) { - QMenu* root_menu = new QMenu(activated_root->title(), m_ui->m_menuAddItem); - root_menu->setIcon(activated_root->icon()); - root_menu->setToolTip(activated_root->description()); - QList specific_root_actions = activated_root->addItemMenu(); + foreach (ServiceRoot* activated_root, qApp->feedReader()->feedsModel()->serviceRoots()) { + QMenu* root_menu = new QMenu(activated_root->title(), m_ui->m_menuAddItem); - if (activated_root->supportsCategoryAdding()) { - QAction* action_new_category = new QAction(qApp->icons()->fromTheme(QSL("folder")), - tr("Add new category"), - m_ui->m_menuAddItem); - root_menu->addAction(action_new_category); - connect(action_new_category, &QAction::triggered, activated_root, &ServiceRoot::addNewCategory); - } + root_menu->setIcon(activated_root->icon()); + root_menu->setToolTip(activated_root->description()); + QList specific_root_actions = activated_root->addItemMenu(); - if (activated_root->supportsFeedAdding()) { - QAction* action_new_feed = new QAction(qApp->icons()->fromTheme(QSL("application-rss+xml")), - tr("Add new feed"), - m_ui->m_menuAddItem); - root_menu->addAction(action_new_feed); - // NOTE: Because of default arguments. - connect(action_new_feed, SIGNAL(triggered(bool)), activated_root, SLOT(addNewFeed())); - } + if (activated_root->supportsCategoryAdding()) { + QAction* action_new_category = new QAction(qApp->icons()->fromTheme(QSL("folder")), + tr("Add new category"), + m_ui->m_menuAddItem); - if (!specific_root_actions.isEmpty()) { - if (!root_menu->isEmpty()) { - root_menu->addSeparator(); - } + root_menu->addAction(action_new_category); + connect(action_new_category, &QAction::triggered, activated_root, &ServiceRoot::addNewCategory); + } - root_menu->addActions(specific_root_actions); - } + if (activated_root->supportsFeedAdding()) { + QAction* action_new_feed = new QAction(qApp->icons()->fromTheme(QSL("application-rss+xml")), + tr("Add new feed"), + m_ui->m_menuAddItem); - m_ui->m_menuAddItem->addMenu(root_menu); - } + root_menu->addAction(action_new_feed); - if (!m_ui->m_menuAddItem->isEmpty()) { - m_ui->m_menuAddItem->addSeparator(); - m_ui->m_menuAddItem->addAction(m_ui->m_actionAddCategoryIntoSelectedAccount); - m_ui->m_menuAddItem->addAction(m_ui->m_actionAddFeedIntoSelectedAccount); - } - else { - m_ui->m_menuAddItem->addAction(m_ui->m_actionNoActions); - } + // NOTE: Because of default arguments. + connect(action_new_feed, SIGNAL(triggered(bool)), activated_root, SLOT(addNewFeed())); + } + + if (!specific_root_actions.isEmpty()) { + if (!root_menu->isEmpty()) { + root_menu->addSeparator(); + } + + root_menu->addActions(specific_root_actions); + } + + m_ui->m_menuAddItem->addMenu(root_menu); + } + + if (!m_ui->m_menuAddItem->isEmpty()) { + m_ui->m_menuAddItem->addSeparator(); + m_ui->m_menuAddItem->addAction(m_ui->m_actionAddCategoryIntoSelectedAccount); + m_ui->m_menuAddItem->addAction(m_ui->m_actionAddFeedIntoSelectedAccount); + } + else { + m_ui->m_menuAddItem->addAction(m_ui->m_actionNoActions); + } } void FormMain::updateRecycleBinMenu() { - m_ui->m_menuRecycleBin->clear(); + m_ui->m_menuRecycleBin->clear(); - foreach (const ServiceRoot* activated_root, qApp->feedReader()->feedsModel()->serviceRoots()) { - QMenu* root_menu = new QMenu(activated_root->title(), m_ui->m_menuRecycleBin); - root_menu->setIcon(activated_root->icon()); - root_menu->setToolTip(activated_root->description()); - RecycleBin* bin = activated_root->recycleBin(); - QList context_menu; + foreach (const ServiceRoot* activated_root, qApp->feedReader()->feedsModel()->serviceRoots()) { + QMenu* root_menu = new QMenu(activated_root->title(), m_ui->m_menuRecycleBin); - if (bin == nullptr) { - QAction* no_action = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), - tr("No recycle bin"), - m_ui->m_menuRecycleBin); - no_action->setEnabled(false); - root_menu->addAction(no_action); - } - else if ((context_menu = bin->contextMenu()).isEmpty()) { - QAction* no_action = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), - tr("No actions possible"), - m_ui->m_menuRecycleBin); - no_action->setEnabled(false); - root_menu->addAction(no_action); - } - else { - root_menu->addActions(context_menu); - } + root_menu->setIcon(activated_root->icon()); + root_menu->setToolTip(activated_root->description()); + RecycleBin* bin = activated_root->recycleBin(); - m_ui->m_menuRecycleBin->addMenu(root_menu); - } + QList context_menu; - if (!m_ui->m_menuRecycleBin->isEmpty()) { - m_ui->m_menuRecycleBin->addSeparator(); - } + if (bin == nullptr) { + QAction* no_action = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), + tr("No recycle bin"), + m_ui->m_menuRecycleBin); - m_ui->m_menuRecycleBin->addAction(m_ui->m_actionRestoreAllRecycleBins); - m_ui->m_menuRecycleBin->addAction(m_ui->m_actionEmptyAllRecycleBins); + no_action->setEnabled(false); + root_menu->addAction(no_action); + } + else if ((context_menu = bin->contextMenu()).isEmpty()) { + QAction* no_action = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), + tr("No actions possible"), + m_ui->m_menuRecycleBin); + + no_action->setEnabled(false); + root_menu->addAction(no_action); + } + else { + root_menu->addActions(context_menu); + } + + m_ui->m_menuRecycleBin->addMenu(root_menu); + } + + if (!m_ui->m_menuRecycleBin->isEmpty()) { + m_ui->m_menuRecycleBin->addSeparator(); + } + + m_ui->m_menuRecycleBin->addAction(m_ui->m_actionRestoreAllRecycleBins); + m_ui->m_menuRecycleBin->addAction(m_ui->m_actionEmptyAllRecycleBins); } void FormMain::updateAccountsMenu() { - m_ui->m_menuAccounts->clear(); + m_ui->m_menuAccounts->clear(); - foreach (ServiceRoot* activated_root, qApp->feedReader()->feedsModel()->serviceRoots()) { - QMenu* root_menu = new QMenu(activated_root->title(), m_ui->m_menuAccounts); - root_menu->setIcon(activated_root->icon()); - root_menu->setToolTip(activated_root->description()); - QList root_actions = activated_root->serviceMenu(); + foreach (ServiceRoot* activated_root, qApp->feedReader()->feedsModel()->serviceRoots()) { + QMenu* root_menu = new QMenu(activated_root->title(), m_ui->m_menuAccounts); - if (root_actions.isEmpty()) { - QAction* no_action = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), - tr("No possible actions"), - m_ui->m_menuAccounts); - no_action->setEnabled(false); - root_menu->addAction(no_action); - } - else { - root_menu->addActions(root_actions); - } + root_menu->setIcon(activated_root->icon()); + root_menu->setToolTip(activated_root->description()); + QList root_actions = activated_root->serviceMenu(); - m_ui->m_menuAccounts->addMenu(root_menu); - } + if (root_actions.isEmpty()) { + QAction* no_action = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), + tr("No possible actions"), + m_ui->m_menuAccounts); - if (m_ui->m_menuAccounts->actions().size() > 0) { - m_ui->m_menuAccounts->addSeparator(); - } + no_action->setEnabled(false); + root_menu->addAction(no_action); + } + else { + root_menu->addActions(root_actions); + } - m_ui->m_menuAccounts->addAction(m_ui->m_actionServiceAdd); - m_ui->m_menuAccounts->addAction(m_ui->m_actionServiceEdit); - m_ui->m_menuAccounts->addAction(m_ui->m_actionServiceDelete); + m_ui->m_menuAccounts->addMenu(root_menu); + } + + if (m_ui->m_menuAccounts->actions().size() > 0) { + m_ui->m_menuAccounts->addSeparator(); + } + + m_ui->m_menuAccounts->addAction(m_ui->m_actionServiceAdd); + m_ui->m_menuAccounts->addAction(m_ui->m_actionServiceEdit); + m_ui->m_menuAccounts->addAction(m_ui->m_actionServiceDelete); } void FormMain::onFeedUpdatesFinished(const FeedDownloadResults& results) { - Q_UNUSED(results) - statusBar()->clearProgressFeeds(); - tabWidget()->feedMessageViewer()->messagesView()->reloadSelections(); + Q_UNUSED(results) + statusBar()->clearProgressFeeds(); + tabWidget()->feedMessageViewer()->messagesView()->reloadSelections(); } void FormMain::onFeedUpdatesStarted() { - m_ui->m_actionStopRunningItemsUpdate->setEnabled(true); - statusBar()->showProgressFeeds(0, tr("Feed update started")); + m_ui->m_actionStopRunningItemsUpdate->setEnabled(true); + statusBar()->showProgressFeeds(0, tr("Feed update started")); } void FormMain::onFeedUpdatesProgress(const Feed* feed, int current, int total) { - statusBar()->showProgressFeeds((current * 100.0) / total, - //: Text display in status bar when particular feed is updated. - tr("Updated feed '%1'").arg(feed->title())); + statusBar()->showProgressFeeds((current * 100.0) / total, + + //: Text display in status bar when particular feed is updated. + tr("Updated feed '%1'").arg(feed->title())); } void FormMain::updateMessageButtonsAvailability() { - const bool one_message_selected = tabWidget()->feedMessageViewer()->messagesView()->selectionModel()->selectedRows().size() == 1; - const bool atleast_one_message_selected = !tabWidget()->feedMessageViewer()->messagesView()->selectionModel()->selectedRows().isEmpty(); - const bool bin_loaded = tabWidget()->feedMessageViewer()->messagesView()->sourceModel()->loadedItem() != nullptr - && tabWidget()->feedMessageViewer()->messagesView()->sourceModel()->loadedItem()->kind() == RootItemKind::Bin; - m_ui->m_actionDeleteSelectedMessages->setEnabled(atleast_one_message_selected); - m_ui->m_actionRestoreSelectedMessages->setEnabled(atleast_one_message_selected && bin_loaded); - m_ui->m_actionMarkSelectedMessagesAsRead->setEnabled(atleast_one_message_selected); - m_ui->m_actionMarkSelectedMessagesAsUnread->setEnabled(atleast_one_message_selected); - m_ui->m_actionOpenSelectedMessagesInternally->setEnabled(atleast_one_message_selected); - m_ui->m_actionOpenSelectedSourceArticlesExternally->setEnabled(atleast_one_message_selected); - m_ui->m_actionSendMessageViaEmail->setEnabled(one_message_selected); - m_ui->m_actionSwitchImportanceOfSelectedMessages->setEnabled(atleast_one_message_selected); + const bool one_message_selected = tabWidget()->feedMessageViewer()->messagesView()->selectionModel()->selectedRows().size() == 1; + const bool atleast_one_message_selected = !tabWidget()->feedMessageViewer()->messagesView()->selectionModel()->selectedRows().isEmpty(); + const bool bin_loaded = tabWidget()->feedMessageViewer()->messagesView()->sourceModel()->loadedItem() != nullptr + && tabWidget()->feedMessageViewer()->messagesView()->sourceModel()->loadedItem()->kind() == RootItemKind::Bin; + + m_ui->m_actionDeleteSelectedMessages->setEnabled(atleast_one_message_selected); + m_ui->m_actionRestoreSelectedMessages->setEnabled(atleast_one_message_selected && bin_loaded); + m_ui->m_actionMarkSelectedMessagesAsRead->setEnabled(atleast_one_message_selected); + m_ui->m_actionMarkSelectedMessagesAsUnread->setEnabled(atleast_one_message_selected); + m_ui->m_actionOpenSelectedMessagesInternally->setEnabled(atleast_one_message_selected); + m_ui->m_actionOpenSelectedSourceArticlesExternally->setEnabled(atleast_one_message_selected); + m_ui->m_actionSendMessageViaEmail->setEnabled(one_message_selected); + m_ui->m_actionSwitchImportanceOfSelectedMessages->setEnabled(atleast_one_message_selected); } void FormMain::updateFeedButtonsAvailability() { - const bool is_update_running = qApp->feedReader()->isFeedUpdateRunning(); - const bool critical_action_running = qApp->feedUpdateLock()->isLocked(); - const RootItem* selected_item = tabWidget()->feedMessageViewer()->feedsView()->selectedItem(); - const bool anything_selected = selected_item != nullptr; - const bool feed_selected = anything_selected && selected_item->kind() == RootItemKind::Feed; - const bool category_selected = anything_selected && selected_item->kind() == RootItemKind::Category; - const bool service_selected = anything_selected && selected_item->kind() == RootItemKind::ServiceRoot; - m_ui->m_actionStopRunningItemsUpdate->setEnabled(is_update_running); - m_ui->m_actionBackupDatabaseSettings->setEnabled(!critical_action_running); - m_ui->m_actionCleanupDatabase->setEnabled(!critical_action_running); - m_ui->m_actionClearSelectedItems->setEnabled(anything_selected); - m_ui->m_actionDeleteSelectedItem->setEnabled(!critical_action_running && anything_selected); - m_ui->m_actionEditSelectedItem->setEnabled(!critical_action_running && anything_selected); - m_ui->m_actionMarkSelectedItemsAsRead->setEnabled(anything_selected); - m_ui->m_actionMarkSelectedItemsAsUnread->setEnabled(anything_selected); - m_ui->m_actionUpdateAllItems->setEnabled(!critical_action_running); - m_ui->m_actionUpdateSelectedItems->setEnabled(!critical_action_running && (feed_selected || category_selected || service_selected)); - m_ui->m_actionViewSelectedItemsNewspaperMode->setEnabled(anything_selected); - m_ui->m_actionExpandCollapseItem->setEnabled(anything_selected); - m_ui->m_actionServiceDelete->setEnabled(service_selected); - m_ui->m_actionServiceEdit->setEnabled(service_selected); - m_ui->m_actionAddFeedIntoSelectedAccount->setEnabled(anything_selected); - m_ui->m_actionAddCategoryIntoSelectedAccount->setEnabled(anything_selected); - m_ui->m_menuAddItem->setEnabled(!critical_action_running); - m_ui->m_menuAccounts->setEnabled(!critical_action_running); - m_ui->m_menuRecycleBin->setEnabled(!critical_action_running); + const bool is_update_running = qApp->feedReader()->isFeedUpdateRunning(); + const bool critical_action_running = qApp->feedUpdateLock()->isLocked(); + const RootItem* selected_item = tabWidget()->feedMessageViewer()->feedsView()->selectedItem(); + const bool anything_selected = selected_item != nullptr; + const bool feed_selected = anything_selected && selected_item->kind() == RootItemKind::Feed; + const bool category_selected = anything_selected && selected_item->kind() == RootItemKind::Category; + const bool service_selected = anything_selected && selected_item->kind() == RootItemKind::ServiceRoot; + + m_ui->m_actionStopRunningItemsUpdate->setEnabled(is_update_running); + m_ui->m_actionBackupDatabaseSettings->setEnabled(!critical_action_running); + m_ui->m_actionCleanupDatabase->setEnabled(!critical_action_running); + m_ui->m_actionClearSelectedItems->setEnabled(anything_selected); + m_ui->m_actionDeleteSelectedItem->setEnabled(!critical_action_running && anything_selected); + m_ui->m_actionEditSelectedItem->setEnabled(!critical_action_running && anything_selected); + m_ui->m_actionMarkSelectedItemsAsRead->setEnabled(anything_selected); + m_ui->m_actionMarkSelectedItemsAsUnread->setEnabled(anything_selected); + m_ui->m_actionUpdateAllItems->setEnabled(!critical_action_running); + m_ui->m_actionUpdateSelectedItems->setEnabled(!critical_action_running && (feed_selected || category_selected || service_selected)); + m_ui->m_actionViewSelectedItemsNewspaperMode->setEnabled(anything_selected); + m_ui->m_actionExpandCollapseItem->setEnabled(anything_selected); + m_ui->m_actionServiceDelete->setEnabled(service_selected); + m_ui->m_actionServiceEdit->setEnabled(service_selected); + m_ui->m_actionAddFeedIntoSelectedAccount->setEnabled(anything_selected); + m_ui->m_actionAddCategoryIntoSelectedAccount->setEnabled(anything_selected); + m_ui->m_menuAddItem->setEnabled(!critical_action_running); + m_ui->m_menuAccounts->setEnabled(!critical_action_running); + m_ui->m_menuRecycleBin->setEnabled(!critical_action_running); } void FormMain::switchVisibility(bool force_hide) { - if (force_hide || isVisible()) { - if (SystemTrayIcon::isSystemTrayActivated()) { - hide(); - } - else { - // Window gets minimized in single-window mode. - showMinimized(); - } - } - else { - display(); - } + if (force_hide || isVisible()) { + if (SystemTrayIcon::isSystemTrayActivated()) { + hide(); + } + else { + // Window gets minimized in single-window mode. + showMinimized(); + } + } + else { + display(); + } } void FormMain::display() { - // Make sure window is not minimized. - setWindowState(windowState() & ~Qt::WindowMinimized); - // Display the window and make sure it is raised on top. - show(); - activateWindow(); - raise(); - // Raise alert event. Check the documentation for more info on this. - Application::alert(this); + // Make sure window is not minimized. + setWindowState(windowState() & ~Qt::WindowMinimized); + + // Display the window and make sure it is raised on top. + show(); + activateWindow(); + raise(); + + // Raise alert event. Check the documentation for more info on this. + Application::alert(this); } void FormMain::setupIcons() { - IconFactory* icon_theme_factory = qApp->icons(); + IconFactory* icon_theme_factory = qApp->icons(); - // Setup icons of this main window. - m_ui->m_actionDownloadManager->setIcon(icon_theme_factory->fromTheme(QSL("emblem-downloads"))); - m_ui->m_actionSettings->setIcon(icon_theme_factory->fromTheme(QSL("document-properties"))); - m_ui->m_actionQuit->setIcon(icon_theme_factory->fromTheme(QSL("application-exit"))); - m_ui->m_actionRestart->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); - m_ui->m_actionAboutGuard->setIcon(icon_theme_factory->fromTheme(QSL("help-about"))); - m_ui->m_actionCheckForUpdates->setIcon(icon_theme_factory->fromTheme(QSL("system-upgrade"))); - m_ui->m_actionCleanupDatabase->setIcon(icon_theme_factory->fromTheme(QSL("edit-clear"))); - m_ui->m_actionReportBug->setIcon(icon_theme_factory->fromTheme(QSL("call-start"))); - m_ui->m_actionBackupDatabaseSettings->setIcon(icon_theme_factory->fromTheme(QSL("document-export"))); - m_ui->m_actionRestoreDatabaseSettings->setIcon(icon_theme_factory->fromTheme(QSL("document-import"))); - m_ui->m_actionDonate->setIcon(icon_theme_factory->fromTheme(QSL("applications-office"))); - m_ui->m_actionDisplayWiki->setIcon(icon_theme_factory->fromTheme(QSL("applications-science"))); + // Setup icons of this main window. + m_ui->m_actionDownloadManager->setIcon(icon_theme_factory->fromTheme(QSL("emblem-downloads"))); + m_ui->m_actionSettings->setIcon(icon_theme_factory->fromTheme(QSL("document-properties"))); + m_ui->m_actionQuit->setIcon(icon_theme_factory->fromTheme(QSL("application-exit"))); + m_ui->m_actionRestart->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); + m_ui->m_actionAboutGuard->setIcon(icon_theme_factory->fromTheme(QSL("help-about"))); + m_ui->m_actionCheckForUpdates->setIcon(icon_theme_factory->fromTheme(QSL("system-upgrade"))); + m_ui->m_actionCleanupDatabase->setIcon(icon_theme_factory->fromTheme(QSL("edit-clear"))); + m_ui->m_actionReportBug->setIcon(icon_theme_factory->fromTheme(QSL("call-start"))); + m_ui->m_actionBackupDatabaseSettings->setIcon(icon_theme_factory->fromTheme(QSL("document-export"))); + m_ui->m_actionRestoreDatabaseSettings->setIcon(icon_theme_factory->fromTheme(QSL("document-import"))); + m_ui->m_actionDonate->setIcon(icon_theme_factory->fromTheme(QSL("applications-office"))); + m_ui->m_actionDisplayWiki->setIcon(icon_theme_factory->fromTheme(QSL("applications-science"))); - // View. - m_ui->m_actionSwitchMainWindow->setIcon(icon_theme_factory->fromTheme(QSL("window-close"))); - m_ui->m_actionFullscreen->setIcon(icon_theme_factory->fromTheme(QSL("view-fullscreen"))); - m_ui->m_actionSwitchFeedsList->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); - m_ui->m_actionSwitchMainMenu->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); - m_ui->m_actionSwitchToolBars->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); - m_ui->m_actionSwitchListHeaders->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); - m_ui->m_actionSwitchStatusBar->setIcon(icon_theme_factory->fromTheme(QSL("dialog-information"))); - m_ui->m_actionSwitchMessageListOrientation->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); - m_ui->m_menuShowHide->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); + // View. + m_ui->m_actionSwitchMainWindow->setIcon(icon_theme_factory->fromTheme(QSL("window-close"))); + m_ui->m_actionFullscreen->setIcon(icon_theme_factory->fromTheme(QSL("view-fullscreen"))); + m_ui->m_actionSwitchFeedsList->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); + m_ui->m_actionSwitchMainMenu->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); + m_ui->m_actionSwitchToolBars->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); + m_ui->m_actionSwitchListHeaders->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); + m_ui->m_actionSwitchStatusBar->setIcon(icon_theme_factory->fromTheme(QSL("dialog-information"))); + m_ui->m_actionSwitchMessageListOrientation->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); + m_ui->m_menuShowHide->setIcon(icon_theme_factory->fromTheme(QSL("view-restore"))); - // Feeds/messages. - m_ui->m_menuAddItem->setIcon(icon_theme_factory->fromTheme(QSL("list-add"))); - m_ui->m_actionStopRunningItemsUpdate->setIcon(icon_theme_factory->fromTheme(QSL("process-stop"))); - m_ui->m_actionUpdateAllItems->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); - m_ui->m_actionUpdateSelectedItems->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); - m_ui->m_actionClearSelectedItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-junk"))); - m_ui->m_actionClearAllItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-junk"))); - m_ui->m_actionDeleteSelectedItem->setIcon(icon_theme_factory->fromTheme(QSL("list-remove"))); - m_ui->m_actionDeleteSelectedMessages->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-junk"))); - m_ui->m_actionEditSelectedItem->setIcon(icon_theme_factory->fromTheme(QSL("document-edit"))); - m_ui->m_actionMarkAllItemsRead->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-read"))); - m_ui->m_actionMarkSelectedItemsAsRead->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-read"))); - m_ui->m_actionMarkSelectedItemsAsUnread->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread"))); - m_ui->m_actionMarkSelectedMessagesAsRead->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-read"))); - m_ui->m_actionMarkSelectedMessagesAsUnread->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread"))); - m_ui->m_actionSwitchImportanceOfSelectedMessages->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-important"))); - m_ui->m_actionOpenSelectedSourceArticlesExternally->setIcon(icon_theme_factory->fromTheme(QSL("document-open"))); - m_ui->m_actionOpenSelectedMessagesInternally->setIcon(icon_theme_factory->fromTheme(QSL("document-open"))); - m_ui->m_actionSendMessageViaEmail->setIcon(icon_theme_factory->fromTheme(QSL("mail-send"))); - m_ui->m_actionViewSelectedItemsNewspaperMode->setIcon(icon_theme_factory->fromTheme(QSL("format-justify-fill"))); - m_ui->m_actionSelectNextItem->setIcon(icon_theme_factory->fromTheme(QSL("go-down"))); - m_ui->m_actionSelectPreviousItem->setIcon(icon_theme_factory->fromTheme(QSL("go-up"))); - m_ui->m_actionSelectNextMessage->setIcon(icon_theme_factory->fromTheme(QSL("go-down"))); - m_ui->m_actionSelectPreviousMessage->setIcon(icon_theme_factory->fromTheme(QSL("go-up"))); - m_ui->m_actionSelectNextUnreadMessage->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread"))); - m_ui->m_actionShowOnlyUnreadItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread"))); - m_ui->m_actionExpandCollapseItem->setIcon(icon_theme_factory->fromTheme(QSL("format-indent-more"))); - m_ui->m_actionRestoreSelectedMessages->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); - m_ui->m_actionRestoreAllRecycleBins->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); - m_ui->m_actionEmptyAllRecycleBins->setIcon(icon_theme_factory->fromTheme(QSL("edit-clear"))); - m_ui->m_actionServiceAdd->setIcon(icon_theme_factory->fromTheme(QSL("list-add"))); - m_ui->m_actionServiceEdit->setIcon(icon_theme_factory->fromTheme(QSL("document-edit"))); - m_ui->m_actionServiceDelete->setIcon(icon_theme_factory->fromTheme(QSL("list-remove"))); - m_ui->m_actionAddFeedIntoSelectedAccount->setIcon(icon_theme_factory->fromTheme(QSL("application-rss+xml"))); - m_ui->m_actionAddCategoryIntoSelectedAccount->setIcon(icon_theme_factory->fromTheme(QSL("folder"))); + // Feeds/messages. + m_ui->m_menuAddItem->setIcon(icon_theme_factory->fromTheme(QSL("list-add"))); + m_ui->m_actionStopRunningItemsUpdate->setIcon(icon_theme_factory->fromTheme(QSL("process-stop"))); + m_ui->m_actionUpdateAllItems->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); + m_ui->m_actionUpdateSelectedItems->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); + m_ui->m_actionClearSelectedItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-junk"))); + m_ui->m_actionClearAllItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-junk"))); + m_ui->m_actionDeleteSelectedItem->setIcon(icon_theme_factory->fromTheme(QSL("list-remove"))); + m_ui->m_actionDeleteSelectedMessages->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-junk"))); + m_ui->m_actionEditSelectedItem->setIcon(icon_theme_factory->fromTheme(QSL("document-edit"))); + m_ui->m_actionMarkAllItemsRead->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-read"))); + m_ui->m_actionMarkSelectedItemsAsRead->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-read"))); + m_ui->m_actionMarkSelectedItemsAsUnread->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread"))); + m_ui->m_actionMarkSelectedMessagesAsRead->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-read"))); + m_ui->m_actionMarkSelectedMessagesAsUnread->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread"))); + m_ui->m_actionSwitchImportanceOfSelectedMessages->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-important"))); + m_ui->m_actionOpenSelectedSourceArticlesExternally->setIcon(icon_theme_factory->fromTheme(QSL("document-open"))); + m_ui->m_actionOpenSelectedMessagesInternally->setIcon(icon_theme_factory->fromTheme(QSL("document-open"))); + m_ui->m_actionSendMessageViaEmail->setIcon(icon_theme_factory->fromTheme(QSL("mail-send"))); + m_ui->m_actionViewSelectedItemsNewspaperMode->setIcon(icon_theme_factory->fromTheme(QSL("format-justify-fill"))); + m_ui->m_actionSelectNextItem->setIcon(icon_theme_factory->fromTheme(QSL("go-down"))); + m_ui->m_actionSelectPreviousItem->setIcon(icon_theme_factory->fromTheme(QSL("go-up"))); + m_ui->m_actionSelectNextMessage->setIcon(icon_theme_factory->fromTheme(QSL("go-down"))); + m_ui->m_actionSelectPreviousMessage->setIcon(icon_theme_factory->fromTheme(QSL("go-up"))); + m_ui->m_actionSelectNextUnreadMessage->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread"))); + m_ui->m_actionShowOnlyUnreadItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread"))); + m_ui->m_actionExpandCollapseItem->setIcon(icon_theme_factory->fromTheme(QSL("format-indent-more"))); + m_ui->m_actionRestoreSelectedMessages->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); + m_ui->m_actionRestoreAllRecycleBins->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh"))); + m_ui->m_actionEmptyAllRecycleBins->setIcon(icon_theme_factory->fromTheme(QSL("edit-clear"))); + m_ui->m_actionServiceAdd->setIcon(icon_theme_factory->fromTheme(QSL("list-add"))); + m_ui->m_actionServiceEdit->setIcon(icon_theme_factory->fromTheme(QSL("document-edit"))); + m_ui->m_actionServiceDelete->setIcon(icon_theme_factory->fromTheme(QSL("list-remove"))); + m_ui->m_actionAddFeedIntoSelectedAccount->setIcon(icon_theme_factory->fromTheme(QSL("application-rss+xml"))); + m_ui->m_actionAddCategoryIntoSelectedAccount->setIcon(icon_theme_factory->fromTheme(QSL("folder"))); - // Tabs & web browser. - m_ui->m_actionTabNewWebBrowser->setIcon(icon_theme_factory->fromTheme(QSL("tab-new"))); - m_ui->m_actionTabsCloseAll->setIcon(icon_theme_factory->fromTheme(QSL("window-close"))); - m_ui->m_actionTabsCloseAllExceptCurrent->setIcon(icon_theme_factory->fromTheme(QSL("window-close"))); + // Tabs & web browser. + m_ui->m_actionTabNewWebBrowser->setIcon(icon_theme_factory->fromTheme(QSL("tab-new"))); + m_ui->m_actionTabsCloseAll->setIcon(icon_theme_factory->fromTheme(QSL("window-close"))); + m_ui->m_actionTabsCloseAllExceptCurrent->setIcon(icon_theme_factory->fromTheme(QSL("window-close"))); m_ui->m_actionTabsNext->setIcon(icon_theme_factory->fromTheme(QSL("go-next"))); m_ui->m_actionTabsPrevious->setIcon(icon_theme_factory->fromTheme(QSL("go-previous"))); // Setup icons on TabWidget too. - m_ui->m_tabWidget->setupIcons(); + m_ui->m_tabWidget->setupIcons(); } void FormMain::loadSize() { - const QRect screen = qApp->desktop()->screenGeometry(); - const Settings* settings = qApp->settings(); - // Reload main window size & position. - resize(settings->value(GROUP(GUI), GUI::MainWindowInitialSize, size()).toSize()); - move(settings->value(GROUP(GUI), GUI::MainWindowInitialPosition, screen.center() - rect().center()).toPoint()); + const QRect screen = qApp->desktop()->screenGeometry(); + const Settings* settings = qApp->settings(); - if (settings->value(GROUP(GUI), SETTING(GUI::MainWindowStartsMaximized)).toBool()) { - setWindowState(windowState() | Qt::WindowMaximized); - // We process events so that window is really maximized fast. - qApp->processEvents(); - } + // Reload main window size & position. + resize(settings->value(GROUP(GUI), GUI::MainWindowInitialSize, size()).toSize()); + move(settings->value(GROUP(GUI), GUI::MainWindowInitialPosition, screen.center() - rect().center()).toPoint()); - // If user exited the application while in fullsreen mode, - // then re-enable it now. - if (settings->value(GROUP(GUI), SETTING(GUI::MainWindowStartsFullscreen)).toBool()) { - m_ui->m_actionFullscreen->setChecked(true); - } + if (settings->value(GROUP(GUI), SETTING(GUI::MainWindowStartsMaximized)).toBool()) { + setWindowState(windowState() | Qt::WindowMaximized); - // Hide the main menu if user wants it. - m_ui->m_actionSwitchMainMenu->setChecked(settings->value(GROUP(GUI), SETTING(GUI::MainMenuVisible)).toBool()); - // Adjust dimensions of "feeds & messages" widget. - m_ui->m_tabWidget->feedMessageViewer()->loadSize(); - m_ui->m_actionSwitchToolBars->setChecked(settings->value(GROUP(GUI), SETTING(GUI::ToolbarsVisible)).toBool()); - m_ui->m_actionSwitchListHeaders->setChecked(settings->value(GROUP(GUI), SETTING(GUI::ListHeadersVisible)).toBool()); - m_ui->m_actionSwitchStatusBar->setChecked(settings->value(GROUP(GUI), SETTING(GUI::StatusBarVisible)).toBool()); - // Make sure that only unread feeds are shown if user has that feature set on. - m_ui->m_actionShowOnlyUnreadItems->setChecked(settings->value(GROUP(Feeds), SETTING(Feeds::ShowOnlyUnreadFeeds)).toBool()); + // We process events so that window is really maximized fast. + qApp->processEvents(); + } + + // If user exited the application while in fullsreen mode, + // then re-enable it now. + if (settings->value(GROUP(GUI), SETTING(GUI::MainWindowStartsFullscreen)).toBool()) { + m_ui->m_actionFullscreen->setChecked(true); + } + + // Hide the main menu if user wants it. + m_ui->m_actionSwitchMainMenu->setChecked(settings->value(GROUP(GUI), SETTING(GUI::MainMenuVisible)).toBool()); + + // Adjust dimensions of "feeds & messages" widget. + m_ui->m_tabWidget->feedMessageViewer()->loadSize(); + m_ui->m_actionSwitchToolBars->setChecked(settings->value(GROUP(GUI), SETTING(GUI::ToolbarsVisible)).toBool()); + m_ui->m_actionSwitchListHeaders->setChecked(settings->value(GROUP(GUI), SETTING(GUI::ListHeadersVisible)).toBool()); + m_ui->m_actionSwitchStatusBar->setChecked(settings->value(GROUP(GUI), SETTING(GUI::StatusBarVisible)).toBool()); + + // Make sure that only unread feeds are shown if user has that feature set on. + m_ui->m_actionShowOnlyUnreadItems->setChecked(settings->value(GROUP(Feeds), SETTING(Feeds::ShowOnlyUnreadFeeds)).toBool()); } void FormMain::saveSize() { - Settings* settings = qApp->settings(); - bool is_fullscreen = isFullScreen(); - bool is_maximized = false; + Settings* settings = qApp->settings(); + bool is_fullscreen = isFullScreen(); + bool is_maximized = false; - if (is_fullscreen) { - m_ui->m_actionFullscreen->setChecked(false); - // We (process events to really) un-fullscreen, so that we can determine if window is really maximized. - qApp->processEvents(); - } + if (is_fullscreen) { + m_ui->m_actionFullscreen->setChecked(false); - if (isMaximized()) { - is_maximized = true; - // Window is maximized, we store that fact to settings and unmaximize. - qApp->settings()->setValue(GROUP(GUI), GUI::IsMainWindowMaximizedBeforeFullscreen, isMaximized()); - setWindowState((windowState() & ~Qt::WindowMaximized) | Qt::WindowActive); - // We process events to really have window un-maximized. - qApp->processEvents(); - } + // We (process events to really) un-fullscreen, so that we can determine if window is really maximized. + qApp->processEvents(); + } - settings->setValue(GROUP(GUI), GUI::MainMenuVisible, m_ui->m_actionSwitchMainMenu->isChecked()); - settings->setValue(GROUP(GUI), GUI::MainWindowInitialPosition, pos()); - settings->setValue(GROUP(GUI), GUI::MainWindowInitialSize, size()); - settings->setValue(GROUP(GUI), GUI::MainWindowStartsMaximized, is_maximized); - settings->setValue(GROUP(GUI), GUI::MainWindowStartsFullscreen, is_fullscreen); - settings->setValue(GROUP(GUI), GUI::StatusBarVisible, m_ui->m_actionSwitchStatusBar->isChecked()); - m_ui->m_tabWidget->feedMessageViewer()->saveSize(); + if (isMaximized()) { + is_maximized = true; + + // Window is maximized, we store that fact to settings and unmaximize. + qApp->settings()->setValue(GROUP(GUI), GUI::IsMainWindowMaximizedBeforeFullscreen, isMaximized()); + setWindowState((windowState() & ~Qt::WindowMaximized) | Qt::WindowActive); + + // We process events to really have window un-maximized. + qApp->processEvents(); + } + + settings->setValue(GROUP(GUI), GUI::MainMenuVisible, m_ui->m_actionSwitchMainMenu->isChecked()); + settings->setValue(GROUP(GUI), GUI::MainWindowInitialPosition, pos()); + settings->setValue(GROUP(GUI), GUI::MainWindowInitialSize, size()); + settings->setValue(GROUP(GUI), GUI::MainWindowStartsMaximized, is_maximized); + settings->setValue(GROUP(GUI), GUI::MainWindowStartsFullscreen, is_fullscreen); + settings->setValue(GROUP(GUI), GUI::StatusBarVisible, m_ui->m_actionSwitchStatusBar->isChecked()); + m_ui->m_tabWidget->feedMessageViewer()->saveSize(); } void FormMain::createConnections() { - // Status bar connections. - connect(m_ui->m_menuAddItem, &QMenu::aboutToShow, this, &FormMain::updateAddItemMenu); - connect(m_ui->m_menuRecycleBin, &QMenu::aboutToShow, this, &FormMain::updateRecycleBinMenu); - connect(m_ui->m_menuAccounts, &QMenu::aboutToShow, this, &FormMain::updateAccountsMenu); - connect(m_ui->m_actionServiceDelete, &QAction::triggered, m_ui->m_actionDeleteSelectedItem, &QAction::triggered); - connect(m_ui->m_actionServiceEdit, &QAction::triggered, m_ui->m_actionEditSelectedItem, &QAction::triggered); + // Status bar connections. + connect(m_ui->m_menuAddItem, &QMenu::aboutToShow, this, &FormMain::updateAddItemMenu); + connect(m_ui->m_menuRecycleBin, &QMenu::aboutToShow, this, &FormMain::updateRecycleBinMenu); + connect(m_ui->m_menuAccounts, &QMenu::aboutToShow, this, &FormMain::updateAccountsMenu); + connect(m_ui->m_actionServiceDelete, &QAction::triggered, m_ui->m_actionDeleteSelectedItem, &QAction::triggered); + connect(m_ui->m_actionServiceEdit, &QAction::triggered, m_ui->m_actionEditSelectedItem, &QAction::triggered); // Menu "File" connections. - connect(m_ui->m_actionBackupDatabaseSettings, &QAction::triggered, this, &FormMain::backupDatabaseSettings); - connect(m_ui->m_actionRestoreDatabaseSettings, &QAction::triggered, this, &FormMain::restoreDatabaseSettings); - connect(m_ui->m_actionQuit, &QAction::triggered, qApp, &Application::quit); - connect(m_ui->m_actionServiceAdd, &QAction::triggered, this, &FormMain::showAddAccountDialog); - connect(m_ui->m_actionRestart, &QAction::triggered, qApp, &Application::restart); + connect(m_ui->m_actionBackupDatabaseSettings, &QAction::triggered, this, &FormMain::backupDatabaseSettings); + connect(m_ui->m_actionRestoreDatabaseSettings, &QAction::triggered, this, &FormMain::restoreDatabaseSettings); + connect(m_ui->m_actionQuit, &QAction::triggered, qApp, &Application::quit); + connect(m_ui->m_actionServiceAdd, &QAction::triggered, this, &FormMain::showAddAccountDialog); + connect(m_ui->m_actionRestart, &QAction::triggered, qApp, &Application::restart); // Menu "View" connections. - connect(m_ui->m_actionFullscreen, &QAction::toggled, this, &FormMain::switchFullscreenMode); - connect(m_ui->m_actionSwitchMainMenu, &QAction::toggled, m_ui->m_menuBar, &QMenuBar::setVisible); - connect(m_ui->m_actionSwitchMainWindow, &QAction::triggered, this, &FormMain::switchVisibility); - connect(m_ui->m_actionSwitchStatusBar, &QAction::toggled, statusBar(), &StatusBar::setVisible); + connect(m_ui->m_actionFullscreen, &QAction::toggled, this, &FormMain::switchFullscreenMode); + connect(m_ui->m_actionSwitchMainMenu, &QAction::toggled, m_ui->m_menuBar, &QMenuBar::setVisible); + connect(m_ui->m_actionSwitchMainWindow, &QAction::triggered, this, &FormMain::switchVisibility); + connect(m_ui->m_actionSwitchStatusBar, &QAction::toggled, statusBar(), &StatusBar::setVisible); // Menu "Tools" connections. - connect(m_ui->m_actionSettings, &QAction::triggered, [this]() { - FormSettings(*this).exec(); - }); - connect(m_ui->m_actionDownloadManager, &QAction::triggered, m_ui->m_tabWidget, &TabWidget::showDownloadManager); - connect(m_ui->m_actionCleanupDatabase, &QAction::triggered, this, &FormMain::showDbCleanupAssistant); + connect(m_ui->m_actionSettings, &QAction::triggered, [this]() { + FormSettings(*this).exec(); + }); + connect(m_ui->m_actionDownloadManager, &QAction::triggered, m_ui->m_tabWidget, &TabWidget::showDownloadManager); + connect(m_ui->m_actionCleanupDatabase, &QAction::triggered, this, &FormMain::showDbCleanupAssistant); // Menu "Help" connections. - connect(m_ui->m_actionAboutGuard, &QAction::triggered, [this]() { - FormAbout(this).exec(); - }); - connect(m_ui->m_actionCheckForUpdates, &QAction::triggered, [this]() { - FormUpdate(this).exec(); - }); - connect(m_ui->m_actionReportBug, &QAction::triggered, this, &FormMain::reportABug); - connect(m_ui->m_actionDonate, &QAction::triggered, this, &FormMain::donate); - connect(m_ui->m_actionDisplayWiki, &QAction::triggered, this, &FormMain::showWiki); + connect(m_ui->m_actionAboutGuard, &QAction::triggered, [this]() { + FormAbout(this).exec(); + }); + connect(m_ui->m_actionCheckForUpdates, &QAction::triggered, [this]() { + FormUpdate(this).exec(); + }); + connect(m_ui->m_actionReportBug, &QAction::triggered, this, &FormMain::reportABug); + connect(m_ui->m_actionDonate, &QAction::triggered, this, &FormMain::donate); + connect(m_ui->m_actionDisplayWiki, &QAction::triggered, this, &FormMain::showWiki); // Tab widget connections. connect(m_ui->m_actionTabsNext, &QAction::triggered, m_ui->m_tabWidget, &TabWidget::gotoNextTab); connect(m_ui->m_actionTabsPrevious, &QAction::triggered, m_ui->m_tabWidget, &TabWidget::gotoPreviousTab); - connect(m_ui->m_actionTabsCloseAllExceptCurrent, &QAction::triggered, m_ui->m_tabWidget, &TabWidget::closeAllTabsExceptCurrent); - connect(m_ui->m_actionTabsCloseAll, &QAction::triggered, m_ui->m_tabWidget, &TabWidget::closeAllTabs); - connect(m_ui->m_actionTabNewWebBrowser, &QAction::triggered, m_ui->m_tabWidget, &TabWidget::addEmptyBrowser); - connect(tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::itemSelected, this, &FormMain::updateFeedButtonsAvailability); - connect(qApp->feedUpdateLock(), &Mutex::locked, this, &FormMain::updateFeedButtonsAvailability); - connect(qApp->feedUpdateLock(), &Mutex::unlocked, this, &FormMain::updateFeedButtonsAvailability); - connect(tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::currentMessageRemoved, - this, &FormMain::updateMessageButtonsAvailability); - connect(tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::currentMessageChanged, - this, &FormMain::updateMessageButtonsAvailability); - connect(qApp->feedReader(), &FeedReader::feedUpdatesStarted, this, &FormMain::onFeedUpdatesStarted); - connect(qApp->feedReader(), &FeedReader::feedUpdatesProgress, this, &FormMain::onFeedUpdatesProgress); - connect(qApp->feedReader(), &FeedReader::feedUpdatesFinished, this, &FormMain::onFeedUpdatesFinished); + connect(m_ui->m_actionTabsCloseAllExceptCurrent, &QAction::triggered, m_ui->m_tabWidget, &TabWidget::closeAllTabsExceptCurrent); + connect(m_ui->m_actionTabsCloseAll, &QAction::triggered, m_ui->m_tabWidget, &TabWidget::closeAllTabs); + connect(m_ui->m_actionTabNewWebBrowser, &QAction::triggered, m_ui->m_tabWidget, &TabWidget::addEmptyBrowser); + connect(tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::itemSelected, this, &FormMain::updateFeedButtonsAvailability); + connect(qApp->feedUpdateLock(), &Mutex::locked, this, &FormMain::updateFeedButtonsAvailability); + connect(qApp->feedUpdateLock(), &Mutex::unlocked, this, &FormMain::updateFeedButtonsAvailability); + connect(tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::currentMessageRemoved, + this, &FormMain::updateMessageButtonsAvailability); + connect(tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::currentMessageChanged, + this, &FormMain::updateMessageButtonsAvailability); + connect(qApp->feedReader(), &FeedReader::feedUpdatesStarted, this, &FormMain::onFeedUpdatesStarted); + connect(qApp->feedReader(), &FeedReader::feedUpdatesProgress, this, &FormMain::onFeedUpdatesProgress); + connect(qApp->feedReader(), &FeedReader::feedUpdatesFinished, this, &FormMain::onFeedUpdatesFinished); // Toolbar forwardings. - connect(m_ui->m_actionAddFeedIntoSelectedAccount, &QAction::triggered, - tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::addFeedIntoSelectedAccount); - connect(m_ui->m_actionAddCategoryIntoSelectedAccount, &QAction::triggered, - tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::addCategoryIntoSelectedAccount); - connect(m_ui->m_actionSwitchImportanceOfSelectedMessages, - &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::switchSelectedMessagesImportance); - connect(m_ui->m_actionDeleteSelectedMessages, - &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::deleteSelectedMessages); - connect(m_ui->m_actionMarkSelectedMessagesAsRead, - &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::markSelectedMessagesRead); - connect(m_ui->m_actionMarkSelectedMessagesAsUnread, &QAction::triggered, - tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::markSelectedMessagesUnread); - connect(m_ui->m_actionOpenSelectedSourceArticlesExternally, - &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::openSelectedSourceMessagesExternally); - connect(m_ui->m_actionOpenSelectedMessagesInternally, - &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::openSelectedMessagesInternally); - connect(m_ui->m_actionSendMessageViaEmail, - &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::sendSelectedMessageViaEmail); - connect(m_ui->m_actionMarkAllItemsRead, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::markAllItemsRead); - connect(m_ui->m_actionMarkSelectedItemsAsRead, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::markSelectedItemRead); - connect(m_ui->m_actionExpandCollapseItem, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::expandCollapseCurrentItem); - connect(m_ui->m_actionMarkSelectedItemsAsUnread, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::markSelectedItemUnread); - connect(m_ui->m_actionClearSelectedItems, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::clearSelectedFeeds); - connect(m_ui->m_actionClearAllItems, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::clearAllFeeds); - connect(m_ui->m_actionUpdateSelectedItems, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::updateSelectedItems); - connect(m_ui->m_actionUpdateAllItems, - &QAction::triggered, qApp->feedReader(), &FeedReader::updateAllFeeds); - connect(m_ui->m_actionStopRunningItemsUpdate, - &QAction::triggered, qApp->feedReader(), &FeedReader::stopRunningFeedUpdate); - connect(m_ui->m_actionEditSelectedItem, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::editSelectedItem); - connect(m_ui->m_actionViewSelectedItemsNewspaperMode, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::openSelectedItemsInNewspaperMode); - connect(m_ui->m_actionDeleteSelectedItem, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::deleteSelectedItem); - connect(m_ui->m_actionSwitchFeedsList, &QAction::triggered, - tabWidget()->feedMessageViewer(), &FeedMessageViewer::switchFeedComponentVisibility); - connect(m_ui->m_actionSelectNextItem, + connect(m_ui->m_actionAddFeedIntoSelectedAccount, &QAction::triggered, + tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::addFeedIntoSelectedAccount); + connect(m_ui->m_actionAddCategoryIntoSelectedAccount, &QAction::triggered, + tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::addCategoryIntoSelectedAccount); + connect(m_ui->m_actionSwitchImportanceOfSelectedMessages, + &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::switchSelectedMessagesImportance); + connect(m_ui->m_actionDeleteSelectedMessages, + &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::deleteSelectedMessages); + connect(m_ui->m_actionMarkSelectedMessagesAsRead, + &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::markSelectedMessagesRead); + connect(m_ui->m_actionMarkSelectedMessagesAsUnread, &QAction::triggered, + tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::markSelectedMessagesUnread); + connect(m_ui->m_actionOpenSelectedSourceArticlesExternally, + &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::openSelectedSourceMessagesExternally); + connect(m_ui->m_actionOpenSelectedMessagesInternally, + &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::openSelectedMessagesInternally); + connect(m_ui->m_actionSendMessageViaEmail, + &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::sendSelectedMessageViaEmail); + connect(m_ui->m_actionMarkAllItemsRead, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::markAllItemsRead); + connect(m_ui->m_actionMarkSelectedItemsAsRead, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::markSelectedItemRead); + connect(m_ui->m_actionExpandCollapseItem, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::expandCollapseCurrentItem); + connect(m_ui->m_actionMarkSelectedItemsAsUnread, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::markSelectedItemUnread); + connect(m_ui->m_actionClearSelectedItems, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::clearSelectedFeeds); + connect(m_ui->m_actionClearAllItems, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::clearAllFeeds); + connect(m_ui->m_actionUpdateSelectedItems, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::updateSelectedItems); + connect(m_ui->m_actionUpdateAllItems, + &QAction::triggered, qApp->feedReader(), &FeedReader::updateAllFeeds); + connect(m_ui->m_actionStopRunningItemsUpdate, + &QAction::triggered, qApp->feedReader(), &FeedReader::stopRunningFeedUpdate); + connect(m_ui->m_actionEditSelectedItem, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::editSelectedItem); + connect(m_ui->m_actionViewSelectedItemsNewspaperMode, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::openSelectedItemsInNewspaperMode); + connect(m_ui->m_actionDeleteSelectedItem, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::deleteSelectedItem); + connect(m_ui->m_actionSwitchFeedsList, &QAction::triggered, + tabWidget()->feedMessageViewer(), &FeedMessageViewer::switchFeedComponentVisibility); + connect(m_ui->m_actionSelectNextItem, &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::selectNextItem); - connect(m_ui->m_actionSwitchToolBars, &QAction::toggled, - tabWidget()->feedMessageViewer(), &FeedMessageViewer::setToolBarsEnabled); - connect(m_ui->m_actionSwitchListHeaders, &QAction::toggled, - tabWidget()->feedMessageViewer(), &FeedMessageViewer::setListHeadersEnabled); - connect(m_ui->m_actionSelectPreviousItem, - &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::selectPreviousItem); - connect(m_ui->m_actionSelectNextMessage, - &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::selectNextItem); - connect(m_ui->m_actionSelectNextUnreadMessage, + connect(m_ui->m_actionSwitchToolBars, &QAction::toggled, + tabWidget()->feedMessageViewer(), &FeedMessageViewer::setToolBarsEnabled); + connect(m_ui->m_actionSwitchListHeaders, &QAction::toggled, + tabWidget()->feedMessageViewer(), &FeedMessageViewer::setListHeadersEnabled); + connect(m_ui->m_actionSelectPreviousItem, + &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::selectPreviousItem); + connect(m_ui->m_actionSelectNextMessage, + &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::selectNextItem); + connect(m_ui->m_actionSelectNextUnreadMessage, &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::selectNextUnreadItem); - connect(m_ui->m_actionSelectPreviousMessage, - &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::selectPreviousItem); - connect(m_ui->m_actionSwitchMessageListOrientation, &QAction::triggered, - tabWidget()->feedMessageViewer(), &FeedMessageViewer::switchMessageSplitterOrientation); - connect(m_ui->m_actionShowOnlyUnreadItems, &QAction::toggled, - tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleShowOnlyUnreadFeeds); - connect(m_ui->m_actionRestoreSelectedMessages, &QAction::triggered, - tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::restoreSelectedMessages); - connect(m_ui->m_actionRestoreAllRecycleBins, &QAction::triggered, - tabWidget()->feedMessageViewer()->feedsView()->sourceModel(), &FeedsModel::restoreAllBins); - connect(m_ui->m_actionEmptyAllRecycleBins, &QAction::triggered, - tabWidget()->feedMessageViewer()->feedsView()->sourceModel(), &FeedsModel::emptyAllBins); + connect(m_ui->m_actionSelectPreviousMessage, + &QAction::triggered, tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::selectPreviousItem); + connect(m_ui->m_actionSwitchMessageListOrientation, &QAction::triggered, + tabWidget()->feedMessageViewer(), &FeedMessageViewer::switchMessageSplitterOrientation); + connect(m_ui->m_actionShowOnlyUnreadItems, &QAction::toggled, + tabWidget()->feedMessageViewer(), &FeedMessageViewer::toggleShowOnlyUnreadFeeds); + connect(m_ui->m_actionRestoreSelectedMessages, &QAction::triggered, + tabWidget()->feedMessageViewer()->messagesView(), &MessagesView::restoreSelectedMessages); + connect(m_ui->m_actionRestoreAllRecycleBins, &QAction::triggered, + tabWidget()->feedMessageViewer()->feedsView()->sourceModel(), &FeedsModel::restoreAllBins); + connect(m_ui->m_actionEmptyAllRecycleBins, &QAction::triggered, + tabWidget()->feedMessageViewer()->feedsView()->sourceModel(), &FeedsModel::emptyAllBins); } void FormMain::backupDatabaseSettings() { - QScopedPointer form(new FormBackupDatabaseSettings(this)); - form->exec(); + QScopedPointer form(new FormBackupDatabaseSettings(this)); + form->exec(); } void FormMain::restoreDatabaseSettings() { - FormRestoreDatabaseSettings form(*this); - form.exec(); + FormRestoreDatabaseSettings form(*this); - if (form.shouldRestart()) { - qApp->restart(); - } + form.exec(); + + if (form.shouldRestart()) { + qApp->restart(); + } } void FormMain::changeEvent(QEvent* event) { - switch (event->type()) { - case QEvent::WindowStateChange: { - if (windowState() & Qt::WindowMinimized && - SystemTrayIcon::isSystemTrayActivated() && - qApp->settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool()) { - event->ignore(); - QTimer::singleShot(CHANGE_EVENT_DELAY, this, SLOT(switchVisibility())); - } + switch (event->type()) { + case QEvent::WindowStateChange: { + if (windowState() & Qt::WindowMinimized && + SystemTrayIcon::isSystemTrayActivated() && + qApp->settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool()) { + event->ignore(); + QTimer::singleShot(CHANGE_EVENT_DELAY, this, SLOT(switchVisibility())); + } - break; - } + break; + } - default: - break; - } + default: + break; + } - QMainWindow::changeEvent(event); + QMainWindow::changeEvent(event); } void FormMain::showWiki() { - if (!qApp->web()->openUrlInExternalBrowser(APP_URL_WIKI)) { - qApp->showGuiMessage(tr("Cannot open external browser"), - tr("Cannot open external browser. Navigate to application website manually."), - QSystemTrayIcon::Warning, this, true); - } + if (!qApp->web()->openUrlInExternalBrowser(APP_URL_WIKI)) { + qApp->showGuiMessage(tr("Cannot open external browser"), + tr("Cannot open external browser. Navigate to application website manually."), + QSystemTrayIcon::Warning, this, true); + } } void FormMain::showAddAccountDialog() { - QScopedPointer form_update(new FormAddAccount(qApp->feedReader()->feedServices(), - qApp->feedReader()->feedsModel(), - this)); - form_update->exec(); + QScopedPointer form_update(new FormAddAccount(qApp->feedReader()->feedServices(), + qApp->feedReader()->feedsModel(), + this)); + form_update->exec(); } void FormMain::reportABug() { - if (!qApp->web()->openUrlInExternalBrowser(QSL(APP_URL_ISSUES_NEW))) { - qApp->showGuiMessage(tr("Cannot open external browser"), - tr("Cannot open external browser. Navigate to application website manually."), - QSystemTrayIcon::Warning, this, true); - } + if (!qApp->web()->openUrlInExternalBrowser(QSL(APP_URL_ISSUES_NEW))) { + qApp->showGuiMessage(tr("Cannot open external browser"), + tr("Cannot open external browser. Navigate to application website manually."), + QSystemTrayIcon::Warning, this, true); + } } void FormMain::donate() { - if (!qApp->web()->openUrlInExternalBrowser(QSL(APP_DONATE_URL))) { - qApp->showGuiMessage(tr("Cannot open external browser"), - tr("Cannot open external browser. Navigate to application website manually."), - QSystemTrayIcon::Warning, this, true); - } + if (!qApp->web()->openUrlInExternalBrowser(QSL(APP_DONATE_URL))) { + qApp->showGuiMessage(tr("Cannot open external browser"), + tr("Cannot open external browser. Navigate to application website manually."), + QSystemTrayIcon::Warning, this, true); + } } diff --git a/src/gui/dialogs/formmain.h b/src/gui/dialogs/formmain.h index ef76b50ef..8ab0e0d09 100755 --- a/src/gui/dialogs/formmain.h +++ b/src/gui/dialogs/formmain.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,86 +23,88 @@ #include "ui_formmain.h" - class StatusBar; class FormMain : public QMainWindow { - Q_OBJECT + Q_OBJECT - friend class TabWidget; - friend class MessagesView; - friend class FeedsView; + friend class TabWidget; + friend class MessagesView; + friend class FeedsView; - public: - // Constructors and destructors. - explicit FormMain(QWidget* parent = 0, Qt::WindowFlags f = 0); - virtual ~FormMain(); + public: - // Returns menu for the tray icon. - QMenu* trayMenu() const; + // Constructors and destructors. + explicit FormMain(QWidget* parent = 0, Qt::WindowFlags f = 0); + virtual ~FormMain(); - // Returns global tab widget. - TabWidget* tabWidget() const; + // Returns menu for the tray icon. + QMenu* trayMenu() const; - // Access to statusbar. - StatusBar* statusBar() const; + // Returns global tab widget. + TabWidget* tabWidget() const; - // Returns list of all globally available actions. - // NOTE: This is used for setting dynamic shortcuts - // for given actions. - QList allActions() const; + // Access to statusbar. + StatusBar* statusBar() const; - // Loads/saves visual state of the application. - void loadSize(); - void saveSize(); + // Returns list of all globally available actions. + // NOTE: This is used for setting dynamic shortcuts + // for given actions. + QList allActions() const; - public slots: - // Displays window on top or switches its visibility. - void display(); + // Loads/saves visual state of the application. + void loadSize(); + void saveSize(); - // Switches visibility of main window. - void switchVisibility(bool force_hide = false); + public slots: - // Turns on/off fullscreen mode - void switchFullscreenMode(); + // Displays window on top or switches its visibility. + void display(); - private slots: - void updateAddItemMenu(); - void updateRecycleBinMenu(); - void updateAccountsMenu(); + // Switches visibility of main window. + void switchVisibility(bool force_hide = false); - void updateMessageButtonsAvailability(); - void updateFeedButtonsAvailability(); + // Turns on/off fullscreen mode + void switchFullscreenMode(); - void onFeedUpdatesStarted(); - void onFeedUpdatesProgress(const Feed* feed, int current, int total); - void onFeedUpdatesFinished(const FeedDownloadResults& results); + private slots: + void updateAddItemMenu(); + void updateRecycleBinMenu(); + void updateAccountsMenu(); - // Displays various dialogs. - void backupDatabaseSettings(); - void restoreDatabaseSettings(); - void showWiki(); - void showAddAccountDialog(); - void showDbCleanupAssistant(); - void reportABug(); - void donate(); + void updateMessageButtonsAvailability(); + void updateFeedButtonsAvailability(); - private: - // Event handler reimplementations. - void changeEvent(QEvent* event); + void onFeedUpdatesStarted(); + void onFeedUpdatesProgress(const Feed* feed, int current, int total); + void onFeedUpdatesFinished(const FeedDownloadResults& results); - // Creates all needed menus and sets them up. - void prepareMenus(); + // Displays various dialogs. + void backupDatabaseSettings(); + void restoreDatabaseSettings(); + void showWiki(); + void showAddAccountDialog(); + void showDbCleanupAssistant(); + void reportABug(); + void donate(); - // Creates needed connections for this window. - void createConnections(); + private: - // Sets up proper icons for this widget. - void setupIcons(); + // Event handler reimplementations. + void changeEvent(QEvent* event); - QScopedPointer m_ui; - QMenu* m_trayMenu; - StatusBar* m_statusBar; + // Creates all needed menus and sets them up. + void prepareMenus(); + + // Creates needed connections for this window. + void createConnections(); + + // Sets up proper icons for this widget. + void setupIcons(); + + QScopedPointer m_ui; + QMenu* m_trayMenu; + StatusBar* m_statusBar; }; #endif // FORMMAIN_H diff --git a/src/gui/dialogs/formrestoredatabasesettings.cpp b/src/gui/dialogs/formrestoredatabasesettings.cpp index e7fad0e16..8b9135dd0 100755 --- a/src/gui/dialogs/formrestoredatabasesettings.cpp +++ b/src/gui/dialogs/formrestoredatabasesettings.cpp @@ -93,12 +93,14 @@ void FormRestoreDatabaseSettings::selectFolder(QString folder) { } const QDir selected_folder(folder); - const QFileInfoList available_databases = selected_folder.entryInfoList(QStringList() << QString("*") + BACKUP_SUFFIX_DATABASE, - QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::CaseSensitive | QDir::NoSymLinks, - QDir::Name); - const QFileInfoList available_settings = selected_folder.entryInfoList(QStringList() << QString("*") + BACKUP_SUFFIX_SETTINGS, - QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::CaseSensitive | QDir::NoSymLinks, - QDir::Name); + const QFileInfoList available_databases = selected_folder.entryInfoList(QStringList() << QString( + "*") + BACKUP_SUFFIX_DATABASE, + QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::CaseSensitive | QDir::NoSymLinks, + QDir::Name); + const QFileInfoList available_settings = selected_folder.entryInfoList(QStringList() << QString( + "*") + BACKUP_SUFFIX_SETTINGS, + QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::CaseSensitive | QDir::NoSymLinks, + QDir::Name); m_ui.m_listDatabase->clear(); m_ui.m_listSettings->clear(); diff --git a/src/gui/dialogs/formrestoredatabasesettings.h b/src/gui/dialogs/formrestoredatabasesettings.h index 610fe7a71..41e9f3506 100755 --- a/src/gui/dialogs/formrestoredatabasesettings.h +++ b/src/gui/dialogs/formrestoredatabasesettings.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,30 +23,29 @@ #include "ui_formrestoredatabasesettings.h" - class FormRestoreDatabaseSettings : public QDialog { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit FormRestoreDatabaseSettings(QWidget& parent); - virtual ~FormRestoreDatabaseSettings(); + public: - bool shouldRestart() const { - return m_shouldRestart; - } + // Constructors and destructors. + explicit FormRestoreDatabaseSettings(QWidget& parent); + virtual ~FormRestoreDatabaseSettings(); - private slots: - void performRestoration(); - void checkOkButton(); - void selectFolderWithGui(); - void selectFolder(QString folder = QString()); + bool shouldRestart() const { + return m_shouldRestart; + } - private: - Ui::FormRestoreDatabaseSettings m_ui; - QPushButton* m_btnRestart; + private slots: + void performRestoration(); + void checkOkButton(); + void selectFolderWithGui(); + void selectFolder(QString folder = QString()); - bool m_shouldRestart; + private: + Ui::FormRestoreDatabaseSettings m_ui; + QPushButton* m_btnRestart; + bool m_shouldRestart; }; #endif // FORMRESTOREDATABASESETTINGS_H diff --git a/src/gui/dialogs/formsettings.cpp b/src/gui/dialogs/formsettings.cpp index d89f8eefb..0956758bf 100755 --- a/src/gui/dialogs/formsettings.cpp +++ b/src/gui/dialogs/formsettings.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,10 +19,10 @@ #include "gui/dialogs/formsettings.h" #include "definitions/definitions.h" -#include "miscellaneous/application.h" -#include "miscellaneous/settings.h" -#include "miscellaneous/iconfactory.h" #include "gui/messagebox.h" +#include "miscellaneous/application.h" +#include "miscellaneous/iconfactory.h" +#include "miscellaneous/settings.h" #include "gui/settings/settingsbrowsermail.h" #include "gui/settings/settingsdatabase.h" @@ -32,108 +33,111 @@ #include "gui/settings/settingslocalization.h" #include "gui/settings/settingsshortcuts.h" - FormSettings::FormSettings(QWidget& parent) - : QDialog(&parent), m_panels(QList()), m_settings(*qApp->settings()) { - m_ui.setupUi(this); - // Set flags and attributes. - setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); - setWindowIcon(qApp->icons()->fromTheme(QSL("emblem-system"))); - m_btnApply = m_ui.m_buttonBox->button(QDialogButtonBox::Apply); - m_btnApply->setEnabled(false); - // Establish needed connections. - connect(m_ui.m_buttonBox, &QDialogButtonBox::accepted, this, &FormSettings::saveSettings); - connect(m_ui.m_buttonBox, &QDialogButtonBox::rejected, this, &FormSettings::cancelSettings); - connect(m_btnApply, &QPushButton::clicked, this, &FormSettings::applySettings); - addSettingsPanel(new SettingsGeneral(&m_settings, this)); - addSettingsPanel(new SettingsDatabase(&m_settings, this)); - addSettingsPanel(new SettingsGui(&m_settings, this)); - addSettingsPanel(new SettingsLocalization(&m_settings, this)); - addSettingsPanel(new SettingsShortcuts(&m_settings, this)); - addSettingsPanel(new SettingsBrowserMail(&m_settings, this)); - addSettingsPanel(new SettingsDownloads(&m_settings, this)); - addSettingsPanel(new SettingsFeedsMessages(&m_settings, this)); - m_ui.m_listSettings->setCurrentRow(0); + : QDialog(&parent), m_panels(QList()), m_settings(*qApp->settings()) { + m_ui.setupUi(this); + + // Set flags and attributes. + setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); + setWindowIcon(qApp->icons()->fromTheme(QSL("emblem-system"))); + m_btnApply = m_ui.m_buttonBox->button(QDialogButtonBox::Apply); + m_btnApply->setEnabled(false); + + // Establish needed connections. + connect(m_ui.m_buttonBox, &QDialogButtonBox::accepted, this, &FormSettings::saveSettings); + connect(m_ui.m_buttonBox, &QDialogButtonBox::rejected, this, &FormSettings::cancelSettings); + connect(m_btnApply, &QPushButton::clicked, this, &FormSettings::applySettings); + addSettingsPanel(new SettingsGeneral(&m_settings, this)); + addSettingsPanel(new SettingsDatabase(&m_settings, this)); + addSettingsPanel(new SettingsGui(&m_settings, this)); + addSettingsPanel(new SettingsLocalization(&m_settings, this)); + addSettingsPanel(new SettingsShortcuts(&m_settings, this)); + addSettingsPanel(new SettingsBrowserMail(&m_settings, this)); + addSettingsPanel(new SettingsDownloads(&m_settings, this)); + addSettingsPanel(new SettingsFeedsMessages(&m_settings, this)); + m_ui.m_listSettings->setCurrentRow(0); } FormSettings::~FormSettings() { - qDebug("Destroying FormSettings distance."); + qDebug("Destroying FormSettings distance."); } void FormSettings::saveSettings() { - applySettings(); - accept(); + applySettings(); + accept(); } void FormSettings::applySettings() { - // Save all settings. - m_settings.checkSettings(); - QStringList panels_for_restart; + // Save all settings. + m_settings.checkSettings(); + QStringList panels_for_restart; - foreach (SettingsPanel* panel, m_panels) { - if (panel->isDirty()) { - panel->saveSettings(); - } + foreach (SettingsPanel* panel, m_panels) { + if (panel->isDirty()) { + panel->saveSettings(); + } - if (panel->requiresRestart()) { - panels_for_restart.append(panel->title().toLower()); - panel->setRequiresRestart(false); - } - } + if (panel->requiresRestart()) { + panels_for_restart.append(panel->title().toLower()); + panel->setRequiresRestart(false); + } + } - if (!panels_for_restart.isEmpty()) { - const QStringList changed_settings_description = panels_for_restart.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8(" • ")); - const QMessageBox::StandardButton clicked_button = MessageBox::show(this, - QMessageBox::Question, - tr("Critical settings were changed"), - tr("Some critical settings were changed and will be applied after the application gets restarted. " - "\n\nYou have to restart manually."), - tr("Do you want to restart now?"), - tr("Changed categories of settings:\n%1.").arg(changed_settings_description .join(QSL(",\n"))), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + if (!panels_for_restart.isEmpty()) { + const QStringList changed_settings_description = panels_for_restart.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8(" • ")); + const QMessageBox::StandardButton clicked_button = MessageBox::show(this, + QMessageBox::Question, + tr("Critical settings were changed"), + tr( + "Some critical settings were changed and will be applied after the application gets restarted. " + "\n\nYou have to restart manually."), + tr("Do you want to restart now?"), + tr("Changed categories of settings:\n%1.").arg( + changed_settings_description.join(QSL(",\n"))), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - if (clicked_button == QMessageBox::Yes) { - qApp->restart(); - } - } + if (clicked_button == QMessageBox::Yes) { + qApp->restart(); + } + } - m_btnApply->setEnabled(false); + m_btnApply->setEnabled(false); } void FormSettings::cancelSettings() { - QStringList changed_panels; + QStringList changed_panels; - foreach (SettingsPanel* panel, m_panels) { - if (panel->isDirty()) { - changed_panels.append(panel->title().toLower()); - } - } + foreach (SettingsPanel* panel, m_panels) { + if (panel->isDirty()) { + changed_panels.append(panel->title().toLower()); + } + } - if (changed_panels.isEmpty()) { - reject(); - } - else { - const QStringList changed_settings_description = changed_panels.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8(" • ")); + if (changed_panels.isEmpty()) { + reject(); + } + else { + const QStringList changed_settings_description = changed_panels.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8(" • ")); - if (MessageBox::show(this, - QMessageBox::Critical, - tr("Some settings are changed and will be lost"), - tr("Some settings were changed and by cancelling this dialog, you would lose these changes."), - tr("Do you really want to close this dialog without saving any settings?"), - tr("Changed categories of settings:\n%1.").arg(changed_settings_description .join(QSL(",\n"))), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == - QMessageBox::Yes) { - reject(); - } - } + if (MessageBox::show(this, + QMessageBox::Critical, + tr("Some settings are changed and will be lost"), + tr("Some settings were changed and by cancelling this dialog, you would lose these changes."), + tr("Do you really want to close this dialog without saving any settings?"), + tr("Changed categories of settings:\n%1.").arg(changed_settings_description.join(QSL(",\n"))), + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == + QMessageBox::Yes) { + reject(); + } + } } void FormSettings::addSettingsPanel(SettingsPanel* panel) { - m_ui.m_listSettings->addItem(panel->title()); - m_panels.append(panel); - m_ui.m_stackedSettings->addWidget(panel); - panel->loadSettings(); - connect(panel, &SettingsPanel::settingsChanged, [this]() { - m_btnApply->setEnabled(true); - }); + m_ui.m_listSettings->addItem(panel->title()); + m_panels.append(panel); + m_ui.m_stackedSettings->addWidget(panel); + panel->loadSettings(); + connect(panel, &SettingsPanel::settingsChanged, [this]() { + m_btnApply->setEnabled(true); + }); } diff --git a/src/gui/dialogs/formsettings.h b/src/gui/dialogs/formsettings.h index fb37355b1..f489fd30c 100755 --- a/src/gui/dialogs/formsettings.h +++ b/src/gui/dialogs/formsettings.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,32 +23,33 @@ #include "ui_formsettings.h" - class Settings; class SettingsPanel; class FormSettings : public QDialog { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit FormSettings(QWidget& parent); - virtual ~FormSettings(); + public: - private slots: - // Saves settings into global configuration. - void saveSettings(); - void applySettings(); - void cancelSettings(); + // Constructors and destructors. + explicit FormSettings(QWidget& parent); + virtual ~FormSettings(); - private: - void addSettingsPanel(SettingsPanel* panel); + private slots: - Ui::FormSettings m_ui; - QPushButton* m_btnApply; + // Saves settings into global configuration. + void saveSettings(); + void applySettings(); + void cancelSettings(); - QList m_panels; - Settings& m_settings; + private: + void addSettingsPanel(SettingsPanel* panel); + + Ui::FormSettings m_ui; + QPushButton* m_btnApply; + + QList m_panels; + Settings& m_settings; }; #endif // FORMSETTINGS_H diff --git a/src/gui/dialogs/formupdate.cpp b/src/gui/dialogs/formupdate.cpp index cae0d109b..187ebe819 100755 --- a/src/gui/dialogs/formupdate.cpp +++ b/src/gui/dialogs/formupdate.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,13 +19,13 @@ #include "gui/dialogs/formupdate.h" #include "definitions/definitions.h" +#include "gui/guiutilities.h" +#include "gui/messagebox.h" #include "miscellaneous/iconfactory.h" #include "miscellaneous/iofactory.h" +#include "network-web/downloader.h" #include "network-web/networkfactory.h" #include "network-web/webfactory.h" -#include "network-web/downloader.h" -#include "gui/messagebox.h" -#include "gui/guiutilities.h" #include @@ -32,216 +33,218 @@ #include #endif - FormUpdate::FormUpdate(QWidget* parent) - : QDialog(parent) { - m_ui.setupUi(this); - m_ui.m_lblCurrentRelease->setText(APP_VERSION); - m_ui.m_tabInfo->removeTab(1); - m_ui.m_buttonBox->setEnabled(false); - // Set flags and attributes. - GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("help-about"))); - connect(&m_downloader, &Downloader::progress, this, &FormUpdate::updateProgress); - connect(&m_downloader, &Downloader::completed, this, &FormUpdate::updateCompleted); + : QDialog(parent) { + m_ui.setupUi(this); + m_ui.m_lblCurrentRelease->setText(APP_VERSION); + m_ui.m_tabInfo->removeTab(1); + m_ui.m_buttonBox->setEnabled(false); - if (isSelfUpdateSupported()) { - m_btnUpdate = m_ui.m_buttonBox->addButton(tr("Download selected update"), QDialogButtonBox::ActionRole); - m_btnUpdate->setToolTip(tr("Download new installation files.")); - } - else { - m_btnUpdate = m_ui.m_buttonBox->addButton(tr("Go to application website"), QDialogButtonBox::ActionRole); - m_btnUpdate->setToolTip(tr("Go to application website to get update packages manually.")); - } + // Set flags and attributes. + GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("help-about"))); + connect(&m_downloader, &Downloader::progress, this, &FormUpdate::updateProgress); + connect(&m_downloader, &Downloader::completed, this, &FormUpdate::updateCompleted); - m_btnUpdate->setVisible(false); - connect(m_btnUpdate, &QPushButton::clicked, this, &FormUpdate::startUpdate); - checkForUpdates(); + if (isSelfUpdateSupported()) { + m_btnUpdate = m_ui.m_buttonBox->addButton(tr("Download selected update"), QDialogButtonBox::ActionRole); + m_btnUpdate->setToolTip(tr("Download new installation files.")); + } + else { + m_btnUpdate = m_ui.m_buttonBox->addButton(tr("Go to application website"), QDialogButtonBox::ActionRole); + m_btnUpdate->setToolTip(tr("Go to application website to get update packages manually.")); + } + + m_btnUpdate->setVisible(false); + connect(m_btnUpdate, &QPushButton::clicked, this, &FormUpdate::startUpdate); + checkForUpdates(); } -FormUpdate::~FormUpdate() { -} +FormUpdate::~FormUpdate() {} bool FormUpdate::isSelfUpdateSupported() const { #if defined(Q_OS_WIN) || defined(Q_OS_MAC) - return true; + return true; #else - return false; + return false; #endif } void FormUpdate::checkForUpdates() { - connect(qApp->system(), &SystemFactory::updatesChecked, [this](QPair, QNetworkReply::NetworkError> update) { - m_ui.m_buttonBox->setEnabled(true); - disconnect(qApp->system(), &SystemFactory::updatesChecked, nullptr, nullptr); + connect(qApp->system(), &SystemFactory::updatesChecked, [this](QPair, QNetworkReply::NetworkError> update) { + m_ui.m_buttonBox->setEnabled(true); + disconnect(qApp->system(), &SystemFactory::updatesChecked, nullptr, nullptr); - if (update.second != QNetworkReply::NoError) { - m_updateInfo = UpdateInfo(); - m_ui.m_tabInfo->setEnabled(false); - //: Unknown release. - m_ui.m_lblAvailableRelease->setText(tr("unknown")); - m_ui.m_txtChanges->clear(); - m_ui.m_lblStatus->setStatus(WidgetWithStatus::Error, - tr("Error: '%1'.").arg(NetworkFactory::networkErrorText(update.second)), - tr("List with updates was not\ndownloaded successfully.")); - } - else { - const bool self_update_supported = isSelfUpdateSupported(); - m_updateInfo = update.first.at(0); - m_ui.m_tabInfo->setEnabled(true); - m_ui.m_lblAvailableRelease->setText(m_updateInfo.m_availableVersion); - m_ui.m_txtChanges->setText(m_updateInfo.m_changes); + if (update.second != QNetworkReply::NoError) { + m_updateInfo = UpdateInfo(); + m_ui.m_tabInfo->setEnabled(false); - if (SystemFactory::isVersionNewer(m_updateInfo.m_availableVersion, APP_VERSION)) { - m_btnUpdate->setVisible(true); - m_ui.m_lblStatus->setStatus(WidgetWithStatus::Ok, - tr("New release available."), - tr("This is new version which can be\ndownloaded.")); + //: Unknown release. + m_ui.m_lblAvailableRelease->setText(tr("unknown")); + m_ui.m_txtChanges->clear(); + m_ui.m_lblStatus->setStatus(WidgetWithStatus::Error, + tr("Error: '%1'.").arg(NetworkFactory::networkErrorText(update.second)), + tr("List with updates was not\ndownloaded successfully.")); + } + else { + const bool self_update_supported = isSelfUpdateSupported(); + m_updateInfo = update.first.at(0); + m_ui.m_tabInfo->setEnabled(true); + m_ui.m_lblAvailableRelease->setText(m_updateInfo.m_availableVersion); + m_ui.m_txtChanges->setText(m_updateInfo.m_changes); - if (self_update_supported) { - loadAvailableFiles(); - } - } - else { - m_ui.m_lblStatus->setStatus(WidgetWithStatus::Warning, - tr("No new release available."), - tr("This release is not newer than\ncurrently installed one.")); - } - } - }); - qApp->system()->checkForUpdates(); + if (SystemFactory::isVersionNewer(m_updateInfo.m_availableVersion, APP_VERSION)) { + m_btnUpdate->setVisible(true); + m_ui.m_lblStatus->setStatus(WidgetWithStatus::Ok, + tr("New release available."), + tr("This is new version which can be\ndownloaded.")); + + if (self_update_supported) { + loadAvailableFiles(); + } + } + else { + m_ui.m_lblStatus->setStatus(WidgetWithStatus::Warning, + tr("No new release available."), + tr("This release is not newer than\ncurrently installed one.")); + } + } + }); + qApp->system()->checkForUpdates(); } void FormUpdate::updateProgress(qint64 bytes_received, qint64 bytes_total) { - if (bytes_received - m_lastDownloadedBytes > 500000 || m_lastDownloadedBytes == 0) { - m_ui.m_lblStatus->setStatus(WidgetWithStatus::Information, - tr("Downloaded %1% (update size is %2 kB).").arg(QString::number(bytes_total == 0 ? 0 : (bytes_received * 100.0) / bytes_total, - 'f', - 2), - QString::number(bytes_total / 1000, - 'f', - 2)), - tr("Downloading update...")); - m_ui.m_lblStatus->repaint(); - m_lastDownloadedBytes = bytes_received; - } + if (bytes_received - m_lastDownloadedBytes > 500000 || m_lastDownloadedBytes == 0) { + m_ui.m_lblStatus->setStatus(WidgetWithStatus::Information, + tr("Downloaded %1% (update size is %2 kB).").arg(QString::number(bytes_total == + 0 ? 0 : (bytes_received * 100.0) / + bytes_total, + 'f', + 2), + QString::number(bytes_total / 1000, + 'f', + 2)), + tr("Downloading update...")); + m_ui.m_lblStatus->repaint(); + m_lastDownloadedBytes = bytes_received; + } } void FormUpdate::saveUpdateFile(const QByteArray& file_contents) { - const QString url_file = m_ui.m_listFiles->currentItem()->data(Qt::UserRole).toString(); + const QString url_file = m_ui.m_listFiles->currentItem()->data(Qt::UserRole).toString(); const QString temp_directory = qApp->tempFolder(); - if (!temp_directory.isEmpty()) { - const QString output_file_name = url_file.mid(url_file.lastIndexOf('/') + 1); - QFile output_file(temp_directory + QDir::separator() + output_file_name); + if (!temp_directory.isEmpty()) { + const QString output_file_name = url_file.mid(url_file.lastIndexOf('/') + 1); + QFile output_file(temp_directory + QDir::separator() + output_file_name); - if (output_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - qDebug("Storing update file to temporary location '%s'.", - qPrintable(QDir::toNativeSeparators(output_file.fileName()))); - output_file.write(file_contents); - output_file.flush(); - output_file.close(); - qDebug("Update file contents was successfuly saved."); - m_updateFilePath = output_file.fileName(); - m_readyToInstall = true; - } - else { - qDebug("Cannot save downloaded update file because target temporary file '%s' cannot be " - "opened for writing.", qPrintable(output_file_name)); - } - } - else { - qDebug("Cannot save downloaded update file because no TEMP directory is available."); - } + if (output_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + qDebug("Storing update file to temporary location '%s'.", + qPrintable(QDir::toNativeSeparators(output_file.fileName()))); + output_file.write(file_contents); + output_file.flush(); + output_file.close(); + qDebug("Update file contents was successfuly saved."); + m_updateFilePath = output_file.fileName(); + m_readyToInstall = true; + } + else { + qDebug("Cannot save downloaded update file because target temporary file '%s' cannot be " + "opened for writing.", qPrintable(output_file_name)); + } + } + else { + qDebug("Cannot save downloaded update file because no TEMP directory is available."); + } } void FormUpdate::loadAvailableFiles() { - m_ui.m_listFiles->clear(); + m_ui.m_listFiles->clear(); - foreach (const UpdateUrl& url, m_updateInfo.m_urls) { - QListWidgetItem* item = new QListWidgetItem(url.m_name + tr(" (size ") + url.m_size + QSL(")")); - item->setData(Qt::UserRole, url.m_fileUrl); - item->setToolTip(url.m_fileUrl); - m_ui.m_listFiles->addItem(item); - } + foreach (const UpdateUrl& url, m_updateInfo.m_urls) { + QListWidgetItem* item = new QListWidgetItem(url.m_name + tr(" (size ") + url.m_size + QSL(")")); - if (m_ui.m_listFiles->count() > 0) { - m_ui.m_listFiles->setCurrentRow(0); - } - else { - m_btnUpdate->setEnabled(false); - } + item->setData(Qt::UserRole, url.m_fileUrl); + item->setToolTip(url.m_fileUrl); + m_ui.m_listFiles->addItem(item); + } - m_ui.m_tabInfo->addTab(m_ui.tabFiles, tr("Available update files")); - m_ui.m_tabInfo->setCurrentIndex(1); + if (m_ui.m_listFiles->count() > 0) { + m_ui.m_listFiles->setCurrentRow(0); + } + else { + m_btnUpdate->setEnabled(false); + } + + m_ui.m_tabInfo->addTab(m_ui.tabFiles, tr("Available update files")); + m_ui.m_tabInfo->setCurrentIndex(1); } void FormUpdate::updateCompleted(QNetworkReply::NetworkError status, QByteArray contents) { - qDebug("Download of application update file was completed with code '%d'.", status); + qDebug("Download of application update file was completed with code '%d'.", status); - switch (status) { - case QNetworkReply::NoError: - saveUpdateFile(contents); - m_ui.m_lblStatus->setStatus(WidgetWithStatus::Ok, tr("Downloaded successfully"), - tr("Package was downloaded successfully.\nYou can install it now.")); - m_btnUpdate->setText(tr("Install")); - m_btnUpdate->setEnabled(true); - break; + switch (status) { + case QNetworkReply::NoError: + saveUpdateFile(contents); + m_ui.m_lblStatus->setStatus(WidgetWithStatus::Ok, tr("Downloaded successfully"), + tr("Package was downloaded successfully.\nYou can install it now.")); + m_btnUpdate->setText(tr("Install")); + m_btnUpdate->setEnabled(true); + break; - default: - m_ui.m_lblStatus->setStatus(WidgetWithStatus::Error, tr("Error occured"), tr("Error occured during downloading of the package.")); - m_btnUpdate->setText(tr("Error occured")); - break; - } + default: + m_ui.m_lblStatus->setStatus(WidgetWithStatus::Error, tr("Error occured"), tr("Error occured during downloading of the package.")); + m_btnUpdate->setText(tr("Error occured")); + break; + } } void FormUpdate::startUpdate() { - QString url_file; - const bool update_for_this_system = isSelfUpdateSupported(); + QString url_file; + const bool update_for_this_system = isSelfUpdateSupported(); - if (update_for_this_system && m_ui.m_listFiles->currentItem() != nullptr) { - url_file = m_ui.m_listFiles->currentItem()->data(Qt::UserRole).toString(); - m_ui.m_listFiles->setEnabled(false); - } - else { - url_file = APP_URL; - } + if (update_for_this_system && m_ui.m_listFiles->currentItem() != nullptr) { + url_file = m_ui.m_listFiles->currentItem()->data(Qt::UserRole).toString(); + m_ui.m_listFiles->setEnabled(false); + } + else { + url_file = APP_URL; + } - if (m_readyToInstall) { - close(); - qDebug("Preparing to launch external installer '%s'.", qPrintable(QDir::toNativeSeparators(m_updateFilePath))); + if (m_readyToInstall) { + close(); + qDebug("Preparing to launch external installer '%s'.", qPrintable(QDir::toNativeSeparators(m_updateFilePath))); #if defined(Q_OS_WIN) - HINSTANCE exec_result = ShellExecute(nullptr, - nullptr, - reinterpret_cast(QDir::toNativeSeparators(m_updateFilePath).utf16()), - nullptr, - nullptr, - SW_NORMAL); - - if (exec_result <= (HINSTANCE)32) { - qDebug("External updater was not launched due to error."); - qApp->showGuiMessage(tr("Cannot update application"), - tr("Cannot launch external updater. Update application manually."), - QSystemTrayIcon::Warning, this); - } - else { - qApp->quit(); - } + HINSTANCE exec_result = ShellExecute(nullptr, + nullptr, + reinterpret_cast(QDir::toNativeSeparators(m_updateFilePath).utf16()), + nullptr, + nullptr, + SW_NORMAL); + if (exec_result <= (HINSTANCE)32) { + qDebug("External updater was not launched due to error."); + qApp->showGuiMessage(tr("Cannot update application"), + tr("Cannot launch external updater. Update application manually."), + QSystemTrayIcon::Warning, this); + } + else { + qApp->quit(); + } #endif - } - else if (update_for_this_system) { - updateProgress(0, 100); - m_btnUpdate->setText(tr("Downloading update...")); - m_btnUpdate->setEnabled(false); - m_downloader.downloadFile(url_file); - } - else { - // Self-update and package are not available. - if (!qApp->web()->openUrlInExternalBrowser(url_file)) { - qApp->showGuiMessage(tr("Cannot update application"), - tr("Cannot navigate to installation file. Check new installation downloads manually on project website."), - QSystemTrayIcon::Warning, - this, true); - } - } + } + else if (update_for_this_system) { + updateProgress(0, 100); + m_btnUpdate->setText(tr("Downloading update...")); + m_btnUpdate->setEnabled(false); + m_downloader.downloadFile(url_file); + } + else { + // Self-update and package are not available. + if (!qApp->web()->openUrlInExternalBrowser(url_file)) { + qApp->showGuiMessage(tr("Cannot update application"), + tr("Cannot navigate to installation file. Check new installation downloads manually on project website."), + QSystemTrayIcon::Warning, + this, true); + } + } } diff --git a/src/gui/dialogs/formupdate.h b/src/gui/dialogs/formupdate.h index 178c0a2cc..d4f99547e 100755 --- a/src/gui/dialogs/formupdate.h +++ b/src/gui/dialogs/formupdate.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -25,42 +26,42 @@ #include "miscellaneous/systemfactory.h" #include "network-web/downloader.h" -#include #include - +#include class FormUpdate : public QDialog { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit FormUpdate(QWidget* parent); - virtual ~FormUpdate(); + public: - // Returns true if application can self-update - // on current platform. - bool isSelfUpdateSupported() const; + // Constructors and destructors. + explicit FormUpdate(QWidget* parent); + virtual ~FormUpdate(); - private slots: - // Check for updates and interprets the results. - void checkForUpdates(); - void startUpdate(); + // Returns true if application can self-update + // on current platform. + bool isSelfUpdateSupported() const; - void updateProgress(qint64 bytes_received, qint64 bytes_total); - void updateCompleted(QNetworkReply::NetworkError status, QByteArray contents); - void saveUpdateFile(const QByteArray& file_contents); + private slots: - private: - void loadAvailableFiles(); + // Check for updates and interprets the results. + void checkForUpdates(); + void startUpdate(); - Ui::FormUpdate m_ui; - QPushButton* m_btnUpdate; + void updateProgress(qint64 bytes_received, qint64 bytes_total); + void updateCompleted(QNetworkReply::NetworkError status, QByteArray contents); + void saveUpdateFile(const QByteArray& file_contents); - Downloader m_downloader; - QString m_updateFilePath; - UpdateInfo m_updateInfo; - bool m_readyToInstall = false; - qint64 m_lastDownloadedBytes = 0; + private: + void loadAvailableFiles(); + + Ui::FormUpdate m_ui; + QPushButton* m_btnUpdate; + Downloader m_downloader; + QString m_updateFilePath; + UpdateInfo m_updateInfo; + bool m_readyToInstall = false; + qint64 m_lastDownloadedBytes = 0; }; #endif // FORMUPDATE_H diff --git a/src/gui/discoverfeedsbutton.cpp b/src/gui/discoverfeedsbutton.cpp index e40d516d3..a0bbde7b3 100755 --- a/src/gui/discoverfeedsbutton.cpp +++ b/src/gui/discoverfeedsbutton.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,76 +18,75 @@ #include "gui/discoverfeedsbutton.h" -#include "miscellaneous/application.h" -#include "miscellaneous/iconfactory.h" -#include "miscellaneous/feedreader.h" +#include "core/feedsmodel.h" #include "gui/dialogs/formmain.h" -#include "gui/tabwidget.h" #include "gui/feedmessageviewer.h" #include "gui/feedsview.h" -#include "core/feedsmodel.h" +#include "gui/tabwidget.h" +#include "miscellaneous/application.h" +#include "miscellaneous/feedreader.h" +#include "miscellaneous/iconfactory.h" #include "services/abstract/serviceroot.h" #include - DiscoverFeedsButton::DiscoverFeedsButton(QWidget* parent) : QToolButton(parent), m_addresses(QStringList()) { - setEnabled(false); - setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml"))); - setPopupMode(QToolButton::InstantPopup); + setEnabled(false); + setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml"))); + setPopupMode(QToolButton::InstantPopup); } -DiscoverFeedsButton::~DiscoverFeedsButton() { -} +DiscoverFeedsButton::~DiscoverFeedsButton() {} void DiscoverFeedsButton::clearFeedAddresses() { - setFeedAddresses(QStringList()); + setFeedAddresses(QStringList()); } void DiscoverFeedsButton::setFeedAddresses(const QStringList& addresses) { - setEnabled(!addresses.isEmpty()); - setToolTip(addresses.isEmpty() ? - tr("This website does not contain any feeds.") : - tr("Click me to add feeds from this website.\nThis website contains %n feed(s).", 0, addresses.size())); + setEnabled(!addresses.isEmpty()); + setToolTip(addresses.isEmpty() ? + tr("This website does not contain any feeds.") : + tr("Click me to add feeds from this website.\nThis website contains %n feed(s).", 0, addresses.size())); - if (menu() == nullptr) { - // Initialize the menu. - setMenu(new QMenu(this)); - connect(menu(), &QMenu::triggered, this, &DiscoverFeedsButton::linkTriggered); - connect(menu(), &QMenu::aboutToShow, this, &DiscoverFeedsButton::fillMenu); - } + if (menu() == nullptr) { + // Initialize the menu. + setMenu(new QMenu(this)); + connect(menu(), &QMenu::triggered, this, &DiscoverFeedsButton::linkTriggered); + connect(menu(), &QMenu::aboutToShow, this, &DiscoverFeedsButton::fillMenu); + } - menu()->hide(); - m_addresses = addresses; + menu()->hide(); + m_addresses = addresses; } void DiscoverFeedsButton::linkTriggered(QAction* action) { - const QString url = action->property("url").toString(); - ServiceRoot* root = static_cast(action->property("root").value()); + const QString url = action->property("url").toString(); + ServiceRoot* root = static_cast(action->property("root").value()); - if (root->supportsFeedAdding()) { - root->addNewFeed(url); - } - else { - qApp->showGuiMessage(tr("Not supported"), - tr("Given account does not support adding feeds."), - QSystemTrayIcon::Warning, - qApp->mainFormWidget(), true); - } + if (root->supportsFeedAdding()) { + root->addNewFeed(url); + } + else { + qApp->showGuiMessage(tr("Not supported"), + tr("Given account does not support adding feeds."), + QSystemTrayIcon::Warning, + qApp->mainFormWidget(), true); + } } void DiscoverFeedsButton::fillMenu() { - menu()->clear(); + menu()->clear(); - foreach (const ServiceRoot* root, qApp->feedReader()->feedsModel()->serviceRoots()) { - QMenu* root_menu = menu()->addMenu(root->icon(), root->title()); + foreach (const ServiceRoot* root, qApp->feedReader()->feedsModel()->serviceRoots()) { + QMenu* root_menu = menu()->addMenu(root->icon(), root->title()); - foreach (const QString& url, m_addresses) { - if (root->supportsFeedAdding()) { - QAction* url_action = root_menu->addAction(root->icon(), url); - url_action->setProperty("url", url); - url_action->setProperty("root", QVariant::fromValue((void*) root)); - } - } - } + foreach (const QString& url, m_addresses) { + if (root->supportsFeedAdding()) { + QAction* url_action = root_menu->addAction(root->icon(), url); + + url_action->setProperty("url", url); + url_action->setProperty("root", QVariant::fromValue((void*) root)); + } + } + } } diff --git a/src/gui/discoverfeedsbutton.h b/src/gui/discoverfeedsbutton.h index ab510106c..483c1b9b2 100755 --- a/src/gui/discoverfeedsbutton.h +++ b/src/gui/discoverfeedsbutton.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,26 +21,27 @@ #include - class DiscoverFeedsButton : public QToolButton { - Q_OBJECT + Q_OBJECT - public: - // Constructors. - explicit DiscoverFeedsButton(QWidget* parent = 0); - virtual ~DiscoverFeedsButton(); + public: - // Feed addresses manipulators. - void clearFeedAddresses(); - void setFeedAddresses(const QStringList& addresses); + // Constructors. + explicit DiscoverFeedsButton(QWidget* parent = 0); + virtual ~DiscoverFeedsButton(); - private slots: - // User chose any of addresses. - void linkTriggered(QAction* action); - void fillMenu(); + // Feed addresses manipulators. + void clearFeedAddresses(); + void setFeedAddresses(const QStringList& addresses); - private: - QStringList m_addresses; + private slots: + + // User chose any of addresses. + void linkTriggered(QAction* action); + void fillMenu(); + + private: + QStringList m_addresses; }; #endif // DISCOVERFEEDSBUTTON_H diff --git a/src/gui/edittableview.cpp b/src/gui/edittableview.cpp index 1a9b30cf6..93d17d0ab 100755 --- a/src/gui/edittableview.cpp +++ b/src/gui/edittableview.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,50 +20,49 @@ #include - -EditTableView::EditTableView(QWidget* parent) : QTableView(parent) { -} +EditTableView::EditTableView(QWidget* parent) : QTableView(parent) {} void EditTableView::keyPressEvent(QKeyEvent* event) { - if (model() && event->key() == Qt::Key_Delete) { - removeSelected(); - event->accept(); - } - else { - QAbstractItemView::keyPressEvent(event); - } + if (model() && event->key() == Qt::Key_Delete) { + removeSelected(); + event->accept(); + } + else { + QAbstractItemView::keyPressEvent(event); + } } void EditTableView::removeSelected() { - if (!model() || !selectionModel() || !selectionModel()->hasSelection()) { - return; - } + if (!model() || !selectionModel() || !selectionModel()->hasSelection()) { + return; + } - const QModelIndexList selected_rows = selectionModel()->selectedRows(); + const QModelIndexList selected_rows = selectionModel()->selectedRows(); - if (selected_rows.isEmpty()) { - return; - } + if (selected_rows.isEmpty()) { + return; + } - const int new_selected_row = selected_rows.at(0).row(); + const int new_selected_row = selected_rows.at(0).row(); - for (int i = selected_rows.count() - 1; i >= 0; i--) { - QModelIndex idx = selected_rows.at(i); - model()->removeRow(idx.row(), rootIndex()); - } + for (int i = selected_rows.count() - 1; i >= 0; i--) { + QModelIndex idx = selected_rows.at(i); - QModelIndex new_selected_index = model()->index(new_selected_row, 0, rootIndex()); + model()->removeRow(idx.row(), rootIndex()); + } - if (!new_selected_index.isValid()) { - new_selected_index = model()->index(new_selected_row - 1, 0, rootIndex()); - } + QModelIndex new_selected_index = model()->index(new_selected_row, 0, rootIndex()); - selectionModel()->select(new_selected_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); - setCurrentIndex(new_selected_index); + if (!new_selected_index.isValid()) { + new_selected_index = model()->index(new_selected_row - 1, 0, rootIndex()); + } + + selectionModel()->select(new_selected_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); + setCurrentIndex(new_selected_index); } void EditTableView::removeAll() { - if (model() != nullptr) { - model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex()); - } + if (model() != nullptr) { + model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex()); + } } diff --git a/src/gui/edittableview.h b/src/gui/edittableview.h index 9619aeebd..ff79ff59a 100755 --- a/src/gui/edittableview.h +++ b/src/gui/edittableview.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,19 +21,18 @@ #include - class EditTableView : public QTableView { - Q_OBJECT + Q_OBJECT - public: - explicit EditTableView(QWidget* parent = 0); + public: + explicit EditTableView(QWidget* parent = 0); - public slots: - void removeSelected(); - void removeAll(); + public slots: + void removeSelected(); + void removeAll(); - private: - void keyPressEvent(QKeyEvent* event); + private: + void keyPressEvent(QKeyEvent* event); }; #endif // EDITTABLEVIEW_H diff --git a/src/gui/feedstoolbar.cpp b/src/gui/feedstoolbar.cpp index 9d9c3314a..29a7b1231 100755 --- a/src/gui/feedstoolbar.cpp +++ b/src/gui/feedstoolbar.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,83 +19,85 @@ #include "gui/feedstoolbar.h" #include "miscellaneous/application.h" -#include "miscellaneous/settings.h" #include "miscellaneous/iconfactory.h" +#include "miscellaneous/settings.h" #include - FeedsToolBar::FeedsToolBar(const QString& title, QWidget* parent) : BaseToolBar(title, parent) { - // Update right margin of filter textbox. - QMargins margins = contentsMargins(); - margins.setRight(margins.right() + FILTER_RIGHT_MARGIN); - setContentsMargins(margins); + // Update right margin of filter textbox. + QMargins margins = contentsMargins(); + + margins.setRight(margins.right() + FILTER_RIGHT_MARGIN); + setContentsMargins(margins); } -FeedsToolBar::~FeedsToolBar() { -} +FeedsToolBar::~FeedsToolBar() {} QList FeedsToolBar::availableActions() const { - return qApp->userActions(); + return qApp->userActions(); } QList FeedsToolBar::changeableActions() const { - return actions(); + return actions(); } void FeedsToolBar::saveChangeableActions(const QStringList& actions) { - qApp->settings()->setValue(GROUP(GUI), GUI::FeedsToolbarActions, actions.join(QSL(","))); - loadSpecificActions(getSpecificActions(actions)); + qApp->settings()->setValue(GROUP(GUI), GUI::FeedsToolbarActions, actions.join(QSL(","))); + loadSpecificActions(getSpecificActions(actions)); } QList FeedsToolBar::getSpecificActions(const QStringList& actions) { - QList available_actions = availableActions(); - QList spec_actions; + QList available_actions = availableActions(); + QList spec_actions; - // Iterate action names and add respectable actions into the toolbar. - foreach (const QString& action_name, actions) { - QAction* matching_action = findMatchingAction(action_name, available_actions); + // Iterate action names and add respectable actions into the toolbar. + foreach (const QString& action_name, actions) { + QAction* matching_action = findMatchingAction(action_name, available_actions); - if (matching_action != nullptr) { - // Add existing standard action. - spec_actions.append(matching_action); - } - else if (action_name == SEPARATOR_ACTION_NAME) { - // Add new separator. - QAction* act = new QAction(this); - act->setSeparator(true); - spec_actions.append(act); - } - else if (action_name == SPACER_ACTION_NAME) { - // Add new spacer. - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - QWidgetAction* action = new QWidgetAction(this); - action->setDefaultWidget(spacer); - action->setIcon(qApp->icons()->fromTheme(QSL("system-search"))); - action->setProperty("type", SPACER_ACTION_NAME); - action->setProperty("name", tr("Toolbar spacer")); - spec_actions.append(action); - } - } + if (matching_action != nullptr) { + // Add existing standard action. + spec_actions.append(matching_action); + } + else if (action_name == SEPARATOR_ACTION_NAME) { + // Add new separator. + QAction* act = new QAction(this); - return spec_actions; + act->setSeparator(true); + spec_actions.append(act); + } + else if (action_name == SPACER_ACTION_NAME) { + // Add new spacer. + QWidget* spacer = new QWidget(this); + + spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + QWidgetAction* action = new QWidgetAction(this); + + action->setDefaultWidget(spacer); + action->setIcon(qApp->icons()->fromTheme(QSL("system-search"))); + action->setProperty("type", SPACER_ACTION_NAME); + action->setProperty("name", tr("Toolbar spacer")); + spec_actions.append(action); + } + } + + return spec_actions; } void FeedsToolBar::loadSpecificActions(const QList& actions) { - clear(); + clear(); - foreach (QAction* act, actions) { - addAction(act); - } + foreach (QAction* act, actions) { + addAction(act); + } } QStringList FeedsToolBar::defaultActions() const { - return QString(GUI::FeedsToolbarActionsDef).split(',', - QString::SkipEmptyParts); + return QString(GUI::FeedsToolbarActionsDef).split(',', + QString::SkipEmptyParts); } QStringList FeedsToolBar::savedActions() const { - return qApp->settings()->value(GROUP(GUI), SETTING(GUI::FeedsToolbarActions)).toString().split(',', - QString::SkipEmptyParts); + return qApp->settings()->value(GROUP(GUI), SETTING(GUI::FeedsToolbarActions)).toString().split(',', + QString::SkipEmptyParts); } diff --git a/src/gui/feedstoolbar.h b/src/gui/feedstoolbar.h index 7fa2766ff..2d536716a 100755 --- a/src/gui/feedstoolbar.h +++ b/src/gui/feedstoolbar.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,24 +21,24 @@ #include "gui/basetoolbar.h" - class FeedsToolBar : public BaseToolBar { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit FeedsToolBar(const QString& title, QWidget* parent = 0); - virtual ~FeedsToolBar(); + public: - QList availableActions() const; - QList changeableActions() const; - void saveChangeableActions(const QStringList& actions); + // Constructors and destructors. + explicit FeedsToolBar(const QString& title, QWidget* parent = 0); + virtual ~FeedsToolBar(); - QList getSpecificActions(const QStringList& actions); - void loadSpecificActions(const QList& actions); + QList availableActions() const; + QList changeableActions() const; + void saveChangeableActions(const QStringList& actions); - QStringList defaultActions() const; - QStringList savedActions() const; + QList getSpecificActions(const QStringList& actions); + void loadSpecificActions(const QList& actions); + + QStringList defaultActions() const; + QStringList savedActions() const; }; #endif // FEEDSTOOLBAR_H diff --git a/src/gui/feedsview.cpp b/src/gui/feedsview.cpp index 1a607f852..c93e83c66 100755 --- a/src/gui/feedsview.cpp +++ b/src/gui/feedsview.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,338 +18,344 @@ #include "gui/feedsview.h" -#include "definitions/definitions.h" #include "core/feedsmodel.h" #include "core/feedsproxymodel.h" -#include "services/abstract/rootitem.h" -#include "miscellaneous/systemfactory.h" -#include "miscellaneous/feedreader.h" -#include "miscellaneous/mutex.h" -#include "gui/systemtrayicon.h" +#include "definitions/definitions.h" +#include "gui/dialogs/formmain.h" #include "gui/messagebox.h" #include "gui/styleditemdelegatewithoutfocus.h" -#include "gui/dialogs/formmain.h" +#include "gui/systemtrayicon.h" +#include "miscellaneous/feedreader.h" +#include "miscellaneous/mutex.h" +#include "miscellaneous/systemfactory.h" #include "services/abstract/feed.h" +#include "services/abstract/rootitem.h" #include "services/abstract/serviceroot.h" +#include "services/standard/gui/formstandardcategorydetails.h" #include "services/standard/standardcategory.h" #include "services/standard/standardfeed.h" -#include "services/standard/gui/formstandardcategorydetails.h" -#include -#include #include -#include +#include +#include #include +#include #include - FeedsView::FeedsView(QWidget* parent) - : QTreeView(parent), - m_contextMenuCategories(nullptr), - m_contextMenuFeeds(nullptr), - m_contextMenuEmptySpace(nullptr), - m_contextMenuOtherItems(nullptr) { - setObjectName(QSL("FeedsView")); + : QTreeView(parent), + m_contextMenuCategories(nullptr), + m_contextMenuFeeds(nullptr), + m_contextMenuEmptySpace(nullptr), + m_contextMenuOtherItems(nullptr) { + setObjectName(QSL("FeedsView")); - // Allocate models. - m_sourceModel = qApp->feedReader()->feedsModel(); - m_proxyModel = qApp->feedReader()->feedsProxyModel(); + // Allocate models. + m_sourceModel = qApp->feedReader()->feedsModel(); + m_proxyModel = qApp->feedReader()->feedsProxyModel(); // Connections. - connect(m_sourceModel, &FeedsModel::requireItemValidationAfterDragDrop, this, &FeedsView::validateItemAfterDragDrop); - connect(m_sourceModel, &FeedsModel::itemExpandRequested, this, &FeedsView::onItemExpandRequested); - connect(m_sourceModel, &FeedsModel::itemExpandStateSaveRequested, this, &FeedsView::onItemExpandStateSaveRequested); - connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState); - connect(m_proxyModel, &FeedsProxyModel::expandAfterFilterIn, this, &FeedsView::expandItemDelayed); + connect(m_sourceModel, &FeedsModel::requireItemValidationAfterDragDrop, this, &FeedsView::validateItemAfterDragDrop); + connect(m_sourceModel, &FeedsModel::itemExpandRequested, this, &FeedsView::onItemExpandRequested); + connect(m_sourceModel, &FeedsModel::itemExpandStateSaveRequested, this, &FeedsView::onItemExpandStateSaveRequested); + connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState); + connect(m_proxyModel, &FeedsProxyModel::expandAfterFilterIn, this, &FeedsView::expandItemDelayed); setModel(m_proxyModel); - setupAppearance(); + setupAppearance(); } FeedsView::~FeedsView() { - qDebug("Destroying FeedsView instance."); + qDebug("Destroying FeedsView instance."); } void FeedsView::setSortingEnabled(bool enable) { - disconnect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState); - QTreeView::setSortingEnabled(enable); - connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState); + disconnect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState); + QTreeView::setSortingEnabled(enable); + connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState); } QList FeedsView::selectedFeeds() const { - const QModelIndex current_index = currentIndex(); + const QModelIndex current_index = currentIndex(); - if (current_index.isValid()) { - return m_sourceModel->feedsForIndex(m_proxyModel->mapToSource(current_index)); - } - else { - return QList(); - } + if (current_index.isValid()) { + return m_sourceModel->feedsForIndex(m_proxyModel->mapToSource(current_index)); + } + else { + return QList(); + } } RootItem* FeedsView::selectedItem() const { - const QModelIndexList selected_rows = selectionModel()->selectedRows(); + const QModelIndexList selected_rows = selectionModel()->selectedRows(); - if (selected_rows.isEmpty()) { - return nullptr; - } - else { - RootItem* selected_item = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(selected_rows.at(0))); - return selected_item == m_sourceModel->rootItem() ? nullptr : selected_item; - } + if (selected_rows.isEmpty()) { + return nullptr; + } + else { + RootItem* selected_item = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(selected_rows.at(0))); + + return selected_item == m_sourceModel->rootItem() ? nullptr : selected_item; + } } void FeedsView::onItemExpandStateSaveRequested(RootItem* item) { - saveExpandStates(item); + saveExpandStates(item); } void FeedsView::saveAllExpandStates() { - saveExpandStates(sourceModel()->rootItem()); + saveExpandStates(sourceModel()->rootItem()); } void FeedsView::saveExpandStates(RootItem* item) { - Settings* settings = qApp->settings(); - QList items = item->getSubTree(RootItemKind::Category | RootItemKind::ServiceRoot); + Settings* settings = qApp->settings(); - // Iterate all categories and save their expand statuses. - foreach (const RootItem* item, items) { - const QString setting_name = item->hashCode(); - QModelIndex source_index = sourceModel()->indexForItem(item); - QModelIndex visible_index = model()->mapFromSource(source_index); - settings->setValue(GROUP(CategoriesExpandStates), - setting_name, - isExpanded(visible_index)); - } + QList items = item->getSubTree(RootItemKind::Category | RootItemKind::ServiceRoot); + + // Iterate all categories and save their expand statuses. + foreach (const RootItem* item, items) { + const QString setting_name = item->hashCode(); + QModelIndex source_index = sourceModel()->indexForItem(item); + QModelIndex visible_index = model()->mapFromSource(source_index); + + settings->setValue(GROUP(CategoriesExpandStates), + setting_name, + isExpanded(visible_index)); + } } void FeedsView::loadAllExpandStates() { - const Settings* settings = qApp->settings(); - QList expandable_items; - expandable_items.append(sourceModel()->rootItem()->getSubTree(RootItemKind::Category | RootItemKind::ServiceRoot)); + const Settings* settings = qApp->settings(); - // Iterate all categories and save their expand statuses. - foreach (const RootItem* item, expandable_items) { - const QString setting_name = item->hashCode(); - setExpanded(model()->mapFromSource(sourceModel()->indexForItem(item)), - settings->value(GROUP(CategoriesExpandStates), setting_name, item->childCount() > 0).toBool()); - } + QList expandable_items; + expandable_items.append(sourceModel()->rootItem()->getSubTree(RootItemKind::Category | RootItemKind::ServiceRoot)); - sortByColumn(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortColumnFeeds)).toInt(), - static_cast(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortOrderFeeds)).toInt())); + // Iterate all categories and save their expand statuses. + foreach (const RootItem* item, expandable_items) { + const QString setting_name = item->hashCode(); + + setExpanded(model()->mapFromSource(sourceModel()->indexForItem(item)), + settings->value(GROUP(CategoriesExpandStates), setting_name, item->childCount() > 0).toBool()); + } + + sortByColumn(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortColumnFeeds)).toInt(), + static_cast(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortOrderFeeds)).toInt())); } void FeedsView::sortByColumn(int column, Qt::SortOrder order) { - const int old_column = header()->sortIndicatorSection(); - const Qt::SortOrder old_order = header()->sortIndicatorOrder(); + const int old_column = header()->sortIndicatorSection(); + const Qt::SortOrder old_order = header()->sortIndicatorOrder(); - if (column == old_column && order == old_order) { - m_proxyModel->sort(column, order); - } - else { - QTreeView::sortByColumn(column, order); - } + if (column == old_column && order == old_order) { + m_proxyModel->sort(column, order); + } + else { + QTreeView::sortByColumn(column, order); + } } void FeedsView::addFeedIntoSelectedAccount() { - const RootItem* selected = selectedItem(); + const RootItem* selected = selectedItem(); - if (selected != nullptr) { - ServiceRoot* root = selected->getParentServiceRoot(); + if (selected != nullptr) { + ServiceRoot* root = selected->getParentServiceRoot(); - if (root->supportsFeedAdding()) { - root->addNewFeed(); - } - else { - qApp->showGuiMessage(tr("Not supported"), - tr("Selected account does not support adding of new feeds."), - QSystemTrayIcon::Warning, - qApp->mainFormWidget(), true); - } - } + if (root->supportsFeedAdding()) { + root->addNewFeed(); + } + else { + qApp->showGuiMessage(tr("Not supported"), + tr("Selected account does not support adding of new feeds."), + QSystemTrayIcon::Warning, + qApp->mainFormWidget(), true); + } + } } void FeedsView::addCategoryIntoSelectedAccount() { - const RootItem* selected = selectedItem(); + const RootItem* selected = selectedItem(); - if (selected != nullptr) { - ServiceRoot* root = selected->getParentServiceRoot(); + if (selected != nullptr) { + ServiceRoot* root = selected->getParentServiceRoot(); - if (root->supportsCategoryAdding()) { - root->addNewCategory(); - } - else { - qApp->showGuiMessage(tr("Not supported"), - tr("Selected account does not support adding of new categories."), - QSystemTrayIcon::Warning, - qApp->mainFormWidget(), true); - } - } + if (root->supportsCategoryAdding()) { + root->addNewCategory(); + } + else { + qApp->showGuiMessage(tr("Not supported"), + tr("Selected account does not support adding of new categories."), + QSystemTrayIcon::Warning, + qApp->mainFormWidget(), true); + } + } } void FeedsView::expandCollapseCurrentItem() { - if (selectionModel()->selectedRows().size() == 1) { - QModelIndex index = selectionModel()->selectedRows().at(0); + if (selectionModel()->selectedRows().size() == 1) { + QModelIndex index = selectionModel()->selectedRows().at(0); - if (!index.child(0, 0).isValid() && index.parent().isValid()) { - setCurrentIndex(index.parent()); - index = index.parent(); - } + if (!index.child(0, 0).isValid() && index.parent().isValid()) { + setCurrentIndex(index.parent()); + index = index.parent(); + } - isExpanded(index) ? collapse(index) : expand(index); - } + isExpanded(index) ? collapse(index) : expand(index); + } } void FeedsView::updateSelectedItems() { - qApp->feedReader()->updateFeeds(selectedFeeds()); + qApp->feedReader()->updateFeeds(selectedFeeds()); } void FeedsView::clearSelectedFeeds() { - m_sourceModel->markItemCleared(selectedItem(), false); + m_sourceModel->markItemCleared(selectedItem(), false); } void FeedsView::clearAllFeeds() { - m_sourceModel->markItemCleared(m_sourceModel->rootItem(), false); + m_sourceModel->markItemCleared(m_sourceModel->rootItem(), false); } void FeedsView::editSelectedItem() { - if (!qApp->feedUpdateLock()->tryLock()) { - // Lock was not obtained because - // it is used probably by feed updater or application - // is quitting. - qApp->showGuiMessage(tr("Cannot edit item"), - tr("Selected item cannot be edited because another critical operation is ongoing."), - QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - // Thus, cannot delete and quit the method. - return; - } + if (!qApp->feedUpdateLock()->tryLock()) { + // Lock was not obtained because + // it is used probably by feed updater or application + // is quitting. + qApp->showGuiMessage(tr("Cannot edit item"), + tr("Selected item cannot be edited because another critical operation is ongoing."), + QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - if (selectedItem()->canBeEdited()) { - selectedItem()->editViaGui(); - } - else { - qApp->showGuiMessage(tr("Cannot edit item"), - tr("Selected item cannot be edited, this is not (yet?) supported."), - QSystemTrayIcon::Warning, - qApp->mainFormWidget(), - true); - } + // Thus, cannot delete and quit the method. + return; + } - // Changes are done, unlock the update master lock. - qApp->feedUpdateLock()->unlock(); + if (selectedItem()->canBeEdited()) { + selectedItem()->editViaGui(); + } + else { + qApp->showGuiMessage(tr("Cannot edit item"), + tr("Selected item cannot be edited, this is not (yet?) supported."), + QSystemTrayIcon::Warning, + qApp->mainFormWidget(), + true); + } + + // Changes are done, unlock the update master lock. + qApp->feedUpdateLock()->unlock(); } void FeedsView::deleteSelectedItem() { - if (!qApp->feedUpdateLock()->tryLock()) { - // Lock was not obtained because - // it is used probably by feed updater or application - // is quitting. - qApp->showGuiMessage(tr("Cannot delete item"), - tr("Selected item cannot be deleted because another critical operation is ongoing."), - QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - // Thus, cannot delete and quit the method. - return; - } + if (!qApp->feedUpdateLock()->tryLock()) { + // Lock was not obtained because + // it is used probably by feed updater or application + // is quitting. + qApp->showGuiMessage(tr("Cannot delete item"), + tr("Selected item cannot be deleted because another critical operation is ongoing."), + QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - if (!currentIndex().isValid()) { - // Changes are done, unlock the update master lock and exit. - qApp->feedUpdateLock()->unlock(); - return; - } + // Thus, cannot delete and quit the method. + return; + } - RootItem* selected_item = selectedItem(); + if (!currentIndex().isValid()) { + // Changes are done, unlock the update master lock and exit. + qApp->feedUpdateLock()->unlock(); + return; + } - if (selected_item != nullptr) { - if (selected_item->canBeDeleted()) { - // Ask user first. - if (MessageBox::show(qApp->mainFormWidget(), - QMessageBox::Question, - tr("Deleting \"%1\"").arg(selected_item->title()), - tr("You are about to completely delete item \"%1\".").arg(selected_item->title()), - tr("Are you sure?"), - QString(), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::No) { - // User refused. - qApp->feedUpdateLock()->unlock(); - return; - } + RootItem* selected_item = selectedItem(); - // We have deleteable item selected, remove it via GUI. - if (!selected_item->deleteViaGui()) { - qApp->showGuiMessage(tr("Cannot delete \"%1\"").arg(selected_item->title()), - tr("This item cannot be deleted because something critically failed. Submit bug report."), - QSystemTrayIcon::Critical, - qApp->mainFormWidget(), - true); - } - } - else { - qApp->showGuiMessage(tr("Cannot delete \"%1\"").arg(selected_item->title()), - tr("This item cannot be deleted, because it does not support it\nor this functionality is not implemented yet."), - QSystemTrayIcon::Critical, - qApp->mainFormWidget(), - true); - } - } + if (selected_item != nullptr) { + if (selected_item->canBeDeleted()) { + // Ask user first. + if (MessageBox::show(qApp->mainFormWidget(), + QMessageBox::Question, + tr("Deleting \"%1\"").arg(selected_item->title()), + tr("You are about to completely delete item \"%1\".").arg(selected_item->title()), + tr("Are you sure?"), + QString(), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::No) { + // User refused. + qApp->feedUpdateLock()->unlock(); + return; + } - // Changes are done, unlock the update master lock. - qApp->feedUpdateLock()->unlock(); + // We have deleteable item selected, remove it via GUI. + if (!selected_item->deleteViaGui()) { + qApp->showGuiMessage(tr("Cannot delete \"%1\"").arg(selected_item->title()), + tr("This item cannot be deleted because something critically failed. Submit bug report."), + QSystemTrayIcon::Critical, + qApp->mainFormWidget(), + true); + } + } + else { + qApp->showGuiMessage(tr("Cannot delete \"%1\"").arg(selected_item->title()), + tr("This item cannot be deleted, because it does not support it\nor this functionality is not implemented yet."), + QSystemTrayIcon::Critical, + qApp->mainFormWidget(), + true); + } + } + + // Changes are done, unlock the update master lock. + qApp->feedUpdateLock()->unlock(); } void FeedsView::markSelectedItemReadStatus(RootItem::ReadStatus read) { - m_sourceModel->markItemRead(selectedItem(), read); + m_sourceModel->markItemRead(selectedItem(), read); } void FeedsView::markSelectedItemRead() { - markSelectedItemReadStatus(RootItem::Read); + markSelectedItemReadStatus(RootItem::Read); } void FeedsView::markSelectedItemUnread() { - markSelectedItemReadStatus(RootItem::Unread); + markSelectedItemReadStatus(RootItem::Unread); } void FeedsView::markAllItemsReadStatus(RootItem::ReadStatus read) { - m_sourceModel->markItemRead(m_sourceModel->rootItem(), read); + m_sourceModel->markItemRead(m_sourceModel->rootItem(), read); } void FeedsView::markAllItemsRead() { - markAllItemsReadStatus(RootItem::Read); + markAllItemsReadStatus(RootItem::Read); } void FeedsView::openSelectedItemsInNewspaperMode() { - RootItem* selected_item = selectedItem(); - const QList messages = m_sourceModel->messagesForItem(selected_item); + RootItem* selected_item = selectedItem(); + const QList messages = m_sourceModel->messagesForItem(selected_item); - if (!messages.isEmpty()) { - emit openMessagesInNewspaperView(selected_item, messages); - } + if (!messages.isEmpty()) { + emit openMessagesInNewspaperView(selected_item, messages); + } } void FeedsView::selectNextItem() { - const QModelIndex& curr_idx = currentIndex(); + const QModelIndex& curr_idx = currentIndex(); - if (m_proxyModel->hasChildren(curr_idx) && !isExpanded(curr_idx)) { - expand(curr_idx); - } + if (m_proxyModel->hasChildren(curr_idx) && !isExpanded(curr_idx)) { + expand(curr_idx); + } - const QModelIndex& index_next = moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier); + const QModelIndex& index_next = moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier); - if (index_next.isValid()) { - setCurrentIndex(index_next); - setFocus(); - } + if (index_next.isValid()) { + setCurrentIndex(index_next); + setFocus(); + } } void FeedsView::selectPreviousItem() { - const QModelIndex& curr_idx = currentIndex(); + const QModelIndex& curr_idx = currentIndex(); - if (m_proxyModel->hasChildren(curr_idx) && !isExpanded(curr_idx)) { - expand(curr_idx); - } + if (m_proxyModel->hasChildren(curr_idx) && !isExpanded(curr_idx)) { + expand(curr_idx); + } - const QModelIndex& index_previous = moveCursor(QAbstractItemView::MoveUp, Qt::NoModifier); + const QModelIndex& index_previous = moveCursor(QAbstractItemView::MoveUp, Qt::NoModifier); - if (index_previous.isValid()) { - setCurrentIndex(index_previous); - setFocus(); + if (index_previous.isValid()) { + setCurrentIndex(index_previous); + setFocus(); } } @@ -416,197 +423,200 @@ QModelIndex FeedsView::nextUnreadItem(QModelIndex default_row) { } void FeedsView::switchVisibility() { - setVisible(!isVisible()); + setVisible(!isVisible()); } void FeedsView::expandItemDelayed(const QModelIndex& idx) { QTimer::singleShot(100, this, [ = ] { - setExpanded(m_proxyModel->mapFromSource(idx), true); - }); + setExpanded(m_proxyModel->mapFromSource(idx), true); + }); } QMenu* FeedsView::initializeContextMenuCategories(RootItem* clicked_item) { - if (m_contextMenuCategories == nullptr) { - m_contextMenuCategories = new QMenu(tr("Context menu for categories"), this); - } - else { - m_contextMenuCategories->clear(); - } + if (m_contextMenuCategories == nullptr) { + m_contextMenuCategories = new QMenu(tr("Context menu for categories"), this); + } + else { + m_contextMenuCategories->clear(); + } - QList specific_actions = clicked_item->contextMenu(); - m_contextMenuCategories->addActions(QList() << - qApp->mainForm()->m_ui->m_actionUpdateSelectedItems << - qApp->mainForm()->m_ui->m_actionEditSelectedItem << - qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode << - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead << - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread << - qApp->mainForm()->m_ui->m_actionDeleteSelectedItem); + QList specific_actions = clicked_item->contextMenu(); + m_contextMenuCategories->addActions(QList() << + qApp->mainForm()->m_ui->m_actionUpdateSelectedItems << + qApp->mainForm()->m_ui->m_actionEditSelectedItem << + qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode << + qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead << + qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread << + qApp->mainForm()->m_ui->m_actionDeleteSelectedItem); - if (!specific_actions.isEmpty()) { - m_contextMenuCategories->addSeparator(); - m_contextMenuCategories->addActions(specific_actions); - } + if (!specific_actions.isEmpty()) { + m_contextMenuCategories->addSeparator(); + m_contextMenuCategories->addActions(specific_actions); + } - return m_contextMenuCategories; + return m_contextMenuCategories; } QMenu* FeedsView::initializeContextMenuFeeds(RootItem* clicked_item) { - if (m_contextMenuFeeds == nullptr) { - m_contextMenuFeeds = new QMenu(tr("Context menu for categories"), this); - } - else { - m_contextMenuFeeds->clear(); - } + if (m_contextMenuFeeds == nullptr) { + m_contextMenuFeeds = new QMenu(tr("Context menu for categories"), this); + } + else { + m_contextMenuFeeds->clear(); + } - QList specific_actions = clicked_item->contextMenu(); - m_contextMenuFeeds->addActions(QList() << - qApp->mainForm()->m_ui->m_actionUpdateSelectedItems << - qApp->mainForm()->m_ui->m_actionEditSelectedItem << - qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode << - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead << - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread << - qApp->mainForm()->m_ui->m_actionDeleteSelectedItem); + QList specific_actions = clicked_item->contextMenu(); + m_contextMenuFeeds->addActions(QList() << + qApp->mainForm()->m_ui->m_actionUpdateSelectedItems << + qApp->mainForm()->m_ui->m_actionEditSelectedItem << + qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode << + qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead << + qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread << + qApp->mainForm()->m_ui->m_actionDeleteSelectedItem); - if (!specific_actions.isEmpty()) { - m_contextMenuFeeds->addSeparator(); - m_contextMenuFeeds->addActions(specific_actions); - } + if (!specific_actions.isEmpty()) { + m_contextMenuFeeds->addSeparator(); + m_contextMenuFeeds->addActions(specific_actions); + } - return m_contextMenuFeeds; + return m_contextMenuFeeds; } QMenu* FeedsView::initializeContextMenuEmptySpace() { - if (m_contextMenuEmptySpace == nullptr) { - m_contextMenuEmptySpace = new QMenu(tr("Context menu for empty space"), this); - m_contextMenuEmptySpace->addAction(qApp->mainForm()->m_ui->m_actionUpdateAllItems); - m_contextMenuEmptySpace->addSeparator(); - } + if (m_contextMenuEmptySpace == nullptr) { + m_contextMenuEmptySpace = new QMenu(tr("Context menu for empty space"), this); + m_contextMenuEmptySpace->addAction(qApp->mainForm()->m_ui->m_actionUpdateAllItems); + m_contextMenuEmptySpace->addSeparator(); + } - return m_contextMenuEmptySpace; + return m_contextMenuEmptySpace; } QMenu* FeedsView::initializeContextMenuOtherItem(RootItem* clicked_item) { - if (m_contextMenuOtherItems == nullptr) { - m_contextMenuOtherItems = new QMenu(tr("Context menu for other items"), this); - } - else { - m_contextMenuOtherItems->clear(); - } + if (m_contextMenuOtherItems == nullptr) { + m_contextMenuOtherItems = new QMenu(tr("Context menu for other items"), this); + } + else { + m_contextMenuOtherItems->clear(); + } - QList specific_actions = clicked_item->contextMenu(); + QList specific_actions = clicked_item->contextMenu(); - if (!specific_actions.isEmpty()) { - m_contextMenuOtherItems->addSeparator(); - m_contextMenuOtherItems->addActions(specific_actions); - } - else { - m_contextMenuOtherItems->addAction(qApp->mainForm()->m_ui->m_actionNoActions); - } + if (!specific_actions.isEmpty()) { + m_contextMenuOtherItems->addSeparator(); + m_contextMenuOtherItems->addActions(specific_actions); + } + else { + m_contextMenuOtherItems->addAction(qApp->mainForm()->m_ui->m_actionNoActions); + } - return m_contextMenuOtherItems; + return m_contextMenuOtherItems; } void FeedsView::setupAppearance() { - // Setup column resize strategies. - header()->setSectionResizeMode(FDS_MODEL_TITLE_INDEX, QHeaderView::Stretch); - header()->setSectionResizeMode(FDS_MODEL_COUNTS_INDEX, QHeaderView::ResizeToContents); + // Setup column resize strategies. + header()->setSectionResizeMode(FDS_MODEL_TITLE_INDEX, QHeaderView::Stretch); + header()->setSectionResizeMode(FDS_MODEL_COUNTS_INDEX, QHeaderView::ResizeToContents); header()->setStretchLastSection(false); header()->setSortIndicatorShown(false); - setUniformRowHeights(true); - setAnimated(true); - setSortingEnabled(true); - setItemsExpandable(true); - setExpandsOnDoubleClick(true); - setEditTriggers(QAbstractItemView::NoEditTriggers); - setIndentation(FEEDS_VIEW_INDENTATION); - setAcceptDrops(false); - setDragEnabled(true); - setDropIndicatorShown(true); - setDragDropMode(QAbstractItemView::InternalMove); - setAllColumnsShowFocus(false); - setRootIsDecorated(false); - setSelectionMode(QAbstractItemView::SingleSelection); - setItemDelegate(new StyledItemDelegateWithoutFocus(this)); + setUniformRowHeights(true); + setAnimated(true); + setSortingEnabled(true); + setItemsExpandable(true); + setExpandsOnDoubleClick(true); + setEditTriggers(QAbstractItemView::NoEditTriggers); + setIndentation(FEEDS_VIEW_INDENTATION); + setAcceptDrops(false); + setDragEnabled(true); + setDropIndicatorShown(true); + setDragDropMode(QAbstractItemView::InternalMove); + setAllColumnsShowFocus(false); + setRootIsDecorated(false); + setSelectionMode(QAbstractItemView::SingleSelection); + setItemDelegate(new StyledItemDelegateWithoutFocus(this)); } void FeedsView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { - RootItem* selected_item = selectedItem(); - m_proxyModel->setSelectedItem(selected_item); - QTreeView::selectionChanged(selected, deselected); - emit itemSelected(selected_item); - m_proxyModel->invalidateReadFeedsFilter(); + RootItem* selected_item = selectedItem(); + + m_proxyModel->setSelectedItem(selected_item); + QTreeView::selectionChanged(selected, deselected); + emit itemSelected(selected_item); + + m_proxyModel->invalidateReadFeedsFilter(); } void FeedsView::keyPressEvent(QKeyEvent* event) { - QTreeView::keyPressEvent(event); + QTreeView::keyPressEvent(event); - if (event->key() == Qt::Key_Delete) { - deleteSelectedItem(); - } + if (event->key() == Qt::Key_Delete) { + deleteSelectedItem(); + } } void FeedsView::contextMenuEvent(QContextMenuEvent* event) { - const QModelIndex clicked_index = indexAt(event->pos()); + const QModelIndex clicked_index = indexAt(event->pos()); - if (clicked_index.isValid()) { - const QModelIndex mapped_index = model()->mapToSource(clicked_index); - RootItem* clicked_item = sourceModel()->itemForIndex(mapped_index); + if (clicked_index.isValid()) { + const QModelIndex mapped_index = model()->mapToSource(clicked_index); + RootItem* clicked_item = sourceModel()->itemForIndex(mapped_index); - if (clicked_item->kind() == RootItemKind::Category) { - // Display context menu for categories. - initializeContextMenuCategories(clicked_item)->exec(event->globalPos()); - } - else if (clicked_item->kind() == RootItemKind::Feed) { - // Display context menu for feeds. - initializeContextMenuFeeds(clicked_item)->exec(event->globalPos()); - } - else { - initializeContextMenuOtherItem(clicked_item)->exec(event->globalPos()); - } - } - else { - // Display menu for empty space. - initializeContextMenuEmptySpace()->exec(event->globalPos()); - } + if (clicked_item->kind() == RootItemKind::Category) { + // Display context menu for categories. + initializeContextMenuCategories(clicked_item)->exec(event->globalPos()); + } + else if (clicked_item->kind() == RootItemKind::Feed) { + // Display context menu for feeds. + initializeContextMenuFeeds(clicked_item)->exec(event->globalPos()); + } + else { + initializeContextMenuOtherItem(clicked_item)->exec(event->globalPos()); + } + } + else { + // Display menu for empty space. + initializeContextMenuEmptySpace()->exec(event->globalPos()); + } } void FeedsView::mouseDoubleClickEvent(QMouseEvent* event) { - QModelIndex idx = indexAt(event->pos()); + QModelIndex idx = indexAt(event->pos()); - if (idx.isValid()) { - RootItem* item = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(idx)); + if (idx.isValid()) { + RootItem* item = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(idx)); - if (item->kind() == RootItemKind::Feed || item->kind() == RootItemKind::Bin) { - const QList messages = m_sourceModel->messagesForItem(item); + if (item->kind() == RootItemKind::Feed || item->kind() == RootItemKind::Bin) { + const QList messages = m_sourceModel->messagesForItem(item); - if (!messages.isEmpty()) { - emit openMessagesInNewspaperView(item, messages); - } - } - } + if (!messages.isEmpty()) { + emit openMessagesInNewspaperView(item, messages); + } + } + } - QTreeView::mouseDoubleClickEvent(event); + QTreeView::mouseDoubleClickEvent(event); } void FeedsView::saveSortState(int column, Qt::SortOrder order) { - qApp->settings()->setValue(GROUP(GUI), GUI::DefaultSortColumnFeeds, column); - qApp->settings()->setValue(GROUP(GUI), GUI::DefaultSortOrderFeeds, order); + qApp->settings()->setValue(GROUP(GUI), GUI::DefaultSortColumnFeeds, column); + qApp->settings()->setValue(GROUP(GUI), GUI::DefaultSortOrderFeeds, order); } void FeedsView::validateItemAfterDragDrop(const QModelIndex& source_index) { - const QModelIndex mapped = m_proxyModel->mapFromSource(source_index); + const QModelIndex mapped = m_proxyModel->mapFromSource(source_index); - if (mapped.isValid()) { - expand(mapped); - setCurrentIndex(mapped); - } + if (mapped.isValid()) { + expand(mapped); + setCurrentIndex(mapped); + } } void FeedsView::onItemExpandRequested(const QList& items, bool exp) { - foreach (const RootItem* item, items) { - QModelIndex source_index = m_sourceModel->indexForItem(item); - QModelIndex proxy_index = m_proxyModel->mapFromSource(source_index); - setExpanded(proxy_index, exp); - } + foreach (const RootItem* item, items) { + QModelIndex source_index = m_sourceModel->indexForItem(item); + QModelIndex proxy_index = m_proxyModel->mapFromSource(source_index); + + setExpanded(proxy_index, exp); + } } diff --git a/src/gui/feedsview.h b/src/gui/feedsview.h index bdd79cf21..82f36334c 100755 --- a/src/gui/feedsview.h +++ b/src/gui/feedsview.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -24,120 +25,119 @@ #include - class FeedsProxyModel; class Feed; class Category; class FeedsView : public QTreeView { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit FeedsView(QWidget* parent = 0); - virtual ~FeedsView(); + public: - // Fundamental accessors. - inline FeedsProxyModel* model() const { - return m_proxyModel; - } + // Constructors and destructors. + explicit FeedsView(QWidget* parent = 0); + virtual ~FeedsView(); - inline FeedsModel* sourceModel() const { - return m_sourceModel; - } + // Fundamental accessors. + inline FeedsProxyModel* model() const { + return m_proxyModel; + } - void setSortingEnabled(bool enable); + inline FeedsModel* sourceModel() const { + return m_sourceModel; + } - // Returns list of selected/all feeds. - // NOTE: This is recursive method which returns all descendants. - QList selectedFeeds() const; + void setSortingEnabled(bool enable); - // Returns pointers to selected feed/category if they are really - // selected. - RootItem* selectedItem() const; + // Returns list of selected/all feeds. + // NOTE: This is recursive method which returns all descendants. + QList selectedFeeds() const; - // Saves/loads expand states of all nodes (feeds/categories) of the list to/from settings. - void saveAllExpandStates(); - void loadAllExpandStates(); + // Returns pointers to selected feed/category if they are really + // selected. + RootItem* selectedItem() const; - public slots: - void sortByColumn(int column, Qt::SortOrder order); + // Saves/loads expand states of all nodes (feeds/categories) of the list to/from settings. + void saveAllExpandStates(); + void loadAllExpandStates(); - void addFeedIntoSelectedAccount(); - void addCategoryIntoSelectedAccount(); - void expandCollapseCurrentItem(); + public slots: + void sortByColumn(int column, Qt::SortOrder order); - // Feed updating. - void updateSelectedItems(); + void addFeedIntoSelectedAccount(); + void addCategoryIntoSelectedAccount(); + void expandCollapseCurrentItem(); - // Feed read/unread manipulators. - void markSelectedItemRead(); - void markSelectedItemUnread(); - void markAllItemsRead(); + // Feed updating. + void updateSelectedItems(); - // Newspaper accessors. - void openSelectedItemsInNewspaperMode(); + // Feed read/unread manipulators. + void markSelectedItemRead(); + void markSelectedItemUnread(); + void markAllItemsRead(); - // Feed clearers. - void clearSelectedFeeds(); - void clearAllFeeds(); + // Newspaper accessors. + void openSelectedItemsInNewspaperMode(); - // Base manipulators. - void editSelectedItem(); - void deleteSelectedItem(); + // Feed clearers. + void clearSelectedFeeds(); + void clearAllFeeds(); - // Selects next/previous item (feed/category) in the list. - void selectNextItem(); - void selectPreviousItem(); + // Base manipulators. + void editSelectedItem(); + void deleteSelectedItem(); + + // Selects next/previous item (feed/category) in the list. + void selectNextItem(); + void selectPreviousItem(); void selectNextUnreadItem(); - // Switches visibility of the widget. - void switchVisibility(); + // Switches visibility of the widget. + void switchVisibility(); - signals: - void itemSelected(RootItem* item); + signals: + void itemSelected(RootItem* item); void requestViewNextUnreadMessage(); - void openMessagesInNewspaperView(RootItem* root, const QList& messages); + void openMessagesInNewspaperView(RootItem* root, const QList& messages); - protected: - void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected); - void keyPressEvent(QKeyEvent* event); - void contextMenuEvent(QContextMenuEvent* event); - void mouseDoubleClickEvent(QMouseEvent* event); + protected: + void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected); + void keyPressEvent(QKeyEvent* event); + void contextMenuEvent(QContextMenuEvent* event); + void mouseDoubleClickEvent(QMouseEvent* event); - private slots: - void expandItemDelayed(const QModelIndex& idx); - void markSelectedItemReadStatus(RootItem::ReadStatus read); - void markAllItemsReadStatus(RootItem::ReadStatus read); + private slots: + void expandItemDelayed(const QModelIndex& idx); + void markSelectedItemReadStatus(RootItem::ReadStatus read); + void markAllItemsReadStatus(RootItem::ReadStatus read); - void saveSortState(int column, Qt::SortOrder order); - void validateItemAfterDragDrop(const QModelIndex& source_index); - void onItemExpandRequested(const QList& items, bool exp); - void onItemExpandStateSaveRequested(RootItem* item); + void saveSortState(int column, Qt::SortOrder order); + void validateItemAfterDragDrop(const QModelIndex& source_index); + void onItemExpandRequested(const QList& items, bool exp); + void onItemExpandStateSaveRequested(RootItem* item); - private: + private: QModelIndex nextPreviousUnreadItem(QModelIndex default_row); QModelIndex nextUnreadItem(QModelIndex default_row); - // Initializes context menus. - QMenu* initializeContextMenuCategories(RootItem* clicked_item); - QMenu* initializeContextMenuFeeds(RootItem* clicked_item); - QMenu* initializeContextMenuEmptySpace(); - QMenu* initializeContextMenuOtherItem(RootItem* clicked_item); + // Initializes context menus. + QMenu* initializeContextMenuCategories(RootItem* clicked_item); + QMenu* initializeContextMenuFeeds(RootItem* clicked_item); + QMenu* initializeContextMenuEmptySpace(); + QMenu* initializeContextMenuOtherItem(RootItem* clicked_item); - // Sets up appearance of this widget. - void setupAppearance(); + // Sets up appearance of this widget. + void setupAppearance(); - void saveExpandStates(RootItem* item); + void saveExpandStates(RootItem* item); - QMenu* m_contextMenuCategories; - QMenu* m_contextMenuFeeds; - QMenu* m_contextMenuEmptySpace; - QMenu* m_contextMenuOtherItems; - - FeedsModel* m_sourceModel; - FeedsProxyModel* m_proxyModel; + QMenu* m_contextMenuCategories; + QMenu* m_contextMenuFeeds; + QMenu* m_contextMenuEmptySpace; + QMenu* m_contextMenuOtherItems; + FeedsModel* m_sourceModel; + FeedsProxyModel* m_proxyModel; }; #endif // FEEDSVIEW_H diff --git a/src/gui/guiutilities.cpp b/src/gui/guiutilities.cpp index 00ab7aebe..0d50d73fd 100755 --- a/src/gui/guiutilities.cpp +++ b/src/gui/guiutilities.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,23 +20,22 @@ #include "definitions/definitions.h" - void GuiUtilities::setLabelAsNotice(QLabel& label, bool is_warning) { - label.setMargin(6); + label.setMargin(6); - if (is_warning) { - label.setStyleSheet(QSL("font-weight: bold; font-style: italic; color: red")); - } - else { - label.setStyleSheet(QSL("font-style: italic;")); - } + if (is_warning) { + label.setStyleSheet(QSL("font-weight: bold; font-style: italic; color: red")); + } + else { + label.setStyleSheet(QSL("font-style: italic;")); + } } void GuiUtilities::applyDialogProperties(QWidget& widget, const QIcon& icon, const QString& title) { - widget.setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); - widget.setWindowIcon(icon); + widget.setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); + widget.setWindowIcon(icon); - if (!title.isEmpty()) { - widget.setWindowTitle(title); - } + if (!title.isEmpty()) { + widget.setWindowTitle(title); + } } diff --git a/src/gui/guiutilities.h b/src/gui/guiutilities.h index c1aed5223..4f54c41c2 100755 --- a/src/gui/guiutilities.h +++ b/src/gui/guiutilities.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,17 +19,16 @@ #ifndef GUIUTILITIES_H #define GUIUTILITIES_H -#include #include - +#include class GuiUtilities { - public: - static void setLabelAsNotice(QLabel& label, bool is_warning); - static void applyDialogProperties(QWidget& widget, const QIcon& icon, const QString& title = QString()); + public: + static void setLabelAsNotice(QLabel& label, bool is_warning); + static void applyDialogProperties(QWidget& widget, const QIcon& icon, const QString& title = QString()); - private: - explicit GuiUtilities(); + private: + explicit GuiUtilities(); }; inline GuiUtilities::GuiUtilities() {} diff --git a/src/gui/labelwithstatus.cpp b/src/gui/labelwithstatus.cpp index 406bbde59..c9382d5b9 100755 --- a/src/gui/labelwithstatus.cpp +++ b/src/gui/labelwithstatus.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,24 +22,25 @@ #include - LabelWithStatus::LabelWithStatus(QWidget* parent) - : WidgetWithStatus(parent) { - m_wdgInput = new QLabel(this); - // Set correct size for the tool button. - int label_height = m_wdgInput->sizeHint().height(); - m_btnStatus->setFixedSize(label_height, label_height); - // Compose the layout. - m_layout->addWidget(m_wdgInput); - m_layout->addWidget(m_btnStatus); + : WidgetWithStatus(parent) { + m_wdgInput = new QLabel(this); + + // Set correct size for the tool button. + int label_height = m_wdgInput->sizeHint().height(); + + m_btnStatus->setFixedSize(label_height, label_height); + + // Compose the layout. + m_layout->addWidget(m_wdgInput); + m_layout->addWidget(m_btnStatus); } -LabelWithStatus::~LabelWithStatus() { -} +LabelWithStatus::~LabelWithStatus() {} void LabelWithStatus::setStatus(WidgetWithStatus::StatusType status, const QString& label_text, const QString& status_text) { - WidgetWithStatus::setStatus(status, status_text); - label()->setText(label_text); + WidgetWithStatus::setStatus(status, status_text); + label()->setText(label_text); } diff --git a/src/gui/labelwithstatus.h b/src/gui/labelwithstatus.h index 71a9a2fb5..42cf7b328 100755 --- a/src/gui/labelwithstatus.h +++ b/src/gui/labelwithstatus.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,21 +23,22 @@ #include - class LabelWithStatus : public WidgetWithStatus { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit LabelWithStatus(QWidget* parent = 0); - virtual ~LabelWithStatus(); + public: - void setStatus(StatusType status, const QString& label_text, const QString& status_text); + // Constructors and destructors. + explicit LabelWithStatus(QWidget* parent = 0); + virtual ~LabelWithStatus(); + + void setStatus(StatusType status, const QString& label_text, const QString& status_text); + + // Access to label. + inline QLabel* label() const { + return static_cast(m_wdgInput); + } - // Access to label. - inline QLabel* label() const { - return static_cast(m_wdgInput); - } }; #endif // LABELWITHSTATUS_H diff --git a/src/gui/lineeditwithstatus.cpp b/src/gui/lineeditwithstatus.cpp index 8c16bda34..22a9aa1cb 100755 --- a/src/gui/lineeditwithstatus.cpp +++ b/src/gui/lineeditwithstatus.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,23 +18,24 @@ #include "gui/lineeditwithstatus.h" -#include "gui/plaintoolbutton.h" #include "gui/baselineedit.h" +#include "gui/plaintoolbutton.h" #include - LineEditWithStatus::LineEditWithStatus(QWidget* parent) - : WidgetWithStatus(parent) { - m_wdgInput = new BaseLineEdit(this); - setFocusProxy(m_wdgInput); - // Set correct size for the tool button. - const int txt_input_height = m_wdgInput->sizeHint().height(); - m_btnStatus->setFixedSize(txt_input_height, txt_input_height); - // Compose the layout. - m_layout->addWidget(m_wdgInput); - m_layout->addWidget(m_btnStatus); + : WidgetWithStatus(parent) { + m_wdgInput = new BaseLineEdit(this); + setFocusProxy(m_wdgInput); + + // Set correct size for the tool button. + const int txt_input_height = m_wdgInput->sizeHint().height(); + + m_btnStatus->setFixedSize(txt_input_height, txt_input_height); + + // Compose the layout. + m_layout->addWidget(m_wdgInput); + m_layout->addWidget(m_btnStatus); } -LineEditWithStatus::~LineEditWithStatus() { -} +LineEditWithStatus::~LineEditWithStatus() {} diff --git a/src/gui/lineeditwithstatus.h b/src/gui/lineeditwithstatus.h index 6f4c483f5..24838ecf9 100755 --- a/src/gui/lineeditwithstatus.h +++ b/src/gui/lineeditwithstatus.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,19 +23,20 @@ #include "gui/baselineedit.h" - class LineEditWithStatus : public WidgetWithStatus { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit LineEditWithStatus(QWidget* parent = 0); - virtual ~LineEditWithStatus(); + public: + + // Constructors and destructors. + explicit LineEditWithStatus(QWidget* parent = 0); + virtual ~LineEditWithStatus(); + + // Access to line edit. + inline BaseLineEdit* lineEdit() const { + return static_cast(m_wdgInput); + } - // Access to line edit. - inline BaseLineEdit* lineEdit() const { - return static_cast(m_wdgInput); - } }; #endif // LINEEDITWITHSTATUS_H diff --git a/src/gui/locationlineedit.cpp b/src/gui/locationlineedit.cpp index 9146b6fa7..ea10d9e1d 100755 --- a/src/gui/locationlineedit.cpp +++ b/src/gui/locationlineedit.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,31 +22,31 @@ #include - LocationLineEdit::LocationLineEdit(QWidget* parent) - : BaseLineEdit(parent), m_mouseSelectsAllText(true), m_googleSuggest(new GoogleSuggest(this)) { - setPlaceholderText(tr("Website address goes here")); - connect(this, &LocationLineEdit::submitted, m_googleSuggest, &GoogleSuggest::preventSuggest); + : BaseLineEdit(parent), m_mouseSelectsAllText(true), m_googleSuggest(new GoogleSuggest(this)) { + setPlaceholderText(tr("Website address goes here")); + connect(this, &LocationLineEdit::submitted, m_googleSuggest, &GoogleSuggest::preventSuggest); } -LocationLineEdit::~LocationLineEdit() { -} +LocationLineEdit::~LocationLineEdit() {} void LocationLineEdit::focusOutEvent(QFocusEvent* event) { - BaseLineEdit::focusOutEvent(event); - // User now left text box, when he enters it again and clicks, - // then all text should be selected. - m_mouseSelectsAllText = true; + BaseLineEdit::focusOutEvent(event); + + // User now left text box, when he enters it again and clicks, + // then all text should be selected. + m_mouseSelectsAllText = true; } void LocationLineEdit::mousePressEvent(QMouseEvent* event) { - if (m_mouseSelectsAllText) { - event->ignore(); - selectAll(); - // User clicked and all text was selected. - m_mouseSelectsAllText = false; - } - else { - BaseLineEdit::mousePressEvent(event); - } + if (m_mouseSelectsAllText) { + event->ignore(); + selectAll(); + + // User clicked and all text was selected. + m_mouseSelectsAllText = false; + } + else { + BaseLineEdit::mousePressEvent(event); + } } diff --git a/src/gui/locationlineedit.h b/src/gui/locationlineedit.h index 9388feef8..cfe07a1b5 100755 --- a/src/gui/locationlineedit.h +++ b/src/gui/locationlineedit.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,25 +21,25 @@ #include "gui/baselineedit.h" - class WebBrowser; class GoogleSuggest; class LocationLineEdit : public BaseLineEdit { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit LocationLineEdit(QWidget* parent = 0); - virtual ~LocationLineEdit(); + public: - protected: - void focusOutEvent(QFocusEvent* event); - void mousePressEvent(QMouseEvent* event); + // Constructors and destructors. + explicit LocationLineEdit(QWidget* parent = 0); + virtual ~LocationLineEdit(); - private: - bool m_mouseSelectsAllText; - GoogleSuggest* m_googleSuggest; + protected: + void focusOutEvent(QFocusEvent* event); + void mousePressEvent(QMouseEvent* event); + + private: + bool m_mouseSelectsAllText; + GoogleSuggest* m_googleSuggest; }; #endif // LOCATIONLINEEDIT_H diff --git a/src/gui/messagebox.cpp b/src/gui/messagebox.cpp index 3723b8e32..0272234b7 100755 --- a/src/gui/messagebox.cpp +++ b/src/gui/messagebox.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -27,7 +28,6 @@ #include #include - MessageBox::MessageBox(QWidget* parent) : QMessageBox(parent) {} MessageBox::~MessageBox() {} @@ -72,9 +72,15 @@ QIcon MessageBox::iconForStatus(QMessageBox::Icon status) { } } -QMessageBox::StandardButton MessageBox::show(QWidget* parent, QMessageBox::Icon icon, const QString& title, const QString& text, - const QString& informative_text, const QString& detailed_text, QMessageBox::StandardButtons buttons, - QMessageBox::StandardButton default_button, bool* dont_show_again) { +QMessageBox::StandardButton MessageBox::show(QWidget* parent, + QMessageBox::Icon icon, + const QString& title, + const QString& text, + const QString& informative_text, + const QString& detailed_text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton default_button, + bool* dont_show_again) { // Create and find needed components. MessageBox msg_box(parent); diff --git a/src/gui/messagebox.h b/src/gui/messagebox.h index 66e4d13a6..f2ea7e994 100755 --- a/src/gui/messagebox.h +++ b/src/gui/messagebox.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,35 +19,34 @@ #ifndef MESSAGEBOX_H #define MESSAGEBOX_H -#include #include - +#include class MessageBox : public QMessageBox { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit MessageBox(QWidget* parent = 0); - virtual ~MessageBox(); + public: - // Custom icon setting. - void setIcon(Icon icon); + // Constructors and destructors. + explicit MessageBox(QWidget* parent = 0); + virtual ~MessageBox(); - static void setCheckBox(QMessageBox* msg_box, const QString& text, bool* data); + // Custom icon setting. + void setIcon(Icon icon); - // Displays custom message box. - static QMessageBox::StandardButton show(QWidget* parent, - QMessageBox::Icon icon, - const QString& title, - const QString& text, - const QString& informative_text = QString(), - const QString& detailed_text = QString(), - QMessageBox::StandardButtons buttons = QMessageBox::Ok, - QMessageBox::StandardButton default_button = QMessageBox::Ok, - bool* dont_show_again = nullptr); + static void setCheckBox(QMessageBox* msg_box, const QString& text, bool* data); - static QIcon iconForStatus(QMessageBox::Icon status); + // Displays custom message box. + static QMessageBox::StandardButton show(QWidget* parent, + QMessageBox::Icon icon, + const QString& title, + const QString& text, + const QString& informative_text = QString(), + const QString& detailed_text = QString(), + QMessageBox::StandardButtons buttons = QMessageBox::Ok, + QMessageBox::StandardButton default_button = QMessageBox::Ok, + bool* dont_show_again = nullptr); + static QIcon iconForStatus(QMessageBox::Icon status); }; #endif // MESSAGEBOX_H diff --git a/src/gui/messagepreviewer.cpp b/src/gui/messagepreviewer.cpp index 9b3e0f9f5..d06db0aeb 100755 --- a/src/gui/messagepreviewer.cpp +++ b/src/gui/messagepreviewer.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,200 +18,206 @@ #include "gui/messagepreviewer.h" -#include "miscellaneous/application.h" -#include "network-web/webfactory.h" -#include "miscellaneous/databasequeries.h" -#include "gui/messagebox.h" #include "gui/dialogs/formmain.h" +#include "gui/messagebox.h" +#include "miscellaneous/application.h" +#include "miscellaneous/databasequeries.h" +#include "network-web/webfactory.h" #include "services/abstract/serviceroot.h" #include #include #include - void MessagePreviewer::createConnections() { - connect(m_ui->m_txtMessage, &QTextBrowser::anchorClicked, [ = ](const QUrl & url) { - if (!url.isEmpty()) { - bool open_externally_now = qApp->settings()->value(GROUP(Browser), - SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool(); + connect(m_ui->m_txtMessage, &QTextBrowser::anchorClicked, [=](const QUrl& url) { + if (!url.isEmpty()) { + bool open_externally_now = qApp->settings()->value(GROUP(Browser), + SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool(); - if (open_externally_now) { - qApp->web()->openUrlInExternalBrowser(url.toString()); - } - else { - // User clicked some URL. Open it in external browser or download? - MessageBox box(qApp->mainForm()); - box.setText(tr("You clicked some link. You can download the link contents or open it in external web browser.")); - box.setInformativeText(tr("What action do you want to take?")); - box.setDetailedText(url.toString()); - QAbstractButton* btn_open = box.addButton(tr("Open in external browser"), QMessageBox::ActionRole); - QAbstractButton* btn_download = box.addButton(tr("Download"), QMessageBox::ActionRole); - QAbstractButton* btn_cancel = box.addButton(QMessageBox::Cancel); - bool always; - MessageBox::setCheckBox(&box, tr("Always open links in external browser."), &always); - box.setDefaultButton(QMessageBox::Cancel); - box.exec(); + if (open_externally_now) { + qApp->web()->openUrlInExternalBrowser(url.toString()); + } + else { + // User clicked some URL. Open it in external browser or download? + MessageBox box(qApp->mainForm()); + box.setText(tr("You clicked some link. You can download the link contents or open it in external web browser.")); + box.setInformativeText(tr("What action do you want to take?")); + box.setDetailedText(url.toString()); + QAbstractButton* btn_open = box.addButton(tr("Open in external browser"), QMessageBox::ActionRole); + QAbstractButton* btn_download = box.addButton(tr("Download"), QMessageBox::ActionRole); + QAbstractButton* btn_cancel = box.addButton(QMessageBox::Cancel); + bool always; + MessageBox::setCheckBox(&box, tr("Always open links in external browser."), &always); + box.setDefaultButton(QMessageBox::Cancel); + box.exec(); - if (box.clickedButton() != box.button(QMessageBox::Cancel)) { - // Store selected checkbox value. - qApp->settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, always); - } + if (box.clickedButton() != box.button(QMessageBox::Cancel)) { + // Store selected checkbox value. + qApp->settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, always); + } - if (box.clickedButton() == btn_open) { - qApp->web()->openUrlInExternalBrowser(url.toString()); - } - else if (box.clickedButton() == btn_download) { - qApp->downloadManager()->download(url); - } + if (box.clickedButton() == btn_open) { + qApp->web()->openUrlInExternalBrowser(url.toString()); + } + else if (box.clickedButton() == btn_download) { + qApp->downloadManager()->download(url); + } - btn_download->deleteLater(); - btn_open->deleteLater(); - btn_cancel->deleteLater(); - } - } - else { - MessageBox::show(qApp->mainForm(), QMessageBox::Warning, tr("Incorrect link"), - tr("Selected hyperlink is invalid.")); - } - }); - connect(m_actionMarkRead = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-read"), tr("Mark message as read")), - &QAction::triggered, - this, - &MessagePreviewer::markMessageAsRead); - connect(m_actionMarkUnread = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-unread"), tr("Mark message as unread")), - &QAction::triggered, - this, - &MessagePreviewer::markMessageAsUnread); - connect(m_actionSwitchImportance = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-important"), tr("Switch message importance")), - &QAction::triggered, - this, - &MessagePreviewer::switchMessageImportance); - connect(m_ui->m_txtMessage, - static_cast(&QTextBrowser::highlighted), - [ = ](const QString & text) { - Q_UNUSED(text) - QToolTip::showText(QCursor::pos(), tr("Click this link to download it or open it with external browser."), this); - }); + btn_download->deleteLater(); + btn_open->deleteLater(); + btn_cancel->deleteLater(); + } + } + else { + MessageBox::show(qApp->mainForm(), QMessageBox::Warning, tr("Incorrect link"), + tr("Selected hyperlink is invalid.")); + } + }); + connect(m_actionMarkRead = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-read"), tr("Mark message as read")), + &QAction::triggered, + this, + &MessagePreviewer::markMessageAsRead); + connect(m_actionMarkUnread = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-unread"), tr("Mark message as unread")), + &QAction::triggered, + this, + &MessagePreviewer::markMessageAsUnread); + connect(m_actionSwitchImportance = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-important"), tr("Switch message importance")), + &QAction::triggered, + this, + &MessagePreviewer::switchMessageImportance); + connect(m_ui->m_txtMessage, + static_cast(&QTextBrowser::highlighted), + [=](const QString& text) { + Q_UNUSED(text) + QToolTip::showText(QCursor::pos(), tr("Click this link to download it or open it with external browser."), this); + }); } MessagePreviewer::MessagePreviewer(QWidget* parent) : QWidget(parent), - m_ui(new Ui::MessagePreviewer), m_pictures(QStringList()) { - m_ui->setupUi(this); - m_ui->m_txtMessage->viewport()->setAutoFillBackground(true); - m_toolBar = new QToolBar(this); - m_toolBar->setOrientation(Qt::Vertical); - m_ui->m_layout->addWidget(m_toolBar, 0, 0, -1, 1); - createConnections(); - m_actionSwitchImportance->setCheckable(true); - reloadFontSettings(); - clear(); + m_ui(new Ui::MessagePreviewer), m_pictures(QStringList()) { + m_ui->setupUi(this); + m_ui->m_txtMessage->viewport()->setAutoFillBackground(true); + m_toolBar = new QToolBar(this); + m_toolBar->setOrientation(Qt::Vertical); + m_ui->m_layout->addWidget(m_toolBar, 0, 0, -1, 1); + createConnections(); + m_actionSwitchImportance->setCheckable(true); + reloadFontSettings(); + clear(); } -MessagePreviewer::~MessagePreviewer() { -} +MessagePreviewer::~MessagePreviewer() {} void MessagePreviewer::reloadFontSettings() { - const Settings* settings = qApp->settings(); - QFont fon; - fon.fromString(settings->value(GROUP(Messages), - SETTING(Messages::PreviewerFontStandard)).toString()); - m_ui->m_txtMessage->setFont(fon); + const Settings* settings = qApp->settings(); + QFont fon; + + fon.fromString(settings->value(GROUP(Messages), + SETTING(Messages::PreviewerFontStandard)).toString()); + m_ui->m_txtMessage->setFont(fon); } void MessagePreviewer::clear() { - m_ui->m_txtMessage->clear(); - m_pictures.clear(); - hide(); + m_ui->m_txtMessage->clear(); + m_pictures.clear(); + hide(); } void MessagePreviewer::hideToolbar() { - m_toolBar->setVisible(false); + m_toolBar->setVisible(false); } void MessagePreviewer::loadMessage(const Message& message, RootItem* root) { - m_message = message; - m_root = root; + m_message = message; + m_root = root; - if (!m_root.isNull()) { - m_actionSwitchImportance->setChecked(m_message.m_isImportant); - m_ui->m_txtMessage->setHtml(prepareHtmlForMessage(m_message)); - updateButtons(); - show(); - m_ui->m_txtMessage->verticalScrollBar()->triggerAction(QScrollBar::SliderToMinimum); - } + if (!m_root.isNull()) { + m_actionSwitchImportance->setChecked(m_message.m_isImportant); + m_ui->m_txtMessage->setHtml(prepareHtmlForMessage(m_message)); + updateButtons(); + show(); + m_ui->m_txtMessage->verticalScrollBar()->triggerAction(QScrollBar::SliderToMinimum); + } } void MessagePreviewer::markMessageAsRead() { - markMessageAsReadUnread(RootItem::Read); + markMessageAsReadUnread(RootItem::Read); } void MessagePreviewer::markMessageAsUnread() { - markMessageAsReadUnread(RootItem::Unread); + markMessageAsReadUnread(RootItem::Unread); } void MessagePreviewer::markMessageAsReadUnread(RootItem::ReadStatus read) { - if (!m_root.isNull()) { - if (m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(), - QList() << m_message, - read)) { - DatabaseQueries::markMessagesReadUnread(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), - QStringList() << QString::number(m_message.m_id), - read); - m_root->getParentServiceRoot()->onAfterSetMessagesRead(m_root.data(), - QList() << m_message, - read); - m_message.m_isRead = read == RootItem::Read; - emit markMessageRead(m_message.m_id, read); - updateButtons(); - } - } + if (!m_root.isNull()) { + if (m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(), + QList() << m_message, + read)) { + DatabaseQueries::markMessagesReadUnread(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), + QStringList() << QString::number(m_message.m_id), + read); + m_root->getParentServiceRoot()->onAfterSetMessagesRead(m_root.data(), + QList() << m_message, + read); + m_message.m_isRead = read == RootItem::Read; + emit markMessageRead(m_message.m_id, read); + + updateButtons(); + } + } } void MessagePreviewer::switchMessageImportance(bool checked) { - if (!m_root.isNull()) { - if (m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), - QList() << ImportanceChange(m_message, - m_message.m_isImportant ? - RootItem::NotImportant : - RootItem::Important))) { + if (!m_root.isNull()) { + if (m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), + QList() << ImportanceChange(m_message, + m_message. + m_isImportant ? + RootItem::NotImportant + : + RootItem::Important))) + { DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), - QStringList() << QString::number(m_message.m_id)); - m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(), - QList() << ImportanceChange(m_message, - m_message.m_isImportant ? - RootItem::NotImportant : - RootItem::Important)); - emit markMessageImportant(m_message.m_id, checked ? RootItem::Important : RootItem::NotImportant); - m_message.m_isImportant = checked; - } - } + QStringList() << QString::number(m_message.m_id)); + m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(), + QList() << ImportanceChange(m_message, + m_message.m_isImportant ? + RootItem::NotImportant : + RootItem::Important)); + emit markMessageImportant(m_message.m_id, checked ? RootItem::Important : RootItem::NotImportant); + + m_message.m_isImportant = checked; + } + } } void MessagePreviewer::updateButtons() { - m_actionMarkRead->setEnabled(!m_message.m_isRead); - m_actionMarkUnread->setEnabled(m_message.m_isRead); + m_actionMarkRead->setEnabled(!m_message.m_isRead); + m_actionMarkUnread->setEnabled(m_message.m_isRead); } QString MessagePreviewer::prepareHtmlForMessage(const Message& message) { - QString html = QString("

%1

").arg(message.m_title); - html += QString("[url] %1
").arg(message.m_url); + QString html = QString("

%1

").arg(message.m_title); - foreach (const Enclosure& enc, message.m_enclosures) { - html += QString("[%2] %1
").arg(enc.m_url, enc.m_mimeType); - } + html += QString("[url] %1
").arg(message.m_url); - int offset = 0; - QRegExp imgTagRegex("\\]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive); - imgTagRegex.setMinimal(true); + foreach (const Enclosure& enc, message.m_enclosures) { + html += QString("[%2] %1
").arg(enc.m_url, enc.m_mimeType); + } - while ((offset = imgTagRegex.indexIn(message.m_contents, offset)) != -1) { - m_pictures.append(imgTagRegex.cap(1)); - offset += imgTagRegex.matchedLength(); - html += QString("[%2] %1
").arg(imgTagRegex.cap(1), tr("image")); - } + int offset = 0; + QRegExp imgTagRegex("\\]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive); - html += "
"; - html += message.m_contents; - return html; + imgTagRegex.setMinimal(true); + + while ((offset = imgTagRegex.indexIn(message.m_contents, offset)) != -1) { + m_pictures.append(imgTagRegex.cap(1)); + offset += imgTagRegex.matchedLength(); + html += QString("[%2] %1
").arg(imgTagRegex.cap(1), tr("image")); + } + + html += "
"; + html += message.m_contents; + return html; } diff --git a/src/gui/messagepreviewer.h b/src/gui/messagepreviewer.h index 77a2b9819..4f6f30402 100755 --- a/src/gui/messagepreviewer.h +++ b/src/gui/messagepreviewer.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -27,52 +28,53 @@ #include - namespace Ui { - class MessagePreviewer; + class MessagePreviewer; } class QToolBar; class MessagePreviewer : public QWidget { - Q_OBJECT + Q_OBJECT - public: - explicit MessagePreviewer(QWidget* parent = 0); - virtual ~MessagePreviewer(); + public: + explicit MessagePreviewer(QWidget* parent = 0); + virtual ~MessagePreviewer(); - void reloadFontSettings(); + void reloadFontSettings(); - public slots: - void clear(); - void hideToolbar(); - void loadMessage(const Message& message, RootItem* root); + public slots: + void clear(); + void hideToolbar(); + void loadMessage(const Message& message, RootItem* root); - private slots: - void markMessageAsRead(); - void markMessageAsUnread(); - void markMessageAsReadUnread(RootItem::ReadStatus read); - void switchMessageImportance(bool checked); + private slots: + void markMessageAsRead(); + void markMessageAsUnread(); + void markMessageAsReadUnread(RootItem::ReadStatus read); + void switchMessageImportance(bool checked); - signals: - void markMessageRead(int id, RootItem::ReadStatus read); - void markMessageImportant(int id, RootItem::Importance important); - void requestMessageListReload(bool mark_current_as_read); + signals: + void markMessageRead(int id, RootItem::ReadStatus read); + void markMessageImportant(int id, RootItem::Importance important); + void requestMessageListReload(bool mark_current_as_read); - private: - void createConnections(); - void updateButtons(); - QString prepareHtmlForMessage(const Message& message); + private: + void createConnections(); + void updateButtons(); + QString prepareHtmlForMessage(const Message& message); - QToolBar* m_toolBar; - QScopedPointer m_ui; - Message m_message; - QStringList m_pictures; - QPointer m_root; + QToolBar* m_toolBar; - QAction* m_actionMarkRead; - QAction* m_actionMarkUnread; - QAction* m_actionSwitchImportance; + QScopedPointer m_ui; + Message m_message; + QStringList m_pictures; + + QPointer m_root; + + QAction* m_actionMarkRead; + QAction* m_actionMarkUnread; + QAction* m_actionSwitchImportance; }; #endif // MESSAGEPREVIEWER_H diff --git a/src/gui/messagessearchlineedit.cpp b/src/gui/messagessearchlineedit.cpp index 8c86a482b..dd841fc86 100755 --- a/src/gui/messagessearchlineedit.cpp +++ b/src/gui/messagessearchlineedit.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,9 +18,6 @@ #include "gui/messagessearchlineedit.h" +MessagesSearchLineEdit::MessagesSearchLineEdit(QWidget* parent) : BaseLineEdit(parent) {} -MessagesSearchLineEdit::MessagesSearchLineEdit(QWidget* parent) : BaseLineEdit(parent) { -} - -MessagesSearchLineEdit::~MessagesSearchLineEdit() { -} +MessagesSearchLineEdit::~MessagesSearchLineEdit() {} diff --git a/src/gui/messagessearchlineedit.h b/src/gui/messagessearchlineedit.h index 0b1bf2a55..357269cfc 100755 --- a/src/gui/messagessearchlineedit.h +++ b/src/gui/messagessearchlineedit.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,16 +21,16 @@ #include "gui/baselineedit.h" - class PlainToolButton; class MessagesSearchLineEdit : public BaseLineEdit { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit MessagesSearchLineEdit(QWidget* parent = 0); - virtual ~MessagesSearchLineEdit(); + public: + + // Constructors and destructors. + explicit MessagesSearchLineEdit(QWidget* parent = 0); + virtual ~MessagesSearchLineEdit(); }; #endif // MESSAGESEARCHLINEEDIT_H diff --git a/src/gui/messagestoolbar.cpp b/src/gui/messagestoolbar.cpp index d44c5da55..12afed357 100755 --- a/src/gui/messagestoolbar.cpp +++ b/src/gui/messagestoolbar.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,139 +24,141 @@ #include "miscellaneous/iconfactory.h" #include "miscellaneous/settings.h" -#include -#include #include - +#include +#include MessagesToolBar::MessagesToolBar(const QString& title, QWidget* parent) - : BaseToolBar(title, parent) { - initializeSearchBox(); - initializeHighlighter(); + : BaseToolBar(title, parent) { + initializeSearchBox(); + initializeHighlighter(); } -MessagesToolBar::~MessagesToolBar() { -} +MessagesToolBar::~MessagesToolBar() {} QList MessagesToolBar::availableActions() const { - QList available_actions = qApp->userActions(); - available_actions.append(m_actionSearchMessages); - available_actions.append(m_actionMessageHighlighter); - return available_actions; + QList available_actions = qApp->userActions(); + available_actions.append(m_actionSearchMessages); + available_actions.append(m_actionMessageHighlighter); + return available_actions; } QList MessagesToolBar::changeableActions() const { - return actions(); + return actions(); } void MessagesToolBar::saveChangeableActions(const QStringList& actions) { - qApp->settings()->setValue(GROUP(GUI), GUI::MessagesToolbarDefaultButtons, actions.join(QSL(","))); - loadSpecificActions(getSpecificActions(actions)); + qApp->settings()->setValue(GROUP(GUI), GUI::MessagesToolbarDefaultButtons, actions.join(QSL(","))); + loadSpecificActions(getSpecificActions(actions)); - // If user hidden search messages box, then remove the filter. - if (!changeableActions().contains(m_actionSearchMessages)) { - m_txtSearchMessages->clear(); - } + // If user hidden search messages box, then remove the filter. + if (!changeableActions().contains(m_actionSearchMessages)) { + m_txtSearchMessages->clear(); + } } QList MessagesToolBar::getSpecificActions(const QStringList& actions) { - QList available_actions = availableActions(); - QList spec_actions; + QList available_actions = availableActions(); + QList spec_actions; - // Iterate action names and add respectable actions into the toolbar. - foreach (const QString& action_name, actions) { - QAction* matching_action = findMatchingAction(action_name, available_actions); + // Iterate action names and add respectable actions into the toolbar. + foreach (const QString& action_name, actions) { + QAction* matching_action = findMatchingAction(action_name, available_actions); - if (matching_action != nullptr) { - // Add existing standard action. - spec_actions.append(matching_action); - } - else if (action_name == SEPARATOR_ACTION_NAME) { - // Add new separator. - QAction* act = new QAction(this); - act->setSeparator(true); - spec_actions.append(act); - } - else if (action_name == SEACRH_MESSAGES_ACTION_NAME) { - // Add search box. - spec_actions.append(m_actionSearchMessages); - } - else if (action_name == HIGHLIGHTER_ACTION_NAME) { - // Add filter button. - spec_actions.append(m_actionMessageHighlighter); - } - else if (action_name == SPACER_ACTION_NAME) { - // Add new spacer. - QWidget* spacer = new QWidget(this); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - QWidgetAction* action = new QWidgetAction(this); - action->setDefaultWidget(spacer); - action->setIcon(qApp->icons()->fromTheme(QSL("go-jump"))); - action->setProperty("type", SPACER_ACTION_NAME); - action->setProperty("name", tr("Toolbar spacer")); - spec_actions.append(action); - } - } + if (matching_action != nullptr) { + // Add existing standard action. + spec_actions.append(matching_action); + } + else if (action_name == SEPARATOR_ACTION_NAME) { + // Add new separator. + QAction* act = new QAction(this); - return spec_actions; + act->setSeparator(true); + spec_actions.append(act); + } + else if (action_name == SEACRH_MESSAGES_ACTION_NAME) { + // Add search box. + spec_actions.append(m_actionSearchMessages); + } + else if (action_name == HIGHLIGHTER_ACTION_NAME) { + // Add filter button. + spec_actions.append(m_actionMessageHighlighter); + } + else if (action_name == SPACER_ACTION_NAME) { + // Add new spacer. + QWidget* spacer = new QWidget(this); + + spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + QWidgetAction* action = new QWidgetAction(this); + + action->setDefaultWidget(spacer); + action->setIcon(qApp->icons()->fromTheme(QSL("go-jump"))); + action->setProperty("type", SPACER_ACTION_NAME); + action->setProperty("name", tr("Toolbar spacer")); + spec_actions.append(action); + } + } + + return spec_actions; } void MessagesToolBar::loadSpecificActions(const QList& actions) { - clear(); + clear(); - foreach (QAction* act, actions) { - addAction(act); - } + foreach (QAction* act, actions) { + addAction(act); + } } void MessagesToolBar::handleMessageHighlighterChange(QAction* action) { - m_btnMessageHighlighter->setIcon(action->icon()); - m_btnMessageHighlighter->setToolTip(action->text()); - emit messageFilterChanged(action->data().value()); + m_btnMessageHighlighter->setIcon(action->icon()); + m_btnMessageHighlighter->setToolTip(action->text()); + emit messageFilterChanged(action->data().value()); } void MessagesToolBar::initializeSearchBox() { - m_txtSearchMessages = new MessagesSearchLineEdit(this); - m_txtSearchMessages->setFixedWidth(FILTER_WIDTH); - m_txtSearchMessages->setPlaceholderText(tr("Search messages")); - // Setup wrapping action for search box. - m_actionSearchMessages = new QWidgetAction(this); - m_actionSearchMessages->setDefaultWidget(m_txtSearchMessages); - m_actionSearchMessages->setIcon(qApp->icons()->fromTheme(QSL("system-search"))); - m_actionSearchMessages->setProperty("type", SEACRH_MESSAGES_ACTION_NAME); - m_actionSearchMessages->setProperty("name", tr("Message search box")); - connect(m_txtSearchMessages, &MessagesSearchLineEdit::textChanged, this, &MessagesToolBar::messageSearchPatternChanged); + m_txtSearchMessages = new MessagesSearchLineEdit(this); + m_txtSearchMessages->setFixedWidth(FILTER_WIDTH); + m_txtSearchMessages->setPlaceholderText(tr("Search messages")); + + // Setup wrapping action for search box. + m_actionSearchMessages = new QWidgetAction(this); + m_actionSearchMessages->setDefaultWidget(m_txtSearchMessages); + m_actionSearchMessages->setIcon(qApp->icons()->fromTheme(QSL("system-search"))); + m_actionSearchMessages->setProperty("type", SEACRH_MESSAGES_ACTION_NAME); + m_actionSearchMessages->setProperty("name", tr("Message search box")); + connect(m_txtSearchMessages, &MessagesSearchLineEdit::textChanged, this, &MessagesToolBar::messageSearchPatternChanged); } void MessagesToolBar::initializeHighlighter() { - m_menuMessageHighlighter = new QMenu(tr("Menu for highlighting messages"), this); - m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-read")), - tr("No extra highlighting"))->setData(QVariant::fromValue(MessagesModel::NoHighlighting)); - m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-unread")), - tr("Highlight unread messages"))->setData(QVariant::fromValue(MessagesModel::HighlightUnread)); - m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-important")), - tr("Highlight important messages"))->setData(QVariant::fromValue(MessagesModel::HighlightImportant)); - m_btnMessageHighlighter = new QToolButton(this); - m_btnMessageHighlighter->setToolTip(tr("Display all messages")); - m_btnMessageHighlighter->setMenu(m_menuMessageHighlighter); - m_btnMessageHighlighter->setPopupMode(QToolButton::MenuButtonPopup); - m_btnMessageHighlighter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read"))); - m_actionMessageHighlighter = new QWidgetAction(this); - m_actionMessageHighlighter->setDefaultWidget(m_btnMessageHighlighter); - m_actionMessageHighlighter->setIcon(m_btnMessageHighlighter->icon()); - m_actionMessageHighlighter->setProperty("type", HIGHLIGHTER_ACTION_NAME); - m_actionMessageHighlighter->setProperty("name", tr("Message highlighter")); - connect(m_menuMessageHighlighter, SIGNAL(triggered(QAction*)), - this, SLOT(handleMessageHighlighterChange(QAction*))); + m_menuMessageHighlighter = new QMenu(tr("Menu for highlighting messages"), this); + m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-read")), + tr("No extra highlighting"))->setData(QVariant::fromValue(MessagesModel::NoHighlighting)); + m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-unread")), + tr("Highlight unread messages"))->setData(QVariant::fromValue(MessagesModel::HighlightUnread)); + m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-important")), + tr("Highlight important messages"))->setData(QVariant::fromValue(MessagesModel::HighlightImportant)); + m_btnMessageHighlighter = new QToolButton(this); + m_btnMessageHighlighter->setToolTip(tr("Display all messages")); + m_btnMessageHighlighter->setMenu(m_menuMessageHighlighter); + m_btnMessageHighlighter->setPopupMode(QToolButton::MenuButtonPopup); + m_btnMessageHighlighter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read"))); + m_actionMessageHighlighter = new QWidgetAction(this); + m_actionMessageHighlighter->setDefaultWidget(m_btnMessageHighlighter); + m_actionMessageHighlighter->setIcon(m_btnMessageHighlighter->icon()); + m_actionMessageHighlighter->setProperty("type", HIGHLIGHTER_ACTION_NAME); + m_actionMessageHighlighter->setProperty("name", tr("Message highlighter")); + connect(m_menuMessageHighlighter, SIGNAL(triggered(QAction*)), + this, SLOT(handleMessageHighlighterChange(QAction*))); } QStringList MessagesToolBar::defaultActions() const { - return QString(GUI::MessagesToolbarDefaultButtonsDef).split(',', - QString::SkipEmptyParts); + return QString(GUI::MessagesToolbarDefaultButtonsDef).split(',', + QString::SkipEmptyParts); } QStringList MessagesToolBar::savedActions() const { - return qApp->settings()->value(GROUP(GUI), - SETTING(GUI::MessagesToolbarDefaultButtons)).toString().split(',', - QString::SkipEmptyParts); + return qApp->settings()->value(GROUP(GUI), + SETTING(GUI::MessagesToolbarDefaultButtons)).toString().split(',', + QString::SkipEmptyParts); } diff --git a/src/gui/messagestoolbar.h b/src/gui/messagestoolbar.h index 12c2d2b38..9fbd92db7 100755 --- a/src/gui/messagestoolbar.h +++ b/src/gui/messagestoolbar.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,61 +23,62 @@ #include "core/messagesmodel.h" - class MessagesSearchLineEdit; class QWidgetAction; class QToolButton; class QMenu; class MessagesToolBar : public BaseToolBar { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit MessagesToolBar(const QString& title, QWidget* parent = 0); - virtual ~MessagesToolBar(); + public: - // External access to search line edit. - inline MessagesSearchLineEdit* searchLineEdit() { - return m_txtSearchMessages; - } + // Constructors and destructors. + explicit MessagesToolBar(const QString& title, QWidget* parent = 0); + virtual ~MessagesToolBar(); - // Implementation of BaseToolBar interface. - QList availableActions() const; - QList changeableActions() const; - void saveChangeableActions(const QStringList& actions); + // External access to search line edit. + inline MessagesSearchLineEdit* searchLineEdit() { + return m_txtSearchMessages; + } - // Loads actions as specified by external actions list. - // NOTE: This is used primarily for reloading actions - // when they are changed from settings. - void loadSpecificActions(const QList& actions); + // Implementation of BaseToolBar interface. + QList availableActions() const; - QList getSpecificActions(const QStringList& actions); + QList changeableActions() const; + void saveChangeableActions(const QStringList& actions); - QStringList defaultActions() const; - QStringList savedActions() const; + // Loads actions as specified by external actions list. + // NOTE: This is used primarily for reloading actions + // when they are changed from settings. + void loadSpecificActions(const QList& actions); - signals: - void messageSearchPatternChanged(const QString& pattern); + QList getSpecificActions(const QStringList& actions); - // Emitted if message filter is changed. - void messageFilterChanged(MessagesModel::MessageHighlighter filter); + QStringList defaultActions() const; + QStringList savedActions() const; - private slots: - // Called when highlighter gets changed. - void handleMessageHighlighterChange(QAction* action); + signals: + void messageSearchPatternChanged(const QString& pattern); - private: - void initializeSearchBox(); - void initializeHighlighter(); + // Emitted if message filter is changed. + void messageFilterChanged(MessagesModel::MessageHighlighter filter); - private: - QWidgetAction* m_actionMessageHighlighter; - QToolButton* m_btnMessageHighlighter; - QMenu* m_menuMessageHighlighter; + private slots: - QWidgetAction* m_actionSearchMessages; - MessagesSearchLineEdit* m_txtSearchMessages; + // Called when highlighter gets changed. + void handleMessageHighlighterChange(QAction* action); + + private: + void initializeSearchBox(); + void initializeHighlighter(); + + private: + QWidgetAction* m_actionMessageHighlighter; + QToolButton* m_btnMessageHighlighter; + QMenu* m_menuMessageHighlighter; + QWidgetAction* m_actionSearchMessages; + MessagesSearchLineEdit* m_txtSearchMessages; }; #endif // NEWSTOOLBAR_H diff --git a/src/gui/messagesview.cpp b/src/gui/messagesview.cpp index a90b16150..77c2198fb 100755 --- a/src/gui/messagesview.cpp +++ b/src/gui/messagesview.cpp @@ -211,7 +211,9 @@ void MessagesView::initializeContextMenu() { } m_contextMenu->addMenu(menu); - m_contextMenu->addActions(QList() << qApp->mainForm()->m_ui->m_actionSendMessageViaEmail << qApp->mainForm()->m_ui->m_actionOpenSelectedSourceArticlesExternally << qApp->mainForm()->m_ui->m_actionOpenSelectedMessagesInternally << qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsRead << qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsUnread << qApp->mainForm()->m_ui->m_actionSwitchImportanceOfSelectedMessages << qApp->mainForm()->m_ui->m_actionDeleteSelectedMessages); + m_contextMenu->addActions( + QList() << qApp->mainForm()->m_ui->m_actionSendMessageViaEmail << qApp->mainForm()->m_ui->m_actionOpenSelectedSourceArticlesExternally << qApp->mainForm()->m_ui->m_actionOpenSelectedMessagesInternally << qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsRead << qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsUnread << qApp->mainForm()->m_ui->m_actionSwitchImportanceOfSelectedMessages << + qApp->mainForm()->m_ui->m_actionDeleteSelectedMessages); if (m_sourceModel->loadedItem() != nullptr && m_sourceModel->loadedItem()->kind() == RootItemKind::Bin) { m_contextMenu->addAction(qApp->mainForm()->m_ui->m_actionRestoreSelectedMessages); @@ -267,7 +269,11 @@ void MessagesView::selectionChanged(const QItemSelection& selected, const QItemS const QModelIndex current_index = currentIndex(); const QModelIndex mapped_current_index = m_proxyModel->mapToSource(current_index); - qDebug("Current row changed - row [%d,%d] source [%d, %d].",current_index.row(), current_index.column(),mapped_current_index.row(), mapped_current_index.column()); + qDebug("Current row changed - row [%d,%d] source [%d, %d].", + current_index.row(), + current_index.column(), + mapped_current_index.row(), + mapped_current_index.column()); if (mapped_current_index.isValid() && selected_rows.count() > 0) { Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()); @@ -310,7 +316,9 @@ void MessagesView::openSelectedSourceMessagesExternally() { const QString link = m_sourceModel->messageAt(m_proxyModel->mapToSource(index).row()).m_url; if (!qApp->web()->openUrlInExternalBrowser(link)) { - qApp->showGuiMessage(tr("Problem with starting external web browser"),tr("External web browser could not be started."),QSystemTrayIcon::Critical); + qApp->showGuiMessage(tr("Problem with starting external web browser"), + tr("External web browser could not be started."), + QSystemTrayIcon::Critical); return; } } @@ -338,7 +346,8 @@ void MessagesView::sendSelectedMessageViaEmail() { const Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(selectionModel()->selectedRows().at(0)).row()); if (!qApp->web()->sendMessageViaEmail(message)) { - MessageBox::show(this,QMessageBox::Critical,tr("Problem with starting external e-mail client"),tr("External e-mail client could not be started.")); + MessageBox::show(this, QMessageBox::Critical, tr("Problem with starting external e-mail client"), + tr("External e-mail client could not be started.")); } } } @@ -520,7 +529,9 @@ void MessagesView::openSelectedMessagesWithExternalTool() { if (!link.isEmpty()) { if (!QProcess::startDetached(tool.executable(), QStringList() << tool.parameters() << link)) { - qApp->showGuiMessage(tr("Cannot run external tool"), tr("External tool '%1' could not be started.").arg(tool.executable()),QSystemTrayIcon::Critical); + qApp->showGuiMessage(tr("Cannot run external tool"), + tr("External tool '%1' could not be started.").arg(tool.executable()), + QSystemTrayIcon::Critical); } } } diff --git a/src/gui/messagetextbrowser.cpp b/src/gui/messagetextbrowser.cpp index 318f5100c..7a7067403 100755 --- a/src/gui/messagetextbrowser.cpp +++ b/src/gui/messagetextbrowser.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,31 +22,28 @@ #include "miscellaneous/iconfactory.h" #include "network-web/networkfactory.h" +MessageTextBrowser::MessageTextBrowser(QWidget* parent) : QTextBrowser(parent) {} -MessageTextBrowser::MessageTextBrowser(QWidget* parent) : QTextBrowser(parent) { -} - -MessageTextBrowser::~MessageTextBrowser() { -} +MessageTextBrowser::~MessageTextBrowser() {} QVariant MessageTextBrowser::loadResource(int type, const QUrl& name) { - Q_UNUSED(name) + Q_UNUSED(name) - switch (type) { - case QTextDocument::ImageResource: { - if (m_imagePlaceholder.isNull()) { - m_imagePlaceholder = qApp->icons()->miscPixmap(QSL("image-placeholder")).scaledToWidth(20, Qt::FastTransformation); - } + switch (type) { + case QTextDocument::ImageResource: { + if (m_imagePlaceholder.isNull()) { + m_imagePlaceholder = qApp->icons()->miscPixmap(QSL("image-placeholder")).scaledToWidth(20, Qt::FastTransformation); + } - return m_imagePlaceholder; - } + return m_imagePlaceholder; + } - default: - return QTextBrowser::loadResource(type, name); - } + default: + return QTextBrowser::loadResource(type, name); + } } void MessageTextBrowser::wheelEvent(QWheelEvent* e) { - QTextBrowser::wheelEvent(e); - qApp->settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, font().toString()); + QTextBrowser::wheelEvent(e); + qApp->settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, font().toString()); } diff --git a/src/gui/messagetextbrowser.h b/src/gui/messagetextbrowser.h index 41be0c620..f729789af 100755 --- a/src/gui/messagetextbrowser.h +++ b/src/gui/messagetextbrowser.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,21 +21,20 @@ #include - class MessageTextBrowser : public QTextBrowser { - Q_OBJECT + Q_OBJECT - public: - explicit MessageTextBrowser(QWidget* parent = 0); - virtual ~MessageTextBrowser(); + public: + explicit MessageTextBrowser(QWidget* parent = 0); + virtual ~MessageTextBrowser(); - QVariant loadResource(int type, const QUrl& name); + QVariant loadResource(int type, const QUrl& name); - protected: - void wheelEvent(QWheelEvent* e); + protected: + void wheelEvent(QWheelEvent* e); - private: - QPixmap m_imagePlaceholder; + private: + QPixmap m_imagePlaceholder; }; #endif // MESSAGETEXTBROWSER_H diff --git a/src/gui/newspaperpreviewer.cpp b/src/gui/newspaperpreviewer.cpp index 0c3c61b79..98e743351 100755 --- a/src/gui/newspaperpreviewer.cpp +++ b/src/gui/newspaperpreviewer.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,47 +18,46 @@ #include "gui/newspaperpreviewer.h" -#include "gui/messagepreviewer.h" #include "gui/dialogs/formmain.h" +#include "gui/messagepreviewer.h" #include "miscellaneous/application.h" #include - NewspaperPreviewer::NewspaperPreviewer(RootItem* root, QList messages, QWidget* parent) - : TabContent(parent), m_ui(new Ui::NewspaperPreviewer), m_root(root), m_messages(messages) { - m_ui->setupUi(this); - connect(m_ui->m_btnShowMoreMessages, &QPushButton::clicked, this, &NewspaperPreviewer::showMoreMessages); - showMoreMessages(); + : TabContent(parent), m_ui(new Ui::NewspaperPreviewer), m_root(root), m_messages(messages) { + m_ui->setupUi(this); + connect(m_ui->m_btnShowMoreMessages, &QPushButton::clicked, this, &NewspaperPreviewer::showMoreMessages); + showMoreMessages(); } -NewspaperPreviewer::~NewspaperPreviewer() { -} +NewspaperPreviewer::~NewspaperPreviewer() {} void NewspaperPreviewer::showMoreMessages() { - if (!m_root.isNull()) { - int current_scroll = m_ui->scrollArea->verticalScrollBar()->value(); + if (!m_root.isNull()) { + int current_scroll = m_ui->scrollArea->verticalScrollBar()->value(); - for (int i = 0; i < 10 && !m_messages.isEmpty(); i++) { - Message msg = m_messages.takeFirst(); - MessagePreviewer* prev = new MessagePreviewer(this); - QMargins margins = prev->layout()->contentsMargins(); - connect(prev, &MessagePreviewer::requestMessageListReload, this, &NewspaperPreviewer::requestMessageListReload); - margins.setRight(0); - prev->layout()->setContentsMargins(margins); - prev->setFixedHeight(300); - prev->loadMessage(msg, m_root); - m_ui->m_layout->insertWidget(m_ui->m_layout->count() - 2, prev); - } + for (int i = 0; i < 10 && !m_messages.isEmpty(); i++) { + Message msg = m_messages.takeFirst(); + MessagePreviewer* prev = new MessagePreviewer(this); + QMargins margins = prev->layout()->contentsMargins(); - m_ui->m_btnShowMoreMessages->setText(tr("Show more messages (%n remaining)", "", m_messages.size())); - m_ui->m_btnShowMoreMessages->setEnabled(!m_messages.isEmpty()); - m_ui->scrollArea->verticalScrollBar()->setValue(current_scroll); - } - else { - qApp->showGuiMessage(tr("Cannot show more messages"), - tr("Cannot show more messages because parent feed was removed."), - QSystemTrayIcon::Warning, - qApp->mainForm(), true); - } + connect(prev, &MessagePreviewer::requestMessageListReload, this, &NewspaperPreviewer::requestMessageListReload); + margins.setRight(0); + prev->layout()->setContentsMargins(margins); + prev->setFixedHeight(300); + prev->loadMessage(msg, m_root); + m_ui->m_layout->insertWidget(m_ui->m_layout->count() - 2, prev); + } + + m_ui->m_btnShowMoreMessages->setText(tr("Show more messages (%n remaining)", "", m_messages.size())); + m_ui->m_btnShowMoreMessages->setEnabled(!m_messages.isEmpty()); + m_ui->scrollArea->verticalScrollBar()->setValue(current_scroll); + } + else { + qApp->showGuiMessage(tr("Cannot show more messages"), + tr("Cannot show more messages because parent feed was removed."), + QSystemTrayIcon::Warning, + qApp->mainForm(), true); + } } diff --git a/src/gui/newspaperpreviewer.h b/src/gui/newspaperpreviewer.h index 3f52ae0da..2e88a8244 100755 --- a/src/gui/newspaperpreviewer.h +++ b/src/gui/newspaperpreviewer.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -29,30 +30,29 @@ #include - namespace Ui { - class NewspaperPreviewer; + class NewspaperPreviewer; } class RootItem; class NewspaperPreviewer : public TabContent { - Q_OBJECT + Q_OBJECT - public: - explicit NewspaperPreviewer(RootItem* root, QList messages, QWidget* parent = 0); - virtual ~NewspaperPreviewer(); + public: + explicit NewspaperPreviewer(RootItem* root, QList messages, QWidget* parent = 0); + virtual ~NewspaperPreviewer(); - private slots: - void showMoreMessages(); + private slots: + void showMoreMessages(); - signals: - void requestMessageListReload(bool mark_current_as_read); + signals: + void requestMessageListReload(bool mark_current_as_read); - private: - QScopedPointer m_ui; - QPointer m_root; - QList m_messages; + private: + QScopedPointer m_ui; + QPointer m_root; + QList m_messages; }; #endif // NEWSPAPERPREVIEWER_H diff --git a/src/gui/plaintoolbutton.cpp b/src/gui/plaintoolbutton.cpp index c0de956a8..27c3f73de 100755 --- a/src/gui/plaintoolbutton.cpp +++ b/src/gui/plaintoolbutton.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,63 +18,61 @@ #include "gui/plaintoolbutton.h" -#include -#include +#include #include #include +#include #include -#include +#include +PlainToolButton::PlainToolButton(QWidget* parent) : QToolButton(parent), m_padding(0) {} -PlainToolButton::PlainToolButton(QWidget* parent) : QToolButton(parent), m_padding(0) { -} - -PlainToolButton::~PlainToolButton() { -} +PlainToolButton::~PlainToolButton() {} void PlainToolButton::paintEvent(QPaintEvent* e) { - Q_UNUSED(e) - QPainter p(this); - QRect rect(QPoint(0, 0), size()); - // Set padding. - rect.adjust(m_padding, m_padding, -m_padding, -m_padding); + Q_UNUSED(e) + QPainter p(this); + QRect rect(QPoint(0, 0), size()); - if (isEnabled()) { - if (underMouse() || isChecked()) { - p.setOpacity(0.7); - } - } - else { - p.setOpacity(0.3); - } + // Set padding. + rect.adjust(m_padding, m_padding, -m_padding, -m_padding); - icon().paint(&p, rect); + if (isEnabled()) { + if (underMouse() || isChecked()) { + p.setOpacity(0.7); + } + } + else { + p.setOpacity(0.3); + } + + icon().paint(&p, rect); } int PlainToolButton::padding() const { - return m_padding; + return m_padding; } void PlainToolButton::setPadding(int padding) { - m_padding = padding; - repaint(); + m_padding = padding; + repaint(); } void PlainToolButton::setChecked(bool checked) { - QToolButton::setChecked(checked); - repaint(); + QToolButton::setChecked(checked); + repaint(); } void PlainToolButton::reactOnActionChange(QAction* action) { - if (action != nullptr) { - setEnabled(action->isEnabled()); - setCheckable(action->isCheckable()); - setChecked(action->isChecked()); - setIcon(action->icon()); - setToolTip(action->toolTip()); - } + if (action != nullptr) { + setEnabled(action->isEnabled()); + setCheckable(action->isCheckable()); + setChecked(action->isChecked()); + setIcon(action->icon()); + setToolTip(action->toolTip()); + } } void PlainToolButton::reactOnSenderActionChange() { - reactOnActionChange(qobject_cast(sender())); + reactOnActionChange(qobject_cast(sender())); } diff --git a/src/gui/plaintoolbutton.h b/src/gui/plaintoolbutton.h index 690e1c8de..0b4dccee9 100755 --- a/src/gui/plaintoolbutton.h +++ b/src/gui/plaintoolbutton.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,30 +21,31 @@ #include - class PlainToolButton : public QToolButton { - Q_OBJECT + Q_OBJECT - public: - // Contructors and destructors. - explicit PlainToolButton(QWidget* parent = 0); - virtual ~PlainToolButton(); + public: - // Padding changers. - int padding() const; - void setPadding(int padding); + // Contructors and destructors. + explicit PlainToolButton(QWidget* parent = 0); + virtual ~PlainToolButton(); - public slots: - void setChecked(bool checked); - void reactOnActionChange(QAction* action); - void reactOnSenderActionChange(); + // Padding changers. + int padding() const; + void setPadding(int padding); - protected: - // Custom look. - void paintEvent(QPaintEvent* e); + public slots: + void setChecked(bool checked); + void reactOnActionChange(QAction* action); + void reactOnSenderActionChange(); - private: - int m_padding; + protected: + + // Custom look. + void paintEvent(QPaintEvent* e); + + private: + int m_padding; }; #endif // CLOSEBUTTON_H diff --git a/src/gui/settings/settingsbrowsermail.cpp b/src/gui/settings/settingsbrowsermail.cpp index 5a352f2b4..814b45511 100755 --- a/src/gui/settings/settingsbrowsermail.cpp +++ b/src/gui/settings/settingsbrowsermail.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,61 +18,61 @@ #include "gui/settings/settingsbrowsermail.h" -#include "network-web/silentnetworkaccessmanager.h" -#include "miscellaneous/application.h" -#include "miscellaneous/textfactory.h" #include "gui/guiutilities.h" +#include "miscellaneous/application.h" #include "miscellaneous/externaltool.h" +#include "miscellaneous/textfactory.h" +#include "network-web/silentnetworkaccessmanager.h" -#include #include #include - +#include SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent), m_ui(new Ui::SettingsBrowserMail) { - m_ui->setupUi(this); + m_ui->setupUi(this); - GuiUtilities::setLabelAsNotice(*m_ui->label, false); - GuiUtilities::setLabelAsNotice(*m_ui->m_lblExternalEmailInfo, false); - GuiUtilities::setLabelAsNotice(*m_ui->m_lblProxyInfo, false); + GuiUtilities::setLabelAsNotice(*m_ui->label, false); + GuiUtilities::setLabelAsNotice(*m_ui->m_lblExternalEmailInfo, false); + GuiUtilities::setLabelAsNotice(*m_ui->m_lblProxyInfo, false); GuiUtilities::setLabelAsNotice(*m_ui->m_lblToolInfo, false); #if defined(USE_WEBENGINE) - m_ui->m_checkOpenLinksInExternal->setVisible(false); + m_ui->m_checkOpenLinksInExternal->setVisible(false); #else - connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings); #endif m_ui->m_listTools->setHeaderLabels(QStringList() << tr("Executable") << tr("Parameters")); m_ui->m_listTools->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); - connect(m_ui->m_cmbProxyType, static_cast(&QComboBox::currentIndexChanged), this, - &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_txtProxyHost, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_txtProxyPassword, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_txtProxyUsername, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_spinProxyPort, static_cast(&QSpinBox::valueChanged), this, &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_grpCustomExternalBrowser, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_grpCustomExternalEmail, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_txtExternalBrowserArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_txtExternalBrowserExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_txtExternalEmailArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_txtExternalEmailExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); - connect(m_ui->m_cmbProxyType, static_cast(&QComboBox::currentIndexChanged), this, - &SettingsBrowserMail::onProxyTypeChanged); - connect(m_ui->m_checkShowPassword, &QCheckBox::stateChanged, this, &SettingsBrowserMail::displayProxyPassword); - connect(m_ui->m_cmbExternalBrowserPreset, static_cast(&QComboBox::currentIndexChanged), this, - &SettingsBrowserMail::changeDefaultBrowserArguments); - connect(m_ui->m_btnExternalBrowserExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectBrowserExecutable); - connect(m_ui->m_cmbExternalEmailPreset, static_cast(&QComboBox::currentIndexChanged), this, - &SettingsBrowserMail::changeDefaultEmailArguments); - connect(m_ui->m_btnExternalEmailExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectEmailExecutable); + connect(m_ui->m_cmbProxyType, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_txtProxyHost, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_txtProxyPassword, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_txtProxyUsername, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_spinProxyPort, static_cast(&QSpinBox::valueChanged), this, + &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_grpCustomExternalBrowser, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_grpCustomExternalEmail, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_txtExternalBrowserArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_txtExternalBrowserExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_txtExternalEmailArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_txtExternalEmailExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); + connect(m_ui->m_cmbProxyType, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsBrowserMail::onProxyTypeChanged); + connect(m_ui->m_checkShowPassword, &QCheckBox::stateChanged, this, &SettingsBrowserMail::displayProxyPassword); + connect(m_ui->m_cmbExternalBrowserPreset, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsBrowserMail::changeDefaultBrowserArguments); + connect(m_ui->m_btnExternalBrowserExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectBrowserExecutable); + connect(m_ui->m_cmbExternalEmailPreset, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsBrowserMail::changeDefaultEmailArguments); + connect(m_ui->m_btnExternalEmailExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectEmailExecutable); connect(m_ui->m_btnAddTool, &QPushButton::clicked, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_btnDeleteTool, &QPushButton::clicked, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_btnAddTool, &QPushButton::clicked, this, &SettingsBrowserMail::addExternalTool); connect(m_ui->m_btnDeleteTool, &QPushButton::clicked, this, &SettingsBrowserMail::deleteSelectedExternalTool); - connect(m_ui->m_listTools, &QTreeWidget::currentItemChanged, [this](QTreeWidgetItem * current, QTreeWidgetItem * previous) { + connect(m_ui->m_listTools, &QTreeWidget::currentItemChanged, [this](QTreeWidgetItem* current, QTreeWidgetItem* previous) { Q_UNUSED(previous) m_ui->m_btnDeleteTool->setEnabled(current != nullptr); @@ -79,52 +80,54 @@ SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent) } SettingsBrowserMail::~SettingsBrowserMail() { - delete m_ui; + delete m_ui; } void SettingsBrowserMail::changeDefaultBrowserArguments(int index) { - if (index != 0) { - m_ui->m_txtExternalBrowserArguments->setText(m_ui->m_cmbExternalBrowserPreset->itemData(index).toString()); - } + if (index != 0) { + m_ui->m_txtExternalBrowserArguments->setText(m_ui->m_cmbExternalBrowserPreset->itemData(index).toString()); + } } void SettingsBrowserMail::selectBrowserExecutable() { - const QString executable_file = QFileDialog::getOpenFileName(this, - tr("Select web browser executable"), - qApp->homeFolder(), - //: File filter for external browser selection dialog. + const QString executable_file = QFileDialog::getOpenFileName(this, + tr("Select web browser executable"), + qApp->homeFolder(), + + //: File filter for external browser selection dialog. #if defined(Q_OS_LINUX) - tr("Executables (*)")); + tr("Executables (*)")); #else - tr("Executables (*.*)")); + tr("Executables (*.*)")); #endif - if (!executable_file.isEmpty()) { - m_ui->m_txtExternalBrowserExecutable->setText(QDir::toNativeSeparators(executable_file)); - } + if (!executable_file.isEmpty()) { + m_ui->m_txtExternalBrowserExecutable->setText(QDir::toNativeSeparators(executable_file)); + } } void SettingsBrowserMail::displayProxyPassword(int state) { - if (state == Qt::Checked) { - m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::Normal); - } - else { - m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit); - } + if (state == Qt::Checked) { + m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::Normal); + } + else { + m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit); + } } void SettingsBrowserMail::onProxyTypeChanged(int index) { - const QNetworkProxy::ProxyType selected_type = static_cast(m_ui->m_cmbProxyType->itemData(index).toInt()); - const bool is_proxy_selected = selected_type != QNetworkProxy::NoProxy && selected_type != QNetworkProxy::DefaultProxy; - m_ui->m_txtProxyHost->setEnabled(is_proxy_selected); - m_ui->m_txtProxyPassword->setEnabled(is_proxy_selected); - m_ui->m_txtProxyUsername->setEnabled(is_proxy_selected); - m_ui->m_spinProxyPort->setEnabled(is_proxy_selected); - m_ui->m_checkShowPassword->setEnabled(is_proxy_selected); - m_ui->m_lblProxyHost->setEnabled(is_proxy_selected); - m_ui->m_lblProxyInfo->setEnabled(is_proxy_selected); - m_ui->m_lblProxyPassword->setEnabled(is_proxy_selected); - m_ui->m_lblProxyPort->setEnabled(is_proxy_selected); + const QNetworkProxy::ProxyType selected_type = static_cast(m_ui->m_cmbProxyType->itemData(index).toInt()); + const bool is_proxy_selected = selected_type != QNetworkProxy::NoProxy && selected_type != QNetworkProxy::DefaultProxy; + + m_ui->m_txtProxyHost->setEnabled(is_proxy_selected); + m_ui->m_txtProxyPassword->setEnabled(is_proxy_selected); + m_ui->m_txtProxyUsername->setEnabled(is_proxy_selected); + m_ui->m_spinProxyPort->setEnabled(is_proxy_selected); + m_ui->m_checkShowPassword->setEnabled(is_proxy_selected); + m_ui->m_lblProxyHost->setEnabled(is_proxy_selected); + m_ui->m_lblProxyInfo->setEnabled(is_proxy_selected); + m_ui->m_lblProxyPassword->setEnabled(is_proxy_selected); + m_ui->m_lblProxyPort->setEnabled(is_proxy_selected); m_ui->m_lblProxyUsername->setEnabled(is_proxy_selected); } @@ -142,6 +145,7 @@ void SettingsBrowserMail::setExternalTools(const QList& list) { foreach (const ExternalTool& tool, list) { QTreeWidgetItem* item = new QTreeWidgetItem(m_ui->m_listTools, QStringList() << tool.executable() << tool.parameters().join(QL1C(' '))); + item->setData(0, Qt::UserRole, QVariant::fromValue(tool)); m_ui->m_listTools->addTopLevelItem(item); @@ -149,94 +153,96 @@ void SettingsBrowserMail::setExternalTools(const QList& list) { } void SettingsBrowserMail::changeDefaultEmailArguments(int index) { - if (index != 0) { - m_ui->m_txtExternalEmailArguments->setText(m_ui->m_cmbExternalEmailPreset->itemData(index).toString()); - } + if (index != 0) { + m_ui->m_txtExternalEmailArguments->setText(m_ui->m_cmbExternalEmailPreset->itemData(index).toString()); + } } void SettingsBrowserMail::selectEmailExecutable() { - QString executable_file = QFileDialog::getOpenFileName(this, - tr("Select e-mail executable"), - qApp->homeFolder(), - //: File filter for external e-mail selection dialog. + QString executable_file = QFileDialog::getOpenFileName(this, + tr("Select e-mail executable"), + qApp->homeFolder(), + + //: File filter for external e-mail selection dialog. #if defined(Q_OS_LINUX) - tr("Executables (*)")); + tr("Executables (*)")); #else - tr("Executables (*.*)")); + tr("Executables (*.*)")); #endif - if (!executable_file.isEmpty()) { - m_ui->m_txtExternalEmailExecutable->setText(QDir::toNativeSeparators(executable_file)); - } + if (!executable_file.isEmpty()) { + m_ui->m_txtExternalEmailExecutable->setText(QDir::toNativeSeparators(executable_file)); + } } void SettingsBrowserMail::loadSettings() { - onBeginLoadSettings(); + onBeginLoadSettings(); #if !defined(USE_WEBENGINE) - m_ui->m_checkOpenLinksInExternal->setChecked(settings()->value(GROUP(Browser), - SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool()); + m_ui->m_checkOpenLinksInExternal->setChecked(settings()->value(GROUP(Browser), + SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool()); #endif // Load settings of web browser GUI. - m_ui->m_cmbExternalBrowserPreset->addItem(tr("Opera 12 or older"), QSL("-nosession %1")); - m_ui->m_txtExternalBrowserExecutable->setText(settings()->value(GROUP(Browser), - SETTING(Browser::CustomExternalBrowserExecutable)).toString()); - m_ui->m_txtExternalBrowserArguments->setText(settings()->value(GROUP(Browser), - SETTING(Browser::CustomExternalBrowserArguments)).toString()); - m_ui->m_grpCustomExternalBrowser->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserEnabled)).toBool()); + m_ui->m_cmbExternalBrowserPreset->addItem(tr("Opera 12 or older"), QSL("-nosession %1")); + m_ui->m_txtExternalBrowserExecutable->setText(settings()->value(GROUP(Browser), + SETTING(Browser::CustomExternalBrowserExecutable)).toString()); + m_ui->m_txtExternalBrowserArguments->setText(settings()->value(GROUP(Browser), + SETTING(Browser::CustomExternalBrowserArguments)).toString()); + m_ui->m_grpCustomExternalBrowser->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserEnabled)).toBool()); // Load settings of e-mail. - m_ui->m_cmbExternalEmailPreset->addItem(tr("Mozilla Thunderbird"), QSL("-compose \"subject='%1',body='%2'\"")); - m_ui->m_txtExternalEmailExecutable->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailExecutable)).toString()); - m_ui->m_txtExternalEmailArguments->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString()); - m_ui->m_grpCustomExternalEmail->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool()); - m_ui->m_cmbProxyType->addItem(tr("No proxy"), QNetworkProxy::NoProxy); - m_ui->m_cmbProxyType->addItem(tr("System proxy"), QNetworkProxy::DefaultProxy); - m_ui->m_cmbProxyType->addItem(tr("Socks5"), QNetworkProxy::Socks5Proxy); - m_ui->m_cmbProxyType->addItem(tr("Http"), QNetworkProxy::HttpProxy); + m_ui->m_cmbExternalEmailPreset->addItem(tr("Mozilla Thunderbird"), QSL("-compose \"subject='%1',body='%2'\"")); + m_ui->m_txtExternalEmailExecutable->setText(settings()->value(GROUP(Browser), + SETTING(Browser::CustomExternalEmailExecutable)).toString()); + m_ui->m_txtExternalEmailArguments->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString()); + m_ui->m_grpCustomExternalEmail->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool()); + m_ui->m_cmbProxyType->addItem(tr("No proxy"), QNetworkProxy::NoProxy); + m_ui->m_cmbProxyType->addItem(tr("System proxy"), QNetworkProxy::DefaultProxy); + m_ui->m_cmbProxyType->addItem(tr("Socks5"), QNetworkProxy::Socks5Proxy); + m_ui->m_cmbProxyType->addItem(tr("Http"), QNetworkProxy::HttpProxy); // Load the settings. - QNetworkProxy::ProxyType selected_proxy_type = static_cast(settings()->value(GROUP(Proxy), - SETTING(Proxy::Type)).toInt()); - m_ui->m_cmbProxyType->setCurrentIndex(m_ui->m_cmbProxyType->findData(selected_proxy_type)); - m_ui->m_txtProxyHost->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Host)).toString()); - m_ui->m_txtProxyUsername->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Username)).toString()); - m_ui->m_txtProxyPassword->setText(TextFactory::decrypt(settings()->value(GROUP(Proxy), SETTING(Proxy::Password)).toString())); - m_ui->m_spinProxyPort->setValue(settings()->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt()); + QNetworkProxy::ProxyType selected_proxy_type = static_cast(settings()->value(GROUP(Proxy), + SETTING(Proxy::Type)).toInt()); + m_ui->m_cmbProxyType->setCurrentIndex(m_ui->m_cmbProxyType->findData(selected_proxy_type)); + m_ui->m_txtProxyHost->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Host)).toString()); + m_ui->m_txtProxyUsername->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Username)).toString()); + m_ui->m_txtProxyPassword->setText(TextFactory::decrypt(settings()->value(GROUP(Proxy), SETTING(Proxy::Password)).toString())); + m_ui->m_spinProxyPort->setValue(settings()->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt()); setExternalTools(ExternalTool::toolsFromSettings()); - onEndLoadSettings(); + onEndLoadSettings(); } void SettingsBrowserMail::saveSettings() { - onBeginSaveSettings(); + onBeginSaveSettings(); #if !defined(USE_WEBENGINE) - settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, m_ui->m_checkOpenLinksInExternal->isChecked()); + settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, m_ui->m_checkOpenLinksInExternal->isChecked()); #endif // Save settings of GUI of web browser. - settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserEnabled, m_ui->m_grpCustomExternalBrowser->isChecked()); - settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserExecutable, m_ui->m_txtExternalBrowserExecutable->text()); - settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserArguments, m_ui->m_txtExternalBrowserArguments->text()); + settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserEnabled, m_ui->m_grpCustomExternalBrowser->isChecked()); + settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserExecutable, m_ui->m_txtExternalBrowserExecutable->text()); + settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserArguments, m_ui->m_txtExternalBrowserArguments->text()); // Save settings of e-mail. - settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailExecutable, m_ui->m_txtExternalEmailExecutable->text()); - settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailArguments, m_ui->m_txtExternalEmailArguments->text()); - settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailEnabled, m_ui->m_grpCustomExternalEmail->isChecked()); - settings()->setValue(GROUP(Proxy), Proxy::Type, m_ui->m_cmbProxyType->itemData(m_ui->m_cmbProxyType->currentIndex())); - settings()->setValue(GROUP(Proxy), Proxy::Host, m_ui->m_txtProxyHost->text()); - settings()->setValue(GROUP(Proxy), Proxy::Username, m_ui->m_txtProxyUsername->text()); - settings()->setValue(GROUP(Proxy), Proxy::Password, TextFactory::encrypt(m_ui->m_txtProxyPassword->text())); - settings()->setValue(GROUP(Proxy), Proxy::Port, m_ui->m_spinProxyPort->value()); + settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailExecutable, m_ui->m_txtExternalEmailExecutable->text()); + settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailArguments, m_ui->m_txtExternalEmailArguments->text()); + settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailEnabled, m_ui->m_grpCustomExternalEmail->isChecked()); + settings()->setValue(GROUP(Proxy), Proxy::Type, m_ui->m_cmbProxyType->itemData(m_ui->m_cmbProxyType->currentIndex())); + settings()->setValue(GROUP(Proxy), Proxy::Host, m_ui->m_txtProxyHost->text()); + settings()->setValue(GROUP(Proxy), Proxy::Username, m_ui->m_txtProxyUsername->text()); + settings()->setValue(GROUP(Proxy), Proxy::Password, TextFactory::encrypt(m_ui->m_txtProxyPassword->text())); + settings()->setValue(GROUP(Proxy), Proxy::Port, m_ui->m_spinProxyPort->value()); auto tools = externalTools(); ExternalTool::setToolsToSettings(tools); // Reload settings for all network access managers. - SilentNetworkAccessManager::instance()->loadSettings(); + SilentNetworkAccessManager::instance()->loadSettings(); onEndSaveSettings(); } @@ -244,6 +250,7 @@ void SettingsBrowserMail::addExternalTool() { QString executable_file = QFileDialog::getOpenFileName(this, tr("Select external tool"), qApp->homeFolder(), + //: File filter for external tool selection dialog. #if defined(Q_OS_LINUX) tr("Executables (*)")); @@ -254,13 +261,18 @@ void SettingsBrowserMail::addExternalTool() { if (!executable_file.isEmpty()) { executable_file = QDir::toNativeSeparators(executable_file); bool ok; - QString parameters = QInputDialog::getText(this, tr("Enter parameters"), - tr("Enter (optional) parameters separated by single space to send to executable when opening URLs."), - QLineEdit::Normal, QString(), &ok); + QString parameters = QInputDialog::getText(this, + tr("Enter parameters"), + tr( + "Enter (optional) parameters separated by single space to send to executable when opening URLs."), + QLineEdit::Normal, + QString(), + &ok); if (ok) { QTreeWidgetItem* item = new QTreeWidgetItem(m_ui->m_listTools, QStringList() << QDir::toNativeSeparators(executable_file) << parameters); + item->setData(0, Qt::UserRole, QVariant::fromValue(ExternalTool(executable_file, parameters.split(QSL(" "))))); m_ui->m_listTools->addTopLevelItem(item); } diff --git a/src/gui/settings/settingsbrowsermail.h b/src/gui/settings/settingsbrowsermail.h index 584dce46d..a0d66813f 100755 --- a/src/gui/settings/settingsbrowsermail.h +++ b/src/gui/settings/settingsbrowsermail.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,36 +24,36 @@ #include "miscellaneous/externaltool.h" #include "ui_settingsbrowsermail.h" - class SettingsBrowserMail : public SettingsPanel { - Q_OBJECT + Q_OBJECT - public: - explicit SettingsBrowserMail(Settings* settings, QWidget* parent = 0); - virtual ~SettingsBrowserMail(); + public: + explicit SettingsBrowserMail(Settings* settings, QWidget* parent = 0); + virtual ~SettingsBrowserMail(); - inline QString title() const { - return tr("Web browser & e-mail & proxy"); - } + inline QString title() const { + return tr("Web browser & e-mail & proxy"); + } void loadSettings(); - void saveSettings(); - private slots: + void saveSettings(); + + private slots: void addExternalTool(); void deleteSelectedExternalTool(); - void changeDefaultBrowserArguments(int index); - void selectBrowserExecutable(); - void changeDefaultEmailArguments(int index); - void selectEmailExecutable(); - void displayProxyPassword(int state); - void onProxyTypeChanged(int index); + void changeDefaultBrowserArguments(int index); + void selectBrowserExecutable(); + void changeDefaultEmailArguments(int index); + void selectEmailExecutable(); + void displayProxyPassword(int state); + void onProxyTypeChanged(int index); - private: + private: QList externalTools() const; void setExternalTools(const QList& list); - Ui::SettingsBrowserMail* m_ui; + Ui::SettingsBrowserMail* m_ui; }; #endif // SETTINGSBROWSERMAIL_H diff --git a/src/gui/settings/settingsdatabase.cpp b/src/gui/settings/settingsdatabase.cpp index 34002344e..d744e1cf1 100755 --- a/src/gui/settings/settingsdatabase.cpp +++ b/src/gui/settings/settingsdatabase.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,190 +18,197 @@ #include "gui/settings/settingsdatabase.h" -#include "miscellaneous/databasefactory.h" #include "definitions/definitions.h" -#include "miscellaneous/application.h" -#include "miscellaneous/textfactory.h" #include "gui/guiutilities.h" - +#include "miscellaneous/application.h" +#include "miscellaneous/databasefactory.h" +#include "miscellaneous/textfactory.h" SettingsDatabase::SettingsDatabase(Settings* settings, QWidget* parent) - : SettingsPanel(settings, parent), m_ui(new Ui::SettingsDatabase) { - m_ui->setupUi(this); - GuiUtilities::setLabelAsNotice(*m_ui->m_lblDataStorageWarning, true); - GuiUtilities::setLabelAsNotice(*m_ui->m_lblMysqlInfo, false); - GuiUtilities::setLabelAsNotice(*m_ui->m_lblSqliteInMemoryWarnings, true); - connect(m_ui->m_cmbDatabaseDriver, static_cast(&QComboBox::currentIndexChanged), this, - &SettingsDatabase::dirtifySettings); - connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings); - connect(m_ui->m_txtMysqlDatabase->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); - connect(m_ui->m_txtMysqlHostname->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); - connect(m_ui->m_txtMysqlPassword->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); - connect(m_ui->m_checkUseTransactions, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings); - connect(m_ui->m_txtMysqlUsername->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); - connect(m_ui->m_spinMysqlPort, static_cast(&QSpinBox::valueChanged), this, &SettingsDatabase::dirtifySettings); - connect(m_ui->m_cmbDatabaseDriver, static_cast(&QComboBox::currentIndexChanged), this, - &SettingsDatabase::selectSqlBackend); - connect(m_ui->m_checkMysqlShowPassword, &QCheckBox::toggled, this, &SettingsDatabase::switchMysqlPasswordVisiblity); - connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlUsernameChanged); - connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlHostnameChanged); - connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlPasswordChanged); - connect(m_ui->m_txtMysqlDatabase->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlDatabaseChanged); - connect(m_ui->m_btnMysqlTestSetup, &QPushButton::clicked, this, &SettingsDatabase::mysqlTestConnection); - connect(m_ui->m_cmbDatabaseDriver, static_cast(&QComboBox::currentIndexChanged), this, - &SettingsDatabase::requireRestart); - connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::requireRestart); - connect(m_ui->m_spinMysqlPort, &QSpinBox::editingFinished, this, &SettingsDatabase::requireRestart); - connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart); - connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart); - connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart); + : SettingsPanel(settings, parent), m_ui(new Ui::SettingsDatabase) { + m_ui->setupUi(this); + GuiUtilities::setLabelAsNotice(*m_ui->m_lblDataStorageWarning, true); + GuiUtilities::setLabelAsNotice(*m_ui->m_lblMysqlInfo, false); + GuiUtilities::setLabelAsNotice(*m_ui->m_lblSqliteInMemoryWarnings, true); + connect(m_ui->m_cmbDatabaseDriver, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsDatabase::dirtifySettings); + connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings); + connect(m_ui->m_txtMysqlDatabase->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); + connect(m_ui->m_txtMysqlHostname->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); + connect(m_ui->m_txtMysqlPassword->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); + connect(m_ui->m_checkUseTransactions, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings); + connect(m_ui->m_txtMysqlUsername->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); + connect(m_ui->m_spinMysqlPort, static_cast(&QSpinBox::valueChanged), this, &SettingsDatabase::dirtifySettings); + connect(m_ui->m_cmbDatabaseDriver, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsDatabase::selectSqlBackend); + connect(m_ui->m_checkMysqlShowPassword, &QCheckBox::toggled, this, &SettingsDatabase::switchMysqlPasswordVisiblity); + connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlUsernameChanged); + connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlHostnameChanged); + connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlPasswordChanged); + connect(m_ui->m_txtMysqlDatabase->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlDatabaseChanged); + connect(m_ui->m_btnMysqlTestSetup, &QPushButton::clicked, this, &SettingsDatabase::mysqlTestConnection); + connect(m_ui->m_cmbDatabaseDriver, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsDatabase::requireRestart); + connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::requireRestart); + connect(m_ui->m_spinMysqlPort, &QSpinBox::editingFinished, this, &SettingsDatabase::requireRestart); + connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart); + connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart); + connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart); } SettingsDatabase::~SettingsDatabase() { - delete m_ui; + delete m_ui; } void SettingsDatabase::mysqlTestConnection() { - const DatabaseFactory::MySQLError error_code = qApp->database()->mysqlTestConnection(m_ui->m_txtMysqlHostname->lineEdit()->text(), - m_ui->m_spinMysqlPort->value(), - m_ui->m_txtMysqlDatabase->lineEdit()->text(), - m_ui->m_txtMysqlUsername->lineEdit()->text(), - m_ui->m_txtMysqlPassword->lineEdit()->text()); - const QString interpretation = qApp->database()->mysqlInterpretErrorCode(error_code); + const DatabaseFactory::MySQLError error_code = qApp->database()->mysqlTestConnection(m_ui->m_txtMysqlHostname->lineEdit()->text(), + m_ui->m_spinMysqlPort->value(), + m_ui->m_txtMysqlDatabase->lineEdit()->text(), + m_ui->m_txtMysqlUsername->lineEdit()->text(), + m_ui->m_txtMysqlPassword->lineEdit()->text()); + const QString interpretation = qApp->database()->mysqlInterpretErrorCode(error_code); - switch (error_code) { - case DatabaseFactory::MySQLOk: - case DatabaseFactory::MySQLUnknownDatabase: - m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Ok, interpretation, interpretation); - break; + switch (error_code) { + case DatabaseFactory::MySQLOk: + case DatabaseFactory::MySQLUnknownDatabase: + m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Ok, interpretation, interpretation); + break; - default: - m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Error, interpretation, interpretation); - break; - } + default: + m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Error, interpretation, interpretation); + break; + } } void SettingsDatabase::onMysqlHostnameChanged(const QString& new_hostname) { - if (new_hostname.isEmpty()) { - m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Warning, tr("Hostname is empty.")); - } - else { - m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Ok, tr("Hostname looks ok.")); - } + if (new_hostname.isEmpty()) { + m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Warning, tr("Hostname is empty.")); + } + else { + m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Ok, tr("Hostname looks ok.")); + } } void SettingsDatabase::onMysqlUsernameChanged(const QString& new_username) { - if (new_username.isEmpty()) { - m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Warning, tr("Username is empty.")); - } - else { - m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Ok, tr("Username looks ok.")); - } + if (new_username.isEmpty()) { + m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Warning, tr("Username is empty.")); + } + else { + m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Ok, tr("Username looks ok.")); + } } void SettingsDatabase::onMysqlPasswordChanged(const QString& new_password) { - if (new_password.isEmpty()) { - m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Warning, tr("Password is empty.")); - } - else { - m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Ok, tr("Password looks ok.")); - } + if (new_password.isEmpty()) { + m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Warning, tr("Password is empty.")); + } + else { + m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Ok, tr("Password looks ok.")); + } } void SettingsDatabase::onMysqlDatabaseChanged(const QString& new_database) { - if (new_database.isEmpty()) { - m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Warning, tr("Working database is empty.")); - } - else { - m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Ok, tr("Working database is ok.")); - } + if (new_database.isEmpty()) { + m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Warning, tr("Working database is empty.")); + } + else { + m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Ok, tr("Working database is ok.")); + } } void SettingsDatabase::selectSqlBackend(int index) { - const QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(index).toString(); + const QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(index).toString(); - if (selected_db_driver == APP_DB_SQLITE_DRIVER) { - m_ui->m_stackedDatabaseDriver->setCurrentIndex(0); - } - else if (selected_db_driver == APP_DB_MYSQL_DRIVER) { - m_ui->m_stackedDatabaseDriver->setCurrentIndex(1); - } - else { - qWarning("GUI for given database driver '%s' is not available.", qPrintable(selected_db_driver)); - } + if (selected_db_driver == APP_DB_SQLITE_DRIVER) { + m_ui->m_stackedDatabaseDriver->setCurrentIndex(0); + } + else if (selected_db_driver == APP_DB_MYSQL_DRIVER) { + m_ui->m_stackedDatabaseDriver->setCurrentIndex(1); + } + else { + qWarning("GUI for given database driver '%s' is not available.", qPrintable(selected_db_driver)); + } } void SettingsDatabase::switchMysqlPasswordVisiblity(bool visible) { - m_ui->m_txtMysqlPassword->lineEdit()->setEchoMode(visible ? QLineEdit::Normal : QLineEdit::Password); + m_ui->m_txtMysqlPassword->lineEdit()->setEchoMode(visible ? QLineEdit::Normal : QLineEdit::Password); } void SettingsDatabase::loadSettings() { - onBeginLoadSettings(); - m_ui->m_checkUseTransactions->setChecked(qApp->settings()->value(GROUP(Database), SETTING(Database::UseTransactions)).toBool()); - m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Information, tr("No connection test triggered so far."), - tr("You did not executed any connection test yet.")); - // Load SQLite. - m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::SQLITE), APP_DB_SQLITE_DRIVER); - // Load in-memory database status. - m_ui->m_checkSqliteUseInMemoryDatabase->setChecked(settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool()); + onBeginLoadSettings(); + m_ui->m_checkUseTransactions->setChecked(qApp->settings()->value(GROUP(Database), SETTING(Database::UseTransactions)).toBool()); + m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Information, tr("No connection test triggered so far."), + tr("You did not executed any connection test yet.")); - if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) { - onMysqlHostnameChanged(QString()); - onMysqlUsernameChanged(QString()); - onMysqlPasswordChanged(QString()); - onMysqlDatabaseChanged(QString()); - // Load MySQL. - m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::MYSQL), APP_DB_MYSQL_DRIVER); - // Setup placeholders. - m_ui->m_txtMysqlHostname->lineEdit()->setPlaceholderText(tr("Hostname of your MySQL server")); - m_ui->m_txtMysqlUsername->lineEdit()->setPlaceholderText(tr("Username to login with")); - m_ui->m_txtMysqlPassword->lineEdit()->setPlaceholderText(tr("Password for your username")); - m_ui->m_txtMysqlDatabase->lineEdit()->setPlaceholderText(tr("Working database which you have full access to.")); - m_ui->m_txtMysqlHostname->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString()); - m_ui->m_txtMysqlUsername->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString()); - m_ui->m_txtMysqlPassword->lineEdit()->setText(TextFactory::decrypt(settings()->value(GROUP(Database), - SETTING(Database::MySQLPassword)).toString())); - m_ui->m_txtMysqlDatabase->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString()); - m_ui->m_spinMysqlPort->setValue(settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt()); - m_ui->m_checkMysqlShowPassword->setChecked(false); - } + // Load SQLite. + m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::SQLITE), APP_DB_SQLITE_DRIVER); - int index_current_backend = m_ui->m_cmbDatabaseDriver->findData(settings()->value(GROUP(Database), - SETTING(Database::ActiveDriver)).toString()); + // Load in-memory database status. + m_ui->m_checkSqliteUseInMemoryDatabase->setChecked(settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool()); - if (index_current_backend >= 0) { - m_ui->m_cmbDatabaseDriver->setCurrentIndex(index_current_backend); - } + if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) { + onMysqlHostnameChanged(QString()); + onMysqlUsernameChanged(QString()); + onMysqlPasswordChanged(QString()); + onMysqlDatabaseChanged(QString()); - onEndLoadSettings(); + // Load MySQL. + m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::MYSQL), APP_DB_MYSQL_DRIVER); + + // Setup placeholders. + m_ui->m_txtMysqlHostname->lineEdit()->setPlaceholderText(tr("Hostname of your MySQL server")); + m_ui->m_txtMysqlUsername->lineEdit()->setPlaceholderText(tr("Username to login with")); + m_ui->m_txtMysqlPassword->lineEdit()->setPlaceholderText(tr("Password for your username")); + m_ui->m_txtMysqlDatabase->lineEdit()->setPlaceholderText(tr("Working database which you have full access to.")); + m_ui->m_txtMysqlHostname->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString()); + m_ui->m_txtMysqlUsername->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString()); + m_ui->m_txtMysqlPassword->lineEdit()->setText(TextFactory::decrypt(settings()->value(GROUP(Database), + SETTING(Database::MySQLPassword)).toString())); + m_ui->m_txtMysqlDatabase->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString()); + m_ui->m_spinMysqlPort->setValue(settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt()); + m_ui->m_checkMysqlShowPassword->setChecked(false); + } + + int index_current_backend = m_ui->m_cmbDatabaseDriver->findData(settings()->value(GROUP(Database), + SETTING(Database::ActiveDriver)).toString()); + + if (index_current_backend >= 0) { + m_ui->m_cmbDatabaseDriver->setCurrentIndex(index_current_backend); + } + + onEndLoadSettings(); } void SettingsDatabase::saveSettings() { - onBeginSaveSettings(); - // Setup in-memory database status. - const bool original_inmemory = settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool(); - const bool new_inmemory = m_ui->m_checkSqliteUseInMemoryDatabase->isChecked(); - qApp->settings()->setValue(GROUP(Database), Database::UseTransactions, m_ui->m_checkUseTransactions->isChecked()); - // Save data storage settings. - QString original_db_driver = settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString(); - QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(m_ui->m_cmbDatabaseDriver->currentIndex()).toString(); - // Save SQLite. - settings()->setValue(GROUP(Database), Database::UseInMemory, new_inmemory); + onBeginSaveSettings(); - if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) { - // Save MySQL. - settings()->setValue(GROUP(Database), Database::MySQLHostname, m_ui->m_txtMysqlHostname->lineEdit()->text()); - settings()->setValue(GROUP(Database), Database::MySQLUsername, m_ui->m_txtMysqlUsername->lineEdit()->text()); - settings()->setValue(GROUP(Database), Database::MySQLPassword, TextFactory::encrypt(m_ui->m_txtMysqlPassword->lineEdit()->text())); - settings()->setValue(GROUP(Database), Database::MySQLDatabase, m_ui->m_txtMysqlDatabase->lineEdit()->text()); - settings()->setValue(GROUP(Database), Database::MySQLPort, m_ui->m_spinMysqlPort->value()); - } + // Setup in-memory database status. + const bool original_inmemory = settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool(); + const bool new_inmemory = m_ui->m_checkSqliteUseInMemoryDatabase->isChecked(); - settings()->setValue(GROUP(Database), Database::ActiveDriver, selected_db_driver); + qApp->settings()->setValue(GROUP(Database), Database::UseTransactions, m_ui->m_checkUseTransactions->isChecked()); - if (original_db_driver != selected_db_driver || original_inmemory != new_inmemory) { - requireRestart(); - } + // Save data storage settings. + QString original_db_driver = settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString(); + QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(m_ui->m_cmbDatabaseDriver->currentIndex()).toString(); - onEndSaveSettings(); + // Save SQLite. + settings()->setValue(GROUP(Database), Database::UseInMemory, new_inmemory); + + if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) { + // Save MySQL. + settings()->setValue(GROUP(Database), Database::MySQLHostname, m_ui->m_txtMysqlHostname->lineEdit()->text()); + settings()->setValue(GROUP(Database), Database::MySQLUsername, m_ui->m_txtMysqlUsername->lineEdit()->text()); + settings()->setValue(GROUP(Database), Database::MySQLPassword, TextFactory::encrypt(m_ui->m_txtMysqlPassword->lineEdit()->text())); + settings()->setValue(GROUP(Database), Database::MySQLDatabase, m_ui->m_txtMysqlDatabase->lineEdit()->text()); + settings()->setValue(GROUP(Database), Database::MySQLPort, m_ui->m_spinMysqlPort->value()); + } + + settings()->setValue(GROUP(Database), Database::ActiveDriver, selected_db_driver); + + if (original_db_driver != selected_db_driver || original_inmemory != new_inmemory) { + requireRestart(); + } + + onEndSaveSettings(); } diff --git a/src/gui/settings/settingsdatabase.h b/src/gui/settings/settingsdatabase.h index f6c4655f6..c6264dbaa 100755 --- a/src/gui/settings/settingsdatabase.h +++ b/src/gui/settings/settingsdatabase.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,31 +23,31 @@ #include "ui_settingsdatabase.h" - class SettingsDatabase : public SettingsPanel { - Q_OBJECT + Q_OBJECT - public: - explicit SettingsDatabase(Settings* settings, QWidget* parent = 0); - virtual ~SettingsDatabase(); + public: + explicit SettingsDatabase(Settings* settings, QWidget* parent = 0); + virtual ~SettingsDatabase(); - inline QString title() const { - return tr("Data storage"); - } + inline QString title() const { + return tr("Data storage"); + } - void loadSettings(); - void saveSettings(); + void loadSettings(); - private: - void mysqlTestConnection(); - void onMysqlHostnameChanged(const QString& new_hostname); - void onMysqlUsernameChanged(const QString& new_username); - void onMysqlPasswordChanged(const QString& new_password); - void onMysqlDatabaseChanged(const QString& new_database); - void selectSqlBackend(int index); - void switchMysqlPasswordVisiblity(bool visible); + void saveSettings(); - Ui::SettingsDatabase* m_ui; + private: + void mysqlTestConnection(); + void onMysqlHostnameChanged(const QString& new_hostname); + void onMysqlUsernameChanged(const QString& new_username); + void onMysqlPasswordChanged(const QString& new_password); + void onMysqlDatabaseChanged(const QString& new_database); + void selectSqlBackend(int index); + void switchMysqlPasswordVisiblity(bool visible); + + Ui::SettingsDatabase* m_ui; }; #endif // SETTINGSDATABASE_H diff --git a/src/gui/settings/settingsdownloads.cpp b/src/gui/settings/settingsdownloads.cpp index deffd394b..80d2db153 100755 --- a/src/gui/settings/settingsdownloads.cpp +++ b/src/gui/settings/settingsdownloads.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,54 +18,53 @@ #include "gui/settings/settingsdownloads.h" +#include "miscellaneous/application.h" #include "miscellaneous/settings.h" #include "network-web/downloadmanager.h" -#include "miscellaneous/application.h" #include - SettingsDownloads::SettingsDownloads(Settings* settings, QWidget* parent) - : SettingsPanel(settings, parent), m_ui(new Ui::SettingsDownloads) { - m_ui->setupUi(this); - connect(m_ui->m_checkOpenManagerWhenDownloadStarts, &QCheckBox::toggled, this, &SettingsDownloads::dirtifySettings); - connect(m_ui->m_txtDownloadsTargetDirectory, &QLineEdit::textChanged, this, &SettingsDownloads::dirtifySettings); - connect(m_ui->m_rbDownloadsAskEachFile, &QRadioButton::toggled, this, &SettingsDownloads::dirtifySettings); - connect(m_ui->m_btnDownloadsTargetDirectory, &QPushButton::clicked, this, &SettingsDownloads::selectDownloadsDirectory); + : SettingsPanel(settings, parent), m_ui(new Ui::SettingsDownloads) { + m_ui->setupUi(this); + connect(m_ui->m_checkOpenManagerWhenDownloadStarts, &QCheckBox::toggled, this, &SettingsDownloads::dirtifySettings); + connect(m_ui->m_txtDownloadsTargetDirectory, &QLineEdit::textChanged, this, &SettingsDownloads::dirtifySettings); + connect(m_ui->m_rbDownloadsAskEachFile, &QRadioButton::toggled, this, &SettingsDownloads::dirtifySettings); + connect(m_ui->m_btnDownloadsTargetDirectory, &QPushButton::clicked, this, &SettingsDownloads::selectDownloadsDirectory); } SettingsDownloads::~SettingsDownloads() { - delete m_ui; + delete m_ui; } void SettingsDownloads::selectDownloadsDirectory() { - const QString target_directory = QFileDialog::getExistingDirectory(this, - tr("Select downloads target directory"), - m_ui->m_txtDownloadsTargetDirectory->text() - ); + const QString target_directory = QFileDialog::getExistingDirectory(this, + tr("Select downloads target directory"), + m_ui->m_txtDownloadsTargetDirectory->text() + ); - if (!target_directory.isEmpty()) { - m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(target_directory)); - } + if (!target_directory.isEmpty()) { + m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(target_directory)); + } } void SettingsDownloads::loadSettings() { - onBeginLoadSettings(); - m_ui->m_checkOpenManagerWhenDownloadStarts->setChecked(settings()->value(GROUP(Downloads), - SETTING(Downloads::ShowDownloadsWhenNewDownloadStarts)).toBool()); - m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(settings()->value(GROUP(Downloads), - SETTING(Downloads::TargetDirectory)).toString())); - m_ui->m_rbDownloadsAskEachFile->setChecked(settings()->value(GROUP(Downloads), - SETTING(Downloads::AlwaysPromptForFilename)).toBool()); - onEndLoadSettings(); + onBeginLoadSettings(); + m_ui->m_checkOpenManagerWhenDownloadStarts->setChecked(settings()->value(GROUP(Downloads), + SETTING(Downloads::ShowDownloadsWhenNewDownloadStarts)).toBool()); + m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(settings()->value(GROUP(Downloads), + SETTING(Downloads::TargetDirectory)).toString())); + m_ui->m_rbDownloadsAskEachFile->setChecked(settings()->value(GROUP(Downloads), + SETTING(Downloads::AlwaysPromptForFilename)).toBool()); + onEndLoadSettings(); } void SettingsDownloads::saveSettings() { - onBeginSaveSettings(); - settings()->setValue(GROUP(Downloads), Downloads::ShowDownloadsWhenNewDownloadStarts, - m_ui->m_checkOpenManagerWhenDownloadStarts->isChecked()); - settings()->setValue(GROUP(Downloads), Downloads::TargetDirectory, m_ui->m_txtDownloadsTargetDirectory->text()); - settings()->setValue(GROUP(Downloads), Downloads::AlwaysPromptForFilename, m_ui->m_rbDownloadsAskEachFile->isChecked()); - qApp->downloadManager()->setDownloadDirectory(m_ui->m_txtDownloadsTargetDirectory->text()); - onEndSaveSettings(); + onBeginSaveSettings(); + settings()->setValue(GROUP(Downloads), Downloads::ShowDownloadsWhenNewDownloadStarts, + m_ui->m_checkOpenManagerWhenDownloadStarts->isChecked()); + settings()->setValue(GROUP(Downloads), Downloads::TargetDirectory, m_ui->m_txtDownloadsTargetDirectory->text()); + settings()->setValue(GROUP(Downloads), Downloads::AlwaysPromptForFilename, m_ui->m_rbDownloadsAskEachFile->isChecked()); + qApp->downloadManager()->setDownloadDirectory(m_ui->m_txtDownloadsTargetDirectory->text()); + onEndSaveSettings(); } diff --git a/src/gui/settings/settingsdownloads.h b/src/gui/settings/settingsdownloads.h index 91390fa65..40fc45e04 100755 --- a/src/gui/settings/settingsdownloads.h +++ b/src/gui/settings/settingsdownloads.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,26 +23,26 @@ #include "ui_settingsdownloads.h" - class SettingsDownloads : public SettingsPanel { - Q_OBJECT + Q_OBJECT - public: - explicit SettingsDownloads(Settings* settings, QWidget* parent = 0); - virtual ~SettingsDownloads(); + public: + explicit SettingsDownloads(Settings* settings, QWidget* parent = 0); + virtual ~SettingsDownloads(); - inline QString title() const { - return tr("Downloads"); - } + inline QString title() const { + return tr("Downloads"); + } - void loadSettings(); - void saveSettings(); + void loadSettings(); - private slots: - void selectDownloadsDirectory(); + void saveSettings(); - private: - Ui::SettingsDownloads* m_ui; + private slots: + void selectDownloadsDirectory(); + + private: + Ui::SettingsDownloads* m_ui; }; #endif // SETTINGSDOWNLOADS_H diff --git a/src/gui/settings/settingsfeedsmessages.cpp b/src/gui/settings/settingsfeedsmessages.cpp index a36066755..07027dd86 100755 --- a/src/gui/settings/settingsfeedsmessages.cpp +++ b/src/gui/settings/settingsfeedsmessages.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,126 +19,128 @@ #include "gui/settings/settingsfeedsmessages.h" #include "definitions/definitions.h" -#include "miscellaneous/application.h" -#include "miscellaneous/feedreader.h" #include "gui/dialogs/formmain.h" #include "gui/feedmessageviewer.h" #include "gui/feedsview.h" +#include "gui/guiutilities.h" #include "gui/messagesview.h" #include "gui/timespinbox.h" -#include "gui/guiutilities.h" +#include "miscellaneous/application.h" +#include "miscellaneous/feedreader.h" #include - SettingsFeedsMessages::SettingsFeedsMessages(Settings* settings, QWidget* parent) - : SettingsPanel(settings, parent), m_ui(new Ui::SettingsFeedsMessages) { - m_ui->setupUi(this); - initializeMessageDateFormats(); - GuiUtilities::setLabelAsNotice(*m_ui->label_9, false); - connect(m_ui->m_checkAutoUpdateNotification, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_checkKeppMessagesInTheMiddle, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_checkMessagesDateTimeFormat, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_checkRemoveReadMessagesOnExit, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_checkUpdateAllFeedsOnStartup, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_spinAutoUpdateInterval, static_cast(&QDoubleSpinBox::valueChanged), - this, &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_spinHeightImageAttachments, static_cast(&QSpinBox::valueChanged), - this, &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, m_ui->m_spinAutoUpdateInterval, &TimeSpinBox::setEnabled); - connect(m_ui->m_spinFeedUpdateTimeout, static_cast(&QSpinBox::valueChanged), this, - &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_cmbMessagesDateTimeFormat, static_cast(&QComboBox::currentIndexChanged), this, - &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_cmbCountsFeedList, &QComboBox::currentTextChanged, this, &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_cmbCountsFeedList, static_cast(&QComboBox::currentIndexChanged), this, - &SettingsFeedsMessages::dirtifySettings); - connect(m_ui->m_btnChangeMessagesFont, &QPushButton::clicked, this, &SettingsFeedsMessages::changeMessagesFont); + : SettingsPanel(settings, parent), m_ui(new Ui::SettingsFeedsMessages) { + m_ui->setupUi(this); + initializeMessageDateFormats(); + GuiUtilities::setLabelAsNotice(*m_ui->label_9, false); + connect(m_ui->m_checkAutoUpdateNotification, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_checkKeppMessagesInTheMiddle, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_checkMessagesDateTimeFormat, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_checkRemoveReadMessagesOnExit, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_checkUpdateAllFeedsOnStartup, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_spinAutoUpdateInterval, static_cast(&QDoubleSpinBox::valueChanged), + this, &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_spinHeightImageAttachments, static_cast(&QSpinBox::valueChanged), + this, &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, m_ui->m_spinAutoUpdateInterval, &TimeSpinBox::setEnabled); + connect(m_ui->m_spinFeedUpdateTimeout, static_cast(&QSpinBox::valueChanged), this, + &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_cmbMessagesDateTimeFormat, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_cmbCountsFeedList, &QComboBox::currentTextChanged, this, &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_cmbCountsFeedList, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsFeedsMessages::dirtifySettings); + connect(m_ui->m_btnChangeMessagesFont, &QPushButton::clicked, this, &SettingsFeedsMessages::changeMessagesFont); - if (!m_ui->m_spinFeedUpdateTimeout->suffix().startsWith(' ')) { - m_ui->m_spinFeedUpdateTimeout->setSuffix(QSL(" ") + m_ui->m_spinFeedUpdateTimeout->suffix()); - } + if (!m_ui->m_spinFeedUpdateTimeout->suffix().startsWith(' ')) { + m_ui->m_spinFeedUpdateTimeout->setSuffix(QSL(" ") + m_ui->m_spinFeedUpdateTimeout->suffix()); + } } SettingsFeedsMessages::~SettingsFeedsMessages() { - delete m_ui; + delete m_ui; } void SettingsFeedsMessages::initializeMessageDateFormats() { - QStringList best_formats; - best_formats << QSL("d/M/yyyy hh:mm:ss") << QSL("ddd, d. M. yy hh:mm:ss") << - QSL("yyyy-MM-dd HH:mm:ss.z") << QSL("yyyy-MM-ddThh:mm:ss") << - QSL("MMM d yyyy hh:mm:ss");; - const QLocale current_locale = qApp->localization()->loadedLocale(); - const QDateTime current_dt = QDateTime::currentDateTime(); + QStringList best_formats; - foreach (const QString& format, best_formats) { - m_ui->m_cmbMessagesDateTimeFormat->addItem(current_locale.toString(current_dt, format), format); - } + best_formats << QSL("d/M/yyyy hh:mm:ss") << QSL("ddd, d. M. yy hh:mm:ss") << + QSL("yyyy-MM-dd HH:mm:ss.z") << QSL("yyyy-MM-ddThh:mm:ss") << + QSL("MMM d yyyy hh:mm:ss");; + const QLocale current_locale = qApp->localization()->loadedLocale(); + const QDateTime current_dt = QDateTime::currentDateTime(); + + foreach (const QString& format, best_formats) { + m_ui->m_cmbMessagesDateTimeFormat->addItem(current_locale.toString(current_dt, format), format); + } } void SettingsFeedsMessages::changeMessagesFont() { - bool ok; - QFont new_font = QFontDialog::getFont(&ok, m_ui->m_lblMessagesFont->font(), - this, tr("Select new font for message viewer"), - QFontDialog::DontUseNativeDialog); + bool ok; + QFont new_font = QFontDialog::getFont(&ok, m_ui->m_lblMessagesFont->font(), + this, tr("Select new font for message viewer"), + QFontDialog::DontUseNativeDialog); - if (ok) { - m_ui->m_lblMessagesFont->setFont(new_font); - dirtifySettings(); - } + if (ok) { + m_ui->m_lblMessagesFont->setFont(new_font); + dirtifySettings(); + } } void SettingsFeedsMessages::loadSettings() { - onBeginLoadSettings(); - m_ui->m_checkAutoUpdateNotification->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::EnableAutoUpdateNotification)).toBool()); - m_ui->m_checkKeppMessagesInTheMiddle->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::KeepCursorInCenter)).toBool()); - m_ui->m_checkRemoveReadMessagesOnExit->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool()); - m_ui->m_checkAutoUpdate->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateEnabled)).toBool()); - m_ui->m_spinAutoUpdateInterval->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateInterval)).toInt()); - m_ui->m_spinFeedUpdateTimeout->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt()); - m_ui->m_checkUpdateAllFeedsOnStartup->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool()); - m_ui->m_cmbCountsFeedList->addItems(QStringList() << "(%unread)" << "[%unread]" << "%unread/%all" << "%unread-%all" << "[%unread|%all]"); - m_ui->m_cmbCountsFeedList->setEditText(settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString()); - m_ui->m_spinHeightImageAttachments->setValue(settings()->value(GROUP(Messages), SETTING(Messages::MessageHeadImageHeight)).toInt()); - initializeMessageDateFormats(); - m_ui->m_checkMessagesDateTimeFormat->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool()); - const int index_format = m_ui->m_cmbMessagesDateTimeFormat->findData(settings()->value(GROUP(Messages), - SETTING(Messages::CustomDateFormat)).toString()); + onBeginLoadSettings(); + m_ui->m_checkAutoUpdateNotification->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::EnableAutoUpdateNotification)).toBool()); + m_ui->m_checkKeppMessagesInTheMiddle->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::KeepCursorInCenter)).toBool()); + m_ui->m_checkRemoveReadMessagesOnExit->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool()); + m_ui->m_checkAutoUpdate->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateEnabled)).toBool()); + m_ui->m_spinAutoUpdateInterval->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateInterval)).toInt()); + m_ui->m_spinFeedUpdateTimeout->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt()); + m_ui->m_checkUpdateAllFeedsOnStartup->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool()); + m_ui->m_cmbCountsFeedList->addItems(QStringList() << "(%unread)" << "[%unread]" << "%unread/%all" << "%unread-%all" << "[%unread|%all]"); + m_ui->m_cmbCountsFeedList->setEditText(settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString()); + m_ui->m_spinHeightImageAttachments->setValue(settings()->value(GROUP(Messages), SETTING(Messages::MessageHeadImageHeight)).toInt()); + initializeMessageDateFormats(); + m_ui->m_checkMessagesDateTimeFormat->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool()); + const int index_format = m_ui->m_cmbMessagesDateTimeFormat->findData(settings()->value(GROUP(Messages), + SETTING(Messages::CustomDateFormat)).toString()); - if (index_format >= 0) { - m_ui->m_cmbMessagesDateTimeFormat->setCurrentIndex(index_format); - } + if (index_format >= 0) { + m_ui->m_cmbMessagesDateTimeFormat->setCurrentIndex(index_format); + } - m_ui->m_lblMessagesFont->setText(tr("Font preview")); - QFont fon; - fon.fromString(settings()->value(GROUP(Messages), - SETTING(Messages::PreviewerFontStandard)).toString()); - m_ui->m_lblMessagesFont->setFont(fon); - onEndLoadSettings(); + m_ui->m_lblMessagesFont->setText(tr("Font preview")); + QFont fon; + + fon.fromString(settings()->value(GROUP(Messages), + SETTING(Messages::PreviewerFontStandard)).toString()); + m_ui->m_lblMessagesFont->setFont(fon); + onEndLoadSettings(); } void SettingsFeedsMessages::saveSettings() { - onBeginSaveSettings(); - settings()->setValue(GROUP(Feeds), Feeds::EnableAutoUpdateNotification, m_ui->m_checkAutoUpdateNotification->isChecked()); - settings()->setValue(GROUP(Messages), Messages::KeepCursorInCenter, m_ui->m_checkKeppMessagesInTheMiddle->isChecked()); - settings()->setValue(GROUP(Messages), Messages::ClearReadOnExit, m_ui->m_checkRemoveReadMessagesOnExit->isChecked()); - settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateEnabled, m_ui->m_checkAutoUpdate->isChecked()); - settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateInterval, m_ui->m_spinAutoUpdateInterval->value()); - settings()->setValue(GROUP(Feeds), Feeds::UpdateTimeout, m_ui->m_spinFeedUpdateTimeout->value()); - settings()->setValue(GROUP(Feeds), Feeds::FeedsUpdateOnStartup, m_ui->m_checkUpdateAllFeedsOnStartup->isChecked()); - settings()->setValue(GROUP(Feeds), Feeds::CountFormat, m_ui->m_cmbCountsFeedList->currentText()); - settings()->setValue(GROUP(Messages), Messages::UseCustomDate, m_ui->m_checkMessagesDateTimeFormat->isChecked()); - settings()->setValue(GROUP(Messages), Messages::MessageHeadImageHeight, m_ui->m_spinHeightImageAttachments->value()); - settings()->setValue(GROUP(Messages), Messages::CustomDateFormat, - m_ui->m_cmbMessagesDateTimeFormat->itemData(m_ui->m_cmbMessagesDateTimeFormat->currentIndex()).toString()); - // Save fonts. - settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, m_ui->m_lblMessagesFont->font().toString()); - qApp->mainForm()->tabWidget()->feedMessageViewer()->loadMessageViewerFonts(); - qApp->feedReader()->updateAutoUpdateStatus(); - qApp->feedReader()->feedsModel()->reloadWholeLayout(); - qApp->feedReader()->messagesModel()->updateDateFormat(); - qApp->feedReader()->messagesModel()->reloadWholeLayout(); - onEndSaveSettings(); + onBeginSaveSettings(); + settings()->setValue(GROUP(Feeds), Feeds::EnableAutoUpdateNotification, m_ui->m_checkAutoUpdateNotification->isChecked()); + settings()->setValue(GROUP(Messages), Messages::KeepCursorInCenter, m_ui->m_checkKeppMessagesInTheMiddle->isChecked()); + settings()->setValue(GROUP(Messages), Messages::ClearReadOnExit, m_ui->m_checkRemoveReadMessagesOnExit->isChecked()); + settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateEnabled, m_ui->m_checkAutoUpdate->isChecked()); + settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateInterval, m_ui->m_spinAutoUpdateInterval->value()); + settings()->setValue(GROUP(Feeds), Feeds::UpdateTimeout, m_ui->m_spinFeedUpdateTimeout->value()); + settings()->setValue(GROUP(Feeds), Feeds::FeedsUpdateOnStartup, m_ui->m_checkUpdateAllFeedsOnStartup->isChecked()); + settings()->setValue(GROUP(Feeds), Feeds::CountFormat, m_ui->m_cmbCountsFeedList->currentText()); + settings()->setValue(GROUP(Messages), Messages::UseCustomDate, m_ui->m_checkMessagesDateTimeFormat->isChecked()); + settings()->setValue(GROUP(Messages), Messages::MessageHeadImageHeight, m_ui->m_spinHeightImageAttachments->value()); + settings()->setValue(GROUP(Messages), Messages::CustomDateFormat, + m_ui->m_cmbMessagesDateTimeFormat->itemData(m_ui->m_cmbMessagesDateTimeFormat->currentIndex()).toString()); + + // Save fonts. + settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, m_ui->m_lblMessagesFont->font().toString()); + qApp->mainForm()->tabWidget()->feedMessageViewer()->loadMessageViewerFonts(); + qApp->feedReader()->updateAutoUpdateStatus(); + qApp->feedReader()->feedsModel()->reloadWholeLayout(); + qApp->feedReader()->messagesModel()->updateDateFormat(); + qApp->feedReader()->messagesModel()->reloadWholeLayout(); + onEndSaveSettings(); } diff --git a/src/gui/settings/settingsfeedsmessages.h b/src/gui/settings/settingsfeedsmessages.h index 0da19867d..53bd359b5 100755 --- a/src/gui/settings/settingsfeedsmessages.h +++ b/src/gui/settings/settingsfeedsmessages.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,28 +23,28 @@ #include "ui_settingsfeedsmessages.h" - class SettingsFeedsMessages : public SettingsPanel { - Q_OBJECT + Q_OBJECT - public: - explicit SettingsFeedsMessages(Settings* settings, QWidget* parent = 0); - virtual ~SettingsFeedsMessages(); + public: + explicit SettingsFeedsMessages(Settings* settings, QWidget* parent = 0); + virtual ~SettingsFeedsMessages(); - inline QString title() const { - return tr("Feeds & messages"); - } + inline QString title() const { + return tr("Feeds & messages"); + } - void loadSettings(); - void saveSettings(); + void loadSettings(); - private slots: - void changeMessagesFont(); + void saveSettings(); - private: - void initializeMessageDateFormats(); + private slots: + void changeMessagesFont(); - Ui::SettingsFeedsMessages* m_ui; + private: + void initializeMessageDateFormats(); + + Ui::SettingsFeedsMessages* m_ui; }; #endif // SETTINGSFEEDSMESSAGES_H diff --git a/src/gui/settings/settingsgeneral.cpp b/src/gui/settings/settingsgeneral.cpp index 606b555ac..2e6ee15f3 100755 --- a/src/gui/settings/settingsgeneral.cpp +++ b/src/gui/settings/settingsgeneral.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,65 +18,65 @@ #include "gui/settings/settingsgeneral.h" -#include "miscellaneous/systemfactory.h" #include "miscellaneous/application.h" - +#include "miscellaneous/systemfactory.h" SettingsGeneral::SettingsGeneral(Settings* settings, QWidget* parent) - : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGeneral) { - m_ui->setupUi(this); - m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text().arg(APP_NAME)); - connect(m_ui->m_checkAutostart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings); - connect(m_ui->m_checkForUpdatesOnStart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings); - connect(m_ui->m_checkRemoveTrolltechJunk, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings); + : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGeneral) { + m_ui->setupUi(this); + m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text().arg(APP_NAME)); + connect(m_ui->m_checkAutostart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings); + connect(m_ui->m_checkForUpdatesOnStart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings); + connect(m_ui->m_checkRemoveTrolltechJunk, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings); } SettingsGeneral::~SettingsGeneral() { - delete m_ui; + delete m_ui; } void SettingsGeneral::loadSettings() { - onBeginLoadSettings(); - m_ui->m_checkForUpdatesOnStart->setChecked(settings()->value(GROUP(General), SETTING(General::UpdateOnStartup)).toBool()); - // Load auto-start status. - const SystemFactory::AutoStartStatus autostart_status = qApp->system()->autoStartStatus(); + onBeginLoadSettings(); + m_ui->m_checkForUpdatesOnStart->setChecked(settings()->value(GROUP(General), SETTING(General::UpdateOnStartup)).toBool()); - switch (autostart_status) { - case SystemFactory::AutoStartStatus::Enabled: - m_ui->m_checkAutostart->setChecked(true); - break; + // Load auto-start status. + const SystemFactory::AutoStartStatus autostart_status = qApp->system()->autoStartStatus(); - case SystemFactory::AutoStartStatus::Disabled: - m_ui->m_checkAutostart->setChecked(false); - break; + switch (autostart_status) { + case SystemFactory::AutoStartStatus::Enabled: + m_ui->m_checkAutostart->setChecked(true); + break; - default: - m_ui->m_checkAutostart->setEnabled(false); - m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text() + tr(" (not supported on this platform)")); - break; - } + case SystemFactory::AutoStartStatus::Disabled: + m_ui->m_checkAutostart->setChecked(false); + break; + + default: + m_ui->m_checkAutostart->setEnabled(false); + m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text() + tr(" (not supported on this platform)")); + break; + } #if defined(Q_OS_WIN) - m_ui->m_checkRemoveTrolltechJunk->setVisible(true); - m_ui->m_checkRemoveTrolltechJunk->setChecked(settings()->value(GROUP(General), SETTING(General::RemoveTrolltechJunk)).toBool()); + m_ui->m_checkRemoveTrolltechJunk->setVisible(true); + m_ui->m_checkRemoveTrolltechJunk->setChecked(settings()->value(GROUP(General), SETTING(General::RemoveTrolltechJunk)).toBool()); #else - m_ui->m_checkRemoveTrolltechJunk->setVisible(false); + m_ui->m_checkRemoveTrolltechJunk->setVisible(false); #endif - onEndLoadSettings(); + onEndLoadSettings(); } void SettingsGeneral::saveSettings() { - onBeginSaveSettings(); + onBeginSaveSettings(); - // If auto-start feature is available and user wants to turn it on, then turn it on. - if (m_ui->m_checkAutostart->isChecked()) { - qApp->system()->setAutoStartStatus(SystemFactory::AutoStartStatus::Enabled); - } - else { - qApp->system()->setAutoStartStatus(SystemFactory::AutoStartStatus::Disabled); - } + // If auto-start feature is available and user wants to turn it on, then turn it on. + if (m_ui->m_checkAutostart->isChecked()) { + qApp->system()->setAutoStartStatus(SystemFactory::AutoStartStatus::Enabled); + } + else { + qApp->system()->setAutoStartStatus(SystemFactory::AutoStartStatus::Disabled); + } - settings()->setValue(GROUP(General), General::UpdateOnStartup, m_ui->m_checkForUpdatesOnStart->isChecked()); - settings()->setValue(GROUP(General), General::RemoveTrolltechJunk, m_ui->m_checkRemoveTrolltechJunk->isChecked()); - onEndSaveSettings(); + settings()->setValue(GROUP(General), General::UpdateOnStartup, m_ui->m_checkForUpdatesOnStart->isChecked()); + settings()->setValue(GROUP(General), General::RemoveTrolltechJunk, m_ui->m_checkRemoveTrolltechJunk->isChecked()); + onEndSaveSettings(); } diff --git a/src/gui/settings/settingsgeneral.h b/src/gui/settings/settingsgeneral.h index 9b230356d..2c6ec1805 100755 --- a/src/gui/settings/settingsgeneral.h +++ b/src/gui/settings/settingsgeneral.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,23 +23,23 @@ #include "ui_settingsgeneral.h" - class SettingsGeneral : public SettingsPanel { - Q_OBJECT + Q_OBJECT - public: - explicit SettingsGeneral(Settings* settings, QWidget* parent = 0); - virtual ~SettingsGeneral(); + public: + explicit SettingsGeneral(Settings* settings, QWidget* parent = 0); + virtual ~SettingsGeneral(); - inline QString title() const { - return tr("General"); - } + inline QString title() const { + return tr("General"); + } - void loadSettings(); - void saveSettings(); + void loadSettings(); - private: - Ui::SettingsGeneral* m_ui; + void saveSettings(); + + private: + Ui::SettingsGeneral* m_ui; }; #endif // SETTINGSGENERAL_H diff --git a/src/gui/settings/settingsgui.cpp b/src/gui/settings/settingsgui.cpp index 03d1ac65d..8ca8cabb2 100755 --- a/src/gui/settings/settingsgui.cpp +++ b/src/gui/settings/settingsgui.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,239 +18,252 @@ #include "gui/settings/settingsgui.h" -#include "gui/systemtrayicon.h" -#include "miscellaneous/settings.h" -#include "miscellaneous/application.h" -#include "miscellaneous/iconfactory.h" #include "gui/dialogs/formmain.h" -#include "gui/tabwidget.h" #include "gui/feedmessageviewer.h" #include "gui/feedstoolbar.h" #include "gui/messagestoolbar.h" #include "gui/statusbar.h" +#include "gui/systemtrayicon.h" +#include "gui/tabwidget.h" +#include "miscellaneous/application.h" +#include "miscellaneous/iconfactory.h" +#include "miscellaneous/settings.h" #include #include +SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGui) { + m_ui->setupUi(this); + m_ui->m_editorMessagesToolbar->activeItemsWidget()->viewport()->installEventFilter(this); + m_ui->m_editorFeedsToolbar->activeItemsWidget()->viewport()->installEventFilter(this); + m_ui->m_editorMessagesToolbar->availableItemsWidget()->viewport()->installEventFilter(this); + m_ui->m_editorFeedsToolbar->availableItemsWidget()->viewport()->installEventFilter(this); + m_ui->m_treeSkins->setColumnCount(4); + m_ui->m_treeSkins->setHeaderHidden(false); + m_ui->m_treeSkins->setHeaderLabels(QStringList() + << /*: Skin list name column. */ tr("Name") + << /*: Version column of skin list. */ tr("Version") + << tr("Author") + << tr("E-mail")); -SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGui) { - m_ui->setupUi(this); - m_ui->m_editorMessagesToolbar->activeItemsWidget()->viewport()->installEventFilter(this); - m_ui->m_editorFeedsToolbar->activeItemsWidget()->viewport()->installEventFilter(this); - m_ui->m_editorMessagesToolbar->availableItemsWidget()->viewport()->installEventFilter(this); - m_ui->m_editorFeedsToolbar->availableItemsWidget()->viewport()->installEventFilter(this); - m_ui->m_treeSkins->setColumnCount(4); - m_ui->m_treeSkins->setHeaderHidden(false); - m_ui->m_treeSkins->setHeaderLabels(QStringList() - << /*: Skin list name column. */ tr("Name") - << /*: Version column of skin list. */ tr("Version") - << tr("Author") - << tr("E-mail")); - // Setup skins. - m_ui->m_treeSkins->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); - m_ui->m_treeSkins->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); - m_ui->m_treeSkins->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents); - m_ui->m_treeSkins->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents); - connect(m_ui->m_cmbIconTheme, static_cast(&QComboBox::currentIndexChanged), this, &SettingsGui::requireRestart); - connect(m_ui->m_cmbIconTheme, static_cast(&QComboBox::currentIndexChanged), this, &SettingsGui::dirtifySettings); - connect(m_ui->m_treeSkins, &QTreeWidget::currentItemChanged, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_grpTray, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_checkEnableNotifications, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_checkHidden, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_checkHideWhenMinimized, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_checkHideTabBarIfOneTabVisible, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_checkCloseTabsDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_checkCloseTabsMiddleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_checkNewTabDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_grbCloseTabs, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_cmbToolbarButtonStyle, static_cast(&QComboBox::currentIndexChanged), this, - &SettingsGui::dirtifySettings); - connect(m_ui->m_editorFeedsToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_editorMessagesToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_editorStatusbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_listStyles, &QListWidget::currentItemChanged, this, &SettingsGui::dirtifySettings); - connect(m_ui->m_cmbSelectToolBar, static_cast(&QComboBox::currentIndexChanged), m_ui->m_stackedToolbars, - &QStackedWidget::setCurrentIndex); + // Setup skins. + m_ui->m_treeSkins->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); + m_ui->m_treeSkins->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + m_ui->m_treeSkins->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents); + m_ui->m_treeSkins->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents); + connect(m_ui->m_cmbIconTheme, static_cast(&QComboBox::currentIndexChanged), this, &SettingsGui::requireRestart); + connect(m_ui->m_cmbIconTheme, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsGui::dirtifySettings); + connect(m_ui->m_treeSkins, &QTreeWidget::currentItemChanged, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_grpTray, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_checkEnableNotifications, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_checkHidden, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_checkHideWhenMinimized, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_checkHideTabBarIfOneTabVisible, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_checkCloseTabsDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_checkCloseTabsMiddleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_checkNewTabDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_grbCloseTabs, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_cmbToolbarButtonStyle, static_cast(&QComboBox::currentIndexChanged), this, + &SettingsGui::dirtifySettings); + connect(m_ui->m_editorFeedsToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_editorMessagesToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_editorStatusbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_listStyles, &QListWidget::currentItemChanged, this, &SettingsGui::dirtifySettings); + connect(m_ui->m_cmbSelectToolBar, static_cast(&QComboBox::currentIndexChanged), m_ui->m_stackedToolbars, + &QStackedWidget::setCurrentIndex); } SettingsGui::~SettingsGui() { - delete m_ui; + delete m_ui; } bool SettingsGui::eventFilter(QObject* obj, QEvent* e) { - Q_UNUSED(obj) + Q_UNUSED(obj) - if (e->type() == QEvent::Drop) { - QDropEvent* drop_event = static_cast(e); + if (e->type() == QEvent::Drop) { + QDropEvent* drop_event = static_cast(e); - if (drop_event->keyboardModifiers() != Qt::NoModifier) { - drop_event->setDropAction(Qt::MoveAction); - } - } + if (drop_event->keyboardModifiers() != Qt::NoModifier) { + drop_event->setDropAction(Qt::MoveAction); + } + } - return false; + return false; } - void SettingsGui::loadSettings() { - onBeginLoadSettings(); + onBeginLoadSettings(); - // Load settings of tray icon. - if (SystemTrayIcon::isSystemTrayAvailable()) { - m_ui->m_grpTray->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UseTrayIcon)).toBool()); - } - // Tray icon is not supported on this machine. - else { - m_ui->m_grpTray->setTitle(m_ui->m_grpTray->title() + QL1C(' ') + tr("(Tray icon is not available.)")); - m_ui->m_grpTray->setChecked(false); - } + // Load settings of tray icon. + if (SystemTrayIcon::isSystemTrayAvailable()) { + m_ui->m_grpTray->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UseTrayIcon)).toBool()); + } - m_ui->m_checkHidden->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool()); - m_ui->m_checkHideWhenMinimized->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool()); - // Load fancy notification settings. - m_ui->m_checkEnableNotifications->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::EnableNotifications)).toBool()); - // Load settings of icon theme. - const QString current_theme = qApp->icons()->currentIconTheme(); + // Tray icon is not supported on this machine. + else { + m_ui->m_grpTray->setTitle(m_ui->m_grpTray->title() + QL1C(' ') + tr("(Tray icon is not available.)")); + m_ui->m_grpTray->setChecked(false); + } - foreach (const QString& icon_theme_name, qApp->icons()->installedIconThemes()) { - if (icon_theme_name == APP_NO_THEME) { - // Add just "no theme" on other systems. - //: Label for disabling icon theme. - m_ui->m_cmbIconTheme->addItem(tr("no icon theme/system icon theme"), APP_NO_THEME); - } - else { - m_ui->m_cmbIconTheme->addItem(icon_theme_name, icon_theme_name); - } - } + m_ui->m_checkHidden->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool()); + m_ui->m_checkHideWhenMinimized->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool()); - // Mark active theme. - if (current_theme == QSL(APP_NO_THEME)) { - // Because "no icon theme" lies at the index 0. - m_ui->m_cmbIconTheme->setCurrentIndex(0); - } - else { - m_ui->m_cmbIconTheme->setCurrentText(current_theme); - } + // Load fancy notification settings. + m_ui->m_checkEnableNotifications->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::EnableNotifications)).toBool()); - // Load skin. - const QString selected_skin = qApp->skins()->selectedSkinName(); + // Load settings of icon theme. + const QString current_theme = qApp->icons()->currentIconTheme(); - foreach (const Skin& skin, qApp->skins()->installedSkins()) { - QTreeWidgetItem* new_item = new QTreeWidgetItem(QStringList() << - skin.m_visibleName << - skin.m_version << - skin.m_author << - skin.m_email); - new_item->setData(0, Qt::UserRole, QVariant::fromValue(skin)); - // Add this skin and mark it as active if its active now. - m_ui->m_treeSkins->addTopLevelItem(new_item); + foreach (const QString& icon_theme_name, qApp->icons()->installedIconThemes()) { + if (icon_theme_name == APP_NO_THEME) { + // Add just "no theme" on other systems. + //: Label for disabling icon theme. + m_ui->m_cmbIconTheme->addItem(tr("no icon theme/system icon theme"), APP_NO_THEME); + } + else { + m_ui->m_cmbIconTheme->addItem(icon_theme_name, icon_theme_name); + } + } - if (skin.m_baseName == selected_skin) { - m_ui->m_treeSkins->setCurrentItem(new_item); - } - } + // Mark active theme. + if (current_theme == QSL(APP_NO_THEME)) { + // Because "no icon theme" lies at the index 0. + m_ui->m_cmbIconTheme->setCurrentIndex(0); + } + else { + m_ui->m_cmbIconTheme->setCurrentText(current_theme); + } - if (m_ui->m_treeSkins->currentItem() == nullptr && - m_ui->m_treeSkins->topLevelItemCount() > 0) { - // Currently active skin is NOT available, select another one as selected - // if possible. - m_ui->m_treeSkins->setCurrentItem(m_ui->m_treeSkins->topLevelItem(0)); - } + // Load skin. + const QString selected_skin = qApp->skins()->selectedSkinName(); - // Load styles. - foreach (const QString& style_name, QStyleFactory::keys()) { - m_ui->m_listStyles->addItem(style_name); - } + foreach (const Skin& skin, qApp->skins()->installedSkins()) { + QTreeWidgetItem* new_item = new QTreeWidgetItem(QStringList() << + skin.m_visibleName << + skin.m_version << + skin.m_author << + skin.m_email); - QList items = m_ui->m_listStyles->findItems(settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString(), - Qt::MatchFixedString); + new_item->setData(0, Qt::UserRole, QVariant::fromValue(skin)); - if (!items.isEmpty()) { - m_ui->m_listStyles->setCurrentItem(items.at(0)); - } + // Add this skin and mark it as active if its active now. + m_ui->m_treeSkins->addTopLevelItem(new_item); - // Load tab settings. - m_ui->m_checkCloseTabsMiddleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool()); - m_ui->m_checkCloseTabsDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool()); - m_ui->m_checkNewTabDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabNewDoubleClick)).toBool()); - m_ui->m_checkHideTabBarIfOneTabVisible->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideTabBarIfOnlyOneTab)).toBool()); - // Load toolbar button style. - m_ui->m_cmbToolbarButtonStyle->addItem(tr("Icon only"), Qt::ToolButtonIconOnly); - m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text only"), Qt::ToolButtonTextOnly); - m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text beside icon"), Qt::ToolButtonTextBesideIcon); - m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text under icon"), Qt::ToolButtonTextUnderIcon); - m_ui->m_cmbToolbarButtonStyle->addItem(tr("Follow OS style"), Qt::ToolButtonFollowStyle); - m_ui->m_cmbToolbarButtonStyle->setCurrentIndex(m_ui->m_cmbToolbarButtonStyle->findData(settings()->value(GROUP(GUI), - SETTING(GUI::ToolbarStyle)).toInt())); - // Load toolbars. - m_ui->m_editorFeedsToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsToolBar()); - m_ui->m_editorMessagesToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->messagesToolBar()); - m_ui->m_editorStatusbar->loadFromToolBar(qApp->mainForm()->statusBar()); - onEndLoadSettings(); + if (skin.m_baseName == selected_skin) { + m_ui->m_treeSkins->setCurrentItem(new_item); + } + } + + if (m_ui->m_treeSkins->currentItem() == nullptr && + m_ui->m_treeSkins->topLevelItemCount() > 0) { + // Currently active skin is NOT available, select another one as selected + // if possible. + m_ui->m_treeSkins->setCurrentItem(m_ui->m_treeSkins->topLevelItem(0)); + } + + // Load styles. + foreach (const QString& style_name, QStyleFactory::keys()) { + m_ui->m_listStyles->addItem(style_name); + } + + QList items = m_ui->m_listStyles->findItems(settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString(), + Qt::MatchFixedString); + + if (!items.isEmpty()) { + m_ui->m_listStyles->setCurrentItem(items.at(0)); + } + + // Load tab settings. + m_ui->m_checkCloseTabsMiddleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool()); + m_ui->m_checkCloseTabsDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool()); + m_ui->m_checkNewTabDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabNewDoubleClick)).toBool()); + m_ui->m_checkHideTabBarIfOneTabVisible->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideTabBarIfOnlyOneTab)).toBool()); + + // Load toolbar button style. + m_ui->m_cmbToolbarButtonStyle->addItem(tr("Icon only"), Qt::ToolButtonIconOnly); + m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text only"), Qt::ToolButtonTextOnly); + m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text beside icon"), Qt::ToolButtonTextBesideIcon); + m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text under icon"), Qt::ToolButtonTextUnderIcon); + m_ui->m_cmbToolbarButtonStyle->addItem(tr("Follow OS style"), Qt::ToolButtonFollowStyle); + m_ui->m_cmbToolbarButtonStyle->setCurrentIndex(m_ui->m_cmbToolbarButtonStyle->findData(settings()->value(GROUP(GUI), + SETTING( + GUI::ToolbarStyle)).toInt())); + + // Load toolbars. + m_ui->m_editorFeedsToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsToolBar()); + m_ui->m_editorMessagesToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->messagesToolBar()); + m_ui->m_editorStatusbar->loadFromToolBar(qApp->mainForm()->statusBar()); + onEndLoadSettings(); } void SettingsGui::saveSettings() { - onBeginSaveSettings(); - // Save toolbar. - settings()->setValue(GROUP(GUI), GUI::ToolbarStyle, m_ui->m_cmbToolbarButtonStyle->itemData(m_ui->m_cmbToolbarButtonStyle->currentIndex())); + onBeginSaveSettings(); - // Save tray icon. - if (SystemTrayIcon::isSystemTrayAvailable()) { - settings()->setValue(GROUP(GUI), GUI::UseTrayIcon, m_ui->m_grpTray->isChecked()); + // Save toolbar. + settings()->setValue(GROUP(GUI), GUI::ToolbarStyle, + m_ui->m_cmbToolbarButtonStyle->itemData(m_ui->m_cmbToolbarButtonStyle->currentIndex())); - if (m_ui->m_grpTray->isChecked()) { - qApp->showTrayIcon(); - } - else { - qApp->deleteTrayIcon(); - } - } + // Save tray icon. + if (SystemTrayIcon::isSystemTrayAvailable()) { + settings()->setValue(GROUP(GUI), GUI::UseTrayIcon, m_ui->m_grpTray->isChecked()); - settings()->setValue(GROUP(GUI), GUI::MainWindowStartsHidden, m_ui->m_checkHidden->isChecked()); - settings()->setValue(GROUP(GUI), GUI::HideMainWindowWhenMinimized, m_ui->m_checkHideWhenMinimized->isChecked()); - // Save notifications. - settings()->setValue(GROUP(GUI), GUI::EnableNotifications, m_ui->m_checkEnableNotifications->isChecked()); - // Save selected icon theme. - QString selected_icon_theme = m_ui->m_cmbIconTheme->itemData(m_ui->m_cmbIconTheme->currentIndex()).toString(); - QString original_icon_theme = qApp->icons()->currentIconTheme(); - qApp->icons()->setCurrentIconTheme(selected_icon_theme); + if (m_ui->m_grpTray->isChecked()) { + qApp->showTrayIcon(); + } + else { + qApp->deleteTrayIcon(); + } + } - // Check if icon theme was changed. - if (selected_icon_theme != original_icon_theme) { - requireRestart(); - } + settings()->setValue(GROUP(GUI), GUI::MainWindowStartsHidden, m_ui->m_checkHidden->isChecked()); + settings()->setValue(GROUP(GUI), GUI::HideMainWindowWhenMinimized, m_ui->m_checkHideWhenMinimized->isChecked()); - // Save and activate new skin. - if (!m_ui->m_treeSkins->selectedItems().isEmpty()) { - const Skin active_skin = m_ui->m_treeSkins->currentItem()->data(0, Qt::UserRole).value(); + // Save notifications. + settings()->setValue(GROUP(GUI), GUI::EnableNotifications, m_ui->m_checkEnableNotifications->isChecked()); - if (qApp->skins()->selectedSkinName() != active_skin.m_baseName) { - qApp->skins()->setCurrentSkinName(active_skin.m_baseName); - requireRestart(); - } - } + // Save selected icon theme. + QString selected_icon_theme = m_ui->m_cmbIconTheme->itemData(m_ui->m_cmbIconTheme->currentIndex()).toString(); + QString original_icon_theme = qApp->icons()->currentIconTheme(); - // Set new style. - if (!m_ui->m_listStyles->selectedItems().isEmpty()) { - const QString new_style = m_ui->m_listStyles->currentItem()->text(); - const QString old_style = qApp->settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString(); + qApp->icons()->setCurrentIconTheme(selected_icon_theme); - if (old_style != new_style) { - requireRestart(); - } + // Check if icon theme was changed. + if (selected_icon_theme != original_icon_theme) { + requireRestart(); + } - qApp->settings()->setValue(GROUP(GUI), GUI::Style, new_style); - } + // Save and activate new skin. + if (!m_ui->m_treeSkins->selectedItems().isEmpty()) { + const Skin active_skin = m_ui->m_treeSkins->currentItem()->data(0, Qt::UserRole).value(); - // Save tab settings. - settings()->setValue(GROUP(GUI), GUI::TabCloseMiddleClick, m_ui->m_checkCloseTabsMiddleClick->isChecked()); - settings()->setValue(GROUP(GUI), GUI::TabCloseDoubleClick, m_ui->m_checkCloseTabsDoubleClick->isChecked()); - settings()->setValue(GROUP(GUI), GUI::TabNewDoubleClick, m_ui->m_checkNewTabDoubleClick->isChecked()); - settings()->setValue(GROUP(GUI), GUI::HideTabBarIfOnlyOneTab, m_ui->m_checkHideTabBarIfOneTabVisible->isChecked()); - m_ui->m_editorFeedsToolbar->saveToolBar(); - m_ui->m_editorMessagesToolbar->saveToolBar(); - m_ui->m_editorStatusbar->saveToolBar(); - qApp->mainForm()->tabWidget()->checkTabBarVisibility(); - qApp->mainForm()->tabWidget()->feedMessageViewer()->refreshVisualProperties(); - onEndSaveSettings(); + if (qApp->skins()->selectedSkinName() != active_skin.m_baseName) { + qApp->skins()->setCurrentSkinName(active_skin.m_baseName); + requireRestart(); + } + } + + // Set new style. + if (!m_ui->m_listStyles->selectedItems().isEmpty()) { + const QString new_style = m_ui->m_listStyles->currentItem()->text(); + const QString old_style = qApp->settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString(); + + if (old_style != new_style) { + requireRestart(); + } + + qApp->settings()->setValue(GROUP(GUI), GUI::Style, new_style); + } + + // Save tab settings. + settings()->setValue(GROUP(GUI), GUI::TabCloseMiddleClick, m_ui->m_checkCloseTabsMiddleClick->isChecked()); + settings()->setValue(GROUP(GUI), GUI::TabCloseDoubleClick, m_ui->m_checkCloseTabsDoubleClick->isChecked()); + settings()->setValue(GROUP(GUI), GUI::TabNewDoubleClick, m_ui->m_checkNewTabDoubleClick->isChecked()); + settings()->setValue(GROUP(GUI), GUI::HideTabBarIfOnlyOneTab, m_ui->m_checkHideTabBarIfOneTabVisible->isChecked()); + m_ui->m_editorFeedsToolbar->saveToolBar(); + m_ui->m_editorMessagesToolbar->saveToolBar(); + m_ui->m_editorStatusbar->saveToolBar(); + qApp->mainForm()->tabWidget()->checkTabBarVisibility(); + qApp->mainForm()->tabWidget()->feedMessageViewer()->refreshVisualProperties(); + onEndSaveSettings(); } diff --git a/src/gui/settings/settingsgui.h b/src/gui/settings/settingsgui.h index 0da52c753..982b371de 100755 --- a/src/gui/settings/settingsgui.h +++ b/src/gui/settings/settingsgui.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,27 +23,28 @@ #include "ui_settingsgui.h" - class SettingsGui : public SettingsPanel { - Q_OBJECT + Q_OBJECT - public: - explicit SettingsGui(Settings* settings, QWidget* parent = 0); - virtual ~SettingsGui(); + public: + explicit SettingsGui(Settings* settings, QWidget* parent = 0); + virtual ~SettingsGui(); - inline QString title() const { - return tr("User interface"); - } + inline QString title() const { + return tr("User interface"); + } - void loadSettings(); - void saveSettings(); + void loadSettings(); - protected: - // Does check of controls before dialog can be submitted. - bool eventFilter(QObject* obj, QEvent* e); + void saveSettings(); - private: - Ui::SettingsGui* m_ui; + protected: + + // Does check of controls before dialog can be submitted. + bool eventFilter(QObject* obj, QEvent* e); + + private: + Ui::SettingsGui* m_ui; }; #endif // SETTINGSGUI_H diff --git a/src/gui/settings/settingslocalization.cpp b/src/gui/settings/settingslocalization.cpp index 140a6de7f..0f587107b 100755 --- a/src/gui/settings/settingslocalization.cpp +++ b/src/gui/settings/settingslocalization.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,70 +18,71 @@ #include "gui/settings/settingslocalization.h" -#include "miscellaneous/localization.h" -#include "miscellaneous/settings.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" - +#include "miscellaneous/localization.h" +#include "miscellaneous/settings.h" SettingsLocalization::SettingsLocalization(Settings* settings, QWidget* parent) - : SettingsPanel(settings, parent), m_ui(new Ui::SettingsLocalization) { - m_ui->setupUi(this); - m_ui->m_treeLanguages->setColumnCount(3); - m_ui->m_treeLanguages->setHeaderHidden(false); - m_ui->m_treeLanguages->setHeaderLabels(QStringList() - << /*: Language column of language list. */ tr("Language") - << /*: Lang. code column of language list. */ tr("Code") - << tr("Author")); - // Setup languages. - m_ui->m_treeLanguages->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); - m_ui->m_treeLanguages->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); - m_ui->m_treeLanguages->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents); - connect(m_ui->m_treeLanguages, &QTreeWidget::currentItemChanged, this, &SettingsLocalization::requireRestart); - connect(m_ui->m_treeLanguages, &QTreeWidget::currentItemChanged, this, &SettingsLocalization::dirtifySettings); + : SettingsPanel(settings, parent), m_ui(new Ui::SettingsLocalization) { + m_ui->setupUi(this); + m_ui->m_treeLanguages->setColumnCount(3); + m_ui->m_treeLanguages->setHeaderHidden(false); + m_ui->m_treeLanguages->setHeaderLabels(QStringList() + << /*: Language column of language list. */ tr("Language") + << /*: Lang. code column of language list. */ tr("Code") + << tr("Author")); + + // Setup languages. + m_ui->m_treeLanguages->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); + m_ui->m_treeLanguages->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + m_ui->m_treeLanguages->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents); + connect(m_ui->m_treeLanguages, &QTreeWidget::currentItemChanged, this, &SettingsLocalization::requireRestart); + connect(m_ui->m_treeLanguages, &QTreeWidget::currentItemChanged, this, &SettingsLocalization::dirtifySettings); } SettingsLocalization::~SettingsLocalization() { - delete m_ui; + delete m_ui; } void SettingsLocalization::loadSettings() { - onBeginLoadSettings(); + onBeginLoadSettings(); - foreach (const Language& language, qApp->localization()->installedLanguages()) { - QTreeWidgetItem* item = new QTreeWidgetItem(m_ui->m_treeLanguages); - item->setText(0, language.m_name); - item->setText(1, language.m_code); - item->setText(2, language.m_author); - item->setIcon(0, qApp->icons()->miscIcon(QString(FLAG_ICON_SUBFOLDER) + QDir::separator() + language.m_code)); - } + foreach (const Language& language, qApp->localization()->installedLanguages()) { + QTreeWidgetItem* item = new QTreeWidgetItem(m_ui->m_treeLanguages); - m_ui->m_treeLanguages->sortByColumn(0, Qt::AscendingOrder); - QList matching_items = m_ui->m_treeLanguages->findItems(qApp->localization()->loadedLanguage(), Qt::MatchContains, 1); + item->setText(0, language.m_name); + item->setText(1, language.m_code); + item->setText(2, language.m_author); + item->setIcon(0, qApp->icons()->miscIcon(QString(FLAG_ICON_SUBFOLDER) + QDir::separator() + language.m_code)); + } - if (!matching_items.isEmpty()) { - m_ui->m_treeLanguages->setCurrentItem(matching_items[0]); - } + m_ui->m_treeLanguages->sortByColumn(0, Qt::AscendingOrder); + QList matching_items = m_ui->m_treeLanguages->findItems(qApp->localization()->loadedLanguage(), Qt::MatchContains, 1); - onEndLoadSettings(); + if (!matching_items.isEmpty()) { + m_ui->m_treeLanguages->setCurrentItem(matching_items[0]); + } + + onEndLoadSettings(); } void SettingsLocalization::saveSettings() { - onBeginSaveSettings(); + onBeginSaveSettings(); - if (m_ui->m_treeLanguages->currentItem() == nullptr) { - qDebug("No localizations loaded in settings dialog, so no saving for them."); - return; - } + if (m_ui->m_treeLanguages->currentItem() == nullptr) { + qDebug("No localizations loaded in settings dialog, so no saving for them."); + return; + } - const QString actual_lang = qApp->localization()->loadedLanguage(); - const QString new_lang = m_ui->m_treeLanguages->currentItem()->text(1); + const QString actual_lang = qApp->localization()->loadedLanguage(); + const QString new_lang = m_ui->m_treeLanguages->currentItem()->text(1); - // Save prompt for restart if language has changed. - if (new_lang != actual_lang) { - requireRestart(); - settings()->setValue(GROUP(General), General::Language, new_lang); - } + // Save prompt for restart if language has changed. + if (new_lang != actual_lang) { + requireRestart(); + settings()->setValue(GROUP(General), General::Language, new_lang); + } - onEndSaveSettings(); + onEndSaveSettings(); } diff --git a/src/gui/settings/settingslocalization.h b/src/gui/settings/settingslocalization.h index 1ca672579..e08dbbdf7 100755 --- a/src/gui/settings/settingslocalization.h +++ b/src/gui/settings/settingslocalization.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,23 +23,23 @@ #include "ui_settingslocalization.h" - class SettingsLocalization : public SettingsPanel { - Q_OBJECT + Q_OBJECT - public: - explicit SettingsLocalization(Settings* settings, QWidget* parent = 0); - virtual ~SettingsLocalization(); + public: + explicit SettingsLocalization(Settings* settings, QWidget* parent = 0); + virtual ~SettingsLocalization(); - inline QString title() const { - return tr("Language"); - } + inline QString title() const { + return tr("Language"); + } - void loadSettings(); - void saveSettings(); + void loadSettings(); - private: - Ui::SettingsLocalization* m_ui; + void saveSettings(); + + private: + Ui::SettingsLocalization* m_ui; }; #endif // SETTINGSLOCALIZATION_H diff --git a/src/gui/settings/settingspanel.cpp b/src/gui/settings/settingspanel.cpp index e6969ad7e..15e5c98ad 100755 --- a/src/gui/settings/settingspanel.cpp +++ b/src/gui/settings/settingspanel.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,55 +20,52 @@ #include "miscellaneous/settings.h" - SettingsPanel::SettingsPanel(Settings* settings, QWidget* parent) - : QWidget(parent), m_requiresRestart(false), m_isDirty(false), m_isLoading(false), m_settings(settings) { -} + : QWidget(parent), m_requiresRestart(false), m_isDirty(false), m_isLoading(false), m_settings(settings) {} void SettingsPanel::onBeginLoadSettings() { - m_isLoading = true; + m_isLoading = true; } void SettingsPanel::onEndLoadSettings() { - m_isLoading = false; - setRequiresRestart(false); - setIsDirty(false); + m_isLoading = false; + setRequiresRestart(false); + setIsDirty(false); } -void SettingsPanel::onBeginSaveSettings() { -} +void SettingsPanel::onBeginSaveSettings() {} void SettingsPanel::onEndSaveSettings() { - setIsDirty(false); + setIsDirty(false); } void SettingsPanel::dirtifySettings() { - if (!m_isLoading) { - setIsDirty(true); - emit settingsChanged(); - } + if (!m_isLoading) { + setIsDirty(true); + emit settingsChanged(); + } } bool SettingsPanel::requiresRestart() const { - return m_requiresRestart; + return m_requiresRestart; } void SettingsPanel::setRequiresRestart(bool requiresRestart) { - m_requiresRestart = requiresRestart; + m_requiresRestart = requiresRestart; } void SettingsPanel::requireRestart() { - setRequiresRestart(true); + setRequiresRestart(true); } bool SettingsPanel::isDirty() const { - return m_isDirty; + return m_isDirty; } void SettingsPanel::setIsDirty(bool is_dirty) { - m_isDirty = is_dirty; + m_isDirty = is_dirty; } Settings* SettingsPanel::settings() const { - return m_settings; + return m_settings; } diff --git a/src/gui/settings/settingspanel.h b/src/gui/settings/settingspanel.h index cac661df8..2d7c403d3 100755 --- a/src/gui/settings/settingspanel.h +++ b/src/gui/settings/settingspanel.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,50 +21,49 @@ #include - class Settings; class SettingsPanel : public QWidget { - Q_OBJECT + Q_OBJECT - public: - explicit SettingsPanel(Settings* settings, QWidget* parent = 0); + public: + explicit SettingsPanel(Settings* settings, QWidget* parent = 0); - virtual QString title() const = 0; + virtual QString title() const = 0; + virtual void loadSettings() = 0; + virtual void saveSettings() = 0; - virtual void loadSettings() = 0; - virtual void saveSettings() = 0; + bool requiresRestart() const; + bool isDirty() const; - bool requiresRestart() const; - bool isDirty() const; + void setIsDirty(bool is_dirty); + void setRequiresRestart(bool requiresRestart); - void setIsDirty(bool is_dirty); - void setRequiresRestart(bool requiresRestart); + protected: + void onBeginLoadSettings(); + void onEndLoadSettings(); + void onBeginSaveSettings(); + void onEndSaveSettings(); - protected: - void onBeginLoadSettings(); - void onEndLoadSettings(); - void onBeginSaveSettings(); - void onEndSaveSettings(); + // Settings to use to save/load. + Settings* settings() const; - // Settings to use to save/load. - Settings* settings() const; + protected slots: - protected slots: - // Sets this settings panel as dirty (some settings are changed) and emits the signal. - // NOTE: This will be probably called by subclasses when user changes some stuff. - void dirtifySettings(); + // Sets this settings panel as dirty (some settings are changed) and emits the signal. + // NOTE: This will be probably called by subclasses when user changes some stuff. + void dirtifySettings(); - void requireRestart(); + void requireRestart(); - signals: - void settingsChanged(); + signals: + void settingsChanged(); - private: - bool m_requiresRestart; - bool m_isDirty; - bool m_isLoading; - Settings* m_settings; + private: + bool m_requiresRestart; + bool m_isDirty; + bool m_isLoading; + Settings* m_settings; }; #endif // SETTINGSPANEL_H diff --git a/src/gui/settings/settingsshortcuts.cpp b/src/gui/settings/settingsshortcuts.cpp index b77f922ba..5fb8f4a25 100755 --- a/src/gui/settings/settingsshortcuts.cpp +++ b/src/gui/settings/settingsshortcuts.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,29 +18,28 @@ #include "gui/settings/settingsshortcuts.h" -#include "miscellaneous/application.h" #include "dynamic-shortcuts/dynamicshortcuts.h" - +#include "miscellaneous/application.h" SettingsShortcuts::SettingsShortcuts(Settings* settings, QWidget* parent) - : SettingsPanel(settings, parent), m_ui(new Ui::SettingsShortcuts) { - m_ui->setupUi(this); - connect(m_ui->m_shortcuts, &DynamicShortcutsWidget::setupChanged, this, &SettingsShortcuts::dirtifySettings); + : SettingsPanel(settings, parent), m_ui(new Ui::SettingsShortcuts) { + m_ui->setupUi(this); + connect(m_ui->m_shortcuts, &DynamicShortcutsWidget::setupChanged, this, &SettingsShortcuts::dirtifySettings); } SettingsShortcuts::~SettingsShortcuts() { - delete m_ui; + delete m_ui; } void SettingsShortcuts::loadSettings() { - onBeginLoadSettings(); - m_ui->m_shortcuts->populate(qApp->userActions()); - onEndLoadSettings(); + onBeginLoadSettings(); + m_ui->m_shortcuts->populate(qApp->userActions()); + onEndLoadSettings(); } void SettingsShortcuts::saveSettings() { - onBeginSaveSettings(); - m_ui->m_shortcuts->updateShortcuts(); - DynamicShortcuts::save(qApp->userActions()); - onEndSaveSettings(); + onBeginSaveSettings(); + m_ui->m_shortcuts->updateShortcuts(); + DynamicShortcuts::save(qApp->userActions()); + onEndSaveSettings(); } diff --git a/src/gui/settings/settingsshortcuts.h b/src/gui/settings/settingsshortcuts.h index 7a87961f5..138f9f529 100755 --- a/src/gui/settings/settingsshortcuts.h +++ b/src/gui/settings/settingsshortcuts.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,23 +23,23 @@ #include "ui_settingsshortcuts.h" - class SettingsShortcuts : public SettingsPanel { - Q_OBJECT + Q_OBJECT - public: - explicit SettingsShortcuts(Settings* settings, QWidget* parent = 0); - virtual ~SettingsShortcuts(); + public: + explicit SettingsShortcuts(Settings* settings, QWidget* parent = 0); + virtual ~SettingsShortcuts(); - inline QString title() const { - return tr("Keyboard shortcuts"); - } + inline QString title() const { + return tr("Keyboard shortcuts"); + } - void loadSettings(); - void saveSettings(); + void loadSettings(); - private: - Ui::SettingsShortcuts* m_ui; + void saveSettings(); + + private: + Ui::SettingsShortcuts* m_ui; }; #endif // SETTINGSSHORTCUTS_H diff --git a/src/gui/squeezelabel.cpp b/src/gui/squeezelabel.cpp index 2aef12f81..68a94ed80 100755 --- a/src/gui/squeezelabel.cpp +++ b/src/gui/squeezelabel.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,19 +18,17 @@ #include "gui/squeezelabel.h" - -SqueezeLabel::SqueezeLabel(QWidget* parent) : QLabel(parent) { -} +SqueezeLabel::SqueezeLabel(QWidget* parent) : QLabel(parent) {} void SqueezeLabel::paintEvent(QPaintEvent* event) { - if (m_squeezedTextCache != text()) { - m_squeezedTextCache = text(); - QFontMetrics fm = fontMetrics(); + if (m_squeezedTextCache != text()) { + m_squeezedTextCache = text(); + QFontMetrics fm = fontMetrics(); - if (fm.width(m_squeezedTextCache) > contentsRect().width()) { - setText(fm.elidedText(text(), Qt::ElideMiddle, width())); - } - } + if (fm.width(m_squeezedTextCache) > contentsRect().width()) { + setText(fm.elidedText(text(), Qt::ElideMiddle, width())); + } + } - QLabel::paintEvent(event); + QLabel::paintEvent(event); } diff --git a/src/gui/squeezelabel.h b/src/gui/squeezelabel.h index b2c17027d..3002384e9 100755 --- a/src/gui/squeezelabel.h +++ b/src/gui/squeezelabel.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,18 +21,17 @@ #include - class SqueezeLabel : public QLabel { - Q_OBJECT + Q_OBJECT - public: - explicit SqueezeLabel(QWidget* parent = 0); + public: + explicit SqueezeLabel(QWidget* parent = 0); - protected: - void paintEvent(QPaintEvent* event); + protected: + void paintEvent(QPaintEvent* event); - private: - QString m_squeezedTextCache; + private: + QString m_squeezedTextCache; }; #endif // SQUEEZELABEL_H diff --git a/src/gui/statusbar.cpp b/src/gui/statusbar.cpp index 7ec35558a..1c8ba5141 100755 --- a/src/gui/statusbar.cpp +++ b/src/gui/statusbar.cpp @@ -37,20 +37,20 @@ StatusBar::StatusBar(QWidget* parent) : QStatusBar(parent), m_mutex(new Mutex(QM m_barProgressFeeds->setFixedWidth(100); m_barProgressFeeds->setVisible(false); m_barProgressFeeds->setObjectName(QSL("m_barProgressFeeds")); - m_barProgressFeedsAction = new QAction(qApp->icons()->fromTheme(QSL("application-rss+xml")),tr("Feed update progress bar"),this); + m_barProgressFeedsAction = new QAction(qApp->icons()->fromTheme(QSL("application-rss+xml")), tr("Feed update progress bar"), this); m_barProgressFeedsAction->setObjectName(QSL("m_barProgressFeedsAction")); m_lblProgressFeeds = new QLabel(this); m_lblProgressFeeds->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); m_lblProgressFeeds->setVisible(false); m_lblProgressFeeds->setObjectName(QSL("m_lblProgressFeeds")); - m_lblProgressFeedsAction = new QAction(qApp->icons()->fromTheme(QSL("application-rss+xml")), tr("Feed update label"),this); + m_lblProgressFeedsAction = new QAction(qApp->icons()->fromTheme(QSL("application-rss+xml")), tr("Feed update label"), this); m_lblProgressFeedsAction->setObjectName(QSL("m_lblProgressFeedsAction")); m_barProgressDownload = new QProgressBar(this); m_barProgressDownload->setTextVisible(true); m_barProgressDownload->setFixedWidth(100); m_barProgressDownload->setVisible(false); m_barProgressDownload->setObjectName(QSL("m_barProgressDownload")); - m_barProgressDownloadAction = new QAction(qApp->icons()->fromTheme(QSL("emblem-downloads")),tr("File download progress bar"),this); + m_barProgressDownloadAction = new QAction(qApp->icons()->fromTheme(QSL("emblem-downloads")), tr("File download progress bar"), this); m_barProgressDownloadAction->setObjectName(QSL("m_barProgressDownloadAction")); m_lblProgressDownload = new QLabel(this); m_lblProgressDownload->setText("Downloading files in background"); @@ -93,7 +93,7 @@ QStringList StatusBar::defaultActions() const { } QStringList StatusBar::savedActions() const { - return qApp->settings()->value(GROUP(GUI), SETTING(GUI::StatusbarActions)).toString().split(',',QString::SkipEmptyParts); + return qApp->settings()->value(GROUP(GUI), SETTING(GUI::StatusbarActions)).toString().split(',', QString::SkipEmptyParts); } QList StatusBar::getSpecificActions(const QStringList& actions) { @@ -157,7 +157,7 @@ QList StatusBar::getSpecificActions(const QStringList& actions) { widget_to_add = tool_button; action_to_add = matching_action; connect(tool_button, &PlainToolButton::clicked, matching_action, &QAction::trigger); - connect(matching_action, &QAction::changed, tool_button,&PlainToolButton::reactOnSenderActionChange); + connect(matching_action, &QAction::changed, tool_button, &PlainToolButton::reactOnSenderActionChange); } else { action_to_add = nullptr; diff --git a/src/gui/styleditemdelegatewithoutfocus.cpp b/src/gui/styleditemdelegatewithoutfocus.cpp index 01b3f3945..60b5a095f 100755 --- a/src/gui/styleditemdelegatewithoutfocus.cpp +++ b/src/gui/styleditemdelegatewithoutfocus.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,20 +18,17 @@ #include "gui/styleditemdelegatewithoutfocus.h" +StyledItemDelegateWithoutFocus::StyledItemDelegateWithoutFocus(QObject* parent) : QStyledItemDelegate(parent) {} -StyledItemDelegateWithoutFocus::StyledItemDelegateWithoutFocus(QObject* parent) : QStyledItemDelegate(parent) { -} - -StyledItemDelegateWithoutFocus::~StyledItemDelegateWithoutFocus() { -} +StyledItemDelegateWithoutFocus::~StyledItemDelegateWithoutFocus() {} void StyledItemDelegateWithoutFocus::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - QStyleOptionViewItem itemOption(option); + QStyleOptionViewItem itemOption(option); - if (itemOption.state & QStyle::State_HasFocus) { - itemOption.state = itemOption.state ^ QStyle::State_HasFocus; - } + if (itemOption.state & QStyle::State_HasFocus) { + itemOption.state = itemOption.state ^ QStyle::State_HasFocus; + } - QStyledItemDelegate::paint(painter, itemOption, index); + QStyledItemDelegate::paint(painter, itemOption, index); } diff --git a/src/gui/styleditemdelegatewithoutfocus.h b/src/gui/styleditemdelegatewithoutfocus.h index fe4fb0055..35d2f808b 100755 --- a/src/gui/styleditemdelegatewithoutfocus.h +++ b/src/gui/styleditemdelegatewithoutfocus.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,16 +22,16 @@ #include #include - class StyledItemDelegateWithoutFocus : public QStyledItemDelegate { - Q_OBJECT + Q_OBJECT - public: - // Constructors. - explicit StyledItemDelegateWithoutFocus(QObject* parent = 0); - virtual ~StyledItemDelegateWithoutFocus(); + public: - void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; + // Constructors. + explicit StyledItemDelegateWithoutFocus(QObject* parent = 0); + virtual ~StyledItemDelegateWithoutFocus(); + + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; }; diff --git a/src/gui/systemtrayicon.cpp b/src/gui/systemtrayicon.cpp index dc62cb4eb..7e4435cda 100755 --- a/src/gui/systemtrayicon.cpp +++ b/src/gui/systemtrayicon.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,156 +19,162 @@ #include "gui/systemtrayicon.h" #include "definitions/definitions.h" -#include "miscellaneous/application.h" -#include "miscellaneous/settings.h" #include "gui/dialogs/formmain.h" #include "gui/dialogs/formsettings.h" +#include "miscellaneous/application.h" +#include "miscellaneous/settings.h" #include #include - #if defined(Q_OS_WIN) -TrayIconMenu::TrayIconMenu(const QString& title, QWidget* parent) : QMenu(title, parent) { -} +TrayIconMenu::TrayIconMenu(const QString& title, QWidget* parent) : QMenu(title, parent) {} -TrayIconMenu::~TrayIconMenu() { -} +TrayIconMenu::~TrayIconMenu() {} bool TrayIconMenu::event(QEvent* event) { - if (event->type() == QEvent::Show && Application::activeModalWidget() != nullptr) { - QTimer::singleShot(0, this, SLOT(hide())); - qApp->showGuiMessage(QSL(APP_LONG_NAME), - tr("Close opened modal dialogs first."), - QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - } + if (event->type() == QEvent::Show && Application::activeModalWidget() != nullptr) { + QTimer::singleShot(0, this, SLOT(hide())); + qApp->showGuiMessage(QSL(APP_LONG_NAME), + tr("Close opened modal dialogs first."), + QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); + } - return QMenu::event(event); + return QMenu::event(event); } + #endif SystemTrayIcon::SystemTrayIcon(const QString& normal_icon, const QString& plain_icon, FormMain* parent) - : QSystemTrayIcon(parent), - m_normalIcon(normal_icon), - m_plainPixmap(plain_icon) { - qDebug("Creating SystemTrayIcon instance."); - m_font.setBold(true); - // Initialize icon. - setNumber(); - setContextMenu(parent->trayMenu()); - // Create necessary connections. - connect(this, &SystemTrayIcon::activated, this, &SystemTrayIcon::onActivated); + : QSystemTrayIcon(parent), + m_normalIcon(normal_icon), + m_plainPixmap(plain_icon) { + qDebug("Creating SystemTrayIcon instance."); + m_font.setBold(true); + + // Initialize icon. + setNumber(); + setContextMenu(parent->trayMenu()); + + // Create necessary connections. + connect(this, &SystemTrayIcon::activated, this, &SystemTrayIcon::onActivated); } SystemTrayIcon::~SystemTrayIcon() { - qDebug("Destroying SystemTrayIcon instance."); - hide(); + qDebug("Destroying SystemTrayIcon instance."); + hide(); } void SystemTrayIcon::onActivated(const QSystemTrayIcon::ActivationReason& reason) { - switch (reason) { - case SystemTrayIcon::Trigger: - case SystemTrayIcon::DoubleClick: - case SystemTrayIcon::MiddleClick: - static_cast(parent())->switchVisibility(); - break; + switch (reason) { + case SystemTrayIcon::Trigger: + case SystemTrayIcon::DoubleClick: + case SystemTrayIcon::MiddleClick: + static_cast(parent())->switchVisibility(); + break; - default: - break; - } + default: + break; + } } bool SystemTrayIcon::isSystemTrayAvailable() { - return QSystemTrayIcon::isSystemTrayAvailable() && QSystemTrayIcon::supportsMessages(); + return QSystemTrayIcon::isSystemTrayAvailable() && QSystemTrayIcon::supportsMessages(); } bool SystemTrayIcon::isSystemTrayActivated() { - return SystemTrayIcon::isSystemTrayAvailable() && qApp->settings()->value(GROUP(GUI), SETTING(GUI::UseTrayIcon)).toBool(); + return SystemTrayIcon::isSystemTrayAvailable() && qApp->settings()->value(GROUP(GUI), SETTING(GUI::UseTrayIcon)).toBool(); } bool SystemTrayIcon::areNotificationsEnabled() { - return qApp->settings()->value(GROUP(GUI), SETTING(GUI::EnableNotifications)).toBool(); + return qApp->settings()->value(GROUP(GUI), SETTING(GUI::EnableNotifications)).toBool(); } void SystemTrayIcon::showPrivate() { - // Make sure that application does not exit some window (for example - // the settings window) gets closed. Behavior for main window - // is handled explicitly by FormMain::closeEvent() method. - qApp->setQuitOnLastWindowClosed(false); - // Display the tray icon. - QSystemTrayIcon::show(); - emit shown(); - qDebug("Tray icon displayed."); + // Make sure that application does not exit some window (for example + // the settings window) gets closed. Behavior for main window + // is handled explicitly by FormMain::closeEvent() method. + qApp->setQuitOnLastWindowClosed(false); + + // Display the tray icon. + QSystemTrayIcon::show(); + emit shown(); + + qDebug("Tray icon displayed."); } void SystemTrayIcon::show() { #if defined(Q_OS_WIN) - // Show immediately. - qDebug("Showing tray icon immediately."); - showPrivate(); + + // Show immediately. + qDebug("Showing tray icon immediately."); + showPrivate(); #else - // Delay avoids race conditions and tray icon is properly displayed. - qDebug("Showing tray icon with 1000 ms delay."); - QTimer::singleShot(1000, this, SLOT(showPrivate())); + + // Delay avoids race conditions and tray icon is properly displayed. + qDebug("Showing tray icon with 1000 ms delay."); + QTimer::singleShot(1000, this, SLOT(showPrivate())); #endif } void SystemTrayIcon::setNumber(int number, bool any_new_message) { - if (number <= 0) { - setToolTip(QSL(APP_LONG_NAME)); - QSystemTrayIcon::setIcon(QIcon(m_normalIcon)); - } - else { - setToolTip(tr("%1\nUnread news: %2").arg(QSL(APP_LONG_NAME), QString::number(number))); - QPixmap background(m_plainPixmap); - QPainter tray_painter; - // FIXME: Here draw different background instead of different color of number. - tray_painter.begin(&background); - tray_painter.setPen(any_new_message ? Qt::black : Qt::black); - tray_painter.setRenderHint(QPainter::SmoothPixmapTransform, true); - tray_painter.setRenderHint(QPainter::TextAntialiasing, true); + if (number <= 0) { + setToolTip(QSL(APP_LONG_NAME)); + QSystemTrayIcon::setIcon(QIcon(m_normalIcon)); + } + else { + setToolTip(tr("%1\nUnread news: %2").arg(QSL(APP_LONG_NAME), QString::number(number))); + QPixmap background(m_plainPixmap); + QPainter tray_painter; - // Numbers with more than 2 digits won't be readable, display - // infinity symbol in that case. - if (number > 999) { - m_font.setPixelSize(100); - tray_painter.setFont(m_font); - tray_painter.drawText(QRect(0, 0, 128, 128), Qt::AlignVCenter | Qt::AlignCenter, QChar(8734)); - } - else { - // Smaller number if it has 3 digits. - if (number > 99) { - m_font.setPixelSize(55); - } - else if (number > 9) { - m_font.setPixelSize(80); - } - // Bigger number if it has just one digit. - else { - m_font.setPixelSize(100); - } + // FIXME: Here draw different background instead of different color of number. + tray_painter.begin(&background); + tray_painter.setPen(any_new_message ? Qt::black : Qt::black); + tray_painter.setRenderHint(QPainter::SmoothPixmapTransform, true); + tray_painter.setRenderHint(QPainter::TextAntialiasing, true); - tray_painter.setFont(m_font); - tray_painter.drawText(QRect(0, 0, 128, 128), Qt::AlignVCenter | Qt::AlignCenter, QString::number(number)); - } + // Numbers with more than 2 digits won't be readable, display + // infinity symbol in that case. + if (number > 999) { + m_font.setPixelSize(100); + tray_painter.setFont(m_font); + tray_painter.drawText(QRect(0, 0, 128, 128), Qt::AlignVCenter | Qt::AlignCenter, QChar(8734)); + } + else { + // Smaller number if it has 3 digits. + if (number > 99) { + m_font.setPixelSize(55); + } + else if (number > 9) { + m_font.setPixelSize(80); + } - tray_painter.end(); - QSystemTrayIcon::setIcon(QIcon(background)); - } + // Bigger number if it has just one digit. + else { + m_font.setPixelSize(100); + } + + tray_painter.setFont(m_font); + tray_painter.drawText(QRect(0, 0, 128, 128), Qt::AlignVCenter | Qt::AlignCenter, QString::number(number)); + } + + tray_painter.end(); + QSystemTrayIcon::setIcon(QIcon(background)); + } } void SystemTrayIcon::showMessage(const QString& title, const QString& message, QSystemTrayIcon::MessageIcon icon, int milliseconds_timeout_hint, std::function functor) { - if (m_connection) { - // Disconnect previous bubble click signalling. - disconnect(m_connection); - } + if (m_connection) { + // Disconnect previous bubble click signalling. + disconnect(m_connection); + } - if (functor) { - // Establish new connection for bubble click. - m_connection = connect(this, &SystemTrayIcon::messageClicked, functor); - } + if (functor) { + // Establish new connection for bubble click. + m_connection = connect(this, &SystemTrayIcon::messageClicked, functor); + } - // NOTE: If connections do not work, then use QMetaObject::invokeMethod(...). - QSystemTrayIcon::showMessage(title, message, icon, milliseconds_timeout_hint); + // NOTE: If connections do not work, then use QMetaObject::invokeMethod(...). + QSystemTrayIcon::showMessage(title, message, icon, milliseconds_timeout_hint); } diff --git a/src/gui/systemtrayicon.h b/src/gui/systemtrayicon.h index eaf6b72bb..cbd5fe7cc 100755 --- a/src/gui/systemtrayicon.h +++ b/src/gui/systemtrayicon.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,71 +23,74 @@ #include "definitions/definitions.h" -#include #include +#include #include - class FormMain; class QEvent; #if defined(Q_OS_WIN) + class TrayIconMenu : public QMenu { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit TrayIconMenu(const QString& title, QWidget* parent); - virtual ~TrayIconMenu(); + public: - protected: - bool event(QEvent* event); + // Constructors and destructors. + explicit TrayIconMenu(const QString& title, QWidget* parent); + virtual ~TrayIconMenu(); + + protected: + bool event(QEvent* event); }; + #endif class SystemTrayIcon : public QSystemTrayIcon { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit SystemTrayIcon(const QString& normal_icon, - const QString& plain_icon, - FormMain* parent = 0); - virtual ~SystemTrayIcon(); + public: - // Sets the number to be visible in the tray icon, number <= 0 removes it. - void setNumber(int number = -1, bool any_new_message = false); + // Constructors and destructors. + explicit SystemTrayIcon(const QString& normal_icon, + const QString& plain_icon, + FormMain* parent = 0); + virtual ~SystemTrayIcon(); - void showMessage(const QString& title, const QString& message, MessageIcon icon = Information, - int milliseconds_timeout_hint = TRAY_ICON_BUBBLE_TIMEOUT, std::function functor = nullptr); + // Sets the number to be visible in the tray icon, number <= 0 removes it. + void setNumber(int number = -1, bool any_new_message = false); - // Returns true if tray icon CAN be constructed on this machine. - static bool isSystemTrayAvailable(); + void showMessage(const QString& title, const QString& message, MessageIcon icon = Information, + int milliseconds_timeout_hint = TRAY_ICON_BUBBLE_TIMEOUT, std::function functor = nullptr); - // Returns true if tray icon CAN be costructed and IS enabled in - // application settings. - static bool isSystemTrayActivated(); + // Returns true if tray icon CAN be constructed on this machine. + static bool isSystemTrayAvailable(); - // Determines whether balloon tips are enabled or not on tray icons. - static bool areNotificationsEnabled(); + // Returns true if tray icon CAN be costructed and IS enabled in + // application settings. + static bool isSystemTrayActivated(); - public slots: - void show(); + // Determines whether balloon tips are enabled or not on tray icons. + static bool areNotificationsEnabled(); - private slots: - void showPrivate(); - void onActivated(const QSystemTrayIcon::ActivationReason& reason); + public slots: + void show(); - signals: - void shown(); + private slots: + void showPrivate(); + void onActivated(const QSystemTrayIcon::ActivationReason& reason); - private: - QIcon m_normalIcon; - QPixmap m_plainPixmap; - QFont m_font = QFont(); + signals: + void shown(); - QMetaObject::Connection m_connection; + private: + QIcon m_normalIcon; + QPixmap m_plainPixmap; + QFont m_font = QFont(); + + QMetaObject::Connection m_connection; }; #endif // SYSTEMTRAYICON_H diff --git a/src/gui/tabbar.cpp b/src/gui/tabbar.cpp index cb507f3eb..4b1436e1f 100755 --- a/src/gui/tabbar.cpp +++ b/src/gui/tabbar.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,125 +19,127 @@ #include "gui/tabbar.h" #include "definitions/definitions.h" -#include "miscellaneous/settings.h" #include "gui/plaintoolbutton.h" +#include "miscellaneous/settings.h" #include #include - TabBar::TabBar(QWidget* parent) : QTabBar(parent) { - setDocumentMode(false); - setUsesScrollButtons(true); - setContextMenuPolicy(Qt::CustomContextMenu); + setDocumentMode(false); + setUsesScrollButtons(true); + setContextMenuPolicy(Qt::CustomContextMenu); } TabBar::~TabBar() { - qDebug("Destroying TabBar instance."); + qDebug("Destroying TabBar instance."); } void TabBar::setTabType(int index, const TabBar::TabType& type) { - const QTabBar::ButtonPosition button_position = static_cast(style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, - 0, - this)); + const QTabBar::ButtonPosition button_position = static_cast(style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, + 0, + this)); - switch (type) { - case TabBar::DownloadManager: - case TabBar::Closable: { - PlainToolButton* close_button = new PlainToolButton(this); - close_button->setIcon(qApp->icons()->fromTheme(QSL("application-exit"))); - close_button->setToolTip(tr("Close this tab.")); - close_button->setText(tr("Close tab")); - close_button->setFixedSize(iconSize()); - // Close underlying tab when button is clicked. - connect(close_button, &PlainToolButton::clicked, this, &TabBar::closeTabViaButton); - setTabButton(index, button_position, close_button); - break; - } + switch (type) { + case TabBar::DownloadManager: + case TabBar::Closable: { + PlainToolButton* close_button = new PlainToolButton(this); - case TabBar::NonClosable: - case TabBar::FeedReader: - default: - setTabButton(index, button_position, 0); - break; - } + close_button->setIcon(qApp->icons()->fromTheme(QSL("application-exit"))); + close_button->setToolTip(tr("Close this tab.")); + close_button->setText(tr("Close tab")); + close_button->setFixedSize(iconSize()); - setTabData(index, QVariant(type)); + // Close underlying tab when button is clicked. + connect(close_button, &PlainToolButton::clicked, this, &TabBar::closeTabViaButton); + setTabButton(index, button_position, close_button); + break; + } + + case TabBar::NonClosable: + case TabBar::FeedReader: + default: + setTabButton(index, button_position, 0); + break; + } + + setTabData(index, QVariant(type)); } void TabBar::closeTabViaButton() { - const QAbstractButton* close_button = qobject_cast(sender()); - const QTabBar::ButtonPosition button_position = static_cast(style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, - 0, - this)); + const QAbstractButton* close_button = qobject_cast(sender()); + const QTabBar::ButtonPosition button_position = static_cast(style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, + 0, + this)); - if (close_button != nullptr) { - // Find index of tab for this close button. - for (int i = 0; i < count(); i++) { - if (tabButton(i, button_position) == close_button) { - emit tabCloseRequested(i); - return; - } - } - } + if (close_button != nullptr) { + // Find index of tab for this close button. + for (int i = 0; i < count(); i++) { + if (tabButton(i, button_position) == close_button) { + emit tabCloseRequested(i); + + return; + } + } + } } void TabBar::wheelEvent(QWheelEvent* event) { - const int current_index = currentIndex(); - const int number_of_tabs = count(); + const int current_index = currentIndex(); + const int number_of_tabs = count(); - // Make sure rotating works. - if (number_of_tabs > 1) { - if (event->delta() > 0) { - // Scroll to the LEFT tab. - setCurrentIndex(current_index == 0 ? - number_of_tabs - 1 : - current_index - 1); - } - else if (event->delta() < 0) { - // Scroll to the RIGHT tab. - setCurrentIndex(current_index == number_of_tabs - 1 ? - 0 : - current_index + 1); - } - } + // Make sure rotating works. + if (number_of_tabs > 1) { + if (event->delta() > 0) { + // Scroll to the LEFT tab. + setCurrentIndex(current_index == 0 ? + number_of_tabs - 1 : + current_index - 1); + } + else if (event->delta() < 0) { + // Scroll to the RIGHT tab. + setCurrentIndex(current_index == number_of_tabs - 1 ? + 0 : + current_index + 1); + } + } } void TabBar::mousePressEvent(QMouseEvent* event) { - QTabBar::mousePressEvent(event); - const int tab_index = tabAt(event->pos()); + QTabBar::mousePressEvent(event); + const int tab_index = tabAt(event->pos()); - // Check if user clicked on some tab or on empty space. - if (tab_index >= 0) { - // Check if user clicked tab with middle button. - // NOTE: This needs to be done here because - // destination does not know the original event. - if (event->button() & Qt::MiddleButton && qApp->settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool()) { - if (tabType(tab_index) == TabBar::Closable || tabType(tab_index) == TabBar::DownloadManager) { - // This tab is closable, so we can close it. - emit tabCloseRequested(tab_index); - } - } - } + // Check if user clicked on some tab or on empty space. + if (tab_index >= 0) { + // Check if user clicked tab with middle button. + // NOTE: This needs to be done here because + // destination does not know the original event. + if (event->button() & Qt::MiddleButton && qApp->settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool()) { + if (tabType(tab_index) == TabBar::Closable || tabType(tab_index) == TabBar::DownloadManager) { + // This tab is closable, so we can close it. + emit tabCloseRequested(tab_index); + } + } + } } void TabBar::mouseDoubleClickEvent(QMouseEvent* event) { - QTabBar::mouseDoubleClickEvent(event); - const int tab_index = tabAt(event->pos()); + QTabBar::mouseDoubleClickEvent(event); + const int tab_index = tabAt(event->pos()); - // Check if user clicked on some tab or on empty space. - if (tab_index >= 0) { - // Check if user clicked tab with middle button. - // NOTE: This needs to be done here because - // destination does not know the original event. - if (event->button() & Qt::LeftButton && qApp->settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool()) { - if ((tabType(tab_index) & (TabBar::Closable | TabBar::DownloadManager)) > 0) { - // This tab is closable, so we can close it. - emit tabCloseRequested(tab_index); - } - } - } - else { - emit emptySpaceDoubleClicked(); - } + // Check if user clicked on some tab or on empty space. + if (tab_index >= 0) { + // Check if user clicked tab with middle button. + // NOTE: This needs to be done here because + // destination does not know the original event. + if (event->button() & Qt::LeftButton && qApp->settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool()) { + if ((tabType(tab_index) & (TabBar::Closable | TabBar::DownloadManager)) > 0) { + // This tab is closable, so we can close it. + emit tabCloseRequested(tab_index); + } + } + } + else { + emit emptySpaceDoubleClicked(); + } } diff --git a/src/gui/tabbar.h b/src/gui/tabbar.h index 33528bd56..004a45691 100755 --- a/src/gui/tabbar.h +++ b/src/gui/tabbar.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,42 +24,44 @@ #include #include - class TabBar : public QTabBar { - Q_OBJECT + Q_OBJECT - public: - enum TabType { - FeedReader = 1, - DownloadManager = 2, - NonClosable = 4, - Closable = 8 - }; + public: + enum TabType { + FeedReader = 1, + DownloadManager = 2, + NonClosable = 4, + Closable = 8 + }; - // Constructors. - explicit TabBar(QWidget* parent = 0); - virtual ~TabBar(); + // Constructors. + explicit TabBar(QWidget* parent = 0); + virtual ~TabBar(); - // Getter/setter for tab type. - void setTabType(int index, const TabBar::TabType& type); + // Getter/setter for tab type. + void setTabType(int index, const TabBar::TabType& type); - inline TabBar::TabType tabType(int index) const { - return static_cast(tabData(index).value()); - } + inline TabBar::TabType tabType(int index) const { + return static_cast(tabData(index).value()); + } - private slots: - // Called when user selects to close tab via close button. - void closeTabViaButton(); + private slots: - private: - // Reimplementations. - void mouseDoubleClickEvent(QMouseEvent* event); - void mousePressEvent(QMouseEvent* event); - void wheelEvent(QWheelEvent* event); + // Called when user selects to close tab via close button. + void closeTabViaButton(); - signals: - // Emmited if empty space on tab bar is double clicked. - void emptySpaceDoubleClicked(); + private: + + // Reimplementations. + void mouseDoubleClickEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent* event); + void wheelEvent(QWheelEvent* event); + + signals: + + // Emmited if empty space on tab bar is double clicked. + void emptySpaceDoubleClicked(); }; #endif // TABBAR_H diff --git a/src/gui/tabcontent.cpp b/src/gui/tabcontent.cpp index a86ab4884..6abd0c483 100755 --- a/src/gui/tabcontent.cpp +++ b/src/gui/tabcontent.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,9 +18,6 @@ #include "gui/tabcontent.h" +TabContent::TabContent(QWidget* parent) : QWidget(parent), m_index(-1) {} -TabContent::TabContent(QWidget* parent) : QWidget(parent), m_index(-1) { -} - -TabContent::~TabContent() { -} +TabContent::~TabContent() {} diff --git a/src/gui/tabcontent.h b/src/gui/tabcontent.h index 13d5a1477..cfa090f6f 100755 --- a/src/gui/tabcontent.h +++ b/src/gui/tabcontent.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -26,32 +27,34 @@ class WebBrowser; // Base class for all widgets which are placed inside tabs of TabWidget class TabContent : public QWidget { - Q_OBJECT + Q_OBJECT - public: - // Contructors. - explicit TabContent(QWidget* parent = 0); - virtual ~TabContent(); + public: - // Gets/sets current index of this TabContent. - // NOTE: This is the index under which this object lies - // in parent tab widget. - inline virtual int index() const { - return m_index; - } + // Contructors. + explicit TabContent(QWidget* parent = 0); + virtual ~TabContent(); - inline virtual void setIndex(int index) { - m_index = index; - } + // Gets/sets current index of this TabContent. + // NOTE: This is the index under which this object lies + // in parent tab widget. + inline virtual int index() const { + return m_index; + } + + inline virtual void setIndex(int index) { + m_index = index; + } #if defined(USE_WEBENGINE) - // Obtains instance contained in this TabContent or nullptr. - // This can be used for obtaining the menu from the instance and so on. - virtual WebBrowser* webBrowser() const = 0; + + // Obtains instance contained in this TabContent or nullptr. + // This can be used for obtaining the menu from the instance and so on. + virtual WebBrowser* webBrowser() const = 0; #endif - protected: - int m_index; + protected: + int m_index; }; #endif // TABCONTENT_H diff --git a/src/gui/tabwidget.cpp b/src/gui/tabwidget.cpp index 42152e0d7..6b57bbbf9 100755 --- a/src/gui/tabwidget.cpp +++ b/src/gui/tabwidget.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,254 +19,259 @@ #include "gui/tabwidget.h" #include "definitions/definitions.h" +#include "gui/feedmessageviewer.h" +#include "gui/feedsview.h" +#include "gui/messagesview.h" +#include "gui/tabbar.h" #include "miscellaneous/application.h" +#include "miscellaneous/iconfactory.h" #include "miscellaneous/settings.h" #include "miscellaneous/textfactory.h" -#include "miscellaneous/iconfactory.h" -#include "gui/tabbar.h" -#include "gui/messagesview.h" -#include "gui/feedsview.h" -#include "gui/feedmessageviewer.h" -#include "gui/plaintoolbutton.h" #include "gui/dialogs/formmain.h" +#include "gui/plaintoolbutton.h" #if defined(USE_WEBENGINE) #include "gui/webbrowser.h" #else -#include "network-web/webfactory.h" #include "gui/newspaperpreviewer.h" +#include "network-web/webfactory.h" #endif #include #include - TabWidget::TabWidget(QWidget* parent) : QTabWidget(parent), m_menuMain(nullptr) { - setTabBar(new TabBar(this)); - setupMainMenuButton(); - initializeTabs(); - createConnections(); + setTabBar(new TabBar(this)); + setupMainMenuButton(); + initializeTabs(); + createConnections(); } TabWidget::~TabWidget() { - qDebug("Destroying TabWidget instance."); + qDebug("Destroying TabWidget instance."); } void TabWidget::setupMainMenuButton() { - m_btnMainMenu = new PlainToolButton(this); - m_btnMainMenu->setAutoRaise(true); - m_btnMainMenu->setPadding(3); - m_btnMainMenu->setToolTip(tr("Displays main menu.")); - m_btnMainMenu->setIcon(qApp->icons()->fromTheme(QSL("go-home"))); - m_btnMainMenu->setPopupMode(QToolButton::InstantPopup); - connect(m_btnMainMenu, &PlainToolButton::clicked, this, &TabWidget::openMainMenu); + m_btnMainMenu = new PlainToolButton(this); + m_btnMainMenu->setAutoRaise(true); + m_btnMainMenu->setPadding(3); + m_btnMainMenu->setToolTip(tr("Displays main menu.")); + m_btnMainMenu->setIcon(qApp->icons()->fromTheme(QSL("go-home"))); + m_btnMainMenu->setPopupMode(QToolButton::InstantPopup); + connect(m_btnMainMenu, &PlainToolButton::clicked, this, &TabWidget::openMainMenu); } void TabWidget::openMainMenu() { - if (m_menuMain == nullptr) { - m_menuMain = new QMenu(tr("Main menu"), this); - m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuFile); - m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuView); - m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuAccounts); - m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuFeeds); - m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuMessages); - m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuWebBrowserTabs); - m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuTools); - m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuHelp); - } + if (m_menuMain == nullptr) { + m_menuMain = new QMenu(tr("Main menu"), this); + m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuFile); + m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuView); + m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuAccounts); + m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuFeeds); + m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuMessages); + m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuWebBrowserTabs); + m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuTools); + m_menuMain->addMenu(qApp->mainForm()->m_ui->m_menuHelp); + } - QPoint button_position = m_btnMainMenu->pos(); - const QSize target_size = m_btnMainMenu->size() / 2.0; - button_position.setX(button_position.x() + target_size.width()); - button_position.setY(button_position.y() + target_size.height()); - m_menuMain->exec(mapToGlobal(button_position)); + QPoint button_position = m_btnMainMenu->pos(); + const QSize target_size = m_btnMainMenu->size() / 2.0; + + button_position.setX(button_position.x() + target_size.width()); + button_position.setY(button_position.y() + target_size.height()); + m_menuMain->exec(mapToGlobal(button_position)); } void TabWidget::showDownloadManager() { - for (int i = 0; i < count(); i++) { - if (widget(i)->metaObject()->className() == QSL("DownloadManager")) { - setCurrentIndex(i); - return; - } - } + for (int i = 0; i < count(); i++) { + if (widget(i)->metaObject()->className() == QSL("DownloadManager")) { + setCurrentIndex(i); + return; + } + } - // Download manager is not opened. Create tab with it. - qApp->downloadManager()->setParent(this); - addTab(qApp->downloadManager(), qApp->icons()->fromTheme(QSL("emblem-downloads")), tr("Downloads"), TabBar::DownloadManager); - setCurrentIndex(count() - 1); + // Download manager is not opened. Create tab with it. + qApp->downloadManager()->setParent(this); + addTab(qApp->downloadManager(), qApp->icons()->fromTheme(QSL("emblem-downloads")), tr("Downloads"), TabBar::DownloadManager); + setCurrentIndex(count() - 1); } void TabWidget::checkTabBarVisibility() { - const bool should_be_visible = count() > 1 || !qApp->settings()->value(GROUP(GUI), SETTING(GUI::HideTabBarIfOnlyOneTab)).toBool(); + const bool should_be_visible = count() > 1 || !qApp->settings()->value(GROUP(GUI), SETTING(GUI::HideTabBarIfOnlyOneTab)).toBool(); - if (should_be_visible) { - setCornerWidget(m_btnMainMenu, Qt::TopLeftCorner); - m_btnMainMenu->setVisible(true); - } - else { - setCornerWidget(0, Qt::TopLeftCorner); - setCornerWidget(0, Qt::TopRightCorner); - m_btnMainMenu->setVisible(false); - } + if (should_be_visible) { + setCornerWidget(m_btnMainMenu, Qt::TopLeftCorner); + m_btnMainMenu->setVisible(true); + } + else { + setCornerWidget(0, Qt::TopLeftCorner); + setCornerWidget(0, Qt::TopRightCorner); + m_btnMainMenu->setVisible(false); + } - tabBar()->setVisible(should_be_visible); + tabBar()->setVisible(should_be_visible); } void TabWidget::tabInserted(int index) { - QTabWidget::tabInserted(index); - checkTabBarVisibility(); - const int count_of_tabs = count(); + QTabWidget::tabInserted(index); + checkTabBarVisibility(); + const int count_of_tabs = count(); - if (index < count_of_tabs - 1 && count_of_tabs > 1) { - // New tab was inserted and the tab is not the last one. - fixContentsAfterMove(index, count_of_tabs - 1); - } + if (index < count_of_tabs - 1 && count_of_tabs > 1) { + // New tab was inserted and the tab is not the last one. + fixContentsAfterMove(index, count_of_tabs - 1); + } } void TabWidget::tabRemoved(int index) { - QTabWidget::tabRemoved(index); - checkTabBarVisibility(); - const int count_of_tabs = count(); + QTabWidget::tabRemoved(index); + checkTabBarVisibility(); + const int count_of_tabs = count(); - if (index < count_of_tabs && count_of_tabs > 1) { - // Some tab was removed and the tab was not the last one. - fixContentsAfterMove(index, count_of_tabs - 1); - } + if (index < count_of_tabs && count_of_tabs > 1) { + // Some tab was removed and the tab was not the last one. + fixContentsAfterMove(index, count_of_tabs - 1); + } } void TabWidget::createConnections() { - connect(tabBar(), &TabBar::tabCloseRequested, this, &TabWidget::closeTab); - connect(tabBar(), &TabBar::emptySpaceDoubleClicked, this, &TabWidget::addEmptyBrowser); - connect(tabBar(), &TabBar::tabMoved, this, &TabWidget::fixContentsAfterMove); - connect(feedMessageViewer()->messagesView(), &MessagesView::openMessagesInNewspaperView, this, &TabWidget::addNewspaperView); - connect(feedMessageViewer()->feedsView(), &FeedsView::openMessagesInNewspaperView, this, &TabWidget::addNewspaperView); + connect(tabBar(), &TabBar::tabCloseRequested, this, &TabWidget::closeTab); + connect(tabBar(), &TabBar::emptySpaceDoubleClicked, this, &TabWidget::addEmptyBrowser); + connect(tabBar(), &TabBar::tabMoved, this, &TabWidget::fixContentsAfterMove); + connect(feedMessageViewer()->messagesView(), &MessagesView::openMessagesInNewspaperView, this, &TabWidget::addNewspaperView); + connect(feedMessageViewer()->feedsView(), &FeedsView::openMessagesInNewspaperView, this, &TabWidget::addNewspaperView); } void TabWidget::initializeTabs() { - // Create widget for "Feeds" page and add it. - m_feedMessageViewer = new FeedMessageViewer(this); - const int index_of_browser = addTab(m_feedMessageViewer, QIcon(), tr("Feeds"), TabBar::FeedReader); - setTabToolTip(index_of_browser, tr("Browse your feeds and messages")); + // Create widget for "Feeds" page and add it. + m_feedMessageViewer = new FeedMessageViewer(this); + const int index_of_browser = addTab(m_feedMessageViewer, QIcon(), tr("Feeds"), TabBar::FeedReader); + + setTabToolTip(index_of_browser, tr("Browse your feeds and messages")); } void TabWidget::setupIcons() { - // Iterate through all tabs and update icons - // accordingly. - for (int index = 0; index < count(); index++) { - // Index 0 usually contains widget which displays feeds & messages. - if (tabBar()->tabType(index) == TabBar::FeedReader) { - setTabIcon(index, qApp->icons()->fromTheme(QSL("application-rss+xml"))); - } - } + // Iterate through all tabs and update icons + // accordingly. + for (int index = 0; index < count(); index++) { + // Index 0 usually contains widget which displays feeds & messages. + if (tabBar()->tabType(index) == TabBar::FeedReader) { + setTabIcon(index, qApp->icons()->fromTheme(QSL("application-rss+xml"))); + } + } } bool TabWidget::closeTab(int index) { - if (tabBar()->tabType(index) == TabBar::Closable) { - removeTab(index, true); - return true; - } - else if (tabBar()->tabType(index) == TabBar::DownloadManager) { - removeTab(index, false); - return true; - } - else { - return false; - } + if (tabBar()->tabType(index) == TabBar::Closable) { + removeTab(index, true); + return true; + } + else if (tabBar()->tabType(index) == TabBar::DownloadManager) { + removeTab(index, false); + return true; + } + else { + return false; + } } void TabWidget::closeAllTabsExceptCurrent() { - // Close tabs after active tab. - int index_of_active = currentIndex(); + // Close tabs after active tab. + int index_of_active = currentIndex(); - for (int i = count() - 1; i >= 0; i--) { - if (i != index_of_active) { - if (i < index_of_active) { - index_of_active--; - } + for (int i = count() - 1; i >= 0; i--) { + if (i != index_of_active) { + if (i < index_of_active) { + index_of_active--; + } - closeTab(i); - } - } + closeTab(i); + } + } } void TabWidget::closeAllTabs() { - for (int i = count() - 1; i >= 0; i--) { - closeTab(i); - } + for (int i = count() - 1; i >= 0; i--) { + closeTab(i); + } } int TabWidget::addNewspaperView(RootItem* root, const QList& messages) { #if defined(USE_WEBENGINE) - WebBrowser* prev = new WebBrowser(this); + WebBrowser* prev = new WebBrowser(this); #else - NewspaperPreviewer* prev = new NewspaperPreviewer(root, messages, this); + NewspaperPreviewer* prev = new NewspaperPreviewer(root, messages, this); #endif - int index = addTab(prev, qApp->icons()->fromTheme(QSL("format-justify-fill")), tr("Newspaper view"), TabBar::Closable); - setCurrentIndex(index); + int index = addTab(prev, qApp->icons()->fromTheme(QSL("format-justify-fill")), tr("Newspaper view"), TabBar::Closable); + + setCurrentIndex(index); #if defined(USE_WEBENGINE) - prev->loadMessages(messages, root); + prev->loadMessages(messages, root); #endif - return index; + return index; } int TabWidget::addEmptyBrowser() { - return addBrowser(false, true); + return addBrowser(false, true); } int TabWidget::addLinkedBrowser(const QUrl& initial_url) { - return addBrowser(false, false, initial_url); + return addBrowser(false, false, initial_url); } int TabWidget::addLinkedBrowser(const QString& initial_url) { - return addLinkedBrowser(QUrl(initial_url)); + return addLinkedBrowser(QUrl(initial_url)); } int TabWidget::addBrowser(bool move_after_current, bool make_active, const QUrl& initial_url) { #if defined(USE_WEBENGINE) - // Create new WebBrowser. - WebBrowser* browser = new WebBrowser(this); - int final_index; - QString browser_tab_name = tr("Web browser"); + + // Create new WebBrowser. + WebBrowser* browser = new WebBrowser(this); + int final_index; + QString browser_tab_name = tr("Web browser"); + #if defined (Q_OS_MACOS) - browser_tab_name = browser_tab_name.prepend(QSL(" ")); + browser_tab_name = browser_tab_name.prepend(QSL(" ")); #endif - if (move_after_current) { - // Insert web browser after current tab. - final_index = insertTab(currentIndex() + 1, browser, qApp->icons()->fromTheme(QSL("text-html")), - browser_tab_name, TabBar::Closable); - } - else { - // Add new browser as the last tab. - final_index = addTab(browser, qApp->icons()->fromTheme(QSL("text-html")), - browser_tab_name, - TabBar::Closable); - } + if (move_after_current) { + // Insert web browser after current tab. + final_index = insertTab(currentIndex() + 1, browser, qApp->icons()->fromTheme(QSL("text-html")), + browser_tab_name, TabBar::Closable); + } + else { + // Add new browser as the last tab. + final_index = addTab(browser, qApp->icons()->fromTheme(QSL("text-html")), + browser_tab_name, + TabBar::Closable); + } - // Make connections. - connect(browser, &WebBrowser::titleChanged, this, &TabWidget::changeTitle); - connect(browser, &WebBrowser::iconChanged, this, &TabWidget::changeIcon); - // Setup the tab index. - browser->setIndex(final_index); + // Make connections. + connect(browser, &WebBrowser::titleChanged, this, &TabWidget::changeTitle); + connect(browser, &WebBrowser::iconChanged, this, &TabWidget::changeIcon); - // Load initial web page if desired. - if (initial_url.isValid()) { - browser->loadUrl(initial_url); - } + // Setup the tab index. + browser->setIndex(final_index); - // Make new web browser active if desired. - if (make_active) { - setCurrentIndex(final_index); - browser->setFocus(Qt::OtherFocusReason); - } + // Load initial web page if desired. + if (initial_url.isValid()) { + browser->loadUrl(initial_url); + } - return final_index; + // Make new web browser active if desired. + if (make_active) { + setCurrentIndex(final_index); + browser->setFocus(Qt::OtherFocusReason); + } + + return final_index; #else - Q_UNUSED(move_after_current) - Q_UNUSED(make_active) - qApp->web()->openUrlInExternalBrowser(initial_url.toString()); - return -1; + Q_UNUSED(move_after_current) + Q_UNUSED(make_active) + qApp->web()->openUrlInExternalBrowser(initial_url.toString()); + return -1; #endif } @@ -289,74 +295,77 @@ void TabWidget::gotoPreviousTab() { void TabWidget::indentTabText(int index) { #if defined (Q_OS_MACOS) + if (tabBar()->tabType(index) != TabBar::FeedReader && !tabIcon(index).isNull()) { + // We have closable tab with some icon, fix the title. + const QString text = tabText(index); - if (tabBar()->tabType(index) != TabBar::FeedReader && !tabIcon(index).isNull()) { - // We have closable tab with some icon, fix the title. - const QString text = tabText(index); - - if (!text.startsWith(QSL(" "))) { - setTabText(index, QSL(" ") + text); - } - } - + if (!text.startsWith(QSL(" "))) { + setTabText(index, QSL(" ") + text); + } + } #else - Q_UNUSED(index) + Q_UNUSED(index) #endif } void TabWidget::removeTab(int index, bool clear_from_memory) { - if (clear_from_memory) { - widget(index)->deleteLater(); - } + if (clear_from_memory) { + widget(index)->deleteLater(); + } - QTabWidget::removeTab(index); + QTabWidget::removeTab(index); } int TabWidget::addTab(TabContent* widget, const QIcon& icon, const QString& label, const TabBar::TabType& type) { - const int index = QTabWidget::addTab(widget, icon, label); - tabBar()->setTabType(index, type); - indentTabText(index); - return index; + const int index = QTabWidget::addTab(widget, icon, label); + + tabBar()->setTabType(index, type); + indentTabText(index); + return index; } int TabWidget::addTab(TabContent* widget, const QString& label, const TabBar::TabType& type) { - const int index = QTabWidget::addTab(widget, label); - tabBar()->setTabType(index, type); - indentTabText(index); - return index; + const int index = QTabWidget::addTab(widget, label); + + tabBar()->setTabType(index, type); + indentTabText(index); + return index; } int TabWidget::insertTab(int index, QWidget* widget, const QIcon& icon, const QString& label, const TabBar::TabType& type) { - const int tab_index = QTabWidget::insertTab(index, widget, icon, label); - tabBar()->setTabType(tab_index, type); - indentTabText(index); - return tab_index; + const int tab_index = QTabWidget::insertTab(index, widget, icon, label); + + tabBar()->setTabType(tab_index, type); + indentTabText(index); + return tab_index; } int TabWidget::insertTab(int index, QWidget* widget, const QString& label, const TabBar::TabType& type) { - const int tab_index = QTabWidget::insertTab(index, widget, label); - tabBar()->setTabType(tab_index, type); - indentTabText(index); - return tab_index; + const int tab_index = QTabWidget::insertTab(index, widget, label); + + tabBar()->setTabType(tab_index, type); + indentTabText(index); + return tab_index; } void TabWidget::changeIcon(int index, const QIcon& new_icon) { - setTabIcon(index, new_icon); - indentTabText(index); + setTabIcon(index, new_icon); + indentTabText(index); } void TabWidget::changeTitle(int index, const QString& new_title) { - setTabText(index, TextFactory::shorten(new_title)); - setTabToolTip(index, new_title); - indentTabText(index); + setTabText(index, TextFactory::shorten(new_title)); + setTabToolTip(index, new_title); + indentTabText(index); } void TabWidget::fixContentsAfterMove(int from, int to) { - from = qMin(from, to); - to = qMax(from, to); + from = qMin(from, to); + to = qMax(from, to); - for (; from <= to; from++) { - TabContent* content = static_cast(widget(from)); - content->setIndex(from); - } + for (; from <= to; from++) { + TabContent* content = static_cast(widget(from)); + + content->setIndex(from); + } } diff --git a/src/gui/tabwidget.h b/src/gui/tabwidget.h index 865d4e91c..fb3e4b725 100755 --- a/src/gui/tabwidget.h +++ b/src/gui/tabwidget.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,119 +21,122 @@ #include +#include "core/message.h" #include "gui/tabbar.h" #include "gui/tabcontent.h" -#include "core/message.h" #include - class QMenu; class PlainToolButton; class RootItem; class FeedMessageViewer; class TabWidget : public QTabWidget { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit TabWidget(QWidget* parent = 0); - virtual ~TabWidget(); + public: - // Manimulators for tabs. - int addTab(TabContent* widget, const QString&, - const TabBar::TabType& type = TabBar::NonClosable); - int addTab(TabContent* widget, const QIcon& icon, - const QString& label, const TabBar::TabType& type = TabBar::NonClosable); - int insertTab(int index, QWidget* widget, const QString& label, - const TabBar::TabType& type = TabBar::Closable); - int insertTab(int index, QWidget* widget, const QIcon& icon, - const QString& label, const TabBar::TabType& type = TabBar::NonClosable); - void removeTab(int index, bool clear_from_memory); + // Constructors and destructors. + explicit TabWidget(QWidget* parent = 0); + virtual ~TabWidget(); - // Returns tab bar. - inline TabBar* tabBar() const { - return static_cast(QTabWidget::tabBar()); - } + // Manimulators for tabs. + int addTab(TabContent* widget, const QString&, + const TabBar::TabType& type = TabBar::NonClosable); + int addTab(TabContent* widget, const QIcon& icon, + const QString& label, const TabBar::TabType& type = TabBar::NonClosable); + int insertTab(int index, QWidget* widget, const QString& label, + const TabBar::TabType& type = TabBar::Closable); + int insertTab(int index, QWidget* widget, const QIcon& icon, + const QString& label, const TabBar::TabType& type = TabBar::NonClosable); + void removeTab(int index, bool clear_from_memory); - // Returns the central widget of this tab. - inline TabContent* widget(int index) const { - return static_cast(QTabWidget::widget(index)); - } + // Returns tab bar. + inline TabBar* tabBar() const { + return static_cast(QTabWidget::tabBar()); + } - inline TabContent* currentWidget() const { - return static_cast(QTabWidget::currentWidget()); - } + // Returns the central widget of this tab. + inline TabContent* widget(int index) const { + return static_cast(QTabWidget::widget(index)); + } - // Initializes TabWidget with tabs, this includes initialization - // of main "Feeds" widget. - void initializeTabs(); + inline TabContent* currentWidget() const { + return static_cast(QTabWidget::currentWidget()); + } - // Sets up icons for this TabWidget. - void setupIcons(); + // Initializes TabWidget with tabs, this includes initialization + // of main "Feeds" widget. + void initializeTabs(); - // Accessor to feed/message viewer. - inline FeedMessageViewer* feedMessageViewer() const { - return m_feedMessageViewer; - } + // Sets up icons for this TabWidget. + void setupIcons(); - protected: - // Creates necesary connections. - void createConnections(); + // Accessor to feed/message viewer. + inline FeedMessageViewer* feedMessageViewer() const { + return m_feedMessageViewer; + } - // Sets up properties of custom corner button. - void setupMainMenuButton(); + protected: - // Handlers of insertin/removing of tabs. - void tabInserted(int index); - void tabRemoved(int index); + // Creates necesary connections. + void createConnections(); - public slots: - // Called when number of tab pages changes. - void checkTabBarVisibility(); + // Sets up properties of custom corner button. + void setupMainMenuButton(); - // Tab closing. - bool closeTab(int index); - void closeAllTabsExceptCurrent(); - void closeAllTabs(); + // Handlers of insertin/removing of tabs. + void tabInserted(int index); + void tabRemoved(int index); - // Displays download manager. - void showDownloadManager(); + public slots: - int addNewspaperView(RootItem* root, const QList& messages); + // Called when number of tab pages changes. + void checkTabBarVisibility(); - // Adds new WebBrowser tab to global TabWidget. - int addEmptyBrowser(); + // Tab closing. + bool closeTab(int index); + void closeAllTabsExceptCurrent(); + void closeAllTabs(); - // Adds new WebBrowser with link. This is used when user - // selects to "Open link in new tab.". - int addLinkedBrowser(const QUrl& initial_url = QUrl()); - int addLinkedBrowser(const QString& initial_url); + // Displays download manager. + void showDownloadManager(); - // General method for adding WebBrowsers. - int addBrowser(bool move_after_current, bool make_active, const QUrl& initial_url = QUrl()); + int addNewspaperView(RootItem* root, const QList& messages); + + // Adds new WebBrowser tab to global TabWidget. + int addEmptyBrowser(); + + // Adds new WebBrowser with link. This is used when user + // selects to "Open link in new tab.". + int addLinkedBrowser(const QUrl& initial_url = QUrl()); + int addLinkedBrowser(const QString& initial_url); + + // General method for adding WebBrowsers. + int addBrowser(bool move_after_current, bool make_active, const QUrl& initial_url = QUrl()); void gotoNextTab(); void gotoPreviousTab(); - private slots: - // Fixes tabs indexes. - void fixContentsAfterMove(int from, int to); + private slots: - // Changes icon/text of the tab. - void changeTitle(int index, const QString& new_title); - void changeIcon(int index, const QIcon& new_icon); + // Fixes tabs indexes. + void fixContentsAfterMove(int from, int to); - // Opens main menu. - void openMainMenu(); + // Changes icon/text of the tab. + void changeTitle(int index, const QString& new_title); + void changeIcon(int index, const QIcon& new_icon); - private: - void indentTabText(int index); + // Opens main menu. + void openMainMenu(); - PlainToolButton* m_btnMainMenu; - QMenu* m_menuMain; - FeedMessageViewer* m_feedMessageViewer; + private: + void indentTabText(int index); + + PlainToolButton* m_btnMainMenu; + QMenu* m_menuMain; + FeedMessageViewer* m_feedMessageViewer; }; #endif // TABWIDGET_H diff --git a/src/gui/timespinbox.cpp b/src/gui/timespinbox.cpp index 67ecff894..e6a9ce3d3 100755 --- a/src/gui/timespinbox.cpp +++ b/src/gui/timespinbox.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,67 +20,66 @@ #include - TimeSpinBox::TimeSpinBox(QWidget* parent) : QDoubleSpinBox(parent) { - setMinimum(5.0); - setAccelerated(true); - setDecimals(0); - setMaximum(10000000.0); + setMinimum(5.0); + setAccelerated(true); + setDecimals(0); + setMaximum(10000000.0); } -TimeSpinBox::~TimeSpinBox() { -} +TimeSpinBox::~TimeSpinBox() {} double TimeSpinBox::valueFromText(const QString& text) const { - bool ok; - double value = text.toDouble(&ok); + bool ok; + double value = text.toDouble(&ok); - if (ok) { - return value; - } - else { - QRegExp rx("\\b[0-9]{1,}\\b"); - QStringList numbers; - int pos = 0; - int count = 0; + if (ok) { + return value; + } + else { + QRegExp rx("\\b[0-9]{1,}\\b"); + QStringList numbers; + int pos = 0; + int count = 0; - while ((pos = rx.indexIn(text, pos)) != -1) { - numbers.append(rx.cap(0)); + while ((pos = rx.indexIn(text, pos)) != -1) { + numbers.append(rx.cap(0)); - if (pos >= 0) { - ++pos; - ++count; - } - } + if (pos >= 0) { + ++pos; + ++count; + } + } - if (numbers.size() == 2) { - return (numbers.at(0).toDouble() * 60.0) + numbers.at(1).toDouble(); - } - else { - return -1.0; - } - } + if (numbers.size() == 2) { + return (numbers.at(0).toDouble() * 60.0) + numbers.at(1).toDouble(); + } + else { + return -1.0; + } + } } QString TimeSpinBox::textFromValue(double val) const { - int minutes_total = (int)val; - int minutes_val = minutes_total % 60; - int hours_val = (minutes_total - minutes_val) / 60; - QString hours = tr("%n hour(s)", "", hours_val); - QString minutes = tr("%n minute(s)", "", minutes_val); - return hours + tr(" and ") + minutes; + int minutes_total = (int)val; + int minutes_val = minutes_total % 60; + int hours_val = (minutes_total - minutes_val) / 60; + QString hours = tr("%n hour(s)", "", hours_val); + QString minutes = tr("%n minute(s)", "", minutes_val); + + return hours + tr(" and ") + minutes; } void TimeSpinBox::fixup(QString& input) const { - bool ok; - double value = input.toDouble(&ok); + bool ok; + double value = input.toDouble(&ok); - if (ok) { - input = textFromValue(value); - } + if (ok) { + input = textFromValue(value); + } } QValidator::State TimeSpinBox::validate(QString& input, int& pos) const { - Q_UNUSED(pos) - return (valueFromText(input) != -1.0) ? QValidator::Acceptable : QValidator::Intermediate; + Q_UNUSED(pos) + return (valueFromText(input) != -1.0) ? QValidator::Acceptable : QValidator::Intermediate; } diff --git a/src/gui/timespinbox.h b/src/gui/timespinbox.h index 7b5619571..ffa3e6d53 100755 --- a/src/gui/timespinbox.h +++ b/src/gui/timespinbox.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,18 +21,17 @@ #include - class TimeSpinBox : public QDoubleSpinBox { - Q_OBJECT + Q_OBJECT - public: - explicit TimeSpinBox(QWidget* parent = 0); - virtual ~TimeSpinBox(); + public: + explicit TimeSpinBox(QWidget* parent = 0); + virtual ~TimeSpinBox(); - double valueFromText(const QString& text) const; - QString textFromValue(double val) const; - void fixup(QString& input) const; - QValidator::State validate(QString& input, int& pos) const; + double valueFromText(const QString& text) const; + QString textFromValue(double val) const; + void fixup(QString& input) const; + QValidator::State validate(QString& input, int& pos) const; }; #endif // TIMESPINBOX_H diff --git a/src/gui/toolbareditor.cpp b/src/gui/toolbareditor.cpp index 53d032ca2..659377bfb 100755 --- a/src/gui/toolbareditor.cpp +++ b/src/gui/toolbareditor.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,243 +23,247 @@ #include - ToolBarEditor::ToolBarEditor(QWidget* parent) - : QWidget(parent), m_ui(new Ui::ToolBarEditor) { - m_ui->setupUi(this); + : QWidget(parent), m_ui(new Ui::ToolBarEditor) { + m_ui->setupUi(this); - // Create connections. - connect(m_ui->m_btnInsertSeparator, &QToolButton::clicked, this, &ToolBarEditor::insertSeparator); - connect(m_ui->m_btnInsertSpacer, &QToolButton::clicked, this, &ToolBarEditor::insertSpacer); - connect(m_ui->m_btnAddSelectedAction, &QToolButton::clicked, this, &ToolBarEditor::addSelectedAction); - connect(m_ui->m_btnDeleteAllActions, &QToolButton::clicked, this, &ToolBarEditor::deleteAllActions); - connect(m_ui->m_btnDeleteSelectedAction, &QToolButton::clicked, this, &ToolBarEditor::deleteSelectedAction); - connect(m_ui->m_btnMoveActionUp, &QToolButton::clicked, this, &ToolBarEditor::moveActionUp); - connect(m_ui->m_btnMoveActionDown, &QToolButton::clicked, this, &ToolBarEditor::moveActionDown); - connect(m_ui->m_btnReset, &QToolButton::clicked, this, &ToolBarEditor::resetToolBar); - connect(m_ui->m_listAvailableActions, &QListWidget::itemSelectionChanged, this, &ToolBarEditor::updateActionsAvailability); - connect(m_ui->m_listActivatedActions, &QListWidget::itemSelectionChanged, this, &ToolBarEditor::updateActionsAvailability); - connect(m_ui->m_listActivatedActions, &QListWidget::itemDoubleClicked, this, &ToolBarEditor::deleteSelectedAction); - connect(m_ui->m_listAvailableActions, &QListWidget::itemDoubleClicked, this, &ToolBarEditor::addSelectedAction); - m_ui->m_listActivatedActions->installEventFilter(this); - m_ui->m_btnInsertSeparator->setIcon(qApp->icons()->fromTheme(QSL("insert-object"))); - m_ui->m_btnInsertSpacer->setIcon(qApp->icons()->fromTheme(QSL("go-jump"))); - m_ui->m_btnAddSelectedAction->setIcon(qApp->icons()->fromTheme(QSL("back"))); - m_ui->m_btnDeleteAllActions->setIcon(qApp->icons()->fromTheme(QSL("application-exit"))); - m_ui->m_btnDeleteSelectedAction->setIcon(qApp->icons()->fromTheme(QSL("forward"))); - m_ui->m_btnMoveActionDown->setIcon(qApp->icons()->fromTheme(QSL("down"))); - m_ui->m_btnMoveActionUp->setIcon(qApp->icons()->fromTheme(QSL("up"))); - m_ui->m_btnReset->setIcon(qApp->icons()->fromTheme(QSL("reload"))); + // Create connections. + connect(m_ui->m_btnInsertSeparator, &QToolButton::clicked, this, &ToolBarEditor::insertSeparator); + connect(m_ui->m_btnInsertSpacer, &QToolButton::clicked, this, &ToolBarEditor::insertSpacer); + connect(m_ui->m_btnAddSelectedAction, &QToolButton::clicked, this, &ToolBarEditor::addSelectedAction); + connect(m_ui->m_btnDeleteAllActions, &QToolButton::clicked, this, &ToolBarEditor::deleteAllActions); + connect(m_ui->m_btnDeleteSelectedAction, &QToolButton::clicked, this, &ToolBarEditor::deleteSelectedAction); + connect(m_ui->m_btnMoveActionUp, &QToolButton::clicked, this, &ToolBarEditor::moveActionUp); + connect(m_ui->m_btnMoveActionDown, &QToolButton::clicked, this, &ToolBarEditor::moveActionDown); + connect(m_ui->m_btnReset, &QToolButton::clicked, this, &ToolBarEditor::resetToolBar); + connect(m_ui->m_listAvailableActions, &QListWidget::itemSelectionChanged, this, &ToolBarEditor::updateActionsAvailability); + connect(m_ui->m_listActivatedActions, &QListWidget::itemSelectionChanged, this, &ToolBarEditor::updateActionsAvailability); + connect(m_ui->m_listActivatedActions, &QListWidget::itemDoubleClicked, this, &ToolBarEditor::deleteSelectedAction); + connect(m_ui->m_listAvailableActions, &QListWidget::itemDoubleClicked, this, &ToolBarEditor::addSelectedAction); + m_ui->m_listActivatedActions->installEventFilter(this); + m_ui->m_btnInsertSeparator->setIcon(qApp->icons()->fromTheme(QSL("insert-object"))); + m_ui->m_btnInsertSpacer->setIcon(qApp->icons()->fromTheme(QSL("go-jump"))); + m_ui->m_btnAddSelectedAction->setIcon(qApp->icons()->fromTheme(QSL("back"))); + m_ui->m_btnDeleteAllActions->setIcon(qApp->icons()->fromTheme(QSL("application-exit"))); + m_ui->m_btnDeleteSelectedAction->setIcon(qApp->icons()->fromTheme(QSL("forward"))); + m_ui->m_btnMoveActionDown->setIcon(qApp->icons()->fromTheme(QSL("down"))); + m_ui->m_btnMoveActionUp->setIcon(qApp->icons()->fromTheme(QSL("up"))); + m_ui->m_btnReset->setIcon(qApp->icons()->fromTheme(QSL("reload"))); } ToolBarEditor::~ToolBarEditor() { - qDebug("Destroying ToolBarEditor instance."); + qDebug("Destroying ToolBarEditor instance."); } void ToolBarEditor::loadFromToolBar(BaseBar* tool_bar) { - m_toolBar = tool_bar; + m_toolBar = tool_bar; - QList activated_actions = m_toolBar->changeableActions(); - QList available_actions = m_toolBar->availableActions(); - loadEditor(activated_actions, available_actions); + QList activated_actions = m_toolBar->changeableActions(); + QList available_actions = m_toolBar->availableActions(); + loadEditor(activated_actions, available_actions); } void ToolBarEditor::saveToolBar() { - QStringList action_names; + QStringList action_names; - for (int i = 0; i < m_ui->m_listActivatedActions->count(); i++) { - action_names.append(m_ui->m_listActivatedActions->item(i)->data(Qt::UserRole).toString()); - } + for (int i = 0; i < m_ui->m_listActivatedActions->count(); i++) { + action_names.append(m_ui->m_listActivatedActions->item(i)->data(Qt::UserRole).toString()); + } - m_toolBar->saveChangeableActions(action_names); + m_toolBar->saveChangeableActions(action_names); } void ToolBarEditor::resetToolBar() { - if (m_toolBar != nullptr) { - loadEditor(m_toolBar->getSpecificActions(m_toolBar->defaultActions()), m_toolBar->availableActions()); - } + if (m_toolBar != nullptr) { + loadEditor(m_toolBar->getSpecificActions(m_toolBar->defaultActions()), m_toolBar->availableActions()); + } } void ToolBarEditor::loadEditor(const QList activated_actions, const QList available_actions) { - m_ui->m_listActivatedActions->clear(); - m_ui->m_listAvailableActions->clear(); + m_ui->m_listActivatedActions->clear(); + m_ui->m_listAvailableActions->clear(); - foreach (const QAction* action, activated_actions) { - QListWidgetItem* action_item = new QListWidgetItem(action->icon(), action->text().replace('&', ""), m_ui->m_listActivatedActions); + foreach (const QAction* action, activated_actions) { + QListWidgetItem* action_item = new QListWidgetItem(action->icon(), action->text().replace('&', ""), m_ui->m_listActivatedActions); - if (action->isSeparator()) { - action_item->setData(Qt::UserRole, SEPARATOR_ACTION_NAME); - action_item->setIcon(qApp->icons()->fromTheme(QSL("insert-object"))); - action_item->setText(tr("Separator")); - action_item->setToolTip(tr("Separator")); - } - else if (action->property("type").isValid()) { - action_item->setData(Qt::UserRole, action->property("type").toString()); - action_item->setText(action->property("name").toString()); - action_item->setToolTip(action_item->text()); - } - else { - action_item->setData(Qt::UserRole, action->objectName()); - action_item->setToolTip(action->toolTip()); - } - } + if (action->isSeparator()) { + action_item->setData(Qt::UserRole, SEPARATOR_ACTION_NAME); + action_item->setIcon(qApp->icons()->fromTheme(QSL("insert-object"))); + action_item->setText(tr("Separator")); + action_item->setToolTip(tr("Separator")); + } + else if (action->property("type").isValid()) { + action_item->setData(Qt::UserRole, action->property("type").toString()); + action_item->setText(action->property("name").toString()); + action_item->setToolTip(action_item->text()); + } + else { + action_item->setData(Qt::UserRole, action->objectName()); + action_item->setToolTip(action->toolTip()); + } + } - foreach (QAction* action, available_actions) { - if (!activated_actions.contains(action)) { - QListWidgetItem* action_item = new QListWidgetItem(action->icon(), action->text().replace('&', ""), m_ui->m_listAvailableActions); + foreach (QAction* action, available_actions) { + if (!activated_actions.contains(action)) { + QListWidgetItem* action_item = new QListWidgetItem(action->icon(), action->text().replace('&', ""), m_ui->m_listAvailableActions); - if (action->isSeparator()) { - action_item->setData(Qt::UserRole, SEPARATOR_ACTION_NAME); - action_item->setText(tr("Separator")); - action_item->setToolTip(tr("Separator")); - action_item->setIcon(qApp->icons()->fromTheme(QSL("insert-object"))); - } - else if (action->property("type").isValid()) { - action_item->setData(Qt::UserRole, action->property("type").toString()); - action_item->setText(action->property("name").toString()); - action_item->setToolTip(action_item->text()); - } - else { - action_item->setData(Qt::UserRole, action->objectName()); - action_item->setToolTip(action->toolTip()); - } - } - } + if (action->isSeparator()) { + action_item->setData(Qt::UserRole, SEPARATOR_ACTION_NAME); + action_item->setText(tr("Separator")); + action_item->setToolTip(tr("Separator")); + action_item->setIcon(qApp->icons()->fromTheme(QSL("insert-object"))); + } + else if (action->property("type").isValid()) { + action_item->setData(Qt::UserRole, action->property("type").toString()); + action_item->setText(action->property("name").toString()); + action_item->setToolTip(action_item->text()); + } + else { + action_item->setData(Qt::UserRole, action->objectName()); + action_item->setToolTip(action->toolTip()); + } + } + } - m_ui->m_listAvailableActions->sortItems(Qt::AscendingOrder); - m_ui->m_listAvailableActions->setCurrentRow(m_ui->m_listAvailableActions->count() >= 0 ? 0 : -1); - m_ui->m_listActivatedActions->setCurrentRow(m_ui->m_listActivatedActions->count() >= 0 ? 0 : -1); + m_ui->m_listAvailableActions->sortItems(Qt::AscendingOrder); + m_ui->m_listAvailableActions->setCurrentRow(m_ui->m_listAvailableActions->count() >= 0 ? 0 : -1); + m_ui->m_listActivatedActions->setCurrentRow(m_ui->m_listActivatedActions->count() >= 0 ? 0 : -1); } bool ToolBarEditor::eventFilter(QObject* object, QEvent* event) { - if (object == m_ui->m_listActivatedActions) { - if (event->type() == QEvent::KeyPress) { - const QKeyEvent* key_event = static_cast(event); + if (object == m_ui->m_listActivatedActions) { + if (event->type() == QEvent::KeyPress) { + const QKeyEvent* key_event = static_cast(event); - if (key_event->key() == Qt::Key_Delete) { - deleteSelectedAction(); - return true; - } - else if (key_event->key() == Qt::Key_Down && key_event->modifiers() & Qt::ControlModifier) { - moveActionDown(); - return true; - } - else if (key_event->key() == Qt::Key_Up && key_event->modifiers() & Qt::ControlModifier) { - moveActionUp(); - return true; - } - } - } + if (key_event->key() == Qt::Key_Delete) { + deleteSelectedAction(); + return true; + } + else if (key_event->key() == Qt::Key_Down && key_event->modifiers() & Qt::ControlModifier) { + moveActionDown(); + return true; + } + else if (key_event->key() == Qt::Key_Up && key_event->modifiers() & Qt::ControlModifier) { + moveActionUp(); + return true; + } + } + } - return false; + return false; } void ToolBarEditor::updateActionsAvailability() { - m_ui->m_btnDeleteAllActions->setEnabled(m_ui->m_listActivatedActions->count() > 0); - m_ui->m_btnDeleteSelectedAction->setEnabled(m_ui->m_listActivatedActions->selectedItems().size() == 1); - m_ui->m_btnMoveActionUp->setEnabled(m_ui->m_listActivatedActions->selectedItems().size() == 1 && - m_ui->m_listActivatedActions->currentRow() > 0); - m_ui->m_btnMoveActionDown->setEnabled(m_ui->m_listActivatedActions->selectedItems().size() == 1 && - m_ui->m_listActivatedActions->currentRow() < m_ui->m_listActivatedActions->count() - 1); - m_ui->m_btnAddSelectedAction->setEnabled(m_ui->m_listAvailableActions->selectedItems().size() > 0); + m_ui->m_btnDeleteAllActions->setEnabled(m_ui->m_listActivatedActions->count() > 0); + m_ui->m_btnDeleteSelectedAction->setEnabled(m_ui->m_listActivatedActions->selectedItems().size() == 1); + m_ui->m_btnMoveActionUp->setEnabled(m_ui->m_listActivatedActions->selectedItems().size() == 1 && + m_ui->m_listActivatedActions->currentRow() > 0); + m_ui->m_btnMoveActionDown->setEnabled(m_ui->m_listActivatedActions->selectedItems().size() == 1 && + m_ui->m_listActivatedActions->currentRow() < m_ui->m_listActivatedActions->count() - 1); + m_ui->m_btnAddSelectedAction->setEnabled(m_ui->m_listAvailableActions->selectedItems().size() > 0); } void ToolBarEditor::insertSpacer() { - const int current_row = m_ui->m_listActivatedActions->currentRow(); - QListWidgetItem* item = new QListWidgetItem(tr("Toolbar spacer")); - item->setIcon(qApp->icons()->fromTheme(QSL("go-jump"))); - item->setData(Qt::UserRole, SPACER_ACTION_NAME); - m_ui->m_listActivatedActions->insertItem(current_row + 1, item); - m_ui->m_listActivatedActions->setCurrentRow(current_row + 1); - emit setupChanged(); + const int current_row = m_ui->m_listActivatedActions->currentRow(); + QListWidgetItem* item = new QListWidgetItem(tr("Toolbar spacer")); + + item->setIcon(qApp->icons()->fromTheme(QSL("go-jump"))); + item->setData(Qt::UserRole, SPACER_ACTION_NAME); + m_ui->m_listActivatedActions->insertItem(current_row + 1, item); + m_ui->m_listActivatedActions->setCurrentRow(current_row + 1); + emit setupChanged(); } void ToolBarEditor::insertSeparator() { - const int current_row = m_ui->m_listActivatedActions->currentRow(); - QListWidgetItem* item = new QListWidgetItem(tr("Separator")); - item->setData(Qt::UserRole, SEPARATOR_ACTION_NAME); - item->setToolTip(tr("Separator")); - item->setIcon(qApp->icons()->fromTheme(QSL("insert-object"))); - m_ui->m_listActivatedActions->insertItem(current_row + 1, item); - m_ui->m_listActivatedActions->setCurrentRow(current_row + 1); - emit setupChanged(); + const int current_row = m_ui->m_listActivatedActions->currentRow(); + QListWidgetItem* item = new QListWidgetItem(tr("Separator")); + + item->setData(Qt::UserRole, SEPARATOR_ACTION_NAME); + item->setToolTip(tr("Separator")); + item->setIcon(qApp->icons()->fromTheme(QSL("insert-object"))); + m_ui->m_listActivatedActions->insertItem(current_row + 1, item); + m_ui->m_listActivatedActions->setCurrentRow(current_row + 1); + emit setupChanged(); } void ToolBarEditor::moveActionDown() { - QList items = m_ui->m_listActivatedActions->selectedItems(); + QList items = m_ui->m_listActivatedActions->selectedItems(); - if (items.size() == 1 && m_ui->m_listActivatedActions->currentRow() < m_ui->m_listActivatedActions->count() - 1) { - QListWidgetItem* selected_item = items.at(0); - int row = m_ui->m_listActivatedActions->row(selected_item); - m_ui->m_listActivatedActions->takeItem(row++); - m_ui->m_listActivatedActions->insertItem(row, selected_item); - m_ui->m_listActivatedActions->setCurrentRow(row); - emit setupChanged(); - } + if (items.size() == 1 && m_ui->m_listActivatedActions->currentRow() < m_ui->m_listActivatedActions->count() - 1) { + QListWidgetItem* selected_item = items.at(0); + int row = m_ui->m_listActivatedActions->row(selected_item); + + m_ui->m_listActivatedActions->takeItem(row++); + m_ui->m_listActivatedActions->insertItem(row, selected_item); + m_ui->m_listActivatedActions->setCurrentRow(row); + emit setupChanged(); + } } void ToolBarEditor::moveActionUp() { - QList items = m_ui->m_listActivatedActions->selectedItems(); + QList items = m_ui->m_listActivatedActions->selectedItems(); - if (items.size() == 1 && m_ui->m_listActivatedActions->currentRow() > 0) { - QListWidgetItem* selected_item = items.at(0); - int row = m_ui->m_listActivatedActions->row(selected_item); - m_ui->m_listActivatedActions->takeItem(row--); - m_ui->m_listActivatedActions->insertItem(row, selected_item); - m_ui->m_listActivatedActions->setCurrentRow(row); - emit setupChanged(); - } + if (items.size() == 1 && m_ui->m_listActivatedActions->currentRow() > 0) { + QListWidgetItem* selected_item = items.at(0); + int row = m_ui->m_listActivatedActions->row(selected_item); + + m_ui->m_listActivatedActions->takeItem(row--); + m_ui->m_listActivatedActions->insertItem(row, selected_item); + m_ui->m_listActivatedActions->setCurrentRow(row); + emit setupChanged(); + } } void ToolBarEditor::addSelectedAction() { - QList items = m_ui->m_listAvailableActions->selectedItems(); + QList items = m_ui->m_listAvailableActions->selectedItems(); - if (items.size() == 1) { - QListWidgetItem* selected_item = items.at(0); - m_ui->m_listActivatedActions->insertItem( - m_ui->m_listActivatedActions->currentRow() + 1, - m_ui->m_listAvailableActions->takeItem(m_ui->m_listAvailableActions->row(selected_item))); - m_ui->m_listActivatedActions->setCurrentRow(m_ui->m_listActivatedActions->currentRow() + 1); - emit setupChanged(); - } + if (items.size() == 1) { + QListWidgetItem* selected_item = items.at(0); + + m_ui->m_listActivatedActions->insertItem( + m_ui->m_listActivatedActions->currentRow() + 1, + m_ui->m_listAvailableActions->takeItem(m_ui->m_listAvailableActions->row(selected_item))); + m_ui->m_listActivatedActions->setCurrentRow(m_ui->m_listActivatedActions->currentRow() + 1); + emit setupChanged(); + } } void ToolBarEditor::deleteSelectedAction() { - QList items = m_ui->m_listActivatedActions->selectedItems(); + QList items = m_ui->m_listActivatedActions->selectedItems(); - if (items.size() == 1) { - QListWidgetItem* selected_item = items.at(0); - const QString data_item = selected_item->data(Qt::UserRole).toString(); + if (items.size() == 1) { + QListWidgetItem* selected_item = items.at(0); + const QString data_item = selected_item->data(Qt::UserRole).toString(); - if (data_item == SEPARATOR_ACTION_NAME || data_item == SPACER_ACTION_NAME) { - m_ui->m_listActivatedActions->takeItem(m_ui->m_listActivatedActions->row(selected_item)); - updateActionsAvailability(); - } - else { - m_ui->m_listAvailableActions->insertItem( - m_ui->m_listAvailableActions->currentRow() + 1, - m_ui->m_listActivatedActions->takeItem(m_ui->m_listActivatedActions->row(selected_item))); - m_ui->m_listAvailableActions->sortItems(Qt::AscendingOrder); - m_ui->m_listAvailableActions->setCurrentRow(m_ui->m_listAvailableActions->currentRow() + 1); - } + if (data_item == SEPARATOR_ACTION_NAME || data_item == SPACER_ACTION_NAME) { + m_ui->m_listActivatedActions->takeItem(m_ui->m_listActivatedActions->row(selected_item)); + updateActionsAvailability(); + } + else { + m_ui->m_listAvailableActions->insertItem( + m_ui->m_listAvailableActions->currentRow() + 1, + m_ui->m_listActivatedActions->takeItem(m_ui->m_listActivatedActions->row(selected_item))); + m_ui->m_listAvailableActions->sortItems(Qt::AscendingOrder); + m_ui->m_listAvailableActions->setCurrentRow(m_ui->m_listAvailableActions->currentRow() + 1); + } - emit setupChanged(); - } + emit setupChanged(); + } } void ToolBarEditor::deleteAllActions() { - QListWidgetItem* taken_item; - QString data_item; + QListWidgetItem* taken_item; + QString data_item; - while ((taken_item = m_ui->m_listActivatedActions->takeItem(0)) != 0) { - data_item = taken_item->data(Qt::UserRole).toString(); + while ((taken_item = m_ui->m_listActivatedActions->takeItem(0)) != 0) { + data_item = taken_item->data(Qt::UserRole).toString(); - if (data_item != SEPARATOR_ACTION_NAME && data_item != SPACER_ACTION_NAME) { - m_ui->m_listAvailableActions->insertItem(m_ui->m_listAvailableActions->currentRow() + 1, taken_item); - } - } + if (data_item != SEPARATOR_ACTION_NAME && data_item != SPACER_ACTION_NAME) { + m_ui->m_listAvailableActions->insertItem(m_ui->m_listAvailableActions->currentRow() + 1, taken_item); + } + } - m_ui->m_listAvailableActions->sortItems(Qt::AscendingOrder); - updateActionsAvailability(); - emit setupChanged(); + m_ui->m_listAvailableActions->sortItems(Qt::AscendingOrder); + updateActionsAvailability(); + emit setupChanged(); } diff --git a/src/gui/toolbareditor.h b/src/gui/toolbareditor.h index 1488e23fe..60fb0c49b 100755 --- a/src/gui/toolbareditor.h +++ b/src/gui/toolbareditor.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,60 +23,60 @@ #include "ui_toolbareditor.h" - namespace Ui { - class ToolBarEditor; + class ToolBarEditor; } class BaseBar; class ToolBarEditor : public QWidget { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit ToolBarEditor(QWidget* parent = 0); - virtual ~ToolBarEditor(); + public: - // Toolbar operations. - void loadFromToolBar(BaseBar* tool_bar); - void saveToolBar(); + // Constructors and destructors. + explicit ToolBarEditor(QWidget* parent = 0); + virtual ~ToolBarEditor(); - inline QListWidget* activeItemsWidget() const { - return m_ui->m_listActivatedActions; - } + // Toolbar operations. + void loadFromToolBar(BaseBar* tool_bar); + void saveToolBar(); - inline QListWidget* availableItemsWidget() const { - return m_ui->m_listAvailableActions; - } + inline QListWidget* activeItemsWidget() const { + return m_ui->m_listActivatedActions; + } - protected: - bool eventFilter(QObject* object, QEvent* event); + inline QListWidget* availableItemsWidget() const { + return m_ui->m_listAvailableActions; + } - private slots: - void updateActionsAvailability(); + protected: + bool eventFilter(QObject* object, QEvent* event); - // Insert common controls. - void insertSpacer(); - void insertSeparator(); + private slots: + void updateActionsAvailability(); - void moveActionDown(); - void moveActionUp(); + // Insert common controls. + void insertSpacer(); + void insertSeparator(); - void addSelectedAction(); - void deleteSelectedAction(); - void deleteAllActions(); + void moveActionDown(); + void moveActionUp(); - void resetToolBar(); + void addSelectedAction(); + void deleteSelectedAction(); + void deleteAllActions(); - signals: - void setupChanged(); + void resetToolBar(); - private: - void loadEditor(const QList activated_actions, const QList available_actions); + signals: + void setupChanged(); - QScopedPointer m_ui; - BaseBar* m_toolBar; + private: + void loadEditor(const QList activated_actions, const QList available_actions); + + QScopedPointer m_ui; + BaseBar* m_toolBar; }; #endif // TOOLBAREDITOR_H diff --git a/src/gui/treeviewcolumnsmenu.cpp b/src/gui/treeviewcolumnsmenu.cpp index 13761be53..d5090f5e6 100755 --- a/src/gui/treeviewcolumnsmenu.cpp +++ b/src/gui/treeviewcolumnsmenu.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,32 +20,31 @@ #include - TreeViewColumnsMenu::TreeViewColumnsMenu(QHeaderView* parent) : QMenu(parent) { - connect(this, &TreeViewColumnsMenu::aboutToShow, this, &TreeViewColumnsMenu::prepareMenu); + connect(this, &TreeViewColumnsMenu::aboutToShow, this, &TreeViewColumnsMenu::prepareMenu); } -TreeViewColumnsMenu::~TreeViewColumnsMenu() { -} +TreeViewColumnsMenu::~TreeViewColumnsMenu() {} void TreeViewColumnsMenu::prepareMenu() { - QHeaderView* header_view = header(); + QHeaderView* header_view = header(); - for (int i = 0; i < header_view->count(); i++) { - QAction* act = addAction(header_view->model()->headerData(i, Qt::Horizontal, Qt::EditRole).toString()); - act->setData(i); - act->setCheckable(true); - act->setChecked(!header_view->isSectionHidden(i)); - connect(act, &QAction::toggled, this, &TreeViewColumnsMenu::actionTriggered); - } + for (int i = 0; i < header_view->count(); i++) { + QAction* act = addAction(header_view->model()->headerData(i, Qt::Horizontal, Qt::EditRole).toString()); + + act->setData(i); + act->setCheckable(true); + act->setChecked(!header_view->isSectionHidden(i)); + connect(act, &QAction::toggled, this, &TreeViewColumnsMenu::actionTriggered); + } } void TreeViewColumnsMenu::actionTriggered(bool toggle) { - Q_UNUSED(toggle) - QAction* send_act = qobject_cast(sender()); - header()->setSectionHidden(send_act->data().toInt(), !send_act->isChecked()); + Q_UNUSED(toggle) + QAction * send_act = qobject_cast(sender()); + header()->setSectionHidden(send_act->data().toInt(), !send_act->isChecked()); } QHeaderView* TreeViewColumnsMenu::header() { - return qobject_cast(parent()); + return qobject_cast(parent()); } diff --git a/src/gui/treeviewcolumnsmenu.h b/src/gui/treeviewcolumnsmenu.h index e09ff854e..7e37c33e2 100755 --- a/src/gui/treeviewcolumnsmenu.h +++ b/src/gui/treeviewcolumnsmenu.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,20 +21,19 @@ #include - class QHeaderView; class TreeViewColumnsMenu : public QMenu { - public: - explicit TreeViewColumnsMenu(QHeaderView* parent); - virtual ~TreeViewColumnsMenu(); + public: + explicit TreeViewColumnsMenu(QHeaderView* parent); + virtual ~TreeViewColumnsMenu(); - private slots: - void prepareMenu(); - void actionTriggered(bool toggle); + private slots: + void prepareMenu(); + void actionTriggered(bool toggle); - private: - QHeaderView* header(); + private: + QHeaderView* header(); }; #endif // TREEVIEWCOLUMNSMENU_H diff --git a/src/gui/treewidget.cpp b/src/gui/treewidget.cpp index 3a55c1f96..50951bd56 100755 --- a/src/gui/treewidget.cpp +++ b/src/gui/treewidget.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -20,182 +21,182 @@ #include - TreeWidget::TreeWidget(QWidget* parent) - : QTreeWidget(parent), m_refreshAllItemsNeeded(true), m_showMode(ItemsCollapsed) { - connect(this, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(sheduleRefresh())); + : QTreeWidget(parent), m_refreshAllItemsNeeded(true), m_showMode(ItemsCollapsed) { + connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(sheduleRefresh())); } void TreeWidget::clear() { - QTreeWidget::clear(); - m_allTreeItems.clear(); + QTreeWidget::clear(); + m_allTreeItems.clear(); } void TreeWidget::sheduleRefresh() { - m_refreshAllItemsNeeded = true; + m_refreshAllItemsNeeded = true; } void TreeWidget::addTopLevelItem(QTreeWidgetItem* item) { - m_allTreeItems.append(item); - QTreeWidget::addTopLevelItem(item); + m_allTreeItems.append(item); + QTreeWidget::addTopLevelItem(item); } void TreeWidget::addTopLevelItems(const QList& items) { - m_allTreeItems.append(items); - QTreeWidget::addTopLevelItems(items); + m_allTreeItems.append(items); + QTreeWidget::addTopLevelItems(items); } void TreeWidget::insertTopLevelItem(int index, QTreeWidgetItem* item) { - m_allTreeItems.append(item); - QTreeWidget::insertTopLevelItem(index, item); + m_allTreeItems.append(item); + QTreeWidget::insertTopLevelItem(index, item); } void TreeWidget::insertTopLevelItems(int index, const QList& items) { - m_allTreeItems.append(items); - QTreeWidget::insertTopLevelItems(index, items); + m_allTreeItems.append(items); + QTreeWidget::insertTopLevelItems(index, items); } void TreeWidget::mousePressEvent(QMouseEvent* event) { - if (event->modifiers() == Qt::ControlModifier) { - emit itemControlClicked(itemAt(event->pos())); - } + if (event->modifiers() == Qt::ControlModifier) { + emit itemControlClicked(itemAt(event->pos())); + } - if (event->buttons() == Qt::MiddleButton) { - emit itemMiddleButtonClicked(itemAt(event->pos())); - } + if (event->buttons() == Qt::MiddleButton) { + emit itemMiddleButtonClicked(itemAt(event->pos())); + } - QTreeWidget::mousePressEvent(event); + QTreeWidget::mousePressEvent(event); } void TreeWidget::iterateAllItems(QTreeWidgetItem* parent) { - int count = parent ? parent->childCount() : topLevelItemCount(); + int count = parent ? parent->childCount() : topLevelItemCount(); - for (int i = 0; i < count; i++) { - QTreeWidgetItem* item = parent ? parent->child(i) : topLevelItem(i); + for (int i = 0; i < count; i++) { + QTreeWidgetItem* item = parent ? parent->child(i) : topLevelItem(i); - if (item->childCount() == 0) { - m_allTreeItems.append(item); - } + if (item->childCount() == 0) { + m_allTreeItems.append(item); + } - iterateAllItems(item); - } + iterateAllItems(item); + } } QList TreeWidget::allItems() { - if (m_refreshAllItemsNeeded) { - m_allTreeItems.clear(); - iterateAllItems(0); - m_refreshAllItemsNeeded = false; - } + if (m_refreshAllItemsNeeded) { + m_allTreeItems.clear(); + iterateAllItems(0); + m_refreshAllItemsNeeded = false; + } - return m_allTreeItems; + return m_allTreeItems; } void TreeWidget::filterString(const QString& string) { - QList _allItems = allItems(); - QList parents; - bool stringIsEmpty = string.isEmpty(); + QList _allItems = allItems(); + QList parents; + bool stringIsEmpty = string.isEmpty(); - foreach (QTreeWidgetItem* item, _allItems) { - bool containsString = stringIsEmpty || item->text(0).contains(string, Qt::CaseInsensitive); + foreach (QTreeWidgetItem* item, _allItems) { + bool containsString = stringIsEmpty || item->text(0).contains(string, Qt::CaseInsensitive); - if (containsString) { - item->setHidden(false); + if (containsString) { + item->setHidden(false); - if (item->parent()) { - if (!parents.contains(item->parent())) { - parents << item->parent(); - } - } - } - else { - item->setHidden(true); + if (item->parent()) { + if (!parents.contains(item->parent())) { + parents << item->parent(); + } + } + } + else { + item->setHidden(true); - if (item->parent()) { - item->parent()->setHidden(true); - } - } - } + if (item->parent()) { + item->parent()->setHidden(true); + } + } + } - for (int i = 0; i < parents.size(); ++i) { - QTreeWidgetItem* parentItem = parents.at(i); - parentItem->setHidden(false); + for (int i = 0; i < parents.size(); ++i) { + QTreeWidgetItem* parentItem = parents.at(i); - if (stringIsEmpty) { - parentItem->setExpanded(m_showMode == ItemsExpanded); - } - else { - parentItem->setExpanded(true); - } + parentItem->setHidden(false); - if (parentItem->parent() && !parents.contains(parentItem->parent())) { - parents << parentItem->parent(); - } - } + if (stringIsEmpty) { + parentItem->setExpanded(m_showMode == ItemsExpanded); + } + else { + parentItem->setExpanded(true); + } + + if (parentItem->parent() && !parents.contains(parentItem->parent())) { + parents << parentItem->parent(); + } + } } bool TreeWidget::appendToParentItem(const QString& parentText, QTreeWidgetItem* item) { - QList list = findItems(parentText, Qt::MatchExactly); + QList list = findItems(parentText, Qt::MatchExactly); - if (list.count() == 0) { - return false; - } + if (list.count() == 0) { + return false; + } - QTreeWidgetItem* parentItem = list.at(0); + QTreeWidgetItem* parentItem = list.at(0); - if (!parentItem) { - return false; - } + if (!parentItem) { + return false; + } - m_allTreeItems.append(item); - parentItem->addChild(item); - return true; + m_allTreeItems.append(item); + parentItem->addChild(item); + return true; } bool TreeWidget::appendToParentItem(QTreeWidgetItem* parent, QTreeWidgetItem* item) { - if (!parent || parent->treeWidget() != this) { - return false; - } + if (!parent || parent->treeWidget() != this) { + return false; + } - m_allTreeItems.append(item); - parent->addChild(item); - return true; + m_allTreeItems.append(item); + parent->addChild(item); + return true; } bool TreeWidget::prependToParentItem(const QString& parentText, QTreeWidgetItem* item) { - QList list = findItems(parentText, Qt::MatchExactly); + QList list = findItems(parentText, Qt::MatchExactly); - if (list.count() == 0) { - return false; - } + if (list.count() == 0) { + return false; + } - QTreeWidgetItem* parentItem = list.at(0); + QTreeWidgetItem* parentItem = list.at(0); - if (!parentItem) { - return false; - } + if (!parentItem) { + return false; + } - m_allTreeItems.append(item); - parentItem->insertChild(0, item); - return true; + m_allTreeItems.append(item); + parentItem->insertChild(0, item); + return true; } bool TreeWidget::prependToParentItem(QTreeWidgetItem* parent, QTreeWidgetItem* item) { - if (!parent || parent->treeWidget() != this) { - return false; - } + if (!parent || parent->treeWidget() != this) { + return false; + } - m_allTreeItems.append(item); - parent->insertChild(0, item); - return true; + m_allTreeItems.append(item); + parent->insertChild(0, item); + return true; } void TreeWidget::deleteItem(QTreeWidgetItem* item) { - m_refreshAllItemsNeeded = true; - delete item; + m_refreshAllItemsNeeded = true; + delete item; } void TreeWidget::deleteItems(const QList& items) { - m_refreshAllItemsNeeded = true; - qDeleteAll(items); + m_refreshAllItemsNeeded = true; + qDeleteAll(items); } diff --git a/src/gui/treewidget.h b/src/gui/treewidget.h index 4275c8ae5..2d47300bb 100755 --- a/src/gui/treewidget.h +++ b/src/gui/treewidget.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -21,55 +22,56 @@ #include - class TreeWidget : public QTreeWidget { - Q_OBJECT + Q_OBJECT - public: - explicit TreeWidget(QWidget* parent = 0); + public: + explicit TreeWidget(QWidget* parent = 0); - enum ItemShowMode { ItemsCollapsed = 0, ItemsExpanded = 1 }; + enum ItemShowMode { ItemsCollapsed = 0, ItemsExpanded = 1 }; - ItemShowMode defaultItemShowMode() { - return m_showMode; - } - void setDefaultItemShowMode(ItemShowMode mode) { - m_showMode = mode; - } + ItemShowMode defaultItemShowMode() { + return m_showMode; + } - QList allItems(); + void setDefaultItemShowMode(ItemShowMode mode) { + m_showMode = mode; + } - bool appendToParentItem(const QString& parentText, QTreeWidgetItem* item); - bool appendToParentItem(QTreeWidgetItem* parent, QTreeWidgetItem* item); - bool prependToParentItem(const QString& parentText, QTreeWidgetItem* item); - bool prependToParentItem(QTreeWidgetItem* parent, QTreeWidgetItem* item); + QList allItems(); - void addTopLevelItem(QTreeWidgetItem* item); - void addTopLevelItems(const QList& items); - void insertTopLevelItem(int index, QTreeWidgetItem* item); - void insertTopLevelItems(int index, const QList& items); + bool appendToParentItem(const QString& parentText, QTreeWidgetItem* item); + bool appendToParentItem(QTreeWidgetItem* parent, QTreeWidgetItem* item); + bool prependToParentItem(const QString& parentText, QTreeWidgetItem* item); + bool prependToParentItem(QTreeWidgetItem* parent, QTreeWidgetItem* item); - void deleteItem(QTreeWidgetItem* item); - void deleteItems(const QList& items); + void addTopLevelItem(QTreeWidgetItem* item); + void addTopLevelItems(const QList& items); + void insertTopLevelItem(int index, QTreeWidgetItem* item); + void insertTopLevelItems(int index, const QList& items); - signals: - void itemControlClicked(QTreeWidgetItem* item); - void itemMiddleButtonClicked(QTreeWidgetItem* item); + void deleteItem(QTreeWidgetItem* item); + void deleteItems(const QList& items); - public slots: - void filterString(const QString& string); - void clear(); + signals: + void itemControlClicked(QTreeWidgetItem* item); + void itemMiddleButtonClicked(QTreeWidgetItem* item); - private slots: - void sheduleRefresh(); + public slots: + void filterString(const QString& string); + void clear(); - private: - void mousePressEvent(QMouseEvent* event); - void iterateAllItems(QTreeWidgetItem* parent); + private slots: + void sheduleRefresh(); - bool m_refreshAllItemsNeeded; - QList m_allTreeItems; - ItemShowMode m_showMode; + private: + void mousePressEvent(QMouseEvent* event); + void iterateAllItems(QTreeWidgetItem* parent); + + bool m_refreshAllItemsNeeded; + + QList m_allTreeItems; + ItemShowMode m_showMode; }; #endif // BOOKMARKSTREEWIDGET_H diff --git a/src/gui/webbrowser.cpp b/src/gui/webbrowser.cpp index 5cf770d61..9d5e04902 100755 --- a/src/gui/webbrowser.cpp +++ b/src/gui/webbrowser.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,266 +18,281 @@ #include "gui/webbrowser.h" +#include "gui/discoverfeedsbutton.h" +#include "gui/locationlineedit.h" +#include "gui/messagebox.h" +#include "gui/webviewer.h" #include "miscellaneous/application.h" #include "miscellaneous/databasequeries.h" #include "network-web/networkfactory.h" #include "network-web/webfactory.h" -#include "gui/messagebox.h" -#include "gui/webviewer.h" -#include "gui/discoverfeedsbutton.h" -#include "gui/locationlineedit.h" #include "services/abstract/serviceroot.h" #include #include -#include #include +#include #include - void WebBrowser::createConnections() { - connect(m_webView, &WebViewer::messageStatusChangeRequested, this, &WebBrowser::receiveMessageStatusChangeRequest); - connect(m_txtLocation, &LocationLineEdit::submitted, - this, static_cast(&WebBrowser::loadUrl)); - connect(m_webView, &WebViewer::urlChanged, this, &WebBrowser::updateUrl); - // Change location textbox status according to webpage status. - connect(m_webView, &WebViewer::loadStarted, this, &WebBrowser::onLoadingStarted); - connect(m_webView, &WebViewer::loadProgress, this, &WebBrowser::onLoadingProgress); - connect(m_webView, &WebViewer::loadFinished, this, &WebBrowser::onLoadingFinished); - // Forward title/icon changes. - connect(m_webView, &WebViewer::titleChanged, this, &WebBrowser::onTitleChanged); + connect(m_webView, &WebViewer::messageStatusChangeRequested, this, &WebBrowser::receiveMessageStatusChangeRequest); + connect(m_txtLocation, &LocationLineEdit::submitted, + this, static_cast(&WebBrowser::loadUrl)); + connect(m_webView, &WebViewer::urlChanged, this, &WebBrowser::updateUrl); + + // Change location textbox status according to webpage status. + connect(m_webView, &WebViewer::loadStarted, this, &WebBrowser::onLoadingStarted); + connect(m_webView, &WebViewer::loadProgress, this, &WebBrowser::onLoadingProgress); + connect(m_webView, &WebViewer::loadFinished, this, &WebBrowser::onLoadingFinished); + + // Forward title/icon changes. + connect(m_webView, &WebViewer::titleChanged, this, &WebBrowser::onTitleChanged); #if QT_VERSION >= 0x050700 - connect(m_webView, &WebViewer::iconChanged, this, &WebBrowser::onIconChanged); + connect(m_webView, &WebViewer::iconChanged, this, &WebBrowser::onIconChanged); #endif } void WebBrowser::updateUrl(const QUrl& url) { - QString url_string = url.toString(); - m_txtLocation->setText(url_string); - //setNavigationBarVisible(url_string != INTERNAL_URL_EMPTY && url_string != INTERNAL_URL_NEWSPAPER); + QString url_string = url.toString(); + + m_txtLocation->setText(url_string); + + //setNavigationBarVisible(url_string != INTERNAL_URL_EMPTY && url_string != INTERNAL_URL_NEWSPAPER); } void WebBrowser::loadUrl(const QUrl& url) { - if (url.isValid()) { - m_webView->load(url); - } + if (url.isValid()) { + m_webView->load(url); + } } WebBrowser::WebBrowser(QWidget* parent) : TabContent(parent), - m_layout(new QVBoxLayout(this)), - m_toolBar(new QToolBar(tr("Navigation panel"), this)), - m_webView(new WebViewer(this)), - m_txtLocation(new LocationLineEdit(this)), - m_btnDiscoverFeeds(new DiscoverFeedsButton(this)), - m_actionBack(m_webView->pageAction(QWebEnginePage::Back)), - m_actionForward(m_webView->pageAction(QWebEnginePage::Forward)), - m_actionReload(m_webView->pageAction(QWebEnginePage::Reload)), - m_actionStop(m_webView->pageAction(QWebEnginePage::Stop)) { - // Initialize the components and layout. - initializeLayout(); - setFocusProxy(m_txtLocation); - setTabOrder(m_txtLocation, m_toolBar); - setTabOrder(m_toolBar, m_webView); - createConnections(); - reloadFontSettings(); + m_layout(new QVBoxLayout(this)), + m_toolBar(new QToolBar(tr("Navigation panel"), this)), + m_webView(new WebViewer(this)), + m_txtLocation(new LocationLineEdit(this)), + m_btnDiscoverFeeds(new DiscoverFeedsButton(this)), + m_actionBack(m_webView->pageAction(QWebEnginePage::Back)), + m_actionForward(m_webView->pageAction(QWebEnginePage::Forward)), + m_actionReload(m_webView->pageAction(QWebEnginePage::Reload)), + m_actionStop(m_webView->pageAction(QWebEnginePage::Stop)) { + // Initialize the components and layout. + initializeLayout(); + setFocusProxy(m_txtLocation); + setTabOrder(m_txtLocation, m_toolBar); + setTabOrder(m_toolBar, m_webView); + createConnections(); + reloadFontSettings(); } WebBrowser::~WebBrowser() { - // Delete members. Do not use scoped pointers here. - delete m_layout; + // Delete members. Do not use scoped pointers here. + delete m_layout; } void WebBrowser::reloadFontSettings() { - QFont fon; - fon.fromString(qApp->settings()->value(GROUP(Messages), - SETTING(Messages::PreviewerFontStandard)).toString()); - QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::StandardFont, fon.family()); - QWebEngineSettings::globalSettings()->setFontSize(QWebEngineSettings::DefaultFontSize, fon.pointSize()); + QFont fon; + + fon.fromString(qApp->settings()->value(GROUP(Messages), + SETTING(Messages::PreviewerFontStandard)).toString()); + QWebEngineSettings::globalSettings()->setFontFamily(QWebEngineSettings::StandardFont, fon.family()); + QWebEngineSettings::globalSettings()->setFontSize(QWebEngineSettings::DefaultFontSize, fon.pointSize()); } void WebBrowser::increaseZoom() { - m_webView->increaseWebPageZoom(); + m_webView->increaseWebPageZoom(); } void WebBrowser::decreaseZoom() { - m_webView->decreaseWebPageZoom(); + m_webView->decreaseWebPageZoom(); } void WebBrowser::resetZoom() { - m_webView->resetWebPageZoom(); + m_webView->resetWebPageZoom(); } void WebBrowser::clear() { - m_webView->clear(); - m_messages.clear(); - hide(); + m_webView->clear(); + m_messages.clear(); + hide(); } void WebBrowser::loadUrl(const QString& url) { - return loadUrl(QUrl::fromUserInput(url)); + return loadUrl(QUrl::fromUserInput(url)); } void WebBrowser::loadMessages(const QList& messages, RootItem* root) { - m_messages = messages; - m_root = root; + m_messages = messages; + m_root = root; - if (!m_root.isNull()) { - m_webView->loadMessages(messages); - show(); - } + if (!m_root.isNull()) { + m_webView->loadMessages(messages); + show(); + } } void WebBrowser::loadMessage(const Message& message, RootItem* root) { - loadMessages(QList() << message, root); + loadMessages(QList() << message, root); } void WebBrowser::receiveMessageStatusChangeRequest(int message_id, WebPage::MessageStatusChange change) { - switch (change) { - case WebPage::MarkRead: - markMessageAsRead(message_id, true); - break; + switch (change) { + case WebPage::MarkRead: + markMessageAsRead(message_id, true); + break; - case WebPage::MarkUnread: - markMessageAsRead(message_id, false); - break; + case WebPage::MarkUnread: + markMessageAsRead(message_id, false); + break; - case WebPage::MarkStarred: - switchMessageImportance(message_id, true); - break; + case WebPage::MarkStarred: + switchMessageImportance(message_id, true); + break; - case WebPage::MarkUnstarred: - switchMessageImportance(message_id, false); - break; + case WebPage::MarkUnstarred: + switchMessageImportance(message_id, false); + break; - default: - break; - } + default: + break; + } } void WebBrowser::onTitleChanged(const QString& new_title) { - if (new_title.isEmpty()) { - //: Webbrowser tab title when no title is available. - emit titleChanged(m_index, tr("No title")); - } - else { - emit titleChanged(m_index, new_title); - } + if (new_title.isEmpty()) { + //: Webbrowser tab title when no title is available. + emit titleChanged(m_index, tr("No title")); + } + else { + emit titleChanged(m_index, new_title); + } } #if QT_VERSION >= 0x050700 void WebBrowser::onIconChanged(const QIcon& icon) { - emit iconChanged(m_index, icon); + emit iconChanged(m_index, icon); } + #endif void WebBrowser::initializeLayout() { - m_toolBar->setFloatable(false); - m_toolBar->setMovable(false); - m_toolBar->setAllowedAreas(Qt::TopToolBarArea); - // Modify action texts. - m_actionBack->setText(tr("Back")); - m_actionBack->setToolTip(tr("Go back.")); - m_actionForward->setText(tr("Forward")); - m_actionForward->setToolTip(tr("Go forward.")); - m_actionReload->setText(tr("Reload")); - m_actionReload->setToolTip(tr("Reload current web page.")); - m_actionStop->setText(tr("Stop")); - m_actionStop->setToolTip(tr("Stop web page loading.")); - QWidgetAction* act_discover = new QWidgetAction(this); - act_discover->setDefaultWidget(m_btnDiscoverFeeds); - // Add needed actions into toolbar. - m_toolBar->addAction(m_actionBack); - m_toolBar->addAction(m_actionForward); - m_toolBar->addAction(m_actionReload); - m_toolBar->addAction(m_actionStop); - m_toolBar->addAction(act_discover); - m_toolBar->addWidget(m_txtLocation); - m_loadingProgress = new QProgressBar(this); - m_loadingProgress->setFixedHeight(5); - m_loadingProgress->setMinimum(0); - m_loadingProgress->setTextVisible(false); - m_loadingProgress->setMaximum(100); - m_loadingProgress->setAttribute(Qt::WA_TranslucentBackground); - // Setup layout. - m_layout->addWidget(m_toolBar); - m_layout->addWidget(m_webView); - m_layout->addWidget(m_loadingProgress); - m_layout->setMargin(0); - m_layout->setSpacing(0); + m_toolBar->setFloatable(false); + m_toolBar->setMovable(false); + m_toolBar->setAllowedAreas(Qt::TopToolBarArea); + + // Modify action texts. + m_actionBack->setText(tr("Back")); + m_actionBack->setToolTip(tr("Go back.")); + m_actionForward->setText(tr("Forward")); + m_actionForward->setToolTip(tr("Go forward.")); + m_actionReload->setText(tr("Reload")); + m_actionReload->setToolTip(tr("Reload current web page.")); + m_actionStop->setText(tr("Stop")); + m_actionStop->setToolTip(tr("Stop web page loading.")); + QWidgetAction* act_discover = new QWidgetAction(this); + + act_discover->setDefaultWidget(m_btnDiscoverFeeds); + + // Add needed actions into toolbar. + m_toolBar->addAction(m_actionBack); + m_toolBar->addAction(m_actionForward); + m_toolBar->addAction(m_actionReload); + m_toolBar->addAction(m_actionStop); + m_toolBar->addAction(act_discover); + m_toolBar->addWidget(m_txtLocation); + m_loadingProgress = new QProgressBar(this); + m_loadingProgress->setFixedHeight(5); + m_loadingProgress->setMinimum(0); + m_loadingProgress->setTextVisible(false); + m_loadingProgress->setMaximum(100); + m_loadingProgress->setAttribute(Qt::WA_TranslucentBackground); + + // Setup layout. + m_layout->addWidget(m_toolBar); + m_layout->addWidget(m_webView); + m_layout->addWidget(m_loadingProgress); + m_layout->setMargin(0); + m_layout->setSpacing(0); } void WebBrowser::onLoadingStarted() { - m_btnDiscoverFeeds->clearFeedAddresses(); - m_loadingProgress->show(); + m_btnDiscoverFeeds->clearFeedAddresses(); + m_loadingProgress->show(); } void WebBrowser::onLoadingProgress(int progress) { - m_loadingProgress->setValue(progress); + m_loadingProgress->setValue(progress); } void WebBrowser::onLoadingFinished(bool success) { - if (success) { - // Let's check if there are any feeds defined on the web and eventually - // display "Add feeds" button. - m_webView->page()->toHtml([this](const QString & result) { - this->m_btnDiscoverFeeds->setFeedAddresses(NetworkFactory::extractFeedLinksFromHtmlPage(m_webView->url(), result)); - }); - } - else { - m_btnDiscoverFeeds->clearFeedAddresses(); - } + if (success) { + // Let's check if there are any feeds defined on the web and eventually + // display "Add feeds" button. + m_webView->page()->toHtml([this](const QString& result) { + this->m_btnDiscoverFeeds->setFeedAddresses(NetworkFactory::extractFeedLinksFromHtmlPage(m_webView->url(), result)); + }); + } + else { + m_btnDiscoverFeeds->clearFeedAddresses(); + } - m_loadingProgress->hide(); - m_loadingProgress->setValue(0); + m_loadingProgress->hide(); + m_loadingProgress->setValue(0); } void WebBrowser::markMessageAsRead(int id, bool read) { - if (!m_root.isNull()) { - Message* msg = findMessage(id); + if (!m_root.isNull()) { + Message* msg = findMessage(id); - if (msg != nullptr && m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(), - QList() << *msg, - read ? RootItem::Read : RootItem::Unread)) { - DatabaseQueries::markMessagesReadUnread(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), - QStringList() << QString::number(msg->m_id), - read ? RootItem::Read : RootItem::Unread); - m_root->getParentServiceRoot()->onAfterSetMessagesRead(m_root.data(), - QList() << *msg, - read ? RootItem::Read : RootItem::Unread); - emit markMessageRead(msg->m_id, read ? RootItem::Read : RootItem::Unread); - msg->m_isRead = read ? RootItem::Read : RootItem::Unread; - } - } + if (msg != nullptr && m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(), + QList() << *msg, + read ? RootItem::Read : RootItem::Unread)) { + DatabaseQueries::markMessagesReadUnread(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), + QStringList() << QString::number(msg->m_id), + read ? RootItem::Read : RootItem::Unread); + m_root->getParentServiceRoot()->onAfterSetMessagesRead(m_root.data(), + QList() << *msg, + read ? RootItem::Read : RootItem::Unread); + emit markMessageRead(msg->m_id, read ? RootItem::Read : RootItem::Unread); + + msg->m_isRead = read ? RootItem::Read : RootItem::Unread; + } + } } void WebBrowser::switchMessageImportance(int id, bool checked) { - if (!m_root.isNull()) { - Message* msg = findMessage(id); + if (!m_root.isNull()) { + Message* msg = findMessage(id); - if (msg != nullptr && m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), - QList() << ImportanceChange(*msg, - msg->m_isImportant ? - RootItem::NotImportant : - RootItem::Important))) { - DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), - QStringList() << QString::number(msg->m_id)); - m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(), - QList() << ImportanceChange(*msg, - msg->m_isImportant ? - RootItem::NotImportant : - RootItem::Important)); - emit markMessageImportant(msg->m_id, msg->m_isImportant ? RootItem::NotImportant : RootItem::Important); - msg->m_isImportant = checked; - } - } + if (msg != nullptr && m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), + QList() << + ImportanceChange(*msg, + msg + ->m_isImportant ? + RootItem + ::NotImportant : + RootItem + ::Important))) { + DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), + QStringList() << QString::number(msg->m_id)); + m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(), + QList() << ImportanceChange(*msg, + msg->m_isImportant ? + RootItem::NotImportant : + RootItem::Important)); + emit markMessageImportant(msg->m_id, msg->m_isImportant ? RootItem::NotImportant : RootItem::Important); + + msg->m_isImportant = checked; + } + } } Message* WebBrowser::findMessage(int id) { - for (int i = 0; i < m_messages.size(); i++) { - if (m_messages.at(i).m_id == id) { - return &m_messages[i]; - } - } + for (int i = 0; i < m_messages.size(); i++) { + if (m_messages.at(i).m_id == id) { + return &m_messages[i]; + } + } - return nullptr; + return nullptr; } diff --git a/src/gui/webbrowser.h b/src/gui/webbrowser.h index 7fedbdc20..2615aead3 100755 --- a/src/gui/webbrowser.h +++ b/src/gui/webbrowser.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -27,7 +28,6 @@ #include #include - class QToolButton; class QVBoxLayout; class QHBoxLayout; @@ -40,83 +40,84 @@ class LocationLineEdit; class DiscoverFeedsButton; class WebBrowser : public TabContent { - Q_OBJECT + Q_OBJECT - public: - explicit WebBrowser(QWidget* parent = 0); - virtual ~WebBrowser(); + public: + explicit WebBrowser(QWidget* parent = 0); + virtual ~WebBrowser(); - WebBrowser* webBrowser() const { - return const_cast(this); - } + WebBrowser* webBrowser() const { + return const_cast(this); + } - WebViewer* viewer() const { - return m_webView; - } + WebViewer* viewer() const { + return m_webView; + } - void reloadFontSettings(); + void reloadFontSettings(); - public slots: - void increaseZoom(); - void decreaseZoom(); - void resetZoom(); + public slots: + void increaseZoom(); + void decreaseZoom(); + void resetZoom(); - void clear(); - void loadUrl(const QString& url); - void loadUrl(const QUrl& url); - void loadMessages(const QList& messages, RootItem* root); - void loadMessage(const Message& message, RootItem* root); + void clear(); + void loadUrl(const QString& url); + void loadUrl(const QUrl& url); + void loadMessages(const QList& messages, RootItem* root); + void loadMessage(const Message& message, RootItem* root); - // Switches visibility of navigation bar. - inline void setNavigationBarVisible(bool visible) { - m_toolBar->setVisible(visible); - } + // Switches visibility of navigation bar. + inline void setNavigationBarVisible(bool visible) { + m_toolBar->setVisible(visible); + } - private slots: - void updateUrl(const QUrl& url); + private slots: + void updateUrl(const QUrl& url); - void onLoadingStarted(); - void onLoadingProgress(int progress); - void onLoadingFinished(bool success); + void onLoadingStarted(); + void onLoadingProgress(int progress); + void onLoadingFinished(bool success); - void receiveMessageStatusChangeRequest(int message_id, WebPage::MessageStatusChange change); + void receiveMessageStatusChangeRequest(int message_id, WebPage::MessageStatusChange change); - void onTitleChanged(const QString& new_title); + void onTitleChanged(const QString& new_title); #if QT_VERSION >= 0x050700 - void onIconChanged(const QIcon& icon); + void onIconChanged(const QIcon& icon); #endif - signals: - // Title/icon is changed. - void iconChanged(int index, const QIcon& icon); - void titleChanged(int index, const QString& title); + signals: - void markMessageRead(int id, RootItem::ReadStatus read); - void markMessageImportant(int id, RootItem::Importance important); - void requestMessageListReload(bool mark_current_as_read); + // Title/icon is changed. + void iconChanged(int index, const QIcon& icon); + void titleChanged(int index, const QString& title); - private: - void initializeLayout(); - Message* findMessage(int id); - void markMessageAsRead(int id, bool read); - void switchMessageImportance(int id, bool checked); - void createConnections(); + void markMessageRead(int id, RootItem::ReadStatus read); + void markMessageImportant(int id, RootItem::Importance important); + void requestMessageListReload(bool mark_current_as_read); - QVBoxLayout* m_layout; - QToolBar* m_toolBar; - WebViewer* m_webView; - LocationLineEdit* m_txtLocation; - DiscoverFeedsButton* m_btnDiscoverFeeds; - QProgressBar* m_loadingProgress; + private: + void initializeLayout(); + Message* findMessage(int id); - QAction* m_actionBack; - QAction* m_actionForward; - QAction* m_actionReload; - QAction* m_actionStop; + void markMessageAsRead(int id, bool read); + void switchMessageImportance(int id, bool checked); + void createConnections(); - QList m_messages; - QPointer m_root; + QVBoxLayout* m_layout; + QToolBar* m_toolBar; + WebViewer* m_webView; + LocationLineEdit* m_txtLocation; + DiscoverFeedsButton* m_btnDiscoverFeeds; + QProgressBar* m_loadingProgress; + QAction* m_actionBack; + QAction* m_actionForward; + QAction* m_actionReload; + QAction* m_actionStop; + + QList m_messages; + QPointer m_root; }; #endif // WEBBROWSER_H diff --git a/src/gui/webviewer.cpp b/src/gui/webviewer.cpp index 9167191cd..6b8137886 100755 --- a/src/gui/webviewer.cpp +++ b/src/gui/webviewer.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,160 +18,164 @@ #include "gui/webviewer.h" -#include "miscellaneous/skinfactory.h" -#include "miscellaneous/application.h" #include "definitions/definitions.h" -#include "network-web/webpage.h" #include "gui/dialogs/formmain.h" #include "gui/tabwidget.h" #include "gui/webbrowser.h" -#include "network-web/webfactory.h" +#include "miscellaneous/application.h" +#include "miscellaneous/skinfactory.h" #include "network-web/adblock/adblockicon.h" #include "network-web/adblock/adblockmanager.h" +#include "network-web/webfactory.h" +#include "network-web/webpage.h" #include - WebViewer::WebViewer(QWidget* parent) : QWebEngineView(parent) { - WebPage* page = new WebPage(this); - connect(page, &WebPage::messageStatusChangeRequested, this, &WebViewer::messageStatusChangeRequested); - setPage(page); + WebPage* page = new WebPage(this); + + connect(page, &WebPage::messageStatusChangeRequested, this, &WebViewer::messageStatusChangeRequested); + setPage(page); } bool WebViewer::canIncreaseZoom() { - return zoomFactor() <= MAX_ZOOM_FACTOR - ZOOM_FACTOR_STEP; + return zoomFactor() <= MAX_ZOOM_FACTOR - ZOOM_FACTOR_STEP; } bool WebViewer::canDecreaseZoom() { - return zoomFactor() >= MIN_ZOOM_FACTOR + ZOOM_FACTOR_STEP; + return zoomFactor() >= MIN_ZOOM_FACTOR + ZOOM_FACTOR_STEP; } WebPage* WebViewer::page() const { - return qobject_cast(QWebEngineView::page()); + return qobject_cast(QWebEngineView::page()); } void WebViewer::displayMessage() { - setHtml(m_messageContents, QUrl::fromUserInput(INTERNAL_URL_MESSAGE)); + setHtml(m_messageContents, QUrl::fromUserInput(INTERNAL_URL_MESSAGE)); } bool WebViewer::increaseWebPageZoom() { - if (canIncreaseZoom()) { - setZoomFactor(zoomFactor() + ZOOM_FACTOR_STEP); - return true; - } - else { - return false; - } + if (canIncreaseZoom()) { + setZoomFactor(zoomFactor() + ZOOM_FACTOR_STEP); + return true; + } + else { + return false; + } } bool WebViewer::decreaseWebPageZoom() { - if (canDecreaseZoom()) { - setZoomFactor(zoomFactor() - ZOOM_FACTOR_STEP); - return true; - } - else { - return false; - } + if (canDecreaseZoom()) { + setZoomFactor(zoomFactor() - ZOOM_FACTOR_STEP); + return true; + } + else { + return false; + } } bool WebViewer::resetWebPageZoom() { - const qreal new_factor = 1.0; + const qreal new_factor = 1.0; - if (new_factor != zoomFactor()) { - setZoomFactor(new_factor); - return true; - } - else { - return false; - } + if (new_factor != zoomFactor()) { + setZoomFactor(new_factor); + return true; + } + else { + return false; + } } void WebViewer::loadMessages(const QList& messages) { - Skin skin = qApp->skins()->currentSkin(); - QString messages_layout; - QString single_message_layout = skin.m_layoutMarkup; + Skin skin = qApp->skins()->currentSkin(); + QString messages_layout; + QString single_message_layout = skin.m_layoutMarkup; - foreach (const Message& message, messages) { - QString enclosures; - QString enclosure_images; + foreach (const Message& message, messages) { + QString enclosures; + QString enclosure_images; - foreach (const Enclosure& enclosure, message.m_enclosures) { - enclosures += skin.m_enclosureMarkup.arg(enclosure.m_url, tr("Attachment"), enclosure.m_mimeType); + foreach (const Enclosure& enclosure, message.m_enclosures) { + enclosures += skin.m_enclosureMarkup.arg(enclosure.m_url, tr("Attachment"), enclosure.m_mimeType); - if (enclosure.m_mimeType.startsWith(QSL("image/"))) { - // Add thumbnail image. - enclosure_images += skin.m_enclosureImageMarkup.arg( - enclosure.m_url, - enclosure.m_mimeType, - qApp->settings()->value(GROUP(Messages), SETTING(Messages::MessageHeadImageHeight)).toString()); - } - } + if (enclosure.m_mimeType.startsWith(QSL("image/"))) { + // Add thumbnail image. + enclosure_images += skin.m_enclosureImageMarkup.arg( + enclosure.m_url, + enclosure.m_mimeType, + qApp->settings()->value(GROUP(Messages), SETTING(Messages::MessageHeadImageHeight)).toString()); + } + } - messages_layout.append(single_message_layout - .arg(message.m_title, - tr("Written by ") + (message.m_author.isEmpty() ? - tr("unknown author") : - message.m_author), - message.m_url, - message.m_contents, - message.m_created.toString(Qt::DefaultLocaleShortDate), - enclosures, - message.m_isRead ? "mark-unread" : "mark-read", - message.m_isImportant ? "mark-unstarred" : "mark-starred", - QString::number(message.m_id)) - .arg(enclosure_images)); - } + messages_layout.append(single_message_layout + .arg(message.m_title, + tr("Written by ") + (message.m_author.isEmpty() ? + tr("unknown author") : + message.m_author), + message.m_url, + message.m_contents, + message.m_created.toString(Qt::DefaultLocaleShortDate), + enclosures, + message.m_isRead ? "mark-unread" : "mark-read", + message.m_isImportant ? "mark-unstarred" : "mark-starred", + QString::number(message.m_id)) + .arg(enclosure_images)); + } - m_messageContents = skin.m_layoutMarkupWrapper.arg(messages.size() == 1 ? messages.at(0).m_title : tr("Newspaper view"), - messages_layout); - bool previously_enabled = isEnabled(); - setEnabled(false); - displayMessage(); - setEnabled(previously_enabled); + m_messageContents = skin.m_layoutMarkupWrapper.arg(messages.size() == 1 ? messages.at(0).m_title : tr("Newspaper view"), + messages_layout); + bool previously_enabled = isEnabled(); + + setEnabled(false); + displayMessage(); + setEnabled(previously_enabled); } void WebViewer::loadMessage(const Message& message) { - loadMessages(QList() << message); + loadMessages(QList() << message); } void WebViewer::clear() { - bool previously_enabled = isEnabled(); - setEnabled(false); - setHtml("", QUrl(INTERNAL_URL_BLANK)); - setEnabled(previously_enabled); + bool previously_enabled = isEnabled(); + + setEnabled(false); + setHtml("", QUrl(INTERNAL_URL_BLANK)); + setEnabled(previously_enabled); } void WebViewer::contextMenuEvent(QContextMenuEvent* event) { - event->accept(); - QMenu* menu = page()->createStandardContextMenu(); - menu->addAction(AdBlockManager::instance()->adBlockIcon()); - menu->addAction(qApp->web()->engineSettingsAction()); - const QPoint pos = event->globalPos(); - QPoint p(pos.x(), pos.y() + 1); - menu->popup(p); + event->accept(); + QMenu* menu = page()->createStandardContextMenu(); + + menu->addAction(AdBlockManager::instance()->adBlockIcon()); + menu->addAction(qApp->web()->engineSettingsAction()); + const QPoint pos = event->globalPos(); + QPoint p(pos.x(), pos.y() + 1); + + menu->popup(p); } QWebEngineView* WebViewer::createWindow(QWebEnginePage::WebWindowType type) { - Q_UNUSED(type) - int index = qApp->mainForm()->tabWidget()->addBrowser(false, false); + Q_UNUSED(type) + int index = qApp->mainForm()->tabWidget()->addBrowser(false, false); - if (index >= 0) { - return qApp->mainForm()->tabWidget()->widget(index)->webBrowser()->viewer(); - } - else { - return nullptr; - } + if (index >= 0) { + return qApp->mainForm()->tabWidget()->widget(index)->webBrowser()->viewer(); + } + else { + return nullptr; + } } void WebViewer::wheelEvent(QWheelEvent* event) { - QWebEngineView::wheelEvent(event); + QWebEngineView::wheelEvent(event); - if ((event->modifiers() & Qt::ControlModifier) > 0) { - if (event->delta() > 0) { - increaseWebPageZoom(); - } - else if (event->delta() < 0) { - decreaseWebPageZoom(); - } - } + if ((event->modifiers() & Qt::ControlModifier) > 0) { + if (event->delta() > 0) { + increaseWebPageZoom(); + } + else if (event->delta() < 0) { + decreaseWebPageZoom(); + } + } } diff --git a/src/gui/webviewer.h b/src/gui/webviewer.h index 2afc2a8fc..8db30f7d1 100755 --- a/src/gui/webviewer.h +++ b/src/gui/webviewer.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,43 +24,44 @@ #include "core/message.h" #include "network-web/webpage.h" - class WebViewer : public QWebEngineView { - Q_OBJECT + Q_OBJECT - public: - explicit WebViewer(QWidget* parent = 0); + public: + explicit WebViewer(QWidget* parent = 0); - bool canIncreaseZoom(); - bool canDecreaseZoom(); + bool canIncreaseZoom(); + bool canDecreaseZoom(); - inline QString messageContents() { - return m_messageContents; - } + inline QString messageContents() { + return m_messageContents; + } - WebPage* page() const; + WebPage* page() const; - public slots: - // Page zoom modifiers. - bool increaseWebPageZoom(); - bool decreaseWebPageZoom(); - bool resetWebPageZoom(); + public slots: - void displayMessage(); - void loadMessages(const QList& messages); - void loadMessage(const Message& message); - void clear(); + // Page zoom modifiers. + bool increaseWebPageZoom(); + bool decreaseWebPageZoom(); + bool resetWebPageZoom(); - protected: - void contextMenuEvent(QContextMenuEvent* event); - QWebEngineView* createWindow(QWebEnginePage::WebWindowType type); - void wheelEvent(QWheelEvent* event); + void displayMessage(); + void loadMessages(const QList& messages); + void loadMessage(const Message& message); + void clear(); - signals: - void messageStatusChangeRequested(int message_id, WebPage::MessageStatusChange change); + protected: + void contextMenuEvent(QContextMenuEvent* event); + QWebEngineView* createWindow(QWebEnginePage::WebWindowType type); - private: - QString m_messageContents; + void wheelEvent(QWheelEvent* event); + + signals: + void messageStatusChangeRequested(int message_id, WebPage::MessageStatusChange change); + + private: + QString m_messageContents; }; #endif // WEBVIEWER_H diff --git a/src/gui/widgetwithstatus.cpp b/src/gui/widgetwithstatus.cpp index 7a6e1888b..701e1c377 100755 --- a/src/gui/widgetwithstatus.cpp +++ b/src/gui/widgetwithstatus.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,54 +23,53 @@ #include - WidgetWithStatus::WidgetWithStatus(QWidget* parent) - : QWidget(parent), m_wdgInput(nullptr) { - m_layout = new QHBoxLayout(this); - m_btnStatus = new PlainToolButton(this); - m_btnStatus->setFocusPolicy(Qt::NoFocus); - m_iconProgress = qApp->icons()->fromTheme(QSL("view-refresh")); - m_iconInformation = qApp->icons()->fromTheme(QSL("dialog-information")); - m_iconWarning = qApp->icons()->fromTheme(QSL("dialog-warning")); - m_iconError = qApp->icons()->fromTheme(QSL("dialog-error")); - m_iconOk = qApp->icons()->fromTheme(QSL("dialog-yes")); - // Set layout properties. - m_layout->setMargin(0); - setLayout(m_layout); - setStatus(Information, QString()); + : QWidget(parent), m_wdgInput(nullptr) { + m_layout = new QHBoxLayout(this); + m_btnStatus = new PlainToolButton(this); + m_btnStatus->setFocusPolicy(Qt::NoFocus); + m_iconProgress = qApp->icons()->fromTheme(QSL("view-refresh")); + m_iconInformation = qApp->icons()->fromTheme(QSL("dialog-information")); + m_iconWarning = qApp->icons()->fromTheme(QSL("dialog-warning")); + m_iconError = qApp->icons()->fromTheme(QSL("dialog-error")); + m_iconOk = qApp->icons()->fromTheme(QSL("dialog-yes")); + + // Set layout properties. + m_layout->setMargin(0); + setLayout(m_layout); + setStatus(Information, QString()); } -WidgetWithStatus::~WidgetWithStatus() { -} +WidgetWithStatus::~WidgetWithStatus() {} void WidgetWithStatus::setStatus(WidgetWithStatus::StatusType status, const QString& tooltip_text) { - m_status = status; + m_status = status; - switch (status) { - case Information: - m_btnStatus->setIcon(m_iconInformation); - break; + switch (status) { + case Information: + m_btnStatus->setIcon(m_iconInformation); + break; - case Progress: - m_btnStatus->setIcon(m_iconProgress); - break; + case Progress: + m_btnStatus->setIcon(m_iconProgress); + break; - case Warning: - m_btnStatus->setIcon(m_iconWarning); - break; + case Warning: + m_btnStatus->setIcon(m_iconWarning); + break; - case Error: - m_btnStatus->setIcon(m_iconError); - break; + case Error: + m_btnStatus->setIcon(m_iconError); + break; - case Ok: - m_btnStatus->setIcon(m_iconOk); - break; + case Ok: + m_btnStatus->setIcon(m_iconOk); + break; - default: - break; - } + default: + break; + } - // Setup the tooltip text. - m_btnStatus->setToolTip(tooltip_text); + // Setup the tooltip text. + m_btnStatus->setToolTip(tooltip_text); } diff --git a/src/gui/widgetwithstatus.h b/src/gui/widgetwithstatus.h index ff3c7dbcf..afa8947af 100755 --- a/src/gui/widgetwithstatus.h +++ b/src/gui/widgetwithstatus.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,48 +19,45 @@ #ifndef WIDGETWITHSTATUS_H #define WIDGETWITHSTATUS_H -#include #include - +#include class PlainToolButton; class QHBoxLayout; class WidgetWithStatus : public QWidget { - Q_OBJECT + Q_OBJECT - public: - enum StatusType { - Information, - Warning, - Error, - Ok, - Progress - }; + public: + enum StatusType { + Information, + Warning, + Error, + Ok, + Progress + }; - // Constructors and destructors. - explicit WidgetWithStatus(QWidget* parent); - virtual ~WidgetWithStatus(); + // Constructors and destructors. + explicit WidgetWithStatus(QWidget* parent); + virtual ~WidgetWithStatus(); - // Sets custom status for this control. - void setStatus(StatusType status, const QString& tooltip_text); + // Sets custom status for this control. + void setStatus(StatusType status, const QString& tooltip_text); - inline StatusType status() const { - return m_status; - } + inline StatusType status() const { + return m_status; + } - protected: - StatusType m_status; - QWidget* m_wdgInput; - PlainToolButton* m_btnStatus; - QHBoxLayout* m_layout; - - QIcon m_iconProgress; - QIcon m_iconInformation; - QIcon m_iconWarning; - QIcon m_iconError; - QIcon m_iconOk; + protected: + StatusType m_status; + QWidget* m_wdgInput; + PlainToolButton* m_btnStatus; + QHBoxLayout* m_layout; + QIcon m_iconProgress; + QIcon m_iconInformation; + QIcon m_iconWarning; + QIcon m_iconError; + QIcon m_iconOk; }; - #endif // WIDGETWITHSTATUS_H diff --git a/src/main.cpp b/src/main.cpp index bc2c6d2c4..839aa0b68 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -16,18 +17,18 @@ // along with RSS Guard. If not, see . #include "definitions/definitions.h" -#include "miscellaneous/application.h" -#include "miscellaneous/databasefactory.h" -#include "miscellaneous/debugging.h" -#include "miscellaneous/iconfactory.h" -#include "miscellaneous/feedreader.h" #include "dynamic-shortcuts/dynamicshortcuts.h" +#include "gui/dialogs/formabout.h" #include "gui/dialogs/formmain.h" +#include "gui/dialogs/formupdate.h" #include "gui/feedmessageviewer.h" #include "gui/feedsview.h" #include "gui/messagebox.h" -#include "gui/dialogs/formupdate.h" -#include "gui/dialogs/formabout.h" +#include "miscellaneous/application.h" +#include "miscellaneous/databasefactory.h" +#include "miscellaneous/debugging.h" +#include "miscellaneous/feedreader.h" +#include "miscellaneous/iconfactory.h" #include "network-web/silentnetworkaccessmanager.h" #include "network-web/webfactory.h" @@ -36,123 +37,137 @@ #include #endif -#include -#include #include +#include #include +#include extern void disableWindowTabbing(); int main(int argc, char* argv[]) { - for (int i = 0; i < argc; i++) { - const QString str = QString::fromLocal8Bit(argv[i]); + for (int i = 0; i < argc; i++) { + const QString str = QString::fromLocal8Bit(argv[i]); - if (str == "-h") { - qDebug("Usage: rssguard [OPTIONS]\n\n" - "Option\t\tMeaning\n" - "-h\t\tDisplays this help."); - return EXIT_SUCCESS; - } - } + if (str == "-h") { + qDebug("Usage: rssguard [OPTIONS]\n\n" + "Option\t\tMeaning\n" + "-h\t\tDisplays this help."); + return EXIT_SUCCESS; + } + } - //: Abbreviation of language, e.g. en. - //: Use ISO 639-1 code here combined with ISO 3166-1 (alpha-2) code. - //: Examples: "cs", "en", "it", "cs_CZ", "en_GB", "en_US". - QObject::tr("LANG_ABBREV"); - //: Name of translator - optional. - QObject::tr("LANG_AUTHOR"); - // Ensure that ini format is used as application settings storage on Mac OS. - QSettings::setDefaultFormat(QSettings::IniFormat); - // Setup debug output system. - qInstallMessageHandler(Debugging::debugHandler); - // Instantiate base application object. - Application application(APP_LOW_NAME, argc, argv); - qDebug("Instantiated Application class."); + //: Abbreviation of language, e.g. en. + //: Use ISO 639-1 code here combined with ISO 3166-1 (alpha-2) code. + //: Examples: "cs", "en", "it", "cs_CZ", "en_GB", "en_US". + QObject::tr("LANG_ABBREV"); - // Check if another instance is running. - if (application.sendMessage((QStringList() << APP_IS_RUNNING << application.arguments().mid(1)).join(ARGUMENTS_LIST_SEPARATOR))) { - qWarning("Another instance of the application is already running. Notifying it."); - return EXIT_FAILURE; - } + //: Name of translator - optional. + QObject::tr("LANG_AUTHOR"); - // Load localization and setup locale before any widget is constructed. - qApp->localization()->loadActiveLanguage(); - application.setFeedReader(new FeedReader(&application)); - QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + // Ensure that ini format is used as application settings storage on Mac OS. + QSettings::setDefaultFormat(QSettings::IniFormat); + + // Setup debug output system. + qInstallMessageHandler(Debugging::debugHandler); + + // Instantiate base application object. + Application application(APP_LOW_NAME, argc, argv); + + qDebug("Instantiated Application class."); + + // Check if another instance is running. + if (application.sendMessage((QStringList() << APP_IS_RUNNING << application.arguments().mid(1)).join(ARGUMENTS_LIST_SEPARATOR))) { + qWarning("Another instance of the application is already running. Notifying it."); + return EXIT_FAILURE; + } + + // Load localization and setup locale before any widget is constructed. + qApp->localization()->loadActiveLanguage(); + application.setFeedReader(new FeedReader(&application)); + QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #ifdef Q_OS_MAC - QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); - disableWindowTabbing(); + QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); + disableWindowTabbing(); #endif - // Register needed metatypes. - qRegisterMetaType>("QList"); - qRegisterMetaType>("QList"); - // Add an extra path for non-system icon themes and set current icon theme - // and skin. - qApp->icons()->setupSearchPaths(); - qApp->icons()->loadCurrentIconTheme(); - qApp->skins()->loadCurrentSkin(); - // These settings needs to be set before any QSettings object. - Application::setApplicationName(APP_NAME); - Application::setApplicationVersion(APP_VERSION); - Application::setOrganizationDomain(APP_URL); - Application::setWindowIcon(QIcon(APP_ICON_PATH)); - // Load activated accounts. - qApp->feedReader()->feedsModel()->loadActivatedServiceAccounts(); - // Setup single-instance behavior. - QObject::connect(&application, &Application::messageReceived, &application, &Application::processExecutionMessage); - qDebug().nospace() << "Creating main application form in thread: \'" << QThread::currentThreadId() << "\'."; - // Instantiate main application window. - FormMain main_window; - // Set correct information for main window. - main_window.setWindowTitle(APP_LONG_NAME); - // Now is a good time to initialize dynamic keyboard shortcuts. - DynamicShortcuts::load(qApp->userActions()); - // Display main window. - if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool() && SystemTrayIcon::isSystemTrayActivated()) { - qDebug("Hiding the main window when the application is starting."); - main_window.switchVisibility(true); - } - else { - qDebug("Showing the main window when the application is starting."); - main_window.show(); - } + // Register needed metatypes. + qRegisterMetaType>("QList"); + qRegisterMetaType>("QList"); - // Display tray icon if it is enabled and available. - if (SystemTrayIcon::isSystemTrayActivated()) { - qApp->showTrayIcon(); - } + // Add an extra path for non-system icon themes and set current icon theme + // and skin. + qApp->icons()->setupSearchPaths(); + qApp->icons()->loadCurrentIconTheme(); + qApp->skins()->loadCurrentSkin(); - if (qApp->isFirstRun() || qApp->isFirstRun(APP_VERSION)) { - qApp->showGuiMessage(QSL(APP_NAME), QObject::tr("Welcome to %1.\n\nPlease, check NEW stuff included in this\n" - "version by clicking this popup notification.").arg(APP_LONG_NAME), - QSystemTrayIcon::NoIcon, 0, false, [] { - FormAbout(qApp->mainForm()).exec(); - }); - } - else { - qApp->showGuiMessage(QSL(APP_NAME), QObject::tr("Welcome to %1.").arg(APP_NAME), QSystemTrayIcon::NoIcon); - } + // These settings needs to be set before any QSettings object. + Application::setApplicationName(APP_NAME); + Application::setApplicationVersion(APP_VERSION); + Application::setOrganizationDomain(APP_URL); + Application::setWindowIcon(QIcon(APP_ICON_PATH)); - if (qApp->settings()->value(GROUP(General), SETTING(General::UpdateOnStartup)).toBool()) { - QObject::connect(qApp->system(), &SystemFactory::updatesChecked, [](QPair, QNetworkReply::NetworkError> updates) { - QObject::disconnect(qApp->system(), &SystemFactory::updatesChecked, nullptr, nullptr); + // Load activated accounts. + qApp->feedReader()->feedsModel()->loadActivatedServiceAccounts(); - if (!updates.first.isEmpty() && updates.second == QNetworkReply::NoError && - SystemFactory::isVersionNewer(updates.first.at(0).m_availableVersion, APP_VERSION)) { - qApp->showGuiMessage(QObject::tr("New version available"), - QObject::tr("Click the bubble for more information."), - QSystemTrayIcon::Information, qApp->mainForm(), false, - [] { - FormUpdate(qApp->mainForm()).exec(); - }); - } - }); - qApp->system()->checkForUpdates(); - } + // Setup single-instance behavior. + QObject::connect(&application, &Application::messageReceived, &application, &Application::processExecutionMessage); + qDebug().nospace() << "Creating main application form in thread: \'" << QThread::currentThreadId() << "\'."; - qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsView()->loadAllExpandStates(); - // Enter global event loop. - return Application::exec(); + // Instantiate main application window. + FormMain main_window; + + // Set correct information for main window. + main_window.setWindowTitle(APP_LONG_NAME); + + // Now is a good time to initialize dynamic keyboard shortcuts. + DynamicShortcuts::load(qApp->userActions()); + + // Display main window. + if (qApp->settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool() && SystemTrayIcon::isSystemTrayActivated()) { + qDebug("Hiding the main window when the application is starting."); + main_window.switchVisibility(true); + } + else { + qDebug("Showing the main window when the application is starting."); + main_window.show(); + } + + // Display tray icon if it is enabled and available. + if (SystemTrayIcon::isSystemTrayActivated()) { + qApp->showTrayIcon(); + } + + if (qApp->isFirstRun() || qApp->isFirstRun(APP_VERSION)) { + qApp->showGuiMessage(QSL(APP_NAME), QObject::tr("Welcome to %1.\n\nPlease, check NEW stuff included in this\n" + "version by clicking this popup notification.").arg(APP_LONG_NAME), + QSystemTrayIcon::NoIcon, 0, false, [] { + FormAbout(qApp->mainForm()).exec(); + }); + } + else { + qApp->showGuiMessage(QSL(APP_NAME), QObject::tr("Welcome to %1.").arg(APP_NAME), QSystemTrayIcon::NoIcon); + } + + if (qApp->settings()->value(GROUP(General), SETTING(General::UpdateOnStartup)).toBool()) { + QObject::connect(qApp->system(), &SystemFactory::updatesChecked, [](QPair, QNetworkReply::NetworkError> updates) { + QObject::disconnect(qApp->system(), &SystemFactory::updatesChecked, nullptr, nullptr); + + if (!updates.first.isEmpty() && updates.second == QNetworkReply::NoError && + SystemFactory::isVersionNewer(updates.first.at(0).m_availableVersion, APP_VERSION)) { + qApp->showGuiMessage(QObject::tr("New version available"), + QObject::tr("Click the bubble for more information."), + QSystemTrayIcon::Information, qApp->mainForm(), false, + [] { + FormUpdate(qApp->mainForm()).exec(); + }); + } + }); + qApp->system()->checkForUpdates(); + } + + qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsView()->loadAllExpandStates(); + + // Enter global event loop. + return Application::exec(); } diff --git a/src/miscellaneous/application.cpp b/src/miscellaneous/application.cpp index 954e90f71..188f402eb 100755 --- a/src/miscellaneous/application.cpp +++ b/src/miscellaneous/application.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,343 +18,346 @@ #include "miscellaneous/application.h" +#include "exceptions/applicationexception.h" +#include "gui/dialogs/formmain.h" +#include "gui/feedmessageviewer.h" +#include "gui/feedsview.h" +#include "gui/messagebox.h" +#include "gui/statusbar.h" +#include "miscellaneous/feedreader.h" #include "miscellaneous/iconfactory.h" #include "miscellaneous/iofactory.h" #include "miscellaneous/mutex.h" -#include "miscellaneous/feedreader.h" -#include "gui/feedsview.h" -#include "gui/feedmessageviewer.h" -#include "gui/messagebox.h" -#include "gui/statusbar.h" -#include "gui/dialogs/formmain.h" -#include "exceptions/applicationexception.h" -#include "services/abstract/serviceroot.h" -#include "services/standard/standardserviceroot.h" -#include "services/standard/standardserviceentrypoint.h" -#include "services/tt-rss/ttrssserviceentrypoint.h" -#include "services/owncloud/owncloudserviceentrypoint.h" #include "network-web/webfactory.h" +#include "services/abstract/serviceroot.h" +#include "services/owncloud/owncloudserviceentrypoint.h" +#include "services/standard/standardserviceentrypoint.h" +#include "services/standard/standardserviceroot.h" +#include "services/tt-rss/ttrssserviceentrypoint.h" -#include #include +#include #if defined(USE_WEBENGINE) -#include "network-web/urlinterceptor.h" -#include "network-web/networkurlinterceptor.h" #include "network-web/adblock/adblockicon.h" #include "network-web/adblock/adblockmanager.h" +#include "network-web/networkurlinterceptor.h" #include "network-web/rssguardschemehandler.h" +#include "network-web/urlinterceptor.h" -#include #include +#include #include #include #endif Application::Application(const QString& id, int& argc, char** argv) - : QtSingleApplication(id, argc, argv), + : QtSingleApplication(id, argc, argv), #if defined(USE_WEBENGINE) - m_urlInterceptor(new NetworkUrlInterceptor(this)), + m_urlInterceptor(new NetworkUrlInterceptor(this)), #endif - m_feedReader(nullptr), - m_updateFeedsLock(new Mutex()), m_userActions(QList()), m_mainForm(nullptr), - m_trayIcon(nullptr), m_settings(Settings::setupSettings(this)), m_webFactory(new WebFactory(this)), - m_system(new SystemFactory(this)), m_skins(new SkinFactory(this)), - m_localization(new Localization(this)), m_icons(new IconFactory(this)), - m_database(new DatabaseFactory(this)), m_downloadManager(nullptr), m_shouldRestart(false) { - connect(this, &Application::aboutToQuit, this, &Application::onAboutToQuit); - connect(this, &Application::commitDataRequest, this, &Application::onCommitData); - connect(this, &Application::saveStateRequest, this, &Application::onSaveState); + m_feedReader(nullptr), + m_updateFeedsLock(new Mutex()), m_userActions(QList()), m_mainForm(nullptr), + m_trayIcon(nullptr), m_settings(Settings::setupSettings(this)), m_webFactory(new WebFactory(this)), + m_system(new SystemFactory(this)), m_skins(new SkinFactory(this)), + m_localization(new Localization(this)), m_icons(new IconFactory(this)), + m_database(new DatabaseFactory(this)), m_downloadManager(nullptr), m_shouldRestart(false) { + connect(this, &Application::aboutToQuit, this, &Application::onAboutToQuit); + connect(this, &Application::commitDataRequest, this, &Application::onCommitData); + connect(this, &Application::saveStateRequest, this, &Application::onSaveState); #if defined(USE_WEBENGINE) - connect(QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested, this, &Application::downloadRequested); + connect(QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested, this, &Application::downloadRequested); - QWebEngineProfile::defaultProfile()->setRequestInterceptor(m_urlInterceptor); - m_urlInterceptor->loadSettings(); + QWebEngineProfile::defaultProfile()->setRequestInterceptor(m_urlInterceptor); + m_urlInterceptor->loadSettings(); QWebEngineProfile::defaultProfile()->installUrlSchemeHandler( - QByteArray(APP_LOW_NAME), - new RssGuardSchemeHandler(QWebEngineProfile::defaultProfile())); + QByteArray(APP_LOW_NAME), + new RssGuardSchemeHandler(QWebEngineProfile::defaultProfile())); #endif } Application::~Application() { - qDebug("Destroying Application instance."); + qDebug("Destroying Application instance."); } FeedReader* Application::feedReader() { - return m_feedReader; + return m_feedReader; } QList Application::userActions() { - if (m_mainForm != nullptr && m_userActions.isEmpty()) { - m_userActions = m_mainForm->allActions(); + if (m_mainForm != nullptr && m_userActions.isEmpty()) { + m_userActions = m_mainForm->allActions(); #if defined(USE_WEBENGINE) - m_userActions.append(AdBlockManager::instance()->adBlockIcon()); + m_userActions.append(AdBlockManager::instance()->adBlockIcon()); #endif - } + } - return m_userActions; + return m_userActions; } bool Application::isFirstRun() { - return settings()->value(GROUP(General), SETTING(General::FirstRun)).toBool(); + return settings()->value(GROUP(General), SETTING(General::FirstRun)).toBool(); } bool Application::isFirstRun(const QString& version) { - if (version == APP_VERSION) { - // Check this only if checked version is equal to actual version. - return settings()->value(GROUP(General), QString(General::FirstRun) + QL1C('_') + version, true).toBool(); - } - else { - return false; - } + if (version == APP_VERSION) { + // Check this only if checked version is equal to actual version. + return settings()->value(GROUP(General), QString(General::FirstRun) + QL1C('_') + version, true).toBool(); + } + else { + return false; + } } WebFactory* Application::web() { - return m_webFactory; + return m_webFactory; } SystemFactory* Application::system() { - return m_system; + return m_system; } SkinFactory* Application::skins() { - return m_skins; + return m_skins; } Localization* Application::localization() { - return m_localization; + return m_localization; } DatabaseFactory* Application::database() { - return m_database; + return m_database; } void Application::eliminateFirstRun() { - settings()->setValue(GROUP(General), General::FirstRun, false); + settings()->setValue(GROUP(General), General::FirstRun, false); } void Application::eliminateFirstRun(const QString& version) { - settings()->setValue(GROUP(General), QString(General::FirstRun) + QL1C('_') + version, false); + settings()->setValue(GROUP(General), QString(General::FirstRun) + QL1C('_') + version, false); } void Application::setFeedReader(FeedReader* feed_reader) { - m_feedReader = feed_reader; - connect(m_feedReader, &FeedReader::feedUpdatesStarted, this, &Application::onFeedUpdatesStarted); - connect(m_feedReader, &FeedReader::feedUpdatesProgress, this, &Application::onFeedUpdatesProgress); - connect(m_feedReader, &FeedReader::feedUpdatesFinished, this, &Application::onFeedUpdatesFinished); + m_feedReader = feed_reader; + connect(m_feedReader, &FeedReader::feedUpdatesStarted, this, &Application::onFeedUpdatesStarted); + connect(m_feedReader, &FeedReader::feedUpdatesProgress, this, &Application::onFeedUpdatesProgress); + connect(m_feedReader, &FeedReader::feedUpdatesFinished, this, &Application::onFeedUpdatesFinished); } IconFactory* Application::icons() { - return m_icons; + return m_icons; } DownloadManager* Application::downloadManager() { - if (m_downloadManager == nullptr) { - m_downloadManager = new DownloadManager(); - connect(m_downloadManager, &DownloadManager::downloadFinished, mainForm()->statusBar(), &StatusBar::clearProgressDownload); - connect(m_downloadManager, &DownloadManager::downloadProgressed, mainForm()->statusBar(), &StatusBar::showProgressDownload); - } + if (m_downloadManager == nullptr) { + m_downloadManager = new DownloadManager(); + connect(m_downloadManager, &DownloadManager::downloadFinished, mainForm()->statusBar(), &StatusBar::clearProgressDownload); + connect(m_downloadManager, &DownloadManager::downloadProgressed, mainForm()->statusBar(), &StatusBar::showProgressDownload); + } - return m_downloadManager; + return m_downloadManager; } Settings* Application::settings() { - return m_settings; + return m_settings; } Mutex* Application::feedUpdateLock() { - return m_updateFeedsLock.data(); + return m_updateFeedsLock.data(); } FormMain* Application::mainForm() { - return m_mainForm; + return m_mainForm; } QWidget* Application::mainFormWidget() { - return m_mainForm; + return m_mainForm; } void Application::setMainForm(FormMain* main_form) { - m_mainForm = main_form; + m_mainForm = main_form; } QString Application::configFolder() { - return IOFactory::getSystemFolder(QStandardPaths::GenericConfigLocation); + return IOFactory::getSystemFolder(QStandardPaths::GenericConfigLocation); } QString Application::userDataAppFolder() { - // In "app" folder, we would like to separate all user data into own subfolder, - // therefore stick to "data" folder in this mode. - return applicationDirPath() + QDir::separator() + QSL("data"); + // In "app" folder, we would like to separate all user data into own subfolder, + // therefore stick to "data" folder in this mode. + return applicationDirPath() + QDir::separator() + QSL("data"); } QString Application::userDataFolder() { - if (settings()->type() == SettingsProperties::Portable) { + if (settings()->type() == SettingsProperties::Portable) { return userDataAppFolder(); - } - else { + } + else { return userDataHomeFolder(); - } + } } QString Application::userDataHomeFolder() { - // Fallback folder. + // Fallback folder. const QString home_folder = homeFolder() + QDir::separator() + QSL(APP_LOW_H_NAME) + QDir::separator() + QSL("data"); - if (QDir().exists(home_folder)) { - return home_folder; - } - else { + if (QDir().exists(home_folder)) { + return home_folder; + } + else { return configFolder() + QDir::separator() + QSL(APP_NAME); - } + } } QString Application::tempFolder() { - return IOFactory::getSystemFolder(QStandardPaths::TempLocation); + return IOFactory::getSystemFolder(QStandardPaths::TempLocation); } QString Application::documentsFolder() { - return IOFactory::getSystemFolder(QStandardPaths::DocumentsLocation); + return IOFactory::getSystemFolder(QStandardPaths::DocumentsLocation); } QString Application::homeFolder() { - return IOFactory::getSystemFolder(QStandardPaths::HomeLocation); + return IOFactory::getSystemFolder(QStandardPaths::HomeLocation); } void Application::backupDatabaseSettings(bool backup_database, bool backup_settings, const QString& target_path, const QString& backup_name) { - if (!QFileInfo(target_path).isWritable()) { - throw ApplicationException(tr("Output directory is not writable.")); - } + if (!QFileInfo(target_path).isWritable()) { + throw ApplicationException(tr("Output directory is not writable.")); + } - if (backup_settings) { - settings()->sync(); + if (backup_settings) { + settings()->sync(); - if (!IOFactory::copyFile(settings()->fileName(), target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_SETTINGS)) { - throw ApplicationException(tr("Settings file not copied to output directory successfully.")); - } - } + if (!IOFactory::copyFile(settings()->fileName(), target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_SETTINGS)) { + throw ApplicationException(tr("Settings file not copied to output directory successfully.")); + } + } - if (backup_database && - (database()->activeDatabaseDriver() == DatabaseFactory::SQLITE || - database()->activeDatabaseDriver() == DatabaseFactory::SQLITE_MEMORY)) { - // We need to save the database first. - database()->saveDatabase(); + if (backup_database && + (database()->activeDatabaseDriver() == DatabaseFactory::SQLITE || + database()->activeDatabaseDriver() == DatabaseFactory::SQLITE_MEMORY)) { + // We need to save the database first. + database()->saveDatabase(); - if (!IOFactory::copyFile(database()->sqliteDatabaseFilePath(), target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_DATABASE)) { - throw ApplicationException(tr("Database file not copied to output directory successfully.")); - } - } + if (!IOFactory::copyFile(database()->sqliteDatabaseFilePath(), + target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_DATABASE)) { + throw ApplicationException(tr("Database file not copied to output directory successfully.")); + } + } } void Application::restoreDatabaseSettings(bool restore_database, bool restore_settings, const QString& source_database_file_path, const QString& source_settings_file_path) { - if (restore_database) { - if (!qApp->database()->initiateRestoration(source_database_file_path)) { - throw ApplicationException(tr("Database restoration was not initiated. Make sure that output directory is writable.")); - } - } + if (restore_database) { + if (!qApp->database()->initiateRestoration(source_database_file_path)) { + throw ApplicationException(tr("Database restoration was not initiated. Make sure that output directory is writable.")); + } + } - if (restore_settings) { - if (!qApp->settings()->initiateRestoration(source_settings_file_path)) { - throw ApplicationException(tr("Settings restoration was not initiated. Make sure that output directory is writable.")); - } - } + if (restore_settings) { + if (!qApp->settings()->initiateRestoration(source_settings_file_path)) { + throw ApplicationException(tr("Settings restoration was not initiated. Make sure that output directory is writable.")); + } + } } void Application::processExecutionMessage(const QString& message) { - qDebug("Received '%s' execution message from another application instance.", qPrintable(message)); - const QStringList messages = message.split(ARGUMENTS_LIST_SEPARATOR); + qDebug("Received '%s' execution message from another application instance.", qPrintable(message)); + const QStringList messages = message.split(ARGUMENTS_LIST_SEPARATOR); - if (messages.contains(APP_QUIT_INSTANCE)) { - quit(); - } - else { - foreach (const QString& msg, messages) { - if (msg == APP_IS_RUNNING) { - showGuiMessage(APP_NAME, tr("Application is already running."), QSystemTrayIcon::Information); - mainForm()->display(); - } - else if (msg.startsWith(QL1S(URI_SCHEME_FEED_SHORT))) { - // Application was running, and someone wants to add new feed. - StandardServiceRoot* root = qApp->feedReader()->feedsModel()->standardServiceRoot(); + if (messages.contains(APP_QUIT_INSTANCE)) { + quit(); + } + else { + foreach (const QString& msg, messages) { + if (msg == APP_IS_RUNNING) { + showGuiMessage(APP_NAME, tr("Application is already running."), QSystemTrayIcon::Information); + mainForm()->display(); + } + else if (msg.startsWith(QL1S(URI_SCHEME_FEED_SHORT))) { + // Application was running, and someone wants to add new feed. + StandardServiceRoot* root = qApp->feedReader()->feedsModel()->standardServiceRoot(); - if (root != nullptr) { - root->checkArgumentForFeedAdding(msg); - } - else { - showGuiMessage(tr("Cannot add feed"), - tr("Feed cannot be added because standard RSS/ATOM account is not enabled."), - QSystemTrayIcon::Warning, qApp->mainForm(), - true); - } - } - } - } + if (root != nullptr) { + root->checkArgumentForFeedAdding(msg); + } + else { + showGuiMessage(tr("Cannot add feed"), + tr("Feed cannot be added because standard RSS/ATOM account is not enabled."), + QSystemTrayIcon::Warning, qApp->mainForm(), + true); + } + } + } + } } SystemTrayIcon* Application::trayIcon() { - if (m_trayIcon == nullptr) { - m_trayIcon = new SystemTrayIcon(APP_ICON_PATH, APP_ICON_PLAIN_PATH, m_mainForm); - connect(m_trayIcon, &SystemTrayIcon::shown, m_feedReader->feedsModel(), &FeedsModel::notifyWithCounts); - connect(m_feedReader->feedsModel(), &FeedsModel::messageCountsChanged, m_trayIcon, &SystemTrayIcon::setNumber); - } + if (m_trayIcon == nullptr) { + m_trayIcon = new SystemTrayIcon(APP_ICON_PATH, APP_ICON_PLAIN_PATH, m_mainForm); + connect(m_trayIcon, &SystemTrayIcon::shown, m_feedReader->feedsModel(), &FeedsModel::notifyWithCounts); + connect(m_feedReader->feedsModel(), &FeedsModel::messageCountsChanged, m_trayIcon, &SystemTrayIcon::setNumber); + } - return m_trayIcon; + return m_trayIcon; } #if defined(USE_WEBENGINE) NetworkUrlInterceptor* Application::urlIinterceptor() { - return m_urlInterceptor; + return m_urlInterceptor; } + #endif void Application::showTrayIcon() { - qDebug("Showing tray icon."); - trayIcon()->show(); + qDebug("Showing tray icon."); + trayIcon()->show(); } void Application::deleteTrayIcon() { - if (m_trayIcon != nullptr) { - qDebug("Disabling tray icon, deleting it and raising main application window."); - m_mainForm->display(); - delete m_trayIcon; - m_trayIcon = nullptr; - // Make sure that application quits when last window is closed. - setQuitOnLastWindowClosed(true); - } + if (m_trayIcon != nullptr) { + qDebug("Disabling tray icon, deleting it and raising main application window."); + m_mainForm->display(); + delete m_trayIcon; + m_trayIcon = nullptr; + + // Make sure that application quits when last window is closed. + setQuitOnLastWindowClosed(true); + } } void Application::showGuiMessage(const QString& title, const QString& message, QSystemTrayIcon::MessageIcon message_type, QWidget* parent, bool show_at_least_msgbox, std::function functor) { - if (SystemTrayIcon::areNotificationsEnabled() && SystemTrayIcon::isSystemTrayActivated()) { - trayIcon()->showMessage(title, message, message_type, TRAY_ICON_BUBBLE_TIMEOUT, functor); - } - else if (show_at_least_msgbox) { - // Tray icon or OSD is not available, display simple text box. - MessageBox::show(parent, (QMessageBox::Icon) message_type, title, message); - } - else { - qDebug("Silencing GUI message: '%s'.", qPrintable(message)); - } + if (SystemTrayIcon::areNotificationsEnabled() && SystemTrayIcon::isSystemTrayActivated()) { + trayIcon()->showMessage(title, message, message_type, TRAY_ICON_BUBBLE_TIMEOUT, functor); + } + else if (show_at_least_msgbox) { + // Tray icon or OSD is not available, display simple text box. + MessageBox::show(parent, (QMessageBox::Icon) message_type, title, message); + } + else { + qDebug("Silencing GUI message: '%s'.", qPrintable(message)); + } } void Application::onCommitData(QSessionManager& manager) { - qDebug("OS asked application to commit its data."); - manager.setRestartHint(QSessionManager::RestartNever); - manager.release(); + qDebug("OS asked application to commit its data."); + manager.setRestartHint(QSessionManager::RestartNever); + manager.release(); } void Application::onSaveState(QSessionManager& manager) { - qDebug("OS asked application to save its state."); - manager.setRestartHint(QSessionManager::RestartNever); - manager.release(); + qDebug("OS asked application to save its state."); + manager.setRestartHint(QSessionManager::RestartNever); + manager.release(); } void Application::onAboutToQuit() { @@ -361,39 +365,41 @@ void Application::onAboutToQuit() { eliminateFirstRun(APP_VERSION); #if defined(USE_WEBENGINE) - AdBlockManager::instance()->save(); + AdBlockManager::instance()->save(); #endif - // Make sure that we obtain close lock BEFORE even trying to quit the application. - const bool locked_safely = feedUpdateLock()->tryLock(4 * CLOSE_LOCK_TIMEOUT); - processEvents(); - qDebug("Cleaning up resources and saving application state."); + // Make sure that we obtain close lock BEFORE even trying to quit the application. + const bool locked_safely = feedUpdateLock()->tryLock(4 * CLOSE_LOCK_TIMEOUT); + + processEvents(); + qDebug("Cleaning up resources and saving application state."); #if defined(Q_OS_WIN) - system()->removeTrolltechJunkRegistryKeys(); + system()->removeTrolltechJunkRegistryKeys(); #endif - qApp->feedReader()->quit(); - database()->saveDatabase(); + qApp->feedReader()->quit(); + database()->saveDatabase(); - if (mainForm() != nullptr) { + if (mainForm() != nullptr) { mainForm()->saveSize(); - } + } - if (locked_safely) { + if (locked_safely) { // Application obtained permission to close in a safe way. qDebug("Close lock was obtained safely."); + // We locked the lock to exit peacefully, unlock it to avoid warnings. feedUpdateLock()->unlock(); - } - else { + } + else { // Request for write lock timed-out. This means // that some critical action can be processed right now. qDebug("Close lock timed-out."); - } + } - // Now, we can check if application should just quit or restart itself. - if (m_shouldRestart) { + // Now, we can check if application should just quit or restart itself. + if (m_shouldRestart) { finish(); qDebug("Killing local peer connection to allow another instance to start."); @@ -409,30 +415,30 @@ void Application::onAboutToQuit() { } void Application::restart() { - m_shouldRestart = true; - quit(); + m_shouldRestart = true; + quit(); } #if defined(USE_WEBENGINE) void Application::downloadRequested(QWebEngineDownloadItem* download_item) { - downloadManager()->download(download_item->url()); - download_item->cancel(); - download_item->deleteLater(); + downloadManager()->download(download_item->url()); + download_item->cancel(); + download_item->deleteLater(); } + #endif -void Application::onFeedUpdatesStarted() { -} +void Application::onFeedUpdatesStarted() {} void Application::onFeedUpdatesProgress(const Feed* feed, int current, int total) { - Q_UNUSED(feed) - Q_UNUSED(current) - Q_UNUSED(total) + Q_UNUSED(feed) + Q_UNUSED(current) + Q_UNUSED(total) } void Application::onFeedUpdatesFinished(FeedDownloadResults results) { - if (!results.updatedFeeds().isEmpty()) { - // Now, inform about results via GUI message/notification. - qApp->showGuiMessage(tr("New messages downloaded"), results.overview(10), QSystemTrayIcon::NoIcon, 0, false); - } + if (!results.updatedFeeds().isEmpty()) { + // Now, inform about results via GUI message/notification. + qApp->showGuiMessage(tr("New messages downloaded"), results.overview(10), QSystemTrayIcon::NoIcon, 0, false); + } } diff --git a/src/miscellaneous/application.h b/src/miscellaneous/application.h index 7dbdf41b7..f43871d2c 100755 --- a/src/miscellaneous/application.h +++ b/src/miscellaneous/application.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,16 +21,16 @@ #include "qtsingleapplication/qtsingleapplication.h" +#include "core/feeddownloader.h" #include "definitions/definitions.h" -#include "miscellaneous/settings.h" -#include "miscellaneous/systemfactory.h" -#include "miscellaneous/skinfactory.h" -#include "miscellaneous/localization.h" +#include "gui/systemtrayicon.h" #include "miscellaneous/databasefactory.h" #include "miscellaneous/iofactory.h" -#include "gui/systemtrayicon.h" +#include "miscellaneous/localization.h" +#include "miscellaneous/settings.h" +#include "miscellaneous/skinfactory.h" +#include "miscellaneous/systemfactory.h" #include "network-web/downloadmanager.h" -#include "core/feeddownloader.h" #include @@ -42,7 +43,6 @@ // Define new qApp macro. Yeaaaaah. #define qApp (Application::instance()) - class FormMain; class IconFactory; class QAction; @@ -56,40 +56,42 @@ class NetworkUrlInterceptor; #endif class Application : public QtSingleApplication { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit Application(const QString& id, int& argc, char** argv); - virtual ~Application(); + public: - FeedReader* feedReader(); - void setFeedReader(FeedReader* feed_reader); + // Constructors and destructors. + explicit Application(const QString& id, int& argc, char** argv); + virtual ~Application(); - // Globally accessible actions. - QList userActions(); + FeedReader* feedReader(); - // Check whether this application starts for the first time (ever). - bool isFirstRun(); + void setFeedReader(FeedReader* feed_reader); - // Check whether GIVEN VERSION of the application starts for the first time. - bool isFirstRun(const QString& version); + // Globally accessible actions. + QList userActions(); - WebFactory* web(); - SystemFactory* system(); - SkinFactory* skins(); - Localization* localization(); - DatabaseFactory* database(); - IconFactory* icons(); - DownloadManager* downloadManager(); - Settings* settings(); - Mutex* feedUpdateLock(); - FormMain* mainForm(); - QWidget* mainFormWidget(); - SystemTrayIcon* trayIcon(); + // Check whether this application starts for the first time (ever). + bool isFirstRun(); + + // Check whether GIVEN VERSION of the application starts for the first time. + bool isFirstRun(const QString& version); + + WebFactory* web(); + SystemFactory* system(); + SkinFactory* skins(); + Localization* localization(); + DatabaseFactory* database(); + IconFactory* icons(); + DownloadManager* downloadManager(); + Settings* settings(); + Mutex* feedUpdateLock(); + FormMain* mainForm(); + QWidget* mainFormWidget(); + SystemTrayIcon* trayIcon(); #if defined(USE_WEBENGINE) - NetworkUrlInterceptor* urlIinterceptor(); + NetworkUrlInterceptor* urlIinterceptor(); #endif QString tempFolder(); @@ -97,93 +99,95 @@ class Application : public QtSingleApplication { QString homeFolder(); QString configFolder(); - // These return user ready folders. + // These return user ready folders. QString userDataAppFolder(); QString userDataHomeFolder(); - // Returns the base folder to which store user data, the "data" folder. - // NOTE: Use this to get correct path under which store user data. + // Returns the base folder to which store user data, the "data" folder. + // NOTE: Use this to get correct path under which store user data. QString userDataFolder(); - void setMainForm(FormMain* main_form); + void setMainForm(FormMain* main_form); - void backupDatabaseSettings(bool backup_database, bool backup_settings, - const QString& target_path, const QString& backup_name); - void restoreDatabaseSettings(bool restore_database, bool restore_settings, - const QString& source_database_file_path = QString(), - const QString& source_settings_file_path = QString()); + void backupDatabaseSettings(bool backup_database, bool backup_settings, + const QString& target_path, const QString& backup_name); + void restoreDatabaseSettings(bool restore_database, bool restore_settings, + const QString& source_database_file_path = QString(), + const QString& source_settings_file_path = QString()); - void showTrayIcon(); - void deleteTrayIcon(); + void showTrayIcon(); + void deleteTrayIcon(); - // Displays given simple message in tray icon bubble or OSD - // or in message box if tray icon is disabled. - void showGuiMessage(const QString& title, const QString& message, QSystemTrayIcon::MessageIcon message_type, - QWidget* parent = nullptr, bool show_at_least_msgbox = false, - std::function functor = nullptr); + // Displays given simple message in tray icon bubble or OSD + // or in message box if tray icon is disabled. + void showGuiMessage(const QString& title, const QString& message, QSystemTrayIcon::MessageIcon message_type, + QWidget* parent = nullptr, bool show_at_least_msgbox = false, + std::function functor = nullptr); - // Returns pointer to "GOD" application singleton. - inline static Application* instance() { - return static_cast(QCoreApplication::instance()); - } + // Returns pointer to "GOD" application singleton. + inline static Application* instance() { + return static_cast(QCoreApplication::instance()); + } - public slots: - // Restarts the application. - void restart(); + public slots: - // Processes incoming message from another RSS Guard instance. - void processExecutionMessage(const QString& message); + // Restarts the application. + void restart(); - private slots: - // Last-minute reactors. - void onCommitData(QSessionManager& manager); - void onSaveState(QSessionManager& manager); - void onAboutToQuit(); + // Processes incoming message from another RSS Guard instance. + void processExecutionMessage(const QString& message); + + private slots: + + // Last-minute reactors. + void onCommitData(QSessionManager& manager); + void onSaveState(QSessionManager& manager); + void onAboutToQuit(); #if defined(USE_WEBENGINE) - void downloadRequested(QWebEngineDownloadItem* download_item); + void downloadRequested(QWebEngineDownloadItem* download_item); #endif - void onFeedUpdatesStarted(); - void onFeedUpdatesProgress(const Feed* feed, int current, int total); - void onFeedUpdatesFinished(FeedDownloadResults results); + void onFeedUpdatesStarted(); + void onFeedUpdatesProgress(const Feed* feed, int current, int total); + void onFeedUpdatesFinished(FeedDownloadResults results); - private: - void eliminateFirstRun(); - void eliminateFirstRun(const QString& version); + private: + void eliminateFirstRun(); + void eliminateFirstRun(const QString& version); #if defined(USE_WEBENGINE) - NetworkUrlInterceptor* m_urlInterceptor; + NetworkUrlInterceptor* m_urlInterceptor; #endif - FeedReader* m_feedReader; + FeedReader* m_feedReader; - // This read-write lock is used by application on its close. - // Application locks this lock for WRITING. - // This means that if application locks that lock, then - // no other transaction-critical action can acquire lock - // for reading and won't be executed, so no critical action - // will be running when application quits - // - // EACH critical action locks this lock for READING. - // Several actions can lock this lock for reading. - // But of user decides to close the application (in other words, - // tries to lock the lock for writing), then no other - // action will be allowed to lock for reading. - QScopedPointer m_updateFeedsLock; + // This read-write lock is used by application on its close. + // Application locks this lock for WRITING. + // This means that if application locks that lock, then + // no other transaction-critical action can acquire lock + // for reading and won't be executed, so no critical action + // will be running when application quits + // + // EACH critical action locks this lock for READING. + // Several actions can lock this lock for reading. + // But of user decides to close the application (in other words, + // tries to lock the lock for writing), then no other + // action will be allowed to lock for reading. + QScopedPointer m_updateFeedsLock; - QList m_userActions; - FormMain* m_mainForm; - SystemTrayIcon* m_trayIcon; - Settings* m_settings; - WebFactory* m_webFactory; - SystemFactory* m_system; - SkinFactory* m_skins; - Localization* m_localization; - IconFactory* m_icons; - DatabaseFactory* m_database; - DownloadManager* m_downloadManager; - bool m_shouldRestart; + QList m_userActions; + FormMain* m_mainForm; + SystemTrayIcon* m_trayIcon; + Settings* m_settings; + WebFactory* m_webFactory; + SystemFactory* m_system; + SkinFactory* m_skins; + Localization* m_localization; + IconFactory* m_icons; + DatabaseFactory* m_database; + DownloadManager* m_downloadManager; + bool m_shouldRestart; }; #endif // APPLICATION_H diff --git a/src/miscellaneous/autosaver.cpp b/src/miscellaneous/autosaver.cpp index daf1ffb91..8bc62e4eb 100755 --- a/src/miscellaneous/autosaver.cpp +++ b/src/miscellaneous/autosaver.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,57 +18,56 @@ #include "miscellaneous/autosaver.h" -#include #include +#include #include #define AUTOSAVE_IN 1000 * 3 // seconds #define MAXWAIT 1000 * 15 // seconds - AutoSaver::AutoSaver(QObject* parent) : QObject(parent) { - Q_ASSERT(parent); + Q_ASSERT(parent); } AutoSaver::~AutoSaver() { - if (m_timer.isActive()) { - qWarning("AutoSaver: still active when destroyed, changes not saved."); + if (m_timer.isActive()) { + qWarning("AutoSaver: still active when destroyed, changes not saved."); - if (parent() && parent()->metaObject()) { - qWarning("Should call saveIfNeccessary."); - } - } + if (parent() && parent()->metaObject()) { + qWarning("Should call saveIfNeccessary."); + } + } } void AutoSaver::changeOccurred() { - if (m_firstChange.isNull()) { - m_firstChange.start(); - } + if (m_firstChange.isNull()) { + m_firstChange.start(); + } - if (m_firstChange.elapsed() > MAXWAIT) { - saveIfNeccessary(); - } - else { - m_timer.start(AUTOSAVE_IN, this); - } + if (m_firstChange.elapsed() > MAXWAIT) { + saveIfNeccessary(); + } + else { + m_timer.start(AUTOSAVE_IN, this); + } } void AutoSaver::timerEvent(QTimerEvent* event) { - if (event->timerId() == m_timer.timerId()) { - saveIfNeccessary(); - } - else { - QObject::timerEvent(event); - } + if (event->timerId() == m_timer.timerId()) { + saveIfNeccessary(); + } + else { + QObject::timerEvent(event); + } } void AutoSaver::saveIfNeccessary() { - if (m_timer.isActive()) { - m_timer.stop(); - m_firstChange = QTime(); + if (m_timer.isActive()) { + m_timer.stop(); + m_firstChange = QTime(); - if (!QMetaObject::invokeMethod(parent(), "save", Qt::DirectConnection)) { - qWarning("AutoSaver: error invoking slot save() on parent."); - } - } + if (!QMetaObject::invokeMethod(parent(), "save", Qt::DirectConnection)) { + qWarning("AutoSaver: error invoking slot save() on parent."); + } + } } diff --git a/src/miscellaneous/autosaver.h b/src/miscellaneous/autosaver.h index 8fb5e2b01..7599b4f49 100755 --- a/src/miscellaneous/autosaver.h +++ b/src/miscellaneous/autosaver.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,29 +19,28 @@ #ifndef AUTOSAVER_H #define AUTOSAVER_H -#include #include +#include #include - class AutoSaver : public QObject { - Q_OBJECT + Q_OBJECT - public: - explicit AutoSaver(QObject* parent); - virtual ~AutoSaver(); + public: + explicit AutoSaver(QObject* parent); + virtual ~AutoSaver(); - void saveIfNeccessary(); + void saveIfNeccessary(); - public slots: - void changeOccurred(); + public slots: + void changeOccurred(); - protected: - void timerEvent(QTimerEvent* event); + protected: + void timerEvent(QTimerEvent* event); - private: - QBasicTimer m_timer; - QTime m_firstChange; + private: + QBasicTimer m_timer; + QTime m_firstChange; }; #endif // AUTOSAVER_H diff --git a/src/miscellaneous/databasecleaner.cpp b/src/miscellaneous/databasecleaner.cpp index acbaac095..c9f5a43fe 100755 --- a/src/miscellaneous/databasecleaner.cpp +++ b/src/miscellaneous/databasecleaner.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,73 +24,75 @@ #include #include +DatabaseCleaner::DatabaseCleaner(QObject* parent) : QObject(parent) {} -DatabaseCleaner::DatabaseCleaner(QObject* parent) : QObject(parent) { -} - -DatabaseCleaner::~DatabaseCleaner() { -} +DatabaseCleaner::~DatabaseCleaner() {} void DatabaseCleaner::purgeDatabaseData(const CleanerOrders& which_data) { - qDebug().nospace() << "Performing database cleanup in thread: \'" << QThread::currentThreadId() << "\'."; - // Inform everyone about the start of the process. - emit purgeStarted(); - bool result = true; - const int difference = 99 / 8; - int progress = 0; - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + qDebug().nospace() << "Performing database cleanup in thread: \'" << QThread::currentThreadId() << "\'."; - if (which_data.m_removeReadMessages) { - progress += difference; - emit purgeProgress(progress, tr("Removing read messages...")); - // Remove read messages. - result &= purgeReadMessages(database); - progress += difference; - emit purgeProgress(progress, tr("Read messages purged...")); - } + // Inform everyone about the start of the process. + emit purgeStarted(); + bool result = true; + const int difference = 99 / 8; + int progress = 0; + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - if (which_data.m_removeRecycleBin) { - progress += difference; - emit purgeProgress(progress, tr("Purging recycle bin...")); - // Remove read messages. - result &= purgeRecycleBin(database); - progress += difference; - emit purgeProgress(progress, tr("Recycle bin purged...")); - } + if (which_data.m_removeReadMessages) { + progress += difference; + emit purgeProgress(progress, tr("Removing read messages...")); - if (which_data.m_removeOldMessages) { - progress += difference; - emit purgeProgress(progress, tr("Removing old messages...")); - // Remove old messages. - result &= purgeOldMessages(database, which_data.m_barrierForRemovingOldMessagesInDays); - progress += difference; - emit purgeProgress(progress, tr("Old messages purged...")); - } + // Remove read messages. + result &= purgeReadMessages(database); + progress += difference; + emit purgeProgress(progress, tr("Read messages purged...")); + } - if (which_data.m_shrinkDatabase) { - progress += difference; - emit purgeProgress(progress, tr("Shrinking database file...")); - // Call driver-specific vacuuming function. - result &= qApp->database()->vacuumDatabase(); - progress += difference; - emit purgeProgress(progress, tr("Database file shrinked...")); - } + if (which_data.m_removeRecycleBin) { + progress += difference; + emit purgeProgress(progress, tr("Purging recycle bin...")); - emit purgeFinished(result); + // Remove read messages. + result &= purgeRecycleBin(database); + progress += difference; + emit purgeProgress(progress, tr("Recycle bin purged...")); + } + + if (which_data.m_removeOldMessages) { + progress += difference; + emit purgeProgress(progress, tr("Removing old messages...")); + + // Remove old messages. + result &= purgeOldMessages(database, which_data.m_barrierForRemovingOldMessagesInDays); + progress += difference; + emit purgeProgress(progress, tr("Old messages purged...")); + } + + if (which_data.m_shrinkDatabase) { + progress += difference; + emit purgeProgress(progress, tr("Shrinking database file...")); + + // Call driver-specific vacuuming function. + result &= qApp->database()->vacuumDatabase(); + progress += difference; + emit purgeProgress(progress, tr("Database file shrinked...")); + } + + emit purgeFinished(result); } bool DatabaseCleaner::purgeStarredMessages(const QSqlDatabase& database) { - return DatabaseQueries::purgeImportantMessages(database); + return DatabaseQueries::purgeImportantMessages(database); } bool DatabaseCleaner::purgeReadMessages(const QSqlDatabase& database) { - return DatabaseQueries::purgeReadMessages(database); + return DatabaseQueries::purgeReadMessages(database); } bool DatabaseCleaner::purgeOldMessages(const QSqlDatabase& database, int days) { - return DatabaseQueries::purgeOldMessages(database, days); + return DatabaseQueries::purgeOldMessages(database, days); } bool DatabaseCleaner::purgeRecycleBin(const QSqlDatabase& database) { - return DatabaseQueries::purgeRecycleBin(database); + return DatabaseQueries::purgeRecycleBin(database); } diff --git a/src/miscellaneous/databasecleaner.h b/src/miscellaneous/databasecleaner.h index f16ee10d5..2fe7c47ad 100755 --- a/src/miscellaneous/databasecleaner.h +++ b/src/miscellaneous/databasecleaner.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,37 +23,37 @@ #include - struct CleanerOrders { - bool m_removeReadMessages; - bool m_shrinkDatabase; - bool m_removeOldMessages; - bool m_removeRecycleBin; - bool m_removeStarredMessages; - int m_barrierForRemovingOldMessagesInDays; + bool m_removeReadMessages; + bool m_shrinkDatabase; + bool m_removeOldMessages; + bool m_removeRecycleBin; + bool m_removeStarredMessages; + int m_barrierForRemovingOldMessagesInDays; }; class DatabaseCleaner : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Constructors. - explicit DatabaseCleaner(QObject* parent = 0); - virtual ~DatabaseCleaner(); + public: - signals: - void purgeStarted(); - void purgeProgress(int progress, const QString& description); - void purgeFinished(bool result); + // Constructors. + explicit DatabaseCleaner(QObject* parent = 0); + virtual ~DatabaseCleaner(); - public slots: - void purgeDatabaseData(const CleanerOrders& which_data); + signals: + void purgeStarted(); + void purgeProgress(int progress, const QString& description); + void purgeFinished(bool result); - private: - bool purgeStarredMessages(const QSqlDatabase& database); - bool purgeReadMessages(const QSqlDatabase& database); - bool purgeOldMessages(const QSqlDatabase& database, int days); - bool purgeRecycleBin(const QSqlDatabase& database); + public slots: + void purgeDatabaseData(const CleanerOrders& which_data); + + private: + bool purgeStarredMessages(const QSqlDatabase& database); + bool purgeReadMessages(const QSqlDatabase& database); + bool purgeOldMessages(const QSqlDatabase& database, int days); + bool purgeRecycleBin(const QSqlDatabase& database); }; #endif // DATABASECLEANER_H diff --git a/src/miscellaneous/databasefactory.cpp b/src/miscellaneous/databasefactory.cpp index 138a606f1..b7e2bf893 100755 --- a/src/miscellaneous/databasefactory.cpp +++ b/src/miscellaneous/databasefactory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,781 +18,807 @@ #include "miscellaneous/databasefactory.h" -#include "miscellaneous/iofactory.h" -#include "miscellaneous/application.h" -#include "miscellaneous/textfactory.h" #include "gui/messagebox.h" +#include "miscellaneous/application.h" +#include "miscellaneous/iofactory.h" +#include "miscellaneous/textfactory.h" #include -#include #include +#include #include - DatabaseFactory::DatabaseFactory(QObject* parent) - : QObject(parent), - m_mysqlDatabaseInitialized(false), - m_sqliteFileBasedDatabaseinitialized(false), - m_sqliteInMemoryDatabaseInitialized(false) { - setObjectName(QSL("DatabaseFactory")); - determineDriver(); + : QObject(parent), + m_mysqlDatabaseInitialized(false), + m_sqliteFileBasedDatabaseinitialized(false), + m_sqliteInMemoryDatabaseInitialized(false) { + setObjectName(QSL("DatabaseFactory")); + determineDriver(); } -DatabaseFactory::~DatabaseFactory() { -} +DatabaseFactory::~DatabaseFactory() {} qint64 DatabaseFactory::getDatabaseFileSize() const { - if (m_activeDatabaseDriver == SQLITE || m_activeDatabaseDriver == SQLITE_MEMORY) { - return QFileInfo(sqliteDatabaseFilePath()).size(); - } - else { - return 0; - } + if (m_activeDatabaseDriver == SQLITE || m_activeDatabaseDriver == SQLITE_MEMORY) { + return QFileInfo(sqliteDatabaseFilePath()).size(); + } + else { + return 0; + } } qint64 DatabaseFactory::getDatabaseDataSize() const { - if (m_activeDatabaseDriver == SQLITE || m_activeDatabaseDriver == SQLITE_MEMORY) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - qint64 result = 1; - QSqlQuery query(database); + if (m_activeDatabaseDriver == SQLITE || m_activeDatabaseDriver == SQLITE_MEMORY) { + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + qint64 result = 1; + QSqlQuery query(database); - if (query.exec(QSL("PRAGMA page_count;"))) { - query.next(); - result *= query.value(0).value(); - } - else { - return 0; - } + if (query.exec(QSL("PRAGMA page_count;"))) { + query.next(); + result *= query.value(0).value(); + } + else { + return 0; + } - if (query.exec(QSL("PRAGMA page_size;"))) { - query.next(); - result *= query.value(0).value(); - } - else { - return 0; - } + if (query.exec(QSL("PRAGMA page_size;"))) { + query.next(); + result *= query.value(0).value(); + } + else { + return 0; + } - return result; - } - else if (m_activeDatabaseDriver == MYSQL) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - qint64 result = 1; - QSqlQuery query(database); + return result; + } + else if (m_activeDatabaseDriver == MYSQL) { + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + qint64 result = 1; + QSqlQuery query(database); - if (query.exec("SELECT Round(Sum(data_length + index_length), 1) " - "FROM information_schema.tables " - "GROUP BY table_schema;")) { - while (query.next()) { - result *= query.value(0).value(); - } + if (query.exec("SELECT Round(Sum(data_length + index_length), 1) " + "FROM information_schema.tables " + "GROUP BY table_schema;")) { + while (query.next()) { + result *= query.value(0).value(); + } - return result; - } - else { - return 0; - } - } - else { - return 0; - } + return result; + } + else { + return 0; + } + } + else { + return 0; + } } DatabaseFactory::MySQLError DatabaseFactory::mysqlTestConnection(const QString& hostname, int port, const QString& w_database, - const QString& username, const QString& password) { - QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, APP_DB_MYSQL_TEST); - database.setHostName(hostname); - database.setPort(port); - database.setUserName(username); - database.setPassword(password); - database.setDatabaseName(w_database); + const QString& username, const QString& password) { + QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, APP_DB_MYSQL_TEST); - if (database.open() && !database.lastError().isValid()) { - QSqlQuery query(QSL("SELECT version();"), database); + database.setHostName(hostname); + database.setPort(port); + database.setUserName(username); + database.setPassword(password); + database.setDatabaseName(w_database); - if (!query.lastError().isValid() && query.next()) { - qDebug("Checked MySQL database, version is '%s'.", qPrintable(query.value(0).toString())); - // Connection succeeded, clean up the mess and return OK status. - database.close(); - return MySQLOk; - } - else { - database.close(); - return MySQLUnknownError; - } - } - else if (database.lastError().isValid()) { - // Connection failed, do cleanup and return specific error code. - return static_cast(database.lastError().number()); - } - else { - return MySQLUnknownError; - } + if (database.open() && !database.lastError().isValid()) { + QSqlQuery query(QSL("SELECT version();"), database); + + if (!query.lastError().isValid() && query.next()) { + qDebug("Checked MySQL database, version is '%s'.", qPrintable(query.value(0).toString())); + + // Connection succeeded, clean up the mess and return OK status. + database.close(); + return MySQLOk; + } + else { + database.close(); + return MySQLUnknownError; + } + } + else if (database.lastError().isValid()) { + // Connection failed, do cleanup and return specific error code. + return static_cast(database.lastError().number()); + } + else { + return MySQLUnknownError; + } } QString DatabaseFactory::mysqlInterpretErrorCode(MySQLError error_code) const { - switch (error_code) { - case MySQLOk: - return tr("MySQL server works as expected."); + switch (error_code) { + case MySQLOk: + return tr("MySQL server works as expected."); - case MySQLUnknownDatabase: - return tr("Selected database does not exist (yet). It will be created. It's okay."); + case MySQLUnknownDatabase: + return tr("Selected database does not exist (yet). It will be created. It's okay."); - case MySQLCantConnect: - case MySQLConnectionError: - case MySQLUnknownHost: - return tr("No MySQL server is running in the target destination."); + case MySQLCantConnect: + case MySQLConnectionError: + case MySQLUnknownHost: + return tr("No MySQL server is running in the target destination."); - case MySQLAccessDenied: - //: Access to MySQL server was denied. - return tr("Access denied. Invalid username or password used."); + case MySQLAccessDenied: - default: - //: Unknown MySQL error arised. - return tr("Unknown error."); - } + //: Access to MySQL server was denied. + return tr("Access denied. Invalid username or password used."); + + default: + + //: Unknown MySQL error arised. + return tr("Unknown error."); + } } bool DatabaseFactory::initiateRestoration(const QString& database_backup_file_path) { - switch (m_activeDatabaseDriver) { - case SQLITE: - case SQLITE_MEMORY: - return IOFactory::copyFile(database_backup_file_path, - m_sqliteDatabaseFilePath + QDir::separator() + - BACKUP_NAME_DATABASE + BACKUP_SUFFIX_DATABASE); + switch (m_activeDatabaseDriver) { + case SQLITE: + case SQLITE_MEMORY: + return IOFactory::copyFile(database_backup_file_path, + m_sqliteDatabaseFilePath + QDir::separator() + + BACKUP_NAME_DATABASE + BACKUP_SUFFIX_DATABASE); - default: - return false; - } + default: + return false; + } } void DatabaseFactory::finishRestoration() { - if (m_activeDatabaseDriver != SQLITE && m_activeDatabaseDriver != SQLITE_MEMORY) { - return; - } + if (m_activeDatabaseDriver != SQLITE && m_activeDatabaseDriver != SQLITE_MEMORY) { + return; + } - const QString backup_database_file = m_sqliteDatabaseFilePath + QDir::separator() + BACKUP_NAME_DATABASE + BACKUP_SUFFIX_DATABASE; + const QString backup_database_file = m_sqliteDatabaseFilePath + QDir::separator() + BACKUP_NAME_DATABASE + BACKUP_SUFFIX_DATABASE; - if (QFile::exists(backup_database_file)) { - qWarning("Backup database file '%s' was detected. Restoring it.", qPrintable(QDir::toNativeSeparators(backup_database_file))); + if (QFile::exists(backup_database_file)) { + qWarning("Backup database file '%s' was detected. Restoring it.", qPrintable(QDir::toNativeSeparators(backup_database_file))); - if (IOFactory::copyFile(backup_database_file, m_sqliteDatabaseFilePath + QDir::separator() + APP_DB_SQLITE_FILE)) { - QFile::remove(backup_database_file); - qDebug("Database file was restored successully."); - } - else { - qCritical("Database file was NOT restored due to error when copying the file."); - } - } + if (IOFactory::copyFile(backup_database_file, m_sqliteDatabaseFilePath + QDir::separator() + APP_DB_SQLITE_FILE)) { + QFile::remove(backup_database_file); + qDebug("Database file was restored successully."); + } + else { + qCritical("Database file was NOT restored due to error when copying the file."); + } + } } void DatabaseFactory::sqliteAssemblyDatabaseFilePath() { - m_sqliteDatabaseFilePath = qApp->userDataFolder() + QDir::separator() + QString(APP_DB_SQLITE_PATH); + m_sqliteDatabaseFilePath = qApp->userDataFolder() + QDir::separator() + QString(APP_DB_SQLITE_PATH); } QSqlDatabase DatabaseFactory::sqliteInitializeInMemoryDatabase() { - QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER); - database.setDatabaseName(QSL(":memory:")); + QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER); - if (!database.open()) { - qFatal("In-memory SQLite database was NOT opened. Delivered error message: '%s'", qPrintable(database.lastError().text())); - } - else { - QSqlQuery query_db(database); - query_db.setForwardOnly(true); - query_db.exec(QSL("PRAGMA encoding = \"UTF-8\"")); - query_db.exec(QSL("PRAGMA synchronous = OFF")); - query_db.exec(QSL("PRAGMA journal_mode = MEMORY")); - query_db.exec(QSL("PRAGMA page_size = 4096")); - query_db.exec(QSL("PRAGMA cache_size = 16384")); - query_db.exec(QSL("PRAGMA count_changes = OFF")); - query_db.exec(QSL("PRAGMA temp_store = MEMORY")); - // Sample query which checks for existence of tables. - query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'")); + database.setDatabaseName(QSL(":memory:")); - if (query_db.lastError().isValid()) { - qWarning("Error occurred. In-memory SQLite database is not initialized. Initializing now."); - QFile file_init(APP_SQL_PATH + QDir::separator() + APP_DB_SQLITE_INIT); + if (!database.open()) { + qFatal("In-memory SQLite database was NOT opened. Delivered error message: '%s'", qPrintable(database.lastError().text())); + } + else { + QSqlQuery query_db(database); - if (!file_init.open(QIODevice::ReadOnly | QIODevice::Text)) { - // Database initialization file not opened. HUGE problem. - qFatal("In-memory SQLite database initialization file '%s' from directory '%s' was not found. In-memory database is uninitialized.", - APP_DB_SQLITE_INIT, - qPrintable(APP_SQL_PATH)); - } + query_db.setForwardOnly(true); + query_db.exec(QSL("PRAGMA encoding = \"UTF-8\"")); + query_db.exec(QSL("PRAGMA synchronous = OFF")); + query_db.exec(QSL("PRAGMA journal_mode = MEMORY")); + query_db.exec(QSL("PRAGMA page_size = 4096")); + query_db.exec(QSL("PRAGMA cache_size = 16384")); + query_db.exec(QSL("PRAGMA count_changes = OFF")); + query_db.exec(QSL("PRAGMA temp_store = MEMORY")); - const QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts); - database.transaction(); + // Sample query which checks for existence of tables. + query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'")); - foreach (const QString& statement, statements) { - query_db.exec(statement); + if (query_db.lastError().isValid()) { + qWarning("Error occurred. In-memory SQLite database is not initialized. Initializing now."); + QFile file_init(APP_SQL_PATH + QDir::separator() + APP_DB_SQLITE_INIT); - if (query_db.lastError().isValid()) { - qFatal("In-memory SQLite database initialization failed. Initialization script '%s' is not correct.", APP_DB_SQLITE_INIT); - } - } + if (!file_init.open(QIODevice::ReadOnly | QIODevice::Text)) { + // Database initialization file not opened. HUGE problem. + qFatal("In-memory SQLite database initialization file '%s' from directory '%s' was not found. In-memory database is uninitialized.", + APP_DB_SQLITE_INIT, + qPrintable(APP_SQL_PATH)); + } - database.commit(); - qDebug("In-memory SQLite database backend should be ready now."); - } - else { - query_db.next(); - qDebug("In-memory SQLite database connection seems to be established."); - qDebug("In-memory SQLite database has version '%s'.", qPrintable(query_db.value(0).toString())); - } + const QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts); - // Loading messages from file-based database. - QSqlDatabase file_database = sqliteConnection(objectName(), StrictlyFileBased); - QSqlQuery copy_contents(database); - // Attach database. - copy_contents.exec(QString("ATTACH DATABASE '%1' AS 'storage';").arg(file_database.databaseName())); - // Copy all stuff. - QStringList tables; + database.transaction(); - if (copy_contents.exec(QSL("SELECT name FROM storage.sqlite_master WHERE type='table';"))) { - while (copy_contents.next()) { - tables.append(copy_contents.value(0).toString()); - } - } - else { - qFatal("Cannot obtain list of table names from file-base SQLite database."); - } + foreach (const QString& statement, statements) { + query_db.exec(statement); - foreach (const QString& table, tables) { - copy_contents.exec(QString("INSERT INTO main.%1 SELECT * FROM storage.%1;").arg(table)); - } + if (query_db.lastError().isValid()) { + qFatal("In-memory SQLite database initialization failed. Initialization script '%s' is not correct.", APP_DB_SQLITE_INIT); + } + } - qDebug("Copying data from file-based database into working in-memory database."); - // Detach database and finish. - copy_contents.exec(QSL("DETACH 'storage'")); - copy_contents.finish(); - query_db.finish(); - } + database.commit(); + qDebug("In-memory SQLite database backend should be ready now."); + } + else { + query_db.next(); + qDebug("In-memory SQLite database connection seems to be established."); + qDebug("In-memory SQLite database has version '%s'.", qPrintable(query_db.value(0).toString())); + } - // Everything is initialized now. - m_sqliteInMemoryDatabaseInitialized = true; - return database; + // Loading messages from file-based database. + QSqlDatabase file_database = sqliteConnection(objectName(), StrictlyFileBased); + QSqlQuery copy_contents(database); + + // Attach database. + copy_contents.exec(QString("ATTACH DATABASE '%1' AS 'storage';").arg(file_database.databaseName())); + + // Copy all stuff. + QStringList tables; + + if (copy_contents.exec(QSL("SELECT name FROM storage.sqlite_master WHERE type='table';"))) { + while (copy_contents.next()) { + tables.append(copy_contents.value(0).toString()); + } + } + else { + qFatal("Cannot obtain list of table names from file-base SQLite database."); + } + + foreach (const QString& table, tables) { + copy_contents.exec(QString("INSERT INTO main.%1 SELECT * FROM storage.%1;").arg(table)); + } + + qDebug("Copying data from file-based database into working in-memory database."); + + // Detach database and finish. + copy_contents.exec(QSL("DETACH 'storage'")); + copy_contents.finish(); + query_db.finish(); + } + + // Everything is initialized now. + m_sqliteInMemoryDatabaseInitialized = true; + return database; } QSqlDatabase DatabaseFactory::sqliteInitializeFileBasedDatabase(const QString& connection_name) { - finishRestoration(); - // Prepare file paths. - const QDir db_path(m_sqliteDatabaseFilePath); - QFile db_file(db_path.absoluteFilePath(APP_DB_SQLITE_FILE)); + finishRestoration(); - // Check if database directory exists. - if (!db_path.exists()) { - if (!db_path.mkpath(db_path.absolutePath())) { - // Failure when create database file path. - qFatal("Directory '%s' for SQLite database file '%s' was NOT created." - "This is HUGE problem.", - qPrintable(db_path.absolutePath()), - qPrintable(db_file.symLinkTarget())); - } - } + // Prepare file paths. + const QDir db_path(m_sqliteDatabaseFilePath); + QFile db_file(db_path.absoluteFilePath(APP_DB_SQLITE_FILE)); - // Folders are created. Create new QSQLDatabase object. - QSqlDatabase database; - database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER, connection_name); - database.setDatabaseName(db_file.fileName()); + // Check if database directory exists. + if (!db_path.exists()) { + if (!db_path.mkpath(db_path.absolutePath())) { + // Failure when create database file path. + qFatal("Directory '%s' for SQLite database file '%s' was NOT created." + "This is HUGE problem.", + qPrintable(db_path.absolutePath()), + qPrintable(db_file.symLinkTarget())); + } + } - if (!database.open()) { - qFatal("File-based SQLite database was NOT opened. Delivered error message: '%s'", - qPrintable(database.lastError().text())); - } - else { - QSqlQuery query_db(database); - query_db.setForwardOnly(true); - query_db.exec(QSL("PRAGMA encoding = \"UTF-8\"")); - query_db.exec(QSL("PRAGMA synchronous = OFF")); - query_db.exec(QSL("PRAGMA journal_mode = MEMORY")); - query_db.exec(QSL("PRAGMA page_size = 4096")); - query_db.exec(QSL("PRAGMA cache_size = 16384")); - query_db.exec(QSL("PRAGMA count_changes = OFF")); - query_db.exec(QSL("PRAGMA temp_store = MEMORY")); + // Folders are created. Create new QSQLDatabase object. + QSqlDatabase database; - // Sample query which checks for existence of tables. - if (!query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'"))) { - qWarning("Error occurred. File-based SQLite database is not initialized. Initializing now."); - QFile file_init(APP_SQL_PATH + QDir::separator() + APP_DB_SQLITE_INIT); + database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER, connection_name); + database.setDatabaseName(db_file.fileName()); - if (!file_init.open(QIODevice::ReadOnly | QIODevice::Text)) { - // Database initialization file not opened. HUGE problem. - qFatal("SQLite database initialization file '%s' from directory '%s' was not found. File-based database is uninitialized.", - APP_DB_SQLITE_INIT, - qPrintable(APP_SQL_PATH)); - } + if (!database.open()) { + qFatal("File-based SQLite database was NOT opened. Delivered error message: '%s'", + qPrintable(database.lastError().text())); + } + else { + QSqlQuery query_db(database); - const QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts); - database.transaction(); + query_db.setForwardOnly(true); + query_db.exec(QSL("PRAGMA encoding = \"UTF-8\"")); + query_db.exec(QSL("PRAGMA synchronous = OFF")); + query_db.exec(QSL("PRAGMA journal_mode = MEMORY")); + query_db.exec(QSL("PRAGMA page_size = 4096")); + query_db.exec(QSL("PRAGMA cache_size = 16384")); + query_db.exec(QSL("PRAGMA count_changes = OFF")); + query_db.exec(QSL("PRAGMA temp_store = MEMORY")); - foreach (const QString& statement, statements) { - query_db.exec(statement); + // Sample query which checks for existence of tables. + if (!query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'"))) { + qWarning("Error occurred. File-based SQLite database is not initialized. Initializing now."); + QFile file_init(APP_SQL_PATH + QDir::separator() + APP_DB_SQLITE_INIT); - if (query_db.lastError().isValid()) { - qFatal("File-based SQLite database initialization failed. Initialization script '%s' is not correct.", - APP_DB_SQLITE_INIT); - } - } + if (!file_init.open(QIODevice::ReadOnly | QIODevice::Text)) { + // Database initialization file not opened. HUGE problem. + qFatal("SQLite database initialization file '%s' from directory '%s' was not found. File-based database is uninitialized.", + APP_DB_SQLITE_INIT, + qPrintable(APP_SQL_PATH)); + } - database.commit(); - query_db.finish(); - qDebug("File-based SQLite database backend should be ready now."); - } - else { - query_db.next(); - const QString installed_db_schema = query_db.value(0).toString(); - query_db.finish(); + const QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts); + + database.transaction(); + + foreach (const QString& statement, statements) { + query_db.exec(statement); + + if (query_db.lastError().isValid()) { + qFatal("File-based SQLite database initialization failed. Initialization script '%s' is not correct.", + APP_DB_SQLITE_INIT); + } + } + + database.commit(); + query_db.finish(); + qDebug("File-based SQLite database backend should be ready now."); + } + else { + query_db.next(); + const QString installed_db_schema = query_db.value(0).toString(); + + query_db.finish(); if (installed_db_schema.toInt() < QString(APP_DB_SCHEMA_VERSION).toInt()) { - if (sqliteUpdateDatabaseSchema(database, installed_db_schema)) { - qDebug("Database schema was updated from '%s' to '%s' successully or it is already up to date.", - qPrintable(installed_db_schema), - APP_DB_SCHEMA_VERSION); - } - else { - qFatal("Database schema was not updated from '%s' to '%s' successully.", - qPrintable(installed_db_schema), - APP_DB_SCHEMA_VERSION); - } - } + if (sqliteUpdateDatabaseSchema(database, installed_db_schema)) { + qDebug("Database schema was updated from '%s' to '%s' successully or it is already up to date.", + qPrintable(installed_db_schema), + APP_DB_SCHEMA_VERSION); + } + else { + qFatal("Database schema was not updated from '%s' to '%s' successully.", + qPrintable(installed_db_schema), + APP_DB_SCHEMA_VERSION); + } + } - qDebug("File-based SQLite database connection '%s' to file '%s' seems to be established.", - qPrintable(connection_name), - qPrintable(QDir::toNativeSeparators(database.databaseName()))); - qDebug("File-based SQLite database has version '%s'.", qPrintable(installed_db_schema)); - } - } + qDebug("File-based SQLite database connection '%s' to file '%s' seems to be established.", + qPrintable(connection_name), + qPrintable(QDir::toNativeSeparators(database.databaseName()))); + qDebug("File-based SQLite database has version '%s'.", qPrintable(installed_db_schema)); + } + } - // Everything is initialized now. - m_sqliteFileBasedDatabaseinitialized = true; - return database; + // Everything is initialized now. + m_sqliteFileBasedDatabaseinitialized = true; + return database; } QString DatabaseFactory::sqliteDatabaseFilePath() const { - return m_sqliteDatabaseFilePath + QDir::separator() + APP_DB_SQLITE_FILE; + return m_sqliteDatabaseFilePath + QDir::separator() + APP_DB_SQLITE_FILE; } bool DatabaseFactory::sqliteUpdateDatabaseSchema(QSqlDatabase database, const QString& source_db_schema_version) { - int working_version = QString(source_db_schema_version).remove('.').toInt(); - const int current_version = QString(APP_DB_SCHEMA_VERSION).remove('.').toInt(); + int working_version = QString(source_db_schema_version).remove('.').toInt(); + const int current_version = QString(APP_DB_SCHEMA_VERSION).remove('.').toInt(); - // Now, it would be good to create backup of SQLite DB file. - if (IOFactory::copyFile(sqliteDatabaseFilePath(), sqliteDatabaseFilePath() + ".bak")) { - qDebug("Creating backup of SQLite DB file."); - } - else { - qFatal("Creation of backup SQLite DB file failed."); - } + // Now, it would be good to create backup of SQLite DB file. + if (IOFactory::copyFile(sqliteDatabaseFilePath(), sqliteDatabaseFilePath() + ".bak")) { + qDebug("Creating backup of SQLite DB file."); + } + else { + qFatal("Creation of backup SQLite DB file failed."); + } - while (working_version != current_version) { - const QString update_file_name = QString(APP_SQL_PATH) + QDir::separator() + - QString(APP_DB_UPDATE_FILE_PATTERN).arg(QSL("sqlite"), - QString::number(working_version), - QString::number(working_version + 1)); + while (working_version != current_version) { + const QString update_file_name = QString(APP_SQL_PATH) + QDir::separator() + + QString(APP_DB_UPDATE_FILE_PATTERN).arg(QSL("sqlite"), + QString::number(working_version), + QString::number(working_version + 1)); - if (!QFile::exists(update_file_name)) { - qFatal("Updating of database schema failed. File '%s' does not exist.", qPrintable(QDir::toNativeSeparators(update_file_name))); - } + if (!QFile::exists(update_file_name)) { + qFatal("Updating of database schema failed. File '%s' does not exist.", qPrintable(QDir::toNativeSeparators(update_file_name))); + } - QFile update_file_handle(update_file_name); + QFile update_file_handle(update_file_name); - if (!update_file_handle.open(QIODevice::Text | QIODevice::ReadOnly | QIODevice::Unbuffered)) { - qFatal("Updating of database schema failed. File '%s' cannot be opened.", qPrintable(QDir::toNativeSeparators(update_file_name))); - } + if (!update_file_handle.open(QIODevice::Text | QIODevice::ReadOnly | QIODevice::Unbuffered)) { + qFatal("Updating of database schema failed. File '%s' cannot be opened.", qPrintable(QDir::toNativeSeparators(update_file_name))); + } - const QStringList statements = QString(update_file_handle.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts); + const QStringList statements = QString(update_file_handle.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts); - foreach (const QString& statement, statements) { - QSqlQuery query = database.exec(statement); + foreach (const QString& statement, statements) { + QSqlQuery query = database.exec(statement); - if (query.lastError().isValid()) { - qFatal("Query for updating database schema failed: '%s'.", qPrintable(query.lastError().text())); - } - } + if (query.lastError().isValid()) { + qFatal("Query for updating database schema failed: '%s'.", qPrintable(query.lastError().text())); + } + } - // Increment the version. - qDebug("Updating database schema: '%d' -> '%d'.", working_version, working_version + 1); - working_version++; - } + // Increment the version. + qDebug("Updating database schema: '%d' -> '%d'.", working_version, working_version + 1); + working_version++; + } - return true; + return true; } bool DatabaseFactory::mysqlUpdateDatabaseSchema(QSqlDatabase database, const QString& source_db_schema_version, const QString& db_name) { - int working_version = QString(source_db_schema_version).remove('.').toInt(); - const int current_version = QString(APP_DB_SCHEMA_VERSION).remove('.').toInt(); + int working_version = QString(source_db_schema_version).remove('.').toInt(); + const int current_version = QString(APP_DB_SCHEMA_VERSION).remove('.').toInt(); - while (working_version != current_version) { - const QString update_file_name = QString(APP_SQL_PATH) + QDir::separator() + - QString(APP_DB_UPDATE_FILE_PATTERN).arg(QSL("mysql"), - QString::number(working_version), - QString::number(working_version + 1)); + while (working_version != current_version) { + const QString update_file_name = QString(APP_SQL_PATH) + QDir::separator() + + QString(APP_DB_UPDATE_FILE_PATTERN).arg(QSL("mysql"), + QString::number(working_version), + QString::number(working_version + 1)); - if (!QFile::exists(update_file_name)) { - qFatal("Updating of database schema failed. File '%s' does not exist.", qPrintable(QDir::toNativeSeparators(update_file_name))); - } + if (!QFile::exists(update_file_name)) { + qFatal("Updating of database schema failed. File '%s' does not exist.", qPrintable(QDir::toNativeSeparators(update_file_name))); + } - QFile update_file_handle(update_file_name); + QFile update_file_handle(update_file_name); - if (!update_file_handle.open(QIODevice::Text | QIODevice::ReadOnly | QIODevice::Unbuffered)) { - qFatal("Updating of database schema failed. File '%s' cannot be opened.", qPrintable(QDir::toNativeSeparators(update_file_name))); - } + if (!update_file_handle.open(QIODevice::Text | QIODevice::ReadOnly | QIODevice::Unbuffered)) { + qFatal("Updating of database schema failed. File '%s' cannot be opened.", qPrintable(QDir::toNativeSeparators(update_file_name))); + } - QStringList statements = QString(update_file_handle.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts); + QStringList statements = QString(update_file_handle.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts); - foreach (QString statement, statements) { - QSqlQuery query = database.exec(statement.replace(APP_DB_NAME_PLACEHOLDER, db_name)); + foreach (QString statement, statements) { + QSqlQuery query = database.exec(statement.replace(APP_DB_NAME_PLACEHOLDER, db_name)); - if (query.lastError().isValid()) { - qFatal("Query for updating database schema failed: '%s'.", qPrintable(query.lastError().text())); - } - } + if (query.lastError().isValid()) { + qFatal("Query for updating database schema failed: '%s'.", qPrintable(query.lastError().text())); + } + } - // Increment the version. - qDebug("Updating database schema: '%d' -> '%d'.", working_version, working_version + 1); - working_version++; - } + // Increment the version. + qDebug("Updating database schema: '%d' -> '%d'.", working_version, working_version + 1); + working_version++; + } - return true; + return true; } QSqlDatabase DatabaseFactory::connection(const QString& connection_name, DesiredType desired_type) { - switch (m_activeDatabaseDriver) { - case MYSQL: - return mysqlConnection(connection_name); + switch (m_activeDatabaseDriver) { + case MYSQL: + return mysqlConnection(connection_name); - case SQLITE: - case SQLITE_MEMORY: - default: - return sqliteConnection(connection_name, desired_type); - } + case SQLITE: + case SQLITE_MEMORY: + default: + return sqliteConnection(connection_name, desired_type); + } } QString DatabaseFactory::humanDriverName(DatabaseFactory::UsedDriver driver) const { - switch (driver) { - case MYSQL: - return tr("MySQL/MariaDB (dedicated database)"); + switch (driver) { + case MYSQL: + return tr("MySQL/MariaDB (dedicated database)"); - case SQLITE: - case SQLITE_MEMORY: - default: - return tr("SQLite (embedded database)"); - } + case SQLITE: + case SQLITE_MEMORY: + default: + return tr("SQLite (embedded database)"); + } } QString DatabaseFactory::humanDriverName(const QString& driver_code) const { - if (driver_code == APP_DB_SQLITE_DRIVER) { - return humanDriverName(SQLITE); - } - else if (driver_code == APP_DB_MYSQL_DRIVER) { - return humanDriverName(MYSQL); - } - else { - return humanDriverName(SQLITE); - } + if (driver_code == APP_DB_SQLITE_DRIVER) { + return humanDriverName(SQLITE); + } + else if (driver_code == APP_DB_MYSQL_DRIVER) { + return humanDriverName(MYSQL); + } + else { + return humanDriverName(SQLITE); + } } void DatabaseFactory::removeConnection(const QString& connection_name) { - qDebug("Removing database connection '%s'.", qPrintable(connection_name)); - QSqlDatabase::removeDatabase(connection_name); + qDebug("Removing database connection '%s'.", qPrintable(connection_name)); + QSqlDatabase::removeDatabase(connection_name); } QString DatabaseFactory::obtainBeginTransactionSql() const { - if (m_activeDatabaseDriver == DatabaseFactory::SQLITE || m_activeDatabaseDriver == DatabaseFactory::SQLITE_MEMORY) { - return QSL("BEGIN IMMEDIATE TRANSACTION;"); - } - else { - return QSL("START TRANSACTION;"); - } + if (m_activeDatabaseDriver == DatabaseFactory::SQLITE || m_activeDatabaseDriver == DatabaseFactory::SQLITE_MEMORY) { + return QSL("BEGIN IMMEDIATE TRANSACTION;"); + } + else { + return QSL("START TRANSACTION;"); + } } void DatabaseFactory::sqliteSaveMemoryDatabase() { - qDebug("Saving in-memory working database back to persistent file-based storage."); - QSqlDatabase database = sqliteConnection(objectName(), StrictlyInMemory); - QSqlDatabase file_database = sqliteConnection(objectName(), StrictlyFileBased); - QSqlQuery copy_contents(database); - // Attach database. - copy_contents.exec(QString(QSL("ATTACH DATABASE '%1' AS 'storage';")).arg(file_database.databaseName())); - // Copy all stuff. - QStringList tables; + qDebug("Saving in-memory working database back to persistent file-based storage."); + QSqlDatabase database = sqliteConnection(objectName(), StrictlyInMemory); + QSqlDatabase file_database = sqliteConnection(objectName(), StrictlyFileBased); + QSqlQuery copy_contents(database); - if (copy_contents.exec(QSL("SELECT name FROM storage.sqlite_master WHERE type='table';"))) { - while (copy_contents.next()) { - tables.append(copy_contents.value(0).toString()); - } - } - else { - qFatal("Cannot obtain list of table names from file-base SQLite database."); - } + // Attach database. + copy_contents.exec(QString(QSL("ATTACH DATABASE '%1' AS 'storage';")).arg(file_database.databaseName())); - foreach (const QString& table, tables) { - copy_contents.exec(QString(QSL("DELETE FROM storage.%1;")).arg(table)); - copy_contents.exec(QString(QSL("INSERT INTO storage.%1 SELECT * FROM main.%1;")).arg(table)); - } + // Copy all stuff. + QStringList tables; - // Detach database and finish. - copy_contents.exec(QSL("DETACH 'storage'")); - copy_contents.finish(); + if (copy_contents.exec(QSL("SELECT name FROM storage.sqlite_master WHERE type='table';"))) { + while (copy_contents.next()) { + tables.append(copy_contents.value(0).toString()); + } + } + else { + qFatal("Cannot obtain list of table names from file-base SQLite database."); + } + + foreach (const QString& table, tables) { + copy_contents.exec(QString(QSL("DELETE FROM storage.%1;")).arg(table)); + copy_contents.exec(QString(QSL("INSERT INTO storage.%1 SELECT * FROM main.%1;")).arg(table)); + } + + // Detach database and finish. + copy_contents.exec(QSL("DETACH 'storage'")); + copy_contents.finish(); } void DatabaseFactory::determineDriver() { - const QString db_driver = qApp->settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString(); + const QString db_driver = qApp->settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString(); - if (db_driver == APP_DB_MYSQL_DRIVER && QSqlDatabase::isDriverAvailable(APP_DB_SQLITE_DRIVER)) { - // User wants to use MySQL and MySQL is actually available. Use it. - m_activeDatabaseDriver = MYSQL; - qDebug("Working database source was as MySQL database."); - } - else { - // User wants to use SQLite, which is always available. Check if file-based - // or in-memory database will be used. - if (qApp->settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool()) { - // Use in-memory SQLite database. - m_activeDatabaseDriver = SQLITE_MEMORY; - qDebug("Working database source was determined as SQLite in-memory database."); - } - else { - // Use strictly file-base SQLite database. - m_activeDatabaseDriver = SQLITE; - qDebug("Working database source was determined as SQLite file-based database."); - } + if (db_driver == APP_DB_MYSQL_DRIVER && QSqlDatabase::isDriverAvailable(APP_DB_SQLITE_DRIVER)) { + // User wants to use MySQL and MySQL is actually available. Use it. + m_activeDatabaseDriver = MYSQL; + qDebug("Working database source was as MySQL database."); + } + else { + // User wants to use SQLite, which is always available. Check if file-based + // or in-memory database will be used. + if (qApp->settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool()) { + // Use in-memory SQLite database. + m_activeDatabaseDriver = SQLITE_MEMORY; + qDebug("Working database source was determined as SQLite in-memory database."); + } + else { + // Use strictly file-base SQLite database. + m_activeDatabaseDriver = SQLITE; + qDebug("Working database source was determined as SQLite file-based database."); + } - sqliteAssemblyDatabaseFilePath(); - } + sqliteAssemblyDatabaseFilePath(); + } } DatabaseFactory::UsedDriver DatabaseFactory::activeDatabaseDriver() const { - return m_activeDatabaseDriver; + return m_activeDatabaseDriver; } QSqlDatabase DatabaseFactory::mysqlConnection(const QString& connection_name) { - if (!m_mysqlDatabaseInitialized) { - // Return initialized database. - return mysqlInitializeDatabase(connection_name); - } - else { - QSqlDatabase database; + if (!m_mysqlDatabaseInitialized) { + // Return initialized database. + return mysqlInitializeDatabase(connection_name); + } + else { + QSqlDatabase database; - if (QSqlDatabase::contains(connection_name)) { - qDebug("MySQL connection '%s' is already active.", qPrintable(connection_name)); - // This database connection was added previously, no need to - // setup its properties. - database = QSqlDatabase::database(connection_name); - } - else { - // Database connection with this name does not exist - // yet, add it and set it up. - database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, connection_name); - database.setHostName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString()); - database.setPort(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt()); - database.setUserName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString()); - database.setPassword(TextFactory::decrypt(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString())); - database.setDatabaseName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString()); - } + if (QSqlDatabase::contains(connection_name)) { + qDebug("MySQL connection '%s' is already active.", qPrintable(connection_name)); - if (!database.isOpen() && !database.open()) { - qFatal("MySQL database was NOT opened. Delivered error message: '%s'.", - qPrintable(database.lastError().text())); - } - else { - qDebug("MySQL database connection '%s' to file '%s' seems to be established.", - qPrintable(connection_name), - qPrintable(QDir::toNativeSeparators(database.databaseName()))); - } + // This database connection was added previously, no need to + // setup its properties. + database = QSqlDatabase::database(connection_name); + } + else { + // Database connection with this name does not exist + // yet, add it and set it up. + database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, connection_name); + database.setHostName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString()); + database.setPort(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt()); + database.setUserName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString()); + database.setPassword(TextFactory::decrypt(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString())); + database.setDatabaseName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString()); + } - return database; - } + if (!database.isOpen() && !database.open()) { + qFatal("MySQL database was NOT opened. Delivered error message: '%s'.", + qPrintable(database.lastError().text())); + } + else { + qDebug("MySQL database connection '%s' to file '%s' seems to be established.", + qPrintable(connection_name), + qPrintable(QDir::toNativeSeparators(database.databaseName()))); + } + + return database; + } } QSqlDatabase DatabaseFactory::mysqlInitializeDatabase(const QString& connection_name) { - // Folders are created. Create new QSQLDatabase object. - QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, connection_name); - const QString database_name = qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString(); - database.setHostName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString()); - database.setPort(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt()); - database.setUserName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString()); - database.setPassword(TextFactory::decrypt(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString())); + // Folders are created. Create new QSQLDatabase object. + QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, connection_name); + const QString database_name = qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString(); - if (!database.open()) { - qCritical("MySQL database was NOT opened. Delivered error message: '%s'", qPrintable(database.lastError().text())); - // Now, we will display error warning and return SQLite connection. - // Also, we set the SQLite driver as active one. - qApp->settings()->setValue(GROUP(Database), Database::ActiveDriver, APP_DB_SQLITE_DRIVER); - determineDriver(); - MessageBox::show(nullptr, QMessageBox::Critical, tr("MySQL database not available"), - tr("%1 cannot use MySQL storage, it is not available. %1 is now switching to SQLite database. Start your MySQL server " - "and make adjustments in application settings.").arg(APP_NAME)); - return connection(objectName(), FromSettings); - } - else { - QSqlQuery query_db(database); - query_db.setForwardOnly(true); + database.setHostName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString()); + database.setPort(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt()); + database.setUserName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString()); + database.setPassword(TextFactory::decrypt(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString())); - if (!query_db.exec(QString("USE %1").arg(database_name)) - || !query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'"))) { - // If no "rssguard" database exists or schema version is wrong, then initialize it. - qWarning("Error occurred. MySQL database is not initialized. Initializing now."); - QFile file_init(APP_SQL_PATH + QDir::separator() + APP_DB_MYSQL_INIT); + if (!database.open()) { + qCritical("MySQL database was NOT opened. Delivered error message: '%s'", qPrintable(database.lastError().text())); - if (!file_init.open(QIODevice::ReadOnly | QIODevice::Text)) { - // Database initialization file not opened. HUGE problem. - qFatal("MySQL database initialization file '%s' from directory '%s' was not found. File-based database is uninitialized.", - APP_DB_MYSQL_INIT, - qPrintable(APP_SQL_PATH)); - } + // Now, we will display error warning and return SQLite connection. + // Also, we set the SQLite driver as active one. + qApp->settings()->setValue(GROUP(Database), Database::ActiveDriver, APP_DB_SQLITE_DRIVER); + determineDriver(); + MessageBox::show(nullptr, QMessageBox::Critical, tr("MySQL database not available"), + tr("%1 cannot use MySQL storage, it is not available. %1 is now switching to SQLite database. Start your MySQL server " + "and make adjustments in application settings.").arg(APP_NAME)); + return connection(objectName(), FromSettings); + } + else { + QSqlQuery query_db(database); - const QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts); - database.transaction(); + query_db.setForwardOnly(true); - foreach (QString statement, statements) { - // Assign real database name and run the query. - query_db.exec(statement.replace(APP_DB_NAME_PLACEHOLDER, database_name)); + if (!query_db.exec(QString("USE %1").arg(database_name)) + || !query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'"))) { + // If no "rssguard" database exists or schema version is wrong, then initialize it. + qWarning("Error occurred. MySQL database is not initialized. Initializing now."); + QFile file_init(APP_SQL_PATH + QDir::separator() + APP_DB_MYSQL_INIT); - if (query_db.lastError().isValid()) { - qFatal("MySQL database initialization failed. Initialization script '%s' is not correct. Error : '%s'.", - APP_DB_MYSQL_INIT, qPrintable(query_db.lastError().databaseText())); - } - } + if (!file_init.open(QIODevice::ReadOnly | QIODevice::Text)) { + // Database initialization file not opened. HUGE problem. + qFatal("MySQL database initialization file '%s' from directory '%s' was not found. File-based database is uninitialized.", + APP_DB_MYSQL_INIT, + qPrintable(APP_SQL_PATH)); + } - database.commit(); - qDebug("MySQL database backend should be ready now."); - } - else { - // Database was previously initialized. Now just check the schema version. - query_db.next(); - const QString installed_db_schema = query_db.value(0).toString(); + const QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT, QString::SkipEmptyParts); - if (installed_db_schema < APP_DB_SCHEMA_VERSION) { - if (mysqlUpdateDatabaseSchema(database, installed_db_schema, database_name)) { - qDebug("Database schema was updated from '%s' to '%s' successully or it is already up to date.", - qPrintable(installed_db_schema), - APP_DB_SCHEMA_VERSION); - } - else { - qFatal("Database schema was not updated from '%s' to '%s' successully.", - qPrintable(installed_db_schema), - APP_DB_SCHEMA_VERSION); - } - } - } + database.transaction(); - query_db.finish(); - } + foreach (QString statement, statements) { + // Assign real database name and run the query. + query_db.exec(statement.replace(APP_DB_NAME_PLACEHOLDER, database_name)); - // Everything is initialized now. - m_mysqlDatabaseInitialized = true; - return database; + if (query_db.lastError().isValid()) { + qFatal("MySQL database initialization failed. Initialization script '%s' is not correct. Error : '%s'.", + APP_DB_MYSQL_INIT, qPrintable(query_db.lastError().databaseText())); + } + } + + database.commit(); + qDebug("MySQL database backend should be ready now."); + } + else { + // Database was previously initialized. Now just check the schema version. + query_db.next(); + const QString installed_db_schema = query_db.value(0).toString(); + + if (installed_db_schema < APP_DB_SCHEMA_VERSION) { + if (mysqlUpdateDatabaseSchema(database, installed_db_schema, database_name)) { + qDebug("Database schema was updated from '%s' to '%s' successully or it is already up to date.", + qPrintable(installed_db_schema), + APP_DB_SCHEMA_VERSION); + } + else { + qFatal("Database schema was not updated from '%s' to '%s' successully.", + qPrintable(installed_db_schema), + APP_DB_SCHEMA_VERSION); + } + } + } + + query_db.finish(); + } + + // Everything is initialized now. + m_mysqlDatabaseInitialized = true; + return database; } bool DatabaseFactory::mysqlVacuumDatabase() { - QSqlDatabase database = mysqlConnection(objectName()); - QSqlQuery query_vacuum(database); - return query_vacuum.exec(QSL("OPTIMIZE TABLE rssguard.feeds;")) && query_vacuum.exec(QSL("OPTIMIZE TABLE rssguard.messages;")); + QSqlDatabase database = mysqlConnection(objectName()); + QSqlQuery query_vacuum(database); + + return query_vacuum.exec(QSL("OPTIMIZE TABLE rssguard.feeds;")) && query_vacuum.exec(QSL("OPTIMIZE TABLE rssguard.messages;")); } QSqlDatabase DatabaseFactory::sqliteConnection(const QString& connection_name, DatabaseFactory::DesiredType desired_type) { - if (desired_type == DatabaseFactory::StrictlyInMemory || - (desired_type == DatabaseFactory::FromSettings && m_activeDatabaseDriver == SQLITE_MEMORY)) { - // We request in-memory database (either user explicitly - // needs in-memory database or it was enabled in the settings). - if (!m_sqliteInMemoryDatabaseInitialized) { - // It is not initialized yet. - return sqliteInitializeInMemoryDatabase(); - } - else { - QSqlDatabase database = QSqlDatabase::database(); - database.setDatabaseName(QSL(":memory:")); + if (desired_type == DatabaseFactory::StrictlyInMemory || + (desired_type == DatabaseFactory::FromSettings && m_activeDatabaseDriver == SQLITE_MEMORY)) { + // We request in-memory database (either user explicitly + // needs in-memory database or it was enabled in the settings). + if (!m_sqliteInMemoryDatabaseInitialized) { + // It is not initialized yet. + return sqliteInitializeInMemoryDatabase(); + } + else { + QSqlDatabase database = QSqlDatabase::database(); - if (!database.isOpen() && !database.open()) { - qFatal("In-memory SQLite database was NOT opened. Delivered error message: '%s'.", - qPrintable(database.lastError().text())); - } - else { - qDebug("In-memory SQLite database connection seems to be established."); - } + database.setDatabaseName(QSL(":memory:")); - return database; - } - } - else { - // We request file-based database. - if (!m_sqliteFileBasedDatabaseinitialized) { - // File-based database is not yet initialised. - return sqliteInitializeFileBasedDatabase(connection_name); - } - else { - QSqlDatabase database; + if (!database.isOpen() && !database.open()) { + qFatal("In-memory SQLite database was NOT opened. Delivered error message: '%s'.", + qPrintable(database.lastError().text())); + } + else { + qDebug("In-memory SQLite database connection seems to be established."); + } - if (QSqlDatabase::contains(connection_name)) { - qDebug("SQLite connection '%s' is already active.", qPrintable(connection_name)); - // This database connection was added previously, no need to - // setup its properties. - database = QSqlDatabase::database(connection_name); - } - else { - // Database connection with this name does not exist - // yet, add it and set it up. - database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER, connection_name); - const QDir db_path(m_sqliteDatabaseFilePath); - QFile db_file(db_path.absoluteFilePath(APP_DB_SQLITE_FILE)); - // Setup database file path. - database.setDatabaseName(db_file.fileName()); - } + return database; + } + } + else { + // We request file-based database. + if (!m_sqliteFileBasedDatabaseinitialized) { + // File-based database is not yet initialised. + return sqliteInitializeFileBasedDatabase(connection_name); + } + else { + QSqlDatabase database; - if (!database.isOpen() && !database.open()) { - qFatal("File-based SQLite database was NOT opened. Delivered error message: '%s'.", - qPrintable(database.lastError().text())); - } - else { - qDebug("File-based SQLite database connection '%s' to file '%s' seems to be established.", - qPrintable(connection_name), - qPrintable(QDir::toNativeSeparators(database.databaseName()))); - } + if (QSqlDatabase::contains(connection_name)) { + qDebug("SQLite connection '%s' is already active.", qPrintable(connection_name)); - return database; - } - } + // This database connection was added previously, no need to + // setup its properties. + database = QSqlDatabase::database(connection_name); + } + else { + // Database connection with this name does not exist + // yet, add it and set it up. + database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER, connection_name); + const QDir db_path(m_sqliteDatabaseFilePath); + QFile db_file(db_path.absoluteFilePath(APP_DB_SQLITE_FILE)); + + // Setup database file path. + database.setDatabaseName(db_file.fileName()); + } + + if (!database.isOpen() && !database.open()) { + qFatal("File-based SQLite database was NOT opened. Delivered error message: '%s'.", + qPrintable(database.lastError().text())); + } + else { + qDebug("File-based SQLite database connection '%s' to file '%s' seems to be established.", + qPrintable(connection_name), + qPrintable(QDir::toNativeSeparators(database.databaseName()))); + } + + return database; + } + } } bool DatabaseFactory::sqliteVacuumDatabase() { - QSqlDatabase database; + QSqlDatabase database; - if (m_activeDatabaseDriver == SQLITE) { - database = sqliteConnection(objectName(), StrictlyFileBased); - } - else if (m_activeDatabaseDriver == SQLITE_MEMORY) { - sqliteSaveMemoryDatabase(); - database = sqliteConnection(objectName(), StrictlyFileBased); - } - else { - return false; - } + if (m_activeDatabaseDriver == SQLITE) { + database = sqliteConnection(objectName(), StrictlyFileBased); + } + else if (m_activeDatabaseDriver == SQLITE_MEMORY) { + sqliteSaveMemoryDatabase(); + database = sqliteConnection(objectName(), StrictlyFileBased); + } + else { + return false; + } - QSqlQuery query_vacuum(database); - return query_vacuum.exec(QSL("VACUUM")); + QSqlQuery query_vacuum(database); + + return query_vacuum.exec(QSL("VACUUM")); } void DatabaseFactory::saveDatabase() { - switch (m_activeDatabaseDriver) { - case SQLITE_MEMORY: - sqliteSaveMemoryDatabase(); - break; + switch (m_activeDatabaseDriver) { + case SQLITE_MEMORY: + sqliteSaveMemoryDatabase(); + break; - default: - break; - } + default: + break; + } } bool DatabaseFactory::vacuumDatabase() { - switch (m_activeDatabaseDriver) { - case SQLITE_MEMORY: - case SQLITE: - return sqliteVacuumDatabase(); + switch (m_activeDatabaseDriver) { + case SQLITE_MEMORY: + case SQLITE: + return sqliteVacuumDatabase(); - case MYSQL: - return mysqlVacuumDatabase(); + case MYSQL: + return mysqlVacuumDatabase(); - default: - return false; - } + default: + return false; + } } diff --git a/src/miscellaneous/databasefactory.h b/src/miscellaneous/databasefactory.h index 225e7ab9f..4f32a9ba0 100755 --- a/src/miscellaneous/databasefactory.h +++ b/src/miscellaneous/databasefactory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,161 +22,162 @@ #include #include - class DatabaseFactory : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Describes available typos of database backend. - enum UsedDriver { - SQLITE, - SQLITE_MEMORY, - MYSQL - }; + public: - // Describes what type of database user wants. - enum DesiredType { - StrictlyFileBased, - StrictlyInMemory, - FromSettings - }; + // Describes available typos of database backend. + enum UsedDriver { + SQLITE, + SQLITE_MEMORY, + MYSQL + }; - // Describes possible MySQL-specific errors. - enum MySQLError { - MySQLOk = 0, - MySQLUnknownError = 1, - MySQLAccessDenied = 1045, - MySQLUnknownDatabase = 1049, - MySQLConnectionError = 2002, - MySQLCantConnect = 2003, - MySQLUnknownHost = 2005 - }; + // Describes what type of database user wants. + enum DesiredType { + StrictlyFileBased, + StrictlyInMemory, + FromSettings + }; - // - // GENERAL stuff. - // + // Describes possible MySQL-specific errors. + enum MySQLError { + MySQLOk = 0, + MySQLUnknownError = 1, + MySQLAccessDenied = 1045, + MySQLUnknownDatabase = 1049, + MySQLConnectionError = 2002, + MySQLCantConnect = 2003, + MySQLUnknownHost = 2005 + }; - // Constructor. - explicit DatabaseFactory(QObject* parent = 0); + // + // GENERAL stuff. + // - // Destructor. - virtual ~DatabaseFactory(); + // Constructor. + explicit DatabaseFactory(QObject* parent = 0); - // Returns size of DB file. - qint64 getDatabaseFileSize() const; + // Destructor. + virtual ~DatabaseFactory(); - // Returns size of data contained in the DB file. - qint64 getDatabaseDataSize() const; + // Returns size of DB file. + qint64 getDatabaseFileSize() const; - // If in-memory is true, then :memory: database is returned - // In-memory database is DEFAULT database. - // NOTE: This always returns OPENED database. - QSqlDatabase connection(const QString& connection_name, DesiredType desired_type = FromSettings); + // Returns size of data contained in the DB file. + qint64 getDatabaseDataSize() const; - QString humanDriverName(UsedDriver driver) const; - QString humanDriverName(const QString& driver_code) const; + // If in-memory is true, then :memory: database is returned + // In-memory database is DEFAULT database. + // NOTE: This always returns OPENED database. + QSqlDatabase connection(const QString& connection_name, DesiredType desired_type = FromSettings); - // Removes connection. - void removeConnection(const QString& connection_name = QString()); + QString humanDriverName(UsedDriver driver) const; + QString humanDriverName(const QString& driver_code) const; - QString obtainBeginTransactionSql() const; + // Removes connection. + void removeConnection(const QString& connection_name = QString()); - // Performs any needed database-related operation to be done - // to gracefully exit the application. - void saveDatabase(); + QString obtainBeginTransactionSql() const; - // Performs cleanup of the database. - bool vacuumDatabase(); + // Performs any needed database-related operation to be done + // to gracefully exit the application. + void saveDatabase(); - // Returns identification of currently active database driver. - UsedDriver activeDatabaseDriver() const; + // Performs cleanup of the database. + bool vacuumDatabase(); - // Copies selected backup database (file) to active database path. - bool initiateRestoration(const QString& database_backup_file_path); + // Returns identification of currently active database driver. + UsedDriver activeDatabaseDriver() const; - // Finishes restoration from backup file. - void finishRestoration(); + // Copies selected backup database (file) to active database path. + bool initiateRestoration(const QString& database_backup_file_path); - // - // SQLITE stuff. - // - QString sqliteDatabaseFilePath() const; + // Finishes restoration from backup file. + void finishRestoration(); - // - // MySQL stuff. - // + // + // SQLITE stuff. + // + QString sqliteDatabaseFilePath() const; - // Tests if database connection with given data - // can be established and returns 0 if it can. - // Otherwise returns MySQL-specific error code. - MySQLError mysqlTestConnection(const QString& hostname, int port, const QString& w_database, - const QString& username, const QString& password); + // + // MySQL stuff. + // - // Interprets MySQL error code. - QString mysqlInterpretErrorCode(MySQLError error_code) const; + // Tests if database connection with given data + // can be established and returns 0 if it can. + // Otherwise returns MySQL-specific error code. + MySQLError mysqlTestConnection(const QString& hostname, int port, const QString& w_database, + const QString& username, const QString& password); - private: - // - // GENERAL stuff. - // + // Interprets MySQL error code. + QString mysqlInterpretErrorCode(MySQLError error_code) const; - // Decides which database backend will be used in this - // application session. - void determineDriver(); + private: - // Holds the type of currently activated database backend. - UsedDriver m_activeDatabaseDriver; + // + // GENERAL stuff. + // - // - // MYSQL stuff. - // + // Decides which database backend will be used in this + // application session. + void determineDriver(); - // Returns (always OPENED) MySQL database connection. - QSqlDatabase mysqlConnection(const QString& connection_name); + // Holds the type of currently activated database backend. + UsedDriver m_activeDatabaseDriver; - // Initializes MySQL database. - QSqlDatabase mysqlInitializeDatabase(const QString& connection_name); + // + // MYSQL stuff. + // - // Updates database schema. - bool mysqlUpdateDatabaseSchema(QSqlDatabase database, const QString& source_db_schema_version, const QString& db_name); + // Returns (always OPENED) MySQL database connection. + QSqlDatabase mysqlConnection(const QString& connection_name); - // Runs "VACUUM" on the database. - bool mysqlVacuumDatabase(); + // Initializes MySQL database. + QSqlDatabase mysqlInitializeDatabase(const QString& connection_name); - // True if MySQL database is fully initialized for use, - // otherwise false. - bool m_mysqlDatabaseInitialized; + // Updates database schema. + bool mysqlUpdateDatabaseSchema(QSqlDatabase database, const QString& source_db_schema_version, const QString& db_name); - // - // SQLITE stuff. - // + // Runs "VACUUM" on the database. + bool mysqlVacuumDatabase(); - QSqlDatabase sqliteConnection(const QString& connection_name, DesiredType desired_type); + // True if MySQL database is fully initialized for use, + // otherwise false. + bool m_mysqlDatabaseInitialized; - // Runs "VACUUM" on the database. - bool sqliteVacuumDatabase(); + // + // SQLITE stuff. + // - // Performs saving of items from in-memory database - // to file-based database. - void sqliteSaveMemoryDatabase(); + QSqlDatabase sqliteConnection(const QString& connection_name, DesiredType desired_type); - // Assemblies database file path. - void sqliteAssemblyDatabaseFilePath(); + // Runs "VACUUM" on the database. + bool sqliteVacuumDatabase(); - // Updates database schema. - bool sqliteUpdateDatabaseSchema(QSqlDatabase database, const QString& source_db_schema_version); + // Performs saving of items from in-memory database + // to file-based database. + void sqliteSaveMemoryDatabase(); - // Creates new connection, initializes database and - // returns opened connections. - QSqlDatabase sqliteInitializeInMemoryDatabase(); - QSqlDatabase sqliteInitializeFileBasedDatabase(const QString& connection_name); + // Assemblies database file path. + void sqliteAssemblyDatabaseFilePath(); - // Path to database file. - QString m_sqliteDatabaseFilePath; + // Updates database schema. + bool sqliteUpdateDatabaseSchema(QSqlDatabase database, const QString& source_db_schema_version); - // Is database file initialized? - bool m_sqliteFileBasedDatabaseinitialized; - bool m_sqliteInMemoryDatabaseInitialized; + // Creates new connection, initializes database and + // returns opened connections. + QSqlDatabase sqliteInitializeInMemoryDatabase(); + QSqlDatabase sqliteInitializeFileBasedDatabase(const QString& connection_name); + + // Path to database file. + QString m_sqliteDatabaseFilePath; + + // Is database file initialized? + bool m_sqliteFileBasedDatabaseinitialized; + bool m_sqliteInMemoryDatabaseInitialized; }; #endif // DATABASEFACTORY_H diff --git a/src/miscellaneous/databasequeries.cpp b/src/miscellaneous/databasequeries.cpp index f33646fab..592959841 100755 --- a/src/miscellaneous/databasequeries.cpp +++ b/src/miscellaneous/databasequeries.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,399 +18,425 @@ #include "miscellaneous/databasequeries.h" -#include "services/abstract/category.h" -#include "services/owncloud/owncloudserviceroot.h" -#include "services/owncloud/owncloudcategory.h" -#include "services/owncloud/owncloudfeed.h" -#include "services/owncloud/network/owncloudnetworkfactory.h" -#include "services/standard/standardserviceroot.h" -#include "services/standard/standardcategory.h" -#include "services/standard/standardfeed.h" -#include "services/tt-rss/ttrssserviceroot.h" -#include "services/tt-rss/ttrsscategory.h" -#include "services/tt-rss/ttrssfeed.h" -#include "services/tt-rss/network/ttrssnetworkfactory.h" -#include "miscellaneous/textfactory.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" +#include "miscellaneous/textfactory.h" +#include "services/abstract/category.h" +#include "services/owncloud/network/owncloudnetworkfactory.h" +#include "services/owncloud/owncloudcategory.h" +#include "services/owncloud/owncloudfeed.h" +#include "services/owncloud/owncloudserviceroot.h" +#include "services/standard/standardcategory.h" +#include "services/standard/standardfeed.h" +#include "services/standard/standardserviceroot.h" +#include "services/tt-rss/network/ttrssnetworkfactory.h" +#include "services/tt-rss/ttrsscategory.h" +#include "services/tt-rss/ttrssfeed.h" +#include "services/tt-rss/ttrssserviceroot.h" -#include -#include #include - +#include +#include bool DatabaseQueries::markMessagesReadUnread(QSqlDatabase db, const QStringList& ids, RootItem::ReadStatus read) { - QSqlQuery q(db); - q.setForwardOnly(true); - return q.exec(QString(QSL("UPDATE Messages SET is_read = %2 WHERE id IN (%1);")) - .arg(ids.join(QSL(", ")), read == RootItem::Read ? QSL("1") : QSL("0"))); + QSqlQuery q(db); + + q.setForwardOnly(true); + return q.exec(QString(QSL("UPDATE Messages SET is_read = %2 WHERE id IN (%1);")) + .arg(ids.join(QSL(", ")), read == RootItem::Read ? QSL("1") : QSL("0"))); } bool DatabaseQueries::markMessageImportant(QSqlDatabase db, int id, RootItem::Importance importance) { - QSqlQuery q(db); - q.setForwardOnly(true); + QSqlQuery q(db); - if (!q.prepare(QSL("UPDATE Messages SET is_important = :important WHERE id = :id;"))) { - qWarning("Query preparation failed for message importance switch."); - return false; - } + q.setForwardOnly(true); - q.bindValue(QSL(":id"), id); - q.bindValue(QSL(":important"), (int) importance); - // Commit changes. - return q.exec(); + if (!q.prepare(QSL("UPDATE Messages SET is_important = :important WHERE id = :id;"))) { + qWarning("Query preparation failed for message importance switch."); + return false; + } + + q.bindValue(QSL(":id"), id); + q.bindValue(QSL(":important"), (int) importance); + + // Commit changes. + return q.exec(); } bool DatabaseQueries::markFeedsReadUnread(QSqlDatabase db, const QStringList& ids, int account_id, RootItem::ReadStatus read) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QString("UPDATE Messages SET is_read = :read " - "WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;").arg(ids.join(QSL(", ")))); - q.bindValue(QSL(":read"), read == RootItem::Read ? 1 : 0); - q.bindValue(QSL(":account_id"), account_id); - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare(QString("UPDATE Messages SET is_read = :read " + "WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;").arg(ids.join(QSL(", ")))); + q.bindValue(QSL(":read"), read == RootItem::Read ? 1 : 0); + q.bindValue(QSL(":account_id"), account_id); + return q.exec(); } bool DatabaseQueries::markBinReadUnread(QSqlDatabase db, int account_id, RootItem::ReadStatus read) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare("UPDATE Messages SET is_read = :read " - "WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"); - q.bindValue(QSL(":read"), read == RootItem::Read ? 1 : 0); - q.bindValue(QSL(":account_id"), account_id); - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare("UPDATE Messages SET is_read = :read " + "WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"); + q.bindValue(QSL(":read"), read == RootItem::Read ? 1 : 0); + q.bindValue(QSL(":account_id"), account_id); + return q.exec(); } bool DatabaseQueries::markAccountReadUnread(QSqlDatabase db, int account_id, RootItem::ReadStatus read) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QSL("UPDATE Messages SET is_read = :read WHERE is_pdeleted = 0 AND account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); - q.bindValue(QSL(":read"), read == RootItem::Read ? 1 : 0); - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare(QSL("UPDATE Messages SET is_read = :read WHERE is_pdeleted = 0 AND account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); + q.bindValue(QSL(":read"), read == RootItem::Read ? 1 : 0); + return q.exec(); } bool DatabaseQueries::switchMessagesImportance(QSqlDatabase db, const QStringList& ids) { - QSqlQuery q(db); - q.setForwardOnly(true); - return q.exec(QString(QSL("UPDATE Messages SET is_important = NOT is_important WHERE id IN (%1);")).arg(ids.join(QSL(", ")))); + QSqlQuery q(db); + + q.setForwardOnly(true); + return q.exec(QString(QSL("UPDATE Messages SET is_important = NOT is_important WHERE id IN (%1);")).arg(ids.join(QSL(", ")))); } bool DatabaseQueries::permanentlyDeleteMessages(QSqlDatabase db, const QStringList& ids) { - QSqlQuery q(db); - q.setForwardOnly(true); - return q.exec(QString(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE id IN (%1);")).arg(ids.join(QSL(", ")))); + QSqlQuery q(db); + + q.setForwardOnly(true); + return q.exec(QString(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE id IN (%1);")).arg(ids.join(QSL(", ")))); } bool DatabaseQueries::deleteOrRestoreMessagesToFromBin(QSqlDatabase db, const QStringList& ids, bool deleted) { - QSqlQuery q(db); - q.setForwardOnly(true); - return q.exec(QString(QSL("UPDATE Messages SET is_deleted = %2, is_pdeleted = %3 WHERE id IN (%1);")).arg(ids.join(QSL(", ")), - QString::number(deleted ? 1 : 0), - QString::number(0))); + QSqlQuery q(db); + + q.setForwardOnly(true); + return q.exec(QString(QSL("UPDATE Messages SET is_deleted = %2, is_pdeleted = %3 WHERE id IN (%1);")).arg(ids.join(QSL(", ")), + QString::number(deleted ? 1 : 0), + QString::number(0))); } bool DatabaseQueries::restoreBin(QSqlDatabase db, int account_id) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare("UPDATE Messages SET is_deleted = 0 " - "WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"); - q.bindValue(QSL(":account_id"), account_id); - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare("UPDATE Messages SET is_deleted = 0 " + "WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"); + q.bindValue(QSL(":account_id"), account_id); + return q.exec(); } bool DatabaseQueries::purgeImportantMessages(QSqlDatabase db) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QSL("DELETE FROM Messages WHERE is_important = 1;")); - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare(QSL("DELETE FROM Messages WHERE is_important = 1;")); + return q.exec(); } bool DatabaseQueries::purgeReadMessages(QSqlDatabase db) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QSL("DELETE FROM Messages WHERE is_important = :is_important AND is_deleted = :is_deleted AND is_read = :is_read;")); - q.bindValue(QSL(":is_read"), 1); - // Remove only messages which are NOT in recycle bin. - q.bindValue(QSL(":is_deleted"), 0); - // Remove only messages which are NOT starred. - q.bindValue(QSL(":is_important"), 0); - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare(QSL("DELETE FROM Messages WHERE is_important = :is_important AND is_deleted = :is_deleted AND is_read = :is_read;")); + q.bindValue(QSL(":is_read"), 1); + + // Remove only messages which are NOT in recycle bin. + q.bindValue(QSL(":is_deleted"), 0); + + // Remove only messages which are NOT starred. + q.bindValue(QSL(":is_important"), 0); + return q.exec(); } bool DatabaseQueries::purgeOldMessages(QSqlDatabase db, int older_than_days) { - QSqlQuery q(db); - const qint64 since_epoch = QDateTime::currentDateTimeUtc().addDays(-older_than_days).toMSecsSinceEpoch(); - q.setForwardOnly(true); - q.prepare(QSL("DELETE FROM Messages WHERE is_important = :is_important AND date_created < :date_created;")); - q.bindValue(QSL(":date_created"), since_epoch); - // Remove only messages which are NOT starred. - q.bindValue(QSL(":is_important"), 0); - return q.exec(); + QSqlQuery q(db); + const qint64 since_epoch = QDateTime::currentDateTimeUtc().addDays(-older_than_days).toMSecsSinceEpoch(); + + q.setForwardOnly(true); + q.prepare(QSL("DELETE FROM Messages WHERE is_important = :is_important AND date_created < :date_created;")); + q.bindValue(QSL(":date_created"), since_epoch); + + // Remove only messages which are NOT starred. + q.bindValue(QSL(":is_important"), 0); + return q.exec(); } bool DatabaseQueries::purgeRecycleBin(QSqlDatabase db) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QSL("DELETE FROM Messages WHERE is_important = :is_important AND is_deleted = :is_deleted;")); - q.bindValue(QSL(":is_deleted"), 1); - // Remove only messages which are NOT starred. - q.bindValue(QSL(":is_important"), 0); - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare(QSL("DELETE FROM Messages WHERE is_important = :is_important AND is_deleted = :is_deleted;")); + q.bindValue(QSL(":is_deleted"), 1); + + // Remove only messages which are NOT starred. + q.bindValue(QSL(":is_important"), 0); + return q.exec(); } QMap> DatabaseQueries::getMessageCountsForCategory(QSqlDatabase db, int custom_id, int account_id, -bool including_total_counts, bool* ok) { - QMap> counts; - QSqlQuery q(db); - q.setForwardOnly(true); + bool including_total_counts, bool* ok) { + QMap> counts; + QSqlQuery q(db); - if (including_total_counts) { - q.prepare("SELECT feed, sum((is_read + 1) % 2), count(*) FROM Messages " - "WHERE feed IN (SELECT custom_id FROM Feeds WHERE category = :category AND account_id = :account_id) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id " - "GROUP BY feed;"); - } - else { - q.prepare("SELECT feed, sum((is_read + 1) % 2) FROM Messages " - "WHERE feed IN (SELECT custom_id FROM Feeds WHERE category = :category AND account_id = :account_id) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id " - "GROUP BY feed;"); - } + q.setForwardOnly(true); - q.bindValue(QSL(":category"), custom_id); - q.bindValue(QSL(":account_id"), account_id); + if (including_total_counts) { + q.prepare("SELECT feed, sum((is_read + 1) % 2), count(*) FROM Messages " + "WHERE feed IN (SELECT custom_id FROM Feeds WHERE category = :category AND account_id = :account_id) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id " + "GROUP BY feed;"); + } + else { + q.prepare("SELECT feed, sum((is_read + 1) % 2) FROM Messages " + "WHERE feed IN (SELECT custom_id FROM Feeds WHERE category = :category AND account_id = :account_id) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id " + "GROUP BY feed;"); + } - if (q.exec()) { - while (q.next()) { - int feed_id = q.value(0).toInt(); - int unread_count = q.value(1).toInt(); + q.bindValue(QSL(":category"), custom_id); + q.bindValue(QSL(":account_id"), account_id); - if (including_total_counts) { - int total_count = q.value(2).toInt(); - counts.insert(feed_id, QPair(unread_count, total_count)); - } - else { - counts.insert(feed_id, QPair(unread_count, 0)); - } - } + if (q.exec()) { + while (q.next()) { + int feed_id = q.value(0).toInt(); + int unread_count = q.value(1).toInt(); - if (ok != nullptr) { - *ok = true; - } - } - else { - if (ok != nullptr) { - *ok = false; - } - } + if (including_total_counts) { + int total_count = q.value(2).toInt(); - return counts; + counts.insert(feed_id, QPair(unread_count, total_count)); + } + else { + counts.insert(feed_id, QPair(unread_count, 0)); + } + } + + if (ok != nullptr) { + *ok = true; + } + } + else { + if (ok != nullptr) { + *ok = false; + } + } + + return counts; } QMap> DatabaseQueries::getMessageCountsForAccount(QSqlDatabase db, int account_id, -bool including_total_counts, bool* ok) { - QMap> counts; - QSqlQuery q(db); - q.setForwardOnly(true); + bool including_total_counts, bool* ok) { + QMap> counts; + QSqlQuery q(db); - if (including_total_counts) { - q.prepare("SELECT feed, sum((is_read + 1) % 2), count(*) FROM Messages " - "WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id " - "GROUP BY feed;"); - } - else { - q.prepare("SELECT feed, sum((is_read + 1) % 2) FROM Messages " - "WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id " - "GROUP BY feed;"); - } + q.setForwardOnly(true); - q.bindValue(QSL(":account_id"), account_id); + if (including_total_counts) { + q.prepare("SELECT feed, sum((is_read + 1) % 2), count(*) FROM Messages " + "WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id " + "GROUP BY feed;"); + } + else { + q.prepare("SELECT feed, sum((is_read + 1) % 2) FROM Messages " + "WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id " + "GROUP BY feed;"); + } - if (q.exec()) { - while (q.next()) { - int feed_id = q.value(0).toInt(); - int unread_count = q.value(1).toInt(); + q.bindValue(QSL(":account_id"), account_id); - if (including_total_counts) { - int total_count = q.value(2).toInt(); - counts.insert(feed_id, QPair(unread_count, total_count)); - } - else { - counts.insert(feed_id, QPair(unread_count, 0)); - } - } + if (q.exec()) { + while (q.next()) { + int feed_id = q.value(0).toInt(); + int unread_count = q.value(1).toInt(); - if (ok != nullptr) { - *ok = true; - } - } - else { - if (ok != nullptr) { - *ok = false; - } - } + if (including_total_counts) { + int total_count = q.value(2).toInt(); - return counts; + counts.insert(feed_id, QPair(unread_count, total_count)); + } + else { + counts.insert(feed_id, QPair(unread_count, 0)); + } + } + + if (ok != nullptr) { + *ok = true; + } + } + else { + if (ok != nullptr) { + *ok = false; + } + } + + return counts; } int DatabaseQueries::getMessageCountsForFeed(QSqlDatabase db, int feed_custom_id, int account_id, bool including_total_counts, bool* ok) { - QSqlQuery q(db); - q.setForwardOnly(true); + QSqlQuery q(db); - if (including_total_counts) { - q.prepare("SELECT count(*) FROM Messages " - "WHERE feed = :feed AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;"); - } - else { - q.prepare("SELECT count(*) FROM Messages " - "WHERE feed = :feed AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 0 AND account_id = :account_id;"); - } + q.setForwardOnly(true); - q.bindValue(QSL(":feed"), feed_custom_id); - q.bindValue(QSL(":account_id"), account_id); + if (including_total_counts) { + q.prepare("SELECT count(*) FROM Messages " + "WHERE feed = :feed AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;"); + } + else { + q.prepare("SELECT count(*) FROM Messages " + "WHERE feed = :feed AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 0 AND account_id = :account_id;"); + } - if (q.exec() && q.next()) { - if (ok != nullptr) { - *ok = true; - } + q.bindValue(QSL(":feed"), feed_custom_id); + q.bindValue(QSL(":account_id"), account_id); - return q.value(0).toInt(); - } - else { - if (ok != nullptr) { - *ok = false; - } + if (q.exec() && q.next()) { + if (ok != nullptr) { + *ok = true; + } - return 0; - } + return q.value(0).toInt(); + } + else { + if (ok != nullptr) { + *ok = false; + } + + return 0; + } } int DatabaseQueries::getMessageCountsForBin(QSqlDatabase db, int account_id, bool including_total_counts, bool* ok) { - QSqlQuery q(db); - q.setForwardOnly(true); + QSqlQuery q(db); - if (including_total_counts) { - q.prepare("SELECT count(*) FROM Messages " - "WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"); - } - else { - q.prepare("SELECT count(*) FROM Messages " - "WHERE is_read = 0 AND is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"); - } + q.setForwardOnly(true); - q.bindValue(QSL(":account_id"), account_id); + if (including_total_counts) { + q.prepare("SELECT count(*) FROM Messages " + "WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"); + } + else { + q.prepare("SELECT count(*) FROM Messages " + "WHERE is_read = 0 AND is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"); + } - if (q.exec() && q.next()) { - if (ok != nullptr) { - *ok = true; - } + q.bindValue(QSL(":account_id"), account_id); - return q.value(0).toInt(); - } - else { - if (ok != nullptr) { - *ok = false; - } + if (q.exec() && q.next()) { + if (ok != nullptr) { + *ok = true; + } - return 0; - } + return q.value(0).toInt(); + } + else { + if (ok != nullptr) { + *ok = false; + } + + return 0; + } } QList DatabaseQueries::getUndeletedMessagesForFeed(QSqlDatabase db, int feed_custom_id, int account_id, bool* ok) { - QList messages; - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare("SELECT * " - "FROM Messages " - "WHERE is_deleted = 0 AND is_pdeleted = 0 AND feed = :feed AND account_id = :account_id;"); - q.bindValue(QSL(":feed"), feed_custom_id); - q.bindValue(QSL(":account_id"), account_id); + QList messages; + QSqlQuery q(db); - if (q.exec()) { - while (q.next()) { - bool decoded; - Message message = Message::fromSqlRecord(q.record(), &decoded); + q.setForwardOnly(true); + q.prepare("SELECT * " + "FROM Messages " + "WHERE is_deleted = 0 AND is_pdeleted = 0 AND feed = :feed AND account_id = :account_id;"); + q.bindValue(QSL(":feed"), feed_custom_id); + q.bindValue(QSL(":account_id"), account_id); - if (decoded) { - messages.append(message); - } - } + if (q.exec()) { + while (q.next()) { + bool decoded; + Message message = Message::fromSqlRecord(q.record(), &decoded); - if (ok != nullptr) { - *ok = true; - } - } - else { - if (ok != nullptr) { - *ok = false; - } - } + if (decoded) { + messages.append(message); + } + } - return messages; + if (ok != nullptr) { + *ok = true; + } + } + else { + if (ok != nullptr) { + *ok = false; + } + } + + return messages; } QList DatabaseQueries::getUndeletedMessagesForBin(QSqlDatabase db, int account_id, bool* ok) { - QList messages; - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare("SELECT * " - "FROM Messages " - "WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"); - q.bindValue(QSL(":account_id"), account_id); + QList messages; + QSqlQuery q(db); - if (q.exec()) { - while (q.next()) { - bool decoded; - Message message = Message::fromSqlRecord(q.record(), &decoded); + q.setForwardOnly(true); + q.prepare("SELECT * " + "FROM Messages " + "WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;"); + q.bindValue(QSL(":account_id"), account_id); - if (decoded) { - messages.append(message); - } - } + if (q.exec()) { + while (q.next()) { + bool decoded; + Message message = Message::fromSqlRecord(q.record(), &decoded); - if (ok != nullptr) { - *ok = true; - } - } - else { - if (ok != nullptr) { - *ok = false; - } - } + if (decoded) { + messages.append(message); + } + } - return messages; + if (ok != nullptr) { + *ok = true; + } + } + else { + if (ok != nullptr) { + *ok = false; + } + } + + return messages; } QList DatabaseQueries::getUndeletedMessagesForAccount(QSqlDatabase db, int account_id, bool* ok) { - QList messages; - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare("SELECT * " - "FROM Messages " - "WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;"); - q.bindValue(QSL(":account_id"), account_id); + QList messages; + QSqlQuery q(db); - if (q.exec()) { - while (q.next()) { - bool decoded; - Message message = Message::fromSqlRecord(q.record(), &decoded); + q.setForwardOnly(true); + q.prepare("SELECT * " + "FROM Messages " + "WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;"); + q.bindValue(QSL(":account_id"), account_id); - if (decoded) { - messages.append(message); - } - } + if (q.exec()) { + while (q.next()) { + bool decoded; + Message message = Message::fromSqlRecord(q.record(), &decoded); - if (ok != nullptr) { - *ok = true; - } - } - else { - if (ok != nullptr) { - *ok = false; - } - } + if (decoded) { + messages.append(message); + } + } - return messages; + if (ok != nullptr) { + *ok = true; + } + } + else { + if (ok != nullptr) { + *ok = false; + } + } + + return messages; } int DatabaseQueries::updateMessages(QSqlDatabase db, @@ -419,712 +446,750 @@ int DatabaseQueries::updateMessages(QSqlDatabase db, const QString& url, bool* any_message_changed, bool* ok) { - if (messages.isEmpty()) { - *any_message_changed = false; - *ok = true; - return 0; - } + if (messages.isEmpty()) { + *any_message_changed = false; + *ok = true; + return 0; + } - bool use_transactions = qApp->settings()->value(GROUP(Database), SETTING(Database::UseTransactions)).toBool(); - // Does not make any difference, since each feed now has - // its own "custom ID" (standard feeds have their custom ID equal to primary key ID). - int updated_messages = 0; - // Prepare queries. - QSqlQuery query_select_with_url(db); - QSqlQuery query_select_with_id(db); - QSqlQuery query_update(db); - QSqlQuery query_insert(db); - QSqlQuery query_begin_transaction(db); - // Here we have query which will check for existence of the "same" message in given feed. - // The two message are the "same" if: - // 1) they belong to the same feed AND, - // 2) they have same URL AND, - // 3) they have same AUTHOR. - query_select_with_url.setForwardOnly(true); - query_select_with_url.prepare("SELECT id, date_created, is_read, is_important, contents FROM Messages " - "WHERE feed = :feed AND title = :title AND url = :url AND author = :author AND account_id = :account_id;"); - // When we have custom ID of the message, we can check directly for existence - // of that particular message. - query_select_with_id.setForwardOnly(true); - query_select_with_id.prepare("SELECT id, date_created, is_read, is_important, contents FROM Messages " - "WHERE custom_id = :custom_id AND account_id = :account_id;"); - // Used to insert new messages. - query_insert.setForwardOnly(true); - query_insert.prepare("INSERT INTO Messages " - "(feed, title, is_read, is_important, url, author, date_created, contents, enclosures, custom_id, custom_hash, account_id) " - "VALUES (:feed, :title, :is_read, :is_important, :url, :author, :date_created, :contents, :enclosures, :custom_id, :custom_hash, :account_id);"); - // Used to update existing messages. - query_update.setForwardOnly(true); - query_update.prepare("UPDATE Messages " - "SET title = :title, is_read = :is_read, is_important = :is_important, url = :url, author = :author, date_created = :date_created, contents = :contents, enclosures = :enclosures " - "WHERE id = :id;"); + bool use_transactions = qApp->settings()->value(GROUP(Database), SETTING(Database::UseTransactions)).toBool(); - if (use_transactions && !query_begin_transaction.exec(qApp->database()->obtainBeginTransactionSql())) { - qCritical("Transaction start for message downloader failed: '%s'.", qPrintable(query_begin_transaction.lastError().text())); - return updated_messages; - } + // Does not make any difference, since each feed now has + // its own "custom ID" (standard feeds have their custom ID equal to primary key ID). + int updated_messages = 0; - foreach (Message message, messages) { - // Check if messages contain relative URLs and if they do, then replace them. - if (message.m_url.startsWith(QL1S("//"))) { - message.m_url = QString(URI_SCHEME_HTTP) + message.m_url.mid(2); - } - else if (message.m_url.startsWith(QL1S("/"))) { - QString new_message_url = QUrl(url).toString(QUrl::RemoveUserInfo | - QUrl::RemovePath | - QUrl::RemoveQuery | - QUrl::RemoveFilename | - QUrl::StripTrailingSlash); - new_message_url += message.m_url; - message.m_url = new_message_url; - } + // Prepare queries. + QSqlQuery query_select_with_url(db); + QSqlQuery query_select_with_id(db); + QSqlQuery query_update(db); + QSqlQuery query_insert(db); + QSqlQuery query_begin_transaction(db); - int id_existing_message = -1; - qint64 date_existing_message; - bool is_read_existing_message; - bool is_important_existing_message; - QString contents_existing_message; + // Here we have query which will check for existence of the "same" message in given feed. + // The two message are the "same" if: + // 1) they belong to the same feed AND, + // 2) they have same URL AND, + // 3) they have same AUTHOR. + query_select_with_url.setForwardOnly(true); + query_select_with_url.prepare("SELECT id, date_created, is_read, is_important, contents FROM Messages " + "WHERE feed = :feed AND title = :title AND url = :url AND author = :author AND account_id = :account_id;"); - if (message.m_customId.isEmpty()) { - // We need to recognize existing messages according URL & AUTHOR. - // NOTE: This particularly concerns messages from standard account. - query_select_with_url.bindValue(QSL(":feed"), feed_custom_id); - query_select_with_url.bindValue(QSL(":title"), message.m_title); - query_select_with_url.bindValue(QSL(":url"), message.m_url); - query_select_with_url.bindValue(QSL(":author"), message.m_author); - query_select_with_url.bindValue(QSL(":account_id"), account_id); + // When we have custom ID of the message, we can check directly for existence + // of that particular message. + query_select_with_id.setForwardOnly(true); + query_select_with_id.prepare("SELECT id, date_created, is_read, is_important, contents FROM Messages " + "WHERE custom_id = :custom_id AND account_id = :account_id;"); - if (query_select_with_url.exec() && query_select_with_url.next()) { - id_existing_message = query_select_with_url.value(0).toInt(); - date_existing_message = query_select_with_url.value(1).value(); - is_read_existing_message = query_select_with_url.value(2).toBool(); - is_important_existing_message = query_select_with_url.value(3).toBool(); - contents_existing_message = query_select_with_url.value(4).toString(); - } - else if (query_select_with_url.lastError().isValid()) { - qWarning("Failed to check for existing message in DB via URL: '%s'.", qPrintable(query_select_with_url.lastError().text())); - } + // Used to insert new messages. + query_insert.setForwardOnly(true); + query_insert.prepare("INSERT INTO Messages " + "(feed, title, is_read, is_important, url, author, date_created, contents, enclosures, custom_id, custom_hash, account_id) " + "VALUES (:feed, :title, :is_read, :is_important, :url, :author, :date_created, :contents, :enclosures, :custom_id, :custom_hash, :account_id);"); - query_select_with_url.finish(); - } - else { - // We can recognize existing messages via their custom ID. - // NOTE: This concerns messages from custom accounts, like TT-RSS or ownCloud News. - query_select_with_id.bindValue(QSL(":account_id"), account_id); - query_select_with_id.bindValue(QSL(":custom_id"), message.m_customId); + // Used to update existing messages. + query_update.setForwardOnly(true); + query_update.prepare("UPDATE Messages " + "SET title = :title, is_read = :is_read, is_important = :is_important, url = :url, author = :author, date_created = :date_created, contents = :contents, enclosures = :enclosures " + "WHERE id = :id;"); - if (query_select_with_id.exec() && query_select_with_id.next()) { - id_existing_message = query_select_with_id.value(0).toInt(); - date_existing_message = query_select_with_id.value(1).value(); - is_read_existing_message = query_select_with_id.value(2).toBool(); - is_important_existing_message = query_select_with_id.value(3).toBool(); - contents_existing_message = query_select_with_id.value(4).toString(); - } - else if (query_select_with_id.lastError().isValid()) { - qDebug("Failed to check for existing message in DB via ID: '%s'.", qPrintable(query_select_with_id.lastError().text())); - } + if (use_transactions && !query_begin_transaction.exec(qApp->database()->obtainBeginTransactionSql())) { + qCritical("Transaction start for message downloader failed: '%s'.", qPrintable(query_begin_transaction.lastError().text())); + return updated_messages; + } - query_select_with_id.finish(); - } + foreach (Message message, messages) { + // Check if messages contain relative URLs and if they do, then replace them. + if (message.m_url.startsWith(QL1S("//"))) { + message.m_url = QString(URI_SCHEME_HTTP) + message.m_url.mid(2); + } + else if (message.m_url.startsWith(QL1S("/"))) { + QString new_message_url = QUrl(url).toString(QUrl::RemoveUserInfo | + QUrl::RemovePath | + QUrl::RemoveQuery | + QUrl::RemoveFilename | + QUrl::StripTrailingSlash); - // Now, check if this message is already in the DB. - if (id_existing_message >= 0) { - // Message is already in the DB. - // - // Now, we update it if at least one of next conditions is true: - // 1) Message has custom ID AND (its date OR read status OR starred status are changed). - // 2) Message has its date fetched from feed AND its date is different from date in DB and contents is changed. - if (/* 1 */ (!message.m_customId.isEmpty() && (message.m_created.toMSecsSinceEpoch() != date_existing_message - || message.m_isRead != is_read_existing_message - || message.m_isImportant != is_important_existing_message)) || - /* 2 */ (message.m_createdFromFeed && message.m_created.toMSecsSinceEpoch() != date_existing_message - && message.m_contents != contents_existing_message)) { - // Message exists, it is changed, update it. - query_update.bindValue(QSL(":title"), message.m_title); - query_update.bindValue(QSL(":is_read"), (int) message.m_isRead); - query_update.bindValue(QSL(":is_important"), (int) message.m_isImportant); - query_update.bindValue(QSL(":url"), message.m_url); - query_update.bindValue(QSL(":author"), message.m_author); - query_update.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch()); - query_update.bindValue(QSL(":contents"), message.m_contents); - query_update.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures)); - query_update.bindValue(QSL(":id"), id_existing_message); - *any_message_changed = true; + new_message_url += message.m_url; + message.m_url = new_message_url; + } - if (query_update.exec() && !message.m_isRead) { - updated_messages++; - } - else if (query_update.lastError().isValid()) { - qWarning("Failed to update message in DB: '%s'.", qPrintable(query_update.lastError().text())); - } + int id_existing_message = -1; + qint64 date_existing_message; + bool is_read_existing_message; + bool is_important_existing_message; + QString contents_existing_message; - query_update.finish(); - qDebug("Updating message '%s' in DB.", qPrintable(message.m_title)); - } - } - else { - // Message with this URL is not fetched in this feed yet. - query_insert.bindValue(QSL(":feed"), feed_custom_id); - query_insert.bindValue(QSL(":title"), message.m_title); - query_insert.bindValue(QSL(":is_read"), (int) message.m_isRead); - query_insert.bindValue(QSL(":is_important"), (int) message.m_isImportant); - query_insert.bindValue(QSL(":url"), message.m_url); - query_insert.bindValue(QSL(":author"), message.m_author); - query_insert.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch()); - query_insert.bindValue(QSL(":contents"), message.m_contents); - query_insert.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures)); - query_insert.bindValue(QSL(":custom_id"), message.m_customId); - query_insert.bindValue(QSL(":custom_hash"), message.m_customHash); - query_insert.bindValue(QSL(":account_id"), account_id); + if (message.m_customId.isEmpty()) { + // We need to recognize existing messages according URL & AUTHOR. + // NOTE: This particularly concerns messages from standard account. + query_select_with_url.bindValue(QSL(":feed"), feed_custom_id); + query_select_with_url.bindValue(QSL(":title"), message.m_title); + query_select_with_url.bindValue(QSL(":url"), message.m_url); + query_select_with_url.bindValue(QSL(":author"), message.m_author); + query_select_with_url.bindValue(QSL(":account_id"), account_id); - if (query_insert.exec() && query_insert.numRowsAffected() == 1) { - updated_messages++; - qDebug("Added new message '%s' to DB.", qPrintable(message.m_title)); - } - else if (query_insert.lastError().isValid()) { - qWarning("Failed to insert message to DB: '%s' - message title is '%s'.", - qPrintable(query_insert.lastError().text()), - qPrintable(message.m_title)); - } + if (query_select_with_url.exec() && query_select_with_url.next()) { + id_existing_message = query_select_with_url.value(0).toInt(); + date_existing_message = query_select_with_url.value(1).value(); + is_read_existing_message = query_select_with_url.value(2).toBool(); + is_important_existing_message = query_select_with_url.value(3).toBool(); + contents_existing_message = query_select_with_url.value(4).toString(); + } + else if (query_select_with_url.lastError().isValid()) { + qWarning("Failed to check for existing message in DB via URL: '%s'.", qPrintable(query_select_with_url.lastError().text())); + } - query_insert.finish(); - } - } + query_select_with_url.finish(); + } + else { + // We can recognize existing messages via their custom ID. + // NOTE: This concerns messages from custom accounts, like TT-RSS or ownCloud News. + query_select_with_id.bindValue(QSL(":account_id"), account_id); + query_select_with_id.bindValue(QSL(":custom_id"), message.m_customId); - // Now, fixup custom IDS for messages which initially did not have them, - // just to keep the data consistent. - if (db.exec("UPDATE Messages " - "SET custom_id = id " - "WHERE custom_id IS NULL OR custom_id = '';").lastError().isValid()) { - qWarning("Failed to set custom ID for all messages: '%s'.", qPrintable(db.lastError().text())); - } + if (query_select_with_id.exec() && query_select_with_id.next()) { + id_existing_message = query_select_with_id.value(0).toInt(); + date_existing_message = query_select_with_id.value(1).value(); + is_read_existing_message = query_select_with_id.value(2).toBool(); + is_important_existing_message = query_select_with_id.value(3).toBool(); + contents_existing_message = query_select_with_id.value(4).toString(); + } + else if (query_select_with_id.lastError().isValid()) { + qDebug("Failed to check for existing message in DB via ID: '%s'.", qPrintable(query_select_with_id.lastError().text())); + } - if (use_transactions && !db.commit()) { - qCritical("Transaction commit for message downloader failed: '%s'.", qPrintable(db.lastError().text())); - db.rollback(); + query_select_with_id.finish(); + } - if (ok != nullptr) { - *ok = false; - updated_messages = 0; - } - } - else { - if (ok != nullptr) { - *ok = true; - } - } + // Now, check if this message is already in the DB. + if (id_existing_message >= 0) { + // Message is already in the DB. + // + // Now, we update it if at least one of next conditions is true: + // 1) Message has custom ID AND (its date OR read status OR starred status are changed). + // 2) Message has its date fetched from feed AND its date is different from date in DB and contents is changed. + if (/* 1 */ (!message.m_customId.isEmpty() && (message.m_created.toMSecsSinceEpoch() != date_existing_message + || message.m_isRead != is_read_existing_message + || message.m_isImportant != is_important_existing_message)) || - return updated_messages; + /* 2 */ (message.m_createdFromFeed && message.m_created.toMSecsSinceEpoch() != date_existing_message + && message.m_contents != contents_existing_message)) { + // Message exists, it is changed, update it. + query_update.bindValue(QSL(":title"), message.m_title); + query_update.bindValue(QSL(":is_read"), (int) message.m_isRead); + query_update.bindValue(QSL(":is_important"), (int) message.m_isImportant); + query_update.bindValue(QSL(":url"), message.m_url); + query_update.bindValue(QSL(":author"), message.m_author); + query_update.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch()); + query_update.bindValue(QSL(":contents"), message.m_contents); + query_update.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures)); + query_update.bindValue(QSL(":id"), id_existing_message); + *any_message_changed = true; + + if (query_update.exec() && !message.m_isRead) { + updated_messages++; + } + else if (query_update.lastError().isValid()) { + qWarning("Failed to update message in DB: '%s'.", qPrintable(query_update.lastError().text())); + } + + query_update.finish(); + qDebug("Updating message '%s' in DB.", qPrintable(message.m_title)); + } + } + else { + // Message with this URL is not fetched in this feed yet. + query_insert.bindValue(QSL(":feed"), feed_custom_id); + query_insert.bindValue(QSL(":title"), message.m_title); + query_insert.bindValue(QSL(":is_read"), (int) message.m_isRead); + query_insert.bindValue(QSL(":is_important"), (int) message.m_isImportant); + query_insert.bindValue(QSL(":url"), message.m_url); + query_insert.bindValue(QSL(":author"), message.m_author); + query_insert.bindValue(QSL(":date_created"), message.m_created.toMSecsSinceEpoch()); + query_insert.bindValue(QSL(":contents"), message.m_contents); + query_insert.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures)); + query_insert.bindValue(QSL(":custom_id"), message.m_customId); + query_insert.bindValue(QSL(":custom_hash"), message.m_customHash); + query_insert.bindValue(QSL(":account_id"), account_id); + + if (query_insert.exec() && query_insert.numRowsAffected() == 1) { + updated_messages++; + qDebug("Added new message '%s' to DB.", qPrintable(message.m_title)); + } + else if (query_insert.lastError().isValid()) { + qWarning("Failed to insert message to DB: '%s' - message title is '%s'.", + qPrintable(query_insert.lastError().text()), + qPrintable(message.m_title)); + } + + query_insert.finish(); + } + } + + // Now, fixup custom IDS for messages which initially did not have them, + // just to keep the data consistent. + if (db.exec("UPDATE Messages " + "SET custom_id = id " + "WHERE custom_id IS NULL OR custom_id = '';").lastError().isValid()) { + qWarning("Failed to set custom ID for all messages: '%s'.", qPrintable(db.lastError().text())); + } + + if (use_transactions && !db.commit()) { + qCritical("Transaction commit for message downloader failed: '%s'.", qPrintable(db.lastError().text())); + db.rollback(); + + if (ok != nullptr) { + *ok = false; + updated_messages = 0; + } + } + else { + if (ok != nullptr) { + *ok = true; + } + } + + return updated_messages; } bool DatabaseQueries::purgeMessagesFromBin(QSqlDatabase db, bool clear_only_read, int account_id) { - QSqlQuery q(db); - q.setForwardOnly(true); + QSqlQuery q(db); - if (clear_only_read) { - q.prepare(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE is_read = 1 AND is_deleted = 1 AND account_id = :account_id;")); - } - else { - q.prepare(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE is_deleted = 1 AND account_id = :account_id;")); - } + q.setForwardOnly(true); - q.bindValue(QSL(":account_id"), account_id); - return q.exec(); + if (clear_only_read) { + q.prepare(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE is_read = 1 AND is_deleted = 1 AND account_id = :account_id;")); + } + else { + q.prepare(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE is_deleted = 1 AND account_id = :account_id;")); + } + + q.bindValue(QSL(":account_id"), account_id); + return q.exec(); } bool DatabaseQueries::deleteAccount(QSqlDatabase db, int account_id) { - QSqlQuery query(db); - query.setForwardOnly(true); - QStringList queries; - queries << QSL("DELETE FROM Messages WHERE account_id = :account_id;") << - QSL("DELETE FROM Feeds WHERE account_id = :account_id;") << - QSL("DELETE FROM Categories WHERE account_id = :account_id;") << - QSL("DELETE FROM Accounts WHERE id = :account_id;"); + QSqlQuery query(db); - foreach (const QString& q, queries) { - query.prepare(q); - query.bindValue(QSL(":account_id"), account_id); + query.setForwardOnly(true); + QStringList queries; - if (!query.exec()) { - qCritical("Removing of account from DB failed, this is critical: '%s'.", qPrintable(query.lastError().text())); - return false; - } - else { - query.finish(); - } - } + queries << QSL("DELETE FROM Messages WHERE account_id = :account_id;") << + QSL("DELETE FROM Feeds WHERE account_id = :account_id;") << + QSL("DELETE FROM Categories WHERE account_id = :account_id;") << + QSL("DELETE FROM Accounts WHERE id = :account_id;"); - return true; + foreach (const QString& q, queries) { + query.prepare(q); + query.bindValue(QSL(":account_id"), account_id); + + if (!query.exec()) { + qCritical("Removing of account from DB failed, this is critical: '%s'.", qPrintable(query.lastError().text())); + return false; + } + else { + query.finish(); + } + } + + return true; } bool DatabaseQueries::deleteAccountData(QSqlDatabase db, int account_id, bool delete_messages_too) { - bool result = true; - QSqlQuery q(db); - q.setForwardOnly(true); + bool result = true; + QSqlQuery q(db); - if (delete_messages_too) { - q.prepare(QSL("DELETE FROM Messages WHERE account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); - result &= q.exec(); - } + q.setForwardOnly(true); - q.prepare(QSL("DELETE FROM Feeds WHERE account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); - result &= q.exec(); - q.prepare(QSL("DELETE FROM Categories WHERE account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); - result &= q.exec(); - return result; + if (delete_messages_too) { + q.prepare(QSL("DELETE FROM Messages WHERE account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); + result &= q.exec(); + } + + q.prepare(QSL("DELETE FROM Feeds WHERE account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); + result &= q.exec(); + q.prepare(QSL("DELETE FROM Categories WHERE account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); + result &= q.exec(); + return result; } bool DatabaseQueries::cleanFeeds(QSqlDatabase db, const QStringList& ids, bool clean_read_only, int account_id) { - QSqlQuery q(db); - q.setForwardOnly(true); + QSqlQuery q(db); - if (clean_read_only) { - q.prepare(QString("UPDATE Messages SET is_deleted = :deleted " - "WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 1 AND account_id = :account_id;") - .arg(ids.join(QSL(", ")))); - } - else { - q.prepare(QString("UPDATE Messages SET is_deleted = :deleted " - "WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;") - .arg(ids.join(QSL(", ")))); - } + q.setForwardOnly(true); - q.bindValue(QSL(":deleted"), 1); - q.bindValue(QSL(":account_id"), account_id); + if (clean_read_only) { + q.prepare(QString("UPDATE Messages SET is_deleted = :deleted " + "WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 1 AND account_id = :account_id;") + .arg(ids.join(QSL(", ")))); + } + else { + q.prepare(QString("UPDATE Messages SET is_deleted = :deleted " + "WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;") + .arg(ids.join(QSL(", ")))); + } - if (!q.exec()) { - qDebug("Cleaning of feeds failed: '%s'.", qPrintable(q.lastError().text())); - return false; - } - else { - return true; - } + q.bindValue(QSL(":deleted"), 1); + q.bindValue(QSL(":account_id"), account_id); + + if (!q.exec()) { + qDebug("Cleaning of feeds failed: '%s'.", qPrintable(q.lastError().text())); + return false; + } + else { + return true; + } } bool DatabaseQueries::purgeLeftoverMessages(QSqlDatabase db, int account_id) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare( - QSL("DELETE FROM Messages WHERE account_id = :account_id AND feed NOT IN (SELECT custom_id FROM Feeds WHERE account_id = :account_id);")); - q.bindValue(QSL(":account_id"), account_id); + QSqlQuery q(db); - if (!q.exec()) { - qWarning("Removing of left over messages failed: '%s'.", qPrintable(q.lastError().text())); - return false; - } - else { - return true; - } + q.setForwardOnly(true); + q.prepare( + QSL("DELETE FROM Messages WHERE account_id = :account_id AND feed NOT IN (SELECT custom_id FROM Feeds WHERE account_id = :account_id);")); + q.bindValue(QSL(":account_id"), account_id); + + if (!q.exec()) { + qWarning("Removing of left over messages failed: '%s'.", qPrintable(q.lastError().text())); + return false; + } + else { + return true; + } } bool DatabaseQueries::storeAccountTree(QSqlDatabase db, RootItem* tree_root, int account_id) { - QSqlQuery query_category(db); - QSqlQuery query_feed(db); - query_category.setForwardOnly(true); - query_feed.setForwardOnly(true); - query_category.prepare("INSERT INTO Categories (parent_id, title, account_id, custom_id) " - "VALUES (:parent_id, :title, :account_id, :custom_id);"); - query_feed.prepare("INSERT INTO Feeds (title, icon, category, protected, update_type, update_interval, account_id, custom_id) " - "VALUES (:title, :icon, :category, :protected, :update_type, :update_interval, :account_id, :custom_id);"); + QSqlQuery query_category(db); + QSqlQuery query_feed(db); - // Iterate all children. - foreach (RootItem* child, tree_root->getSubTree()) { - if (child->kind() == RootItemKind::Category) { - query_category.bindValue(QSL(":parent_id"), child->parent()->id()); - query_category.bindValue(QSL(":title"), child->title()); - query_category.bindValue(QSL(":account_id"), account_id); - query_category.bindValue(QSL(":custom_id"), QString::number(child->toCategory()->customId())); + query_category.setForwardOnly(true); + query_feed.setForwardOnly(true); + query_category.prepare("INSERT INTO Categories (parent_id, title, account_id, custom_id) " + "VALUES (:parent_id, :title, :account_id, :custom_id);"); + query_feed.prepare("INSERT INTO Feeds (title, icon, category, protected, update_type, update_interval, account_id, custom_id) " + "VALUES (:title, :icon, :category, :protected, :update_type, :update_interval, :account_id, :custom_id);"); - if (query_category.exec()) { - child->setId(query_category.lastInsertId().toInt()); - } - else { - return false; - } - } - else if (child->kind() == RootItemKind::Feed) { - Feed* feed = child->toFeed(); - query_feed.bindValue(QSL(":title"), feed->title()); - query_feed.bindValue(QSL(":icon"), qApp->icons()->toByteArray(feed->icon())); - query_feed.bindValue(QSL(":category"), feed->parent()->customId()); - query_feed.bindValue(QSL(":protected"), 0); - query_feed.bindValue(QSL(":update_type"), (int) feed->autoUpdateType()); - query_feed.bindValue(QSL(":update_interval"), feed->autoUpdateInitialInterval()); - query_feed.bindValue(QSL(":account_id"), account_id); - query_feed.bindValue(QSL(":custom_id"), feed->customId()); + // Iterate all children. + foreach (RootItem* child, tree_root->getSubTree()) { + if (child->kind() == RootItemKind::Category) { + query_category.bindValue(QSL(":parent_id"), child->parent()->id()); + query_category.bindValue(QSL(":title"), child->title()); + query_category.bindValue(QSL(":account_id"), account_id); + query_category.bindValue(QSL(":custom_id"), QString::number(child->toCategory()->customId())); - if (query_feed.exec()) { - feed->setId(query_feed.lastInsertId().toInt()); - } - else { - return false; - } - } - } + if (query_category.exec()) { + child->setId(query_category.lastInsertId().toInt()); + } + else { + return false; + } + } + else if (child->kind() == RootItemKind::Feed) { + Feed* feed = child->toFeed(); - return true; + query_feed.bindValue(QSL(":title"), feed->title()); + query_feed.bindValue(QSL(":icon"), qApp->icons()->toByteArray(feed->icon())); + query_feed.bindValue(QSL(":category"), feed->parent()->customId()); + query_feed.bindValue(QSL(":protected"), 0); + query_feed.bindValue(QSL(":update_type"), (int) feed->autoUpdateType()); + query_feed.bindValue(QSL(":update_interval"), feed->autoUpdateInitialInterval()); + query_feed.bindValue(QSL(":account_id"), account_id); + query_feed.bindValue(QSL(":custom_id"), feed->customId()); + + if (query_feed.exec()) { + feed->setId(query_feed.lastInsertId().toInt()); + } + else { + return false; + } + } + } + + return true; } QStringList DatabaseQueries::customIdsOfMessagesFromAccount(QSqlDatabase db, int account_id, bool* ok) { - QSqlQuery q(db); - QStringList ids; - q.setForwardOnly(true); - q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); + QSqlQuery q(db); + QStringList ids; - if (ok != nullptr) { - *ok = q.exec(); - } - else { - q.exec(); - } + q.setForwardOnly(true); + q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); - while (q.next()) { - ids.append(q.value(0).toString()); - } + if (ok != nullptr) { + *ok = q.exec(); + } + else { + q.exec(); + } - return ids; + while (q.next()) { + ids.append(q.value(0).toString()); + } + + return ids; } QStringList DatabaseQueries::customIdsOfMessagesFromBin(QSqlDatabase db, int account_id, bool* ok) { - QSqlQuery q(db); - QStringList ids; - q.setForwardOnly(true); - q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); + QSqlQuery q(db); + QStringList ids; - if (ok != nullptr) { - *ok = q.exec(); - } - else { - q.exec(); - } + q.setForwardOnly(true); + q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); - while (q.next()) { - ids.append(q.value(0).toString()); - } + if (ok != nullptr) { + *ok = q.exec(); + } + else { + q.exec(); + } - return ids; + while (q.next()) { + ids.append(q.value(0).toString()); + } + + return ids; } QStringList DatabaseQueries::customIdsOfMessagesFromFeed(QSqlDatabase db, int feed_custom_id, int account_id, bool* ok) { - QSqlQuery q(db); - QStringList ids; - q.setForwardOnly(true); - q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND feed = :feed AND account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); - q.bindValue(QSL(":feed"), feed_custom_id); + QSqlQuery q(db); + QStringList ids; - if (ok != nullptr) { - *ok = q.exec(); - } - else { - q.exec(); - } + q.setForwardOnly(true); + q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND feed = :feed AND account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); + q.bindValue(QSL(":feed"), feed_custom_id); - while (q.next()) { - ids.append(q.value(0).toString()); - } + if (ok != nullptr) { + *ok = q.exec(); + } + else { + q.exec(); + } - return ids; + while (q.next()) { + ids.append(q.value(0).toString()); + } + + return ids; } QList DatabaseQueries::getOwnCloudAccounts(QSqlDatabase db, bool* ok) { - QSqlQuery query(db); - QList roots; + QSqlQuery query(db); - if (query.exec("SELECT * FROM OwnCloudAccounts;")) { - while (query.next()) { - OwnCloudServiceRoot* root = new OwnCloudServiceRoot(); - root->setId(query.value(0).toInt()); - root->setAccountId(query.value(0).toInt()); - root->network()->setAuthUsername(query.value(1).toString()); - root->network()->setAuthPassword(TextFactory::decrypt(query.value(2).toString())); - root->network()->setUrl(query.value(3).toString()); - root->network()->setForceServerSideUpdate(query.value(4).toBool()); - root->updateTitle(); - roots.append(root); - } + QList roots; - if (ok != nullptr) { - *ok = true; - } - } - else { - qWarning("OwnCloud: Getting list of activated accounts failed: '%s'.", qPrintable(query.lastError().text())); + if (query.exec("SELECT * FROM OwnCloudAccounts;")) { + while (query.next()) { + OwnCloudServiceRoot* root = new OwnCloudServiceRoot(); - if (ok != nullptr) { - *ok = false; - } - } + root->setId(query.value(0).toInt()); + root->setAccountId(query.value(0).toInt()); + root->network()->setAuthUsername(query.value(1).toString()); + root->network()->setAuthPassword(TextFactory::decrypt(query.value(2).toString())); + root->network()->setUrl(query.value(3).toString()); + root->network()->setForceServerSideUpdate(query.value(4).toBool()); + root->updateTitle(); + roots.append(root); + } - return roots; + if (ok != nullptr) { + *ok = true; + } + } + else { + qWarning("OwnCloud: Getting list of activated accounts failed: '%s'.", qPrintable(query.lastError().text())); + + if (ok != nullptr) { + *ok = false; + } + } + + return roots; } QList DatabaseQueries::getTtRssAccounts(QSqlDatabase db, bool* ok) { - QSqlQuery query(db); - QList roots; + QSqlQuery query(db); - if (query.exec("SELECT * FROM TtRssAccounts;")) { - while (query.next()) { - TtRssServiceRoot* root = new TtRssServiceRoot(); - root->setId(query.value(0).toInt()); - root->setAccountId(query.value(0).toInt()); - root->network()->setUsername(query.value(1).toString()); - root->network()->setPassword(TextFactory::decrypt(query.value(2).toString())); - root->network()->setAuthIsUsed(query.value(3).toBool()); - root->network()->setAuthUsername(query.value(4).toString()); - root->network()->setAuthPassword(TextFactory::decrypt(query.value(5).toString())); - root->network()->setUrl(query.value(6).toString()); - root->network()->setForceServerSideUpdate(query.value(7).toBool()); - root->updateTitle(); - roots.append(root); - } + QList roots; - if (ok != nullptr) { - *ok = true; - } - } - else { - qWarning("TT-RSS: Getting list of activated accounts failed: '%s'.", qPrintable(query.lastError().text())); + if (query.exec("SELECT * FROM TtRssAccounts;")) { + while (query.next()) { + TtRssServiceRoot* root = new TtRssServiceRoot(); - if (ok != nullptr) { - *ok = false; - } - } + root->setId(query.value(0).toInt()); + root->setAccountId(query.value(0).toInt()); + root->network()->setUsername(query.value(1).toString()); + root->network()->setPassword(TextFactory::decrypt(query.value(2).toString())); + root->network()->setAuthIsUsed(query.value(3).toBool()); + root->network()->setAuthUsername(query.value(4).toString()); + root->network()->setAuthPassword(TextFactory::decrypt(query.value(5).toString())); + root->network()->setUrl(query.value(6).toString()); + root->network()->setForceServerSideUpdate(query.value(7).toBool()); + root->updateTitle(); + roots.append(root); + } - return roots; + if (ok != nullptr) { + *ok = true; + } + } + else { + qWarning("TT-RSS: Getting list of activated accounts failed: '%s'.", qPrintable(query.lastError().text())); + + if (ok != nullptr) { + *ok = false; + } + } + + return roots; } bool DatabaseQueries::deleteOwnCloudAccount(QSqlDatabase db, int account_id) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QSL("DELETE FROM OwnCloudAccounts WHERE id = :id;")); - q.bindValue(QSL(":id"), account_id); - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare(QSL("DELETE FROM OwnCloudAccounts WHERE id = :id;")); + q.bindValue(QSL(":id"), account_id); + return q.exec(); } bool DatabaseQueries::overwriteOwnCloudAccount(QSqlDatabase db, const QString& username, const QString& password, const QString& url, bool force_server_side_feed_update, int account_id) { - QSqlQuery query(db); - query.prepare("UPDATE OwnCloudAccounts " - "SET username = :username, password = :password, url = :url, force_update = :force_update " - "WHERE id = :id;"); - query.bindValue(QSL(":username"), username); - query.bindValue(QSL(":password"), TextFactory::encrypt(password)); - query.bindValue(QSL(":url"), url); - query.bindValue(QSL(":force_update"), force_server_side_feed_update ? 1 : 0); - query.bindValue(QSL(":id"), account_id); + QSqlQuery query(db); - if (query.exec()) { - return true; - } - else { - qWarning("ownCloud: Updating account failed: '%s'.", qPrintable(query.lastError().text())); - return false; - } + query.prepare("UPDATE OwnCloudAccounts " + "SET username = :username, password = :password, url = :url, force_update = :force_update " + "WHERE id = :id;"); + query.bindValue(QSL(":username"), username); + query.bindValue(QSL(":password"), TextFactory::encrypt(password)); + query.bindValue(QSL(":url"), url); + query.bindValue(QSL(":force_update"), force_server_side_feed_update ? 1 : 0); + query.bindValue(QSL(":id"), account_id); + + if (query.exec()) { + return true; + } + else { + qWarning("ownCloud: Updating account failed: '%s'.", qPrintable(query.lastError().text())); + return false; + } } bool DatabaseQueries::createOwnCloudAccount(QSqlDatabase db, int id_to_assign, const QString& username, const QString& password, const QString& url, bool force_server_side_feed_update) { - QSqlQuery q(db); - q.prepare("INSERT INTO OwnCloudAccounts (id, username, password, url, force_update) " - "VALUES (:id, :username, :password, :url, :force_update);"); - q.bindValue(QSL(":id"), id_to_assign); - q.bindValue(QSL(":username"), username); - q.bindValue(QSL(":password"), TextFactory::encrypt(password)); - q.bindValue(QSL(":url"), url); - q.bindValue(QSL(":force_update"), force_server_side_feed_update ? 1 : 0); + QSqlQuery q(db); - if (q.exec()) { - return true; - } - else { - qWarning("ownCloud: Inserting of new account failed: '%s'.", qPrintable(q.lastError().text())); - return false; - } + q.prepare("INSERT INTO OwnCloudAccounts (id, username, password, url, force_update) " + "VALUES (:id, :username, :password, :url, :force_update);"); + q.bindValue(QSL(":id"), id_to_assign); + q.bindValue(QSL(":username"), username); + q.bindValue(QSL(":password"), TextFactory::encrypt(password)); + q.bindValue(QSL(":url"), url); + q.bindValue(QSL(":force_update"), force_server_side_feed_update ? 1 : 0); + + if (q.exec()) { + return true; + } + else { + qWarning("ownCloud: Inserting of new account failed: '%s'.", qPrintable(q.lastError().text())); + return false; + } } int DatabaseQueries::createAccount(QSqlDatabase db, const QString& code, bool* ok) { - QSqlQuery q(db); + QSqlQuery q(db); - // First obtain the ID, which can be assigned to this new account. - if (!q.exec("SELECT max(id) FROM Accounts;") || !q.next()) { - qWarning("Getting max ID from Accounts table failed: '%s'.", qPrintable(q.lastError().text())); + // First obtain the ID, which can be assigned to this new account. + if (!q.exec("SELECT max(id) FROM Accounts;") || !q.next()) { + qWarning("Getting max ID from Accounts table failed: '%s'.", qPrintable(q.lastError().text())); - if (ok != nullptr) { - *ok = false; - } + if (ok != nullptr) { + *ok = false; + } - return 0; - } + return 0; + } - int id_to_assign = q.value(0).toInt() + 1; - q.prepare(QSL("INSERT INTO Accounts (id, type) VALUES (:id, :type);")); - q.bindValue(QSL(":id"), id_to_assign); - q.bindValue(QSL(":type"), code); + int id_to_assign = q.value(0).toInt() + 1; - if (q.exec()) { - if (ok != nullptr) { - *ok = true; - } + q.prepare(QSL("INSERT INTO Accounts (id, type) VALUES (:id, :type);")); + q.bindValue(QSL(":id"), id_to_assign); + q.bindValue(QSL(":type"), code); - return id_to_assign; - } - else { - if (ok != nullptr) { - *ok = false; - } + if (q.exec()) { + if (ok != nullptr) { + *ok = true; + } - qWarning("Inserting of new account failed: '%s'.", qPrintable(q.lastError().text())); - return 0; - } + return id_to_assign; + } + else { + if (ok != nullptr) { + *ok = false; + } + + qWarning("Inserting of new account failed: '%s'.", qPrintable(q.lastError().text())); + return 0; + } } Assignment DatabaseQueries::getOwnCloudCategories(QSqlDatabase db, int account_id, bool* ok) { - Assignment categories; - // Obtain data for categories from the database. - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QSL("SELECT * FROM Categories WHERE account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); + Assignment categories; - if (!q.exec()) { - qFatal("ownCloud: Query for obtaining categories failed. Error message: '%s'.", qPrintable(q.lastError().text())); + // Obtain data for categories from the database. + QSqlQuery q(db); - if (ok != nullptr) { - *ok = false; - } - } + q.setForwardOnly(true); + q.prepare(QSL("SELECT * FROM Categories WHERE account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); - while (q.next()) { - AssignmentItem pair; - pair.first = q.value(CAT_DB_PARENT_ID_INDEX).toInt(); - pair.second = new OwnCloudCategory(q.record()); - categories << pair; - } + if (!q.exec()) { + qFatal("ownCloud: Query for obtaining categories failed. Error message: '%s'.", qPrintable(q.lastError().text())); - if (ok != nullptr) { - *ok = true; - } + if (ok != nullptr) { + *ok = false; + } + } - return categories; + while (q.next()) { + AssignmentItem pair; + + pair.first = q.value(CAT_DB_PARENT_ID_INDEX).toInt(); + pair.second = new OwnCloudCategory(q.record()); + categories << pair; + } + + if (ok != nullptr) { + *ok = true; + } + + return categories; } Assignment DatabaseQueries::getOwnCloudFeeds(QSqlDatabase db, int account_id, bool* ok) { - Assignment feeds; - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QSL("SELECT * FROM Feeds WHERE account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); + Assignment feeds; + QSqlQuery q(db); - if (!q.exec()) { - qFatal("ownCloud: Query for obtaining feeds failed. Error message: '%s'.", qPrintable(q.lastError().text())); + q.setForwardOnly(true); + q.prepare(QSL("SELECT * FROM Feeds WHERE account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); - if (ok != nullptr) { - *ok = false; - } - } + if (!q.exec()) { + qFatal("ownCloud: Query for obtaining feeds failed. Error message: '%s'.", qPrintable(q.lastError().text())); - while (q.next()) { - AssignmentItem pair; - pair.first = q.value(FDS_DB_CATEGORY_INDEX).toInt(); - pair.second = new OwnCloudFeed(q.record()); - feeds << pair; - } + if (ok != nullptr) { + *ok = false; + } + } - if (ok != nullptr) { - *ok = true; - } + while (q.next()) { + AssignmentItem pair; - return feeds; + pair.first = q.value(FDS_DB_CATEGORY_INDEX).toInt(); + pair.second = new OwnCloudFeed(q.record()); + feeds << pair; + } + + if (ok != nullptr) { + *ok = true; + } + + return feeds; } bool DatabaseQueries::deleteFeed(QSqlDatabase db, int feed_custom_id, int account_id) { - QSqlQuery q(db); - q.setForwardOnly(true); - // Remove all messages from this feed. - q.prepare(QSL("DELETE FROM Messages WHERE feed = :feed AND account_id = :account_id;")); - q.bindValue(QSL(":feed"), feed_custom_id); - q.bindValue(QSL(":account_id"), account_id); + QSqlQuery q(db); - if (!q.exec()) { - return false; - } + q.setForwardOnly(true); - // Remove feed itself. - q.prepare(QSL("DELETE FROM Feeds WHERE custom_id = :feed AND account_id = :account_id;")); - q.bindValue(QSL(":feed"), feed_custom_id); - q.bindValue(QSL(":account_id"), account_id); - return q.exec(); + // Remove all messages from this feed. + q.prepare(QSL("DELETE FROM Messages WHERE feed = :feed AND account_id = :account_id;")); + q.bindValue(QSL(":feed"), feed_custom_id); + q.bindValue(QSL(":account_id"), account_id); + + if (!q.exec()) { + return false; + } + + // Remove feed itself. + q.prepare(QSL("DELETE FROM Feeds WHERE custom_id = :feed AND account_id = :account_id;")); + q.bindValue(QSL(":feed"), feed_custom_id); + q.bindValue(QSL(":account_id"), account_id); + return q.exec(); } bool DatabaseQueries::deleteCategory(QSqlDatabase db, int id) { - QSqlQuery q(db); - // Remove this category from database. - q.setForwardOnly(true); - q.prepare(QSL("DELETE FROM Categories WHERE id = :category;")); - q.bindValue(QSL(":category"), id); - return q.exec(); + QSqlQuery q(db); + + // Remove this category from database. + q.setForwardOnly(true); + q.prepare(QSL("DELETE FROM Categories WHERE id = :category;")); + q.bindValue(QSL(":category"), id); + return q.exec(); } int DatabaseQueries::addCategory(QSqlDatabase db, int parent_id, int account_id, const QString& title, const QString& description, QDateTime creation_date, const QIcon& icon, bool* ok) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare("INSERT INTO Categories " - "(parent_id, title, description, date_created, icon, account_id) " - "VALUES (:parent_id, :title, :description, :date_created, :icon, :account_id);"); - q.bindValue(QSL(":parent_id"), parent_id); - q.bindValue(QSL(":title"), title); - q.bindValue(QSL(":description"), description); - q.bindValue(QSL(":date_created"), creation_date.toMSecsSinceEpoch()); - q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon)); - q.bindValue(QSL(":account_id"), account_id); + QSqlQuery q(db); - if (!q.exec()) { - qDebug("Failed to add category to database: '%s'.", qPrintable(q.lastError().text())); + q.setForwardOnly(true); + q.prepare("INSERT INTO Categories " + "(parent_id, title, description, date_created, icon, account_id) " + "VALUES (:parent_id, :title, :description, :date_created, :icon, :account_id);"); + q.bindValue(QSL(":parent_id"), parent_id); + q.bindValue(QSL(":title"), title); + q.bindValue(QSL(":description"), description); + q.bindValue(QSL(":date_created"), creation_date.toMSecsSinceEpoch()); + q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon)); + q.bindValue(QSL(":account_id"), account_id); - if (ok != nullptr) { - *ok = false; - } + if (!q.exec()) { + qDebug("Failed to add category to database: '%s'.", qPrintable(q.lastError().text())); - // Query failed. - return 0; - } - else { - if (ok != nullptr) { - *ok = true; - } + if (ok != nullptr) { + *ok = false; + } - int new_id = q.lastInsertId().toInt(); - // Now set custom ID in the DB. - q.prepare(QSL("UPDATE Categories SET custom_id = :custom_id WHERE id = :id;")); - q.bindValue(QSL(":custom_id"), QString::number(new_id)); - q.bindValue(QSL(":id"), new_id); - q.exec(); - return new_id; - } + // Query failed. + return 0; + } + else { + if (ok != nullptr) { + *ok = true; + } + + int new_id = q.lastInsertId().toInt(); + + // Now set custom ID in the DB. + q.prepare(QSL("UPDATE Categories SET custom_id = :custom_id WHERE id = :id;")); + q.bindValue(QSL(":custom_id"), QString::number(new_id)); + q.bindValue(QSL(":id"), new_id); + q.exec(); + return new_id; + } } bool DatabaseQueries::editCategory(QSqlDatabase db, int parent_id, int category_id, const QString& title, const QString& description, const QIcon& icon) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare("UPDATE Categories " - "SET title = :title, description = :description, icon = :icon, parent_id = :parent_id " - "WHERE id = :id;"); - q.bindValue(QSL(":title"), title); - q.bindValue(QSL(":description"), description); - q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon)); - q.bindValue(QSL(":parent_id"), parent_id); - q.bindValue(QSL(":id"), category_id); - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare("UPDATE Categories " + "SET title = :title, description = :description, icon = :icon, parent_id = :parent_id " + "WHERE id = :id;"); + q.bindValue(QSL(":title"), title); + q.bindValue(QSL(":description"), description); + q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon)); + q.bindValue(QSL(":parent_id"), parent_id); + q.bindValue(QSL(":id"), category_id); + return q.exec(); } int DatabaseQueries::addFeed(QSqlDatabase db, int parent_id, int account_id, const QString& title, @@ -1133,56 +1198,58 @@ int DatabaseQueries::addFeed(QSqlDatabase db, int parent_id, int account_id, con const QString& username, const QString& password, Feed::AutoUpdateType auto_update_type, int auto_update_interval, StandardFeed::Type feed_format, bool* ok) { - QSqlQuery q(db); - qDebug() << "Adding feed with title '" << title.toUtf8() << "' to DB."; - q.setForwardOnly(true); - q.prepare("INSERT INTO Feeds " - "(title, description, date_created, icon, category, encoding, url, protected, username, password, update_type, update_interval, type, account_id) " - "VALUES (:title, :description, :date_created, :icon, :category, :encoding, :url, :protected, :username, :password, :update_type, :update_interval, :type, :account_id);"); - q.bindValue(QSL(":title"), title.toUtf8()); - q.bindValue(QSL(":description"), description.toUtf8()); - q.bindValue(QSL(":date_created"), creation_date.toMSecsSinceEpoch()); - q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon)); - q.bindValue(QSL(":category"), parent_id); - q.bindValue(QSL(":encoding"), encoding); - q.bindValue(QSL(":url"), url); - q.bindValue(QSL(":protected"), is_protected ? 1 : 0); - q.bindValue(QSL(":username"), username); - q.bindValue(QSL(":account_id"), account_id); + QSqlQuery q(db); - if (password.isEmpty()) { - q.bindValue(QSL(":password"), password); - } - else { - q.bindValue(QSL(":password"), TextFactory::encrypt(password)); - } + qDebug() << "Adding feed with title '" << title.toUtf8() << "' to DB."; + q.setForwardOnly(true); + q.prepare("INSERT INTO Feeds " + "(title, description, date_created, icon, category, encoding, url, protected, username, password, update_type, update_interval, type, account_id) " + "VALUES (:title, :description, :date_created, :icon, :category, :encoding, :url, :protected, :username, :password, :update_type, :update_interval, :type, :account_id);"); + q.bindValue(QSL(":title"), title.toUtf8()); + q.bindValue(QSL(":description"), description.toUtf8()); + q.bindValue(QSL(":date_created"), creation_date.toMSecsSinceEpoch()); + q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon)); + q.bindValue(QSL(":category"), parent_id); + q.bindValue(QSL(":encoding"), encoding); + q.bindValue(QSL(":url"), url); + q.bindValue(QSL(":protected"), is_protected ? 1 : 0); + q.bindValue(QSL(":username"), username); + q.bindValue(QSL(":account_id"), account_id); - q.bindValue(QSL(":update_type"), (int) auto_update_type); - q.bindValue(QSL(":update_interval"), auto_update_interval); - q.bindValue(QSL(":type"), (int) feed_format); + if (password.isEmpty()) { + q.bindValue(QSL(":password"), password); + } + else { + q.bindValue(QSL(":password"), TextFactory::encrypt(password)); + } - if (q.exec()) { - int new_id = q.lastInsertId().toInt(); - // Now set custom ID in the DB. - q.prepare(QSL("UPDATE Feeds SET custom_id = :custom_id WHERE id = :id;")); - q.bindValue(QSL(":custom_id"), QString::number(new_id)); - q.bindValue(QSL(":id"), new_id); - q.exec(); + q.bindValue(QSL(":update_type"), (int) auto_update_type); + q.bindValue(QSL(":update_interval"), auto_update_interval); + q.bindValue(QSL(":type"), (int) feed_format); - if (ok != nullptr) { - *ok = true; - } + if (q.exec()) { + int new_id = q.lastInsertId().toInt(); - return new_id; - } - else { - if (ok != nullptr) { - *ok = false; - } + // Now set custom ID in the DB. + q.prepare(QSL("UPDATE Feeds SET custom_id = :custom_id WHERE id = :id;")); + q.bindValue(QSL(":custom_id"), QString::number(new_id)); + q.bindValue(QSL(":id"), new_id); + q.exec(); - qDebug("Failed to add feed to database: '%s'.", qPrintable(q.lastError().text())); - return 0; - } + if (ok != nullptr) { + *ok = true; + } + + return new_id; + } + else { + if (ok != nullptr) { + *ok = false; + } + + qDebug("Failed to add feed to database: '%s'.", qPrintable(q.lastError().text())); + return 0; + } } bool DatabaseQueries::editFeed(QSqlDatabase db, int parent_id, int feed_id, const QString& title, @@ -1191,273 +1258,291 @@ bool DatabaseQueries::editFeed(QSqlDatabase db, int parent_id, int feed_id, cons const QString& username, const QString& password, Feed::AutoUpdateType auto_update_type, int auto_update_interval, StandardFeed::Type feed_format) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare("UPDATE Feeds " - "SET title = :title, description = :description, icon = :icon, category = :category, encoding = :encoding, url = :url, protected = :protected, username = :username, password = :password, update_type = :update_type, update_interval = :update_interval, type = :type " - "WHERE id = :id;"); - q.bindValue(QSL(":title"), title); - q.bindValue(QSL(":description"), description); - q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon)); - q.bindValue(QSL(":category"), parent_id); - q.bindValue(QSL(":encoding"), encoding); - q.bindValue(QSL(":url"), url); - q.bindValue(QSL(":protected"), is_protected ? 1 : 0); - q.bindValue(QSL(":username"), username); + QSqlQuery q(db); - if (password.isEmpty()) { - q.bindValue(QSL(":password"), password); - } - else { - q.bindValue(QSL(":password"), TextFactory::encrypt(password)); - } + q.setForwardOnly(true); + q.prepare("UPDATE Feeds " + "SET title = :title, description = :description, icon = :icon, category = :category, encoding = :encoding, url = :url, protected = :protected, username = :username, password = :password, update_type = :update_type, update_interval = :update_interval, type = :type " + "WHERE id = :id;"); + q.bindValue(QSL(":title"), title); + q.bindValue(QSL(":description"), description); + q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon)); + q.bindValue(QSL(":category"), parent_id); + q.bindValue(QSL(":encoding"), encoding); + q.bindValue(QSL(":url"), url); + q.bindValue(QSL(":protected"), is_protected ? 1 : 0); + q.bindValue(QSL(":username"), username); - q.bindValue(QSL(":update_type"), (int) auto_update_type); - q.bindValue(QSL(":update_interval"), auto_update_interval); - q.bindValue(QSL(":type"), feed_format); - q.bindValue(QSL(":id"), feed_id); - return q.exec(); + if (password.isEmpty()) { + q.bindValue(QSL(":password"), password); + } + else { + q.bindValue(QSL(":password"), TextFactory::encrypt(password)); + } + + q.bindValue(QSL(":update_type"), (int) auto_update_type); + q.bindValue(QSL(":update_interval"), auto_update_interval); + q.bindValue(QSL(":type"), feed_format); + q.bindValue(QSL(":id"), feed_id); + return q.exec(); } bool DatabaseQueries::editBaseFeed(QSqlDatabase db, int feed_id, Feed::AutoUpdateType auto_update_type, int auto_update_interval) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare("UPDATE Feeds " - "SET update_type = :update_type, update_interval = :update_interval " - "WHERE id = :id;"); - q.bindValue(QSL(":update_type"), (int) auto_update_type); - q.bindValue(QSL(":update_interval"), auto_update_interval); - q.bindValue(QSL(":id"), feed_id); - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare("UPDATE Feeds " + "SET update_type = :update_type, update_interval = :update_interval " + "WHERE id = :id;"); + q.bindValue(QSL(":update_type"), (int) auto_update_type); + q.bindValue(QSL(":update_interval"), auto_update_interval); + q.bindValue(QSL(":id"), feed_id); + return q.exec(); } QList DatabaseQueries::getAccounts(QSqlDatabase db, bool* ok) { - QSqlQuery q(db); - QList roots; - q.setForwardOnly(true); - q.prepare(QSL("SELECT id FROM Accounts WHERE type = :type;")); - q.bindValue(QSL(":type"), SERVICE_CODE_STD_RSS); + QSqlQuery q(db); - if (q.exec()) { - while (q.next()) { - StandardServiceRoot* root = new StandardServiceRoot(); - root->setAccountId(q.value(0).toInt()); - roots.append(root); - } + QList roots; + q.setForwardOnly(true); + q.prepare(QSL("SELECT id FROM Accounts WHERE type = :type;")); + q.bindValue(QSL(":type"), SERVICE_CODE_STD_RSS); - if (ok != nullptr) { - *ok = true; - } - } - else { - if (ok != nullptr) { - *ok = false; - } - } + if (q.exec()) { + while (q.next()) { + StandardServiceRoot* root = new StandardServiceRoot(); - return roots; + root->setAccountId(q.value(0).toInt()); + roots.append(root); + } + + if (ok != nullptr) { + *ok = true; + } + } + else { + if (ok != nullptr) { + *ok = false; + } + } + + return roots; } Assignment DatabaseQueries::getCategories(QSqlDatabase db, int account_id, bool* ok) { - Assignment categories; - // Obtain data for categories from the database. - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QSL("SELECT * FROM Categories WHERE account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); + Assignment categories; - if (!q.exec()) { - qFatal("Query for obtaining categories failed. Error message: '%s'.", - qPrintable(q.lastError().text())); + // Obtain data for categories from the database. + QSqlQuery q(db); - if (ok != nullptr) { - *ok = false; - } - } - else { - if (ok != nullptr) { - *ok = true; - } - } + q.setForwardOnly(true); + q.prepare(QSL("SELECT * FROM Categories WHERE account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); - while (q.next()) { - AssignmentItem pair; - pair.first = q.value(CAT_DB_PARENT_ID_INDEX).toInt(); - pair.second = new StandardCategory(q.record()); - categories << pair; - } + if (!q.exec()) { + qFatal("Query for obtaining categories failed. Error message: '%s'.", + qPrintable(q.lastError().text())); - return categories; + if (ok != nullptr) { + *ok = false; + } + } + else { + if (ok != nullptr) { + *ok = true; + } + } + + while (q.next()) { + AssignmentItem pair; + + pair.first = q.value(CAT_DB_PARENT_ID_INDEX).toInt(); + pair.second = new StandardCategory(q.record()); + categories << pair; + } + + return categories; } Assignment DatabaseQueries::getFeeds(QSqlDatabase db, int account_id, bool* ok) { - Assignment feeds; - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QSL("SELECT * FROM Feeds WHERE account_id = :account_id;")); - q.bindValue(QSL(":account_id"), account_id); + Assignment feeds; + QSqlQuery q(db); - if (!q.exec()) { - qFatal("Query for obtaining feeds failed. Error message: '%s'.", - qPrintable(q.lastError().text())); + q.setForwardOnly(true); + q.prepare(QSL("SELECT * FROM Feeds WHERE account_id = :account_id;")); + q.bindValue(QSL(":account_id"), account_id); - if (ok != nullptr) { - *ok = false; - } - } + if (!q.exec()) { + qFatal("Query for obtaining feeds failed. Error message: '%s'.", + qPrintable(q.lastError().text())); - if (ok != nullptr) { - *ok = true; - } + if (ok != nullptr) { + *ok = false; + } + } - while (q.next()) { - // Process this feed. - StandardFeed::Type type = static_cast(q.value(FDS_DB_TYPE_INDEX).toInt()); + if (ok != nullptr) { + *ok = true; + } - switch (type) { - case StandardFeed::Atom10: - case StandardFeed::Rdf: - case StandardFeed::Rss0X: - case StandardFeed::Rss2X: { - AssignmentItem pair; - pair.first = q.value(FDS_DB_CATEGORY_INDEX).toInt(); - pair.second = new StandardFeed(q.record()); - qobject_cast(pair.second)->setType(type); - feeds << pair; - break; - } + while (q.next()) { + // Process this feed. + StandardFeed::Type type = static_cast(q.value(FDS_DB_TYPE_INDEX).toInt()); - default: - break; - } - } + switch (type) { + case StandardFeed::Atom10: + case StandardFeed::Rdf: + case StandardFeed::Rss0X: + case StandardFeed::Rss2X: { + AssignmentItem pair; - return feeds; + pair.first = q.value(FDS_DB_CATEGORY_INDEX).toInt(); + pair.second = new StandardFeed(q.record()); + qobject_cast(pair.second)->setType(type); + feeds << pair; + break; + } + + default: + break; + } + } + + return feeds; } bool DatabaseQueries::deleteTtRssAccount(QSqlDatabase db, int account_id) { - QSqlQuery q(db); - q.setForwardOnly(true); - q.prepare(QSL("DELETE FROM TtRssAccounts WHERE id = :id;")); - q.bindValue(QSL(":id"), account_id); - // Remove extra entry in "Tiny Tiny RSS accounts list" and then delete - // all the categories/feeds and messages. - return q.exec(); + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare(QSL("DELETE FROM TtRssAccounts WHERE id = :id;")); + q.bindValue(QSL(":id"), account_id); + + // Remove extra entry in "Tiny Tiny RSS accounts list" and then delete + // all the categories/feeds and messages. + return q.exec(); } bool DatabaseQueries::overwriteTtRssAccount(QSqlDatabase db, const QString& username, const QString& password, bool auth_protected, const QString& auth_username, const QString& auth_password, const QString& url, bool force_server_side_feed_update, int account_id) { - QSqlQuery q(db); - q.prepare("UPDATE TtRssAccounts " - "SET username = :username, password = :password, url = :url, auth_protected = :auth_protected, " - "auth_username = :auth_username, auth_password = :auth_password, force_update = :force_update " - "WHERE id = :id;"); - q.bindValue(QSL(":username"), username); - q.bindValue(QSL(":password"), TextFactory::encrypt(password)); - q.bindValue(QSL(":url"), url); - q.bindValue(QSL(":auth_protected"), auth_protected ? 1 : 0); - q.bindValue(QSL(":auth_username"), auth_username); - q.bindValue(QSL(":auth_password"), TextFactory::encrypt(auth_password)); - q.bindValue(QSL(":force_update"), force_server_side_feed_update ? 1 : 0); - q.bindValue(QSL(":id"), account_id); + QSqlQuery q(db); - if (q.exec()) { - return true; - } - else { - qWarning("TT-RSS: Updating account failed: '%s'.", qPrintable(q.lastError().text())); - return false; - } + q.prepare("UPDATE TtRssAccounts " + "SET username = :username, password = :password, url = :url, auth_protected = :auth_protected, " + "auth_username = :auth_username, auth_password = :auth_password, force_update = :force_update " + "WHERE id = :id;"); + q.bindValue(QSL(":username"), username); + q.bindValue(QSL(":password"), TextFactory::encrypt(password)); + q.bindValue(QSL(":url"), url); + q.bindValue(QSL(":auth_protected"), auth_protected ? 1 : 0); + q.bindValue(QSL(":auth_username"), auth_username); + q.bindValue(QSL(":auth_password"), TextFactory::encrypt(auth_password)); + q.bindValue(QSL(":force_update"), force_server_side_feed_update ? 1 : 0); + q.bindValue(QSL(":id"), account_id); + + if (q.exec()) { + return true; + } + else { + qWarning("TT-RSS: Updating account failed: '%s'.", qPrintable(q.lastError().text())); + return false; + } } bool DatabaseQueries::createTtRssAccount(QSqlDatabase db, int id_to_assign, const QString& username, const QString& password, bool auth_protected, const QString& auth_username, const QString& auth_password, const QString& url, bool force_server_side_feed_update) { - QSqlQuery q(db); - q.prepare("INSERT INTO TtRssAccounts (id, username, password, auth_protected, auth_username, auth_password, url, force_update) " - "VALUES (:id, :username, :password, :auth_protected, :auth_username, :auth_password, :url, :force_update);"); - q.bindValue(QSL(":id"), id_to_assign); - q.bindValue(QSL(":username"), username); - q.bindValue(QSL(":password"), TextFactory::encrypt(password)); - q.bindValue(QSL(":auth_protected"), auth_protected ? 1 : 0); - q.bindValue(QSL(":auth_username"), auth_username); - q.bindValue(QSL(":auth_password"), TextFactory::encrypt(auth_password)); - q.bindValue(QSL(":url"), url); - q.bindValue(QSL(":force_update"), force_server_side_feed_update ? 1 : 0); + QSqlQuery q(db); - if (q.exec()) { - return true; - } - else { - qWarning("TT-RSS: Saving of new account failed: '%s'.", qPrintable(q.lastError().text())); - return false; - } + q.prepare("INSERT INTO TtRssAccounts (id, username, password, auth_protected, auth_username, auth_password, url, force_update) " + "VALUES (:id, :username, :password, :auth_protected, :auth_username, :auth_password, :url, :force_update);"); + q.bindValue(QSL(":id"), id_to_assign); + q.bindValue(QSL(":username"), username); + q.bindValue(QSL(":password"), TextFactory::encrypt(password)); + q.bindValue(QSL(":auth_protected"), auth_protected ? 1 : 0); + q.bindValue(QSL(":auth_username"), auth_username); + q.bindValue(QSL(":auth_password"), TextFactory::encrypt(auth_password)); + q.bindValue(QSL(":url"), url); + q.bindValue(QSL(":force_update"), force_server_side_feed_update ? 1 : 0); + + if (q.exec()) { + return true; + } + else { + qWarning("TT-RSS: Saving of new account failed: '%s'.", qPrintable(q.lastError().text())); + return false; + } } Assignment DatabaseQueries::getTtRssCategories(QSqlDatabase db, int account_id, bool* ok) { - Assignment categories; - // Obtain data for categories from the database. - QSqlQuery query_categories(db); - query_categories.setForwardOnly(true); - query_categories.prepare(QSL("SELECT * FROM Categories WHERE account_id = :account_id;")); - query_categories.bindValue(QSL(":account_id"), account_id); + Assignment categories; - if (!query_categories.exec()) { - qFatal("Query for obtaining categories failed. Error message: '%s'.", qPrintable(query_categories.lastError().text())); + // Obtain data for categories from the database. + QSqlQuery query_categories(db); - if (ok != nullptr) { - *ok = false; - } - } - else { - if (ok != nullptr) { - *ok = true; - } - } + query_categories.setForwardOnly(true); + query_categories.prepare(QSL("SELECT * FROM Categories WHERE account_id = :account_id;")); + query_categories.bindValue(QSL(":account_id"), account_id); - while (query_categories.next()) { - AssignmentItem pair; - pair.first = query_categories.value(CAT_DB_PARENT_ID_INDEX).toInt(); - pair.second = new TtRssCategory(query_categories.record()); - categories << pair; - } + if (!query_categories.exec()) { + qFatal("Query for obtaining categories failed. Error message: '%s'.", qPrintable(query_categories.lastError().text())); - return categories; + if (ok != nullptr) { + *ok = false; + } + } + else { + if (ok != nullptr) { + *ok = true; + } + } + + while (query_categories.next()) { + AssignmentItem pair; + + pair.first = query_categories.value(CAT_DB_PARENT_ID_INDEX).toInt(); + pair.second = new TtRssCategory(query_categories.record()); + categories << pair; + } + + return categories; } Assignment DatabaseQueries::getTtRssFeeds(QSqlDatabase db, int account_id, bool* ok) { - Assignment feeds; - // All categories are now loaded. - QSqlQuery query_feeds(db); - query_feeds.setForwardOnly(true); - query_feeds.prepare(QSL("SELECT * FROM Feeds WHERE account_id = :account_id;")); - query_feeds.bindValue(QSL(":account_id"), account_id); + Assignment feeds; - if (!query_feeds.exec()) { - qFatal("Query for obtaining feeds failed. Error message: '%s'.", qPrintable(query_feeds.lastError().text())); + // All categories are now loaded. + QSqlQuery query_feeds(db); - if (ok != nullptr) { - *ok = false; - } - } - else { - if (ok != nullptr) { - *ok = true; - } - } + query_feeds.setForwardOnly(true); + query_feeds.prepare(QSL("SELECT * FROM Feeds WHERE account_id = :account_id;")); + query_feeds.bindValue(QSL(":account_id"), account_id); - while (query_feeds.next()) { - AssignmentItem pair; - pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt(); - pair.second = new TtRssFeed(query_feeds.record()); - feeds << pair; - } + if (!query_feeds.exec()) { + qFatal("Query for obtaining feeds failed. Error message: '%s'.", qPrintable(query_feeds.lastError().text())); - return feeds; + if (ok != nullptr) { + *ok = false; + } + } + else { + if (ok != nullptr) { + *ok = true; + } + } + + while (query_feeds.next()) { + AssignmentItem pair; + + pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt(); + pair.second = new TtRssFeed(query_feeds.record()); + feeds << pair; + } + + return feeds; } -DatabaseQueries::DatabaseQueries() { -} +DatabaseQueries::DatabaseQueries() {} diff --git a/src/miscellaneous/databasequeries.h b/src/miscellaneous/databasequeries.h index c8444c390..4cd286228 100755 --- a/src/miscellaneous/databasequeries.h +++ b/src/miscellaneous/databasequeries.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -25,106 +26,105 @@ #include - class DatabaseQueries { - public: - // Mark read/unread/starred/delete messages. - static bool markMessagesReadUnread(QSqlDatabase db, const QStringList& ids, RootItem::ReadStatus read); - static bool markMessageImportant(QSqlDatabase db, int id, RootItem::Importance importance); - static bool markFeedsReadUnread(QSqlDatabase db, const QStringList& ids, int account_id, RootItem::ReadStatus read); - static bool markBinReadUnread(QSqlDatabase db, int account_id, RootItem::ReadStatus read); - static bool markAccountReadUnread(QSqlDatabase db, int account_id, RootItem::ReadStatus read); - static bool switchMessagesImportance(QSqlDatabase db, const QStringList& ids); - static bool permanentlyDeleteMessages(QSqlDatabase db, const QStringList& ids); - static bool deleteOrRestoreMessagesToFromBin(QSqlDatabase db, const QStringList& ids, bool deleted); - static bool restoreBin(QSqlDatabase db, int account_id); + public: - // Purge database. - static bool purgeImportantMessages(QSqlDatabase db); - static bool purgeReadMessages(QSqlDatabase db); - static bool purgeOldMessages(QSqlDatabase db, int older_than_days); - static bool purgeRecycleBin(QSqlDatabase db); - static bool purgeMessagesFromBin(QSqlDatabase db, bool clear_only_read, int account_id); - static bool purgeLeftoverMessages(QSqlDatabase db, int account_id); + // Mark read/unread/starred/delete messages. + static bool markMessagesReadUnread(QSqlDatabase db, const QStringList& ids, RootItem::ReadStatus read); + static bool markMessageImportant(QSqlDatabase db, int id, RootItem::Importance importance); + static bool markFeedsReadUnread(QSqlDatabase db, const QStringList& ids, int account_id, RootItem::ReadStatus read); + static bool markBinReadUnread(QSqlDatabase db, int account_id, RootItem::ReadStatus read); + static bool markAccountReadUnread(QSqlDatabase db, int account_id, RootItem::ReadStatus read); + static bool switchMessagesImportance(QSqlDatabase db, const QStringList& ids); + static bool permanentlyDeleteMessages(QSqlDatabase db, const QStringList& ids); + static bool deleteOrRestoreMessagesToFromBin(QSqlDatabase db, const QStringList& ids, bool deleted); + static bool restoreBin(QSqlDatabase db, int account_id); - // Obtain counts of unread/all messages. - static QMap> getMessageCountsForCategory(QSqlDatabase db, int custom_id, int account_id, - bool including_total_counts, bool* ok = nullptr); - static QMap> getMessageCountsForAccount(QSqlDatabase db, int account_id, - bool including_total_counts, bool* ok = nullptr); - static int getMessageCountsForFeed(QSqlDatabase db, int feed_custom_id, int account_id, - bool including_total_counts, bool* ok = nullptr); - static int getMessageCountsForBin(QSqlDatabase db, int account_id, bool including_total_counts, bool* ok = nullptr); + // Purge database. + static bool purgeImportantMessages(QSqlDatabase db); + static bool purgeReadMessages(QSqlDatabase db); + static bool purgeOldMessages(QSqlDatabase db, int older_than_days); + static bool purgeRecycleBin(QSqlDatabase db); + static bool purgeMessagesFromBin(QSqlDatabase db, bool clear_only_read, int account_id); + static bool purgeLeftoverMessages(QSqlDatabase db, int account_id); - // Get messages (for newspaper view for example). - static QList getUndeletedMessagesForFeed(QSqlDatabase db, int feed_custom_id, int account_id, bool* ok = nullptr); - static QList getUndeletedMessagesForBin(QSqlDatabase db, int account_id, bool* ok = nullptr); - static QList getUndeletedMessagesForAccount(QSqlDatabase db, int account_id, bool* ok = nullptr); + // Obtain counts of unread/all messages. + static QMap> getMessageCountsForCategory(QSqlDatabase db, int custom_id, int account_id, + bool including_total_counts, bool* ok = nullptr); + static QMap> getMessageCountsForAccount(QSqlDatabase db, int account_id, + bool including_total_counts, bool* ok = nullptr); + static int getMessageCountsForFeed(QSqlDatabase db, int feed_custom_id, int account_id, + bool including_total_counts, bool* ok = nullptr); + static int getMessageCountsForBin(QSqlDatabase db, int account_id, bool including_total_counts, bool* ok = nullptr); - // Custom ID accumulators. - static QStringList customIdsOfMessagesFromAccount(QSqlDatabase db, int account_id, bool* ok = nullptr); - static QStringList customIdsOfMessagesFromBin(QSqlDatabase db, int account_id, bool* ok = nullptr); - static QStringList customIdsOfMessagesFromFeed(QSqlDatabase db, int feed_custom_id, int account_id, bool* ok = nullptr); + // Get messages (for newspaper view for example). + static QList getUndeletedMessagesForFeed(QSqlDatabase db, int feed_custom_id, int account_id, bool* ok = nullptr); + static QList getUndeletedMessagesForBin(QSqlDatabase db, int account_id, bool* ok = nullptr); + static QList getUndeletedMessagesForAccount(QSqlDatabase db, int account_id, bool* ok = nullptr); - // Common accounts methods. - static int updateMessages(QSqlDatabase db, const QList& messages, int feed_custom_id, - int account_id, const QString& url, bool* any_message_changed, bool* ok = nullptr); - static bool deleteAccount(QSqlDatabase db, int account_id); - static bool deleteAccountData(QSqlDatabase db, int account_id, bool delete_messages_too); - static bool cleanFeeds(QSqlDatabase db, const QStringList& ids, bool clean_read_only, int account_id); + // Custom ID accumulators. + static QStringList customIdsOfMessagesFromAccount(QSqlDatabase db, int account_id, bool* ok = nullptr); + static QStringList customIdsOfMessagesFromBin(QSqlDatabase db, int account_id, bool* ok = nullptr); + static QStringList customIdsOfMessagesFromFeed(QSqlDatabase db, int feed_custom_id, int account_id, bool* ok = nullptr); - static bool storeAccountTree(QSqlDatabase db, RootItem* tree_root, int account_id); - static bool editBaseFeed(QSqlDatabase db, int feed_id, Feed::AutoUpdateType auto_update_type, - int auto_update_interval); + // Common accounts methods. + static int updateMessages(QSqlDatabase db, const QList& messages, int feed_custom_id, + int account_id, const QString& url, bool* any_message_changed, bool* ok = nullptr); + static bool deleteAccount(QSqlDatabase db, int account_id); + static bool deleteAccountData(QSqlDatabase db, int account_id, bool delete_messages_too); + static bool cleanFeeds(QSqlDatabase db, const QStringList& ids, bool clean_read_only, int account_id); + static bool storeAccountTree(QSqlDatabase db, RootItem* tree_root, int account_id); + static bool editBaseFeed(QSqlDatabase db, int feed_id, Feed::AutoUpdateType auto_update_type, + int auto_update_interval); - // ownCloud account. - static QList getOwnCloudAccounts(QSqlDatabase db, bool* ok = nullptr); - static bool deleteOwnCloudAccount(QSqlDatabase db, int account_id); - static bool overwriteOwnCloudAccount(QSqlDatabase db, const QString& username, const QString& password, - const QString& url, bool force_server_side_feed_update, int account_id); - static bool createOwnCloudAccount(QSqlDatabase db, int id_to_assign, const QString& username, const QString& password, - const QString& url, bool force_server_side_feed_update); - static int createAccount(QSqlDatabase db, const QString& code, bool* ok = nullptr); - static Assignment getOwnCloudCategories(QSqlDatabase db, int account_id, bool* ok = nullptr); - static Assignment getOwnCloudFeeds(QSqlDatabase db, int account_id, bool* ok = nullptr); + // ownCloud account. + static QList getOwnCloudAccounts(QSqlDatabase db, bool* ok = nullptr); + static bool deleteOwnCloudAccount(QSqlDatabase db, int account_id); + static bool overwriteOwnCloudAccount(QSqlDatabase db, const QString& username, const QString& password, + const QString& url, bool force_server_side_feed_update, int account_id); + static bool createOwnCloudAccount(QSqlDatabase db, int id_to_assign, const QString& username, const QString& password, + const QString& url, bool force_server_side_feed_update); + static int createAccount(QSqlDatabase db, const QString& code, bool* ok = nullptr); + static Assignment getOwnCloudCategories(QSqlDatabase db, int account_id, bool* ok = nullptr); + static Assignment getOwnCloudFeeds(QSqlDatabase db, int account_id, bool* ok = nullptr); - // Standard account. - static bool deleteFeed(QSqlDatabase db, int feed_custom_id, int account_id); - static bool deleteCategory(QSqlDatabase db, int id); - static int addCategory(QSqlDatabase db, int parent_id, int account_id, const QString& title, - const QString& description, QDateTime creation_date, const QIcon& icon, bool* ok = nullptr); - static bool editCategory(QSqlDatabase db, int parent_id, int category_id, - const QString& title, const QString& description, const QIcon& icon); - static int addFeed(QSqlDatabase db, int parent_id, int account_id, const QString& title, - const QString& description, QDateTime creation_date, const QIcon& icon, - const QString& encoding, const QString& url, bool is_protected, - const QString& username, const QString& password, - Feed::AutoUpdateType auto_update_type, - int auto_update_interval, StandardFeed::Type feed_format, bool* ok = nullptr); - static bool editFeed(QSqlDatabase db, int parent_id, int feed_id, const QString& title, - const QString& description, const QIcon& icon, - const QString& encoding, const QString& url, bool is_protected, - const QString& username, const QString& password, Feed::AutoUpdateType auto_update_type, - int auto_update_interval, StandardFeed::Type feed_format); - static QList getAccounts(QSqlDatabase db, bool* ok = nullptr); - static Assignment getCategories(QSqlDatabase db, int account_id, bool* ok = nullptr); - static Assignment getFeeds(QSqlDatabase db, int account_id, bool* ok = nullptr); + // Standard account. + static bool deleteFeed(QSqlDatabase db, int feed_custom_id, int account_id); + static bool deleteCategory(QSqlDatabase db, int id); + static int addCategory(QSqlDatabase db, int parent_id, int account_id, const QString& title, + const QString& description, QDateTime creation_date, const QIcon& icon, bool* ok = nullptr); + static bool editCategory(QSqlDatabase db, int parent_id, int category_id, + const QString& title, const QString& description, const QIcon& icon); + static int addFeed(QSqlDatabase db, int parent_id, int account_id, const QString& title, + const QString& description, QDateTime creation_date, const QIcon& icon, + const QString& encoding, const QString& url, bool is_protected, + const QString& username, const QString& password, + Feed::AutoUpdateType auto_update_type, + int auto_update_interval, StandardFeed::Type feed_format, bool* ok = nullptr); + static bool editFeed(QSqlDatabase db, int parent_id, int feed_id, const QString& title, + const QString& description, const QIcon& icon, + const QString& encoding, const QString& url, bool is_protected, + const QString& username, const QString& password, Feed::AutoUpdateType auto_update_type, + int auto_update_interval, StandardFeed::Type feed_format); + static QList getAccounts(QSqlDatabase db, bool* ok = nullptr); + static Assignment getCategories(QSqlDatabase db, int account_id, bool* ok = nullptr); + static Assignment getFeeds(QSqlDatabase db, int account_id, bool* ok = nullptr); - // TT-RSS acccount. - static QList getTtRssAccounts(QSqlDatabase db, bool* ok = nullptr); - static bool deleteTtRssAccount(QSqlDatabase db, int account_id); - static bool overwriteTtRssAccount(QSqlDatabase db, const QString& username, const QString& password, - bool auth_protected, const QString& auth_username, const QString& auth_password, - const QString& url, bool force_server_side_feed_update, int account_id); - static bool createTtRssAccount(QSqlDatabase db, int id_to_assign, const QString& username, - const QString& password, bool auth_protected, const QString& auth_username, - const QString& auth_password, const QString& url, - bool force_server_side_feed_update); - static Assignment getTtRssCategories(QSqlDatabase db, int account_id, bool* ok = nullptr); - static Assignment getTtRssFeeds(QSqlDatabase db, int account_id, bool* ok = nullptr); + // TT-RSS acccount. + static QList getTtRssAccounts(QSqlDatabase db, bool* ok = nullptr); + static bool deleteTtRssAccount(QSqlDatabase db, int account_id); + static bool overwriteTtRssAccount(QSqlDatabase db, const QString& username, const QString& password, + bool auth_protected, const QString& auth_username, const QString& auth_password, + const QString& url, bool force_server_side_feed_update, int account_id); + static bool createTtRssAccount(QSqlDatabase db, int id_to_assign, const QString& username, + const QString& password, bool auth_protected, const QString& auth_username, + const QString& auth_password, const QString& url, + bool force_server_side_feed_update); + static Assignment getTtRssCategories(QSqlDatabase db, int account_id, bool* ok = nullptr); + static Assignment getTtRssFeeds(QSqlDatabase db, int account_id, bool* ok = nullptr); - private: - explicit DatabaseQueries(); + private: + explicit DatabaseQueries(); }; #endif // DATABASEQUERIES_H diff --git a/src/miscellaneous/debugging.cpp b/src/miscellaneous/debugging.cpp index 63faf9a58..bb1d8a498 100755 --- a/src/miscellaneous/debugging.cpp +++ b/src/miscellaneous/debugging.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,58 +22,58 @@ #include +#include #include #include -#include #include - -Debugging::Debugging() { -} +Debugging::Debugging() {} void Debugging::performLog(const char* message, QtMsgType type, const char* file, const char* function, int line) { - const char* type_string = typeToString(type); - std::time_t t = std::time(nullptr); - char mbstr[32]; - std::strftime(mbstr, sizeof(mbstr), "%y/%d/%m %H:%M:%S", std::localtime(&t)); + const char* type_string = typeToString(type); - // Write to console. - if (file == 0 || function == 0 || line < 0) { - fprintf(stderr, "[%s] %s: %s (%s)\n", APP_LOW_NAME, type_string, message, mbstr); - } - else { - fprintf(stderr, "[%s] %s (%s)\n Type: %s\n File: %s (line %d)\n Function: %s\n\n", - APP_LOW_NAME, message, mbstr, type_string, file, line, function); - } + std::time_t t = std::time(nullptr); + char mbstr[32]; - if (type == QtFatalMsg) { - qApp->exit(EXIT_FAILURE); - } + std::strftime(mbstr, sizeof(mbstr), "%y/%d/%m %H:%M:%S", std::localtime(&t)); + + // Write to console. + if (file == 0 || function == 0 || line < 0) { + fprintf(stderr, "[%s] %s: %s (%s)\n", APP_LOW_NAME, type_string, message, mbstr); + } + else { + fprintf(stderr, "[%s] %s (%s)\n Type: %s\n File: %s (line %d)\n Function: %s\n\n", + APP_LOW_NAME, message, mbstr, type_string, file, line, function); + } + + if (type == QtFatalMsg) { + qApp->exit(EXIT_FAILURE); + } } const char* Debugging::typeToString(QtMsgType type) { - switch (type) { - case QtDebugMsg: - return "DEBUG"; + switch (type) { + case QtDebugMsg: + return "DEBUG"; - case QtWarningMsg: - return "WARNING"; + case QtWarningMsg: + return "WARNING"; - case QtCriticalMsg: - return "CRITICAL"; + case QtCriticalMsg: + return "CRITICAL"; - case QtFatalMsg: - default: - return "FATAL (terminating application)"; - } + case QtFatalMsg: + default: + return "FATAL (terminating application)"; + } } void Debugging::debugHandler(QtMsgType type, const QMessageLogContext& placement, const QString& message) { #ifndef QT_NO_DEBUG_OUTPUT - performLog(qPrintable(message), type, placement.file, placement.function, placement.line); + performLog(qPrintable(message), type, placement.file, placement.function, placement.line); #else - Q_UNUSED(type) - Q_UNUSED(placement) - Q_UNUSED(message) + Q_UNUSED(type) + Q_UNUSED(placement) + Q_UNUSED(message) #endif } diff --git a/src/miscellaneous/debugging.h b/src/miscellaneous/debugging.h index 02f5e9a4f..062e9e842 100755 --- a/src/miscellaneous/debugging.h +++ b/src/miscellaneous/debugging.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,18 +21,19 @@ #include - class Debugging { - public: - // Specifies format of output console messages. - // NOTE: QT_NO_DEBUG_OUTPUT - disables debug outputs completely!!! - static void debugHandler(QtMsgType type, const QMessageLogContext& placement, const QString& message); - static void performLog(const char* message, QtMsgType type, const char* file = 0, const char* function = 0, int line = -1); - static const char* typeToString(QtMsgType type); + public: - private: - // Constructor. - explicit Debugging(); + // Specifies format of output console messages. + // NOTE: QT_NO_DEBUG_OUTPUT - disables debug outputs completely!!! + static void debugHandler(QtMsgType type, const QMessageLogContext& placement, const QString& message); + static void performLog(const char* message, QtMsgType type, const char* file = 0, const char* function = 0, int line = -1); + static const char* typeToString(QtMsgType type); + + private: + + // Constructor. + explicit Debugging(); }; #endif // DEBUGGING_H diff --git a/src/miscellaneous/externaltool.cpp b/src/miscellaneous/externaltool.cpp old mode 100644 new mode 100755 index 0a60e67ad..ac47ff9f8 --- a/src/miscellaneous/externaltool.cpp +++ b/src/miscellaneous/externaltool.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,12 +19,11 @@ #include "miscellaneous/externaltool.h" #include "definitions/definitions.h" -#include "miscellaneous/application.h" #include "exceptions/applicationexception.h" +#include "miscellaneous/application.h" -#include #include - +#include void ExternalTool::sanitizeParameters() { m_executable = QDir::toNativeSeparators(m_executable); @@ -31,11 +31,9 @@ void ExternalTool::sanitizeParameters() { m_parameters.removeAll(QString()); } -ExternalTool::ExternalTool() { -} +ExternalTool::ExternalTool() {} -ExternalTool::ExternalTool(const ExternalTool& other) : ExternalTool(other.executable(), other.parameters()) { -} +ExternalTool::ExternalTool(const ExternalTool& other) : ExternalTool(other.executable(), other.parameters()) {} ExternalTool::ExternalTool(const QString& executable, const QStringList& parameters) : m_executable(executable), m_parameters(parameters) { @@ -71,6 +69,7 @@ ExternalTool ExternalTool::fromString(const QString& str) { QList ExternalTool::toolsFromSettings() { QStringList tools_encoded = qApp->settings()->value(GROUP(Browser), SETTING(Browser::ExternalTools)).toStringList(); + QList tools; foreach (const QString& tool_encoded, tools_encoded) { diff --git a/src/miscellaneous/externaltool.h b/src/miscellaneous/externaltool.h old mode 100644 new mode 100755 index de445894f..c692396f3 --- a/src/miscellaneous/externaltool.h +++ b/src/miscellaneous/externaltool.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,9 +19,8 @@ #ifndef EXTERNALTOOL_H #define EXTERNALTOOL_H -#include #include - +#include class ExternalTool { public: @@ -39,6 +39,7 @@ class ExternalTool { private: QString m_executable; QStringList m_parameters; + void sanitizeParameters(); }; diff --git a/src/miscellaneous/feedreader.cpp b/src/miscellaneous/feedreader.cpp index 2350085f4..af75f98cf 100755 --- a/src/miscellaneous/feedreader.cpp +++ b/src/miscellaneous/feedreader.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,198 +18,199 @@ #include "miscellaneous/feedreader.h" -#include "services/standard/standardserviceentrypoint.h" -#include "services/owncloud/owncloudserviceentrypoint.h" -#include "services/tt-rss/ttrssserviceentrypoint.h" #include "services/abstract/serviceroot.h" +#include "services/owncloud/owncloudserviceentrypoint.h" +#include "services/standard/standardserviceentrypoint.h" +#include "services/tt-rss/ttrssserviceentrypoint.h" +#include "core/feeddownloader.h" #include "core/feedsmodel.h" #include "core/feedsproxymodel.h" #include "core/messagesmodel.h" #include "core/messagesproxymodel.h" -#include "core/feeddownloader.h" -#include "miscellaneous/databasecleaner.h" #include "miscellaneous/application.h" +#include "miscellaneous/databasecleaner.h" #include "miscellaneous/mutex.h" +#include #include #include -#include - FeedReader::FeedReader(QObject* parent) - : QObject(parent), m_feedServices(QList()), - m_autoUpdateTimer(new QTimer(this)), - m_feedDownloaderThread(nullptr), m_feedDownloader(nullptr), - m_dbCleanerThread(nullptr), m_dbCleaner(nullptr) { - m_feedsModel = new FeedsModel(this); - m_feedsProxyModel = new FeedsProxyModel(m_feedsModel, this); - m_messagesModel = new MessagesModel(this); - m_messagesProxyModel = new MessagesProxyModel(m_messagesModel, this); - connect(m_autoUpdateTimer, &QTimer::timeout, this, &FeedReader::executeNextAutoUpdate); - updateAutoUpdateStatus(); - asyncCacheSaveFinished(); + : QObject(parent), m_feedServices(QList()), + m_autoUpdateTimer(new QTimer(this)), + m_feedDownloaderThread(nullptr), m_feedDownloader(nullptr), + m_dbCleanerThread(nullptr), m_dbCleaner(nullptr) { + m_feedsModel = new FeedsModel(this); + m_feedsProxyModel = new FeedsProxyModel(m_feedsModel, this); + m_messagesModel = new MessagesModel(this); + m_messagesProxyModel = new MessagesProxyModel(m_messagesModel, this); + connect(m_autoUpdateTimer, &QTimer::timeout, this, &FeedReader::executeNextAutoUpdate); + updateAutoUpdateStatus(); + asyncCacheSaveFinished(); - if (qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool()) { - qDebug("Requesting update for all feeds on application startup."); - QTimer::singleShot(STARTUP_UPDATE_DELAY, this, SLOT(updateAllFeeds())); - } + if (qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool()) { + qDebug("Requesting update for all feeds on application startup."); + QTimer::singleShot(STARTUP_UPDATE_DELAY, this, SLOT(updateAllFeeds())); + } } FeedReader::~FeedReader() { - qDebug("Destroying FeedReader instance."); - qDeleteAll(m_feedServices); + qDebug("Destroying FeedReader instance."); + qDeleteAll(m_feedServices); } QList FeedReader::feedServices() { - if (m_feedServices.isEmpty()) { - // NOTE: All installed services create their entry points here. - m_feedServices.append(new StandardServiceEntryPoint()); - m_feedServices.append(new TtRssServiceEntryPoint()); - m_feedServices.append(new OwnCloudServiceEntryPoint()); - } + if (m_feedServices.isEmpty()) { + // NOTE: All installed services create their entry points here. + m_feedServices.append(new StandardServiceEntryPoint()); + m_feedServices.append(new TtRssServiceEntryPoint()); + m_feedServices.append(new OwnCloudServiceEntryPoint()); + } - return m_feedServices; + return m_feedServices; } void FeedReader::updateFeeds(const QList& feeds) { - if (!qApp->feedUpdateLock()->tryLock()) { - qApp->showGuiMessage(tr("Cannot update all items"), - tr("You cannot update all items because another critical operation is ongoing."), - QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - return; - } + if (!qApp->feedUpdateLock()->tryLock()) { + qApp->showGuiMessage(tr("Cannot update all items"), + tr("You cannot update all items because another critical operation is ongoing."), + QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); + return; + } - if (m_feedDownloader == nullptr) { - m_feedDownloader = new FeedDownloader(); - m_feedDownloaderThread = new QThread(); + if (m_feedDownloader == nullptr) { + m_feedDownloader = new FeedDownloader(); + m_feedDownloaderThread = new QThread(); - // Downloader setup. - qRegisterMetaType>("QList"); - m_feedDownloader->moveToThread(m_feedDownloaderThread); + // Downloader setup. + qRegisterMetaType>("QList"); + m_feedDownloader->moveToThread(m_feedDownloaderThread); connect(m_feedDownloaderThread, &QThread::finished, m_feedDownloaderThread, &QThread::deleteLater); - connect(m_feedDownloader, &FeedDownloader::updateFinished, this, &FeedReader::feedUpdatesFinished); - connect(m_feedDownloader, &FeedDownloader::updateProgress, this, &FeedReader::feedUpdatesProgress); - connect(m_feedDownloader, &FeedDownloader::updateStarted, this, &FeedReader::feedUpdatesStarted); - connect(m_feedDownloader, &FeedDownloader::updateFinished, qApp->feedUpdateLock(), &Mutex::unlock); + connect(m_feedDownloader, &FeedDownloader::updateFinished, this, &FeedReader::feedUpdatesFinished); + connect(m_feedDownloader, &FeedDownloader::updateProgress, this, &FeedReader::feedUpdatesProgress); + connect(m_feedDownloader, &FeedDownloader::updateStarted, this, &FeedReader::feedUpdatesStarted); + connect(m_feedDownloader, &FeedDownloader::updateFinished, qApp->feedUpdateLock(), &Mutex::unlock); - // Connections are made, start the feed downloader thread. - m_feedDownloaderThread->start(); - } + // Connections are made, start the feed downloader thread. + m_feedDownloaderThread->start(); + } - QMetaObject::invokeMethod(m_feedDownloader, "updateFeeds", Q_ARG(QList, feeds)); + QMetaObject::invokeMethod(m_feedDownloader, "updateFeeds", Q_ARG(QList, feeds)); } void FeedReader::updateAutoUpdateStatus() { - // Restore global intervals. - // NOTE: Specific per-feed interval are left intact. - m_globalAutoUpdateInitialInterval = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateInterval)).toInt(); - m_globalAutoUpdateRemainingInterval = m_globalAutoUpdateInitialInterval; - m_globalAutoUpdateEnabled = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateEnabled)).toBool(); + // Restore global intervals. + // NOTE: Specific per-feed interval are left intact. + m_globalAutoUpdateInitialInterval = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateInterval)).toInt(); + m_globalAutoUpdateRemainingInterval = m_globalAutoUpdateInitialInterval; + m_globalAutoUpdateEnabled = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateEnabled)).toBool(); - // Start global auto-update timer if it is not running yet. - // NOTE: The timer must run even if global auto-update - // is not enabled because user can still enable auto-update - // for individual feeds. - if (!m_autoUpdateTimer->isActive()) { - m_autoUpdateTimer->setInterval(AUTO_UPDATE_INTERVAL); - m_autoUpdateTimer->start(); - qDebug("Auto-update timer started with interval %d.", m_autoUpdateTimer->interval()); - } - else { - qDebug("Auto-update timer is already running."); - } + // Start global auto-update timer if it is not running yet. + // NOTE: The timer must run even if global auto-update + // is not enabled because user can still enable auto-update + // for individual feeds. + if (!m_autoUpdateTimer->isActive()) { + m_autoUpdateTimer->setInterval(AUTO_UPDATE_INTERVAL); + m_autoUpdateTimer->start(); + qDebug("Auto-update timer started with interval %d.", m_autoUpdateTimer->interval()); + } + else { + qDebug("Auto-update timer is already running."); + } } bool FeedReader::autoUpdateEnabled() const { - return m_globalAutoUpdateEnabled; + return m_globalAutoUpdateEnabled; } int FeedReader::autoUpdateRemainingInterval() const { - return m_globalAutoUpdateRemainingInterval; + return m_globalAutoUpdateRemainingInterval; } int FeedReader::autoUpdateInitialInterval() const { - return m_globalAutoUpdateInitialInterval; + return m_globalAutoUpdateInitialInterval; } void FeedReader::updateAllFeeds() { - updateFeeds(m_feedsModel->rootItem()->getSubTreeFeeds()); + updateFeeds(m_feedsModel->rootItem()->getSubTreeFeeds()); } void FeedReader::stopRunningFeedUpdate() { - if (m_feedDownloader != nullptr) { - QMetaObject::invokeMethod(m_feedDownloader, "stopRunningUpdate"); - } + if (m_feedDownloader != nullptr) { + QMetaObject::invokeMethod(m_feedDownloader, "stopRunningUpdate"); + } } bool FeedReader::isFeedUpdateRunning() const { - return m_feedDownloader != nullptr && m_feedDownloader->isUpdateRunning(); + return m_feedDownloader != nullptr && m_feedDownloader->isUpdateRunning(); } DatabaseCleaner* FeedReader::databaseCleaner() { - if (m_dbCleaner == nullptr) { - m_dbCleaner = new DatabaseCleaner(); - m_dbCleanerThread = new QThread(); + if (m_dbCleaner == nullptr) { + m_dbCleaner = new DatabaseCleaner(); + m_dbCleanerThread = new QThread(); - // Downloader setup. - qRegisterMetaType("CleanerOrders"); - m_dbCleaner->moveToThread(m_dbCleanerThread); - connect(m_dbCleanerThread, SIGNAL(finished()), m_dbCleanerThread, SLOT(deleteLater())); + // Downloader setup. + qRegisterMetaType("CleanerOrders"); + m_dbCleaner->moveToThread(m_dbCleanerThread); + connect(m_dbCleanerThread, SIGNAL(finished()), m_dbCleanerThread, SLOT(deleteLater())); - // Connections are made, start the feed downloader thread. - m_dbCleanerThread->start(); - } + // Connections are made, start the feed downloader thread. + m_dbCleanerThread->start(); + } - return m_dbCleaner; + return m_dbCleaner; } FeedDownloader* FeedReader::feedDownloader() const { - return m_feedDownloader; + return m_feedDownloader; } FeedsModel* FeedReader::feedsModel() const { - return m_feedsModel; + return m_feedsModel; } MessagesModel* FeedReader::messagesModel() const { - return m_messagesModel; + return m_messagesModel; } void FeedReader::executeNextAutoUpdate() { - if (!qApp->feedUpdateLock()->tryLock()) { - qDebug("Delaying scheduled feed auto-updates for one minute due to another running update."); - // Cannot update, quit. - return; - } + if (!qApp->feedUpdateLock()->tryLock()) { + qDebug("Delaying scheduled feed auto-updates for one minute due to another running update."); - // If global auto-update is enabled and its interval counter reached zero, - // then we need to restore it. - if (m_globalAutoUpdateEnabled && --m_globalAutoUpdateRemainingInterval < 0) { - // We should start next auto-update interval. - m_globalAutoUpdateRemainingInterval = m_globalAutoUpdateInitialInterval; - } + // Cannot update, quit. + return; + } - qDebug("Starting auto-update event, pass %d/%d.", m_globalAutoUpdateRemainingInterval, m_globalAutoUpdateInitialInterval); - // Pass needed interval data and lets the model decide which feeds - // should be updated in this pass. - QList feeds_for_update = m_feedsModel->feedsForScheduledUpdate(m_globalAutoUpdateEnabled && - m_globalAutoUpdateRemainingInterval == 0); - qApp->feedUpdateLock()->unlock(); + // If global auto-update is enabled and its interval counter reached zero, + // then we need to restore it. + if (m_globalAutoUpdateEnabled && --m_globalAutoUpdateRemainingInterval < 0) { + // We should start next auto-update interval. + m_globalAutoUpdateRemainingInterval = m_globalAutoUpdateInitialInterval; + } - if (!feeds_for_update.isEmpty()) { - // Request update for given feeds. - updateFeeds(feeds_for_update); + qDebug("Starting auto-update event, pass %d/%d.", m_globalAutoUpdateRemainingInterval, m_globalAutoUpdateInitialInterval); - // NOTE: OSD/bubble informing about performing - // of scheduled update can be shown now. - if (qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::EnableAutoUpdateNotification)).toBool()) { - qApp->showGuiMessage(tr("Starting auto-update of some feeds"), - tr("I will auto-update %n feed(s).", 0, feeds_for_update.size()), - QSystemTrayIcon::Information); - } - } + // Pass needed interval data and lets the model decide which feeds + // should be updated in this pass. + QList feeds_for_update = m_feedsModel->feedsForScheduledUpdate(m_globalAutoUpdateEnabled && + m_globalAutoUpdateRemainingInterval == 0); + qApp->feedUpdateLock()->unlock(); + + if (!feeds_for_update.isEmpty()) { + // Request update for given feeds. + updateFeeds(feeds_for_update); + + // NOTE: OSD/bubble informing about performing + // of scheduled update can be shown now. + if (qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::EnableAutoUpdateNotification)).toBool()) { + qApp->showGuiMessage(tr("Starting auto-update of some feeds"), + tr("I will auto-update %n feed(s).", 0, feeds_for_update.size()), + QSystemTrayIcon::Information); + } + } } void FeedReader::checkServicesForAsyncOperations() { @@ -221,69 +223,70 @@ void FeedReader::checkServicesForAsyncOperations() { } void FeedReader::asyncCacheSaveFinished() { - qDebug("I will start next check for cached service data in 30 seconds."); + qDebug("I will start next check for cached service data in 30 seconds."); QTimer::singleShot(60000, [&] { - qDebug("Starting next check for cached service data in NOW."); + qDebug("Starting next check for cached service data in NOW."); checkServicesForAsyncOperations(); - }); + }); } void FeedReader::quit() { - if (m_autoUpdateTimer->isActive()) { - m_autoUpdateTimer->stop(); - } + if (m_autoUpdateTimer->isActive()) { + m_autoUpdateTimer->stop(); + } // Close worker threads. - if (m_feedDownloaderThread != nullptr && m_feedDownloaderThread->isRunning()) { - m_feedDownloader->stopRunningUpdate(); + if (m_feedDownloaderThread != nullptr && m_feedDownloaderThread->isRunning()) { + m_feedDownloader->stopRunningUpdate(); - if (m_feedDownloader->isUpdateRunning()) { - QEventLoop loop(this); - connect(m_feedDownloader, &FeedDownloader::updateFinished, &loop, &QEventLoop::quit); - loop.exec(); - } + if (m_feedDownloader->isUpdateRunning()) { + QEventLoop loop(this); - qDebug("Quitting feed downloader thread."); - m_feedDownloaderThread->quit(); + connect(m_feedDownloader, &FeedDownloader::updateFinished, &loop, &QEventLoop::quit); + loop.exec(); + } - if (!m_feedDownloaderThread->wait(CLOSE_LOCK_TIMEOUT)) { - qCritical("Feed downloader thread is running despite it was told to quit. Terminating it."); - m_feedDownloaderThread->terminate(); - } - } + qDebug("Quitting feed downloader thread."); + m_feedDownloaderThread->quit(); - if (m_dbCleanerThread != nullptr && m_dbCleanerThread->isRunning()) { - qDebug("Quitting database cleaner thread."); - m_dbCleanerThread->quit(); + if (!m_feedDownloaderThread->wait(CLOSE_LOCK_TIMEOUT)) { + qCritical("Feed downloader thread is running despite it was told to quit. Terminating it."); + m_feedDownloaderThread->terminate(); + } + } - if (!m_dbCleanerThread->wait(CLOSE_LOCK_TIMEOUT)) { - qCritical("Database cleaner thread is running despite it was told to quit. Terminating it."); - m_dbCleanerThread->terminate(); - } - } + if (m_dbCleanerThread != nullptr && m_dbCleanerThread->isRunning()) { + qDebug("Quitting database cleaner thread."); + m_dbCleanerThread->quit(); - // Close workers. - if (m_feedDownloader != nullptr) { - qDebug("Feed downloader exists. Deleting it from memory."); - m_feedDownloader->deleteLater(); - } + if (!m_dbCleanerThread->wait(CLOSE_LOCK_TIMEOUT)) { + qCritical("Database cleaner thread is running despite it was told to quit. Terminating it."); + m_dbCleanerThread->terminate(); + } + } - if (m_dbCleaner != nullptr) { - qDebug("Database cleaner exists. Deleting it from memory."); - m_dbCleaner->deleteLater(); - } + // Close workers. + if (m_feedDownloader != nullptr) { + qDebug("Feed downloader exists. Deleting it from memory."); + m_feedDownloader->deleteLater(); + } - if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool()) { - m_feedsModel->markItemCleared(m_feedsModel->rootItem(), true); - } + if (m_dbCleaner != nullptr) { + qDebug("Database cleaner exists. Deleting it from memory."); + m_dbCleaner->deleteLater(); + } - m_feedsModel->stopServiceAccounts(); + if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool()) { + m_feedsModel->markItemCleared(m_feedsModel->rootItem(), true); + } + + m_feedsModel->stopServiceAccounts(); } MessagesProxyModel* FeedReader::messagesProxyModel() const { - return m_messagesProxyModel; + return m_messagesProxyModel; } FeedsProxyModel* FeedReader::feedsProxyModel() const { - return m_feedsProxyModel; + return m_feedsProxyModel; } diff --git a/src/miscellaneous/feedreader.h b/src/miscellaneous/feedreader.h index 5515c5069..daf2ad670 100755 --- a/src/miscellaneous/feedreader.h +++ b/src/miscellaneous/feedreader.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,12 +21,11 @@ #include -#include "services/abstract/feed.h" #include "core/feeddownloader.h" +#include "services/abstract/feed.h" #include - class FeedsModel; class MessagesModel; class MessagesProxyModel; @@ -35,75 +35,74 @@ class DatabaseCleaner; class QTimer; class FeedReader : public QObject { - Q_OBJECT + Q_OBJECT - public: - explicit FeedReader(QObject* parent = 0); - virtual ~FeedReader(); + public: + explicit FeedReader(QObject* parent = 0); + virtual ~FeedReader(); - // List of all installed "feed service plugins", including obligatory - // "standard" service entry point. - QList feedServices(); + // List of all installed "feed service plugins", including obligatory + // "standard" service entry point. + QList feedServices(); - // Access to DB cleaner. - DatabaseCleaner* databaseCleaner(); + // Access to DB cleaner. + DatabaseCleaner* databaseCleaner(); + FeedDownloader* feedDownloader() const; + FeedsModel* feedsModel() const; + MessagesModel* messagesModel() const; + FeedsProxyModel* feedsProxyModel() const; + MessagesProxyModel* messagesProxyModel() const; - FeedDownloader* feedDownloader() const; - FeedsModel* feedsModel() const; - MessagesModel* messagesModel() const; - FeedsProxyModel* feedsProxyModel() const; - MessagesProxyModel* messagesProxyModel() const; + // Schedules given feeds for update. + void updateFeeds(const QList& feeds); - // Schedules given feeds for update. - void updateFeeds(const QList& feeds); + // True if feed update is running right now. + bool isFeedUpdateRunning() const; - // True if feed update is running right now. - bool isFeedUpdateRunning() const; + // Resets global auto-update intervals according to settings + // and starts/stop the timer as needed. + void updateAutoUpdateStatus(); - // Resets global auto-update intervals according to settings - // and starts/stop the timer as needed. - void updateAutoUpdateStatus(); + bool autoUpdateEnabled() const; + int autoUpdateRemainingInterval() const; + int autoUpdateInitialInterval() const; - bool autoUpdateEnabled() const; - int autoUpdateRemainingInterval() const; - int autoUpdateInitialInterval() const; + public slots: - public slots: - // Schedules all feeds from all accounts for update. - void updateAllFeeds(); - void stopRunningFeedUpdate(); - void quit(); + // Schedules all feeds from all accounts for update. + void updateAllFeeds(); + void stopRunningFeedUpdate(); + void quit(); - private slots: - // Is executed when next auto-update round could be done. - void executeNextAutoUpdate(); - void checkServicesForAsyncOperations(); - void asyncCacheSaveFinished(); + private slots: - signals: - void feedUpdatesStarted(); - void feedUpdatesFinished(FeedDownloadResults updated_feeds); - void feedUpdatesProgress(const Feed* feed, int current, int total); + // Is executed when next auto-update round could be done. + void executeNextAutoUpdate(); + void checkServicesForAsyncOperations(); + void asyncCacheSaveFinished(); - private: - QList m_feedServices; + signals: + void feedUpdatesStarted(); + void feedUpdatesFinished(FeedDownloadResults updated_feeds); + void feedUpdatesProgress(const Feed* feed, int current, int total); - FeedsModel* m_feedsModel; - FeedsProxyModel* m_feedsProxyModel; - MessagesModel* m_messagesModel; - MessagesProxyModel* m_messagesProxyModel; + private: + QList m_feedServices; - // Auto-update stuff. - QTimer* m_autoUpdateTimer; - bool m_globalAutoUpdateEnabled; - int m_globalAutoUpdateInitialInterval; - int m_globalAutoUpdateRemainingInterval; + FeedsModel* m_feedsModel; + FeedsProxyModel* m_feedsProxyModel; + MessagesModel* m_messagesModel; + MessagesProxyModel* m_messagesProxyModel; - QThread* m_feedDownloaderThread; - FeedDownloader* m_feedDownloader; - - QThread* m_dbCleanerThread; - DatabaseCleaner* m_dbCleaner; + // Auto-update stuff. + QTimer* m_autoUpdateTimer; + bool m_globalAutoUpdateEnabled; + int m_globalAutoUpdateInitialInterval; + int m_globalAutoUpdateRemainingInterval; + QThread* m_feedDownloaderThread; + FeedDownloader* m_feedDownloader; + QThread* m_dbCleanerThread; + DatabaseCleaner* m_dbCleaner; }; #endif // FEEDREADER_H diff --git a/src/miscellaneous/iconfactory.cpp b/src/miscellaneous/iconfactory.cpp index c171b139f..a60b3eba0 100755 --- a/src/miscellaneous/iconfactory.cpp +++ b/src/miscellaneous/iconfactory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,124 +22,129 @@ #include - -IconFactory::IconFactory(QObject* parent) : QObject(parent) { -} +IconFactory::IconFactory(QObject* parent) : QObject(parent) {} IconFactory::~IconFactory() { - qDebug("Destroying IconFactory instance."); + qDebug("Destroying IconFactory instance."); } QIcon IconFactory::fromByteArray(QByteArray array) { - array = QByteArray::fromBase64(array); - QIcon icon; - QBuffer buffer(&array); - buffer.open(QIODevice::ReadOnly); - QDataStream in(&buffer); - in.setVersion(QDataStream::Qt_4_7); - in >> icon; - buffer.close(); - return icon; + array = QByteArray::fromBase64(array); + QIcon icon; + QBuffer buffer(&array); + + buffer.open(QIODevice::ReadOnly); + QDataStream in(&buffer); + + in.setVersion(QDataStream::Qt_4_7); + in >> icon; + buffer.close(); + return icon; } QByteArray IconFactory::toByteArray(const QIcon& icon) { - QByteArray array; - QBuffer buffer(&array); - buffer.open(QIODevice::WriteOnly); - QDataStream out(&buffer); - out.setVersion(QDataStream::Qt_4_7); - out << icon; - buffer.close(); - return array.toBase64(); + QByteArray array; + QBuffer buffer(&array); + + buffer.open(QIODevice::WriteOnly); + QDataStream out(&buffer); + + out.setVersion(QDataStream::Qt_4_7); + out << icon; + buffer.close(); + return array.toBase64(); } QPixmap IconFactory::pixmap(const QString& name) { - if (QIcon::themeName() == APP_NO_THEME) { - return QPixmap(); - } - else { - return QIcon::fromTheme(name).pixmap(64, 64); - } + if (QIcon::themeName() == APP_NO_THEME) { + return QPixmap(); + } + else { + return QIcon::fromTheme(name).pixmap(64, 64); + } } QIcon IconFactory::fromTheme(const QString& name) { - return QIcon::fromTheme(name); + return QIcon::fromTheme(name); } QPixmap IconFactory::miscPixmap(const QString& name) { - return QPixmap(QString(APP_THEME_PATH) + QDir::separator() + "misc" + QDir::separator() + name + ".png"); + return QPixmap(QString(APP_THEME_PATH) + QDir::separator() + "misc" + QDir::separator() + name + ".png"); } QIcon IconFactory::miscIcon(const QString& name) { - return QIcon(QString(APP_THEME_PATH) + QDir::separator() + "misc" + QDir::separator() + name + ".png"); + return QIcon(QString(APP_THEME_PATH) + QDir::separator() + "misc" + QDir::separator() + name + ".png"); } void IconFactory::setupSearchPaths() { - QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << APP_THEME_PATH); - qDebug("Available icon theme paths: %s.", - qPrintable(QIcon::themeSearchPaths() - .replaceInStrings(QRegExp(QSL("^|$")), QSL("\'")) - .replaceInStrings(QRegExp(QSL("/")), QDir::separator()).join(QSL(", ")))); + QIcon::setThemeSearchPaths(QIcon::themeSearchPaths() << APP_THEME_PATH); + qDebug("Available icon theme paths: %s.", + qPrintable(QIcon::themeSearchPaths() + .replaceInStrings(QRegExp(QSL("^|$")), QSL("\'")) + .replaceInStrings(QRegExp(QSL("/")), QDir::separator()).join(QSL(", ")))); } void IconFactory::setCurrentIconTheme(const QString& theme_name) { - qApp->settings()->setValue(GROUP(GUI), GUI::IconTheme, theme_name); + qApp->settings()->setValue(GROUP(GUI), GUI::IconTheme, theme_name); } void IconFactory::loadCurrentIconTheme() { - const QStringList installed_themes = installedIconThemes(); - const QString theme_name_from_settings = qApp->settings()->value(GROUP(GUI), SETTING(GUI::IconTheme)).toString(); + const QStringList installed_themes = installedIconThemes(); + const QString theme_name_from_settings = qApp->settings()->value(GROUP(GUI), SETTING(GUI::IconTheme)).toString(); - if (QIcon::themeName() == theme_name_from_settings) { - qDebug("Icon theme '%s' already loaded.", qPrintable(theme_name_from_settings)); - return; - } + if (QIcon::themeName() == theme_name_from_settings) { + qDebug("Icon theme '%s' already loaded.", qPrintable(theme_name_from_settings)); + return; + } - // Display list of installed themes. - qDebug("Installed icon themes are: %s.", - qPrintable(QStringList(installed_themes) - .replaceInStrings(QRegExp(QSL("^|$")), QSL("\'")) - .replaceInStrings(QRegExp(QSL("^\\'$")), QSL("\'\'")).join(QSL(", ")))); + // Display list of installed themes. + qDebug("Installed icon themes are: %s.", + qPrintable(QStringList(installed_themes) + .replaceInStrings(QRegExp(QSL("^|$")), QSL("\'")) + .replaceInStrings(QRegExp(QSL("^\\'$")), QSL("\'\'")).join(QSL(", ")))); - if (installed_themes.contains(theme_name_from_settings)) { - // Desired icon theme is installed and can be loaded. - qDebug("Loading icon theme '%s'.", qPrintable(theme_name_from_settings)); - QIcon::setThemeName(theme_name_from_settings); - } - else { - // Desired icon theme is not currently available. - // Install "default" icon theme instead. - qWarning("Icon theme '%s' cannot be loaded because it is not installed. No icon theme (or default icon theme) is loaded now.", - qPrintable(theme_name_from_settings)); - QIcon::setThemeName(APP_NO_THEME); - } + if (installed_themes.contains(theme_name_from_settings)) { + // Desired icon theme is installed and can be loaded. + qDebug("Loading icon theme '%s'.", qPrintable(theme_name_from_settings)); + QIcon::setThemeName(theme_name_from_settings); + } + else { + // Desired icon theme is not currently available. + // Install "default" icon theme instead. + qWarning("Icon theme '%s' cannot be loaded because it is not installed. No icon theme (or default icon theme) is loaded now.", + qPrintable(theme_name_from_settings)); + QIcon::setThemeName(APP_NO_THEME); + } } QStringList IconFactory::installedIconThemes() const { - QStringList icon_theme_names; - icon_theme_names << APP_NO_THEME; - // Iterate all directories with icon themes. - QStringList icon_themes_paths = QIcon::themeSearchPaths(); - QStringList filters_index; - filters_index.append("index.theme"); - icon_themes_paths.removeDuplicates(); + QStringList icon_theme_names; - foreach (const QString& icon_path, icon_themes_paths) { - const QDir icon_dir(icon_path); + icon_theme_names << APP_NO_THEME; - // Iterate all icon themes in this directory. - foreach (const QFileInfo& icon_theme_path, icon_dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | - QDir::Readable | QDir::CaseSensitive | - QDir::NoSymLinks, - QDir::Time)) { - QDir icon_theme_dir = QDir(icon_theme_path.absoluteFilePath()); + // Iterate all directories with icon themes. + QStringList icon_themes_paths = QIcon::themeSearchPaths(); + QStringList filters_index; - if (icon_theme_dir.exists(filters_index.at(0))) { - icon_theme_names << icon_theme_dir.dirName(); - } - } - } + filters_index.append("index.theme"); + icon_themes_paths.removeDuplicates(); - icon_theme_names.removeDuplicates(); - return icon_theme_names; + foreach (const QString& icon_path, icon_themes_paths) { + const QDir icon_dir(icon_path); + + // Iterate all icon themes in this directory. + foreach (const QFileInfo& icon_theme_path, icon_dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | + QDir::Readable | QDir::CaseSensitive | + QDir::NoSymLinks, + QDir::Time)) { + QDir icon_theme_dir = QDir(icon_theme_path.absoluteFilePath()); + + if (icon_theme_dir.exists(filters_index.at(0))) { + icon_theme_names << icon_theme_dir.dirName(); + } + } + } + + icon_theme_names.removeDuplicates(); + return icon_theme_names; } diff --git a/src/miscellaneous/iconfactory.h b/src/miscellaneous/iconfactory.h index a8f07f2f0..8ce9bd5f9 100755 --- a/src/miscellaneous/iconfactory.h +++ b/src/miscellaneous/iconfactory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,54 +24,54 @@ #include "definitions/definitions.h" #include "miscellaneous/application.h" -#include -#include -#include #include - +#include +#include +#include class IconFactory : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Constructor. - explicit IconFactory(QObject* parent = 0); + public: - // Destructor. - virtual ~IconFactory(); + // Constructor. + explicit IconFactory(QObject* parent = 0); - // Used to store/retrieve QIcons from/to Base64-encoded - // byte array. - static QIcon fromByteArray(QByteArray array); - static QByteArray toByteArray(const QIcon& icon); + // Destructor. + virtual ~IconFactory(); - QPixmap pixmap(const QString& name); + // Used to store/retrieve QIcons from/to Base64-encoded + // byte array. + static QIcon fromByteArray(QByteArray array); + static QByteArray toByteArray(const QIcon& icon); - // Returns icon from active theme or invalid icon if - // "no icon theme" is set. - QIcon fromTheme(const QString& name); + QPixmap pixmap(const QString& name); - QPixmap miscPixmap(const QString& name); - QIcon miscIcon(const QString& name); + // Returns icon from active theme or invalid icon if + // "no icon theme" is set. + QIcon fromTheme(const QString& name); - // Adds custom application path to be search for icons. - void setupSearchPaths(); + QPixmap miscPixmap(const QString& name); + QIcon miscIcon(const QString& name); - // Returns list of installed themes, including "default" theme. - QStringList installedIconThemes() const; + // Adds custom application path to be search for icons. + void setupSearchPaths(); - // Loads name of selected icon theme (from settings) for the application and - // activates it. If that particular theme is not installed, then - // "default" theme is loaded. - void loadCurrentIconTheme(); + // Returns list of installed themes, including "default" theme. + QStringList installedIconThemes() const; - // Returns name of currently activated theme for the application. - inline QString currentIconTheme() const { - return QIcon::themeName(); - } + // Loads name of selected icon theme (from settings) for the application and + // activates it. If that particular theme is not installed, then + // "default" theme is loaded. + void loadCurrentIconTheme(); - // Sets icon theme with given name as the active one and loads it. - void setCurrentIconTheme(const QString& theme_name); + // Returns name of currently activated theme for the application. + inline QString currentIconTheme() const { + return QIcon::themeName(); + } + + // Sets icon theme with given name as the active one and loads it. + void setCurrentIconTheme(const QString& theme_name); }; #endif // ICONFACTORY_H diff --git a/src/miscellaneous/iofactory.cpp b/src/miscellaneous/iofactory.cpp index ece033507..09b8397b0 100755 --- a/src/miscellaneous/iofactory.cpp +++ b/src/miscellaneous/iofactory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,105 +22,104 @@ #include "exceptions/ioexception.h" #include -#include #include +#include #include #include #include - -IOFactory::IOFactory() { -} +IOFactory::IOFactory() {} bool IOFactory::isFolderWritable(const QString& folder) { - QString real_file = folder; + QString real_file = folder; - if (!real_file.endsWith(QDir::separator())) { - real_file += QDir::separator(); - } + if (!real_file.endsWith(QDir::separator())) { + real_file += QDir::separator(); + } - real_file += "test-permissions-file"; - return QTemporaryFile(real_file).open(); + real_file += "test-permissions-file"; + return QTemporaryFile(real_file).open(); } QString IOFactory::getSystemFolder(QStandardPaths::StandardLocation location) { - return QStandardPaths::writableLocation(location); + return QStandardPaths::writableLocation(location); } QString IOFactory::ensureUniqueFilename(const QString& name, const QString& append_format) { - if (!QFile::exists(name)) { - return name; - } + if (!QFile::exists(name)) { + return name; + } - QString tmp_filename = name; - int i = 1; + QString tmp_filename = name; + int i = 1; - while (QFile::exists(tmp_filename)) { - tmp_filename = name; - const int index = tmp_filename.lastIndexOf(QL1C('.')); - const QString append_string = append_format.arg(i++); + while (QFile::exists(tmp_filename)) { + tmp_filename = name; + const int index = tmp_filename.lastIndexOf(QL1C('.')); + const QString append_string = append_format.arg(i++); - if (index < 0) { - tmp_filename.append(append_string); - } - else { - tmp_filename = tmp_filename.left(index) + append_string + tmp_filename.mid(index); - } - } + if (index < 0) { + tmp_filename.append(append_string); + } + else { + tmp_filename = tmp_filename.left(index) + append_string + tmp_filename.mid(index); + } + } - return tmp_filename; + return tmp_filename; } QString IOFactory::filterBadCharsFromFilename(const QString& name) { - QString value = name; - value.replace(QL1C('/'), QL1C('-')); - value.remove(QL1C('\\')); - value.remove(QL1C(':')); - value.remove(QL1C('*')); - value.remove(QL1C('?')); - value.remove(QL1C('"')); - value.remove(QL1C('<')); - value.remove(QL1C('>')); - value.remove(QL1C('|')); - return value; + QString value = name; + + value.replace(QL1C('/'), QL1C('-')); + value.remove(QL1C('\\')); + value.remove(QL1C(':')); + value.remove(QL1C('*')); + value.remove(QL1C('?')); + value.remove(QL1C('"')); + value.remove(QL1C('<')); + value.remove(QL1C('>')); + value.remove(QL1C('|')); + return value; } QByteArray IOFactory::readTextFile(const QString& file_path) { - QFile input_file(file_path); - QByteArray input_data; + QFile input_file(file_path); + QByteArray input_data; - if (input_file.open(QIODevice::Text | QIODevice::Unbuffered | QIODevice::ReadOnly)) { - input_data = input_file.readAll(); - input_file.close(); - return input_data; - } - else { - throw IOException(tr("Cannot open file '%1' for reading.").arg(QDir::toNativeSeparators(file_path))); - } + if (input_file.open(QIODevice::Text | QIODevice::Unbuffered | QIODevice::ReadOnly)) { + input_data = input_file.readAll(); + input_file.close(); + return input_data; + } + else { + throw IOException(tr("Cannot open file '%1' for reading.").arg(QDir::toNativeSeparators(file_path))); + } } void IOFactory::writeTextFile(const QString& file_path, const QByteArray& data, const QString& encoding) { - Q_UNUSED(encoding) - QFile input_file(file_path); - QTextStream stream(&input_file); + Q_UNUSED(encoding) + QFile input_file(file_path); + QTextStream stream(&input_file); - if (input_file.open(QIODevice::Text | QIODevice::WriteOnly)) { - stream << data; - stream.flush(); - input_file.flush(); - input_file.close(); - } - else { - throw IOException(tr("Cannot open file '%1' for writting.").arg(QDir::toNativeSeparators(file_path))); - } + if (input_file.open(QIODevice::Text | QIODevice::WriteOnly)) { + stream << data; + stream.flush(); + input_file.flush(); + input_file.close(); + } + else { + throw IOException(tr("Cannot open file '%1' for writting.").arg(QDir::toNativeSeparators(file_path))); + } } bool IOFactory::copyFile(const QString& source, const QString& destination) { - if (QFile::exists(destination)) { - if (!QFile::remove(destination)) { - return false; - } - } + if (QFile::exists(destination)) { + if (!QFile::remove(destination)) { + return false; + } + } - return QFile::copy(source, destination); + return QFile::copy(source, destination); } diff --git a/src/miscellaneous/iofactory.h b/src/miscellaneous/iofactory.h index 8d24bce47..8234287e9 100755 --- a/src/miscellaneous/iofactory.h +++ b/src/miscellaneous/iofactory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -24,34 +25,32 @@ #include - class IOFactory { - Q_DECLARE_TR_FUNCTIONS(IOFactory) + Q_DECLARE_TR_FUNCTIONS(IOFactory) - private: - IOFactory(); + private: + IOFactory(); - public: - static bool isFolderWritable(const QString& folder); + public: + static bool isFolderWritable(const QString& folder); - // Returns system-wide folder according to type. - static QString getSystemFolder(QStandardPaths::StandardLocation location); + // Returns system-wide folder according to type. + static QString getSystemFolder(QStandardPaths::StandardLocation location); - // Checks given file if it exists and if it does, then generates non-existing new file - // according to format. - static QString ensureUniqueFilename(const QString& name, const QString& append_format = QSL("(%1)")); + // Checks given file if it exists and if it does, then generates non-existing new file + // according to format. + static QString ensureUniqueFilename(const QString& name, const QString& append_format = QSL("(%1)")); - // Filters out shit characters from filename. - static QString filterBadCharsFromFilename(const QString& name); + // Filters out shit characters from filename. + static QString filterBadCharsFromFilename(const QString& name); - // Returns contents of a file. - // Throws exception when no such file exists. - static QByteArray readTextFile(const QString& file_path); + // Returns contents of a file. + // Throws exception when no such file exists. + static QByteArray readTextFile(const QString& file_path); + static void writeTextFile(const QString& file_path, const QByteArray& data, const QString& encoding = QSL("UTF-8")); - static void writeTextFile(const QString& file_path, const QByteArray& data, const QString& encoding = QSL("UTF-8")); - - // Copies file, overwrites destination. - static bool copyFile(const QString& source, const QString& destination); + // Copies file, overwrites destination. + static bool copyFile(const QString& source, const QString& destination); }; #endif // IOFACTORY_H diff --git a/src/miscellaneous/localization.cpp b/src/miscellaneous/localization.cpp index 461ace39e..e33726d2d 100755 --- a/src/miscellaneous/localization.cpp +++ b/src/miscellaneous/localization.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,74 +20,73 @@ #include "miscellaneous/application.h" -#include #include #include #include - +#include Localization::Localization(QObject* parent) - : QObject(parent) { -} + : QObject(parent) {} -Localization::~Localization() { -} +Localization::~Localization() {} QString Localization::desiredLanguage() const { - return qApp->settings()->value(GROUP(General), SETTING(General::Language)).toString(); + return qApp->settings()->value(GROUP(General), SETTING(General::Language)).toString(); } void Localization::loadActiveLanguage() { - QTranslator* qt_translator = new QTranslator(qApp); - QTranslator* app_translator = new QTranslator(qApp); - QString desired_localization = desiredLanguage(); - qDebug("Starting to load active localization. Desired localization is '%s'.", qPrintable(desired_localization)); + QTranslator* qt_translator = new QTranslator(qApp); + QTranslator* app_translator = new QTranslator(qApp); + QString desired_localization = desiredLanguage(); - if (app_translator->load(QLocale(desired_localization), "rssguard", QSL("_"), APP_LANG_PATH)) { - const QString real_loaded_locale = app_translator->translate("QObject", "LANG_ABBREV"); - Application::installTranslator(app_translator); - qDebug("Application localization '%s' loaded successfully, specifically sublocalization '%s' was loaded.", - qPrintable(desired_localization), - qPrintable(real_loaded_locale)); - desired_localization = real_loaded_locale; - } - else { - qWarning("Application localization '%s' was not loaded. Loading '%s' instead.", - qPrintable(desired_localization), - DEFAULT_LOCALE); - desired_localization = DEFAULT_LOCALE; - } + qDebug("Starting to load active localization. Desired localization is '%s'.", qPrintable(desired_localization)); - if (qt_translator->load(QLocale(desired_localization), "qtbase", QSL("_"), APP_LANG_PATH)) { - Application::installTranslator(qt_translator); - qDebug("Qt localization '%s' loaded successfully.", qPrintable(desired_localization)); - } - else { - qWarning("Qt localization '%s' was not loaded.", qPrintable(desired_localization)); - } + if (app_translator->load(QLocale(desired_localization), "rssguard", QSL("_"), APP_LANG_PATH)) { + const QString real_loaded_locale = app_translator->translate("QObject", "LANG_ABBREV"); - m_loadedLanguage = desired_localization; - m_loadedLocale = QLocale(desired_localization); - QLocale::setDefault(m_loadedLocale); + Application::installTranslator(app_translator); + qDebug("Application localization '%s' loaded successfully, specifically sublocalization '%s' was loaded.", + qPrintable(desired_localization), + qPrintable(real_loaded_locale)); + desired_localization = real_loaded_locale; + } + else { + qWarning("Application localization '%s' was not loaded. Loading '%s' instead.", + qPrintable(desired_localization), + DEFAULT_LOCALE); + desired_localization = DEFAULT_LOCALE; + } + + if (qt_translator->load(QLocale(desired_localization), "qtbase", QSL("_"), APP_LANG_PATH)) { + Application::installTranslator(qt_translator); + qDebug("Qt localization '%s' loaded successfully.", qPrintable(desired_localization)); + } + else { + qWarning("Qt localization '%s' was not loaded.", qPrintable(desired_localization)); + } + + m_loadedLanguage = desired_localization; + m_loadedLocale = QLocale(desired_localization); + QLocale::setDefault(m_loadedLocale); } QList Localization::installedLanguages() const { - QList languages; - const QDir file_dir(APP_LANG_PATH); - QTranslator translator; + QList languages; + const QDir file_dir(APP_LANG_PATH); + QTranslator translator; - // Iterate all found language files. - foreach (const QFileInfo& file, file_dir.entryInfoList(QStringList() << "rssguard_*.qm", QDir::Files, QDir::Name)) { - if (translator.load(file.absoluteFilePath())) { - Language new_language; - new_language.m_code = translator.translate("QObject", "LANG_ABBREV"); - new_language.m_author = translator.translate("QObject", "LANG_AUTHOR"); - new_language.m_email = translator.translate("QObject", "LANG_EMAIL"); - new_language.m_name = QLocale(new_language.m_code).nativeLanguageName(); - languages << new_language; - } - } + // Iterate all found language files. + foreach (const QFileInfo& file, file_dir.entryInfoList(QStringList() << "rssguard_*.qm", QDir::Files, QDir::Name)) { + if (translator.load(file.absoluteFilePath())) { + Language new_language; - return languages; + new_language.m_code = translator.translate("QObject", "LANG_ABBREV"); + new_language.m_author = translator.translate("QObject", "LANG_AUTHOR"); + new_language.m_email = translator.translate("QObject", "LANG_EMAIL"); + new_language.m_name = QLocale(new_language.m_code).nativeLanguageName(); + languages << new_language; + } + } + + return languages; } - diff --git a/src/miscellaneous/localization.h b/src/miscellaneous/localization.h index 8160d4db7..7a486c723 100755 --- a/src/miscellaneous/localization.h +++ b/src/miscellaneous/localization.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,52 +21,53 @@ #include -#include #include - +#include struct Language { - QString m_name; - QString m_code; - QString m_author; - QString m_email; + QString m_name; + QString m_code; + QString m_author; + QString m_email; }; class Localization : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Constructor. - explicit Localization(QObject* parent = 0); + public: - // Destructor. - virtual ~Localization(); + // Constructor. + explicit Localization(QObject* parent = 0); - // Returns code of language that should - // be loaded according to settings. - QString desiredLanguage() const; + // Destructor. + virtual ~Localization(); - // Loads currently active language. - void loadActiveLanguage(); + // Returns code of language that should + // be loaded according to settings. + QString desiredLanguage() const; - // Returns list of installed application localizations. - // This list is used ie. in settings dialog. - QList installedLanguages() const; + // Loads currently active language. + void loadActiveLanguage(); - // Returns empty string or loaded language - // name if it is really loaded. - inline QString loadedLanguage() const { - return m_loadedLanguage; - } + // Returns list of installed application localizations. + // This list is used ie. in settings dialog. + QList installedLanguages() const; - inline QLocale loadedLocale() const { - return m_loadedLocale; - } + // Returns empty string or loaded language + // name if it is really loaded. + inline QString loadedLanguage() const { + return m_loadedLanguage; + } - private: - // Code of loaded language. - QString m_loadedLanguage; - QLocale m_loadedLocale; + inline QLocale loadedLocale() const { + return m_loadedLocale; + } + + private: + + // Code of loaded language. + QString m_loadedLanguage; + QLocale m_loadedLocale; }; #endif // LOCALIZATION_H diff --git a/src/miscellaneous/mutex.cpp b/src/miscellaneous/mutex.cpp index a66cc950f..eb592845c 100755 --- a/src/miscellaneous/mutex.cpp +++ b/src/miscellaneous/mutex.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,58 +18,56 @@ #include "miscellaneous/mutex.h" - -Mutex::Mutex(QMutex::RecursionMode mode, QObject* parent) : QObject(parent), m_mutex(new QMutex(mode)), m_isLocked(false) { -} +Mutex::Mutex(QMutex::RecursionMode mode, QObject* parent) : QObject(parent), m_mutex(new QMutex(mode)), m_isLocked(false) {} Mutex::~Mutex() { - qDebug("Destroying Mutex instance."); + qDebug("Destroying Mutex instance."); } void Mutex::lock() { - m_mutex->lock(); - setLocked(); + m_mutex->lock(); + setLocked(); } bool Mutex::tryLock() { - bool result; + bool result; - if ((result = m_mutex->tryLock())) { - setLocked(); - } + if ((result = m_mutex->tryLock())) { + setLocked(); + } - return result; + return result; } bool Mutex::tryLock(int timeout) { - bool result; + bool result; - if ((result = m_mutex->tryLock(timeout))) { - setLocked(); - } + if ((result = m_mutex->tryLock(timeout))) { + setLocked(); + } - return result; + return result; } void Mutex::unlock() { - m_mutex->unlock(); - setUnlocked(); + m_mutex->unlock(); + setUnlocked(); } void Mutex::setLocked() { - m_isLocked = true; - emit locked(); + m_isLocked = true; + emit locked(); } void Mutex::setUnlocked() { - m_isLocked = false; - emit unlocked(); + m_isLocked = false; + emit unlocked(); } bool Mutex::isLocked() const { - return m_isLocked; + return m_isLocked; } Mutex::operator QMutex* () const { - return m_mutex.data(); + return m_mutex.data(); } diff --git a/src/miscellaneous/mutex.h b/src/miscellaneous/mutex.h index 33a8a57a3..41e9f41e3 100755 --- a/src/miscellaneous/mutex.h +++ b/src/miscellaneous/mutex.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,40 +22,41 @@ #include #include - class Mutex : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Constructors. - explicit Mutex(QMutex::RecursionMode mode = QMutex::NonRecursive, QObject* parent = 0); - virtual ~Mutex(); + public: - // Main methods. - bool tryLock(); - bool tryLock(int timeout); + // Constructors. + explicit Mutex(QMutex::RecursionMode mode = QMutex::NonRecursive, QObject* parent = 0); + virtual ~Mutex(); - // Identifies if mutes is locked or not. - bool isLocked() const; + // Main methods. + bool tryLock(); + bool tryLock(int timeout); - operator QMutex* () const; + // Identifies if mutes is locked or not. + bool isLocked() const; - public slots: - void lock(); - void unlock(); + operator QMutex* () const; - protected: - // These methods set proper value for m_isLocked and emit signals. - void setLocked(); - void setUnlocked(); + public slots: + void lock(); + void unlock(); - signals: - void locked(); - void unlocked(); + protected: - private: - QScopedPointer m_mutex; - bool m_isLocked; + // These methods set proper value for m_isLocked and emit signals. + void setLocked(); + void setUnlocked(); + + signals: + void locked(); + void unlocked(); + + private: + QScopedPointer m_mutex; + bool m_isLocked; }; #endif // MUTEX_H diff --git a/src/miscellaneous/settings.cpp b/src/miscellaneous/settings.cpp index 1a3b7b374..b8b6ca9a5 100755 --- a/src/miscellaneous/settings.cpp +++ b/src/miscellaneous/settings.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,365 +22,432 @@ #include "miscellaneous/iofactory.h" #include #include -#include #include +#include - -DKEY WebEngineAttributes::ID = "web_engine_attributes"; +DKEY WebEngineAttributes::ID = "web_engine_attributes"; // AdBlock. -DKEY AdBlock::ID = "adblock"; +DKEY AdBlock::ID = "adblock"; +DKEY AdBlock::DisabledRules = "disabled_rules"; -DKEY AdBlock::DisabledRules = "disabled_rules"; DVALUE(QStringList) AdBlock::DisabledRulesDef = QStringList(); -DKEY AdBlock::AdBlockEnabled = "enabled"; +DKEY AdBlock::AdBlockEnabled = "enabled"; + DVALUE(bool) AdBlock::AdBlockEnabledDef = false; -DKEY AdBlock::LastUpdatedOn = "last_updated_on"; +DKEY AdBlock::LastUpdatedOn = "last_updated_on"; + DVALUE(QDateTime) AdBlock::LastUpdatedOnDef = QDateTime(); // Feeds. -DKEY Feeds::ID = "feeds"; +DKEY Feeds::ID = "feeds"; +DKEY Feeds::UpdateTimeout = "feed_update_timeout"; -DKEY Feeds::UpdateTimeout = "feed_update_timeout"; -DVALUE(int) Feeds::UpdateTimeoutDef = DOWNLOAD_TIMEOUT; +DVALUE(int) Feeds::UpdateTimeoutDef = DOWNLOAD_TIMEOUT; -DKEY Feeds::EnableAutoUpdateNotification = "enable_auto_update_notification"; -DVALUE(bool) Feeds::EnableAutoUpdateNotificationDef = true; +DKEY Feeds::EnableAutoUpdateNotification = "enable_auto_update_notification"; -DKEY Feeds::CountFormat = "count_format"; -DVALUE(char*) Feeds::CountFormatDef = "(%unread)"; +DVALUE(bool) Feeds::EnableAutoUpdateNotificationDef = true; -DKEY Feeds::AutoUpdateInterval = "auto_update_interval"; -DVALUE(int) Feeds::AutoUpdateIntervalDef = DEFAULT_AUTO_UPDATE_INTERVAL; +DKEY Feeds::CountFormat = "count_format"; -DKEY Feeds::AutoUpdateEnabled = "auto_update_enabled"; -DVALUE(bool) Feeds::AutoUpdateEnabledDef = false; +DVALUE(char*) Feeds::CountFormatDef = "(%unread)"; + +DKEY Feeds::AutoUpdateInterval = "auto_update_interval"; + +DVALUE(int) Feeds::AutoUpdateIntervalDef = DEFAULT_AUTO_UPDATE_INTERVAL; + +DKEY Feeds::AutoUpdateEnabled = "auto_update_enabled"; + +DVALUE(bool) Feeds::AutoUpdateEnabledDef = false; + +DKEY Feeds::FeedsUpdateOnStartup = "feeds_update_on_startup"; -DKEY Feeds::FeedsUpdateOnStartup = "feeds_update_on_startup"; DVALUE(bool) Feeds::FeedsUpdateOnStartupDef = false; -DKEY Feeds::ShowOnlyUnreadFeeds = "show_only_unread_feeds"; -DVALUE(bool) Feeds::ShowOnlyUnreadFeedsDef = false; +DKEY Feeds::ShowOnlyUnreadFeeds = "show_only_unread_feeds"; + +DVALUE(bool) Feeds::ShowOnlyUnreadFeedsDef = false; // Messages. -DKEY Messages::ID = "messages"; +DKEY Messages::ID = "messages"; +DKEY Messages::MessageHeadImageHeight = "message_head_image_height"; -DKEY Messages::MessageHeadImageHeight = "message_head_image_height"; -DVALUE(int) Messages::MessageHeadImageHeightDef = 36; +DVALUE(int) Messages::MessageHeadImageHeightDef = 36; -DKEY Messages::UseCustomDate = "use_custom_date"; -DVALUE(bool) Messages::UseCustomDateDef = false; +DKEY Messages::UseCustomDate = "use_custom_date"; -DKEY Messages::CustomDateFormat = "custom_date_format"; -DVALUE(char*) Messages::CustomDateFormatDef = ""; +DVALUE(bool) Messages::UseCustomDateDef = false; -DKEY Messages::ClearReadOnExit = "clear_read_on_exit"; -DVALUE(bool) Messages::ClearReadOnExitDef = false; +DKEY Messages::CustomDateFormat = "custom_date_format"; -DKEY Messages::KeepCursorInCenter = "keep_cursor_center"; -DVALUE(bool) Messages::KeepCursorInCenterDef = false; +DVALUE(char*) Messages::CustomDateFormatDef = ""; -DKEY Messages::PreviewerFontStandard = "previewer_font_standard"; -NON_CONST_DVALUE(QString) Messages::PreviewerFontStandardDef = QFont(QFont().family(), 12).toString(); +DKEY Messages::ClearReadOnExit = "clear_read_on_exit"; + +DVALUE(bool) Messages::ClearReadOnExitDef = false; + +DKEY Messages::KeepCursorInCenter = "keep_cursor_center"; + +DVALUE(bool) Messages::KeepCursorInCenterDef = false; + +DKEY Messages::PreviewerFontStandard = "previewer_font_standard"; + +NON_CONST_DVALUE(QString) Messages::PreviewerFontStandardDef = QFont(QFont().family(), 12).toString(); // GUI. -DKEY GUI::ID = "gui"; +DKEY GUI::ID = "gui"; +DKEY GUI::MessageViewState = "msg_view_state"; -DKEY GUI::MessageViewState = "msg_view_state"; -DVALUE(QString) GUI::MessageViewStateDef = QString(); +DVALUE(QString) GUI::MessageViewStateDef = QString(); -DKEY GUI::SplitterFeeds = "splitter_feeds"; -DVALUE(char*) GUI::SplitterFeedsDef = ""; +DKEY GUI::SplitterFeeds = "splitter_feeds"; -DKEY GUI::SplitterMessages = "splitter_messages"; -DVALUE(char*) GUI::SplitterMessagesDef = ""; +DVALUE(char*) GUI::SplitterFeedsDef = ""; -DKEY GUI::ToolbarStyle = "toolbar_style"; -DVALUE(Qt::ToolButtonStyle) GUI::ToolbarStyleDef = Qt::ToolButtonIconOnly; +DKEY GUI::SplitterMessages = "splitter_messages"; -DKEY GUI::FeedsToolbarActions = "feeds_toolbar"; -DVALUE(char*) GUI::FeedsToolbarActionsDef = "m_actionUpdateAllItems,m_actionStopRunningItemsUpdate,m_actionMarkAllItemsRead"; +DVALUE(char*) GUI::SplitterMessagesDef = ""; -DKEY GUI::StatusbarActions = "status_bar"; -DVALUE(char*) GUI::StatusbarActionsDef = - "m_lblProgressFeedsAction,m_barProgressFeedsAction,m_actionUpdateAllItems,m_actionUpdateSelectedItems,m_actionStopRunningItemsUpdate,m_actionFullscreen,m_actionQuit"; +DKEY GUI::ToolbarStyle = "toolbar_style"; -DKEY GUI::MainWindowInitialSize = "window_size"; -DKEY GUI::MainWindowInitialPosition = "window_position"; +DVALUE(Qt::ToolButtonStyle) GUI::ToolbarStyleDef = Qt::ToolButtonIconOnly; -DKEY GUI::IsMainWindowMaximizedBeforeFullscreen = "is_window_maximized_before_fullscreen"; -DVALUE(bool) GUI::IsMainWindowMaximizedBeforeFullscreenDef = false; +DKEY GUI::FeedsToolbarActions = "feeds_toolbar"; -DKEY GUI::MainWindowStartsFullscreen = "start_in_fullscreen"; -DVALUE(bool) GUI::MainWindowStartsFullscreenDef = false; +DVALUE(char*) GUI::FeedsToolbarActionsDef = "m_actionUpdateAllItems,m_actionStopRunningItemsUpdate,m_actionMarkAllItemsRead"; -DKEY GUI::MainWindowStartsHidden = "start_hidden"; -DVALUE(bool) GUI::MainWindowStartsHiddenDef = false; +DKEY GUI::StatusbarActions = "status_bar"; -DKEY GUI::MainWindowStartsMaximized = "window_is_maximized"; -DVALUE(bool) GUI::MainWindowStartsMaximizedDef = false; +DVALUE(char*) GUI::StatusbarActionsDef = + "m_lblProgressFeedsAction,m_barProgressFeedsAction,m_actionUpdateAllItems,m_actionUpdateSelectedItems,m_actionStopRunningItemsUpdate,m_actionFullscreen,m_actionQuit"; -DKEY GUI::MainMenuVisible = "main_menu_visible"; -DVALUE(bool) GUI::MainMenuVisibleDef = true; +DKEY GUI::MainWindowInitialSize = "window_size"; +DKEY GUI::MainWindowInitialPosition = "window_position"; +DKEY GUI::IsMainWindowMaximizedBeforeFullscreen = "is_window_maximized_before_fullscreen"; -DKEY GUI::ToolbarsVisible = "enable_toolbars"; -DVALUE(bool) GUI::ToolbarsVisibleDef = true; +DVALUE(bool) GUI::IsMainWindowMaximizedBeforeFullscreenDef = false; -DKEY GUI::ListHeadersVisible = "enable_list_headers"; -DVALUE(bool) GUI::ListHeadersVisibleDef = true; +DKEY GUI::MainWindowStartsFullscreen = "start_in_fullscreen"; -DKEY GUI::StatusBarVisible = "enable_status_bar"; -DVALUE(bool) GUI::StatusBarVisibleDef = true; +DVALUE(bool) GUI::MainWindowStartsFullscreenDef = false; -DKEY GUI::HideMainWindowWhenMinimized = "hide_when_minimized"; -DVALUE(bool) GUI::HideMainWindowWhenMinimizedDef = false; +DKEY GUI::MainWindowStartsHidden = "start_hidden"; + +DVALUE(bool) GUI::MainWindowStartsHiddenDef = false; + +DKEY GUI::MainWindowStartsMaximized = "window_is_maximized"; + +DVALUE(bool) GUI::MainWindowStartsMaximizedDef = false; + +DKEY GUI::MainMenuVisible = "main_menu_visible"; + +DVALUE(bool) GUI::MainMenuVisibleDef = true; + +DKEY GUI::ToolbarsVisible = "enable_toolbars"; + +DVALUE(bool) GUI::ToolbarsVisibleDef = true; + +DKEY GUI::ListHeadersVisible = "enable_list_headers"; + +DVALUE(bool) GUI::ListHeadersVisibleDef = true; + +DKEY GUI::StatusBarVisible = "enable_status_bar"; + +DVALUE(bool) GUI::StatusBarVisibleDef = true; + +DKEY GUI::HideMainWindowWhenMinimized = "hide_when_minimized"; + +DVALUE(bool) GUI::HideMainWindowWhenMinimizedDef = false; + +DKEY GUI::UseTrayIcon = "use_tray_icon"; -DKEY GUI::UseTrayIcon = "use_tray_icon"; DVALUE(bool) GUI::UseTrayIconDef = true; -DKEY GUI::EnableNotifications = "enable_notifications"; -DVALUE(bool) GUI::EnableNotificationsDef = true; +DKEY GUI::EnableNotifications = "enable_notifications"; -DKEY GUI::TabCloseMiddleClick = "tab_close_mid_button"; -DVALUE(bool) GUI::TabCloseMiddleClickDef = true; +DVALUE(bool) GUI::EnableNotificationsDef = true; -DKEY GUI::TabCloseDoubleClick = "tab_close_double_button"; -DVALUE(bool) GUI::TabCloseDoubleClickDef = true; +DKEY GUI::TabCloseMiddleClick = "tab_close_mid_button"; -DKEY GUI::TabNewDoubleClick = "tab_new_double_button"; -DVALUE(bool) GUI::TabNewDoubleClickDef = true; +DVALUE(bool) GUI::TabCloseMiddleClickDef = true; -DKEY GUI::HideTabBarIfOnlyOneTab = "hide_tabbar_one_tab"; -DVALUE(bool) GUI::HideTabBarIfOnlyOneTabDef = false; +DKEY GUI::TabCloseDoubleClick = "tab_close_double_button"; + +DVALUE(bool) GUI::TabCloseDoubleClickDef = true; + +DKEY GUI::TabNewDoubleClick = "tab_new_double_button"; + +DVALUE(bool) GUI::TabNewDoubleClickDef = true; + +DKEY GUI::HideTabBarIfOnlyOneTab = "hide_tabbar_one_tab"; + +DVALUE(bool) GUI::HideTabBarIfOnlyOneTabDef = false; + +DKEY GUI::MessagesToolbarDefaultButtons = "messages_toolbar"; -DKEY GUI::MessagesToolbarDefaultButtons = "messages_toolbar"; DVALUE(char*) GUI::MessagesToolbarDefaultButtonsDef = - "m_actionMarkSelectedMessagesAsRead,m_actionMarkSelectedMessagesAsUnread,m_actionSwitchImportanceOfSelectedMessages,separator,highlighter,spacer,search"; + "m_actionMarkSelectedMessagesAsRead,m_actionMarkSelectedMessagesAsUnread,m_actionSwitchImportanceOfSelectedMessages,separator,highlighter,spacer,search"; -DKEY GUI::DefaultSortColumnFeeds = "default_sort_column_feeds"; -DVALUE(int) GUI::DefaultSortColumnFeedsDef = FDS_MODEL_TITLE_INDEX; +DKEY GUI::DefaultSortColumnFeeds = "default_sort_column_feeds"; -DKEY GUI::DefaultSortOrderFeeds = "default_sort_order_feeds"; -DVALUE(Qt::SortOrder) GUI::DefaultSortOrderFeedsDef = Qt::AscendingOrder; +DVALUE(int) GUI::DefaultSortColumnFeedsDef = FDS_MODEL_TITLE_INDEX; -DKEY GUI::IconTheme = "icon_theme_name"; -DVALUE(char*) GUI::IconThemeDef = APP_THEME_DEFAULT; +DKEY GUI::DefaultSortOrderFeeds = "default_sort_order_feeds"; -DKEY GUI::Skin = "skin"; -DVALUE(char*) GUI::SkinDef = APP_SKIN_DEFAULT; +DVALUE(Qt::SortOrder) GUI::DefaultSortOrderFeedsDef = Qt::AscendingOrder; -DKEY GUI::Style = "style"; -DVALUE(char*) GUI::StyleDef = APP_STYLE_DEFAULT; +DKEY GUI::IconTheme = "icon_theme_name"; +DVALUE(char*) GUI::IconThemeDef = APP_THEME_DEFAULT; + +DKEY GUI::Skin = "skin"; + +DVALUE(char*) GUI::SkinDef = APP_SKIN_DEFAULT; + +DKEY GUI::Style = "style"; + +DVALUE(char*) GUI::StyleDef = APP_STYLE_DEFAULT; // General. -DKEY General::ID = "main"; +DKEY General::ID = "main"; +DKEY General::UpdateOnStartup = "update_on_start"; -DKEY General::UpdateOnStartup = "update_on_start"; -DVALUE(bool) General::UpdateOnStartupDef = true; +DVALUE(bool) General::UpdateOnStartupDef = true; -DKEY General::RemoveTrolltechJunk = "remove_trolltech_junk"; -DVALUE(bool) General::RemoveTrolltechJunkDef = false; +DKEY General::RemoveTrolltechJunk = "remove_trolltech_junk"; -DKEY General::FirstRun = "first_run"; -DVALUE(bool) General::FirstRunDef = true; +DVALUE(bool) General::RemoveTrolltechJunkDef = false; + +DKEY General::FirstRun = "first_run"; + +DVALUE(bool) General::FirstRunDef = true; + +DKEY General::Language = "language"; -DKEY General::Language = "language"; DVALUE(QString) General::LanguageDef = QLocale::system().name(); // Downloads. -DKEY Downloads::ID = "download_manager"; +DKEY Downloads::ID = "download_manager"; +DKEY Downloads::AlwaysPromptForFilename = "prompt_for_filename"; -DKEY Downloads::AlwaysPromptForFilename = "prompt_for_filename"; -DVALUE(bool) Downloads::AlwaysPromptForFilenameDef = false; +DVALUE(bool) Downloads::AlwaysPromptForFilenameDef = false; -DKEY Downloads::TargetDirectory = "target_directory"; -DVALUE(QString) Downloads::TargetDirectoryDef = IOFactory::getSystemFolder(QStandardPaths::DesktopLocation); +DKEY Downloads::TargetDirectory = "target_directory"; -DKEY Downloads::RemovePolicy = "remove_policy"; -DVALUE(int) Downloads::RemovePolicyDef = DownloadManager::Never; +DVALUE(QString) Downloads::TargetDirectoryDef = IOFactory::getSystemFolder(QStandardPaths::DesktopLocation); -DKEY Downloads::TargetExplicitDirectory = "target_explicit_directory"; -DVALUE(QString) Downloads::TargetExplicitDirectoryDef = IOFactory::getSystemFolder(QStandardPaths::DesktopLocation); +DKEY Downloads::RemovePolicy = "remove_policy"; + +DVALUE(int) Downloads::RemovePolicyDef = DownloadManager::Never; + +DKEY Downloads::TargetExplicitDirectory = "target_explicit_directory"; + +DVALUE(QString) Downloads::TargetExplicitDirectoryDef = IOFactory::getSystemFolder(QStandardPaths::DesktopLocation); DKEY Downloads::ShowDownloadsWhenNewDownloadStarts = "show_downloads_on_new_download_start"; + DVALUE(bool) Downloads::ShowDownloadsWhenNewDownloadStartsDef = true; -DKEY Downloads::ItemUrl = "download_%1_url"; -DKEY Downloads::ItemLocation = "download_%1_location"; -DKEY Downloads::ItemDone = "download_%1_done"; +DKEY Downloads::ItemUrl = "download_%1_url"; +DKEY Downloads::ItemLocation = "download_%1_location"; +DKEY Downloads::ItemDone = "download_%1_done"; // Proxy. -DKEY Proxy::ID = "proxy"; +DKEY Proxy::ID = "proxy"; +DKEY Proxy::Type = "proxy_type"; -DKEY Proxy::Type = "proxy_type"; -DVALUE(QNetworkProxy::ProxyType) Proxy::TypeDef = QNetworkProxy::NoProxy; +DVALUE(QNetworkProxy::ProxyType) Proxy::TypeDef = QNetworkProxy::NoProxy; -DKEY Proxy::Host = "host"; -DVALUE(QString) Proxy::HostDef = QString(); +DKEY Proxy::Host = "host"; -DKEY Proxy::Username = "username"; -DVALUE(QString) Proxy::UsernameDef = QString(); +DVALUE(QString) Proxy::HostDef = QString(); -DKEY Proxy::Password = "password"; -DVALUE(QString) Proxy::PasswordDef = QString(); +DKEY Proxy::Username = "username"; -DKEY Proxy::Port = "port"; -DVALUE(int) Proxy::PortDef = 80; +DVALUE(QString) Proxy::UsernameDef = QString(); + +DKEY Proxy::Password = "password"; + +DVALUE(QString) Proxy::PasswordDef = QString(); + +DKEY Proxy::Port = "port"; + +DVALUE(int) Proxy::PortDef = 80; // Database. -DKEY Database::ID = "database"; +DKEY Database::ID = "database"; +DKEY Database::UseTransactions = "use_transactions"; -DKEY Database::UseTransactions = "use_transactions"; -DVALUE(bool) Database::UseTransactionsDef = false; +DVALUE(bool) Database::UseTransactionsDef = false; -DKEY Database::UseInMemory = "use_in_memory_db"; -DVALUE(bool) Database::UseInMemoryDef = false; +DKEY Database::UseInMemory = "use_in_memory_db"; -DKEY Database::MySQLHostname = "mysql_hostname"; -DVALUE(QString) Database::MySQLHostnameDef = QString(); +DVALUE(bool) Database::UseInMemoryDef = false; -DKEY Database::MySQLUsername = "mysql_username"; -DVALUE(QString) Database::MySQLUsernameDef = QString(); +DKEY Database::MySQLHostname = "mysql_hostname"; -DKEY Database::MySQLPassword = "mysql_password"; -DVALUE(QString) Database::MySQLPasswordDef = QString(); +DVALUE(QString) Database::MySQLHostnameDef = QString(); -DKEY Database::MySQLDatabase = "mysql_database"; -DVALUE(char*) Database::MySQLDatabaseDef = APP_LOW_NAME; +DKEY Database::MySQLUsername = "mysql_username"; -DKEY Database::MySQLPort = "mysql_port"; -DVALUE(int) Database::MySQLPortDef = APP_DB_MYSQL_PORT; +DVALUE(QString) Database::MySQLUsernameDef = QString(); -DKEY Database::ActiveDriver = "database_driver"; -DVALUE(char*) Database::ActiveDriverDef = APP_DB_SQLITE_DRIVER; +DKEY Database::MySQLPassword = "mysql_password"; + +DVALUE(QString) Database::MySQLPasswordDef = QString(); + +DKEY Database::MySQLDatabase = "mysql_database"; + +DVALUE(char*) Database::MySQLDatabaseDef = APP_LOW_NAME; + +DKEY Database::MySQLPort = "mysql_port"; + +DVALUE(int) Database::MySQLPortDef = APP_DB_MYSQL_PORT; + +DKEY Database::ActiveDriver = "database_driver"; + +DVALUE(char*) Database::ActiveDriverDef = APP_DB_SQLITE_DRIVER; // Keyboard. DKEY Keyboard::ID = "keyboard"; // Web browser. -DKEY Browser::ID = "browser"; +DKEY Browser::ID = "browser"; +DKEY Browser::SendDNT = "send_dnt"; -DKEY Browser::SendDNT = "send_dnt"; -VALUE(bool) Browser::SendDNTDef = false; +VALUE(bool) Browser::SendDNTDef = false; -DKEY Browser::OpenLinksInExternalBrowserRightAway = "open_link_externally_wo_confirmation"; -DVALUE(bool) Browser::OpenLinksInExternalBrowserRightAwayDef = false; +DKEY Browser::OpenLinksInExternalBrowserRightAway = "open_link_externally_wo_confirmation"; -DKEY Browser::CustomExternalBrowserEnabled = "custom_external_browser"; -DVALUE(bool) Browser::CustomExternalBrowserEnabledDef = false; +DVALUE(bool) Browser::OpenLinksInExternalBrowserRightAwayDef = false; + +DKEY Browser::CustomExternalBrowserEnabled = "custom_external_browser"; + +DVALUE(bool) Browser::CustomExternalBrowserEnabledDef = false; + +DKEY Browser::CustomExternalBrowserExecutable = "external_browser_executable"; -DKEY Browser::CustomExternalBrowserExecutable = "external_browser_executable"; DVALUE(QString) Browser::CustomExternalBrowserExecutableDef = QString(); -DKEY Browser::CustomExternalBrowserArguments = "external_browser_arguments"; -DVALUE(char*) Browser::CustomExternalBrowserArgumentsDef = "%1"; +DKEY Browser::CustomExternalBrowserArguments = "external_browser_arguments"; -DKEY Browser::CustomExternalEmailEnabled = "custom_external_email"; -DVALUE(bool) Browser::CustomExternalEmailEnabledDef = false; +DVALUE(char*) Browser::CustomExternalBrowserArgumentsDef = "%1"; -DKEY Browser::CustomExternalEmailExecutable = "external_email_executable"; -DVALUE(QString) Browser::CustomExternalEmailExecutableDef = QString(); +DKEY Browser::CustomExternalEmailEnabled = "custom_external_email"; -DKEY Browser::CustomExternalEmailArguments = "external_email_arguments"; -DVALUE(char*) Browser::CustomExternalEmailArgumentsDef = ""; +DVALUE(bool) Browser::CustomExternalEmailEnabledDef = false; + +DKEY Browser::CustomExternalEmailExecutable = "external_email_executable"; + +DVALUE(QString) Browser::CustomExternalEmailExecutableDef = QString(); + +DKEY Browser::CustomExternalEmailArguments = "external_email_arguments"; + +DVALUE(char*) Browser::CustomExternalEmailArgumentsDef = ""; + +DKEY Browser::ExternalTools = "external_tools"; -DKEY Browser::ExternalTools = "external_tools"; DVALUE(QStringList) Browser::ExternalToolsDef = QStringList(); // Categories. -DKEY CategoriesExpandStates::ID = "categories_expand_states"; +DKEY CategoriesExpandStates::ID = "categories_expand_states"; Settings::Settings(const QString& file_name, Format format, const SettingsProperties::SettingsType& status, QObject* parent) - : QSettings(file_name, format, parent), m_initializationStatus(status) { -} + : QSettings(file_name, format, parent), m_initializationStatus(status) {} -Settings::~Settings() { -} +Settings::~Settings() {} QString Settings::pathName() const { - return QFileInfo(fileName()).absolutePath(); + return QFileInfo(fileName()).absolutePath(); } QSettings::Status Settings::checkSettings() { - qDebug("Syncing settings."); - sync(); - return status(); + qDebug("Syncing settings."); + sync(); + return status(); } bool Settings::initiateRestoration(const QString& settings_backup_file_path) { - return IOFactory::copyFile(settings_backup_file_path, - QFileInfo(fileName()).absolutePath() + QDir::separator() + - BACKUP_NAME_SETTINGS + BACKUP_SUFFIX_SETTINGS); + return IOFactory::copyFile(settings_backup_file_path, + QFileInfo(fileName()).absolutePath() + QDir::separator() + + BACKUP_NAME_SETTINGS + BACKUP_SUFFIX_SETTINGS); } void Settings::finishRestoration(const QString& desired_settings_file_path) { - const QString backup_settings_file = QFileInfo(desired_settings_file_path).absolutePath() + QDir::separator() + - BACKUP_NAME_SETTINGS + BACKUP_SUFFIX_SETTINGS; + const QString backup_settings_file = QFileInfo(desired_settings_file_path).absolutePath() + QDir::separator() + + BACKUP_NAME_SETTINGS + BACKUP_SUFFIX_SETTINGS; - if (QFile::exists(backup_settings_file)) { - qWarning("Backup settings file '%s' was detected. Restoring it.", qPrintable(QDir::toNativeSeparators(backup_settings_file))); + if (QFile::exists(backup_settings_file)) { + qWarning("Backup settings file '%s' was detected. Restoring it.", qPrintable(QDir::toNativeSeparators(backup_settings_file))); - if (IOFactory::copyFile(backup_settings_file, desired_settings_file_path)) { - QFile::remove(backup_settings_file); - qDebug("Settings file was restored successully."); - } - else { - qCritical("Settings file was NOT restored due to error when copying the file."); - } - } + if (IOFactory::copyFile(backup_settings_file, desired_settings_file_path)) { + QFile::remove(backup_settings_file); + qDebug("Settings file was restored successully."); + } + else { + qCritical("Settings file was NOT restored due to error when copying the file."); + } + } } Settings* Settings::setupSettings(QObject* parent) { - Settings* new_settings; - // If settings file exists (and is writable) in executable file working directory - // (in subdirectory APP_CFG_PATH), then use it (portable settings). - // Otherwise use settings file stored in home path. - const SettingsProperties properties = determineProperties(); - finishRestoration(properties.m_absoluteSettingsFileName); - // Portable settings are available, use them. - new_settings = new Settings(properties.m_absoluteSettingsFileName, QSettings::IniFormat, properties.m_type, parent); + Settings* new_settings; - // Check if portable settings are available. - if (properties.m_type == SettingsProperties::Portable) { - qDebug("Initializing settings in '%s' (portable way).", qPrintable(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))); - } - else { - qDebug("Initializing settings in '%s' (non-portable way).", qPrintable(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))); - } + // If settings file exists (and is writable) in executable file working directory + // (in subdirectory APP_CFG_PATH), then use it (portable settings). + // Otherwise use settings file stored in home path. + const SettingsProperties properties = determineProperties(); - return new_settings; + finishRestoration(properties.m_absoluteSettingsFileName); + + // Portable settings are available, use them. + new_settings = new Settings(properties.m_absoluteSettingsFileName, QSettings::IniFormat, properties.m_type, parent); + + // Check if portable settings are available. + if (properties.m_type == SettingsProperties::Portable) { + qDebug("Initializing settings in '%s' (portable way).", qPrintable(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))); + } + else { + qDebug("Initializing settings in '%s' (non-portable way).", + qPrintable(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))); + } + + return new_settings; } SettingsProperties Settings::determineProperties() { - SettingsProperties properties; - properties.m_settingsSuffix = QDir::separator() + QSL(APP_CFG_PATH) + QDir::separator() + QSL(APP_CFG_FILE); - const QString app_path = qApp->userDataAppFolder(); - const QString home_path = qApp->userDataHomeFolder(); - // We will use PORTABLE settings only and only if it is available and NON-PORTABLE - // settings was not initialized before. + SettingsProperties properties; + + properties.m_settingsSuffix = QDir::separator() + QSL(APP_CFG_PATH) + QDir::separator() + QSL(APP_CFG_FILE); + const QString app_path = qApp->userDataAppFolder(); + const QString home_path = qApp->userDataHomeFolder(); + + // We will use PORTABLE settings only and only if it is available and NON-PORTABLE + // settings was not initialized before. #if defined (Q_OS_LINUX) || defined (Q_OS_MACOS) - // DO NOT use portable settings for Linux, it is really not used on that platform. - const bool will_we_use_portable_settings = false; + + // DO NOT use portable settings for Linux, it is really not used on that platform. + const bool will_we_use_portable_settings = false; #else - const QString exe_path = qApp->applicationDirPath(); - const QString home_path_file = home_path + properties.m_settingsSuffix; - const bool portable_settings_available = IOFactory::isFolderWritable(exe_path); - const bool non_portable_settings_exist = QFile::exists(home_path_file); - const bool will_we_use_portable_settings = portable_settings_available && !non_portable_settings_exist; + const QString exe_path = qApp->applicationDirPath(); + const QString home_path_file = home_path + properties.m_settingsSuffix; + const bool portable_settings_available = IOFactory::isFolderWritable(exe_path); + const bool non_portable_settings_exist = QFile::exists(home_path_file); + const bool will_we_use_portable_settings = portable_settings_available && !non_portable_settings_exist; #endif - if (will_we_use_portable_settings) { - properties.m_type = SettingsProperties::Portable; - properties.m_baseDirectory = app_path; - } - else { - properties.m_type = SettingsProperties::NonPortable; - properties.m_baseDirectory = home_path; - } + if (will_we_use_portable_settings) { + properties.m_type = SettingsProperties::Portable; + properties.m_baseDirectory = app_path; + } + else { + properties.m_type = SettingsProperties::NonPortable; + properties.m_baseDirectory = home_path; + } - properties.m_absoluteSettingsFileName = properties.m_baseDirectory + properties.m_settingsSuffix; - return properties; + properties.m_absoluteSettingsFileName = properties.m_baseDirectory + properties.m_settingsSuffix; + return properties; } diff --git a/src/miscellaneous/settings.h b/src/miscellaneous/settings.h index e2a980c45..3868ad97c 100755 --- a/src/miscellaneous/settings.h +++ b/src/miscellaneous/settings.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -24,11 +25,11 @@ #include "miscellaneous/settingsproperties.h" +#include +#include +#include #include #include -#include -#include -#include #define KEY extern const char* #define DKEY const char* @@ -36,351 +37,416 @@ #define NON_CONST_VALUE(x) extern x #define DVALUE(x) const x #define NON_CONST_DVALUE(x) x -#define SETTING(x) x, x##Def -#define DEFAULT_VALUE(x) x##Def +#define SETTING(x) x, x ## Def +#define DEFAULT_VALUE(x) x ## Def #define GROUP(x) x::ID - namespace WebEngineAttributes { - KEY ID; + KEY ID; } namespace AdBlock { - KEY ID; + KEY ID; + KEY AdBlockEnabled; - KEY AdBlockEnabled; - VALUE(bool) AdBlockEnabledDef; + VALUE(bool) AdBlockEnabledDef; - KEY DisabledRules; - VALUE(QStringList) DisabledRulesDef; + KEY DisabledRules; - KEY LastUpdatedOn; - VALUE(QDateTime) LastUpdatedOnDef; + VALUE(QStringList) DisabledRulesDef; + + KEY LastUpdatedOn; + + VALUE(QDateTime) LastUpdatedOnDef; } // Feeds. namespace Feeds { - KEY ID; + KEY ID; + KEY UpdateTimeout; - KEY UpdateTimeout; - VALUE(int) UpdateTimeoutDef; + VALUE(int) UpdateTimeoutDef; - KEY EnableAutoUpdateNotification; - VALUE(bool) EnableAutoUpdateNotificationDef; + KEY EnableAutoUpdateNotification; - KEY CountFormat; - VALUE(char*) CountFormatDef; + VALUE(bool) EnableAutoUpdateNotificationDef; - KEY AutoUpdateInterval; - VALUE(int) AutoUpdateIntervalDef; + KEY CountFormat; - KEY AutoUpdateEnabled; - VALUE(bool) AutoUpdateEnabledDef; + VALUE(char*) CountFormatDef; - KEY FeedsUpdateOnStartup; - VALUE(bool) FeedsUpdateOnStartupDef; + KEY AutoUpdateInterval; - KEY ShowOnlyUnreadFeeds; - VALUE(bool) ShowOnlyUnreadFeedsDef; + VALUE(int) AutoUpdateIntervalDef; + + KEY AutoUpdateEnabled; + + VALUE(bool) AutoUpdateEnabledDef; + + KEY FeedsUpdateOnStartup; + + VALUE(bool) FeedsUpdateOnStartupDef; + + KEY ShowOnlyUnreadFeeds; + + VALUE(bool) ShowOnlyUnreadFeedsDef; } // Messages. namespace Messages { - KEY ID; + KEY ID; + KEY MessageHeadImageHeight; - KEY MessageHeadImageHeight; - VALUE(int) MessageHeadImageHeightDef; + VALUE(int) MessageHeadImageHeightDef; - KEY UseCustomDate; - VALUE(bool) UseCustomDateDef; + KEY UseCustomDate; - KEY CustomDateFormat; - VALUE(char*) CustomDateFormatDef; + VALUE(bool) UseCustomDateDef; - KEY ClearReadOnExit; - VALUE(bool) ClearReadOnExitDef; + KEY CustomDateFormat; - KEY KeepCursorInCenter; - VALUE(bool) KeepCursorInCenterDef; + VALUE(char*) CustomDateFormatDef; - KEY PreviewerFontStandard; - NON_CONST_VALUE(QString) PreviewerFontStandardDef; + KEY ClearReadOnExit; + + VALUE(bool) ClearReadOnExitDef; + + KEY KeepCursorInCenter; + + VALUE(bool) KeepCursorInCenterDef; + + KEY PreviewerFontStandard; + + NON_CONST_VALUE(QString) PreviewerFontStandardDef; } // GUI. namespace GUI { - KEY ID; + KEY ID; + KEY MessageViewState; - KEY MessageViewState; - VALUE(QString) MessageViewStateDef; + VALUE(QString) MessageViewStateDef; - KEY SplitterFeeds; - VALUE(char*) SplitterFeedsDef; + KEY SplitterFeeds; - KEY SplitterMessages; - VALUE(char*) SplitterMessagesDef; + VALUE(char*) SplitterFeedsDef; - KEY ToolbarStyle; - VALUE(Qt::ToolButtonStyle) ToolbarStyleDef; + KEY SplitterMessages; - KEY FeedsToolbarActions; - VALUE(char*) FeedsToolbarActionsDef; + VALUE(char*) SplitterMessagesDef; - KEY StatusbarActions; - VALUE(char*) StatusbarActionsDef; + KEY ToolbarStyle; - KEY MainWindowInitialSize; - KEY MainWindowInitialPosition; + VALUE(Qt::ToolButtonStyle) ToolbarStyleDef; - KEY IsMainWindowMaximizedBeforeFullscreen; - VALUE(bool) IsMainWindowMaximizedBeforeFullscreenDef; + KEY FeedsToolbarActions; - KEY MainWindowStartsFullscreen; - VALUE(bool) MainWindowStartsFullscreenDef; + VALUE(char*) FeedsToolbarActionsDef; - KEY MainWindowStartsHidden; - VALUE(bool) MainWindowStartsHiddenDef; + KEY StatusbarActions; - KEY MainWindowStartsMaximized; - VALUE(bool) MainWindowStartsMaximizedDef; + VALUE(char*) StatusbarActionsDef; - KEY MainMenuVisible; - VALUE(bool) MainMenuVisibleDef; + KEY MainWindowInitialSize; + KEY MainWindowInitialPosition; + KEY IsMainWindowMaximizedBeforeFullscreen; - KEY ToolbarsVisible; - VALUE(bool) ToolbarsVisibleDef; + VALUE(bool) IsMainWindowMaximizedBeforeFullscreenDef; - KEY ListHeadersVisible; - VALUE(bool) ListHeadersVisibleDef; + KEY MainWindowStartsFullscreen; - KEY StatusBarVisible; - VALUE(bool) StatusBarVisibleDef; + VALUE(bool) MainWindowStartsFullscreenDef; - KEY HideMainWindowWhenMinimized; - VALUE(bool) HideMainWindowWhenMinimizedDef; + KEY MainWindowStartsHidden; - KEY UseTrayIcon; - VALUE(bool) UseTrayIconDef; + VALUE(bool) MainWindowStartsHiddenDef; - KEY EnableNotifications; - VALUE(bool) EnableNotificationsDef; + KEY MainWindowStartsMaximized; - KEY TabCloseMiddleClick; - VALUE(bool) TabCloseMiddleClickDef; + VALUE(bool) MainWindowStartsMaximizedDef; - KEY TabCloseDoubleClick; - VALUE(bool) TabCloseDoubleClickDef; + KEY MainMenuVisible; - KEY TabNewDoubleClick; - VALUE(bool) TabNewDoubleClickDef; + VALUE(bool) MainMenuVisibleDef; - KEY HideTabBarIfOnlyOneTab; - VALUE(bool) HideTabBarIfOnlyOneTabDef; + KEY ToolbarsVisible; - KEY MessagesToolbarDefaultButtons; - VALUE(char*) MessagesToolbarDefaultButtonsDef; + VALUE(bool) ToolbarsVisibleDef; - KEY DefaultSortColumnFeeds; - VALUE(int) DefaultSortColumnFeedsDef; + KEY ListHeadersVisible; - KEY DefaultSortOrderFeeds; - VALUE(Qt::SortOrder) DefaultSortOrderFeedsDef; + VALUE(bool) ListHeadersVisibleDef; - KEY IconTheme; - VALUE(char*) IconThemeDef; + KEY StatusBarVisible; - KEY Skin; - VALUE(char*) SkinDef; + VALUE(bool) StatusBarVisibleDef; - KEY Style; - VALUE(char*) StyleDef; + KEY HideMainWindowWhenMinimized; + + VALUE(bool) HideMainWindowWhenMinimizedDef; + + KEY UseTrayIcon; + + VALUE(bool) UseTrayIconDef; + + KEY EnableNotifications; + + VALUE(bool) EnableNotificationsDef; + + KEY TabCloseMiddleClick; + + VALUE(bool) TabCloseMiddleClickDef; + + KEY TabCloseDoubleClick; + + VALUE(bool) TabCloseDoubleClickDef; + + KEY TabNewDoubleClick; + + VALUE(bool) TabNewDoubleClickDef; + + KEY HideTabBarIfOnlyOneTab; + + VALUE(bool) HideTabBarIfOnlyOneTabDef; + + KEY MessagesToolbarDefaultButtons; + + VALUE(char*) MessagesToolbarDefaultButtonsDef; + + KEY DefaultSortColumnFeeds; + + VALUE(int) DefaultSortColumnFeedsDef; + + KEY DefaultSortOrderFeeds; + + VALUE(Qt::SortOrder) DefaultSortOrderFeedsDef; + + KEY IconTheme; + + VALUE(char*) IconThemeDef; + + KEY Skin; + + VALUE(char*) SkinDef; + + KEY Style; + + VALUE(char*) StyleDef; } // General. namespace General { - KEY ID; + KEY ID; + KEY UpdateOnStartup; - KEY UpdateOnStartup; - VALUE(bool) UpdateOnStartupDef; + VALUE(bool) UpdateOnStartupDef; - KEY RemoveTrolltechJunk; - VALUE(bool) RemoveTrolltechJunkDef; + KEY RemoveTrolltechJunk; - KEY FirstRun; - VALUE(bool) FirstRunDef; + VALUE(bool) RemoveTrolltechJunkDef; - KEY Language; - VALUE(QString) LanguageDef; + KEY FirstRun; + + VALUE(bool) FirstRunDef; + + KEY Language; + + VALUE(QString) LanguageDef; } // Downloads. namespace Downloads { - KEY ID; + KEY ID; + KEY AlwaysPromptForFilename; - KEY AlwaysPromptForFilename; - VALUE(bool) AlwaysPromptForFilenameDef; + VALUE(bool) AlwaysPromptForFilenameDef; - KEY TargetDirectory; - VALUE(QString) TargetDirectoryDef; + KEY TargetDirectory; - KEY RemovePolicy; - VALUE(int) RemovePolicyDef; + VALUE(QString) TargetDirectoryDef; - KEY TargetExplicitDirectory; - VALUE(QString) TargetExplicitDirectoryDef; + KEY RemovePolicy; - KEY ShowDownloadsWhenNewDownloadStarts; - VALUE(bool) ShowDownloadsWhenNewDownloadStartsDef; + VALUE(int) RemovePolicyDef; - KEY ItemUrl; - KEY ItemLocation; - KEY ItemDone; + KEY TargetExplicitDirectory; + + VALUE(QString) TargetExplicitDirectoryDef; + + KEY ShowDownloadsWhenNewDownloadStarts; + + VALUE(bool) ShowDownloadsWhenNewDownloadStartsDef; + + KEY ItemUrl; + KEY ItemLocation; + KEY ItemDone; } // Proxy. namespace Proxy { - KEY ID; + KEY ID; + KEY Type; - KEY Type; - VALUE(QNetworkProxy::ProxyType) TypeDef; + VALUE(QNetworkProxy::ProxyType) TypeDef; - KEY Host; - VALUE(QString) HostDef; + KEY Host; - KEY Username; - VALUE(QString) UsernameDef; + VALUE(QString) HostDef; - KEY Password; - VALUE(QString) PasswordDef; + KEY Username; - KEY Port; - VALUE(int) PortDef; + VALUE(QString) UsernameDef; + + KEY Password; + + VALUE(QString) PasswordDef; + + KEY Port; + + VALUE(int) PortDef; } // Database. namespace Database { - KEY ID; + KEY ID; + KEY UseTransactions; - KEY UseTransactions; - VALUE(bool) UseTransactionsDef; + VALUE(bool) UseTransactionsDef; - KEY UseInMemory; - VALUE(bool) UseInMemoryDef; + KEY UseInMemory; - KEY MySQLHostname; - VALUE(QString) MySQLHostnameDef; + VALUE(bool) UseInMemoryDef; - KEY MySQLUsername; - VALUE(QString) MySQLUsernameDef; + KEY MySQLHostname; - KEY MySQLPassword; - VALUE(QString) MySQLPasswordDef; + VALUE(QString) MySQLHostnameDef; - KEY MySQLPort; - VALUE(int) MySQLPortDef; + KEY MySQLUsername; - KEY MySQLDatabase; - VALUE(char*) MySQLDatabaseDef; + VALUE(QString) MySQLUsernameDef; - KEY ActiveDriver; - VALUE(char*) ActiveDriverDef; + KEY MySQLPassword; + + VALUE(QString) MySQLPasswordDef; + + KEY MySQLPort; + + VALUE(int) MySQLPortDef; + + KEY MySQLDatabase; + + VALUE(char*) MySQLDatabaseDef; + + KEY ActiveDriver; + + VALUE(char*) ActiveDriverDef; } // Keyboard. namespace Keyboard { - KEY ID; + KEY ID; } // Web browser. namespace Browser { - KEY ID; + KEY ID; + KEY SendDNT; - KEY SendDNT; - VALUE(bool) SendDNTDef; + VALUE(bool) SendDNTDef; - KEY OpenLinksInExternalBrowserRightAway; - VALUE(bool) OpenLinksInExternalBrowserRightAwayDef; + KEY OpenLinksInExternalBrowserRightAway; - KEY CustomExternalBrowserEnabled; - VALUE(bool) CustomExternalBrowserEnabledDef; + VALUE(bool) OpenLinksInExternalBrowserRightAwayDef; - KEY CustomExternalBrowserExecutable; - VALUE(QString) CustomExternalBrowserExecutableDef; + KEY CustomExternalBrowserEnabled; - KEY CustomExternalBrowserArguments; - VALUE(char*) CustomExternalBrowserArgumentsDef; + VALUE(bool) CustomExternalBrowserEnabledDef; - KEY CustomExternalEmailEnabled; - VALUE(bool) CustomExternalEmailEnabledDef; + KEY CustomExternalBrowserExecutable; - KEY CustomExternalEmailExecutable; - VALUE(QString) CustomExternalEmailExecutableDef; + VALUE(QString) CustomExternalBrowserExecutableDef; + + KEY CustomExternalBrowserArguments; + + VALUE(char*) CustomExternalBrowserArgumentsDef; + + KEY CustomExternalEmailEnabled; + + VALUE(bool) CustomExternalEmailEnabledDef; + + KEY CustomExternalEmailExecutable; + + VALUE(QString) CustomExternalEmailExecutableDef; KEY ExternalTools; + VALUE(QStringList) ExternalToolsDef; - KEY CustomExternalEmailArguments; - VALUE(char*) CustomExternalEmailArgumentsDef; + KEY CustomExternalEmailArguments; + + VALUE(char*) CustomExternalEmailArgumentsDef; } // Categories. namespace CategoriesExpandStates { - KEY ID; + KEY ID; } class Settings : public QSettings { - Q_OBJECT + Q_OBJECT - public: - // Destructor. - virtual ~Settings(); + public: - // Type of used settings. - inline SettingsProperties::SettingsType type() const { - return m_initializationStatus; - } + // Destructor. + virtual ~Settings(); - // Getters/setters for settings values. - inline QVariant value(const QString& section, const QString& key, const QVariant& default_value = QVariant()) const { - return QSettings::value(QString(QSL("%1/%2")).arg(section, key), default_value); - } + // Type of used settings. + inline SettingsProperties::SettingsType type() const { + return m_initializationStatus; + } - inline void setValue(const QString& section, const QString& key, const QVariant& value) { - QSettings::setValue(QString(QSL("%1/%2")).arg(section, key), value); - } + // Getters/setters for settings values. + inline QVariant value(const QString& section, const QString& key, const QVariant& default_value = QVariant()) const { + return QSettings::value(QString(QSL("%1/%2")).arg(section, key), default_value); + } - inline void setValue(const QString& key, const QVariant& value) { - QSettings::setValue(key, value); - } + inline void setValue(const QString& section, const QString& key, const QVariant& value) { + QSettings::setValue(QString(QSL("%1/%2")).arg(section, key), value); + } - inline bool contains(const QString& section, const QString& key) const { - return QSettings::contains(QString(QSL("%1/%2")).arg(section, key)); - } + inline void setValue(const QString& key, const QVariant& value) { + QSettings::setValue(key, value); + } - inline void remove(const QString& section, const QString& key) { - QSettings::remove(QString(QSL("%1/%2")).arg(section, key)); - } + inline bool contains(const QString& section, const QString& key) const { + return QSettings::contains(QString(QSL("%1/%2")).arg(section, key)); + } - // Returns the path which contains the settings. - QString pathName() const; + inline void remove(const QString& section, const QString& key) { + QSettings::remove(QString(QSL("%1/%2")).arg(section, key)); + } - // Synchronizes settings. - QSettings::Status checkSettings(); + // Returns the path which contains the settings. + QString pathName() const; - bool initiateRestoration(const QString& settings_backup_file_path); - static void finishRestoration(const QString& desired_settings_file_path); + // Synchronizes settings. + QSettings::Status checkSettings(); - // Creates settings file in correct location. - static Settings* setupSettings(QObject* parent); + bool initiateRestoration(const QString& settings_backup_file_path); + static void finishRestoration(const QString& desired_settings_file_path); - // Returns properties of the actual application-wide settings. - static SettingsProperties determineProperties(); + // Creates settings file in correct location. + static Settings* setupSettings(QObject* parent); - private: - // Constructor. - explicit Settings(const QString& file_name, Format format, const SettingsProperties::SettingsType& type, QObject* parent = 0); + // Returns properties of the actual application-wide settings. + static SettingsProperties determineProperties(); - SettingsProperties::SettingsType m_initializationStatus; + private: + + // Constructor. + explicit Settings(const QString& file_name, Format format, const SettingsProperties::SettingsType& type, QObject* parent = 0); + + SettingsProperties::SettingsType m_initializationStatus; }; #endif // SETTINGS_H diff --git a/src/miscellaneous/settingsproperties.h b/src/miscellaneous/settingsproperties.h index 9d2d96984..a905363f0 100755 --- a/src/miscellaneous/settingsproperties.h +++ b/src/miscellaneous/settingsproperties.h @@ -3,20 +3,18 @@ #include - // Describes possible types of loaded settings. // Describes characteristics of settings. struct SettingsProperties { - enum SettingsType { - Portable, - NonPortable - }; - - SettingsType m_type; - QString m_baseDirectory; - QString m_settingsSuffix; - QString m_absoluteSettingsFileName; + enum SettingsType { + Portable, + NonPortable + }; + SettingsType m_type; + QString m_baseDirectory; + QString m_settingsSuffix; + QString m_absoluteSettingsFileName; }; #endif // SETTINGSPROPERTIES_H diff --git a/src/miscellaneous/simplecrypt/simplecrypt.cpp b/src/miscellaneous/simplecrypt/simplecrypt.cpp index 0a4ce60ac..cd8050e27 100755 --- a/src/miscellaneous/simplecrypt/simplecrypt.cpp +++ b/src/miscellaneous/simplecrypt/simplecrypt.cpp @@ -1,246 +1,261 @@ /* -Copyright (c) 2011, Andre Somers -All rights reserved. + Copyright (c) 2011, Andre Somers + All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of the Rathenau Instituut, Andre Somers nor the + * Neither the name of the Rathenau Instituut, Andre Somers nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL ANDRE SOMERS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR #######; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL ANDRE SOMERS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR #######; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #include "miscellaneous/simplecrypt/simplecrypt.h" #include -#include -#include -#include #include #include +#include +#include +#include - -SimpleCrypt::SimpleCrypt(): - m_key(0), - m_compressionMode(CompressionAlways), - m_protectionMode(ProtectionHash), - m_lastError(ErrorNoError) { - qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF)); +SimpleCrypt::SimpleCrypt() : + m_key(0), + m_compressionMode(CompressionAlways), + m_protectionMode(ProtectionHash), + m_lastError(ErrorNoError) { + qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF)); } -SimpleCrypt::SimpleCrypt(quint64 key): - m_key(key), - m_compressionMode(CompressionAlways), - m_protectionMode(ProtectionHash), - m_lastError(ErrorNoError) { - qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF)); - splitKey(); +SimpleCrypt::SimpleCrypt(quint64 key) : + m_key(key), + m_compressionMode(CompressionAlways), + m_protectionMode(ProtectionHash), + m_lastError(ErrorNoError) { + qsrand(uint(QDateTime::currentMSecsSinceEpoch() & 0xFFFF)); + splitKey(); } void SimpleCrypt::setKey(quint64 key) { - m_key = key; - splitKey(); + m_key = key; + splitKey(); } void SimpleCrypt::splitKey() { - m_keyParts.clear(); - m_keyParts.resize(8); + m_keyParts.clear(); + m_keyParts.resize(8); - for (int i = 0; i < 8; i++) { - quint64 part = m_key; + for (int i = 0; i < 8; i++) { + quint64 part = m_key; - for (int j = i; j > 0; j--) { - part = part >> 8; - } + for (int j = i; j > 0; j--) { + part = part >> 8; + } - part = part & 0xff; - m_keyParts[i] = static_cast(part); - } + part = part & 0xff; + m_keyParts[i] = static_cast(part); + } } QByteArray SimpleCrypt::encryptToByteArray(const QString& plaintext) { - return encryptToByteArray(plaintext.toUtf8()); + return encryptToByteArray(plaintext.toUtf8()); } QByteArray SimpleCrypt::encryptToByteArray(QByteArray plaintext) { - if (m_keyParts.isEmpty()) { - qWarning() << "No key set."; - m_lastError = ErrorNoKeySet; - return QByteArray(); - } + if (m_keyParts.isEmpty()) { + qWarning() << "No key set."; + m_lastError = ErrorNoKeySet; + return QByteArray(); + } - QByteArray ba = plaintext; - CryptoFlags flags = CryptoFlagNone; + QByteArray ba = plaintext; + CryptoFlags flags = CryptoFlagNone; - if (m_compressionMode == CompressionAlways) { - ba = qCompress(ba, 9); //maximum compression - flags |= CryptoFlagCompression; - } - else if (m_compressionMode == CompressionAuto) { - QByteArray compressed = qCompress(ba, 9); + if (m_compressionMode == CompressionAlways) { + ba = qCompress(ba, 9); //maximum compression + flags |= CryptoFlagCompression; + } + else if (m_compressionMode == CompressionAuto) { + QByteArray compressed = qCompress(ba, 9); - if (compressed.count() < ba.count()) { - ba = compressed; - flags |= CryptoFlagCompression; - } - } + if (compressed.count() < ba.count()) { + ba = compressed; + flags |= CryptoFlagCompression; + } + } - QByteArray integrityProtection; + QByteArray integrityProtection; - if (m_protectionMode == ProtectionChecksum) { - flags |= CryptoFlagChecksum; - QDataStream s(&integrityProtection, QIODevice::WriteOnly); - s << qChecksum(ba.constData(), ba.length()); - } - else if (m_protectionMode == ProtectionHash) { - flags |= CryptoFlagHash; - QCryptographicHash hash(QCryptographicHash::Sha1); - hash.addData(ba); - integrityProtection += hash.result(); - } + if (m_protectionMode == ProtectionChecksum) { + flags |= CryptoFlagChecksum; + QDataStream s(&integrityProtection, QIODevice::WriteOnly); - //prepend a random char to the string - char randomChar = char(qrand() & 0xFF); - ba = randomChar + integrityProtection + ba; - int pos(0); - char lastChar(0); - int cnt = ba.count(); + s << qChecksum(ba.constData(), ba.length()); + } + else if (m_protectionMode == ProtectionHash) { + flags |= CryptoFlagHash; + QCryptographicHash hash(QCryptographicHash::Sha1); - while (pos < cnt) { - ba[pos] = ba.at(pos) ^ m_keyParts.at(pos % 8) ^ lastChar; - lastChar = ba.at(pos); - ++pos; - } + hash.addData(ba); + integrityProtection += hash.result(); + } - QByteArray resultArray; - resultArray.append(char(0x03)); //version for future updates to algorithm - resultArray.append(char(flags)); //encryption flags - resultArray.append(ba); - m_lastError = ErrorNoError; - return resultArray; + //prepend a random char to the string + char randomChar = char(qrand() & 0xFF); + + ba = randomChar + integrityProtection + ba; + int pos(0); + char lastChar(0); + int cnt = ba.count(); + + while (pos < cnt) { + ba[pos] = ba.at(pos) ^ m_keyParts.at(pos % 8) ^ lastChar; + lastChar = ba.at(pos); + ++pos; + } + + QByteArray resultArray; + + resultArray.append(char(0x03)); //version for future updates to algorithm + resultArray.append(char(flags)); //encryption flags + resultArray.append(ba); + m_lastError = ErrorNoError; + return resultArray; } QString SimpleCrypt::encryptToString(const QString& plaintext) { - QByteArray plaintextArray = plaintext.toUtf8(); - QByteArray cypher = encryptToByteArray(plaintextArray); - QString cypherString = QString::fromLatin1(cypher.toBase64()); - return cypherString; + QByteArray plaintextArray = plaintext.toUtf8(); + QByteArray cypher = encryptToByteArray(plaintextArray); + QString cypherString = QString::fromLatin1(cypher.toBase64()); + + return cypherString; } QString SimpleCrypt::encryptToString(QByteArray plaintext) { - QByteArray cypher = encryptToByteArray(plaintext); - QString cypherString = QString::fromLatin1(cypher.toBase64()); - return cypherString; + QByteArray cypher = encryptToByteArray(plaintext); + QString cypherString = QString::fromLatin1(cypher.toBase64()); + + return cypherString; } QString SimpleCrypt::decryptToString(const QString& cyphertext) { - QByteArray cyphertextArray = QByteArray::fromBase64(cyphertext.toLatin1()); - QByteArray plaintextArray = decryptToByteArray(cyphertextArray); - QString plaintext = QString::fromUtf8(plaintextArray, plaintextArray.size()); - return plaintext; + QByteArray cyphertextArray = QByteArray::fromBase64(cyphertext.toLatin1()); + QByteArray plaintextArray = decryptToByteArray(cyphertextArray); + QString plaintext = QString::fromUtf8(plaintextArray, plaintextArray.size()); + + return plaintext; } QString SimpleCrypt::decryptToString(QByteArray cypher) { - QByteArray ba = decryptToByteArray(cypher); - QString plaintext = QString::fromUtf8(ba, ba.size()); - return plaintext; + QByteArray ba = decryptToByteArray(cypher); + QString plaintext = QString::fromUtf8(ba, ba.size()); + + return plaintext; } QByteArray SimpleCrypt::decryptToByteArray(const QString& cyphertext) { - QByteArray cyphertextArray = QByteArray::fromBase64(cyphertext.toLatin1()); - QByteArray ba = decryptToByteArray(cyphertextArray); - return ba; + QByteArray cyphertextArray = QByteArray::fromBase64(cyphertext.toLatin1()); + QByteArray ba = decryptToByteArray(cyphertextArray); + + return ba; } QByteArray SimpleCrypt::decryptToByteArray(QByteArray cypher) { - if (m_keyParts.isEmpty()) { - qWarning() << "No key set."; - m_lastError = ErrorNoKeySet; - return QByteArray(); - } + if (m_keyParts.isEmpty()) { + qWarning() << "No key set."; + m_lastError = ErrorNoKeySet; + return QByteArray(); + } - QByteArray ba = cypher; + QByteArray ba = cypher; - if (cypher.count() < 3) { - return QByteArray(); - } + if (cypher.count() < 3) { + return QByteArray(); + } - char version = ba.at(0); + char version = ba.at(0); - if (version != 3) { //we only work with version 3 - m_lastError = ErrorUnknownVersion; - qWarning() << "Invalid version or not a cyphertext."; - return QByteArray(); - } + if (version != 3) { //we only work with version 3 + m_lastError = ErrorUnknownVersion; + qWarning() << "Invalid version or not a cyphertext."; + return QByteArray(); + } - CryptoFlags flags = CryptoFlags(ba.at(1)); - ba = ba.mid(2); - int pos(0); - int cnt(ba.count()); - char lastChar = 0; + CryptoFlags flags = CryptoFlags(ba.at(1)); - while (pos < cnt) { - char currentChar = ba[pos]; - ba[pos] = ba.at(pos) ^ lastChar ^ m_keyParts.at(pos % 8); - lastChar = currentChar; - ++pos; - } + ba = ba.mid(2); + int pos(0); + int cnt(ba.count()); + char lastChar = 0; - ba = ba.mid(1); //chop off the random number at the start - bool integrityOk(true); + while (pos < cnt) { + char currentChar = ba[pos]; - if (flags.testFlag(CryptoFlagChecksum)) { - if (ba.length() < 2) { - m_lastError = ErrorIntegrityFailed; - return QByteArray(); - } + ba[pos] = ba.at(pos) ^ lastChar ^ m_keyParts.at(pos % 8); + lastChar = currentChar; + ++pos; + } - quint16 storedChecksum; - { - QDataStream s(&ba, QIODevice::ReadOnly); - s >> storedChecksum; - } - ba = ba.mid(2); - quint16 checksum = qChecksum(ba.constData(), ba.length()); - integrityOk = (checksum == storedChecksum); - } - else if (flags.testFlag(CryptoFlagHash)) { - if (ba.length() < 20) { - m_lastError = ErrorIntegrityFailed; - return QByteArray(); - } + ba = ba.mid(1); //chop off the random number at the start + bool integrityOk(true); - QByteArray storedHash = ba.left(20); - ba = ba.mid(20); - QCryptographicHash hash(QCryptographicHash::Sha1); - hash.addData(ba); - integrityOk = (hash.result() == storedHash); - } + if (flags.testFlag(CryptoFlagChecksum)) { + if (ba.length() < 2) { + m_lastError = ErrorIntegrityFailed; + return QByteArray(); + } - if (!integrityOk) { - m_lastError = ErrorIntegrityFailed; - return QByteArray(); - } + quint16 storedChecksum; + { + QDataStream s(&ba, QIODevice::ReadOnly); - if (flags.testFlag(CryptoFlagCompression)) { - ba = qUncompress(ba); - } + s >> storedChecksum; + } - m_lastError = ErrorNoError; - return ba; + ba = ba.mid(2); + quint16 checksum = qChecksum(ba.constData(), ba.length()); + + integrityOk = (checksum == storedChecksum); + } + else if (flags.testFlag(CryptoFlagHash)) { + if (ba.length() < 20) { + m_lastError = ErrorIntegrityFailed; + return QByteArray(); + } + + QByteArray storedHash = ba.left(20); + + ba = ba.mid(20); + QCryptographicHash hash(QCryptographicHash::Sha1); + + hash.addData(ba); + integrityOk = (hash.result() == storedHash); + } + + if (!integrityOk) { + m_lastError = ErrorIntegrityFailed; + return QByteArray(); + } + + if (flags.testFlag(CryptoFlagCompression)) { + ba = qUncompress(ba); + } + + m_lastError = ErrorNoError; + return ba; } diff --git a/src/miscellaneous/simplecrypt/simplecrypt.h b/src/miscellaneous/simplecrypt/simplecrypt.h index ede64995b..cd888c3d2 100755 --- a/src/miscellaneous/simplecrypt/simplecrypt.h +++ b/src/miscellaneous/simplecrypt/simplecrypt.h @@ -1,239 +1,253 @@ /* -Copyright (c) 2011, Andre Somers -All rights reserved. + Copyright (c) 2011, Andre Somers + All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of the Rathenau Instituut, Andre Somers nor the + * Neither the name of the Rathenau Instituut, Andre Somers nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL ANDRE SOMERS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR #######; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL ANDRE SOMERS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR #######; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef SIMPLECRYPT_H #define SIMPLECRYPT_H +#include #include #include -#include - /** - @short Simple encryption and decryption of strings and byte arrays + @short Simple encryption and decryption of strings and byte arrays - This class provides a simple implementation of encryption and decryption - of strings and byte arrays. + This class provides a simple implementation of encryption and decryption + of strings and byte arrays. - @warning The encryption provided by this class is NOT strong encryption. It may - help to shield things from curious eyes, but it will NOT stand up to someone - determined to break the encryption. Don't say you were not warned. + @warning The encryption provided by this class is NOT strong encryption. It may + help to shield things from curious eyes, but it will NOT stand up to someone + determined to break the encryption. Don't say you were not warned. - The class uses a 64 bit key. Simply create an instance of the class, set the key, - and use the encryptToString() method to calculate an encrypted version of the input string. - To decrypt that string again, use an instance of SimpleCrypt initialized with - the same key, and call the decryptToString() method with the encrypted string. If the key - matches, the decrypted version of the string will be returned again. + The class uses a 64 bit key. Simply create an instance of the class, set the key, + and use the encryptToString() method to calculate an encrypted version of the input string. + To decrypt that string again, use an instance of SimpleCrypt initialized with + the same key, and call the decryptToString() method with the encrypted string. If the key + matches, the decrypted version of the string will be returned again. - If you do not provide a key, or if something else is wrong, the encryption and - decryption function will return an empty string or will return a string containing nonsense. - lastError() will return a value indicating if the method was succesful, and if not, why not. + If you do not provide a key, or if something else is wrong, the encryption and + decryption function will return an empty string or will return a string containing nonsense. + lastError() will return a value indicating if the method was succesful, and if not, why not. + + SimpleCrypt is prepared for the case that the encryption and decryption + algorithm is changed in a later version, by prepending a version identifier to the cypertext. + */ - SimpleCrypt is prepared for the case that the encryption and decryption - algorithm is changed in a later version, by prepending a version identifier to the cypertext. - */ class SimpleCrypt { - public: - /** - CompressionMode describes if compression will be applied to the data to be - encrypted. - */ - enum CompressionMode { - CompressionAuto, /*!< Only apply compression if that results in a shorter plaintext. */ - CompressionAlways, /*!< Always apply compression. Note that for short inputs, a compression may result in longer data */ - CompressionNever /*!< Never apply compression. */ - }; - /** - IntegrityProtectionMode describes measures taken to make it possible to detect problems with the data - or wrong decryption keys. + public: - Measures involve adding a checksum or a cryptograhpic hash to the data to be encrypted. This - increases the length of the resulting cypertext, but makes it possible to check if the plaintext - appears to be valid after decryption. - */ - enum IntegrityProtectionMode { - ProtectionNone, /*!< The integerity of the encrypted data is not protected. It is not really possible to detect a wrong key, for instance. */ - ProtectionChecksum,/*!< A simple checksum is used to verify that the data is in order. If not, an empty string is returned. */ - ProtectionHash /*!< A cryptographic hash is used to verify the integrity of the data. This method produces a much stronger, but longer check */ - }; - /** - Error describes the type of error that occured. - */ - enum Error { - ErrorNoError, /*!< No error occurred. */ - ErrorNoKeySet, /*!< No key was set. You can not encrypt or decrypt without a valid key. */ - ErrorUnknownVersion, /*!< The version of this data is unknown, or the data is otherwise not valid. */ - ErrorIntegrityFailed /*!< The integrity check of the data failed. Perhaps the wrong key was used. */ - }; + /** + CompressionMode describes if compression will be applied to the data to be + encrypted. + */ + enum CompressionMode { + CompressionAuto, /*!< Only apply compression if that results in a shorter plaintext. */ + CompressionAlways, /*!< Always apply compression. Note that for short inputs, a compression may result in longer data */ + CompressionNever /*!< Never apply compression. */ + }; - /** - Constructor. + /** + IntegrityProtectionMode describes measures taken to make it possible to detect problems with the data + or wrong decryption keys. - Constructs a SimpleCrypt instance without a valid key set on it. - */ - SimpleCrypt(); - /** - Constructor. + Measures involve adding a checksum or a cryptograhpic hash to the data to be encrypted. This + increases the length of the resulting cypertext, but makes it possible to check if the plaintext + appears to be valid after decryption. + */ + enum IntegrityProtectionMode { + ProtectionNone, /*!< The integerity of the encrypted data is not protected. It is not really possible to detect a wrong key, for instance. */ + ProtectionChecksum,/*!< A simple checksum is used to verify that the data is in order. If not, an empty string is returned. */ + ProtectionHash /*!< A cryptographic hash is used to verify the integrity of the data. This method produces a much stronger, but longer check */ + }; - Constructs a SimpleCrypt instance and initializes it with the given @arg key. - */ - explicit SimpleCrypt(quint64 key); + /** + Error describes the type of error that occured. + */ + enum Error { + ErrorNoError, /*!< No error occurred. */ + ErrorNoKeySet, /*!< No key was set. You can not encrypt or decrypt without a valid key. */ + ErrorUnknownVersion, /*!< The version of this data is unknown, or the data is otherwise not valid. */ + ErrorIntegrityFailed /*!< The integrity check of the data failed. Perhaps the wrong key was used. */ + }; - /** - (Re-) initializes the key with the given @arg key. - */ - void setKey(quint64 key); - /** - Returns true if SimpleCrypt has been initialized with a key. - */ - bool hasKey() const { - return !m_keyParts.isEmpty(); - } + /** + Constructor. - /** - Sets the compression mode to use when encrypting data. The default mode is Auto. + Constructs a SimpleCrypt instance without a valid key set on it. + */ + SimpleCrypt(); - Note that decryption is not influenced by this mode, as the decryption recognizes - what mode was used when encrypting. - */ - void setCompressionMode(CompressionMode mode) { - m_compressionMode = mode; - } - /** - Returns the CompressionMode that is currently in use. - */ - CompressionMode compressionMode() const { - return m_compressionMode; - } + /** + Constructor. - /** - Sets the integrity mode to use when encrypting data. The default mode is Checksum. + Constructs a SimpleCrypt instance and initializes it with the given @arg key. + */ + explicit SimpleCrypt(quint64 key); - Note that decryption is not influenced by this mode, as the decryption recognizes - what mode was used when encrypting. - */ - void setIntegrityProtectionMode(IntegrityProtectionMode mode) { - m_protectionMode = mode; - } - /** - Returns the IntegrityProtectionMode that is currently in use. - */ - IntegrityProtectionMode integrityProtectionMode() const { - return m_protectionMode; - } + /** + (Re-) initializes the key with the given @arg key. + */ + void setKey(quint64 key); - /** - Returns the last error that occurred. - */ - Error lastError() const { - return m_lastError; - } + /** + Returns true if SimpleCrypt has been initialized with a key. + */ + bool hasKey() const { + return !m_keyParts.isEmpty(); + } - /** - Encrypts the @arg plaintext string with the key the class was initialized with, and returns - a cyphertext the result. The result is a base64 encoded version of the binary array that is the - actual result of the string, so it can be stored easily in a text format. - */ - QString encryptToString(const QString& plaintext) ; - /** - Encrypts the @arg plaintext QByteArray with the key the class was initialized with, and returns - a cyphertext the result. The result is a base64 encoded version of the binary array that is the - actual result of the encryption, so it can be stored easily in a text format. - */ - QString encryptToString(QByteArray plaintext) ; - /** - Encrypts the @arg plaintext string with the key the class was initialized with, and returns - a binary cyphertext in a QByteArray the result. + /** + Sets the compression mode to use when encrypting data. The default mode is Auto. - This method returns a byte array, that is useable for storing a binary format. If you need - a string you can store in a text file, use encryptToString() instead. - */ - QByteArray encryptToByteArray(const QString& plaintext) ; - /** - Encrypts the @arg plaintext QByteArray with the key the class was initialized with, and returns - a binary cyphertext in a QByteArray the result. + Note that decryption is not influenced by this mode, as the decryption recognizes + what mode was used when encrypting. + */ + void setCompressionMode(CompressionMode mode) { + m_compressionMode = mode; + } - This method returns a byte array, that is useable for storing a binary format. If you need - a string you can store in a text file, use encryptToString() instead. - */ - QByteArray encryptToByteArray(QByteArray plaintext) ; + /** + Returns the CompressionMode that is currently in use. + */ + CompressionMode compressionMode() const { + return m_compressionMode; + } - /** - Decrypts a cyphertext string encrypted with this class with the set key back to the - plain text version. + /** + Sets the integrity mode to use when encrypting data. The default mode is Checksum. - If an error occured, such as non-matching keys between encryption and decryption, - an empty string or a string containing nonsense may be returned. - */ - QString decryptToString(const QString& cyphertext) ; - /** - Decrypts a cyphertext string encrypted with this class with the set key back to the - plain text version. + Note that decryption is not influenced by this mode, as the decryption recognizes + what mode was used when encrypting. + */ + void setIntegrityProtectionMode(IntegrityProtectionMode mode) { + m_protectionMode = mode; + } - If an error occured, such as non-matching keys between encryption and decryption, - an empty string or a string containing nonsense may be returned. - */ - QByteArray decryptToByteArray(const QString& cyphertext) ; - /** - Decrypts a cyphertext binary encrypted with this class with the set key back to the - plain text version. + /** + Returns the IntegrityProtectionMode that is currently in use. + */ + IntegrityProtectionMode integrityProtectionMode() const { + return m_protectionMode; + } - If an error occured, such as non-matching keys between encryption and decryption, - an empty string or a string containing nonsense may be returned. - */ - QString decryptToString(QByteArray cypher) ; - /** - Decrypts a cyphertext binary encrypted with this class with the set key back to the - plain text version. + /** + Returns the last error that occurred. + */ + Error lastError() const { + return m_lastError; + } - If an error occured, such as non-matching keys between encryption and decryption, - an empty string or a string containing nonsense may be returned. - */ - QByteArray decryptToByteArray(QByteArray cypher) ; + /** + Encrypts the @arg plaintext string with the key the class was initialized with, and returns + a cyphertext the result. The result is a base64 encoded version of the binary array that is the + actual result of the string, so it can be stored easily in a text format. + */ + QString encryptToString(const QString& plaintext); - //enum to describe options that have been used for the encryption. Currently only one, but - //that only leaves room for future extensions like adding a cryptographic hash... - enum CryptoFlag {CryptoFlagNone = 0, - CryptoFlagCompression = 0x01, - CryptoFlagChecksum = 0x02, - CryptoFlagHash = 0x04 - }; + /** + Encrypts the @arg plaintext QByteArray with the key the class was initialized with, and returns + a cyphertext the result. The result is a base64 encoded version of the binary array that is the + actual result of the encryption, so it can be stored easily in a text format. + */ + QString encryptToString(QByteArray plaintext); - Q_DECLARE_FLAGS(CryptoFlags, CryptoFlag) + /** + Encrypts the @arg plaintext string with the key the class was initialized with, and returns + a binary cyphertext in a QByteArray the result. - private: - void splitKey(); + This method returns a byte array, that is useable for storing a binary format. If you need + a string you can store in a text file, use encryptToString() instead. + */ + QByteArray encryptToByteArray(const QString& plaintext); - quint64 m_key; - QVector m_keyParts; - CompressionMode m_compressionMode; - IntegrityProtectionMode m_protectionMode; - Error m_lastError; + /** + Encrypts the @arg plaintext QByteArray with the key the class was initialized with, and returns + a binary cyphertext in a QByteArray the result. + + This method returns a byte array, that is useable for storing a binary format. If you need + a string you can store in a text file, use encryptToString() instead. + */ + QByteArray encryptToByteArray(QByteArray plaintext); + + /** + Decrypts a cyphertext string encrypted with this class with the set key back to the + plain text version. + + If an error occured, such as non-matching keys between encryption and decryption, + an empty string or a string containing nonsense may be returned. + */ + QString decryptToString(const QString& cyphertext); + + /** + Decrypts a cyphertext string encrypted with this class with the set key back to the + plain text version. + + If an error occured, such as non-matching keys between encryption and decryption, + an empty string or a string containing nonsense may be returned. + */ + QByteArray decryptToByteArray(const QString& cyphertext); + + /** + Decrypts a cyphertext binary encrypted with this class with the set key back to the + plain text version. + + If an error occured, such as non-matching keys between encryption and decryption, + an empty string or a string containing nonsense may be returned. + */ + QString decryptToString(QByteArray cypher); + + /** + Decrypts a cyphertext binary encrypted with this class with the set key back to the + plain text version. + + If an error occured, such as non-matching keys between encryption and decryption, + an empty string or a string containing nonsense may be returned. + */ + QByteArray decryptToByteArray(QByteArray cypher); + + //enum to describe options that have been used for the encryption. Currently only one, but + //that only leaves room for future extensions like adding a cryptographic hash... + enum CryptoFlag {CryptoFlagNone = 0, + CryptoFlagCompression = 0x01, + CryptoFlagChecksum = 0x02, + CryptoFlagHash = 0x04}; + + Q_DECLARE_FLAGS(CryptoFlags, CryptoFlag) + + private: + void splitKey(); + + quint64 m_key; + + QVector m_keyParts; + CompressionMode m_compressionMode; + IntegrityProtectionMode m_protectionMode; + Error m_lastError; }; + Q_DECLARE_OPERATORS_FOR_FLAGS(SimpleCrypt::CryptoFlags) #endif // SimpleCrypt_H diff --git a/src/miscellaneous/simpleregexp.cpp b/src/miscellaneous/simpleregexp.cpp index c4b09bbd4..d74002578 100755 --- a/src/miscellaneous/simpleregexp.cpp +++ b/src/miscellaneous/simpleregexp.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -18,60 +19,57 @@ #include "miscellaneous/simpleregexp.h" - SimpleRegExp::SimpleRegExp() - : QRegularExpression(QString(), QRegularExpression::DotMatchesEverythingOption), m_matchedLength(-1) { -} + : QRegularExpression(QString(), QRegularExpression::DotMatchesEverythingOption), m_matchedLength(-1) {} SimpleRegExp::SimpleRegExp(const QString& pattern, Qt::CaseSensitivity cs) - : QRegularExpression(pattern, QRegularExpression::DotMatchesEverythingOption), m_matchedLength(-1) { - if (cs == Qt::CaseInsensitive) { - setPatternOptions(patternOptions() | QRegularExpression::CaseInsensitiveOption); - } + : QRegularExpression(pattern, QRegularExpression::DotMatchesEverythingOption), m_matchedLength(-1) { + if (cs == Qt::CaseInsensitive) { + setPatternOptions(patternOptions() | QRegularExpression::CaseInsensitiveOption); + } } SimpleRegExp::SimpleRegExp(const SimpleRegExp& re) - : QRegularExpression(re), m_matchedLength(-1) { -} + : QRegularExpression(re), m_matchedLength(-1) {} void SimpleRegExp::setMinimal(bool minimal) { - QRegularExpression::PatternOptions opt; + QRegularExpression::PatternOptions opt; - if (minimal) { - opt = patternOptions() | QRegularExpression::InvertedGreedinessOption; - } - else { - opt = patternOptions() & ~QRegularExpression::InvertedGreedinessOption; - } + if (minimal) { + opt = patternOptions() | QRegularExpression::InvertedGreedinessOption; + } + else { + opt = patternOptions() & ~QRegularExpression::InvertedGreedinessOption; + } - setPatternOptions(opt); + setPatternOptions(opt); } int SimpleRegExp::indexIn(const QString& str, int offset) const { - SimpleRegExp* that = const_cast(this); - QRegularExpressionMatch m = match(str, offset); + SimpleRegExp* that = const_cast(this); + QRegularExpressionMatch m = match(str, offset); - if (!m.hasMatch()) { - that->m_matchedLength = -1; - that->m_capturedTexts.clear(); - return -1; - } - else { - that->m_matchedLength = m.capturedLength(); - that->m_capturedTexts = m.capturedTexts(); - return m.capturedStart(); - } + if (!m.hasMatch()) { + that->m_matchedLength = -1; + that->m_capturedTexts.clear(); + return -1; + } + else { + that->m_matchedLength = m.capturedLength(); + that->m_capturedTexts = m.capturedTexts(); + return m.capturedStart(); + } } int SimpleRegExp::matchedLength() const { - return m_matchedLength; + return m_matchedLength; } QString SimpleRegExp::cap(int nth) const { - if (nth >= 0 && m_capturedTexts.size() > nth) { - return m_capturedTexts.at(nth); - } - else { - return QString(); - } + if (nth >= 0 && m_capturedTexts.size() > nth) { + return m_capturedTexts.at(nth); + } + else { + return QString(); + } } diff --git a/src/miscellaneous/simpleregexp.h b/src/miscellaneous/simpleregexp.h index a65db8245..ddd73ce4c 100755 --- a/src/miscellaneous/simpleregexp.h +++ b/src/miscellaneous/simpleregexp.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -22,21 +23,20 @@ #include #include - class SimpleRegExp : public QRegularExpression { - public: - explicit SimpleRegExp(); - explicit SimpleRegExp(const QString& pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive); - explicit SimpleRegExp(const SimpleRegExp& re); + public: + explicit SimpleRegExp(); + explicit SimpleRegExp(const QString& pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive); + explicit SimpleRegExp(const SimpleRegExp& re); - void setMinimal(bool minimal); - int indexIn(const QString& str, int offset = 0) const; - int matchedLength() const; - QString cap(int nth = 0) const; + void setMinimal(bool minimal); + int indexIn(const QString& str, int offset = 0) const; + int matchedLength() const; + QString cap(int nth = 0) const; - private: - QStringList m_capturedTexts; - int m_matchedLength; + private: + QStringList m_capturedTexts; + int m_matchedLength; }; #endif // SIMPLEREGEXP_H diff --git a/src/miscellaneous/skinfactory.cpp b/src/miscellaneous/skinfactory.cpp index 4d312a725..80b8c1cf9 100755 --- a/src/miscellaneous/skinfactory.cpp +++ b/src/miscellaneous/skinfactory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,160 +21,168 @@ #include "miscellaneous/application.h" #include -#include #include #include +#include +SkinFactory::SkinFactory(QObject* parent) : QObject(parent) {} -SkinFactory::SkinFactory(QObject* parent) : QObject(parent) { -} - -SkinFactory::~SkinFactory() { -} +SkinFactory::~SkinFactory() {} void SkinFactory::loadCurrentSkin() { - QList skin_names_to_try; - skin_names_to_try.append(selectedSkinName()); - skin_names_to_try.append(APP_SKIN_DEFAULT); - bool skin_parsed; - Skin skin_data; - QString skin_name; + QList skin_names_to_try; + skin_names_to_try.append(selectedSkinName()); + skin_names_to_try.append(APP_SKIN_DEFAULT); + bool skin_parsed; + Skin skin_data; + QString skin_name; - while (!skin_names_to_try.isEmpty()) { - skin_name = skin_names_to_try.takeFirst(); - skin_data = skinInfo(skin_name, &skin_parsed); + while (!skin_names_to_try.isEmpty()) { + skin_name = skin_names_to_try.takeFirst(); + skin_data = skinInfo(skin_name, &skin_parsed); - if (skin_parsed) { - loadSkinFromData(skin_data); - // Set this 'Skin' object as active one. - m_currentSkin = skin_data; - qDebug("Skin '%s' loaded.", qPrintable(skin_name)); - return; - } - else { - qWarning("Failed to load skin '%s'.", qPrintable(skin_name)); - } - } + if (skin_parsed) { + loadSkinFromData(skin_data); - qCritical("Failed to load selected or default skin. Quitting!"); + // Set this 'Skin' object as active one. + m_currentSkin = skin_data; + qDebug("Skin '%s' loaded.", qPrintable(skin_name)); + return; + } + else { + qWarning("Failed to load skin '%s'.", qPrintable(skin_name)); + } + } + + qCritical("Failed to load selected or default skin. Quitting!"); } void SkinFactory::loadSkinFromData(const Skin& skin) { - if (!skin.m_rawData.isEmpty()) { - qApp->setStyleSheet(skin.m_rawData); - } + if (!skin.m_rawData.isEmpty()) { + qApp->setStyleSheet(skin.m_rawData); + } - qApp->setStyle(qApp->settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString()); + qApp->setStyle(qApp->settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString()); } void SkinFactory::setCurrentSkinName(const QString& skin_name) { - qApp->settings()->setValue(GROUP(GUI), GUI::Skin, skin_name); + qApp->settings()->setValue(GROUP(GUI), GUI::Skin, skin_name); } QString SkinFactory::customSkinBaseFolder() const { - return qApp->userDataFolder() + QDir::separator() + APP_SKIN_USER_FOLDER; + return qApp->userDataFolder() + QDir::separator() + APP_SKIN_USER_FOLDER; } QString SkinFactory::selectedSkinName() const { - return qApp->settings()->value(GROUP(GUI), SETTING(GUI::Skin)).toString(); + return qApp->settings()->value(GROUP(GUI), SETTING(GUI::Skin)).toString(); } QString SkinFactory::adBlockedPage(const QString& subscription, const QString& rule) { - const QString& adblocked = currentSkin().m_adblocked.arg(tr("This page was blocked by AdBlock"), - tr("Blocked by set: \"%1\"
Blocked by filter: \"%2\"") - .arg(subscription, - rule)); - return currentSkin().m_layoutMarkupWrapper.arg(tr("This page was blocked by AdBlock"), adblocked); + const QString& adblocked = currentSkin().m_adblocked.arg(tr("This page was blocked by AdBlock"), + tr("Blocked by set: \"%1\"
Blocked by filter: \"%2\"") + .arg(subscription, + rule)); + + return currentSkin().m_layoutMarkupWrapper.arg(tr("This page was blocked by AdBlock"), adblocked); } Skin SkinFactory::skinInfo(const QString& skin_name, bool* ok) const { - Skin skin; - QStringList base_skin_folders; - base_skin_folders.append(APP_SKIN_PATH); - base_skin_folders.append(customSkinBaseFolder()); + Skin skin; + QStringList base_skin_folders; - while (!base_skin_folders.isEmpty()) { - const QString skin_folder = base_skin_folders.takeAt(0) + QDir::separator() + skin_name + QDir::separator(); - const QString metadata_file = skin_folder + APP_SKIN_METADATA_FILE; + base_skin_folders.append(APP_SKIN_PATH); + base_skin_folders.append(customSkinBaseFolder()); - if (QFile::exists(metadata_file)) { - QFile skin_file(metadata_file); - QDomDocument dokument; + while (!base_skin_folders.isEmpty()) { + const QString skin_folder = base_skin_folders.takeAt(0) + QDir::separator() + skin_name + QDir::separator(); + const QString metadata_file = skin_folder + APP_SKIN_METADATA_FILE; - if (!skin_file.open(QIODevice::Text | QIODevice::ReadOnly) || !dokument.setContent(&skin_file, true)) { - if (ok) { - *ok = false; - } + if (QFile::exists(metadata_file)) { + QFile skin_file(metadata_file); + QDomDocument dokument; - return skin; - } + if (!skin_file.open(QIODevice::Text | QIODevice::ReadOnly) || !dokument.setContent(&skin_file, true)) { + if (ok) { + *ok = false; + } - const QDomNode skin_node = dokument.namedItem(QSL("skin")); - // Obtain visible skin name. - skin.m_visibleName = skin_name; - // Obtain author. - skin.m_author = skin_node.namedItem(QSL("author")).namedItem(QSL("name")).toElement().text(); - // Obtain email. - skin.m_email = skin_node.namedItem(QSL("author")).namedItem(QSL("email")).toElement().text(); - // Obtain version. - skin.m_version = skin_node.attributes().namedItem(QSL("version")).toAttr().value(); - // Obtain other information. - skin.m_baseName = skin_name; - // Free resources. - skin_file.close(); - skin_file.deleteLater(); - // Here we use "/" instead of QDir::separator() because CSS2.1 url field - // accepts '/' as path elements separator. - // - // "##" is placeholder for the actual path to skin file. This is needed for using - // images within the QSS file. - // So if one uses "##/images/border.png" in QSS then it is - // replaced by fully absolute path and target file can - // be safely loaded. - skin.m_layoutMarkupWrapper = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("html_wrapper.html"))); - skin.m_layoutMarkupWrapper = skin.m_layoutMarkupWrapper.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_name); - skin.m_enclosureImageMarkup = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("html_enclosure_image.html"))); - skin.m_enclosureImageMarkup = skin.m_enclosureImageMarkup.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_name); - skin.m_layoutMarkup = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("html_single_message.html"))); - skin.m_layoutMarkup = skin.m_layoutMarkup.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_name); - skin.m_enclosureMarkup = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("html_enclosure_every.html"))); - skin.m_enclosureMarkup = skin.m_enclosureMarkup.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_name); - skin.m_rawData = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("theme.css"))); - skin.m_rawData = skin.m_rawData.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_name); - skin.m_adblocked = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("html_adblocked.html"))); + return skin; + } - if (ok != nullptr) { - *ok = !skin.m_author.isEmpty() && !skin.m_version.isEmpty() && - !skin.m_baseName.isEmpty() && !skin.m_email.isEmpty() && - !skin.m_layoutMarkup.isEmpty(); - } + const QDomNode skin_node = dokument.namedItem(QSL("skin")); - break; - } - } + // Obtain visible skin name. + skin.m_visibleName = skin_name; - return skin; + // Obtain author. + skin.m_author = skin_node.namedItem(QSL("author")).namedItem(QSL("name")).toElement().text(); + + // Obtain email. + skin.m_email = skin_node.namedItem(QSL("author")).namedItem(QSL("email")).toElement().text(); + + // Obtain version. + skin.m_version = skin_node.attributes().namedItem(QSL("version")).toAttr().value(); + + // Obtain other information. + skin.m_baseName = skin_name; + + // Free resources. + skin_file.close(); + skin_file.deleteLater(); + + // Here we use "/" instead of QDir::separator() because CSS2.1 url field + // accepts '/' as path elements separator. + // + // "##" is placeholder for the actual path to skin file. This is needed for using + // images within the QSS file. + // So if one uses "##/images/border.png" in QSS then it is + // replaced by fully absolute path and target file can + // be safely loaded. + skin.m_layoutMarkupWrapper = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("html_wrapper.html"))); + skin.m_layoutMarkupWrapper = skin.m_layoutMarkupWrapper.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_name); + skin.m_enclosureImageMarkup = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("html_enclosure_image.html"))); + skin.m_enclosureImageMarkup = skin.m_enclosureImageMarkup.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_name); + skin.m_layoutMarkup = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("html_single_message.html"))); + skin.m_layoutMarkup = skin.m_layoutMarkup.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_name); + skin.m_enclosureMarkup = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("html_enclosure_every.html"))); + skin.m_enclosureMarkup = skin.m_enclosureMarkup.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_name); + skin.m_rawData = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("theme.css"))); + skin.m_rawData = skin.m_rawData.replace(QSL("##"), APP_SKIN_PATH + QL1S("/") + skin_name); + skin.m_adblocked = QString::fromUtf8(IOFactory::readTextFile(skin_folder + QL1S("html_adblocked.html"))); + + if (ok != nullptr) { + *ok = !skin.m_author.isEmpty() && !skin.m_version.isEmpty() && + !skin.m_baseName.isEmpty() && !skin.m_email.isEmpty() && + !skin.m_layoutMarkup.isEmpty(); + } + + break; + } + } + + return skin; } QList SkinFactory::installedSkins() const { - QList skins; - bool skin_load_ok; - QStringList skin_directories = QDir(APP_SKIN_PATH).entryList(QDir::Dirs | - QDir::NoDotAndDotDot | - QDir::NoSymLinks | - QDir::Readable); - skin_directories.append(QDir(customSkinBaseFolder()).entryList(QDir::Dirs | - QDir::NoDotAndDotDot | - QDir::NoSymLinks | - QDir::Readable)); + QList skins; + bool skin_load_ok; + QStringList skin_directories = QDir(APP_SKIN_PATH).entryList(QDir::Dirs | + QDir::NoDotAndDotDot | + QDir::NoSymLinks | + QDir::Readable); - foreach (const QString& base_directory, skin_directories) { - const Skin skin_info = skinInfo(base_directory, &skin_load_ok); + skin_directories.append(QDir(customSkinBaseFolder()).entryList(QDir::Dirs | + QDir::NoDotAndDotDot | + QDir::NoSymLinks | + QDir::Readable)); - if (skin_load_ok) { - skins.append(skin_info); - } - } + foreach (const QString& base_directory, skin_directories) { + const Skin skin_info = skinInfo(base_directory, &skin_load_ok); - return skins; + if (skin_load_ok) { + skins.append(skin_info); + } + } + + return skins; } diff --git a/src/miscellaneous/skinfactory.h b/src/miscellaneous/skinfactory.h index ccba62a48..450dfb8ad 100755 --- a/src/miscellaneous/skinfactory.h +++ b/src/miscellaneous/skinfactory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,67 +21,67 @@ #include -#include #include - +#include struct Skin { - QString m_baseName; - QString m_visibleName; - QString m_author; - QString m_email; - QString m_version; - QString m_rawData; - QString m_adblocked; - QString m_layoutMarkupWrapper; - QString m_enclosureImageMarkup; - QString m_layoutMarkup; - QString m_enclosureMarkup; + QString m_baseName; + QString m_visibleName; + QString m_author; + QString m_email; + QString m_version; + QString m_rawData; + QString m_adblocked; + QString m_layoutMarkupWrapper; + QString m_enclosureImageMarkup; + QString m_layoutMarkup; + QString m_enclosureMarkup; }; Q_DECLARE_METATYPE(Skin) class SkinFactory : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Constructor. - explicit SkinFactory(QObject* parent = 0); + public: - // Destructor. - virtual ~SkinFactory(); + // Constructor. + explicit SkinFactory(QObject* parent = 0); - // Loads skin name from settings and sets it as active. - void loadCurrentSkin(); + // Destructor. + virtual ~SkinFactory(); - inline Skin currentSkin() const { - return m_currentSkin; - } + // Loads skin name from settings and sets it as active. + void loadCurrentSkin(); - // Returns the name of the skin, that should be activated - // after application restart. - QString selectedSkinName() const; + inline Skin currentSkin() const { + return m_currentSkin; + } - QString adBlockedPage(const QString& subscription, const QString& rule); + // Returns the name of the skin, that should be activated + // after application restart. + QString selectedSkinName() const; - // Gets skin about a particular skin. - Skin skinInfo(const QString& skin_name, bool* ok = nullptr) const; + QString adBlockedPage(const QString& subscription, const QString& rule); - // Returns list of installed skins. - QList installedSkins() const; + // Gets skin about a particular skin. + Skin skinInfo(const QString& skin_name, bool* ok = nullptr) const; - // Sets the desired skin as the active one if it exists. - void setCurrentSkinName(const QString& skin_name); + // Returns list of installed skins. + QList installedSkins() const; - QString customSkinBaseFolder() const; + // Sets the desired skin as the active one if it exists. + void setCurrentSkinName(const QString& skin_name); - private: + QString customSkinBaseFolder() const; - // Loads the skin from give skin_data. - void loadSkinFromData(const Skin& skin); + private: - // Holds name of the current skin. - Skin m_currentSkin; + // Loads the skin from give skin_data. + void loadSkinFromData(const Skin& skin); + + // Holds name of the current skin. + Skin m_currentSkin; }; #endif // SKINFACTORY_H diff --git a/src/miscellaneous/systemfactory.cpp b/src/miscellaneous/systemfactory.cpp index 480eb244c..7ed0aa33e 100755 --- a/src/miscellaneous/systemfactory.cpp +++ b/src/miscellaneous/systemfactory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,280 +18,285 @@ #include "miscellaneous/systemfactory.h" -#include "network-web/networkfactory.h" #include "miscellaneous/application.h" #include "miscellaneous/systemfactory.h" +#include "network-web/networkfactory.h" #if defined(Q_OS_WIN) #include #endif -#include -#include +#include +#include #include +#include +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include - +#include +#include typedef QPair UpdateCheck; -SystemFactory::SystemFactory(QObject* parent) : QObject(parent) { -} +SystemFactory::SystemFactory(QObject* parent) : QObject(parent) {} -SystemFactory::~SystemFactory() { -} +SystemFactory::~SystemFactory() {} SystemFactory::AutoStartStatus SystemFactory::autoStartStatus() const { - // User registry way to auto-start the application on Windows. + // User registry way to auto-start the application on Windows. #if defined(Q_OS_WIN) - QSettings registry_key(QSL("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"), - QSettings::NativeFormat); - const bool autostart_enabled = registry_key.value(QSL(APP_LOW_NAME), - QString()).toString().replace(QL1C('\\'), - QL1C('/')) == - Application::applicationFilePath(); - - if (autostart_enabled) { - return AutoStartStatus::Enabled; - } - else { - return AutoStartStatus::Disabled; - } + QSettings registry_key(QSL("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"), + QSettings::NativeFormat); + const bool autostart_enabled = registry_key.value(QSL(APP_LOW_NAME), + QString()).toString().replace(QL1C('\\'), + QL1C('/')) == + Application::applicationFilePath(); + if (autostart_enabled) { + return AutoStartStatus::Enabled; + } + else { + return AutoStartStatus::Disabled; + } #elif defined(Q_OS_LINUX) - // Use proper freedesktop.org way to auto-start the application on Linux. - // INFO: http://standards.freedesktop.org/autostart-spec/latest/ - const QString desktop_file_location = autostartDesktopFileLocation(); - // No correct path was found. - if (desktop_file_location.isEmpty()) { - qWarning("Searching for auto-start function status failed. HOME variable not found."); - return AutoStartStatus::Unavailable; - } + // Use proper freedesktop.org way to auto-start the application on Linux. + // INFO: http://standards.freedesktop.org/autostart-spec/latest/ + const QString desktop_file_location = autostartDesktopFileLocation(); - // We found correct path, now check if file exists and return correct status. - if (QFile::exists(desktop_file_location)) { - // File exists, we must read it and check if "Hidden" attribute is defined and what is its value. - QSettings desktop_settings(desktop_file_location, QSettings::IniFormat); - bool hidden_value = desktop_settings.value(QSL("Desktop Entry/Hidden"), false).toBool(); - return hidden_value ? AutoStartStatus::Disabled : AutoStartStatus::Enabled; - } - else { - return AutoStartStatus::Disabled; - } + // No correct path was found. + if (desktop_file_location.isEmpty()) { + qWarning("Searching for auto-start function status failed. HOME variable not found."); + return AutoStartStatus::Unavailable; + } + // We found correct path, now check if file exists and return correct status. + if (QFile::exists(desktop_file_location)) { + // File exists, we must read it and check if "Hidden" attribute is defined and what is its value. + QSettings desktop_settings(desktop_file_location, QSettings::IniFormat); + bool hidden_value = desktop_settings.value(QSL("Desktop Entry/Hidden"), false).toBool(); + + return hidden_value ? AutoStartStatus::Disabled : AutoStartStatus::Enabled; + } + else { + return AutoStartStatus::Disabled; + } #else - // Disable auto-start functionality on unsupported platforms. - return AutoStartStatus::Unavailable; + + // Disable auto-start functionality on unsupported platforms. + return AutoStartStatus::Unavailable; #endif } #if defined(Q_OS_LINUX) QString SystemFactory::autostartDesktopFileLocation() const { - const QString xdg_config_path(qgetenv("XDG_CONFIG_HOME")); - QString desktop_file_location; + const QString xdg_config_path(qgetenv("XDG_CONFIG_HOME")); + QString desktop_file_location; - if (!xdg_config_path.isEmpty()) { - // XDG_CONFIG_HOME variable is specified. Look for .desktop file - // in 'autostart' subdirectory. - desktop_file_location = xdg_config_path + QSL("/autostart/") + APP_DESKTOP_ENTRY_FILE; - } - else { - // Desired variable is not set, look for the default 'autostart' subdirectory. - const QString home_directory(qgetenv("HOME")); + if (!xdg_config_path.isEmpty()) { + // XDG_CONFIG_HOME variable is specified. Look for .desktop file + // in 'autostart' subdirectory. + desktop_file_location = xdg_config_path + QSL("/autostart/") + APP_DESKTOP_ENTRY_FILE; + } + else { + // Desired variable is not set, look for the default 'autostart' subdirectory. + const QString home_directory(qgetenv("HOME")); - if (!home_directory.isEmpty()) { - // Home directory exists. Check if target .desktop file exists and - // return according status. - desktop_file_location = home_directory + QSL("/.config/autostart/") + APP_DESKTOP_ENTRY_FILE; - } - } + if (!home_directory.isEmpty()) { + // Home directory exists. Check if target .desktop file exists and + // return according status. + desktop_file_location = home_directory + QSL("/.config/autostart/") + APP_DESKTOP_ENTRY_FILE; + } + } - return desktop_file_location; + return desktop_file_location; } + #endif bool SystemFactory::setAutoStartStatus(AutoStartStatus new_status) { - const SystemFactory::AutoStartStatus current_status = SystemFactory::autoStartStatus(); + const SystemFactory::AutoStartStatus current_status = SystemFactory::autoStartStatus(); - // Auto-start feature is not even available, exit. - if (current_status == AutoStartStatus::Unavailable) { - return false; - } + // Auto-start feature is not even available, exit. + if (current_status == AutoStartStatus::Unavailable) { + return false; + } #if defined(Q_OS_WIN) - QSettings registry_key(QSL("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"), QSettings::NativeFormat); + QSettings registry_key(QSL("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"), QSettings::NativeFormat); - switch (new_status) { - case AutoStartStatus::Enabled: - registry_key.setValue(APP_LOW_NAME, - Application::applicationFilePath().replace(QL1C('/'), QL1C('\\'))); - return true; + switch (new_status) { + case AutoStartStatus::Enabled: + registry_key.setValue(APP_LOW_NAME, + Application::applicationFilePath().replace(QL1C('/'), QL1C('\\'))); + return true; - case AutoStartStatus::Disabled: - registry_key.remove(APP_LOW_NAME); - return true; - - default: - return false; - } + case AutoStartStatus::Disabled: + registry_key.remove(APP_LOW_NAME); + return true; + default: + return false; + } #elif defined(Q_OS_LINUX) - // Note that we expect here that no other program uses - // "rssguard.desktop" desktop file. - const QString destination_file = autostartDesktopFileLocation(); - const QString destination_folder = QFileInfo(destination_file).absolutePath(); - switch (new_status) { - case AutoStartStatus::Enabled: { - if (QFile::exists(destination_file)) { - if (!QFile::remove(destination_file)) { - return false; - } - } + // Note that we expect here that no other program uses + // "rssguard.desktop" desktop file. + const QString destination_file = autostartDesktopFileLocation(); + const QString destination_folder = QFileInfo(destination_file).absolutePath(); - if (!QDir().mkpath(destination_folder)) { - return false; - } + switch (new_status) { + case AutoStartStatus::Enabled: { + if (QFile::exists(destination_file)) { + if (!QFile::remove(destination_file)) { + return false; + } + } - const QString source_autostart_desktop_file = QString(APP_DESKTOP_ENTRY_PATH) + QDir::separator() + APP_DESKTOP_SOURCE_ENTRY_FILE; - return QFile::copy(source_autostart_desktop_file, destination_file); - } + if (!QDir().mkpath(destination_folder)) { + return false; + } - case AutoStartStatus::Disabled: - return QFile::remove(destination_file); + const QString source_autostart_desktop_file = QString(APP_DESKTOP_ENTRY_PATH) + QDir::separator() + APP_DESKTOP_SOURCE_ENTRY_FILE; - default: - return false; - } + return QFile::copy(source_autostart_desktop_file, destination_file); + } + case AutoStartStatus::Disabled: + return QFile::remove(destination_file); + + default: + return false; + } #else - return false; + return false; #endif } #if defined(Q_OS_WIN) bool SystemFactory::removeTrolltechJunkRegistryKeys() { - if (qApp->settings()->value(GROUP(General), SETTING(General::RemoveTrolltechJunk)).toBool()) { - QSettings registry_key(QSL("HKEY_CURRENT_USER\\Software\\TrollTech"), QSettings::NativeFormat); - registry_key.remove(QSL("")); - registry_key.sync(); - return registry_key.status() == QSettings::NoError; - } - else { - return false; - } + if (qApp->settings()->value(GROUP(General), SETTING(General::RemoveTrolltechJunk)).toBool()) { + QSettings registry_key(QSL("HKEY_CURRENT_USER\\Software\\TrollTech"), QSettings::NativeFormat); + + registry_key.remove(QSL("")); + registry_key.sync(); + return registry_key.status() == QSettings::NoError; + } + else { + return false; + } } + #endif QString SystemFactory::loggedInUser() const { - QString name = qgetenv("USER"); + QString name = qgetenv("USER"); - if (name.isEmpty()) { - name = qgetenv("USERNAME"); - } + if (name.isEmpty()) { + name = qgetenv("USERNAME"); + } - if (name.isEmpty()) { - name = tr("anonymous"); - } + if (name.isEmpty()) { + name = tr("anonymous"); + } - return name; + return name; } void SystemFactory::checkForUpdates() const { - Downloader* downloader = new Downloader(); - connect(downloader, &Downloader::completed, [this, downloader]() { - QPair, QNetworkReply::NetworkError> result; - result.second = downloader->lastOutputError(); + Downloader* downloader = new Downloader(); - if (result.second == QNetworkReply::NoError) { - QByteArray obtained_data = downloader->lastOutputData(); - result.first = parseUpdatesFile(obtained_data); - } + connect(downloader, &Downloader::completed, [this, downloader]() { + QPair, QNetworkReply::NetworkError> result; + result.second = downloader->lastOutputError(); - emit updatesChecked(result); - downloader->deleteLater(); - }); - downloader->downloadFile(RELEASES_LIST); + if (result.second == QNetworkReply::NoError) { + QByteArray obtained_data = downloader->lastOutputData(); + result.first = parseUpdatesFile(obtained_data); + } + + emit updatesChecked(result); + downloader->deleteLater(); + }); + downloader->downloadFile(RELEASES_LIST); } bool SystemFactory::isVersionNewer(const QString& new_version, const QString& base_version) { - QStringList base_version_tkn = base_version.split(QL1C('.')); - QStringList new_version_tkn = new_version.split(QL1C('.')); + QStringList base_version_tkn = base_version.split(QL1C('.')); + QStringList new_version_tkn = new_version.split(QL1C('.')); - while (!base_version_tkn.isEmpty() && !new_version_tkn.isEmpty()) { - const int base_number = base_version_tkn.takeFirst().toInt(); - const int new_number = new_version_tkn.takeFirst().toInt(); + while (!base_version_tkn.isEmpty() && !new_version_tkn.isEmpty()) { + const int base_number = base_version_tkn.takeFirst().toInt(); + const int new_number = new_version_tkn.takeFirst().toInt(); - if (new_number > base_number) { - // New version is indeed higher thatn current version. - return true; - } - else if (new_number < base_number) { - return false; - } - } + if (new_number > base_number) { + // New version is indeed higher thatn current version. + return true; + } + else if (new_number < base_number) { + return false; + } + } - // Versions are either the same or they have unequal sizes. - if (base_version_tkn.isEmpty() && new_version_tkn.isEmpty()) { - // Versions are the same. - return false; - } - else { - if (new_version_tkn.isEmpty()) { - return false; - } - else { - return new_version_tkn.join(QString()).toInt() > 0; - } - } + // Versions are either the same or they have unequal sizes. + if (base_version_tkn.isEmpty() && new_version_tkn.isEmpty()) { + // Versions are the same. + return false; + } + else { + if (new_version_tkn.isEmpty()) { + return false; + } + else { + return new_version_tkn.join(QString()).toInt() > 0; + } + } } bool SystemFactory::isVersionEqualOrNewer(const QString& new_version, const QString& base_version) { - return new_version == base_version || isVersionNewer(new_version, base_version); + return new_version == base_version || isVersionNewer(new_version, base_version); } bool SystemFactory::openFolderFile(const QString& file_path) { #if defined(Q_OS_WIN) - return QProcess::startDetached(QString("explorer.exe /select, \"") + QDir::toNativeSeparators(file_path) + "\""); + return QProcess::startDetached(QString("explorer.exe /select, \"") + QDir::toNativeSeparators(file_path) + "\""); #else - const QString folder = QDir::toNativeSeparators(QFileInfo(file_path).absoluteDir().absolutePath()); - return QDesktopServices::openUrl(QUrl::fromLocalFile(folder)); + const QString folder = QDir::toNativeSeparators(QFileInfo(file_path).absoluteDir().absolutePath()); + + return QDesktopServices::openUrl(QUrl::fromLocalFile(folder)); #endif } QList SystemFactory::parseUpdatesFile(const QByteArray& updates_file) const { - QList updates; - QJsonArray document = QJsonDocument::fromJson(updates_file).array(); + QList updates; + QJsonArray document = QJsonDocument::fromJson(updates_file).array(); - for (int i = 0; i < document.size(); i++) { - QJsonObject release = document.at(i).toObject(); - UpdateInfo update; - update.m_date = QDateTime::fromString(release["published_at"].toString(), QSL("yyyy-MM-ddTHH:mm:ssZ")); - update.m_availableVersion = release["tag_name"].toString(); - update.m_changes = release["body"].toString(); - QJsonArray assets = release["assets"].toArray(); + for (int i = 0; i < document.size(); i++) { + QJsonObject release = document.at(i).toObject(); + UpdateInfo update; - for (int j = 0; j < assets.size(); j++) { - QJsonObject asset = assets.at(j).toObject(); - UpdateUrl url; - url.m_fileUrl = asset["browser_download_url"].toString(); - url.m_name = asset["name"].toString(); - url.m_size = asset["size"].toVariant().toString() + tr(" bytes"); - update.m_urls.append(url); - } + update.m_date = QDateTime::fromString(release["published_at"].toString(), QSL("yyyy-MM-ddTHH:mm:ssZ")); + update.m_availableVersion = release["tag_name"].toString(); + update.m_changes = release["body"].toString(); + QJsonArray assets = release["assets"].toArray(); - updates.append(update); - } + for (int j = 0; j < assets.size(); j++) { + QJsonObject asset = assets.at(j).toObject(); + UpdateUrl url; - qSort(updates.begin(), updates.end(), [](const UpdateInfo & a, const UpdateInfo & b) -> bool { - return a.m_date > b.m_date; - }); - return updates; + url.m_fileUrl = asset["browser_download_url"].toString(); + url.m_name = asset["name"].toString(); + url.m_size = asset["size"].toVariant().toString() + tr(" bytes"); + update.m_urls.append(url); + } + + updates.append(update); + } + + qSort(updates.begin(), updates.end(), [](const UpdateInfo& a, const UpdateInfo& b) -> bool { + return a.m_date > b.m_date; + }); + return updates; } diff --git a/src/miscellaneous/systemfactory.h b/src/miscellaneous/systemfactory.h index ddf2bfcaf..d267ea4e4 100755 --- a/src/miscellaneous/systemfactory.h +++ b/src/miscellaneous/systemfactory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,82 +23,83 @@ #include "network-web/downloader.h" -#include #include -#include +#include #include - +#include class UpdateUrl { - public: + public: - QString m_fileUrl; - QString m_name; - QString m_size; + QString m_fileUrl; + QString m_name; + QString m_size; }; class UpdateInfo { - public: + public: - QString m_availableVersion; - QString m_changes; - QDateTime m_date; + QString m_availableVersion; + QString m_changes; + QDateTime m_date; - QList m_urls; + QList m_urls; }; Q_DECLARE_METATYPE(UpdateInfo) class SystemFactory : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Specifies possible states of auto-start functionality. - enum class AutoStartStatus { - Enabled, - Disabled, - Unavailable - }; + public: - explicit SystemFactory(QObject* parent = nullptr); - virtual ~SystemFactory(); + // Specifies possible states of auto-start functionality. + enum class AutoStartStatus { + Enabled, + Disabled, + Unavailable + }; - // Returns current status of auto-start function. - SystemFactory::AutoStartStatus autoStartStatus() const; + explicit SystemFactory(QObject* parent = nullptr); + virtual ~SystemFactory(); - // Sets new status for auto-start function. - // Function returns false if setting of - // new status failed. - bool setAutoStartStatus(AutoStartStatus new_status); + // Returns current status of auto-start function. + SystemFactory::AutoStartStatus autoStartStatus() const; + + // Sets new status for auto-start function. + // Function returns false if setting of + // new status failed. + bool setAutoStartStatus(AutoStartStatus new_status); #if defined(Q_OS_WIN) - bool removeTrolltechJunkRegistryKeys(); + bool removeTrolltechJunkRegistryKeys(); #endif #if defined(Q_OS_LINUX) - // Returns standard location where auto-start .desktop files - // should be placed. - QString autostartDesktopFileLocation() const; + + // Returns standard location where auto-start .desktop files + // should be placed. + QString autostartDesktopFileLocation() const; #endif - // Retrieves username of currently logged-in user. - QString loggedInUser() const; + // Retrieves username of currently logged-in user. + QString loggedInUser() const; - // Tries to download list with new updates. - void checkForUpdates() const; + // Tries to download list with new updates. + void checkForUpdates() const; - // Checks if update is newer than current application version. - static bool isVersionNewer(const QString& new_version, const QString& base_version); - static bool isVersionEqualOrNewer(const QString& new_version, const QString& base_version); + // Checks if update is newer than current application version. + static bool isVersionNewer(const QString& new_version, const QString& base_version); + static bool isVersionEqualOrNewer(const QString& new_version, const QString& base_version); + static bool openFolderFile(const QString& file_path); - static bool openFolderFile(const QString& file_path); + signals: + void updatesChecked(QPair, QNetworkReply::NetworkError> updates) const; - signals: - void updatesChecked(QPair, QNetworkReply::NetworkError> updates) const; + private: - private: - // Performs parsing of downloaded file with list of updates. - QList parseUpdatesFile(const QByteArray& updates_file) const; + // Performs parsing of downloaded file with list of updates. + QList parseUpdatesFile(const QByteArray& updates_file) const; }; #endif // SYSTEMFACTORY_H diff --git a/src/miscellaneous/textfactory.cpp b/src/miscellaneous/textfactory.cpp index 536b0f085..2dec7b52c 100755 --- a/src/miscellaneous/textfactory.cpp +++ b/src/miscellaneous/textfactory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,138 +19,139 @@ #include "miscellaneous/textfactory.h" #include "definitions/definitions.h" -#include "miscellaneous/application.h" -#include "miscellaneous/simplecrypt/simplecrypt.h" -#include "miscellaneous/iofactory.h" #include "exceptions/applicationexception.h" +#include "miscellaneous/application.h" +#include "miscellaneous/iofactory.h" +#include "miscellaneous/simplecrypt/simplecrypt.h" +#include +#include #include #include -#include -#include - quint64 TextFactory::s_encryptionKey = 0x0; -TextFactory::TextFactory() { -} +TextFactory::TextFactory() {} int TextFactory::stringHeight(const QString& string, const QFontMetrics& metrics) { - const int count_lines = string.split(QL1C('\n')).size(); - return metrics.height() * count_lines; + const int count_lines = string.split(QL1C('\n')).size(); + + return metrics.height() * count_lines; } int TextFactory::stringWidth(const QString& string, const QFontMetrics& metrics) { - const QStringList lines = string.split(QL1C('\n')); - int width = 0; + const QStringList lines = string.split(QL1C('\n')); + int width = 0; - foreach (const QString& line, lines) { - int line_width = metrics.width(line); + foreach (const QString& line, lines) { + int line_width = metrics.width(line); - if (line_width > width) { - width = line_width; - } - } + if (line_width > width) { + width = line_width; + } + } - return width; + return width; } QDateTime TextFactory::parseDateTime(const QString& date_time) { - const QString input_date = date_time.simplified(); - QDateTime dt; - QTime time_zone_offset; - const QLocale locale(QLocale::C); - bool positive_time_zone_offset = false; - QStringList date_patterns; - date_patterns << QSL("yyyy-MM-ddTHH:mm:ss") << QSL("MMM dd yyyy hh:mm:ss") << - QSL("MMM d yyyy hh:mm:ss") << QSL("ddd, dd MMM yyyy HH:mm:ss") << - QSL("dd MMM yyyy") << QSL("yyyy-MM-dd HH:mm:ss.z") << QSL("yyyy-MM-dd") << - QSL("yyyy") << QSL("yyyy-MM") << QSL("yyyy-MM-dd") << QSL("yyyy-MM-ddThh:mm") << - QSL("yyyy-MM-ddThh:mm:ss"); - QStringList timezone_offset_patterns; - timezone_offset_patterns << QSL("+hh:mm") << QSL("-hh:mm") << QSL("+hhmm") - << QSL("-hhmm") << QSL("+hh") << QSL("-hh"); + const QString input_date = date_time.simplified(); + QDateTime dt; + QTime time_zone_offset; + const QLocale locale(QLocale::C); + bool positive_time_zone_offset = false; + QStringList date_patterns; - if (input_date.size() >= TIMEZONE_OFFSET_LIMIT) { - foreach (const QString& pattern, timezone_offset_patterns) { - time_zone_offset = QTime::fromString(input_date.right(pattern.size()), pattern); + date_patterns << QSL("yyyy-MM-ddTHH:mm:ss") << QSL("MMM dd yyyy hh:mm:ss") << + QSL("MMM d yyyy hh:mm:ss") << QSL("ddd, dd MMM yyyy HH:mm:ss") << + QSL("dd MMM yyyy") << QSL("yyyy-MM-dd HH:mm:ss.z") << QSL("yyyy-MM-dd") << + QSL("yyyy") << QSL("yyyy-MM") << QSL("yyyy-MM-dd") << QSL("yyyy-MM-ddThh:mm") << + QSL("yyyy-MM-ddThh:mm:ss"); + QStringList timezone_offset_patterns; - if (time_zone_offset.isValid()) { - positive_time_zone_offset = pattern.at(0) == QL1C('+'); - break; - } - } - } + timezone_offset_patterns << QSL("+hh:mm") << QSL("-hh:mm") << QSL("+hhmm") + << QSL("-hhmm") << QSL("+hh") << QSL("-hh"); - // Iterate over patterns and check if input date/time matches the pattern. - foreach (const QString& pattern, date_patterns) { - dt = locale.toDateTime(input_date.left(pattern.size()), pattern); + if (input_date.size() >= TIMEZONE_OFFSET_LIMIT) { + foreach (const QString& pattern, timezone_offset_patterns) { + time_zone_offset = QTime::fromString(input_date.right(pattern.size()), pattern); - if (dt.isValid()) { - // Make sure that this date/time is considered UTC. - dt.setTimeSpec(Qt::UTC); + if (time_zone_offset.isValid()) { + positive_time_zone_offset = pattern.at(0) == QL1C('+'); + break; + } + } + } - if (time_zone_offset.isValid()) { - // Time zone offset was detected. - if (positive_time_zone_offset) { - // Offset is positive, so we have to subtract it to get - // the original UTC. - return dt.addSecs(- QTime(0, 0, 0, 0).secsTo(time_zone_offset)); - } - else { - // Vice versa. - return dt.addSecs(QTime(0, 0, 0, 0).secsTo(time_zone_offset)); - } - } - else { - return dt; - } - } - } + // Iterate over patterns and check if input date/time matches the pattern. + foreach (const QString& pattern, date_patterns) { + dt = locale.toDateTime(input_date.left(pattern.size()), pattern); - // Parsing failed, return invalid datetime. - return QDateTime(); + if (dt.isValid()) { + // Make sure that this date/time is considered UTC. + dt.setTimeSpec(Qt::UTC); + + if (time_zone_offset.isValid()) { + // Time zone offset was detected. + if (positive_time_zone_offset) { + // Offset is positive, so we have to subtract it to get + // the original UTC. + return dt.addSecs(-QTime(0, 0, 0, 0).secsTo(time_zone_offset)); + } + else { + // Vice versa. + return dt.addSecs(QTime(0, 0, 0, 0).secsTo(time_zone_offset)); + } + } + else { + return dt; + } + } + } + + // Parsing failed, return invalid datetime. + return QDateTime(); } QDateTime TextFactory::parseDateTime(qint64 milis_from_epoch) { - return QDateTime::fromMSecsSinceEpoch(milis_from_epoch); + return QDateTime::fromMSecsSinceEpoch(milis_from_epoch); } QString TextFactory::encrypt(const QString& text) { - return SimpleCrypt(initializeSecretEncryptionKey()).encryptToString(text); + return SimpleCrypt(initializeSecretEncryptionKey()).encryptToString(text); } QString TextFactory::decrypt(const QString& text) { - return SimpleCrypt(initializeSecretEncryptionKey()).decryptToString(text); + return SimpleCrypt(initializeSecretEncryptionKey()).decryptToString(text); } QString TextFactory::shorten(const QString& input, int text_length_limit) { - if (input.size() > text_length_limit) { - return input.left(text_length_limit - ELLIPSIS_LENGTH) + QString(ELLIPSIS_LENGTH, QL1C('.')); - } - else { - return input; - } + if (input.size() > text_length_limit) { + return input.left(text_length_limit - ELLIPSIS_LENGTH) + QString(ELLIPSIS_LENGTH, QL1C('.')); + } + else { + return input; + } } quint64 TextFactory::initializeSecretEncryptionKey() { - if (s_encryptionKey == 0x0) { - // Check if file with encryption key exists. - QString encryption_file_path = qApp->settings()->pathName() + QDir::separator() + ENCRYPTION_FILE_NAME; + if (s_encryptionKey == 0x0) { + // Check if file with encryption key exists. + QString encryption_file_path = qApp->settings()->pathName() + QDir::separator() + ENCRYPTION_FILE_NAME; - try { - s_encryptionKey = (quint64) QString(IOFactory::readTextFile(encryption_file_path)).toLongLong(); - } - catch (ApplicationException) { - // Well, key does not exist or is invalid, generate and save one. - s_encryptionKey = generateSecretEncryptionKey(); - IOFactory::writeTextFile(encryption_file_path, QString::number(s_encryptionKey).toLocal8Bit()); - } - } + try { + s_encryptionKey = (quint64) QString(IOFactory::readTextFile(encryption_file_path)).toLongLong(); + } + catch (ApplicationException) { + // Well, key does not exist or is invalid, generate and save one. + s_encryptionKey = generateSecretEncryptionKey(); + IOFactory::writeTextFile(encryption_file_path, QString::number(s_encryptionKey).toLocal8Bit()); + } + } - return s_encryptionKey; + return s_encryptionKey; } quint64 TextFactory::generateSecretEncryptionKey() { - return RAND_MAX * qrand() + qrand(); + return RAND_MAX * qrand() + qrand(); } diff --git a/src/miscellaneous/textfactory.h b/src/miscellaneous/textfactory.h index 83296b8eb..990f66d65 100755 --- a/src/miscellaneous/textfactory.h +++ b/src/miscellaneous/textfactory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,41 +24,40 @@ #include #include - class TextFactory { - private: - // Constructors and destructors. - TextFactory(); + private: - public: - // Returns true if lhs is smaller than rhs if case-insensitive string comparison is used. - static inline bool isCaseInsensitiveLessThan(const QString& lhs, const QString& rhs) { - return lhs.toLower() < rhs.toLower(); - } + // Constructors and destructors. + TextFactory(); - static int stringHeight(const QString& string, const QFontMetrics& metrics); - static int stringWidth(const QString& string, const QFontMetrics& metrics); + public: - // Tries to parse input textual date/time representation. - // Returns invalid date/time if processing fails. - // NOTE: This method tries to always return time in UTC+00:00. - static QDateTime parseDateTime(const QString& date_time); + // Returns true if lhs is smaller than rhs if case-insensitive string comparison is used. + static inline bool isCaseInsensitiveLessThan(const QString& lhs, const QString& rhs) { + return lhs.toLower() < rhs.toLower(); + } - // Converts 1970-epoch miliseconds to date/time. - // NOTE: This apparently returns date/time in localtime. - static QDateTime parseDateTime(qint64 milis_from_epoch); + static int stringHeight(const QString& string, const QFontMetrics& metrics); + static int stringWidth(const QString& string, const QFontMetrics& metrics); - static QString encrypt(const QString& text); - static QString decrypt(const QString& text); + // Tries to parse input textual date/time representation. + // Returns invalid date/time if processing fails. + // NOTE: This method tries to always return time in UTC+00:00. + static QDateTime parseDateTime(const QString& date_time); - // Shortens input string according to given length limit. - static QString shorten(const QString& input, int text_length_limit = TEXT_TITLE_LIMIT); + // Converts 1970-epoch miliseconds to date/time. + // NOTE: This apparently returns date/time in localtime. + static QDateTime parseDateTime(qint64 milis_from_epoch); + static QString encrypt(const QString& text); + static QString decrypt(const QString& text); - private: - static quint64 initializeSecretEncryptionKey(); - static quint64 generateSecretEncryptionKey(); + // Shortens input string according to given length limit. + static QString shorten(const QString& input, int text_length_limit = TEXT_TITLE_LIMIT); - static quint64 s_encryptionKey; + private: + static quint64 initializeSecretEncryptionKey(); + static quint64 generateSecretEncryptionKey(); + static quint64 s_encryptionKey; }; #endif // TEXTFACTORY_H diff --git a/src/network-web/adblock/adblockaddsubscriptiondialog.cpp b/src/network-web/adblock/adblockaddsubscriptiondialog.cpp index 79cba641b..e34500407 100755 --- a/src/network-web/adblock/adblockaddsubscriptiondialog.cpp +++ b/src/network-web/adblock/adblockaddsubscriptiondialog.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -22,81 +23,80 @@ #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" -#include #include - +#include AdBlockAddSubscriptionDialog::AdBlockAddSubscriptionDialog(QWidget* parent) - : QDialog(parent), m_ui(new Ui::AdBlockAddSubscriptionDialog) { - m_ui->setupUi(this); - m_knownSubscriptions << Subscription(QSL("EasyList (English)"), ADBLOCK_EASYLIST_URL) - << Subscription(QSL("BSI Lista Polska (Polish)"), QSL("http://www.bsi.info.pl/filtrABP.txt")) - << Subscription(QSL("EasyList Czech and Slovak (Czech)"), - QSL("https://raw.githubusercontent.com/tomasko126/easylistczechandslovak/master/filters.txt")) - << Subscription(QSL("dutchblock (Dutch)"), QSL("http://groenewoudt.net/dutchblock/list.txt")) - << Subscription(QSL("Filtros Nauscopicos (Spanish)"), QSL("http://abp.mozilla-hispano.org/nauscopio/filtros.txt")) - << Subscription(QSL("IsraelList (Hebrew)"), QSL("http://secure.fanboy.co.nz/israelilist/IsraelList.txt")) - << Subscription(QSL("NLBlock (Dutch)"), QSL("http://www.verzijlbergh.com/adblock/nlblock.txt")) - << Subscription(QSL("Peter Lowe's list (English)"), - QSL("http://pgl.yoyo.org/adservers/serverlist.php?hostformat=adblockplus&mimetype=plaintext")) - << Subscription(QSL("PLgeneral (Polish)"), QSL("http://www.niecko.pl/adblock/adblock.txt")) - << Subscription(QSL("Schacks Adblock Plus liste (Danish)"), QSL("http://adblock.schack.dk/block.txt")) - << Subscription(QSL("Xfiles (Italian)"), QSL("http://mozilla.gfsolone.com/filtri.txt")) - << Subscription(QSL("EasyPrivacy (English)"), QSL("http://easylist-downloads.adblockplus.org/easyprivacy.txt")) - << Subscription(QSL("RU Adlist (Russian)"), QSL("https://easylist-downloads.adblockplus.org/advblock.txt")) - << Subscription(QSL("ABPindo (Indonesian)"), - QSL("https://raw.githubusercontent.com/heradhis/indonesianadblockrules/master/subscriptions/abpindo.txt")) - << Subscription(QSL("Easylist China (Chinese)"), QSL("https://easylist-downloads.adblockplus.org/easylistchina.txt")) - << Subscription(QSL("Anti-Adblock Killer"), - QSL("https://raw.githubusercontent.com/reek/anti-adblock-killer/master/anti-adblock-killer-filters.txt")); + : QDialog(parent), m_ui(new Ui::AdBlockAddSubscriptionDialog) { + m_ui->setupUi(this); + m_knownSubscriptions << Subscription(QSL("EasyList (English)"), ADBLOCK_EASYLIST_URL) + << Subscription(QSL("BSI Lista Polska (Polish)"), QSL("http://www.bsi.info.pl/filtrABP.txt")) + << Subscription(QSL("EasyList Czech and Slovak (Czech)"), + QSL("https://raw.githubusercontent.com/tomasko126/easylistczechandslovak/master/filters.txt")) + << Subscription(QSL("dutchblock (Dutch)"), QSL("http://groenewoudt.net/dutchblock/list.txt")) + << Subscription(QSL("Filtros Nauscopicos (Spanish)"), QSL("http://abp.mozilla-hispano.org/nauscopio/filtros.txt")) + << Subscription(QSL("IsraelList (Hebrew)"), QSL("http://secure.fanboy.co.nz/israelilist/IsraelList.txt")) + << Subscription(QSL("NLBlock (Dutch)"), QSL("http://www.verzijlbergh.com/adblock/nlblock.txt")) + << Subscription(QSL("Peter Lowe's list (English)"), + QSL("http://pgl.yoyo.org/adservers/serverlist.php?hostformat=adblockplus&mimetype=plaintext")) + << Subscription(QSL("PLgeneral (Polish)"), QSL("http://www.niecko.pl/adblock/adblock.txt")) + << Subscription(QSL("Schacks Adblock Plus liste (Danish)"), QSL("http://adblock.schack.dk/block.txt")) + << Subscription(QSL("Xfiles (Italian)"), QSL("http://mozilla.gfsolone.com/filtri.txt")) + << Subscription(QSL("EasyPrivacy (English)"), QSL("http://easylist-downloads.adblockplus.org/easyprivacy.txt")) + << Subscription(QSL("RU Adlist (Russian)"), QSL("https://easylist-downloads.adblockplus.org/advblock.txt")) + << Subscription(QSL("ABPindo (Indonesian)"), + QSL("https://raw.githubusercontent.com/heradhis/indonesianadblockrules/master/subscriptions/abpindo.txt")) + << Subscription(QSL("Easylist China (Chinese)"), QSL("https://easylist-downloads.adblockplus.org/easylistchina.txt")) + << Subscription(QSL("Anti-Adblock Killer"), + QSL("https://raw.githubusercontent.com/reek/anti-adblock-killer/master/anti-adblock-killer-filters.txt")); - foreach (const Subscription& subscription, m_knownSubscriptions) { - m_ui->m_cmbPresets->addItem(subscription.m_title); - } + foreach (const Subscription& subscription, m_knownSubscriptions) { + m_ui->m_cmbPresets->addItem(subscription.m_title); + } - connect(m_ui->m_cmbPresets, static_cast(&QComboBox::currentIndexChanged), this, - &AdBlockAddSubscriptionDialog::indexChanged); - connect(m_ui->m_cbUsePredefined, &QCheckBox::toggled, this, &AdBlockAddSubscriptionDialog::presetsEnabledChanged); - m_ui->m_cbUsePredefined->setChecked(true); - indexChanged(0); - setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); - setWindowIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE)); + connect(m_ui->m_cmbPresets, static_cast(&QComboBox::currentIndexChanged), this, + &AdBlockAddSubscriptionDialog::indexChanged); + connect(m_ui->m_cbUsePredefined, &QCheckBox::toggled, this, &AdBlockAddSubscriptionDialog::presetsEnabledChanged); + m_ui->m_cbUsePredefined->setChecked(true); + indexChanged(0); + setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); + setWindowIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE)); } QString AdBlockAddSubscriptionDialog::title() const { - return m_ui->m_txtTitle->text(); + return m_ui->m_txtTitle->text(); } QString AdBlockAddSubscriptionDialog::url() const { - return m_ui->m_txtUrl->text(); + return m_ui->m_txtUrl->text(); } void AdBlockAddSubscriptionDialog::indexChanged(int index) { - const Subscription subscription = m_knownSubscriptions.at(index); - const int pos = subscription.m_title.indexOf(QLatin1Char('(')); + const Subscription subscription = m_knownSubscriptions.at(index); + const int pos = subscription.m_title.indexOf(QLatin1Char('(')); - if (pos > 0) { - m_ui->m_txtTitle->setText(subscription.m_title.left(pos).trimmed()); - } - else { - m_ui->m_txtTitle->setText(subscription.m_title); - } + if (pos > 0) { + m_ui->m_txtTitle->setText(subscription.m_title.left(pos).trimmed()); + } + else { + m_ui->m_txtTitle->setText(subscription.m_title); + } - m_ui->m_txtUrl->setText(subscription.m_url); + m_ui->m_txtUrl->setText(subscription.m_url); } void AdBlockAddSubscriptionDialog::presetsEnabledChanged(bool enabled) { - m_ui->m_txtTitle->setEnabled(!enabled); - m_ui->m_txtUrl->setEnabled(!enabled); + m_ui->m_txtTitle->setEnabled(!enabled); + m_ui->m_txtUrl->setEnabled(!enabled); - if (!enabled) { - // Presets are disabled, clear txts. - m_ui->m_txtTitle->clear(); - m_ui->m_txtUrl->clear(); - m_ui->m_txtTitle->setFocus(); - } + if (!enabled) { + // Presets are disabled, clear txts. + m_ui->m_txtTitle->clear(); + m_ui->m_txtUrl->clear(); + m_ui->m_txtTitle->setFocus(); + } } AdBlockAddSubscriptionDialog::~AdBlockAddSubscriptionDialog() { - delete m_ui; + delete m_ui; } diff --git a/src/network-web/adblock/adblockaddsubscriptiondialog.h b/src/network-web/adblock/adblockaddsubscriptiondialog.h index 69d4247d0..146ea2286 100755 --- a/src/network-web/adblock/adblockaddsubscriptiondialog.h +++ b/src/network-web/adblock/adblockaddsubscriptiondialog.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -24,41 +25,41 @@ #include "ui_adblockaddsubscriptiondialog.h" - namespace Ui { - class AdBlockAddSubscriptionDialog; + class AdBlockAddSubscriptionDialog; } class AdBlockAddSubscriptionDialog : public QDialog { - Q_OBJECT + Q_OBJECT - public: - explicit AdBlockAddSubscriptionDialog(QWidget* parent = 0); - virtual ~AdBlockAddSubscriptionDialog(); + public: + explicit AdBlockAddSubscriptionDialog(QWidget* parent = 0); + virtual ~AdBlockAddSubscriptionDialog(); - QString title() const; - QString url() const; + QString title() const; + QString url() const; - private slots: - void indexChanged(int index); - void presetsEnabledChanged(bool enabled); + private slots: + void indexChanged(int index); + void presetsEnabledChanged(bool enabled); - private: - Ui::AdBlockAddSubscriptionDialog* m_ui; + private: + Ui::AdBlockAddSubscriptionDialog* m_ui; - struct Subscription { - QString m_title; - QString m_url; + struct Subscription { + QString m_title; + QString m_url; - Subscription() {} + Subscription() {} - Subscription(const QString& t, const QString& u) { - m_title = t; - m_url = u; - } - }; + Subscription(const QString& t, const QString& u) { + m_title = t; + m_url = u; + } - QVector m_knownSubscriptions; + }; + + QVector m_knownSubscriptions; }; #endif // ADBLOCKADDSUBSCRIPTIONDIALOG_H diff --git a/src/network-web/adblock/adblockdialog.cpp b/src/network-web/adblock/adblockdialog.cpp index a5bf6bb27..bfb95a91c 100755 --- a/src/network-web/adblock/adblockdialog.cpp +++ b/src/network-web/adblock/adblockdialog.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -18,141 +19,146 @@ #include "network-web/adblock/adblockdialog.h" +#include "network-web/adblock/adblockaddsubscriptiondialog.h" #include "network-web/adblock/adblockmanager.h" #include "network-web/adblock/adblocksubscription.h" #include "network-web/adblock/adblocktreewidget.h" -#include "network-web/adblock/adblockaddsubscriptiondialog.h" -#include "network-web/webfactory.h" +#include "definitions/definitions.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" -#include "definitions/definitions.h" +#include "network-web/webfactory.h" -#include -#include -#include #include - +#include +#include +#include AdBlockDialog::AdBlockDialog(QWidget* parent) - : QDialog(parent), m_ui(new Ui::AdBlockDialog), m_manager(AdBlockManager::instance()), m_currentTreeWidget(0), m_currentSubscription(0), - m_loaded(false) { - m_ui->setupUi(this); - m_ui->m_cbEnable->setChecked(m_manager->isEnabled()); - setAttribute(Qt::WA_DeleteOnClose); - setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); - setWindowIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE)); - QPushButton* btn_options = m_ui->m_buttonBox->addButton(QDialogButtonBox::FirstButton); - btn_options->setText(tr("Options")); - QMenu* menu = new QMenu(btn_options); - m_actionAddRule = menu->addAction(tr("Add rule"), this, &AdBlockDialog::addRule); - m_actionRemoveRule = menu->addAction(tr("Remove rule"), this, &AdBlockDialog::removeRule); - menu->addSeparator(); - m_actionAddSubscription = menu->addAction(tr("Add subscription"), this, &AdBlockDialog::addSubscription); - m_actionRemoveSubscription = menu->addAction(tr("Remove subscription"), this, &AdBlockDialog::removeSubscription); - menu->addAction(tr("Update subscriptions"), m_manager, &AdBlockManager::updateAllSubscriptions); - menu->addSeparator(); - menu->addAction(tr("Learn about writing rules..."), this, &AdBlockDialog::learnAboutRules); - btn_options->setMenu(menu); - connect(menu, &QMenu::aboutToShow, this, &AdBlockDialog::aboutToShowMenu); - connect(m_ui->m_cbEnable, &QCheckBox::toggled, this, &AdBlockDialog::enableAdBlock); - connect(m_ui->m_tabSubscriptions, &QTabWidget::currentChanged, this, &AdBlockDialog::currentChanged); - connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &AdBlockDialog::close); - load(); - m_ui->m_buttonBox->setFocus(); + : QDialog(parent), m_ui(new Ui::AdBlockDialog), m_manager(AdBlockManager::instance()), m_currentTreeWidget(0), m_currentSubscription(0), + m_loaded(false) { + m_ui->setupUi(this); + m_ui->m_cbEnable->setChecked(m_manager->isEnabled()); + setAttribute(Qt::WA_DeleteOnClose); + setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); + setWindowIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE)); + QPushButton* btn_options = m_ui->m_buttonBox->addButton(QDialogButtonBox::FirstButton); + + btn_options->setText(tr("Options")); + QMenu* menu = new QMenu(btn_options); + + m_actionAddRule = menu->addAction(tr("Add rule"), this, &AdBlockDialog::addRule); + m_actionRemoveRule = menu->addAction(tr("Remove rule"), this, &AdBlockDialog::removeRule); + menu->addSeparator(); + m_actionAddSubscription = menu->addAction(tr("Add subscription"), this, &AdBlockDialog::addSubscription); + m_actionRemoveSubscription = menu->addAction(tr("Remove subscription"), this, &AdBlockDialog::removeSubscription); + menu->addAction(tr("Update subscriptions"), m_manager, &AdBlockManager::updateAllSubscriptions); + menu->addSeparator(); + menu->addAction(tr("Learn about writing rules..."), this, &AdBlockDialog::learnAboutRules); + btn_options->setMenu(menu); + connect(menu, &QMenu::aboutToShow, this, &AdBlockDialog::aboutToShowMenu); + connect(m_ui->m_cbEnable, &QCheckBox::toggled, this, &AdBlockDialog::enableAdBlock); + connect(m_ui->m_tabSubscriptions, &QTabWidget::currentChanged, this, &AdBlockDialog::currentChanged); + connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &AdBlockDialog::close); + load(); + m_ui->m_buttonBox->setFocus(); } void AdBlockDialog::showRule(const AdBlockRule* rule) const { - AdBlockSubscription* subscription = rule->subscription(); + AdBlockSubscription* subscription = rule->subscription(); - if (subscription) { - for (int i = 0; i < m_ui->m_tabSubscriptions->count(); ++i) { - AdBlockTreeWidget* treeWidget = qobject_cast(m_ui->m_tabSubscriptions->widget(i)); + if (subscription) { + for (int i = 0; i < m_ui->m_tabSubscriptions->count(); ++i) { + AdBlockTreeWidget* treeWidget = qobject_cast(m_ui->m_tabSubscriptions->widget(i)); - if (subscription == treeWidget->subscription()) { - treeWidget->showRule(rule); - m_ui->m_tabSubscriptions->setCurrentIndex(i); - break; - } - } - } + if (subscription == treeWidget->subscription()) { + treeWidget->showRule(rule); + m_ui->m_tabSubscriptions->setCurrentIndex(i); + break; + } + } + } } void AdBlockDialog::addRule() { - m_currentTreeWidget->addRule(); + m_currentTreeWidget->addRule(); } void AdBlockDialog::removeRule() { - m_currentTreeWidget->removeRule(); + m_currentTreeWidget->removeRule(); } void AdBlockDialog::addSubscription() { - AdBlockAddSubscriptionDialog dialog(this); + AdBlockAddSubscriptionDialog dialog(this); - if (dialog.exec() != QDialog::Accepted) { - return; - } + if (dialog.exec() != QDialog::Accepted) { + return; + } - QString title = dialog.title(); - QString url = dialog.url(); + QString title = dialog.title(); + QString url = dialog.url(); - if (AdBlockSubscription* subscription = m_manager->addSubscription(title, url)) { - AdBlockTreeWidget* tree = new AdBlockTreeWidget(subscription, m_ui->m_tabSubscriptions); - int index = m_ui->m_tabSubscriptions->insertTab(m_ui->m_tabSubscriptions->count() - 1, tree, subscription->title()); - m_ui->m_tabSubscriptions->setCurrentIndex(index); - } + if (AdBlockSubscription* subscription = m_manager->addSubscription(title, url)) { + AdBlockTreeWidget* tree = new AdBlockTreeWidget(subscription, m_ui->m_tabSubscriptions); + int index = m_ui->m_tabSubscriptions->insertTab(m_ui->m_tabSubscriptions->count() - 1, tree, subscription->title()); + + m_ui->m_tabSubscriptions->setCurrentIndex(index); + } } void AdBlockDialog::removeSubscription() { - if (m_manager->removeSubscription(m_currentSubscription)) { - delete m_currentTreeWidget; - } + if (m_manager->removeSubscription(m_currentSubscription)) { + delete m_currentTreeWidget; + } } void AdBlockDialog::currentChanged(int index) { - if (index != -1) { - m_currentTreeWidget = qobject_cast(m_ui->m_tabSubscriptions->widget(index)); - m_currentSubscription = m_currentTreeWidget->subscription(); - } + if (index != -1) { + m_currentTreeWidget = qobject_cast(m_ui->m_tabSubscriptions->widget(index)); + m_currentSubscription = m_currentTreeWidget->subscription(); + } } void AdBlockDialog::enableAdBlock(bool state) { - m_manager->setEnabled(state); + m_manager->setEnabled(state); - if (state) { - load(); - } + if (state) { + load(); + } } void AdBlockDialog::aboutToShowMenu() { - bool subscriptionEditable = m_currentSubscription && m_currentSubscription->canEditRules(); - bool subscriptionRemovable = m_currentSubscription && m_currentSubscription->canBeRemoved(); - m_actionAddRule->setEnabled(subscriptionEditable); - m_actionRemoveRule->setEnabled(subscriptionEditable); - m_actionRemoveSubscription->setEnabled(subscriptionRemovable); + bool subscriptionEditable = m_currentSubscription && m_currentSubscription->canEditRules(); + bool subscriptionRemovable = m_currentSubscription && m_currentSubscription->canBeRemoved(); + + m_actionAddRule->setEnabled(subscriptionEditable); + m_actionRemoveRule->setEnabled(subscriptionEditable); + m_actionRemoveSubscription->setEnabled(subscriptionRemovable); } void AdBlockDialog::learnAboutRules() { - qApp->web()->openUrlInExternalBrowser(QSL(ADBLOCK_HOWTO_FILTERS)); + qApp->web()->openUrlInExternalBrowser(QSL(ADBLOCK_HOWTO_FILTERS)); } void AdBlockDialog::loadSubscriptions() { - for (int i = 0; i < m_ui->m_tabSubscriptions->count(); ++i) { - AdBlockTreeWidget* treeWidget = qobject_cast(m_ui->m_tabSubscriptions->widget(i)); - treeWidget->refresh(); - } + for (int i = 0; i < m_ui->m_tabSubscriptions->count(); ++i) { + AdBlockTreeWidget* treeWidget = qobject_cast(m_ui->m_tabSubscriptions->widget(i)); + + treeWidget->refresh(); + } } void AdBlockDialog::load() { - if (m_loaded || !m_ui->m_cbEnable->isChecked()) { - return; - } + if (m_loaded || !m_ui->m_cbEnable->isChecked()) { + return; + } - foreach (AdBlockSubscription* subscription, m_manager->subscriptions()) { - AdBlockTreeWidget* tree = new AdBlockTreeWidget(subscription, m_ui->m_tabSubscriptions); - m_ui->m_tabSubscriptions->addTab(tree, subscription->title()); - } + foreach (AdBlockSubscription* subscription, m_manager->subscriptions()) { + AdBlockTreeWidget* tree = new AdBlockTreeWidget(subscription, m_ui->m_tabSubscriptions); - m_loaded = true; - QTimer::singleShot(50, this, SLOT(loadSubscriptions())); + m_ui->m_tabSubscriptions->addTab(tree, subscription->title()); + } + + m_loaded = true; + QTimer::singleShot(50, this, SLOT(loadSubscriptions())); } diff --git a/src/network-web/adblock/adblockdialog.h b/src/network-web/adblock/adblockdialog.h index eabd641c3..b815e7568 100755 --- a/src/network-web/adblock/adblockdialog.h +++ b/src/network-web/adblock/adblockdialog.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -23,50 +24,46 @@ #include "ui_adblockdialog.h" - class AdBlockSubscription; class AdBlockTreeWidget; class AdBlockManager; class AdBlockRule; class AdBlockDialog : public QDialog { - Q_OBJECT + Q_OBJECT - public: - explicit AdBlockDialog(QWidget* parent = 0); + public: + explicit AdBlockDialog(QWidget* parent = 0); - void showRule(const AdBlockRule* rule) const; + void showRule(const AdBlockRule* rule) const; - private slots: - void addRule(); - void removeRule(); + private slots: + void addRule(); + void removeRule(); - void addSubscription(); - void removeSubscription(); + void addSubscription(); + void removeSubscription(); - void currentChanged(int index); - void enableAdBlock(bool state); + void currentChanged(int index); + void enableAdBlock(bool state); - void aboutToShowMenu(); - void learnAboutRules(); + void aboutToShowMenu(); + void learnAboutRules(); - void loadSubscriptions(); - void load(); + void loadSubscriptions(); + void load(); - private: - AdBlockManager* m_manager; - AdBlockTreeWidget* m_currentTreeWidget; - AdBlockSubscription* m_currentSubscription; + private: + AdBlockManager* m_manager; + AdBlockTreeWidget* m_currentTreeWidget; + AdBlockSubscription* m_currentSubscription; + QAction* m_actionAddRule; + QAction* m_actionRemoveRule; + QAction* m_actionAddSubscription; + QAction* m_actionRemoveSubscription; + bool m_loaded; - QAction* m_actionAddRule; - QAction* m_actionRemoveRule; - QAction* m_actionAddSubscription; - QAction* m_actionRemoveSubscription; - - bool m_loaded; - - Ui::AdBlockDialog* m_ui; + Ui::AdBlockDialog* m_ui; }; #endif // ADBLOCKDIALOG_H - diff --git a/src/network-web/adblock/adblockicon.cpp b/src/network-web/adblock/adblockicon.cpp index 6e637ee5c..a57224ccd 100755 --- a/src/network-web/adblock/adblockicon.cpp +++ b/src/network-web/adblock/adblockicon.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -18,159 +19,162 @@ #include "network-web/adblock/adblockicon.h" -#include "network-web/adblock/adblockrule.h" -#include "network-web/adblock/adblockmanager.h" -#include "network-web/adblock/adblocksubscription.h" -#include "miscellaneous/application.h" -#include "network-web/webpage.h" +#include "gui/dialogs/formmain.h" #include "gui/webbrowser.h" #include "gui/webviewer.h" -#include "gui/dialogs/formmain.h" +#include "miscellaneous/application.h" +#include "network-web/adblock/adblockmanager.h" +#include "network-web/adblock/adblockrule.h" +#include "network-web/adblock/adblocksubscription.h" +#include "network-web/webpage.h" #include #include #include - AdBlockIcon::AdBlockIcon(AdBlockManager* parent) - : QAction(parent), m_manager(parent), m_flashTimer(0), m_timerTicks(0), m_enabled(m_manager->isEnabled()) { - setToolTip(tr("AdBlock lets you block unwanted content on web pages")); - setText(QSL("AdBlock")); - setMenu(new QMenu()); - setIcon(m_enabled ? qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE) : qApp->icons()->miscIcon(ADBLOCK_ICON_DISABLED)); - connect(m_manager, SIGNAL(enabledChanged(bool)), this, SLOT(setEnabled(bool))); - connect(menu(), SIGNAL(aboutToShow()), this, SLOT(createMenu())); - connect(this, &QAction::triggered, m_manager, &AdBlockManager::showDialog); + : QAction(parent), m_manager(parent), m_flashTimer(0), m_timerTicks(0), m_enabled(m_manager->isEnabled()) { + setToolTip(tr("AdBlock lets you block unwanted content on web pages")); + setText(QSL("AdBlock")); + setMenu(new QMenu()); + setIcon(m_enabled ? qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE) : qApp->icons()->miscIcon(ADBLOCK_ICON_DISABLED)); + connect(m_manager, SIGNAL(enabledChanged(bool)), this, SLOT(setEnabled(bool))); + connect(menu(), SIGNAL(aboutToShow()), this, SLOT(createMenu())); + connect(this, &QAction::triggered, m_manager, &AdBlockManager::showDialog); } AdBlockIcon::~AdBlockIcon() { - for (int i = 0; i < m_blockedPopups.count(); ++i) { - delete m_blockedPopups.at(i).first; - } + for (int i = 0; i < m_blockedPopups.count(); ++i) { + delete m_blockedPopups.at(i).first; + } - if (menu() != nullptr) { - menu()->deleteLater(); - } + if (menu() != nullptr) { + menu()->deleteLater(); + } } void AdBlockIcon::popupBlocked(const QString& ruleString, const QUrl& url) { - int index = ruleString.lastIndexOf(QLatin1String(" (")); - const QString subscriptionName = ruleString.left(index); - const QString filter = ruleString.mid(index + 2, ruleString.size() - index - 3); - AdBlockSubscription* subscription = m_manager->subscriptionByName(subscriptionName); + int index = ruleString.lastIndexOf(QLatin1String(" (")); + const QString subscriptionName = ruleString.left(index); + const QString filter = ruleString.mid(index + 2, ruleString.size() - index - 3); + AdBlockSubscription* subscription = m_manager->subscriptionByName(subscriptionName); - if (filter.isEmpty() || !subscription) { - return; - } + if (filter.isEmpty() || !subscription) { + return; + } - QPair pair; - pair.first = new AdBlockRule(filter, subscription); - pair.second = url; - m_blockedPopups.append(pair); - qApp->showGuiMessage(tr("Blocked popup window"), tr("AdBlock blocked unwanted popup window."), QSystemTrayIcon::Information); + QPair pair; + pair.first = new AdBlockRule(filter, subscription); + pair.second = url; + m_blockedPopups.append(pair); + qApp->showGuiMessage(tr("Blocked popup window"), tr("AdBlock blocked unwanted popup window."), QSystemTrayIcon::Information); - if (!m_flashTimer) { - m_flashTimer = new QTimer(this); - } + if (!m_flashTimer) { + m_flashTimer = new QTimer(this); + } - if (m_flashTimer->isActive()) { - stopAnimation(); - } + if (m_flashTimer->isActive()) { + stopAnimation(); + } - m_flashTimer->setInterval(500); - m_flashTimer->start(); - connect(m_flashTimer, &QTimer::timeout, this, &AdBlockIcon::animateIcon); + m_flashTimer->setInterval(500); + m_flashTimer->start(); + connect(m_flashTimer, &QTimer::timeout, this, &AdBlockIcon::animateIcon); } void AdBlockIcon::createMenu(QMenu* menu) { - if (!menu) { - menu = qobject_cast(sender()); + if (!menu) { + menu = qobject_cast(sender()); - if (!menu) { - return; - } - } + if (!menu) { + return; + } + } - menu->clear(); - AdBlockCustomList* customList = m_manager->customList(); - WebPage* page = qApp->mainForm()->tabWidget()->currentWidget()->webBrowser()->viewer()->page(); - const QUrl pageUrl = page->url(); - menu->addAction(tr("Show AdBlock &settings"), m_manager, SLOT(showDialog())); - menu->addSeparator(); + menu->clear(); + AdBlockCustomList* customList = m_manager->customList(); + WebPage* page = qApp->mainForm()->tabWidget()->currentWidget()->webBrowser()->viewer()->page(); + const QUrl pageUrl = page->url(); - if (!pageUrl.host().isEmpty() && m_enabled && m_manager->canRunOnScheme(pageUrl.scheme())) { - const QString host = page->url().host().contains(QLatin1String("www.")) ? pageUrl.host().mid(4) : pageUrl.host(); - const QString hostFilter = QString("@@||%1^$document").arg(host); - const QString pageFilter = QString("@@|%1|$document").arg(pageUrl.toString()); - QAction* act = menu->addAction(tr("Disable on %1").arg(host)); - act->setCheckable(true); - act->setChecked(customList->containsFilter(hostFilter)); - act->setData(hostFilter); - connect(act, SIGNAL(triggered()), this, SLOT(toggleCustomFilter())); - act = menu->addAction(tr("Disable only on this page")); - act->setCheckable(true); - act->setChecked(customList->containsFilter(pageFilter)); - act->setData(pageFilter); - connect(act, SIGNAL(triggered()), this, SLOT(toggleCustomFilter())); - menu->addSeparator(); - } + menu->addAction(tr("Show AdBlock &settings"), m_manager, SLOT(showDialog())); + menu->addSeparator(); + + if (!pageUrl.host().isEmpty() && m_enabled && m_manager->canRunOnScheme(pageUrl.scheme())) { + const QString host = page->url().host().contains(QLatin1String("www.")) ? pageUrl.host().mid(4) : pageUrl.host(); + const QString hostFilter = QString("@@||%1^$document").arg(host); + const QString pageFilter = QString("@@|%1|$document").arg(pageUrl.toString()); + QAction* act = menu->addAction(tr("Disable on %1").arg(host)); + + act->setCheckable(true); + act->setChecked(customList->containsFilter(hostFilter)); + act->setData(hostFilter); + connect(act, SIGNAL(triggered()), this, SLOT(toggleCustomFilter())); + act = menu->addAction(tr("Disable only on this page")); + act->setCheckable(true); + act->setChecked(customList->containsFilter(pageFilter)); + act->setData(pageFilter); + connect(act, SIGNAL(triggered()), this, SLOT(toggleCustomFilter())); + menu->addSeparator(); + } } void AdBlockIcon::showMenu(const QPoint& pos) { - QMenu menu; - createMenu(&menu); - menu.exec(pos); + QMenu menu; + + createMenu(&menu); + menu.exec(pos); } void AdBlockIcon::toggleCustomFilter() { - QAction* action = qobject_cast(sender()); + QAction* action = qobject_cast(sender()); - if (!action) { - return; - } + if (!action) { + return; + } - const QString filter = action->data().toString(); - AdBlockCustomList* customList = m_manager->customList(); + const QString filter = action->data().toString(); + AdBlockCustomList* customList = m_manager->customList(); - if (customList->containsFilter(filter)) { - customList->removeFilter(filter); - } - else { - AdBlockRule* rule = new AdBlockRule(filter, customList); - customList->addRule(rule); - } + if (customList->containsFilter(filter)) { + customList->removeFilter(filter); + } + else { + AdBlockRule* rule = new AdBlockRule(filter, customList); + + customList->addRule(rule); + } } void AdBlockIcon::animateIcon() { - ++m_timerTicks; + ++m_timerTicks; - if (m_timerTicks > 10) { - stopAnimation(); - return; - } + if (m_timerTicks > 10) { + stopAnimation(); + return; + } - if (icon().isNull()) { - setIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE)); - } - else { - setIcon(QIcon()); - } + if (icon().isNull()) { + setIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE)); + } + else { + setIcon(QIcon()); + } } void AdBlockIcon::stopAnimation() { - m_timerTicks = 0; - m_flashTimer->stop(); - disconnect(m_flashTimer, SIGNAL(timeout()), this, SLOT(animateIcon())); - setEnabled(m_enabled); + m_timerTicks = 0; + m_flashTimer->stop(); + disconnect(m_flashTimer, SIGNAL(timeout()), this, SLOT(animateIcon())); + setEnabled(m_enabled); } void AdBlockIcon::setEnabled(bool enabled) { - if (enabled) { - setIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE)); - } - else { - setIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_DISABLED)); - } + if (enabled) { + setIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_ACTIVE)); + } + else { + setIcon(qApp->icons()->miscIcon(ADBLOCK_ICON_DISABLED)); + } - m_enabled = enabled; + m_enabled = enabled; } diff --git a/src/network-web/adblock/adblockicon.h b/src/network-web/adblock/adblockicon.h index af780d3eb..b7bd6ce5e 100755 --- a/src/network-web/adblock/adblockicon.h +++ b/src/network-web/adblock/adblockicon.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -23,7 +24,6 @@ #include "network-web/adblock/adblockrule.h" - class QMenu; class QUrl; class QAction; @@ -33,32 +33,32 @@ class AdBlockManager; class BrowserWindow; class AdBlockIcon : public QAction { - Q_OBJECT + Q_OBJECT - public: - explicit AdBlockIcon(AdBlockManager* parent = 0); - virtual ~AdBlockIcon(); + public: + explicit AdBlockIcon(AdBlockManager* parent = 0); + virtual ~AdBlockIcon(); - void popupBlocked(const QString& ruleString, const QUrl& url); + void popupBlocked(const QString& ruleString, const QUrl& url); - public slots: - void setEnabled(bool enabled); - void createMenu(QMenu* menu = 0); + public slots: + void setEnabled(bool enabled); + void createMenu(QMenu* menu = 0); - private slots: - void showMenu(const QPoint& pos); - void toggleCustomFilter(); + private slots: + void showMenu(const QPoint& pos); + void toggleCustomFilter(); - void animateIcon(); - void stopAnimation(); + void animateIcon(); + void stopAnimation(); - private: - AdBlockManager* m_manager; - QVector> m_blockedPopups; - QTimer* m_flashTimer; + private: + AdBlockManager* m_manager; - int m_timerTicks; - bool m_enabled; + QVector> m_blockedPopups; + QTimer* m_flashTimer; + int m_timerTicks; + bool m_enabled; }; #endif // ADBLOCKICON_H diff --git a/src/network-web/adblock/adblockmanager.cpp b/src/network-web/adblock/adblockmanager.cpp index 86f711df1..88dc78ec1 100755 --- a/src/network-web/adblock/adblockmanager.cpp +++ b/src/network-web/adblock/adblockmanager.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -21,8 +22,8 @@ #include "miscellaneous/application.h" #include "miscellaneous/settings.h" #include "network-web/adblock/adblockdialog.h" -#include "network-web/adblock/adblockmatcher.h" #include "network-web/adblock/adblockicon.h" +#include "network-web/adblock/adblockmatcher.h" #include "network-web/adblock/adblocksubscription.h" #include "network-web/adblock/adblockurlinterceptor.h" #include "network-web/networkurlinterceptor.h" @@ -40,326 +41,336 @@ Q_GLOBAL_STATIC(AdBlockManager, qz_adblock_manager) - AdBlockManager::AdBlockManager(QObject* parent) - : QObject(parent), m_loaded(false), m_enabled(true), m_matcher(new AdBlockMatcher(this)), m_interceptor(new AdBlockUrlInterceptor(this)) { - load(); - m_adblockIcon = new AdBlockIcon(this); - m_adblockIcon->setObjectName(QSL("m_adblockIconAction")); + : QObject(parent), m_loaded(false), m_enabled(true), m_matcher(new AdBlockMatcher(this)), m_interceptor(new AdBlockUrlInterceptor(this)) { + load(); + m_adblockIcon = new AdBlockIcon(this); + m_adblockIcon->setObjectName(QSL("m_adblockIconAction")); } AdBlockManager::~AdBlockManager() { - qDeleteAll(m_subscriptions); + qDeleteAll(m_subscriptions); } AdBlockManager* AdBlockManager::instance() { - return qz_adblock_manager(); + return qz_adblock_manager(); } void AdBlockManager::setEnabled(bool enabled) { - if (m_enabled == enabled) { - return; - } + if (m_enabled == enabled) { + return; + } - m_enabled = enabled; - emit enabledChanged(enabled); - qApp->settings()->setValue(GROUP(AdBlock), AdBlock::AdBlockEnabled, m_enabled); - load(); - // TODO: Reload user stylesheet. - // mApp->reloadUserStyleSheet(); - QMutexLocker locker(&m_mutex); + m_enabled = enabled; + emit enabledChanged(enabled); - if (m_enabled) { - m_matcher->update(); - } - else { - m_matcher->clear(); - } + qApp->settings()->setValue(GROUP(AdBlock), AdBlock::AdBlockEnabled, m_enabled); + load(); + + // TODO: Reload user stylesheet. + // mApp->reloadUserStyleSheet(); + QMutexLocker locker(&m_mutex); + + if (m_enabled) { + m_matcher->update(); + } + else { + m_matcher->clear(); + } } QList AdBlockManager::subscriptions() const { - return m_subscriptions; + return m_subscriptions; } bool AdBlockManager::block(QWebEngineUrlRequestInfo& request) { - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - if (!isEnabled()) { - return false; - } + if (!isEnabled()) { + return false; + } - const QString urlString = request.requestUrl().toEncoded().toLower(); - const QString urlDomain = request.requestUrl().host().toLower(); - const QString urlScheme = request.requestUrl().scheme().toLower(); + const QString urlString = request.requestUrl().toEncoded().toLower(); + const QString urlDomain = request.requestUrl().host().toLower(); + const QString urlScheme = request.requestUrl().scheme().toLower(); - if (!canRunOnScheme(urlScheme) || !canBeBlocked(request.firstPartyUrl())) { - return false; - } + if (!canRunOnScheme(urlScheme) || !canBeBlocked(request.firstPartyUrl())) { + return false; + } - bool res = false; - const AdBlockRule* blockedRule = m_matcher->match(request, urlDomain, urlString); + bool res = false; + const AdBlockRule* blockedRule = m_matcher->match(request, urlDomain, urlString); - if (blockedRule) { - if (request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeMainFrame) { - QUrlQuery query; - QUrl url(QSL("rssguard:adblockedpage")); - query.addQueryItem(QSL("rule"), blockedRule->filter()); - query.addQueryItem(QSL("subscription"), blockedRule->subscription()->title()); - url.setQuery(query); - request.redirect(url); - } - else { - res = true; - request.block(true); - } - } + if (blockedRule) { + if (request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeMainFrame) { + QUrlQuery query; + QUrl url(QSL("rssguard:adblockedpage")); - return res; + query.addQueryItem(QSL("rule"), blockedRule->filter()); + query.addQueryItem(QSL("subscription"), blockedRule->subscription()->title()); + url.setQuery(query); + request.redirect(url); + } + else { + res = true; + request.block(true); + } + } + + return res; } QStringList AdBlockManager::disabledRules() const { - return m_disabledRules; + return m_disabledRules; } void AdBlockManager::addDisabledRule(const QString& filter) { - m_disabledRules.append(filter); + m_disabledRules.append(filter); } void AdBlockManager::removeDisabledRule(const QString& filter) { - m_disabledRules.removeOne(filter); + m_disabledRules.removeOne(filter); } bool AdBlockManager::addSubscriptionFromUrl(const QUrl& url) { - const QList> queryItems = QUrlQuery(url).queryItems(QUrl::FullyDecoded); - QString subscriptionTitle; - QString subscriptionUrl; + const QList> queryItems = QUrlQuery(url).queryItems(QUrl::FullyDecoded); + QString subscriptionTitle; + QString subscriptionUrl; - for (int i = 0; i < queryItems.count(); ++i) { - QPair pair = queryItems.at(i); + for (int i = 0; i < queryItems.count(); ++i) { + QPair pair = queryItems.at(i); - if (pair.first == QL1S("location")) { - subscriptionUrl = pair.second; - } - else if (pair.first == QL1S("title")) { - subscriptionTitle = pair.second; - } - } + if (pair.first == QL1S("location")) { + subscriptionUrl = pair.second; + } + else if (pair.first == QL1S("title")) { + subscriptionTitle = pair.second; + } + } - if (subscriptionTitle.isEmpty() || subscriptionUrl.isEmpty()) { - return false; - } + if (subscriptionTitle.isEmpty() || subscriptionUrl.isEmpty()) { + return false; + } - const QString message = tr("Do you want to add %1 subscription?").arg(subscriptionTitle); - QMessageBox::StandardButton result = QMessageBox::question(nullptr, tr("Add AdBlock subscription"), message, - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + const QString message = tr("Do you want to add %1 subscription?").arg(subscriptionTitle); - if (result == QMessageBox::Yes) { - AdBlockManager::instance()->addSubscription(subscriptionTitle, subscriptionUrl); - AdBlockManager::instance()->showDialog(); - } + QMessageBox::StandardButton result = QMessageBox::question(nullptr, tr("Add AdBlock subscription"), message, + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - return true; + if (result == QMessageBox::Yes) { + AdBlockManager::instance()->addSubscription(subscriptionTitle, subscriptionUrl); + AdBlockManager::instance()->showDialog(); + } + + return true; } AdBlockSubscription* AdBlockManager::addSubscription(const QString& title, const QString& url) { - if (title.isEmpty() || url.isEmpty()) { - return 0; - } + if (title.isEmpty() || url.isEmpty()) { + return 0; + } - QString fileName = title + QSL(".txt"); - QString filePath = storedListsPath() + QDir::separator() + fileName; - QByteArray data = QString("Title: %1\nUrl: %2\n[Adblock Plus 1.1.1]").arg(title, url).toLatin1(); - QSaveFile file(filePath); + QString fileName = title + QSL(".txt"); + QString filePath = storedListsPath() + QDir::separator() + fileName; + QByteArray data = QString("Title: %1\nUrl: %2\n[Adblock Plus 1.1.1]").arg(title, url).toLatin1(); + QSaveFile file(filePath); - if (!file.open(QFile::WriteOnly)) { - qWarning("Cannot save AdBlock subscription to file '%s'.", qPrintable(filePath)); - return 0; - } + if (!file.open(QFile::WriteOnly)) { + qWarning("Cannot save AdBlock subscription to file '%s'.", qPrintable(filePath)); + return 0; + } - file.write(data); - file.commit(); - AdBlockSubscription* subscription = new AdBlockSubscription(title, this); - subscription->setUrl(QUrl(url)); - subscription->setFilePath(filePath); - subscription->loadSubscription(m_disabledRules); - m_subscriptions.insert(m_subscriptions.count() - 1, subscription); - // TODO: Reload user stylesheet. - // connect(subscription, SIGNAL(subscriptionUpdated()), mApp, SLOT(reloadUserStyleSheet())); - connect(subscription, SIGNAL(subscriptionChanged()), this, SLOT(updateMatcher())); - return subscription; + file.write(data); + file.commit(); + AdBlockSubscription* subscription = new AdBlockSubscription(title, this); + + subscription->setUrl(QUrl(url)); + subscription->setFilePath(filePath); + subscription->loadSubscription(m_disabledRules); + m_subscriptions.insert(m_subscriptions.count() - 1, subscription); + + // TODO: Reload user stylesheet. + // connect(subscription, SIGNAL(subscriptionUpdated()), mApp, SLOT(reloadUserStyleSheet())); + connect(subscription, SIGNAL(subscriptionChanged()), this, SLOT(updateMatcher())); + return subscription; } bool AdBlockManager::removeSubscription(AdBlockSubscription* subscription) { - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - if (!m_subscriptions.contains(subscription) || !subscription->canBeRemoved()) { - return false; - } + if (!m_subscriptions.contains(subscription) || !subscription->canBeRemoved()) { + return false; + } - QFile(subscription->filePath()).remove(); - m_subscriptions.removeOne(subscription); - m_matcher->update(); - delete subscription; - return true; + QFile(subscription->filePath()).remove(); + m_subscriptions.removeOne(subscription); + m_matcher->update(); + delete subscription; + return true; } AdBlockCustomList* AdBlockManager::customList() const { - foreach (AdBlockSubscription* subscription, m_subscriptions) { - AdBlockCustomList* list = qobject_cast(subscription); + foreach (AdBlockSubscription* subscription, m_subscriptions) { + AdBlockCustomList* list = qobject_cast(subscription); - if (list) { - return list; - } - } + if (list) { + return list; + } + } - return 0; + return 0; } QString AdBlockManager::storedListsPath() { - return qApp->userDataFolder() + QDir::separator() + ADBLOCK_LISTS_SUBDIRECTORY; + return qApp->userDataFolder() + QDir::separator() + ADBLOCK_LISTS_SUBDIRECTORY; } void AdBlockManager::load() { - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - if (m_loaded) { - return; - } + if (m_loaded) { + return; + } - m_enabled = qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::AdBlockEnabled)).toBool(); - m_disabledRules = qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::DisabledRules)).toStringList(); - QDateTime lastUpdate = qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::LastUpdatedOn)).toDateTime(); + m_enabled = qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::AdBlockEnabled)).toBool(); + m_disabledRules = qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::DisabledRules)).toStringList(); + QDateTime lastUpdate = qApp->settings()->value(GROUP(AdBlock), SETTING(AdBlock::LastUpdatedOn)).toDateTime(); - if (!m_enabled) { - return; - } + if (!m_enabled) { + return; + } - QDir adblockDir(storedListsPath()); + QDir adblockDir(storedListsPath()); - // Create if neccessary - if (!adblockDir.exists()) { - QDir().mkpath(storedListsPath()); - } + // Create if neccessary + if (!adblockDir.exists()) { + QDir().mkpath(storedListsPath()); + } - foreach (const QString& fileName, adblockDir.entryList(QStringList("*.txt"), QDir::Files)) { - if (fileName == ADBLOCK_CUSTOMLIST_NAME) { - continue; - } + foreach (const QString& fileName, adblockDir.entryList(QStringList("*.txt"), QDir::Files)) { + if (fileName == ADBLOCK_CUSTOMLIST_NAME) { + continue; + } - const QString absolutePath = adblockDir.absoluteFilePath(fileName); - QFile file(absolutePath); + const QString absolutePath = adblockDir.absoluteFilePath(fileName); + QFile file(absolutePath); - if (!file.open(QFile::ReadOnly)) { - continue; - } + if (!file.open(QFile::ReadOnly)) { + continue; + } - QTextStream textStream(&file); - textStream.setCodec("UTF-8"); - QString title = textStream.readLine(1024).remove(QLatin1String("Title: ")); - QUrl url = QUrl(textStream.readLine(1024).remove(QLatin1String("Url: "))); + QTextStream textStream(&file); - if (title.isEmpty() || !url.isValid()) { - qWarning("Invalid AdBlock subscription file '%s'.", qPrintable(absolutePath)); - continue; - } + textStream.setCodec("UTF-8"); + QString title = textStream.readLine(1024).remove(QLatin1String("Title: ")); + QUrl url = QUrl(textStream.readLine(1024).remove(QLatin1String("Url: "))); - AdBlockSubscription* subscription = new AdBlockSubscription(title, this); - subscription->setUrl(url); - subscription->setFilePath(absolutePath); - m_subscriptions.append(subscription); - } + if (title.isEmpty() || !url.isValid()) { + qWarning("Invalid AdBlock subscription file '%s'.", qPrintable(absolutePath)); + continue; + } - // Append CustomList. - AdBlockCustomList* customList = new AdBlockCustomList(this); - m_subscriptions.append(customList); + AdBlockSubscription* subscription = new AdBlockSubscription(title, this); - // Load all subscriptions. - foreach (AdBlockSubscription* subscription, m_subscriptions) { - subscription->loadSubscription(m_disabledRules); - // TODO: Reload user stylesheet. - // connect(subscription, SIGNAL(subscriptionUpdated()), mApp, SLOT(reloadUserStyleSheet())); - connect(subscription, SIGNAL(subscriptionChanged()), this, SLOT(updateMatcher())); - } + subscription->setUrl(url); + subscription->setFilePath(absolutePath); + m_subscriptions.append(subscription); + } - if (lastUpdate.addDays(ADBLOCK_UPDATE_DAYS_INTERVAL) < QDateTime::currentDateTime()) { - QTimer::singleShot(1000 * 60, this, SLOT(updateAllSubscriptions())); - } + // Append CustomList. + AdBlockCustomList* customList = new AdBlockCustomList(this); - m_matcher->update(); - m_loaded = true; - qApp->urlIinterceptor()->installUrlInterceptor(m_interceptor); + m_subscriptions.append(customList); + + // Load all subscriptions. + foreach (AdBlockSubscription* subscription, m_subscriptions) { + subscription->loadSubscription(m_disabledRules); + + // TODO: Reload user stylesheet. + // connect(subscription, SIGNAL(subscriptionUpdated()), mApp, SLOT(reloadUserStyleSheet())); + connect(subscription, SIGNAL(subscriptionChanged()), this, SLOT(updateMatcher())); + } + + if (lastUpdate.addDays(ADBLOCK_UPDATE_DAYS_INTERVAL) < QDateTime::currentDateTime()) { + QTimer::singleShot(1000 * 60, this, SLOT(updateAllSubscriptions())); + } + + m_matcher->update(); + m_loaded = true; + qApp->urlIinterceptor()->installUrlInterceptor(m_interceptor); } void AdBlockManager::updateMatcher() { - QMutexLocker locker(&m_mutex); - m_matcher->update(); + QMutexLocker locker(&m_mutex); + + m_matcher->update(); } void AdBlockManager::updateAllSubscriptions() { - foreach (AdBlockSubscription* subscription, m_subscriptions) { - subscription->updateSubscription(); - } + foreach (AdBlockSubscription* subscription, m_subscriptions) { + subscription->updateSubscription(); + } - qApp->settings()->setValue(GROUP(AdBlock), AdBlock::LastUpdatedOn, QDateTime::currentDateTime()); + qApp->settings()->setValue(GROUP(AdBlock), AdBlock::LastUpdatedOn, QDateTime::currentDateTime()); } void AdBlockManager::save() { - if (!m_loaded) { - return; - } + if (!m_loaded) { + return; + } - foreach (AdBlockSubscription* subscription, m_subscriptions) { - subscription->saveSubscription(); - } + foreach (AdBlockSubscription* subscription, m_subscriptions) { + subscription->saveSubscription(); + } - qApp->settings()->setValue(GROUP(AdBlock), AdBlock::AdBlockEnabled, m_enabled); - qApp->settings()->setValue(GROUP(AdBlock), AdBlock::DisabledRules, m_disabledRules); + qApp->settings()->setValue(GROUP(AdBlock), AdBlock::AdBlockEnabled, m_enabled); + qApp->settings()->setValue(GROUP(AdBlock), AdBlock::DisabledRules, m_disabledRules); } bool AdBlockManager::isEnabled() const { - return m_enabled; + return m_enabled; } bool AdBlockManager::canRunOnScheme(const QString& scheme) const { - return !(scheme == QSL("file") || scheme == QSL("qrc") || scheme == QSL("data") || scheme == QSL("abp")); + return !(scheme == QSL("file") || scheme == QSL("qrc") || scheme == QSL("data") || scheme == QSL("abp")); } bool AdBlockManager::canBeBlocked(const QUrl& url) const { - return !m_matcher->adBlockDisabledForUrl(url); + return !m_matcher->adBlockDisabledForUrl(url); } QString AdBlockManager::elementHidingRules(const QUrl& url) const { - if (!isEnabled() || !canRunOnScheme(url.scheme()) || !canBeBlocked(url)) { - return QString(); - } - else { - return m_matcher->elementHidingRules(); - } + if (!isEnabled() || !canRunOnScheme(url.scheme()) || !canBeBlocked(url)) { + return QString(); + } + else { + return m_matcher->elementHidingRules(); + } } QString AdBlockManager::elementHidingRulesForDomain(const QUrl& url) const { - if (!isEnabled() || !canRunOnScheme(url.scheme()) || !canBeBlocked(url)) { - return QString(); - } - else { - return m_matcher->elementHidingRulesForDomain(url.host()); - } + if (!isEnabled() || !canRunOnScheme(url.scheme()) || !canBeBlocked(url)) { + return QString(); + } + else { + return m_matcher->elementHidingRulesForDomain(url.host()); + } } AdBlockSubscription* AdBlockManager::subscriptionByName(const QString& name) const { - foreach (AdBlockSubscription* subscription, m_subscriptions) { - if (subscription->title() == name) { - return subscription; - } - } + foreach (AdBlockSubscription* subscription, m_subscriptions) { + if (subscription->title() == name) { + return subscription; + } + } - return 0; + return 0; } void AdBlockManager::showDialog() { - if (!m_adBlockDialog) { - m_adBlockDialog = new AdBlockDialog(); - } + if (!m_adBlockDialog) { + m_adBlockDialog = new AdBlockDialog(); + } - m_adBlockDialog.data()->exec(); + m_adBlockDialog.data()->exec(); } diff --git a/src/network-web/adblock/adblockmanager.h b/src/network-web/adblock/adblockmanager.h index ecf2c1ca1..33443f1e4 100755 --- a/src/network-web/adblock/adblockmanager.h +++ b/src/network-web/adblock/adblockmanager.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -24,7 +25,6 @@ #include #include - class QUrl; class QWebEngineUrlRequestInfo; class AdBlockMatcher; @@ -36,69 +36,67 @@ class AdBlockUrlInterceptor; class AdBlockIcon; class AdBlockManager : public QObject { - Q_OBJECT + Q_OBJECT - public: - explicit AdBlockManager(QObject* parent = 0); - virtual ~AdBlockManager(); + public: + explicit AdBlockManager(QObject* parent = 0); + virtual ~AdBlockManager(); - void load(); - void save(); + void load(); + void save(); - bool isEnabled() const; - bool canRunOnScheme(const QString& scheme) const; + bool isEnabled() const; + bool canRunOnScheme(const QString& scheme) const; - QString elementHidingRules(const QUrl& url) const; - QString elementHidingRulesForDomain(const QUrl& url) const; + QString elementHidingRules(const QUrl& url) const; + QString elementHidingRulesForDomain(const QUrl& url) const; - AdBlockSubscription* subscriptionByName(const QString& name) const; - QList subscriptions() const; + AdBlockSubscription* subscriptionByName(const QString& name) const; - bool block(QWebEngineUrlRequestInfo& request); + QList subscriptions() const; - QStringList disabledRules() const; - void addDisabledRule(const QString& filter); - void removeDisabledRule(const QString& filter); + bool block(QWebEngineUrlRequestInfo& request); - bool addSubscriptionFromUrl(const QUrl& url); + QStringList disabledRules() const; + void addDisabledRule(const QString& filter); + void removeDisabledRule(const QString& filter); - AdBlockSubscription* addSubscription(const QString& title, const QString& url); - bool removeSubscription(AdBlockSubscription* subscription); + bool addSubscriptionFromUrl(const QUrl& url); - AdBlockCustomList* customList() const; + AdBlockSubscription* addSubscription(const QString& title, const QString& url); - inline AdBlockIcon* adBlockIcon() const { - return m_adblockIcon; - } + bool removeSubscription(AdBlockSubscription* subscription); - static QString storedListsPath(); + AdBlockCustomList* customList() const; + inline AdBlockIcon* adBlockIcon() const { + return m_adblockIcon; + } - static AdBlockManager* instance(); + static QString storedListsPath(); + static AdBlockManager* instance(); - signals: - void enabledChanged(bool enabled); + signals: + void enabledChanged(bool enabled); - public slots: - void setEnabled(bool enabled); - void updateMatcher(); - void updateAllSubscriptions(); - void showDialog(); + public slots: + void setEnabled(bool enabled); + void updateMatcher(); + void updateAllSubscriptions(); + void showDialog(); - private: - inline bool canBeBlocked(const QUrl& url) const; + private: + inline bool canBeBlocked(const QUrl& url) const; + bool m_loaded; + bool m_enabled; + AdBlockIcon* m_adblockIcon; - bool m_loaded; - bool m_enabled; + QList m_subscriptions; + AdBlockMatcher* m_matcher; + QStringList m_disabledRules; + AdBlockUrlInterceptor* m_interceptor; - AdBlockIcon* m_adblockIcon; - - QList m_subscriptions; - AdBlockMatcher* m_matcher; - QStringList m_disabledRules; - - AdBlockUrlInterceptor* m_interceptor; - QPointer m_adBlockDialog; - QMutex m_mutex; + QPointer m_adBlockDialog; + QMutex m_mutex; }; #endif // ADBLOCKMANAGER_H diff --git a/src/network-web/adblock/adblockmatcher.cpp b/src/network-web/adblock/adblockmatcher.cpp index 88e1e9864..99c08354d 100755 --- a/src/network-web/adblock/adblockmatcher.cpp +++ b/src/network-web/adblock/adblockmatcher.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -16,219 +17,219 @@ // You should have received a copy of the GNU General Public License // along with RSS Guard. If not, see . -#include "network-web/adblock/adblockmatcher.h" #include "network-web/adblock/adblockmanager.h" +#include "network-web/adblock/adblockmatcher.h" #include "network-web/adblock/adblockrule.h" #include "network-web/adblock/adblocksubscription.h" #include "definitions/definitions.h" - AdBlockMatcher::AdBlockMatcher(AdBlockManager* manager) - : QObject(manager), m_manager(manager) { -} + : QObject(manager), m_manager(manager) {} AdBlockMatcher::~AdBlockMatcher() { - clear(); + clear(); } const AdBlockRule* AdBlockMatcher::match(const QWebEngineUrlRequestInfo& request, const QString& urlDomain, const QString& urlString) const { - // Exception rules. - if (m_networkExceptionTree.find(request, urlDomain, urlString)) { - return 0; - } + // Exception rules. + if (m_networkExceptionTree.find(request, urlDomain, urlString)) { + return 0; + } - int count = m_networkExceptionRules.count(); + int count = m_networkExceptionRules.count(); - for (int i = 0; i < count; ++i) { - const AdBlockRule* rule = m_networkExceptionRules.at(i); + for (int i = 0; i < count; ++i) { + const AdBlockRule* rule = m_networkExceptionRules.at(i); - if (rule->networkMatch(request, urlDomain, urlString)) { - return 0; - } - } + if (rule->networkMatch(request, urlDomain, urlString)) { + return 0; + } + } - // Block rules. - if (const AdBlockRule* rule = m_networkBlockTree.find(request, urlDomain, urlString)) { - return rule; - } + // Block rules. + if (const AdBlockRule* rule = m_networkBlockTree.find(request, urlDomain, urlString)) { + return rule; + } - count = m_networkBlockRules.count(); + count = m_networkBlockRules.count(); - for (int i = 0; i < count; ++i) { - const AdBlockRule* rule = m_networkBlockRules.at(i); + for (int i = 0; i < count; ++i) { + const AdBlockRule* rule = m_networkBlockRules.at(i); - if (rule->networkMatch(request, urlDomain, urlString)) { - return rule; - } - } + if (rule->networkMatch(request, urlDomain, urlString)) { + return rule; + } + } - return 0; + return 0; } bool AdBlockMatcher::adBlockDisabledForUrl(const QUrl& url) const { - int count = m_documentRules.count(); + int count = m_documentRules.count(); - for (int i = 0; i < count; ++i) { - if (m_documentRules.at(i)->urlMatch(url)) { - return true; - } - } + for (int i = 0; i < count; ++i) { + if (m_documentRules.at(i)->urlMatch(url)) { + return true; + } + } - return false; + return false; } bool AdBlockMatcher::elemHideDisabledForUrl(const QUrl& url) const { - if (adBlockDisabledForUrl(url)) { - return true; - } + if (adBlockDisabledForUrl(url)) { + return true; + } - int count = m_elemhideRules.count(); + int count = m_elemhideRules.count(); - for (int i = 0; i < count; ++i) { - if (m_elemhideRules.at(i)->urlMatch(url)) { - return true; - } - } + for (int i = 0; i < count; ++i) { + if (m_elemhideRules.at(i)->urlMatch(url)) { + return true; + } + } - return false; + return false; } QString AdBlockMatcher::elementHidingRules() const { - return m_elementHidingRules; + return m_elementHidingRules; } QString AdBlockMatcher::elementHidingRulesForDomain(const QString& domain) const { - QString rules; - int addedRulesCount = 0; - int count = m_domainRestrictedCssRules.count(); + QString rules; + int addedRulesCount = 0; + int count = m_domainRestrictedCssRules.count(); - for (int i = 0; i < count; ++i) { - const AdBlockRule* rule = m_domainRestrictedCssRules.at(i); + for (int i = 0; i < count; ++i) { + const AdBlockRule* rule = m_domainRestrictedCssRules.at(i); - if (!rule->matchDomain(domain)) { - continue; - } + if (!rule->matchDomain(domain)) { + continue; + } - if (Q_UNLIKELY(addedRulesCount == 1000)) { - rules.append(rule->cssSelector()); - rules.append(QSL("{display:none !important;}\n")); - addedRulesCount = 0; - } - else { - rules.append(rule->cssSelector() + QLatin1Char(',')); - addedRulesCount++; - } - } + if (Q_UNLIKELY(addedRulesCount == 1000)) { + rules.append(rule->cssSelector()); + rules.append(QSL("{display:none !important;}\n")); + addedRulesCount = 0; + } + else { + rules.append(rule->cssSelector() + QLatin1Char(',')); + addedRulesCount++; + } + } - if (addedRulesCount != 0) { - rules = rules.left(rules.size() - 1); - rules.append(QSL("{display:none !important;}\n")); - } + if (addedRulesCount != 0) { + rules = rules.left(rules.size() - 1); + rules.append(QSL("{display:none !important;}\n")); + } - return rules; + return rules; } void AdBlockMatcher::update() { - clear(); - QHash cssRulesHash; - QVector exceptionCssRules; + clear(); + QHash cssRulesHash; + QVector exceptionCssRules; - foreach (AdBlockSubscription* subscription, m_manager->subscriptions()) { - foreach (const AdBlockRule* rule, subscription->allRules()) { - // Don't add internally disabled rules to cache. - if (rule->isInternalDisabled()) { - continue; - } + foreach (AdBlockSubscription* subscription, m_manager->subscriptions()) { + foreach (const AdBlockRule* rule, subscription->allRules()) { + // Don't add internally disabled rules to cache. + if (rule->isInternalDisabled()) { + continue; + } - if (rule->isCssRule()) { - // We will add only enabled css rules to cache, because there is no enabled/disabled - // check on match. They are directly embedded to pages. - if (!rule->isEnabled()) { - continue; - } + if (rule->isCssRule()) { + // We will add only enabled css rules to cache, because there is no enabled/disabled + // check on match. They are directly embedded to pages. + if (!rule->isEnabled()) { + continue; + } - if (rule->isException()) { - exceptionCssRules.append(rule); - } - else { - cssRulesHash.insert(rule->cssSelector(), rule); - } - } - else if (rule->isDocument()) { - m_documentRules.append(rule); - } - else if (rule->isElemhide()) { - m_elemhideRules.append(rule); - } - else if (rule->isException()) { - if (!m_networkExceptionTree.add(rule)) { - m_networkExceptionRules.append(rule); - } - } - else { - if (!m_networkBlockTree.add(rule)) { - m_networkBlockRules.append(rule); - } - } - } - } + if (rule->isException()) { + exceptionCssRules.append(rule); + } + else { + cssRulesHash.insert(rule->cssSelector(), rule); + } + } + else if (rule->isDocument()) { + m_documentRules.append(rule); + } + else if (rule->isElemhide()) { + m_elemhideRules.append(rule); + } + else if (rule->isException()) { + if (!m_networkExceptionTree.add(rule)) { + m_networkExceptionRules.append(rule); + } + } + else { + if (!m_networkBlockTree.add(rule)) { + m_networkBlockRules.append(rule); + } + } + } + } - foreach (const AdBlockRule* rule, exceptionCssRules) { - const AdBlockRule* originalRule = cssRulesHash.value(rule->cssSelector()); + foreach (const AdBlockRule* rule, exceptionCssRules) { + const AdBlockRule* originalRule = cssRulesHash.value(rule->cssSelector()); - // If we don't have this selector, the exception does nothing. - if (!originalRule) { - continue; - } + // If we don't have this selector, the exception does nothing. + if (!originalRule) { + continue; + } - AdBlockRule* copiedRule = originalRule->copy(); - copiedRule->m_options |= AdBlockRule::DomainRestrictedOption; - copiedRule->m_blockedDomains.append(rule->m_allowedDomains); - cssRulesHash[rule->cssSelector()] = copiedRule; - m_createdRules.append(copiedRule); - } + AdBlockRule* copiedRule = originalRule->copy(); - // Apparently, excessive amount of selectors for one CSS rule is not what WebKit likes. - // (In my testings, 4931 is the number that makes it crash). - // So let's split it by 1000 selectors. - int hidingRulesCount = 0; - QHashIterator it(cssRulesHash); + copiedRule->m_options |= AdBlockRule::DomainRestrictedOption; + copiedRule->m_blockedDomains.append(rule->m_allowedDomains); + cssRulesHash[rule->cssSelector()] = copiedRule; + m_createdRules.append(copiedRule); + } - while (it.hasNext()) { - it.next(); - const AdBlockRule* rule = it.value(); + // Apparently, excessive amount of selectors for one CSS rule is not what WebKit likes. + // (In my testings, 4931 is the number that makes it crash). + // So let's split it by 1000 selectors. + int hidingRulesCount = 0; - if (rule->isDomainRestricted()) { - m_domainRestrictedCssRules.append(rule); - } - else if (Q_UNLIKELY(hidingRulesCount == 1000)) { - m_elementHidingRules.append(rule->cssSelector()); - m_elementHidingRules.append(QL1S("{display:none !important;} ")); - hidingRulesCount = 0; - } - else { - m_elementHidingRules.append(rule->cssSelector() + QLatin1Char(',')); - hidingRulesCount++; - } - } + QHashIterator it(cssRulesHash); - if (hidingRulesCount != 0) { - m_elementHidingRules = m_elementHidingRules.left(m_elementHidingRules.size() - 1); - m_elementHidingRules.append(QL1S("{display:none !important;} ")); - } + while (it.hasNext()) { + it.next(); + const AdBlockRule* rule = it.value(); + + if (rule->isDomainRestricted()) { + m_domainRestrictedCssRules.append(rule); + } + else if (Q_UNLIKELY(hidingRulesCount == 1000)) { + m_elementHidingRules.append(rule->cssSelector()); + m_elementHidingRules.append(QL1S("{display:none !important;} ")); + hidingRulesCount = 0; + } + else { + m_elementHidingRules.append(rule->cssSelector() + QLatin1Char(',')); + hidingRulesCount++; + } + } + + if (hidingRulesCount != 0) { + m_elementHidingRules = m_elementHidingRules.left(m_elementHidingRules.size() - 1); + m_elementHidingRules.append(QL1S("{display:none !important;} ")); + } } void AdBlockMatcher::clear() { - m_networkExceptionTree.clear(); - m_networkExceptionRules.clear(); - m_networkBlockTree.clear(); - m_networkBlockRules.clear(); - m_domainRestrictedCssRules.clear(); - m_elementHidingRules.clear(); - m_documentRules.clear(); - m_elemhideRules.clear(); - qDeleteAll(m_createdRules); - m_createdRules.clear(); + m_networkExceptionTree.clear(); + m_networkExceptionRules.clear(); + m_networkBlockTree.clear(); + m_networkBlockRules.clear(); + m_domainRestrictedCssRules.clear(); + m_elementHidingRules.clear(); + m_documentRules.clear(); + m_elemhideRules.clear(); + qDeleteAll(m_createdRules); + m_createdRules.clear(); } diff --git a/src/network-web/adblock/adblockmatcher.h b/src/network-web/adblock/adblockmatcher.h index 7f22a0a1f..b6f217645 100755 --- a/src/network-web/adblock/adblockmatcher.h +++ b/src/network-web/adblock/adblockmatcher.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -26,42 +27,41 @@ #include #include - class QWebEngineUrlRequestInfo; class AdBlockManager; class AdBlockMatcher : public QObject { - Q_OBJECT + Q_OBJECT - public: - explicit AdBlockMatcher(AdBlockManager* manager); - virtual ~AdBlockMatcher(); + public: + explicit AdBlockMatcher(AdBlockManager* manager); + virtual ~AdBlockMatcher(); - const AdBlockRule* match(const QWebEngineUrlRequestInfo& request, const QString& urlDomain, const QString& urlString) const; + const AdBlockRule* match(const QWebEngineUrlRequestInfo& request, const QString& urlDomain, const QString& urlString) const; - bool adBlockDisabledForUrl(const QUrl& url) const; - bool elemHideDisabledForUrl(const QUrl& url) const; + bool adBlockDisabledForUrl(const QUrl& url) const; + bool elemHideDisabledForUrl(const QUrl& url) const; - QString elementHidingRules() const; - QString elementHidingRulesForDomain(const QString& domain) const; + QString elementHidingRules() const; + QString elementHidingRulesForDomain(const QString& domain) const; - public slots: - void update(); - void clear(); + public slots: + void update(); + void clear(); - private: - AdBlockManager* m_manager; + private: + AdBlockManager* m_manager; - QVector m_createdRules; - QVector m_networkExceptionRules; - QVector m_networkBlockRules; - QVector m_domainRestrictedCssRules; - QVector m_documentRules; - QVector m_elemhideRules; + QVector m_createdRules; + QVector m_networkExceptionRules; + QVector m_networkBlockRules; + QVector m_domainRestrictedCssRules; + QVector m_documentRules; + QVector m_elemhideRules; - QString m_elementHidingRules; - AdBlockSearchTree m_networkBlockTree; - AdBlockSearchTree m_networkExceptionTree; + QString m_elementHidingRules; + AdBlockSearchTree m_networkBlockTree; + AdBlockSearchTree m_networkExceptionTree; }; #endif // ADBLOCKMATCHER_H diff --git a/src/network-web/adblock/adblockrule.cpp b/src/network-web/adblock/adblockrule.cpp index a87061c36..b607815e6 100755 --- a/src/network-web/adblock/adblockrule.cpp +++ b/src/network-web/adblock/adblockrule.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -47,681 +48,694 @@ #include "network-web/adblock/adblockrule.h" -#include "network-web/adblock/adblocksubscription.h" #include "definitions/definitions.h" #include "miscellaneous/simpleregexp.h" +#include "network-web/adblock/adblocksubscription.h" -#include #include #include +#include #include #include - static QString toSecondLevelDomain(const QUrl& url) { - const QString topLevelDomain = url.topLevelDomain(); - const QString urlHost = url.host(); + const QString topLevelDomain = url.topLevelDomain(); + const QString urlHost = url.host(); - if (topLevelDomain.isEmpty() || urlHost.isEmpty()) { - return QString(); - } + if (topLevelDomain.isEmpty() || urlHost.isEmpty()) { + return QString(); + } - QString domain = urlHost.left(urlHost.size() - topLevelDomain.size()); + QString domain = urlHost.left(urlHost.size() - topLevelDomain.size()); - if (domain.count(QL1C('.')) == 0) { - return urlHost; - } + if (domain.count(QL1C('.')) == 0) { + return urlHost; + } - while (domain.count(QL1C('.')) != 0) { - domain = domain.mid(domain.indexOf(QL1C('.')) + 1); - } + while (domain.count(QL1C('.')) != 0) { + domain = domain.mid(domain.indexOf(QL1C('.')) + 1); + } - return domain + topLevelDomain; + return domain + topLevelDomain; } AdBlockRule::AdBlockRule(const QString& filter, AdBlockSubscription* subscription) - : m_subscription(subscription), m_type(StringContainsMatchRule), m_caseSensitivity(Qt::CaseInsensitive), - m_isEnabled(true), m_isException(false), m_isInternalDisabled(false), m_regExp(0) { - setFilter(filter); + : m_subscription(subscription), m_type(StringContainsMatchRule), m_caseSensitivity(Qt::CaseInsensitive), + m_isEnabled(true), m_isException(false), m_isInternalDisabled(false), m_regExp(0) { + setFilter(filter); } AdBlockRule::~AdBlockRule() { - delete m_regExp; + delete m_regExp; } AdBlockRule* AdBlockRule::copy() const { - AdBlockRule* rule = new AdBlockRule(); - rule->m_subscription = m_subscription; - rule->m_type = m_type; - rule->m_options = m_options; - rule->m_exceptions = m_exceptions; - rule->m_filter = m_filter; - rule->m_matchString = m_matchString; - rule->m_caseSensitivity = m_caseSensitivity; - rule->m_isEnabled = m_isEnabled; - rule->m_isException = m_isException; - rule->m_isInternalDisabled = m_isInternalDisabled; - rule->m_allowedDomains = m_allowedDomains; - rule->m_blockedDomains = m_blockedDomains; + AdBlockRule* rule = new AdBlockRule(); - if (m_regExp) { - rule->m_regExp = new RegExp; - rule->m_regExp->regExp = m_regExp->regExp; - rule->m_regExp->matchers = m_regExp->matchers; - } + rule->m_subscription = m_subscription; + rule->m_type = m_type; + rule->m_options = m_options; + rule->m_exceptions = m_exceptions; + rule->m_filter = m_filter; + rule->m_matchString = m_matchString; + rule->m_caseSensitivity = m_caseSensitivity; + rule->m_isEnabled = m_isEnabled; + rule->m_isException = m_isException; + rule->m_isInternalDisabled = m_isInternalDisabled; + rule->m_allowedDomains = m_allowedDomains; + rule->m_blockedDomains = m_blockedDomains; - return rule; + if (m_regExp) { + rule->m_regExp = new RegExp; + rule->m_regExp->regExp = m_regExp->regExp; + rule->m_regExp->matchers = m_regExp->matchers; + } + + return rule; } AdBlockSubscription* AdBlockRule::subscription() const { - return m_subscription; + return m_subscription; } void AdBlockRule::setSubscription(AdBlockSubscription* subscription) { - m_subscription = subscription; + m_subscription = subscription; } QString AdBlockRule::filter() const { - return m_filter; + return m_filter; } void AdBlockRule::setFilter(const QString& filter) { - m_filter = filter; - parseFilter(); + m_filter = filter; + parseFilter(); } bool AdBlockRule::isCssRule() const { - return m_type == CssRule; + return m_type == CssRule; } QString AdBlockRule::cssSelector() const { - return m_matchString; + return m_matchString; } bool AdBlockRule::isDocument() const { - return hasOption(DocumentOption); + return hasOption(DocumentOption); } bool AdBlockRule::isElemhide() const { - return hasOption(ElementHideOption); + return hasOption(ElementHideOption); } bool AdBlockRule::isDomainRestricted() const { - return hasOption(DomainRestrictedOption); + return hasOption(DomainRestrictedOption); } bool AdBlockRule::isException() const { - return m_isException; + return m_isException; } bool AdBlockRule::isComment() const { - return m_filter.startsWith(QL1C('!')); + return m_filter.startsWith(QL1C('!')); } bool AdBlockRule::isEnabled() const { - return m_isEnabled; + return m_isEnabled; } void AdBlockRule::setEnabled(bool enabled) { - m_isEnabled = enabled; + m_isEnabled = enabled; } bool AdBlockRule::isSlow() const { - return m_regExp != 0; + return m_regExp != 0; } bool AdBlockRule::isInternalDisabled() const { - return m_isInternalDisabled; + return m_isInternalDisabled; } bool AdBlockRule::urlMatch(const QUrl& url) const { - if (!hasOption(DocumentOption) && !hasOption(ElementHideOption)) { - return false; - } - else { - const QString encodedUrl = url.toEncoded(); - const QString domain = url.host(); - return stringMatch(domain, encodedUrl); - } + if (!hasOption(DocumentOption) && !hasOption(ElementHideOption)) { + return false; + } + else { + const QString encodedUrl = url.toEncoded(); + const QString domain = url.host(); + + return stringMatch(domain, encodedUrl); + } } bool AdBlockRule::networkMatch(const QWebEngineUrlRequestInfo& request, const QString& domain, const QString& encodedUrl) const { - if (m_type == CssRule || !m_isEnabled || m_isInternalDisabled) { - return false; - } + if (m_type == CssRule || !m_isEnabled || m_isInternalDisabled) { + return false; + } - bool matched = stringMatch(domain, encodedUrl); + bool matched = stringMatch(domain, encodedUrl); - if (matched) { - // Check domain restrictions. - if (hasOption(DomainRestrictedOption) && !matchDomain(request.firstPartyUrl().host())) { - return false; - } + if (matched) { + // Check domain restrictions. + if (hasOption(DomainRestrictedOption) && !matchDomain(request.firstPartyUrl().host())) { + return false; + } - // Check third-party restriction. - if (hasOption(ThirdPartyOption) && !matchThirdParty(request)) { - return false; - } + // Check third-party restriction. + if (hasOption(ThirdPartyOption) && !matchThirdParty(request)) { + return false; + } - // Check object restrictions. - if (hasOption(ObjectOption) && !matchObject(request)) { - return false; - } + // Check object restrictions. + if (hasOption(ObjectOption) && !matchObject(request)) { + return false; + } - // Check subdocument restriction. - if (hasOption(SubdocumentOption) && !matchSubdocument(request)) { - return false; - } + // Check subdocument restriction. + if (hasOption(SubdocumentOption) && !matchSubdocument(request)) { + return false; + } - // Check xmlhttprequest restriction. - if (hasOption(XMLHttpRequestOption) && !matchXmlHttpRequest(request)) { - return false; - } + // Check xmlhttprequest restriction. + if (hasOption(XMLHttpRequestOption) && !matchXmlHttpRequest(request)) { + return false; + } - // Check image restriction. - if (hasOption(ImageOption) && !matchImage(request)) { - return false; - } + // Check image restriction. + if (hasOption(ImageOption) && !matchImage(request)) { + return false; + } - // Check script restriction. - if (hasOption(ScriptOption) && !matchScript(request)) { - return false; - } + // Check script restriction. + if (hasOption(ScriptOption) && !matchScript(request)) { + return false; + } - // Check stylesheet restriction. - if (hasOption(StyleSheetOption) && !matchStyleSheet(request)) { - return false; - } + // Check stylesheet restriction. + if (hasOption(StyleSheetOption) && !matchStyleSheet(request)) { + return false; + } - // Check object-subrequest restriction. - if (hasOption(ObjectSubrequestOption) && !matchObjectSubrequest(request)) { - return false; - } - } + // Check object-subrequest restriction. + if (hasOption(ObjectSubrequestOption) && !matchObjectSubrequest(request)) { + return false; + } + } - return matched; + return matched; } bool AdBlockRule::matchDomain(const QString& domain) const { - if (!m_isEnabled) { - return false; - } + if (!m_isEnabled) { + return false; + } - if (!hasOption(DomainRestrictedOption)) { - return true; - } + if (!hasOption(DomainRestrictedOption)) { + return true; + } - if (m_blockedDomains.isEmpty()) { - foreach (const QString& d, m_allowedDomains) { - if (isMatchingDomain(domain, d)) { - return true; - } - } - } - else if (m_allowedDomains.isEmpty()) { - foreach (const QString& d, m_blockedDomains) { - if (isMatchingDomain(domain, d)) { - return false; - } - } + if (m_blockedDomains.isEmpty()) { + foreach (const QString& d, m_allowedDomains) { + if (isMatchingDomain(domain, d)) { + return true; + } + } + } + else if (m_allowedDomains.isEmpty()) { + foreach (const QString& d, m_blockedDomains) { + if (isMatchingDomain(domain, d)) { + return false; + } + } - return true; - } - else { - foreach (const QString& d, m_blockedDomains) { - if (isMatchingDomain(domain, d)) { - return false; - } - } + return true; + } + else { + foreach (const QString& d, m_blockedDomains) { + if (isMatchingDomain(domain, d)) { + return false; + } + } - foreach (const QString& d, m_allowedDomains) { - if (isMatchingDomain(domain, d)) { - return true; - } - } - } + foreach (const QString& d, m_allowedDomains) { + if (isMatchingDomain(domain, d)) { + return true; + } + } + } - return false; + return false; } bool AdBlockRule::matchThirdParty(const QWebEngineUrlRequestInfo& request) const { - // Third-party matching should be performed on second-level domains. - const QString firstPartyHost = toSecondLevelDomain(request.firstPartyUrl()); - const QString host = toSecondLevelDomain(request.requestUrl()); - bool match = firstPartyHost != host; - return hasException(ThirdPartyOption) ? !match : match; + // Third-party matching should be performed on second-level domains. + const QString firstPartyHost = toSecondLevelDomain(request.firstPartyUrl()); + const QString host = toSecondLevelDomain(request.requestUrl()); + bool match = firstPartyHost != host; + + return hasException(ThirdPartyOption) ? !match : match; } bool AdBlockRule::matchObject(const QWebEngineUrlRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeObject; - return hasException(ObjectOption) ? !match : match; + bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeObject; + + return hasException(ObjectOption) ? !match : match; } bool AdBlockRule::matchSubdocument(const QWebEngineUrlRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeSubFrame; - return hasException(SubdocumentOption) ? !match : match; + bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeSubFrame; + + return hasException(SubdocumentOption) ? !match : match; } bool AdBlockRule::matchXmlHttpRequest(const QWebEngineUrlRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeXhr; - return hasException(XMLHttpRequestOption) ? !match : match; + bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeXhr; + + return hasException(XMLHttpRequestOption) ? !match : match; } bool AdBlockRule::matchImage(const QWebEngineUrlRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeImage; - return hasException(ImageOption) ? !match : match; + bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeImage; + + return hasException(ImageOption) ? !match : match; } bool AdBlockRule::matchScript(const QWebEngineUrlRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeScript; - return hasException(ScriptOption) ? !match : match; + bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeScript; + + return hasException(ScriptOption) ? !match : match; } bool AdBlockRule::matchStyleSheet(const QWebEngineUrlRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeStylesheet; - return hasException(StyleSheetOption) ? !match : match; + bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeStylesheet; + + return hasException(StyleSheetOption) ? !match : match; } bool AdBlockRule::matchObjectSubrequest(const QWebEngineUrlRequestInfo& request) const { - bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeSubResource; - return hasException(ObjectSubrequestOption) ? !match : match; + bool match = request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeSubResource; + + return hasException(ObjectSubrequestOption) ? !match : match; } void AdBlockRule::parseFilter() { - QString parsedLine = m_filter; + QString parsedLine = m_filter; - // Empty rule or just comment. - if (m_filter.trimmed().isEmpty() || m_filter.startsWith(QL1C('!'))) { - // We want to differentiate rule disabled by user and rule disabled in subscription file - // m_isInternalDisabled is also used when rule is disabled due to all options not being supported. - m_isEnabled = false; - m_isInternalDisabled = true; - m_type = Invalid; - return; - } + // Empty rule or just comment. + if (m_filter.trimmed().isEmpty() || m_filter.startsWith(QL1C('!'))) { + // We want to differentiate rule disabled by user and rule disabled in subscription file + // m_isInternalDisabled is also used when rule is disabled due to all options not being supported. + m_isEnabled = false; + m_isInternalDisabled = true; + m_type = Invalid; + return; + } - // CSS Element hiding rule. - if (parsedLine.contains(QL1S("##")) || parsedLine.contains(QL1S("#@#"))) { - m_type = CssRule; - int pos = parsedLine.indexOf(QL1C('#')); + // CSS Element hiding rule. + if (parsedLine.contains(QL1S("##")) || parsedLine.contains(QL1S("#@#"))) { + m_type = CssRule; + int pos = parsedLine.indexOf(QL1C('#')); - // Domain restricted rule. - if (!parsedLine.startsWith(QL1S("##"))) { - QString domains = parsedLine.left(pos); - parseDomains(domains, QL1C(',')); - } + // Domain restricted rule. + if (!parsedLine.startsWith(QL1S("##"))) { + QString domains = parsedLine.left(pos); - m_isException = parsedLine.at(pos + 1) == QL1C('@'); - m_matchString = parsedLine.mid(m_isException ? pos + 3 : pos + 2); - // CSS rule cannot have more options -> stop parsing. - return; - } + parseDomains(domains, QL1C(',')); + } - // Exception always starts with @@. - if (parsedLine.startsWith(QL1S("@@"))) { - m_isException = true; - parsedLine = parsedLine.mid(2); - } + m_isException = parsedLine.at(pos + 1) == QL1C('@'); + m_matchString = parsedLine.mid(m_isException ? pos + 3 : pos + 2); - // Parse all options following $ char - int optionsIndex = parsedLine.indexOf(QL1C('$')); + // CSS rule cannot have more options -> stop parsing. + return; + } - if (optionsIndex >= 0) { - const QStringList options = parsedLine.mid(optionsIndex + 1).split(QL1C(','), QString::SkipEmptyParts); - int handledOptions = 0; + // Exception always starts with @@. + if (parsedLine.startsWith(QL1S("@@"))) { + m_isException = true; + parsedLine = parsedLine.mid(2); + } - foreach (const QString& option, options) { - if (option.startsWith(QL1S("domain="))) { - parseDomains(option.mid(7), QL1C('|')); - ++handledOptions; - } - else if (option == QL1S("match-case")) { - m_caseSensitivity = Qt::CaseSensitive; - ++handledOptions; - } - else if (option.endsWith(QL1S("third-party"))) { - setOption(ThirdPartyOption); - setException(ThirdPartyOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("object"))) { - setOption(ObjectOption); - setException(ObjectOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("subdocument"))) { - setOption(SubdocumentOption); - setException(SubdocumentOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("xmlhttprequest"))) { - setOption(XMLHttpRequestOption); - setException(XMLHttpRequestOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("image"))) { - setOption(ImageOption); - setException(ImageOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("script"))) { - setOption(ScriptOption); - setException(ScriptOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("stylesheet"))) { - setOption(StyleSheetOption); - setException(StyleSheetOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option.endsWith(QL1S("object-subrequest"))) { - setOption(ObjectSubrequestOption); - setException(ObjectSubrequestOption, option.startsWith(QL1C('~'))); - ++handledOptions; - } - else if (option == QL1S("document") && m_isException) { - setOption(DocumentOption); - ++handledOptions; - } - else if (option == QL1S("elemhide") && m_isException) { - setOption(ElementHideOption); - ++handledOptions; - } - else if (option == QL1S("collapse")) { - // Hiding placeholders of blocked elements is enabled by default. - ++handledOptions; - } - } + // Parse all options following $ char + int optionsIndex = parsedLine.indexOf(QL1C('$')); - // If we don't handle all options, it's safer to just disable this rule. - if (handledOptions != options.count()) { - m_isInternalDisabled = true; - m_type = Invalid; - return; - } + if (optionsIndex >= 0) { + const QStringList options = parsedLine.mid(optionsIndex + 1).split(QL1C(','), QString::SkipEmptyParts); + int handledOptions = 0; - parsedLine = parsedLine.left(optionsIndex); - } + foreach (const QString& option, options) { + if (option.startsWith(QL1S("domain="))) { + parseDomains(option.mid(7), QL1C('|')); + ++handledOptions; + } + else if (option == QL1S("match-case")) { + m_caseSensitivity = Qt::CaseSensitive; + ++handledOptions; + } + else if (option.endsWith(QL1S("third-party"))) { + setOption(ThirdPartyOption); + setException(ThirdPartyOption, option.startsWith(QL1C('~'))); + ++handledOptions; + } + else if (option.endsWith(QL1S("object"))) { + setOption(ObjectOption); + setException(ObjectOption, option.startsWith(QL1C('~'))); + ++handledOptions; + } + else if (option.endsWith(QL1S("subdocument"))) { + setOption(SubdocumentOption); + setException(SubdocumentOption, option.startsWith(QL1C('~'))); + ++handledOptions; + } + else if (option.endsWith(QL1S("xmlhttprequest"))) { + setOption(XMLHttpRequestOption); + setException(XMLHttpRequestOption, option.startsWith(QL1C('~'))); + ++handledOptions; + } + else if (option.endsWith(QL1S("image"))) { + setOption(ImageOption); + setException(ImageOption, option.startsWith(QL1C('~'))); + ++handledOptions; + } + else if (option.endsWith(QL1S("script"))) { + setOption(ScriptOption); + setException(ScriptOption, option.startsWith(QL1C('~'))); + ++handledOptions; + } + else if (option.endsWith(QL1S("stylesheet"))) { + setOption(StyleSheetOption); + setException(StyleSheetOption, option.startsWith(QL1C('~'))); + ++handledOptions; + } + else if (option.endsWith(QL1S("object-subrequest"))) { + setOption(ObjectSubrequestOption); + setException(ObjectSubrequestOption, option.startsWith(QL1C('~'))); + ++handledOptions; + } + else if (option == QL1S("document") && m_isException) { + setOption(DocumentOption); + ++handledOptions; + } + else if (option == QL1S("elemhide") && m_isException) { + setOption(ElementHideOption); + ++handledOptions; + } + else if (option == QL1S("collapse")) { + // Hiding placeholders of blocked elements is enabled by default. + ++handledOptions; + } + } - // Rule is classic regexp. - if (parsedLine.startsWith(QL1C('/')) && parsedLine.endsWith(QL1C('/'))) { - parsedLine = parsedLine.mid(1); - parsedLine = parsedLine.left(parsedLine.size() - 1); - m_type = RegExpMatchRule; - m_regExp = new RegExp; - m_regExp->regExp = SimpleRegExp(parsedLine, m_caseSensitivity); - m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsedLine)); - return; - } + // If we don't handle all options, it's safer to just disable this rule. + if (handledOptions != options.count()) { + m_isInternalDisabled = true; + m_type = Invalid; + return; + } - // Remove starting and ending wildcards (*). - if (parsedLine.startsWith(QL1C('*'))) { - parsedLine = parsedLine.mid(1); - } + parsedLine = parsedLine.left(optionsIndex); + } - if (parsedLine.endsWith(QL1C('*'))) { - parsedLine = parsedLine.left(parsedLine.size() - 1); - } + // Rule is classic regexp. + if (parsedLine.startsWith(QL1C('/')) && parsedLine.endsWith(QL1C('/'))) { + parsedLine = parsedLine.mid(1); + parsedLine = parsedLine.left(parsedLine.size() - 1); + m_type = RegExpMatchRule; + m_regExp = new RegExp; + m_regExp->regExp = SimpleRegExp(parsedLine, m_caseSensitivity); + m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsedLine)); + return; + } - // We can use fast string matching for domain here. - if (filterIsOnlyDomain(parsedLine)) { - parsedLine = parsedLine.mid(2); - parsedLine = parsedLine.left(parsedLine.size() - 1); - m_type = DomainMatchRule; - m_matchString = parsedLine; - return; - } + // Remove starting and ending wildcards (*). + if (parsedLine.startsWith(QL1C('*'))) { + parsedLine = parsedLine.mid(1); + } - // If rule contains only | at end, we can also use string matching. - if (filterIsOnlyEndsMatch(parsedLine)) { - parsedLine = parsedLine.left(parsedLine.size() - 1); - m_type = StringEndsMatchRule; - m_matchString = parsedLine; - return; - } + if (parsedLine.endsWith(QL1C('*'))) { + parsedLine = parsedLine.left(parsedLine.size() - 1); + } - // If we still find a wildcard (*) or separator (^) or (|) - // we must modify parsedLine to comply with SimpleRegExp. - if (parsedLine.contains(QL1C('*')) || parsedLine.contains(QL1C('^')) || parsedLine.contains(QL1C('|'))) { - m_type = RegExpMatchRule; - m_regExp = new RegExp; - m_regExp->regExp = SimpleRegExp(createRegExpFromFilter(parsedLine), m_caseSensitivity); - m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsedLine)); - return; - } + // We can use fast string matching for domain here. + if (filterIsOnlyDomain(parsedLine)) { + parsedLine = parsedLine.mid(2); + parsedLine = parsedLine.left(parsedLine.size() - 1); + m_type = DomainMatchRule; + m_matchString = parsedLine; + return; + } - // We haven't found anything that needs use of regexp, yay! - m_type = StringContainsMatchRule; - m_matchString = parsedLine; + // If rule contains only | at end, we can also use string matching. + if (filterIsOnlyEndsMatch(parsedLine)) { + parsedLine = parsedLine.left(parsedLine.size() - 1); + m_type = StringEndsMatchRule; + m_matchString = parsedLine; + return; + } + + // If we still find a wildcard (*) or separator (^) or (|) + // we must modify parsedLine to comply with SimpleRegExp. + if (parsedLine.contains(QL1C('*')) || parsedLine.contains(QL1C('^')) || parsedLine.contains(QL1C('|'))) { + m_type = RegExpMatchRule; + m_regExp = new RegExp; + m_regExp->regExp = SimpleRegExp(createRegExpFromFilter(parsedLine), m_caseSensitivity); + m_regExp->matchers = createStringMatchers(parseRegExpFilter(parsedLine)); + return; + } + + // We haven't found anything that needs use of regexp, yay! + m_type = StringContainsMatchRule; + m_matchString = parsedLine; } void AdBlockRule::parseDomains(const QString& domains, const QChar& separator) { - QStringList domainsList = domains.split(separator, QString::SkipEmptyParts); + QStringList domainsList = domains.split(separator, QString::SkipEmptyParts); - foreach (const QString domain, domainsList) { - if (domain.isEmpty()) { - continue; - } + foreach (const QString domain, domainsList) { + if (domain.isEmpty()) { + continue; + } - if (domain.startsWith(QL1C('~'))) { - m_blockedDomains.append(domain.mid(1)); - } - else { - m_allowedDomains.append(domain); - } - } + if (domain.startsWith(QL1C('~'))) { + m_blockedDomains.append(domain.mid(1)); + } + else { + m_allowedDomains.append(domain); + } + } - if (!m_blockedDomains.isEmpty() || !m_allowedDomains.isEmpty()) { - setOption(DomainRestrictedOption); - } + if (!m_blockedDomains.isEmpty() || !m_allowedDomains.isEmpty()) { + setOption(DomainRestrictedOption); + } } bool AdBlockRule::filterIsOnlyDomain(const QString& filter) const { - if (!filter.endsWith(QL1C('^')) || !filter.startsWith(QL1S("||"))) { - return false; - } + if (!filter.endsWith(QL1C('^')) || !filter.startsWith(QL1S("||"))) { + return false; + } - for (int i = 0; i < filter.size(); ++i) { - switch (filter.at(i).toLatin1()) { - case '/': - case ':': - case '?': - case '=': - case '&': - case '*': - return false; + for (int i = 0; i < filter.size(); ++i) { + switch (filter.at(i).toLatin1()) { + case '/': + case ':': + case '?': + case '=': + case '&': + case '*': + return false; - default: - break; - } - } + default: + break; + } + } - return true; + return true; } bool AdBlockRule::filterIsOnlyEndsMatch(const QString& filter) const { - for (int i = 0; i < filter.size(); ++i) { - switch (filter.at(i).toLatin1()) { - case '^': - case '*': - return false; + for (int i = 0; i < filter.size(); ++i) { + switch (filter.at(i).toLatin1()) { + case '^': + case '*': + return false; - case '|': - return i == filter.size() - 1; + case '|': + return i == filter.size() - 1; - default: - break; - } - } + default: + break; + } + } - return false; + return false; } static bool wordCharacter(const QChar& c) { - return c.isLetterOrNumber() || c.isMark() || c == QL1C('_'); + return c.isLetterOrNumber() || c.isMark() || c == QL1C('_'); } QString AdBlockRule::createRegExpFromFilter(const QString& filter) const { - QString parsed; - parsed.reserve(filter.size()); - bool hadWildcard = false; // Filter multiple wildcards. + QString parsed; - for (int i = 0; i < filter.size(); ++i) { - const QChar c = filter.at(i); + parsed.reserve(filter.size()); + bool hadWildcard = false; // Filter multiple wildcards. - switch (c.toLatin1()) { - case '^': - parsed.append(QL1S("(?:[^\\w\\d\\-.%]|$)")); - break; + for (int i = 0; i < filter.size(); ++i) { + const QChar c = filter.at(i); - case '*': - if (!hadWildcard) { - parsed.append(QL1S(".*")); - } + switch (c.toLatin1()) { + case '^': + parsed.append(QL1S("(?:[^\\w\\d\\-.%]|$)")); + break; - break; + case '*': + if (!hadWildcard) { + parsed.append(QL1S(".*")); + } - case '|': - if (i == 0) { - if (filter.size() > 1 && filter.at(1) == QL1C('|')) { - parsed.append(QL1S("^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?")); - i++; - } - else { - parsed.append('^'); - } + break; - break; - } - else if (i == filter.size() - 1) { - parsed.append(QL1C('$')); - break; - } + case '|': + if (i == 0) { + if (filter.size() > 1 && filter.at(1) == QL1C('|')) { + parsed.append(QL1S("^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?")); + i++; + } + else { + parsed.append('^'); + } - // fallthrough + break; + } + else if (i == filter.size() - 1) { + parsed.append(QL1C('$')); + break; + } - default: - if (!wordCharacter(c)) { - parsed.append(QL1C('\\') + c); - } - else { - parsed.append(c); - } - } + // fallthrough - hadWildcard = c == QL1C('*'); - } + default: + if (!wordCharacter(c)) { + parsed.append(QL1C('\\') + c); + } + else { + parsed.append(c); + } + } - return parsed; + hadWildcard = c == QL1C('*'); + } + + return parsed; } QList AdBlockRule::createStringMatchers(const QStringList& filters) const { - QList matchers; - matchers.reserve(filters.size()); + QList matchers; + matchers.reserve(filters.size()); - foreach (const QString& filter, filters) { - matchers.append(QStringMatcher(filter, m_caseSensitivity)); - } + foreach (const QString& filter, filters) { + matchers.append(QStringMatcher(filter, m_caseSensitivity)); + } - return matchers; + return matchers; } bool AdBlockRule::stringMatch(const QString& domain, const QString& encodedUrl) const { - if (m_type == StringContainsMatchRule) { - return encodedUrl.contains(m_matchString, m_caseSensitivity); - } - else if (m_type == DomainMatchRule) { - return isMatchingDomain(domain, m_matchString); - } - else if (m_type == StringEndsMatchRule) { - return encodedUrl.endsWith(m_matchString, m_caseSensitivity); - } - else if (m_type == RegExpMatchRule) { - if (!isMatchingRegExpStrings(encodedUrl)) { - return false; - } - else { - return (m_regExp->regExp.indexIn(encodedUrl) != -1); - } - } + if (m_type == StringContainsMatchRule) { + return encodedUrl.contains(m_matchString, m_caseSensitivity); + } + else if (m_type == DomainMatchRule) { + return isMatchingDomain(domain, m_matchString); + } + else if (m_type == StringEndsMatchRule) { + return encodedUrl.endsWith(m_matchString, m_caseSensitivity); + } + else if (m_type == RegExpMatchRule) { + if (!isMatchingRegExpStrings(encodedUrl)) { + return false; + } + else { + return (m_regExp->regExp.indexIn(encodedUrl) != -1); + } + } - return false; + return false; } bool AdBlockRule::matchDomain(const QString& pattern, const QString& domain) const { - if (pattern == domain) { - return true; - } + if (pattern == domain) { + return true; + } - if (!domain.endsWith(pattern)) { - return false; - } + if (!domain.endsWith(pattern)) { + return false; + } - int index = domain.indexOf(pattern); - return index > 0 && domain[index - 1] == QLatin1Char('.'); + int index = domain.indexOf(pattern); + + return index > 0 && domain[index - 1] == QLatin1Char('.'); } bool AdBlockRule::isMatchingDomain(const QString& domain, const QString& filter) const { - return matchDomain(filter, domain); + return matchDomain(filter, domain); } bool AdBlockRule::isMatchingRegExpStrings(const QString& url) const { - Q_ASSERT(m_regExp); + Q_ASSERT(m_regExp); - foreach (const QStringMatcher& matcher, m_regExp->matchers) { - if (matcher.indexIn(url) == -1) { - return false; - } - } + foreach (const QStringMatcher& matcher, m_regExp->matchers) { + if (matcher.indexIn(url) == -1) { + return false; + } + } - return true; + return true; } // Split regexp filter into strings that can be used with QString::contains // Don't use parts that contains only 1 char and duplicated parts. QStringList AdBlockRule::parseRegExpFilter(const QString& filter) const { - QStringList list; - int startPos = -1; + QStringList list; + int startPos = -1; - for (int i = 0; i < filter.size(); ++i) { - const QChar c = filter.at(i); + for (int i = 0; i < filter.size(); ++i) { + const QChar c = filter.at(i); - // Meta characters in AdBlock rules are | * ^ - if (c == QL1C('|') || c == QL1C('*') || c == QL1C('^')) { - const QString sub = filter.mid(startPos, i - startPos); + // Meta characters in AdBlock rules are | * ^ + if (c == QL1C('|') || c == QL1C('*') || c == QL1C('^')) { + const QString sub = filter.mid(startPos, i - startPos); - if (sub.size() > 1) { - list.append(sub); - } + if (sub.size() > 1) { + list.append(sub); + } - startPos = i + 1; - } - } + startPos = i + 1; + } + } - const QString sub = filter.mid(startPos); + const QString sub = filter.mid(startPos); - if (sub.size() > 1) { - list.append(sub); - } + if (sub.size() > 1) { + list.append(sub); + } - list.removeDuplicates(); - return list; + list.removeDuplicates(); + return list; } bool AdBlockRule::hasOption(const AdBlockRule::RuleOption& opt) const { - return (m_options & opt); + return (m_options & opt); } bool AdBlockRule::hasException(const AdBlockRule::RuleOption& opt) const { - return (m_exceptions & opt); + return (m_exceptions & opt); } void AdBlockRule::setOption(const AdBlockRule::RuleOption& opt) { - m_options |= opt; + m_options |= opt; } void AdBlockRule::setException(const AdBlockRule::RuleOption& opt, bool on) { - if (on) { - m_exceptions |= opt; - } + if (on) { + m_exceptions |= opt; + } } diff --git a/src/network-web/adblock/adblockrule.h b/src/network-web/adblock/adblockrule.h index 989d0cb37..dda97ae80 100755 --- a/src/network-web/adblock/adblockrule.h +++ b/src/network-web/adblock/adblockrule.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -53,135 +54,131 @@ #include "miscellaneous/simpleregexp.h" - class QUrl; class QWebEngineUrlRequestInfo; class AdBlockSubscription; class AdBlockRule { - Q_DISABLE_COPY(AdBlockRule) + Q_DISABLE_COPY(AdBlockRule) - public: - explicit AdBlockRule(const QString& filter = QString(), AdBlockSubscription* subscription = 0); - virtual ~AdBlockRule(); + public: + explicit AdBlockRule(const QString& filter = QString(), AdBlockSubscription* subscription = 0); + virtual ~AdBlockRule(); - AdBlockRule* copy() const; + AdBlockRule* copy() const; + AdBlockSubscription* subscription() const; - AdBlockSubscription* subscription() const; - void setSubscription(AdBlockSubscription* subscription); + void setSubscription(AdBlockSubscription* subscription); - QString filter() const; - void setFilter(const QString& filter); + QString filter() const; + void setFilter(const QString& filter); - bool isCssRule() const; - QString cssSelector() const; + bool isCssRule() const; + QString cssSelector() const; - bool isDocument() const; - bool isElemhide() const; + bool isDocument() const; + bool isElemhide() const; - bool isDomainRestricted() const; - bool isException() const; + bool isDomainRestricted() const; + bool isException() const; - bool isComment() const; - bool isEnabled() const; - void setEnabled(bool enabled); + bool isComment() const; + bool isEnabled() const; + void setEnabled(bool enabled); - bool isSlow() const; - bool isInternalDisabled() const; + bool isSlow() const; + bool isInternalDisabled() const; - bool urlMatch(const QUrl& url) const; - bool networkMatch(const QWebEngineUrlRequestInfo& request, const QString& domain, const QString& encodedUrl) const; + bool urlMatch(const QUrl& url) const; + bool networkMatch(const QWebEngineUrlRequestInfo& request, const QString& domain, const QString& encodedUrl) const; - bool matchDomain(const QString& domain) const; - bool matchThirdParty(const QWebEngineUrlRequestInfo& request) const; - bool matchObject(const QWebEngineUrlRequestInfo& request) const; - bool matchSubdocument(const QWebEngineUrlRequestInfo& request) const; - bool matchXmlHttpRequest(const QWebEngineUrlRequestInfo& request) const; - bool matchImage(const QWebEngineUrlRequestInfo& request) const; - bool matchScript(const QWebEngineUrlRequestInfo& request) const; - bool matchStyleSheet(const QWebEngineUrlRequestInfo& request) const; - bool matchObjectSubrequest(const QWebEngineUrlRequestInfo& request) const; + bool matchDomain(const QString& domain) const; + bool matchThirdParty(const QWebEngineUrlRequestInfo& request) const; + bool matchObject(const QWebEngineUrlRequestInfo& request) const; + bool matchSubdocument(const QWebEngineUrlRequestInfo& request) const; + bool matchXmlHttpRequest(const QWebEngineUrlRequestInfo& request) const; + bool matchImage(const QWebEngineUrlRequestInfo& request) const; + bool matchScript(const QWebEngineUrlRequestInfo& request) const; + bool matchStyleSheet(const QWebEngineUrlRequestInfo& request) const; + bool matchObjectSubrequest(const QWebEngineUrlRequestInfo& request) const; - protected: - bool matchDomain(const QString& pattern, const QString& domain) const; - bool stringMatch(const QString& domain, const QString& encodedUrl) const; - bool isMatchingDomain(const QString& domain, const QString& filter) const; - bool isMatchingRegExpStrings(const QString& url) const; - QStringList parseRegExpFilter(const QString& filter) const; + protected: + bool matchDomain(const QString& pattern, const QString& domain) const; + bool stringMatch(const QString& domain, const QString& encodedUrl) const; + bool isMatchingDomain(const QString& domain, const QString& filter) const; + bool isMatchingRegExpStrings(const QString& url) const; + QStringList parseRegExpFilter(const QString& filter) const; - private: - enum RuleType { - CssRule = 0, - DomainMatchRule = 1, - RegExpMatchRule = 2, - StringEndsMatchRule = 3, - StringContainsMatchRule = 4, - Invalid = 5 - }; + private: + enum RuleType { + CssRule = 0, + DomainMatchRule = 1, + RegExpMatchRule = 2, + StringEndsMatchRule = 3, + StringContainsMatchRule = 4, + Invalid = 5 + }; + enum RuleOption { + DomainRestrictedOption = 1, + ThirdPartyOption = 2, + ObjectOption = 4, + SubdocumentOption = 8, + XMLHttpRequestOption = 16, + ImageOption = 32, + ScriptOption = 64, + StyleSheetOption = 128, + ObjectSubrequestOption = 256, - enum RuleOption { - DomainRestrictedOption = 1, - ThirdPartyOption = 2, - ObjectOption = 4, - SubdocumentOption = 8, - XMLHttpRequestOption = 16, - ImageOption = 32, - ScriptOption = 64, - StyleSheetOption = 128, - ObjectSubrequestOption = 256, + // Exception only options. + DocumentOption = 1024, + ElementHideOption = 2048 + }; - // Exception only options. - DocumentOption = 1024, - ElementHideOption = 2048 - }; + Q_DECLARE_FLAGS(RuleOptions, RuleOption) - Q_DECLARE_FLAGS(RuleOptions, RuleOption) + inline bool hasOption(const RuleOption& opt) const; + inline bool hasException(const RuleOption& opt) const; + inline void setOption(const RuleOption& opt); + inline void setException(const RuleOption& opt, bool on); - inline bool hasOption(const RuleOption& opt) const; - inline bool hasException(const RuleOption& opt) const; + void parseFilter(); + void parseDomains(const QString& domains, const QChar& separator); + bool filterIsOnlyDomain(const QString& filter) const; + bool filterIsOnlyEndsMatch(const QString& filter) const; + QString createRegExpFromFilter(const QString& filter) const; + QList createStringMatchers(const QStringList& filters) const; - inline void setOption(const RuleOption& opt); - inline void setException(const RuleOption& opt, bool on); + AdBlockSubscription* m_subscription; + RuleType m_type; + RuleOptions m_options; + RuleOptions m_exceptions; - void parseFilter(); - void parseDomains(const QString& domains, const QChar& separator); - bool filterIsOnlyDomain(const QString& filter) const; - bool filterIsOnlyEndsMatch(const QString& filter) const; - QString createRegExpFromFilter(const QString& filter) const; - QList createStringMatchers(const QStringList& filters) const; + // Original rule filter + QString m_filter; - AdBlockSubscription* m_subscription; + // Parsed rule for string matching (CSS Selector for CSS rules) + QString m_matchString; - RuleType m_type; - RuleOptions m_options; - RuleOptions m_exceptions; + // Case sensitivity for string matching + Qt::CaseSensitivity m_caseSensitivity; - // Original rule filter - QString m_filter; - // Parsed rule for string matching (CSS Selector for CSS rules) - QString m_matchString; - // Case sensitivity for string matching - Qt::CaseSensitivity m_caseSensitivity; + bool m_isEnabled; + bool m_isException; + bool m_isInternalDisabled; + QStringList m_allowedDomains; + QStringList m_blockedDomains; + struct RegExp { + SimpleRegExp regExp; - bool m_isEnabled; - bool m_isException; - bool m_isInternalDisabled; + QList matchers; + }; - QStringList m_allowedDomains; - QStringList m_blockedDomains; + // Use dynamic allocation to save memory + RegExp* m_regExp; - struct RegExp { - SimpleRegExp regExp; - QList matchers; - }; - - // Use dynamic allocation to save memory - RegExp* m_regExp; - - friend class AdBlockMatcher; - friend class AdBlockSearchTree; - friend class AdBlockSubscription; + friend class AdBlockMatcher; + friend class AdBlockSearchTree; + friend class AdBlockSubscription; }; #endif // ADBLOCKRULE_H - diff --git a/src/network-web/adblock/adblocksearchtree.cpp b/src/network-web/adblock/adblocksearchtree.cpp index 0096586b6..c43ea7d21 100755 --- a/src/network-web/adblock/adblocksearchtree.cpp +++ b/src/network-web/adblock/adblocksearchtree.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -16,121 +17,119 @@ // You should have received a copy of the GNU General Public License // along with RSS Guard. If not, see . -#include "network-web/adblock/adblocksearchtree.h" #include "network-web/adblock/adblockrule.h" +#include "network-web/adblock/adblocksearchtree.h" #include - -AdBlockSearchTree::AdBlockSearchTree() : m_root(new Node) { -} +AdBlockSearchTree::AdBlockSearchTree() : m_root(new Node) {} AdBlockSearchTree::~AdBlockSearchTree() { - deleteNode(m_root); + deleteNode(m_root); } void AdBlockSearchTree::clear() { - deleteNode(m_root); - m_root = new Node; + deleteNode(m_root); + m_root = new Node; } bool AdBlockSearchTree::add(const AdBlockRule* rule) { - if (rule->m_type != AdBlockRule::StringContainsMatchRule) { - return false; - } + if (rule->m_type != AdBlockRule::StringContainsMatchRule) { + return false; + } - const QString filter = rule->m_matchString; - int len = filter.size(); + const QString filter = rule->m_matchString; + int len = filter.size(); - if (len <= 0) { - qDebug("AdBlockSearchTree: Inserting rule with filter len <= 0!"); - return false; - } + if (len <= 0) { + qDebug("AdBlockSearchTree: Inserting rule with filter len <= 0!"); + return false; + } - Node* node = m_root; + Node* node = m_root; - for (int i = 0; i < len; ++i) { - const QChar c = filter.at(i); - Node* next = node->children.value(c); + for (int i = 0; i < len; ++i) { + const QChar c = filter.at(i); + Node* next = node->children.value(c); - if (!next) { - next = new Node; - next->c = c; - node->children[c] = next; - } + if (!next) { + next = new Node; + next->c = c; + node->children[c] = next; + } - node = next; - } + node = next; + } - node->rule = rule; - return true; + node->rule = rule; + return true; } const AdBlockRule* AdBlockSearchTree::find(const QWebEngineUrlRequestInfo& request, const QString& domain, const QString& urlString) const { - int len = urlString.size(); + int len = urlString.size(); - if (len <= 0) { - return 0; - } + if (len <= 0) { + return 0; + } - const QChar* string = urlString.constData(); + const QChar* string = urlString.constData(); - for (int i = 0; i < len; ++i) { - const AdBlockRule* rule = prefixSearch(request, domain, urlString, string++, len - i); + for (int i = 0; i < len; ++i) { + const AdBlockRule* rule = prefixSearch(request, domain, urlString, string++, len - i); - if (rule) { - return rule; - } - } + if (rule) { + return rule; + } + } - return 0; + return 0; } const AdBlockRule* AdBlockSearchTree::prefixSearch(const QWebEngineUrlRequestInfo& request, const QString& domain, const QString& urlString, const QChar* string, int len) const { - if (len <= 0) { - return 0; - } + if (len <= 0) { + return 0; + } - QChar c = string[0]; - Node* node = m_root->children.value(c); + QChar c = string[0]; + Node* node = m_root->children.value(c); - if (!node) { - return nullptr; - } + if (!node) { + return nullptr; + } - for (int i = 1; i < len; ++i) { - const QChar c = (++string)[0]; + for (int i = 1; i < len; ++i) { + const QChar c = (++string)[0]; - if (node->rule && node->rule->networkMatch(request, domain, urlString)) { - return node->rule; - } + if (node->rule && node->rule->networkMatch(request, domain, urlString)) { + return node->rule; + } - node = node->children.value(c); + node = node->children.value(c); - if (!node) { - return nullptr; - } - } + if (!node) { + return nullptr; + } + } - if (node->rule && node->rule->networkMatch(request, domain, urlString)) { - return node->rule; - } + if (node->rule && node->rule->networkMatch(request, domain, urlString)) { + return node->rule; + } - return nullptr; + return nullptr; } void AdBlockSearchTree::deleteNode(AdBlockSearchTree::Node* node) { - if (!node) { - return; - } + if (!node) { + return; + } - QHashIterator i(node->children); + QHashIterator i(node->children); - while (i.hasNext()) { - i.next(); - deleteNode(i.value()); - } + while (i.hasNext()) { + i.next(); + deleteNode(i.value()); + } - delete node; + delete node; } diff --git a/src/network-web/adblock/adblocksearchtree.h b/src/network-web/adblock/adblocksearchtree.h index cb26a1356..8b984c48e 100755 --- a/src/network-web/adblock/adblocksearchtree.h +++ b/src/network-web/adblock/adblocksearchtree.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -22,35 +23,35 @@ #include #include - class QWebEngineUrlRequestInfo; class AdBlockRule; class AdBlockSearchTree { - public: - explicit AdBlockSearchTree(); - virtual ~AdBlockSearchTree(); + public: + explicit AdBlockSearchTree(); + virtual ~AdBlockSearchTree(); - void clear(); + void clear(); - bool add(const AdBlockRule* rule); - const AdBlockRule* find(const QWebEngineUrlRequestInfo& request, const QString& domain, const QString& urlString) const; + bool add(const AdBlockRule* rule); + const AdBlockRule* find(const QWebEngineUrlRequestInfo& request, const QString& domain, const QString& urlString) const; - private: - struct Node { - QChar c; - const AdBlockRule* rule; - QHash children; + private: + struct Node { + QChar c; + const AdBlockRule* rule; - Node() : c(0), rule(0) { } - }; + QHash children; - const AdBlockRule* prefixSearch(const QWebEngineUrlRequestInfo& request, const QString& domain, - const QString& urlString, const QChar* string, int len) const; + Node() : c(0), rule(0) { } - void deleteNode(Node* node); + }; + const AdBlockRule* prefixSearch(const QWebEngineUrlRequestInfo& request, const QString& domain, + const QString& urlString, const QChar* string, int len) const; - Node* m_root; + void deleteNode(Node* node); + + Node* m_root; }; #endif // ADBLOCKSEARCHTREE_H diff --git a/src/network-web/adblock/adblocksubscription.cpp b/src/network-web/adblock/adblocksubscription.cpp index cdfe32d9a..277268f2c 100755 --- a/src/network-web/adblock/adblocksubscription.cpp +++ b/src/network-web/adblock/adblocksubscription.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -46,359 +47,365 @@ #include "network-web/adblock/adblocksubscription.h" -#include "network-web/adblock/adblockmanager.h" -#include "network-web/adblock/adblocksearchtree.h" #include "definitions/definitions.h" -#include "network-web/silentnetworkaccessmanager.h" -#include "miscellaneous/iofactory.h" #include "exceptions/applicationexception.h" #include "miscellaneous/application.h" +#include "miscellaneous/iofactory.h" +#include "network-web/adblock/adblockmanager.h" +#include "network-web/adblock/adblocksearchtree.h" +#include "network-web/silentnetworkaccessmanager.h" +#include #include -#include #include #include -#include - +#include AdBlockSubscription::AdBlockSubscription(const QString& title, QObject* parent) - : QObject(parent), m_reply(0), m_title(title), m_updated(false) { -} + : QObject(parent), m_reply(0), m_title(title), m_updated(false) {} QString AdBlockSubscription::title() const { - return m_title; + return m_title; } QString AdBlockSubscription::filePath() const { - return m_filePath; + return m_filePath; } void AdBlockSubscription::setFilePath(const QString& path) { - m_filePath = path; + m_filePath = path; } QUrl AdBlockSubscription::url() const { - return m_url; + return m_url; } void AdBlockSubscription::setUrl(const QUrl& url) { - m_url = url; + m_url = url; } void AdBlockSubscription::loadSubscription(const QStringList& disabledRules) { - QFile file(m_filePath); + QFile file(m_filePath); - if (!file.exists()) { - QTimer::singleShot(0, this, SLOT(updateSubscription())); - return; - } + if (!file.exists()) { + QTimer::singleShot(0, this, SLOT(updateSubscription())); + return; + } - if (!file.open(QFile::ReadOnly)) { - qWarning("Unable to open adblock file '%s' for reading.", qPrintable(m_filePath)); - QTimer::singleShot(0, this, SLOT(updateSubscription())); - return; - } + if (!file.open(QFile::ReadOnly)) { + qWarning("Unable to open adblock file '%s' for reading.", qPrintable(m_filePath)); + QTimer::singleShot(0, this, SLOT(updateSubscription())); + return; + } - QTextStream textStream(&file); - textStream.setCodec("UTF-8"); - // Header is on 3rd line. - textStream.readLine(1024); - textStream.readLine(1024); - QString header = textStream.readLine(1024); + QTextStream textStream(&file); - if (!header.startsWith(QL1S("[Adblock")) || m_title.isEmpty()) { - qWarning("Invalid format of AdBlock file '%s'.", qPrintable(m_filePath)); - QTimer::singleShot(0, this, SLOT(updateSubscription())); - return; - } + textStream.setCodec("UTF-8"); - m_rules.clear(); + // Header is on 3rd line. + textStream.readLine(1024); + textStream.readLine(1024); + QString header = textStream.readLine(1024); - while (!textStream.atEnd()) { - AdBlockRule* rule = new AdBlockRule(textStream.readLine(), this); + if (!header.startsWith(QL1S("[Adblock")) || m_title.isEmpty()) { + qWarning("Invalid format of AdBlock file '%s'.", qPrintable(m_filePath)); + QTimer::singleShot(0, this, SLOT(updateSubscription())); + return; + } - if (disabledRules.contains(rule->filter())) { - rule->setEnabled(false); - } + m_rules.clear(); - m_rules.append(rule); - } + while (!textStream.atEnd()) { + AdBlockRule* rule = new AdBlockRule(textStream.readLine(), this); - // Initial update. - if (m_rules.isEmpty() && !m_updated) { - QTimer::singleShot(0, this, SLOT(updateSubscription())); - } + if (disabledRules.contains(rule->filter())) { + rule->setEnabled(false); + } + + m_rules.append(rule); + } + + // Initial update. + if (m_rules.isEmpty() && !m_updated) { + QTimer::singleShot(0, this, SLOT(updateSubscription())); + } } -void AdBlockSubscription::saveSubscription() { -} +void AdBlockSubscription::saveSubscription() {} void AdBlockSubscription::updateSubscription() { - if (m_reply || !m_url.isValid()) { - return; - } + if (m_reply || !m_url.isValid()) { + return; + } - SilentNetworkAccessManager* mgs = new SilentNetworkAccessManager(this); - m_reply = mgs->get(QNetworkRequest(m_url)); - connect(m_reply, &QNetworkReply::finished, this, &AdBlockSubscription::subscriptionDownloaded); + SilentNetworkAccessManager* mgs = new SilentNetworkAccessManager(this); + + m_reply = mgs->get(QNetworkRequest(m_url)); + connect(m_reply, &QNetworkReply::finished, this, &AdBlockSubscription::subscriptionDownloaded); } void AdBlockSubscription::subscriptionDownloaded() { - if (m_reply != qobject_cast(sender())) { - return; - } + if (m_reply != qobject_cast(sender())) { + return; + } - bool error = false; - const QByteArray response = QString::fromUtf8(m_reply->readAll()).toUtf8(); + bool error = false; + const QByteArray response = QString::fromUtf8(m_reply->readAll()).toUtf8(); - if (m_reply->error() != QNetworkReply::NoError || !response.startsWith(QByteArray("[Adblock")) || !saveDownloadedData(response)) { - error = true; - } + if (m_reply->error() != QNetworkReply::NoError || !response.startsWith(QByteArray("[Adblock")) || !saveDownloadedData(response)) { + error = true; + } - m_reply->manager()->deleteLater(); - m_reply->deleteLater(); - m_reply = 0; + m_reply->manager()->deleteLater(); + m_reply->deleteLater(); + m_reply = 0; - if (error) { - emit subscriptionError(tr("Cannot load subscription!")); - return; - } + if (error) { + emit subscriptionError(tr("Cannot load subscription!")); - loadSubscription(AdBlockManager::instance()->disabledRules()); - emit subscriptionUpdated(); - emit subscriptionChanged(); + return; + } + + loadSubscription(AdBlockManager::instance()->disabledRules()); + emit subscriptionUpdated(); + emit subscriptionChanged(); } bool AdBlockSubscription::saveDownloadedData(const QByteArray& data) { - QSaveFile file(m_filePath); + QSaveFile file(m_filePath); - if (!file.open(QFile::WriteOnly)) { - qWarning("Unable to open AdBlock file '%s' for writing.", qPrintable(m_filePath)); - return false; - } - else { - // Write subscription header - file.write(QString("Title: %1\nUrl: %2\n").arg(title(), url().toString()).toUtf8()); - file.write(data); - file.commit(); - return true; - } + if (!file.open(QFile::WriteOnly)) { + qWarning("Unable to open AdBlock file '%s' for writing.", qPrintable(m_filePath)); + return false; + } + else { + // Write subscription header + file.write(QString("Title: %1\nUrl: %2\n").arg(title(), url().toString()).toUtf8()); + file.write(data); + file.commit(); + return true; + } } const AdBlockRule* AdBlockSubscription::rule(int offset) const { - if (IS_IN_ARRAY(offset, m_rules)) { - return m_rules[offset]; - } - else { - return 0; - } + if (IS_IN_ARRAY(offset, m_rules)) { + return m_rules[offset]; + } + else { + return 0; + } } QVector AdBlockSubscription::allRules() const { - return m_rules; + return m_rules; } const AdBlockRule* AdBlockSubscription::enableRule(int offset) { - if (IS_IN_ARRAY(offset, m_rules)) { - AdBlockRule* rule = m_rules[offset]; - rule->setEnabled(true); - AdBlockManager::instance()->removeDisabledRule(rule->filter()); - emit subscriptionChanged(); + if (IS_IN_ARRAY(offset, m_rules)) { + AdBlockRule* rule = m_rules[offset]; - if (rule->isCssRule()) { - // TODO: Reload user stylesheet. - } + rule->setEnabled(true); + AdBlockManager::instance()->removeDisabledRule(rule->filter()); + emit subscriptionChanged(); - return rule; - } - else { - return 0; - } + if (rule->isCssRule()) { + // TODO: Reload user stylesheet. + } + + return rule; + } + else { + return 0; + } } const AdBlockRule* AdBlockSubscription::disableRule(int offset) { - if (!IS_IN_ARRAY(offset, m_rules)) { - return 0; - } + if (!IS_IN_ARRAY(offset, m_rules)) { + return 0; + } - AdBlockRule* rule = m_rules[offset]; - rule->setEnabled(false); - AdBlockManager::instance()->addDisabledRule(rule->filter()); - emit subscriptionChanged(); + AdBlockRule* rule = m_rules[offset]; - if (rule->isCssRule()) { - // TODO: Reload user stylesheet. - } + rule->setEnabled(false); + AdBlockManager::instance()->addDisabledRule(rule->filter()); + emit subscriptionChanged(); - return rule; + if (rule->isCssRule()) { + // TODO: Reload user stylesheet. + } + + return rule; } bool AdBlockSubscription::canEditRules() const { - return false; + return false; } bool AdBlockSubscription::canBeRemoved() const { - return true; + return true; } int AdBlockSubscription::addRule(AdBlockRule* rule) { - Q_UNUSED(rule) - return -1; + Q_UNUSED(rule) + return -1; } bool AdBlockSubscription::removeRule(int offset) { - Q_UNUSED(offset) - return false; + Q_UNUSED(offset) + return false; } const AdBlockRule* AdBlockSubscription::replaceRule(AdBlockRule* rule, int offset) { - Q_UNUSED(rule) - Q_UNUSED(offset) - return 0; + Q_UNUSED(rule) + Q_UNUSED(offset) + return 0; } AdBlockSubscription::~AdBlockSubscription() { - qDeleteAll(m_rules); + qDeleteAll(m_rules); } // AdBlockCustomList AdBlockCustomList::AdBlockCustomList(QObject* parent) - : AdBlockSubscription(tr("Custom rules"), parent) { - setFilePath(AdBlockManager::storedListsPath() + QDir::separator() + ADBLOCK_CUSTOMLIST_NAME); + : AdBlockSubscription(tr("Custom rules"), parent) { + setFilePath(AdBlockManager::storedListsPath() + QDir::separator() + ADBLOCK_CUSTOMLIST_NAME); } void AdBlockCustomList::loadSubscription(const QStringList& disabledRules) { - // DuckDuckGo ad whitelist rules - // They cannot be removed, but can be disabled. - // Please consider not disabling them. Thanks! - const QString ddg1 = QSL("@@||duckduckgo.com^$document"); - const QString ddg2 = QSL("duckduckgo.com#@#.has-ad"); - QString rules; + // DuckDuckGo ad whitelist rules + // They cannot be removed, but can be disabled. + // Please consider not disabling them. Thanks! + const QString ddg1 = QSL("@@||duckduckgo.com^$document"); + const QString ddg2 = QSL("duckduckgo.com#@#.has-ad"); + QString rules; - try { - rules = QString::fromUtf8(IOFactory::readTextFile(filePath())); - } - catch (ApplicationException&) { - } + try { + rules = QString::fromUtf8(IOFactory::readTextFile(filePath())); + } + catch (ApplicationException&) {} - QFile file(filePath()); + QFile file(filePath()); - if (!file.exists()) { - saveSubscription(); - } + if (!file.exists()) { + saveSubscription(); + } - if (file.open(QFile::WriteOnly | QFile::Append)) { - QTextStream stream(&file); - stream.setCodec("UTF-8"); + if (file.open(QFile::WriteOnly | QFile::Append)) { + QTextStream stream(&file); - if (!rules.contains(ddg1 + QL1S("\n"))) { - stream << ddg1 << endl; - } + stream.setCodec("UTF-8"); - if (!rules.contains(QL1S("\n") + ddg2)) { - stream << ddg2 << endl; - } - } + if (!rules.contains(ddg1 + QL1S("\n"))) { + stream << ddg1 << endl; + } - file.close(); - AdBlockSubscription::loadSubscription(disabledRules); + if (!rules.contains(QL1S("\n") + ddg2)) { + stream << ddg2 << endl; + } + } + + file.close(); + AdBlockSubscription::loadSubscription(disabledRules); } void AdBlockCustomList::saveSubscription() { - QFile file(filePath()); + QFile file(filePath()); - if (!file.open(QFile::ReadWrite | QFile::Truncate)) { - qWarning("Unable to open AdBlock file '%s' for writing.", qPrintable(filePath())); - return; - } + if (!file.open(QFile::ReadWrite | QFile::Truncate)) { + qWarning("Unable to open AdBlock file '%s' for writing.", qPrintable(filePath())); + return; + } - QTextStream textStream(&file); - textStream.setCodec("UTF-8"); - textStream << "Title: " << title() << endl; - textStream << "Url: " << url().toString() << endl; - textStream << "[Adblock Plus 1.1.1]" << endl; + QTextStream textStream(&file); - foreach (const AdBlockRule* rule, m_rules) { - textStream << rule->filter() << endl; - } + textStream.setCodec("UTF-8"); + textStream << "Title: " << title() << endl; + textStream << "Url: " << url().toString() << endl; + textStream << "[Adblock Plus 1.1.1]" << endl; - file.close(); + foreach (const AdBlockRule* rule, m_rules) { + textStream << rule->filter() << endl; + } + + file.close(); } bool AdBlockCustomList::canEditRules() const { - return true; + return true; } bool AdBlockCustomList::canBeRemoved() const { - return false; + return false; } bool AdBlockCustomList::containsFilter(const QString& filter) const { - foreach (const AdBlockRule* rule, m_rules) { - if (rule->filter() == filter) { - return true; - } - } + foreach (const AdBlockRule* rule, m_rules) { + if (rule->filter() == filter) { + return true; + } + } - return false; + return false; } bool AdBlockCustomList::removeFilter(const QString& filter) { - for (int i = 0; i < m_rules.count(); ++i) { - const AdBlockRule* rule = m_rules.at(i); + for (int i = 0; i < m_rules.count(); ++i) { + const AdBlockRule* rule = m_rules.at(i); - if (rule->filter() == filter) { - return removeRule(i); - } - } + if (rule->filter() == filter) { + return removeRule(i); + } + } - return false; + return false; } int AdBlockCustomList::addRule(AdBlockRule* rule) { - m_rules.append(rule); - emit subscriptionChanged(); + m_rules.append(rule); + emit subscriptionChanged(); - if (rule->isCssRule()) { - // TODO: Reload user stylesheet. - } + if (rule->isCssRule()) { + // TODO: Reload user stylesheet. + } - return m_rules.count() - 1; + return m_rules.count() - 1; } bool AdBlockCustomList::removeRule(int offset) { - if (!IS_IN_ARRAY(offset, m_rules)) { - return false; - } + if (!IS_IN_ARRAY(offset, m_rules)) { + return false; + } - AdBlockRule* rule = m_rules.at(offset); - const QString filter = rule->filter(); - m_rules.remove(offset); - emit subscriptionChanged(); + AdBlockRule* rule = m_rules.at(offset); + const QString filter = rule->filter(); - if (rule->isCssRule()) { - // TODO: Reload user stylesheet. - } + m_rules.remove(offset); + emit subscriptionChanged(); - AdBlockManager::instance()->removeDisabledRule(filter); - delete rule; - return true; + if (rule->isCssRule()) { + // TODO: Reload user stylesheet. + } + + AdBlockManager::instance()->removeDisabledRule(filter); + delete rule; + return true; } const AdBlockRule* AdBlockCustomList::replaceRule(AdBlockRule* rule, int offset) { - if (!IS_IN_ARRAY(offset, m_rules)) { - return 0; - } + if (!IS_IN_ARRAY(offset, m_rules)) { + return 0; + } - AdBlockRule* oldRule = m_rules.at(offset); - m_rules[offset] = rule; - emit subscriptionChanged(); + AdBlockRule* oldRule = m_rules.at(offset); - if (rule->isCssRule() || oldRule->isCssRule()) { - // TODO: Reload user stylesheet. - } + m_rules[offset] = rule; + emit subscriptionChanged(); - delete oldRule; - return m_rules[offset]; + if (rule->isCssRule() || oldRule->isCssRule()) { + // TODO: Reload user stylesheet. + } + + delete oldRule; + return m_rules[offset]; } diff --git a/src/network-web/adblock/adblocksubscription.h b/src/network-web/adblock/adblocksubscription.h index e3ecfc56c..204758305 100755 --- a/src/network-web/adblock/adblocksubscription.h +++ b/src/network-web/adblock/adblocksubscription.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -47,91 +48,86 @@ #ifndef ADBLOCKSUBSCRIPTION_H #define ADBLOCKSUBSCRIPTION_H -#include #include +#include #include "network-web/adblock/adblockrule.h" #include "network-web/adblock/adblocksearchtree.h" - class QUrl; class QNetworkReply; class AdBlockSubscription : public QObject { - Q_OBJECT + Q_OBJECT - public: - explicit AdBlockSubscription(const QString& title, QObject* parent = 0); - virtual ~AdBlockSubscription(); + public: + explicit AdBlockSubscription(const QString& title, QObject* parent = 0); + virtual ~AdBlockSubscription(); - QString title() const; + QString title() const; - QString filePath() const; - void setFilePath(const QString& path); + QString filePath() const; + void setFilePath(const QString& path); - QUrl url() const; - void setUrl(const QUrl& url); + QUrl url() const; + void setUrl(const QUrl& url); - virtual void loadSubscription(const QStringList& disabledRules); - virtual void saveSubscription(); + virtual void loadSubscription(const QStringList& disabledRules); + virtual void saveSubscription(); + const AdBlockRule* rule(int offset) const; - const AdBlockRule* rule(int offset) const; - QVector allRules() const; + QVector allRules() const; - const AdBlockRule* enableRule(int offset); - const AdBlockRule* disableRule(int offset); + const AdBlockRule* enableRule(int offset); + const AdBlockRule* disableRule(int offset); + virtual bool canEditRules() const; + virtual bool canBeRemoved() const; + virtual int addRule(AdBlockRule* rule); + virtual bool removeRule(int offset); + virtual const AdBlockRule* replaceRule(AdBlockRule* rule, int offset); - virtual bool canEditRules() const; - virtual bool canBeRemoved() const; + public slots: + void updateSubscription(); - virtual int addRule(AdBlockRule* rule); - virtual bool removeRule(int offset); - virtual const AdBlockRule* replaceRule(AdBlockRule* rule, int offset); + signals: + void subscriptionChanged(); + void subscriptionUpdated(); + void subscriptionError(const QString& message); - public slots: - void updateSubscription(); + protected slots: + void subscriptionDownloaded(); - signals: - void subscriptionChanged(); - void subscriptionUpdated(); - void subscriptionError(const QString& message); + protected: + virtual bool saveDownloadedData(const QByteArray& data); + QNetworkReply* m_reply; - protected slots: - void subscriptionDownloaded(); + QVector m_rules; - protected: - virtual bool saveDownloadedData(const QByteArray& data); - - QNetworkReply* m_reply; - QVector m_rules; - - private: - QString m_title; - QString m_filePath; - - QUrl m_url; - bool m_updated; + private: + QString m_title; + QString m_filePath; + QUrl m_url; + bool m_updated; }; class AdBlockCustomList : public AdBlockSubscription { - Q_OBJECT + Q_OBJECT - public: - explicit AdBlockCustomList(QObject* parent = 0); + public: + explicit AdBlockCustomList(QObject* parent = 0); - void loadSubscription(const QStringList& disabledRules); - void saveSubscription(); + void loadSubscription(const QStringList& disabledRules); + void saveSubscription(); - bool canEditRules() const; - bool canBeRemoved() const; + bool canEditRules() const; + bool canBeRemoved() const; - bool containsFilter(const QString& filter) const; - bool removeFilter(const QString& filter); + bool containsFilter(const QString& filter) const; + bool removeFilter(const QString& filter); - int addRule(AdBlockRule* rule); - bool removeRule(int offset); - const AdBlockRule* replaceRule(AdBlockRule* rule, int offset); + int addRule(AdBlockRule* rule); + bool removeRule(int offset); + const AdBlockRule* replaceRule(AdBlockRule* rule, int offset); }; #endif // ADBLOCKSUBSCRIPTION_H - diff --git a/src/network-web/adblock/adblocktreewidget.cpp b/src/network-web/adblock/adblocktreewidget.cpp index ed823e786..998b3d938 100755 --- a/src/network-web/adblock/adblocktreewidget.cpp +++ b/src/network-web/adblock/adblocktreewidget.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -20,225 +21,234 @@ #include "network-web/adblock/adblocksubscription.h" -#include -#include -#include #include +#include #include - +#include +#include AdBlockTreeWidget::AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent) - : TreeWidget(parent), m_subscription(subscription), m_topItem(0), m_itemChangingBlock(false) { - setContextMenuPolicy(Qt::CustomContextMenu); - setDefaultItemShowMode(TreeWidget::ItemsExpanded); - setHeaderHidden(true); - setAlternatingRowColors(true); - setLayoutDirection(Qt::LeftToRight); - setIndentation(5); - connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequested(QPoint))); - connect(this, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT(itemChanged(QTreeWidgetItem*))); - connect(m_subscription, SIGNAL(subscriptionUpdated()), this, SLOT(subscriptionUpdated())); - connect(m_subscription, SIGNAL(subscriptionError(QString)), this, SLOT(subscriptionError(QString))); + : TreeWidget(parent), m_subscription(subscription), m_topItem(0), m_itemChangingBlock(false) { + setContextMenuPolicy(Qt::CustomContextMenu); + setDefaultItemShowMode(TreeWidget::ItemsExpanded); + setHeaderHidden(true); + setAlternatingRowColors(true); + setLayoutDirection(Qt::LeftToRight); + setIndentation(5); + connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequested(QPoint))); + connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(itemChanged(QTreeWidgetItem*))); + connect(m_subscription, SIGNAL(subscriptionUpdated()), this, SLOT(subscriptionUpdated())); + connect(m_subscription, SIGNAL(subscriptionError(QString)), this, SLOT(subscriptionError(QString))); } AdBlockSubscription* AdBlockTreeWidget::subscription() const { - return m_subscription; + return m_subscription; } void AdBlockTreeWidget::showRule(const AdBlockRule* rule) { - if (!m_topItem && rule) { - m_ruleToBeSelected = rule->filter(); - } - else if (!m_ruleToBeSelected.isEmpty()) { - QList items = findItems(m_ruleToBeSelected, Qt::MatchRecursive); + if (!m_topItem && rule) { + m_ruleToBeSelected = rule->filter(); + } + else if (!m_ruleToBeSelected.isEmpty()) { + QList items = findItems(m_ruleToBeSelected, Qt::MatchRecursive); - if (!items.isEmpty()) { - QTreeWidgetItem* item = items.at(0); - setCurrentItem(item); - scrollToItem(item, QAbstractItemView::PositionAtCenter); - } + if (!items.isEmpty()) { + QTreeWidgetItem* item = items.at(0); - m_ruleToBeSelected.clear(); - } + setCurrentItem(item); + scrollToItem(item, QAbstractItemView::PositionAtCenter); + } + + m_ruleToBeSelected.clear(); + } } void AdBlockTreeWidget::contextMenuRequested(const QPoint& pos) { - if (!m_subscription->canEditRules()) { - return; - } + if (!m_subscription->canEditRules()) { + return; + } - QTreeWidgetItem* item = itemAt(pos); + QTreeWidgetItem* item = itemAt(pos); - if (!item) { - return; - } + if (!item) { + return; + } - QMenu menu; - menu.addAction(tr("Add rule"), this, SLOT(addRule())); - menu.addSeparator(); - QAction* deleteAction = menu.addAction(tr("Remove rule"), this, SLOT(removeRule())); + QMenu menu; - if (!item->parent()) { - deleteAction->setDisabled(true); - } + menu.addAction(tr("Add rule"), this, SLOT(addRule())); + menu.addSeparator(); + QAction* deleteAction = menu.addAction(tr("Remove rule"), this, SLOT(removeRule())); - menu.exec(viewport()->mapToGlobal(pos)); + if (!item->parent()) { + deleteAction->setDisabled(true); + } + + menu.exec(viewport()->mapToGlobal(pos)); } void AdBlockTreeWidget::itemChanged(QTreeWidgetItem* item) { - if (!item || m_itemChangingBlock) { - return; - } + if (!item || m_itemChangingBlock) { + return; + } - m_itemChangingBlock = true; - int offset = item->data(0, Qt::UserRole + 10).toInt(); - const AdBlockRule* oldRule = m_subscription->rule(offset); + m_itemChangingBlock = true; + int offset = item->data(0, Qt::UserRole + 10).toInt(); + const AdBlockRule* oldRule = m_subscription->rule(offset); - if (item->checkState(0) == Qt::Unchecked && oldRule->isEnabled()) { - // Disable rule. - const AdBlockRule* rule = m_subscription->disableRule(offset); - adjustItemFeatures(item, rule); - } - else if (item->checkState(0) == Qt::Checked && !oldRule->isEnabled()) { - // Enable rule. - const AdBlockRule* rule = m_subscription->enableRule(offset); - adjustItemFeatures(item, rule); - } - else if (m_subscription->canEditRules()) { - // Custom rule has been changed. - AdBlockRule* newRule = new AdBlockRule(item->text(0), m_subscription); - const AdBlockRule* rule = m_subscription->replaceRule(newRule, offset); - adjustItemFeatures(item, rule); - } + if (item->checkState(0) == Qt::Unchecked && oldRule->isEnabled()) { + // Disable rule. + const AdBlockRule* rule = m_subscription->disableRule(offset); - m_itemChangingBlock = false; + adjustItemFeatures(item, rule); + } + else if (item->checkState(0) == Qt::Checked && !oldRule->isEnabled()) { + // Enable rule. + const AdBlockRule* rule = m_subscription->enableRule(offset); + + adjustItemFeatures(item, rule); + } + else if (m_subscription->canEditRules()) { + // Custom rule has been changed. + AdBlockRule* newRule = new AdBlockRule(item->text(0), m_subscription); + const AdBlockRule* rule = m_subscription->replaceRule(newRule, offset); + + adjustItemFeatures(item, rule); + } + + m_itemChangingBlock = false; } void AdBlockTreeWidget::copyFilter() { - QTreeWidgetItem* item = currentItem(); + QTreeWidgetItem* item = currentItem(); - if (!item) { - return; - } + if (!item) { + return; + } - QApplication::clipboard()->setText(item->text(0)); + QApplication::clipboard()->setText(item->text(0)); } void AdBlockTreeWidget::addRule() { - if (!m_subscription->canEditRules()) { - return; - } + if (!m_subscription->canEditRules()) { + return; + } - QString newRule = QInputDialog::getText(this, tr("Add custom rule"), tr("Please write your rule here:")); + QString newRule = QInputDialog::getText(this, tr("Add custom rule"), tr("Please write your rule here:")); - if (newRule.isEmpty()) { - return; - } + if (newRule.isEmpty()) { + return; + } - AdBlockRule* rule = new AdBlockRule(newRule, m_subscription); - int offset = m_subscription->addRule(rule); - QTreeWidgetItem* item = new QTreeWidgetItem(); - item->setText(0, newRule); - item->setData(0, Qt::UserRole + 10, offset); - item->setFlags(item->flags() | Qt::ItemIsEditable); - m_itemChangingBlock = true; - m_topItem->addChild(item); - m_itemChangingBlock = false; - adjustItemFeatures(item, rule); + AdBlockRule* rule = new AdBlockRule(newRule, m_subscription); + int offset = m_subscription->addRule(rule); + QTreeWidgetItem* item = new QTreeWidgetItem(); + + item->setText(0, newRule); + item->setData(0, Qt::UserRole + 10, offset); + item->setFlags(item->flags() | Qt::ItemIsEditable); + m_itemChangingBlock = true; + m_topItem->addChild(item); + m_itemChangingBlock = false; + adjustItemFeatures(item, rule); } void AdBlockTreeWidget::removeRule() { - QTreeWidgetItem* item = currentItem(); + QTreeWidgetItem* item = currentItem(); - if (!item || !m_subscription->canEditRules() || item == m_topItem) { - return; - } + if (!item || !m_subscription->canEditRules() || item == m_topItem) { + return; + } - int offset = item->data(0, Qt::UserRole + 10).toInt(); - m_subscription->removeRule(offset); - deleteItem(item); + int offset = item->data(0, Qt::UserRole + 10).toInt(); + + m_subscription->removeRule(offset); + deleteItem(item); } void AdBlockTreeWidget::subscriptionUpdated() { - refresh(); - m_itemChangingBlock = true; - m_topItem->setText(0, tr("%1 (recently updated)").arg(m_subscription->title())); - m_itemChangingBlock = false; + refresh(); + m_itemChangingBlock = true; + m_topItem->setText(0, tr("%1 (recently updated)").arg(m_subscription->title())); + m_itemChangingBlock = false; } void AdBlockTreeWidget::subscriptionError(const QString& message) { - refresh(); - m_itemChangingBlock = true; - m_topItem->setText(0, tr("%1 (error: %2)").arg(m_subscription->title(), message)); - m_itemChangingBlock = false; + refresh(); + m_itemChangingBlock = true; + m_topItem->setText(0, tr("%1 (error: %2)").arg(m_subscription->title(), message)); + m_itemChangingBlock = false; } void AdBlockTreeWidget::adjustItemFeatures(QTreeWidgetItem* item, const AdBlockRule* rule) { - if (!rule->isEnabled()) { - QFont font; - font.setItalic(true); - item->setForeground(0, QColor(Qt::gray)); + if (!rule->isEnabled()) { + QFont font; - if (!rule->isComment()) { - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - item->setCheckState(0, Qt::Unchecked); - item->setFont(0, font); - } + font.setItalic(true); + item->setForeground(0, QColor(Qt::gray)); - return; - } + if (!rule->isComment()) { + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setCheckState(0, Qt::Unchecked); + item->setFont(0, font); + } - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - item->setCheckState(0, Qt::Checked); + return; + } - if (rule->isException()) { - item->setForeground(0, QColor(Qt::darkGreen)); - item->setFont(0, QFont()); - } - else if (rule->isCssRule()) { - item->setForeground(0, QColor(Qt::darkBlue)); - item->setFont(0, QFont()); - } + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + item->setCheckState(0, Qt::Checked); + + if (rule->isException()) { + item->setForeground(0, QColor(Qt::darkGreen)); + item->setFont(0, QFont()); + } + else if (rule->isCssRule()) { + item->setForeground(0, QColor(Qt::darkBlue)); + item->setFont(0, QFont()); + } } void AdBlockTreeWidget::keyPressEvent(QKeyEvent* event) { - if (event->key() == Qt::Key_C && event->modifiers() & Qt::ControlModifier) { - copyFilter(); - } + if (event->key() == Qt::Key_C && event->modifiers() & Qt::ControlModifier) { + copyFilter(); + } - if (event->key() == Qt::Key_Delete) { - removeRule(); - } + if (event->key() == Qt::Key_Delete) { + removeRule(); + } - TreeWidget::keyPressEvent(event); + TreeWidget::keyPressEvent(event); } void AdBlockTreeWidget::refresh() { - m_itemChangingBlock = true; - clear(); - QFont boldFont; - boldFont.setBold(true); - m_topItem = new QTreeWidgetItem(this); - m_topItem->setText(0, m_subscription->title()); - m_topItem->setFont(0, boldFont); - m_topItem->setExpanded(true); - addTopLevelItem(m_topItem); - const QVector& allRules = m_subscription->allRules(); - int index = 0; + m_itemChangingBlock = true; + clear(); + QFont boldFont; - foreach (const AdBlockRule* rule, allRules) { - QTreeWidgetItem* item = new QTreeWidgetItem(m_topItem); - item->setText(0, rule->filter()); - item->setData(0, Qt::UserRole + 10, index); + boldFont.setBold(true); + m_topItem = new QTreeWidgetItem(this); + m_topItem->setText(0, m_subscription->title()); + m_topItem->setFont(0, boldFont); + m_topItem->setExpanded(true); + addTopLevelItem(m_topItem); + const QVector& allRules = m_subscription->allRules(); + int index = 0; - if (m_subscription->canEditRules()) { - item->setFlags(item->flags() | Qt::ItemIsEditable); - } + foreach (const AdBlockRule* rule, allRules) { + QTreeWidgetItem* item = new QTreeWidgetItem(m_topItem); - adjustItemFeatures(item, rule); - ++index; - } + item->setText(0, rule->filter()); + item->setData(0, Qt::UserRole + 10, index); - showRule(0); - m_itemChangingBlock = false; + if (m_subscription->canEditRules()) { + item->setFlags(item->flags() | Qt::ItemIsEditable); + } + + adjustItemFeatures(item, rule); + ++index; + } + + showRule(0); + m_itemChangingBlock = false; } diff --git a/src/network-web/adblock/adblocktreewidget.h b/src/network-web/adblock/adblocktreewidget.h index cc4d1c69f..27d61bfe9 100755 --- a/src/network-web/adblock/adblocktreewidget.h +++ b/src/network-web/adblock/adblocktreewidget.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -21,42 +22,40 @@ #include "gui/treewidget.h" - class AdBlockSubscription; class AdBlockRule; class AdBlockTreeWidget : public TreeWidget { - Q_OBJECT + Q_OBJECT - public: - explicit AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent = 0); + public: + explicit AdBlockTreeWidget(AdBlockSubscription* subscription, QWidget* parent = 0); - AdBlockSubscription* subscription() const; + AdBlockSubscription* subscription() const; - void showRule(const AdBlockRule* rule); - void refresh(); + void showRule(const AdBlockRule* rule); + void refresh(); - public slots: - void addRule(); - void removeRule(); + public slots: + void addRule(); + void removeRule(); - private slots: - void contextMenuRequested(const QPoint& pos); - void itemChanged(QTreeWidgetItem* item); - void copyFilter(); + private slots: + void contextMenuRequested(const QPoint& pos); + void itemChanged(QTreeWidgetItem* item); + void copyFilter(); - void subscriptionUpdated(); - void subscriptionError(const QString& message); + void subscriptionUpdated(); + void subscriptionError(const QString& message); - private: - void adjustItemFeatures(QTreeWidgetItem* item, const AdBlockRule* rule); - void keyPressEvent(QKeyEvent* event); + private: + void adjustItemFeatures(QTreeWidgetItem* item, const AdBlockRule* rule); + void keyPressEvent(QKeyEvent* event); - AdBlockSubscription* m_subscription; - QTreeWidgetItem* m_topItem; - - QString m_ruleToBeSelected; - bool m_itemChangingBlock; + AdBlockSubscription* m_subscription; + QTreeWidgetItem* m_topItem; + QString m_ruleToBeSelected; + bool m_itemChangingBlock; }; #endif // ADBLOCKTREEWIDGET_H diff --git a/src/network-web/adblock/adblockurlinterceptor.cpp b/src/network-web/adblock/adblockurlinterceptor.cpp index 378d25637..a2369d26c 100755 --- a/src/network-web/adblock/adblockurlinterceptor.cpp +++ b/src/network-web/adblock/adblockurlinterceptor.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -20,11 +21,9 @@ #include "network-web/adblock/adblockmanager.h" - AdBlockUrlInterceptor::AdBlockUrlInterceptor(AdBlockManager* manager) - : UrlInterceptor(manager), m_manager(manager) { -} + : UrlInterceptor(manager), m_manager(manager) {} void AdBlockUrlInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - info.block(m_manager->block(info)); + info.block(m_manager->block(info)); } diff --git a/src/network-web/adblock/adblockurlinterceptor.h b/src/network-web/adblock/adblockurlinterceptor.h index affc1d57e..41fce7a3f 100755 --- a/src/network-web/adblock/adblockurlinterceptor.h +++ b/src/network-web/adblock/adblockurlinterceptor.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -21,19 +22,18 @@ #include "network-web/urlinterceptor.h" - class AdBlockManager; class AdBlockUrlInterceptor : public UrlInterceptor { - Q_OBJECT + Q_OBJECT - public: - explicit AdBlockUrlInterceptor(AdBlockManager* manager); + public: + explicit AdBlockUrlInterceptor(AdBlockManager* manager); - void interceptRequest(QWebEngineUrlRequestInfo& info); + void interceptRequest(QWebEngineUrlRequestInfo& info); - private: - AdBlockManager* m_manager; + private: + AdBlockManager* m_manager; }; #endif // ADBLOCKURLINTERCEPTOR_H diff --git a/src/network-web/basenetworkaccessmanager.cpp b/src/network-web/basenetworkaccessmanager.cpp index a609a065a..03c118442 100755 --- a/src/network-web/basenetworkaccessmanager.cpp +++ b/src/network-web/basenetworkaccessmanager.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -24,56 +25,58 @@ #include #include - BaseNetworkAccessManager::BaseNetworkAccessManager(QObject* parent) - : QNetworkAccessManager(parent) { - connect(this, &BaseNetworkAccessManager::sslErrors, this, &BaseNetworkAccessManager::onSslErrors); - loadSettings(); + : QNetworkAccessManager(parent) { + connect(this, &BaseNetworkAccessManager::sslErrors, this, &BaseNetworkAccessManager::onSslErrors); + loadSettings(); } -BaseNetworkAccessManager::~BaseNetworkAccessManager() { -} +BaseNetworkAccessManager::~BaseNetworkAccessManager() {} void BaseNetworkAccessManager::loadSettings() { - QNetworkProxy new_proxy; - const QNetworkProxy::ProxyType selected_proxy_type = static_cast(qApp->settings()->value(GROUP(Proxy), - SETTING(Proxy::Type)).toInt()); + QNetworkProxy new_proxy; + const QNetworkProxy::ProxyType selected_proxy_type = static_cast(qApp->settings()->value(GROUP(Proxy), + SETTING(Proxy::Type)). + toInt()); - if (selected_proxy_type == QNetworkProxy::NoProxy) { - // No extra setting is needed, set new proxy and exit this method. - setProxy(QNetworkProxy::NoProxy); - } - else if (selected_proxy_type == QNetworkProxy::DefaultProxy) { - setProxy(QNetworkProxy::applicationProxy()); - } - else { - const Settings* settings = qApp->settings(); - // Custom proxy is selected, set it up. - new_proxy.setType(selected_proxy_type); - new_proxy.setHostName(settings->value(GROUP(Proxy), SETTING(Proxy::Host)).toString()); - new_proxy.setPort(settings->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt()); - new_proxy.setUser(settings->value(GROUP(Proxy), SETTING(Proxy::Username)).toString()); - new_proxy.setPassword(TextFactory::decrypt(settings->value(GROUP(Proxy), SETTING(Proxy::Password)).toString())); - setProxy(new_proxy); - } + if (selected_proxy_type == QNetworkProxy::NoProxy) { + // No extra setting is needed, set new proxy and exit this method. + setProxy(QNetworkProxy::NoProxy); + } + else if (selected_proxy_type == QNetworkProxy::DefaultProxy) { + setProxy(QNetworkProxy::applicationProxy()); + } + else { + const Settings* settings = qApp->settings(); - qDebug("Settings of BaseNetworkAccessManager loaded."); + // Custom proxy is selected, set it up. + new_proxy.setType(selected_proxy_type); + new_proxy.setHostName(settings->value(GROUP(Proxy), SETTING(Proxy::Host)).toString()); + new_proxy.setPort(settings->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt()); + new_proxy.setUser(settings->value(GROUP(Proxy), SETTING(Proxy::Username)).toString()); + new_proxy.setPassword(TextFactory::decrypt(settings->value(GROUP(Proxy), SETTING(Proxy::Password)).toString())); + setProxy(new_proxy); + } + + qDebug("Settings of BaseNetworkAccessManager loaded."); } void BaseNetworkAccessManager::onSslErrors(QNetworkReply* reply, const QList& error) { - qWarning("Ignoring SSL errors for '%s': '%s' (code %d).", qPrintable(reply->url().toString()), qPrintable(reply->errorString()), - (int) reply->error()); - reply->ignoreSslErrors(error); + qWarning("Ignoring SSL errors for '%s': '%s' (code %d).", qPrintable(reply->url().toString()), qPrintable(reply->errorString()), + (int) reply->error()); + reply->ignoreSslErrors(error); } QNetworkReply* BaseNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData) { - QNetworkRequest new_request = request; - // This rapidly speeds up loading of web sites. - // NOTE: https://en.wikipedia.org/wiki/HTTP_pipelining - new_request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); - // Setup custom user-agent. - new_request.setRawHeader(USER_AGENT_HTTP_HEADER, QString(APP_USERAGENT).toLocal8Bit()); - return QNetworkAccessManager::createRequest(op, new_request, outgoingData); + QNetworkRequest new_request = request; + + // This rapidly speeds up loading of web sites. + // NOTE: https://en.wikipedia.org/wiki/HTTP_pipelining + new_request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); + + // Setup custom user-agent. + new_request.setRawHeader(USER_AGENT_HTTP_HEADER, QString(APP_USERAGENT).toLocal8Bit()); + return QNetworkAccessManager::createRequest(op, new_request, outgoingData); } diff --git a/src/network-web/basenetworkaccessmanager.h b/src/network-web/basenetworkaccessmanager.h index 1e2b25833..d56ea657f 100755 --- a/src/network-web/basenetworkaccessmanager.h +++ b/src/network-web/basenetworkaccessmanager.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,28 +21,31 @@ #include - // This is base class for all network access managers. class BaseNetworkAccessManager : public QNetworkAccessManager { - Q_OBJECT + Q_OBJECT - public: - // Constructors and desctructors. - explicit BaseNetworkAccessManager(QObject* parent = 0); - virtual ~BaseNetworkAccessManager(); + public: - public slots: - // Loads network settings for this instance. - // NOTE: This sets up proxy settings. - virtual void loadSettings(); + // Constructors and desctructors. + explicit BaseNetworkAccessManager(QObject* parent = 0); + virtual ~BaseNetworkAccessManager(); - protected slots: - // Called when some SSL-related errors are detected. - void onSslErrors(QNetworkReply* reply, const QList& error); + public slots: - protected: - // Creates custom request. - QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData); + // Loads network settings for this instance. + // NOTE: This sets up proxy settings. + virtual void loadSettings(); + + protected slots: + + // Called when some SSL-related errors are detected. + void onSslErrors(QNetworkReply* reply, const QList& error); + + protected: + + // Creates custom request. + QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData); }; #endif // BASENETWORKACCESSMANAGER_H diff --git a/src/network-web/downloader.cpp b/src/network-web/downloader.cpp index 4982b7ec4..12c55c84a 100755 --- a/src/network-web/downloader.cpp +++ b/src/network-web/downloader.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,188 +22,190 @@ #include - Downloader::Downloader(QObject* parent) - : QObject(parent), m_activeReply(nullptr), m_downloadManager(new SilentNetworkAccessManager(this)), - m_timer(new QTimer(this)), m_customHeaders(QHash()), m_inputData(QByteArray()), - m_targetProtected(false), m_targetUsername(QString()), m_targetPassword(QString()), - m_lastOutputData(QByteArray()), m_lastOutputError(QNetworkReply::NoError), m_lastContentType(QVariant()) { - m_timer->setInterval(DOWNLOAD_TIMEOUT); - m_timer->setSingleShot(true); - connect(m_timer, &QTimer::timeout, this, &Downloader::cancel); + : QObject(parent), m_activeReply(nullptr), m_downloadManager(new SilentNetworkAccessManager(this)), + m_timer(new QTimer(this)), m_customHeaders(QHash()), m_inputData(QByteArray()), + m_targetProtected(false), m_targetUsername(QString()), m_targetPassword(QString()), + m_lastOutputData(QByteArray()), m_lastOutputError(QNetworkReply::NoError), m_lastContentType(QVariant()) { + m_timer->setInterval(DOWNLOAD_TIMEOUT); + m_timer->setSingleShot(true); + connect(m_timer, &QTimer::timeout, this, &Downloader::cancel); } -Downloader::~Downloader() { -} +Downloader::~Downloader() {} void Downloader::downloadFile(const QString& url, int timeout, bool protected_contents, const QString& username, const QString& password) { - manipulateData(url, QNetworkAccessManager::GetOperation, QByteArray(), timeout, - protected_contents, username, password); + manipulateData(url, QNetworkAccessManager::GetOperation, QByteArray(), timeout, + protected_contents, username, password); } void Downloader::uploadFile(const QString& url, const QByteArray& data, int timeout, bool protected_contents, const QString& username, const QString& password) { - manipulateData(url, QNetworkAccessManager::PostOperation, data, timeout, protected_contents, username, password); + manipulateData(url, QNetworkAccessManager::PostOperation, data, timeout, protected_contents, username, password); } void Downloader::manipulateData(const QString& url, QNetworkAccessManager::Operation operation, const QByteArray& data, int timeout, bool protected_contents, const QString& username, const QString& password) { - QNetworkRequest request; - QString non_const_url = url; - QHashIterator i(m_customHeaders); + QNetworkRequest request; + QString non_const_url = url; - while (i.hasNext()) { - i.next(); - request.setRawHeader(i.key(), i.value()); - } + QHashIterator i(m_customHeaders); - m_inputData = data; - // Set url for this request and fire it up. - m_timer->setInterval(timeout); + while (i.hasNext()) { + i.next(); + request.setRawHeader(i.key(), i.value()); + } - if (non_const_url.startsWith(URI_SCHEME_FEED)) { - qDebug("Replacing URI schemes for '%s'.", qPrintable(non_const_url)); - request.setUrl(non_const_url.replace(QRegExp(QString('^') + URI_SCHEME_FEED), QString(URI_SCHEME_HTTP))); - } - else { - request.setUrl(non_const_url); - } + m_inputData = data; - m_targetProtected = protected_contents; - m_targetUsername = username; - m_targetPassword = password; + // Set url for this request and fire it up. + m_timer->setInterval(timeout); - if (operation == QNetworkAccessManager::PostOperation) { - runPostRequest(request, m_inputData); - } - else if (operation == QNetworkAccessManager::GetOperation) { - runGetRequest(request); - } - else if (operation == QNetworkAccessManager::PutOperation) { - runPutRequest(request, m_inputData); - } - else if (operation == QNetworkAccessManager::DeleteOperation) { - runDeleteRequest(request); - } + if (non_const_url.startsWith(URI_SCHEME_FEED)) { + qDebug("Replacing URI schemes for '%s'.", qPrintable(non_const_url)); + request.setUrl(non_const_url.replace(QRegExp(QString('^') + URI_SCHEME_FEED), QString(URI_SCHEME_HTTP))); + } + else { + request.setUrl(non_const_url); + } + + m_targetProtected = protected_contents; + m_targetUsername = username; + m_targetPassword = password; + + if (operation == QNetworkAccessManager::PostOperation) { + runPostRequest(request, m_inputData); + } + else if (operation == QNetworkAccessManager::GetOperation) { + runGetRequest(request); + } + else if (operation == QNetworkAccessManager::PutOperation) { + runPutRequest(request, m_inputData); + } + else if (operation == QNetworkAccessManager::DeleteOperation) { + runDeleteRequest(request); + } } void Downloader::finished() { - QNetworkReply* reply = qobject_cast(sender()); - QNetworkAccessManager::Operation reply_operation = reply->operation(); - m_timer->stop(); - // In this phase, some part of downloading process is completed. - const QUrl redirection_url = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + QNetworkReply* reply = qobject_cast(sender()); - if (redirection_url.isValid()) { - // Communication indicates that HTTP redirection is needed. - // Setup redirection URL and download again. - QNetworkRequest request = reply->request(); + QNetworkAccessManager::Operation reply_operation = reply->operation(); + m_timer->stop(); - if (redirection_url.host().isEmpty()) { - request.setUrl(QUrl(reply->request().url().scheme() + QSL("://") + reply->request().url().host() + redirection_url.toString())); - } - else { - request.setUrl(redirection_url); - } + // In this phase, some part of downloading process is completed. + const QUrl redirection_url = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); - m_activeReply->deleteLater(); - m_activeReply = nullptr; + if (redirection_url.isValid()) { + // Communication indicates that HTTP redirection is needed. + // Setup redirection URL and download again. + QNetworkRequest request = reply->request(); - if (reply_operation == QNetworkAccessManager::GetOperation) { - runGetRequest(request); - } - else if (reply_operation == QNetworkAccessManager::PostOperation) { - runPostRequest(request, m_inputData); - } - else if (reply_operation == QNetworkAccessManager::PutOperation) { - runPutRequest(request, m_inputData); - } - else if (reply_operation == QNetworkAccessManager::DeleteOperation) { - runDeleteRequest(request); - } - } - else { - // No redirection is indicated. Final file is obtained in our "reply" object. - // Read the data into output buffer. - m_lastOutputData = reply->readAll(); - m_lastContentType = reply->header(QNetworkRequest::ContentTypeHeader); - m_lastOutputError = reply->error(); - m_activeReply->deleteLater(); - m_activeReply = nullptr; - emit completed(m_lastOutputError, m_lastOutputData); - } + if (redirection_url.host().isEmpty()) { + request.setUrl(QUrl(reply->request().url().scheme() + QSL("://") + reply->request().url().host() + redirection_url.toString())); + } + else { + request.setUrl(redirection_url); + } + + m_activeReply->deleteLater(); + m_activeReply = nullptr; + + if (reply_operation == QNetworkAccessManager::GetOperation) { + runGetRequest(request); + } + else if (reply_operation == QNetworkAccessManager::PostOperation) { + runPostRequest(request, m_inputData); + } + else if (reply_operation == QNetworkAccessManager::PutOperation) { + runPutRequest(request, m_inputData); + } + else if (reply_operation == QNetworkAccessManager::DeleteOperation) { + runDeleteRequest(request); + } + } + else { + // No redirection is indicated. Final file is obtained in our "reply" object. + // Read the data into output buffer. + m_lastOutputData = reply->readAll(); + m_lastContentType = reply->header(QNetworkRequest::ContentTypeHeader); + m_lastOutputError = reply->error(); + m_activeReply->deleteLater(); + m_activeReply = nullptr; + emit completed(m_lastOutputError, m_lastOutputData); + } } void Downloader::progressInternal(qint64 bytes_received, qint64 bytes_total) { - if (m_timer->interval() > 0) { - m_timer->start(); - } + if (m_timer->interval() > 0) { + m_timer->start(); + } - emit progress(bytes_received, bytes_total); + emit progress(bytes_received, bytes_total); } void Downloader::runDeleteRequest(const QNetworkRequest& request) { - m_timer->start(); - m_activeReply = m_downloadManager->deleteResource(request); - m_activeReply->setProperty("protected", m_targetProtected); - m_activeReply->setProperty("username", m_targetUsername); - m_activeReply->setProperty("password", m_targetPassword); - connect(m_activeReply, &QNetworkReply::downloadProgress, this, &Downloader::progressInternal); - connect(m_activeReply, &QNetworkReply::finished, this, &Downloader::finished); + m_timer->start(); + m_activeReply = m_downloadManager->deleteResource(request); + m_activeReply->setProperty("protected", m_targetProtected); + m_activeReply->setProperty("username", m_targetUsername); + m_activeReply->setProperty("password", m_targetPassword); + connect(m_activeReply, &QNetworkReply::downloadProgress, this, &Downloader::progressInternal); + connect(m_activeReply, &QNetworkReply::finished, this, &Downloader::finished); } void Downloader::runPutRequest(const QNetworkRequest& request, const QByteArray& data) { - m_timer->start(); - m_activeReply = m_downloadManager->put(request, data); - m_activeReply->setProperty("protected", m_targetProtected); - m_activeReply->setProperty("username", m_targetUsername); - m_activeReply->setProperty("password", m_targetPassword); - connect(m_activeReply, &QNetworkReply::downloadProgress, this, &Downloader::progressInternal); - connect(m_activeReply, &QNetworkReply::finished, this, &Downloader::finished); + m_timer->start(); + m_activeReply = m_downloadManager->put(request, data); + m_activeReply->setProperty("protected", m_targetProtected); + m_activeReply->setProperty("username", m_targetUsername); + m_activeReply->setProperty("password", m_targetPassword); + connect(m_activeReply, &QNetworkReply::downloadProgress, this, &Downloader::progressInternal); + connect(m_activeReply, &QNetworkReply::finished, this, &Downloader::finished); } void Downloader::runPostRequest(const QNetworkRequest& request, const QByteArray& data) { - m_timer->start(); - m_activeReply = m_downloadManager->post(request, data); - m_activeReply->setProperty("protected", m_targetProtected); - m_activeReply->setProperty("username", m_targetUsername); - m_activeReply->setProperty("password", m_targetPassword); - connect(m_activeReply, &QNetworkReply::downloadProgress, this, &Downloader::progressInternal); - connect(m_activeReply, &QNetworkReply::finished, this, &Downloader::finished); + m_timer->start(); + m_activeReply = m_downloadManager->post(request, data); + m_activeReply->setProperty("protected", m_targetProtected); + m_activeReply->setProperty("username", m_targetUsername); + m_activeReply->setProperty("password", m_targetPassword); + connect(m_activeReply, &QNetworkReply::downloadProgress, this, &Downloader::progressInternal); + connect(m_activeReply, &QNetworkReply::finished, this, &Downloader::finished); } void Downloader::runGetRequest(const QNetworkRequest& request) { - m_timer->start(); - m_activeReply = m_downloadManager->get(request); - m_activeReply->setProperty("protected", m_targetProtected); - m_activeReply->setProperty("username", m_targetUsername); - m_activeReply->setProperty("password", m_targetPassword); - connect(m_activeReply, &QNetworkReply::downloadProgress, this, &Downloader::progressInternal); - connect(m_activeReply, &QNetworkReply::finished, this, &Downloader::finished); + m_timer->start(); + m_activeReply = m_downloadManager->get(request); + m_activeReply->setProperty("protected", m_targetProtected); + m_activeReply->setProperty("username", m_targetUsername); + m_activeReply->setProperty("password", m_targetPassword); + connect(m_activeReply, &QNetworkReply::downloadProgress, this, &Downloader::progressInternal); + connect(m_activeReply, &QNetworkReply::finished, this, &Downloader::finished); } QVariant Downloader::lastContentType() const { - return m_lastContentType; + return m_lastContentType; } void Downloader::cancel() { - if (m_activeReply != nullptr) { - // Download action timed-out, too slow connection or target is not reachable. - m_activeReply->abort(); - } + if (m_activeReply != nullptr) { + // Download action timed-out, too slow connection or target is not reachable. + m_activeReply->abort(); + } } void Downloader::appendRawHeader(const QByteArray& name, const QByteArray& value) { - if (!value.isEmpty()) { - m_customHeaders.insert(name, value); - } + if (!value.isEmpty()) { + m_customHeaders.insert(name, value); + } } QNetworkReply::NetworkError Downloader::lastOutputError() const { - return m_lastOutputError; + return m_lastOutputError; } QByteArray Downloader::lastOutputData() const { - return m_lastOutputData; + return m_lastOutputData; } diff --git a/src/network-web/downloader.h b/src/network-web/downloader.h index bda3cebd7..8b2758f38 100755 --- a/src/network-web/downloader.h +++ b/src/network-web/downloader.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -25,74 +26,78 @@ #include #include - class SilentNetworkAccessManager; class QTimer; class Downloader : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit Downloader(QObject* parent = nullptr); - virtual ~Downloader(); + public: - // Access to last received full output data/error/content-type. - QByteArray lastOutputData() const; - QNetworkReply::NetworkError lastOutputError() const; - QVariant lastContentType() const; + // Constructors and destructors. + explicit Downloader(QObject* parent = nullptr); + virtual ~Downloader(); - public slots: - void cancel(); + // Access to last received full output data/error/content-type. + QByteArray lastOutputData() const; + QNetworkReply::NetworkError lastOutputError() const; + QVariant lastContentType() const; - void appendRawHeader(const QByteArray& name, const QByteArray& value); + public slots: + void cancel(); - // Performs asynchronous download of given file. Redirections are handled. - void downloadFile(const QString& url, int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false, - const QString& username = QString(), const QString& password = QString()); + void appendRawHeader(const QByteArray& name, const QByteArray& value); - void uploadFile(const QString& url, const QByteArray& data, int timeout = DOWNLOAD_TIMEOUT, - bool protected_contents = false, const QString& username = QString(), - const QString& password = QString()); + // Performs asynchronous download of given file. Redirections are handled. + void downloadFile(const QString& url, int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false, + const QString& username = QString(), const QString& password = QString()); - void manipulateData(const QString& url, QNetworkAccessManager::Operation operation, - const QByteArray& data = QByteArray(), - int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false, - const QString& username = QString(), const QString& password = QString()); + void uploadFile(const QString& url, const QByteArray& data, int timeout = DOWNLOAD_TIMEOUT, + bool protected_contents = false, const QString& username = QString(), + const QString& password = QString()); - signals: - // Emitted when new progress is known. - void progress(qint64 bytes_received, qint64 bytes_total); - void completed(QNetworkReply::NetworkError status, QByteArray contents = QByteArray()); + void manipulateData(const QString& url, QNetworkAccessManager::Operation operation, + const QByteArray& data = QByteArray(), + int timeout = DOWNLOAD_TIMEOUT, bool protected_contents = false, + const QString& username = QString(), const QString& password = QString()); - private slots: - // Called when current reply is processed. - void finished(); + signals: - // Called when progress of downloaded file changes. - void progressInternal(qint64 bytes_received, qint64 bytes_total); + // Emitted when new progress is known. + void progress(qint64 bytes_received, qint64 bytes_total); + void completed(QNetworkReply::NetworkError status, QByteArray contents = QByteArray()); - private: - void runDeleteRequest(const QNetworkRequest& request); - void runPutRequest(const QNetworkRequest& request, const QByteArray& data); - void runPostRequest(const QNetworkRequest& request, const QByteArray& data); - void runGetRequest(const QNetworkRequest& request); + private slots: - private: - QNetworkReply* m_activeReply; - QScopedPointer m_downloadManager; - QTimer* m_timer; - QHash m_customHeaders; - QByteArray m_inputData; + // Called when current reply is processed. + void finished(); - bool m_targetProtected; - QString m_targetUsername; - QString m_targetPassword; + // Called when progress of downloaded file changes. + void progressInternal(qint64 bytes_received, qint64 bytes_total); - // Response data. - QByteArray m_lastOutputData; - QNetworkReply::NetworkError m_lastOutputError; - QVariant m_lastContentType; + private: + void runDeleteRequest(const QNetworkRequest& request); + void runPutRequest(const QNetworkRequest& request, const QByteArray& data); + void runPostRequest(const QNetworkRequest& request, const QByteArray& data); + void runGetRequest(const QNetworkRequest& request); + + private: + QNetworkReply* m_activeReply; + + QScopedPointer m_downloadManager; + QTimer* m_timer; + + QHash m_customHeaders; + QByteArray m_inputData; + bool m_targetProtected; + QString m_targetUsername; + QString m_targetPassword; + + // Response data. + QByteArray m_lastOutputData; + + QNetworkReply::NetworkError m_lastOutputError; + QVariant m_lastContentType; }; #endif // DOWNLOADER_H diff --git a/src/network-web/downloadmanager.cpp b/src/network-web/downloadmanager.cpp index 1f1618f81..8e5836cf0 100755 --- a/src/network-web/downloadmanager.cpp +++ b/src/network-web/downloadmanager.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,785 +18,798 @@ #include "network-web/downloadmanager.h" -#include "miscellaneous/autosaver.h" -#include "miscellaneous/application.h" -#include "miscellaneous/settings.h" #include "gui/dialogs/formmain.h" -#include "gui/tabwidget.h" #include "gui/messagebox.h" +#include "gui/tabwidget.h" +#include "miscellaneous/application.h" +#include "miscellaneous/autosaver.h" +#include "miscellaneous/settings.h" #include "network-web/silentnetworkaccessmanager.h" #include +#include #include #include #include #include #include +#include #include #include -#include #include -#include - DownloadItem::DownloadItem(QNetworkReply* reply, QWidget* parent) : QWidget(parent), - m_ui(new Ui::DownloadItem), m_reply(reply), - m_bytesReceived(0), m_requestFileName(false), m_startedSaving(false), m_finishedDownloading(false), - m_gettingFileName(false), m_canceledFileSelect(false) { - m_ui->setupUi(this); - m_ui->m_btnTryAgain->hide(); - m_requestFileName = qApp->settings()->value(GROUP(Downloads), SETTING(Downloads::AlwaysPromptForFilename)).toBool(); + m_ui(new Ui::DownloadItem), m_reply(reply), + m_bytesReceived(0), m_requestFileName(false), m_startedSaving(false), m_finishedDownloading(false), + m_gettingFileName(false), m_canceledFileSelect(false) { + m_ui->setupUi(this); + m_ui->m_btnTryAgain->hide(); + m_requestFileName = qApp->settings()->value(GROUP(Downloads), SETTING(Downloads::AlwaysPromptForFilename)).toBool(); connect(m_ui->m_btnStopDownload, &QToolButton::clicked, this, &DownloadItem::stop); - connect(m_ui->m_btnOpenFile, &QToolButton::clicked, this, &DownloadItem::openFile); - connect(m_ui->m_btnTryAgain, &QToolButton::clicked, this, &DownloadItem::tryAgain); - connect(m_ui->m_btnOpenFolder, &QToolButton::clicked, this, &DownloadItem::openFolder); - init(); + connect(m_ui->m_btnOpenFile, &QToolButton::clicked, this, &DownloadItem::openFile); + connect(m_ui->m_btnTryAgain, &QToolButton::clicked, this, &DownloadItem::tryAgain); + connect(m_ui->m_btnOpenFolder, &QToolButton::clicked, this, &DownloadItem::openFolder); + init(); } DownloadItem::~DownloadItem() { - delete m_ui; + delete m_ui; } void DownloadItem::init() { - if (m_reply == nullptr) { - return; - } + if (m_reply == nullptr) { + return; + } - m_startedSaving = false; - m_finishedDownloading = false; - m_ui->m_btnOpenFile->setEnabled(false); - m_ui->m_btnOpenFolder->setEnabled(false); - m_url = m_reply->url(); - m_reply->setParent(this); + m_startedSaving = false; + m_finishedDownloading = false; + m_ui->m_btnOpenFile->setEnabled(false); + m_ui->m_btnOpenFolder->setEnabled(false); + m_url = m_reply->url(); + m_reply->setParent(this); connect(m_reply, &QNetworkReply::readyRead, this, &DownloadItem::downloadReadyRead); - connect(m_reply, static_cast(&QNetworkReply::error), this, &DownloadItem::error); - connect(m_reply, &QNetworkReply::downloadProgress, this, &DownloadItem::downloadProgress); - connect(m_reply, &QNetworkReply::metaDataChanged, this, &DownloadItem::metaDataChanged); - connect(m_reply, &QNetworkReply::finished, this, &DownloadItem::finished); + connect(m_reply, static_cast(&QNetworkReply::error), this, &DownloadItem::error); + connect(m_reply, &QNetworkReply::downloadProgress, this, &DownloadItem::downloadProgress); + connect(m_reply, &QNetworkReply::metaDataChanged, this, &DownloadItem::metaDataChanged); + connect(m_reply, &QNetworkReply::finished, this, &DownloadItem::finished); // Reset info. - m_ui->m_lblInfoDownload->clear(); - m_ui->m_progressDownload->setValue(0); - getFileName(); + m_ui->m_lblInfoDownload->clear(); + m_ui->m_progressDownload->setValue(0); + getFileName(); // Start timer for the download estimation. - m_downloadTime.start(); + m_downloadTime.start(); - if (m_reply->error() != QNetworkReply::NoError) { - error(m_reply->error()); - finished(); - } + if (m_reply->error() != QNetworkReply::NoError) { + error(m_reply->error()); + finished(); + } } void DownloadItem::getFileName() { - if (m_gettingFileName) { - return; - } + if (m_gettingFileName) { + return; + } - const QString download_directory = qApp->downloadManager()->downloadDirectory(); - QString chosen_filename = saveFileName(download_directory); - const QString filename_for_prompt = qApp->settings()->value(GROUP(Downloads), SETTING(Downloads::TargetExplicitDirectory)).toString() + - QDir::separator() + - QFileInfo(chosen_filename).fileName(); + const QString download_directory = qApp->downloadManager()->downloadDirectory(); + QString chosen_filename = saveFileName(download_directory); + const QString filename_for_prompt = qApp->settings()->value(GROUP(Downloads), SETTING(Downloads::TargetExplicitDirectory)).toString() + + QDir::separator() + + QFileInfo(chosen_filename).fileName(); - if (m_requestFileName) { - // User must provide the path where he wants to save downloaded file in. - m_gettingFileName = true; - chosen_filename = QFileDialog::getSaveFileName(this, tr("Select destination for downloaded file"), filename_for_prompt); - m_gettingFileName = false; + if (m_requestFileName) { + // User must provide the path where he wants to save downloaded file in. + m_gettingFileName = true; + chosen_filename = QFileDialog::getSaveFileName(this, tr("Select destination for downloaded file"), filename_for_prompt); + m_gettingFileName = false; - if (chosen_filename.isEmpty()) { - stop(); - m_ui->m_progressDownload->setVisible(false); - m_ui->m_lblLocalFilename->setText(tr("Selection of local file cancelled.")); - m_canceledFileSelect = true; - return; - } + if (chosen_filename.isEmpty()) { + stop(); + m_ui->m_progressDownload->setVisible(false); + m_ui->m_lblLocalFilename->setText(tr("Selection of local file cancelled.")); + m_canceledFileSelect = true; + return; + } - const QFileInfo file_info = QFileInfo(chosen_filename); - qApp->settings()->setValue(GROUP(Downloads), Downloads::TargetExplicitDirectory, - QDir::toNativeSeparators(QFileInfo(chosen_filename).absolutePath())); - qApp->downloadManager()->setDownloadDirectory(file_info.absoluteDir().absolutePath()); - } + const QFileInfo file_info = QFileInfo(chosen_filename); - m_output.setFileName(chosen_filename); + qApp->settings()->setValue(GROUP(Downloads), Downloads::TargetExplicitDirectory, + QDir::toNativeSeparators(QFileInfo(chosen_filename).absolutePath())); + qApp->downloadManager()->setDownloadDirectory(file_info.absoluteDir().absolutePath()); + } + + m_output.setFileName(chosen_filename); // Check file path for saving. - const QDir save_dir = QFileInfo(m_output.fileName()).dir(); + const QDir save_dir = QFileInfo(m_output.fileName()).dir(); - if (!save_dir.exists() && !save_dir.mkpath(save_dir.absolutePath())) { - stop(); - m_ui->m_progressDownload->setVisible(false); - m_ui->m_lblInfoDownload->setText(tr("Download directory couldn't be created")); - return; - } + if (!save_dir.exists() && !save_dir.mkpath(save_dir.absolutePath())) { + stop(); + m_ui->m_progressDownload->setVisible(false); + m_ui->m_lblInfoDownload->setText(tr("Download directory couldn't be created")); + return; + } - updateInfoAndUrlLabel(); + updateInfoAndUrlLabel(); - if (m_requestFileName) { - downloadReadyRead(); - } + if (m_requestFileName) { + downloadReadyRead(); + } } QString DownloadItem::saveFileName(const QString& directory) const { - QString path; + QString path; - if (m_reply->hasRawHeader("Content-Disposition")) { - const QString value = QLatin1String(m_reply->rawHeader("Content-Disposition")); - const int pos = value.indexOf(QL1S("filename=")); + if (m_reply->hasRawHeader("Content-Disposition")) { + const QString value = QLatin1String(m_reply->rawHeader("Content-Disposition")); + const int pos = value.indexOf(QL1S("filename=")); - if (pos != -1) { - QString name = value.mid(pos + 9); + if (pos != -1) { + QString name = value.mid(pos + 9); - if (name.startsWith(QL1C('"')) && name.endsWith(QL1C('"'))) { - name = name.mid(1, name.size() - 2); - } + if (name.startsWith(QL1C('"')) && name.endsWith(QL1C('"'))) { + name = name.mid(1, name.size() - 2); + } - path = name; - } - } + path = name; + } + } - if (path.isEmpty()) { - path = m_url.path(); - } + if (path.isEmpty()) { + path = m_url.path(); + } - const QFileInfo info(path); - QString base_name = info.completeBaseName(); - QString end_name = info.suffix(); + const QFileInfo info(path); + QString base_name = info.completeBaseName(); + QString end_name = info.suffix(); - if (base_name.isEmpty()) { - base_name = QSL("unnamed_download"); - } + if (base_name.isEmpty()) { + base_name = QSL("unnamed_download"); + } - if (!end_name.isEmpty()) { - end_name = QL1C('.') + end_name; - } + if (!end_name.isEmpty()) { + end_name = QL1C('.') + end_name; + } - QString name = directory + base_name + end_name; + QString name = directory + base_name + end_name; - if (!m_requestFileName && QFile::exists(name)) { - int i = 1; + if (!m_requestFileName && QFile::exists(name)) { + int i = 1; - do { - name = directory + base_name + QL1C('-') + QString::number(i++) + end_name; - } - while (QFile::exists(name)); - } + do { + name = directory + base_name + QL1C('-') + QString::number(i++) + end_name; + } + while (QFile::exists(name)); + } - return name; + return name; } void DownloadItem::stop() { - setUpdatesEnabled(false); - m_ui->m_btnStopDownload->setEnabled(false); - m_ui->m_btnStopDownload->hide(); - m_ui->m_btnTryAgain->setEnabled(true); - m_ui->m_btnTryAgain->show(); - setUpdatesEnabled(true); - m_reply->abort(); - emit downloadFinished(); + setUpdatesEnabled(false); + m_ui->m_btnStopDownload->setEnabled(false); + m_ui->m_btnStopDownload->hide(); + m_ui->m_btnTryAgain->setEnabled(true); + m_ui->m_btnTryAgain->show(); + setUpdatesEnabled(true); + m_reply->abort(); + emit downloadFinished(); } void DownloadItem::openFile() { - if (!QDesktopServices::openUrl(QUrl::fromLocalFile(m_output.fileName()))) { - qApp->showGuiMessage(tr("Cannot open file"), tr("Cannot open output file. Open it manually."), - QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - } + if (!QDesktopServices::openUrl(QUrl::fromLocalFile(m_output.fileName()))) { + qApp->showGuiMessage(tr("Cannot open file"), tr("Cannot open output file. Open it manually."), + QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); + } } void DownloadItem::openFolder() { - if (m_output.exists()) { - if (!SystemFactory::openFolderFile(m_output.fileName())) { - MessageBox::show(this, - QMessageBox::Warning, - tr("Cannot open directory"), - tr("Cannot open output directory. Open it manually."), - QString(), - m_output.fileName()); - } - } + if (m_output.exists()) { + if (!SystemFactory::openFolderFile(m_output.fileName())) { + MessageBox::show(this, + QMessageBox::Warning, + tr("Cannot open directory"), + tr("Cannot open output directory. Open it manually."), + QString(), + m_output.fileName()); + } + } } void DownloadItem::tryAgain() { - if (!m_ui->m_btnTryAgain->isEnabled()) { - return; - } + if (!m_ui->m_btnTryAgain->isEnabled()) { + return; + } - m_ui->m_btnTryAgain->setEnabled(false); - m_ui->m_btnTryAgain->setVisible(false); - m_ui->m_btnStopDownload->setEnabled(true); - m_ui->m_btnStopDownload->setVisible(true); - m_ui->m_progressDownload->setVisible(true); - QNetworkReply* new_download = qApp->downloadManager()->networkManager()->get(QNetworkRequest(m_url)); + m_ui->m_btnTryAgain->setEnabled(false); + m_ui->m_btnTryAgain->setVisible(false); + m_ui->m_btnStopDownload->setEnabled(true); + m_ui->m_btnStopDownload->setVisible(true); + m_ui->m_progressDownload->setVisible(true); + QNetworkReply* new_download = qApp->downloadManager()->networkManager()->get(QNetworkRequest(m_url)); - if (m_reply) { - m_reply->deleteLater(); - } + if (m_reply) { + m_reply->deleteLater(); + } - if (m_output.exists()) { - m_output.remove(); - } + if (m_output.exists()) { + m_output.remove(); + } - m_reply = new_download; - init(); - emit statusChanged(); + m_reply = new_download; + init(); + emit statusChanged(); } void DownloadItem::downloadReadyRead() { - if (m_requestFileName && m_output.fileName().isEmpty()) { - return; - } + if (m_requestFileName && m_output.fileName().isEmpty()) { + return; + } - if (!m_output.isOpen()) { - if (!m_requestFileName) { - getFileName(); - } + if (!m_output.isOpen()) { + if (!m_requestFileName) { + getFileName(); + } - if (!m_output.open(QIODevice::WriteOnly)) { - m_ui->m_lblInfoDownload->setText(tr("Error opening output file: %1").arg(m_output.errorString())); - stop(); - emit statusChanged(); - return; - } + if (!m_output.open(QIODevice::WriteOnly)) { + m_ui->m_lblInfoDownload->setText(tr("Error opening output file: %1").arg(m_output.errorString())); + stop(); + emit statusChanged(); - emit statusChanged(); - } + return; + } - if (-1 == m_output.write(m_reply->readAll())) { - m_ui->m_lblInfoDownload->setText(tr("Error when saving file: %1").arg(m_output.errorString())); - m_ui->m_btnStopDownload->click(); - } - else { - m_startedSaving = true; + emit statusChanged(); + } - if (m_finishedDownloading) { - finished(); - } - } + if (-1 == m_output.write(m_reply->readAll())) { + m_ui->m_lblInfoDownload->setText(tr("Error when saving file: %1").arg(m_output.errorString())); + m_ui->m_btnStopDownload->click(); + } + else { + m_startedSaving = true; + + if (m_finishedDownloading) { + finished(); + } + } } void DownloadItem::error(QNetworkReply::NetworkError code) { - Q_UNUSED(code) + Q_UNUSED(code) m_ui->m_lblInfoDownload->setText(tr("Error: %1").arg(m_reply->errorString())); - m_ui->m_btnTryAgain->setEnabled(true); - m_ui->m_btnTryAgain->setVisible(true); - emit downloadFinished(); + m_ui->m_btnTryAgain->setEnabled(true); + m_ui->m_btnTryAgain->setVisible(true); + emit downloadFinished(); } void DownloadItem::metaDataChanged() { - QVariant locationHeader = m_reply->header(QNetworkRequest::LocationHeader); + QVariant locationHeader = m_reply->header(QNetworkRequest::LocationHeader); - if (locationHeader.isValid()) { - m_url = locationHeader.toUrl(); - m_reply->deleteLater(); - m_reply = qApp->downloadManager()->networkManager()->get(QNetworkRequest(m_url)); - init(); - return; - } + if (locationHeader.isValid()) { + m_url = locationHeader.toUrl(); + m_reply->deleteLater(); + m_reply = qApp->downloadManager()->networkManager()->get(QNetworkRequest(m_url)); + init(); + return; + } } void DownloadItem::downloadProgress(qint64 bytes_received, qint64 bytes_total) { - QTime now = QTime::currentTime(); + QTime now = QTime::currentTime(); - if (m_lastProgressTime.isValid() && m_lastProgressTime.msecsTo(now) < 25) { - return; - } + if (m_lastProgressTime.isValid() && m_lastProgressTime.msecsTo(now) < 25) { + return; + } - m_lastProgressTime = now; - m_bytesReceived = bytes_received; - qint64 currentValue = 0; - qint64 totalValue = 0; + m_lastProgressTime = now; + m_bytesReceived = bytes_received; + qint64 currentValue = 0; + qint64 totalValue = 0; - if (bytes_total > 0) { - currentValue = bytes_received * 100 / bytes_total; - totalValue = 100; - } + if (bytes_total > 0) { + currentValue = bytes_received * 100 / bytes_total; + totalValue = 100; + } - m_ui->m_progressDownload->setValue(currentValue); - m_ui->m_progressDownload->setMaximum(totalValue); - emit progress(currentValue, totalValue); - updateDownloadInfoLabel(); + m_ui->m_progressDownload->setValue(currentValue); + m_ui->m_progressDownload->setMaximum(totalValue); + emit progress(currentValue, totalValue); + + updateDownloadInfoLabel(); } qint64 DownloadItem::bytesTotal() const { - return m_reply->header(QNetworkRequest::ContentLengthHeader).toULongLong(); + return m_reply->header(QNetworkRequest::ContentLengthHeader).toULongLong(); } qint64 DownloadItem::bytesReceived() const { - return m_bytesReceived; + return m_bytesReceived; } double DownloadItem::remainingTime() const { - if (!downloading()) { - return -1.0; - } + if (!downloading()) { + return -1.0; + } - double time_remaining = ((double)(bytesTotal() - bytesReceived())) / currentSpeed(); + double time_remaining = ((double)(bytesTotal() - bytesReceived())) / currentSpeed(); - // When downloading the ETA should never be 0. - if ((int) time_remaining == 0) { - time_remaining = 1.0; - } + // When downloading the ETA should never be 0. + if ((int) time_remaining == 0) { + time_remaining = 1.0; + } - return time_remaining; + return time_remaining; } double DownloadItem::currentSpeed() const { - if (!downloading()) { - return -1.0; - } - else { - return m_bytesReceived * 1000.0 / m_downloadTime.elapsed(); - } + if (!downloading()) { + return -1.0; + } + else { + return m_bytesReceived * 1000.0 / m_downloadTime.elapsed(); + } } void DownloadItem::updateDownloadInfoLabel() { - if (m_reply->error() != QNetworkReply::NoError) { - return; - } + if (m_reply->error() != QNetworkReply::NoError) { + return; + } - const qint64 bytes_total = m_reply->header(QNetworkRequest::ContentLengthHeader).toULongLong(); - bool running = !downloadedSuccessfully(); - double speed = currentSpeed(); - double time_remaining = remainingTime(); - QString info; + const qint64 bytes_total = m_reply->header(QNetworkRequest::ContentLengthHeader).toULongLong(); + bool running = !downloadedSuccessfully(); + double speed = currentSpeed(); + double time_remaining = remainingTime(); + QString info; - if (running) { - QString remaining; + if (running) { + QString remaining; - if (bytes_total != 0) { - remaining = DownloadManager::timeString(time_remaining); - } + if (bytes_total != 0) { + remaining = DownloadManager::timeString(time_remaining); + } - info = QString(tr("%1 of %2 (%3 per second) - %4")).arg(DownloadManager::dataString(m_bytesReceived), - bytes_total == 0 ? QSL("?") : DownloadManager::dataString(bytes_total), - DownloadManager::dataString((int)speed), - remaining); - } - else { - if (m_bytesReceived == bytes_total) { - info = DownloadManager::dataString(m_output.size()); - } - else { - info = tr("%1 of %2 - download completed").arg(DownloadManager::dataString(m_bytesReceived), - DownloadManager::dataString(m_bytesReceived)); - } - } + info = QString(tr("%1 of %2 (%3 per second) - %4")).arg(DownloadManager::dataString(m_bytesReceived), + bytes_total == 0 ? QSL("?") : DownloadManager::dataString(bytes_total), + DownloadManager::dataString((int)speed), + remaining); + } + else { + if (m_bytesReceived == bytes_total) { + info = DownloadManager::dataString(m_output.size()); + } + else { + info = tr("%1 of %2 - download completed").arg(DownloadManager::dataString(m_bytesReceived), + DownloadManager::dataString(m_bytesReceived)); + } + } - m_ui->m_lblInfoDownload->setText(info); + m_ui->m_lblInfoDownload->setText(info); } bool DownloadItem::downloading() const { - return (m_ui->m_progressDownload->isVisible()); + return (m_ui->m_progressDownload->isVisible()); } bool DownloadItem::downloadedSuccessfully() const { - return (m_ui->m_btnStopDownload->isHidden() && m_ui->m_btnTryAgain->isHidden()); + return (m_ui->m_btnStopDownload->isHidden() && m_ui->m_btnTryAgain->isHidden()); } void DownloadItem::finished() { - m_finishedDownloading = true; + m_finishedDownloading = true; - if (!m_startedSaving) { - return; - } + if (!m_startedSaving) { + return; + } - m_ui->m_progressDownload->hide(); - m_ui->m_btnStopDownload->setEnabled(false); - m_ui->m_btnStopDownload->hide(); - m_ui->m_btnOpenFile->setEnabled(true); - m_ui->m_btnOpenFolder->setEnabled(true); - m_output.close(); - updateDownloadInfoLabel(); - emit statusChanged(); - emit downloadFinished(); + m_ui->m_progressDownload->hide(); + m_ui->m_btnStopDownload->setEnabled(false); + m_ui->m_btnStopDownload->hide(); + m_ui->m_btnOpenFile->setEnabled(true); + m_ui->m_btnOpenFolder->setEnabled(true); + m_output.close(); + updateDownloadInfoLabel(); + emit statusChanged(); + emit downloadFinished(); - if (downloadedSuccessfully()) { - qApp->showGuiMessage(tr("Download finished"), - tr("File '%1' is downloaded.\nClick here to open parent directory.").arg(QDir::toNativeSeparators(m_output.fileName())), - QSystemTrayIcon::Information, 0, false, [this] { - openFolder(); - }); - } + if (downloadedSuccessfully()) { + qApp->showGuiMessage(tr("Download finished"), + tr("File '%1' is downloaded.\nClick here to open parent directory.").arg(QDir::toNativeSeparators( + m_output.fileName())), + QSystemTrayIcon::Information, + 0, + false, + [this] { + openFolder(); + }); + } } void DownloadItem::updateInfoAndUrlLabel() { - m_ui->m_lblRemoteFilename->setText(tr("URL: %1").arg(m_url.toString())); - m_ui->m_lblLocalFilename->setText(tr("Local file: %1").arg(QDir::toNativeSeparators(m_output.fileName()))); + m_ui->m_lblRemoteFilename->setText(tr("URL: %1").arg(m_url.toString())); + m_ui->m_lblLocalFilename->setText(tr("Local file: %1").arg(QDir::toNativeSeparators(m_output.fileName()))); } DownloadManager::DownloadManager(QWidget* parent) : TabContent(parent), m_ui(new Ui::DownloadManager), - m_autoSaver(new AutoSaver(this)), m_model(new DownloadModel(this)), - m_networkManager(SilentNetworkAccessManager::instance()), m_iconProvider(nullptr), m_removePolicy(Never) { - m_ui->setupUi(this); - m_ui->m_viewDownloads->setShowGrid(false); - m_ui->m_viewDownloads->verticalHeader()->hide(); - m_ui->m_viewDownloads->horizontalHeader()->hide(); - m_ui->m_viewDownloads->setAlternatingRowColors(true); - m_ui->m_viewDownloads->horizontalHeader()->setStretchLastSection(true); - m_ui->m_viewDownloads->setModel(m_model); - setDownloadDirectory(qApp->settings()->value(GROUP(Downloads), SETTING(Downloads::TargetDirectory)).toString()); - connect(m_ui->m_btnCleanup, &QPushButton::clicked, this, &DownloadManager::cleanup); - load(); + m_autoSaver(new AutoSaver(this)), m_model(new DownloadModel(this)), + m_networkManager(SilentNetworkAccessManager::instance()), m_iconProvider(nullptr), m_removePolicy(Never) { + m_ui->setupUi(this); + m_ui->m_viewDownloads->setShowGrid(false); + m_ui->m_viewDownloads->verticalHeader()->hide(); + m_ui->m_viewDownloads->horizontalHeader()->hide(); + m_ui->m_viewDownloads->setAlternatingRowColors(true); + m_ui->m_viewDownloads->horizontalHeader()->setStretchLastSection(true); + m_ui->m_viewDownloads->setModel(m_model); + setDownloadDirectory(qApp->settings()->value(GROUP(Downloads), SETTING(Downloads::TargetDirectory)).toString()); + connect(m_ui->m_btnCleanup, &QPushButton::clicked, this, &DownloadManager::cleanup); + load(); } DownloadManager::~DownloadManager() { - m_autoSaver->changeOccurred(); - m_autoSaver->saveIfNeccessary(); - qDebug("Destroying DownloadManager instance."); + m_autoSaver->changeOccurred(); + m_autoSaver->saveIfNeccessary(); + qDebug("Destroying DownloadManager instance."); } int DownloadManager::activeDownloads() const { - int count = 0; + int count = 0; - foreach (const DownloadItem* download, m_downloads) { - if (download->downloading()) { - count++; - } - } + foreach (const DownloadItem* download, m_downloads) { + if (download->downloading()) { + count++; + } + } - return count; + return count; } int DownloadManager::downloadProgress() const { - qint64 bytes_total = 0; - qint64 bytes_received = 0; + qint64 bytes_total = 0; + qint64 bytes_received = 0; - foreach (const DownloadItem* download, m_downloads) { - if (download->downloading()) { - bytes_total += download->bytesTotal(); - bytes_received += download->bytesReceived(); - } - } + foreach (const DownloadItem* download, m_downloads) { + if (download->downloading()) { + bytes_total += download->bytesTotal(); + bytes_received += download->bytesReceived(); + } + } - if (bytes_total <= 0) { - return -1; - } - else { - return (bytes_received * 100.0) / bytes_total; - } + if (bytes_total <= 0) { + return -1; + } + else { + return (bytes_received * 100.0) / bytes_total; + } } void DownloadManager::download(const QNetworkRequest& request) { - if (!request.url().isEmpty()) { - handleUnsupportedContent(m_networkManager->get(request)); - } + if (!request.url().isEmpty()) { + handleUnsupportedContent(m_networkManager->get(request)); + } } void DownloadManager::download(const QUrl& url) { - download(QNetworkRequest(url)); + download(QNetworkRequest(url)); } void DownloadManager::handleUnsupportedContent(QNetworkReply* reply) { - if (reply == nullptr || reply->url().isEmpty()) { - return; - } + if (reply == nullptr || reply->url().isEmpty()) { + return; + } - const QVariant header = reply->header(QNetworkRequest::ContentLengthHeader); - bool ok; - const int size = header.toInt(&ok); + const QVariant header = reply->header(QNetworkRequest::ContentLengthHeader); + bool ok; + const int size = header.toInt(&ok); - if (ok && size == 0) { - return; - } + if (ok && size == 0) { + return; + } - DownloadItem* item = new DownloadItem(reply, this); - addItem(item); + DownloadItem* item = new DownloadItem(reply, this); - if (!item->m_canceledFileSelect && qApp->settings()->value(GROUP(Downloads), - SETTING(Downloads::ShowDownloadsWhenNewDownloadStarts)).toBool()) { - qApp->mainForm()->tabWidget()->showDownloadManager(); - } + addItem(item); + + if (!item->m_canceledFileSelect && qApp->settings()->value(GROUP(Downloads), + SETTING(Downloads::ShowDownloadsWhenNewDownloadStarts)).toBool()) { + qApp->mainForm()->tabWidget()->showDownloadManager(); + } } void DownloadManager::addItem(DownloadItem* item) { - connect(item, &DownloadItem::statusChanged, this, static_cast(&DownloadManager::updateRow)); - connect(item, &DownloadItem::progress, this, &DownloadManager::itemProgress); - connect(item, &DownloadItem::downloadFinished, this, &DownloadManager::itemFinished); + connect(item, &DownloadItem::statusChanged, this, static_cast(&DownloadManager::updateRow)); + connect(item, &DownloadItem::progress, this, &DownloadManager::itemProgress); + connect(item, &DownloadItem::downloadFinished, this, &DownloadManager::itemFinished); const int row = m_downloads.count(); - m_model->beginInsertRows(QModelIndex(), row, row); - m_downloads.append(item); - m_model->endInsertRows(); - m_ui->m_viewDownloads->setIndexWidget(m_model->index(row, 0), item); - QIcon icon = style()->standardIcon(QStyle::SP_FileIcon); - item->m_ui->m_lblFileIcon->setPixmap(icon.pixmap(DOWNLOADER_ICON_SIZE, DOWNLOADER_ICON_SIZE)); - m_ui->m_viewDownloads->setRowHeight(row, item->sizeHint().height()); + + m_model->beginInsertRows(QModelIndex(), row, row); + m_downloads.append(item); + m_model->endInsertRows(); + m_ui->m_viewDownloads->setIndexWidget(m_model->index(row, 0), item); + QIcon icon = style()->standardIcon(QStyle::SP_FileIcon); + + item->m_ui->m_lblFileIcon->setPixmap(icon.pixmap(DOWNLOADER_ICON_SIZE, DOWNLOADER_ICON_SIZE)); + m_ui->m_viewDownloads->setRowHeight(row, item->sizeHint().height()); // Just in case of download finishes before it is actually added. - updateRow(item); + updateRow(item); } QNetworkAccessManager* DownloadManager::networkManager() const { - return m_networkManager; + return m_networkManager; } int DownloadManager::totalDownloads() const { - return m_downloads.size(); + return m_downloads.size(); } void DownloadManager::itemFinished() { - emit downloadFinished(); + emit downloadFinished(); } void DownloadManager::updateRow() { - if (DownloadItem* item = qobject_cast(sender())) { - updateRow(item); - } + if (DownloadItem* item = qobject_cast(sender())) { + updateRow(item); + } } void DownloadManager::itemProgress() { - int progress = downloadProgress(); + int progress = downloadProgress(); - if (progress < 0) { - emit downloadFinished(); - } - else { - emit downloadProgressed(progress, tr("Downloading %n file(s)...", "", activeDownloads())); - } + if (progress < 0) { + emit downloadFinished(); + } + else { + emit downloadProgressed(progress, tr("Downloading %n file(s)...", "", activeDownloads())); + } } void DownloadManager::updateRow(DownloadItem* item) { - const int row = m_downloads.indexOf(item); + const int row = m_downloads.indexOf(item); - if (row == -1) { - return; - } + if (row == -1) { + return; + } - if (m_iconProvider.isNull()) { - m_iconProvider.reset(new QFileIconProvider()); - } + if (m_iconProvider.isNull()) { + m_iconProvider.reset(new QFileIconProvider()); + } - QIcon icon = m_iconProvider->icon(item->m_output.fileName()); + QIcon icon = m_iconProvider->icon(item->m_output.fileName()); - if (icon.isNull()) { - icon = style()->standardIcon(QStyle::SP_FileIcon); - } + if (icon.isNull()) { + icon = style()->standardIcon(QStyle::SP_FileIcon); + } - item->m_ui->m_lblFileIcon->setPixmap(icon.pixmap(DOWNLOADER_ICON_SIZE, DOWNLOADER_ICON_SIZE)); - int old_height = m_ui->m_viewDownloads->rowHeight(row); - m_ui->m_viewDownloads->setRowHeight(row, qMax(old_height, item->minimumSizeHint().height())); + item->m_ui->m_lblFileIcon->setPixmap(icon.pixmap(DOWNLOADER_ICON_SIZE, DOWNLOADER_ICON_SIZE)); + int old_height = m_ui->m_viewDownloads->rowHeight(row); + + m_ui->m_viewDownloads->setRowHeight(row, qMax(old_height, item->minimumSizeHint().height())); // Remove the item if: - // a) It is not downloading and private browsing is enabled. - // OR - // b) Item is already downloaded and it should be remove from downloader list. - bool remove = item->downloadedSuccessfully() && removePolicy() == DownloadManager::OnSuccessfullDownload; + // a) It is not downloading and private browsing is enabled. + // OR + // b) Item is already downloaded and it should be remove from downloader list. + bool remove = item->downloadedSuccessfully() && removePolicy() == DownloadManager::OnSuccessfullDownload; - if (remove) { - m_model->removeRow(row); - } + if (remove) { + m_model->removeRow(row); + } - m_ui->m_btnCleanup->setEnabled(m_downloads.count() - activeDownloads() > 0); + m_ui->m_btnCleanup->setEnabled(m_downloads.count() - activeDownloads() > 0); } DownloadManager::RemovePolicy DownloadManager::removePolicy() const { - return m_removePolicy; + return m_removePolicy; } void DownloadManager::setRemovePolicy(RemovePolicy policy) { - if (policy != m_removePolicy) { - m_removePolicy = policy; - m_autoSaver->changeOccurred(); - } + if (policy != m_removePolicy) { + m_removePolicy = policy; + m_autoSaver->changeOccurred(); + } } void DownloadManager::save() const { - if (m_removePolicy == OnExit) { - // No saving. - return; - } + if (m_removePolicy == OnExit) { + // No saving. + return; + } - Settings* settings = qApp->settings(); - QString key; - settings->setValue(GROUP(Downloads), Downloads::RemovePolicy, (int) removePolicy()); + Settings* settings = qApp->settings(); + QString key; - // Save all download items. - for (int i = 0; i < m_downloads.count(); i++) { - settings->setValue(GROUP(Downloads), QString(Downloads::ItemUrl).arg(i), m_downloads[i]->m_url); - settings->setValue(GROUP(Downloads), QString(Downloads::ItemLocation).arg(i), QFileInfo(m_downloads[i]->m_output).filePath()); - settings->setValue(GROUP(Downloads), QString(Downloads::ItemDone).arg(i), m_downloads[i]->downloadedSuccessfully()); - } + settings->setValue(GROUP(Downloads), Downloads::RemovePolicy, (int) removePolicy()); - // Remove all redundant saved download items. - int i = m_downloads.size(); + // Save all download items. + for (int i = 0; i < m_downloads.count(); i++) { + settings->setValue(GROUP(Downloads), QString(Downloads::ItemUrl).arg(i), m_downloads[i]->m_url); + settings->setValue(GROUP(Downloads), QString(Downloads::ItemLocation).arg(i), QFileInfo(m_downloads[i]->m_output).filePath()); + settings->setValue(GROUP(Downloads), QString(Downloads::ItemDone).arg(i), m_downloads[i]->downloadedSuccessfully()); + } - while (!(key = QString(Downloads::ItemUrl).arg(i)).isEmpty() && settings->contains(GROUP(Downloads), key)) { - settings->remove(GROUP(Downloads), key); - settings->remove(GROUP(Downloads), QString(Downloads::ItemLocation).arg(i)); - settings->remove(GROUP(Downloads), QString(Downloads::ItemDone).arg(i)); - i++; - } + // Remove all redundant saved download items. + int i = m_downloads.size(); + + while (!(key = QString(Downloads::ItemUrl).arg(i)).isEmpty() && settings->contains(GROUP(Downloads), key)) { + settings->remove(GROUP(Downloads), key); + settings->remove(GROUP(Downloads), QString(Downloads::ItemLocation).arg(i)); + settings->remove(GROUP(Downloads), QString(Downloads::ItemDone).arg(i)); + i++; + } } void DownloadManager::load() { - const Settings* settings = qApp->settings(); - int i = 0; - // Restore the policy. - m_removePolicy = static_cast(settings->value(GROUP(Downloads), SETTING(Downloads::RemovePolicy)).toInt()); + const Settings* settings = qApp->settings(); + int i = 0; - // Restore downloads. - while (settings->contains(GROUP(Downloads), QString(Downloads::ItemUrl).arg(i))) { - QUrl url = settings->value(GROUP(Downloads), QString(Downloads::ItemUrl).arg(i)).toUrl(); - QString file_name = settings->value(GROUP(Downloads), QString(Downloads::ItemLocation).arg(i)).toString(); - bool done = settings->value(GROUP(Downloads), QString(Downloads::ItemDone).arg(i), true).toBool(); + // Restore the policy. + m_removePolicy = static_cast(settings->value(GROUP(Downloads), SETTING(Downloads::RemovePolicy)).toInt()); - if (!url.isEmpty() && !file_name.isEmpty()) { - DownloadItem* item = new DownloadItem(0, this); - item->m_output.setFileName(file_name); - item->m_url = url; - item->updateInfoAndUrlLabel(); - item->m_ui->m_btnStopDownload->setVisible(false); - item->m_ui->m_btnStopDownload->setEnabled(false); - item->m_ui->m_btnTryAgain->setVisible(!done); - item->m_ui->m_btnTryAgain->setEnabled(!done); - item->m_ui->m_progressDownload->setVisible(false); - addItem(item); - } + // Restore downloads. + while (settings->contains(GROUP(Downloads), QString(Downloads::ItemUrl).arg(i))) { + QUrl url = settings->value(GROUP(Downloads), QString(Downloads::ItemUrl).arg(i)).toUrl(); + QString file_name = settings->value(GROUP(Downloads), QString(Downloads::ItemLocation).arg(i)).toString(); + bool done = settings->value(GROUP(Downloads), QString(Downloads::ItemDone).arg(i), true).toBool(); - i++; - } + if (!url.isEmpty() && !file_name.isEmpty()) { + DownloadItem* item = new DownloadItem(0, this); - m_ui->m_btnCleanup->setEnabled(m_downloads.size() - activeDownloads() > 0); + item->m_output.setFileName(file_name); + item->m_url = url; + item->updateInfoAndUrlLabel(); + item->m_ui->m_btnStopDownload->setVisible(false); + item->m_ui->m_btnStopDownload->setEnabled(false); + item->m_ui->m_btnTryAgain->setVisible(!done); + item->m_ui->m_btnTryAgain->setEnabled(!done); + item->m_ui->m_progressDownload->setVisible(false); + addItem(item); + } + + i++; + } + + m_ui->m_btnCleanup->setEnabled(m_downloads.size() - activeDownloads() > 0); } void DownloadManager::cleanup() { - if (!m_downloads.isEmpty()) { - m_model->removeRows(0, m_downloads.count()); - m_ui->m_btnCleanup->setEnabled(false); - } + if (!m_downloads.isEmpty()) { + m_model->removeRows(0, m_downloads.count()); + m_ui->m_btnCleanup->setEnabled(false); + } } void DownloadManager::setDownloadDirectory(const QString& directory) { - m_downloadDirectory = directory; + m_downloadDirectory = directory; - if (!m_downloadDirectory.isEmpty() && !m_downloadDirectory.endsWith(QDir::separator())) { - m_downloadDirectory += QDir::separator(); - } + if (!m_downloadDirectory.isEmpty() && !m_downloadDirectory.endsWith(QDir::separator())) { + m_downloadDirectory += QDir::separator(); + } } QString DownloadManager::downloadDirectory() { - return m_downloadDirectory; + return m_downloadDirectory; } QString DownloadManager::timeString(double time_remaining) { - QString remaining; + QString remaining; - if (time_remaining > 60) { - time_remaining = time_remaining / 60; - time_remaining = floor(time_remaining); - remaining = tr("%n minutes remaining", "", (int) time_remaining); - } - else { - time_remaining = floor(time_remaining); - remaining = tr("%n seconds remaining", "", (int) time_remaining); - } + if (time_remaining > 60) { + time_remaining = time_remaining / 60; + time_remaining = floor(time_remaining); + remaining = tr("%n minutes remaining", "", (int) time_remaining); + } + else { + time_remaining = floor(time_remaining); + remaining = tr("%n seconds remaining", "", (int) time_remaining); + } - return remaining; + return remaining; } QString DownloadManager::dataString(qint64 size) { - QString unit; - double new_size; + QString unit; + double new_size; - if (size < 1024) { - new_size = size; - unit = tr("bytes"); - } - else if (size < 1024 * 1024) { - new_size = (double)size / (double)1024; - unit = tr("kB"); - } - else if (size < 1024 * 1024 * 1024) { - new_size = (double)size / (double)(1024 * 1024); - unit = tr("MB"); - } - else { - new_size = (double)size / (double)(1024 * 1024 * 1024); - unit = tr("GB"); - } + if (size < 1024) { + new_size = size; + unit = tr("bytes"); + } + else if (size < 1024 * 1024) { + new_size = (double)size / (double)1024; + unit = tr("kB"); + } + else if (size < 1024 * 1024 * 1024) { + new_size = (double)size / (double)(1024 * 1024); + unit = tr("MB"); + } + else { + new_size = (double)size / (double)(1024 * 1024 * 1024); + unit = tr("GB"); + } - return QString(QL1S("%1 %2")).arg(new_size, 0, 'f', 1).arg(unit); + return QString(QL1S("%1 %2")).arg(new_size, 0, 'f', 1).arg(unit); } DownloadModel::DownloadModel(DownloadManager* download_manager, QObject* parent) - : QAbstractListModel(parent), m_downloadManager(download_manager) { -} + : QAbstractListModel(parent), m_downloadManager(download_manager) {} QVariant DownloadModel::data(const QModelIndex& index, int role) const { - if (index.row() < 0 || index.row() >= rowCount(index.parent())) { - return QVariant(); - } + if (index.row() < 0 || index.row() >= rowCount(index.parent())) { + return QVariant(); + } - if (role == Qt::ToolTipRole) { - if (!m_downloadManager->m_downloads.at(index.row())->downloadedSuccessfully()) { - return m_downloadManager->m_downloads.at(index.row())->m_ui->m_lblInfoDownload->text(); - } - } + if (role == Qt::ToolTipRole) { + if (!m_downloadManager->m_downloads.at(index.row())->downloadedSuccessfully()) { + return m_downloadManager->m_downloads.at(index.row())->m_ui->m_lblInfoDownload->text(); + } + } - return QVariant(); + return QVariant(); } int DownloadModel::rowCount(const QModelIndex& parent) const { - return parent.isValid() ? 0 : m_downloadManager->m_downloads.count(); + return parent.isValid() ? 0 : m_downloadManager->m_downloads.count(); } bool DownloadModel::removeRows(int row, int count, const QModelIndex& parent) { - if (parent.isValid()) { - return false; - } + if (parent.isValid()) { + return false; + } - int lastRow = row + count - 1; + int lastRow = row + count - 1; - for (int i = lastRow; i >= row; --i) { - if (m_downloadManager->m_downloads.at(i)->downloadedSuccessfully() || - m_downloadManager->m_downloads.at(i)->m_ui->m_btnTryAgain->isEnabled()) { - beginRemoveRows(parent, i, i); - m_downloadManager->m_downloads.takeAt(i)->deleteLater(); - endRemoveRows(); - } - } + for (int i = lastRow; i >= row; --i) { + if (m_downloadManager->m_downloads.at(i)->downloadedSuccessfully() || + m_downloadManager->m_downloads.at(i)->m_ui->m_btnTryAgain->isEnabled()) { + beginRemoveRows(parent, i, i); + m_downloadManager->m_downloads.takeAt(i)->deleteLater(); + endRemoveRows(); + } + } - m_downloadManager->m_autoSaver->changeOccurred(); + m_downloadManager->m_autoSaver->changeOccurred(); - if (m_downloadManager->totalDownloads() == 0) { - m_downloadManager->m_ui->m_btnCleanup->setEnabled(false); - } + if (m_downloadManager->totalDownloads() == 0) { + m_downloadManager->m_ui->m_btnCleanup->setEnabled(false); + } - return true; + return true; } Qt::ItemFlags DownloadModel::flags(const QModelIndex& index) const { - if (index.row() < 0 || index.row() >= rowCount(index.parent())) { - return Qt::NoItemFlags; - } + if (index.row() < 0 || index.row() >= rowCount(index.parent())) { + return Qt::NoItemFlags; + } - Qt::ItemFlags default_flags = QAbstractItemModel::flags(index); - DownloadItem* item = m_downloadManager->m_downloads.at(index.row()); + Qt::ItemFlags default_flags = QAbstractItemModel::flags(index); + DownloadItem* item = m_downloadManager->m_downloads.at(index.row()); - if (item->downloadedSuccessfully()) { - return default_flags | Qt::ItemIsDragEnabled; - } + if (item->downloadedSuccessfully()) { + return default_flags | Qt::ItemIsDragEnabled; + } - return default_flags; + return default_flags; } QMimeData* DownloadModel::mimeData(const QModelIndexList& indexes) const { - QMimeData* mimeData = new QMimeData(); - QList urls; + QMimeData* mimeData = new QMimeData(); - foreach (const QModelIndex& index, indexes) { - if (!index.isValid()) { - continue; - } + QList urls; - urls.append(QUrl::fromLocalFile(QFileInfo(m_downloadManager->m_downloads.at(index.row())->m_output).absoluteFilePath())); - } + foreach (const QModelIndex& index, indexes) { + if (!index.isValid()) { + continue; + } - mimeData->setUrls(urls); - return mimeData; + urls.append(QUrl::fromLocalFile(QFileInfo(m_downloadManager->m_downloads.at(index.row())->m_output).absoluteFilePath())); + } + + mimeData->setUrls(urls); + return mimeData; } diff --git a/src/network-web/downloadmanager.h b/src/network-web/downloadmanager.h index 712a7b9c9..1964ef239 100755 --- a/src/network-web/downloadmanager.h +++ b/src/network-web/downloadmanager.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,15 +19,14 @@ #ifndef DOWNLOADMANAGER_H #define DOWNLOADMANAGER_H -#include "ui_downloadmanager.h" #include "ui_downloaditem.h" +#include "ui_downloadmanager.h" #include "gui/tabcontent.h" -#include -#include #include - +#include +#include class AutoSaver; class DownloadModel; @@ -34,61 +34,62 @@ class QFileIconProvider; class QMimeData; class DownloadItem : public QWidget { - Q_OBJECT + Q_OBJECT - // Friends of this class. - friend class DownloadManager; - friend class DownloadModel; + // Friends of this class. + friend class DownloadManager; + friend class DownloadModel; - public: - // Constructors. - explicit DownloadItem(QNetworkReply* reply = 0, QWidget* parent = 0); - virtual ~DownloadItem(); + public: - bool downloading() const; - bool downloadedSuccessfully() const; + // Constructors. + explicit DownloadItem(QNetworkReply* reply = 0, QWidget* parent = 0); + virtual ~DownloadItem(); - qint64 bytesTotal() const; - qint64 bytesReceived() const; - double remainingTime() const; - double currentSpeed() const; + bool downloading() const; + bool downloadedSuccessfully() const; - private slots: - void stop(); - void tryAgain(); - void openFile(); - void openFolder(); + qint64 bytesTotal() const; + qint64 bytesReceived() const; + double remainingTime() const; + double currentSpeed() const; - void downloadReadyRead(); - void error(QNetworkReply::NetworkError code); - void downloadProgress(qint64 bytes_received, qint64 bytes_total); - void metaDataChanged(); - void finished(); + private slots: + void stop(); + void tryAgain(); + void openFile(); + void openFolder(); - signals: - void statusChanged(); - void progress(qint64 bytes_received, qint64 bytes_total); - void downloadFinished(); + void downloadReadyRead(); + void error(QNetworkReply::NetworkError code); + void downloadProgress(qint64 bytes_received, qint64 bytes_total); + void metaDataChanged(); + void finished(); - private: - void updateInfoAndUrlLabel(); - void getFileName(); - void init(); - void updateDownloadInfoLabel(); - QString saveFileName(const QString& directory) const; + signals: + void statusChanged(); + void progress(qint64 bytes_received, qint64 bytes_total); + void downloadFinished(); - Ui::DownloadItem* m_ui; - QUrl m_url; - QFile m_output; - QNetworkReply* m_reply; - qint64 m_bytesReceived; - QTime m_downloadTime; - QTime m_lastProgressTime; - bool m_requestFileName; - bool m_startedSaving; - bool m_finishedDownloading; - bool m_gettingFileName; - bool m_canceledFileSelect; + private: + void updateInfoAndUrlLabel(); + void getFileName(); + void init(); + void updateDownloadInfoLabel(); + QString saveFileName(const QString& directory) const; + + Ui::DownloadItem* m_ui; + QUrl m_url; + QFile m_output; + QNetworkReply* m_reply; + qint64 m_bytesReceived; + QTime m_downloadTime; + QTime m_lastProgressTime; + bool m_requestFileName; + bool m_startedSaving; + bool m_finishedDownloading; + bool m_gettingFileName; + bool m_canceledFileSelect; }; #if defined(USE_WEBENGINE) @@ -96,92 +97,93 @@ class WebBrowser; #endif class DownloadManager : public TabContent { - Q_OBJECT - Q_PROPERTY(RemovePolicy removePolicy READ removePolicy WRITE setRemovePolicy) + Q_OBJECT + Q_PROPERTY(RemovePolicy removePolicy READ removePolicy WRITE setRemovePolicy) - friend class DownloadModel; + friend class DownloadModel; - public: - enum RemovePolicy { - Never, - OnExit, - OnSuccessfullDownload - }; + public: + enum RemovePolicy { + Never, + OnExit, + OnSuccessfullDownload + }; - Q_ENUM(RemovePolicy) + Q_ENUM(RemovePolicy) - explicit DownloadManager(QWidget* parent = 0); - virtual ~DownloadManager(); + explicit DownloadManager(QWidget* parent = 0); + virtual ~DownloadManager(); #if defined(USE_WEBENGINE) - WebBrowser* webBrowser() const { - return nullptr; - } + WebBrowser* webBrowser() const { + return nullptr; + } #endif - QNetworkAccessManager* networkManager() const; + QNetworkAccessManager* networkManager() const; - int totalDownloads() const; - int activeDownloads() const; - int downloadProgress() const; + int totalDownloads() const; + int activeDownloads() const; + int downloadProgress() const; - RemovePolicy removePolicy() const; - void setRemovePolicy(RemovePolicy policy); + RemovePolicy removePolicy() const; + void setRemovePolicy(RemovePolicy policy); - void setDownloadDirectory(const QString& directory); - QString downloadDirectory(); + void setDownloadDirectory(const QString& directory); + QString downloadDirectory(); - static QString timeString(double time_remaining); - static QString dataString(qint64 size); + static QString timeString(double time_remaining); + static QString dataString(qint64 size); - public slots: - void download(const QNetworkRequest& request); - void download(const QUrl& url); - void handleUnsupportedContent(QNetworkReply* reply); - void cleanup(); + public slots: + void download(const QNetworkRequest& request); + void download(const QUrl& url); + void handleUnsupportedContent(QNetworkReply* reply); + void cleanup(); - private slots: - void save() const; - void load(); + private slots: + void save() const; + void load(); - void updateRow(DownloadItem* item); - void updateRow(); - void itemProgress(); - void itemFinished(); + void updateRow(DownloadItem* item); + void updateRow(); + void itemProgress(); + void itemFinished(); - signals: - void downloadProgressed(int progress, const QString& description); - void downloadFinished(); + signals: + void downloadProgressed(int progress, const QString& description); + void downloadFinished(); - private: - void addItem(DownloadItem* item); + private: + void addItem(DownloadItem* item); - QScopedPointer m_ui; - AutoSaver* m_autoSaver; - DownloadModel* m_model; - QNetworkAccessManager* m_networkManager; - QScopedPointer m_iconProvider; - QList m_downloads; - RemovePolicy m_removePolicy; - QString m_downloadDirectory; + QScopedPointer m_ui; + AutoSaver* m_autoSaver; + DownloadModel* m_model; + QNetworkAccessManager* m_networkManager; + + QScopedPointer m_iconProvider; + QList m_downloads; + RemovePolicy m_removePolicy; + QString m_downloadDirectory; }; class DownloadModel : public QAbstractListModel { - Q_OBJECT + Q_OBJECT - friend class DownloadManager; + friend class DownloadManager; - public: - explicit DownloadModel(DownloadManager* download_manager, QObject* parent = 0); + public: + explicit DownloadModel(DownloadManager* download_manager, QObject* parent = 0); - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - int rowCount(const QModelIndex& parent = QModelIndex()) const; - bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()); - Qt::ItemFlags flags(const QModelIndex& index) const; - QMimeData* mimeData(const QModelIndexList& indexes) const; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + int rowCount(const QModelIndex& parent = QModelIndex()) const; + bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()); + Qt::ItemFlags flags(const QModelIndex& index) const; + QMimeData* mimeData(const QModelIndexList& indexes) const; - private: - DownloadManager* m_downloadManager; + private: + DownloadManager* m_downloadManager; }; #endif // DOWNLOADMANAGER_H diff --git a/src/network-web/googlesuggest.cpp b/src/network-web/googlesuggest.cpp index 53e482940..d871a0072 100755 --- a/src/network-web/googlesuggest.cpp +++ b/src/network-web/googlesuggest.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -46,153 +47,153 @@ #include "network-web/googlesuggest.h" #include "definitions/definitions.h" -#include "network-web/silentnetworkaccessmanager.h" #include "gui/locationlineedit.h" +#include "network-web/silentnetworkaccessmanager.h" -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include - +#include +#include GoogleSuggest::GoogleSuggest(LocationLineEdit* editor, QObject* parent) - : QObject(parent), editor(editor), popup(new QListWidget()), m_enteredText(QString()) { - popup->setWindowFlags(Qt::Popup); - popup->setFocusPolicy(Qt::NoFocus); - popup->setFocusProxy(editor); - popup->setMouseTracking(true); - popup->setSelectionBehavior(QAbstractItemView::SelectRows); - popup->setFrameStyle(QFrame::Box | QFrame::Plain); - popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - popup->installEventFilter(this); - timer = new QTimer(this); - timer->setSingleShot(true); - timer->setInterval(500); - connect(popup.data(), &QListWidget::itemClicked, this, &GoogleSuggest::doneCompletion); - connect(timer, &QTimer::timeout, this, &GoogleSuggest::autoSuggest); - connect(editor, &LocationLineEdit::textEdited, timer, static_cast(&QTimer::start)); + : QObject(parent), editor(editor), popup(new QListWidget()), m_enteredText(QString()) { + popup->setWindowFlags(Qt::Popup); + popup->setFocusPolicy(Qt::NoFocus); + popup->setFocusProxy(editor); + popup->setMouseTracking(true); + popup->setSelectionBehavior(QAbstractItemView::SelectRows); + popup->setFrameStyle(QFrame::Box | QFrame::Plain); + popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + popup->installEventFilter(this); + timer = new QTimer(this); + timer->setSingleShot(true); + timer->setInterval(500); + connect(popup.data(), &QListWidget::itemClicked, this, &GoogleSuggest::doneCompletion); + connect(timer, &QTimer::timeout, this, &GoogleSuggest::autoSuggest); + connect(editor, &LocationLineEdit::textEdited, timer, static_cast(&QTimer::start)); } -GoogleSuggest::~GoogleSuggest() { -} +GoogleSuggest::~GoogleSuggest() {} bool GoogleSuggest::eventFilter(QObject* object, QEvent* event) { - if (object != popup.data()) { - return false; - } + if (object != popup.data()) { + return false; + } - if (event->type() == QEvent::MouseButtonPress) { - popup->hide(); - editor->setFocus(); - return true; - } + if (event->type() == QEvent::MouseButtonPress) { + popup->hide(); + editor->setFocus(); + return true; + } - if (event->type() == QEvent::KeyPress) { - bool consumed = false; - const int key = static_cast(event)->key(); + if (event->type() == QEvent::KeyPress) { + bool consumed = false; + const int key = static_cast(event)->key(); - switch (key) { - case Qt::Key_Enter: - case Qt::Key_Return: - doneCompletion(); - consumed = true; + switch (key) { + case Qt::Key_Enter: + case Qt::Key_Return: + doneCompletion(); + consumed = true; - case Qt::Key_Escape: - editor->setFocus(); - popup->hide(); - consumed = true; + case Qt::Key_Escape: + editor->setFocus(); + popup->hide(); + consumed = true; - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_PageUp: - case Qt::Key_PageDown: - break; + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_PageUp: + case Qt::Key_PageDown: + break; - default: - editor->setFocus(); - editor->event(event); - popup->hide(); - break; - } + default: + editor->setFocus(); + editor->event(event); + popup->hide(); + break; + } - return consumed; - } + return consumed; + } - return false; + return false; } void GoogleSuggest::showCompletion(const QStringList& choices) { - if (choices.isEmpty()) { - return; - } + if (choices.isEmpty()) { + return; + } - popup->setUpdatesEnabled(false); - popup->clear(); + popup->setUpdatesEnabled(false); + popup->clear(); - foreach (const QString& choice, choices) { - new QListWidgetItem(choice, popup.data()); - } + foreach (const QString& choice, choices) { + new QListWidgetItem(choice, popup.data()); + } - popup->setCurrentItem(popup->item(0)); - popup->adjustSize(); - popup->setUpdatesEnabled(true); - popup->resize(editor->width(), popup->sizeHintForRow(0) * qMin(7, choices.count()) + 3); - popup->move(editor->mapToGlobal(QPoint(0, editor->height()))); - popup->setFocus(); - popup->show(); + popup->setCurrentItem(popup->item(0)); + popup->adjustSize(); + popup->setUpdatesEnabled(true); + popup->resize(editor->width(), popup->sizeHintForRow(0) * qMin(7, choices.count()) + 3); + popup->move(editor->mapToGlobal(QPoint(0, editor->height()))); + popup->setFocus(); + popup->show(); } void GoogleSuggest::doneCompletion() { - timer->stop(); - popup->hide(); - editor->setFocus(); - QListWidgetItem* item = popup->currentItem(); + timer->stop(); + popup->hide(); + editor->setFocus(); + QListWidgetItem* item = popup->currentItem(); - if (item != nullptr) { - editor->submit(QString(GOOGLE_SEARCH_URL).arg(item->text())); - } + if (item != nullptr) { + editor->submit(QString(GOOGLE_SEARCH_URL).arg(item->text())); + } } void GoogleSuggest::preventSuggest() { - timer->stop(); + timer->stop(); } void GoogleSuggest::autoSuggest() { - m_enteredText = QUrl::toPercentEncoding(editor->text()); - QString url = QString(GOOGLE_SUGGEST_URL).arg(m_enteredText); - connect(SilentNetworkAccessManager::instance()->get(QNetworkRequest(QString(url))), &QNetworkReply::finished, - this, &GoogleSuggest::handleNetworkData); + m_enteredText = QUrl::toPercentEncoding(editor->text()); + QString url = QString(GOOGLE_SUGGEST_URL).arg(m_enteredText); + + connect(SilentNetworkAccessManager::instance()->get(QNetworkRequest(QString(url))), &QNetworkReply::finished, + this, &GoogleSuggest::handleNetworkData); } void GoogleSuggest::handleNetworkData() { - QScopedPointer reply(static_cast(sender())); + QScopedPointer reply(static_cast(sender())); - if (!reply->error()) { - QStringList choices; - QDomDocument xml; - QByteArray response = reply->readAll(); - const QTextCodec* c = QTextCodec::codecForUtfText(response); - xml.setContent(c->toUnicode(response)); - QDomNodeList suggestions = xml.elementsByTagName(QSL("suggestion")); + if (!reply->error()) { + QStringList choices; + QDomDocument xml; + QByteArray response = reply->readAll(); + const QTextCodec* c = QTextCodec::codecForUtfText(response); - for (int i = 0; i < suggestions.size(); i++) { - const QDomElement element = suggestions.at(i).toElement(); + xml.setContent(c->toUnicode(response)); + QDomNodeList suggestions = xml.elementsByTagName(QSL("suggestion")); - if (element.attributes().contains(QSL("data"))) { - choices.append(element.attribute(QSL("data"))); - } - } + for (int i = 0; i < suggestions.size(); i++) { + const QDomElement element = suggestions.at(i).toElement(); - if (choices.isEmpty()) { - choices.append(m_enteredText); - } + if (element.attributes().contains(QSL("data"))) { + choices.append(element.attribute(QSL("data"))); + } + } - showCompletion(choices); - } + if (choices.isEmpty()) { + choices.append(m_enteredText); + } + + showCompletion(choices); + } } diff --git a/src/network-web/googlesuggest.h b/src/network-web/googlesuggest.h index 52afc7f47..6b68d414a 100755 --- a/src/network-web/googlesuggest.h +++ b/src/network-web/googlesuggest.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -48,7 +49,6 @@ #include - class LocationLineEdit; class QNetworkReply; class QTimer; @@ -56,27 +56,29 @@ class QListWidget; class QNetworkAccessManager; class GoogleSuggest : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Constructors. - explicit GoogleSuggest(LocationLineEdit* editor, QObject* parent = 0); - virtual ~GoogleSuggest(); + public: - bool eventFilter(QObject* object, QEvent* event); - void showCompletion(const QStringList& choices); + // Constructors. + explicit GoogleSuggest(LocationLineEdit* editor, QObject* parent = 0); + virtual ~GoogleSuggest(); - public slots: - void doneCompletion(); - void preventSuggest(); - void autoSuggest(); - void handleNetworkData(); + bool eventFilter(QObject* object, QEvent* event); + void showCompletion(const QStringList& choices); - private: - LocationLineEdit* editor; - QScopedPointer popup; - QTimer* timer; - QString m_enteredText; + public slots: + void doneCompletion(); + void preventSuggest(); + void autoSuggest(); + void handleNetworkData(); + + private: + LocationLineEdit* editor; + + QScopedPointer popup; + QTimer* timer; + QString m_enteredText; }; #endif // GOOGLESUGGEST_H diff --git a/src/network-web/networkfactory.cpp b/src/network-web/networkfactory.cpp index 826c7513a..2d53a7518 100755 --- a/src/network-web/networkfactory.cpp +++ b/src/network-web/networkfactory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,133 +20,147 @@ #include "definitions/definitions.h" #include "miscellaneous/settings.h" -#include "network-web/silentnetworkaccessmanager.h" #include "network-web/downloader.h" +#include "network-web/silentnetworkaccessmanager.h" #include -#include #include #include #include +#include - -NetworkFactory::NetworkFactory() { -} +NetworkFactory::NetworkFactory() {} QStringList NetworkFactory::extractFeedLinksFromHtmlPage(const QUrl& url, const QString& html) { - QStringList feeds; - const QRegExp rx(FEED_REGEX_MATCHER, Qt::CaseInsensitive); - const QRegExp rx_href(FEED_HREF_REGEX_MATCHER, Qt::CaseInsensitive); + QStringList feeds; + const QRegExp rx(FEED_REGEX_MATCHER, Qt::CaseInsensitive); + const QRegExp rx_href(FEED_HREF_REGEX_MATCHER, Qt::CaseInsensitive); - for (int pos = 0; (pos = rx.indexIn(html, pos)) != -1; pos += rx.matchedLength()) { - QString link_element = html.mid(pos, rx.matchedLength()); + for (int pos = 0; (pos = rx.indexIn(html, pos)) != -1; pos += rx.matchedLength()) { + QString link_element = html.mid(pos, rx.matchedLength()); - if (rx_href.indexIn(link_element) != -1) { - QString href_attribute = rx_href.capturedTexts().at(0); - QString feed_link = href_attribute.mid(6, href_attribute.size() - 7); + if (rx_href.indexIn(link_element) != -1) { + QString href_attribute = rx_href.capturedTexts().at(0); + QString feed_link = href_attribute.mid(6, href_attribute.size() - 7); - if (feed_link.startsWith(QL1S("//"))) { - feed_link = QString(URI_SCHEME_HTTP) + feed_link.mid(2); - } - else if (feed_link.startsWith(QL1C('/'))) { - feed_link = url.toString(QUrl::RemovePath | QUrl::RemoveQuery | QUrl::StripTrailingSlash) + feed_link; - } + if (feed_link.startsWith(QL1S("//"))) { + feed_link = QString(URI_SCHEME_HTTP) + feed_link.mid(2); + } + else if (feed_link.startsWith(QL1C('/'))) { + feed_link = url.toString(QUrl::RemovePath | QUrl::RemoveQuery | QUrl::StripTrailingSlash) + feed_link; + } - feeds.append(feed_link); - } - } + feeds.append(feed_link); + } + } - return feeds; + return feeds; } QString NetworkFactory::networkErrorText(QNetworkReply::NetworkError error_code) { - switch (error_code) { - case QNetworkReply::ProtocolUnknownError: - case QNetworkReply::ProtocolFailure: - //: Network status. - return tr("protocol error"); + switch (error_code) { + case QNetworkReply::ProtocolUnknownError: + case QNetworkReply::ProtocolFailure: - case QNetworkReply::ContentAccessDenied: - return tr("access to content was denied"); + //: Network status. + return tr("protocol error"); - case QNetworkReply::HostNotFoundError: - //: Network status. - return tr("host not found"); + case QNetworkReply::ContentAccessDenied: + return tr("access to content was denied"); - case QNetworkReply::OperationCanceledError: - case QNetworkReply::TimeoutError: - return tr("connection timed out or was cancelled"); + case QNetworkReply::HostNotFoundError: - case QNetworkReply::RemoteHostClosedError: - case QNetworkReply::ConnectionRefusedError: - //: Network status. - return tr("connection refused"); + //: Network status. + return tr("host not found"); - case QNetworkReply::ProxyTimeoutError: - //: Network status. - return tr("connection timed out"); + case QNetworkReply::OperationCanceledError: + case QNetworkReply::TimeoutError: + return tr("connection timed out or was cancelled"); - case QNetworkReply::SslHandshakeFailedError: - //: Network status. - return tr("SSL handshake failed"); + case QNetworkReply::RemoteHostClosedError: + case QNetworkReply::ConnectionRefusedError: - case QNetworkReply::ProxyConnectionClosedError: - case QNetworkReply::ProxyConnectionRefusedError: - //: Network status. - return tr("proxy server connection refused"); + //: Network status. + return tr("connection refused"); - case QNetworkReply::TemporaryNetworkFailureError: - //: Network status. - return tr("temporary failure"); + case QNetworkReply::ProxyTimeoutError: - case QNetworkReply::AuthenticationRequiredError: - //: Network status. - return tr("authentication failed"); + //: Network status. + return tr("connection timed out"); - case QNetworkReply::ProxyAuthenticationRequiredError: - //: Network status. - return tr("proxy authentication required"); + case QNetworkReply::SslHandshakeFailedError: - case QNetworkReply::ProxyNotFoundError: - //: Network status. - return tr("proxy server not found"); + //: Network status. + return tr("SSL handshake failed"); - case QNetworkReply::NoError: - //: Network status. - return tr("no errors"); + case QNetworkReply::ProxyConnectionClosedError: + case QNetworkReply::ProxyConnectionRefusedError: - case QNetworkReply::UnknownContentError: - //: Network status. - return tr("unknown content"); + //: Network status. + return tr("proxy server connection refused"); - case QNetworkReply::ContentNotFoundError: - //: Network status. - return tr("content not found"); + case QNetworkReply::TemporaryNetworkFailureError: - default: - //: Network status. - return tr("unknown error"); - } + //: Network status. + return tr("temporary failure"); + + case QNetworkReply::AuthenticationRequiredError: + + //: Network status. + return tr("authentication failed"); + + case QNetworkReply::ProxyAuthenticationRequiredError: + + //: Network status. + return tr("proxy authentication required"); + + case QNetworkReply::ProxyNotFoundError: + + //: Network status. + return tr("proxy server not found"); + + case QNetworkReply::NoError: + + //: Network status. + return tr("no errors"); + + case QNetworkReply::UnknownContentError: + + //: Network status. + return tr("unknown content"); + + case QNetworkReply::ContentNotFoundError: + + //: Network status. + return tr("content not found"); + + default: + + //: Network status. + return tr("unknown error"); + } } QNetworkReply::NetworkError NetworkFactory::downloadIcon(const QList& urls, int timeout, QIcon& output) { - QNetworkReply::NetworkError network_result = QNetworkReply::UnknownNetworkError; + QNetworkReply::NetworkError network_result = QNetworkReply::UnknownNetworkError; - foreach (const QString& url, urls) { - const QString google_s2_with_url = QString("http://www.google.com/s2/favicons?domain=%1").arg(QUrl(url).host()); - QByteArray icon_data; - network_result = performNetworkOperation(google_s2_with_url, timeout, QByteArray(), QString(), icon_data, - QNetworkAccessManager::GetOperation).first; + foreach (const QString& url, urls) { + const QString google_s2_with_url = QString("http://www.google.com/s2/favicons?domain=%1").arg(QUrl(url).host()); + QByteArray icon_data; - if (network_result == QNetworkReply::NoError) { - QPixmap icon_pixmap; - icon_pixmap.loadFromData(icon_data); - output = QIcon(icon_pixmap); - break; - } - } + network_result = performNetworkOperation(google_s2_with_url, timeout, QByteArray(), QString(), icon_data, + QNetworkAccessManager::GetOperation).first; - return network_result; + if (network_result == QNetworkReply::NoError) { + QPixmap icon_pixmap; + + icon_pixmap.loadFromData(icon_data); + output = QIcon(icon_pixmap); + break; + } + } + + return network_result; } Downloader* NetworkFactory::performAsyncNetworkOperation(const QString& url, int timeout, const QByteArray& input_data, @@ -174,45 +189,48 @@ NetworkResult NetworkFactory::performNetworkOperation(const QString& url, int ti const QString& input_content_type, QByteArray& output, QNetworkAccessManager::Operation operation, bool protected_contents, const QString& username, const QString& password, bool set_basic_header) { - Downloader downloader; - QEventLoop loop; - NetworkResult result; + Downloader downloader; + QEventLoop loop; + NetworkResult result; - if (!input_content_type.isEmpty()) { - downloader.appendRawHeader("Content-Type", input_content_type.toLocal8Bit()); - } + if (!input_content_type.isEmpty()) { + downloader.appendRawHeader("Content-Type", input_content_type.toLocal8Bit()); + } - if (set_basic_header) { - QString basic_value = username + ":" + password; - QString header_value = QString("Basic ") + QString(basic_value.toUtf8().toBase64()); - downloader.appendRawHeader("Authorization", header_value.toLocal8Bit()); - } + if (set_basic_header) { + QString basic_value = username + ":" + password; + QString header_value = QString("Basic ") + QString(basic_value.toUtf8().toBase64()); - // We need to quit event loop when the download finishes. - QObject::connect(&downloader, &Downloader::completed, &loop, &QEventLoop::quit); - downloader.manipulateData(url, operation, input_data, timeout, protected_contents, username, password); - loop.exec(); - output = downloader.lastOutputData(); - result.first = downloader.lastOutputError(); - result.second = downloader.lastContentType(); - return result; + downloader.appendRawHeader("Authorization", header_value.toLocal8Bit()); + } + + // We need to quit event loop when the download finishes. + QObject::connect(&downloader, &Downloader::completed, &loop, &QEventLoop::quit); + downloader.manipulateData(url, operation, input_data, timeout, protected_contents, username, password); + loop.exec(); + output = downloader.lastOutputData(); + result.first = downloader.lastOutputError(); + result.second = downloader.lastContentType(); + return result; } NetworkResult NetworkFactory::downloadFeedFile(const QString& url, int timeout, QByteArray& output, bool protected_contents, const QString& username, const QString& password) { - // Here, we want to achieve "synchronous" approach because we want synchronout download API for - // some use-cases too. - Downloader downloader; - QEventLoop loop; - NetworkResult result; - downloader.appendRawHeader("Accept", ACCEPT_HEADER_FOR_FEED_DOWNLOADER); - // We need to quit event loop when the download finishes. - QObject::connect(&downloader, &Downloader::completed, &loop, &QEventLoop::quit); - downloader.downloadFile(url, timeout, protected_contents, username, password); - loop.exec(); - output = downloader.lastOutputData(); - result.first = downloader.lastOutputError(); - result.second = downloader.lastContentType(); - return result; + // Here, we want to achieve "synchronous" approach because we want synchronout download API for + // some use-cases too. + Downloader downloader; + QEventLoop loop; + NetworkResult result; + + downloader.appendRawHeader("Accept", ACCEPT_HEADER_FOR_FEED_DOWNLOADER); + + // We need to quit event loop when the download finishes. + QObject::connect(&downloader, &Downloader::completed, &loop, &QEventLoop::quit); + downloader.downloadFile(url, timeout, protected_contents, username, password); + loop.exec(); + output = downloader.lastOutputData(); + result.first = downloader.lastOutputError(); + result.second = downloader.lastContentType(); + return result; } diff --git a/src/network-web/networkfactory.h b/src/network-web/networkfactory.h index b1598dd87..115412971 100755 --- a/src/network-web/networkfactory.h +++ b/src/network-web/networkfactory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,47 +19,45 @@ #ifndef NETWORKFACTORY_H #define NETWORKFACTORY_H -#include #include +#include #include #include - typedef QPair NetworkResult; + class Downloader; class NetworkFactory { - Q_DECLARE_TR_FUNCTIONS(NetworkFactory) + Q_DECLARE_TR_FUNCTIONS(NetworkFactory) - private: - // Constructor. - explicit NetworkFactory(); + private: - public: - static QStringList extractFeedLinksFromHtmlPage(const QUrl& url, const QString& html); + // Constructor. + explicit NetworkFactory(); - // Returns human readable text for given network error. - static QString networkErrorText(QNetworkReply::NetworkError error_code); + public: + static QStringList extractFeedLinksFromHtmlPage(const QUrl& url, const QString& html); - // Performs SYNCHRONOUS download if favicon for the site, - // given URL belongs to. - static QNetworkReply::NetworkError downloadIcon(const QList& urls, int timeout, QIcon& output); + // Returns human readable text for given network error. + static QString networkErrorText(QNetworkReply::NetworkError error_code); + // Performs SYNCHRONOUS download if favicon for the site, + // given URL belongs to. + static QNetworkReply::NetworkError downloadIcon(const QList& urls, int timeout, QIcon& output); static Downloader* performAsyncNetworkOperation(const QString& url, int timeout, const QByteArray& input_data, const QString& input_content_type, QNetworkAccessManager::Operation operation, bool protected_contents = false, const QString& username = QString(), const QString& password = QString(), bool set_basic_header = false); - - static NetworkResult performNetworkOperation(const QString& url, int timeout, const QByteArray& input_data, - const QString& input_content_type, QByteArray& output, - QNetworkAccessManager::Operation operation, - bool protected_contents = false, const QString& username = QString(), - const QString& password = QString(), bool set_basic_header = false); - - static NetworkResult downloadFeedFile(const QString& url, int timeout, QByteArray& output, - bool protected_contents = false, const QString& username = QString(), - const QString& password = QString()); + static NetworkResult performNetworkOperation(const QString& url, int timeout, const QByteArray& input_data, + const QString& input_content_type, QByteArray& output, + QNetworkAccessManager::Operation operation, + bool protected_contents = false, const QString& username = QString(), + const QString& password = QString(), bool set_basic_header = false); + static NetworkResult downloadFeedFile(const QString& url, int timeout, QByteArray& output, + bool protected_contents = false, const QString& username = QString(), + const QString& password = QString()); }; #endif // NETWORKFACTORY_H diff --git a/src/network-web/networkurlinterceptor.cpp b/src/network-web/networkurlinterceptor.cpp index f645752c2..791bdc229 100755 --- a/src/network-web/networkurlinterceptor.cpp +++ b/src/network-web/networkurlinterceptor.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -18,37 +19,35 @@ #include "network-web/networkurlinterceptor.h" -#include "network-web/urlinterceptor.h" #include "miscellaneous/application.h" #include "miscellaneous/settings.h" - +#include "network-web/urlinterceptor.h" NetworkUrlInterceptor::NetworkUrlInterceptor(QObject* parent) - : QWebEngineUrlRequestInterceptor(parent), m_sendDNT(false) { -} + : QWebEngineUrlRequestInterceptor(parent), m_sendDNT(false) {} void NetworkUrlInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) { - if (m_sendDNT) { - info.setHttpHeader(QByteArrayLiteral("DNT"), QByteArrayLiteral("1")); - } + if (m_sendDNT) { + info.setHttpHeader(QByteArrayLiteral("DNT"), QByteArrayLiteral("1")); + } - // NOTE: Here we can add custom headers for each webengine request, for example "User-Agent". + // NOTE: Here we can add custom headers for each webengine request, for example "User-Agent". - foreach (UrlInterceptor* interceptor, m_interceptors) { - interceptor->interceptRequest(info); - } + foreach (UrlInterceptor* interceptor, m_interceptors) { + interceptor->interceptRequest(info); + } } void NetworkUrlInterceptor::installUrlInterceptor(UrlInterceptor* interceptor) { - if (!m_interceptors.contains(interceptor)) { - m_interceptors.append(interceptor); - } + if (!m_interceptors.contains(interceptor)) { + m_interceptors.append(interceptor); + } } void NetworkUrlInterceptor::removeUrlInterceptor(UrlInterceptor* interceptor) { - m_interceptors.removeOne(interceptor); + m_interceptors.removeOne(interceptor); } void NetworkUrlInterceptor::loadSettings() { - m_sendDNT = qApp->settings()->value(GROUP(Browser), SETTING(Browser::SendDNT)).toBool(); + m_sendDNT = qApp->settings()->value(GROUP(Browser), SETTING(Browser::SendDNT)).toBool(); } diff --git a/src/network-web/networkurlinterceptor.h b/src/network-web/networkurlinterceptor.h index c3d42ceb4..840e4a8e3 100755 --- a/src/network-web/networkurlinterceptor.h +++ b/src/network-web/networkurlinterceptor.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -21,25 +22,24 @@ #include - class UrlInterceptor; class NetworkUrlInterceptor : public QWebEngineUrlRequestInterceptor { - Q_OBJECT + Q_OBJECT - public: - explicit NetworkUrlInterceptor(QObject* parent = nullptr); + public: + explicit NetworkUrlInterceptor(QObject* parent = nullptr); - void interceptRequest(QWebEngineUrlRequestInfo& info) Q_DECL_OVERRIDE; + void interceptRequest(QWebEngineUrlRequestInfo& info) Q_DECL_OVERRIDE; - void installUrlInterceptor(UrlInterceptor* interceptor); - void removeUrlInterceptor(UrlInterceptor* interceptor); + void installUrlInterceptor(UrlInterceptor* interceptor); + void removeUrlInterceptor(UrlInterceptor* interceptor); - void loadSettings(); + void loadSettings(); - private: - QList m_interceptors; - bool m_sendDNT; + private: + QList m_interceptors; + bool m_sendDNT; }; #endif // NETWORKURLINTERCEPTOR_H diff --git a/src/network-web/rssguardschemehandler.cpp b/src/network-web/rssguardschemehandler.cpp index 6381e47e7..8462ce79f 100755 --- a/src/network-web/rssguardschemehandler.cpp +++ b/src/network-web/rssguardschemehandler.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -26,37 +27,36 @@ #include #include +RssGuardSchemeHandler::RssGuardSchemeHandler(QObject* parent) : QWebEngineUrlSchemeHandler(parent) {} -RssGuardSchemeHandler::RssGuardSchemeHandler(QObject* parent) : QWebEngineUrlSchemeHandler(parent) { -} - -RssGuardSchemeHandler::~RssGuardSchemeHandler() { -} +RssGuardSchemeHandler::~RssGuardSchemeHandler() {} void RssGuardSchemeHandler::requestStarted(QWebEngineUrlRequestJob* job) { - // Decide which data we want. - QByteArray data = targetData(job->requestUrl()); + // Decide which data we want. + QByteArray data = targetData(job->requestUrl()); - if (data.isEmpty()) { - job->fail(QWebEngineUrlRequestJob::UrlNotFound); - } - else { - QBuffer* buf = new QBuffer(job); - buf->setData(data); - job->reply(QByteArray("text/html"), buf); - } + if (data.isEmpty()) { + job->fail(QWebEngineUrlRequestJob::UrlNotFound); + } + else { + QBuffer* buf = new QBuffer(job); + + buf->setData(data); + job->reply(QByteArray("text/html"), buf); + } } QByteArray RssGuardSchemeHandler::targetData(const QUrl& url) { - const QString& url_string = url.toString(); + const QString& url_string = url.toString(); - if (url_string.contains(QSL(ADBLOCK_ADBLOCKED_PAGE))) { - QUrlQuery query(url); - const QString& subscription = query.queryItemValue(QSL("subscription")); - const QString& rule = query.queryItemValue(QSL("rule")); - return qApp->skins()->adBlockedPage(subscription, rule).toUtf8(); - } - else { - return QByteArray(); - } + if (url_string.contains(QSL(ADBLOCK_ADBLOCKED_PAGE))) { + QUrlQuery query(url); + const QString& subscription = query.queryItemValue(QSL("subscription")); + const QString& rule = query.queryItemValue(QSL("rule")); + + return qApp->skins()->adBlockedPage(subscription, rule).toUtf8(); + } + else { + return QByteArray(); + } } diff --git a/src/network-web/rssguardschemehandler.h b/src/network-web/rssguardschemehandler.h index 4a05ac3dd..f8bbd49b3 100755 --- a/src/network-web/rssguardschemehandler.h +++ b/src/network-web/rssguardschemehandler.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -22,21 +23,20 @@ #include #include - class QWebEngineUrlRequestJob; class QBuffer; class RssGuardSchemeHandler : public QWebEngineUrlSchemeHandler { - Q_OBJECT + Q_OBJECT - public: - explicit RssGuardSchemeHandler(QObject* parent = nullptr); - virtual ~RssGuardSchemeHandler(); + public: + explicit RssGuardSchemeHandler(QObject* parent = nullptr); + virtual ~RssGuardSchemeHandler(); - void requestStarted(QWebEngineUrlRequestJob* job); + void requestStarted(QWebEngineUrlRequestJob* job); - private: - QByteArray targetData(const QUrl& url); + private: + QByteArray targetData(const QUrl& url); }; #endif // RSSGUARDSCHEMEHANDLER_H diff --git a/src/network-web/silentnetworkaccessmanager.cpp b/src/network-web/silentnetworkaccessmanager.cpp index a3a5e3010..c9171b234 100755 --- a/src/network-web/silentnetworkaccessmanager.cpp +++ b/src/network-web/silentnetworkaccessmanager.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,37 +20,37 @@ #include "miscellaneous/application.h" -#include #include +#include Q_GLOBAL_STATIC(SilentNetworkAccessManager, qz_silent_acmanager) - SilentNetworkAccessManager::SilentNetworkAccessManager(QObject* parent) - : BaseNetworkAccessManager(parent) { - connect(this, &SilentNetworkAccessManager::authenticationRequired, - this, &SilentNetworkAccessManager::onAuthenticationRequired, Qt::DirectConnection); + : BaseNetworkAccessManager(parent) { + connect(this, &SilentNetworkAccessManager::authenticationRequired, + this, &SilentNetworkAccessManager::onAuthenticationRequired, Qt::DirectConnection); } SilentNetworkAccessManager::~SilentNetworkAccessManager() { - qDebug("Destroying SilentNetworkAccessManager instance."); + qDebug("Destroying SilentNetworkAccessManager instance."); } SilentNetworkAccessManager* SilentNetworkAccessManager::instance() { - return qz_silent_acmanager(); + return qz_silent_acmanager(); } void SilentNetworkAccessManager::onAuthenticationRequired(QNetworkReply* reply, QAuthenticator* authenticator) { - if (reply->property("protected").toBool()) { - // This feed contains authentication information, it is good. - authenticator->setUser(reply->property("username").toString()); - authenticator->setPassword(reply->property("password").toString()); - reply->setProperty("authentication-given", true); - qDebug("Item '%s' requested authentication and got it.", qPrintable(reply->url().toString())); - } - else { - reply->setProperty("authentication-given", false); - // Authentication is required but this feed does not contain it. - qWarning("Item '%s' requested authentication but username/password is not available.", qPrintable(reply->url().toString())); - } + if (reply->property("protected").toBool()) { + // This feed contains authentication information, it is good. + authenticator->setUser(reply->property("username").toString()); + authenticator->setPassword(reply->property("password").toString()); + reply->setProperty("authentication-given", true); + qDebug("Item '%s' requested authentication and got it.", qPrintable(reply->url().toString())); + } + else { + reply->setProperty("authentication-given", false); + + // Authentication is required but this feed does not contain it. + qWarning("Item '%s' requested authentication but username/password is not available.", qPrintable(reply->url().toString())); + } } diff --git a/src/network-web/silentnetworkaccessmanager.h b/src/network-web/silentnetworkaccessmanager.h index 1f162ad67..f4c000532 100755 --- a/src/network-web/silentnetworkaccessmanager.h +++ b/src/network-web/silentnetworkaccessmanager.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,23 +23,24 @@ #include - // Network manager used for more communication for feeds. // This network manager does not provide any GUI interaction options. class SilentNetworkAccessManager : public BaseNetworkAccessManager { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit SilentNetworkAccessManager(QObject* parent = 0); - virtual ~SilentNetworkAccessManager(); + public: - // Returns pointer to global silent network manager - static SilentNetworkAccessManager* instance(); + // Constructors and destructors. + explicit SilentNetworkAccessManager(QObject* parent = 0); + virtual ~SilentNetworkAccessManager(); - public slots: - // This cannot do any GUI stuff. - void onAuthenticationRequired(QNetworkReply* reply, QAuthenticator* authenticator); + // Returns pointer to global silent network manager + static SilentNetworkAccessManager* instance(); + + public slots: + + // This cannot do any GUI stuff. + void onAuthenticationRequired(QNetworkReply* reply, QAuthenticator* authenticator); }; #endif // SILENTNETWORKACCESSMANAGER_H diff --git a/src/network-web/urlinterceptor.h b/src/network-web/urlinterceptor.h index 12f4e43f3..a42f1baab 100755 --- a/src/network-web/urlinterceptor.h +++ b/src/network-web/urlinterceptor.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // Copyright (C) 2010-2014 by David Rosca @@ -16,20 +17,19 @@ // You should have received a copy of the GNU General Public License // along with RSS Guard. If not, see . - #ifndef URLINTERCEPTOR_H #define URLINTERCEPTOR_H #include #include - class UrlInterceptor : public QObject { - Q_OBJECT + Q_OBJECT - public: - explicit UrlInterceptor(QObject* parent = Q_NULLPTR) : QObject(parent) { } - virtual void interceptRequest(QWebEngineUrlRequestInfo& info) = 0; + public: + explicit UrlInterceptor(QObject* parent = Q_NULLPTR) : QObject(parent) { } + + virtual void interceptRequest(QWebEngineUrlRequestInfo& info) = 0; }; #endif // URLINTERCEPTOR_H diff --git a/src/network-web/webfactory.cpp b/src/network-web/webfactory.cpp index 2b39cde1d..c18423217 100755 --- a/src/network-web/webfactory.cpp +++ b/src/network-web/webfactory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,208 +21,213 @@ #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" -#include -#include -#include #include +#include +#include +#include #if defined (USE_WEBENGINE) #include #endif - WebFactory::WebFactory(QObject* parent) - : QObject(parent), m_escapes(QMap()), m_deEscapes(QMap()) { + : QObject(parent), m_escapes(QMap()), m_deEscapes(QMap()) { #if defined (USE_WEBENGINE) - m_engineSettings = nullptr; + m_engineSettings = nullptr; #endif } WebFactory::~WebFactory() { #if defined (USE_WEBENGINE) - - if (m_engineSettings != nullptr && m_engineSettings->menu() != nullptr) { - m_engineSettings->menu()->deleteLater(); - } - + if (m_engineSettings != nullptr && m_engineSettings->menu() != nullptr) { + m_engineSettings->menu()->deleteLater(); + } #endif } bool WebFactory::sendMessageViaEmail(const Message& message) { - if (qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool()) { - const QString browser = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailExecutable)).toString(); - const QString arguments = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString(); - return QProcess::startDetached(QString("\"") + browser + QSL("\" ") + arguments.arg(message.m_title, - stripTags(message.m_contents))); - } - else { - // Send it via mailto protocol. - // NOTE: http://en.wikipedia.org/wiki/Mailto - return QDesktopServices::openUrl(QString("mailto:?subject=%1&body=%2").arg(QString(QUrl::toPercentEncoding(message.m_title)), - QString(QUrl::toPercentEncoding(stripTags(message.m_contents))))); - } + if (qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool()) { + const QString browser = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailExecutable)).toString(); + const QString arguments = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString(); + + return QProcess::startDetached(QString("\"") + browser + QSL("\" ") + arguments.arg(message.m_title, + stripTags(message.m_contents))); + } + else { + // Send it via mailto protocol. + // NOTE: http://en.wikipedia.org/wiki/Mailto + return QDesktopServices::openUrl(QString("mailto:?subject=%1&body=%2").arg(QString(QUrl::toPercentEncoding(message.m_title)), + QString(QUrl::toPercentEncoding(stripTags( + message.m_contents))))); + } } bool WebFactory::openUrlInExternalBrowser(const QString& url) { - if (qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserEnabled)).toBool()) { - const QString browser = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserExecutable)).toString(); - const QString arguments = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserArguments)).toString(); - const QString call_line = "\"" + browser + "\" \"" + arguments.arg(url) + "\""; - qDebug("Running command '%s'.", qPrintable(call_line)); - const bool result = QProcess::startDetached(call_line); + if (qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserEnabled)).toBool()) { + const QString browser = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserExecutable)).toString(); + const QString arguments = qApp->settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserArguments)).toString(); + const QString call_line = "\"" + browser + "\" \"" + arguments.arg(url) + "\""; - if (!result) { - qDebug("External web browser call failed."); - } + qDebug("Running command '%s'.", qPrintable(call_line)); + const bool result = QProcess::startDetached(call_line); - return result; - } - else { - return QDesktopServices::openUrl(url); - } + if (!result) { + qDebug("External web browser call failed."); + } + + return result; + } + else { + return QDesktopServices::openUrl(url); + } } QString WebFactory::stripTags(QString text) { - return text.remove(QRegExp(QSL("<[^>]*>"))); + return text.remove(QRegExp(QSL("<[^>]*>"))); } QString WebFactory::escapeHtml(const QString& html) { - if (m_escapes.isEmpty()) { - genereteEscapes(); - } + if (m_escapes.isEmpty()) { + genereteEscapes(); + } - QString output = html; - QMapIterator i(m_escapes); + QString output = html; - while (i.hasNext()) { - i.next(); - output = output.replace(i.key(), i.value()); - } + QMapIterator i(m_escapes); - return output; + while (i.hasNext()) { + i.next(); + output = output.replace(i.key(), i.value()); + } + + return output; } QString WebFactory::deEscapeHtml(const QString& text) { - if (m_deEscapes.isEmpty()) { - generateDeescapes(); - } + if (m_deEscapes.isEmpty()) { + generateDeescapes(); + } - QString output = text; - QMapIterator i(m_deEscapes); + QString output = text; - while (i.hasNext()) { - i.next(); - output = output.replace(i.key(), i.value()); - } + QMapIterator i(m_deEscapes); - return output; + while (i.hasNext()) { + i.next(); + output = output.replace(i.key(), i.value()); + } + + return output; } QString WebFactory::toSecondLevelDomain(const QUrl& url) { - const QString top_level_domain = url.topLevelDomain(); - const QString url_host = url.host(); + const QString top_level_domain = url.topLevelDomain(); + const QString url_host = url.host(); - if (top_level_domain.isEmpty() || url_host.isEmpty()) { - return QString(); - } + if (top_level_domain.isEmpty() || url_host.isEmpty()) { + return QString(); + } - QString domain = url_host.left(url_host.size() - top_level_domain.size()); + QString domain = url_host.left(url_host.size() - top_level_domain.size()); - if (domain.count(QL1C('.')) == 0) { - return url_host; - } + if (domain.count(QL1C('.')) == 0) { + return url_host; + } - while (domain.count(QL1C('.')) != 0) { - domain = domain.mid(domain.indexOf(QL1C('.')) + 1); - } + while (domain.count(QL1C('.')) != 0) { + domain = domain.mid(domain.indexOf(QL1C('.')) + 1); + } - return domain + top_level_domain; + return domain + top_level_domain; } #if defined (USE_WEBENGINE) QAction* WebFactory::engineSettingsAction() { - if (m_engineSettings == nullptr) { - m_engineSettings = new QAction(qApp->icons()->fromTheme(QSL("applications-internet")), tr("Web engine settings"), this); - m_engineSettings->setMenu(new QMenu()); - createMenu(m_engineSettings->menu()); - connect(m_engineSettings->menu(), SIGNAL(aboutToShow()), this, SLOT(createMenu())); - } + if (m_engineSettings == nullptr) { + m_engineSettings = new QAction(qApp->icons()->fromTheme(QSL("applications-internet")), tr("Web engine settings"), this); + m_engineSettings->setMenu(new QMenu()); + createMenu(m_engineSettings->menu()); + connect(m_engineSettings->menu(), SIGNAL(aboutToShow()), this, SLOT(createMenu())); + } - return m_engineSettings; + return m_engineSettings; } void WebFactory::createMenu(QMenu* menu) { - if (menu == nullptr) { - menu = qobject_cast(sender()); + if (menu == nullptr) { + menu = qobject_cast(sender()); - if (menu == nullptr) { - return; - } - } + if (menu == nullptr) { + return; + } + } - menu->clear(); - QList actions; - actions << createEngineSettingsAction(tr("Auto-load images"), QWebEngineSettings::AutoLoadImages); - actions << createEngineSettingsAction(tr("JS enabled"), QWebEngineSettings::JavascriptEnabled); - actions << createEngineSettingsAction(tr("JS can open popup windows"), QWebEngineSettings::JavascriptCanOpenWindows); - actions << createEngineSettingsAction(tr("JS can access clipboard"), QWebEngineSettings::JavascriptCanAccessClipboard); - actions << createEngineSettingsAction(tr("Hyperlinks can get focus"), QWebEngineSettings::LinksIncludedInFocusChain); - actions << createEngineSettingsAction(tr("Local storage enabled"), QWebEngineSettings::LocalStorageEnabled); - actions << createEngineSettingsAction(tr("Local content can access remote URLs"), QWebEngineSettings::LocalContentCanAccessRemoteUrls); - actions << createEngineSettingsAction(tr("XSS auditing enabled"), QWebEngineSettings::XSSAuditingEnabled); - actions << createEngineSettingsAction(tr("Spatial navigation enabled"), QWebEngineSettings::SpatialNavigationEnabled); - actions << createEngineSettingsAction(tr("Local content can access local files"), QWebEngineSettings::LocalContentCanAccessFileUrls); - actions << createEngineSettingsAction(tr("Hyperlink auditing enabled"), QWebEngineSettings::HyperlinkAuditingEnabled); - actions << createEngineSettingsAction(tr("Animate scrolling"), QWebEngineSettings::ScrollAnimatorEnabled); - actions << createEngineSettingsAction(tr("Error pages enabled"), QWebEngineSettings::ErrorPageEnabled); - actions << createEngineSettingsAction(tr("Plugins enabled"), QWebEngineSettings::PluginsEnabled); - actions << createEngineSettingsAction(tr("Fullscreen enabled"), QWebEngineSettings::FullScreenSupportEnabled); + menu->clear(); + QList actions; + actions << createEngineSettingsAction(tr("Auto-load images"), QWebEngineSettings::AutoLoadImages); + actions << createEngineSettingsAction(tr("JS enabled"), QWebEngineSettings::JavascriptEnabled); + actions << createEngineSettingsAction(tr("JS can open popup windows"), QWebEngineSettings::JavascriptCanOpenWindows); + actions << createEngineSettingsAction(tr("JS can access clipboard"), QWebEngineSettings::JavascriptCanAccessClipboard); + actions << createEngineSettingsAction(tr("Hyperlinks can get focus"), QWebEngineSettings::LinksIncludedInFocusChain); + actions << createEngineSettingsAction(tr("Local storage enabled"), QWebEngineSettings::LocalStorageEnabled); + actions << createEngineSettingsAction(tr("Local content can access remote URLs"), QWebEngineSettings::LocalContentCanAccessRemoteUrls); + actions << createEngineSettingsAction(tr("XSS auditing enabled"), QWebEngineSettings::XSSAuditingEnabled); + actions << createEngineSettingsAction(tr("Spatial navigation enabled"), QWebEngineSettings::SpatialNavigationEnabled); + actions << createEngineSettingsAction(tr("Local content can access local files"), QWebEngineSettings::LocalContentCanAccessFileUrls); + actions << createEngineSettingsAction(tr("Hyperlink auditing enabled"), QWebEngineSettings::HyperlinkAuditingEnabled); + actions << createEngineSettingsAction(tr("Animate scrolling"), QWebEngineSettings::ScrollAnimatorEnabled); + actions << createEngineSettingsAction(tr("Error pages enabled"), QWebEngineSettings::ErrorPageEnabled); + actions << createEngineSettingsAction(tr("Plugins enabled"), QWebEngineSettings::PluginsEnabled); + actions << createEngineSettingsAction(tr("Fullscreen enabled"), QWebEngineSettings::FullScreenSupportEnabled); #if !defined(Q_OS_LINUX) - actions << createEngineSettingsAction(tr("Screen capture enabled"), QWebEngineSettings::ScreenCaptureEnabled); - actions << createEngineSettingsAction(tr("WebGL enabled"), QWebEngineSettings::WebGLEnabled); - actions << createEngineSettingsAction(tr("Accelerate 2D canvas"), QWebEngineSettings::Accelerated2dCanvasEnabled); - actions << createEngineSettingsAction(tr("Print element backgrounds"), QWebEngineSettings::PrintElementBackgrounds); - actions << createEngineSettingsAction(tr("Allow running insecure content"), QWebEngineSettings::AllowRunningInsecureContent); - actions << createEngineSettingsAction(tr("Allow geolocation on insecure origins"), QWebEngineSettings::AllowGeolocationOnInsecureOrigins); + actions << createEngineSettingsAction(tr("Screen capture enabled"), QWebEngineSettings::ScreenCaptureEnabled); + actions << createEngineSettingsAction(tr("WebGL enabled"), QWebEngineSettings::WebGLEnabled); + actions << createEngineSettingsAction(tr("Accelerate 2D canvas"), QWebEngineSettings::Accelerated2dCanvasEnabled); + actions << createEngineSettingsAction(tr("Print element backgrounds"), QWebEngineSettings::PrintElementBackgrounds); + actions << createEngineSettingsAction(tr("Allow running insecure content"), QWebEngineSettings::AllowRunningInsecureContent); + actions << createEngineSettingsAction(tr("Allow geolocation on insecure origins"), QWebEngineSettings::AllowGeolocationOnInsecureOrigins); #endif - menu->addActions(actions); + menu->addActions(actions); } void WebFactory::webEngineSettingChanged(bool enabled) { - const QAction* const act = qobject_cast(sender()); - QWebEngineSettings::WebAttribute attribute = static_cast(act->data().toInt()); - qApp->settings()->setValue(WebEngineAttributes::ID, QString::number(static_cast(attribute)), enabled); - QWebEngineProfile::defaultProfile()->settings()->setAttribute(attribute, act->isChecked()); + const QAction* const act = qobject_cast(sender()); + + QWebEngineSettings::WebAttribute attribute = static_cast(act->data().toInt()); + qApp->settings()->setValue(WebEngineAttributes::ID, QString::number(static_cast(attribute)), enabled); + QWebEngineProfile::defaultProfile()->settings()->setAttribute(attribute, act->isChecked()); } QAction* WebFactory::createEngineSettingsAction(const QString& title, QWebEngineSettings::WebAttribute attribute) { - QAction* act = new QAction(title, m_engineSettings->menu()); - act->setData(attribute); - act->setCheckable(true); - act->setChecked(qApp->settings()->value(WebEngineAttributes::ID, QString::number(static_cast(attribute)), true).toBool()); - QWebEngineProfile::defaultProfile()->settings()->setAttribute(attribute, act->isChecked()); - connect(act, &QAction::toggled, this, &WebFactory::webEngineSettingChanged); - return act; + QAction* act = new QAction(title, m_engineSettings->menu()); + + act->setData(attribute); + act->setCheckable(true); + act->setChecked(qApp->settings()->value(WebEngineAttributes::ID, QString::number(static_cast(attribute)), true).toBool()); + QWebEngineProfile::defaultProfile()->settings()->setAttribute(attribute, act->isChecked()); + connect(act, &QAction::toggled, this, &WebFactory::webEngineSettingChanged); + return act; } + #endif void WebFactory::genereteEscapes() { - m_escapes[QSL("<")] = QL1C('<'); - m_escapes[QSL(">")] = QL1C('>'); - m_escapes[QSL("&")] = QL1C('&'); - m_escapes[QSL(""")] = QL1C('\"'); - m_escapes[QSL(" ")] = QL1C(' '); - m_escapes[QSL("±")] = QSL("±"); - m_escapes[QSL("×")] = QSL("×"); - m_escapes[QSL("'")] = QL1C('\''); + m_escapes[QSL("<")] = QL1C('<'); + m_escapes[QSL(">")] = QL1C('>'); + m_escapes[QSL("&")] = QL1C('&'); + m_escapes[QSL(""")] = QL1C('\"'); + m_escapes[QSL(" ")] = QL1C(' '); + m_escapes[QSL("±")] = QSL("±"); + m_escapes[QSL("×")] = QSL("×"); + m_escapes[QSL("'")] = QL1C('\''); } void WebFactory::generateDeescapes() { - m_deEscapes[QSL("<")] = QSL("<"); - m_deEscapes[QSL(">")] = QSL(">"); - m_deEscapes[QSL("&")] = QSL("&"); - m_deEscapes[QSL("\"")] = QSL("""); - m_deEscapes[QSL("±")] = QSL("±"); - m_deEscapes[QSL("×")] = QSL("×"); - m_deEscapes[QSL("\'")] = QSL("'"); + m_deEscapes[QSL("<")] = QSL("<"); + m_deEscapes[QSL(">")] = QSL(">"); + m_deEscapes[QSL("&")] = QSL("&"); + m_deEscapes[QSL("\"")] = QSL("""); + m_deEscapes[QSL("±")] = QSL("±"); + m_deEscapes[QSL("×")] = QSL("×"); + m_deEscapes[QSL("\'")] = QSL("'"); } diff --git a/src/network-web/webfactory.h b/src/network-web/webfactory.h index b82e93a4e..8dc87fc08 100755 --- a/src/network-web/webfactory.h +++ b/src/network-web/webfactory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -28,58 +29,61 @@ #include #endif - #if defined (USE_WEBENGINE) class QMenu; #endif class WebFactory : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Constructor. - explicit WebFactory(QObject* parent = nullptr); + public: - // Destructor. - virtual ~WebFactory(); + // Constructor. + explicit WebFactory(QObject* parent = nullptr); - // Strips "<....>" (HTML, XML) tags from given text. - QString stripTags(QString text); + // Destructor. + virtual ~WebFactory(); - // HTML entity escaping. - QString escapeHtml(const QString& html); - QString deEscapeHtml(const QString& text); + // Strips "<....>" (HTML, XML) tags from given text. + QString stripTags(QString text); - QString toSecondLevelDomain(const QUrl& url); + // HTML entity escaping. + QString escapeHtml(const QString& html); + QString deEscapeHtml(const QString& text); + + QString toSecondLevelDomain(const QUrl& url); #if defined (USE_WEBENGINE) - QAction* engineSettingsAction(); + QAction* engineSettingsAction(); #endif - public slots: - // Opens given string URL in external browser. - bool openUrlInExternalBrowser(const QString& url); - bool sendMessageViaEmail(const Message& message); + public slots: + + // Opens given string URL in external browser. + bool openUrlInExternalBrowser(const QString& url); + bool sendMessageViaEmail(const Message& message); #if defined (USE_WEBENGINE) - private slots: - void createMenu(QMenu* menu = nullptr); - void webEngineSettingChanged(bool enabled); - private: - QAction* createEngineSettingsAction(const QString& title, QWebEngineSettings::WebAttribute attribute); + private slots: + void createMenu(QMenu* menu = nullptr); + void webEngineSettingChanged(bool enabled); + + private: + QAction* createEngineSettingsAction(const QString& title, QWebEngineSettings::WebAttribute attribute); #endif - private: - // Escape sequences generators. - void genereteEscapes(); - void generateDeescapes(); + private: - QMap m_escapes; - QMap m_deEscapes; + // Escape sequences generators. + void genereteEscapes(); + void generateDeescapes(); + + QMap m_escapes; + QMap m_deEscapes; #if defined (USE_WEBENGINE) - QAction* m_engineSettings; + QAction* m_engineSettings; #endif }; diff --git a/src/network-web/webpage.cpp b/src/network-web/webpage.cpp index 98886cdfc..6d5605875 100755 --- a/src/network-web/webpage.cpp +++ b/src/network-web/webpage.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,52 +21,51 @@ #include "definitions/definitions.h" #include "gui/webviewer.h" -#include #include - +#include WebPage::WebPage(QObject* parent) : QWebEnginePage(parent) { - setBackgroundColor(Qt::transparent); + setBackgroundColor(Qt::transparent); } WebViewer* WebPage::view() const { - return qobject_cast(QWebEnginePage::view()); + return qobject_cast(QWebEnginePage::view()); } void WebPage::javaScriptAlert(const QUrl& securityOrigin, const QString& msg) { - QStringList parts = msg.split(QL1C('-')); + QStringList parts = msg.split(QL1C('-')); - if (parts.size() == 2) { - int message_id = parts.at(0).toInt(); - QString action = parts.at(1); + if (parts.size() == 2) { + int message_id = parts.at(0).toInt(); + QString action = parts.at(1); - if (action == QSL("read")) { - emit messageStatusChangeRequested(message_id, MarkRead); - } - else if (action == QSL("unread")) { - emit messageStatusChangeRequested(message_id, MarkUnread); - } - else if (action == QSL("starred")) { - emit messageStatusChangeRequested(message_id, MarkStarred); - } - else if (action == QSL("unstarred")) { - emit messageStatusChangeRequested(message_id, MarkUnstarred); - } - else { - QWebEnginePage::javaScriptAlert(securityOrigin, msg); - } - } - else { - QWebEnginePage::javaScriptAlert(securityOrigin, msg); - } + if (action == QSL("read")) { + emit messageStatusChangeRequested(message_id, MarkRead); + } + else if (action == QSL("unread")) { + emit messageStatusChangeRequested(message_id, MarkUnread); + } + else if (action == QSL("starred")) { + emit messageStatusChangeRequested(message_id, MarkStarred); + } + else if (action == QSL("unstarred")) { + emit messageStatusChangeRequested(message_id, MarkUnstarred); + } + else { + QWebEnginePage::javaScriptAlert(securityOrigin, msg); + } + } + else { + QWebEnginePage::javaScriptAlert(securityOrigin, msg); + } } bool WebPage::acceptNavigationRequest(const QUrl& url, NavigationType type, bool isMainFrame) { - if (url.host() == INTERNAL_URL_MESSAGE_HOST) { - setHtml(view()->messageContents(), QUrl(INTERNAL_URL_MESSAGE)); - return true; - } - else { - return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame); - } + if (url.host() == INTERNAL_URL_MESSAGE_HOST) { + setHtml(view()->messageContents(), QUrl(INTERNAL_URL_MESSAGE)); + return true; + } + else { + return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame); + } } diff --git a/src/network-web/webpage.h b/src/network-web/webpage.h index 3d6c7c68c..989b7fb9c 100755 --- a/src/network-web/webpage.h +++ b/src/network-web/webpage.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,30 +21,29 @@ #include - class WebViewer; class WebPage : public QWebEnginePage { - Q_OBJECT + Q_OBJECT - public: - enum MessageStatusChange { - MarkRead, - MarkUnread, - MarkStarred, - MarkUnstarred - }; + public: + enum MessageStatusChange { + MarkRead, + MarkUnread, + MarkStarred, + MarkUnstarred + }; - explicit WebPage(QObject* parent = 0); + explicit WebPage(QObject* parent = 0); - WebViewer* view() const; + WebViewer* view() const; - protected: - void javaScriptAlert(const QUrl& securityOrigin, const QString& msg); - bool acceptNavigationRequest(const QUrl& url, NavigationType type, bool isMainFrame); + protected: + void javaScriptAlert(const QUrl& securityOrigin, const QString& msg); + bool acceptNavigationRequest(const QUrl& url, NavigationType type, bool isMainFrame); - signals: - void messageStatusChangeRequested(int message_id, WebPage::MessageStatusChange change); + signals: + void messageStatusChangeRequested(int message_id, WebPage::MessageStatusChange change); }; #endif // WEBPAGE_H diff --git a/src/qtsingleapplication/qtlocalpeer.cpp b/src/qtsingleapplication/qtlocalpeer.cpp index 694da68a1..6b7356075 100755 --- a/src/qtsingleapplication/qtlocalpeer.cpp +++ b/src/qtsingleapplication/qtlocalpeer.cpp @@ -38,17 +38,19 @@ ** ****************************************************************************/ - #include "qtlocalpeer.h" #include -#include #include +#include #if defined(Q_OS_WIN) -#include #include -typedef BOOL(WINAPI* PProcessIdToSessionId)(DWORD, DWORD*); +#include + +typedef BOOL (WINAPI * PProcessIdToSessionId)(DWORD, DWORD*); + static PProcessIdToSessionId pProcessIdToSessionId = 0; + #endif #if defined(Q_OS_UNIX) || defined(Q_OS_OS2) #include @@ -68,167 +70,170 @@ namespace QtLP_Private { const char* QtLocalPeer::ack = "ack"; QtLocalPeer::QtLocalPeer(QObject* parent, const QString& appId) - : QObject(parent), id(appId) { - QString prefix = id; + : QObject(parent), id(appId) { + QString prefix = id; - if (id.isEmpty()) { - id = QCoreApplication::applicationFilePath(); + if (id.isEmpty()) { + id = QCoreApplication::applicationFilePath(); #if defined(Q_OS_WIN) - id = id.toLower(); + id = id.toLower(); #endif - prefix = id.section(QLatin1Char('/'), -1); - } + prefix = id.section(QLatin1Char('/'), -1); + } - prefix.remove(QRegExp("[^a-zA-Z]")); - prefix.truncate(6); - QByteArray idc = id.toUtf8(); - quint16 idNum = qChecksum(idc.constData(), idc.size()); - socketName = QLatin1String("qtsingleapp-") + prefix - + QLatin1Char('-') + QString::number(idNum, 16); + prefix.remove(QRegExp("[^a-zA-Z]")); + prefix.truncate(6); + QByteArray idc = id.toUtf8(); + quint16 idNum = qChecksum(idc.constData(), idc.size()); + + socketName = QLatin1String("qtsingleapp-") + prefix + + QLatin1Char('-') + QString::number(idNum, 16); #if defined(Q_OS_WIN) + if (!pProcessIdToSessionId) { + QLibrary lib("kernel32"); - if (!pProcessIdToSessionId) { - QLibrary lib("kernel32"); - pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); - } + pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); + } - if (pProcessIdToSessionId) { - DWORD sessionId = 0; - pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); - socketName += QLatin1Char('-') + QString::number(sessionId, 16); - } + if (pProcessIdToSessionId) { + DWORD sessionId = 0; + pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); + socketName += QLatin1Char('-') + QString::number(sessionId, 16); + } #else - socketName += QLatin1Char('-') + QString::number(::getuid(), 16); + socketName += QLatin1Char('-') + QString::number(::getuid(), 16); #endif - server = new QLocalServer(this); - QString lockName = QDir(QDir::tempPath()).absolutePath() - + QLatin1Char('/') + socketName - + QLatin1String("-lockfile"); - lockFile.setFileName(lockName); - lockFile.open(QIODevice::ReadWrite); + server = new QLocalServer(this); + QString lockName = QDir(QDir::tempPath()).absolutePath() + + QLatin1Char('/') + socketName + + QLatin1String("-lockfile"); + + lockFile.setFileName(lockName); + lockFile.open(QIODevice::ReadWrite); } QtLocalPeer::~QtLocalPeer() { - if (server != nullptr) { - server->close(); - } + if (server != nullptr) { + server->close(); + } } - - bool QtLocalPeer::isClient() { - if (lockFile.isLocked()) { - return false; - } + if (lockFile.isLocked()) { + return false; + } - if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) { - return true; - } + if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) { + return true; + } - bool res = server->listen(socketName); -#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) + bool res = server->listen(socketName); - // ### Workaround - if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { - QFile::remove(QDir::cleanPath(QDir::tempPath()) + QLatin1Char('/') + socketName); - res = server->listen(socketName); - } +#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4, 5, 0)) + // ### Workaround + if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { + QFile::remove(QDir::cleanPath(QDir::tempPath()) + QLatin1Char('/') + socketName); + res = server->listen(socketName); + } #endif - if (!res) { - qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); - } + if (!res) { + qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); + } - QObject::connect(server, &QLocalServer::newConnection, this, &QtLocalPeer::receiveConnection); - return false; + QObject::connect(server, &QLocalServer::newConnection, this, &QtLocalPeer::receiveConnection); + return false; } - bool QtLocalPeer::sendMessage(const QString& message, int timeout) { - if (!isClient()) { - return false; - } + if (!isClient()) { + return false; + } - QLocalSocket socket; - bool connOk = false; + QLocalSocket socket; + bool connOk = false; - for (int i = 0; i < 2; i++) { - // Try twice, in case the other instance is just starting up - socket.connectToServer(socketName); - connOk = socket.waitForConnected(timeout / 2); + for (int i = 0; i < 2; i++) { + // Try twice, in case the other instance is just starting up + socket.connectToServer(socketName); + connOk = socket.waitForConnected(timeout / 2); - if (connOk || i) { - break; - } + if (connOk || i) { + break; + } + + int ms = 250; - int ms = 250; #if defined(Q_OS_WIN) - Sleep(DWORD(ms)); + Sleep(DWORD(ms)); #else - struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; - nanosleep(&ts, nullptr); + struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; + + nanosleep(&ts, nullptr); #endif - } + } - if (!connOk) { - return false; - } + if (!connOk) { + return false; + } - QByteArray uMsg(message.toUtf8()); - QDataStream ds(&socket); - ds.writeBytes(uMsg.constData(), uMsg.size()); - bool res = socket.waitForBytesWritten(timeout); + QByteArray uMsg(message.toUtf8()); + QDataStream ds(&socket); - if (res) { - res &= socket.waitForReadyRead(timeout); // wait for ack + ds.writeBytes(uMsg.constData(), uMsg.size()); + bool res = socket.waitForBytesWritten(timeout); - if (res) { - res &= (socket.read(qstrlen(ack)) == ack); - } - } + if (res) { + res &= socket.waitForReadyRead(timeout); // wait for ack - return res; + if (res) { + res &= (socket.read(qstrlen(ack)) == ack); + } + } + + return res; } - void QtLocalPeer::receiveConnection() { - QLocalSocket* socket = server->nextPendingConnection(); + QLocalSocket* socket = server->nextPendingConnection(); - if (!socket) { - return; - } + if (!socket) { + return; + } - while (socket->bytesAvailable() < (int)sizeof(quint32)) { - socket->waitForReadyRead(); - } + while (socket->bytesAvailable() < (int)sizeof(quint32)) { + socket->waitForReadyRead(); + } - QDataStream ds(socket); - QByteArray uMsg; - quint32 remaining; - ds >> remaining; - uMsg.resize(remaining); - int got = 0; - char* uMsgBuf = uMsg.data(); + QDataStream ds(socket); + QByteArray uMsg; + quint32 remaining; - do { - got = ds.readRawData(uMsgBuf, remaining); - remaining -= got; - uMsgBuf += got; - } - while (remaining && got >= 0 && socket->waitForReadyRead(2000)); + ds >> remaining; + uMsg.resize(remaining); + int got = 0; + char* uMsgBuf = uMsg.data(); - if (got < 0) { - qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); - delete socket; - return; - } + do { + got = ds.readRawData(uMsgBuf, remaining); + remaining -= got; + uMsgBuf += got; + } + while (remaining && got >= 0 && socket->waitForReadyRead(2000)); - QString message(QString::fromUtf8(uMsg)); - socket->write(ack, qstrlen(ack)); - socket->waitForBytesWritten(1000); - socket->waitForDisconnected(1000); // make sure client reads ack - delete socket; - emit messageReceived(message); //### (might take a long time to return) + if (got < 0) { + qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); + delete socket; + return; + } + + QString message(QString::fromUtf8(uMsg)); + + socket->write(ack, qstrlen(ack)); + socket->waitForBytesWritten(1000); + socket->waitForDisconnected(1000); // make sure client reads ack + delete socket; + emit messageReceived(message); //### (might take a long time to return) } diff --git a/src/qtsingleapplication/qtlocalpeer.h b/src/qtsingleapplication/qtlocalpeer.h index bd61252b2..0078037f1 100755 --- a/src/qtsingleapplication/qtlocalpeer.h +++ b/src/qtsingleapplication/qtlocalpeer.h @@ -41,38 +41,39 @@ #ifndef QTLOCALPEER_H #define QTLOCALPEER_H +#include #include #include -#include #include "qtlockedfile.h" class QtLocalPeer : public QObject { - Q_OBJECT + Q_OBJECT - public: - QtLocalPeer(QObject* parent = 0, const QString& appId = QString()); - ~QtLocalPeer(); - bool isClient(); - bool sendMessage(const QString& message, int timeout); - QString applicationId() const { - return id; - } + public: + QtLocalPeer(QObject* parent = 0, const QString& appId = QString()); + ~QtLocalPeer(); + bool isClient(); + bool sendMessage(const QString& message, int timeout); + QString applicationId() const { + return id; + } - Q_SIGNALS: - void messageReceived(const QString& message); +Q_SIGNALS: + void messageReceived(const QString& message); - protected Q_SLOTS: - void receiveConnection(); + protected Q_SLOTS: + void receiveConnection(); - public: - QString id; - QString socketName; - QLocalServer* server; - QtLP_Private::QtLockedFile lockFile; + public: + QString id; + QString socketName; + QLocalServer* server; - private: - static const char* ack; + QtLP_Private::QtLockedFile lockFile; + + private: + static const char* ack; }; #endif // QTLOCALPEER_H diff --git a/src/qtsingleapplication/qtlockedfile.cpp b/src/qtsingleapplication/qtlockedfile.cpp index 35def70e9..8f51952f4 100755 --- a/src/qtsingleapplication/qtlockedfile.cpp +++ b/src/qtsingleapplication/qtlockedfile.cpp @@ -63,7 +63,7 @@ The lock provided by an instance of \e QtLockedFile is released whenever the program terminates. This is true even when the program crashes and no destructors are called. -*/ + */ /*! \enum QtLockedFile::LockMode @@ -72,21 +72,21 @@ \value ReadLock A read lock. \value WriteLock A write lock. \value NoLock Neither a read lock nor a write lock. -*/ + */ /*! Constructs an unlocked \e QtLockedFile object. This constructor behaves in the same way as \e QFile::QFile(). \sa QFile::QFile() -*/ + */ QtLockedFile::QtLockedFile() - : QFile() { + : QFile() { #ifdef Q_OS_WIN - wmutex = 0; - rmutex = 0; + wmutex = 0; + rmutex = 0; #endif - m_lock_mode = NoLock; + m_lock_mode = NoLock; } /*! @@ -95,36 +95,36 @@ QtLockedFile::QtLockedFile() QString&). \sa QFile::QFile() -*/ + */ QtLockedFile::QtLockedFile(const QString& name) - : QFile(name) { + : QFile(name) { #ifdef Q_OS_WIN - wmutex = 0; - rmutex = 0; + wmutex = 0; + rmutex = 0; #endif - m_lock_mode = NoLock; + m_lock_mode = NoLock; } /*! - Opens the file in OpenMode \a mode. + Opens the file in OpenMode \a mode. - This is identical to QFile::open(), with the one exception that the - Truncate mode flag is disallowed. Truncation would conflict with the - advisory file locking, since the file would be modified before the - write lock is obtained. If truncation is required, use resize(0) - after obtaining the write lock. + This is identical to QFile::open(), with the one exception that the + Truncate mode flag is disallowed. Truncation would conflict with the + advisory file locking, since the file would be modified before the + write lock is obtained. If truncation is required, use resize(0) + after obtaining the write lock. - Returns true if successful; otherwise false. + Returns true if successful; otherwise false. - \sa QFile::open(), QFile::resize() -*/ + \sa QFile::open(), QFile::resize() + */ bool QtLockedFile::open(OpenMode mode) { - if (mode & QIODevice::Truncate) { - qWarning("QtLockedFile::open(): Truncate mode not allowed."); - return false; - } + if (mode & QIODevice::Truncate) { + qWarning("QtLockedFile::open(): Truncate mode not allowed."); + return false; + } - return QFile::open(mode); + return QFile::open(mode); } /*! @@ -132,9 +132,9 @@ bool QtLockedFile::open(OpenMode mode) { otherwise returns \e false. \sa lockMode() -*/ + */ bool QtLockedFile::isLocked() const { - return m_lock_mode != NoLock; + return m_lock_mode != NoLock; } /*! @@ -142,9 +142,9 @@ bool QtLockedFile::isLocked() const { QtLockedFile::NoLock. \sa isLocked() -*/ + */ QtLockedFile::LockMode QtLockedFile::lockMode() const { - return m_lock_mode; + return m_lock_mode; } /*! @@ -166,7 +166,7 @@ QtLockedFile::LockMode QtLockedFile::lockMode() const { locked by this object, and \e false otherwise. \sa unlock(), isLocked(), lockMode() -*/ + */ /*! \fn bool QtLockedFile::unlock() @@ -179,11 +179,11 @@ QtLockedFile::LockMode QtLockedFile::lockMode() const { not locked by this object, and \e false otherwise. \sa lock(), isLocked(), lockMode() -*/ + */ /*! \fn QtLockedFile::~QtLockedFile() Destroys the \e QtLockedFile object. If any locks were held, they are released. -*/ + */ diff --git a/src/qtsingleapplication/qtlockedfile.h b/src/qtsingleapplication/qtlockedfile.h index bb9449d4e..ab26caaa8 100755 --- a/src/qtsingleapplication/qtlockedfile.h +++ b/src/qtsingleapplication/qtlockedfile.h @@ -64,35 +64,36 @@ namespace QtLP_Private { - class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile { - Q_OBJECT + class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile { + Q_OBJECT - public: - enum LockMode { NoLock = 0, ReadLock, WriteLock }; + public: + enum LockMode { NoLock = 0, ReadLock, WriteLock }; - QtLockedFile(); - QtLockedFile(const QString& name); - ~QtLockedFile(); + QtLockedFile(); + QtLockedFile(const QString& name); - bool open(OpenMode mode); + ~QtLockedFile(); - bool lock(LockMode mode, bool block = true); - bool unlock(); - bool isLocked() const; - LockMode lockMode() const; + bool open(OpenMode mode); - private: + bool lock(LockMode mode, bool block = true); + bool unlock(); + bool isLocked() const; + LockMode lockMode() const; + + private: #ifdef Q_OS_WIN - Qt::HANDLE wmutex; - Qt::HANDLE rmutex; - QVector rmutexes; - QString mutexname; - - Qt::HANDLE getMutexHandle(int idx, bool doCreate); - bool waitMutex(Qt::HANDLE mutex, bool doBlock); + Qt::HANDLE wmutex; + Qt::HANDLE rmutex; + QVector rmutexes; + QString mutexname; + Qt::HANDLE getMutexHandle(int idx, bool doCreate); + bool waitMutex(Qt::HANDLE mutex, bool doBlock); #endif - LockMode m_lock_mode; - }; + LockMode m_lock_mode; + }; + } #endif diff --git a/src/qtsingleapplication/qtlockedfile_unix.cpp b/src/qtsingleapplication/qtlockedfile_unix.cpp index 58a0f6f9a..cb1732431 100755 --- a/src/qtsingleapplication/qtlockedfile_unix.cpp +++ b/src/qtsingleapplication/qtlockedfile_unix.cpp @@ -38,92 +38,89 @@ ** ****************************************************************************/ -#include #include -#include #include +#include +#include #include "qtlockedfile.h" bool QtLockedFile::lock(LockMode mode, bool block) { - if (!isOpen()) { - qWarning("QtLockedFile::lock(): file is not opened"); - return false; - } + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } - if (mode == NoLock) { - return unlock(); - } + if (mode == NoLock) { + return unlock(); + } - if (mode == m_lock_mode) { - return true; - } + if (mode == m_lock_mode) { + return true; + } - if (m_lock_mode != NoLock) { - unlock(); - } + if (m_lock_mode != NoLock) { + unlock(); + } - struct flock fl; + struct flock fl; - fl.l_whence = SEEK_SET; + fl.l_whence = SEEK_SET; - fl.l_start = 0; + fl.l_start = 0; - fl.l_len = 0; + fl.l_len = 0; - fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; + fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; - int cmd = block ? F_SETLKW : F_SETLK; + int cmd = block ? F_SETLKW : F_SETLK; + int ret = fcntl(handle(), cmd, &fl); - int ret = fcntl(handle(), cmd, &fl); + if (ret == -1) { + if (errno != EINTR && errno != EAGAIN) { + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + } - if (ret == -1) { - if (errno != EINTR && errno != EAGAIN) { - qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); - } + return false; + } - return false; - } - - m_lock_mode = mode; - return true; + m_lock_mode = mode; + return true; } - bool QtLockedFile::unlock() { - if (!isOpen()) { - qWarning("QtLockedFile::unlock(): file is not opened"); - return false; - } + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } - if (!isLocked()) { - return true; - } + if (!isLocked()) { + return true; + } - struct flock fl; + struct flock fl; - fl.l_whence = SEEK_SET; + fl.l_whence = SEEK_SET; - fl.l_start = 0; + fl.l_start = 0; - fl.l_len = 0; + fl.l_len = 0; - fl.l_type = F_UNLCK; + fl.l_type = F_UNLCK; - int ret = fcntl(handle(), F_SETLKW, &fl); + int ret = fcntl(handle(), F_SETLKW, &fl); - if (ret == -1) { - qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); - return false; - } + if (ret == -1) { + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } - m_lock_mode = NoLock; - return true; + m_lock_mode = NoLock; + return true; } QtLockedFile::~QtLockedFile() { - if (isOpen()) { - unlock(); - } + if (isOpen()) { + unlock(); + } } - diff --git a/src/qtsingleapplication/qtlockedfile_win.cpp b/src/qtsingleapplication/qtlockedfile_win.cpp index f439b92af..f819ddf7d 100755 --- a/src/qtsingleapplication/qtlockedfile_win.cpp +++ b/src/qtsingleapplication/qtlockedfile_win.cpp @@ -43,6 +43,7 @@ #include #define MUTEX_PREFIX "QtLockedFile mutex " + // Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS #define MAX_READERS MAXIMUM_WAIT_OBJECTS @@ -51,198 +52,197 @@ #endif Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) { - if (mutexname.isEmpty()) { - QFileInfo fi(*this); - mutexname = QString::fromLatin1(MUTEX_PREFIX) - + fi.absoluteFilePath().toLower(); - } + if (mutexname.isEmpty()) { + QFileInfo fi(*this); - QString mname(mutexname); + mutexname = QString::fromLatin1(MUTEX_PREFIX) + + fi.absoluteFilePath().toLower(); + } - if (idx >= 0) { - mname += QString::number(idx); - } + QString mname(mutexname); - Qt::HANDLE mutex; + if (idx >= 0) { + mname += QString::number(idx); + } - if (doCreate) { - QT_WA({ mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, - { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); }); + Qt::HANDLE mutex; - if (!mutex) { - qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); - return 0; - } - } - else { - QT_WA({ mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, - { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); }); + if (doCreate) { + QT_WA({ mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, + { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); }); - if (!mutex) { - if (GetLastError() != ERROR_FILE_NOT_FOUND) { - qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); - } + if (!mutex) { + qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); + return 0; + } + } + else { + QT_WA({ mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, + { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); }); - return 0; - } - } + if (!mutex) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) { + qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); + } - return mutex; + return 0; + } + } + + return mutex; } bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) { - Q_ASSERT(mutex); - DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); + Q_ASSERT(mutex); + DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); - switch (res) { - case WAIT_OBJECT_0: - case WAIT_ABANDONED: - return true; - break; + switch (res) { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + return true; + break; - case WAIT_TIMEOUT: - break; + case WAIT_TIMEOUT: + break; - default: - qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); - } + default: + qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); + } - return false; + return false; } - - bool QtLockedFile::lock(LockMode mode, bool block) { - if (!isOpen()) { - qWarning("QtLockedFile::lock(): file is not opened"); - return false; - } + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } - if (mode == NoLock) { - return unlock(); - } + if (mode == NoLock) { + return unlock(); + } - if (mode == m_lock_mode) { - return true; - } + if (mode == m_lock_mode) { + return true; + } - if (m_lock_mode != NoLock) { - unlock(); - } + if (m_lock_mode != NoLock) { + unlock(); + } - if (!wmutex && !(wmutex = getMutexHandle(-1, true))) { - return false; - } + if (!wmutex && !(wmutex = getMutexHandle(-1, true))) { + return false; + } - if (!waitMutex(wmutex, block)) { - return false; - } + if (!waitMutex(wmutex, block)) { + return false; + } - if (mode == ReadLock) { - int idx = 0; + if (mode == ReadLock) { + int idx = 0; - for (; idx < MAX_READERS; idx++) { - rmutex = getMutexHandle(idx, false); + for (; idx < MAX_READERS; idx++) { + rmutex = getMutexHandle(idx, false); - if (!rmutex || waitMutex(rmutex, false)) { - break; - } + if (!rmutex || waitMutex(rmutex, false)) { + break; + } - CloseHandle(rmutex); - } + CloseHandle(rmutex); + } - bool ok = true; + bool ok = true; - if (idx >= MAX_READERS) { - qWarning("QtLockedFile::lock(): too many readers"); - rmutex = 0; - ok = false; - } - else if (!rmutex) { - rmutex = getMutexHandle(idx, true); + if (idx >= MAX_READERS) { + qWarning("QtLockedFile::lock(): too many readers"); + rmutex = 0; + ok = false; + } + else if (!rmutex) { + rmutex = getMutexHandle(idx, true); - if (!rmutex || !waitMutex(rmutex, false)) { - ok = false; - } - } + if (!rmutex || !waitMutex(rmutex, false)) { + ok = false; + } + } - if (!ok && rmutex) { - CloseHandle(rmutex); - rmutex = 0; - } + if (!ok && rmutex) { + CloseHandle(rmutex); + rmutex = 0; + } - ReleaseMutex(wmutex); + ReleaseMutex(wmutex); - if (!ok) { - return false; - } - } - else { - Q_ASSERT(rmutexes.isEmpty()); + if (!ok) { + return false; + } + } + else { + Q_ASSERT(rmutexes.isEmpty()); - for (int i = 0; i < MAX_READERS; i++) { - Qt::HANDLE mutex = getMutexHandle(i, false); + for (int i = 0; i < MAX_READERS; i++) { + Qt::HANDLE mutex = getMutexHandle(i, false); - if (mutex) { - rmutexes.append(mutex); - } - } + if (mutex) { + rmutexes.append(mutex); + } + } - if (rmutexes.size()) { - DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), - TRUE, block ? INFINITE : 0); + if (rmutexes.size()) { + DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), + TRUE, block ? INFINITE : 0); - if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { - if (res != WAIT_TIMEOUT) { - qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); - } + if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { + if (res != WAIT_TIMEOUT) { + qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); + } - m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky - unlock(); - return false; - } - } - } + m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky + unlock(); + return false; + } + } + } - m_lock_mode = mode; - return true; + m_lock_mode = mode; + return true; } bool QtLockedFile::unlock() { - if (!isOpen()) { - qWarning("QtLockedFile::unlock(): file is not opened"); - return false; - } + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } - if (!isLocked()) { - return true; - } + if (!isLocked()) { + return true; + } - if (m_lock_mode == ReadLock) { - ReleaseMutex(rmutex); - CloseHandle(rmutex); - rmutex = 0; - } - else { - foreach (Qt::HANDLE mutex, rmutexes) { - ReleaseMutex(mutex); - CloseHandle(mutex); - } + if (m_lock_mode == ReadLock) { + ReleaseMutex(rmutex); + CloseHandle(rmutex); + rmutex = 0; + } + else { + foreach (Qt::HANDLE mutex, rmutexes) { + ReleaseMutex(mutex); + CloseHandle(mutex); + } - rmutexes.clear(); - ReleaseMutex(wmutex); - } + rmutexes.clear(); + ReleaseMutex(wmutex); + } - m_lock_mode = QtLockedFile::NoLock; - return true; + m_lock_mode = QtLockedFile::NoLock; + return true; } QtLockedFile::~QtLockedFile() { - if (isOpen()) { - unlock(); - } + if (isOpen()) { + unlock(); + } - if (wmutex) { - CloseHandle(wmutex); - } + if (wmutex) { + CloseHandle(wmutex); + } } diff --git a/src/qtsingleapplication/qtsingleapplication.cpp b/src/qtsingleapplication/qtsingleapplication.cpp index f4ae963ab..a4ad36e7a 100755 --- a/src/qtsingleapplication/qtsingleapplication.cpp +++ b/src/qtsingleapplication/qtsingleapplication.cpp @@ -38,12 +38,10 @@ ** ****************************************************************************/ - -#include "qtsingleapplication.h" #include "qtlocalpeer.h" +#include "qtsingleapplication.h" #include - /*! \class QtSingleApplication qtsingleapplication.h \brief The QtSingleApplication class provides an API to detect and @@ -130,16 +128,14 @@ library. \sa QtSingleCoreApplication -*/ - + */ void QtSingleApplication::sysInit(const QString& appId) { - actWin = 0; - peer = new QtLocalPeer(this, appId); - connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::messageReceived); + actWin = 0; + peer = new QtLocalPeer(this, appId); + connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::messageReceived); } - /*! Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc, \a @@ -148,23 +144,22 @@ void QtSingleApplication::sysInit(const QString& appId) { If you are creating a console application (i.e. setting \a GUIenabled to false), you may consider using QtSingleCoreApplication instead. -*/ + */ QtSingleApplication::QtSingleApplication(int& argc, char** argv, bool GUIenabled) - : QApplication(argc, argv, GUIenabled) { - sysInit(); + : QApplication(argc, argv, GUIenabled) { + sysInit(); } - /*! Creates a QtSingleApplication object with the application identifier \a appId. \a argc and \a argv are passed on to the QAppliation constructor. -*/ + */ QtSingleApplication::QtSingleApplication(const QString& appId, int& argc, char** argv) - : QApplication(argc, argv) { - sysInit(appId); + : QApplication(argc, argv) { + sysInit(appId); } #if QT_VERSION < 0x050000 @@ -173,52 +168,52 @@ QtSingleApplication::QtSingleApplication(const QString& appId, int& argc, char** Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc, \a argv, and \a type are passed on to the QAppliation constructor. -*/ + */ QtSingleApplication::QtSingleApplication(int& argc, char** argv, Type type) - : QApplication(argc, argv, type) { - sysInit(); + : QApplication(argc, argv, type) { + sysInit(); } - # if defined(Q_WS_X11) + /*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, - and \a cmap are passed on to the QApplication constructor. -*/ + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, + and \a cmap are passed on to the QApplication constructor. + */ QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, visual, cmap) { - sysInit(); + : QApplication(dpy, visual, cmap) { + sysInit(); } /*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a - argv, \a visual, and \a cmap are passed on to the QApplication - constructor. -*/ + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a + argv, \a visual, and \a cmap are passed on to the QApplication + constructor. + */ QtSingleApplication::QtSingleApplication(Display* dpy, int& argc, char** argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) { - sysInit(); + : QApplication(dpy, argc, argv, visual, cmap) { + sysInit(); } /*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be \a appId. \a dpy, \a argc, \a - argv, \a visual, and \a cmap are passed on to the QApplication - constructor. -*/ + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be \a appId. \a dpy, \a argc, \a + argv, \a visual, and \a cmap are passed on to the QApplication + constructor. + */ QtSingleApplication::QtSingleApplication(Display* dpy, const QString& appId, int argc, char** argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) { - sysInit(appId); + : QApplication(dpy, argc, argv, visual, cmap) { + sysInit(appId); } + # endif // Q_WS_X11 #endif // QT_VERSION < 0x050000 - /*! Returns true if another instance of this application is running; otherwise false. @@ -228,13 +223,12 @@ QtSingleApplication::QtSingleApplication(Display* dpy, const QString& appId, int another session). \sa sendMessage() -*/ + */ bool QtSingleApplication::isRunning() { - return peer->isClient(); + return peer->isClient(); } - /*! Tries to send the text \a message to the currently running instance. The QtSingleApplication object in the running instance @@ -247,81 +241,77 @@ bool QtSingleApplication::isRunning() { message within \a timeout milliseconds, this function return false. \sa isRunning(), messageReceived() -*/ + */ bool QtSingleApplication::sendMessage(const QString& message, int timeout) { - return peer->sendMessage(message, timeout); + return peer->sendMessage(message, timeout); } - /*! Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application. -*/ + */ QString QtSingleApplication::id() const { - return peer->applicationId(); + return peer->applicationId(); } - /*! - Sets the activation window of this application to \a aw. The - activation window is the widget that will be activated by - activateWindow(). This is typically the application's main window. + Sets the activation window of this application to \a aw. The + activation window is the widget that will be activated by + activateWindow(). This is typically the application's main window. - If \a activateOnMessage is true (the default), the window will be - activated automatically every time a message is received, just prior - to the messageReceived() signal being emitted. + If \a activateOnMessage is true (the default), the window will be + activated automatically every time a message is received, just prior + to the messageReceived() signal being emitted. - \sa activateWindow(), messageReceived() -*/ + \sa activateWindow(), messageReceived() + */ void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) { - actWin = aw; + actWin = aw; - if (activateOnMessage) { - connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow); - } - else { - disconnect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow); - } + if (activateOnMessage) { + connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow); + } + else { + disconnect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow); + } } - /*! Returns the applications activation window if one has been set by calling setActivationWindow(), otherwise returns 0. \sa setActivationWindow() -*/ + */ QWidget* QtSingleApplication::activationWindow() const { - return actWin; + return actWin; } - /*! - De-minimizes, raises, and activates this application's activation window. - This function does nothing if no activation window has been set. + De-minimizes, raises, and activates this application's activation window. + This function does nothing if no activation window has been set. - This is a convenience function to show the user that this - application instance has been activated when he has tried to start - another instance. + This is a convenience function to show the user that this + application instance has been activated when he has tried to start + another instance. - This function should typically be called in response to the - messageReceived() signal. By default, that will happen - automatically, if an activation window has been set. + This function should typically be called in response to the + messageReceived() signal. By default, that will happen + automatically, if an activation window has been set. - \sa setActivationWindow(), messageReceived(), initialize() -*/ + \sa setActivationWindow(), messageReceived(), initialize() + */ void QtSingleApplication::activateWindow() { - if (actWin) { - actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); - actWin->raise(); - actWin->activateWindow(); - } + if (actWin) { + actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); + actWin->raise(); + actWin->activateWindow(); + } } void QtSingleApplication::finish() { - delete peer; - peer = 0; + delete peer; + peer = 0; } /*! @@ -331,11 +321,10 @@ void QtSingleApplication::finish() { message from another instance of this application. \sa sendMessage(), setActivationWindow(), activateWindow() -*/ - + */ /*! \fn void QtSingleApplication::initialize(bool dummy = true) \obsolete -*/ + */ diff --git a/src/qtsingleapplication/qtsingleapplication.h b/src/qtsingleapplication/qtsingleapplication.h index 383c97821..d33e358b1 100755 --- a/src/qtsingleapplication/qtsingleapplication.h +++ b/src/qtsingleapplication/qtsingleapplication.h @@ -62,46 +62,44 @@ class QtLocalPeer; #endif class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication { - Q_OBJECT + Q_OBJECT - public: - QtSingleApplication(int& argc, char** argv, bool GUIenabled = true); - QtSingleApplication(const QString& id, int& argc, char** argv); + public: + QtSingleApplication(int& argc, char** argv, bool GUIenabled = true); + QtSingleApplication(const QString& id, int& argc, char** argv); #if QT_VERSION < 0x050000 - QtSingleApplication(int& argc, char** argv, Type type); + QtSingleApplication(int& argc, char** argv, Type type); # if defined(Q_WS_X11) - QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); - QtSingleApplication(Display* dpy, int& argc, char** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0); - QtSingleApplication(Display* dpy, const QString& appId, int argc, char** argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); + QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); + QtSingleApplication(Display* dpy, int& argc, char** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0); + QtSingleApplication(Display* dpy, const QString& appId, int argc, char** argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); # endif // Q_WS_X11 #endif // QT_VERSION < 0x050000 - bool isRunning(); - QString id() const; + bool isRunning(); + QString id() const; - void setActivationWindow(QWidget* aw, bool activateOnMessage = true); - QWidget* activationWindow() const; + void setActivationWindow(QWidget* aw, bool activateOnMessage = true); + QWidget* activationWindow() const; - // Obsolete: - void initialize(bool dummy = true) { - isRunning(); - Q_UNUSED(dummy) - } + // Obsolete: + void initialize(bool dummy = true) { + isRunning(); + Q_UNUSED(dummy) + } - public Q_SLOTS: - bool sendMessage(const QString& message, int timeout = 5000); - void activateWindow(); - void finish(); + public Q_SLOTS: + bool sendMessage(const QString& message, int timeout = 5000); + void activateWindow(); + void finish(); +Q_SIGNALS: + void messageReceived(const QString& message); - Q_SIGNALS: - void messageReceived(const QString& message); - - - private: - void sysInit(const QString& appId = QString()); - QtLocalPeer* peer; - QWidget* actWin; + private: + void sysInit(const QString& appId = QString()); + QtLocalPeer* peer; + QWidget* actWin; }; #endif // QTSINGLEAPPLICATION_H diff --git a/src/qtsingleapplication/qtsinglecoreapplication.cpp b/src/qtsingleapplication/qtsinglecoreapplication.cpp index 7f31002b8..cdbc75ee0 100755 --- a/src/qtsingleapplication/qtsinglecoreapplication.cpp +++ b/src/qtsingleapplication/qtsinglecoreapplication.cpp @@ -38,9 +38,8 @@ ** ****************************************************************************/ - -#include "qtsinglecoreapplication.h" #include "qtlocalpeer.h" +#include "qtsinglecoreapplication.h" /*! \class QtSingleCoreApplication qtsinglecoreapplication.h @@ -62,33 +61,31 @@ command-line tool that sends commands to a GUI application. \sa QtSingleApplication -*/ + */ /*! Creates a QtSingleCoreApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc and \a argv are passed on to the QCoreAppliation constructor. -*/ + */ QtSingleCoreApplication::QtSingleCoreApplication(int& argc, char** argv) - : QCoreApplication(argc, argv) { - peer = new QtLocalPeer(this); - connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleCoreApplication::messageReceived); + : QCoreApplication(argc, argv) { + peer = new QtLocalPeer(this); + connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleCoreApplication::messageReceived); } - /*! Creates a QtSingleCoreApplication object with the application identifier \a appId. \a argc and \a argv are passed on to the QCoreAppliation constructor. -*/ + */ QtSingleCoreApplication::QtSingleCoreApplication(const QString& appId, int& argc, char** argv) - : QCoreApplication(argc, argv) { - peer = new QtLocalPeer(this, appId); - connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleCoreApplication::messageReceived); + : QCoreApplication(argc, argv) { + peer = new QtLocalPeer(this, appId); + connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleCoreApplication::messageReceived); } - /*! Returns true if another instance of this application is running; otherwise false. @@ -98,13 +95,12 @@ QtSingleCoreApplication::QtSingleCoreApplication(const QString& appId, int& argc another session). \sa sendMessage() -*/ + */ bool QtSingleCoreApplication::isRunning() { - return peer->isClient(); + return peer->isClient(); } - /*! Tries to send the text \a message to the currently running instance. The QtSingleCoreApplication object in the running instance @@ -117,23 +113,21 @@ bool QtSingleCoreApplication::isRunning() { message within \a timeout milliseconds, this function return false. \sa isRunning(), messageReceived() -*/ + */ bool QtSingleCoreApplication::sendMessage(const QString& message, int timeout) { - return peer->sendMessage(message, timeout); + return peer->sendMessage(message, timeout); } - /*! Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application. -*/ + */ QString QtSingleCoreApplication::id() const { - return peer->applicationId(); + return peer->applicationId(); } - /*! \fn void QtSingleCoreApplication::messageReceived(const QString& message) @@ -141,4 +135,4 @@ QString QtSingleCoreApplication::id() const { message from another instance of this application. \sa sendMessage() -*/ + */ diff --git a/src/qtsingleapplication/qtsinglecoreapplication.h b/src/qtsingleapplication/qtsinglecoreapplication.h index 9b6d69f04..8342be0be 100755 --- a/src/qtsingleapplication/qtsinglecoreapplication.h +++ b/src/qtsingleapplication/qtsinglecoreapplication.h @@ -46,25 +46,23 @@ class QtLocalPeer; class QtSingleCoreApplication : public QCoreApplication { - Q_OBJECT + Q_OBJECT - public: - QtSingleCoreApplication(int& argc, char** argv); - QtSingleCoreApplication(const QString& id, int& argc, char** argv); + public: + QtSingleCoreApplication(int& argc, char** argv); + QtSingleCoreApplication(const QString& id, int& argc, char** argv); - bool isRunning(); - QString id() const; + bool isRunning(); + QString id() const; - public Q_SLOTS: - bool sendMessage(const QString& message, int timeout = 5000); + public Q_SLOTS: + bool sendMessage(const QString& message, int timeout = 5000); +Q_SIGNALS: + void messageReceived(const QString& message); - Q_SIGNALS: - void messageReceived(const QString& message); - - - private: - QtLocalPeer* peer; + private: + QtLocalPeer* peer; }; #endif // QTSINGLECOREAPPLICATION_H diff --git a/src/services/abstract/accountcheckmodel.cpp b/src/services/abstract/accountcheckmodel.cpp index 84325acaf..93e670deb 100755 --- a/src/services/abstract/accountcheckmodel.cpp +++ b/src/services/abstract/accountcheckmodel.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,261 +22,261 @@ #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" - AccountCheckModel::AccountCheckModel(QObject* parent) - : QAbstractItemModel(parent), m_rootItem(nullptr), m_checkStates(QHash()), m_recursiveChange(false) { -} + : QAbstractItemModel(parent), m_rootItem(nullptr), m_checkStates(QHash()), m_recursiveChange(false) {} -AccountCheckModel::~AccountCheckModel() { -} +AccountCheckModel::~AccountCheckModel() {} RootItem* AccountCheckModel::itemForIndex(const QModelIndex& index) const { - if (index.isValid() && index.model() == this) { - return static_cast(index.internalPointer()); - } - else { - return m_rootItem; - } + if (index.isValid() && index.model() == this) { + return static_cast(index.internalPointer()); + } + else { + return m_rootItem; + } } RootItem* AccountCheckModel::rootItem() const { - return m_rootItem; + return m_rootItem; } void AccountCheckModel::setRootItem(RootItem* root_item) { - if (m_rootItem != nullptr) { - delete m_rootItem; - } + if (m_rootItem != nullptr) { + delete m_rootItem; + } - m_rootItem = root_item; + m_rootItem = root_item; } void AccountCheckModel::checkAllItems() { - if (m_rootItem != nullptr) { - foreach (RootItem* root_child, m_rootItem->childItems()) { - if (root_child->kind() == RootItemKind::Feed || root_child->kind() == RootItemKind::Category) { - setItemChecked(root_child, Qt::Checked); - } - } - } + if (m_rootItem != nullptr) { + foreach (RootItem* root_child, m_rootItem->childItems()) { + if (root_child->kind() == RootItemKind::Feed || root_child->kind() == RootItemKind::Category) { + setItemChecked(root_child, Qt::Checked); + } + } + } } void AccountCheckModel::uncheckAllItems() { - if (m_rootItem != nullptr) { - foreach (RootItem* root_child, m_rootItem->childItems()) { - if (root_child->kind() == RootItemKind::Feed || root_child->kind() == RootItemKind::Category) { - setData(indexForItem(root_child), Qt::Unchecked, Qt::CheckStateRole); - } - } - } + if (m_rootItem != nullptr) { + foreach (RootItem* root_child, m_rootItem->childItems()) { + if (root_child->kind() == RootItemKind::Feed || root_child->kind() == RootItemKind::Category) { + setData(indexForItem(root_child), Qt::Unchecked, Qt::CheckStateRole); + } + } + } } QModelIndex AccountCheckModel::index(int row, int column, const QModelIndex& parent) const { - if (!hasIndex(row, column, parent)) { - return QModelIndex(); - } + if (!hasIndex(row, column, parent)) { + return QModelIndex(); + } - RootItem* parent_item = itemForIndex(parent); - RootItem* child_item = parent_item->child(row); + RootItem* parent_item = itemForIndex(parent); + RootItem* child_item = parent_item->child(row); - if (child_item) { - return createIndex(row, column, child_item); - } - else { - return QModelIndex(); - } + if (child_item) { + return createIndex(row, column, child_item); + } + else { + return QModelIndex(); + } } QModelIndex AccountCheckModel::indexForItem(RootItem* item) const { - if (item == nullptr || item->kind() == RootItemKind::ServiceRoot || item->kind() == RootItemKind::Root) { - // Root item lies on invalid index. - return QModelIndex(); - } + if (item == nullptr || item->kind() == RootItemKind::ServiceRoot || item->kind() == RootItemKind::Root) { + // Root item lies on invalid index. + return QModelIndex(); + } - QList parents; - // Start with root item (which obviously has invalid index). - parents << indexForItem(m_rootItem); + QList parents; - while (!parents.isEmpty()) { - QModelIndex active_index = parents.takeFirst(); - int row_count = rowCount(active_index); + // Start with root item (which obviously has invalid index). + parents << indexForItem(m_rootItem); - if (row_count > 0) { - // This index has children. - // Lets take a look if our target item is among them. - RootItem* active_item = itemForIndex(active_index); - int candidate_index = active_item->childItems().indexOf(item); + while (!parents.isEmpty()) { + QModelIndex active_index = parents.takeFirst(); + int row_count = rowCount(active_index); - if (candidate_index >= 0) { - // We found our item. - return index(candidate_index, 0, active_index); - } - else { - // Item is not found, add all "categories" from active_item. - for (int i = 0; i < row_count; i++) { - RootItem* possible_category = active_item->child(i); + if (row_count > 0) { + // This index has children. + // Lets take a look if our target item is among them. + RootItem* active_item = itemForIndex(active_index); + int candidate_index = active_item->childItems().indexOf(item); - if (possible_category->kind() == RootItemKind::Category) { - parents << index(i, 0, active_index); - } - } - } - } - } + if (candidate_index >= 0) { + // We found our item. + return index(candidate_index, 0, active_index); + } + else { + // Item is not found, add all "categories" from active_item. + for (int i = 0; i < row_count; i++) { + RootItem* possible_category = active_item->child(i); - return QModelIndex(); + if (possible_category->kind() == RootItemKind::Category) { + parents << index(i, 0, active_index); + } + } + } + } + } + + return QModelIndex(); } QModelIndex AccountCheckModel::parent(const QModelIndex& child) const { - if (!child.isValid()) { - return QModelIndex(); - } + if (!child.isValid()) { + return QModelIndex(); + } - RootItem* child_item = itemForIndex(child); - RootItem* parent_item = child_item->parent(); + RootItem* child_item = itemForIndex(child); + RootItem* parent_item = child_item->parent(); - if (parent_item == m_rootItem) { - return QModelIndex(); - } - else { - return createIndex(parent_item->row(), 0, parent_item); - } + if (parent_item == m_rootItem) { + return QModelIndex(); + } + else { + return createIndex(parent_item->row(), 0, parent_item); + } } int AccountCheckModel::rowCount(const QModelIndex& parent) const { - if (parent.column() > 0) { - return 0; - } - else { - RootItem* item = itemForIndex(parent); + if (parent.column() > 0) { + return 0; + } + else { + RootItem* item = itemForIndex(parent); - if (item != nullptr) { - return item->childCount(); - } - else { - return 0; - } - } + if (item != nullptr) { + return item->childCount(); + } + else { + return 0; + } + } } int AccountCheckModel::columnCount(const QModelIndex& parent) const { - Q_UNUSED(parent) - return 1; + Q_UNUSED(parent) + return 1; } QVariant AccountCheckModel::data(const QModelIndex& index, int role) const { - if (index.column() != 0) { - return QVariant(); - } + if (index.column() != 0) { + return QVariant(); + } - RootItem* item = itemForIndex(index); + RootItem* item = itemForIndex(index); - if (role == Qt::CheckStateRole) { - if (m_checkStates.contains(item)) { - return m_checkStates.value(item); - } - else { - return static_cast(Qt::Unchecked); - } - } - else if (role == Qt::DecorationRole) { - switch (item->kind()) { - case RootItemKind::Category: - case RootItemKind::Bin: - case RootItemKind::Feed: - return item->icon(); + if (role == Qt::CheckStateRole) { + if (m_checkStates.contains(item)) { + return m_checkStates.value(item); + } + else { + return static_cast(Qt::Unchecked); + } + } + else if (role == Qt::DecorationRole) { + switch (item->kind()) { + case RootItemKind::Category: + case RootItemKind::Bin: + case RootItemKind::Feed: + return item->icon(); - default: - return QVariant(); - } - } - else if (role == Qt::DisplayRole) { - switch (item->kind()) { - case RootItemKind::Category: - return QVariant(item->data(index.column(), role).toString() + tr(" (category)")); + default: + return QVariant(); + } + } + else if (role == Qt::DisplayRole) { + switch (item->kind()) { + case RootItemKind::Category: + return QVariant(item->data(index.column(), role).toString() + tr(" (category)")); - case RootItemKind::Feed: - return QVariant(item->data(index.column(), role).toString() + tr(" (feed)")); + case RootItemKind::Feed: + return QVariant(item->data(index.column(), role).toString() + tr(" (feed)")); - default: - return item->title(); - } - } - else { - return QVariant(); - } + default: + return item->title(); + } + } + else { + return QVariant(); + } } bool AccountCheckModel::setData(const QModelIndex& index, const QVariant& value, int role) { - if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole) { - RootItem* item = itemForIndex(index); + if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole) { + RootItem* item = itemForIndex(index); - if (item == m_rootItem) { - // Cannot set data on root item. - return false; - } + if (item == m_rootItem) { + // Cannot set data on root item. + return false; + } - // Change data for the actual item. - m_checkStates[item] = static_cast(value.toInt()); - emit dataChanged(index, index); + // Change data for the actual item. + m_checkStates[item] = static_cast(value.toInt()); + emit dataChanged(index, index); - if (m_recursiveChange) { - return true; - } + if (m_recursiveChange) { + return true; + } - // Set new data for all descendants of this actual item. - foreach (RootItem* child, item->childItems()) { - setData(indexForItem(child), value, Qt::CheckStateRole); - } + // Set new data for all descendants of this actual item. + foreach (RootItem* child, item->childItems()) { + setData(indexForItem(child), value, Qt::CheckStateRole); + } - // Now we need to change new data to all parents. - QModelIndex parent_index = index; - m_recursiveChange = true; + // Now we need to change new data to all parents. + QModelIndex parent_index = index; - // Iterate all valid parents. - while ((parent_index = parent_index.parent()).isValid()) { - // We now have parent index. Get parent item too. - item = item->parent(); - // Check children of this new parent item. - Qt::CheckState parent_state = Qt::Unchecked; + m_recursiveChange = true; - foreach (RootItem* child_of_parent, item->childItems()) { - if (m_checkStates.contains(child_of_parent) && m_checkStates[child_of_parent] == Qt::Checked) { - // We found out, that some child of this item is checked, - // therefore this item must be checked too. - parent_state = Qt::Checked; - break; - } - } + // Iterate all valid parents. + while ((parent_index = parent_index.parent()).isValid()) { + // We now have parent index. Get parent item too. + item = item->parent(); - setData(parent_index, parent_state, Qt::CheckStateRole); - } + // Check children of this new parent item. + Qt::CheckState parent_state = Qt::Unchecked; - m_recursiveChange = false; - return true; - } + foreach (RootItem* child_of_parent, item->childItems()) { + if (m_checkStates.contains(child_of_parent) && m_checkStates[child_of_parent] == Qt::Checked) { + // We found out, that some child of this item is checked, + // therefore this item must be checked too. + parent_state = Qt::Checked; + break; + } + } - return false; + setData(parent_index, parent_state, Qt::CheckStateRole); + } + + m_recursiveChange = false; + return true; + } + + return false; } Qt::ItemFlags AccountCheckModel::flags(const QModelIndex& index) const { - if (!index.isValid() || itemForIndex(index)->kind() == RootItemKind::Bin) { - return Qt::NoItemFlags; - } + if (!index.isValid() || itemForIndex(index)->kind() == RootItemKind::Bin) { + return Qt::NoItemFlags; + } - Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; - if (index.column() == 0) { - flags |= Qt::ItemIsUserCheckable; - } + if (index.column() == 0) { + flags |= Qt::ItemIsUserCheckable; + } - return flags; + return flags; } bool AccountCheckModel::isItemChecked(RootItem* item) { - return m_checkStates.contains(item) && m_checkStates.value(item, Qt::Unchecked); + return m_checkStates.contains(item) && m_checkStates.value(item, Qt::Unchecked); } bool AccountCheckModel::setItemChecked(RootItem* item, Qt::CheckState check) { - return setData(indexForItem(item), check, Qt::CheckStateRole); + return setData(indexForItem(item), check, Qt::CheckStateRole); } diff --git a/src/services/abstract/accountcheckmodel.h b/src/services/abstract/accountcheckmodel.h index 4ab088e7f..283a8d6db 100755 --- a/src/services/abstract/accountcheckmodel.h +++ b/src/services/abstract/accountcheckmodel.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,47 +23,48 @@ #include "services/abstract/rootitem.h" - class AccountCheckModel : public QAbstractItemModel { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit AccountCheckModel(QObject* parent = 0); - virtual ~AccountCheckModel(); + public: - QModelIndex index(int row, int column, const QModelIndex& parent) const; - QModelIndex parent(const QModelIndex& child) const; - int rowCount(const QModelIndex& parent) const; - int columnCount(const QModelIndex& parent) const; - QVariant data(const QModelIndex& index, int role) const; - bool setData(const QModelIndex& index, const QVariant& value, int role); - Qt::ItemFlags flags(const QModelIndex& index) const; + // Constructors and destructors. + explicit AccountCheckModel(QObject* parent = 0); + virtual ~AccountCheckModel(); - bool isItemChecked(RootItem* item); - bool setItemChecked(RootItem* item, Qt::CheckState check); + QModelIndex index(int row, int column, const QModelIndex& parent) const; + QModelIndex parent(const QModelIndex& child) const; + int rowCount(const QModelIndex& parent) const; + int columnCount(const QModelIndex& parent) const; + QVariant data(const QModelIndex& index, int role) const; + bool setData(const QModelIndex& index, const QVariant& value, int role); + Qt::ItemFlags flags(const QModelIndex& index) const; - // Returns feed/category which lies at the specified index or - // root item if index is invalid. - RootItem* itemForIndex(const QModelIndex& index) const; + bool isItemChecked(RootItem* item); + bool setItemChecked(RootItem* item, Qt::CheckState check); - // Returns source QModelIndex on which lies given item. - QModelIndex indexForItem(RootItem* item) const; + // Returns feed/category which lies at the specified index or + // root item if index is invalid. + RootItem* itemForIndex(const QModelIndex& index) const; - // Root item manipulators. - RootItem* rootItem() const; - void setRootItem(RootItem* root_item); + // Returns source QModelIndex on which lies given item. + QModelIndex indexForItem(RootItem* item) const; - public slots: - void checkAllItems(); - void uncheckAllItems(); + // Root item manipulators. + RootItem* rootItem() const; - protected: - RootItem* m_rootItem; + void setRootItem(RootItem* root_item); - private: - QHash m_checkStates; - bool m_recursiveChange; + public slots: + void checkAllItems(); + void uncheckAllItems(); + + protected: + RootItem* m_rootItem; + + private: + QHash m_checkStates; + bool m_recursiveChange; }; #endif // ACCOUNTCHECKMODEL_H diff --git a/src/services/abstract/cacheforserviceroot.cpp b/src/services/abstract/cacheforserviceroot.cpp index 55c49cb47..8320f3703 100755 --- a/src/services/abstract/cacheforserviceroot.cpp +++ b/src/services/abstract/cacheforserviceroot.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,57 +21,55 @@ #include "miscellaneous/application.h" #include "miscellaneous/mutex.h" -#include #include - +#include CacheForServiceRoot::CacheForServiceRoot() : m_cacheSaveMutex(new Mutex(QMutex::NonRecursive, nullptr)), - m_cachedStatesRead(QMap()), - m_cachedStatesImportant(QMap>()) { -} + m_cachedStatesRead(QMap()), + m_cachedStatesImportant(QMap>()) {} CacheForServiceRoot::~CacheForServiceRoot() { - m_cacheSaveMutex->deleteLater(); + m_cacheSaveMutex->deleteLater(); } void CacheForServiceRoot::addMessageStatesToCache(const QList& ids_of_messages, RootItem::Importance importance) { - m_cacheSaveMutex->lock(); + m_cacheSaveMutex->lock(); - QList& list_act = m_cachedStatesImportant[importance]; - QList& list_other = m_cachedStatesImportant[importance == RootItem::Important ? RootItem::NotImportant : RootItem::Important]; + QList& list_act = m_cachedStatesImportant[importance]; + QList& list_other = m_cachedStatesImportant[importance == RootItem::Important ? RootItem::NotImportant : RootItem::Important]; - // Store changes, they will be sent to server later. - list_act.append(ids_of_messages); - QSet set_act = list_act.toSet(); - QSet set_other = list_other.toSet(); + // Store changes, they will be sent to server later. + list_act.append(ids_of_messages); + QSet set_act = list_act.toSet(); + QSet set_other = list_other.toSet(); - // Now, we want to remove all IDS from list_other, which are contained in list. - set_other -= set_act; - list_act.clear(); - list_act.append(set_act.toList()); - list_other.clear(); - list_other.append(set_other.toList()); + // Now, we want to remove all IDS from list_other, which are contained in list. + set_other -= set_act; + list_act.clear(); + list_act.append(set_act.toList()); + list_other.clear(); + list_other.append(set_other.toList()); - m_cacheSaveMutex->unlock(); + m_cacheSaveMutex->unlock(); } void CacheForServiceRoot::addMessageStatesToCache(const QStringList& ids_of_messages, RootItem::ReadStatus read) { - m_cacheSaveMutex->lock(); + m_cacheSaveMutex->lock(); - QStringList& list_act = m_cachedStatesRead[read]; - QStringList& list_other = m_cachedStatesRead[read == RootItem::Read ? RootItem::Unread : RootItem::Read]; + QStringList& list_act = m_cachedStatesRead[read]; + QStringList& list_other = m_cachedStatesRead[read == RootItem::Read ? RootItem::Unread : RootItem::Read]; - // Store changes, they will be sent to server later. - list_act.append(ids_of_messages); - QSet set_act = list_act.toSet(); - QSet set_other = list_other.toSet(); + // Store changes, they will be sent to server later. + list_act.append(ids_of_messages); + QSet set_act = list_act.toSet(); + QSet set_other = list_other.toSet(); - // Now, we want to remove all IDS from list_other, which are contained in list. - set_other -= set_act; - list_act.clear(); - list_act.append(set_act.toList()); - list_other.clear(); - list_other.append(set_other.toList()); + // Now, we want to remove all IDS from list_other, which are contained in list. + set_other -= set_act; + list_act.clear(); + list_act.append(set_act.toList()); + list_other.clear(); + list_other.append(set_other.toList()); m_cacheSaveMutex->unlock(); } @@ -89,6 +88,7 @@ void CacheForServiceRoot::saveCacheToFile(int accId) { if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { QDataStream stream(&file); + stream << m_cachedStatesImportant << m_cachedStatesRead; file.flush(); file.close(); @@ -111,12 +111,12 @@ void CacheForServiceRoot::loadCacheFromFile(int accId) { // Load from file. const QString file_cache = qApp->userDataFolder() + QDir::separator() + QString::number(accId) + "-cached-msgs.dat"; - QFile file(file_cache); if (file.exists()) { if (file.open(QIODevice::ReadOnly)) { QDataStream stream(&file); + stream >> m_cachedStatesImportant >> m_cachedStatesRead; file.flush(); file.close(); @@ -129,24 +129,24 @@ void CacheForServiceRoot::loadCacheFromFile(int accId) { } QPair, QMap>> CacheForServiceRoot::takeMessageCache() { - m_cacheSaveMutex->lock(); + m_cacheSaveMutex->lock(); if (isEmpty()) { - // No cached changes. - m_cacheSaveMutex->unlock(); + // No cached changes. + m_cacheSaveMutex->unlock(); - return QPair, QMap>>(); - } + return QPair, QMap>>(); + } - // Make copy of changes. - QMap cached_data_read = m_cachedStatesRead; - cached_data_read.detach(); + // Make copy of changes. + QMap cached_data_read = m_cachedStatesRead; + cached_data_read.detach(); - QMap> cached_data_imp = m_cachedStatesImportant; - cached_data_imp.detach(); + QMap> cached_data_imp = m_cachedStatesImportant; + cached_data_imp.detach(); clearCache(); - m_cacheSaveMutex->unlock(); + m_cacheSaveMutex->unlock(); return QPair, QMap>>(cached_data_read, cached_data_imp); } diff --git a/src/services/abstract/cacheforserviceroot.h b/src/services/abstract/cacheforserviceroot.h index 4320af252..96bc7d502 100755 --- a/src/services/abstract/cacheforserviceroot.h +++ b/src/services/abstract/cacheforserviceroot.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,32 +21,32 @@ #include "services/abstract/serviceroot.h" -#include -#include #include - +#include +#include class Mutex; class CacheForServiceRoot { - public: - explicit CacheForServiceRoot(); - virtual ~CacheForServiceRoot(); + public: + explicit CacheForServiceRoot(); + virtual ~CacheForServiceRoot(); - void addMessageStatesToCache(const QList& ids_of_messages, RootItem::Importance importance); - void addMessageStatesToCache(const QStringList& ids_of_messages, RootItem::ReadStatus read); + void addMessageStatesToCache(const QList& ids_of_messages, RootItem::Importance importance); + void addMessageStatesToCache(const QStringList& ids_of_messages, RootItem::ReadStatus read); // Persistently saves/loads cached changes to/from file. // NOTE: The whole cache is cleared after save is done and before load is done. void saveCacheToFile(int accId); void loadCacheFromFile(int accId); - protected: - QPair, QMap>> takeMessageCache(); + protected: + QPair, QMap>> takeMessageCache(); - Mutex* m_cacheSaveMutex; - QMap m_cachedStatesRead; - QMap> m_cachedStatesImportant; + Mutex* m_cacheSaveMutex; + + QMap m_cachedStatesRead; + QMap> m_cachedStatesImportant; private: bool isEmpty() const; diff --git a/src/services/abstract/category.cpp b/src/services/abstract/category.cpp index 544d35224..6592a1678 100755 --- a/src/services/abstract/category.cpp +++ b/src/services/abstract/category.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,47 +20,49 @@ #include "miscellaneous/application.h" #include "miscellaneous/databasequeries.h" -#include "services/abstract/serviceroot.h" #include "services/abstract/feed.h" - +#include "services/abstract/serviceroot.h" Category::Category(RootItem* parent) : RootItem(parent) { - setKind(RootItemKind::Category); + setKind(RootItemKind::Category); } -Category::~Category() { -} +Category::~Category() {} void Category::updateCounts(bool including_total_count) { - QList feeds; + QList feeds; - foreach (RootItem* child, getSubTree()) { - if (child->kind() == RootItemKind::Feed) { - feeds.append(child->toFeed()); - } - else if (child->kind() != RootItemKind::Category && child->kind() != RootItemKind::ServiceRoot) { - child->updateCounts(including_total_count); - } - } + foreach (RootItem* child, getSubTree()) { + if (child->kind() == RootItemKind::Feed) { + feeds.append(child->toFeed()); + } + else if (child->kind() != RootItemKind::Category && child->kind() != RootItemKind::ServiceRoot) { + child->updateCounts(including_total_count); + } + } - if (feeds.isEmpty()) { - return; - } + if (feeds.isEmpty()) { + return; + } - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - bool ok; - QMap> counts = DatabaseQueries::getMessageCountsForCategory(database, customId(), getParentServiceRoot()->accountId(), - including_total_count, &ok); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + bool ok; - if (ok) { - foreach (Feed* feed, feeds) { - if (counts.contains(feed->customId())) { - feed->setCountOfUnreadMessages(counts.value(feed->customId()).first); + QMap> counts = DatabaseQueries::getMessageCountsForCategory(database, + customId(), + getParentServiceRoot()->accountId(), + including_total_count, + &ok); - if (including_total_count) { - feed->setCountOfAllMessages(counts.value(feed->customId()).second); - } - } - } - } + if (ok) { + foreach (Feed* feed, feeds) { + if (counts.contains(feed->customId())) { + feed->setCountOfUnreadMessages(counts.value(feed->customId()).first); + + if (including_total_count) { + feed->setCountOfAllMessages(counts.value(feed->customId()).second); + } + } + } + } } diff --git a/src/services/abstract/category.h b/src/services/abstract/category.h index b9d646da7..2031e40a5 100755 --- a/src/services/abstract/category.h +++ b/src/services/abstract/category.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,15 +21,14 @@ #include "services/abstract/rootitem.h" - class Category : public RootItem { - Q_OBJECT + Q_OBJECT - public: - explicit Category(RootItem* parent = nullptr); - virtual ~Category(); + public: + explicit Category(RootItem* parent = nullptr); + virtual ~Category(); - void updateCounts(bool including_total_count); + void updateCounts(bool including_total_count); }; #endif // CATEGORY_H diff --git a/src/services/abstract/feed.cpp b/src/services/abstract/feed.cpp index 9c2d3f8b2..e20bd16a1 100755 --- a/src/services/abstract/feed.cpp +++ b/src/services/abstract/feed.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,225 +20,236 @@ #include "definitions/definitions.h" #include "miscellaneous/application.h" -#include "miscellaneous/mutex.h" #include "miscellaneous/databasequeries.h" #include "miscellaneous/feedreader.h" +#include "miscellaneous/mutex.h" #include "services/abstract/recyclebin.h" #include "services/abstract/serviceroot.h" #include - Feed::Feed(RootItem* parent) - : RootItem(parent), m_url(QString()), m_status(Normal), m_autoUpdateType(DefaultAutoUpdate), - m_autoUpdateInitialInterval(DEFAULT_AUTO_UPDATE_INTERVAL), m_autoUpdateRemainingInterval(DEFAULT_AUTO_UPDATE_INTERVAL), - m_totalCount(0), m_unreadCount(0) { - setKind(RootItemKind::Feed); - setAutoDelete(false); + : RootItem(parent), m_url(QString()), m_status(Normal), m_autoUpdateType(DefaultAutoUpdate), + m_autoUpdateInitialInterval(DEFAULT_AUTO_UPDATE_INTERVAL), m_autoUpdateRemainingInterval(DEFAULT_AUTO_UPDATE_INTERVAL), + m_totalCount(0), m_unreadCount(0) { + setKind(RootItemKind::Feed); + setAutoDelete(false); } -Feed::~Feed() { -} +Feed::~Feed() {} QList Feed::undeletedMessages() const { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - return DatabaseQueries::getUndeletedMessagesForFeed(database, customId(), getParentServiceRoot()->accountId()); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + + return DatabaseQueries::getUndeletedMessagesForFeed(database, customId(), getParentServiceRoot()->accountId()); } QVariant Feed::data(int column, int role) const { - switch (role) { - case Qt::ToolTipRole: - if (column == FDS_MODEL_TITLE_INDEX) { - //: Tooltip for feed. - return tr("%1" - "%2\n\n" - "Auto-update status: %3").arg(title(), - description().isEmpty() ? QString() : QString('\n') + description(), - getAutoUpdateStatusDescription()); - } - else { - return RootItem::data(column, role); - } + switch (role) { + case Qt::ToolTipRole: + if (column == FDS_MODEL_TITLE_INDEX) { + //: Tooltip for feed. + return tr("%1" + "%2\n\n" + "Auto-update status: %3").arg(title(), + description().isEmpty() ? QString() : QString('\n') + description(), + getAutoUpdateStatusDescription()); + } + else { + return RootItem::data(column, role); + } - case Qt::ForegroundRole: - switch (status()) { - case NewMessages: - return QColor(Qt::blue); + case Qt::ForegroundRole: + switch (status()) { + case NewMessages: + return QColor(Qt::blue); - case NetworkError: - case ParsingError: - case OtherError: - return QColor(Qt::red); + case NetworkError: + case ParsingError: + case OtherError: + return QColor(Qt::red); - default: - return QVariant(); - } + default: + return QVariant(); + } - default: - return RootItem::data(column, role); - } + default: + return RootItem::data(column, role); + } } int Feed::autoUpdateInitialInterval() const { - return m_autoUpdateInitialInterval; + return m_autoUpdateInitialInterval; } int Feed::countOfAllMessages() const { - return m_totalCount; + return m_totalCount; } int Feed::countOfUnreadMessages() const { - return m_unreadCount; + return m_unreadCount; } void Feed::setCountOfAllMessages(int count_all_messages) { - m_totalCount = count_all_messages; + m_totalCount = count_all_messages; } void Feed::setCountOfUnreadMessages(int count_unread_messages) { - if (status() == NewMessages && count_unread_messages < countOfUnreadMessages()) { - setStatus(Normal); - } + if (status() == NewMessages && count_unread_messages < countOfUnreadMessages()) { + setStatus(Normal); + } - m_unreadCount = count_unread_messages; + m_unreadCount = count_unread_messages; } void Feed::setAutoUpdateInitialInterval(int auto_update_interval) { - // If new initial auto-update interval is set, then - // we should reset time that remains to the next auto-update. - m_autoUpdateInitialInterval = auto_update_interval; - m_autoUpdateRemainingInterval = auto_update_interval; + // If new initial auto-update interval is set, then + // we should reset time that remains to the next auto-update. + m_autoUpdateInitialInterval = auto_update_interval; + m_autoUpdateRemainingInterval = auto_update_interval; } Feed::AutoUpdateType Feed::autoUpdateType() const { - return m_autoUpdateType; + return m_autoUpdateType; } void Feed::setAutoUpdateType(Feed::AutoUpdateType auto_update_type) { - m_autoUpdateType = auto_update_type; + m_autoUpdateType = auto_update_type; } int Feed::autoUpdateRemainingInterval() const { - return m_autoUpdateRemainingInterval; + return m_autoUpdateRemainingInterval; } void Feed::setAutoUpdateRemainingInterval(int auto_update_remaining_interval) { - m_autoUpdateRemainingInterval = auto_update_remaining_interval; + m_autoUpdateRemainingInterval = auto_update_remaining_interval; } Feed::Status Feed::status() const { - return m_status; + return m_status; } void Feed::setStatus(const Feed::Status& status) { - m_status = status; + m_status = status; } QString Feed::url() const { - return m_url; + return m_url; } void Feed::setUrl(const QString& url) { - m_url = url; + m_url = url; } void Feed::updateCounts(bool including_total_count) { - bool is_main_thread = QThread::currentThread() == qApp->thread(); - QSqlDatabase database = is_main_thread ? - qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings) : - qApp->database()->connection(QSL("feed_upd"), DatabaseFactory::FromSettings); - int account_id = getParentServiceRoot()->accountId(); + bool is_main_thread = QThread::currentThread() == qApp->thread(); + QSqlDatabase database = is_main_thread ? + qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings) : + qApp->database()->connection(QSL("feed_upd"), DatabaseFactory::FromSettings); + int account_id = getParentServiceRoot()->accountId(); - if (including_total_count) { - setCountOfAllMessages(DatabaseQueries::getMessageCountsForFeed(database, customId(), account_id, true)); - } + if (including_total_count) { + setCountOfAllMessages(DatabaseQueries::getMessageCountsForFeed(database, customId(), account_id, true)); + } - setCountOfUnreadMessages(DatabaseQueries::getMessageCountsForFeed(database, customId(), account_id, false)); + setCountOfUnreadMessages(DatabaseQueries::getMessageCountsForFeed(database, customId(), account_id, false)); } void Feed::run() { - qDebug().nospace() << "Downloading new messages for feed " - << customId() << " in thread: \'" - << QThread::currentThreadId() << "\'."; - // Save all cached data first. - getParentServiceRoot()->saveAllCachedData(); - bool error_during_obtaining; - QList msgs = obtainNewMessages(&error_during_obtaining); - qDebug().nospace() << "Downloaded " << msgs.size() << " messages for feed " - << customId() << " in thread: \'" - << QThread::currentThreadId() << "\'."; + qDebug().nospace() << "Downloading new messages for feed " + << customId() << " in thread: \'" + << QThread::currentThreadId() << "\'."; - // Now, do some general operations on messages (tweak encoding etc.). - for (int i = 0; i < msgs.size(); i++) { - // Also, make sure that HTML encoding, encoding of special characters, etc., is fixed. - msgs[i].m_contents = QUrl::fromPercentEncoding(msgs[i].m_contents.toUtf8()); - msgs[i].m_author = msgs[i].m_author.toUtf8(); - // Sanitize title. Remove newlines etc. - msgs[i].m_title = QUrl::fromPercentEncoding(msgs[i].m_title.toUtf8()) - // Replace all continuous white space. - .replace(QRegExp(QSL("[\\s]{2,}")), QSL(" ")) - // Remove all newlines and leading white space. - .remove(QRegExp(QSL("([\\n\\r])|(^\\s)"))); - } + // Save all cached data first. + getParentServiceRoot()->saveAllCachedData(); + bool error_during_obtaining; - emit messagesObtained(msgs, error_during_obtaining); + QList msgs = obtainNewMessages(&error_during_obtaining); + qDebug().nospace() << "Downloaded " << msgs.size() << " messages for feed " + << customId() << " in thread: \'" + << QThread::currentThreadId() << "\'."; + + // Now, do some general operations on messages (tweak encoding etc.). + for (int i = 0; i < msgs.size(); i++) { + // Also, make sure that HTML encoding, encoding of special characters, etc., is fixed. + msgs[i].m_contents = QUrl::fromPercentEncoding(msgs[i].m_contents.toUtf8()); + msgs[i].m_author = msgs[i].m_author.toUtf8(); + + // Sanitize title. Remove newlines etc. + msgs[i].m_title = QUrl::fromPercentEncoding(msgs[i].m_title.toUtf8()) + + // Replace all continuous white space. + .replace(QRegExp(QSL("[\\s]{2,}")), QSL(" ")) + + // Remove all newlines and leading white space. + .remove(QRegExp(QSL("([\\n\\r])|(^\\s)"))); + } + + emit messagesObtained(msgs, error_during_obtaining); } int Feed::updateMessages(const QList& messages, bool error_during_obtaining) { - QList items_to_update; - int updated_messages = 0; - bool is_main_thread = QThread::currentThread() == qApp->thread(); - qDebug("Updating messages in DB. Main thread: '%s'.", qPrintable(is_main_thread ? "true" : "false")); + QList items_to_update; + int updated_messages = 0; + bool is_main_thread = QThread::currentThread() == qApp->thread(); - if (!error_during_obtaining) { - bool anything_updated = false; - bool ok = true; + qDebug("Updating messages in DB. Main thread: '%s'.", qPrintable(is_main_thread ? "true" : "false")); - if (!messages.isEmpty()) { - int custom_id = customId(); - int account_id = getParentServiceRoot()->accountId(); - QSqlDatabase database = is_main_thread ? - qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings) : - qApp->database()->connection(QSL("feed_upd"), DatabaseFactory::FromSettings); - updated_messages = DatabaseQueries::updateMessages(database, messages, custom_id, account_id, url(), &anything_updated, &ok); - } + if (!error_during_obtaining) { + bool anything_updated = false; + bool ok = true; - if (ok) { - setStatus(updated_messages > 0 ? NewMessages : Normal); - updateCounts(true); + if (!messages.isEmpty()) { + int custom_id = customId(); + int account_id = getParentServiceRoot()->accountId(); + QSqlDatabase database = is_main_thread ? + qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings) : + qApp->database()->connection(QSL("feed_upd"), DatabaseFactory::FromSettings); - if (getParentServiceRoot()->recycleBin() != nullptr && anything_updated) { - getParentServiceRoot()->recycleBin()->updateCounts(true); - items_to_update.append(getParentServiceRoot()->recycleBin()); - } - } - } + updated_messages = DatabaseQueries::updateMessages(database, messages, custom_id, account_id, url(), &anything_updated, &ok); + } - items_to_update.append(this); - getParentServiceRoot()->itemChanged(items_to_update); - return updated_messages; + if (ok) { + setStatus(updated_messages > 0 ? NewMessages : Normal); + updateCounts(true); + + if (getParentServiceRoot()->recycleBin() != nullptr && anything_updated) { + getParentServiceRoot()->recycleBin()->updateCounts(true); + items_to_update.append(getParentServiceRoot()->recycleBin()); + } + } + } + + items_to_update.append(this); + getParentServiceRoot()->itemChanged(items_to_update); + return updated_messages; } QString Feed::getAutoUpdateStatusDescription() const { - QString auto_update_string; + QString auto_update_string; - switch (autoUpdateType()) { - case DontAutoUpdate: - //: Describes feed auto-update status. - auto_update_string = tr("does not use auto-update"); - break; + switch (autoUpdateType()) { + case DontAutoUpdate: - case DefaultAutoUpdate: - //: Describes feed auto-update status. - auto_update_string = tr("uses global settings (%n minute(s) to next auto-update)", 0, qApp->feedReader()->autoUpdateRemainingInterval()); - break; + //: Describes feed auto-update status. + auto_update_string = tr("does not use auto-update"); + break; - case SpecificAutoUpdate: - default: - //: Describes feed auto-update status. - auto_update_string = tr("uses specific settings (%n minute(s) to next auto-update)", 0, autoUpdateRemainingInterval()); - break; - } + case DefaultAutoUpdate: - return auto_update_string; + //: Describes feed auto-update status. + auto_update_string = tr("uses global settings (%n minute(s) to next auto-update)", + 0, + qApp->feedReader()->autoUpdateRemainingInterval()); + break; + + case SpecificAutoUpdate: + default: + + //: Describes feed auto-update status. + auto_update_string = tr("uses specific settings (%n minute(s) to next auto-update)", 0, autoUpdateRemainingInterval()); + break; + } + + return auto_update_string; } diff --git a/src/services/abstract/feed.h b/src/services/abstract/feed.h index a30d7456b..a18175d24 100755 --- a/src/services/abstract/feed.h +++ b/src/services/abstract/feed.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,87 +23,88 @@ #include "core/message.h" -#include #include - +#include // Base class for "feed" nodes. class Feed : public RootItem, public QRunnable { - Q_OBJECT + Q_OBJECT - public: - // Specifies the auto-update strategy for the feed. - enum AutoUpdateType { - DontAutoUpdate = 0, - DefaultAutoUpdate = 1, - SpecificAutoUpdate = 2 - }; + public: - // Specifies the actual "status" of the feed. - // For example if it has new messages, error - // occurred, and so on. - enum Status { - Normal = 0, - NewMessages = 1, - NetworkError = 2, - ParsingError = 3, - OtherError = 4 - }; + // Specifies the auto-update strategy for the feed. + enum AutoUpdateType { + DontAutoUpdate = 0, + DefaultAutoUpdate = 1, + SpecificAutoUpdate = 2 + }; - // Constructors. - explicit Feed(RootItem* parent = nullptr); - virtual ~Feed(); + // Specifies the actual "status" of the feed. + // For example if it has new messages, error + // occurred, and so on. + enum Status { + Normal = 0, + NewMessages = 1, + NetworkError = 2, + ParsingError = 3, + OtherError = 4 + }; - QList undeletedMessages() const; + // Constructors. + explicit Feed(RootItem* parent = nullptr); + virtual ~Feed(); - int countOfAllMessages() const; - int countOfUnreadMessages() const; + QList undeletedMessages() const; - void setCountOfAllMessages(int count_all_messages); - void setCountOfUnreadMessages(int count_unread_messages); + int countOfAllMessages() const; + int countOfUnreadMessages() const; - QVariant data(int column, int role) const; + void setCountOfAllMessages(int count_all_messages); + void setCountOfUnreadMessages(int count_unread_messages); - int autoUpdateInitialInterval() const; - void setAutoUpdateInitialInterval(int auto_update_interval); + QVariant data(int column, int role) const; - AutoUpdateType autoUpdateType() const; - void setAutoUpdateType(AutoUpdateType auto_update_type); + int autoUpdateInitialInterval() const; + void setAutoUpdateInitialInterval(int auto_update_interval); - int autoUpdateRemainingInterval() const; - void setAutoUpdateRemainingInterval(int auto_update_remaining_interval); + AutoUpdateType autoUpdateType() const; + void setAutoUpdateType(AutoUpdateType auto_update_type); - Status status() const; - void setStatus(const Status& status); + int autoUpdateRemainingInterval() const; + void setAutoUpdateRemainingInterval(int auto_update_remaining_interval); - QString url() const; - void setUrl(const QString& url); + Status status() const; + void setStatus(const Status& status); - // Runs update in thread (thread pooled). - void run(); + QString url() const; + void setUrl(const QString& url); - public slots: - void updateCounts(bool including_total_count); - int updateMessages(const QList& messages, bool error_during_obtaining); + // Runs update in thread (thread pooled). + void run(); - protected: - QString getAutoUpdateStatusDescription() const; + public slots: + void updateCounts(bool including_total_count); + int updateMessages(const QList& messages, bool error_during_obtaining); - signals: - void messagesObtained(QList messages, bool error_during_obtaining); + protected: + QString getAutoUpdateStatusDescription() const; - private: - // Performs synchronous obtaining of new messages for this feed. - virtual QList obtainNewMessages(bool* error_during_obtaining) = 0; + signals: + void messagesObtained(QList messages, bool error_during_obtaining); - private: - QString m_url; - Status m_status; - AutoUpdateType m_autoUpdateType; - int m_autoUpdateInitialInterval; - int m_autoUpdateRemainingInterval; - int m_totalCount; - int m_unreadCount; + private: + + // Performs synchronous obtaining of new messages for this feed. + virtual QList obtainNewMessages(bool* error_during_obtaining) = 0; + + private: + QString m_url; + Status m_status; + AutoUpdateType m_autoUpdateType; + int m_autoUpdateInitialInterval; + int m_autoUpdateRemainingInterval; + int m_totalCount; + int m_unreadCount; }; Q_DECLARE_METATYPE(Feed::AutoUpdateType) diff --git a/src/services/abstract/gui/formfeeddetails.cpp b/src/services/abstract/gui/formfeeddetails.cpp index 25c7f998e..a34f7b659 100755 --- a/src/services/abstract/gui/formfeeddetails.cpp +++ b/src/services/abstract/gui/formfeeddetails.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,385 +18,397 @@ #include "services/abstract/gui/formfeeddetails.h" -#include "definitions/definitions.h" #include "core/feedsmodel.h" -#include "services/abstract/rootitem.h" -#include "services/abstract/category.h" -#include "services/standard/standardserviceroot.h" -#include "services/standard/standardfeed.h" -#include "miscellaneous/textfactory.h" -#include "miscellaneous/iconfactory.h" -#include "network-web/networkfactory.h" +#include "definitions/definitions.h" #include "gui/baselineedit.h" #include "gui/messagebox.h" #include "gui/systemtrayicon.h" +#include "miscellaneous/iconfactory.h" +#include "miscellaneous/textfactory.h" +#include "network-web/networkfactory.h" +#include "services/abstract/category.h" +#include "services/abstract/rootitem.h" +#include "services/standard/standardfeed.h" +#include "services/standard/standardserviceroot.h" -#include -#include +#include #include #include -#include -#include -#include #include - +#include +#include +#include +#include FormFeedDetails::FormFeedDetails(ServiceRoot* service_root, QWidget* parent) - : QDialog(parent), - m_editableFeed(nullptr), - m_serviceRoot(service_root) { - initialize(); - createConnections(); - // Initialize that shit. - onTitleChanged(QString()); - onDescriptionChanged(QString()); - onUrlChanged(QString()); - onUsernameChanged(QString()); - onPasswordChanged(QString()); + : QDialog(parent), + m_editableFeed(nullptr), + m_serviceRoot(service_root) { + initialize(); + createConnections(); + + // Initialize that shit. + onTitleChanged(QString()); + onDescriptionChanged(QString()); + onUrlChanged(QString()); + onUsernameChanged(QString()); + onPasswordChanged(QString()); } -FormFeedDetails::~FormFeedDetails() { -} +FormFeedDetails::~FormFeedDetails() {} int FormFeedDetails::addEditFeed(Feed* input_feed, RootItem* parent_to_select, const QString& url) { - // Load categories. - loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot); + // Load categories. + loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot); - if (input_feed == nullptr) { - // User is adding new category. - setWindowTitle(tr("Add new feed")); - // Make sure that "default" icon is used as the default option for new - // feed. - m_actionUseDefaultIcon->trigger(); - int default_encoding_index = m_ui->m_cmbEncoding->findText(DEFAULT_FEED_ENCODING); + if (input_feed == nullptr) { + // User is adding new category. + setWindowTitle(tr("Add new feed")); - if (default_encoding_index >= 0) { - m_ui->m_cmbEncoding->setCurrentIndex(default_encoding_index); - } + // Make sure that "default" icon is used as the default option for new + // feed. + m_actionUseDefaultIcon->trigger(); + int default_encoding_index = m_ui->m_cmbEncoding->findText(DEFAULT_FEED_ENCODING); - if (parent_to_select != nullptr) { - if (parent_to_select->kind() == RootItemKind::Category) { - m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) parent_to_select))); - } - else if (parent_to_select->kind() == RootItemKind::Feed) { - int target_item = m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) parent_to_select->parent())); + if (default_encoding_index >= 0) { + m_ui->m_cmbEncoding->setCurrentIndex(default_encoding_index); + } - if (target_item >= 0) { - m_ui->m_cmbParentCategory->setCurrentIndex(target_item); - } - } - } + if (parent_to_select != nullptr) { + if (parent_to_select->kind() == RootItemKind::Category) { + m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) parent_to_select))); + } + else if (parent_to_select->kind() == RootItemKind::Feed) { + int target_item = m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) parent_to_select->parent())); - if (!url.isEmpty()) { - m_ui->m_txtUrl->lineEdit()->setText(url); - } - else if (Application::clipboard()->mimeData()->hasText()) { - m_ui->m_txtUrl->lineEdit()->setText(Application::clipboard()->text()); - } - } - else { - // User is editing existing category. - setWindowTitle(tr("Edit feed '%1'").arg(input_feed->title())); - setEditableFeed(input_feed); - } + if (target_item >= 0) { + m_ui->m_cmbParentCategory->setCurrentIndex(target_item); + } + } + } - // Run the dialog. - return QDialog::exec(); + if (!url.isEmpty()) { + m_ui->m_txtUrl->lineEdit()->setText(url); + } + else if (Application::clipboard()->mimeData()->hasText()) { + m_ui->m_txtUrl->lineEdit()->setText(Application::clipboard()->text()); + } + } + else { + // User is editing existing category. + setWindowTitle(tr("Edit feed '%1'").arg(input_feed->title())); + setEditableFeed(input_feed); + } + + // Run the dialog. + return QDialog::exec(); } void FormFeedDetails::onTitleChanged(const QString& new_title) { - if (new_title.simplified().size() >= MIN_CATEGORY_NAME_LENGTH) { - m_ui->m_txtTitle->setStatus(LineEditWithStatus::Ok, tr("Feed name is ok.")); - } - else { - m_ui->m_txtTitle->setStatus(LineEditWithStatus::Error, tr("Feed name is too short.")); - } + if (new_title.simplified().size() >= MIN_CATEGORY_NAME_LENGTH) { + m_ui->m_txtTitle->setStatus(LineEditWithStatus::Ok, tr("Feed name is ok.")); + } + else { + m_ui->m_txtTitle->setStatus(LineEditWithStatus::Error, tr("Feed name is too short.")); + } } void FormFeedDetails::onDescriptionChanged(const QString& new_description) { - if (new_description.simplified().isEmpty()) { - m_ui->m_txtDescription->setStatus(LineEditWithStatus::Warning, tr("Description is empty.")); - } - else { - m_ui->m_txtDescription->setStatus(LineEditWithStatus::Ok, tr("The description is ok.")); - } + if (new_description.simplified().isEmpty()) { + m_ui->m_txtDescription->setStatus(LineEditWithStatus::Warning, tr("Description is empty.")); + } + else { + m_ui->m_txtDescription->setStatus(LineEditWithStatus::Ok, tr("The description is ok.")); + } } void FormFeedDetails::onUrlChanged(const QString& new_url) { - if (QRegExp(URL_REGEXP).exactMatch(new_url)) { - // New url is well-formed. - m_ui->m_txtUrl->setStatus(LineEditWithStatus::Ok, tr("The URL is ok.")); - } - else if (!new_url.simplified().isEmpty()) { - // New url is not well-formed but is not empty on the other hand. - m_ui->m_txtUrl->setStatus(LineEditWithStatus::Warning, - tr("The URL does not meet standard pattern. Does your URL start with \"http://\" or \"https://\" prefix.")); - } - else { - // New url is empty. - m_ui->m_txtUrl->setStatus(LineEditWithStatus::Error, tr("The URL is empty.")); - } + if (QRegExp(URL_REGEXP).exactMatch(new_url)) { + // New url is well-formed. + m_ui->m_txtUrl->setStatus(LineEditWithStatus::Ok, tr("The URL is ok.")); + } + else if (!new_url.simplified().isEmpty()) { + // New url is not well-formed but is not empty on the other hand. + m_ui->m_txtUrl->setStatus(LineEditWithStatus::Warning, + tr("The URL does not meet standard pattern. Does your URL start with \"http://\" or \"https://\" prefix.")); + } + else { + // New url is empty. + m_ui->m_txtUrl->setStatus(LineEditWithStatus::Error, tr("The URL is empty.")); + } } void FormFeedDetails::onUsernameChanged(const QString& new_username) { - bool is_username_ok = !m_ui->m_gbAuthentication->isChecked() || !new_username.simplified().isEmpty(); - m_ui->m_txtUsername->setStatus(is_username_ok ? - LineEditWithStatus::Ok : - LineEditWithStatus::Warning, - is_username_ok ? - tr("Username is ok or it is not needed.") : - tr("Username is empty.")); + bool is_username_ok = !m_ui->m_gbAuthentication->isChecked() || !new_username.simplified().isEmpty(); + + m_ui->m_txtUsername->setStatus(is_username_ok ? + LineEditWithStatus::Ok : + LineEditWithStatus::Warning, + is_username_ok ? + tr("Username is ok or it is not needed.") : + tr("Username is empty.")); } void FormFeedDetails::onPasswordChanged(const QString& new_password) { - bool is_password_ok = !m_ui->m_gbAuthentication->isChecked() || !new_password.simplified().isEmpty(); - m_ui->m_txtPassword->setStatus(is_password_ok ? - LineEditWithStatus::Ok : - LineEditWithStatus::Warning, - is_password_ok ? - tr("Password is ok or it is not needed.") : - tr("Password is empty.")); + bool is_password_ok = !m_ui->m_gbAuthentication->isChecked() || !new_password.simplified().isEmpty(); + + m_ui->m_txtPassword->setStatus(is_password_ok ? + LineEditWithStatus::Ok : + LineEditWithStatus::Warning, + is_password_ok ? + tr("Password is ok or it is not needed.") : + tr("Password is empty.")); } void FormFeedDetails::onAuthenticationSwitched() { - onUsernameChanged(m_ui->m_txtUsername->lineEdit()->text()); - onPasswordChanged(m_ui->m_txtPassword->lineEdit()->text()); + onUsernameChanged(m_ui->m_txtUsername->lineEdit()->text()); + onPasswordChanged(m_ui->m_txtPassword->lineEdit()->text()); } void FormFeedDetails::onAutoUpdateTypeChanged(int new_index) { - Feed::AutoUpdateType auto_update_type = static_cast(m_ui->m_cmbAutoUpdateType->itemData(new_index).toInt()); + Feed::AutoUpdateType auto_update_type = static_cast(m_ui->m_cmbAutoUpdateType->itemData(new_index).toInt()); - switch (auto_update_type) { - case Feed::DontAutoUpdate: - case Feed::DefaultAutoUpdate: - m_ui->m_spinAutoUpdateInterval->setEnabled(false); - break; + switch (auto_update_type) { + case Feed::DontAutoUpdate: + case Feed::DefaultAutoUpdate: + m_ui->m_spinAutoUpdateInterval->setEnabled(false); + break; - case Feed::SpecificAutoUpdate: - default: - m_ui->m_spinAutoUpdateInterval->setEnabled(true); - } + case Feed::SpecificAutoUpdate: + default: + m_ui->m_spinAutoUpdateInterval->setEnabled(true); + } } void FormFeedDetails::onNoIconSelected() { - m_ui->m_btnIcon->setIcon(QIcon()); + m_ui->m_btnIcon->setIcon(QIcon()); } void FormFeedDetails::onLoadIconFromFile() { - QFileDialog dialog(this, tr("Select icon file for the feed"), - qApp->homeFolder(), tr("Images (*.bmp *.jpg *.jpeg *.png *.svg *.tga)")); - dialog.setFileMode(QFileDialog::ExistingFile); - dialog.setWindowIcon(qApp->icons()->fromTheme(QSL("image-x-generic"))); - dialog.setOptions(QFileDialog::DontUseNativeDialog | QFileDialog::ReadOnly); - dialog.setViewMode(QFileDialog::Detail); - dialog.setLabelText(QFileDialog::Accept, tr("Select icon")); - dialog.setLabelText(QFileDialog::Reject, tr("Cancel")); - //: Label for field with icon file name textbox for selection dialog. - dialog.setLabelText(QFileDialog::LookIn, tr("Look in:")); - dialog.setLabelText(QFileDialog::FileName, tr("Icon name:")); - dialog.setLabelText(QFileDialog::FileType, tr("Icon type:")); + QFileDialog dialog(this, tr("Select icon file for the feed"), + qApp->homeFolder(), tr("Images (*.bmp *.jpg *.jpeg *.png *.svg *.tga)")); - if (dialog.exec() == QDialog::Accepted) { - m_ui->m_btnIcon->setIcon(QIcon(dialog.selectedFiles().value(0))); - } + dialog.setFileMode(QFileDialog::ExistingFile); + dialog.setWindowIcon(qApp->icons()->fromTheme(QSL("image-x-generic"))); + dialog.setOptions(QFileDialog::DontUseNativeDialog | QFileDialog::ReadOnly); + dialog.setViewMode(QFileDialog::Detail); + dialog.setLabelText(QFileDialog::Accept, tr("Select icon")); + dialog.setLabelText(QFileDialog::Reject, tr("Cancel")); + + //: Label for field with icon file name textbox for selection dialog. + dialog.setLabelText(QFileDialog::LookIn, tr("Look in:")); + dialog.setLabelText(QFileDialog::FileName, tr("Icon name:")); + dialog.setLabelText(QFileDialog::FileType, tr("Icon type:")); + + if (dialog.exec() == QDialog::Accepted) { + m_ui->m_btnIcon->setIcon(QIcon(dialog.selectedFiles().value(0))); + } } void FormFeedDetails::onUseDefaultIcon() { - m_ui->m_btnIcon->setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml"))); + m_ui->m_btnIcon->setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml"))); } -void FormFeedDetails::apply() { -} +void FormFeedDetails::apply() {} void FormFeedDetails::guessFeed() { - QPair result = StandardFeed::guessFeed(m_ui->m_txtUrl->lineEdit()->text(), - m_ui->m_txtUsername->lineEdit()->text(), - m_ui->m_txtPassword->lineEdit()->text()); + QPair result = StandardFeed::guessFeed(m_ui->m_txtUrl->lineEdit()->text(), + m_ui->m_txtUsername->lineEdit()->text(), + m_ui->m_txtPassword->lineEdit()->text()); - if (result.first != nullptr) { - // Icon or whole feed was guessed. - m_ui->m_btnIcon->setIcon(result.first->icon()); - m_ui->m_txtTitle->lineEdit()->setText(result.first->title()); - m_ui->m_txtDescription->lineEdit()->setText(result.first->description()); - m_ui->m_cmbType->setCurrentIndex(m_ui->m_cmbType->findData(QVariant::fromValue((int) result.first->type()))); - int encoding_index = m_ui->m_cmbEncoding->findText(result.first->encoding(), Qt::MatchFixedString); + if (result.first != nullptr) { + // Icon or whole feed was guessed. + m_ui->m_btnIcon->setIcon(result.first->icon()); + m_ui->m_txtTitle->lineEdit()->setText(result.first->title()); + m_ui->m_txtDescription->lineEdit()->setText(result.first->description()); + m_ui->m_cmbType->setCurrentIndex(m_ui->m_cmbType->findData(QVariant::fromValue((int) result.first->type()))); + int encoding_index = m_ui->m_cmbEncoding->findText(result.first->encoding(), Qt::MatchFixedString); - if (encoding_index >= 0) { - m_ui->m_cmbEncoding->setCurrentIndex(encoding_index); - } - else { - m_ui->m_cmbEncoding->setCurrentIndex(m_ui->m_cmbEncoding->findText(DEFAULT_FEED_ENCODING, - Qt::MatchFixedString)); - } + if (encoding_index >= 0) { + m_ui->m_cmbEncoding->setCurrentIndex(encoding_index); + } + else { + m_ui->m_cmbEncoding->setCurrentIndex(m_ui->m_cmbEncoding->findText(DEFAULT_FEED_ENCODING, + Qt::MatchFixedString)); + } - if (result.second == QNetworkReply::NoError) { - m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Ok, - tr("All metadata fetched successfully."), - tr("Feed and icon metadata fetched.")); - } - else { - m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Warning, - tr("Result: %1.").arg(NetworkFactory::networkErrorText(result.second)), - tr("Feed or icon metadata not fetched.")); - } + if (result.second == QNetworkReply::NoError) { + m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Ok, + tr("All metadata fetched successfully."), + tr("Feed and icon metadata fetched.")); + } + else { + m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Warning, + tr("Result: %1.").arg(NetworkFactory::networkErrorText(result.second)), + tr("Feed or icon metadata not fetched.")); + } - // Remove temporary feed object. - delete result.first; - } - else { - // No feed guessed, even no icon available. - m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Error, - tr("Error: %1.").arg(NetworkFactory::networkErrorText(result.second)), - tr("No metadata fetched.")); - } + // Remove temporary feed object. + delete result.first; + } + else { + // No feed guessed, even no icon available. + m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Error, + tr("Error: %1.").arg(NetworkFactory::networkErrorText(result.second)), + tr("No metadata fetched.")); + } } void FormFeedDetails::guessIconOnly() { - QPair result = StandardFeed::guessFeed(m_ui->m_txtUrl->lineEdit()->text(), - m_ui->m_txtUsername->lineEdit()->text(), - m_ui->m_txtPassword->lineEdit()->text()); + QPair result = StandardFeed::guessFeed(m_ui->m_txtUrl->lineEdit()->text(), + m_ui->m_txtUsername->lineEdit()->text(), + m_ui->m_txtPassword->lineEdit()->text()); - if (result.first != nullptr) { - // Icon or whole feed was guessed. - m_ui->m_btnIcon->setIcon(result.first->icon()); + if (result.first != nullptr) { + // Icon or whole feed was guessed. + m_ui->m_btnIcon->setIcon(result.first->icon()); - if (result.second == QNetworkReply::NoError) { - m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Ok, - tr("Icon fetched successfully."), - tr("Icon metadata fetched.")); - } - else { - m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Warning, - tr("Result: %1.").arg(NetworkFactory::networkErrorText(result.second)), - tr("Icon metadata not fetched.")); - } + if (result.second == QNetworkReply::NoError) { + m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Ok, + tr("Icon fetched successfully."), + tr("Icon metadata fetched.")); + } + else { + m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Warning, + tr("Result: %1.").arg(NetworkFactory::networkErrorText(result.second)), + tr("Icon metadata not fetched.")); + } - // Remove temporary feed object. - delete result.first; - } - else { - // No feed guessed, even no icon available. - m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Error, - tr("Error: %1.").arg(NetworkFactory::networkErrorText(result.second)), - tr("No icon fetched.")); - } + // Remove temporary feed object. + delete result.first; + } + else { + // No feed guessed, even no icon available. + m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Error, + tr("Error: %1.").arg(NetworkFactory::networkErrorText(result.second)), + tr("No icon fetched.")); + } } void FormFeedDetails::createConnections() { - // General connections. - connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormFeedDetails::apply); - connect(m_ui->m_txtTitle->lineEdit(), &BaseLineEdit::textChanged, this, &FormFeedDetails::onTitleChanged); - connect(m_ui->m_txtDescription->lineEdit(), &BaseLineEdit::textChanged, this, &FormFeedDetails::onDescriptionChanged); - connect(m_ui->m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormFeedDetails::onUrlChanged); - connect(m_ui->m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormFeedDetails::onUsernameChanged); - connect(m_ui->m_txtPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormFeedDetails::onPasswordChanged); - connect(m_ui->m_gbAuthentication, &QGroupBox::toggled, this, &FormFeedDetails::onAuthenticationSwitched); - connect(m_ui->m_cmbAutoUpdateType, static_cast(&QComboBox::currentIndexChanged), this, - &FormFeedDetails::onAutoUpdateTypeChanged); - connect(m_ui->m_btnFetchMetadata, &QPushButton::clicked, this, &FormFeedDetails::guessFeed); - // Icon connections. - connect(m_actionFetchIcon, &QAction::triggered, this, &FormFeedDetails::guessIconOnly); - connect(m_actionLoadIconFromFile, &QAction::triggered, this, &FormFeedDetails::onLoadIconFromFile); - connect(m_actionNoIcon, &QAction::triggered, this, &FormFeedDetails::onNoIconSelected); - connect(m_actionUseDefaultIcon, &QAction::triggered, this, &FormFeedDetails::onUseDefaultIcon); + // General connections. + connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormFeedDetails::apply); + connect(m_ui->m_txtTitle->lineEdit(), &BaseLineEdit::textChanged, this, &FormFeedDetails::onTitleChanged); + connect(m_ui->m_txtDescription->lineEdit(), &BaseLineEdit::textChanged, this, &FormFeedDetails::onDescriptionChanged); + connect(m_ui->m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormFeedDetails::onUrlChanged); + connect(m_ui->m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormFeedDetails::onUsernameChanged); + connect(m_ui->m_txtPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormFeedDetails::onPasswordChanged); + connect(m_ui->m_gbAuthentication, &QGroupBox::toggled, this, &FormFeedDetails::onAuthenticationSwitched); + connect(m_ui->m_cmbAutoUpdateType, static_cast(&QComboBox::currentIndexChanged), this, + &FormFeedDetails::onAutoUpdateTypeChanged); + connect(m_ui->m_btnFetchMetadata, &QPushButton::clicked, this, &FormFeedDetails::guessFeed); + + // Icon connections. + connect(m_actionFetchIcon, &QAction::triggered, this, &FormFeedDetails::guessIconOnly); + connect(m_actionLoadIconFromFile, &QAction::triggered, this, &FormFeedDetails::onLoadIconFromFile); + connect(m_actionNoIcon, &QAction::triggered, this, &FormFeedDetails::onNoIconSelected); + connect(m_actionUseDefaultIcon, &QAction::triggered, this, &FormFeedDetails::onUseDefaultIcon); } void FormFeedDetails::setEditableFeed(Feed* editable_feed) { - m_editableFeed = editable_feed; - m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) editable_feed->parent()))); - m_ui->m_txtTitle->lineEdit()->setText(editable_feed->title()); - m_ui->m_txtDescription->lineEdit()->setText(editable_feed->description()); - m_ui->m_btnIcon->setIcon(editable_feed->icon()); - m_ui->m_txtUrl->lineEdit()->setText(editable_feed->url()); - m_ui->m_cmbAutoUpdateType->setCurrentIndex(m_ui->m_cmbAutoUpdateType->findData(QVariant::fromValue((int) editable_feed->autoUpdateType()))); - m_ui->m_spinAutoUpdateInterval->setValue(editable_feed->autoUpdateInitialInterval()); + m_editableFeed = editable_feed; + m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) editable_feed->parent()))); + m_ui->m_txtTitle->lineEdit()->setText(editable_feed->title()); + m_ui->m_txtDescription->lineEdit()->setText(editable_feed->description()); + m_ui->m_btnIcon->setIcon(editable_feed->icon()); + m_ui->m_txtUrl->lineEdit()->setText(editable_feed->url()); + m_ui->m_cmbAutoUpdateType->setCurrentIndex(m_ui->m_cmbAutoUpdateType->findData(QVariant::fromValue((int) editable_feed->autoUpdateType()))); + m_ui->m_spinAutoUpdateInterval->setValue(editable_feed->autoUpdateInitialInterval()); } void FormFeedDetails::initialize() { - m_ui.reset(new Ui::FormFeedDetails()); - m_ui->setupUi(this); - // Set flags and attributes. - setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); - setWindowIcon(qApp->icons()->fromTheme(QSL("application-rss+xml"))); - // Set text boxes. - m_ui->m_txtTitle->lineEdit()->setPlaceholderText(tr("Feed title")); - m_ui->m_txtTitle->lineEdit()->setToolTip(tr("Set title for your feed.")); - m_ui->m_txtDescription->lineEdit()->setPlaceholderText(tr("Feed description")); - m_ui->m_txtDescription->lineEdit()->setToolTip(tr("Set description for your feed.")); - m_ui->m_txtUrl->lineEdit()->setPlaceholderText(tr("Full feed url including scheme")); - m_ui->m_txtUrl->lineEdit()->setToolTip(tr("Set url for your feed.")); - m_ui->m_txtUsername->lineEdit()->setPlaceholderText(tr("Username")); - m_ui->m_txtUsername->lineEdit()->setToolTip(tr("Set username to access the feed.")); - m_ui->m_txtPassword->lineEdit()->setPlaceholderText(tr("Password")); - m_ui->m_txtPassword->lineEdit()->setToolTip(tr("Set password to access the feed.")); - // Add standard feed types. - m_ui->m_cmbType->addItem(StandardFeed::typeToString(StandardFeed::Atom10), QVariant::fromValue((int) StandardFeed::Atom10)); - m_ui->m_cmbType->addItem(StandardFeed::typeToString(StandardFeed::Rdf), QVariant::fromValue((int) StandardFeed::Rdf)); - m_ui->m_cmbType->addItem(StandardFeed::typeToString(StandardFeed::Rss0X), QVariant::fromValue((int) StandardFeed::Rss0X)); - m_ui->m_cmbType->addItem(StandardFeed::typeToString(StandardFeed::Rss2X), QVariant::fromValue((int) StandardFeed::Rss2X)); - // Load available encodings. - const QList encodings = QTextCodec::availableCodecs(); - QStringList encoded_encodings; + m_ui.reset(new Ui::FormFeedDetails()); + m_ui->setupUi(this); - foreach (const QByteArray& encoding, encodings) { - encoded_encodings.append(encoding); - } + // Set flags and attributes. + setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); + setWindowIcon(qApp->icons()->fromTheme(QSL("application-rss+xml"))); - // Sort encodings and add them. - qSort(encoded_encodings.begin(), encoded_encodings.end(), TextFactory::isCaseInsensitiveLessThan); - m_ui->m_cmbEncoding->addItems(encoded_encodings); - // Setup menu & actions for icon selection. - m_iconMenu = new QMenu(tr("Icon selection"), this); - m_actionLoadIconFromFile = new QAction(qApp->icons()->fromTheme(QSL("image-x-generic")), - tr("Load icon from file..."), - this); - m_actionNoIcon = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), - tr("Do not use icon"), - this); - m_actionUseDefaultIcon = new QAction(qApp->icons()->fromTheme(QSL("application-rss+xml")), - tr("Use default icon"), - this); - m_actionFetchIcon = new QAction(qApp->icons()->fromTheme(QSL("emblem-downloads")), - tr("Fetch icon from feed"), - this); - m_iconMenu->addAction(m_actionFetchIcon); - m_iconMenu->addAction(m_actionLoadIconFromFile); - m_iconMenu->addAction(m_actionUseDefaultIcon); - m_iconMenu->addAction(m_actionNoIcon); - m_ui->m_btnIcon->setMenu(m_iconMenu); - // Set feed metadata fetch label. - m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Information, - tr("No metadata fetched so far."), - tr("No metadata fetched so far.")); - // Setup auto-update options. - m_ui->m_spinAutoUpdateInterval->setValue(DEFAULT_AUTO_UPDATE_INTERVAL); - m_ui->m_cmbAutoUpdateType->addItem(tr("Auto-update using global interval"), QVariant::fromValue((int) Feed::DefaultAutoUpdate)); - m_ui->m_cmbAutoUpdateType->addItem(tr("Auto-update every"), QVariant::fromValue((int) Feed::SpecificAutoUpdate)); - m_ui->m_cmbAutoUpdateType->addItem(tr("Do not auto-update at all"), QVariant::fromValue((int) Feed::DontAutoUpdate)); - // Set tab order. - setTabOrder(m_ui->m_cmbParentCategory, m_ui->m_cmbType); - setTabOrder(m_ui->m_cmbType, m_ui->m_cmbEncoding); - setTabOrder(m_ui->m_cmbEncoding, m_ui->m_cmbAutoUpdateType); - setTabOrder(m_ui->m_cmbAutoUpdateType, m_ui->m_spinAutoUpdateInterval); - setTabOrder(m_ui->m_spinAutoUpdateInterval, m_ui->m_txtTitle->lineEdit()); - setTabOrder(m_ui->m_txtTitle->lineEdit(), m_ui->m_txtDescription->lineEdit()); - setTabOrder(m_ui->m_txtDescription->lineEdit(), m_ui->m_txtUrl->lineEdit()); - setTabOrder(m_ui->m_txtUrl->lineEdit(), m_ui->m_btnFetchMetadata); - setTabOrder(m_ui->m_btnFetchMetadata, m_ui->m_btnIcon); - setTabOrder(m_ui->m_btnIcon, m_ui->m_gbAuthentication); - setTabOrder(m_ui->m_gbAuthentication, m_ui->m_txtUsername->lineEdit()); - setTabOrder(m_ui->m_txtUsername->lineEdit(), m_ui->m_txtPassword->lineEdit()); - m_ui->m_txtUrl->lineEdit()->setFocus(Qt::TabFocusReason); + // Set text boxes. + m_ui->m_txtTitle->lineEdit()->setPlaceholderText(tr("Feed title")); + m_ui->m_txtTitle->lineEdit()->setToolTip(tr("Set title for your feed.")); + m_ui->m_txtDescription->lineEdit()->setPlaceholderText(tr("Feed description")); + m_ui->m_txtDescription->lineEdit()->setToolTip(tr("Set description for your feed.")); + m_ui->m_txtUrl->lineEdit()->setPlaceholderText(tr("Full feed url including scheme")); + m_ui->m_txtUrl->lineEdit()->setToolTip(tr("Set url for your feed.")); + m_ui->m_txtUsername->lineEdit()->setPlaceholderText(tr("Username")); + m_ui->m_txtUsername->lineEdit()->setToolTip(tr("Set username to access the feed.")); + m_ui->m_txtPassword->lineEdit()->setPlaceholderText(tr("Password")); + m_ui->m_txtPassword->lineEdit()->setToolTip(tr("Set password to access the feed.")); + + // Add standard feed types. + m_ui->m_cmbType->addItem(StandardFeed::typeToString(StandardFeed::Atom10), QVariant::fromValue((int) StandardFeed::Atom10)); + m_ui->m_cmbType->addItem(StandardFeed::typeToString(StandardFeed::Rdf), QVariant::fromValue((int) StandardFeed::Rdf)); + m_ui->m_cmbType->addItem(StandardFeed::typeToString(StandardFeed::Rss0X), QVariant::fromValue((int) StandardFeed::Rss0X)); + m_ui->m_cmbType->addItem(StandardFeed::typeToString(StandardFeed::Rss2X), QVariant::fromValue((int) StandardFeed::Rss2X)); + + // Load available encodings. + const QList encodings = QTextCodec::availableCodecs(); + QStringList encoded_encodings; + + foreach (const QByteArray& encoding, encodings) { + encoded_encodings.append(encoding); + } + + // Sort encodings and add them. + qSort(encoded_encodings.begin(), encoded_encodings.end(), TextFactory::isCaseInsensitiveLessThan); + m_ui->m_cmbEncoding->addItems(encoded_encodings); + + // Setup menu & actions for icon selection. + m_iconMenu = new QMenu(tr("Icon selection"), this); + m_actionLoadIconFromFile = new QAction(qApp->icons()->fromTheme(QSL("image-x-generic")), + tr("Load icon from file..."), + this); + m_actionNoIcon = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), + tr("Do not use icon"), + this); + m_actionUseDefaultIcon = new QAction(qApp->icons()->fromTheme(QSL("application-rss+xml")), + tr("Use default icon"), + this); + m_actionFetchIcon = new QAction(qApp->icons()->fromTheme(QSL("emblem-downloads")), + tr("Fetch icon from feed"), + this); + m_iconMenu->addAction(m_actionFetchIcon); + m_iconMenu->addAction(m_actionLoadIconFromFile); + m_iconMenu->addAction(m_actionUseDefaultIcon); + m_iconMenu->addAction(m_actionNoIcon); + m_ui->m_btnIcon->setMenu(m_iconMenu); + + // Set feed metadata fetch label. + m_ui->m_lblFetchMetadata->setStatus(WidgetWithStatus::Information, + tr("No metadata fetched so far."), + tr("No metadata fetched so far.")); + + // Setup auto-update options. + m_ui->m_spinAutoUpdateInterval->setValue(DEFAULT_AUTO_UPDATE_INTERVAL); + m_ui->m_cmbAutoUpdateType->addItem(tr("Auto-update using global interval"), QVariant::fromValue((int) Feed::DefaultAutoUpdate)); + m_ui->m_cmbAutoUpdateType->addItem(tr("Auto-update every"), QVariant::fromValue((int) Feed::SpecificAutoUpdate)); + m_ui->m_cmbAutoUpdateType->addItem(tr("Do not auto-update at all"), QVariant::fromValue((int) Feed::DontAutoUpdate)); + + // Set tab order. + setTabOrder(m_ui->m_cmbParentCategory, m_ui->m_cmbType); + setTabOrder(m_ui->m_cmbType, m_ui->m_cmbEncoding); + setTabOrder(m_ui->m_cmbEncoding, m_ui->m_cmbAutoUpdateType); + setTabOrder(m_ui->m_cmbAutoUpdateType, m_ui->m_spinAutoUpdateInterval); + setTabOrder(m_ui->m_spinAutoUpdateInterval, m_ui->m_txtTitle->lineEdit()); + setTabOrder(m_ui->m_txtTitle->lineEdit(), m_ui->m_txtDescription->lineEdit()); + setTabOrder(m_ui->m_txtDescription->lineEdit(), m_ui->m_txtUrl->lineEdit()); + setTabOrder(m_ui->m_txtUrl->lineEdit(), m_ui->m_btnFetchMetadata); + setTabOrder(m_ui->m_btnFetchMetadata, m_ui->m_btnIcon); + setTabOrder(m_ui->m_btnIcon, m_ui->m_gbAuthentication); + setTabOrder(m_ui->m_gbAuthentication, m_ui->m_txtUsername->lineEdit()); + setTabOrder(m_ui->m_txtUsername->lineEdit(), m_ui->m_txtPassword->lineEdit()); + m_ui->m_txtUrl->lineEdit()->setFocus(Qt::TabFocusReason); } void FormFeedDetails::loadCategories(const QList categories, RootItem* root_item) { - m_ui->m_cmbParentCategory->addItem(root_item->icon(), - root_item->title(), - QVariant::fromValue((void*) root_item)); + m_ui->m_cmbParentCategory->addItem(root_item->icon(), + root_item->title(), + QVariant::fromValue((void*) root_item)); - foreach (Category* category, categories) { - m_ui->m_cmbParentCategory->addItem(category->icon(), - category->title(), - QVariant::fromValue((void*) category)); - } + foreach (Category* category, categories) { + m_ui->m_cmbParentCategory->addItem(category->icon(), + category->title(), + QVariant::fromValue((void*) category)); + } } diff --git a/src/services/abstract/gui/formfeeddetails.h b/src/services/abstract/gui/formfeeddetails.h index fae253785..59d59a5fc 100755 --- a/src/services/abstract/gui/formfeeddetails.h +++ b/src/services/abstract/gui/formfeeddetails.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,9 +23,8 @@ #include "ui_formfeeddetails.h" - namespace Ui { - class FormFeedDetails; + class FormFeedDetails; } class ServiceRoot; @@ -33,65 +33,68 @@ class Category; class RootItem; class FormFeedDetails : public QDialog { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit FormFeedDetails(ServiceRoot* service_root, QWidget* parent = 0); - virtual ~FormFeedDetails(); + public: - public slots: - // Executes add/edit standard feed dialog. - int addEditFeed(Feed* input_feed, RootItem* parent_to_select, const QString& url = QString()); + // Constructors and destructors. + explicit FormFeedDetails(ServiceRoot* service_root, QWidget* parent = 0); + virtual ~FormFeedDetails(); - protected slots: - // Applies changes. - // NOTE: This must be reimplemented in subclasses. Also this - // base implementation must be called first. - virtual void apply() = 0; + public slots: - void guessFeed(); - void guessIconOnly(); + // Executes add/edit standard feed dialog. + int addEditFeed(Feed* input_feed, RootItem* parent_to_select, const QString& url = QString()); - // Trigerred when title/description/url/username/password changes. - void onTitleChanged(const QString& new_title); - void onDescriptionChanged(const QString& new_description); - void onUrlChanged(const QString& new_url); - void onUsernameChanged(const QString& new_username); - void onPasswordChanged(const QString& new_password); - void onAuthenticationSwitched(); - void onAutoUpdateTypeChanged(int new_index); + protected slots: - // Icon selectors. - void onNoIconSelected(); - void onLoadIconFromFile(); - void onUseDefaultIcon(); + // Applies changes. + // NOTE: This must be reimplemented in subclasses. Also this + // base implementation must be called first. + virtual void apply() = 0; - protected: - // Sets the feed which will be edited. - // NOTE: This must be reimplemented in subclasses. Also this - // base implementation must be called first. - void virtual setEditableFeed(Feed* editable_feed); + void guessFeed(); + void guessIconOnly(); - // Creates needed connections. - void createConnections(); + // Trigerred when title/description/url/username/password changes. + void onTitleChanged(const QString& new_title); + void onDescriptionChanged(const QString& new_description); + void onUrlChanged(const QString& new_url); + void onUsernameChanged(const QString& new_username); + void onPasswordChanged(const QString& new_password); + void onAuthenticationSwitched(); + void onAutoUpdateTypeChanged(int new_index); - // Initializes the dialog. - void initialize(); + // Icon selectors. + void onNoIconSelected(); + void onLoadIconFromFile(); + void onUseDefaultIcon(); - // Loads categories into the dialog from the model. - void loadCategories(const QList categories, RootItem* root_item); + protected: - protected: - QScopedPointer m_ui; - Feed* m_editableFeed; - ServiceRoot* m_serviceRoot; + // Sets the feed which will be edited. + // NOTE: This must be reimplemented in subclasses. Also this + // base implementation must be called first. + void virtual setEditableFeed(Feed* editable_feed); - QMenu* m_iconMenu; - QAction* m_actionLoadIconFromFile; - QAction* m_actionUseDefaultIcon; - QAction* m_actionFetchIcon; - QAction* m_actionNoIcon; + // Creates needed connections. + void createConnections(); + + // Initializes the dialog. + void initialize(); + + // Loads categories into the dialog from the model. + void loadCategories(const QList categories, RootItem* root_item); + + protected: + QScopedPointer m_ui; + Feed* m_editableFeed; + ServiceRoot* m_serviceRoot; + QMenu* m_iconMenu; + QAction* m_actionLoadIconFromFile; + QAction* m_actionUseDefaultIcon; + QAction* m_actionFetchIcon; + QAction* m_actionNoIcon; }; #endif // FORMFEEDDETAILS_H diff --git a/src/services/abstract/label.cpp b/src/services/abstract/label.cpp index ed2f8f6b6..e915d3fd6 100755 --- a/src/services/abstract/label.cpp +++ b/src/services/abstract/label.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,6 +18,4 @@ #include "services/abstract/label.h" - -Label::Label(RootItem* parent_item) : RootItem(parent_item) { -} +Label::Label(RootItem* parent_item) : RootItem(parent_item) {} diff --git a/src/services/abstract/label.h b/src/services/abstract/label.h index 15cab172a..534ab4834 100755 --- a/src/services/abstract/label.h +++ b/src/services/abstract/label.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,10 +21,9 @@ #include "services/abstract/rootitem.h" - class Label : public RootItem { - public: - explicit Label(RootItem* parent_item = nullptr); + public: + explicit Label(RootItem* parent_item = nullptr); }; #endif // LABEL_H diff --git a/src/services/abstract/labelsrootitem.cpp b/src/services/abstract/labelsrootitem.cpp index fa1b24c48..bb5185efa 100755 --- a/src/services/abstract/labelsrootitem.cpp +++ b/src/services/abstract/labelsrootitem.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,9 +20,8 @@ #include "miscellaneous/iconfactory.h" - LabelsRootItem::LabelsRootItem(RootItem* parent_item) : RootItem(parent_item) { - setTitle(tr("Labels")); - setIcon(qApp->icons()->fromTheme(QSL("stock_bookmark"))); - setKind(RootItemKind::LabelsRoot); + setTitle(tr("Labels")); + setIcon(qApp->icons()->fromTheme(QSL("stock_bookmark"))); + setKind(RootItemKind::LabelsRoot); } diff --git a/src/services/abstract/labelsrootitem.h b/src/services/abstract/labelsrootitem.h index a166c8de9..c96377081 100755 --- a/src/services/abstract/labelsrootitem.h +++ b/src/services/abstract/labelsrootitem.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,12 +21,11 @@ #include "services/abstract/rootitem.h" - class LabelsRootItem : public RootItem { - Q_OBJECT + Q_OBJECT - public: - explicit LabelsRootItem(RootItem* parent_item = nullptr); + public: + explicit LabelsRootItem(RootItem* parent_item = nullptr); }; #endif // LABELSROOTITEM_H diff --git a/src/services/abstract/recyclebin.cpp b/src/services/abstract/recyclebin.cpp index 0da224791..93fa2635a 100755 --- a/src/services/abstract/recyclebin.cpp +++ b/src/services/abstract/recyclebin.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,125 +19,126 @@ #include "services/abstract/recyclebin.h" #include "miscellaneous/application.h" +#include "miscellaneous/databasequeries.h" #include "miscellaneous/iconfactory.h" #include "miscellaneous/textfactory.h" -#include "miscellaneous/databasequeries.h" #include "services/abstract/serviceroot.h" #include - RecycleBin::RecycleBin(RootItem* parent_item) : RootItem(parent_item), m_totalCount(0), - m_unreadCount(0), m_contextMenu(QList()) { - setKind(RootItemKind::Bin); - setId(ID_RECYCLE_BIN); - setIcon(qApp->icons()->fromTheme(QSL("user-trash"))); - setTitle(tr("Recycle bin")); - setDescription(tr("Recycle bin contains all deleted messages from all feeds.")); - setCreationDate(QDateTime::currentDateTime()); + m_unreadCount(0), m_contextMenu(QList()) { + setKind(RootItemKind::Bin); + setId(ID_RECYCLE_BIN); + setIcon(qApp->icons()->fromTheme(QSL("user-trash"))); + setTitle(tr("Recycle bin")); + setDescription(tr("Recycle bin contains all deleted messages from all feeds.")); + setCreationDate(QDateTime::currentDateTime()); } -RecycleBin::~RecycleBin() { -} +RecycleBin::~RecycleBin() {} int RecycleBin::countOfUnreadMessages() const { - return m_unreadCount; + return m_unreadCount; } int RecycleBin::countOfAllMessages() const { - return m_totalCount; + return m_totalCount; } void RecycleBin::updateCounts(bool update_total_count) { - bool is_main_thread = QThread::currentThread() == qApp->thread(); - QSqlDatabase database = is_main_thread ? - qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings) : - qApp->database()->connection(QSL("feed_upd"), DatabaseFactory::FromSettings); - m_unreadCount = DatabaseQueries::getMessageCountsForBin(database, getParentServiceRoot()->accountId(), false); + bool is_main_thread = QThread::currentThread() == qApp->thread(); + QSqlDatabase database = is_main_thread ? + qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings) : + qApp->database()->connection(QSL("feed_upd"), DatabaseFactory::FromSettings); - if (update_total_count) { - m_totalCount = DatabaseQueries::getMessageCountsForBin(database, getParentServiceRoot()->accountId(), true); - } + m_unreadCount = DatabaseQueries::getMessageCountsForBin(database, getParentServiceRoot()->accountId(), false); + + if (update_total_count) { + m_totalCount = DatabaseQueries::getMessageCountsForBin(database, getParentServiceRoot()->accountId(), true); + } } QVariant RecycleBin::data(int column, int role) const { - switch (role) { - case Qt::ToolTipRole: - return tr("Recycle bin\n\n%1").arg(tr("%n deleted message(s).", 0, countOfAllMessages())); + switch (role) { + case Qt::ToolTipRole: + return tr("Recycle bin\n\n%1").arg(tr("%n deleted message(s).", 0, countOfAllMessages())); - default: - return RootItem::data(column, role); - } + default: + return RootItem::data(column, role); + } } QList RecycleBin::contextMenu() { - if (m_contextMenu.isEmpty()) { - QAction* restore_action = new QAction(qApp->icons()->fromTheme(QSL("recycle-bin-restore-all")), - tr("Restore recycle bin"), - this); - QAction* empty_action = new QAction(qApp->icons()->fromTheme(QSL("recycle-bin-empty")), - tr("Empty recycle bin"), - this); - connect(restore_action, &QAction::triggered, this, &RecycleBin::restore); - connect(empty_action, &QAction::triggered, this, &RecycleBin::empty); - m_contextMenu.append(restore_action); - m_contextMenu.append(empty_action); - } + if (m_contextMenu.isEmpty()) { + QAction* restore_action = new QAction(qApp->icons()->fromTheme(QSL("recycle-bin-restore-all")), + tr("Restore recycle bin"), + this); + QAction* empty_action = new QAction(qApp->icons()->fromTheme(QSL("recycle-bin-empty")), + tr("Empty recycle bin"), + this); - return m_contextMenu; + connect(restore_action, &QAction::triggered, this, &RecycleBin::restore); + connect(empty_action, &QAction::triggered, this, &RecycleBin::empty); + m_contextMenu.append(restore_action); + m_contextMenu.append(empty_action); + } + + return m_contextMenu; } QList RecycleBin::undeletedMessages() const { - const int account_id = getParentServiceRoot()->accountId(); - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - return DatabaseQueries::getUndeletedMessagesForBin(database, account_id); + const int account_id = getParentServiceRoot()->accountId(); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + + return DatabaseQueries::getUndeletedMessagesForBin(database, account_id); } bool RecycleBin::markAsReadUnread(RootItem::ReadStatus status) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - ServiceRoot* parent_root = getParentServiceRoot(); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + ServiceRoot* parent_root = getParentServiceRoot(); - if (DatabaseQueries::markBinReadUnread(database, parent_root->accountId(), status)) { - updateCounts(false); - parent_root->itemChanged(QList() << this); - parent_root->requestReloadMessageList(status == RootItem::Read); - return true; - } - else { - return false; - } + if (DatabaseQueries::markBinReadUnread(database, parent_root->accountId(), status)) { + updateCounts(false); + parent_root->itemChanged(QList() << this); + parent_root->requestReloadMessageList(status == RootItem::Read); + return true; + } + else { + return false; + } } bool RecycleBin::cleanMessages(bool clear_only_read) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - ServiceRoot* parent_root = getParentServiceRoot(); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + ServiceRoot* parent_root = getParentServiceRoot(); - if (DatabaseQueries::purgeMessagesFromBin(database, clear_only_read, parent_root->accountId())) { - updateCounts(true); - parent_root->itemChanged(QList() << this); - parent_root->requestReloadMessageList(true); - return true;; - } - else { - return false; - } + if (DatabaseQueries::purgeMessagesFromBin(database, clear_only_read, parent_root->accountId())) { + updateCounts(true); + parent_root->itemChanged(QList() << this); + parent_root->requestReloadMessageList(true); + return true;; + } + else { + return false; + } } bool RecycleBin::empty() { - return cleanMessages(false); + return cleanMessages(false); } bool RecycleBin::restore() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - ServiceRoot* parent_root = getParentServiceRoot(); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + ServiceRoot* parent_root = getParentServiceRoot(); - if (DatabaseQueries::restoreBin(database, parent_root->accountId())) { - parent_root->updateCounts(true); - parent_root->itemChanged(parent_root->getSubTree()); - parent_root->requestReloadMessageList(true); - return true; - } - else { - return false; - } + if (DatabaseQueries::restoreBin(database, parent_root->accountId())) { + parent_root->updateCounts(true); + parent_root->itemChanged(parent_root->getSubTree()); + parent_root->requestReloadMessageList(true); + return true; + } + else { + return false; + } } diff --git a/src/services/abstract/recyclebin.h b/src/services/abstract/recyclebin.h index d8cd692c1..1c37048d8 100755 --- a/src/services/abstract/recyclebin.h +++ b/src/services/abstract/recyclebin.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,49 +21,49 @@ #include "services/abstract/rootitem.h" - class RecycleBin : public RootItem { - Q_OBJECT + Q_OBJECT - public: - explicit RecycleBin(RootItem* parent_item = nullptr); - virtual ~RecycleBin(); + public: + explicit RecycleBin(RootItem* parent_item = nullptr); + virtual ~RecycleBin(); - QVariant data(int column, int role) const; + QVariant data(int column, int role) const; - QList contextMenu(); - QList undeletedMessages() const; + QList contextMenu(); + QList undeletedMessages() const; - bool markAsReadUnread(ReadStatus status); - bool cleanMessages(bool clear_only_read); + bool markAsReadUnread(ReadStatus status); + bool cleanMessages(bool clear_only_read); - int countOfUnreadMessages() const; - int countOfAllMessages() const; + int countOfUnreadMessages() const; + int countOfAllMessages() const; - void updateCounts(bool update_total_count); + void updateCounts(bool update_total_count); - public slots: - ///////////////////////////////////////// - // /* Members to override. - ///////////////////////////////////////// + public slots: - // Empties the bin - removes all messages from it (does not remove - // them from DB, just permanently hide them, so that they are not - // re-downloaded). - virtual bool empty(); + ///////////////////////////////////////// + // /* Members to override. + ///////////////////////////////////////// - // Performs complete restoration of all messages contained in the bin - virtual bool restore(); + // Empties the bin - removes all messages from it (does not remove + // them from DB, just permanently hide them, so that they are not + // re-downloaded). + virtual bool empty(); - ///////////////////////////////////////// - // Members to override. */ - ///////////////////////////////////////// + // Performs complete restoration of all messages contained in the bin + virtual bool restore(); - private: - int m_totalCount; - int m_unreadCount; + ///////////////////////////////////////// + // Members to override. */ + ///////////////////////////////////////// - QList m_contextMenu; + private: + int m_totalCount; + int m_unreadCount; + + QList m_contextMenu; }; #endif // RECYCLEBIN_H diff --git a/src/services/abstract/rootitem.cpp b/src/services/abstract/rootitem.cpp index e3f3c0ae8..5198d2161 100755 --- a/src/services/abstract/rootitem.cpp +++ b/src/services/abstract/rootitem.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,465 +18,468 @@ #include "services/abstract/rootitem.h" -#include "services/abstract/serviceroot.h" -#include "services/abstract/feed.h" -#include "services/abstract/category.h" -#include "services/abstract/recyclebin.h" #include "miscellaneous/application.h" +#include "services/abstract/category.h" +#include "services/abstract/feed.h" +#include "services/abstract/recyclebin.h" +#include "services/abstract/serviceroot.h" #include - RootItem::RootItem(RootItem* parent_item) - : QObject(nullptr), - m_kind(RootItemKind::Root), - m_id(NO_PARENT_CATEGORY), - m_customId(NO_PARENT_CATEGORY), - m_title(QString()), - m_description(QString()), - m_icon(QIcon()), - m_creationDate(QDateTime()), - m_childItems(QList()), - m_parentItem(parent_item) { - setupFonts(); + : QObject(nullptr), + m_kind(RootItemKind::Root), + m_id(NO_PARENT_CATEGORY), + m_customId(NO_PARENT_CATEGORY), + m_title(QString()), + m_description(QString()), + m_icon(QIcon()), + m_creationDate(QDateTime()), + m_childItems(QList()), + m_parentItem(parent_item) { + setupFonts(); } RootItem::~RootItem() { - qDeleteAll(m_childItems); + qDeleteAll(m_childItems); } QString RootItem::hashCode() const { - ServiceRoot* root = getParentServiceRoot(); - int acc_id = root == nullptr ? 0 : root->accountId(); - return - QString::number(acc_id) + QL1S("-") + - QString::number(kind()) + QL1S("-") + - QString::number(id()); + ServiceRoot* root = getParentServiceRoot(); + int acc_id = root == nullptr ? 0 : root->accountId(); + + return + QString::number(acc_id) + QL1S("-") + + QString::number(kind()) + QL1S("-") + + QString::number(id()); } QList RootItem::contextMenu() { - return QList(); + return QList(); } bool RootItem::canBeEdited() const { - return false; + return false; } bool RootItem::editViaGui() { - return false; + return false; } bool RootItem::canBeDeleted() const { - return false; + return false; } bool RootItem::deleteViaGui() { - return false; + return false; } bool RootItem::markAsReadUnread(ReadStatus status) { - bool result = true; + bool result = true; - foreach (RootItem* child, m_childItems) { - result &= child->markAsReadUnread(status); - } + foreach (RootItem* child, m_childItems) { + result &= child->markAsReadUnread(status); + } - return result; + return result; } QList RootItem::undeletedMessages() const { - QList messages; + QList messages; - foreach (RootItem* child, m_childItems) { - messages.append(child->undeletedMessages()); - } + foreach (RootItem* child, m_childItems) { + messages.append(child->undeletedMessages()); + } - return messages; + return messages; } bool RootItem::cleanMessages(bool clear_only_read) { - bool result = true; + bool result = true; - foreach (RootItem* child, m_childItems) { - if (child->kind() != RootItemKind::Bin) { - result &= child->cleanMessages(clear_only_read); - } - } + foreach (RootItem* child, m_childItems) { + if (child->kind() != RootItemKind::Bin) { + result &= child->cleanMessages(clear_only_read); + } + } - return result; + return result; } void RootItem::updateCounts(bool including_total_count) { - foreach (RootItem* child, m_childItems) { - child->updateCounts(including_total_count); - } + foreach (RootItem* child, m_childItems) { + child->updateCounts(including_total_count); + } } void RootItem::setupFonts() { - m_normalFont = Application::font("FeedsView"); - m_boldFont = m_normalFont; - m_boldFont.setBold(true); + m_normalFont = Application::font("FeedsView"); + m_boldFont = m_normalFont; + m_boldFont.setBold(true); } int RootItem::row() const { - if (m_parentItem) { - return m_parentItem->m_childItems.indexOf(const_cast(this)); - } - else { - // This item has no parent. Therefore, its row index is 0. - return 0; - } + if (m_parentItem) { + return m_parentItem->m_childItems.indexOf(const_cast(this)); + } + else { + // This item has no parent. Therefore, its row index is 0. + return 0; + } } QVariant RootItem::data(int column, int role) const { - Q_UNUSED(column) - Q_UNUSED(role) + Q_UNUSED(column) + Q_UNUSED(role) - switch (role) { - case Qt::ToolTipRole: - if (column == FDS_MODEL_TITLE_INDEX) { - return m_title; - } - else if (column == FDS_MODEL_COUNTS_INDEX) { - //: Tooltip for "unread" column of feed list. - return tr("%n unread message(s).", 0, countOfUnreadMessages()); - } - else { - return QVariant(); - } + switch (role) { + case Qt::ToolTipRole: + if (column == FDS_MODEL_TITLE_INDEX) { + return m_title; + } + else if (column == FDS_MODEL_COUNTS_INDEX) { + //: Tooltip for "unread" column of feed list. + return tr("%n unread message(s).", 0, countOfUnreadMessages()); + } + else { + return QVariant(); + } - case Qt::EditRole: - if (column == FDS_MODEL_TITLE_INDEX) { - return m_title; - } - else if (column == FDS_MODEL_COUNTS_INDEX) { - return countOfUnreadMessages(); - } - else { - return QVariant(); - } + case Qt::EditRole: + if (column == FDS_MODEL_TITLE_INDEX) { + return m_title; + } + else if (column == FDS_MODEL_COUNTS_INDEX) { + return countOfUnreadMessages(); + } + else { + return QVariant(); + } - case Qt::FontRole: - return countOfUnreadMessages() > 0 ? m_boldFont : m_normalFont; + case Qt::FontRole: + return countOfUnreadMessages() > 0 ? m_boldFont : m_normalFont; - case Qt::DisplayRole: - if (column == FDS_MODEL_TITLE_INDEX) { - return m_title; - } - else if (column == FDS_MODEL_COUNTS_INDEX) { - int count_all = countOfAllMessages(); - int count_unread = countOfUnreadMessages(); - return qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString() - .replace(PLACEHOLDER_UNREAD_COUNTS, count_unread < 0 ? QSL("-") : QString::number(count_unread)) - .replace(PLACEHOLDER_ALL_COUNTS, count_all < 0 ? QSL("-") : QString::number(count_all)); - } - else { - return QVariant(); - } + case Qt::DisplayRole: + if (column == FDS_MODEL_TITLE_INDEX) { + return m_title; + } + else if (column == FDS_MODEL_COUNTS_INDEX) { + int count_all = countOfAllMessages(); + int count_unread = countOfUnreadMessages(); - case Qt::DecorationRole: - if (column == FDS_MODEL_TITLE_INDEX) { - return icon(); - } - else { - return QVariant(); - } + return qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString() + .replace(PLACEHOLDER_UNREAD_COUNTS, count_unread < 0 ? QSL("-") : QString::number(count_unread)) + .replace(PLACEHOLDER_ALL_COUNTS, count_all < 0 ? QSL("-") : QString::number(count_all)); + } + else { + return QVariant(); + } - case Qt::TextAlignmentRole: - if (column == FDS_MODEL_COUNTS_INDEX) { - return Qt::AlignCenter; - } - else { - return QVariant(); - } + case Qt::DecorationRole: + if (column == FDS_MODEL_TITLE_INDEX) { + return icon(); + } + else { + return QVariant(); + } - default: - return QVariant(); - } + case Qt::TextAlignmentRole: + if (column == FDS_MODEL_COUNTS_INDEX) { + return Qt::AlignCenter; + } + else { + return QVariant(); + } + + default: + return QVariant(); + } } Qt::ItemFlags RootItem::additionalFlags() const { - return Qt::NoItemFlags; + return Qt::NoItemFlags; } bool RootItem::performDragDropChange(RootItem* target_item) { - Q_UNUSED(target_item) - return false; + Q_UNUSED(target_item) + return false; } int RootItem::countOfAllMessages() const { - int total_count = 0; + int total_count = 0; - foreach (RootItem* child_item, m_childItems) { - total_count += child_item->countOfAllMessages(); - } + foreach (RootItem* child_item, m_childItems) { + total_count += child_item->countOfAllMessages(); + } - return total_count; + return total_count; } bool RootItem::isChildOf(const RootItem* root) const { - if (root == nullptr) { - return false; - } + if (root == nullptr) { + return false; + } - const RootItem* this_item = this; + const RootItem* this_item = this; - while (this_item->kind() != RootItemKind::Root) { - if (root->childItems().contains(const_cast(this_item))) { - return true; - } - else { - this_item = this_item->parent(); - } - } + while (this_item->kind() != RootItemKind::Root) { + if (root->childItems().contains(const_cast(this_item))) { + return true; + } + else { + this_item = this_item->parent(); + } + } - return false; + return false; } bool RootItem::isParentOf(const RootItem* child) const { - if (child == nullptr) { - return false; - } - else { - return child->isChildOf(this); - } + if (child == nullptr) { + return false; + } + else { + return child->isChildOf(this); + } } QList RootItem::getSubTree() const { - QList children; - QList traversable_items; - traversable_items.append(const_cast(this)); + QList children; + QList traversable_items; + traversable_items.append(const_cast(this)); - // Iterate all nested items. - while (!traversable_items.isEmpty()) { - RootItem* active_item = traversable_items.takeFirst(); - children.append(active_item); - traversable_items.append(active_item->childItems()); - } + // Iterate all nested items. + while (!traversable_items.isEmpty()) { + RootItem* active_item = traversable_items.takeFirst(); - return children; + children.append(active_item); + traversable_items.append(active_item->childItems()); + } + + return children; } QList RootItem::getSubTree(RootItemKind::Kind kind_of_item) const { - QList children; - QList traversable_items; - traversable_items.append(const_cast(this)); + QList children; + QList traversable_items; + traversable_items.append(const_cast(this)); - // Iterate all nested items. - while (!traversable_items.isEmpty()) { - RootItem* active_item = traversable_items.takeFirst(); + // Iterate all nested items. + while (!traversable_items.isEmpty()) { + RootItem* active_item = traversable_items.takeFirst(); - if ((active_item->kind() & kind_of_item) > 0) { - children.append(active_item); - } + if ((active_item->kind() & kind_of_item) > 0) { + children.append(active_item); + } - traversable_items.append(active_item->childItems()); - } + traversable_items.append(active_item->childItems()); + } - return children; + return children; } QList RootItem::getSubTreeCategories() const { - QList children; - QList traversable_items; - traversable_items.append(const_cast(this)); + QList children; + QList traversable_items; + traversable_items.append(const_cast(this)); - // Iterate all nested items. - while (!traversable_items.isEmpty()) { - RootItem* active_item = traversable_items.takeFirst(); + // Iterate all nested items. + while (!traversable_items.isEmpty()) { + RootItem* active_item = traversable_items.takeFirst(); - if (active_item->kind() == RootItemKind::Category) { - children.append(active_item->toCategory()); - } + if (active_item->kind() == RootItemKind::Category) { + children.append(active_item->toCategory()); + } - traversable_items.append(active_item->childItems()); - } + traversable_items.append(active_item->childItems()); + } - return children; + return children; } QHash RootItem::getHashedSubTreeCategories() const { - QHash children; - QList traversable_items; - traversable_items.append(const_cast(this)); + QHash children; + QList traversable_items; + traversable_items.append(const_cast(this)); - // Iterate all nested items. - while (!traversable_items.isEmpty()) { - RootItem* active_item = traversable_items.takeFirst(); + // Iterate all nested items. + while (!traversable_items.isEmpty()) { + RootItem* active_item = traversable_items.takeFirst(); - if (active_item->kind() == RootItemKind::Category && !children.contains(active_item->customId())) { - children.insert(active_item->customId(), active_item->toCategory()); - } + if (active_item->kind() == RootItemKind::Category && !children.contains(active_item->customId())) { + children.insert(active_item->customId(), active_item->toCategory()); + } - traversable_items.append(active_item->childItems()); - } + traversable_items.append(active_item->childItems()); + } - return children; + return children; } QHash RootItem::getHashedSubTreeFeeds() const { - QHash children; - QList traversable_items; - traversable_items.append(const_cast(this)); + QHash children; + QList traversable_items; + traversable_items.append(const_cast(this)); - // Iterate all nested items. - while (!traversable_items.isEmpty()) { - RootItem* active_item = traversable_items.takeFirst(); + // Iterate all nested items. + while (!traversable_items.isEmpty()) { + RootItem* active_item = traversable_items.takeFirst(); - if (active_item->kind() == RootItemKind::Feed && !children.contains(active_item->customId())) { - children.insert(active_item->customId(), active_item->toFeed()); - } + if (active_item->kind() == RootItemKind::Feed && !children.contains(active_item->customId())) { + children.insert(active_item->customId(), active_item->toFeed()); + } - traversable_items.append(active_item->childItems()); - } + traversable_items.append(active_item->childItems()); + } - return children; + return children; } QList RootItem::getSubTreeFeeds() const { - QList children; - QList traversable_items; - traversable_items.append(const_cast(this)); + QList children; + QList traversable_items; + traversable_items.append(const_cast(this)); - // Iterate all nested items. - while (!traversable_items.isEmpty()) { - RootItem* active_item = traversable_items.takeFirst(); + // Iterate all nested items. + while (!traversable_items.isEmpty()) { + RootItem* active_item = traversable_items.takeFirst(); - if (active_item->kind() == RootItemKind::Feed) { - children.append(active_item->toFeed()); - } + if (active_item->kind() == RootItemKind::Feed) { + children.append(active_item->toFeed()); + } - traversable_items.append(active_item->childItems()); - } + traversable_items.append(active_item->childItems()); + } - return children; + return children; } ServiceRoot* RootItem::getParentServiceRoot() const { - const RootItem* working_parent = this; + const RootItem* working_parent = this; - while (working_parent->kind() != RootItemKind::Root) { - if (working_parent->kind() == RootItemKind::ServiceRoot) { - return working_parent->toServiceRoot(); - } - else { - working_parent = working_parent->parent(); - } - } + while (working_parent->kind() != RootItemKind::Root) { + if (working_parent->kind() == RootItemKind::ServiceRoot) { + return working_parent->toServiceRoot(); + } + else { + working_parent = working_parent->parent(); + } + } - return nullptr; + return nullptr; } RootItemKind::Kind RootItem::kind() const { - return m_kind; + return m_kind; } void RootItem::setKind(RootItemKind::Kind kind) { - m_kind = kind; + m_kind = kind; } QIcon RootItem::icon() const { - return m_icon; + return m_icon; } void RootItem::setIcon(const QIcon& icon) { - m_icon = icon; + m_icon = icon; } int RootItem::id() const { - return m_id; + return m_id; } void RootItem::setId(int id) { - m_id = id; + m_id = id; } QString RootItem::title() const { - return m_title; + return m_title; } void RootItem::setTitle(const QString& title) { - m_title = title; + m_title = title; } QDateTime RootItem::creationDate() const { - return m_creationDate; + return m_creationDate; } void RootItem::setCreationDate(const QDateTime& creation_date) { - m_creationDate = creation_date; + m_creationDate = creation_date; } QString RootItem::description() const { - return m_description; + return m_description; } void RootItem::setDescription(const QString& description) { - m_description = description; + m_description = description; } QFont RootItem::normalFont() const { - return m_normalFont; + return m_normalFont; } void RootItem::setNormalFont(const QFont& normal_font) { - m_normalFont = normal_font; + m_normalFont = normal_font; } QFont RootItem::boldFont() const { - return m_boldFont; + return m_boldFont; } void RootItem::setBoldFont(const QFont& bold_font) { - m_boldFont = bold_font; + m_boldFont = bold_font; } bool RootItem::removeChild(RootItem* child) { - return m_childItems.removeOne(child); + return m_childItems.removeOne(child); } int RootItem::customId() const { - return m_customId; + return m_customId; } void RootItem::setCustomId(int custom_id) { - m_customId = custom_id; + m_customId = custom_id; } Category* RootItem::toCategory() const { - return static_cast(const_cast(this)); + return static_cast(const_cast(this)); } Feed* RootItem::toFeed() const { - return static_cast(const_cast(this)); + return static_cast(const_cast(this)); } ServiceRoot* RootItem::toServiceRoot() const { - return static_cast(const_cast(this)); + return static_cast(const_cast(this)); } int RootItem::countOfUnreadMessages() const { - int total_count = 0; + int total_count = 0; - foreach (RootItem* child_item, m_childItems) { - total_count += child_item->countOfUnreadMessages(); - } + foreach (RootItem* child_item, m_childItems) { + total_count += child_item->countOfUnreadMessages(); + } - return total_count; + return total_count; } bool RootItem::removeChild(int index) { - if (index >= 0 && index < m_childItems.size()) { - m_childItems.removeAt(index); - return true; - } - else { - return false; - } + if (index >= 0 && index < m_childItems.size()) { + m_childItems.removeAt(index); + return true; + } + else { + return false; + } } QDataStream& operator>>(QDataStream& in, RootItem::ReadStatus& myObj) { int obj; + in >> obj; myObj = (RootItem::ReadStatus)obj; @@ -491,6 +495,7 @@ QDataStream& operator<<(QDataStream& out, const RootItem::ReadStatus& myObj) { QDataStream& operator>>(QDataStream& in, RootItem::Importance& myObj) { int obj; + in >> obj; myObj = (RootItem::Importance)obj; diff --git a/src/services/abstract/rootitem.h b/src/services/abstract/rootitem.h index 933c989df..0d1954df9 100755 --- a/src/services/abstract/rootitem.h +++ b/src/services/abstract/rootitem.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,10 +21,9 @@ #include "core/message.h" -#include #include #include - +#include class Category; class Feed; @@ -31,217 +31,213 @@ class ServiceRoot; class QAction; namespace RootItemKind { - // Describes the kind of the item. - enum Kind { - Root = 1, - Bin = 2, - Feed = 4, - Category = 8, - ServiceRoot = 16, - LabelsRoot = 32 - }; + // Describes the kind of the item. + enum Kind { + Root = 1, + Bin = 2, + Feed = 4, + Category = 8, + ServiceRoot = 16, + LabelsRoot = 32 + }; + inline Kind operator|(Kind a, Kind b) { + return static_cast(static_cast(a) | static_cast(b)); + } - inline Kind operator|(Kind a, Kind b) { - return static_cast(static_cast(a) | static_cast(b)); - } } // Represents ROOT item of FeedsModel. // NOTE: This class is derived to add functionality for // all other non-root items of FeedsModel. class RootItem : public QObject { - Q_OBJECT + Q_OBJECT - public: - // Holds statuses for feeds/messages - // to be marked read/unread. - enum ReadStatus { - Unread = 0, - Read = 1 - }; + public: - // Holds statuses for messages - // to be switched importance (starred). - enum Importance { - NotImportant = 0, - Important = 1 - }; + // Holds statuses for feeds/messages + // to be marked read/unread. + enum ReadStatus { + Unread = 0, + Read = 1 + }; - // Constructors and destructors. - explicit RootItem(RootItem* parent_item = nullptr); - virtual ~RootItem(); + // Holds statuses for messages + // to be switched importance (starred). + enum Importance { + NotImportant = 0, + Important = 1 + }; - virtual QString hashCode() const; + // Constructors and destructors. + explicit RootItem(RootItem* parent_item = nullptr); + virtual ~RootItem(); - // Returns list of specific actions which can be done with the item. - // Do not include general actions here like actions: Mark as read, Update, ... - // NOTE: Ownership of returned actions is not switched to caller, free them when needed. - virtual QList contextMenu(); + virtual QString hashCode() const; - // Can properties of this item be edited? - virtual bool canBeEdited() const; + // Returns list of specific actions which can be done with the item. + // Do not include general actions here like actions: Mark as read, Update, ... + // NOTE: Ownership of returned actions is not switched to caller, free them when needed. + virtual QList contextMenu(); - // Performs editing of properties of this item (probably via dialog) - // and returns result status. - virtual bool editViaGui(); + // Can properties of this item be edited? + virtual bool canBeEdited() const; - // Can the item be deleted? - virtual bool canBeDeleted() const; + // Performs editing of properties of this item (probably via dialog) + // and returns result status. + virtual bool editViaGui(); - // Performs deletion of the item, this - // method should NOT display any additional dialogs. - // Returns result status. - virtual bool deleteViaGui(); + // Can the item be deleted? + virtual bool canBeDeleted() const; - // Performs all needed steps (DB update, remote server update) - // to mark this item as read/unread. - virtual bool markAsReadUnread(ReadStatus status); + // Performs deletion of the item, this + // method should NOT display any additional dialogs. + // Returns result status. + virtual bool deleteViaGui(); - // Get ALL undeleted messages from this item in one single list. - // This is currently used for displaying items in "newspaper mode". - virtual QList undeletedMessages() const; + // Performs all needed steps (DB update, remote server update) + // to mark this item as read/unread. + virtual bool markAsReadUnread(ReadStatus status); - // This method should "clean" all messages it contains. - // What "clean" means? It means delete messages -> move them to recycle bin - // or eventually remove them completely if there is no recycle bin functionality. - // If this method is called on "recycle bin" instance of your - // service account, it should "empty" the recycle bin. - virtual bool cleanMessages(bool clear_only_read); + // Get ALL undeleted messages from this item in one single list. + // This is currently used for displaying items in "newspaper mode". + virtual QList undeletedMessages() const; - // Updates counts of all/unread messages for this feed. - virtual void updateCounts(bool including_total_count); + // This method should "clean" all messages it contains. + // What "clean" means? It means delete messages -> move them to recycle bin + // or eventually remove them completely if there is no recycle bin functionality. + // If this method is called on "recycle bin" instance of your + // service account, it should "empty" the recycle bin. + virtual bool cleanMessages(bool clear_only_read); - virtual int row() const; - virtual QVariant data(int column, int role) const; - virtual Qt::ItemFlags additionalFlags() const; - virtual bool performDragDropChange(RootItem* target_item); + // Updates counts of all/unread messages for this feed. + virtual void updateCounts(bool including_total_count); + virtual int row() const; + virtual QVariant data(int column, int role) const; + virtual Qt::ItemFlags additionalFlags() const; + virtual bool performDragDropChange(RootItem* target_item); - // Each item offers "counts" of messages. - // Returns counts of messages of all child items summed up. - virtual int countOfUnreadMessages() const; - virtual int countOfAllMessages() const; + // Each item offers "counts" of messages. + // Returns counts of messages of all child items summed up. + virtual int countOfUnreadMessages() const; + virtual int countOfAllMessages() const; + inline RootItem* parent() const { + return m_parentItem; + } - inline RootItem* parent() const { - return m_parentItem; - } + inline void setParent(RootItem* parent_item) { + m_parentItem = parent_item; + } - inline void setParent(RootItem* parent_item) { - m_parentItem = parent_item; - } + inline RootItem* child(int row) { + return m_childItems.value(row); + } - inline RootItem* child(int row) { - return m_childItems.value(row); - } + inline int childCount() const { + return m_childItems.size(); + } - inline int childCount() const { - return m_childItems.size(); - } + inline void appendChild(RootItem* child) { + m_childItems.append(child); + child->setParent(this); + } - inline void appendChild(RootItem* child) { - m_childItems.append(child); - child->setParent(this); - } + // Access to children. + inline QList childItems() const { + return m_childItems; + } - // Access to children. - inline QList childItems() const { - return m_childItems; - } + // Removes all children from this item. + // NOTE: Children are NOT freed from the memory. + inline void clearChildren() { + m_childItems.clear(); + } - // Removes all children from this item. - // NOTE: Children are NOT freed from the memory. - inline void clearChildren() { - m_childItems.clear(); - } + inline void setChildItems(const QList& child_items) { + m_childItems = child_items; + } - inline void setChildItems(const QList& child_items) { - m_childItems = child_items; - } + // Removes particular child at given index. + // NOTE: Child is NOT freed from the memory. + bool removeChild(int index); - // Removes particular child at given index. - // NOTE: Child is NOT freed from the memory. - bool removeChild(int index); - bool removeChild(RootItem* child); + bool removeChild(RootItem* child); - // Checks whether "this" object is child (direct or indirect) - // of the given root. - bool isChildOf(const RootItem* root) const; + // Checks whether "this" object is child (direct or indirect) + // of the given root. + bool isChildOf(const RootItem* root) const; - // Is "this" item parent (direct or indirect) if given child? - bool isParentOf(const RootItem* child) const; + // Is "this" item parent (direct or indirect) if given child? + bool isParentOf(const RootItem* child) const; - // Returns flat list of all items from subtree where this item is a root. - // Returned list includes this item too. - QList getSubTree() const; - QList getSubTree(RootItemKind::Kind kind_of_item) const; - QList getSubTreeCategories() const; - QHash getHashedSubTreeCategories() const; - QHash getHashedSubTreeFeeds() const; - QList getSubTreeFeeds() const; + // Returns flat list of all items from subtree where this item is a root. + // Returned list includes this item too. + QList getSubTree() const; + QList getSubTree(RootItemKind::Kind kind_of_item) const; + QList getSubTreeCategories() const; + QHash getHashedSubTreeCategories() const; + QHash getHashedSubTreeFeeds() const; + QList getSubTreeFeeds() const; - // Returns the service root node which is direct or indirect parent of current item. - ServiceRoot* getParentServiceRoot() const; + // Returns the service root node which is direct or indirect parent of current item. + ServiceRoot* getParentServiceRoot() const; - RootItemKind::Kind kind() const; - void setKind(RootItemKind::Kind kind); + RootItemKind::Kind kind() const; + void setKind(RootItemKind::Kind kind); - // Each item can have icon. - QIcon icon() const; - void setIcon(const QIcon& icon); + // Each item can have icon. + QIcon icon() const; + void setIcon(const QIcon& icon); - // This ALWAYS represents primary column number/ID under which - // the item is stored in DB. - int id() const; - void setId(int id); + // This ALWAYS represents primary column number/ID under which + // the item is stored in DB. + int id() const; + void setId(int id); - // Each item has its title. - QString title() const; - void setTitle(const QString& title); + // Each item has its title. + QString title() const; + void setTitle(const QString& title); - QDateTime creationDate() const; - void setCreationDate(const QDateTime& creation_date); + QDateTime creationDate() const; + void setCreationDate(const QDateTime& creation_date); - QString description() const; - void setDescription(const QString& description); + QString description() const; + void setDescription(const QString& description); - QFont normalFont() const; - void setNormalFont(const QFont& normal_font); + QFont normalFont() const; + void setNormalFont(const QFont& normal_font); - QFont boldFont() const; - void setBoldFont(const QFont& bold_font); + QFont boldFont() const; + void setBoldFont(const QFont& bold_font); - // NOTE: For standard feed/category, this WILL equal to id(). - int customId() const; - void setCustomId(int custom_id); + // NOTE: For standard feed/category, this WILL equal to id(). + int customId() const; + void setCustomId(int custom_id); - // Converters - Category* toCategory() const; - Feed* toFeed() const; - ServiceRoot* toServiceRoot() const; + // Converters + Category* toCategory() const; + Feed* toFeed() const; + ServiceRoot* toServiceRoot() const; - private: - void setupFonts(); + private: + void setupFonts(); - RootItemKind::Kind m_kind; - int m_id; - int m_customId; - QString m_title; - QString m_description; - QIcon m_icon; - QDateTime m_creationDate; + RootItemKind::Kind m_kind; + int m_id; + int m_customId; + QString m_title; + QString m_description; + QIcon m_icon; + QDateTime m_creationDate; + QFont m_normalFont; + QFont m_boldFont; - QFont m_normalFont; - QFont m_boldFont; - - QList m_childItems; - RootItem* m_parentItem; + QList m_childItems; + RootItem* m_parentItem; }; QDataStream& operator<<(QDataStream& out, const RootItem::Importance& myObj); - QDataStream& operator>>(QDataStream& in, RootItem::Importance& myObj); - QDataStream& operator<<(QDataStream& out, const RootItem::ReadStatus& myObj); - QDataStream& operator>>(QDataStream& in, RootItem::ReadStatus& myObj); #endif // ROOTITEM_H diff --git a/src/services/abstract/serviceentrypoint.cpp b/src/services/abstract/serviceentrypoint.cpp index 2d220433f..54ec4f260 100755 --- a/src/services/abstract/serviceentrypoint.cpp +++ b/src/services/abstract/serviceentrypoint.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,6 +18,4 @@ #include "services/abstract/serviceentrypoint.h" - -ServiceEntryPoint::~ServiceEntryPoint() { -} +ServiceEntryPoint::~ServiceEntryPoint() {} diff --git a/src/services/abstract/serviceentrypoint.h b/src/services/abstract/serviceentrypoint.h index 4cd2ef818..fb088712f 100755 --- a/src/services/abstract/serviceentrypoint.h +++ b/src/services/abstract/serviceentrypoint.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,60 +23,60 @@ #include #include - class ServiceRoot; class FeedsModel; // TOP LEVEL class which provides basic information about the "service" class ServiceEntryPoint { - public: - // Constructors. - virtual ~ServiceEntryPoint(); + public: - ///////////////////////////////////////// - // /* Members to override. - ///////////////////////////////////////// + // Constructors. + virtual ~ServiceEntryPoint(); - // Creates new service root item, which is ready to be added - // into the model. This method can for example display - // some kind of first-time configuration dialog inside itself - // before returning the root item. - // Returns NULL if initialization of new root cannot be done. - virtual ServiceRoot* createNewRoot() const = 0; + ///////////////////////////////////////// + // /* Members to override. + ///////////////////////////////////////// - // Performs initialization of all service accounts created using this entry - // point from persistent DB. - // Returns list of root nodes which will be afterwards added - // to the global feed model. - virtual QList initializeSubtree() const = 0; + // Creates new service root item, which is ready to be added + // into the model. This method can for example display + // some kind of first-time configuration dialog inside itself + // before returning the root item. + // Returns NULL if initialization of new root cannot be done. + virtual ServiceRoot* createNewRoot() const = 0; - // Can this service account be added just once? - // NOTE: This is true particularly for "standard" service - // which operates with normal RSS/ATOM feeds. - virtual bool isSingleInstanceService() const = 0; + // Performs initialization of all service accounts created using this entry + // point from persistent DB. + // Returns list of root nodes which will be afterwards added + // to the global feed model. + virtual QList initializeSubtree() const = 0; - // Human readable service name, for example "TT-RSS". - virtual QString name() const = 0; + // Can this service account be added just once? + // NOTE: This is true particularly for "standard" service + // which operates with normal RSS/ATOM feeds. + virtual bool isSingleInstanceService() const = 0; - // Some arbitrary string. - // NOTE: Keep in sync with ServiceRoot::code(). - virtual QString code() const = 0; + // Human readable service name, for example "TT-RSS". + virtual QString name() const = 0; - // Human readable service description, for example "Services which offers TT-RSS integration.". - virtual QString description() const = 0; + // Some arbitrary string. + // NOTE: Keep in sync with ServiceRoot::code(). + virtual QString code() const = 0; - // Version of the service, using of semantic versioning is recommended. - virtual QString version() const = 0; + // Human readable service description, for example "Services which offers TT-RSS integration.". + virtual QString description() const = 0; - // Author of the service. - virtual QString author() const = 0; + // Version of the service, using of semantic versioning is recommended. + virtual QString version() const = 0; - // Icon of the service. - virtual QIcon icon() const = 0; + // Author of the service. + virtual QString author() const = 0; - ///////////////////////////////////////// - // Members to override. */ - ///////////////////////////////////////// + // Icon of the service. + virtual QIcon icon() const = 0; + + ///////////////////////////////////////// + // Members to override. */ + ///////////////////////////////////////// }; #endif // SERVICE_H diff --git a/src/services/abstract/serviceroot.cpp b/src/services/abstract/serviceroot.cpp index d4e76e9a7..5e10dbdf3 100755 --- a/src/services/abstract/serviceroot.cpp +++ b/src/services/abstract/serviceroot.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,481 +21,496 @@ #include "core/feedsmodel.h" #include "core/messagesmodel.h" #include "miscellaneous/application.h" +#include "miscellaneous/databasequeries.h" #include "miscellaneous/iconfactory.h" #include "miscellaneous/textfactory.h" -#include "miscellaneous/databasequeries.h" #include "services/abstract/category.h" #include "services/abstract/feed.h" #include "services/abstract/recyclebin.h" - ServiceRoot::ServiceRoot(RootItem* parent) : RootItem(parent), m_accountId(NO_PARENT_CATEGORY) { - setKind(RootItemKind::ServiceRoot); - setCreationDate(QDateTime::currentDateTime()); + setKind(RootItemKind::ServiceRoot); + setCreationDate(QDateTime::currentDateTime()); } -ServiceRoot::~ServiceRoot() { -} +ServiceRoot::~ServiceRoot() {} bool ServiceRoot::deleteViaGui() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - if (DatabaseQueries::deleteAccount(database, accountId())) { + if (DatabaseQueries::deleteAccount(database, accountId())) { stop(); - requestItemRemoval(this); - return true; - } - else { - return false; - } + requestItemRemoval(this); + return true; + } + else { + return false; + } } bool ServiceRoot::markAsReadUnread(RootItem::ReadStatus status) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - if (DatabaseQueries::markAccountReadUnread(database, accountId(), status)) { - updateCounts(false); - itemChanged(getSubTree()); - requestReloadMessageList(status == RootItem::Read); - return true; - } - else { - return false; - } + if (DatabaseQueries::markAccountReadUnread(database, accountId(), status)) { + updateCounts(false); + itemChanged(getSubTree()); + requestReloadMessageList(status == RootItem::Read); + return true; + } + else { + return false; + } } QList ServiceRoot::addItemMenu() { - return QList(); + return QList(); } QList ServiceRoot::contextMenu() { - return serviceMenu(); + return serviceMenu(); } QList ServiceRoot::serviceMenu() { - return QList(); + return QList(); } void ServiceRoot::updateCounts(bool including_total_count) { - QList feeds; + QList feeds; - foreach (RootItem* child, getSubTree()) { - if (child->kind() == RootItemKind::Feed) { - feeds.append(child->toFeed()); - } - else if (child->kind() != RootItemKind::Category && child->kind() != RootItemKind::ServiceRoot) { - child->updateCounts(including_total_count); - } - } + foreach (RootItem* child, getSubTree()) { + if (child->kind() == RootItemKind::Feed) { + feeds.append(child->toFeed()); + } + else if (child->kind() != RootItemKind::Category && child->kind() != RootItemKind::ServiceRoot) { + child->updateCounts(including_total_count); + } + } - if (feeds.isEmpty()) { - return; - } + if (feeds.isEmpty()) { + return; + } - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - bool ok; - QMap> counts = DatabaseQueries::getMessageCountsForAccount(database, accountId(), including_total_count, &ok); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + bool ok; - if (ok) { - foreach (Feed* feed, feeds) { - if (counts.contains(feed->customId())) { - feed->setCountOfUnreadMessages(counts.value(feed->customId()).first); + QMap> counts = DatabaseQueries::getMessageCountsForAccount(database, accountId(), including_total_count, &ok); - if (including_total_count) { - feed->setCountOfAllMessages(counts.value(feed->customId()).second); - } - } - else { - feed->setCountOfUnreadMessages(0); + if (ok) { + foreach (Feed* feed, feeds) { + if (counts.contains(feed->customId())) { + feed->setCountOfUnreadMessages(counts.value(feed->customId()).first); - if (including_total_count) { - feed->setCountOfAllMessages(0); - } - } - } - } + if (including_total_count) { + feed->setCountOfAllMessages(counts.value(feed->customId()).second); + } + } + else { + feed->setCountOfUnreadMessages(0); + + if (including_total_count) { + feed->setCountOfAllMessages(0); + } + } + } + } } void ServiceRoot::completelyRemoveAllData() { - // Purge old data from SQL and clean all model items. - removeOldFeedTree(true); - cleanAllItems(); - updateCounts(true); - itemChanged(QList() << this); - requestReloadMessageList(true); + // Purge old data from SQL and clean all model items. + removeOldFeedTree(true); + cleanAllItems(); + updateCounts(true); + itemChanged(QList() << this); + requestReloadMessageList(true); } void ServiceRoot::removeOldFeedTree(bool including_messages) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - DatabaseQueries::deleteAccountData(database, accountId(), including_messages); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + + DatabaseQueries::deleteAccountData(database, accountId(), including_messages); } void ServiceRoot::cleanAllItems() { - foreach (RootItem* top_level_item, childItems()) { - if (top_level_item->kind() != RootItemKind::Bin) { - requestItemRemoval(top_level_item); - } - } + foreach (RootItem* top_level_item, childItems()) { + if (top_level_item->kind() != RootItemKind::Bin) { + requestItemRemoval(top_level_item); + } + } } bool ServiceRoot::cleanFeeds(QList items, bool clean_read_only) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - if (DatabaseQueries::cleanFeeds(database, textualFeedIds(items), clean_read_only, accountId())) { - // Messages are cleared, now inform model about need to reload data. - QList itemss; + if (DatabaseQueries::cleanFeeds(database, textualFeedIds(items), clean_read_only, accountId())) { + // Messages are cleared, now inform model about need to reload data. + QList itemss; - foreach (Feed* feed, items) { - feed->updateCounts(true); - itemss.append(feed); - } + foreach (Feed* feed, items) { + feed->updateCounts(true); + itemss.append(feed); + } - RecycleBin* bin = recycleBin(); + RecycleBin* bin = recycleBin(); - if (bin != nullptr) { - bin->updateCounts(true); - itemss.append(bin); - } + if (bin != nullptr) { + bin->updateCounts(true); + itemss.append(bin); + } - itemChanged(itemss); - requestReloadMessageList(true); - return true; - } - else { - return false; - } + itemChanged(itemss); + requestReloadMessageList(true); + return true; + } + else { + return false; + } } void ServiceRoot::storeNewFeedTree(RootItem* root) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - if (DatabaseQueries::storeAccountTree(database, root, accountId())) { - RecycleBin* bin = recycleBin(); + if (DatabaseQueries::storeAccountTree(database, root, accountId())) { + RecycleBin* bin = recycleBin(); - if (bin != nullptr && !childItems().contains(bin)) { - // As the last item, add recycle bin, which is needed. - appendChild(bin); - bin->updateCounts(true); - } - } + if (bin != nullptr && !childItems().contains(bin)) { + // As the last item, add recycle bin, which is needed. + appendChild(bin); + bin->updateCounts(true); + } + } } void ServiceRoot::removeLeftOverMessages() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - DatabaseQueries::purgeLeftoverMessages(database, accountId()); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + + DatabaseQueries::purgeLeftoverMessages(database, accountId()); } QList ServiceRoot::undeletedMessages() const { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - return DatabaseQueries::getUndeletedMessagesForAccount(database, accountId()); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + + return DatabaseQueries::getUndeletedMessagesForAccount(database, accountId()); } -void ServiceRoot::saveAllCachedData() { -} +void ServiceRoot::saveAllCachedData() {} void ServiceRoot::itemChanged(const QList& items) { - emit dataChanged(items); + emit dataChanged(items); } void ServiceRoot::requestReloadMessageList(bool mark_selected_messages_read) { - emit reloadMessageListRequested(mark_selected_messages_read); + emit reloadMessageListRequested(mark_selected_messages_read); } void ServiceRoot::requestItemExpand(const QList& items, bool expand) { - emit itemExpandRequested(items, expand); + emit itemExpandRequested(items, expand); } void ServiceRoot::requestItemExpandStateSave(RootItem* subtree_root) { - emit itemExpandStateSaveRequested(subtree_root); + emit itemExpandStateSaveRequested(subtree_root); } void ServiceRoot::requestItemReassignment(RootItem* item, RootItem* new_parent) { - emit itemReassignmentRequested(item, new_parent); + emit itemReassignmentRequested(item, new_parent); } void ServiceRoot::requestItemRemoval(RootItem* item) { - emit itemRemovalRequested(item); + emit itemRemovalRequested(item); } void ServiceRoot::syncIn() { - QIcon original_icon = icon(); - setIcon(qApp->icons()->fromTheme(QSL("view-refresh"))); - itemChanged(QList() << this); - RootItem* new_tree = obtainNewTreeForSyncIn(); + QIcon original_icon = icon(); - if (new_tree != nullptr) { - // Purge old data from SQL and clean all model items. - requestItemExpandStateSave(this); - QMap feed_custom_data = storeCustomFeedsData(); - removeOldFeedTree(false); - cleanAllItems(); - restoreCustomFeedsData(feed_custom_data, new_tree->getHashedSubTreeFeeds()); - // Model is clean, now store new tree into DB and - // set primary IDs of the items. - storeNewFeedTree(new_tree); - // We have new feed, some feeds were maybe removed, - // so remove left over messages. - removeLeftOverMessages(); + setIcon(qApp->icons()->fromTheme(QSL("view-refresh"))); + itemChanged(QList() << this); + RootItem* new_tree = obtainNewTreeForSyncIn(); - foreach (RootItem* top_level_item, new_tree->childItems()) { - top_level_item->setParent(nullptr); - requestItemReassignment(top_level_item, this); - } + if (new_tree != nullptr) { + // Purge old data from SQL and clean all model items. + requestItemExpandStateSave(this); + QMap feed_custom_data = storeCustomFeedsData(); + removeOldFeedTree(false); + cleanAllItems(); + restoreCustomFeedsData(feed_custom_data, new_tree->getHashedSubTreeFeeds()); - updateCounts(true); - new_tree->clearChildren(); - new_tree->deleteLater(); - QList all_items = getSubTree(); - itemChanged(all_items); - requestReloadMessageList(true); - // Now we must refresh expand states. - QList items_to_expand; + // Model is clean, now store new tree into DB and + // set primary IDs of the items. + storeNewFeedTree(new_tree); - foreach (RootItem* item, all_items) { - if (qApp->settings()->value(GROUP(CategoriesExpandStates), item->hashCode(), item->childCount() > 0).toBool()) { - items_to_expand.append(item); - } - } + // We have new feed, some feeds were maybe removed, + // so remove left over messages. + removeLeftOverMessages(); - if (!items_to_expand.contains(this)) { - items_to_expand.prepend(this); - } + foreach (RootItem* top_level_item, new_tree->childItems()) { + top_level_item->setParent(nullptr); + requestItemReassignment(top_level_item, this); + } - requestItemExpand(items_to_expand, true); - } + updateCounts(true); + new_tree->clearChildren(); + new_tree->deleteLater(); + QList all_items = getSubTree(); + itemChanged(all_items); + requestReloadMessageList(true); - setIcon(original_icon); - itemChanged(QList() << this); + // Now we must refresh expand states. + QList items_to_expand; + + foreach (RootItem* item, all_items) { + if (qApp->settings()->value(GROUP(CategoriesExpandStates), item->hashCode(), item->childCount() > 0).toBool()) { + items_to_expand.append(item); + } + } + + if (!items_to_expand.contains(this)) { + items_to_expand.prepend(this); + } + + requestItemExpand(items_to_expand, true); + } + + setIcon(original_icon); + itemChanged(QList() << this); } RootItem* ServiceRoot::obtainNewTreeForSyncIn() const { - return nullptr; + return nullptr; } QStringList ServiceRoot::customIDSOfMessagesForItem(RootItem* item) { - if (item->getParentServiceRoot() != this) { - // Not item from this account. - return QStringList(); - } - else { - QStringList list; + if (item->getParentServiceRoot() != this) { + // Not item from this account. + return QStringList(); + } + else { + QStringList list; - switch (item->kind()) { - case RootItemKind::Category: { - foreach (RootItem* child, item->childItems()) { - list.append(customIDSOfMessagesForItem(child)); - } + switch (item->kind()) { + case RootItemKind::Category: { + foreach (RootItem* child, item->childItems()) { + list.append(customIDSOfMessagesForItem(child)); + } - return list; - } + return list; + } - case RootItemKind::ServiceRoot: { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - list = DatabaseQueries::customIdsOfMessagesFromAccount(database, accountId()); - break; - } + case RootItemKind::ServiceRoot: { + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - case RootItemKind::Bin: { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - list = DatabaseQueries::customIdsOfMessagesFromBin(database, accountId()); - break; - } + list = DatabaseQueries::customIdsOfMessagesFromAccount(database, accountId()); + break; + } - case RootItemKind::Feed: { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - list = DatabaseQueries::customIdsOfMessagesFromFeed(database, item->customId(), accountId()); - break; - } + case RootItemKind::Bin: { + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - default: - break; - } + list = DatabaseQueries::customIdsOfMessagesFromBin(database, accountId()); + break; + } - qDebug() << "Custom IDs of messages for some operation are:" << list; - return list; - } + case RootItemKind::Feed: { + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + + list = DatabaseQueries::customIdsOfMessagesFromFeed(database, item->customId(), accountId()); + break; + } + + default: + break; + } + + qDebug() << "Custom IDs of messages for some operation are:" << list; + return list; + } } bool ServiceRoot::markFeedsReadUnread(QList items, RootItem::ReadStatus read) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - if (DatabaseQueries::markFeedsReadUnread(database, textualFeedIds(items), accountId(), read)) { - QList itemss; + if (DatabaseQueries::markFeedsReadUnread(database, textualFeedIds(items), accountId(), read)) { + QList itemss; - foreach (Feed* feed, items) { - feed->updateCounts(false); - itemss.append(feed); - } + foreach (Feed* feed, items) { + feed->updateCounts(false); + itemss.append(feed); + } - itemChanged(itemss); - requestReloadMessageList(read == RootItem::Read); - return true; - } - else { - return false; - } + itemChanged(itemss); + requestReloadMessageList(read == RootItem::Read); + return true; + } + else { + return false; + } } QStringList ServiceRoot::textualFeedIds(const QList& feeds) const { - QStringList stringy_ids; - stringy_ids.reserve(feeds.size()); + QStringList stringy_ids; - foreach (const Feed* feed, feeds) { - stringy_ids.append(QString("'%1'").arg(QString::number(feed->customId()))); - } + stringy_ids.reserve(feeds.size()); - return stringy_ids; + foreach (const Feed* feed, feeds) { + stringy_ids.append(QString("'%1'").arg(QString::number(feed->customId()))); + } + + return stringy_ids; } QStringList ServiceRoot::customIDsOfMessages(const QList& changes) { - QStringList list; + QStringList list; - for (int i = 0; i < changes.size(); i++) { - list.append(changes.at(i).first.m_customId); - } + for (int i = 0; i < changes.size(); i++) { + list.append(changes.at(i).first.m_customId); + } - return list; + return list; } QStringList ServiceRoot::customIDsOfMessages(const QList& messages) { - QStringList list; + QStringList list; - foreach (const Message& message, messages) { - list.append(message.m_customId); - } + foreach (const Message& message, messages) { + list.append(message.m_customId); + } - return list; + return list; } int ServiceRoot::accountId() const { - return m_accountId; + return m_accountId; } void ServiceRoot::setAccountId(int account_id) { - m_accountId = account_id; + m_accountId = account_id; } bool ServiceRoot::loadMessagesForItem(RootItem* item, MessagesModel* model) { - if (item->kind() == RootItemKind::Bin) { - model->setFilter(QString("Messages.is_deleted = 1 AND Messages.is_pdeleted = 0 AND Messages.account_id = %1").arg(QString::number( - accountId()))); - } - else { - QList children = item->getSubTreeFeeds(); - QString filter_clause = textualFeedIds(children).join(QSL(", ")); - model->setFilter( - QString("Feeds.custom_id IN (%1) AND Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND Messages.account_id = %2").arg(filter_clause, - QString::number(accountId()))); - qDebug("Loading messages from feeds: %s.", qPrintable(filter_clause)); - } + if (item->kind() == RootItemKind::Bin) { + model->setFilter(QString("Messages.is_deleted = 1 AND Messages.is_pdeleted = 0 AND Messages.account_id = %1").arg(QString::number( + accountId()))); + } + else { + QList children = item->getSubTreeFeeds(); + QString filter_clause = textualFeedIds(children).join(QSL(", ")); - return true; + model->setFilter( + QString("Feeds.custom_id IN (%1) AND Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND Messages.account_id = %2").arg( + filter_clause, + QString:: + number(accountId()))); + qDebug("Loading messages from feeds: %s.", qPrintable(filter_clause)); + } + + return true; } bool ServiceRoot::onBeforeSetMessagesRead(RootItem* selected_item, const QList& messages, RootItem::ReadStatus read) { - Q_UNUSED(messages) - Q_UNUSED(read) - Q_UNUSED(selected_item) - return true; + Q_UNUSED(messages) + Q_UNUSED(read) + Q_UNUSED(selected_item) + return true; } bool ServiceRoot::onAfterSetMessagesRead(RootItem* selected_item, const QList& messages, RootItem::ReadStatus read) { - Q_UNUSED(messages) - Q_UNUSED(read) - selected_item->updateCounts(false); - itemChanged(QList() << selected_item); - return true; + Q_UNUSED(messages) + Q_UNUSED(read) + selected_item->updateCounts(false); + itemChanged(QList() << selected_item); + return true; } bool ServiceRoot::onBeforeSwitchMessageImportance(RootItem* selected_item, const QList& changes) { - Q_UNUSED(selected_item) - Q_UNUSED(changes) - return true; + Q_UNUSED(selected_item) + Q_UNUSED(changes) + return true; } bool ServiceRoot::onAfterSwitchMessageImportance(RootItem* selected_item, const QList& changes) { - Q_UNUSED(selected_item) - Q_UNUSED(changes) - return true; + Q_UNUSED(selected_item) + Q_UNUSED(changes) + return true; } bool ServiceRoot::onBeforeMessagesDelete(RootItem* selected_item, const QList& messages) { - Q_UNUSED(selected_item) - Q_UNUSED(messages) - return true; + Q_UNUSED(selected_item) + Q_UNUSED(messages) + return true; } bool ServiceRoot::onAfterMessagesDelete(RootItem* selected_item, const QList& messages) { - Q_UNUSED(messages) - // User deleted some messages he selected in message list. - selected_item->updateCounts(true); - RecycleBin* bin = recycleBin(); + Q_UNUSED(messages) - if (selected_item->kind() == RootItemKind::Bin) { - itemChanged(QList() << bin); - } - else { - if (bin != nullptr) { - bin->updateCounts(true); - itemChanged(QList() << selected_item << bin); - } - else { - itemChanged(QList() << selected_item); - } - } + // User deleted some messages he selected in message list. + selected_item->updateCounts(true); + RecycleBin* bin = recycleBin(); - return true; + if (selected_item->kind() == RootItemKind::Bin) { + itemChanged(QList() << bin); + } + else { + if (bin != nullptr) { + bin->updateCounts(true); + itemChanged(QList() << selected_item << bin); + } + else { + itemChanged(QList() << selected_item); + } + } + + return true; } bool ServiceRoot::onBeforeMessagesRestoredFromBin(RootItem* selected_item, const QList& messages) { - Q_UNUSED(selected_item) - Q_UNUSED(messages) - return true; + Q_UNUSED(selected_item) + Q_UNUSED(messages) + return true; } bool ServiceRoot::onAfterMessagesRestoredFromBin(RootItem* selected_item, const QList& messages) { - Q_UNUSED(selected_item) - Q_UNUSED(messages) - updateCounts(true); - itemChanged(getSubTree()); - return true; + Q_UNUSED(selected_item) + Q_UNUSED(messages) + updateCounts(true); + itemChanged(getSubTree()); + return true; } void ServiceRoot::assembleFeeds(Assignment feeds) { - QHash categories = getHashedSubTreeCategories(); + QHash categories = getHashedSubTreeCategories(); - foreach (const AssignmentItem& feed, feeds) { - if (feed.first == NO_PARENT_CATEGORY) { - // This is top-level feed, add it to the root item. - appendChild(feed.second); - } - else if (categories.contains(feed.first)) { - // This feed belongs to this category. - categories.value(feed.first)->appendChild(feed.second); - } - else { - qWarning("Feed '%s' is loose, skipping it.", qPrintable(feed.second->title())); - } - } + foreach (const AssignmentItem& feed, feeds) { + if (feed.first == NO_PARENT_CATEGORY) { + // This is top-level feed, add it to the root item. + appendChild(feed.second); + } + else if (categories.contains(feed.first)) { + // This feed belongs to this category. + categories.value(feed.first)->appendChild(feed.second); + } + else { + qWarning("Feed '%s' is loose, skipping it.", qPrintable(feed.second->title())); + } + } } void ServiceRoot::assembleCategories(Assignment categories) { - QHash assignments; - assignments.insert(NO_PARENT_CATEGORY, this); + QHash assignments; + assignments.insert(NO_PARENT_CATEGORY, this); - // Add top-level categories. - while (!categories.isEmpty()) { - for (int i = 0; i < categories.size(); i++) { - if (assignments.contains(categories.at(i).first)) { - // Parent category of this category is already added. - assignments.value(categories.at(i).first)->appendChild(categories.at(i).second); - // Now, added category can be parent for another categories, add it. - assignments.insert(categories.at(i).second->id(), categories.at(i).second); - // Remove the category from the list, because it was - // added to the final collection. - categories.removeAt(i); - i--; - } - } - } + // Add top-level categories. + while (!categories.isEmpty()) { + for (int i = 0; i < categories.size(); i++) { + if (assignments.contains(categories.at(i).first)) { + // Parent category of this category is already added. + assignments.value(categories.at(i).first)->appendChild(categories.at(i).second); + + // Now, added category can be parent for another categories, add it. + assignments.insert(categories.at(i).second->id(), categories.at(i).second); + + // Remove the category from the list, because it was + // added to the final collection. + categories.removeAt(i); + i--; + } + } + } } diff --git a/src/services/abstract/serviceroot.h b/src/services/abstract/serviceroot.h index cbf5818b0..8819ca51c 100755 --- a/src/services/abstract/serviceroot.h +++ b/src/services/abstract/serviceroot.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -24,7 +25,6 @@ #include - class FeedsModel; class RecycleBin; class QAction; @@ -39,179 +39,179 @@ typedef QPair ImportanceChange; // NOTE: The root usually contains some core functionality of the // service like service account username/password etc. class ServiceRoot : public RootItem { - Q_OBJECT + Q_OBJECT - public: - explicit ServiceRoot(RootItem* parent = nullptr); - virtual ~ServiceRoot(); + public: + explicit ServiceRoot(RootItem* parent = nullptr); + virtual ~ServiceRoot(); - bool deleteViaGui(); - bool markAsReadUnread(ReadStatus status); + bool deleteViaGui(); + bool markAsReadUnread(ReadStatus status); - virtual bool supportsFeedAdding() const = 0; - virtual bool supportsCategoryAdding() const = 0; + virtual bool supportsFeedAdding() const = 0; + virtual bool supportsCategoryAdding() const = 0; - // Returns list of specific actions for "Add new item" main window menu. - // So typical list of returned actions could look like: - // a) Add new feed - // b) Add new category - // c) ... - // NOTE: Caller does NOT take ownership of created menu! - virtual QList addItemMenu(); + // Returns list of specific actions for "Add new item" main window menu. + // So typical list of returned actions could look like: + // a) Add new feed + // b) Add new category + // c) ... + // NOTE: Caller does NOT take ownership of created menu! + virtual QList addItemMenu(); - // Returns actions to display as context menu. - QList contextMenu(); + // Returns actions to display as context menu. + QList contextMenu(); - // Returns list of specific actions to be shown in main window menu - // bar in sections "Services -> 'this service'". - // NOTE: Caller does NOT take ownership of created menu! - virtual QList serviceMenu(); + // Returns list of specific actions to be shown in main window menu + // bar in sections "Services -> 'this service'". + // NOTE: Caller does NOT take ownership of created menu! + virtual QList serviceMenu(); - // Access to recycle bin of this account if there is any. - virtual RecycleBin* recycleBin() const = 0; + // Access to recycle bin of this account if there is any. + virtual RecycleBin* recycleBin() const = 0; - void updateCounts(bool including_total_count); + void updateCounts(bool including_total_count); - QList undeletedMessages() const; + QList undeletedMessages() const; - // Start/stop services. - // Start method is called when feed model gets initialized OR after user adds new service. - // Account should synchronously initialize its children (load them from DB is recommended - // here). - // - // Stop method is called just before application exits OR when - // user explicitly deletes existing service instance. - virtual void start(bool freshly_activated) = 0; - virtual void stop() = 0; + // Start/stop services. + // Start method is called when feed model gets initialized OR after user adds new service. + // Account should synchronously initialize its children (load them from DB is recommended + // here). + // + // Stop method is called just before application exits OR when + // user explicitly deletes existing service instance. + virtual void start(bool freshly_activated) = 0; + virtual void stop() = 0; + virtual void saveAllCachedData(); - virtual void saveAllCachedData(); + // Account ID corresponds with DB attribute Accounts (id). + int accountId() const; + void setAccountId(int account_id); - // Account ID corresponds with DB attribute Accounts (id). - int accountId() const; - void setAccountId(int account_id); + // Returns the UNIQUE code of the given service. + // NOTE: Keep in sync with ServiceEntryRoot::code(). + virtual QString code() const = 0; - // Returns the UNIQUE code of the given service. - // NOTE: Keep in sync with ServiceEntryRoot::code(). - virtual QString code() const = 0; + // Removes all/read only messages from given underlying feeds. + bool cleanFeeds(QList items, bool clean_read_only); - // Removes all/read only messages from given underlying feeds. - bool cleanFeeds(QList items, bool clean_read_only); + // This method should prepare messages for given "item" (download them maybe?) + // into predefined "Messages" table + // and then use method QSqlTableModel::setFilter(....). + // NOTE: It would be more preferable if all messages are downloaded + // right when feeds are updated. + virtual bool loadMessagesForItem(RootItem* item, MessagesModel* model); - // This method should prepare messages for given "item" (download them maybe?) - // into predefined "Messages" table - // and then use method QSqlTableModel::setFilter(....). - // NOTE: It would be more preferable if all messages are downloaded - // right when feeds are updated. - virtual bool loadMessagesForItem(RootItem* item, MessagesModel* model); + // Called BEFORE this read status update (triggered by user in message list) is stored in DB, + // when false is returned, change is aborted. + // This is the place to make some other changes like updating + // some ONLINE service or something. + // + // "read" is status which is ABOUT TO BE SET. + virtual bool onBeforeSetMessagesRead(RootItem* selected_item, const QList& messages, ReadStatus read); - // Called BEFORE this read status update (triggered by user in message list) is stored in DB, - // when false is returned, change is aborted. - // This is the place to make some other changes like updating - // some ONLINE service or something. - // - // "read" is status which is ABOUT TO BE SET. - virtual bool onBeforeSetMessagesRead(RootItem* selected_item, const QList& messages, ReadStatus read); + // Called AFTER this read status update (triggered by user in message list) is stored in DB, + // when false is returned, change is aborted. + // Here service root should inform (via signals) + // which items are actually changed. + // + // "read" is status which is ABOUT TO BE SET. + virtual bool onAfterSetMessagesRead(RootItem* selected_item, const QList& messages, ReadStatus read); - // Called AFTER this read status update (triggered by user in message list) is stored in DB, - // when false is returned, change is aborted. - // Here service root should inform (via signals) - // which items are actually changed. - // - // "read" is status which is ABOUT TO BE SET. - virtual bool onAfterSetMessagesRead(RootItem* selected_item, const QList& messages, ReadStatus read); + // Called BEFORE this importance switch update is stored in DB, + // when false is returned, change is aborted. + // This is the place to make some other changes like updating + // some ONLINE service or something. + // + // "changes" - list of pairs - + virtual bool onBeforeSwitchMessageImportance(RootItem* selected_item, const QList& changes); - // Called BEFORE this importance switch update is stored in DB, - // when false is returned, change is aborted. - // This is the place to make some other changes like updating - // some ONLINE service or something. - // - // "changes" - list of pairs - - virtual bool onBeforeSwitchMessageImportance(RootItem* selected_item, const QList& changes); + // Called AFTER this importance switch update is stored in DB, + // when false is returned, change is aborted. + // Here service root should inform (via signals) + // which items are actually changed. + // + // "changes" - list of pairs - + virtual bool onAfterSwitchMessageImportance(RootItem* selected_item, const QList& changes); - // Called AFTER this importance switch update is stored in DB, - // when false is returned, change is aborted. - // Here service root should inform (via signals) - // which items are actually changed. - // - // "changes" - list of pairs - - virtual bool onAfterSwitchMessageImportance(RootItem* selected_item, const QList& changes); + // Called BEFORE the list of messages is about to be deleted + // by the user from message list. + virtual bool onBeforeMessagesDelete(RootItem* selected_item, const QList& messages); - // Called BEFORE the list of messages is about to be deleted - // by the user from message list. - virtual bool onBeforeMessagesDelete(RootItem* selected_item, const QList& messages); + // Called AFTER the list of messages was deleted + // by the user from message list. + virtual bool onAfterMessagesDelete(RootItem* selected_item, const QList& messages); - // Called AFTER the list of messages was deleted - // by the user from message list. - virtual bool onAfterMessagesDelete(RootItem* selected_item, const QList& messages); + // Called BEFORE the list of messages is about to be restored from recycle bin + // by the user from message list. + // Selected item is naturally recycle bin. + virtual bool onBeforeMessagesRestoredFromBin(RootItem* selected_item, const QList& messages); - // Called BEFORE the list of messages is about to be restored from recycle bin - // by the user from message list. - // Selected item is naturally recycle bin. - virtual bool onBeforeMessagesRestoredFromBin(RootItem* selected_item, const QList& messages); + // Called AFTER the list of messages was restored from recycle bin + // by the user from message list. + // Selected item is naturally recycle bin. + virtual bool onAfterMessagesRestoredFromBin(RootItem* selected_item, const QList& messages); - // Called AFTER the list of messages was restored from recycle bin - // by the user from message list. - // Selected item is naturally recycle bin. - virtual bool onAfterMessagesRestoredFromBin(RootItem* selected_item, const QList& messages); + void completelyRemoveAllData(); + QStringList customIDSOfMessagesForItem(RootItem* item); + bool markFeedsReadUnread(QList items, ReadStatus read); - void completelyRemoveAllData(); - QStringList customIDSOfMessagesForItem(RootItem* item); - bool markFeedsReadUnread(QList items, ReadStatus read); + // Obvious methods to wrap signals. + void itemChanged(const QList& items); + void requestReloadMessageList(bool mark_selected_messages_read); + void requestItemExpand(const QList& items, bool expand); + void requestItemExpandStateSave(RootItem* subtree_root); + void requestItemReassignment(RootItem* item, RootItem* new_parent); + void requestItemRemoval(RootItem* item); - // Obvious methods to wrap signals. - void itemChanged(const QList& items); - void requestReloadMessageList(bool mark_selected_messages_read); - void requestItemExpand(const QList& items, bool expand); - void requestItemExpandStateSave(RootItem* subtree_root); - void requestItemReassignment(RootItem* item, RootItem* new_parent); - void requestItemRemoval(RootItem* item); + public slots: + virtual void addNewFeed(const QString& url = QString()) = 0; + virtual void addNewCategory() = 0; + virtual void syncIn(); - public slots: - virtual void addNewFeed(const QString& url = QString()) = 0; - virtual void addNewCategory() = 0; - virtual void syncIn(); + protected: - protected: - // This method should obtain new tree of feed/messages/etc to perform - // sync in. - virtual RootItem* obtainNewTreeForSyncIn() const; + // This method should obtain new tree of feed/messages/etc to perform + // sync in. + virtual RootItem* obtainNewTreeForSyncIn() const; - // Removes all messages/categories/feeds which are - // associated with this account. - void removeOldFeedTree(bool including_messages); - void storeNewFeedTree(RootItem* root); - void cleanAllItems(); + // Removes all messages/categories/feeds which are + // associated with this account. + void removeOldFeedTree(bool including_messages); + void storeNewFeedTree(RootItem* root); + void cleanAllItems(); - // Removes messages which do not belong to any - // existing feed. - // - // NOTE: This situation may happen if user deletes some feed - // from another machine and then performs sync-in on this machine. - void removeLeftOverMessages(); + // Removes messages which do not belong to any + // existing feed. + // + // NOTE: This situation may happen if user deletes some feed + // from another machine and then performs sync-in on this machine. + void removeLeftOverMessages(); - QStringList textualFeedIds(const QList& feeds) const; - QStringList customIDsOfMessages(const QList& changes); - QStringList customIDsOfMessages(const QList& messages); + QStringList textualFeedIds(const QList& feeds) const; + QStringList customIDsOfMessages(const QList& changes); + QStringList customIDsOfMessages(const QList& messages); - // Takes lists of feeds/categories and assembles them into the tree structure. - void assembleCategories(Assignment categories); - void assembleFeeds(Assignment feeds); + // Takes lists of feeds/categories and assembles them into the tree structure. + void assembleCategories(Assignment categories); + void assembleFeeds(Assignment feeds); - signals: - // Emitted if data in any item belonging to this root are changed. - void dataChanged(QList items); - void reloadMessageListRequested(bool mark_selected_messages_read); - void itemExpandRequested(QList items, bool expand); - void itemExpandStateSaveRequested(RootItem* subtree_root); + signals: - void itemReassignmentRequested(RootItem* item, RootItem* new_parent); - void itemRemovalRequested(RootItem* item); + // Emitted if data in any item belonging to this root are changed. + void dataChanged(QList items); + void reloadMessageListRequested(bool mark_selected_messages_read); + void itemExpandRequested(QList items, bool expand); + void itemExpandStateSaveRequested(RootItem* subtree_root); - private: - virtual QMap storeCustomFeedsData() = 0; - virtual void restoreCustomFeedsData(const QMap& data, const QHash& feeds) = 0; + void itemReassignmentRequested(RootItem* item, RootItem* new_parent); + void itemRemovalRequested(RootItem* item); - int m_accountId; + private: + virtual QMap storeCustomFeedsData() = 0; + virtual void restoreCustomFeedsData(const QMap& data, const QHash& feeds) = 0; + int m_accountId; }; #endif // SERVICEROOT_H diff --git a/src/services/owncloud/definitions.h b/src/services/owncloud/definitions.h index fb19ac250..7ed85770c 100755 --- a/src/services/owncloud/definitions.h +++ b/src/services/owncloud/definitions.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -24,4 +25,3 @@ #define MINIMAL_OC_VERSION "6.0.5" #endif // OWNCLOUD_DEFINITIONS_H - diff --git a/src/services/owncloud/gui/formeditowncloudaccount.cpp b/src/services/owncloud/gui/formeditowncloudaccount.cpp index 47ed6d762..06c5ef6e1 100755 --- a/src/services/owncloud/gui/formeditowncloudaccount.cpp +++ b/src/services/owncloud/gui/formeditowncloudaccount.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,36 +18,35 @@ #include "services/owncloud/gui/formeditowncloudaccount.h" -#include "services/owncloud/definitions.h" -#include "services/owncloud/owncloudserviceroot.h" -#include "services/owncloud/network/owncloudnetworkfactory.h" +#include "gui/guiutilities.h" #include "miscellaneous/iconfactory.h" #include "network-web/networkfactory.h" -#include "gui/guiutilities.h" - +#include "services/owncloud/definitions.h" +#include "services/owncloud/network/owncloudnetworkfactory.h" +#include "services/owncloud/owncloudserviceroot.h" FormEditOwnCloudAccount::FormEditOwnCloudAccount(QWidget* parent) - : QDialog(parent), m_ui(new Ui::FormEditOwnCloudAccount), m_editableRoot(nullptr) { - m_ui->setupUi(this); - m_btnOk = m_ui->m_buttonBox->button(QDialogButtonBox::Ok); + : QDialog(parent), m_ui(new Ui::FormEditOwnCloudAccount), m_editableRoot(nullptr) { + m_ui->setupUi(this); + m_btnOk = m_ui->m_buttonBox->button(QDialogButtonBox::Ok); GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("owncloud"))); m_ui->m_lblTestResult->label()->setWordWrap(true); - m_ui->m_lblServerSideUpdateInformation->setText(tr("Leaving this option on causes that updates " - "of feeds will be probably much slower and may time-out often.")); - m_ui->m_lblDescription->setText(tr("Note that at least version %1 is required.").arg(MINIMAL_OC_VERSION)); - m_ui->m_txtPassword->lineEdit()->setPlaceholderText(tr("Password for your ownCloud account")); - m_ui->m_txtUsername->lineEdit()->setPlaceholderText(tr("Username for your ownCloud account")); - m_ui->m_txtUrl->lineEdit()->setPlaceholderText(tr("URL of your ownCloud server, without any API path")); - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Information, - tr("No test done yet."), - tr("Here, results of connection test are shown.")); + m_ui->m_lblServerSideUpdateInformation->setText(tr("Leaving this option on causes that updates " + "of feeds will be probably much slower and may time-out often.")); + m_ui->m_lblDescription->setText(tr("Note that at least version %1 is required.").arg(MINIMAL_OC_VERSION)); + m_ui->m_txtPassword->lineEdit()->setPlaceholderText(tr("Password for your ownCloud account")); + m_ui->m_txtUsername->lineEdit()->setPlaceholderText(tr("Username for your ownCloud account")); + m_ui->m_txtUrl->lineEdit()->setPlaceholderText(tr("URL of your ownCloud server, without any API path")); + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Information, + tr("No test done yet."), + tr("Here, results of connection test are shown.")); m_ui->m_lblLimitMessages->setText( - tr("Limiting number of downloaded messages per feed makes updating of feeds faster but if your feed contains " - "bigger number of messages than specified limit, then some messages might not be downloaded during feed update.")); + tr("Limiting number of downloaded messages per feed makes updating of feeds faster but if your feed contains " + "bigger number of messages than specified limit, then some messages might not be downloaded during feed update.")); - connect(m_ui->m_spinLimitMessages, static_cast(&QSpinBox::valueChanged), [ = ](int value) { + connect(m_ui->m_spinLimitMessages, static_cast(&QSpinBox::valueChanged), [=](int value) { if (value <= 0) { m_ui->m_spinLimitMessages->setSuffix(QSL(" ") + tr("= unlimited")); } @@ -62,152 +62,155 @@ FormEditOwnCloudAccount::FormEditOwnCloudAccount(QWidget* parent) setTabOrder(m_ui->m_txtUrl->lineEdit(), m_ui->m_checkServerSideUpdate); setTabOrder(m_ui->m_checkServerSideUpdate, m_ui->m_spinLimitMessages); setTabOrder(m_ui->m_spinLimitMessages, m_ui->m_txtUsername->lineEdit()); - setTabOrder(m_ui->m_txtUsername->lineEdit(), m_ui->m_txtPassword->lineEdit()); - setTabOrder(m_ui->m_txtPassword->lineEdit(), m_ui->m_checkShowPassword); - setTabOrder(m_ui->m_checkShowPassword, m_ui->m_btnTestSetup); - setTabOrder(m_ui->m_btnTestSetup, m_ui->m_buttonBox); + setTabOrder(m_ui->m_txtUsername->lineEdit(), m_ui->m_txtPassword->lineEdit()); + setTabOrder(m_ui->m_txtPassword->lineEdit(), m_ui->m_checkShowPassword); + setTabOrder(m_ui->m_checkShowPassword, m_ui->m_btnTestSetup); + setTabOrder(m_ui->m_btnTestSetup, m_ui->m_buttonBox); connect(m_ui->m_checkShowPassword, &QCheckBox::toggled, this, &FormEditOwnCloudAccount::displayPassword); - connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormEditOwnCloudAccount::onClickedOk); - connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &FormEditOwnCloudAccount::onClickedCancel); - connect(m_ui->m_txtPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::onPasswordChanged); - connect(m_ui->m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::onUsernameChanged); - connect(m_ui->m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::onUrlChanged); - connect(m_ui->m_txtPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::checkOkButton); - connect(m_ui->m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::checkOkButton); - connect(m_ui->m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::checkOkButton); - connect(m_ui->m_btnTestSetup, &QPushButton::clicked, this, &FormEditOwnCloudAccount::performTest); + connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormEditOwnCloudAccount::onClickedOk); + connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &FormEditOwnCloudAccount::onClickedCancel); + connect(m_ui->m_txtPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::onPasswordChanged); + connect(m_ui->m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::onUsernameChanged); + connect(m_ui->m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::onUrlChanged); + connect(m_ui->m_txtPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::checkOkButton); + connect(m_ui->m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::checkOkButton); + connect(m_ui->m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditOwnCloudAccount::checkOkButton); + connect(m_ui->m_btnTestSetup, &QPushButton::clicked, this, &FormEditOwnCloudAccount::performTest); onPasswordChanged(); - onUsernameChanged(); - onUrlChanged(); - checkOkButton(); - displayPassword(false); + onUsernameChanged(); + onUrlChanged(); + checkOkButton(); + displayPassword(false); } -FormEditOwnCloudAccount::~FormEditOwnCloudAccount() { -} +FormEditOwnCloudAccount::~FormEditOwnCloudAccount() {} OwnCloudServiceRoot* FormEditOwnCloudAccount::execForCreate() { - setWindowTitle(tr("Add new ownCloud News account")); - exec(); - return m_editableRoot; + setWindowTitle(tr("Add new ownCloud News account")); + exec(); + return m_editableRoot; } void FormEditOwnCloudAccount::execForEdit(OwnCloudServiceRoot* existing_root) { - setWindowTitle(tr("Edit existing ownCloud News account")); - m_editableRoot = existing_root; - m_ui->m_txtUsername->lineEdit()->setText(existing_root->network()->authUsername()); - m_ui->m_txtPassword->lineEdit()->setText(existing_root->network()->authPassword()); - m_ui->m_txtUrl->lineEdit()->setText(existing_root->network()->url()); - m_ui->m_checkServerSideUpdate->setChecked(existing_root->network()->forceServerSideUpdate()); + setWindowTitle(tr("Edit existing ownCloud News account")); + m_editableRoot = existing_root; + m_ui->m_txtUsername->lineEdit()->setText(existing_root->network()->authUsername()); + m_ui->m_txtPassword->lineEdit()->setText(existing_root->network()->authPassword()); + m_ui->m_txtUrl->lineEdit()->setText(existing_root->network()->url()); + m_ui->m_checkServerSideUpdate->setChecked(existing_root->network()->forceServerSideUpdate()); m_ui->m_spinLimitMessages->setValue(existing_root->network()->batchSize()); - exec(); + exec(); } void FormEditOwnCloudAccount::displayPassword(bool display) { - m_ui->m_txtPassword->lineEdit()->setEchoMode(display ? QLineEdit::Normal : QLineEdit::Password); + m_ui->m_txtPassword->lineEdit()->setEchoMode(display ? QLineEdit::Normal : QLineEdit::Password); } void FormEditOwnCloudAccount::performTest() { - OwnCloudNetworkFactory factory; + OwnCloudNetworkFactory factory; - factory.setAuthUsername(m_ui->m_txtUsername->lineEdit()->text()); - factory.setAuthPassword(m_ui->m_txtPassword->lineEdit()->text()); - factory.setUrl(m_ui->m_txtUrl->lineEdit()->text()); - factory.setForceServerSideUpdate(m_ui->m_checkServerSideUpdate->isChecked()); + factory.setAuthUsername(m_ui->m_txtUsername->lineEdit()->text()); + factory.setAuthPassword(m_ui->m_txtPassword->lineEdit()->text()); + factory.setUrl(m_ui->m_txtUrl->lineEdit()->text()); + factory.setForceServerSideUpdate(m_ui->m_checkServerSideUpdate->isChecked()); - OwnCloudStatusResponse result = factory.status(); + OwnCloudStatusResponse result = factory.status(); - if (result.isLoaded()) { - if (!SystemFactory::isVersionEqualOrNewer(result.version(), MINIMAL_OC_VERSION)) { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, - tr("Selected ownCloud News server is running unsupported version (%1). At least version %2 is required.").arg(result.version(), - MINIMAL_OC_VERSION), - tr("Selected ownCloud News server is running unsupported version.")); - } - else { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Ok, - tr("ownCloud News server is okay, running with version %1, while at least version %2 is required.").arg(result.version(), - MINIMAL_OC_VERSION), - tr("ownCloud News server is okay.")); - } - } - else if (factory.lastError() != QNetworkReply::NoError) { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, - tr("Network error: '%1'.").arg(NetworkFactory::networkErrorText(factory.lastError())), - tr("Network error, have you entered correct ownCloud endpoint and password?")); - } - else { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, - tr("Unspecified error, did you enter correct URL?"), - tr("Unspecified error, did you enter correct URL?")); - } + if (result.isLoaded()) { + if (!SystemFactory::isVersionEqualOrNewer(result.version(), MINIMAL_OC_VERSION)) { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, + tr( + "Selected ownCloud News server is running unsupported version (%1). At least version %2 is required.").arg( + result.version(), + MINIMAL_OC_VERSION), + tr("Selected ownCloud News server is running unsupported version.")); + } + else { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Ok, + tr( + "ownCloud News server is okay, running with version %1, while at least version %2 is required.").arg( + result.version(), + MINIMAL_OC_VERSION), + tr("ownCloud News server is okay.")); + } + } + else if (factory.lastError() != QNetworkReply::NoError) { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, + tr("Network error: '%1'.").arg(NetworkFactory::networkErrorText(factory.lastError())), + tr("Network error, have you entered correct ownCloud endpoint and password?")); + } + else { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, + tr("Unspecified error, did you enter correct URL?"), + tr("Unspecified error, did you enter correct URL?")); + } } void FormEditOwnCloudAccount::onClickedOk() { - bool editing_account = true; + bool editing_account = true; - if (m_editableRoot == nullptr) { - // We want to confirm newly created account. - // So save new account into DB, setup its properties. - m_editableRoot = new OwnCloudServiceRoot(); - editing_account = false; - } + if (m_editableRoot == nullptr) { + // We want to confirm newly created account. + // So save new account into DB, setup its properties. + m_editableRoot = new OwnCloudServiceRoot(); + editing_account = false; + } - m_editableRoot->network()->setUrl(m_ui->m_txtUrl->lineEdit()->text()); - m_editableRoot->network()->setAuthUsername(m_ui->m_txtUsername->lineEdit()->text()); - m_editableRoot->network()->setAuthPassword(m_ui->m_txtPassword->lineEdit()->text()); - m_editableRoot->network()->setForceServerSideUpdate(m_ui->m_checkServerSideUpdate->isChecked()); + m_editableRoot->network()->setUrl(m_ui->m_txtUrl->lineEdit()->text()); + m_editableRoot->network()->setAuthUsername(m_ui->m_txtUsername->lineEdit()->text()); + m_editableRoot->network()->setAuthPassword(m_ui->m_txtPassword->lineEdit()->text()); + m_editableRoot->network()->setForceServerSideUpdate(m_ui->m_checkServerSideUpdate->isChecked()); m_editableRoot->network()->setBatchSize(m_ui->m_spinLimitMessages->value()); - m_editableRoot->saveAccountDataToDatabase(); - accept(); + m_editableRoot->saveAccountDataToDatabase(); + accept(); - if (editing_account) { - m_editableRoot->completelyRemoveAllData(); - m_editableRoot->syncIn(); - } + if (editing_account) { + m_editableRoot->completelyRemoveAllData(); + m_editableRoot->syncIn(); + } } void FormEditOwnCloudAccount::onClickedCancel() { - reject(); + reject(); } void FormEditOwnCloudAccount::onUsernameChanged() { - const QString username = m_ui->m_txtUsername->lineEdit()->text(); + const QString username = m_ui->m_txtUsername->lineEdit()->text(); - if (username.isEmpty()) { - m_ui->m_txtUsername->setStatus(WidgetWithStatus::Error, tr("Username cannot be empty.")); - } - else { - m_ui->m_txtUsername->setStatus(WidgetWithStatus::Ok, tr("Username is okay.")); - } + if (username.isEmpty()) { + m_ui->m_txtUsername->setStatus(WidgetWithStatus::Error, tr("Username cannot be empty.")); + } + else { + m_ui->m_txtUsername->setStatus(WidgetWithStatus::Ok, tr("Username is okay.")); + } } void FormEditOwnCloudAccount::onPasswordChanged() { - const QString password = m_ui->m_txtPassword->lineEdit()->text(); + const QString password = m_ui->m_txtPassword->lineEdit()->text(); - if (password.isEmpty()) { - m_ui->m_txtPassword->setStatus(WidgetWithStatus::Error, tr("Password cannot be empty.")); - } - else { - m_ui->m_txtPassword->setStatus(WidgetWithStatus::Ok, tr("Password is okay.")); - } + if (password.isEmpty()) { + m_ui->m_txtPassword->setStatus(WidgetWithStatus::Error, tr("Password cannot be empty.")); + } + else { + m_ui->m_txtPassword->setStatus(WidgetWithStatus::Ok, tr("Password is okay.")); + } } void FormEditOwnCloudAccount::onUrlChanged() { - const QString url = m_ui->m_txtUrl->lineEdit()->text(); + const QString url = m_ui->m_txtUrl->lineEdit()->text(); - if (url.isEmpty()) { - m_ui->m_txtUrl->setStatus(WidgetWithStatus::Error, tr("URL cannot be empty.")); - } - else { - m_ui->m_txtUrl->setStatus(WidgetWithStatus::Ok, tr("URL is okay.")); - } + if (url.isEmpty()) { + m_ui->m_txtUrl->setStatus(WidgetWithStatus::Error, tr("URL cannot be empty.")); + } + else { + m_ui->m_txtUrl->setStatus(WidgetWithStatus::Ok, tr("URL is okay.")); + } } void FormEditOwnCloudAccount::checkOkButton() { - m_btnOk->setEnabled(!m_ui->m_txtUsername->lineEdit()->text().isEmpty() && - !m_ui->m_txtPassword->lineEdit()->text().isEmpty() && - !m_ui->m_txtUrl->lineEdit()->text().isEmpty()); + m_btnOk->setEnabled(!m_ui->m_txtUsername->lineEdit()->text().isEmpty() && + !m_ui->m_txtPassword->lineEdit()->text().isEmpty() && + !m_ui->m_txtUrl->lineEdit()->text().isEmpty()); } diff --git a/src/services/owncloud/gui/formeditowncloudaccount.h b/src/services/owncloud/gui/formeditowncloudaccount.h index f213e1439..a233612bd 100755 --- a/src/services/owncloud/gui/formeditowncloudaccount.h +++ b/src/services/owncloud/gui/formeditowncloudaccount.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,38 +23,38 @@ #include "ui_formeditowncloudaccount.h" - namespace Ui { - class FormEditAccount; + class FormEditAccount; } class OwnCloudServiceRoot; class FormEditOwnCloudAccount : public QDialog { - Q_OBJECT + Q_OBJECT - public: - explicit FormEditOwnCloudAccount(QWidget* parent = 0); - virtual ~FormEditOwnCloudAccount(); + public: + explicit FormEditOwnCloudAccount(QWidget* parent = 0); + virtual ~FormEditOwnCloudAccount(); - OwnCloudServiceRoot* execForCreate(); - void execForEdit(OwnCloudServiceRoot* existing_root); + OwnCloudServiceRoot* execForCreate(); - private slots: - void displayPassword(bool display); - void performTest(); - void onClickedOk(); - void onClickedCancel(); + void execForEdit(OwnCloudServiceRoot* existing_root); - void onUsernameChanged(); - void onPasswordChanged(); - void onUrlChanged(); - void checkOkButton(); + private slots: + void displayPassword(bool display); + void performTest(); + void onClickedOk(); + void onClickedCancel(); - private: - QScopedPointer m_ui; - OwnCloudServiceRoot* m_editableRoot; - QPushButton* m_btnOk; + void onUsernameChanged(); + void onPasswordChanged(); + void onUrlChanged(); + void checkOkButton(); + + private: + QScopedPointer m_ui; + OwnCloudServiceRoot* m_editableRoot; + QPushButton* m_btnOk; }; #endif // FORMEDITOWNCLOUDACCOUNT_H diff --git a/src/services/owncloud/gui/formowncloudfeeddetails.cpp b/src/services/owncloud/gui/formowncloudfeeddetails.cpp index 07f1a74b1..bfe25f6fa 100755 --- a/src/services/owncloud/gui/formowncloudfeeddetails.cpp +++ b/src/services/owncloud/gui/formowncloudfeeddetails.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,83 +18,83 @@ #include "services/owncloud/gui/formowncloudfeeddetails.h" +#include "miscellaneous/application.h" +#include "services/owncloud/network/owncloudnetworkfactory.h" #include "services/owncloud/owncloudfeed.h" #include "services/owncloud/owncloudserviceroot.h" -#include "services/owncloud/network/owncloudnetworkfactory.h" -#include "miscellaneous/application.h" #include - FormOwnCloudFeedDetails::FormOwnCloudFeedDetails(ServiceRoot* service_root, QWidget* parent) - : FormFeedDetails(service_root, parent) { - m_ui->m_spinAutoUpdateInterval->setEnabled(false); - m_ui->m_cmbAutoUpdateType->setEnabled(false); - m_ui->m_cmbType->setEnabled(false); - m_ui->m_cmbEncoding->setEnabled(false); - m_ui->m_btnFetchMetadata->setEnabled(false); - m_ui->m_btnIcon->setEnabled(false); - m_ui->m_txtTitle->setEnabled(false); - m_ui->m_txtUrl->setEnabled(true); - m_ui->m_txtDescription->setEnabled(false); + : FormFeedDetails(service_root, parent) { + m_ui->m_spinAutoUpdateInterval->setEnabled(false); + m_ui->m_cmbAutoUpdateType->setEnabled(false); + m_ui->m_cmbType->setEnabled(false); + m_ui->m_cmbEncoding->setEnabled(false); + m_ui->m_btnFetchMetadata->setEnabled(false); + m_ui->m_btnIcon->setEnabled(false); + m_ui->m_txtTitle->setEnabled(false); + m_ui->m_txtUrl->setEnabled(true); + m_ui->m_txtDescription->setEnabled(false); } void FormOwnCloudFeedDetails::apply() { - if (m_editableFeed != nullptr) { - bool renamed = false; + if (m_editableFeed != nullptr) { + bool renamed = false; - if (m_ui->m_txtTitle->lineEdit()->text() != m_editableFeed->title()) { - if (!qobject_cast(m_serviceRoot)->network()->renameFeed(m_ui->m_txtTitle->lineEdit()->text(), - m_editableFeed->customId())) { - qWarning("ownCloud: DoÅ¡lo k problému pÅ™i prejmenování kanálu s ownCloud ID '%d'.", m_editableFeed->customId()); - } - else { - renamed = true; - } - } + if (m_ui->m_txtTitle->lineEdit()->text() != m_editableFeed->title()) { + if (!qobject_cast(m_serviceRoot)->network()->renameFeed(m_ui->m_txtTitle->lineEdit()->text(), + m_editableFeed->customId())) { + qWarning("ownCloud: DoÅ¡lo k problému pÅ™i prejmenování kanálu s ownCloud ID '%d'.", m_editableFeed->customId()); + } + else { + renamed = true; + } + } - // User edited auto-update status. Save it. - OwnCloudFeed* new_feed_data = new OwnCloudFeed(); - new_feed_data->setAutoUpdateType(static_cast(m_ui->m_cmbAutoUpdateType->itemData( - m_ui->m_cmbAutoUpdateType->currentIndex()).toInt())); - new_feed_data->setAutoUpdateInitialInterval(m_ui->m_spinAutoUpdateInterval->value()); - qobject_cast(m_editableFeed)->editItself(new_feed_data); - delete new_feed_data; + // User edited auto-update status. Save it. + OwnCloudFeed* new_feed_data = new OwnCloudFeed(); - if (renamed) { - QTimer::singleShot(200, m_serviceRoot, SLOT(syncIn())); - } - } - else { - const RootItem* parent = static_cast(m_ui->m_cmbParentCategory->itemData( - m_ui->m_cmbParentCategory->currentIndex()).value()); - const int category_id = parent->kind() == RootItemKind::ServiceRoot ? 0 : parent->customId(); - const bool response = qobject_cast(m_serviceRoot)->network()->createFeed(m_ui->m_txtUrl->lineEdit()->text(), - category_id); + new_feed_data->setAutoUpdateType(static_cast(m_ui->m_cmbAutoUpdateType->itemData( + m_ui->m_cmbAutoUpdateType->currentIndex()).toInt())); + new_feed_data->setAutoUpdateInitialInterval(m_ui->m_spinAutoUpdateInterval->value()); + qobject_cast(m_editableFeed)->editItself(new_feed_data); + delete new_feed_data; - if (response) { - // Feed was added online. - accept(); - qApp->showGuiMessage(tr("Feed added"), tr("Feed was added, triggering sync in now."), QSystemTrayIcon::Information); - QTimer::singleShot(100, m_serviceRoot, SLOT(syncIn())); - } - else { - reject(); - qApp->showGuiMessage(tr("Cannot add feed"), - tr("Feed was not added due to error."), - QSystemTrayIcon::Critical, qApp->mainFormWidget(), true); - } - } + if (renamed) { + QTimer::singleShot(200, m_serviceRoot, SLOT(syncIn())); + } + } + else { + const RootItem* parent = static_cast(m_ui->m_cmbParentCategory->itemData( + m_ui->m_cmbParentCategory->currentIndex()).value()); + const int category_id = parent->kind() == RootItemKind::ServiceRoot ? 0 : parent->customId(); + const bool response = qobject_cast(m_serviceRoot)->network()->createFeed(m_ui->m_txtUrl->lineEdit()->text(), + category_id); - accept(); + if (response) { + // Feed was added online. + accept(); + qApp->showGuiMessage(tr("Feed added"), tr("Feed was added, triggering sync in now."), QSystemTrayIcon::Information); + QTimer::singleShot(100, m_serviceRoot, SLOT(syncIn())); + } + else { + reject(); + qApp->showGuiMessage(tr("Cannot add feed"), + tr("Feed was not added due to error."), + QSystemTrayIcon::Critical, qApp->mainFormWidget(), true); + } + } + + accept(); } void FormOwnCloudFeedDetails::setEditableFeed(Feed* editable_feed) { - m_ui->m_cmbAutoUpdateType->setEnabled(true); - FormFeedDetails::setEditableFeed(editable_feed); - m_ui->m_txtTitle->setEnabled(true); - m_ui->m_gbAuthentication->setEnabled(false); - m_ui->m_txtUrl->setEnabled(false); - m_ui->m_lblParentCategory->setEnabled(false); - m_ui->m_cmbParentCategory->setEnabled(false); + m_ui->m_cmbAutoUpdateType->setEnabled(true); + FormFeedDetails::setEditableFeed(editable_feed); + m_ui->m_txtTitle->setEnabled(true); + m_ui->m_gbAuthentication->setEnabled(false); + m_ui->m_txtUrl->setEnabled(false); + m_ui->m_lblParentCategory->setEnabled(false); + m_ui->m_cmbParentCategory->setEnabled(false); } diff --git a/src/services/owncloud/gui/formowncloudfeeddetails.h b/src/services/owncloud/gui/formowncloudfeeddetails.h index 1c1bdc913..fbacac080 100755 --- a/src/services/owncloud/gui/formowncloudfeeddetails.h +++ b/src/services/owncloud/gui/formowncloudfeeddetails.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,18 +21,17 @@ #include "services/abstract/gui/formfeeddetails.h" - class FormOwnCloudFeedDetails : public FormFeedDetails { - Q_OBJECT + Q_OBJECT - public: - explicit FormOwnCloudFeedDetails(ServiceRoot* service_root, QWidget* parent = 0); + public: + explicit FormOwnCloudFeedDetails(ServiceRoot* service_root, QWidget* parent = 0); - protected slots: - void apply(); + protected slots: + void apply(); - protected: - void setEditableFeed(Feed* editable_feed); + protected: + void setEditableFeed(Feed* editable_feed); }; #endif // FORMOWNCLOUDFEEDDETAILS_H diff --git a/src/services/owncloud/network/owncloudnetworkfactory.cpp b/src/services/owncloud/network/owncloudnetworkfactory.cpp index ee01ef432..188688b10 100755 --- a/src/services/owncloud/network/owncloudnetworkfactory.cpp +++ b/src/services/owncloud/network/owncloudnetworkfactory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -31,7 +32,6 @@ #include #include - OwnCloudNetworkFactory::OwnCloudNetworkFactory() : m_url(QString()), m_fixedUrl(QString()), m_forceServerSideUpdate(false), m_authUsername(QString()), m_authPassword(QString()), m_batchSize(-1), m_urlUser(QString()), m_urlStatus(QString()), @@ -47,8 +47,7 @@ QString OwnCloudNetworkFactory::url() const { void OwnCloudNetworkFactory::setUrl(const QString& url) { m_url = url; - if (url.endsWith('/') - ) { + if (url.endsWith('/')) { m_fixedUrl = url; } else { @@ -108,8 +107,7 @@ OwnCloudUserResponse OwnCloudNetworkFactory::userInfo() { true); OwnCloudUserResponse user_response(QString::fromUtf8(result_raw)); - if (network_reply.first != QNetworkReply::NoError - ) { + if (network_reply.first != QNetworkReply::NoError) { qWarning("ownCloud: Obtaining user info failed with error %d.", network_reply.first); } @@ -128,8 +126,7 @@ OwnCloudStatusResponse OwnCloudNetworkFactory::status() { true); OwnCloudStatusResponse status_response(QString::fromUtf8(result_raw)); - if (network_reply.first != QNetworkReply::NoError - ) { + if (network_reply.first != QNetworkReply::NoError) { qWarning("ownCloud: Obtaining status info failed with error %d.", network_reply.first); } @@ -147,8 +144,7 @@ OwnCloudGetFeedsCategoriesResponse OwnCloudNetworkFactory::feedsCategories() { true, m_authUsername, m_authPassword, true); - if (network_reply.first != QNetworkReply::NoError - ) { + if (network_reply.first != QNetworkReply::NoError) { qWarning("ownCloud: Obtaining of categories failed with error %d.", network_reply.first); m_lastError = network_reply.first; return OwnCloudGetFeedsCategoriesResponse(); @@ -156,7 +152,6 @@ OwnCloudGetFeedsCategoriesResponse OwnCloudNetworkFactory::feedsCategories() { QString content_categories = QString::fromUtf8(result_raw); - // Now, obtain feeds. network_reply = NetworkFactory::performNetworkOperation(m_urlFeeds, qApp->settings()->value(GROUP(Feeds), @@ -166,8 +161,7 @@ OwnCloudGetFeedsCategoriesResponse OwnCloudNetworkFactory::feedsCategories() { true, m_authUsername, m_authPassword, true); - if (network_reply.first != QNetworkReply::NoError - ) { + if (network_reply.first != QNetworkReply::NoError) { qWarning("ownCloud: Obtaining of feeds failed with error %d.", network_reply.first); m_lastError = network_reply.first; return OwnCloudGetFeedsCategoriesResponse(); @@ -175,7 +169,6 @@ OwnCloudGetFeedsCategoriesResponse OwnCloudNetworkFactory::feedsCategories() { QString content_feeds = QString::fromUtf8(result_raw); - m_lastError = network_reply.first; return OwnCloudGetFeedsCategoriesResponse(content_categories, content_feeds); } @@ -192,8 +185,7 @@ bool OwnCloudNetworkFactory::deleteFeed(int feed_id) { m_lastError = network_reply.first; - if (network_reply.first != QNetworkReply::NoError - ) { + if (network_reply.first != QNetworkReply::NoError) { qWarning("ownCloud: Obtaining of categories failed with error %d.", network_reply.first); return false; } @@ -218,11 +210,9 @@ bool OwnCloudNetworkFactory::createFeed(const QString& url, int parent_id) { QNetworkAccessManager::PostOperation, true, m_authUsername, m_authPassword, true); - m_lastError = network_reply.first; - if (network_reply.first != QNetworkReply::NoError - ) { + if (network_reply.first != QNetworkReply::NoError) { qWarning("ownCloud: Creating of category failed with error %d.", network_reply.first); return false; } @@ -248,11 +238,9 @@ bool OwnCloudNetworkFactory::renameFeed(const QString& new_name, int feed_id) { true, m_authUsername, m_authPassword, true); - m_lastError = network_reply.first; - if (network_reply.first != QNetworkReply::NoError - ) { + if (network_reply.first != QNetworkReply::NoError) { qWarning("ownCloud: Renaming of feed failed with error %d.", network_reply.first); return false; } @@ -262,8 +250,7 @@ bool OwnCloudNetworkFactory::renameFeed(const QString& new_name, int feed_id) { } OwnCloudGetMessagesResponse OwnCloudNetworkFactory::getMessages(int feed_id) { - if (forceServerSideUpdate() - ) { + if (forceServerSideUpdate()) { triggerFeedUpdate(feed_id); } @@ -280,9 +267,7 @@ OwnCloudGetMessagesResponse OwnCloudNetworkFactory::getMessages(int feed_id) { true); OwnCloudGetMessagesResponse msgs_response(QString::fromUtf8(result_raw)); - - if (network_reply.first != QNetworkReply::NoError - ) { + if (network_reply.first != QNetworkReply::NoError) { qWarning("ownCloud: Obtaining messages failed with error %d.", network_reply.first); } @@ -291,14 +276,11 @@ OwnCloudGetMessagesResponse OwnCloudNetworkFactory::getMessages(int feed_id) { } QNetworkReply::NetworkError OwnCloudNetworkFactory::triggerFeedUpdate(int feed_id) { - if (userId().isEmpty() - ) { + if (userId().isEmpty()) { // We need to get user ID first. OwnCloudUserResponse info = userInfo(); - - if (lastError() != QNetworkReply::NoError - ) { + if (lastError() != QNetworkReply::NoError) { return lastError(); } else { @@ -318,8 +300,7 @@ QNetworkReply::NetworkError OwnCloudNetworkFactory::triggerFeedUpdate(int feed_i true, m_authUsername, m_authPassword, true); - if (network_reply.first != QNetworkReply::NoError - ) { + if (network_reply.first != QNetworkReply::NoError) { qWarning("ownCloud: Feeds update failed with error %d.", network_reply.first); } @@ -331,8 +312,7 @@ void OwnCloudNetworkFactory::markMessagesRead(RootItem::ReadStatus status, const QJsonArray ids; QString final_url; - if (status == RootItem::Read - ) { + if (status == RootItem::Read) { final_url = m_fixedUrl + API_PATH + "items/read/multiple"; } else { @@ -354,7 +334,6 @@ void OwnCloudNetworkFactory::markMessagesRead(RootItem::ReadStatus status, const true, m_authUsername, m_authPassword, true); - QObject::connect(downloader, &Downloader::completed, downloader, &Downloader::deleteLater); } @@ -365,8 +344,7 @@ void OwnCloudNetworkFactory::markMessagesStarred(RootItem::Importance importance QJsonArray ids; QString final_url; - if (importance == RootItem::Important - ) { + if (importance == RootItem::Important) { final_url = m_fixedUrl + API_PATH + "items/star/multiple"; } else { @@ -376,7 +354,6 @@ void OwnCloudNetworkFactory::markMessagesStarred(RootItem::Importance importance for (int i = 0; i < feed_ids.size(); i++) { QJsonObject item; - item["feedId"] = feed_ids.at(i); item["guidHash"] = guid_hashes.at(i); ids.append(item); @@ -393,7 +370,6 @@ void OwnCloudNetworkFactory::markMessagesStarred(RootItem::Importance importance true, m_authUsername, m_authPassword, true); - QObject::connect(downloader, &Downloader::completed, downloader, &Downloader::deleteLater); } @@ -433,8 +409,7 @@ OwnCloudUserResponse::OwnCloudUserResponse(const QString& raw_content) : OwnClou OwnCloudUserResponse::~OwnCloudUserResponse() {} QString OwnCloudUserResponse::displayName() const { - if (isLoaded() - ) { + if (isLoaded()) { return m_rawContent["displayName"].toString(); } else { @@ -443,8 +418,7 @@ QString OwnCloudUserResponse::displayName() const { } QString OwnCloudUserResponse::userId() const { - if (isLoaded() - ) { + if (isLoaded()) { return m_rawContent["userId"].toString(); } else { @@ -453,8 +427,7 @@ QString OwnCloudUserResponse::userId() const { } QDateTime OwnCloudUserResponse::lastLoginTime() const { - if (isLoaded() - ) { + if (isLoaded()) { return QDateTime::fromMSecsSinceEpoch(m_rawContent["lastLoginTimestamp"].toDouble()); } else { @@ -463,15 +436,12 @@ QDateTime OwnCloudUserResponse::lastLoginTime() const { } QIcon OwnCloudUserResponse::avatar() const { - if (isLoaded() - ) { + if (isLoaded()) { QString image_data = m_rawContent["avatar"].toObject()["data"].toString(); QByteArray decoded_data = QByteArray::fromBase64(image_data.toLocal8Bit()); QPixmap image; - - if (image.loadFromData(decoded_data) - ) { + if (image.loadFromData(decoded_data)) { return QIcon(image); } } @@ -479,14 +449,12 @@ QIcon OwnCloudUserResponse::avatar() const { return QIcon(); } - OwnCloudStatusResponse::OwnCloudStatusResponse(const QString& raw_content) : OwnCloudResponse(raw_content) {} OwnCloudStatusResponse::~OwnCloudStatusResponse() {} QString OwnCloudStatusResponse::version() const { - if (isLoaded() - ) { + if (isLoaded()) { return m_rawContent["version"].toString(); } else { @@ -495,8 +463,7 @@ QString OwnCloudStatusResponse::version() const { } bool OwnCloudStatusResponse::misconfiguredCron() const { - if (isLoaded() - ) { + if (isLoaded()) { return m_rawContent["warnings"].toObject()["improperlyConfiguredCron"].toBool(); } else { @@ -504,7 +471,6 @@ bool OwnCloudStatusResponse::misconfiguredCron() const { } } - OwnCloudGetFeedsCategoriesResponse::OwnCloudGetFeedsCategoriesResponse(const QString& raw_categories, const QString& raw_feeds) : m_contentCategories(raw_categories), m_contentFeeds(raw_feeds) {} @@ -522,10 +488,10 @@ RootItem* OwnCloudGetFeedsCategoriesResponse::feedsCategories(bool obtain_icons) QJsonObject item = cat.toObject(); OwnCloudCategory* category = new OwnCloudCategory(); - category->setTitle(item["name"].toString()); category->setCustomId(item["id"].toInt()); cats.insert(category->customId(), category); + // All categories in ownCloud are top-level. parent->appendChild(category); } @@ -535,25 +501,19 @@ RootItem* OwnCloudGetFeedsCategoriesResponse::feedsCategories(bool obtain_icons) QJsonObject item = fed.toObject(); OwnCloudFeed* feed = new OwnCloudFeed(); - - if (obtain_icons - ) { + if (obtain_icons) { QString icon_path = item["faviconLink"].toString(); - - if (!icon_path.isEmpty() - ) { + if (!icon_path.isEmpty()) { QByteArray icon_data; - if (NetworkFactory::performNetworkOperation(icon_path, DOWNLOAD_TIMEOUT, QByteArray(), QString(), icon_data, - QNetworkAccessManager::GetOperation).first == QNetworkReply::NoError - ) { + QNetworkAccessManager::GetOperation).first == + QNetworkReply::NoError) { // Icon downloaded, set it up. QPixmap icon_pixmap; - icon_pixmap.loadFromData(icon_data); feed->setIcon(QIcon(icon_pixmap)); } @@ -570,7 +530,6 @@ RootItem* OwnCloudGetFeedsCategoriesResponse::feedsCategories(bool obtain_icons) return parent; } - OwnCloudGetMessagesResponse::OwnCloudGetMessagesResponse(const QString& raw_content) : OwnCloudResponse(raw_content) {} OwnCloudGetMessagesResponse::~OwnCloudGetMessagesResponse() {} @@ -582,7 +541,6 @@ QListOwnCloudGetMessagesResponse::messages() const { QJsonObject message_map = message.toObject(); Message msg; - msg.m_author = message_map["author"].toString(); msg.m_contents = message_map["body"].toString(); msg.m_created = TextFactory::parseDateTime(message_map["pubDate"].toDouble() * 1000); @@ -592,12 +550,9 @@ QListOwnCloudGetMessagesResponse::messages() const { QString enclosure_link = message_map["enclosureLink"].toString(); - - if (!enclosure_link.isEmpty() - ) { + if (!enclosure_link.isEmpty()) { Enclosure enclosure; - enclosure.m_mimeType = message_map["enclosureMime"].toString(); enclosure.m_url = enclosure_link; msg.m_enclosures.append(enclosure); diff --git a/src/services/owncloud/network/owncloudnetworkfactory.h b/src/services/owncloud/network/owncloudnetworkfactory.h index 2f08b4825..6faed2656 100755 --- a/src/services/owncloud/network/owncloudnetworkfactory.h +++ b/src/services/owncloud/network/owncloudnetworkfactory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -27,7 +28,6 @@ #include #include - class OwnCloudResponse { public: explicit OwnCloudResponse(const QString& raw_content = QString()); @@ -74,7 +74,7 @@ class RootItem; class OwnCloudGetFeedsCategoriesResponse { public: explicit OwnCloudGetFeedsCategoriesResponse(const QString& raw_categories = QString(), - const QString& raw_feeds = QString()); + const QString& raw_feeds = QString()); virtual ~OwnCloudGetFeedsCategoriesResponse(); // Returns tree of feeds/categories. @@ -143,6 +143,7 @@ class OwnCloudNetworkFactory { bool m_forceServerSideUpdate; QString m_authUsername; QString m_authPassword; + QNetworkReply::NetworkError m_lastError; int m_batchSize; diff --git a/src/services/owncloud/owncloudcategory.cpp b/src/services/owncloud/owncloudcategory.cpp index 64695447b..a549de627 100755 --- a/src/services/owncloud/owncloudcategory.cpp +++ b/src/services/owncloud/owncloudcategory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,31 +18,29 @@ #include "services/owncloud/owncloudcategory.h" -#include "services/owncloud/owncloudserviceroot.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" - +#include "services/owncloud/owncloudserviceroot.h" OwnCloudCategory::OwnCloudCategory(RootItem* parent) : Category(parent) { - // Categories in ownCloud have now icons etc. They just have titles. - setIcon(qApp->icons()->fromTheme(QSL("folder"))); + // Categories in ownCloud have now icons etc. They just have titles. + setIcon(qApp->icons()->fromTheme(QSL("folder"))); } OwnCloudCategory::OwnCloudCategory(const QSqlRecord& record) : Category(nullptr) { - setIcon(qApp->icons()->fromTheme(QSL("folder"))); - setId(record.value(CAT_DB_ID_INDEX).toInt()); - setTitle(record.value(CAT_DB_TITLE_INDEX).toString()); - setCustomId(record.value(CAT_DB_CUSTOM_ID_INDEX).toInt()); + setIcon(qApp->icons()->fromTheme(QSL("folder"))); + setId(record.value(CAT_DB_ID_INDEX).toInt()); + setTitle(record.value(CAT_DB_TITLE_INDEX).toString()); + setCustomId(record.value(CAT_DB_CUSTOM_ID_INDEX).toInt()); } OwnCloudServiceRoot* OwnCloudCategory::serviceRoot() const { - return qobject_cast(getParentServiceRoot()); + return qobject_cast(getParentServiceRoot()); } bool OwnCloudCategory::markAsReadUnread(RootItem::ReadStatus status) { - serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status); - return serviceRoot()->markFeedsReadUnread(getSubTreeFeeds(), status); + serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status); + return serviceRoot()->markFeedsReadUnread(getSubTreeFeeds(), status); } -OwnCloudCategory::~OwnCloudCategory() { -} +OwnCloudCategory::~OwnCloudCategory() {} diff --git a/src/services/owncloud/owncloudcategory.h b/src/services/owncloud/owncloudcategory.h index bc086980e..8ca6c5a60 100755 --- a/src/services/owncloud/owncloudcategory.h +++ b/src/services/owncloud/owncloudcategory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,21 +21,20 @@ #include "services/abstract/category.h" - class OwnCloudServiceRoot; class OwnCloudCategory : public Category { - Q_OBJECT + Q_OBJECT - public: - explicit OwnCloudCategory(RootItem* parent = nullptr); - explicit OwnCloudCategory(const QSqlRecord& record); - virtual ~OwnCloudCategory(); + public: + explicit OwnCloudCategory(RootItem* parent = nullptr); + explicit OwnCloudCategory(const QSqlRecord& record); + virtual ~OwnCloudCategory(); - bool markAsReadUnread(ReadStatus status); + bool markAsReadUnread(ReadStatus status); - private: - OwnCloudServiceRoot* serviceRoot() const; + private: + OwnCloudServiceRoot* serviceRoot() const; }; #endif // OWNCLOUDSERVICECATEGORY_H diff --git a/src/services/owncloud/owncloudfeed.cpp b/src/services/owncloud/owncloudfeed.cpp index 59adf1960..6850fe206 100755 --- a/src/services/owncloud/owncloudfeed.cpp +++ b/src/services/owncloud/owncloudfeed.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,102 +18,100 @@ #include "services/owncloud/owncloudfeed.h" -#include "miscellaneous/iconfactory.h" #include "miscellaneous/databasequeries.h" -#include "services/owncloud/owncloudserviceroot.h" -#include "services/owncloud/network/owncloudnetworkfactory.h" +#include "miscellaneous/iconfactory.h" #include "services/owncloud/gui/formowncloudfeeddetails.h" +#include "services/owncloud/network/owncloudnetworkfactory.h" +#include "services/owncloud/owncloudserviceroot.h" #include - -OwnCloudFeed::OwnCloudFeed(RootItem* parent) : Feed(parent) { -} +OwnCloudFeed::OwnCloudFeed(RootItem* parent) : Feed(parent) {} OwnCloudFeed::OwnCloudFeed(const QSqlRecord& record) : Feed(nullptr) { - setTitle(record.value(FDS_DB_TITLE_INDEX).toString()); - setId(record.value(FDS_DB_ID_INDEX).toInt()); - setIcon(qApp->icons()->fromByteArray(record.value(FDS_DB_ICON_INDEX).toByteArray())); - setAutoUpdateType(static_cast(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt())); - setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt()); - setCustomId(record.value(FDS_DB_CUSTOM_ID_INDEX).toInt()); - qDebug("Custom ID of Nextcloud feed when loading from DB is '%s'.", qPrintable(record.value(FDS_DB_CUSTOM_ID_INDEX).toString())); + setTitle(record.value(FDS_DB_TITLE_INDEX).toString()); + setId(record.value(FDS_DB_ID_INDEX).toInt()); + setIcon(qApp->icons()->fromByteArray(record.value(FDS_DB_ICON_INDEX).toByteArray())); + setAutoUpdateType(static_cast(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt())); + setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt()); + setCustomId(record.value(FDS_DB_CUSTOM_ID_INDEX).toInt()); + qDebug("Custom ID of Nextcloud feed when loading from DB is '%s'.", qPrintable(record.value(FDS_DB_CUSTOM_ID_INDEX).toString())); } -OwnCloudFeed::~OwnCloudFeed() { -} +OwnCloudFeed::~OwnCloudFeed() {} bool OwnCloudFeed::canBeEdited() const { - return true; + return true; } bool OwnCloudFeed::editViaGui() { - QPointer form_pointer = new FormOwnCloudFeedDetails(serviceRoot(), qApp->mainFormWidget()); - form_pointer.data()->addEditFeed(this, nullptr); - delete form_pointer.data(); - return false; + QPointer form_pointer = new FormOwnCloudFeedDetails(serviceRoot(), qApp->mainFormWidget()); + form_pointer.data()->addEditFeed(this, nullptr); + delete form_pointer.data(); + return false; } bool OwnCloudFeed::canBeDeleted() const { - return true; + return true; } bool OwnCloudFeed::deleteViaGui() { - if (serviceRoot()->network()->deleteFeed(customId()) && removeItself()) { - serviceRoot()->requestItemRemoval(this); - return true; - } - else { - return false; - } + if (serviceRoot()->network()->deleteFeed(customId()) && removeItself()) { + serviceRoot()->requestItemRemoval(this); + return true; + } + else { + return false; + } } bool OwnCloudFeed::editItself(OwnCloudFeed* new_feed_data) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - if (!DatabaseQueries::editBaseFeed(database, id(), new_feed_data->autoUpdateType(), - new_feed_data->autoUpdateInitialInterval())) { - // Persistent storage update failed, no way to continue now. - return false; - } - else { - setAutoUpdateType(new_feed_data->autoUpdateType()); - setAutoUpdateInitialInterval(new_feed_data->autoUpdateInitialInterval()); - return true; - } + if (!DatabaseQueries::editBaseFeed(database, id(), new_feed_data->autoUpdateType(), + new_feed_data->autoUpdateInitialInterval())) { + // Persistent storage update failed, no way to continue now. + return false; + } + else { + setAutoUpdateType(new_feed_data->autoUpdateType()); + setAutoUpdateInitialInterval(new_feed_data->autoUpdateInitialInterval()); + return true; + } } bool OwnCloudFeed::removeItself() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - return DatabaseQueries::deleteFeed(database, customId(), serviceRoot()->accountId()); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + + return DatabaseQueries::deleteFeed(database, customId(), serviceRoot()->accountId()); } bool OwnCloudFeed::markAsReadUnread(RootItem::ReadStatus status) { - serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status); - return getParentServiceRoot()->markFeedsReadUnread(QList() << this, status); + serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status); + return getParentServiceRoot()->markFeedsReadUnread(QList() << this, status); } bool OwnCloudFeed::cleanMessages(bool clear_only_read) { - return getParentServiceRoot()->cleanFeeds(QList() << this, clear_only_read); + return getParentServiceRoot()->cleanFeeds(QList() << this, clear_only_read); } OwnCloudServiceRoot* OwnCloudFeed::serviceRoot() const { - return qobject_cast(getParentServiceRoot()); + return qobject_cast(getParentServiceRoot()); } QList OwnCloudFeed::obtainNewMessages(bool* error_during_obtaining) { - OwnCloudGetMessagesResponse messages = serviceRoot()->network()->getMessages(customId()); + OwnCloudGetMessagesResponse messages = serviceRoot()->network()->getMessages(customId()); - if (serviceRoot()->network()->lastError() != QNetworkReply::NoError) { - setStatus(Feed::NetworkError); - *error_during_obtaining = true; - serviceRoot()->itemChanged(QList() << this); - return QList(); - } - else { - *error_during_obtaining = false; - return messages.messages(); - } + if (serviceRoot()->network()->lastError() != QNetworkReply::NoError) { + setStatus(Feed::NetworkError); + *error_during_obtaining = true; + serviceRoot()->itemChanged(QList() << this); + return QList(); + } + else { + *error_during_obtaining = false; + return messages.messages(); + } - return QList(); + return QList(); } diff --git a/src/services/owncloud/owncloudfeed.h b/src/services/owncloud/owncloudfeed.h index 601a031ab..12e23af01 100755 --- a/src/services/owncloud/owncloudfeed.h +++ b/src/services/owncloud/owncloudfeed.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,32 +21,31 @@ #include "services/abstract/feed.h" - class OwnCloudServiceRoot; class OwnCloudFeed : public Feed { - Q_OBJECT + Q_OBJECT - public: - explicit OwnCloudFeed(RootItem* parent = nullptr); - explicit OwnCloudFeed(const QSqlRecord& record); - virtual ~OwnCloudFeed(); + public: + explicit OwnCloudFeed(RootItem* parent = nullptr); + explicit OwnCloudFeed(const QSqlRecord& record); + virtual ~OwnCloudFeed(); - bool canBeEdited() const; - bool editViaGui(); - bool canBeDeleted() const; - bool deleteViaGui(); + bool canBeEdited() const; + bool editViaGui(); + bool canBeDeleted() const; + bool deleteViaGui(); - bool editItself(OwnCloudFeed* new_feed_data); - bool removeItself(); + bool editItself(OwnCloudFeed* new_feed_data); + bool removeItself(); - bool markAsReadUnread(ReadStatus status); - bool cleanMessages(bool clear_only_read); + bool markAsReadUnread(ReadStatus status); + bool cleanMessages(bool clear_only_read); - OwnCloudServiceRoot* serviceRoot() const; + OwnCloudServiceRoot* serviceRoot() const; - private: - QList obtainNewMessages(bool* error_during_obtaining); + private: + QList obtainNewMessages(bool* error_during_obtaining); }; #endif // OWNCLOUDFEED_H diff --git a/src/services/owncloud/owncloudrecyclebin.cpp b/src/services/owncloud/owncloudrecyclebin.cpp index 3a682e1cb..cc276ec40 100755 --- a/src/services/owncloud/owncloudrecyclebin.cpp +++ b/src/services/owncloud/owncloudrecyclebin.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,24 +18,21 @@ #include "services/owncloud/owncloudrecyclebin.h" -#include "services/owncloud/owncloudserviceroot.h" #include "services/abstract/cacheforserviceroot.h" #include "services/owncloud/network/owncloudnetworkfactory.h" +#include "services/owncloud/owncloudserviceroot.h" #include +OwnCloudRecycleBin::OwnCloudRecycleBin(RootItem* parent) : RecycleBin(parent) {} -OwnCloudRecycleBin::OwnCloudRecycleBin(RootItem* parent) : RecycleBin(parent) { -} - -OwnCloudRecycleBin::~OwnCloudRecycleBin() { -} +OwnCloudRecycleBin::~OwnCloudRecycleBin() {} OwnCloudServiceRoot* OwnCloudRecycleBin::serviceRoot() { - return qobject_cast(getParentServiceRoot()); + return qobject_cast(getParentServiceRoot()); } bool OwnCloudRecycleBin::markAsReadUnread(RootItem::ReadStatus status) { - serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status); - return RecycleBin::markAsReadUnread(status); + serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status); + return RecycleBin::markAsReadUnread(status); } diff --git a/src/services/owncloud/owncloudrecyclebin.h b/src/services/owncloud/owncloudrecyclebin.h index 39246a66c..5da6b1995 100755 --- a/src/services/owncloud/owncloudrecyclebin.h +++ b/src/services/owncloud/owncloudrecyclebin.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,18 +21,18 @@ #include "services/abstract/recyclebin.h" - class OwnCloudServiceRoot; class OwnCloudRecycleBin : public RecycleBin { - Q_OBJECT + Q_OBJECT - public: - explicit OwnCloudRecycleBin(RootItem* parent = nullptr); - virtual ~OwnCloudRecycleBin(); + public: + explicit OwnCloudRecycleBin(RootItem* parent = nullptr); + virtual ~OwnCloudRecycleBin(); - OwnCloudServiceRoot* serviceRoot(); - bool markAsReadUnread(ReadStatus status); + OwnCloudServiceRoot* serviceRoot(); + + bool markAsReadUnread(ReadStatus status); }; #endif // OWNCLOUDRECYCLEBIN_H diff --git a/src/services/owncloud/owncloudserviceentrypoint.cpp b/src/services/owncloud/owncloudserviceentrypoint.cpp index 48ca47bf4..32c385b44 100755 --- a/src/services/owncloud/owncloudserviceentrypoint.cpp +++ b/src/services/owncloud/owncloudserviceentrypoint.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -19,55 +20,52 @@ #include "definitions/definitions.h" #include "miscellaneous/application.h" -#include "miscellaneous/iconfactory.h" #include "miscellaneous/databasequeries.h" +#include "miscellaneous/iconfactory.h" #include "services/owncloud/definitions.h" -#include "services/owncloud/owncloudserviceroot.h" #include "services/owncloud/gui/formeditowncloudaccount.h" +#include "services/owncloud/owncloudserviceroot.h" +OwnCloudServiceEntryPoint::OwnCloudServiceEntryPoint() {} -OwnCloudServiceEntryPoint::OwnCloudServiceEntryPoint() { -} - -OwnCloudServiceEntryPoint::~OwnCloudServiceEntryPoint() { -} +OwnCloudServiceEntryPoint::~OwnCloudServiceEntryPoint() {} ServiceRoot* OwnCloudServiceEntryPoint::createNewRoot() const { - QScopedPointer form_acc(new FormEditOwnCloudAccount(qApp->mainFormWidget())); - return form_acc->execForCreate(); + QScopedPointer form_acc(new FormEditOwnCloudAccount(qApp->mainFormWidget())); + return form_acc->execForCreate(); } QList OwnCloudServiceEntryPoint::initializeSubtree() const { - QSqlDatabase database = qApp->database()->connection(QSL("OwnCloudServiceEntryPoint"), DatabaseFactory::FromSettings); - return DatabaseQueries::getOwnCloudAccounts(database); + QSqlDatabase database = qApp->database()->connection(QSL("OwnCloudServiceEntryPoint"), DatabaseFactory::FromSettings); + + return DatabaseQueries::getOwnCloudAccounts(database); } bool OwnCloudServiceEntryPoint::isSingleInstanceService() const { - return false; + return false; } QString OwnCloudServiceEntryPoint::name() const { - return QSL("NextCloud News"); + return QSL("NextCloud News"); } QString OwnCloudServiceEntryPoint::code() const { - return SERVICE_CODE_OWNCLOUD; + return SERVICE_CODE_OWNCLOUD; } QString OwnCloudServiceEntryPoint::description() const { - return QObject::tr("The News app is an RSS/Atom feed aggregator. It is part of Nextcloud suite. This plugin implements %1 API.").arg( - API_VERSION); + return QObject::tr("The News app is an RSS/Atom feed aggregator. It is part of Nextcloud suite. This plugin implements %1 API.").arg( + API_VERSION); } QString OwnCloudServiceEntryPoint::version() const { - return APP_VERSION; + return APP_VERSION; } QString OwnCloudServiceEntryPoint::author() const { - return APP_AUTHOR; + return APP_AUTHOR; } QIcon OwnCloudServiceEntryPoint::icon() const { - return qApp->icons()->miscIcon(QSL("nextcloud")); + return qApp->icons()->miscIcon(QSL("nextcloud")); } - diff --git a/src/services/owncloud/owncloudserviceentrypoint.h b/src/services/owncloud/owncloudserviceentrypoint.h index 770bdd671..99a59448d 100755 --- a/src/services/owncloud/owncloudserviceentrypoint.h +++ b/src/services/owncloud/owncloudserviceentrypoint.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,21 +21,21 @@ #include "services/abstract/serviceentrypoint.h" - class OwnCloudServiceEntryPoint : public ServiceEntryPoint { - public: - explicit OwnCloudServiceEntryPoint(); - virtual ~OwnCloudServiceEntryPoint(); + public: + explicit OwnCloudServiceEntryPoint(); + virtual ~OwnCloudServiceEntryPoint(); - ServiceRoot* createNewRoot() const; - QList initializeSubtree() const; - bool isSingleInstanceService() const; - QString name() const; - QString code() const; - QString description() const; - QString version() const; - QString author() const; - QIcon icon() const; + ServiceRoot* createNewRoot() const; + + QList initializeSubtree() const; + bool isSingleInstanceService() const; + QString name() const; + QString code() const; + QString description() const; + QString version() const; + QString author() const; + QIcon icon() const; }; #endif // OWNCLOUDSERVICEENTRYPOINT_H diff --git a/src/services/owncloud/owncloudserviceroot.cpp b/src/services/owncloud/owncloudserviceroot.cpp index e7374767c..b25e84f92 100755 --- a/src/services/owncloud/owncloudserviceroot.cpp +++ b/src/services/owncloud/owncloudserviceroot.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,85 +19,84 @@ #include "services/owncloud/owncloudserviceroot.h" #include "definitions/definitions.h" -#include "miscellaneous/databasequeries.h" #include "miscellaneous/application.h" -#include "miscellaneous/textfactory.h" +#include "miscellaneous/databasequeries.h" #include "miscellaneous/iconfactory.h" #include "miscellaneous/mutex.h" -#include "services/owncloud/owncloudserviceentrypoint.h" -#include "services/owncloud/owncloudrecyclebin.h" -#include "services/owncloud/owncloudfeed.h" -#include "services/owncloud/owncloudcategory.h" -#include "services/owncloud/network/owncloudnetworkfactory.h" +#include "miscellaneous/textfactory.h" #include "services/owncloud/gui/formeditowncloudaccount.h" #include "services/owncloud/gui/formowncloudfeeddetails.h" - +#include "services/owncloud/network/owncloudnetworkfactory.h" +#include "services/owncloud/owncloudcategory.h" +#include "services/owncloud/owncloudfeed.h" +#include "services/owncloud/owncloudrecyclebin.h" +#include "services/owncloud/owncloudserviceentrypoint.h" OwnCloudServiceRoot::OwnCloudServiceRoot(RootItem* parent) - : ServiceRoot(parent), CacheForServiceRoot(), m_recycleBin(new OwnCloudRecycleBin(this)), - m_actionSyncIn(nullptr), m_serviceMenu(QList()), m_network(new OwnCloudNetworkFactory()) { - setIcon(OwnCloudServiceEntryPoint().icon()); + : ServiceRoot(parent), CacheForServiceRoot(), m_recycleBin(new OwnCloudRecycleBin(this)), + m_actionSyncIn(nullptr), m_serviceMenu(QList()), m_network(new OwnCloudNetworkFactory()) { + setIcon(OwnCloudServiceEntryPoint().icon()); } OwnCloudServiceRoot::~OwnCloudServiceRoot() { - delete m_network; + delete m_network; } bool OwnCloudServiceRoot::canBeEdited() const { - return true; + return true; } bool OwnCloudServiceRoot::canBeDeleted() const { - return true; + return true; } bool OwnCloudServiceRoot::editViaGui() { - QScopedPointer form_pointer(new FormEditOwnCloudAccount(qApp->mainFormWidget())); - form_pointer.data()->execForEdit(this); - return true; + QScopedPointer form_pointer(new FormEditOwnCloudAccount(qApp->mainFormWidget())); + form_pointer.data()->execForEdit(this); + return true; } bool OwnCloudServiceRoot::deleteViaGui() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - if (DatabaseQueries::deleteOwnCloudAccount(database, accountId())) { - return ServiceRoot::deleteViaGui(); - } - else { - return false; - } + if (DatabaseQueries::deleteOwnCloudAccount(database, accountId())) { + return ServiceRoot::deleteViaGui(); + } + else { + return false; + } } bool OwnCloudServiceRoot::supportsFeedAdding() const { - return true; + return true; } bool OwnCloudServiceRoot::supportsCategoryAdding() const { - return false; + return false; } QList OwnCloudServiceRoot::serviceMenu() { - if (m_serviceMenu.isEmpty()) { - m_actionSyncIn = new QAction(qApp->icons()->fromTheme(QSL("view-refresh")), tr("Sync in"), this); - connect(m_actionSyncIn, &QAction::triggered, this, &OwnCloudServiceRoot::syncIn); - m_serviceMenu.append(m_actionSyncIn); - } + if (m_serviceMenu.isEmpty()) { + m_actionSyncIn = new QAction(qApp->icons()->fromTheme(QSL("view-refresh")), tr("Sync in"), this); + connect(m_actionSyncIn, &QAction::triggered, this, &OwnCloudServiceRoot::syncIn); + m_serviceMenu.append(m_actionSyncIn); + } - return m_serviceMenu; + return m_serviceMenu; } RecycleBin* OwnCloudServiceRoot::recycleBin() const { - return m_recycleBin; + return m_recycleBin; } void OwnCloudServiceRoot::start(bool freshly_activated) { - Q_UNUSED(freshly_activated) - loadFromDatabase(); + Q_UNUSED(freshly_activated) + loadFromDatabase(); loadCacheFromFile(accountId()); - if (qApp->isFirstRun(QSL("3.1.1")) || (childCount() == 1 && child(0)->kind() == RootItemKind::Bin)) { - syncIn(); - } + if (qApp->isFirstRun(QSL("3.1.1")) || (childCount() == 1 && child(0)->kind() == RootItemKind::Bin)) { + syncIn(); + } } void OwnCloudServiceRoot::stop() { @@ -104,194 +104,200 @@ void OwnCloudServiceRoot::stop() { } QString OwnCloudServiceRoot::code() const { - return OwnCloudServiceEntryPoint().code(); + return OwnCloudServiceEntryPoint().code(); } bool OwnCloudServiceRoot::markAsReadUnread(RootItem::ReadStatus status) { - addMessageStatesToCache(customIDSOfMessagesForItem(this), status); - return ServiceRoot::markAsReadUnread(status); + addMessageStatesToCache(customIDSOfMessagesForItem(this), status); + return ServiceRoot::markAsReadUnread(status); } OwnCloudNetworkFactory* OwnCloudServiceRoot::network() const { - return m_network; + return m_network; } void OwnCloudServiceRoot::saveAllCachedData() { - QPair, QMap>> msgCache = takeMessageCache(); - QMapIterator i(msgCache.first); + QPair, QMap>> msgCache = takeMessageCache(); + QMapIterator i(msgCache.first); - // Save the actual data read/unread. - while (i.hasNext()) { - i.next(); - auto key = i.key(); - QStringList ids = i.value(); + // Save the actual data read/unread. + while (i.hasNext()) { + i.next(); + auto key = i.key(); + QStringList ids = i.value(); - if (!ids.isEmpty()) { - network()->markMessagesRead(key, ids); - } - } + if (!ids.isEmpty()) { + network()->markMessagesRead(key, ids); + } + } - QMapIterator> j(msgCache.second); + QMapIterator> j(msgCache.second); - // Save the actual data important/not important. - while (j.hasNext()) { - j.next(); - auto key = j.key(); - QList messages = j.value(); + // Save the actual data important/not important. + while (j.hasNext()) { + j.next(); + auto key = j.key(); - if (!messages.isEmpty()) { - QStringList feed_ids, guid_hashes; + QList messages = j.value(); - foreach (const Message& msg, messages) { - feed_ids.append(msg.m_feedId); - guid_hashes.append(msg.m_customHash); - } + if (!messages.isEmpty()) { + QStringList feed_ids, guid_hashes; - network()->markMessagesStarred(key, feed_ids, guid_hashes); - } - } + foreach (const Message& msg, messages) { + feed_ids.append(msg.m_feedId); + guid_hashes.append(msg.m_customHash); + } + + network()->markMessagesStarred(key, feed_ids, guid_hashes); + } + } } bool OwnCloudServiceRoot::onBeforeSetMessagesRead(RootItem* selected_item, const QList& messages, RootItem::ReadStatus read) { - Q_UNUSED(selected_item) - addMessageStatesToCache(customIDsOfMessages(messages), read); - return true; + Q_UNUSED(selected_item) + addMessageStatesToCache(customIDsOfMessages(messages), read); + return true; } bool OwnCloudServiceRoot::onBeforeSwitchMessageImportance(RootItem* selected_item, const QList& changes) { - Q_UNUSED(selected_item) - // Now, we need to separate the changes because of ownCloud API limitations. - QList mark_starred_msgs; - QList mark_unstarred_msgs; + Q_UNUSED(selected_item) - foreach (const ImportanceChange& pair, changes) { - if (pair.second == RootItem::Important) { - mark_starred_msgs.append(pair.first); - } - else { - mark_unstarred_msgs.append(pair.first); - } - } + // Now, we need to separate the changes because of ownCloud API limitations. + QList mark_starred_msgs; + QList mark_unstarred_msgs; - if (!mark_starred_msgs.isEmpty()) { - addMessageStatesToCache(mark_starred_msgs, RootItem::Important); - } + foreach (const ImportanceChange& pair, changes) { + if (pair.second == RootItem::Important) { + mark_starred_msgs.append(pair.first); + } + else { + mark_unstarred_msgs.append(pair.first); + } + } - if (!mark_unstarred_msgs.isEmpty()) { - addMessageStatesToCache(mark_unstarred_msgs, RootItem::NotImportant); - } + if (!mark_starred_msgs.isEmpty()) { + addMessageStatesToCache(mark_starred_msgs, RootItem::Important); + } - return true; + if (!mark_unstarred_msgs.isEmpty()) { + addMessageStatesToCache(mark_unstarred_msgs, RootItem::NotImportant); + } + + return true; } void OwnCloudServiceRoot::updateTitle() { - QString host = QUrl(m_network->url()).host(); + QString host = QUrl(m_network->url()).host(); - if (host.isEmpty()) { - host = m_network->url(); - } + if (host.isEmpty()) { + host = m_network->url(); + } - setTitle(m_network->authUsername() + QL1S("@") + host + QSL(" (Nextcloud News)")); + setTitle(m_network->authUsername() + QL1S("@") + host + QSL(" (Nextcloud News)")); } void OwnCloudServiceRoot::saveAccountDataToDatabase() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - if (accountId() != NO_PARENT_CATEGORY) { - if (DatabaseQueries::overwriteOwnCloudAccount(database, m_network->authUsername(), - m_network->authPassword(), m_network->url(), - m_network->forceServerSideUpdate(), accountId())) { - updateTitle(); - itemChanged(QList() << this); - } - } - else { - bool saved; - int id_to_assign = DatabaseQueries::createAccount(database, code(), &saved); + if (accountId() != NO_PARENT_CATEGORY) { + if (DatabaseQueries::overwriteOwnCloudAccount(database, m_network->authUsername(), + m_network->authPassword(), m_network->url(), + m_network->forceServerSideUpdate(), accountId())) { + updateTitle(); + itemChanged(QList() << this); + } + } + else { + bool saved; + int id_to_assign = DatabaseQueries::createAccount(database, code(), &saved); - if (saved) { - if (DatabaseQueries::createOwnCloudAccount(database, id_to_assign, m_network->authUsername(), - m_network->authPassword(), m_network->url(), - m_network->forceServerSideUpdate())) { - setId(id_to_assign); - setAccountId(id_to_assign); - updateTitle(); - } - } - } + if (saved) { + if (DatabaseQueries::createOwnCloudAccount(database, id_to_assign, m_network->authUsername(), + m_network->authPassword(), m_network->url(), + m_network->forceServerSideUpdate())) { + setId(id_to_assign); + setAccountId(id_to_assign); + updateTitle(); + } + } + } } void OwnCloudServiceRoot::addNewFeed(const QString& url) { - if (!qApp->feedUpdateLock()->tryLock()) { - // Lock was not obtained because - // it is used probably by feed updater or application - // is quitting. - qApp->showGuiMessage(tr("Cannot add item"), - tr("Cannot add feed because another critical operation is ongoing."), - QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - // Thus, cannot delete and quit the method. - return; - } + if (!qApp->feedUpdateLock()->tryLock()) { + // Lock was not obtained because + // it is used probably by feed updater or application + // is quitting. + qApp->showGuiMessage(tr("Cannot add item"), + tr("Cannot add feed because another critical operation is ongoing."), + QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - QScopedPointer form_pointer(new FormOwnCloudFeedDetails(this, qApp->mainFormWidget())); - form_pointer.data()->addEditFeed(nullptr, this, url); - qApp->feedUpdateLock()->unlock(); + // Thus, cannot delete and quit the method. + return; + } + + QScopedPointer form_pointer(new FormOwnCloudFeedDetails(this, qApp->mainFormWidget())); + form_pointer.data()->addEditFeed(nullptr, this, url); + qApp->feedUpdateLock()->unlock(); } -void OwnCloudServiceRoot::addNewCategory() { -} +void OwnCloudServiceRoot::addNewCategory() {} QMap OwnCloudServiceRoot::storeCustomFeedsData() { - QMap custom_data; + QMap custom_data; - foreach (const Feed* feed, getSubTreeFeeds()) { - QVariantMap feed_custom_data; - feed_custom_data.insert(QSL("auto_update_interval"), feed->autoUpdateInitialInterval()); - feed_custom_data.insert(QSL("auto_update_type"), feed->autoUpdateType()); - custom_data.insert(feed->customId(), feed_custom_data); - } + foreach (const Feed* feed, getSubTreeFeeds()) { + QVariantMap feed_custom_data; - return custom_data; + feed_custom_data.insert(QSL("auto_update_interval"), feed->autoUpdateInitialInterval()); + feed_custom_data.insert(QSL("auto_update_type"), feed->autoUpdateType()); + custom_data.insert(feed->customId(), feed_custom_data); + } + + return custom_data; } void OwnCloudServiceRoot::restoreCustomFeedsData(const QMap& data, const QHash& feeds) { - QMapIterator i(data); + QMapIterator i(data); - while (i.hasNext()) { - i.next(); - const int custom_id = i.key(); + while (i.hasNext()) { + i.next(); + const int custom_id = i.key(); - if (feeds.contains(custom_id)) { - Feed* feed = feeds.value(custom_id); - QVariantMap feed_custom_data = i.value().toMap(); - feed->setAutoUpdateInitialInterval(feed_custom_data.value(QSL("auto_update_interval")).toInt()); - feed->setAutoUpdateType(static_cast(feed_custom_data.value(QSL("auto_update_type")).toInt())); - } - } + if (feeds.contains(custom_id)) { + Feed* feed = feeds.value(custom_id); + QVariantMap feed_custom_data = i.value().toMap(); + + feed->setAutoUpdateInitialInterval(feed_custom_data.value(QSL("auto_update_interval")).toInt()); + feed->setAutoUpdateType(static_cast(feed_custom_data.value(QSL("auto_update_type")).toInt())); + } + } } RootItem* OwnCloudServiceRoot::obtainNewTreeForSyncIn() const { - OwnCloudGetFeedsCategoriesResponse feed_cats_response = m_network->feedsCategories(); + OwnCloudGetFeedsCategoriesResponse feed_cats_response = m_network->feedsCategories(); - if (m_network->lastError() == QNetworkReply::NoError) { - return feed_cats_response.feedsCategories(true); - } - else { - return nullptr; - } + if (m_network->lastError() == QNetworkReply::NoError) { + return feed_cats_response.feedsCategories(true); + } + else { + return nullptr; + } } void OwnCloudServiceRoot::loadFromDatabase() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - Assignment categories = DatabaseQueries::getOwnCloudCategories(database, accountId()); - Assignment feeds = DatabaseQueries::getOwnCloudFeeds(database, accountId()); - // All data are now obtained, lets create the hierarchy. - assembleCategories(categories); - assembleFeeds(feeds); - // As the last item, add recycle bin, which is needed. - appendChild(m_recycleBin); - updateCounts(true); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + Assignment categories = DatabaseQueries::getOwnCloudCategories(database, accountId()); + Assignment feeds = DatabaseQueries::getOwnCloudFeeds(database, accountId()); + + // All data are now obtained, lets create the hierarchy. + assembleCategories(categories); + assembleFeeds(feeds); + + // As the last item, add recycle bin, which is needed. + appendChild(m_recycleBin); + updateCounts(true); } diff --git a/src/services/owncloud/owncloudserviceroot.h b/src/services/owncloud/owncloudserviceroot.h index fcbcf64af..7c2d0be59 100755 --- a/src/services/owncloud/owncloudserviceroot.h +++ b/src/services/owncloud/owncloudserviceroot.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,62 +19,62 @@ #ifndef OWNCLOUDSERVICEROOT_H #define OWNCLOUDSERVICEROOT_H -#include "services/abstract/serviceroot.h" #include "services/abstract/cacheforserviceroot.h" +#include "services/abstract/serviceroot.h" #include - class OwnCloudNetworkFactory; class OwnCloudRecycleBin; class Mutex; class OwnCloudServiceRoot : public ServiceRoot, public CacheForServiceRoot { - Q_OBJECT + Q_OBJECT - public: - explicit OwnCloudServiceRoot(RootItem* parent = nullptr); - virtual ~OwnCloudServiceRoot(); + public: + explicit OwnCloudServiceRoot(RootItem* parent = nullptr); + virtual ~OwnCloudServiceRoot(); - bool canBeEdited() const; - bool canBeDeleted() const; - bool editViaGui(); - bool deleteViaGui(); - bool supportsFeedAdding() const; - bool supportsCategoryAdding() const; - QList serviceMenu(); - RecycleBin* recycleBin() const; - void start(bool freshly_activated); - void stop(); - QString code() const; - bool markAsReadUnread(ReadStatus status); + bool canBeEdited() const; + bool canBeDeleted() const; + bool editViaGui(); + bool deleteViaGui(); + bool supportsFeedAdding() const; + bool supportsCategoryAdding() const; + QList serviceMenu(); + RecycleBin* recycleBin() const; - OwnCloudNetworkFactory* network() const; + void start(bool freshly_activated); + void stop(); + QString code() const; + bool markAsReadUnread(ReadStatus status); - bool onBeforeSetMessagesRead(RootItem* selected_item, const QList& messages, ReadStatus read); - bool onBeforeSwitchMessageImportance(RootItem* selected_item, const QList& changes); + OwnCloudNetworkFactory* network() const; - void updateTitle(); - void saveAccountDataToDatabase(); + bool onBeforeSetMessagesRead(RootItem* selected_item, const QList& messages, ReadStatus read); + bool onBeforeSwitchMessageImportance(RootItem* selected_item, const QList& changes); + void updateTitle(); + void saveAccountDataToDatabase(); - void saveAllCachedData(); + void saveAllCachedData(); - public slots: - void addNewFeed(const QString& url); - void addNewCategory(); + public slots: + void addNewFeed(const QString& url); + void addNewCategory(); - private: - QMap storeCustomFeedsData(); - void restoreCustomFeedsData(const QMap& data, const QHash& feeds); - RootItem* obtainNewTreeForSyncIn() const; + private: + QMap storeCustomFeedsData(); + void restoreCustomFeedsData(const QMap& data, const QHash& feeds); + RootItem* obtainNewTreeForSyncIn() const; - void loadFromDatabase(); + void loadFromDatabase(); - OwnCloudRecycleBin* m_recycleBin; - QAction* m_actionSyncIn; - QList m_serviceMenu; - OwnCloudNetworkFactory* m_network; + OwnCloudRecycleBin* m_recycleBin; + QAction* m_actionSyncIn; + + QList m_serviceMenu; + OwnCloudNetworkFactory* m_network; }; #endif // OWNCLOUDSERVICEROOT_H diff --git a/src/services/standard/atomparser.cpp b/src/services/standard/atomparser.cpp index e74fa4592..d3f6b6b4a 100755 --- a/src/services/standard/atomparser.cpp +++ b/src/services/standard/atomparser.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,115 +18,113 @@ #include "services/standard/atomparser.h" +#include "miscellaneous/application.h" #include "miscellaneous/textfactory.h" #include "network-web/webfactory.h" -#include "miscellaneous/application.h" #include "exceptions/applicationexception.h" +AtomParser::AtomParser(const QString& data) : FeedParser(data), m_atomNamespace(QSL("http://www.w3.org/2005/Atom")) {} -AtomParser::AtomParser(const QString& data) : FeedParser(data), m_atomNamespace(QSL("http://www.w3.org/2005/Atom")) { -} - -AtomParser::~AtomParser() { -} +AtomParser::~AtomParser() {} QString AtomParser::feedAuthor() const { - QDomNodeList authors = m_xml.documentElement().elementsByTagNameNS(m_atomNamespace, QSL("author")); - QStringList author_str; + QDomNodeList authors = m_xml.documentElement().elementsByTagNameNS(m_atomNamespace, QSL("author")); + QStringList author_str; - for (int i = 0; i < authors.size(); i++) { - QDomNodeList names = authors.at(i).toElement().elementsByTagNameNS(m_atomNamespace, QSL("name")); + for (int i = 0; i < authors.size(); i++) { + QDomNodeList names = authors.at(i).toElement().elementsByTagNameNS(m_atomNamespace, QSL("name")); - if (!names.isEmpty()) { - const QString name = names.at(0).toElement().text(); + if (!names.isEmpty()) { + const QString name = names.at(0).toElement().text(); - if (!name.isEmpty() && !author_str.contains(name)) { - author_str.append(name); - } - } - } + if (!name.isEmpty() && !author_str.contains(name)) { + author_str.append(name); + } + } + } - return author_str.join(", "); + return author_str.join(", "); } Message AtomParser::extractMessage(const QDomElement& msg_element, QDateTime current_time) const { - Message new_message; - QString title = textsFromPath(msg_element, m_atomNamespace, QSL("title"), true).join(QSL(", ")); - QString summary = textsFromPath(msg_element, m_atomNamespace, QSL("content"), true).join(QSL(", ")); + Message new_message; + QString title = textsFromPath(msg_element, m_atomNamespace, QSL("title"), true).join(QSL(", ")); + QString summary = textsFromPath(msg_element, m_atomNamespace, QSL("content"), true).join(QSL(", ")); - if (summary.isEmpty()) { - summary = textsFromPath(msg_element, m_atomNamespace, QSL("summary"), true).join(QSL(", ")); - } + if (summary.isEmpty()) { + summary = textsFromPath(msg_element, m_atomNamespace, QSL("summary"), true).join(QSL(", ")); + } - // Now we obtained maximum of information for title & description. - if (title.isEmpty() && summary.isEmpty()) { - // BOTH title and description are empty, skip this message. - throw new ApplicationException(QSL("Not enough data for the message.")); - } + // Now we obtained maximum of information for title & description. + if (title.isEmpty() && summary.isEmpty()) { + // BOTH title and description are empty, skip this message. + throw new ApplicationException(QSL("Not enough data for the message.")); + } - // Title is not empty, description does not matter. - new_message.m_title = qApp->web()->stripTags(title); - new_message.m_contents = summary; - new_message.m_author = qApp->web()->escapeHtml(messageAuthor(msg_element)); - QString updated = textsFromPath(msg_element, m_atomNamespace, QSL("updated"), true).join(QSL(", ")); - // Deal with creation date. - new_message.m_created = TextFactory::parseDateTime(updated); - new_message.m_createdFromFeed = !new_message.m_created.isNull(); + // Title is not empty, description does not matter. + new_message.m_title = qApp->web()->stripTags(title); + new_message.m_contents = summary; + new_message.m_author = qApp->web()->escapeHtml(messageAuthor(msg_element)); + QString updated = textsFromPath(msg_element, m_atomNamespace, QSL("updated"), true).join(QSL(", ")); - if (!new_message.m_createdFromFeed) { - // Date was NOT obtained from the feed, set current date as creation date for the message. - new_message.m_created = current_time; - } + // Deal with creation date. + new_message.m_created = TextFactory::parseDateTime(updated); + new_message.m_createdFromFeed = !new_message.m_created.isNull(); - // Deal with links - QDomNodeList elem_links = msg_element.toElement().elementsByTagNameNS(m_atomNamespace, QSL("link")); - QString last_link_alternate, last_link_other; + if (!new_message.m_createdFromFeed) { + // Date was NOT obtained from the feed, set current date as creation date for the message. + new_message.m_created = current_time; + } - for (int i = 0; i < elem_links.size(); i++) { - QDomElement link = elem_links.at(i).toElement(); - QString attribute = link.attribute(QSL("rel")); + // Deal with links + QDomNodeList elem_links = msg_element.toElement().elementsByTagNameNS(m_atomNamespace, QSL("link")); + QString last_link_alternate, last_link_other; - if (attribute == QSL("enclosure")) { - new_message.m_enclosures.append(Enclosure(link.attribute(QSL("href")), link.attribute(QSL("type")))); - qDebug("Adding enclosure '%s' for the message.", qPrintable(new_message.m_enclosures.last().m_url)); - } - else if (attribute.isEmpty() || attribute == QSL("alternate")) { - last_link_alternate = link.attribute(QSL("href")); - } - else { - last_link_other = link.attribute(QSL("href")); - } - } + for (int i = 0; i < elem_links.size(); i++) { + QDomElement link = elem_links.at(i).toElement(); + QString attribute = link.attribute(QSL("rel")); - if (!last_link_alternate.isEmpty()) { - new_message.m_url = last_link_alternate; - } - else if (!last_link_other.isEmpty()) { - new_message.m_url = last_link_other; - } - else if (!new_message.m_enclosures.isEmpty()) { - new_message.m_url = new_message.m_enclosures.first().m_url; - } + if (attribute == QSL("enclosure")) { + new_message.m_enclosures.append(Enclosure(link.attribute(QSL("href")), link.attribute(QSL("type")))); + qDebug("Adding enclosure '%s' for the message.", qPrintable(new_message.m_enclosures.last().m_url)); + } + else if (attribute.isEmpty() || attribute == QSL("alternate")) { + last_link_alternate = link.attribute(QSL("href")); + } + else { + last_link_other = link.attribute(QSL("href")); + } + } - return new_message; + if (!last_link_alternate.isEmpty()) { + new_message.m_url = last_link_alternate; + } + else if (!last_link_other.isEmpty()) { + new_message.m_url = last_link_other; + } + else if (!new_message.m_enclosures.isEmpty()) { + new_message.m_url = new_message.m_enclosures.first().m_url; + } + + return new_message; } QString AtomParser::messageAuthor(const QDomElement& msg_element) const { - QDomNodeList authors = msg_element.elementsByTagNameNS(m_atomNamespace, QSL("author")); - QStringList author_str; + QDomNodeList authors = msg_element.elementsByTagNameNS(m_atomNamespace, QSL("author")); + QStringList author_str; - for (int i = 0; i < authors.size(); i++) { - QDomNodeList names = authors.at(i).toElement().elementsByTagNameNS(m_atomNamespace, QSL("name")); + for (int i = 0; i < authors.size(); i++) { + QDomNodeList names = authors.at(i).toElement().elementsByTagNameNS(m_atomNamespace, QSL("name")); - if (!names.isEmpty()) { - author_str.append(names.at(0).toElement().text()); - } - } + if (!names.isEmpty()) { + author_str.append(names.at(0).toElement().text()); + } + } - return author_str.join(", "); + return author_str.join(", "); } QDomNodeList AtomParser::messageElements() { - return m_xml.elementsByTagNameNS(m_atomNamespace, QSL("entry")); + return m_xml.elementsByTagNameNS(m_atomNamespace, QSL("entry")); } diff --git a/src/services/standard/atomparser.h b/src/services/standard/atomparser.h index 5dd50755b..b860064d5 100755 --- a/src/services/standard/atomparser.h +++ b/src/services/standard/atomparser.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,23 +23,22 @@ #include "core/message.h" -#include #include - +#include class AtomParser : public FeedParser { - public: - explicit AtomParser(const QString& data); - virtual ~AtomParser(); + public: + explicit AtomParser(const QString& data); + virtual ~AtomParser(); - private: - QDomNodeList messageElements(); - QString feedAuthor() const; - Message extractMessage(const QDomElement& msg_element, QDateTime current_time) const; - QString messageAuthor(const QDomElement& msg_element) const; + private: + QDomNodeList messageElements(); + QString feedAuthor() const; + Message extractMessage(const QDomElement& msg_element, QDateTime current_time) const; + QString messageAuthor(const QDomElement& msg_element) const; - private: - QString m_atomNamespace; + private: + QString m_atomNamespace; }; #endif // ATOMPARSER_H diff --git a/src/services/standard/feedparser.cpp b/src/services/standard/feedparser.cpp index 5abb83fe4..01bee3b68 100755 --- a/src/services/standard/feedparser.cpp +++ b/src/services/standard/feedparser.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,80 +22,81 @@ #include - FeedParser::FeedParser(const QString& data) : m_xmlData(data) { - m_xml.setContent(m_xmlData, true); + m_xml.setContent(m_xmlData, true); } -FeedParser::~FeedParser() { -} +FeedParser::~FeedParser() {} QList FeedParser::messages() { - QString feed_author = feedAuthor(); - QList messages; - QDateTime current_time = QDateTime::currentDateTime(); - // Pull out all messages. - QDomNodeList messages_in_xml = messageElements(); + QString feed_author = feedAuthor(); - for (int i = 0; i < messages_in_xml.size(); i++) { - QDomNode message_item = messages_in_xml.item(i); + QList messages; + QDateTime current_time = QDateTime::currentDateTime(); - try { - Message new_message = extractMessage(message_item.toElement(), current_time); + // Pull out all messages. + QDomNodeList messages_in_xml = messageElements(); - if (new_message.m_author.isEmpty()) { - new_message.m_author = feed_author; - } + for (int i = 0; i < messages_in_xml.size(); i++) { + QDomNode message_item = messages_in_xml.item(i); - messages.append(new_message); - } - catch (const ApplicationException& ex) { - qDebug() << ex.message(); - } - } + try { + Message new_message = extractMessage(message_item.toElement(), current_time); - return messages; + if (new_message.m_author.isEmpty()) { + new_message.m_author = feed_author; + } + + messages.append(new_message); + } + catch (const ApplicationException& ex) { + qDebug() << ex.message(); + } + } + + return messages; } QStringList FeedParser::textsFromPath(const QDomElement& element, const QString& namespace_uri, const QString& xml_path, bool only_first) const { - QStringList paths = xml_path.split('/'); - QStringList result; - QList current_elements; - current_elements.append(element); + QStringList paths = xml_path.split('/'); + QStringList result; - while (!paths.isEmpty()) { - QList next_elements; - QString next_local_name = paths.takeFirst(); + QList current_elements; + current_elements.append(element); - foreach (const QDomElement& elem, current_elements) { - QDomNodeList elements = elem.elementsByTagNameNS(namespace_uri, next_local_name); + while (!paths.isEmpty()) { + QList next_elements; + QString next_local_name = paths.takeFirst(); - for (int i = 0; i < elements.size(); i++) { - next_elements.append(elements.at(i).toElement()); + foreach (const QDomElement& elem, current_elements) { + QDomNodeList elements = elem.elementsByTagNameNS(namespace_uri, next_local_name); - if (only_first) { - break; - } - } + for (int i = 0; i < elements.size(); i++) { + next_elements.append(elements.at(i).toElement()); - if (next_elements.size() == 1 && only_first) { - break; - } - } + if (only_first) { + break; + } + } - current_elements = next_elements; - } + if (next_elements.size() == 1 && only_first) { + break; + } + } - if (!current_elements.isEmpty()) { - foreach (const QDomElement& elem, current_elements) { - result.append(elem.text()); - } - } + current_elements = next_elements; + } - return result; + if (!current_elements.isEmpty()) { + foreach (const QDomElement& elem, current_elements) { + result.append(elem.text()); + } + } + + return result; } QString FeedParser::feedAuthor() const { - return ""; + return ""; } diff --git a/src/services/standard/feedparser.h b/src/services/standard/feedparser.h index 78cb08c3d..8b456afee 100755 --- a/src/services/standard/feedparser.h +++ b/src/services/standard/feedparser.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,23 +24,22 @@ #include "core/message.h" - class FeedParser { - public: - explicit FeedParser(const QString& data); - virtual ~FeedParser(); + public: + explicit FeedParser(const QString& data); + virtual ~FeedParser(); - virtual QList messages(); + virtual QList messages(); - protected: - QStringList textsFromPath(const QDomElement& element, const QString& namespace_uri, const QString& xml_path, bool only_first) const; - virtual QDomNodeList messageElements() = 0; - virtual QString feedAuthor() const; - virtual Message extractMessage(const QDomElement& msg_element, QDateTime current_time) const = 0; + protected: + QStringList textsFromPath(const QDomElement& element, const QString& namespace_uri, const QString& xml_path, bool only_first) const; + virtual QDomNodeList messageElements() = 0; + virtual QString feedAuthor() const; + virtual Message extractMessage(const QDomElement& msg_element, QDateTime current_time) const = 0; - protected: - QString m_xmlData; - QDomDocument m_xml; + protected: + QString m_xmlData; + QDomDocument m_xml; }; #endif // FEEDPARSER_H diff --git a/src/services/standard/gui/formstandardcategorydetails.cpp b/src/services/standard/gui/formstandardcategorydetails.cpp index fbace356e..ce78d043e 100755 --- a/src/services/standard/gui/formstandardcategorydetails.cpp +++ b/src/services/standard/gui/formstandardcategorydetails.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,235 +18,245 @@ #include "services/standard/gui/formstandardcategorydetails.h" -#include "definitions/definitions.h" -#include "services/abstract/rootitem.h" #include "core/feedsmodel.h" -#include "miscellaneous/iconfactory.h" -#include "gui/feedsview.h" +#include "definitions/definitions.h" #include "gui/baselineedit.h" +#include "gui/feedsview.h" #include "gui/messagebox.h" #include "gui/systemtrayicon.h" +#include "miscellaneous/iconfactory.h" #include "services/abstract/category.h" +#include "services/abstract/rootitem.h" #include "services/standard/standardcategory.h" #include "services/standard/standardserviceroot.h" -#include -#include -#include -#include -#include -#include #include +#include #include - +#include +#include +#include +#include +#include FormStandardCategoryDetails::FormStandardCategoryDetails(StandardServiceRoot* service_root, QWidget* parent) - : QDialog(parent), m_editableCategory(nullptr), m_serviceRoot(service_root) { - initialize(); - createConnections(); - // Initialize text boxes. - onTitleChanged(QString()); - onDescriptionChanged(QString()); + : QDialog(parent), m_editableCategory(nullptr), m_serviceRoot(service_root) { + initialize(); + createConnections(); + + // Initialize text boxes. + onTitleChanged(QString()); + onDescriptionChanged(QString()); } FormStandardCategoryDetails::~FormStandardCategoryDetails() { - qDebug("Destroying FormCategoryDetails instance."); + qDebug("Destroying FormCategoryDetails instance."); } void FormStandardCategoryDetails::createConnections() { - // General connections. - connect(m_ui->m_buttonBox, SIGNAL(accepted()), this, SLOT(apply())); - connect(m_ui->m_txtTitle->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onTitleChanged(QString))); - connect(m_ui->m_txtDescription->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onDescriptionChanged(QString))); - // Icon connections. - connect(m_actionLoadIconFromFile, SIGNAL(triggered()), this, SLOT(onLoadIconFromFile())); - connect(m_actionNoIcon, SIGNAL(triggered()), this, SLOT(onNoIconSelected())); - connect(m_actionUseDefaultIcon, SIGNAL(triggered()), this, SLOT(onUseDefaultIcon())); + // General connections. + connect(m_ui->m_buttonBox, SIGNAL(accepted()), this, SLOT(apply())); + connect(m_ui->m_txtTitle->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onTitleChanged(QString))); + connect(m_ui->m_txtDescription->lineEdit(), SIGNAL(textChanged(QString)), this, SLOT(onDescriptionChanged(QString))); + + // Icon connections. + connect(m_actionLoadIconFromFile, SIGNAL(triggered()), this, SLOT(onLoadIconFromFile())); + connect(m_actionNoIcon, SIGNAL(triggered()), this, SLOT(onNoIconSelected())); + connect(m_actionUseDefaultIcon, SIGNAL(triggered()), this, SLOT(onUseDefaultIcon())); } void FormStandardCategoryDetails::setEditableCategory(StandardCategory* editable_category) { - m_editableCategory = editable_category; - m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) editable_category->parent()))); - m_ui->m_txtTitle->lineEdit()->setText(editable_category->title()); - m_ui->m_txtDescription->lineEdit()->setText(editable_category->description()); - m_ui->m_btnIcon->setIcon(editable_category->icon()); + m_editableCategory = editable_category; + m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) editable_category->parent()))); + m_ui->m_txtTitle->lineEdit()->setText(editable_category->title()); + m_ui->m_txtDescription->lineEdit()->setText(editable_category->description()); + m_ui->m_btnIcon->setIcon(editable_category->icon()); } int FormStandardCategoryDetails::addEditCategory(StandardCategory* input_category, RootItem* parent_to_select) { - // Load categories. - loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot, input_category); + // Load categories. + loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot, input_category); - if (input_category == nullptr) { - // User is adding new category. - setWindowTitle(tr("Add new category")); - // Make sure that "default" icon is used as the default option for new - // categories. - m_actionUseDefaultIcon->trigger(); + if (input_category == nullptr) { + // User is adding new category. + setWindowTitle(tr("Add new category")); - // Load parent from suggested item. - if (parent_to_select != nullptr) { - if (parent_to_select->kind() == RootItemKind::Category) { - m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) parent_to_select))); - } - else if (parent_to_select->kind() == RootItemKind::Feed) { - int target_item = m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) parent_to_select->parent())); + // Make sure that "default" icon is used as the default option for new + // categories. + m_actionUseDefaultIcon->trigger(); - if (target_item >= 0) { - m_ui->m_cmbParentCategory->setCurrentIndex(target_item); - } - } - } - } - else { - // User is editing existing category. - setWindowTitle(tr("Edit existing category")); - setEditableCategory(input_category); - } + // Load parent from suggested item. + if (parent_to_select != nullptr) { + if (parent_to_select->kind() == RootItemKind::Category) { + m_ui->m_cmbParentCategory->setCurrentIndex(m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) parent_to_select))); + } + else if (parent_to_select->kind() == RootItemKind::Feed) { + int target_item = m_ui->m_cmbParentCategory->findData(QVariant::fromValue((void*) parent_to_select->parent())); - // Run the dialog. - return QDialog::exec(); + if (target_item >= 0) { + m_ui->m_cmbParentCategory->setCurrentIndex(target_item); + } + } + } + } + else { + // User is editing existing category. + setWindowTitle(tr("Edit existing category")); + setEditableCategory(input_category); + } + + // Run the dialog. + return QDialog::exec(); } void FormStandardCategoryDetails::apply() { - RootItem* parent = static_cast(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()).value()); - StandardCategory* new_category = new StandardCategory(); - new_category->setTitle(m_ui->m_txtTitle->lineEdit()->text()); - new_category->setCreationDate(QDateTime::currentDateTime()); - new_category->setDescription(m_ui->m_txtDescription->lineEdit()->text()); - new_category->setIcon(m_ui->m_btnIcon->icon()); + RootItem* parent = static_cast(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()).value()); + StandardCategory* new_category = new StandardCategory(); - if (m_editableCategory == nullptr) { - // Add the category. - if (new_category->addItself(parent)) { - m_serviceRoot->requestItemReassignment(new_category, parent); - accept(); - } - else { - delete new_category; - qApp->showGuiMessage(tr("Cannot add category"), - tr("Category was not added due to error."), - QSystemTrayIcon::Critical, - qApp->mainFormWidget(), true); - } - } - else { - new_category->setParent(parent); - bool edited = m_editableCategory->editItself(new_category); + new_category->setTitle(m_ui->m_txtTitle->lineEdit()->text()); + new_category->setCreationDate(QDateTime::currentDateTime()); + new_category->setDescription(m_ui->m_txtDescription->lineEdit()->text()); + new_category->setIcon(m_ui->m_btnIcon->icon()); - if (edited) { - m_serviceRoot->requestItemReassignment(m_editableCategory, new_category->parent()); - accept(); - } - else { - qApp->showGuiMessage(tr("Cannot edit category"), - tr("Category was not edited due to error."), - QSystemTrayIcon::Critical, this, true); - } + if (m_editableCategory == nullptr) { + // Add the category. + if (new_category->addItself(parent)) { + m_serviceRoot->requestItemReassignment(new_category, parent); + accept(); + } + else { + delete new_category; + qApp->showGuiMessage(tr("Cannot add category"), + tr("Category was not added due to error."), + QSystemTrayIcon::Critical, + qApp->mainFormWidget(), true); + } + } + else { + new_category->setParent(parent); + bool edited = m_editableCategory->editItself(new_category); - delete new_category; - } + if (edited) { + m_serviceRoot->requestItemReassignment(m_editableCategory, new_category->parent()); + accept(); + } + else { + qApp->showGuiMessage(tr("Cannot edit category"), + tr("Category was not edited due to error."), + QSystemTrayIcon::Critical, this, true); + } + + delete new_category; + } } void FormStandardCategoryDetails::onTitleChanged(const QString& new_title) { - if (new_title.simplified().size() >= MIN_CATEGORY_NAME_LENGTH) { - m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); - m_ui->m_txtTitle->setStatus(WidgetWithStatus::Ok, tr("Category name is ok.")); - } - else { - m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - m_ui->m_txtTitle->setStatus(WidgetWithStatus::Error, tr("Category name is too short.")); - } + if (new_title.simplified().size() >= MIN_CATEGORY_NAME_LENGTH) { + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + m_ui->m_txtTitle->setStatus(WidgetWithStatus::Ok, tr("Category name is ok.")); + } + else { + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + m_ui->m_txtTitle->setStatus(WidgetWithStatus::Error, tr("Category name is too short.")); + } } void FormStandardCategoryDetails::onDescriptionChanged(const QString& new_description) { - if (new_description.simplified().isEmpty()) { - m_ui->m_txtDescription->setStatus(LineEditWithStatus::Warning, tr("Description is empty.")); - } - else { - m_ui->m_txtDescription->setStatus(LineEditWithStatus::Ok, tr("The description is ok.")); - } + if (new_description.simplified().isEmpty()) { + m_ui->m_txtDescription->setStatus(LineEditWithStatus::Warning, tr("Description is empty.")); + } + else { + m_ui->m_txtDescription->setStatus(LineEditWithStatus::Ok, tr("The description is ok.")); + } } void FormStandardCategoryDetails::onNoIconSelected() { - m_ui->m_btnIcon->setIcon(QIcon()); + m_ui->m_btnIcon->setIcon(QIcon()); } void FormStandardCategoryDetails::onLoadIconFromFile() { - QFileDialog dialog(this, tr("Select icon file for the category"), - qApp->homeFolder(), tr("Images (*.bmp *.jpg *.jpeg *.png *.svg *.tga)")); - dialog.setFileMode(QFileDialog::ExistingFile); - dialog.setWindowIcon(qApp->icons()->fromTheme(QSL("image-x-generic"))); - dialog.setOptions(QFileDialog::DontUseNativeDialog | QFileDialog::ReadOnly); - dialog.setViewMode(QFileDialog::Detail); - dialog.setLabelText(QFileDialog::Accept, tr("Select icon")); - dialog.setLabelText(QFileDialog::Reject, tr("Cancel")); - //: Label to describe the folder for icon file selection dialog. - dialog.setLabelText(QFileDialog::LookIn, tr("Look in:")); - dialog.setLabelText(QFileDialog::FileName, tr("Icon name:")); - dialog.setLabelText(QFileDialog::FileType, tr("Icon type:")); + QFileDialog dialog(this, tr("Select icon file for the category"), + qApp->homeFolder(), tr("Images (*.bmp *.jpg *.jpeg *.png *.svg *.tga)")); - if (dialog.exec() == QDialog::Accepted) { - m_ui->m_btnIcon->setIcon(QIcon(dialog.selectedFiles().value(0))); - } + dialog.setFileMode(QFileDialog::ExistingFile); + dialog.setWindowIcon(qApp->icons()->fromTheme(QSL("image-x-generic"))); + dialog.setOptions(QFileDialog::DontUseNativeDialog | QFileDialog::ReadOnly); + dialog.setViewMode(QFileDialog::Detail); + dialog.setLabelText(QFileDialog::Accept, tr("Select icon")); + dialog.setLabelText(QFileDialog::Reject, tr("Cancel")); + + //: Label to describe the folder for icon file selection dialog. + dialog.setLabelText(QFileDialog::LookIn, tr("Look in:")); + dialog.setLabelText(QFileDialog::FileName, tr("Icon name:")); + dialog.setLabelText(QFileDialog::FileType, tr("Icon type:")); + + if (dialog.exec() == QDialog::Accepted) { + m_ui->m_btnIcon->setIcon(QIcon(dialog.selectedFiles().value(0))); + } } void FormStandardCategoryDetails::onUseDefaultIcon() { - m_ui->m_btnIcon->setIcon(qApp->icons()->fromTheme(QSL("folder"))); + m_ui->m_btnIcon->setIcon(qApp->icons()->fromTheme(QSL("folder"))); } void FormStandardCategoryDetails::initialize() { - m_ui.reset(new Ui::FormStandardCategoryDetails()); - m_ui->setupUi(this); - // Set text boxes. - m_ui->m_txtTitle->lineEdit()->setPlaceholderText(tr("Category title")); - m_ui->m_txtTitle->lineEdit()->setToolTip(tr("Set title for your category.")); - m_ui->m_txtDescription->lineEdit()->setPlaceholderText(tr("Category description")); - m_ui->m_txtDescription->lineEdit()->setToolTip(tr("Set description for your category.")); - // Set flags and attributes. - setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); - setWindowIcon(qApp->icons()->fromTheme(QSL("folder"))); - // Setup button box. - m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - // Setup menu & actions for icon selection. - m_iconMenu = new QMenu(tr("Icon selection"), this); - m_actionLoadIconFromFile = new QAction(qApp->icons()->fromTheme(QSL("image-x-generic")), - tr("Load icon from file..."), - this); - m_actionNoIcon = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), - tr("Do not use icon"), - this); - m_actionUseDefaultIcon = new QAction(qApp->icons()->fromTheme(QSL("folder")), - tr("Use default icon"), - this); - m_iconMenu->addAction(m_actionLoadIconFromFile); - m_iconMenu->addAction(m_actionUseDefaultIcon); - m_iconMenu->addAction(m_actionNoIcon); - m_ui->m_btnIcon->setMenu(m_iconMenu); - // Setup tab order. - setTabOrder(m_ui->m_cmbParentCategory, m_ui->m_txtTitle->lineEdit()); - setTabOrder(m_ui->m_txtTitle->lineEdit(), m_ui->m_txtDescription->lineEdit()); - setTabOrder(m_ui->m_txtDescription->lineEdit(), m_ui->m_btnIcon); - setTabOrder(m_ui->m_btnIcon, m_ui->m_buttonBox); - m_ui->m_txtTitle->lineEdit()->setFocus(Qt::TabFocusReason); + m_ui.reset(new Ui::FormStandardCategoryDetails()); + m_ui->setupUi(this); + + // Set text boxes. + m_ui->m_txtTitle->lineEdit()->setPlaceholderText(tr("Category title")); + m_ui->m_txtTitle->lineEdit()->setToolTip(tr("Set title for your category.")); + m_ui->m_txtDescription->lineEdit()->setPlaceholderText(tr("Category description")); + m_ui->m_txtDescription->lineEdit()->setToolTip(tr("Set description for your category.")); + + // Set flags and attributes. + setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); + setWindowIcon(qApp->icons()->fromTheme(QSL("folder"))); + + // Setup button box. + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + + // Setup menu & actions for icon selection. + m_iconMenu = new QMenu(tr("Icon selection"), this); + m_actionLoadIconFromFile = new QAction(qApp->icons()->fromTheme(QSL("image-x-generic")), + tr("Load icon from file..."), + this); + m_actionNoIcon = new QAction(qApp->icons()->fromTheme(QSL("dialog-error")), + tr("Do not use icon"), + this); + m_actionUseDefaultIcon = new QAction(qApp->icons()->fromTheme(QSL("folder")), + tr("Use default icon"), + this); + m_iconMenu->addAction(m_actionLoadIconFromFile); + m_iconMenu->addAction(m_actionUseDefaultIcon); + m_iconMenu->addAction(m_actionNoIcon); + m_ui->m_btnIcon->setMenu(m_iconMenu); + + // Setup tab order. + setTabOrder(m_ui->m_cmbParentCategory, m_ui->m_txtTitle->lineEdit()); + setTabOrder(m_ui->m_txtTitle->lineEdit(), m_ui->m_txtDescription->lineEdit()); + setTabOrder(m_ui->m_txtDescription->lineEdit(), m_ui->m_btnIcon); + setTabOrder(m_ui->m_btnIcon, m_ui->m_buttonBox); + m_ui->m_txtTitle->lineEdit()->setFocus(Qt::TabFocusReason); } void FormStandardCategoryDetails::loadCategories(const QList categories, RootItem* root_item, StandardCategory* input_category) { - m_ui->m_cmbParentCategory->addItem(root_item->icon(), - root_item->title(), - QVariant::fromValue((void*) root_item)); + m_ui->m_cmbParentCategory->addItem(root_item->icon(), + root_item->title(), + QVariant::fromValue((void*) root_item)); - foreach (Category* category, categories) { - if (input_category != nullptr && (category == input_category || category->isChildOf(input_category))) { - // This category cannot be selected as the new - // parent for currently edited category, so - // don't add it. - continue; - } + foreach (Category* category, categories) { + if (input_category != nullptr && (category == input_category || category->isChildOf(input_category))) { + // This category cannot be selected as the new + // parent for currently edited category, so + // don't add it. + continue; + } - m_ui->m_cmbParentCategory->addItem(category->data(FDS_MODEL_TITLE_INDEX, Qt::DecorationRole).value(), - category->title(), - QVariant::fromValue((void*) category)); - } + m_ui->m_cmbParentCategory->addItem(category->data(FDS_MODEL_TITLE_INDEX, Qt::DecorationRole).value(), + category->title(), + QVariant::fromValue((void*) category)); + } } diff --git a/src/services/standard/gui/formstandardcategorydetails.h b/src/services/standard/gui/formstandardcategorydetails.h index f52578a74..c89b3b41f 100755 --- a/src/services/standard/gui/formstandardcategorydetails.h +++ b/src/services/standard/gui/formstandardcategorydetails.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,9 +23,8 @@ #include - namespace Ui { - class FormStandardCategoryDetails; + class FormStandardCategoryDetails; } class Category; @@ -36,54 +36,57 @@ class QMenu; class QAction; class FormStandardCategoryDetails : public QDialog { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors. - explicit FormStandardCategoryDetails(StandardServiceRoot* service_root, QWidget* parent = 0); - virtual ~FormStandardCategoryDetails(); + public: - public slots: - // Executes add/edit standard category dialog. - int addEditCategory(StandardCategory* input_category, RootItem* parent_to_select); + // Constructors and destructors. + explicit FormStandardCategoryDetails(StandardServiceRoot* service_root, QWidget* parent = 0); + virtual ~FormStandardCategoryDetails(); - protected slots: - // Applies changes. - void apply(); + public slots: - // Trigerred when title/description changes. - void onTitleChanged(const QString& new_title); - void onDescriptionChanged(const QString& new_description); + // Executes add/edit standard category dialog. + int addEditCategory(StandardCategory* input_category, RootItem* parent_to_select); - // Icon selectors. - void onNoIconSelected(); - void onLoadIconFromFile(); - void onUseDefaultIcon(); + protected slots: - protected: - // Creates needed connections. - void createConnections(); + // Applies changes. + void apply(); - // Sets the category which will be edited. - void setEditableCategory(StandardCategory* editable_category); + // Trigerred when title/description changes. + void onTitleChanged(const QString& new_title); + void onDescriptionChanged(const QString& new_description); - // Initializes the dialog. - void initialize(); + // Icon selectors. + void onNoIconSelected(); + void onLoadIconFromFile(); + void onUseDefaultIcon(); - // Loads categories into the dialog + give root "category" - // and make sure that no childs of input category (including) - // input category are loaded. - void loadCategories(const QList categories, RootItem* root_item, StandardCategory* input_category); + protected: - private: - QScopedPointer m_ui; - StandardCategory* m_editableCategory; - StandardServiceRoot* m_serviceRoot; + // Creates needed connections. + void createConnections(); - QMenu* m_iconMenu; - QAction* m_actionLoadIconFromFile; - QAction* m_actionUseDefaultIcon; - QAction* m_actionNoIcon; + // Sets the category which will be edited. + void setEditableCategory(StandardCategory* editable_category); + + // Initializes the dialog. + void initialize(); + + // Loads categories into the dialog + give root "category" + // and make sure that no childs of input category (including) + // input category are loaded. + void loadCategories(const QList categories, RootItem* root_item, StandardCategory* input_category); + + private: + QScopedPointer m_ui; + StandardCategory* m_editableCategory; + StandardServiceRoot* m_serviceRoot; + QMenu* m_iconMenu; + QAction* m_actionLoadIconFromFile; + QAction* m_actionUseDefaultIcon; + QAction* m_actionNoIcon; }; #endif // FORMCATEGORYDETAILS_H diff --git a/src/services/standard/gui/formstandardfeeddetails.cpp b/src/services/standard/gui/formstandardfeeddetails.cpp index 614c8bb69..ef852d328 100755 --- a/src/services/standard/gui/formstandardfeeddetails.cpp +++ b/src/services/standard/gui/formstandardfeeddetails.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,72 +18,74 @@ #include "services/standard/gui/formstandardfeeddetails.h" -#include "services/standard/standardfeed.h" -#include "services/abstract/serviceroot.h" #include "miscellaneous/application.h" - +#include "services/abstract/serviceroot.h" +#include "services/standard/standardfeed.h" FormStandardFeedDetails::FormStandardFeedDetails(ServiceRoot* service_root, QWidget* parent) - : FormFeedDetails(service_root, parent) { -} + : FormFeedDetails(service_root, parent) {} void FormStandardFeedDetails::apply() { - RootItem* parent = static_cast(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()).value()); - StandardFeed::Type type = static_cast(m_ui->m_cmbType->itemData(m_ui->m_cmbType->currentIndex()).value()); - StandardFeed* new_feed = new StandardFeed(); - // Setup data for new_feed. - new_feed->setTitle(m_ui->m_txtTitle->lineEdit()->text()); - new_feed->setCreationDate(QDateTime::currentDateTime()); - new_feed->setDescription(m_ui->m_txtDescription->lineEdit()->text()); - new_feed->setIcon(m_ui->m_btnIcon->icon()); - new_feed->setEncoding(m_ui->m_cmbEncoding->currentText()); - new_feed->setType(type); - new_feed->setUrl(m_ui->m_txtUrl->lineEdit()->text()); - new_feed->setPasswordProtected(m_ui->m_gbAuthentication->isChecked()); - new_feed->setUsername(m_ui->m_txtUsername->lineEdit()->text()); - new_feed->setPassword(m_ui->m_txtPassword->lineEdit()->text()); - new_feed->setAutoUpdateType(static_cast(m_ui->m_cmbAutoUpdateType->itemData( - m_ui->m_cmbAutoUpdateType->currentIndex()).toInt())); - new_feed->setAutoUpdateInitialInterval(m_ui->m_spinAutoUpdateInterval->value()); + RootItem* parent = static_cast(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()).value()); - if (m_editableFeed == nullptr) { - // Add the feed. - if (new_feed->addItself(parent)) { - m_serviceRoot->requestItemReassignment(new_feed, parent); - accept(); - } - else { - delete new_feed; - qApp->showGuiMessage(tr("Cannot add feed"), - tr("Feed was not added due to error."), - QSystemTrayIcon::Critical, this, true); - } - } - else { - new_feed->setParent(parent); - // Edit the feed. - bool edited = qobject_cast(m_editableFeed)->editItself(new_feed); + StandardFeed::Type type = static_cast(m_ui->m_cmbType->itemData(m_ui->m_cmbType->currentIndex()).value()); + StandardFeed* new_feed = new StandardFeed(); - if (edited) { - m_serviceRoot->requestItemReassignment(m_editableFeed, new_feed->parent()); - accept(); - } - else { - qApp->showGuiMessage(tr("Cannot edit feed"), - tr("Feed was not edited due to error."), - QSystemTrayIcon::Critical, this, true); - } + // Setup data for new_feed. + new_feed->setTitle(m_ui->m_txtTitle->lineEdit()->text()); + new_feed->setCreationDate(QDateTime::currentDateTime()); + new_feed->setDescription(m_ui->m_txtDescription->lineEdit()->text()); + new_feed->setIcon(m_ui->m_btnIcon->icon()); + new_feed->setEncoding(m_ui->m_cmbEncoding->currentText()); + new_feed->setType(type); + new_feed->setUrl(m_ui->m_txtUrl->lineEdit()->text()); + new_feed->setPasswordProtected(m_ui->m_gbAuthentication->isChecked()); + new_feed->setUsername(m_ui->m_txtUsername->lineEdit()->text()); + new_feed->setPassword(m_ui->m_txtPassword->lineEdit()->text()); + new_feed->setAutoUpdateType(static_cast(m_ui->m_cmbAutoUpdateType->itemData( + m_ui->m_cmbAutoUpdateType->currentIndex()).toInt())); + new_feed->setAutoUpdateInitialInterval(m_ui->m_spinAutoUpdateInterval->value()); - delete new_feed; - } + if (m_editableFeed == nullptr) { + // Add the feed. + if (new_feed->addItself(parent)) { + m_serviceRoot->requestItemReassignment(new_feed, parent); + accept(); + } + else { + delete new_feed; + qApp->showGuiMessage(tr("Cannot add feed"), + tr("Feed was not added due to error."), + QSystemTrayIcon::Critical, this, true); + } + } + else { + new_feed->setParent(parent); + + // Edit the feed. + bool edited = qobject_cast(m_editableFeed)->editItself(new_feed); + + if (edited) { + m_serviceRoot->requestItemReassignment(m_editableFeed, new_feed->parent()); + accept(); + } + else { + qApp->showGuiMessage(tr("Cannot edit feed"), + tr("Feed was not edited due to error."), + QSystemTrayIcon::Critical, this, true); + } + + delete new_feed; + } } void FormStandardFeedDetails::setEditableFeed(Feed* editable_feed) { - FormFeedDetails::setEditableFeed(editable_feed); - StandardFeed* feed = qobject_cast(editable_feed); - m_ui->m_cmbType->setCurrentIndex(m_ui->m_cmbType->findData(QVariant::fromValue((int) feed->type()))); - m_ui->m_cmbEncoding->setCurrentIndex(m_ui->m_cmbEncoding->findData(feed->encoding(), Qt::DisplayRole, Qt::MatchFixedString)); - m_ui->m_gbAuthentication->setChecked(feed->passwordProtected()); - m_ui->m_txtUsername->lineEdit()->setText(feed->username()); - m_ui->m_txtPassword->lineEdit()->setText(feed->password()); + FormFeedDetails::setEditableFeed(editable_feed); + StandardFeed* feed = qobject_cast(editable_feed); + + m_ui->m_cmbType->setCurrentIndex(m_ui->m_cmbType->findData(QVariant::fromValue((int) feed->type()))); + m_ui->m_cmbEncoding->setCurrentIndex(m_ui->m_cmbEncoding->findData(feed->encoding(), Qt::DisplayRole, Qt::MatchFixedString)); + m_ui->m_gbAuthentication->setChecked(feed->passwordProtected()); + m_ui->m_txtUsername->lineEdit()->setText(feed->username()); + m_ui->m_txtPassword->lineEdit()->setText(feed->password()); } diff --git a/src/services/standard/gui/formstandardfeeddetails.h b/src/services/standard/gui/formstandardfeeddetails.h index 7e968b2b7..53e254ac4 100755 --- a/src/services/standard/gui/formstandardfeeddetails.h +++ b/src/services/standard/gui/formstandardfeeddetails.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,18 +21,17 @@ #include "services/abstract/gui/formfeeddetails.h" - class FormStandardFeedDetails : public FormFeedDetails { - Q_OBJECT + Q_OBJECT - public: - explicit FormStandardFeedDetails(ServiceRoot* service_root, QWidget* parent = 0); + public: + explicit FormStandardFeedDetails(ServiceRoot* service_root, QWidget* parent = 0); - protected slots: - void apply(); + protected slots: + void apply(); - protected: - void setEditableFeed(Feed* editable_feed); + protected: + void setEditableFeed(Feed* editable_feed); }; #endif // FORMSSFEEDDETAILS_H diff --git a/src/services/standard/gui/formstandardimportexport.cpp b/src/services/standard/gui/formstandardimportexport.cpp index d36f5eb56..7f908307f 100755 --- a/src/services/standard/gui/formstandardimportexport.cpp +++ b/src/services/standard/gui/formstandardimportexport.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,286 +18,290 @@ #include "services/standard/gui/formstandardimportexport.h" -#include "services/abstract/category.h" -#include "services/standard/standardfeedsimportexportmodel.h" -#include "services/standard/standardserviceroot.h" #include "core/feedsmodel.h" -#include "miscellaneous/application.h" +#include "exceptions/ioexception.h" +#include "gui/dialogs/formmain.h" #include "gui/feedmessageviewer.h" #include "gui/feedsview.h" #include "gui/messagebox.h" -#include "gui/dialogs/formmain.h" -#include "exceptions/ioexception.h" - +#include "miscellaneous/application.h" +#include "services/abstract/category.h" +#include "services/standard/standardfeedsimportexportmodel.h" +#include "services/standard/standardserviceroot.h" #include #include - FormStandardImportExport::FormStandardImportExport(StandardServiceRoot* service_root, QWidget* parent) - : QDialog(parent), m_ui(new Ui::FormStandardImportExport), m_serviceRoot(service_root) { - m_ui->setupUi(this); - m_model = new FeedsImportExportModel(m_ui->m_treeFeeds); - connect(m_model, &FeedsImportExportModel::parsingStarted, this, &FormStandardImportExport::onParsingStarted); - connect(m_model, &FeedsImportExportModel::parsingFinished, this, &FormStandardImportExport::onParsingFinished); - connect(m_model, &FeedsImportExportModel::parsingProgress, this, &FormStandardImportExport::onParsingProgress); - setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); - m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Error, tr("No file is selected."), tr("No file is selected.")); - m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->disconnect(); - m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet.")); - connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormStandardImportExport::performAction); - connect(m_ui->m_btnSelectFile, &QPushButton::clicked, this, &FormStandardImportExport::selectFile); - connect(m_ui->m_btnCheckAllItems, &QPushButton::clicked, m_model, &FeedsImportExportModel::checkAllItems); - connect(m_ui->m_btnUncheckAllItems, &QPushButton::clicked, m_model, &FeedsImportExportModel::uncheckAllItems); + : QDialog(parent), m_ui(new Ui::FormStandardImportExport), m_serviceRoot(service_root) { + m_ui->setupUi(this); + m_model = new FeedsImportExportModel(m_ui->m_treeFeeds); + connect(m_model, &FeedsImportExportModel::parsingStarted, this, &FormStandardImportExport::onParsingStarted); + connect(m_model, &FeedsImportExportModel::parsingFinished, this, &FormStandardImportExport::onParsingFinished); + connect(m_model, &FeedsImportExportModel::parsingProgress, this, &FormStandardImportExport::onParsingProgress); + setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); + m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Error, tr("No file is selected."), tr("No file is selected.")); + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->disconnect(); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet.")); + connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormStandardImportExport::performAction); + connect(m_ui->m_btnSelectFile, &QPushButton::clicked, this, &FormStandardImportExport::selectFile); + connect(m_ui->m_btnCheckAllItems, &QPushButton::clicked, m_model, &FeedsImportExportModel::checkAllItems); + connect(m_ui->m_btnUncheckAllItems, &QPushButton::clicked, m_model, &FeedsImportExportModel::uncheckAllItems); } -FormStandardImportExport::~FormStandardImportExport() { -} +FormStandardImportExport::~FormStandardImportExport() {} void FormStandardImportExport::setMode(const FeedsImportExportModel::Mode& mode) { - m_model->setMode(mode); - m_ui->m_progressBar->setVisible(false); + m_model->setMode(mode); + m_ui->m_progressBar->setVisible(false); - switch (mode) { - case FeedsImportExportModel::Export: { - m_model->setRootItem(m_serviceRoot); - m_model->checkAllItems(); - m_ui->m_treeFeeds->setModel(m_model); - m_ui->m_treeFeeds->expandAll(); - m_ui->m_cmbRootNode->setVisible(false); - m_ui->m_lblRootNode->setVisible(false); - m_ui->m_groupFile->setTitle(tr("Destination file")); - m_ui->m_groupFeeds->setTitle(tr("Source feeds && categories")); - setWindowTitle(tr("Export feeds")); - setWindowIcon(qApp->icons()->fromTheme(QSL("document-export"))); - break; - } + switch (mode) { + case FeedsImportExportModel::Export: { + m_model->setRootItem(m_serviceRoot); + m_model->checkAllItems(); + m_ui->m_treeFeeds->setModel(m_model); + m_ui->m_treeFeeds->expandAll(); + m_ui->m_cmbRootNode->setVisible(false); + m_ui->m_lblRootNode->setVisible(false); + m_ui->m_groupFile->setTitle(tr("Destination file")); + m_ui->m_groupFeeds->setTitle(tr("Source feeds && categories")); + setWindowTitle(tr("Export feeds")); + setWindowIcon(qApp->icons()->fromTheme(QSL("document-export"))); + break; + } - case FeedsImportExportModel::Import: { - m_ui->m_groupFile->setTitle(tr("Source file")); - m_ui->m_groupFeeds->setTitle(tr("Target feeds && categories")); - m_ui->m_groupFeeds->setDisabled(true); - // Load categories. - loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot); - setWindowTitle(tr("Import feeds")); - setWindowIcon(qApp->icons()->fromTheme(QSL("document-import"))); - break; - } + case FeedsImportExportModel::Import: { + m_ui->m_groupFile->setTitle(tr("Source file")); + m_ui->m_groupFeeds->setTitle(tr("Target feeds && categories")); + m_ui->m_groupFeeds->setDisabled(true); - default: - break; - } + // Load categories. + loadCategories(m_serviceRoot->getSubTreeCategories(), m_serviceRoot); + setWindowTitle(tr("Import feeds")); + setWindowIcon(qApp->icons()->fromTheme(QSL("document-import"))); + break; + } - m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + default: + break; + } + + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); } void FormStandardImportExport::selectFile() { - switch (m_model->mode()) { - case FeedsImportExportModel::Import: - selectImportFile(); - break; + switch (m_model->mode()) { + case FeedsImportExportModel::Import: + selectImportFile(); + break; - case FeedsImportExportModel::Export: { - selectExportFile(); - break; - } + case FeedsImportExportModel::Export: { + selectExportFile(); + break; + } - default: - break; - } + default: + break; + } } void FormStandardImportExport::onParsingStarted() { - m_ui->m_lblResult->setStatus(WidgetWithStatus::Progress, tr("Parsing data..."), tr("Parsing data...")); - m_ui->m_btnSelectFile->setEnabled(false); - m_ui->m_groupFeeds->setEnabled(false); - m_ui->m_progressBar->setValue(0); - m_ui->m_progressBar->setVisible(true); - m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Progress, tr("Parsing data..."), tr("Parsing data...")); + m_ui->m_btnSelectFile->setEnabled(false); + m_ui->m_groupFeeds->setEnabled(false); + m_ui->m_progressBar->setValue(0); + m_ui->m_progressBar->setVisible(true); + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); } void FormStandardImportExport::onParsingFinished(int count_failed, int count_succeeded, bool parsing_error) { - Q_UNUSED(count_failed) - Q_UNUSED(count_succeeded) - m_ui->m_progressBar->setVisible(false); - m_ui->m_progressBar->setValue(0); - m_model->checkAllItems(); + Q_UNUSED(count_failed) + Q_UNUSED(count_succeeded) + m_ui->m_progressBar->setVisible(false); + m_ui->m_progressBar->setValue(0); + m_model->checkAllItems(); - if (!parsing_error) { - m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Feeds were loaded."), tr("Feeds were loaded.")); - m_ui->m_groupFeeds->setEnabled(true); - m_ui->m_btnSelectFile->setEnabled(true); - m_ui->m_treeFeeds->setModel(m_model); - m_ui->m_treeFeeds->expandAll(); - } - else { - m_ui->m_groupFeeds->setEnabled(false); - m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Error, file is not well-formed. Select another file."), - tr("Error occurred. File is not well-formed. Select another file.")); - } + if (!parsing_error) { + m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Feeds were loaded."), tr("Feeds were loaded.")); + m_ui->m_groupFeeds->setEnabled(true); + m_ui->m_btnSelectFile->setEnabled(true); + m_ui->m_treeFeeds->setModel(m_model); + m_ui->m_treeFeeds->expandAll(); + } + else { + m_ui->m_groupFeeds->setEnabled(false); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Error, file is not well-formed. Select another file."), + tr("Error occurred. File is not well-formed. Select another file.")); + } - m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); } void FormStandardImportExport::onParsingProgress(int completed, int total) { - m_ui->m_progressBar->setMaximum(total); - m_ui->m_progressBar->setValue(completed); + m_ui->m_progressBar->setMaximum(total); + m_ui->m_progressBar->setValue(completed); } void FormStandardImportExport::selectExportFile() { - const QString filter_opml20 = tr("OPML 2.0 files (*.opml)"); - const QString filter_txt_url_per_line = tr("TXT files [one URL per line] (*.txt)"); - QString filter; - QString selected_filter; - // Add more filters here. - filter += filter_opml20; - filter += ";;"; - filter += filter_txt_url_per_line; - QString selected_file = QFileDialog::getSaveFileName(this, tr("Select file for feeds export"), - qApp->homeFolder(), filter, &selected_filter); + const QString filter_opml20 = tr("OPML 2.0 files (*.opml)"); + const QString filter_txt_url_per_line = tr("TXT files [one URL per line] (*.txt)"); + QString filter; + QString selected_filter; - if (!selected_file.isEmpty()) { - if (selected_filter == filter_opml20) { - m_conversionType = OPML20; + // Add more filters here. + filter += filter_opml20; + filter += ";;"; + filter += filter_txt_url_per_line; + QString selected_file = QFileDialog::getSaveFileName(this, tr("Select file for feeds export"), + qApp->homeFolder(), filter, &selected_filter); - if (!selected_file.endsWith(QL1S(".opml"))) { - selected_file += QL1S(".opml"); - } - } - else if (selected_filter == filter_txt_url_per_line) { - m_conversionType = TXTUrlPerLine; + if (!selected_file.isEmpty()) { + if (selected_filter == filter_opml20) { + m_conversionType = OPML20; - if (!selected_file.endsWith(QL1S(".txt"))) { - selected_file += QL1S(".txt"); - } - } + if (!selected_file.endsWith(QL1S(".opml"))) { + selected_file += QL1S(".opml"); + } + } + else if (selected_filter == filter_txt_url_per_line) { + m_conversionType = TXTUrlPerLine; - m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(selected_file), tr("File is selected.")); - } + if (!selected_file.endsWith(QL1S(".txt"))) { + selected_file += QL1S(".txt"); + } + } - m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(m_ui->m_lblSelectFile->status() == WidgetWithStatus::Ok); + m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(selected_file), tr("File is selected.")); + } + + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(m_ui->m_lblSelectFile->status() == WidgetWithStatus::Ok); } void FormStandardImportExport::selectImportFile() { - const QString filter_opml20 = tr("OPML 2.0 files (*.opml)"); - const QString filter_txt_url_per_line = tr("TXT files [one URL per line] (*.txt)"); - QString filter; - QString selected_filter; - // Add more filters here. - filter += filter_opml20; - filter += ";;"; - filter += filter_txt_url_per_line; - const QString selected_file = QFileDialog::getOpenFileName(this, tr("Select file for feeds import"), qApp->homeFolder(), - filter, &selected_filter); + const QString filter_opml20 = tr("OPML 2.0 files (*.opml)"); + const QString filter_txt_url_per_line = tr("TXT files [one URL per line] (*.txt)"); + QString filter; + QString selected_filter; - if (!selected_file.isEmpty()) { - if (selected_filter == filter_opml20) { - m_conversionType = OPML20; - } - else if (selected_filter == filter_txt_url_per_line) { - m_conversionType = TXTUrlPerLine; - } + // Add more filters here. + filter += filter_opml20; + filter += ";;"; + filter += filter_txt_url_per_line; + const QString selected_file = QFileDialog::getOpenFileName(this, tr("Select file for feeds import"), qApp->homeFolder(), + filter, &selected_filter); - m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(selected_file), tr("File is selected.")); - QMessageBox::StandardButton answer = MessageBox::show(this, QMessageBox::Warning, tr("Get online metadata"), - tr("Metadata for your feeds can be fetched online. Note that the action " - "could take several minutes, depending on number of feeds."), - tr("Do you want to fetch feed metadata online?"), QString(), QMessageBox::Yes | QMessageBox::No, - QMessageBox::Yes); - parseImportFile(selected_file, answer == QMessageBox::Yes); - } + if (!selected_file.isEmpty()) { + if (selected_filter == filter_opml20) { + m_conversionType = OPML20; + } + else if (selected_filter == filter_txt_url_per_line) { + m_conversionType = TXTUrlPerLine; + } + + m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(selected_file), tr("File is selected.")); + QMessageBox::StandardButton answer = MessageBox::show(this, + QMessageBox::Warning, + tr("Get online metadata"), + tr("Metadata for your feeds can be fetched online. Note that the action " + "could take several minutes, depending on number of feeds."), + tr("Do you want to fetch feed metadata online?"), + QString(), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); + parseImportFile(selected_file, answer == QMessageBox::Yes); + } } void FormStandardImportExport::parseImportFile(const QString& file_name, bool fetch_metadata_online) { - QFile input_file(file_name); - QByteArray input_data; + QFile input_file(file_name); + QByteArray input_data; - if (input_file.open(QIODevice::Text | QIODevice::Unbuffered | QIODevice::ReadOnly)) { - input_data = input_file.readAll(); - input_file.close(); - } - else { - m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Cannot open source file."), tr("Cannot open source file.")); - return; - } + if (input_file.open(QIODevice::Text | QIODevice::Unbuffered | QIODevice::ReadOnly)) { + input_data = input_file.readAll(); + input_file.close(); + } + else { + m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Cannot open source file."), tr("Cannot open source file.")); + return; + } - switch (m_conversionType) { - case OPML20: - m_model->importAsOPML20(input_data, fetch_metadata_online); - break; + switch (m_conversionType) { + case OPML20: + m_model->importAsOPML20(input_data, fetch_metadata_online); + break; - case TXTUrlPerLine: - m_model->importAsTxtURLPerLine(input_data, fetch_metadata_online); - break; + case TXTUrlPerLine: + m_model->importAsTxtURLPerLine(input_data, fetch_metadata_online); + break; - default: - return; - } + default: + return; + } } void FormStandardImportExport::performAction() { - switch (m_model->mode()) { - case FeedsImportExportModel::Import: - importFeeds(); - break; + switch (m_model->mode()) { + case FeedsImportExportModel::Import: + importFeeds(); + break; - case FeedsImportExportModel::Export: - exportFeeds(); - break; + case FeedsImportExportModel::Export: + exportFeeds(); + break; - default: - break; - } + default: + break; + } } void FormStandardImportExport::exportFeeds() { - QByteArray result_data; - bool result_export = false; + QByteArray result_data; + bool result_export = false; - switch (m_conversionType) { - case OPML20: - result_export = m_model->exportToOMPL20(result_data); - break; + switch (m_conversionType) { + case OPML20: + result_export = m_model->exportToOMPL20(result_data); + break; - case TXTUrlPerLine: - result_export = m_model->exportToTxtURLPerLine(result_data); - break; + case TXTUrlPerLine: + result_export = m_model->exportToTxtURLPerLine(result_data); + break; - default: - break; - } + default: + break; + } - if (result_export) { - try { - IOFactory::writeTextFile(m_ui->m_lblSelectFile->label()->text(), result_data); - m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Feeds were exported successfully."), tr("Feeds were exported successfully.")); - } - catch (IOException& ex) { - m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Cannot write into destination file: '%1'."), ex.message()); - } - } - else { - m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Critical error occurred."), tr("Critical error occurred.")); - } + if (result_export) { + try { + IOFactory::writeTextFile(m_ui->m_lblSelectFile->label()->text(), result_data); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Feeds were exported successfully."), tr("Feeds were exported successfully.")); + } + catch (IOException& ex) { + m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Cannot write into destination file: '%1'."), ex.message()); + } + } + else { + m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Critical error occurred."), tr("Critical error occurred.")); + } } void FormStandardImportExport::importFeeds() { - QString output_message; - RootItem* parent = static_cast(m_ui->m_cmbRootNode->itemData(m_ui->m_cmbRootNode->currentIndex()).value()); + QString output_message; + RootItem* parent = static_cast(m_ui->m_cmbRootNode->itemData(m_ui->m_cmbRootNode->currentIndex()).value()); - if (m_serviceRoot->mergeImportExportModel(m_model, parent, output_message)) { - m_serviceRoot->requestItemExpand(parent->getSubTree(), true); - m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, output_message, output_message); - } - else { - m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, output_message, output_message); - } + if (m_serviceRoot->mergeImportExportModel(m_model, parent, output_message)) { + m_serviceRoot->requestItemExpand(parent->getSubTree(), true); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, output_message, output_message); + } + else { + m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, output_message, output_message); + } } void FormStandardImportExport::loadCategories(const QList categories, RootItem* root_item) { - m_ui->m_cmbRootNode->addItem(root_item->icon(), root_item->title(), QVariant::fromValue((void*) root_item)); + m_ui->m_cmbRootNode->addItem(root_item->icon(), root_item->title(), QVariant::fromValue((void*) root_item)); - foreach (Category* category, categories) { - m_ui->m_cmbRootNode->addItem(category->icon(), category->title(), QVariant::fromValue((void*) category)); - } + foreach (Category* category, categories) { + m_ui->m_cmbRootNode->addItem(category->icon(), category->title(), QVariant::fromValue((void*) category)); + } } diff --git a/src/services/standard/gui/formstandardimportexport.h b/src/services/standard/gui/formstandardimportexport.h index 9806c0a78..0ab35a99b 100755 --- a/src/services/standard/gui/formstandardimportexport.h +++ b/src/services/standard/gui/formstandardimportexport.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,53 +21,53 @@ #include -#include "ui_formstandardimportexport.h" #include "services/standard/standardfeedsimportexportmodel.h" +#include "ui_formstandardimportexport.h" namespace Ui { - class FormStandardImportExport; + class FormStandardImportExport; } class Category; class StandardServiceRoot; class FormStandardImportExport : public QDialog { - Q_OBJECT + Q_OBJECT - public: - enum ConversionType { - OPML20 = 0, - TXTUrlPerLine = 1 - }; + public: + enum ConversionType { + OPML20 = 0, + TXTUrlPerLine = 1 + }; - // Constructors. - explicit FormStandardImportExport(StandardServiceRoot* service_root, QWidget* parent = 0); - virtual ~FormStandardImportExport(); + // Constructors. + explicit FormStandardImportExport(StandardServiceRoot* service_root, QWidget* parent = 0); + virtual ~FormStandardImportExport(); - void setMode(const FeedsImportExportModel::Mode& mode); + void setMode(const FeedsImportExportModel::Mode& mode); - private slots: - void performAction(); - void selectFile(); + private slots: + void performAction(); + void selectFile(); - void onParsingStarted(); - void onParsingFinished(int count_failed, int count_succeeded, bool parsing_error); - void onParsingProgress(int completed, int total); + void onParsingStarted(); + void onParsingFinished(int count_failed, int count_succeeded, bool parsing_error); + void onParsingProgress(int completed, int total); - private: - void selectExportFile(); - void selectImportFile(); - void parseImportFile(const QString& file_name, bool fetch_metadata_online); + private: + void selectExportFile(); + void selectImportFile(); + void parseImportFile(const QString& file_name, bool fetch_metadata_online); - void exportFeeds(); - void importFeeds(); + void exportFeeds(); + void importFeeds(); - void loadCategories(const QList categories, RootItem* root_item); + void loadCategories(const QList categories, RootItem* root_item); - QScopedPointer m_ui; - ConversionType m_conversionType; - FeedsImportExportModel* m_model; - StandardServiceRoot* m_serviceRoot; + QScopedPointer m_ui; + ConversionType m_conversionType; + FeedsImportExportModel* m_model; + StandardServiceRoot* m_serviceRoot; }; #endif // FORMEXPORT_H diff --git a/src/services/standard/rdfparser.cpp b/src/services/standard/rdfparser.cpp index 1edfe0a81..6b7259a63 100755 --- a/src/services/standard/rdfparser.cpp +++ b/src/services/standard/rdfparser.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,81 +18,82 @@ #include "services/standard/rdfparser.h" +#include "miscellaneous/application.h" #include "miscellaneous/textfactory.h" #include "network-web/webfactory.h" -#include "miscellaneous/application.h" #include +RdfParser::RdfParser() {} -RdfParser::RdfParser() { -} - -RdfParser::~RdfParser() { -} +RdfParser::~RdfParser() {} QList RdfParser::parseXmlData(const QString& data) { - QList messages; - QDomDocument xml_file; - QDateTime current_time = QDateTime::currentDateTime(); - xml_file.setContent(data, true); - // Pull out all messages. - QDomNodeList messages_in_xml = xml_file.elementsByTagName(QSL("item")); + QList messages; + QDomDocument xml_file; + QDateTime current_time = QDateTime::currentDateTime(); - for (int i = 0; i < messages_in_xml.size(); i++) { - QDomNode message_item = messages_in_xml.item(i); - Message new_message; - // Deal with title and description. - QString elem_title = message_item.namedItem(QSL("title")).toElement().text().simplified(); - QString elem_description = message_item.namedItem(QSL("description")).toElement().text(); + xml_file.setContent(data, true); - // Now we obtained maximum of information for title & description. - if (elem_title.isEmpty()) { - if (elem_description.isEmpty()) { - // BOTH title and description are empty, skip this message. - continue; - } - else { - // Title is empty but description is not. - new_message.m_title = qApp->web()->escapeHtml(qApp->web()->stripTags(elem_description.simplified())); - new_message.m_contents = elem_description; - } - } - else { - // Title is really not empty, description does not matter. - new_message.m_title = qApp->web()->escapeHtml(qApp->web()->stripTags(elem_title)); - new_message.m_contents = elem_description; - } + // Pull out all messages. + QDomNodeList messages_in_xml = xml_file.elementsByTagName(QSL("item")); - // Deal with link and author. - new_message.m_url = message_item.namedItem(QSL("link")).toElement().text(); - new_message.m_author = message_item.namedItem(QSL("creator")).toElement().text(); - // Deal with creation date. - QString elem_updated = message_item.namedItem(QSL("date")).toElement().text(); + for (int i = 0; i < messages_in_xml.size(); i++) { + QDomNode message_item = messages_in_xml.item(i); + Message new_message; - if (elem_updated.isEmpty()) { - elem_updated = message_item.namedItem(QSL("dc:date")).toElement().text(); - } + // Deal with title and description. + QString elem_title = message_item.namedItem(QSL("title")).toElement().text().simplified(); + QString elem_description = message_item.namedItem(QSL("description")).toElement().text(); - // Deal with creation date. - new_message.m_created = TextFactory::parseDateTime(elem_updated); - new_message.m_createdFromFeed = !new_message.m_created.isNull(); + // Now we obtained maximum of information for title & description. + if (elem_title.isEmpty()) { + if (elem_description.isEmpty()) { + // BOTH title and description are empty, skip this message. + continue; + } + else { + // Title is empty but description is not. + new_message.m_title = qApp->web()->escapeHtml(qApp->web()->stripTags(elem_description.simplified())); + new_message.m_contents = elem_description; + } + } + else { + // Title is really not empty, description does not matter. + new_message.m_title = qApp->web()->escapeHtml(qApp->web()->stripTags(elem_title)); + new_message.m_contents = elem_description; + } - if (!new_message.m_createdFromFeed) { - // Date was NOT obtained from the feed, set current date as creation date for the message. - new_message.m_created = current_time; - } + // Deal with link and author. + new_message.m_url = message_item.namedItem(QSL("link")).toElement().text(); + new_message.m_author = message_item.namedItem(QSL("creator")).toElement().text(); - if (new_message.m_author.isNull()) { - new_message.m_author = ""; - } + // Deal with creation date. + QString elem_updated = message_item.namedItem(QSL("date")).toElement().text(); - if (new_message.m_url.isNull()) { - new_message.m_url = ""; - } + if (elem_updated.isEmpty()) { + elem_updated = message_item.namedItem(QSL("dc:date")).toElement().text(); + } - messages.append(new_message); - } + // Deal with creation date. + new_message.m_created = TextFactory::parseDateTime(elem_updated); + new_message.m_createdFromFeed = !new_message.m_created.isNull(); - return messages; + if (!new_message.m_createdFromFeed) { + // Date was NOT obtained from the feed, set current date as creation date for the message. + new_message.m_created = current_time; + } + + if (new_message.m_author.isNull()) { + new_message.m_author = ""; + } + + if (new_message.m_url.isNull()) { + new_message.m_url = ""; + } + + messages.append(new_message); + } + + return messages; } diff --git a/src/services/standard/rdfparser.h b/src/services/standard/rdfparser.h index 760d05c44..9dd3aa083 100755 --- a/src/services/standard/rdfparser.h +++ b/src/services/standard/rdfparser.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,13 +23,12 @@ #include - class RdfParser { - public: - explicit RdfParser(); - virtual ~RdfParser(); + public: + explicit RdfParser(); + virtual ~RdfParser(); - QList parseXmlData(const QString& data); + QList parseXmlData(const QString& data); }; #endif // RDFPARSER_H diff --git a/src/services/standard/rssparser.cpp b/src/services/standard/rssparser.cpp index bb3345d1a..550eabefa 100755 --- a/src/services/standard/rssparser.cpp +++ b/src/services/standard/rssparser.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,105 +18,103 @@ #include "services/standard/rssparser.h" +#include "exceptions/applicationexception.h" +#include "miscellaneous/application.h" +#include "miscellaneous/iofactory.h" #include "miscellaneous/textfactory.h" #include "network-web/webfactory.h" -#include "miscellaneous/iofactory.h" -#include "miscellaneous/application.h" -#include "exceptions/applicationexception.h" #include +RssParser::RssParser(const QString& data) : FeedParser(data) {} -RssParser::RssParser(const QString& data) : FeedParser(data) { -} - -RssParser::~RssParser() { -} +RssParser::~RssParser() {} QDomNodeList RssParser::messageElements() { - QDomNode channel_elem = m_xml.namedItem(QSL("rss")).namedItem(QSL("channel")); + QDomNode channel_elem = m_xml.namedItem(QSL("rss")).namedItem(QSL("channel")); - if (channel_elem.isNull()) { - return QDomNodeList(); - } - else { - return channel_elem.toElement().elementsByTagName(QSL("item")); - } + if (channel_elem.isNull()) { + return QDomNodeList(); + } + else { + return channel_elem.toElement().elementsByTagName(QSL("item")); + } } Message RssParser::extractMessage(const QDomElement& msg_element, QDateTime current_time) const { - Message new_message; - // Deal with titles & descriptions. - QString elem_title = msg_element.namedItem(QSL("title")).toElement().text().simplified(); - QString elem_description = msg_element.namedItem(QSL("encoded")).toElement().text(); - QString elem_enclosure = msg_element.namedItem(QSL("enclosure")).toElement().attribute(QSL("url")); - QString elem_enclosure_type = msg_element.namedItem(QSL("enclosure")).toElement().attribute(QSL("type")); + Message new_message; - if (elem_description.isEmpty()) { - elem_description = msg_element.namedItem(QSL("description")).toElement().text(); - } + // Deal with titles & descriptions. + QString elem_title = msg_element.namedItem(QSL("title")).toElement().text().simplified(); + QString elem_description = msg_element.namedItem(QSL("encoded")).toElement().text(); + QString elem_enclosure = msg_element.namedItem(QSL("enclosure")).toElement().attribute(QSL("url")); + QString elem_enclosure_type = msg_element.namedItem(QSL("enclosure")).toElement().attribute(QSL("type")); - // Now we obtained maximum of information for title & description. - if (elem_title.isEmpty()) { - if (elem_description.isEmpty()) { - // BOTH title and description are empty, skip this message. - throw new ApplicationException(QSL("Not enough data for the message.")); - } - else { - // Title is empty but description is not. - new_message.m_title = qApp->web()->stripTags(elem_description.simplified()); - new_message.m_contents = elem_description; - } - } - else { - // Title is really not empty, description does not matter. - new_message.m_title = qApp->web()->stripTags(elem_title); - new_message.m_contents = elem_description; - } + if (elem_description.isEmpty()) { + elem_description = msg_element.namedItem(QSL("description")).toElement().text(); + } - if (!elem_enclosure.isEmpty()) { - new_message.m_enclosures.append(Enclosure(elem_enclosure, elem_enclosure_type)); - qDebug("Adding enclosure '%s' for the message.", qPrintable(elem_enclosure)); - } + // Now we obtained maximum of information for title & description. + if (elem_title.isEmpty()) { + if (elem_description.isEmpty()) { + // BOTH title and description are empty, skip this message. + throw new ApplicationException(QSL("Not enough data for the message.")); + } + else { + // Title is empty but description is not. + new_message.m_title = qApp->web()->stripTags(elem_description.simplified()); + new_message.m_contents = elem_description; + } + } + else { + // Title is really not empty, description does not matter. + new_message.m_title = qApp->web()->stripTags(elem_title); + new_message.m_contents = elem_description; + } - // Deal with link and author. - new_message.m_url = msg_element.namedItem(QSL("link")).toElement().text(); + if (!elem_enclosure.isEmpty()) { + new_message.m_enclosures.append(Enclosure(elem_enclosure, elem_enclosure_type)); + qDebug("Adding enclosure '%s' for the message.", qPrintable(elem_enclosure)); + } - if (new_message.m_url.isEmpty() && !new_message.m_enclosures.isEmpty()) { - new_message.m_url = new_message.m_enclosures.first().m_url; - } + // Deal with link and author. + new_message.m_url = msg_element.namedItem(QSL("link")).toElement().text(); - if (new_message.m_url.isEmpty()) { - // Try to get "href" attribute. - new_message.m_url = msg_element.namedItem(QSL("link")).toElement().attribute(QSL("href")); - } + if (new_message.m_url.isEmpty() && !new_message.m_enclosures.isEmpty()) { + new_message.m_url = new_message.m_enclosures.first().m_url; + } - new_message.m_author = msg_element.namedItem(QSL("author")).toElement().text(); + if (new_message.m_url.isEmpty()) { + // Try to get "href" attribute. + new_message.m_url = msg_element.namedItem(QSL("link")).toElement().attribute(QSL("href")); + } - if (new_message.m_author.isEmpty()) { - new_message.m_author = msg_element.namedItem(QSL("creator")).toElement().text(); - } + new_message.m_author = msg_element.namedItem(QSL("author")).toElement().text(); - // Deal with creation date. - new_message.m_created = TextFactory::parseDateTime(msg_element.namedItem(QSL("pubDate")).toElement().text()); + if (new_message.m_author.isEmpty()) { + new_message.m_author = msg_element.namedItem(QSL("creator")).toElement().text(); + } - if (new_message.m_created.isNull()) { - new_message.m_created = TextFactory::parseDateTime(msg_element.namedItem(QSL("date")).toElement().text()); - } + // Deal with creation date. + new_message.m_created = TextFactory::parseDateTime(msg_element.namedItem(QSL("pubDate")).toElement().text()); - if (!(new_message.m_createdFromFeed = !new_message.m_created.isNull())) { - // Date was NOT obtained from the feed, - // set current date as creation date for the message. - new_message.m_created = current_time; - } + if (new_message.m_created.isNull()) { + new_message.m_created = TextFactory::parseDateTime(msg_element.namedItem(QSL("date")).toElement().text()); + } - if (new_message.m_author.isNull()) { - new_message.m_author = ""; - } + if (!(new_message.m_createdFromFeed = !new_message.m_created.isNull())) { + // Date was NOT obtained from the feed, + // set current date as creation date for the message. + new_message.m_created = current_time; + } - if (new_message.m_url.isNull()) { - new_message.m_url = ""; - } + if (new_message.m_author.isNull()) { + new_message.m_author = ""; + } - return new_message; + if (new_message.m_url.isNull()) { + new_message.m_url = ""; + } + + return new_message; } diff --git a/src/services/standard/rssparser.h b/src/services/standard/rssparser.h index ba7030ecc..df715a4ce 100755 --- a/src/services/standard/rssparser.h +++ b/src/services/standard/rssparser.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -24,15 +25,14 @@ #include - class RssParser : public FeedParser { - public: - explicit RssParser(const QString& data); - virtual ~RssParser(); + public: + explicit RssParser(const QString& data); + virtual ~RssParser(); - private: - QDomNodeList messageElements(); - Message extractMessage(const QDomElement& msg_element, QDateTime current_time) const; + private: + QDomNodeList messageElements(); + Message extractMessage(const QDomElement& msg_element, QDateTime current_time) const; }; #endif // RSSPARSER_H diff --git a/src/services/standard/standardcategory.cpp b/src/services/standard/standardcategory.cpp index f5f7a1653..758585a34 100755 --- a/src/services/standard/standardcategory.cpp +++ b/src/services/standard/standardcategory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,174 +18,175 @@ #include "services/standard/standardcategory.h" -#include "definitions/definitions.h" -#include "miscellaneous/databasequeries.h" -#include "miscellaneous/textfactory.h" -#include "miscellaneous/settings.h" -#include "miscellaneous/iconfactory.h" #include "core/feedsmodel.h" +#include "definitions/definitions.h" #include "gui/feedmessageviewer.h" #include "gui/feedsview.h" +#include "miscellaneous/databasequeries.h" +#include "miscellaneous/iconfactory.h" +#include "miscellaneous/settings.h" +#include "miscellaneous/textfactory.h" #include "services/standard/gui/formstandardcategorydetails.h" -#include "services/standard/standardserviceroot.h" #include "services/standard/standardfeed.h" +#include "services/standard/standardserviceroot.h" #include - -StandardCategory::StandardCategory(RootItem* parent_item) : Category(parent_item) { -} +StandardCategory::StandardCategory(RootItem* parent_item) : Category(parent_item) {} StandardCategory::StandardCategory(const StandardCategory& other) - : Category(nullptr) { - setId(other.id()); - setCustomId(other.customId()); - setTitle(other.title()); - setDescription(other.description()); - setIcon(other.icon()); - setCreationDate(other.creationDate()); - setChildItems(other.childItems()); - setParent(other.parent()); + : Category(nullptr) { + setId(other.id()); + setCustomId(other.customId()); + setTitle(other.title()); + setDescription(other.description()); + setIcon(other.icon()); + setCreationDate(other.creationDate()); + setChildItems(other.childItems()); + setParent(other.parent()); } StandardCategory::~StandardCategory() { - qDebug("Destroying Category instance."); + qDebug("Destroying Category instance."); } StandardServiceRoot* StandardCategory::serviceRoot() const { - return qobject_cast(getParentServiceRoot()); + return qobject_cast(getParentServiceRoot()); } QVariant StandardCategory::data(int column, int role) const { - switch (role) { - case Qt::ToolTipRole: - if (column == FDS_MODEL_TITLE_INDEX) { - //: Tooltip for standard feed. - return tr("%1 (category)" - "%2%3").arg(title(), - description().isEmpty() ? QString() : QSL("\n") + description(), - childCount() == 0 ? - tr("\nThis category does not contain any nested items.") : - QString()); - } - else { - return Category::data(column, role); - } + switch (role) { + case Qt::ToolTipRole: + if (column == FDS_MODEL_TITLE_INDEX) { + //: Tooltip for standard feed. + return tr("%1 (category)" + "%2%3").arg(title(), + description().isEmpty() ? QString() : QSL("\n") + description(), + childCount() == 0 ? + tr("\nThis category does not contain any nested items.") : + QString()); + } + else { + return Category::data(column, role); + } - default: - return Category::data(column, role); - } + default: + return Category::data(column, role); + } } Qt::ItemFlags StandardCategory::additionalFlags() const { - return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; + return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } bool StandardCategory::performDragDropChange(RootItem* target_item) { - StandardCategory* category_new = new StandardCategory(*this); - category_new->clearChildren(); - category_new->setParent(target_item); + StandardCategory* category_new = new StandardCategory(*this); - if (editItself(category_new)) { - serviceRoot()->requestItemReassignment(this, target_item); - delete category_new; - return true; - } - else { - delete category_new; - return false; - } + category_new->clearChildren(); + category_new->setParent(target_item); + + if (editItself(category_new)) { + serviceRoot()->requestItemReassignment(this, target_item); + delete category_new; + return true; + } + else { + delete category_new; + return false; + } } bool StandardCategory::editViaGui() { - QScopedPointer form_pointer(new FormStandardCategoryDetails(serviceRoot(), qApp->mainFormWidget())); - form_pointer.data()->addEditCategory(this, nullptr); - return false; + QScopedPointer form_pointer(new FormStandardCategoryDetails(serviceRoot(), qApp->mainFormWidget())); + form_pointer.data()->addEditCategory(this, nullptr); + return false; } bool StandardCategory::deleteViaGui() { - if (removeItself()) { - serviceRoot()->requestItemRemoval(this); - return true; - } - else { - return false; - } + if (removeItself()) { + serviceRoot()->requestItemRemoval(this); + return true; + } + else { + return false; + } } bool StandardCategory::markAsReadUnread(ReadStatus status) { - return serviceRoot()->markFeedsReadUnread(getSubTreeFeeds(), status); + return serviceRoot()->markFeedsReadUnread(getSubTreeFeeds(), status); } bool StandardCategory::cleanMessages(bool clean_read_only) { - return serviceRoot()->cleanFeeds(getSubTreeFeeds(), clean_read_only); + return serviceRoot()->cleanFeeds(getSubTreeFeeds(), clean_read_only); } bool StandardCategory::removeItself() { - bool children_removed = true; + bool children_removed = true; - // Remove all child items (feeds and categories) - // from the database. - foreach (RootItem* child, childItems()) { - if (child->kind() == RootItemKind::Category) { - children_removed &= static_cast(child)->removeItself(); - } - else if (child->kind() == RootItemKind::Feed) { - children_removed &= static_cast(child)->removeItself(); - } - } + // Remove all child items (feeds and categories) + // from the database. + foreach (RootItem* child, childItems()) { + if (child->kind() == RootItemKind::Category) { + children_removed &= static_cast(child)->removeItself(); + } + else if (child->kind() == RootItemKind::Feed) { + children_removed &= static_cast(child)->removeItself(); + } + } - if (children_removed) { - // Children are removed, remove this standard category too. - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - return DatabaseQueries::deleteCategory(database, id()); - } - else { - return false; - } + if (children_removed) { + // Children are removed, remove this standard category too. + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + + return DatabaseQueries::deleteCategory(database, id()); + } + else { + return false; + } } bool StandardCategory::addItself(RootItem* parent) { - // Now, add category to persistent storage. - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - int new_id = DatabaseQueries::addCategory(database, parent->id(), parent->getParentServiceRoot()->accountId(), - title(), description(), creationDate(), icon()); + // Now, add category to persistent storage. + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + int new_id = DatabaseQueries::addCategory(database, parent->id(), parent->getParentServiceRoot()->accountId(), + title(), description(), creationDate(), icon()); - if (new_id <= 0) { - return false; - } - else { - setId(new_id); - setCustomId(new_id); - return true; - } + if (new_id <= 0) { + return false; + } + else { + setId(new_id); + setCustomId(new_id); + return true; + } } bool StandardCategory::editItself(StandardCategory* new_category_data) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - StandardCategory* original_category = this; - RootItem* new_parent = new_category_data->parent(); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + StandardCategory* original_category = this; + RootItem* new_parent = new_category_data->parent(); - if (DatabaseQueries::editCategory(database, new_parent->id(), original_category->id(), - new_category_data->title(), new_category_data->description(), - new_category_data->icon())) { - // Setup new model data for the original item. - original_category->setDescription(new_category_data->description()); - original_category->setIcon(new_category_data->icon()); - original_category->setTitle(new_category_data->title()); - // Editing is done. - return true; - } - else { - return false; - } + if (DatabaseQueries::editCategory(database, new_parent->id(), original_category->id(), + new_category_data->title(), new_category_data->description(), + new_category_data->icon())) { + // Setup new model data for the original item. + original_category->setDescription(new_category_data->description()); + original_category->setIcon(new_category_data->icon()); + original_category->setTitle(new_category_data->title()); + + // Editing is done. + return true; + } + else { + return false; + } } StandardCategory::StandardCategory(const QSqlRecord& record) : Category(nullptr) { - setId(record.value(CAT_DB_ID_INDEX).toInt()); - setCustomId(id()); - setTitle(record.value(CAT_DB_TITLE_INDEX).toString()); - setDescription(record.value(CAT_DB_DESCRIPTION_INDEX).toString()); - setCreationDate(TextFactory::parseDateTime(record.value(CAT_DB_DCREATED_INDEX).value()).toLocalTime()); - setIcon(qApp->icons()->fromByteArray(record.value(CAT_DB_ICON_INDEX).toByteArray())); + setId(record.value(CAT_DB_ID_INDEX).toInt()); + setCustomId(id()); + setTitle(record.value(CAT_DB_TITLE_INDEX).toString()); + setDescription(record.value(CAT_DB_DESCRIPTION_INDEX).toString()); + setCreationDate(TextFactory::parseDateTime(record.value(CAT_DB_DCREATED_INDEX).value()).toLocalTime()); + setIcon(qApp->icons()->fromByteArray(record.value(CAT_DB_ICON_INDEX).toByteArray())); } diff --git a/src/services/standard/standardcategory.h b/src/services/standard/standardcategory.h index 310d80d1d..519dd1508 100755 --- a/src/services/standard/standardcategory.h +++ b/src/services/standard/standardcategory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,9 +21,8 @@ #include "services/abstract/category.h" -#include #include - +#include class FeedsModel; class StandardServiceRoot; @@ -31,42 +31,43 @@ class StandardServiceRoot; // NOTE: This class should be derived to create PARTICULAR category types. // NOTE: This class should not be instantiated directly. class StandardCategory : public Category { - Q_OBJECT + Q_OBJECT - public: - // Constructors and destructors - explicit StandardCategory(RootItem* parent_item = nullptr); - explicit StandardCategory(const StandardCategory& other); - explicit StandardCategory(const QSqlRecord& record); - virtual ~StandardCategory(); + public: - StandardServiceRoot* serviceRoot() const; + // Constructors and destructors + explicit StandardCategory(RootItem* parent_item = nullptr); + explicit StandardCategory(const StandardCategory& other); + explicit StandardCategory(const QSqlRecord& record); + virtual ~StandardCategory(); - // Returns the actual data representation of standard category. - QVariant data(int column, int role) const; - Qt::ItemFlags additionalFlags() const; - bool performDragDropChange(RootItem* target_item); + StandardServiceRoot* serviceRoot() const; - bool canBeEdited() const { - return true; - } + // Returns the actual data representation of standard category. + QVariant data(int column, int role) const; + Qt::ItemFlags additionalFlags() const; + bool performDragDropChange(RootItem* target_item); - bool canBeDeleted() const { - return true; - } + bool canBeEdited() const { + return true; + } - bool editViaGui(); - bool deleteViaGui(); + bool canBeDeleted() const { + return true; + } - bool markAsReadUnread(ReadStatus status); - bool cleanMessages(bool clean_read_only); + bool editViaGui(); + bool deleteViaGui(); - // Removes category and all its children from persistent - // database. - bool removeItself(); + bool markAsReadUnread(ReadStatus status); + bool cleanMessages(bool clean_read_only); - bool addItself(RootItem* parent); - bool editItself(StandardCategory* new_category_data); + // Removes category and all its children from persistent + // database. + bool removeItself(); + + bool addItself(RootItem* parent); + bool editItself(StandardCategory* new_category_data); }; #endif // FEEDSMODELCLASSICCATEGORY_H diff --git a/src/services/standard/standardfeed.cpp b/src/services/standard/standardfeed.cpp index 7b8c781dc..63e8120d4 100755 --- a/src/services/standard/standardfeed.cpp +++ b/src/services/standard/standardfeed.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,460 +18,469 @@ #include "services/standard/standardfeed.h" -#include "definitions/definitions.h" -#include "services/standard/rssparser.h" -#include "services/standard/rdfparser.h" -#include "services/standard/atomparser.h" #include "core/feedsmodel.h" -#include "miscellaneous/databasequeries.h" -#include "miscellaneous/textfactory.h" -#include "miscellaneous/settings.h" -#include "miscellaneous/iconfactory.h" -#include "miscellaneous/simplecrypt/simplecrypt.h" -#include "network-web/networkfactory.h" +#include "definitions/definitions.h" #include "gui/feedmessageviewer.h" #include "gui/feedsview.h" +#include "miscellaneous/databasequeries.h" +#include "miscellaneous/iconfactory.h" +#include "miscellaneous/settings.h" +#include "miscellaneous/simplecrypt/simplecrypt.h" +#include "miscellaneous/textfactory.h" +#include "network-web/networkfactory.h" #include "services/abstract/recyclebin.h" +#include "services/standard/atomparser.h" #include "services/standard/gui/formstandardfeeddetails.h" +#include "services/standard/rdfparser.h" +#include "services/standard/rssparser.h" #include "services/standard/standardserviceroot.h" -#include -#include -#include #include -#include #include +#include +#include +#include +#include #include - StandardFeed::StandardFeed(RootItem* parent_item) - : Feed(parent_item) { - m_passwordProtected = false; - m_username = QString(); - m_password = QString(); - m_networkError = QNetworkReply::NoError; - m_type = Rss0X; - m_encoding = QString(); + : Feed(parent_item) { + m_passwordProtected = false; + m_username = QString(); + m_password = QString(); + m_networkError = QNetworkReply::NoError; + m_type = Rss0X; + m_encoding = QString(); } StandardFeed::StandardFeed(const StandardFeed& other) - : Feed(nullptr) { - m_passwordProtected = other.passwordProtected(); - m_username = other.username(); - m_password = other.password(); - m_networkError = other.networkError(); - m_type = other.type(); - m_encoding = other.encoding(); - setCountOfAllMessages(other.countOfAllMessages()); - setCountOfUnreadMessages(other.countOfUnreadMessages()); - setUrl(other.url()); - setStatus(other.status()); - setAutoUpdateType(other.autoUpdateType()); - setAutoUpdateInitialInterval(other.autoUpdateInitialInterval()); - setAutoUpdateRemainingInterval(other.autoUpdateRemainingInterval()); - setTitle(other.title()); - setId(other.id()); - setCustomId(other.customId()); - setIcon(other.icon()); - setChildItems(other.childItems()); - setParent(other.parent()); - setCreationDate(other.creationDate()); - setDescription(other.description()); + : Feed(nullptr) { + m_passwordProtected = other.passwordProtected(); + m_username = other.username(); + m_password = other.password(); + m_networkError = other.networkError(); + m_type = other.type(); + m_encoding = other.encoding(); + setCountOfAllMessages(other.countOfAllMessages()); + setCountOfUnreadMessages(other.countOfUnreadMessages()); + setUrl(other.url()); + setStatus(other.status()); + setAutoUpdateType(other.autoUpdateType()); + setAutoUpdateInitialInterval(other.autoUpdateInitialInterval()); + setAutoUpdateRemainingInterval(other.autoUpdateRemainingInterval()); + setTitle(other.title()); + setId(other.id()); + setCustomId(other.customId()); + setIcon(other.icon()); + setChildItems(other.childItems()); + setParent(other.parent()); + setCreationDate(other.creationDate()); + setDescription(other.description()); } StandardFeed::~StandardFeed() { - qDebug("Destroying Feed instance."); + qDebug("Destroying Feed instance."); } QList StandardFeed::contextMenu() { - return serviceRoot()->getContextMenuForFeed(this); + return serviceRoot()->getContextMenuForFeed(this); } StandardServiceRoot* StandardFeed::serviceRoot() const { - return qobject_cast(getParentServiceRoot()); + return qobject_cast(getParentServiceRoot()); } bool StandardFeed::editViaGui() { - QScopedPointer form_pointer(new FormStandardFeedDetails(serviceRoot(), qApp->mainFormWidget())); - form_pointer.data()->addEditFeed(this, nullptr); - return false; + QScopedPointer form_pointer(new FormStandardFeedDetails(serviceRoot(), qApp->mainFormWidget())); + form_pointer.data()->addEditFeed(this, nullptr); + return false; } bool StandardFeed::deleteViaGui() { - if (removeItself()) { - serviceRoot()->requestItemRemoval(this); - return true; - } - else { - return false; - } + if (removeItself()) { + serviceRoot()->requestItemRemoval(this); + return true; + } + else { + return false; + } } bool StandardFeed::markAsReadUnread(ReadStatus status) { - return serviceRoot()->markFeedsReadUnread(QList() << this, status); + return serviceRoot()->markFeedsReadUnread(QList() << this, status); } bool StandardFeed::cleanMessages(bool clean_read_only) { - return serviceRoot()->cleanFeeds(QList() << this, clean_read_only); + return serviceRoot()->cleanFeeds(QList() << this, clean_read_only); } QVariant StandardFeed::data(int column, int role) const { - switch (role) { - case Qt::ToolTipRole: - if (column == FDS_MODEL_TITLE_INDEX) { - //: Tooltip for feed. - return tr("%1 (%2)" - "%3\n\n" - "Network status: %6\n" - "Encoding: %4\n" - "Auto-update status: %5").arg(title(), - StandardFeed::typeToString(type()), - description().isEmpty() ? QString() : QString('\n') + description(), - encoding(), - getAutoUpdateStatusDescription(), - NetworkFactory::networkErrorText(m_networkError)); - } - else { - return QVariant(); - } + switch (role) { + case Qt::ToolTipRole: + if (column == FDS_MODEL_TITLE_INDEX) { + //: Tooltip for feed. + return tr("%1 (%2)" + "%3\n\n" + "Network status: %6\n" + "Encoding: %4\n" + "Auto-update status: %5").arg(title(), + StandardFeed::typeToString(type()), + description().isEmpty() ? QString() : QString('\n') + description(), + encoding(), + getAutoUpdateStatusDescription(), + NetworkFactory::networkErrorText(m_networkError)); + } + else { + return QVariant(); + } - default: - return Feed::data(column, role); - } + default: + return Feed::data(column, role); + } } QString StandardFeed::typeToString(StandardFeed::Type type) { - switch (type) { - case Atom10: - return QSL("ATOM 1.0"); + switch (type) { + case Atom10: + return QSL("ATOM 1.0"); - case Rdf: - return QSL("RDF (RSS 1.0)"); + case Rdf: + return QSL("RDF (RSS 1.0)"); - case Rss0X: - return QSL("RSS 0.91/0.92/0.93"); + case Rss0X: + return QSL("RSS 0.91/0.92/0.93"); - case Rss2X: - default: - return QSL("RSS 2.0/2.0.1"); - } + case Rss2X: + default: + return QSL("RSS 2.0/2.0.1"); + } } void StandardFeed::fetchMetadataForItself() { - QPair metadata = guessFeed(url(), username(), password()); + QPair metadata = guessFeed(url(), username(), password()); - if (metadata.first != nullptr && metadata.second == QNetworkReply::NoError) { - // Some properties are not updated when new metadata are fetched. - metadata.first->setParent(parent()); - metadata.first->setUrl(url()); - metadata.first->setPasswordProtected(passwordProtected()); - metadata.first->setUsername(username()); - metadata.first->setPassword(password()); - metadata.first->setAutoUpdateType(autoUpdateType()); - metadata.first->setAutoUpdateInitialInterval(autoUpdateInitialInterval()); - editItself(metadata.first); - delete metadata.first; - // Notify the model about fact, that it needs to reload new information about - // this item, particularly the icon. - serviceRoot()->itemChanged(QList() << this); - } - else { - qApp->showGuiMessage(tr("Metadata not fetched"), - tr("Metadata was not fetched because: %1.").arg(NetworkFactory::networkErrorText(metadata.second)), - QSystemTrayIcon::Critical); - } + if (metadata.first != nullptr && metadata.second == QNetworkReply::NoError) { + // Some properties are not updated when new metadata are fetched. + metadata.first->setParent(parent()); + metadata.first->setUrl(url()); + metadata.first->setPasswordProtected(passwordProtected()); + metadata.first->setUsername(username()); + metadata.first->setPassword(password()); + metadata.first->setAutoUpdateType(autoUpdateType()); + metadata.first->setAutoUpdateInitialInterval(autoUpdateInitialInterval()); + editItself(metadata.first); + delete metadata.first; + + // Notify the model about fact, that it needs to reload new information about + // this item, particularly the icon. + serviceRoot()->itemChanged(QList() << this); + } + else { + qApp->showGuiMessage(tr("Metadata not fetched"), + tr("Metadata was not fetched because: %1.").arg(NetworkFactory::networkErrorText(metadata.second)), + QSystemTrayIcon::Critical); + } } QPair StandardFeed::guessFeed(const QString& url, - const QString& username, - const QString& password) { - QPair result; - result.first = nullptr; - QByteArray feed_contents; - NetworkResult network_result = NetworkFactory::downloadFeedFile(url, - qApp->settings()->value(GROUP(Feeds), - SETTING(Feeds::UpdateTimeout)).toInt(), - feed_contents, - !username.isEmpty(), - username, - password); - result.second = network_result.first; + const QString& username, + const QString& password) { + QPair result; + result.first = nullptr; + QByteArray feed_contents; + NetworkResult network_result = NetworkFactory::downloadFeedFile(url, + qApp->settings()->value(GROUP(Feeds), + SETTING(Feeds::UpdateTimeout)).toInt(), + feed_contents, + !username.isEmpty(), + username, + password); - if (result.second == QNetworkReply::NoError || !feed_contents.isEmpty()) { - // Feed XML was obtained, now we need to try to guess - // its encoding before we can read further data. - QString xml_schema_encoding; - QString xml_contents_encoded; - QRegExp encoding_rexp(QSL("encoding=\"[^\"]\\S+\"")); + result.second = network_result.first; - if (encoding_rexp.indexIn(feed_contents) != -1 && - !(xml_schema_encoding = encoding_rexp.cap(0)).isEmpty()) { - // Some "encoding" attribute was found get the encoding - // out of it. - encoding_rexp.setPattern(QSL("[^\"]\\S+[^\"]")); - encoding_rexp.indexIn(xml_schema_encoding, 9); - xml_schema_encoding = encoding_rexp.cap(0); - } + if (result.second == QNetworkReply::NoError || !feed_contents.isEmpty()) { + // Feed XML was obtained, now we need to try to guess + // its encoding before we can read further data. + QString xml_schema_encoding; + QString xml_contents_encoded; + QRegExp encoding_rexp(QSL("encoding=\"[^\"]\\S+\"")); - if (result.first == nullptr) { - result.first = new StandardFeed(); - } + if (encoding_rexp.indexIn(feed_contents) != -1 && + !(xml_schema_encoding = encoding_rexp.cap(0)).isEmpty()) { + // Some "encoding" attribute was found get the encoding + // out of it. + encoding_rexp.setPattern(QSL("[^\"]\\S+[^\"]")); + encoding_rexp.indexIn(xml_schema_encoding, 9); + xml_schema_encoding = encoding_rexp.cap(0); + } - QTextCodec* custom_codec = QTextCodec::codecForName(xml_schema_encoding.toLocal8Bit()); + if (result.first == nullptr) { + result.first = new StandardFeed(); + } - if (custom_codec != nullptr) { - // Feed encoding was probably guessed. - xml_contents_encoded = custom_codec->toUnicode(feed_contents); - result.first->setEncoding(xml_schema_encoding); - } - else { - // Feed encoding probably not guessed, set it as - // default. - xml_contents_encoded = feed_contents; - result.first->setEncoding(DEFAULT_FEED_ENCODING); - } + QTextCodec* custom_codec = QTextCodec::codecForName(xml_schema_encoding.toLocal8Bit()); - // Feed XML was obtained, guess it now. - QDomDocument xml_document; - QString error_msg; - int error_line, error_column; + if (custom_codec != nullptr) { + // Feed encoding was probably guessed. + xml_contents_encoded = custom_codec->toUnicode(feed_contents); + result.first->setEncoding(xml_schema_encoding); + } + else { + // Feed encoding probably not guessed, set it as + // default. + xml_contents_encoded = feed_contents; + result.first->setEncoding(DEFAULT_FEED_ENCODING); + } - if (!xml_document.setContent(xml_contents_encoded, - &error_msg, - &error_line, - &error_column)) { - qDebug("XML of feed '%s' is not valid and cannot be loaded. Error: '%s' " - "(line %d, column %d).", - qPrintable(url), - qPrintable(error_msg), - error_line, error_column); - result.second = QNetworkReply::UnknownContentError; - // XML is invalid, exit. - return result; - } + // Feed XML was obtained, guess it now. + QDomDocument xml_document; + QString error_msg; + int error_line, error_column; - QDomElement root_element = xml_document.documentElement(); - QString root_tag_name = root_element.tagName(); - QList icon_possible_locations; - icon_possible_locations.append(url); + if (!xml_document.setContent(xml_contents_encoded, + &error_msg, + &error_line, + &error_column)) { + qDebug("XML of feed '%s' is not valid and cannot be loaded. Error: '%s' " + "(line %d, column %d).", + qPrintable(url), + qPrintable(error_msg), + error_line, error_column); + result.second = QNetworkReply::UnknownContentError; - if (root_tag_name == QL1S("rdf:RDF")) { - // We found RDF feed. - QDomElement channel_element = root_element.namedItem(QSL("channel")).toElement(); - result.first->setType(Rdf); - result.first->setTitle(channel_element.namedItem(QSL("title")).toElement().text()); - result.first->setDescription(channel_element.namedItem(QSL("description")).toElement().text()); - QString source_link = channel_element.namedItem(QSL("link")).toElement().text(); + // XML is invalid, exit. + return result; + } - if (!source_link.isEmpty()) { - icon_possible_locations.prepend(source_link); - } - } - else if (root_tag_name == QL1S("rss")) { - // We found RSS 0.91/0.92/0.93/2.0/2.0.1 feed. - QString rss_type = root_element.attribute("version", "2.0"); + QDomElement root_element = xml_document.documentElement(); + QString root_tag_name = root_element.tagName(); - if (rss_type == QL1S("0.91") || rss_type == QL1S("0.92") || rss_type == QL1S("0.93")) { - result.first->setType(Rss0X); - } - else { - result.first->setType(Rss2X); - } + QList icon_possible_locations; + icon_possible_locations.append(url); - QDomElement channel_element = root_element.namedItem(QSL("channel")).toElement(); - result.first->setTitle(channel_element.namedItem(QSL("title")).toElement().text()); - result.first->setDescription(channel_element.namedItem(QSL("description")).toElement().text()); - QString source_link = channel_element.namedItem(QSL("link")).toElement().text(); + if (root_tag_name == QL1S("rdf:RDF")) { + // We found RDF feed. + QDomElement channel_element = root_element.namedItem(QSL("channel")).toElement(); - if (!source_link.isEmpty()) { - icon_possible_locations.prepend(source_link); - } - } - else if (root_tag_name == QL1S("feed")) { - // We found ATOM feed. - result.first->setType(Atom10); - result.first->setTitle(root_element.namedItem(QSL("title")).toElement().text()); - result.first->setDescription(root_element.namedItem(QSL("subtitle")).toElement().text()); - QString source_link = root_element.namedItem(QSL("link")).toElement().text(); + result.first->setType(Rdf); + result.first->setTitle(channel_element.namedItem(QSL("title")).toElement().text()); + result.first->setDescription(channel_element.namedItem(QSL("description")).toElement().text()); + QString source_link = channel_element.namedItem(QSL("link")).toElement().text(); - if (!source_link.isEmpty()) { - icon_possible_locations.prepend(source_link); - } - } - else { - // File was downloaded and it really was XML file - // but feed format was NOT recognized. - result.second = QNetworkReply::UnknownContentError; - } + if (!source_link.isEmpty()) { + icon_possible_locations.prepend(source_link); + } + } + else if (root_tag_name == QL1S("rss")) { + // We found RSS 0.91/0.92/0.93/2.0/2.0.1 feed. + QString rss_type = root_element.attribute("version", "2.0"); - // Try to obtain icon. - QIcon icon_data; + if (rss_type == QL1S("0.91") || rss_type == QL1S("0.92") || rss_type == QL1S("0.93")) { + result.first->setType(Rss0X); + } + else { + result.first->setType(Rss2X); + } - if ((result.second = NetworkFactory::downloadIcon(icon_possible_locations, - DOWNLOAD_TIMEOUT, - icon_data)) == QNetworkReply::NoError) { - // Icon for feed was downloaded and is stored now in _icon_data. - result.first->setIcon(icon_data); - } - } + QDomElement channel_element = root_element.namedItem(QSL("channel")).toElement(); - return result; + result.first->setTitle(channel_element.namedItem(QSL("title")).toElement().text()); + result.first->setDescription(channel_element.namedItem(QSL("description")).toElement().text()); + QString source_link = channel_element.namedItem(QSL("link")).toElement().text(); + + if (!source_link.isEmpty()) { + icon_possible_locations.prepend(source_link); + } + } + else if (root_tag_name == QL1S("feed")) { + // We found ATOM feed. + result.first->setType(Atom10); + result.first->setTitle(root_element.namedItem(QSL("title")).toElement().text()); + result.first->setDescription(root_element.namedItem(QSL("subtitle")).toElement().text()); + QString source_link = root_element.namedItem(QSL("link")).toElement().text(); + + if (!source_link.isEmpty()) { + icon_possible_locations.prepend(source_link); + } + } + else { + // File was downloaded and it really was XML file + // but feed format was NOT recognized. + result.second = QNetworkReply::UnknownContentError; + } + + // Try to obtain icon. + QIcon icon_data; + + if ((result.second = NetworkFactory::downloadIcon(icon_possible_locations, + DOWNLOAD_TIMEOUT, + icon_data)) == QNetworkReply::NoError) { + // Icon for feed was downloaded and is stored now in _icon_data. + result.first->setIcon(icon_data); + } + } + + return result; } Qt::ItemFlags StandardFeed::additionalFlags() const { - return Qt::ItemIsDragEnabled; + return Qt::ItemIsDragEnabled; } bool StandardFeed::performDragDropChange(RootItem* target_item) { - StandardFeed* feed_new = new StandardFeed(*this); - feed_new->setParent(target_item); + StandardFeed* feed_new = new StandardFeed(*this); - if (editItself(feed_new)) { - serviceRoot()->requestItemReassignment(this, target_item); - delete feed_new; - return true; - } - else { - delete feed_new; - return false; - } + feed_new->setParent(target_item); + + if (editItself(feed_new)) { + serviceRoot()->requestItemReassignment(this, target_item); + delete feed_new; + return true; + } + else { + delete feed_new; + return false; + } } bool StandardFeed::removeItself() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - return DatabaseQueries::deleteFeed(database, customId(), getParentServiceRoot()->accountId()); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + + return DatabaseQueries::deleteFeed(database, customId(), getParentServiceRoot()->accountId()); } bool StandardFeed::addItself(RootItem* parent) { - // Now, add feed to persistent storage. - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - bool ok; - int new_id = DatabaseQueries::addFeed(database, parent->id(), parent->getParentServiceRoot()->accountId(), title(), - description(), creationDate(), icon(), encoding(), url(), passwordProtected(), - username(), password(), autoUpdateType(), autoUpdateInitialInterval(), type(), &ok); + // Now, add feed to persistent storage. + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + bool ok; + int new_id = DatabaseQueries::addFeed(database, parent->id(), parent->getParentServiceRoot()->accountId(), title(), + description(), creationDate(), icon(), encoding(), url(), passwordProtected(), + username(), password(), autoUpdateType(), autoUpdateInitialInterval(), type(), &ok); - if (!ok) { - // Query failed. - return false; - } - else { - // New feed was added, fetch is primary id from the database. - setId(new_id); - setCustomId(new_id); - return true; - } + if (!ok) { + // Query failed. + return false; + } + else { + // New feed was added, fetch is primary id from the database. + setId(new_id); + setCustomId(new_id); + return true; + } } bool StandardFeed::editItself(StandardFeed* new_feed_data) { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - StandardFeed* original_feed = this; - RootItem* new_parent = new_feed_data->parent(); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + StandardFeed* original_feed = this; + RootItem* new_parent = new_feed_data->parent(); - if (!DatabaseQueries::editFeed(database, new_parent->id(), original_feed->id(), new_feed_data->title(), - new_feed_data->description(), new_feed_data->icon(), - new_feed_data->encoding(), new_feed_data->url(), new_feed_data->passwordProtected(), - new_feed_data->username(), new_feed_data->password(), - new_feed_data->autoUpdateType(), new_feed_data->autoUpdateInitialInterval(), - new_feed_data->type())) { - // Persistent storage update failed, no way to continue now. - return false; - } + if (!DatabaseQueries::editFeed(database, new_parent->id(), original_feed->id(), new_feed_data->title(), + new_feed_data->description(), new_feed_data->icon(), + new_feed_data->encoding(), new_feed_data->url(), new_feed_data->passwordProtected(), + new_feed_data->username(), new_feed_data->password(), + new_feed_data->autoUpdateType(), new_feed_data->autoUpdateInitialInterval(), + new_feed_data->type())) { + // Persistent storage update failed, no way to continue now. + return false; + } - // Setup new model data for the original item. - original_feed->setTitle(new_feed_data->title()); - original_feed->setDescription(new_feed_data->description()); - original_feed->setIcon(new_feed_data->icon()); - original_feed->setEncoding(new_feed_data->encoding()); - original_feed->setDescription(new_feed_data->description()); - original_feed->setUrl(new_feed_data->url()); - original_feed->setPasswordProtected(new_feed_data->passwordProtected()); - original_feed->setUsername(new_feed_data->username()); - original_feed->setPassword(new_feed_data->password()); - original_feed->setAutoUpdateType(new_feed_data->autoUpdateType()); - original_feed->setAutoUpdateInitialInterval(new_feed_data->autoUpdateInitialInterval()); - original_feed->setType(new_feed_data->type()); - // Editing is done. - return true; + // Setup new model data for the original item. + original_feed->setTitle(new_feed_data->title()); + original_feed->setDescription(new_feed_data->description()); + original_feed->setIcon(new_feed_data->icon()); + original_feed->setEncoding(new_feed_data->encoding()); + original_feed->setDescription(new_feed_data->description()); + original_feed->setUrl(new_feed_data->url()); + original_feed->setPasswordProtected(new_feed_data->passwordProtected()); + original_feed->setUsername(new_feed_data->username()); + original_feed->setPassword(new_feed_data->password()); + original_feed->setAutoUpdateType(new_feed_data->autoUpdateType()); + original_feed->setAutoUpdateInitialInterval(new_feed_data->autoUpdateInitialInterval()); + original_feed->setType(new_feed_data->type()); + + // Editing is done. + return true; } QList StandardFeed::obtainNewMessages(bool* error_during_obtaining) { - QByteArray feed_contents; - int download_timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); - m_networkError = NetworkFactory::downloadFeedFile(url(), download_timeout, feed_contents, - passwordProtected(), username(), password()).first; + QByteArray feed_contents; + int download_timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); - if (m_networkError != QNetworkReply::NoError) { - qWarning("Error during fetching of new messages for feed '%s' (id %d).", qPrintable(url()), id()); - setStatus(NetworkError); - *error_during_obtaining = true; - return QList(); - } - else if (status() != NewMessages) { - setStatus(Normal); - *error_during_obtaining = false; - } + m_networkError = NetworkFactory::downloadFeedFile(url(), download_timeout, feed_contents, + passwordProtected(), username(), password()).first; - // Encode downloaded data for further parsing. - QTextCodec* codec = QTextCodec::codecForName(encoding().toLocal8Bit()); - QString formatted_feed_contents; + if (m_networkError != QNetworkReply::NoError) { + qWarning("Error during fetching of new messages for feed '%s' (id %d).", qPrintable(url()), id()); + setStatus(NetworkError); + *error_during_obtaining = true; + return QList(); + } + else if (status() != NewMessages) { + setStatus(Normal); + *error_during_obtaining = false; + } - if (codec == nullptr) { - // No suitable codec for this encoding was found. - // Use non-converted data. - formatted_feed_contents = feed_contents; - } - else { - formatted_feed_contents = codec->toUnicode(feed_contents); - } + // Encode downloaded data for further parsing. + QTextCodec* codec = QTextCodec::codecForName(encoding().toLocal8Bit()); + QString formatted_feed_contents; - // Feed data are downloaded and encoded. - // Parse data and obtain messages. - QList messages; + if (codec == nullptr) { + // No suitable codec for this encoding was found. + // Use non-converted data. + formatted_feed_contents = feed_contents; + } + else { + formatted_feed_contents = codec->toUnicode(feed_contents); + } - switch (type()) { - case StandardFeed::Rss0X: - case StandardFeed::Rss2X: - messages = RssParser(formatted_feed_contents).messages(); - break; + // Feed data are downloaded and encoded. + // Parse data and obtain messages. + QList messages; - case StandardFeed::Rdf: - messages = RdfParser().parseXmlData(formatted_feed_contents); - break; + switch (type()) { + case StandardFeed::Rss0X: + case StandardFeed::Rss2X: + messages = RssParser(formatted_feed_contents).messages(); + break; - case StandardFeed::Atom10: - messages = AtomParser(formatted_feed_contents).messages(); + case StandardFeed::Rdf: + messages = RdfParser().parseXmlData(formatted_feed_contents); + break; - default: - break; - } + case StandardFeed::Atom10: + messages = AtomParser(formatted_feed_contents).messages(); - return messages; + default: + break; + } + + return messages; } QNetworkReply::NetworkError StandardFeed::networkError() const { - return m_networkError; + return m_networkError; } StandardFeed::StandardFeed(const QSqlRecord& record) : Feed(nullptr) { - setTitle(QString::fromUtf8(record.value(FDS_DB_TITLE_INDEX).toByteArray())); - setId(record.value(FDS_DB_ID_INDEX).toInt()); - setCustomId(id()); - setDescription(QString::fromUtf8(record.value(FDS_DB_DESCRIPTION_INDEX).toByteArray())); - setCreationDate(TextFactory::parseDateTime(record.value(FDS_DB_DCREATED_INDEX).value()).toLocalTime()); - setIcon(qApp->icons()->fromByteArray(record.value(FDS_DB_ICON_INDEX).toByteArray())); - setEncoding(record.value(FDS_DB_ENCODING_INDEX).toString()); - setUrl(record.value(FDS_DB_URL_INDEX).toString()); - setPasswordProtected(record.value(FDS_DB_PROTECTED_INDEX).toBool()); - setUsername(record.value(FDS_DB_USERNAME_INDEX).toString()); + setTitle(QString::fromUtf8(record.value(FDS_DB_TITLE_INDEX).toByteArray())); + setId(record.value(FDS_DB_ID_INDEX).toInt()); + setCustomId(id()); + setDescription(QString::fromUtf8(record.value(FDS_DB_DESCRIPTION_INDEX).toByteArray())); + setCreationDate(TextFactory::parseDateTime(record.value(FDS_DB_DCREATED_INDEX).value()).toLocalTime()); + setIcon(qApp->icons()->fromByteArray(record.value(FDS_DB_ICON_INDEX).toByteArray())); + setEncoding(record.value(FDS_DB_ENCODING_INDEX).toString()); + setUrl(record.value(FDS_DB_URL_INDEX).toString()); + setPasswordProtected(record.value(FDS_DB_PROTECTED_INDEX).toBool()); + setUsername(record.value(FDS_DB_USERNAME_INDEX).toString()); - if (record.value(FDS_DB_PASSWORD_INDEX).toString().isEmpty()) { - setPassword(record.value(FDS_DB_PASSWORD_INDEX).toString()); - } - else { - setPassword(TextFactory::decrypt(record.value(FDS_DB_PASSWORD_INDEX).toString())); - } + if (record.value(FDS_DB_PASSWORD_INDEX).toString().isEmpty()) { + setPassword(record.value(FDS_DB_PASSWORD_INDEX).toString()); + } + else { + setPassword(TextFactory::decrypt(record.value(FDS_DB_PASSWORD_INDEX).toString())); + } - setAutoUpdateType(static_cast(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt())); - setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt()); - m_networkError = QNetworkReply::NoError; + setAutoUpdateType(static_cast(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt())); + setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt()); + m_networkError = QNetworkReply::NoError; } diff --git a/src/services/standard/standardfeed.h b/src/services/standard/standardfeed.h index 6f4c36a22..be9d610dd 100755 --- a/src/services/standard/standardfeed.h +++ b/src/services/standard/standardfeed.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,13 +21,12 @@ #include "services/abstract/feed.h" -#include -#include -#include -#include -#include #include - +#include +#include +#include +#include +#include class Message; class FeedsModel; @@ -35,123 +35,126 @@ class StandardServiceRoot; // Represents BASE class for feeds contained in FeedsModel. // NOTE: This class should be derived to create PARTICULAR feed types. class StandardFeed : public Feed { - Q_OBJECT + Q_OBJECT - public: - // Describes possible types of feeds. - // NOTE: This is equivalent to attribute Feeds(type). - enum Type { - Rss0X = 0, - Rss2X = 1, - Rdf = 2, // Sometimes denoted as RSS 1.0. - Atom10 = 3 - }; + public: - // Constructors and destructors. - explicit StandardFeed(RootItem* parent_item = nullptr); - explicit StandardFeed(const StandardFeed& other); - explicit StandardFeed(const QSqlRecord& record); - virtual ~StandardFeed(); + // Describes possible types of feeds. + // NOTE: This is equivalent to attribute Feeds(type). + enum Type { + Rss0X = 0, + Rss2X = 1, + Rdf = 2, // Sometimes denoted as RSS 1.0. + Atom10 = 3 + }; - StandardServiceRoot* serviceRoot() const; - QList contextMenu(); + // Constructors and destructors. + explicit StandardFeed(RootItem* parent_item = nullptr); + explicit StandardFeed(const StandardFeed& other); + explicit StandardFeed(const QSqlRecord& record); + virtual ~StandardFeed(); - bool canBeEdited() const { - return true; - } + StandardServiceRoot* serviceRoot() const; - bool canBeDeleted() const { - return true; - } + QList contextMenu(); - bool editViaGui(); - bool deleteViaGui(); + bool canBeEdited() const { + return true; + } - bool markAsReadUnread(ReadStatus status); - bool cleanMessages(bool clean_read_only); + bool canBeDeleted() const { + return true; + } - QVariant data(int column, int role) const; + bool editViaGui(); + bool deleteViaGui(); - // Obtains data related to this feed. - Qt::ItemFlags additionalFlags() const; - bool performDragDropChange(RootItem* target_item); + bool markAsReadUnread(ReadStatus status); + bool cleanMessages(bool clean_read_only); - // Removes this standard feed from persistent - // storage. - bool removeItself(); - bool addItself(RootItem* parent); - bool editItself(StandardFeed* new_feed_data); + QVariant data(int column, int role) const; - // Other getters/setters. - inline Type type() const { - return m_type; - } + // Obtains data related to this feed. + Qt::ItemFlags additionalFlags() const; + bool performDragDropChange(RootItem* target_item); - inline void setType(Type type) { - m_type = type; - } + // Removes this standard feed from persistent + // storage. + bool removeItself(); + bool addItself(RootItem* parent); + bool editItself(StandardFeed* new_feed_data); - inline bool passwordProtected() const { - return m_passwordProtected; - } + // Other getters/setters. + inline Type type() const { + return m_type; + } - inline void setPasswordProtected(bool passwordProtected) { - m_passwordProtected = passwordProtected; - } + inline void setType(Type type) { + m_type = type; + } - inline QString username() const { - return m_username; - } + inline bool passwordProtected() const { + return m_passwordProtected; + } - inline void setUsername(const QString& username) { - m_username = username; - } + inline void setPasswordProtected(bool passwordProtected) { + m_passwordProtected = passwordProtected; + } - inline QString password() const { - return m_password; - } + inline QString username() const { + return m_username; + } - inline void setPassword(const QString& password) { - m_password = password; - } + inline void setUsername(const QString& username) { + m_username = username; + } - inline QString encoding() const { - return m_encoding; - } + inline QString password() const { + return m_password; + } - inline void setEncoding(const QString& encoding) { - m_encoding = encoding; - } + inline void setPassword(const QString& password) { + m_password = password; + } - QNetworkReply::NetworkError networkError() const; + inline QString encoding() const { + return m_encoding; + } - // Tries to guess feed hidden under given URL - // and uses given credentials. - // Returns pointer to guessed feed (if at least partially - // guessed) and retrieved error/status code from network layer - // or NULL feed. - static QPair guessFeed(const QString& url, - const QString& username = QString(), - const QString& password = QString()); + inline void setEncoding(const QString& encoding) { + m_encoding = encoding; + } - // Converts particular feed type to string. - static QString typeToString(Type type); + QNetworkReply::NetworkError networkError() const; - public slots: - // Fetches metadata for the feed. - void fetchMetadataForItself(); + // Tries to guess feed hidden under given URL + // and uses given credentials. + // Returns pointer to guessed feed (if at least partially + // guessed) and retrieved error/status code from network layer + // or NULL feed. + static QPair guessFeed(const QString& url, + const QString& username = QString(), + const QString& password = QString()); - private: - QList obtainNewMessages(bool* error_during_obtaining); + // Converts particular feed type to string. + static QString typeToString(Type type); - private: - bool m_passwordProtected; - QString m_username; - QString m_password; + public slots: - Type m_type; - QNetworkReply::NetworkError m_networkError; - QString m_encoding; + // Fetches metadata for the feed. + void fetchMetadataForItself(); + + private: + QList obtainNewMessages(bool* error_during_obtaining); + + private: + bool m_passwordProtected; + QString m_username; + QString m_password; + Type m_type; + + QNetworkReply::NetworkError m_networkError; + QString m_encoding; }; Q_DECLARE_METATYPE(StandardFeed::Type) diff --git a/src/services/standard/standardfeedsimportexportmodel.cpp b/src/services/standard/standardfeedsimportexportmodel.cpp index a3a86d127..d69463900 100755 --- a/src/services/standard/standardfeedsimportexportmodel.cpp +++ b/src/services/standard/standardfeedsimportexportmodel.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,315 +18,332 @@ #include "services/standard/standardfeedsimportexportmodel.h" -#include "services/standard/standardfeed.h" -#include "services/standard/standardcategory.h" -#include "services/standard/standardserviceroot.h" #include "definitions/definitions.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" +#include "services/standard/standardcategory.h" +#include "services/standard/standardfeed.h" +#include "services/standard/standardserviceroot.h" +#include #include #include -#include -#include #include - +#include FeedsImportExportModel::FeedsImportExportModel(QObject* parent) - : AccountCheckModel(parent), m_mode(Import) { -} + : AccountCheckModel(parent), m_mode(Import) {} FeedsImportExportModel::~FeedsImportExportModel() { - if (m_rootItem != nullptr && m_mode == Import) { - // Delete all model items, but only if we are in import mode. Export mode shares - // root item with main feed model, thus cannot be deleted from memory now. - delete m_rootItem; - } + if (m_rootItem != nullptr && m_mode == Import) { + // Delete all model items, but only if we are in import mode. Export mode shares + // root item with main feed model, thus cannot be deleted from memory now. + delete m_rootItem; + } } bool FeedsImportExportModel::exportToOMPL20(QByteArray& result) { - QDomDocument opml_document; - QDomProcessingInstruction xml_declaration = opml_document.createProcessingInstruction(QSL("xml"), - QSL("version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"")); - opml_document.appendChild(xml_declaration); - // Added OPML 2.0 metadata. - opml_document.appendChild(opml_document.createElement(QSL("opml"))); - opml_document.documentElement().setAttribute(QSL("version"), QSL("version")); - opml_document.documentElement().setAttribute("xmlns:rssguard", APP_URL); - QDomElement elem_opml_head = opml_document.createElement(QSL("head")); - QDomElement elem_opml_title = opml_document.createElement(QSL("title")); - QDomText text_opml_title = opml_document.createTextNode(QString(APP_NAME)); - elem_opml_title.appendChild(text_opml_title); - elem_opml_head.appendChild(elem_opml_title); - QDomElement elem_opml_created = opml_document.createElement(QSL("dateCreated")); - QDomText text_opml_created = opml_document.createTextNode(QLocale::c().toString(QDateTime::currentDateTimeUtc(), - QSL("ddd, dd MMM yyyy hh:mm:ss")) + QL1S(" GMT")); - elem_opml_created.appendChild(text_opml_created); - elem_opml_head.appendChild(elem_opml_created); - opml_document.documentElement().appendChild(elem_opml_head); - QDomElement elem_opml_body = opml_document.createElement(QSL("body")); - QStack items_to_process; - items_to_process.push(m_rootItem); - QStack elements_to_use; - elements_to_use.push(elem_opml_body); + QDomDocument opml_document; + QDomProcessingInstruction xml_declaration = opml_document.createProcessingInstruction(QSL("xml"), + QSL( + "version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"")); - // Process all unprocessed nodes. - while (!items_to_process.isEmpty()) { - QDomElement active_element = elements_to_use.pop(); - RootItem* active_item = items_to_process.pop(); + opml_document.appendChild(xml_declaration); - foreach (RootItem* child_item, active_item->childItems()) { - if (!isItemChecked(child_item)) { - continue; - } + // Added OPML 2.0 metadata. + opml_document.appendChild(opml_document.createElement(QSL("opml"))); + opml_document.documentElement().setAttribute(QSL("version"), QSL("version")); + opml_document.documentElement().setAttribute("xmlns:rssguard", APP_URL); + QDomElement elem_opml_head = opml_document.createElement(QSL("head")); + QDomElement elem_opml_title = opml_document.createElement(QSL("title")); + QDomText text_opml_title = opml_document.createTextNode(QString(APP_NAME)); - switch (child_item->kind()) { - case RootItemKind::Category: { - QDomElement outline_category = opml_document.createElement(QSL("outline")); - outline_category.setAttribute(QSL("text"), child_item->title()); - outline_category.setAttribute(QSL("description"), child_item->description()); - outline_category.setAttribute(QSL("rssguard:icon"), QString(qApp->icons()->toByteArray(child_item->icon()))); - active_element.appendChild(outline_category); - items_to_process.push(child_item); - elements_to_use.push(outline_category); - break; - } + elem_opml_title.appendChild(text_opml_title); + elem_opml_head.appendChild(elem_opml_title); + QDomElement elem_opml_created = opml_document.createElement(QSL("dateCreated")); + QDomText text_opml_created = opml_document.createTextNode(QLocale::c().toString(QDateTime::currentDateTimeUtc(), + QSL("ddd, dd MMM yyyy hh:mm:ss")) + QL1S(" GMT")); - case RootItemKind::Feed: { - StandardFeed* child_feed = static_cast(child_item); - QDomElement outline_feed = opml_document.createElement("outline"); - outline_feed.setAttribute(QSL("text"), child_feed->title()); - outline_feed.setAttribute(QSL("xmlUrl"), child_feed->url()); - outline_feed.setAttribute(QSL("description"), child_feed->description()); - outline_feed.setAttribute(QSL("encoding"), child_feed->encoding()); - outline_feed.setAttribute(QSL("title"), child_feed->title()); - outline_feed.setAttribute(QSL("rssguard:icon"), QString(qApp->icons()->toByteArray(child_feed->icon()))); + elem_opml_created.appendChild(text_opml_created); + elem_opml_head.appendChild(elem_opml_created); + opml_document.documentElement().appendChild(elem_opml_head); + QDomElement elem_opml_body = opml_document.createElement(QSL("body")); - switch (child_feed->type()) { - case StandardFeed::Rss0X: - case StandardFeed::Rss2X: - outline_feed.setAttribute(QSL("version"), QSL("RSS")); - break; + QStack items_to_process; + items_to_process.push(m_rootItem); + QStack elements_to_use; + elements_to_use.push(elem_opml_body); - case StandardFeed::Rdf: - outline_feed.setAttribute(QSL("version"), QSL("RSS1")); - break; + // Process all unprocessed nodes. + while (!items_to_process.isEmpty()) { + QDomElement active_element = elements_to_use.pop(); + RootItem* active_item = items_to_process.pop(); - case StandardFeed::Atom10: - outline_feed.setAttribute(QSL("version"), QSL("ATOM")); - break; + foreach (RootItem* child_item, active_item->childItems()) { + if (!isItemChecked(child_item)) { + continue; + } - default: - break; - } + switch (child_item->kind()) { + case RootItemKind::Category: { + QDomElement outline_category = opml_document.createElement(QSL("outline")); - active_element.appendChild(outline_feed); - break; - } + outline_category.setAttribute(QSL("text"), child_item->title()); + outline_category.setAttribute(QSL("description"), child_item->description()); + outline_category.setAttribute(QSL("rssguard:icon"), QString(qApp->icons()->toByteArray(child_item->icon()))); + active_element.appendChild(outline_category); + items_to_process.push(child_item); + elements_to_use.push(outline_category); + break; + } - default: - break; - } - } - } + case RootItemKind::Feed: { + StandardFeed* child_feed = static_cast(child_item); + QDomElement outline_feed = opml_document.createElement("outline"); - opml_document.documentElement().appendChild(elem_opml_body); - result = opml_document.toByteArray(2); - return true; + outline_feed.setAttribute(QSL("text"), child_feed->title()); + outline_feed.setAttribute(QSL("xmlUrl"), child_feed->url()); + outline_feed.setAttribute(QSL("description"), child_feed->description()); + outline_feed.setAttribute(QSL("encoding"), child_feed->encoding()); + outline_feed.setAttribute(QSL("title"), child_feed->title()); + outline_feed.setAttribute(QSL("rssguard:icon"), QString(qApp->icons()->toByteArray(child_feed->icon()))); + + switch (child_feed->type()) { + case StandardFeed::Rss0X: + case StandardFeed::Rss2X: + outline_feed.setAttribute(QSL("version"), QSL("RSS")); + break; + + case StandardFeed::Rdf: + outline_feed.setAttribute(QSL("version"), QSL("RSS1")); + break; + + case StandardFeed::Atom10: + outline_feed.setAttribute(QSL("version"), QSL("ATOM")); + break; + + default: + break; + } + + active_element.appendChild(outline_feed); + break; + } + + default: + break; + } + } + } + + opml_document.documentElement().appendChild(elem_opml_body); + result = opml_document.toByteArray(2); + return true; } void FeedsImportExportModel::importAsOPML20(const QByteArray& data, bool fetch_metadata_online) { - emit parsingStarted(); - emit layoutAboutToBeChanged(); - setRootItem(nullptr); - emit layoutChanged(); - QDomDocument opml_document; + emit parsingStarted(); + emit layoutAboutToBeChanged(); - if (!opml_document.setContent(data)) { - emit parsingFinished(0, 0, true); - } + setRootItem(nullptr); + emit layoutChanged(); + QDomDocument opml_document; - if (opml_document.documentElement().isNull() || opml_document.documentElement().tagName() != QSL("opml") || - opml_document.documentElement().elementsByTagName(QSL("body")).size() != 1) { - // This really is not an OPML file. - emit parsingFinished(0, 0, true); - } + if (!opml_document.setContent(data)) { + emit parsingFinished(0, 0, true); + } - int completed = 0, total = 0, succeded = 0, failed = 0; - StandardServiceRoot* root_item = new StandardServiceRoot(); - QStack model_items; - model_items.push(root_item); - QStack elements_to_process; - elements_to_process.push(opml_document.documentElement().elementsByTagName(QSL("body")).at(0).toElement()); + if (opml_document.documentElement().isNull() || opml_document.documentElement().tagName() != QSL("opml") || + opml_document.documentElement().elementsByTagName(QSL("body")).size() != 1) { + // This really is not an OPML file. + emit parsingFinished(0, 0, true); + } - while (!elements_to_process.isEmpty()) { - RootItem* active_model_item = model_items.pop(); - QDomElement active_element = elements_to_process.pop(); - int current_count = active_element.childNodes().size(); - total += current_count; + int completed = 0, total = 0, succeded = 0, failed = 0; + StandardServiceRoot* root_item = new StandardServiceRoot(); - for (int i = 0; i < current_count; i++) { - QDomNode child = active_element.childNodes().at(i); + QStack model_items; + model_items.push(root_item); + QStack elements_to_process; + elements_to_process.push(opml_document.documentElement().elementsByTagName(QSL("body")).at(0).toElement()); - if (child.isElement()) { - QDomElement child_element = child.toElement(); + while (!elements_to_process.isEmpty()) { + RootItem* active_model_item = model_items.pop(); + QDomElement active_element = elements_to_process.pop(); + int current_count = active_element.childNodes().size(); - // Now analyze if this element is category or feed. - // NOTE: All feeds must include xmlUrl attribute and text attribute. - if (child_element.attributes().contains(QSL("xmlUrl")) && child.attributes().contains(QSL("text"))) { - // This is FEED. - // Add feed and end this iteration. - QString feed_url = child_element.attribute(QSL("xmlUrl")); + total += current_count; - if (!feed_url.isEmpty()) { - QPair guessed; + for (int i = 0; i < current_count; i++) { + QDomNode child = active_element.childNodes().at(i); - if (fetch_metadata_online && - (guessed = StandardFeed::guessFeed(feed_url)).second == QNetworkReply::NoError) { - // We should obtain fresh metadata from online feed source. - guessed.first->setUrl(feed_url); - active_model_item->appendChild(guessed.first); - succeded++; - } - else { - QString feed_title = child_element.attribute(QSL("text")); - QString feed_encoding = child_element.attribute(QSL("encoding"), DEFAULT_FEED_ENCODING); - QString feed_type = child_element.attribute(QSL("version"), DEFAULT_FEED_TYPE).toUpper(); - QString feed_description = child_element.attribute(QSL("description")); - QIcon feed_icon = qApp->icons()->fromByteArray(child_element.attribute(QSL("rssguard:icon")).toLocal8Bit()); - StandardFeed* new_feed = new StandardFeed(active_model_item); - new_feed->setTitle(feed_title); - new_feed->setDescription(feed_description); - new_feed->setEncoding(feed_encoding); - new_feed->setUrl(feed_url); - new_feed->setCreationDate(QDateTime::currentDateTime()); - new_feed->setIcon(feed_icon.isNull() ? qApp->icons()->fromTheme(QSL("application-rss+xml")) : feed_icon); + if (child.isElement()) { + QDomElement child_element = child.toElement(); - if (feed_type == QL1S("RSS1")) { - new_feed->setType(StandardFeed::Rdf); - } - else if (feed_type == QL1S("ATOM")) { - new_feed->setType(StandardFeed::Atom10); - } - else { - new_feed->setType(StandardFeed::Rss2X); - } + // Now analyze if this element is category or feed. + // NOTE: All feeds must include xmlUrl attribute and text attribute. + if (child_element.attributes().contains(QSL("xmlUrl")) && child.attributes().contains(QSL("text"))) { + // This is FEED. + // Add feed and end this iteration. + QString feed_url = child_element.attribute(QSL("xmlUrl")); - active_model_item->appendChild(new_feed); + if (!feed_url.isEmpty()) { + QPair guessed; - if (fetch_metadata_online && guessed.second != QNetworkReply::NoError) { - failed++; - } - else { - succeded++; - } - } - } - } - else { - // This must be CATEGORY. - // Add category and continue. - QString category_title = child_element.attribute(QSL("text")); - QString category_description = child_element.attribute(QSL("description")); - QIcon category_icon = qApp->icons()->fromByteArray(child_element.attribute(QSL("rssguard:icon")).toLocal8Bit()); + if (fetch_metadata_online && + (guessed = StandardFeed::guessFeed(feed_url)).second == QNetworkReply::NoError) { + // We should obtain fresh metadata from online feed source. + guessed.first->setUrl(feed_url); + active_model_item->appendChild(guessed.first); + succeded++; + } + else { + QString feed_title = child_element.attribute(QSL("text")); + QString feed_encoding = child_element.attribute(QSL("encoding"), DEFAULT_FEED_ENCODING); + QString feed_type = child_element.attribute(QSL("version"), DEFAULT_FEED_TYPE).toUpper(); + QString feed_description = child_element.attribute(QSL("description")); + QIcon feed_icon = qApp->icons()->fromByteArray(child_element.attribute(QSL("rssguard:icon")).toLocal8Bit()); + StandardFeed* new_feed = new StandardFeed(active_model_item); - if (category_title.isEmpty()) { - qWarning("Given OMPL file provided category without valid text attribute. Using fallback name."); - category_title = child_element.attribute(QSL("title")); + new_feed->setTitle(feed_title); + new_feed->setDescription(feed_description); + new_feed->setEncoding(feed_encoding); + new_feed->setUrl(feed_url); + new_feed->setCreationDate(QDateTime::currentDateTime()); + new_feed->setIcon(feed_icon.isNull() ? qApp->icons()->fromTheme(QSL("application-rss+xml")) : feed_icon); - if (category_title.isEmpty()) { - category_title = tr("Category ") + QString::number(QDateTime::currentDateTime().toMSecsSinceEpoch()); - } - } + if (feed_type == QL1S("RSS1")) { + new_feed->setType(StandardFeed::Rdf); + } + else if (feed_type == QL1S("ATOM")) { + new_feed->setType(StandardFeed::Atom10); + } + else { + new_feed->setType(StandardFeed::Rss2X); + } - StandardCategory* new_category = new StandardCategory(active_model_item); - new_category->setTitle(category_title); - new_category->setIcon(category_icon.isNull() ? qApp->icons()->fromTheme(QSL("folder")) : category_icon); - new_category->setCreationDate(QDateTime::currentDateTime()); - new_category->setDescription(category_description); - active_model_item->appendChild(new_category); - // Children of this node must be processed later. - elements_to_process.push(child_element); - model_items.push(new_category); - } + active_model_item->appendChild(new_feed); - emit parsingProgress(++completed, total); - } - } - } + if (fetch_metadata_online && guessed.second != QNetworkReply::NoError) { + failed++; + } + else { + succeded++; + } + } + } + } + else { + // This must be CATEGORY. + // Add category and continue. + QString category_title = child_element.attribute(QSL("text")); + QString category_description = child_element.attribute(QSL("description")); + QIcon category_icon = qApp->icons()->fromByteArray(child_element.attribute(QSL("rssguard:icon")).toLocal8Bit()); - // Now, XML is processed and we have result in form of pointer item structure. - emit layoutAboutToBeChanged(); - setRootItem(root_item); - emit layoutChanged(); - emit parsingFinished(failed, succeded, false); + if (category_title.isEmpty()) { + qWarning("Given OMPL file provided category without valid text attribute. Using fallback name."); + category_title = child_element.attribute(QSL("title")); + + if (category_title.isEmpty()) { + category_title = tr("Category ") + QString::number(QDateTime::currentDateTime().toMSecsSinceEpoch()); + } + } + + StandardCategory* new_category = new StandardCategory(active_model_item); + + new_category->setTitle(category_title); + new_category->setIcon(category_icon.isNull() ? qApp->icons()->fromTheme(QSL("folder")) : category_icon); + new_category->setCreationDate(QDateTime::currentDateTime()); + new_category->setDescription(category_description); + active_model_item->appendChild(new_category); + + // Children of this node must be processed later. + elements_to_process.push(child_element); + model_items.push(new_category); + } + + emit parsingProgress(++completed, total); + } + } + } + + // Now, XML is processed and we have result in form of pointer item structure. + emit layoutAboutToBeChanged(); + + setRootItem(root_item); + emit layoutChanged(); + emit parsingFinished(failed, succeded, false); } bool FeedsImportExportModel::exportToTxtURLPerLine(QByteArray& result) { - foreach (const Feed* const feed, m_rootItem->getSubTreeFeeds()) { - result += feed->url() + QL1S("\n"); - } + foreach (const Feed* const feed, m_rootItem->getSubTreeFeeds()) { + result += feed->url() + QL1S("\n"); + } - return true; + return true; } void FeedsImportExportModel::importAsTxtURLPerLine(const QByteArray& data, bool fetch_metadata_online) { - emit parsingStarted(); - emit layoutAboutToBeChanged(); - setRootItem(nullptr); - emit layoutChanged(); - int completed = 0, succeded = 0, failed = 0; - StandardServiceRoot* root_item = new StandardServiceRoot(); - QList urls = data.split('\n'); + emit parsingStarted(); + emit layoutAboutToBeChanged(); - foreach (const QByteArray& url, urls) { - if (!url.isEmpty()) { - QPair guessed; + setRootItem(nullptr); + emit layoutChanged(); + int completed = 0, succeded = 0, failed = 0; + StandardServiceRoot* root_item = new StandardServiceRoot(); - if (fetch_metadata_online && - (guessed = StandardFeed::guessFeed(url)).second == QNetworkReply::NoError) { - guessed.first->setUrl(url); - root_item->appendChild(guessed.first); - succeded++; - } - else { - StandardFeed* feed = new StandardFeed(); - feed->setUrl(url); - feed->setTitle(url); - feed->setCreationDate(QDateTime::currentDateTime()); - feed->setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml"))); - feed->setEncoding(DEFAULT_FEED_ENCODING); - root_item->appendChild(feed); + QList urls = data.split('\n'); - if (fetch_metadata_online && guessed.second != QNetworkReply::NoError) { - failed++; - } - else { - succeded++; - } - } + foreach (const QByteArray& url, urls) { + if (!url.isEmpty()) { + QPair guessed; - qApp->processEvents(); - } - else { - qWarning("Detected empty URL when parsing input TXT [one URL per line] data."); - failed++; - } + if (fetch_metadata_online && + (guessed = StandardFeed::guessFeed(url)).second == QNetworkReply::NoError) { + guessed.first->setUrl(url); + root_item->appendChild(guessed.first); + succeded++; + } + else { + StandardFeed* feed = new StandardFeed(); - emit parsingProgress(++completed, urls.size()); - } + feed->setUrl(url); + feed->setTitle(url); + feed->setCreationDate(QDateTime::currentDateTime()); + feed->setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml"))); + feed->setEncoding(DEFAULT_FEED_ENCODING); + root_item->appendChild(feed); - // Now, XML is processed and we have result in form of pointer item structure. - emit layoutAboutToBeChanged(); - setRootItem(root_item); - emit layoutChanged(); - emit parsingFinished(failed, succeded, false); + if (fetch_metadata_online && guessed.second != QNetworkReply::NoError) { + failed++; + } + else { + succeded++; + } + } + + qApp->processEvents(); + } + else { + qWarning("Detected empty URL when parsing input TXT [one URL per line] data."); + failed++; + } + + emit parsingProgress(++completed, urls.size()); + } + + // Now, XML is processed and we have result in form of pointer item structure. + emit layoutAboutToBeChanged(); + + setRootItem(root_item); + emit layoutChanged(); + emit parsingFinished(failed, succeded, false); } FeedsImportExportModel::Mode FeedsImportExportModel::mode() const { - return m_mode; + return m_mode; } void FeedsImportExportModel::setMode(const FeedsImportExportModel::Mode& mode) { - m_mode = mode; + m_mode = mode; } diff --git a/src/services/standard/standardfeedsimportexportmodel.h b/src/services/standard/standardfeedsimportexportmodel.h index bb440d9ca..5d6c0c93b 100755 --- a/src/services/standard/standardfeedsimportexportmodel.h +++ b/src/services/standard/standardfeedsimportexportmodel.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,42 +21,42 @@ #include "services/abstract/accountcheckmodel.h" - class FeedsImportExportModel : public AccountCheckModel { - Q_OBJECT + Q_OBJECT - public: - enum Mode { - Import, - Export - }; + public: + enum Mode { + Import, + Export + }; - // Constructors and destructors. - explicit FeedsImportExportModel(QObject* parent = 0); - virtual ~FeedsImportExportModel(); + // Constructors and destructors. + explicit FeedsImportExportModel(QObject* parent = 0); + virtual ~FeedsImportExportModel(); - // Exports to OPML 2.0 - // NOTE: http://dev.opml.org/spec2.html - bool exportToOMPL20(QByteArray& result); - void importAsOPML20(const QByteArray& data, bool fetch_metadata_online); + // Exports to OPML 2.0 + // NOTE: http://dev.opml.org/spec2.html + bool exportToOMPL20(QByteArray& result); + void importAsOPML20(const QByteArray& data, bool fetch_metadata_online); - // Exports to plain text format - // where there is one feed URL per line. - bool exportToTxtURLPerLine(QByteArray& result); - void importAsTxtURLPerLine(const QByteArray& data, bool fetch_metadata_online); + // Exports to plain text format + // where there is one feed URL per line. + bool exportToTxtURLPerLine(QByteArray& result); + void importAsTxtURLPerLine(const QByteArray& data, bool fetch_metadata_online); - Mode mode() const; - void setMode(const Mode& mode); + Mode mode() const; + void setMode(const Mode& mode); - signals: - // These signals are emitted when user selects some data - // to be imported/parsed into the model. - void parsingStarted(); - void parsingProgress(int completed, int total); - void parsingFinished(int count_failed, int count_succeeded, bool parsing_error); + signals: - private: - Mode m_mode; + // These signals are emitted when user selects some data + // to be imported/parsed into the model. + void parsingStarted(); + void parsingProgress(int completed, int total); + void parsingFinished(int count_failed, int count_succeeded, bool parsing_error); + + private: + Mode m_mode; }; #endif // STANDARDFEEDSIMPORTEXPORTMODEL_H diff --git a/src/services/standard/standardserviceentrypoint.cpp b/src/services/standard/standardserviceentrypoint.cpp index 82cb9e928..7fc047439 100755 --- a/src/services/standard/standardserviceentrypoint.cpp +++ b/src/services/standard/standardserviceentrypoint.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -15,7 +16,6 @@ // You should have received a copy of the GNU General Public License // along with RSS Guard. If not, see . - #include "services/standard/standardserviceentrypoint.h" #include "definitions/definitions.h" @@ -23,59 +23,58 @@ #include "miscellaneous/databasequeries.h" #include "services/standard/standardserviceroot.h" +StandardServiceEntryPoint::StandardServiceEntryPoint() {} -StandardServiceEntryPoint::StandardServiceEntryPoint() { -} - -StandardServiceEntryPoint::~StandardServiceEntryPoint() { -} +StandardServiceEntryPoint::~StandardServiceEntryPoint() {} bool StandardServiceEntryPoint::isSingleInstanceService() const { - return true; + return true; } QString StandardServiceEntryPoint::name() const { - return QObject::tr("Standard online feeds (RSS/RDF/ATOM)"); + return QObject::tr("Standard online feeds (RSS/RDF/ATOM)"); } QString StandardServiceEntryPoint::description() const { - return QObject::tr("This service offers integration with standard online RSS/RDF/ATOM feeds and podcasts."); + return QObject::tr("This service offers integration with standard online RSS/RDF/ATOM feeds and podcasts."); } QString StandardServiceEntryPoint::version() const { - return APP_VERSION; + return APP_VERSION; } QString StandardServiceEntryPoint::author() const { - return APP_AUTHOR; + return APP_AUTHOR; } QIcon StandardServiceEntryPoint::icon() const { - return QIcon(APP_ICON_PATH); + return QIcon(APP_ICON_PATH); } QString StandardServiceEntryPoint::code() const { - return SERVICE_CODE_STD_RSS; + return SERVICE_CODE_STD_RSS; } ServiceRoot* StandardServiceEntryPoint::createNewRoot() const { - // Switch DB. - QSqlDatabase database = qApp->database()->connection(QSL("StandardServiceEntryPoint"), DatabaseFactory::FromSettings); - bool ok; - int new_id = DatabaseQueries::createAccount(database, code(), &ok); + // Switch DB. + QSqlDatabase database = qApp->database()->connection(QSL("StandardServiceEntryPoint"), DatabaseFactory::FromSettings); + bool ok; + int new_id = DatabaseQueries::createAccount(database, code(), &ok); - if (ok) { - StandardServiceRoot* root = new StandardServiceRoot(); - root->setAccountId(new_id); - return root; - } - else { - return nullptr; - } + if (ok) { + StandardServiceRoot* root = new StandardServiceRoot(); + + root->setAccountId(new_id); + return root; + } + else { + return nullptr; + } } QList StandardServiceEntryPoint::initializeSubtree() const { - // Check DB if standard account is enabled. - QSqlDatabase database = qApp->database()->connection(QSL("StandardServiceEntryPoint"), DatabaseFactory::FromSettings); - return DatabaseQueries::getAccounts(database); + // Check DB if standard account is enabled. + QSqlDatabase database = qApp->database()->connection(QSL("StandardServiceEntryPoint"), DatabaseFactory::FromSettings); + + return DatabaseQueries::getAccounts(database); } diff --git a/src/services/standard/standardserviceentrypoint.h b/src/services/standard/standardserviceentrypoint.h index 172cd2c02..dfcceb6ed 100755 --- a/src/services/standard/standardserviceentrypoint.h +++ b/src/services/standard/standardserviceentrypoint.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,22 +21,22 @@ #include "services/abstract/serviceentrypoint.h" - class StandardServiceEntryPoint : public ServiceEntryPoint { - public: - explicit StandardServiceEntryPoint(); - virtual ~StandardServiceEntryPoint(); + public: + explicit StandardServiceEntryPoint(); + virtual ~StandardServiceEntryPoint(); - bool isSingleInstanceService() const; - QString name() const; - QString description() const; - QString version() const; - QString author() const; - QIcon icon() const; - QString code() const; + bool isSingleInstanceService() const; + QString name() const; + QString description() const; + QString version() const; + QString author() const; + QIcon icon() const; + QString code() const; - ServiceRoot* createNewRoot() const; - QList initializeSubtree() const; + ServiceRoot* createNewRoot() const; + + QList initializeSubtree() const; }; #endif // STANDARDSERVICEENTRYPOINT_H diff --git a/src/services/standard/standardserviceroot.cpp b/src/services/standard/standardserviceroot.cpp index 323fa0cab..ff3cfe13d 100755 --- a/src/services/standard/standardserviceroot.cpp +++ b/src/services/standard/standardserviceroot.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,334 +18,341 @@ #include "services/standard/standardserviceroot.h" -#include "definitions/definitions.h" -#include "miscellaneous/application.h" -#include "miscellaneous/settings.h" -#include "miscellaneous/iconfactory.h" -#include "miscellaneous/databasequeries.h" -#include "miscellaneous/mutex.h" #include "core/feedsmodel.h" -#include "gui/messagebox.h" +#include "definitions/definitions.h" #include "exceptions/applicationexception.h" -#include "services/abstract/recyclebin.h" +#include "gui/messagebox.h" +#include "miscellaneous/application.h" +#include "miscellaneous/databasequeries.h" +#include "miscellaneous/iconfactory.h" +#include "miscellaneous/mutex.h" +#include "miscellaneous/settings.h" #include "services/abstract/labelsrootitem.h" -#include "services/standard/standardserviceentrypoint.h" -#include "services/standard/standardfeed.h" -#include "services/standard/standardcategory.h" -#include "services/standard/standardfeedsimportexportmodel.h" +#include "services/abstract/recyclebin.h" #include "services/standard/gui/formstandardcategorydetails.h" #include "services/standard/gui/formstandardfeeddetails.h" #include "services/standard/gui/formstandardimportexport.h" +#include "services/standard/standardcategory.h" +#include "services/standard/standardfeed.h" +#include "services/standard/standardfeedsimportexportmodel.h" +#include "services/standard/standardserviceentrypoint.h" -#include #include -#include #include - +#include +#include StandardServiceRoot::StandardServiceRoot(RootItem* parent) - : ServiceRoot(parent), m_recycleBin(new RecycleBin(this)), - m_actionExportFeeds(nullptr), m_actionImportFeeds(nullptr), m_serviceMenu(QList()), - m_feedContextMenu(QList()), m_actionFeedFetchMetadata(nullptr) { - setTitle(qApp->system()->loggedInUser() + QL1S("@") + QL1S(APP_LOW_NAME)); - setIcon(StandardServiceEntryPoint().icon()); - setDescription(tr("This is obligatory service account for standard RSS/RDF/ATOM feeds.")); + : ServiceRoot(parent), m_recycleBin(new RecycleBin(this)), + m_actionExportFeeds(nullptr), m_actionImportFeeds(nullptr), m_serviceMenu(QList()), + m_feedContextMenu(QList()), m_actionFeedFetchMetadata(nullptr) { + setTitle(qApp->system()->loggedInUser() + QL1S("@") + QL1S(APP_LOW_NAME)); + setIcon(StandardServiceEntryPoint().icon()); + setDescription(tr("This is obligatory service account for standard RSS/RDF/ATOM feeds.")); } StandardServiceRoot::~StandardServiceRoot() { - qDeleteAll(m_serviceMenu); - qDeleteAll(m_feedContextMenu); + qDeleteAll(m_serviceMenu); + qDeleteAll(m_feedContextMenu); } void StandardServiceRoot::start(bool freshly_activated) { - loadFromDatabase(); + loadFromDatabase(); - if (freshly_activated && getSubTree(RootItemKind::Feed).isEmpty()) { - // In other words, if there are no feeds or categories added. - if (MessageBox::show(qApp->mainFormWidget(), QMessageBox::Question, QObject::tr("Load initial set of feeds"), - tr("This new account does not include any feeds. You can now add default set of feeds."), - tr("Do you want to load initial set of feeds?"), - QString(), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - QString target_opml_file = APP_INITIAL_FEEDS_PATH + QDir::separator() + FEED_INITIAL_OPML_PATTERN; - QString current_locale = qApp->localization()->loadedLanguage(); - QString file_to_load; + if (freshly_activated && getSubTree(RootItemKind::Feed).isEmpty()) { + // In other words, if there are no feeds or categories added. + if (MessageBox::show(qApp->mainFormWidget(), QMessageBox::Question, QObject::tr("Load initial set of feeds"), + tr("This new account does not include any feeds. You can now add default set of feeds."), + tr("Do you want to load initial set of feeds?"), + QString(), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + QString target_opml_file = APP_INITIAL_FEEDS_PATH + QDir::separator() + FEED_INITIAL_OPML_PATTERN; + QString current_locale = qApp->localization()->loadedLanguage(); + QString file_to_load; - if (QFile::exists(target_opml_file.arg(current_locale))) { - file_to_load = target_opml_file.arg(current_locale); - } - else if (QFile::exists(target_opml_file.arg(DEFAULT_LOCALE))) { - file_to_load = target_opml_file.arg(DEFAULT_LOCALE); - } + if (QFile::exists(target_opml_file.arg(current_locale))) { + file_to_load = target_opml_file.arg(current_locale); + } + else if (QFile::exists(target_opml_file.arg(DEFAULT_LOCALE))) { + file_to_load = target_opml_file.arg(DEFAULT_LOCALE); + } - FeedsImportExportModel model; - QString output_msg; + FeedsImportExportModel model; + QString output_msg; - try { - model.importAsOPML20(IOFactory::readTextFile(file_to_load), false); - model.checkAllItems(); + try { + model.importAsOPML20(IOFactory::readTextFile(file_to_load), false); + model.checkAllItems(); - if (mergeImportExportModel(&model, this, output_msg)) { - requestItemExpand(getSubTree(), true); - } - } - catch (ApplicationException& ex) { - MessageBox::show(qApp->mainFormWidget(), QMessageBox::Critical, tr("Error when loading initial feeds"), ex.message()); - } - } - } + if (mergeImportExportModel(&model, this, output_msg)) { + requestItemExpand(getSubTree(), true); + } + } + catch (ApplicationException& ex) { + MessageBox::show(qApp->mainFormWidget(), QMessageBox::Critical, tr("Error when loading initial feeds"), ex.message()); + } + } + } - checkArgumentsForFeedAdding(); + checkArgumentsForFeedAdding(); } void StandardServiceRoot::stop() { - qDebug("Stopping StandardServiceRoot instance."); + qDebug("Stopping StandardServiceRoot instance."); } QString StandardServiceRoot::code() const { - return StandardServiceEntryPoint().code(); + return StandardServiceEntryPoint().code(); } bool StandardServiceRoot::canBeEdited() const { - return false; + return false; } bool StandardServiceRoot::canBeDeleted() const { - return true; + return true; } bool StandardServiceRoot::deleteViaGui() { - return ServiceRoot::deleteViaGui(); + return ServiceRoot::deleteViaGui(); } bool StandardServiceRoot::supportsFeedAdding() const { - return true; + return true; } bool StandardServiceRoot::supportsCategoryAdding() const { - return true; + return true; } void StandardServiceRoot::addNewFeed(const QString& url) { - if (!qApp->feedUpdateLock()->tryLock()) { - // Lock was not obtained because - // it is used probably by feed updater or application - // is quitting. - qApp->showGuiMessage(tr("Cannot add item"), - tr("Cannot add feed because another critical operation is ongoing."), - QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - // Thus, cannot delete and quit the method. - return; - } + if (!qApp->feedUpdateLock()->tryLock()) { + // Lock was not obtained because + // it is used probably by feed updater or application + // is quitting. + qApp->showGuiMessage(tr("Cannot add item"), + tr("Cannot add feed because another critical operation is ongoing."), + QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - QScopedPointer form_pointer(new FormStandardFeedDetails(this, qApp->mainFormWidget())); - form_pointer.data()->addEditFeed(nullptr, nullptr, url); - qApp->feedUpdateLock()->unlock(); + // Thus, cannot delete and quit the method. + return; + } + + QScopedPointer form_pointer(new FormStandardFeedDetails(this, qApp->mainFormWidget())); + form_pointer.data()->addEditFeed(nullptr, nullptr, url); + qApp->feedUpdateLock()->unlock(); } QVariant StandardServiceRoot::data(int column, int role) const { - switch (role) { - case Qt::ToolTipRole: - if (column == FDS_MODEL_TITLE_INDEX) { - return tr("This is service account for standard RSS/RDF/ATOM feeds.\n\nAccount ID: %1").arg(accountId()); - } - else { - return ServiceRoot::data(column, role); - } + switch (role) { + case Qt::ToolTipRole: + if (column == FDS_MODEL_TITLE_INDEX) { + return tr("This is service account for standard RSS/RDF/ATOM feeds.\n\nAccount ID: %1").arg(accountId()); + } + else { + return ServiceRoot::data(column, role); + } - default: - return ServiceRoot::data(column, role); - } + default: + return ServiceRoot::data(column, role); + } } Qt::ItemFlags StandardServiceRoot::additionalFlags() const { - return Qt::ItemIsDropEnabled; + return Qt::ItemIsDropEnabled; } RecycleBin* StandardServiceRoot::recycleBin() const { - return m_recycleBin; + return m_recycleBin; } void StandardServiceRoot::loadFromDatabase() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - Assignment categories = DatabaseQueries::getCategories(database, accountId()); - Assignment feeds = DatabaseQueries::getFeeds(database, accountId()); - // All data are now obtained, lets create the hierarchy. - assembleCategories(categories); - assembleFeeds(feeds); - // As the last item, add recycle bin, which is needed. - appendChild(recycleBin()); - //appendChild(new LabelsRootItem(this)); - updateCounts(true); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + Assignment categories = DatabaseQueries::getCategories(database, accountId()); + Assignment feeds = DatabaseQueries::getFeeds(database, accountId()); + + // All data are now obtained, lets create the hierarchy. + assembleCategories(categories); + assembleFeeds(feeds); + + // As the last item, add recycle bin, which is needed. + appendChild(recycleBin()); + + //appendChild(new LabelsRootItem(this)); + updateCounts(true); } void StandardServiceRoot::checkArgumentsForFeedAdding() { - foreach (const QString& arg, qApp->arguments().mid(1)) { - checkArgumentForFeedAdding(arg); - } + foreach (const QString& arg, qApp->arguments().mid(1)) { + checkArgumentForFeedAdding(arg); + } } QMap StandardServiceRoot::storeCustomFeedsData() { - return QMap(); + return QMap(); } void StandardServiceRoot::restoreCustomFeedsData(const QMap& data, const QHash& feeds) { - Q_UNUSED(feeds) - Q_UNUSED(data) + Q_UNUSED(feeds) + Q_UNUSED(data) } QString StandardServiceRoot::processFeedUrl(const QString& feed_url) { - if (feed_url.startsWith(QL1S(URI_SCHEME_FEED_SHORT))) { - QString without_feed_prefix = feed_url.mid(5); + if (feed_url.startsWith(QL1S(URI_SCHEME_FEED_SHORT))) { + QString without_feed_prefix = feed_url.mid(5); - if (without_feed_prefix.startsWith(QL1S("https:")) || without_feed_prefix.startsWith(QL1S("http:"))) { - return without_feed_prefix; - } - else { - return feed_url; - } - } - else { - return feed_url; - } + if (without_feed_prefix.startsWith(QL1S("https:")) || without_feed_prefix.startsWith(QL1S("http:"))) { + return without_feed_prefix; + } + else { + return feed_url; + } + } + else { + return feed_url; + } } void StandardServiceRoot::checkArgumentForFeedAdding(const QString& argument) { - if (argument.startsWith(QL1S(URI_SCHEME_FEED_SHORT))) { - addNewFeed(processFeedUrl(argument)); - } + if (argument.startsWith(QL1S(URI_SCHEME_FEED_SHORT))) { + addNewFeed(processFeedUrl(argument)); + } } QList StandardServiceRoot::getContextMenuForFeed(StandardFeed* feed) { - if (m_feedContextMenu.isEmpty()) { - // Initialize. - m_actionFeedFetchMetadata = new QAction(qApp->icons()->fromTheme(QSL("emblem-downloads")), tr("Fetch metadata"), nullptr); - m_feedContextMenu.append(m_actionFeedFetchMetadata); - } + if (m_feedContextMenu.isEmpty()) { + // Initialize. + m_actionFeedFetchMetadata = new QAction(qApp->icons()->fromTheme(QSL("emblem-downloads")), tr("Fetch metadata"), nullptr); + m_feedContextMenu.append(m_actionFeedFetchMetadata); + } - // Make connections. - disconnect(m_actionFeedFetchMetadata, &QAction::triggered, 0, 0); - connect(m_actionFeedFetchMetadata, &QAction::triggered, feed, &StandardFeed::fetchMetadataForItself); - return m_feedContextMenu; + // Make connections. + disconnect(m_actionFeedFetchMetadata, &QAction::triggered, 0, 0); + connect(m_actionFeedFetchMetadata, &QAction::triggered, feed, &StandardFeed::fetchMetadataForItself); + return m_feedContextMenu; } bool StandardServiceRoot::mergeImportExportModel(FeedsImportExportModel* model, RootItem* target_root_node, QString& output_message) { - QStack original_parents; - original_parents.push(target_root_node); - QStack new_parents; - new_parents.push(model->rootItem()); - bool some_feed_category_error = false; + QStack original_parents; + original_parents.push(target_root_node); + QStack new_parents; + new_parents.push(model->rootItem()); + bool some_feed_category_error = false; - // Iterate all new items we would like to merge into current model. - while (!new_parents.isEmpty()) { - RootItem* target_parent = original_parents.pop(); - RootItem* source_parent = new_parents.pop(); + // Iterate all new items we would like to merge into current model. + while (!new_parents.isEmpty()) { + RootItem* target_parent = original_parents.pop(); + RootItem* source_parent = new_parents.pop(); - foreach (RootItem* source_item, source_parent->childItems()) { - if (!model->isItemChecked(source_item)) { - // We can skip this item, because it is not checked and should not be imported. - // NOTE: All descendants are thus skipped too. - continue; - } + foreach (RootItem* source_item, source_parent->childItems()) { + if (!model->isItemChecked(source_item)) { + // We can skip this item, because it is not checked and should not be imported. + // NOTE: All descendants are thus skipped too. + continue; + } - if (source_item->kind() == RootItemKind::Category) { - StandardCategory* source_category = static_cast(source_item); - StandardCategory* new_category = new StandardCategory(*source_category); - QString new_category_title = new_category->title(); - // Add category to model. - new_category->clearChildren(); + if (source_item->kind() == RootItemKind::Category) { + StandardCategory* source_category = static_cast(source_item); + StandardCategory* new_category = new StandardCategory(*source_category); + QString new_category_title = new_category->title(); - if (new_category->addItself(target_parent)) { - requestItemReassignment(new_category, target_parent); - // Process all children of this category. - original_parents.push(new_category); - new_parents.push(source_category); - } - else { - delete new_category; - // Add category failed, but this can mean that the same category (with same title) - // already exists. If such a category exists in current parent, then find it and - // add descendants to it. - RootItem* existing_category = nullptr; + // Add category to model. + new_category->clearChildren(); - foreach (RootItem* child, target_parent->childItems()) { - if (child->kind() == RootItemKind::Category && child->title() == new_category_title) { - existing_category = child; - } - } + if (new_category->addItself(target_parent)) { + requestItemReassignment(new_category, target_parent); - if (existing_category != nullptr) { - original_parents.push(existing_category); - new_parents.push(source_category); - } - else { - some_feed_category_error = true; - } - } - } - else if (source_item->kind() == RootItemKind::Feed) { - StandardFeed* source_feed = static_cast(source_item); - StandardFeed* new_feed = new StandardFeed(*source_feed); + // Process all children of this category. + original_parents.push(new_category); + new_parents.push(source_category); + } + else { + delete new_category; - // Append this feed and end this iteration. - if (new_feed->addItself(target_parent)) { - requestItemReassignment(new_feed, target_parent); - } - else { - delete new_feed; - some_feed_category_error = true; - } - } - } - } + // Add category failed, but this can mean that the same category (with same title) + // already exists. If such a category exists in current parent, then find it and + // add descendants to it. + RootItem* existing_category = nullptr; - if (some_feed_category_error) { - output_message = tr("Import successful, but some feeds/categories were not imported due to error."); - } - else { - output_message = tr("Import was completely successful."); - } + foreach (RootItem* child, target_parent->childItems()) { + if (child->kind() == RootItemKind::Category && child->title() == new_category_title) { + existing_category = child; + } + } - return !some_feed_category_error; + if (existing_category != nullptr) { + original_parents.push(existing_category); + new_parents.push(source_category); + } + else { + some_feed_category_error = true; + } + } + } + else if (source_item->kind() == RootItemKind::Feed) { + StandardFeed* source_feed = static_cast(source_item); + StandardFeed* new_feed = new StandardFeed(*source_feed); + + // Append this feed and end this iteration. + if (new_feed->addItself(target_parent)) { + requestItemReassignment(new_feed, target_parent); + } + else { + delete new_feed; + some_feed_category_error = true; + } + } + } + } + + if (some_feed_category_error) { + output_message = tr("Import successful, but some feeds/categories were not imported due to error."); + } + else { + output_message = tr("Import was completely successful."); + } + + return !some_feed_category_error; } void StandardServiceRoot::addNewCategory() { - if (!qApp->feedUpdateLock()->tryLock()) { - // Lock was not obtained because - // it is used probably by feed updater or application - // is quitting. - qApp->showGuiMessage(tr("Cannot add category"), - tr("Cannot add category because another critical operation is ongoing."), - QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - // Thus, cannot delete and quit the method. - return; - } + if (!qApp->feedUpdateLock()->tryLock()) { + // Lock was not obtained because + // it is used probably by feed updater or application + // is quitting. + qApp->showGuiMessage(tr("Cannot add category"), + tr("Cannot add category because another critical operation is ongoing."), + QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - QScopedPointer form_pointer(new FormStandardCategoryDetails(this, qApp->mainFormWidget())); - form_pointer.data()->addEditCategory(nullptr, nullptr); - qApp->feedUpdateLock()->unlock(); + // Thus, cannot delete and quit the method. + return; + } + + QScopedPointer form_pointer(new FormStandardCategoryDetails(this, qApp->mainFormWidget())); + form_pointer.data()->addEditCategory(nullptr, nullptr); + qApp->feedUpdateLock()->unlock(); } void StandardServiceRoot::importFeeds() { - QScopedPointer form(new FormStandardImportExport(this, qApp->mainFormWidget())); - form.data()->setMode(FeedsImportExportModel::Import); - form.data()->exec(); + QScopedPointer form(new FormStandardImportExport(this, qApp->mainFormWidget())); + form.data()->setMode(FeedsImportExportModel::Import); + form.data()->exec(); } void StandardServiceRoot::exportFeeds() { - QScopedPointer form(new FormStandardImportExport(this, qApp->mainFormWidget())); - form.data()->setMode(FeedsImportExportModel::Export); - form.data()->exec(); + QScopedPointer form(new FormStandardImportExport(this, qApp->mainFormWidget())); + form.data()->setMode(FeedsImportExportModel::Export); + form.data()->exec(); } QList StandardServiceRoot::serviceMenu() { - if (m_serviceMenu.isEmpty()) { - m_actionExportFeeds = new QAction(qApp->icons()->fromTheme("document-export"), tr("Export feeds"), this); - m_actionImportFeeds = new QAction(qApp->icons()->fromTheme("document-import"), tr("Import feeds"), this); - connect(m_actionExportFeeds, &QAction::triggered, this, &StandardServiceRoot::exportFeeds); - connect(m_actionImportFeeds, &QAction::triggered, this, &StandardServiceRoot::importFeeds); - m_serviceMenu.append(m_actionExportFeeds); - m_serviceMenu.append(m_actionImportFeeds); - } + if (m_serviceMenu.isEmpty()) { + m_actionExportFeeds = new QAction(qApp->icons()->fromTheme("document-export"), tr("Export feeds"), this); + m_actionImportFeeds = new QAction(qApp->icons()->fromTheme("document-import"), tr("Import feeds"), this); + connect(m_actionExportFeeds, &QAction::triggered, this, &StandardServiceRoot::exportFeeds); + connect(m_actionImportFeeds, &QAction::triggered, this, &StandardServiceRoot::importFeeds); + m_serviceMenu.append(m_actionExportFeeds); + m_serviceMenu.append(m_actionImportFeeds); + } - return m_serviceMenu; + return m_serviceMenu; } diff --git a/src/services/standard/standardserviceroot.h b/src/services/standard/standardserviceroot.h index 94efdd279..9f79bedab 100755 --- a/src/services/standard/standardserviceroot.h +++ b/src/services/standard/standardserviceroot.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,7 +24,6 @@ #include #include - class RecycleBin; class StandardCategory; class StandardFeed; @@ -31,63 +31,64 @@ class FeedsImportExportModel; class QMenu; class StandardServiceRoot : public ServiceRoot { - Q_OBJECT + Q_OBJECT - public: - explicit StandardServiceRoot(RootItem* parent = nullptr); - virtual ~StandardServiceRoot(); + public: + explicit StandardServiceRoot(RootItem* parent = nullptr); + virtual ~StandardServiceRoot(); - // Start/stop root. - void start(bool freshly_activated); - void stop(); + // Start/stop root. + void start(bool freshly_activated); + void stop(); - QString code() const; + QString code() const; - bool canBeEdited() const; - bool canBeDeleted() const; - bool deleteViaGui(); - bool supportsFeedAdding() const; - bool supportsCategoryAdding() const; + bool canBeEdited() const; + bool canBeDeleted() const; + bool deleteViaGui(); + bool supportsFeedAdding() const; + bool supportsCategoryAdding() const; - QVariant data(int column, int role) const; - Qt::ItemFlags additionalFlags() const; + QVariant data(int column, int role) const; + Qt::ItemFlags additionalFlags() const; - // Access to recycle bin. - RecycleBin* recycleBin() const; + // Access to recycle bin. + RecycleBin* recycleBin() const; - // Returns menu to be shown in "Services -> service" menu. - QList serviceMenu(); + // Returns menu to be shown in "Services -> service" menu. + QList serviceMenu(); - // Returns context specific menu actions for given feed. - QList getContextMenuForFeed(StandardFeed* feed); + // Returns context specific menu actions for given feed. + QList getContextMenuForFeed(StandardFeed* feed); - // Takes structure residing under given root item and adds feeds/categories from - // it to active structure. - // NOTE: This is used for import/export of the model. - bool mergeImportExportModel(FeedsImportExportModel* model, RootItem* target_root_node, QString& output_message); + // Takes structure residing under given root item and adds feeds/categories from + // it to active structure. + // NOTE: This is used for import/export of the model. + bool mergeImportExportModel(FeedsImportExportModel* model, RootItem* target_root_node, QString& output_message); - void loadFromDatabase(); - void checkArgumentForFeedAdding(const QString& argument); + void loadFromDatabase(); + void checkArgumentForFeedAdding(const QString& argument); - public slots: - void addNewFeed(const QString& url = QString()); - void addNewCategory(); - void importFeeds(); - void exportFeeds(); + public slots: + void addNewFeed(const QString& url = QString()); + void addNewCategory(); + void importFeeds(); + void exportFeeds(); - private: - QString processFeedUrl(const QString& feed_url); - void checkArgumentsForFeedAdding(); + private: + QString processFeedUrl(const QString& feed_url); + void checkArgumentsForFeedAdding(); - RecycleBin* m_recycleBin; - QAction* m_actionExportFeeds; - QAction* m_actionImportFeeds; - QList m_serviceMenu; - QList m_feedContextMenu; - QAction* m_actionFeedFetchMetadata; + RecycleBin* m_recycleBin; + QAction* m_actionExportFeeds; + QAction* m_actionImportFeeds; - QMap storeCustomFeedsData(); - void restoreCustomFeedsData(const QMap& data, const QHash& feeds); + QList m_serviceMenu; + QList m_feedContextMenu; + QAction* m_actionFeedFetchMetadata; + + QMap storeCustomFeedsData(); + void restoreCustomFeedsData(const QMap& data, const QHash& feeds); }; #endif // STANDARDSERVICEROOT_H diff --git a/src/services/tt-rss/definitions.h b/src/services/tt-rss/definitions.h index 80db6e355..2cb6ae09c 100755 --- a/src/services/tt-rss/definitions.h +++ b/src/services/tt-rss/definitions.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // diff --git a/src/services/tt-rss/gui/formeditttrssaccount.cpp b/src/services/tt-rss/gui/formeditttrssaccount.cpp index e4b6a1baf..2bdfa1092 100755 --- a/src/services/tt-rss/gui/formeditttrssaccount.cpp +++ b/src/services/tt-rss/gui/formeditttrssaccount.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -15,254 +16,266 @@ // You should have received a copy of the GNU General Public License // along with RSS Guard. If not, see . - #include "services/tt-rss/gui/formeditttrssaccount.h" -#include "services/tt-rss/definitions.h" -#include "services/tt-rss/ttrssserviceroot.h" -#include "services/tt-rss/network/ttrssnetworkfactory.h" +#include "gui/guiutilities.h" #include "miscellaneous/iconfactory.h" #include "network-web/networkfactory.h" -#include "gui/guiutilities.h" - +#include "services/tt-rss/definitions.h" +#include "services/tt-rss/network/ttrssnetworkfactory.h" +#include "services/tt-rss/ttrssserviceroot.h" FormEditTtRssAccount::FormEditTtRssAccount(QWidget* parent) - : QDialog(parent), m_ui(new Ui::FormEditTtRssAccount), m_editableRoot(nullptr) { - m_ui->setupUi(this); - m_btnOk = m_ui->m_buttonBox->button(QDialogButtonBox::Ok); + : QDialog(parent), m_ui(new Ui::FormEditTtRssAccount), m_editableRoot(nullptr) { + m_ui->setupUi(this); + m_btnOk = m_ui->m_buttonBox->button(QDialogButtonBox::Ok); GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("tinytinyrss"))); m_ui->m_lblTestResult->label()->setWordWrap(true); - m_ui->m_lblServerSideUpdateInformation->setText(tr("Leaving this option on causes that updates " - "of feeds will be probably much slower and may time-out often.")); - m_ui->m_lblDescription->setText(tr("Note that at least API level %1 is required.").arg(MINIMAL_API_LEVEL)); - m_ui->m_txtHttpUsername->lineEdit()->setPlaceholderText(tr("HTTP authentication username")); - m_ui->m_txtHttpPassword->lineEdit()->setPlaceholderText(tr("HTTP authentication password")); - m_ui->m_txtPassword->lineEdit()->setPlaceholderText(tr("Password for your TT-RSS account")); - m_ui->m_txtUsername->lineEdit()->setPlaceholderText(tr("Username for your TT-RSS account")); - m_ui->m_txtUrl->lineEdit()->setPlaceholderText(tr("URL of your TT-RSS instance WITHOUT trailing \"/api/\" string")); - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Information, - tr("No test done yet."), - tr("Here, results of connection test are shown.")); + m_ui->m_lblServerSideUpdateInformation->setText(tr("Leaving this option on causes that updates " + "of feeds will be probably much slower and may time-out often.")); + m_ui->m_lblDescription->setText(tr("Note that at least API level %1 is required.").arg(MINIMAL_API_LEVEL)); + m_ui->m_txtHttpUsername->lineEdit()->setPlaceholderText(tr("HTTP authentication username")); + m_ui->m_txtHttpPassword->lineEdit()->setPlaceholderText(tr("HTTP authentication password")); + m_ui->m_txtPassword->lineEdit()->setPlaceholderText(tr("Password for your TT-RSS account")); + m_ui->m_txtUsername->lineEdit()->setPlaceholderText(tr("Username for your TT-RSS account")); + m_ui->m_txtUrl->lineEdit()->setPlaceholderText(tr("URL of your TT-RSS instance WITHOUT trailing \"/api/\" string")); + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Information, + tr("No test done yet."), + tr("Here, results of connection test are shown.")); GuiUtilities::setLabelAsNotice(*m_ui->m_lblDescription, false); GuiUtilities::setLabelAsNotice(*m_ui->m_lblServerSideUpdateInformation, false); setTabOrder(m_ui->m_txtUrl->lineEdit(), m_ui->m_checkServerSideUpdate); - setTabOrder(m_ui->m_checkServerSideUpdate, m_ui->m_txtUsername->lineEdit()); - setTabOrder(m_ui->m_txtUsername->lineEdit(), m_ui->m_txtPassword->lineEdit()); - setTabOrder(m_ui->m_txtPassword->lineEdit(), m_ui->m_checkShowPassword); - setTabOrder(m_ui->m_checkShowPassword, m_ui->m_gbHttpAuthentication); - setTabOrder(m_ui->m_gbHttpAuthentication, m_ui->m_txtHttpUsername->lineEdit()); - setTabOrder(m_ui->m_txtHttpUsername->lineEdit(), m_ui->m_txtHttpPassword->lineEdit()); - setTabOrder(m_ui->m_txtHttpPassword->lineEdit(), m_ui->m_checkShowHttpPassword); - setTabOrder(m_ui->m_checkShowHttpPassword, m_ui->m_btnTestSetup); - setTabOrder(m_ui->m_btnTestSetup, m_ui->m_buttonBox); + setTabOrder(m_ui->m_checkServerSideUpdate, m_ui->m_txtUsername->lineEdit()); + setTabOrder(m_ui->m_txtUsername->lineEdit(), m_ui->m_txtPassword->lineEdit()); + setTabOrder(m_ui->m_txtPassword->lineEdit(), m_ui->m_checkShowPassword); + setTabOrder(m_ui->m_checkShowPassword, m_ui->m_gbHttpAuthentication); + setTabOrder(m_ui->m_gbHttpAuthentication, m_ui->m_txtHttpUsername->lineEdit()); + setTabOrder(m_ui->m_txtHttpUsername->lineEdit(), m_ui->m_txtHttpPassword->lineEdit()); + setTabOrder(m_ui->m_txtHttpPassword->lineEdit(), m_ui->m_checkShowHttpPassword); + setTabOrder(m_ui->m_checkShowHttpPassword, m_ui->m_btnTestSetup); + setTabOrder(m_ui->m_btnTestSetup, m_ui->m_buttonBox); connect(m_ui->m_checkShowPassword, &QCheckBox::toggled, this, &FormEditTtRssAccount::displayPassword); - connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormEditTtRssAccount::onClickedOk); - connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &FormEditTtRssAccount::onClickedCancel); - connect(m_ui->m_txtPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::onPasswordChanged); - connect(m_ui->m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::onUsernameChanged); - connect(m_ui->m_txtHttpPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::onHttpPasswordChanged); - connect(m_ui->m_txtHttpUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::onHttpUsernameChanged); - connect(m_ui->m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::onUrlChanged); - connect(m_ui->m_txtPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::checkOkButton); - connect(m_ui->m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::checkOkButton); - connect(m_ui->m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::checkOkButton); - connect(m_ui->m_btnTestSetup, &QPushButton::clicked, this, &FormEditTtRssAccount::performTest); - connect(m_ui->m_gbHttpAuthentication, &QGroupBox::toggled, this, &FormEditTtRssAccount::onHttpPasswordChanged); - connect(m_ui->m_gbHttpAuthentication, &QGroupBox::toggled, this, &FormEditTtRssAccount::onHttpUsernameChanged); - connect(m_ui->m_checkShowHttpPassword, &QCheckBox::toggled, this, &FormEditTtRssAccount::displayHttpPassword); + connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormEditTtRssAccount::onClickedOk); + connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &FormEditTtRssAccount::onClickedCancel); + connect(m_ui->m_txtPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::onPasswordChanged); + connect(m_ui->m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::onUsernameChanged); + connect(m_ui->m_txtHttpPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::onHttpPasswordChanged); + connect(m_ui->m_txtHttpUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::onHttpUsernameChanged); + connect(m_ui->m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::onUrlChanged); + connect(m_ui->m_txtPassword->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::checkOkButton); + connect(m_ui->m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::checkOkButton); + connect(m_ui->m_txtUrl->lineEdit(), &BaseLineEdit::textChanged, this, &FormEditTtRssAccount::checkOkButton); + connect(m_ui->m_btnTestSetup, &QPushButton::clicked, this, &FormEditTtRssAccount::performTest); + connect(m_ui->m_gbHttpAuthentication, &QGroupBox::toggled, this, &FormEditTtRssAccount::onHttpPasswordChanged); + connect(m_ui->m_gbHttpAuthentication, &QGroupBox::toggled, this, &FormEditTtRssAccount::onHttpUsernameChanged); + connect(m_ui->m_checkShowHttpPassword, &QCheckBox::toggled, this, &FormEditTtRssAccount::displayHttpPassword); onPasswordChanged(); - onUsernameChanged(); - onUrlChanged(); - onHttpPasswordChanged(); - onHttpUsernameChanged(); - checkOkButton(); - displayPassword(false); - displayHttpPassword(false); + onUsernameChanged(); + onUrlChanged(); + onHttpPasswordChanged(); + onHttpUsernameChanged(); + checkOkButton(); + displayPassword(false); + displayHttpPassword(false); } -FormEditTtRssAccount::~FormEditTtRssAccount() { -} +FormEditTtRssAccount::~FormEditTtRssAccount() {} TtRssServiceRoot* FormEditTtRssAccount::execForCreate() { - setWindowTitle(tr("Add new Tiny Tiny RSS account")); - exec(); - return m_editableRoot; + setWindowTitle(tr("Add new Tiny Tiny RSS account")); + exec(); + return m_editableRoot; } void FormEditTtRssAccount::execForEdit(TtRssServiceRoot* existing_root) { - setWindowTitle(tr("Edit existing Tiny Tiny RSS account")); - m_editableRoot = existing_root; - m_ui->m_gbHttpAuthentication->setChecked(existing_root->network()->authIsUsed()); - m_ui->m_txtHttpPassword->lineEdit()->setText(existing_root->network()->authPassword()); - m_ui->m_txtHttpUsername->lineEdit()->setText(existing_root->network()->authUsername()); - m_ui->m_txtUsername->lineEdit()->setText(existing_root->network()->username()); - m_ui->m_txtPassword->lineEdit()->setText(existing_root->network()->password()); - m_ui->m_txtUrl->lineEdit()->setText(existing_root->network()->url()); - m_ui->m_checkServerSideUpdate->setChecked(existing_root->network()->forceServerSideUpdate()); - exec(); + setWindowTitle(tr("Edit existing Tiny Tiny RSS account")); + m_editableRoot = existing_root; + m_ui->m_gbHttpAuthentication->setChecked(existing_root->network()->authIsUsed()); + m_ui->m_txtHttpPassword->lineEdit()->setText(existing_root->network()->authPassword()); + m_ui->m_txtHttpUsername->lineEdit()->setText(existing_root->network()->authUsername()); + m_ui->m_txtUsername->lineEdit()->setText(existing_root->network()->username()); + m_ui->m_txtPassword->lineEdit()->setText(existing_root->network()->password()); + m_ui->m_txtUrl->lineEdit()->setText(existing_root->network()->url()); + m_ui->m_checkServerSideUpdate->setChecked(existing_root->network()->forceServerSideUpdate()); + exec(); } void FormEditTtRssAccount::displayPassword(bool display) { - m_ui->m_txtPassword->lineEdit()->setEchoMode(display ? QLineEdit::Normal : QLineEdit::Password); + m_ui->m_txtPassword->lineEdit()->setEchoMode(display ? QLineEdit::Normal : QLineEdit::Password); } void FormEditTtRssAccount::displayHttpPassword(bool display) { - m_ui->m_txtHttpPassword->lineEdit()->setEchoMode(display ? QLineEdit::Normal : QLineEdit::Password); + m_ui->m_txtHttpPassword->lineEdit()->setEchoMode(display ? QLineEdit::Normal : QLineEdit::Password); } void FormEditTtRssAccount::performTest() { - TtRssNetworkFactory factory; - factory.setUsername(m_ui->m_txtUsername->lineEdit()->text()); - factory.setPassword(m_ui->m_txtPassword->lineEdit()->text()); - factory.setUrl(m_ui->m_txtUrl->lineEdit()->text()); - factory.setAuthIsUsed(m_ui->m_gbHttpAuthentication->isChecked()); - factory.setAuthUsername(m_ui->m_txtHttpUsername->lineEdit()->text()); - factory.setAuthPassword(m_ui->m_txtHttpPassword->lineEdit()->text()); - factory.setForceServerSideUpdate(m_ui->m_checkServerSideUpdate->isChecked()); - TtRssLoginResponse result = factory.login(); + TtRssNetworkFactory factory; - if (result.isLoaded()) { - if (result.hasError()) { - QString error = result.error(); + factory.setUsername(m_ui->m_txtUsername->lineEdit()->text()); + factory.setPassword(m_ui->m_txtPassword->lineEdit()->text()); + factory.setUrl(m_ui->m_txtUrl->lineEdit()->text()); + factory.setAuthIsUsed(m_ui->m_gbHttpAuthentication->isChecked()); + factory.setAuthUsername(m_ui->m_txtHttpUsername->lineEdit()->text()); + factory.setAuthPassword(m_ui->m_txtHttpPassword->lineEdit()->text()); + factory.setForceServerSideUpdate(m_ui->m_checkServerSideUpdate->isChecked()); + TtRssLoginResponse result = factory.login(); - if (error == API_DISABLED) { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, - tr("API access on selected server is not enabled."), - tr("API access on selected server is not enabled.")); - } - else if (error == LOGIN_ERROR) { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, - tr("Entered credentials are incorrect."), - tr("Entered credentials are incorrect.")); - } - else { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, - tr("Other error occurred, contact developers."), - tr("Other error occurred, contact developers.")); - } - } - else if (result.apiLevel() < MINIMAL_API_LEVEL) { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, - tr("Selected Tiny Tiny RSS server is running unsupported version of API (%1). At least API level %2 is required.").arg(QString::number( - result.apiLevel()), - QString::number(MINIMAL_API_LEVEL)), - tr("Selected Tiny Tiny RSS server is running unsupported version of API.")); - } - else { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Ok, - tr("Tiny Tiny RSS server is okay, running with API level %1, while at least API level %2 is required.").arg(QString::number( - result.apiLevel()), - QString::number(MINIMAL_API_LEVEL)), - tr("Tiny Tiny RSS server is okay.")); - } - } - else if (factory.lastError() != QNetworkReply::NoError) { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, - tr("Network error: '%1'.").arg(NetworkFactory::networkErrorText(factory.lastError())), - tr("Network error, have you entered correct Tiny Tiny RSS API endpoint and password?")); - } - else { - m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, - tr("Unspecified error, did you enter correct URL?"), - tr("Unspecified error, did you enter correct URL?")); - } + if (result.isLoaded()) { + if (result.hasError()) { + QString error = result.error(); + + if (error == API_DISABLED) { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, + tr("API access on selected server is not enabled."), + tr("API access on selected server is not enabled.")); + } + else if (error == LOGIN_ERROR) { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, + tr("Entered credentials are incorrect."), + tr("Entered credentials are incorrect.")); + } + else { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, + tr("Other error occurred, contact developers."), + tr("Other error occurred, contact developers.")); + } + } + else if (result.apiLevel() < MINIMAL_API_LEVEL) { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, + tr( + "Selected Tiny Tiny RSS server is running unsupported version of API (%1). At least API level %2 is required.").arg( + QString::number( + result + . + apiLevel()), + QString + :: + number(MINIMAL_API_LEVEL)), + tr("Selected Tiny Tiny RSS server is running unsupported version of API.")); + } + else { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Ok, + tr( + "Tiny Tiny RSS server is okay, running with API level %1, while at least API level %2 is required.").arg( + QString::number( + result + . + apiLevel()), + QString + :: + number(MINIMAL_API_LEVEL)), + tr("Tiny Tiny RSS server is okay.")); + } + } + else if (factory.lastError() != QNetworkReply::NoError) { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, + tr("Network error: '%1'.").arg(NetworkFactory::networkErrorText(factory.lastError())), + tr("Network error, have you entered correct Tiny Tiny RSS API endpoint and password?")); + } + else { + m_ui->m_lblTestResult->setStatus(WidgetWithStatus::Error, + tr("Unspecified error, did you enter correct URL?"), + tr("Unspecified error, did you enter correct URL?")); + } } void FormEditTtRssAccount::onClickedOk() { - bool editing_account = true; + bool editing_account = true; - if (m_editableRoot == nullptr) { - // We want to confirm newly created account. - // So save new account into DB, setup its properties. - m_editableRoot = new TtRssServiceRoot(); - editing_account = false; - } + if (m_editableRoot == nullptr) { + // We want to confirm newly created account. + // So save new account into DB, setup its properties. + m_editableRoot = new TtRssServiceRoot(); + editing_account = false; + } - m_editableRoot->network()->setUrl(m_ui->m_txtUrl->lineEdit()->text()); - m_editableRoot->network()->setUsername(m_ui->m_txtUsername->lineEdit()->text()); - m_editableRoot->network()->setPassword(m_ui->m_txtPassword->lineEdit()->text()); - m_editableRoot->network()->setAuthIsUsed(m_ui->m_gbHttpAuthentication->isChecked()); - m_editableRoot->network()->setAuthUsername(m_ui->m_txtHttpUsername->lineEdit()->text()); - m_editableRoot->network()->setAuthPassword(m_ui->m_txtHttpPassword->lineEdit()->text()); - m_editableRoot->network()->setForceServerSideUpdate(m_ui->m_checkServerSideUpdate->isChecked()); - m_editableRoot->saveAccountDataToDatabase(); - accept(); + m_editableRoot->network()->setUrl(m_ui->m_txtUrl->lineEdit()->text()); + m_editableRoot->network()->setUsername(m_ui->m_txtUsername->lineEdit()->text()); + m_editableRoot->network()->setPassword(m_ui->m_txtPassword->lineEdit()->text()); + m_editableRoot->network()->setAuthIsUsed(m_ui->m_gbHttpAuthentication->isChecked()); + m_editableRoot->network()->setAuthUsername(m_ui->m_txtHttpUsername->lineEdit()->text()); + m_editableRoot->network()->setAuthPassword(m_ui->m_txtHttpPassword->lineEdit()->text()); + m_editableRoot->network()->setForceServerSideUpdate(m_ui->m_checkServerSideUpdate->isChecked()); + m_editableRoot->saveAccountDataToDatabase(); + accept(); - if (editing_account) { - m_editableRoot->network()->logout(); - m_editableRoot->completelyRemoveAllData(); - m_editableRoot->syncIn(); - } + if (editing_account) { + m_editableRoot->network()->logout(); + m_editableRoot->completelyRemoveAllData(); + m_editableRoot->syncIn(); + } } void FormEditTtRssAccount::onClickedCancel() { - reject(); + reject(); } void FormEditTtRssAccount::onUsernameChanged() { - const QString username = m_ui->m_txtUsername->lineEdit()->text(); + const QString username = m_ui->m_txtUsername->lineEdit()->text(); - if (username.isEmpty()) { - m_ui->m_txtUsername->setStatus(WidgetWithStatus::Error, tr("Username cannot be empty.")); - } - else { - m_ui->m_txtUsername->setStatus(WidgetWithStatus::Ok, tr("Username is okay.")); - } + if (username.isEmpty()) { + m_ui->m_txtUsername->setStatus(WidgetWithStatus::Error, tr("Username cannot be empty.")); + } + else { + m_ui->m_txtUsername->setStatus(WidgetWithStatus::Ok, tr("Username is okay.")); + } } void FormEditTtRssAccount::onPasswordChanged() { - const QString password = m_ui->m_txtPassword->lineEdit()->text(); + const QString password = m_ui->m_txtPassword->lineEdit()->text(); - if (password.isEmpty()) { - m_ui->m_txtPassword->setStatus(WidgetWithStatus::Error, tr("Password cannot be empty.")); - } - else { - m_ui->m_txtPassword->setStatus(WidgetWithStatus::Ok, tr("Password is okay.")); - } + if (password.isEmpty()) { + m_ui->m_txtPassword->setStatus(WidgetWithStatus::Error, tr("Password cannot be empty.")); + } + else { + m_ui->m_txtPassword->setStatus(WidgetWithStatus::Ok, tr("Password is okay.")); + } } void FormEditTtRssAccount::onHttpUsernameChanged() { - const bool is_username_ok = !m_ui->m_gbHttpAuthentication->isChecked() || !m_ui->m_txtHttpUsername->lineEdit()->text().isEmpty(); - m_ui->m_txtHttpUsername->setStatus(is_username_ok ? - LineEditWithStatus::Ok : - LineEditWithStatus::Warning, - is_username_ok ? - tr("Username is ok or it is not needed.") : - tr("Username is empty.")); + const bool is_username_ok = !m_ui->m_gbHttpAuthentication->isChecked() || !m_ui->m_txtHttpUsername->lineEdit()->text().isEmpty(); + + m_ui->m_txtHttpUsername->setStatus(is_username_ok ? + LineEditWithStatus::Ok : + LineEditWithStatus::Warning, + is_username_ok ? + tr("Username is ok or it is not needed.") : + tr("Username is empty.")); } void FormEditTtRssAccount::onHttpPasswordChanged() { - const bool is_username_ok = !m_ui->m_gbHttpAuthentication->isChecked() || !m_ui->m_txtHttpPassword->lineEdit()->text().isEmpty(); - m_ui->m_txtHttpPassword->setStatus(is_username_ok ? - LineEditWithStatus::Ok : - LineEditWithStatus::Warning, - is_username_ok ? - tr("Password is ok or it is not needed.") : - tr("Password is empty.")); + const bool is_username_ok = !m_ui->m_gbHttpAuthentication->isChecked() || !m_ui->m_txtHttpPassword->lineEdit()->text().isEmpty(); + + m_ui->m_txtHttpPassword->setStatus(is_username_ok ? + LineEditWithStatus::Ok : + LineEditWithStatus::Warning, + is_username_ok ? + tr("Password is ok or it is not needed.") : + tr("Password is empty.")); } void FormEditTtRssAccount::onUrlChanged() { - const QString url = m_ui->m_txtUrl->lineEdit()->text(); + const QString url = m_ui->m_txtUrl->lineEdit()->text(); - if (url.isEmpty()) { - m_ui->m_txtUrl->setStatus(WidgetWithStatus::Error, tr("URL cannot be empty.")); - } - else if (url.endsWith(QL1S("/api/")) || url.endsWith(QL1S("/api"))) { - m_ui->m_txtUrl->setStatus(WidgetWithStatus::Warning, tr("URL should NOT end with \"/api/\".")); - } - else { - m_ui->m_txtUrl->setStatus(WidgetWithStatus::Ok, tr("URL is okay.")); - } + if (url.isEmpty()) { + m_ui->m_txtUrl->setStatus(WidgetWithStatus::Error, tr("URL cannot be empty.")); + } + else if (url.endsWith(QL1S("/api/")) || url.endsWith(QL1S("/api"))) { + m_ui->m_txtUrl->setStatus(WidgetWithStatus::Warning, tr("URL should NOT end with \"/api/\".")); + } + else { + m_ui->m_txtUrl->setStatus(WidgetWithStatus::Ok, tr("URL is okay.")); + } } void FormEditTtRssAccount::checkOkButton() { - m_btnOk->setEnabled(!m_ui->m_txtUsername->lineEdit()->text().isEmpty() && - !m_ui->m_txtPassword->lineEdit()->text().isEmpty() && - !m_ui->m_txtUrl->lineEdit()->text().isEmpty()); + m_btnOk->setEnabled(!m_ui->m_txtUsername->lineEdit()->text().isEmpty() && + !m_ui->m_txtPassword->lineEdit()->text().isEmpty() && + !m_ui->m_txtUrl->lineEdit()->text().isEmpty()); } diff --git a/src/services/tt-rss/gui/formeditttrssaccount.h b/src/services/tt-rss/gui/formeditttrssaccount.h index 990d1664c..28d122dd1 100755 --- a/src/services/tt-rss/gui/formeditttrssaccount.h +++ b/src/services/tt-rss/gui/formeditttrssaccount.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,41 +23,41 @@ #include "ui_formeditttrssaccount.h" - namespace Ui { - class FormEditTtRssAccount; + class FormEditTtRssAccount; } class TtRssServiceRoot; class FormEditTtRssAccount : public QDialog { - Q_OBJECT + Q_OBJECT - public: - explicit FormEditTtRssAccount(QWidget* parent = 0); - virtual ~FormEditTtRssAccount(); + public: + explicit FormEditTtRssAccount(QWidget* parent = 0); + virtual ~FormEditTtRssAccount(); - TtRssServiceRoot* execForCreate(); - void execForEdit(TtRssServiceRoot* existing_root); + TtRssServiceRoot* execForCreate(); - private slots: - void displayPassword(bool display); - void displayHttpPassword(bool display); - void performTest(); - void onClickedOk(); - void onClickedCancel(); + void execForEdit(TtRssServiceRoot* existing_root); - void onUsernameChanged(); - void onPasswordChanged(); - void onHttpUsernameChanged(); - void onHttpPasswordChanged(); - void onUrlChanged(); - void checkOkButton(); + private slots: + void displayPassword(bool display); + void displayHttpPassword(bool display); + void performTest(); + void onClickedOk(); + void onClickedCancel(); - private: - QScopedPointer m_ui; - TtRssServiceRoot* m_editableRoot; - QPushButton* m_btnOk; + void onUsernameChanged(); + void onPasswordChanged(); + void onHttpUsernameChanged(); + void onHttpPasswordChanged(); + void onUrlChanged(); + void checkOkButton(); + + private: + QScopedPointer m_ui; + TtRssServiceRoot* m_editableRoot; + QPushButton* m_btnOk; }; #endif // FORMEDITACCOUNT_H diff --git a/src/services/tt-rss/gui/formttrssfeeddetails.cpp b/src/services/tt-rss/gui/formttrssfeeddetails.cpp index e4e62e459..5a3a93971 100755 --- a/src/services/tt-rss/gui/formttrssfeeddetails.cpp +++ b/src/services/tt-rss/gui/formttrssfeeddetails.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -17,76 +18,78 @@ #include "services/tt-rss/gui/formttrssfeeddetails.h" +#include "miscellaneous/application.h" #include "services/tt-rss/definitions.h" -#include "services/tt-rss/ttrssserviceroot.h" +#include "services/tt-rss/network/ttrssnetworkfactory.h" #include "services/tt-rss/ttrsscategory.h" #include "services/tt-rss/ttrssfeed.h" -#include "services/tt-rss/network/ttrssnetworkfactory.h" -#include "miscellaneous/application.h" +#include "services/tt-rss/ttrssserviceroot.h" #include - FormTtRssFeedDetails::FormTtRssFeedDetails(ServiceRoot* service_root, QWidget* parent) - : FormFeedDetails(service_root, parent) { - m_ui->m_spinAutoUpdateInterval->setEnabled(false); - m_ui->m_cmbAutoUpdateType->setEnabled(false); - m_ui->m_cmbType->setEnabled(false); - m_ui->m_cmbEncoding->setEnabled(false); - m_ui->m_btnFetchMetadata->setEnabled(false); - m_ui->m_btnIcon->setEnabled(false); - m_ui->m_txtTitle->setEnabled(false); - m_ui->m_txtDescription->setEnabled(false); + : FormFeedDetails(service_root, parent) { + m_ui->m_spinAutoUpdateInterval->setEnabled(false); + m_ui->m_cmbAutoUpdateType->setEnabled(false); + m_ui->m_cmbType->setEnabled(false); + m_ui->m_cmbEncoding->setEnabled(false); + m_ui->m_btnFetchMetadata->setEnabled(false); + m_ui->m_btnIcon->setEnabled(false); + m_ui->m_txtTitle->setEnabled(false); + m_ui->m_txtDescription->setEnabled(false); } void FormTtRssFeedDetails::apply() { - if (m_editableFeed != nullptr) { - // User edited auto-update status. Save it. - TtRssFeed* new_feed_data = new TtRssFeed(); - new_feed_data->setAutoUpdateType(static_cast(m_ui->m_cmbAutoUpdateType->itemData( - m_ui->m_cmbAutoUpdateType->currentIndex()).toInt())); - new_feed_data->setAutoUpdateInitialInterval(m_ui->m_spinAutoUpdateInterval->value()); - qobject_cast(m_editableFeed)->editItself(new_feed_data); - delete new_feed_data; - } - else { - RootItem* parent = static_cast(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()).value()); - TtRssServiceRoot* root = parent->kind() == RootItemKind::Category ? - qobject_cast(parent)->serviceRoot() : - qobject_cast(parent); - const int category_id = parent->kind() == RootItemKind::ServiceRoot ? - 0 : - qobject_cast(parent)->customId(); - const TtRssSubscribeToFeedResponse response = root->network()->subscribeToFeed(m_ui->m_txtUrl->lineEdit()->text(), - category_id, - m_ui->m_gbAuthentication->isChecked(), - m_ui->m_txtUsername->lineEdit()->text(), - m_ui->m_txtPassword->lineEdit()->text()); + if (m_editableFeed != nullptr) { + // User edited auto-update status. Save it. + TtRssFeed* new_feed_data = new TtRssFeed(); - if (response.code() == STF_INSERTED) { - // Feed was added online. - accept(); - qApp->showGuiMessage(tr("Feed added"), tr("Feed was added, triggering sync in now."), QSystemTrayIcon::Information); - QTimer::singleShot(100, root, SLOT(syncIn())); - } - else { - reject(); - qApp->showGuiMessage(tr("Cannot add feed"), - tr("Feed was not added due to error."), - QSystemTrayIcon::Critical, qApp->mainFormWidget(), true); - } - } + new_feed_data->setAutoUpdateType(static_cast(m_ui->m_cmbAutoUpdateType->itemData( + m_ui->m_cmbAutoUpdateType->currentIndex()).toInt())); + new_feed_data->setAutoUpdateInitialInterval(m_ui->m_spinAutoUpdateInterval->value()); + qobject_cast(m_editableFeed)->editItself(new_feed_data); + delete new_feed_data; + } + else { + RootItem* parent = + static_cast(m_ui->m_cmbParentCategory->itemData(m_ui->m_cmbParentCategory->currentIndex()).value()); + TtRssServiceRoot* root = parent->kind() == RootItemKind::Category ? + qobject_cast(parent)->serviceRoot() : + qobject_cast(parent); + const int category_id = parent->kind() == RootItemKind::ServiceRoot ? + 0 : + qobject_cast(parent)->customId(); + const TtRssSubscribeToFeedResponse response = root->network()->subscribeToFeed(m_ui->m_txtUrl->lineEdit()->text(), + category_id, + m_ui->m_gbAuthentication->isChecked(), + m_ui->m_txtUsername->lineEdit()->text(), + m_ui->m_txtPassword->lineEdit()->text()); - accept(); + if (response.code() == STF_INSERTED) { + // Feed was added online. + accept(); + qApp->showGuiMessage(tr("Feed added"), tr("Feed was added, triggering sync in now."), QSystemTrayIcon::Information); + QTimer::singleShot(100, root, SLOT(syncIn())); + } + else { + reject(); + qApp->showGuiMessage(tr("Cannot add feed"), + tr("Feed was not added due to error."), + QSystemTrayIcon::Critical, qApp->mainFormWidget(), true); + } + } + + accept(); } void FormTtRssFeedDetails::setEditableFeed(Feed* editable_feed) { - m_ui->m_cmbAutoUpdateType->setEnabled(true); - FormFeedDetails::setEditableFeed(editable_feed); - // Tiny Tiny RSS does not support editing of these features. - // User can edit only individual auto-update statuses. - m_ui->m_gbAuthentication->setEnabled(false); - m_ui->m_txtUrl->setEnabled(false); - m_ui->m_lblParentCategory->setEnabled(false); - m_ui->m_cmbParentCategory->setEnabled(false); + m_ui->m_cmbAutoUpdateType->setEnabled(true); + FormFeedDetails::setEditableFeed(editable_feed); + + // Tiny Tiny RSS does not support editing of these features. + // User can edit only individual auto-update statuses. + m_ui->m_gbAuthentication->setEnabled(false); + m_ui->m_txtUrl->setEnabled(false); + m_ui->m_lblParentCategory->setEnabled(false); + m_ui->m_cmbParentCategory->setEnabled(false); } diff --git a/src/services/tt-rss/gui/formttrssfeeddetails.h b/src/services/tt-rss/gui/formttrssfeeddetails.h index 7aa262ad8..9528c9bd2 100755 --- a/src/services/tt-rss/gui/formttrssfeeddetails.h +++ b/src/services/tt-rss/gui/formttrssfeeddetails.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,19 +21,19 @@ #include "services/abstract/gui/formfeeddetails.h" - class FormTtRssFeedDetails : public FormFeedDetails { - Q_OBJECT + Q_OBJECT - public: - explicit FormTtRssFeedDetails(ServiceRoot* service_root, QWidget* parent = 0); + public: + explicit FormTtRssFeedDetails(ServiceRoot* service_root, QWidget* parent = 0); - // FormFeedDetails interface - protected slots: - void apply(); + // FormFeedDetails interface - protected: - void setEditableFeed(Feed* editable_feed); + protected slots: + void apply(); + + protected: + void setEditableFeed(Feed* editable_feed); }; #endif // FORMTTRSSFEEDDETAILS_H diff --git a/src/services/tt-rss/network/ttrssnetworkfactory.cpp b/src/services/tt-rss/network/ttrssnetworkfactory.cpp index 452f6ba61..2e9194117 100755 --- a/src/services/tt-rss/network/ttrssnetworkfactory.cpp +++ b/src/services/tt-rss/network/ttrssnetworkfactory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,618 +19,630 @@ #include "services/tt-rss/network/ttrssnetworkfactory.h" #include "definitions/definitions.h" -#include "services/abstract/rootitem.h" -#include "services/tt-rss/definitions.h" -#include "services/tt-rss/ttrssfeed.h" -#include "services/tt-rss/ttrsscategory.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" #include "miscellaneous/textfactory.h" #include "network-web/networkfactory.h" +#include "services/abstract/rootitem.h" +#include "services/tt-rss/definitions.h" +#include "services/tt-rss/ttrsscategory.h" +#include "services/tt-rss/ttrssfeed.h" -#include #include +#include #include #include - TtRssNetworkFactory::TtRssNetworkFactory() - : m_bareUrl(QString()), m_fullUrl(QString()), m_username(QString()), m_password(QString()), m_forceServerSideUpdate(false), - m_authIsUsed(false), - m_authUsername(QString()), m_authPassword(QString()), m_sessionId(QString()), - m_lastLoginTime(QDateTime()), m_lastError(QNetworkReply::NoError) { -} + : m_bareUrl(QString()), m_fullUrl(QString()), m_username(QString()), m_password(QString()), m_forceServerSideUpdate(false), + m_authIsUsed(false), + m_authUsername(QString()), m_authPassword(QString()), m_sessionId(QString()), + m_lastLoginTime(QDateTime()), m_lastError(QNetworkReply::NoError) {} -TtRssNetworkFactory::~TtRssNetworkFactory() { -} +TtRssNetworkFactory::~TtRssNetworkFactory() {} QString TtRssNetworkFactory::url() const { - return m_bareUrl; + return m_bareUrl; } void TtRssNetworkFactory::setUrl(const QString& url) { - m_bareUrl = url; + m_bareUrl = url; - if (!m_bareUrl.endsWith(QSL("/"))) { - m_bareUrl = m_bareUrl + QSL("/"); - } + if (!m_bareUrl.endsWith(QSL("/"))) { + m_bareUrl = m_bareUrl + QSL("/"); + } - if (!m_bareUrl.endsWith(QSL("api/"))) { - m_fullUrl = m_bareUrl + QSL("api/"); - } - else { - m_fullUrl = m_bareUrl; - } + if (!m_bareUrl.endsWith(QSL("api/"))) { + m_fullUrl = m_bareUrl + QSL("api/"); + } + else { + m_fullUrl = m_bareUrl; + } } QString TtRssNetworkFactory::username() const { - return m_username; + return m_username; } void TtRssNetworkFactory::setUsername(const QString& username) { - m_username = username; + m_username = username; } QString TtRssNetworkFactory::password() const { - return m_password; + return m_password; } void TtRssNetworkFactory::setPassword(const QString& password) { - m_password = password; + m_password = password; } QDateTime TtRssNetworkFactory::lastLoginTime() const { - return m_lastLoginTime; + return m_lastLoginTime; } QNetworkReply::NetworkError TtRssNetworkFactory::lastError() const { - return m_lastError; + return m_lastError; } TtRssLoginResponse TtRssNetworkFactory::login() { - if (!m_sessionId.isEmpty()) { - qDebug("TT-RSS: Session ID is not empty before login, logging out first."); - logout(); - } + if (!m_sessionId.isEmpty()) { + qDebug("TT-RSS: Session ID is not empty before login, logging out first."); + logout(); + } - QJsonObject json; - json["op"] = QSL("login"); - json["user"] = m_username; - json["password"] = m_password; - QByteArray result_raw; - NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, qApp->settings()->value(GROUP(Feeds), - SETTING(Feeds::UpdateTimeout)).toInt(), - QJsonDocument(json).toJson(QJsonDocument::Compact), CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - TtRssLoginResponse login_response(QString::fromUtf8(result_raw)); + QJsonObject json; - if (network_reply.first == QNetworkReply::NoError) { - m_sessionId = login_response.sessionId(); - m_lastLoginTime = QDateTime::currentDateTime(); - } - else { - qWarning("TT-RSS: Login failed with error %d.", network_reply.first); - } + json["op"] = QSL("login"); + json["user"] = m_username; + json["password"] = m_password; + QByteArray result_raw; + NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, + qApp->settings()->value(GROUP(Feeds), + SETTING( + Feeds::UpdateTimeout)).toInt(), + QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, + result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, + m_authUsername, + m_authPassword); + TtRssLoginResponse login_response(QString::fromUtf8(result_raw)); - m_lastError = network_reply.first; - return login_response; + if (network_reply.first == QNetworkReply::NoError) { + m_sessionId = login_response.sessionId(); + m_lastLoginTime = QDateTime::currentDateTime(); + } + else { + qWarning("TT-RSS: Login failed with error %d.", network_reply.first); + } + + m_lastError = network_reply.first; + return login_response; } TtRssResponse TtRssNetworkFactory::logout() { - if (!m_sessionId.isEmpty()) { - QJsonObject json; - json["op"] = QSL("logout"); - json["sid"] = m_sessionId; - QByteArray result_raw; - NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, qApp->settings()->value(GROUP(Feeds), - SETTING(Feeds::UpdateTimeout)).toInt(), - QJsonDocument(json).toJson(QJsonDocument::Compact), CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - m_lastError = network_reply.first; + if (!m_sessionId.isEmpty()) { + QJsonObject json; - if (m_lastError == QNetworkReply::NoError) { - m_sessionId.clear(); - } - else { - qWarning("TT-RSS: Logout failed with error %d.", network_reply.first); - } + json["op"] = QSL("logout"); + json["sid"] = m_sessionId; + QByteArray result_raw; + NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, + qApp->settings()->value(GROUP(Feeds), + SETTING( + Feeds::UpdateTimeout)).toInt(), + QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, + result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, + m_authUsername, + m_authPassword); - return TtRssResponse(QString::fromUtf8(result_raw)); - } - else { - qWarning("TT-RSS: Cannot logout because session ID is empty."); - m_lastError = QNetworkReply::NoError; - return TtRssResponse(); - } + m_lastError = network_reply.first; + + if (m_lastError == QNetworkReply::NoError) { + m_sessionId.clear(); + } + else { + qWarning("TT-RSS: Logout failed with error %d.", network_reply.first); + } + + return TtRssResponse(QString::fromUtf8(result_raw)); + } + else { + qWarning("TT-RSS: Cannot logout because session ID is empty."); + m_lastError = QNetworkReply::NoError; + return TtRssResponse(); + } } TtRssGetFeedsCategoriesResponse TtRssNetworkFactory::getFeedsCategories() { - QJsonObject json; - json["op"] = QSL("getFeedTree"); - json["sid"] = m_sessionId; - json["include_empty"] = true; - const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); - QByteArray result_raw; - NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, - QJsonDocument(json).toJson(QJsonDocument::Compact), - CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - TtRssGetFeedsCategoriesResponse result(QString::fromUtf8(result_raw)); + QJsonObject json; - if (result.isNotLoggedIn()) { - // We are not logged in. - login(); - json["sid"] = m_sessionId; - network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, QJsonDocument(json).toJson(QJsonDocument::Compact), - CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - result = TtRssGetFeedsCategoriesResponse(QString::fromUtf8(result_raw)); - } + json["op"] = QSL("getFeedTree"); + json["sid"] = m_sessionId; + json["include_empty"] = true; + const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); + QByteArray result_raw; + NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, + QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, m_authUsername, m_authPassword); + TtRssGetFeedsCategoriesResponse result(QString::fromUtf8(result_raw)); - if (network_reply.first != QNetworkReply::NoError) { - qWarning("TT-RSS: getFeedTree failed with error %d.", network_reply.first); - } + if (result.isNotLoggedIn()) { + // We are not logged in. + login(); + json["sid"] = m_sessionId; + network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, m_authUsername, m_authPassword); + result = TtRssGetFeedsCategoriesResponse(QString::fromUtf8(result_raw)); + } - m_lastError = network_reply.first; - return result; + if (network_reply.first != QNetworkReply::NoError) { + qWarning("TT-RSS: getFeedTree failed with error %d.", network_reply.first); + } + + m_lastError = network_reply.first; + return result; } TtRssGetHeadlinesResponse TtRssNetworkFactory::getHeadlines(int feed_id, int limit, int skip, bool show_content, bool include_attachments, bool sanitize) { - QJsonObject json; - json["op"] = QSL("getHeadlines"); - json["sid"] = m_sessionId; - json["feed_id"] = feed_id; - json["force_update"] = m_forceServerSideUpdate; - json["limit"] = limit; - json["skip"] = skip; - json["show_content"] = show_content; - json["include_attachments"] = include_attachments; - json["sanitize"] = sanitize; - const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); - QByteArray result_raw; - NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, - QJsonDocument(json).toJson(QJsonDocument::Compact), - CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - TtRssGetHeadlinesResponse result(QString::fromUtf8(result_raw)); + QJsonObject json; - if (result.isNotLoggedIn()) { - // We are not logged in. - login(); - json["sid"] = m_sessionId; - network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, QJsonDocument(json).toJson(QJsonDocument::Compact), - CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - result = TtRssGetHeadlinesResponse(QString::fromUtf8(result_raw)); - } + json["op"] = QSL("getHeadlines"); + json["sid"] = m_sessionId; + json["feed_id"] = feed_id; + json["force_update"] = m_forceServerSideUpdate; + json["limit"] = limit; + json["skip"] = skip; + json["show_content"] = show_content; + json["include_attachments"] = include_attachments; + json["sanitize"] = sanitize; + const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); + QByteArray result_raw; + NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, + QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, m_authUsername, m_authPassword); + TtRssGetHeadlinesResponse result(QString::fromUtf8(result_raw)); - IOFactory::writeTextFile("aaa", result_raw); + if (result.isNotLoggedIn()) { + // We are not logged in. + login(); + json["sid"] = m_sessionId; + network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, m_authUsername, m_authPassword); + result = TtRssGetHeadlinesResponse(QString::fromUtf8(result_raw)); + } - if (network_reply.first != QNetworkReply::NoError) { - qWarning("TT-RSS: getHeadlines failed with error %d.", network_reply.first); - } + IOFactory::writeTextFile("aaa", result_raw); - m_lastError = network_reply.first; - return result; + if (network_reply.first != QNetworkReply::NoError) { + qWarning("TT-RSS: getHeadlines failed with error %d.", network_reply.first); + } + + m_lastError = network_reply.first; + return result; } TtRssUpdateArticleResponse TtRssNetworkFactory::updateArticles(const QStringList& ids, - UpdateArticle::OperatingField field, - UpdateArticle::Mode mode) { - QJsonObject json; - json["op"] = QSL("updateArticle"); - json["sid"] = m_sessionId; - json["article_ids"] = ids.join(QSL(",")); - json["mode"] = (int) mode; - json["field"] = (int) field; - const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); - QByteArray result_raw; - NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, - QJsonDocument(json).toJson(QJsonDocument::Compact), - CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - TtRssUpdateArticleResponse result(QString::fromUtf8(result_raw)); + UpdateArticle::OperatingField field, + UpdateArticle::Mode mode) { + QJsonObject json; - if (result.isNotLoggedIn()) { - // We are not logged in. - login(); - json["sid"] = m_sessionId; - network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, QJsonDocument(json).toJson(QJsonDocument::Compact), - CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - result = TtRssUpdateArticleResponse(QString::fromUtf8(result_raw)); - } + json["op"] = QSL("updateArticle"); + json["sid"] = m_sessionId; + json["article_ids"] = ids.join(QSL(",")); + json["mode"] = (int) mode; + json["field"] = (int) field; + const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); + QByteArray result_raw; + NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, + QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, m_authUsername, m_authPassword); + TtRssUpdateArticleResponse result(QString::fromUtf8(result_raw)); - if (network_reply.first != QNetworkReply::NoError) { - qWarning("TT-RSS: updateArticle failed with error %d.", network_reply.first); - } + if (result.isNotLoggedIn()) { + // We are not logged in. + login(); + json["sid"] = m_sessionId; + network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, m_authUsername, m_authPassword); + result = TtRssUpdateArticleResponse(QString::fromUtf8(result_raw)); + } - m_lastError = network_reply.first; - return result; + if (network_reply.first != QNetworkReply::NoError) { + qWarning("TT-RSS: updateArticle failed with error %d.", network_reply.first); + } + + m_lastError = network_reply.first; + return result; } TtRssSubscribeToFeedResponse TtRssNetworkFactory::subscribeToFeed(const QString& url, int category_id, - bool protectd, const QString& username, - const QString& password) { - QJsonObject json; - json["op"] = QSL("subscribeToFeed"); - json["sid"] = m_sessionId; - json["feed_url"] = url; - json["category_id"] = category_id; + bool protectd, const QString& username, + const QString& password) { + QJsonObject json; - if (protectd) { - json["login"] = username; - json["password"] = password; - } + json["op"] = QSL("subscribeToFeed"); + json["sid"] = m_sessionId; + json["feed_url"] = url; + json["category_id"] = category_id; - const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); - QByteArray result_raw; - NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, - QJsonDocument(json).toJson(QJsonDocument::Compact), - CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - TtRssSubscribeToFeedResponse result(QString::fromUtf8(result_raw)); + if (protectd) { + json["login"] = username; + json["password"] = password; + } - if (result.isNotLoggedIn()) { - // We are not logged in. - login(); - json["sid"] = m_sessionId; - network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, QJsonDocument(json).toJson(QJsonDocument::Compact), - CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - result = TtRssSubscribeToFeedResponse(QString::fromUtf8(result_raw)); - } + const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); + QByteArray result_raw; + NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, + QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, m_authUsername, m_authPassword); + TtRssSubscribeToFeedResponse result(QString::fromUtf8(result_raw)); - if (network_reply.first != QNetworkReply::NoError) { - qWarning("TT-RSS: updateArticle failed with error %d.", network_reply.first); - } + if (result.isNotLoggedIn()) { + // We are not logged in. + login(); + json["sid"] = m_sessionId; + network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, m_authUsername, m_authPassword); + result = TtRssSubscribeToFeedResponse(QString::fromUtf8(result_raw)); + } - m_lastError = network_reply.first; - return result; + if (network_reply.first != QNetworkReply::NoError) { + qWarning("TT-RSS: updateArticle failed with error %d.", network_reply.first); + } + + m_lastError = network_reply.first; + return result; } TtRssUnsubscribeFeedResponse TtRssNetworkFactory::unsubscribeFeed(int feed_id) { - QJsonObject json; - json["op"] = QSL("unsubscribeFeed"); - json["sid"] = m_sessionId; - json["feed_id"] = feed_id; - const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); - QByteArray result_raw; - NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, - QJsonDocument(json).toJson(QJsonDocument::Compact), CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - TtRssUnsubscribeFeedResponse result(QString::fromUtf8(result_raw)); + QJsonObject json; - if (result.isNotLoggedIn()) { - // We are not logged in. - login(); - json["sid"] = m_sessionId; - network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, QJsonDocument(json).toJson(QJsonDocument::Compact), - CONTENT_TYPE, result_raw, - QNetworkAccessManager::PostOperation, - m_authIsUsed, m_authUsername, m_authPassword); - result = TtRssUnsubscribeFeedResponse(QString::fromUtf8(result_raw)); - } + json["op"] = QSL("unsubscribeFeed"); + json["sid"] = m_sessionId; + json["feed_id"] = feed_id; + const int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); + QByteArray result_raw; + NetworkResult network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, + timeout, + QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, + result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, + m_authUsername, + m_authPassword); + TtRssUnsubscribeFeedResponse result(QString::fromUtf8(result_raw)); - if (network_reply.first != QNetworkReply::NoError) { - qWarning("TT-RSS: getFeeds failed with error %d.", network_reply.first); - } + if (result.isNotLoggedIn()) { + // We are not logged in. + login(); + json["sid"] = m_sessionId; + network_reply = NetworkFactory::performNetworkOperation(m_fullUrl, timeout, QJsonDocument(json).toJson(QJsonDocument::Compact), + CONTENT_TYPE, result_raw, + QNetworkAccessManager::PostOperation, + m_authIsUsed, m_authUsername, m_authPassword); + result = TtRssUnsubscribeFeedResponse(QString::fromUtf8(result_raw)); + } - m_lastError = network_reply.first; - return result; + if (network_reply.first != QNetworkReply::NoError) { + qWarning("TT-RSS: getFeeds failed with error %d.", network_reply.first); + } + + m_lastError = network_reply.first; + return result; } bool TtRssNetworkFactory::forceServerSideUpdate() const { - return m_forceServerSideUpdate; + return m_forceServerSideUpdate; } void TtRssNetworkFactory::setForceServerSideUpdate(bool force_server_side_update) { - m_forceServerSideUpdate = force_server_side_update; + m_forceServerSideUpdate = force_server_side_update; } bool TtRssNetworkFactory::authIsUsed() const { - return m_authIsUsed; + return m_authIsUsed; } void TtRssNetworkFactory::setAuthIsUsed(bool auth_is_used) { - m_authIsUsed = auth_is_used; + m_authIsUsed = auth_is_used; } QString TtRssNetworkFactory::authUsername() const { - return m_authUsername; + return m_authUsername; } void TtRssNetworkFactory::setAuthUsername(const QString& auth_username) { - m_authUsername = auth_username; + m_authUsername = auth_username; } QString TtRssNetworkFactory::authPassword() const { - return m_authPassword; + return m_authPassword; } void TtRssNetworkFactory::setAuthPassword(const QString& auth_password) { - m_authPassword = auth_password; + m_authPassword = auth_password; } TtRssResponse::TtRssResponse(const QString& raw_content) { - m_rawContent = QJsonDocument::fromJson(raw_content.toUtf8()).object(); + m_rawContent = QJsonDocument::fromJson(raw_content.toUtf8()).object(); } -TtRssResponse::~TtRssResponse() { -} +TtRssResponse::~TtRssResponse() {} bool TtRssResponse::isLoaded() const { - return !m_rawContent.isEmpty(); + return !m_rawContent.isEmpty(); } int TtRssResponse::seq() const { - if (!isLoaded()) { - return CONTENT_NOT_LOADED; - } - else { - return m_rawContent["seq"].toInt(); - } + if (!isLoaded()) { + return CONTENT_NOT_LOADED; + } + else { + return m_rawContent["seq"].toInt(); + } } int TtRssResponse::status() const { - if (!isLoaded()) { - return CONTENT_NOT_LOADED; - } - else { - return m_rawContent["status"].toInt(); - } + if (!isLoaded()) { + return CONTENT_NOT_LOADED; + } + else { + return m_rawContent["status"].toInt(); + } } bool TtRssResponse::isNotLoggedIn() const { - return status() == API_STATUS_ERR && hasError() && error() == NOT_LOGGED_IN; + return status() == API_STATUS_ERR && hasError() && error() == NOT_LOGGED_IN; } QString TtRssResponse::toString() const { - return QJsonDocument(m_rawContent).toJson(QJsonDocument::Compact); + return QJsonDocument(m_rawContent).toJson(QJsonDocument::Compact); } -TtRssLoginResponse::TtRssLoginResponse(const QString& raw_content) : TtRssResponse(raw_content) { -} +TtRssLoginResponse::TtRssLoginResponse(const QString& raw_content) : TtRssResponse(raw_content) {} -TtRssLoginResponse::~TtRssLoginResponse() { -} +TtRssLoginResponse::~TtRssLoginResponse() {} int TtRssLoginResponse::apiLevel() const { - if (!isLoaded()) { - return CONTENT_NOT_LOADED; - } - else { - return m_rawContent["content"].toObject()["api_level"].toInt(); - } + if (!isLoaded()) { + return CONTENT_NOT_LOADED; + } + else { + return m_rawContent["content"].toObject()["api_level"].toInt(); + } } QString TtRssLoginResponse::sessionId() const { - if (!isLoaded()) { - return QString(); - } - else { - return m_rawContent["content"].toObject()["session_id"].toString(); - } + if (!isLoaded()) { + return QString(); + } + else { + return m_rawContent["content"].toObject()["session_id"].toString(); + } } QString TtRssResponse::error() const { - if (!isLoaded()) { - return QString(); - } - else { - return m_rawContent["content"].toObject()["error"].toString(); - } + if (!isLoaded()) { + return QString(); + } + else { + return m_rawContent["content"].toObject()["error"].toString(); + } } bool TtRssResponse::hasError() const { - if (!isLoaded()) { - return false; - } - else { - return m_rawContent["content"].toObject().contains("error"); - } + if (!isLoaded()) { + return false; + } + else { + return m_rawContent["content"].toObject().contains("error"); + } } +TtRssGetFeedsCategoriesResponse::TtRssGetFeedsCategoriesResponse(const QString& raw_content) : TtRssResponse(raw_content) {} -TtRssGetFeedsCategoriesResponse::TtRssGetFeedsCategoriesResponse(const QString& raw_content) : TtRssResponse(raw_content) { -} - -TtRssGetFeedsCategoriesResponse::~TtRssGetFeedsCategoriesResponse() { -} +TtRssGetFeedsCategoriesResponse::~TtRssGetFeedsCategoriesResponse() {} RootItem* TtRssGetFeedsCategoriesResponse::feedsCategories(bool obtain_icons, QString base_address) const { - RootItem* parent = new RootItem(); - // Chop the "api/" from the end of the address. - base_address.chop(4); - qDebug("TT-RSS: Chopped base address to '%s' to get feed icons.", qPrintable(base_address)); + RootItem* parent = new RootItem(); - if (status() == API_STATUS_OK) { - // We have data, construct object tree according to data. - QJsonArray items_to_process = m_rawContent["content"].toObject()["categories"].toObject()["items"].toArray(); - QVector> pairs; + // Chop the "api/" from the end of the address. + base_address.chop(4); + qDebug("TT-RSS: Chopped base address to '%s' to get feed icons.", qPrintable(base_address)); - foreach (const QJsonValue& item, items_to_process) { - pairs.append(QPair(parent, item)); - } + if (status() == API_STATUS_OK) { + // We have data, construct object tree according to data. + QJsonArray items_to_process = m_rawContent["content"].toObject()["categories"].toObject()["items"].toArray(); - while (!pairs.isEmpty()) { - QPair pair = pairs.takeFirst(); - RootItem* act_parent = pair.first; - QJsonObject item = pair.second.toObject(); - int item_id = item["bare_id"].toInt(); - bool is_category = item.contains("type") && item["type"].toString() == GFT_TYPE_CATEGORY; + QVector> pairs; - if (item_id >= 0) { - if (is_category) { - if (item_id == 0) { - // This is "Uncategorized" category, all its feeds belong to top-level root. - if (item.contains("items")) { - foreach (const QJsonValue& child_feed, item["items"].toArray()) { - pairs.append(QPair(parent, child_feed)); - } - } - } - else { - TtRssCategory* category = new TtRssCategory(); - category->setTitle(item["name"].toString()); - category->setCustomId(item_id); - act_parent->appendChild(category); + foreach (const QJsonValue& item, items_to_process) { + pairs.append(QPair(parent, item)); + } - if (item.contains("items")) { - foreach (const QJsonValue& child, item["items"].toArray()) { - pairs.append(QPair(category, child)); - } - } - } - } - else { - // We have feed. - TtRssFeed* feed = new TtRssFeed(); + while (!pairs.isEmpty()) { + QPair pair = pairs.takeFirst(); + RootItem* act_parent = pair.first; + QJsonObject item = pair.second.toObject(); + int item_id = item["bare_id"].toInt(); + bool is_category = item.contains("type") && item["type"].toString() == GFT_TYPE_CATEGORY; - if (obtain_icons) { - QString icon_path = item["icon"].type() == QJsonValue::String ? item["icon"].toString() : QString(); + if (item_id >= 0) { + if (is_category) { + if (item_id == 0) { + // This is "Uncategorized" category, all its feeds belong to top-level root. + if (item.contains("items")) { + foreach (const QJsonValue& child_feed, item["items"].toArray()) { + pairs.append(QPair(parent, child_feed)); + } + } + } + else { + TtRssCategory* category = new TtRssCategory(); - if (!icon_path.isEmpty()) { - // Chop the "api/" suffix out and append - QString full_icon_address = base_address + QL1C('/') + icon_path; - QByteArray icon_data; + category->setTitle(item["name"].toString()); + category->setCustomId(item_id); + act_parent->appendChild(category); - if (NetworkFactory::performNetworkOperation(full_icon_address, DOWNLOAD_TIMEOUT, - QByteArray(), QString(), icon_data, - QNetworkAccessManager::GetOperation).first == QNetworkReply::NoError) { - // Icon downloaded, set it up. - QPixmap icon_pixmap; - icon_pixmap.loadFromData(icon_data); - feed->setIcon(QIcon(icon_pixmap)); - } - } - } + if (item.contains("items")) { + foreach (const QJsonValue& child, item["items"].toArray()) { + pairs.append(QPair(category, child)); + } + } + } + } + else { + // We have feed. + TtRssFeed* feed = new TtRssFeed(); - feed->setTitle(item["name"].toString()); - feed->setCustomId(item_id); - act_parent->appendChild(feed); - } - } - } - } + if (obtain_icons) { + QString icon_path = item["icon"].type() == QJsonValue::String ? item["icon"].toString() : QString(); - return parent; + if (!icon_path.isEmpty()) { + // Chop the "api/" suffix out and append + QString full_icon_address = base_address + QL1C('/') + icon_path; + QByteArray icon_data; + + if (NetworkFactory::performNetworkOperation(full_icon_address, DOWNLOAD_TIMEOUT, + QByteArray(), QString(), icon_data, + QNetworkAccessManager::GetOperation).first == QNetworkReply::NoError) { + // Icon downloaded, set it up. + QPixmap icon_pixmap; + + icon_pixmap.loadFromData(icon_data); + feed->setIcon(QIcon(icon_pixmap)); + } + } + } + + feed->setTitle(item["name"].toString()); + feed->setCustomId(item_id); + act_parent->appendChild(feed); + } + } + } + } + + return parent; } +TtRssGetHeadlinesResponse::TtRssGetHeadlinesResponse(const QString& raw_content) : TtRssResponse(raw_content) {} -TtRssGetHeadlinesResponse::TtRssGetHeadlinesResponse(const QString& raw_content) : TtRssResponse(raw_content) { -} - -TtRssGetHeadlinesResponse::~TtRssGetHeadlinesResponse() { -} +TtRssGetHeadlinesResponse::~TtRssGetHeadlinesResponse() {} QList TtRssGetHeadlinesResponse::messages() const { - QList messages; + QList messages; - foreach (const QJsonValue& item, m_rawContent["content"].toArray()) { - QJsonObject mapped = item.toObject(); - Message message; - message.m_author = mapped["author"].toString(); - message.m_isRead = !mapped["unread"].toBool(); - message.m_isImportant = mapped["marked"].toBool(); - message.m_contents = mapped["content"].toString(); - // Multiply by 1000 because Tiny Tiny RSS API does not include miliseconds in Unix - // date/time number. - message.m_created = TextFactory::parseDateTime(mapped["updated"].toDouble() * 1000); - message.m_createdFromFeed = true; - message.m_customId = QString::number(mapped["id"].toInt()); - message.m_feedId = mapped["feed_id"].toString(); - message.m_title = mapped["title"].toString(); - message.m_url = mapped["link"].toString(); + foreach (const QJsonValue& item, m_rawContent["content"].toArray()) { + QJsonObject mapped = item.toObject(); + Message message; - if (mapped.contains(QSL("attachments"))) { - // Process enclosures. - foreach (const QJsonValue& attachment, mapped["attachments"].toArray()) { - QJsonObject mapped_attachemnt = attachment.toObject(); - Enclosure enclosure; - enclosure.m_mimeType = mapped_attachemnt["content_type"].toString(); - enclosure.m_url = mapped_attachemnt["content_url"].toString(); - message.m_enclosures.append(enclosure); - } - } + message.m_author = mapped["author"].toString(); + message.m_isRead = !mapped["unread"].toBool(); + message.m_isImportant = mapped["marked"].toBool(); + message.m_contents = mapped["content"].toString(); - messages.append(message); - } + // Multiply by 1000 because Tiny Tiny RSS API does not include miliseconds in Unix + // date/time number. + message.m_created = TextFactory::parseDateTime(mapped["updated"].toDouble() * 1000); + message.m_createdFromFeed = true; + message.m_customId = QString::number(mapped["id"].toInt()); + message.m_feedId = mapped["feed_id"].toString(); + message.m_title = mapped["title"].toString(); + message.m_url = mapped["link"].toString(); - return messages; + if (mapped.contains(QSL("attachments"))) { + // Process enclosures. + foreach (const QJsonValue& attachment, mapped["attachments"].toArray()) { + QJsonObject mapped_attachemnt = attachment.toObject(); + Enclosure enclosure; + + enclosure.m_mimeType = mapped_attachemnt["content_type"].toString(); + enclosure.m_url = mapped_attachemnt["content_url"].toString(); + message.m_enclosures.append(enclosure); + } + } + + messages.append(message); + } + + return messages; } +TtRssUpdateArticleResponse::TtRssUpdateArticleResponse(const QString& raw_content) : TtRssResponse(raw_content) {} -TtRssUpdateArticleResponse::TtRssUpdateArticleResponse(const QString& raw_content) : TtRssResponse(raw_content) { -} - -TtRssUpdateArticleResponse::~TtRssUpdateArticleResponse() { -} +TtRssUpdateArticleResponse::~TtRssUpdateArticleResponse() {} QString TtRssUpdateArticleResponse::updateStatus() const { - if (m_rawContent.contains(QSL("content"))) { - return m_rawContent["content"].toObject()["status"].toString(); - } - else { - return QString(); - } + if (m_rawContent.contains(QSL("content"))) { + return m_rawContent["content"].toObject()["status"].toString(); + } + else { + return QString(); + } } int TtRssUpdateArticleResponse::articlesUpdated() const { - if (m_rawContent.contains(QSL("content"))) { - return m_rawContent["content"].toObject()["updated"].toInt(); - } - else { - return 0; - } + if (m_rawContent.contains(QSL("content"))) { + return m_rawContent["content"].toObject()["updated"].toInt(); + } + else { + return 0; + } } -TtRssSubscribeToFeedResponse::TtRssSubscribeToFeedResponse(const QString& raw_content) : TtRssResponse(raw_content) { -} +TtRssSubscribeToFeedResponse::TtRssSubscribeToFeedResponse(const QString& raw_content) : TtRssResponse(raw_content) {} -TtRssSubscribeToFeedResponse::~TtRssSubscribeToFeedResponse() { -} +TtRssSubscribeToFeedResponse::~TtRssSubscribeToFeedResponse() {} int TtRssSubscribeToFeedResponse::code() const { - if (m_rawContent.contains(QSL("content"))) { - return m_rawContent["content"].toObject()["status"].toObject()["code"].toInt(); - } - else { - return STF_UNKNOWN; - } + if (m_rawContent.contains(QSL("content"))) { + return m_rawContent["content"].toObject()["status"].toObject()["code"].toInt(); + } + else { + return STF_UNKNOWN; + } } +TtRssUnsubscribeFeedResponse::TtRssUnsubscribeFeedResponse(const QString& raw_content) : TtRssResponse(raw_content) {} -TtRssUnsubscribeFeedResponse::TtRssUnsubscribeFeedResponse(const QString& raw_content) : TtRssResponse(raw_content) { -} - -TtRssUnsubscribeFeedResponse::~TtRssUnsubscribeFeedResponse() { -} +TtRssUnsubscribeFeedResponse::~TtRssUnsubscribeFeedResponse() {} QString TtRssUnsubscribeFeedResponse::code() const { - if (m_rawContent.contains(QSL("content"))) { - QJsonObject map = m_rawContent["content"].toObject(); + if (m_rawContent.contains(QSL("content"))) { + QJsonObject map = m_rawContent["content"].toObject(); - if (map.contains(QSL("error"))) { - return map["error"].toString(); - } - else if (map.contains(QSL("status"))) { - return map["status"].toString(); - } - } + if (map.contains(QSL("error"))) { + return map["error"].toString(); + } + else if (map.contains(QSL("status"))) { + return map["status"].toString(); + } + } - return QString(); + return QString(); } diff --git a/src/services/tt-rss/network/ttrssnetworkfactory.h b/src/services/tt-rss/network/ttrssnetworkfactory.h index a14716fa5..06f2d9472 100755 --- a/src/services/tt-rss/network/ttrssnetworkfactory.h +++ b/src/services/tt-rss/network/ttrssnetworkfactory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,168 +21,167 @@ #include "core/message.h" -#include -#include -#include #include - +#include +#include +#include class RootItem; class TtRssFeed; class TtRssResponse { - public: - explicit TtRssResponse(const QString& raw_content = QString()); - virtual ~TtRssResponse(); + public: + explicit TtRssResponse(const QString& raw_content = QString()); + virtual ~TtRssResponse(); - bool isLoaded() const; + bool isLoaded() const; - int seq() const; - int status() const; - QString error() const; - bool hasError() const; - bool isNotLoggedIn() const; - QString toString() const; + int seq() const; + int status() const; + QString error() const; + bool hasError() const; + bool isNotLoggedIn() const; + QString toString() const; - protected: - QJsonObject m_rawContent; + protected: + QJsonObject m_rawContent; }; class TtRssLoginResponse : public TtRssResponse { - public: - explicit TtRssLoginResponse(const QString& raw_content = QString()); - virtual ~TtRssLoginResponse(); + public: + explicit TtRssLoginResponse(const QString& raw_content = QString()); + virtual ~TtRssLoginResponse(); - int apiLevel() const; - QString sessionId() const; + int apiLevel() const; + QString sessionId() const; }; class TtRssGetFeedsCategoriesResponse : public TtRssResponse { - public: - explicit TtRssGetFeedsCategoriesResponse(const QString& raw_content = QString()); - virtual ~TtRssGetFeedsCategoriesResponse(); + public: + explicit TtRssGetFeedsCategoriesResponse(const QString& raw_content = QString()); + virtual ~TtRssGetFeedsCategoriesResponse(); - // Returns tree of feeds/categories. - // Top-level root of the tree is not needed here. - // Returned items do not have primary IDs assigned. - RootItem* feedsCategories(bool obtain_icons, QString base_address = QString()) const; + // Returns tree of feeds/categories. + // Top-level root of the tree is not needed here. + // Returned items do not have primary IDs assigned. + RootItem* feedsCategories(bool obtain_icons, QString base_address = QString()) const; }; class TtRssGetHeadlinesResponse : public TtRssResponse { - public: - explicit TtRssGetHeadlinesResponse(const QString& raw_content = QString()); - virtual ~TtRssGetHeadlinesResponse(); + public: + explicit TtRssGetHeadlinesResponse(const QString& raw_content = QString()); + virtual ~TtRssGetHeadlinesResponse(); - QList messages() const; + QList messages() const; }; class TtRssUpdateArticleResponse : public TtRssResponse { - public: - explicit TtRssUpdateArticleResponse(const QString& raw_content = QString()); - virtual ~TtRssUpdateArticleResponse(); + public: + explicit TtRssUpdateArticleResponse(const QString& raw_content = QString()); + virtual ~TtRssUpdateArticleResponse(); - QString updateStatus() const; - int articlesUpdated() const; + QString updateStatus() const; + int articlesUpdated() const; }; class TtRssSubscribeToFeedResponse : public TtRssResponse { - public: - explicit TtRssSubscribeToFeedResponse(const QString& raw_content = QString()); - virtual ~TtRssSubscribeToFeedResponse(); + public: + explicit TtRssSubscribeToFeedResponse(const QString& raw_content = QString()); + virtual ~TtRssSubscribeToFeedResponse(); - int code() const; + int code() const; }; class TtRssUnsubscribeFeedResponse : public TtRssResponse { - public: - explicit TtRssUnsubscribeFeedResponse(const QString& raw_content = QString()); - virtual ~TtRssUnsubscribeFeedResponse(); + public: + explicit TtRssUnsubscribeFeedResponse(const QString& raw_content = QString()); + virtual ~TtRssUnsubscribeFeedResponse(); - QString code() const; + QString code() const; }; namespace UpdateArticle { - enum Mode { - SetToFalse = 0, - SetToTrue = 1, - Togggle = 2 - }; - - enum OperatingField { - Starred = 0, - Published = 1, - Unread = 2 - }; + enum Mode { + SetToFalse = 0, + SetToTrue = 1, + Togggle = 2 + }; + enum OperatingField { + Starred = 0, + Published = 1, + Unread = 2 + }; } class TtRssNetworkFactory { - public: - explicit TtRssNetworkFactory(); - virtual ~TtRssNetworkFactory(); + public: + explicit TtRssNetworkFactory(); + virtual ~TtRssNetworkFactory(); - QString url() const; - void setUrl(const QString& url); + QString url() const; + void setUrl(const QString& url); - QString username() const; - void setUsername(const QString& username); + QString username() const; + void setUsername(const QString& username); - QString password() const; - void setPassword(const QString& password); + QString password() const; + void setPassword(const QString& password); - bool authIsUsed() const; - void setAuthIsUsed(bool auth_is_used); + bool authIsUsed() const; + void setAuthIsUsed(bool auth_is_used); - QString authUsername() const; - void setAuthUsername(const QString& auth_username); + QString authUsername() const; + void setAuthUsername(const QString& auth_username); - QString authPassword() const; - void setAuthPassword(const QString& auth_password); + QString authPassword() const; + void setAuthPassword(const QString& auth_password); - bool forceServerSideUpdate() const; - void setForceServerSideUpdate(bool force_server_side_update); + bool forceServerSideUpdate() const; + void setForceServerSideUpdate(bool force_server_side_update); - // Metadata. - QDateTime lastLoginTime() const; - QNetworkReply::NetworkError lastError() const; + // Metadata. + QDateTime lastLoginTime() const; + QNetworkReply::NetworkError lastError() const; - // Operations. + // Operations. - // Logs user in. - TtRssLoginResponse login(); + // Logs user in. + TtRssLoginResponse login(); - // Logs user out. - TtRssResponse logout(); + // Logs user out. + TtRssResponse logout(); - // Gets feeds from the server. - TtRssGetFeedsCategoriesResponse getFeedsCategories(); + // Gets feeds from the server. + TtRssGetFeedsCategoriesResponse getFeedsCategories(); - // Gets headlines (messages) from the server. - TtRssGetHeadlinesResponse getHeadlines(int feed_id, int limit, int skip, - bool show_content, bool include_attachments, - bool sanitize); + // Gets headlines (messages) from the server. + TtRssGetHeadlinesResponse getHeadlines(int feed_id, int limit, int skip, + bool show_content, bool include_attachments, + bool sanitize); - TtRssUpdateArticleResponse updateArticles(const QStringList& ids, UpdateArticle::OperatingField field, - UpdateArticle::Mode mode); + TtRssUpdateArticleResponse updateArticles(const QStringList& ids, UpdateArticle::OperatingField field, + UpdateArticle::Mode mode); - TtRssSubscribeToFeedResponse subscribeToFeed(const QString& url, int category_id, bool protectd = false, - const QString& username = QString(), const QString& password = QString()); + TtRssSubscribeToFeedResponse subscribeToFeed(const QString& url, int category_id, bool protectd = false, + const QString& username = QString(), const QString& password = QString()); - TtRssUnsubscribeFeedResponse unsubscribeFeed(int feed_id); + TtRssUnsubscribeFeedResponse unsubscribeFeed(int feed_id); - //TtRssGetConfigResponse getConfig(); + //TtRssGetConfigResponse getConfig(); - private: - QString m_bareUrl; - QString m_fullUrl; - QString m_username; - QString m_password; - bool m_forceServerSideUpdate; - bool m_authIsUsed; - QString m_authUsername; - QString m_authPassword; - QString m_sessionId; - QDateTime m_lastLoginTime; - QNetworkReply::NetworkError m_lastError; + private: + QString m_bareUrl; + QString m_fullUrl; + QString m_username; + QString m_password; + bool m_forceServerSideUpdate; + bool m_authIsUsed; + QString m_authUsername; + QString m_authPassword; + QString m_sessionId; + QDateTime m_lastLoginTime; + + QNetworkReply::NetworkError m_lastError; }; #endif // TTRSSNETWORKFACTORY_H diff --git a/src/services/tt-rss/ttrsscategory.cpp b/src/services/tt-rss/ttrsscategory.cpp index 3f1f8ec5b..604ba0f11 100755 --- a/src/services/tt-rss/ttrsscategory.cpp +++ b/src/services/tt-rss/ttrsscategory.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,45 +22,43 @@ #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" #include "services/tt-rss/definitions.h" -#include "services/tt-rss/ttrssserviceroot.h" #include "services/tt-rss/network/ttrssnetworkfactory.h" +#include "services/tt-rss/ttrssserviceroot.h" #include - TtRssCategory::TtRssCategory(RootItem* parent) : Category(parent) { - setIcon(qApp->icons()->fromTheme(QSL("folder"))); + setIcon(qApp->icons()->fromTheme(QSL("folder"))); } TtRssCategory::TtRssCategory(const QSqlRecord& record) : Category(nullptr) { - setIcon(qApp->icons()->fromTheme(QSL("folder"))); - setId(record.value(CAT_DB_ID_INDEX).toInt()); - setTitle(record.value(CAT_DB_TITLE_INDEX).toString()); - setCustomId(record.value(CAT_DB_CUSTOM_ID_INDEX).toInt()); + setIcon(qApp->icons()->fromTheme(QSL("folder"))); + setId(record.value(CAT_DB_ID_INDEX).toInt()); + setTitle(record.value(CAT_DB_TITLE_INDEX).toString()); + setCustomId(record.value(CAT_DB_CUSTOM_ID_INDEX).toInt()); } -TtRssCategory::~TtRssCategory() { -} +TtRssCategory::~TtRssCategory() {} TtRssServiceRoot* TtRssCategory::serviceRoot() const { - return qobject_cast(getParentServiceRoot()); + return qobject_cast(getParentServiceRoot()); } bool TtRssCategory::markAsReadUnread(RootItem::ReadStatus status) { - const QStringList ids = serviceRoot()->customIDSOfMessagesForItem(this); - TtRssUpdateArticleResponse response = serviceRoot()->network()->updateArticles(ids, UpdateArticle::Unread, - status == RootItem::Unread ? - UpdateArticle::SetToTrue : - UpdateArticle::SetToFalse); + const QStringList ids = serviceRoot()->customIDSOfMessagesForItem(this); + TtRssUpdateArticleResponse response = serviceRoot()->network()->updateArticles(ids, UpdateArticle::Unread, + status == RootItem::Unread ? + UpdateArticle::SetToTrue : + UpdateArticle::SetToFalse); - if (serviceRoot()->network()->lastError() != QNetworkReply::NoError || response.updateStatus() != STATUS_OK) { - return false; - } - else { - return serviceRoot()->markFeedsReadUnread(getSubTreeFeeds(), status); - } + if (serviceRoot()->network()->lastError() != QNetworkReply::NoError || response.updateStatus() != STATUS_OK) { + return false; + } + else { + return serviceRoot()->markFeedsReadUnread(getSubTreeFeeds(), status); + } } bool TtRssCategory::cleanMessages(bool clear_only_read) { - return serviceRoot()->cleanFeeds(getSubTreeFeeds(), clear_only_read); + return serviceRoot()->cleanFeeds(getSubTreeFeeds(), clear_only_read); } diff --git a/src/services/tt-rss/ttrsscategory.h b/src/services/tt-rss/ttrsscategory.h index 3428f0d21..629f7c9b2 100755 --- a/src/services/tt-rss/ttrsscategory.h +++ b/src/services/tt-rss/ttrsscategory.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,20 +23,20 @@ #include - class TtRssServiceRoot; class TtRssCategory : public Category { - Q_OBJECT + Q_OBJECT - public: - explicit TtRssCategory(RootItem* parent = nullptr); - explicit TtRssCategory(const QSqlRecord& record); - virtual ~TtRssCategory(); + public: + explicit TtRssCategory(RootItem* parent = nullptr); + explicit TtRssCategory(const QSqlRecord& record); + virtual ~TtRssCategory(); - TtRssServiceRoot* serviceRoot() const; - bool markAsReadUnread(ReadStatus status); - bool cleanMessages(bool clear_only_read); + TtRssServiceRoot* serviceRoot() const; + + bool markAsReadUnread(ReadStatus status); + bool cleanMessages(bool clear_only_read); }; #endif // TTRSSCATEGORY_H diff --git a/src/services/tt-rss/ttrssfeed.cpp b/src/services/tt-rss/ttrssfeed.cpp index 0fb22af4e..145df54d5 100755 --- a/src/services/tt-rss/ttrssfeed.cpp +++ b/src/services/tt-rss/ttrssfeed.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -23,159 +24,160 @@ #include "miscellaneous/iconfactory.h" #include "miscellaneous/textfactory.h" #include "services/tt-rss/definitions.h" -#include "services/tt-rss/ttrssserviceroot.h" -#include "services/tt-rss/ttrsscategory.h" -#include "services/tt-rss/network/ttrssnetworkfactory.h" #include "services/tt-rss/gui/formttrssfeeddetails.h" +#include "services/tt-rss/network/ttrssnetworkfactory.h" +#include "services/tt-rss/ttrsscategory.h" +#include "services/tt-rss/ttrssserviceroot.h" #include - TtRssFeed::TtRssFeed(RootItem* parent) - : Feed(parent) { -} + : Feed(parent) {} TtRssFeed::TtRssFeed(const QSqlRecord& record) : Feed(nullptr) { - setTitle(record.value(FDS_DB_TITLE_INDEX).toString()); - setId(record.value(FDS_DB_ID_INDEX).toInt()); - setIcon(qApp->icons()->fromByteArray(record.value(FDS_DB_ICON_INDEX).toByteArray())); - setAutoUpdateType(static_cast(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt())); - setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt()); - setCustomId(record.value(FDS_DB_CUSTOM_ID_INDEX).toInt()); - qDebug("Custom ID of TT-RSS feed when loading from DB is '%s'.", qPrintable(record.value(FDS_DB_CUSTOM_ID_INDEX).toString())); + setTitle(record.value(FDS_DB_TITLE_INDEX).toString()); + setId(record.value(FDS_DB_ID_INDEX).toInt()); + setIcon(qApp->icons()->fromByteArray(record.value(FDS_DB_ICON_INDEX).toByteArray())); + setAutoUpdateType(static_cast(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt())); + setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt()); + setCustomId(record.value(FDS_DB_CUSTOM_ID_INDEX).toInt()); + qDebug("Custom ID of TT-RSS feed when loading from DB is '%s'.", qPrintable(record.value(FDS_DB_CUSTOM_ID_INDEX).toString())); } -TtRssFeed::~TtRssFeed() { -} +TtRssFeed::~TtRssFeed() {} TtRssServiceRoot* TtRssFeed::serviceRoot() const { - return qobject_cast(getParentServiceRoot()); + return qobject_cast(getParentServiceRoot()); } QVariant TtRssFeed::data(int column, int role) const { - switch (role) { - case Qt::ToolTipRole: - if (column == FDS_MODEL_TITLE_INDEX) { - QString auto_update_string; + switch (role) { + case Qt::ToolTipRole: + if (column == FDS_MODEL_TITLE_INDEX) { + QString auto_update_string; - switch (autoUpdateType()) { - case DontAutoUpdate: - //: Describes feed auto-update status. - auto_update_string = tr("does not use auto-update"); - break; + switch (autoUpdateType()) { + case DontAutoUpdate: - case DefaultAutoUpdate: - //: Describes feed auto-update status. - auto_update_string = tr("uses global settings"); - break; + //: Describes feed auto-update status. + auto_update_string = tr("does not use auto-update"); + break; - case SpecificAutoUpdate: - default: - //: Describes feed auto-update status. - auto_update_string = tr("uses specific settings " - "(%n minute(s) to next auto-update)", - 0, - autoUpdateRemainingInterval()); - break; - } + case DefaultAutoUpdate: - //: Tooltip for feed. - return tr("%1" - "%2\n\n" - "Auto-update status: %3").arg(title(), - description().isEmpty() ? QString() : QString('\n') + description(), - auto_update_string); - } - else { - return Feed::data(column, role); - } + //: Describes feed auto-update status. + auto_update_string = tr("uses global settings"); + break; - default: - return Feed::data(column, role); - } + case SpecificAutoUpdate: + default: + + //: Describes feed auto-update status. + auto_update_string = tr("uses specific settings " + "(%n minute(s) to next auto-update)", + 0, + autoUpdateRemainingInterval()); + break; + } + + //: Tooltip for feed. + return tr("%1" + "%2\n\n" + "Auto-update status: %3").arg(title(), + description().isEmpty() ? QString() : QString('\n') + description(), + auto_update_string); + } + else { + return Feed::data(column, role); + } + + default: + return Feed::data(column, role); + } } bool TtRssFeed::canBeEdited() const { - return true; + return true; } bool TtRssFeed::editViaGui() { - QPointer form_pointer = new FormTtRssFeedDetails(serviceRoot(), qApp->mainFormWidget()); - form_pointer.data()->addEditFeed(this, nullptr); - delete form_pointer.data(); - return false; + QPointer form_pointer = new FormTtRssFeedDetails(serviceRoot(), qApp->mainFormWidget()); + form_pointer.data()->addEditFeed(this, nullptr); + delete form_pointer.data(); + return false; } bool TtRssFeed::canBeDeleted() const { - return true; + return true; } bool TtRssFeed::deleteViaGui() { - TtRssUnsubscribeFeedResponse response = serviceRoot()->network()->unsubscribeFeed(customId()); + TtRssUnsubscribeFeedResponse response = serviceRoot()->network()->unsubscribeFeed(customId()); - if (response.code() == UFF_OK && removeItself()) { - serviceRoot()->requestItemRemoval(this); - return true; - } - else { - qWarning("TT-RSS: Unsubscribing from feed failed, received JSON: '%s'", qPrintable(response.toString())); - return false; - } + if (response.code() == UFF_OK && removeItself()) { + serviceRoot()->requestItemRemoval(this); + return true; + } + else { + qWarning("TT-RSS: Unsubscribing from feed failed, received JSON: '%s'", qPrintable(response.toString())); + return false; + } } bool TtRssFeed::markAsReadUnread(RootItem::ReadStatus status) { - serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status); - return getParentServiceRoot()->markFeedsReadUnread(QList() << this, status); + serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status); + return getParentServiceRoot()->markFeedsReadUnread(QList() << this, status); } bool TtRssFeed::cleanMessages(bool clear_only_read) { - return getParentServiceRoot()->cleanFeeds(QList() << this, clear_only_read); + return getParentServiceRoot()->cleanFeeds(QList() << this, clear_only_read); } bool TtRssFeed::editItself(TtRssFeed* new_feed_data) { - QSqlDatabase database = qApp->database()->connection("aa", DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection("aa", DatabaseFactory::FromSettings); - if (DatabaseQueries::editBaseFeed(database, id(), new_feed_data->autoUpdateType(), - new_feed_data->autoUpdateInitialInterval())) { - setAutoUpdateType(new_feed_data->autoUpdateType()); - setAutoUpdateInitialInterval(new_feed_data->autoUpdateInitialInterval()); - return true; - } - else { - return false; - } + if (DatabaseQueries::editBaseFeed(database, id(), new_feed_data->autoUpdateType(), + new_feed_data->autoUpdateInitialInterval())) { + setAutoUpdateType(new_feed_data->autoUpdateType()); + setAutoUpdateInitialInterval(new_feed_data->autoUpdateInitialInterval()); + return true; + } + else { + return false; + } } QList TtRssFeed::obtainNewMessages(bool* error_during_obtaining) { - QList messages; - int newly_added_messages = 0; - int limit = MAX_MESSAGES; - int skip = 0; + QList messages; + int newly_added_messages = 0; + int limit = MAX_MESSAGES; + int skip = 0; - do { - TtRssGetHeadlinesResponse headlines = serviceRoot()->network()->getHeadlines(customId(), limit, skip, - true, true, false); + do { + TtRssGetHeadlinesResponse headlines = serviceRoot()->network()->getHeadlines(customId(), limit, skip, + true, true, false); - if (serviceRoot()->network()->lastError() != QNetworkReply::NoError) { - setStatus(Feed::NetworkError); - *error_during_obtaining = true; - serviceRoot()->itemChanged(QList() << this); - return QList(); - } - else { - QList new_messages = headlines.messages(); - messages.append(new_messages); - newly_added_messages = new_messages.size(); - skip += newly_added_messages; - } - } - while (newly_added_messages > 0); + if (serviceRoot()->network()->lastError() != QNetworkReply::NoError) { + setStatus(Feed::NetworkError); + *error_during_obtaining = true; + serviceRoot()->itemChanged(QList() << this); + return QList(); + } + else { + QList new_messages = headlines.messages(); + messages.append(new_messages); + newly_added_messages = new_messages.size(); + skip += newly_added_messages; + } + } + while (newly_added_messages > 0); - *error_during_obtaining = false; - return messages; + *error_during_obtaining = false; + return messages; } bool TtRssFeed::removeItself() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - return DatabaseQueries::deleteFeed(database, customId(), serviceRoot()->accountId()); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + + return DatabaseQueries::deleteFeed(database, customId(), serviceRoot()->accountId()); } diff --git a/src/services/tt-rss/ttrssfeed.h b/src/services/tt-rss/ttrssfeed.h index 73059f872..cb477e066 100755 --- a/src/services/tt-rss/ttrssfeed.h +++ b/src/services/tt-rss/ttrssfeed.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -22,32 +23,32 @@ #include - class TtRssServiceRoot; class TtRssFeed : public Feed { - Q_OBJECT + Q_OBJECT - public: - explicit TtRssFeed(RootItem* parent = nullptr); - explicit TtRssFeed(const QSqlRecord& record); - virtual ~TtRssFeed(); + public: + explicit TtRssFeed(RootItem* parent = nullptr); + explicit TtRssFeed(const QSqlRecord& record); + virtual ~TtRssFeed(); - TtRssServiceRoot* serviceRoot() const; - QVariant data(int column, int role) const; - bool canBeEdited() const; - bool editViaGui(); - bool canBeDeleted() const; - bool deleteViaGui(); + TtRssServiceRoot* serviceRoot() const; - bool markAsReadUnread(ReadStatus status); - bool cleanMessages(bool clear_only_read); + QVariant data(int column, int role) const; + bool canBeEdited() const; + bool editViaGui(); + bool canBeDeleted() const; + bool deleteViaGui(); - bool editItself(TtRssFeed* new_feed_data); - bool removeItself(); + bool markAsReadUnread(ReadStatus status); + bool cleanMessages(bool clear_only_read); - private: - QList obtainNewMessages(bool* error_during_obtaining); + bool editItself(TtRssFeed* new_feed_data); + bool removeItself(); + + private: + QList obtainNewMessages(bool* error_during_obtaining); }; #endif // TTRSSFEED_H diff --git a/src/services/tt-rss/ttrssrecyclebin.cpp b/src/services/tt-rss/ttrssrecyclebin.cpp index febc97b69..ed56bf12f 100755 --- a/src/services/tt-rss/ttrssrecyclebin.cpp +++ b/src/services/tt-rss/ttrssrecyclebin.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -21,18 +22,15 @@ #include "services/tt-rss/network/ttrssnetworkfactory.h" #include "services/tt-rss/ttrssserviceroot.h" +TtRssRecycleBin::TtRssRecycleBin(RootItem* parent) : RecycleBin(parent) {} -TtRssRecycleBin::TtRssRecycleBin(RootItem* parent) : RecycleBin(parent) { -} - -TtRssRecycleBin::~TtRssRecycleBin() { -} +TtRssRecycleBin::~TtRssRecycleBin() {} TtRssServiceRoot* TtRssRecycleBin::serviceRoot() { - return qobject_cast(getParentServiceRoot()); + return qobject_cast(getParentServiceRoot()); } bool TtRssRecycleBin::markAsReadUnread(RootItem::ReadStatus status) { - serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status); - return RecycleBin::markAsReadUnread(status); + serviceRoot()->addMessageStatesToCache(getParentServiceRoot()->customIDSOfMessagesForItem(this), status); + return RecycleBin::markAsReadUnread(status); } diff --git a/src/services/tt-rss/ttrssrecyclebin.h b/src/services/tt-rss/ttrssrecyclebin.h index 1065cecd8..e6d4ae0e1 100755 --- a/src/services/tt-rss/ttrssrecyclebin.h +++ b/src/services/tt-rss/ttrssrecyclebin.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -20,18 +21,18 @@ #include "services/abstract/recyclebin.h" - class TtRssServiceRoot; class TtRssRecycleBin : public RecycleBin { - Q_OBJECT + Q_OBJECT - public: - explicit TtRssRecycleBin(RootItem* parent = nullptr); - virtual ~TtRssRecycleBin(); + public: + explicit TtRssRecycleBin(RootItem* parent = nullptr); + virtual ~TtRssRecycleBin(); - TtRssServiceRoot* serviceRoot(); - bool markAsReadUnread(ReadStatus status); + TtRssServiceRoot* serviceRoot(); + + bool markAsReadUnread(ReadStatus status); }; #endif // TTRSSRECYCLEBIN_H diff --git a/src/services/tt-rss/ttrssserviceentrypoint.cpp b/src/services/tt-rss/ttrssserviceentrypoint.cpp index 427c692b5..3b677480a 100755 --- a/src/services/tt-rss/ttrssserviceentrypoint.cpp +++ b/src/services/tt-rss/ttrssserviceentrypoint.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,60 +19,57 @@ #include "services/tt-rss/ttrssserviceentrypoint.h" #include "definitions/definitions.h" -#include "miscellaneous/iconfactory.h" #include "miscellaneous/databasequeries.h" +#include "miscellaneous/iconfactory.h" #include "services/tt-rss/definitions.h" -#include "services/tt-rss/ttrssserviceroot.h" #include "services/tt-rss/gui/formeditttrssaccount.h" +#include "services/tt-rss/ttrssserviceroot.h" #include +TtRssServiceEntryPoint::TtRssServiceEntryPoint() {} -TtRssServiceEntryPoint::TtRssServiceEntryPoint() { -} - - -TtRssServiceEntryPoint::~TtRssServiceEntryPoint() { -} +TtRssServiceEntryPoint::~TtRssServiceEntryPoint() {} bool TtRssServiceEntryPoint::isSingleInstanceService() const { - return false; + return false; } QString TtRssServiceEntryPoint::name() const { - return QSL("Tiny Tiny RSS"); + return QSL("Tiny Tiny RSS"); } QString TtRssServiceEntryPoint::description() const { - return QObject::tr("This service offers integration with Tiny Tiny RSS.\n\n" - "Tiny Tiny RSS is an open source web-based news feed (RSS/Atom) reader and aggregator, " - "designed to allow you to read news from any location, while feeling as close to a real " - "desktop application as possible.\n\nAt least API level %1 is required.").arg(MINIMAL_API_LEVEL); + return QObject::tr("This service offers integration with Tiny Tiny RSS.\n\n" + "Tiny Tiny RSS is an open source web-based news feed (RSS/Atom) reader and aggregator, " + "designed to allow you to read news from any location, while feeling as close to a real " + "desktop application as possible.\n\nAt least API level %1 is required.").arg(MINIMAL_API_LEVEL); } QString TtRssServiceEntryPoint::version() const { - return APP_VERSION; + return APP_VERSION; } QString TtRssServiceEntryPoint::author() const { - return APP_AUTHOR; + return APP_AUTHOR; } QIcon TtRssServiceEntryPoint::icon() const { - return qApp->icons()->miscIcon(QSL("tt-rss")); + return qApp->icons()->miscIcon(QSL("tt-rss")); } QString TtRssServiceEntryPoint::code() const { - return SERVICE_CODE_TT_RSS; + return SERVICE_CODE_TT_RSS; } ServiceRoot* TtRssServiceEntryPoint::createNewRoot() const { - QScopedPointer form_acc(new FormEditTtRssAccount(qApp->mainFormWidget())); - return form_acc->execForCreate(); + QScopedPointer form_acc(new FormEditTtRssAccount(qApp->mainFormWidget())); + return form_acc->execForCreate(); } QList TtRssServiceEntryPoint::initializeSubtree() const { - // Check DB if standard account is enabled. - QSqlDatabase database = qApp->database()->connection(QSL("TtRssServiceEntryPoint"), DatabaseFactory::FromSettings); - return DatabaseQueries::getTtRssAccounts(database); + // Check DB if standard account is enabled. + QSqlDatabase database = qApp->database()->connection(QSL("TtRssServiceEntryPoint"), DatabaseFactory::FromSettings); + + return DatabaseQueries::getTtRssAccounts(database); } diff --git a/src/services/tt-rss/ttrssserviceentrypoint.h b/src/services/tt-rss/ttrssserviceentrypoint.h index ebe3ec0fa..2ec6801b3 100755 --- a/src/services/tt-rss/ttrssserviceentrypoint.h +++ b/src/services/tt-rss/ttrssserviceentrypoint.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -15,28 +16,27 @@ // You should have received a copy of the GNU General Public License // along with RSS Guard. If not, see . - #ifndef TTRSSSERVICEENTRYPOINT_H #define TTRSSSERVICEENTRYPOINT_H #include "services/abstract/serviceentrypoint.h" - class TtRssServiceEntryPoint : public ServiceEntryPoint { - public: - explicit TtRssServiceEntryPoint(); - virtual ~TtRssServiceEntryPoint(); + public: + explicit TtRssServiceEntryPoint(); + virtual ~TtRssServiceEntryPoint(); - bool isSingleInstanceService() const; - QString name() const; - QString description() const; - QString version() const; - QString author() const; - QIcon icon() const; - QString code() const; + bool isSingleInstanceService() const; + QString name() const; + QString description() const; + QString version() const; + QString author() const; + QIcon icon() const; + QString code() const; - ServiceRoot* createNewRoot() const; - QList initializeSubtree() const; + ServiceRoot* createNewRoot() const; + + QList initializeSubtree() const; }; #endif // TTRSSSERVICEENTRYPOINT_H diff --git a/src/services/tt-rss/ttrssserviceroot.cpp b/src/services/tt-rss/ttrssserviceroot.cpp index b33ef2240..eb37ea35c 100755 --- a/src/services/tt-rss/ttrssserviceroot.cpp +++ b/src/services/tt-rss/ttrssserviceroot.cpp @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,312 +19,319 @@ #include "services/tt-rss/ttrssserviceroot.h" #include "miscellaneous/application.h" -#include "miscellaneous/settings.h" -#include "miscellaneous/mutex.h" -#include "miscellaneous/textfactory.h" #include "miscellaneous/databasequeries.h" -#include "network-web/networkfactory.h" #include "miscellaneous/iconfactory.h" -#include "services/tt-rss/ttrssserviceentrypoint.h" -#include "services/tt-rss/ttrssfeed.h" -#include "services/tt-rss/ttrssrecyclebin.h" -#include "services/tt-rss/ttrsscategory.h" +#include "miscellaneous/mutex.h" +#include "miscellaneous/settings.h" +#include "miscellaneous/textfactory.h" +#include "network-web/networkfactory.h" #include "services/tt-rss/definitions.h" -#include "services/tt-rss/network/ttrssnetworkfactory.h" #include "services/tt-rss/gui/formeditttrssaccount.h" #include "services/tt-rss/gui/formttrssfeeddetails.h" +#include "services/tt-rss/network/ttrssnetworkfactory.h" +#include "services/tt-rss/ttrsscategory.h" +#include "services/tt-rss/ttrssfeed.h" +#include "services/tt-rss/ttrssrecyclebin.h" +#include "services/tt-rss/ttrssserviceentrypoint.h" -#include -#include #include - +#include +#include TtRssServiceRoot::TtRssServiceRoot(RootItem* parent) - : ServiceRoot(parent), CacheForServiceRoot(), m_recycleBin(new TtRssRecycleBin(this)), - m_actionSyncIn(nullptr), m_serviceMenu(QList()), m_network(new TtRssNetworkFactory()) { - setIcon(TtRssServiceEntryPoint().icon()); + : ServiceRoot(parent), CacheForServiceRoot(), m_recycleBin(new TtRssRecycleBin(this)), + m_actionSyncIn(nullptr), m_serviceMenu(QList()), m_network(new TtRssNetworkFactory()) { + setIcon(TtRssServiceEntryPoint().icon()); } TtRssServiceRoot::~TtRssServiceRoot() { - delete m_network; + delete m_network; } void TtRssServiceRoot::start(bool freshly_activated) { - Q_UNUSED(freshly_activated) - loadFromDatabase(); + Q_UNUSED(freshly_activated) + loadFromDatabase(); loadCacheFromFile(accountId()); - if (qApp->isFirstRun(QSL("3.1.1")) || (childCount() == 1 && child(0)->kind() == RootItemKind::Bin)) { - syncIn(); - } + if (qApp->isFirstRun(QSL("3.1.1")) || (childCount() == 1 && child(0)->kind() == RootItemKind::Bin)) { + syncIn(); + } } void TtRssServiceRoot::stop() { saveCacheToFile(accountId()); - m_network->logout(); - qDebug("Stopping Tiny Tiny RSS account, logging out with result '%d'.", (int) m_network->lastError()); + m_network->logout(); + qDebug("Stopping Tiny Tiny RSS account, logging out with result '%d'.", (int) m_network->lastError()); } QString TtRssServiceRoot::code() const { - return TtRssServiceEntryPoint().code(); + return TtRssServiceEntryPoint().code(); } bool TtRssServiceRoot::editViaGui() { - QScopedPointer form_pointer(new FormEditTtRssAccount(qApp->mainFormWidget())); - form_pointer.data()->execForEdit(this); - return true; + QScopedPointer form_pointer(new FormEditTtRssAccount(qApp->mainFormWidget())); + form_pointer.data()->execForEdit(this); + return true; } bool TtRssServiceRoot::deleteViaGui() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - // Remove extra entry in "Tiny Tiny RSS accounts list" and then delete - // all the categories/feeds and messages. - if (DatabaseQueries::deleteTtRssAccount(database, accountId())) { - return ServiceRoot::deleteViaGui(); - } - else { - return false; - } + // Remove extra entry in "Tiny Tiny RSS accounts list" and then delete + // all the categories/feeds and messages. + if (DatabaseQueries::deleteTtRssAccount(database, accountId())) { + return ServiceRoot::deleteViaGui(); + } + else { + return false; + } } bool TtRssServiceRoot::markAsReadUnread(RootItem::ReadStatus status) { - addMessageStatesToCache(customIDSOfMessagesForItem(this), status); - return ServiceRoot::markAsReadUnread(status); + addMessageStatesToCache(customIDSOfMessagesForItem(this), status); + return ServiceRoot::markAsReadUnread(status); } bool TtRssServiceRoot::supportsFeedAdding() const { - return true; + return true; } bool TtRssServiceRoot::supportsCategoryAdding() const { - return false; + return false; } void TtRssServiceRoot::addNewFeed(const QString& url) { - if (!qApp->feedUpdateLock()->tryLock()) { - // Lock was not obtained because - // it is used probably by feed updater or application - // is quitting. - qApp->showGuiMessage(tr("Cannot add item"), - tr("Cannot add feed because another critical operation is ongoing."), - QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - // Thus, cannot delete and quit the method. - return; - } + if (!qApp->feedUpdateLock()->tryLock()) { + // Lock was not obtained because + // it is used probably by feed updater or application + // is quitting. + qApp->showGuiMessage(tr("Cannot add item"), + tr("Cannot add feed because another critical operation is ongoing."), + QSystemTrayIcon::Warning, qApp->mainFormWidget(), true); - QScopedPointer form_pointer(new FormTtRssFeedDetails(this, qApp->mainFormWidget())); - form_pointer.data()->addEditFeed(nullptr, this, url); - qApp->feedUpdateLock()->unlock(); + // Thus, cannot delete and quit the method. + return; + } + + QScopedPointer form_pointer(new FormTtRssFeedDetails(this, qApp->mainFormWidget())); + form_pointer.data()->addEditFeed(nullptr, this, url); + qApp->feedUpdateLock()->unlock(); } void TtRssServiceRoot::addNewCategory() { - // NOTE: Do nothing. + // NOTE: Do nothing. } bool TtRssServiceRoot::canBeEdited() const { - return true; + return true; } bool TtRssServiceRoot::canBeDeleted() const { - return true; + return true; } QVariant TtRssServiceRoot::data(int column, int role) const { - switch (role) { - case Qt::ToolTipRole: - if (column == FDS_MODEL_TITLE_INDEX) { - return tr("Tiny Tiny RSS\n\nAccount ID: %3\nUsername: %1\nServer: %2\n" - "Last error: %4\nLast login on: %5").arg(m_network->username(), - m_network->url(), - QString::number(accountId()), - NetworkFactory::networkErrorText(m_network->lastError()), - m_network->lastLoginTime().isValid() ? - m_network->lastLoginTime().toString(Qt::DefaultLocaleShortDate) : - QSL("-")); - } - else { - return ServiceRoot::data(column, role); - } + switch (role) { + case Qt::ToolTipRole: + if (column == FDS_MODEL_TITLE_INDEX) { + return tr("Tiny Tiny RSS\n\nAccount ID: %3\nUsername: %1\nServer: %2\n" + "Last error: %4\nLast login on: %5").arg(m_network->username(), + m_network->url(), + QString::number(accountId()), + NetworkFactory::networkErrorText(m_network->lastError()), + m_network->lastLoginTime().isValid() ? + m_network->lastLoginTime().toString(Qt::DefaultLocaleShortDate) : + QSL("-")); + } + else { + return ServiceRoot::data(column, role); + } - default: - return ServiceRoot::data(column, role); - } + default: + return ServiceRoot::data(column, role); + } } RecycleBin* TtRssServiceRoot::recycleBin() const { - return m_recycleBin; + return m_recycleBin; } void TtRssServiceRoot::saveAllCachedData() { - QPair, QMap>> msgCache = takeMessageCache(); - QMapIterator i(msgCache.first); + QPair, QMap>> msgCache = takeMessageCache(); + QMapIterator i(msgCache.first); - // Save the actual data read/unread. - while (i.hasNext()) { - i.next(); - auto key = i.key(); - QStringList ids = i.value(); + // Save the actual data read/unread. + while (i.hasNext()) { + i.next(); + auto key = i.key(); + QStringList ids = i.value(); - if (!ids.isEmpty()) { - network()->updateArticles(ids, - UpdateArticle::Unread, - key == RootItem::Unread ? UpdateArticle::SetToTrue : UpdateArticle::SetToFalse); - } - } + if (!ids.isEmpty()) { + network()->updateArticles(ids, + UpdateArticle::Unread, + key == RootItem::Unread ? UpdateArticle::SetToTrue : UpdateArticle::SetToFalse); + } + } - QMapIterator> j(msgCache.second); + QMapIterator> j(msgCache.second); - // Save the actual data important/not important. - while (j.hasNext()) { - j.next(); - auto key = j.key(); - QList messages = j.value(); + // Save the actual data important/not important. + while (j.hasNext()) { + j.next(); + auto key = j.key(); - if (!messages.isEmpty()) { - QStringList ids = customIDsOfMessages(messages); - network()->updateArticles(ids, - UpdateArticle::Starred, - key == RootItem::Important ? UpdateArticle::SetToTrue : UpdateArticle::SetToFalse); - } - } + QList messages = j.value(); + + if (!messages.isEmpty()) { + QStringList ids = customIDsOfMessages(messages); + + network()->updateArticles(ids, + UpdateArticle::Starred, + key == RootItem::Important ? UpdateArticle::SetToTrue : UpdateArticle::SetToFalse); + } + } } QList TtRssServiceRoot::serviceMenu() { - if (m_serviceMenu.isEmpty()) { - m_actionSyncIn = new QAction(qApp->icons()->fromTheme(QSL("view-refresh")), tr("Sync in"), this); - connect(m_actionSyncIn, &QAction::triggered, this, &TtRssServiceRoot::syncIn); - m_serviceMenu.append(m_actionSyncIn); - } + if (m_serviceMenu.isEmpty()) { + m_actionSyncIn = new QAction(qApp->icons()->fromTheme(QSL("view-refresh")), tr("Sync in"), this); + connect(m_actionSyncIn, &QAction::triggered, this, &TtRssServiceRoot::syncIn); + m_serviceMenu.append(m_actionSyncIn); + } - return m_serviceMenu; + return m_serviceMenu; } bool TtRssServiceRoot::onBeforeSetMessagesRead(RootItem* selected_item, const QList& messages, RootItem::ReadStatus read) { - Q_UNUSED(selected_item) - addMessageStatesToCache(customIDsOfMessages(messages), read); - return true; + Q_UNUSED(selected_item) + addMessageStatesToCache(customIDsOfMessages(messages), read); + return true; } bool TtRssServiceRoot::onBeforeSwitchMessageImportance(RootItem* selected_item, const QList& changes) { - Q_UNUSED(selected_item) - // Now, we need to separate the changes because of ownCloud API limitations. - QList mark_starred_msgs; - QList mark_unstarred_msgs; + Q_UNUSED(selected_item) - foreach (const ImportanceChange& pair, changes) { - if (pair.second == RootItem::Important) { - mark_starred_msgs.append(pair.first); - } - else { - mark_unstarred_msgs.append(pair.first); - } - } + // Now, we need to separate the changes because of ownCloud API limitations. + QList mark_starred_msgs; + QList mark_unstarred_msgs; - if (!mark_starred_msgs.isEmpty()) { - addMessageStatesToCache(mark_starred_msgs, RootItem::Important); - } + foreach (const ImportanceChange& pair, changes) { + if (pair.second == RootItem::Important) { + mark_starred_msgs.append(pair.first); + } + else { + mark_unstarred_msgs.append(pair.first); + } + } - if (!mark_unstarred_msgs.isEmpty()) { - addMessageStatesToCache(mark_unstarred_msgs, RootItem::NotImportant); - } + if (!mark_starred_msgs.isEmpty()) { + addMessageStatesToCache(mark_starred_msgs, RootItem::Important); + } - return true; + if (!mark_unstarred_msgs.isEmpty()) { + addMessageStatesToCache(mark_unstarred_msgs, RootItem::NotImportant); + } + + return true; } TtRssNetworkFactory* TtRssServiceRoot::network() const { - return m_network; + return m_network; } void TtRssServiceRoot::saveAccountDataToDatabase() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - if (accountId() != NO_PARENT_CATEGORY) { - // We are overwritting previously saved data. - if (DatabaseQueries::overwriteTtRssAccount(database, m_network->username(), m_network->password(), - m_network->authIsUsed(), m_network->authUsername(), - m_network->authPassword(), m_network->url(), - m_network->forceServerSideUpdate(), accountId())) { - updateTitle(); - itemChanged(QList() << this); - } - } - else { - bool saved; - int id_to_assign = DatabaseQueries::createAccount(database, code(), &saved); + if (accountId() != NO_PARENT_CATEGORY) { + // We are overwritting previously saved data. + if (DatabaseQueries::overwriteTtRssAccount(database, m_network->username(), m_network->password(), + m_network->authIsUsed(), m_network->authUsername(), + m_network->authPassword(), m_network->url(), + m_network->forceServerSideUpdate(), accountId())) { + updateTitle(); + itemChanged(QList() << this); + } + } + else { + bool saved; + int id_to_assign = DatabaseQueries::createAccount(database, code(), &saved); - if (saved) { - if (DatabaseQueries::createTtRssAccount(database, id_to_assign, m_network->username(), - m_network->password(), m_network->authIsUsed(), - m_network->authUsername(), m_network->authPassword(), - m_network->url(), m_network->forceServerSideUpdate())) { - setId(id_to_assign); - setAccountId(id_to_assign); - updateTitle(); - } - } - } + if (saved) { + if (DatabaseQueries::createTtRssAccount(database, id_to_assign, m_network->username(), + m_network->password(), m_network->authIsUsed(), + m_network->authUsername(), m_network->authPassword(), + m_network->url(), m_network->forceServerSideUpdate())) { + setId(id_to_assign); + setAccountId(id_to_assign); + updateTitle(); + } + } + } } void TtRssServiceRoot::loadFromDatabase() { - QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); - Assignment categories = DatabaseQueries::getTtRssCategories(database, accountId()); - Assignment feeds = DatabaseQueries::getTtRssFeeds(database, accountId()); - // All data are now obtained, lets create the hierarchy. - assembleCategories(categories); - assembleFeeds(feeds); - // As the last item, add recycle bin, which is needed. - appendChild(m_recycleBin); - updateCounts(true); + QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings); + Assignment categories = DatabaseQueries::getTtRssCategories(database, accountId()); + Assignment feeds = DatabaseQueries::getTtRssFeeds(database, accountId()); + + // All data are now obtained, lets create the hierarchy. + assembleCategories(categories); + assembleFeeds(feeds); + + // As the last item, add recycle bin, which is needed. + appendChild(m_recycleBin); + updateCounts(true); } void TtRssServiceRoot::updateTitle() { - QString host = QUrl(m_network->url()).host(); + QString host = QUrl(m_network->url()).host(); - if (host.isEmpty()) { - host = m_network->url(); - } + if (host.isEmpty()) { + host = m_network->url(); + } - setTitle(m_network->username() + QL1S("@") + host + QSL(" (Tiny Tiny RSS)")); + setTitle(m_network->username() + QL1S("@") + host + QSL(" (Tiny Tiny RSS)")); } RootItem* TtRssServiceRoot::obtainNewTreeForSyncIn() const { - TtRssGetFeedsCategoriesResponse feed_cats_response = m_network->getFeedsCategories(); + TtRssGetFeedsCategoriesResponse feed_cats_response = m_network->getFeedsCategories(); - if (m_network->lastError() == QNetworkReply::NoError) { - return feed_cats_response.feedsCategories(true, m_network->url()); - } - else { - return nullptr; - } + if (m_network->lastError() == QNetworkReply::NoError) { + return feed_cats_response.feedsCategories(true, m_network->url()); + } + else { + return nullptr; + } } QMap TtRssServiceRoot::storeCustomFeedsData() { - QMap custom_data; + QMap custom_data; - foreach (const Feed* feed, getSubTreeFeeds()) { - QVariantMap feed_custom_data; - feed_custom_data.insert(QSL("auto_update_interval"), feed->autoUpdateInitialInterval()); - feed_custom_data.insert(QSL("auto_update_type"), feed->autoUpdateType()); - custom_data.insert(feed->customId(), feed_custom_data); - } + foreach (const Feed* feed, getSubTreeFeeds()) { + QVariantMap feed_custom_data; - return custom_data; + feed_custom_data.insert(QSL("auto_update_interval"), feed->autoUpdateInitialInterval()); + feed_custom_data.insert(QSL("auto_update_type"), feed->autoUpdateType()); + custom_data.insert(feed->customId(), feed_custom_data); + } + + return custom_data; } void TtRssServiceRoot::restoreCustomFeedsData(const QMap& data, const QHash& feeds) { - QMapIterator i(data); + QMapIterator i(data); - while (i.hasNext()) { - i.next(); - const int custom_id = i.key(); + while (i.hasNext()) { + i.next(); + const int custom_id = i.key(); - if (feeds.contains(custom_id)) { - Feed* feed = feeds.value(custom_id); - QVariantMap feed_custom_data = i.value().toMap(); - feed->setAutoUpdateInitialInterval(feed_custom_data.value(QSL("auto_update_interval")).toInt()); - feed->setAutoUpdateType(static_cast(feed_custom_data.value(QSL("auto_update_type")).toInt())); - } - } + if (feeds.contains(custom_id)) { + Feed* feed = feeds.value(custom_id); + QVariantMap feed_custom_data = i.value().toMap(); + + feed->setAutoUpdateInitialInterval(feed_custom_data.value(QSL("auto_update_interval")).toInt()); + feed->setAutoUpdateType(static_cast(feed_custom_data.value(QSL("auto_update_type")).toInt())); + } + } } diff --git a/src/services/tt-rss/ttrssserviceroot.h b/src/services/tt-rss/ttrssserviceroot.h index 6a8de0c5e..5f211f3fe 100755 --- a/src/services/tt-rss/ttrssserviceroot.h +++ b/src/services/tt-rss/ttrssserviceroot.h @@ -1,4 +1,5 @@ // This file is part of RSS Guard. + // // Copyright (C) 2011-2017 by Martin Rotter // @@ -18,63 +19,65 @@ #ifndef TTRSSSERVICEROOT_H #define TTRSSSERVICEROOT_H -#include "services/abstract/serviceroot.h" #include "services/abstract/cacheforserviceroot.h" +#include "services/abstract/serviceroot.h" #include - class TtRssCategory; class TtRssFeed; class TtRssNetworkFactory; class TtRssRecycleBin; class TtRssServiceRoot : public ServiceRoot, public CacheForServiceRoot { - Q_OBJECT + Q_OBJECT - public: - explicit TtRssServiceRoot(RootItem* parent = nullptr); - virtual ~TtRssServiceRoot(); + public: + explicit TtRssServiceRoot(RootItem* parent = nullptr); + virtual ~TtRssServiceRoot(); - void start(bool freshly_activated); - void stop(); - QString code() const; - bool canBeEdited() const; - bool canBeDeleted() const; - bool editViaGui(); - bool deleteViaGui(); - bool markAsReadUnread(ReadStatus status); - bool supportsFeedAdding() const; - bool supportsCategoryAdding() const; - QVariant data(int column, int role) const; - QList serviceMenu(); - RecycleBin* recycleBin() const; - void saveAllCachedData(); + void start(bool freshly_activated); + void stop(); + QString code() const; + bool canBeEdited() const; + bool canBeDeleted() const; + bool editViaGui(); + bool deleteViaGui(); + bool markAsReadUnread(ReadStatus status); + bool supportsFeedAdding() const; + bool supportsCategoryAdding() const; + QVariant data(int column, int role) const; + QList serviceMenu(); + RecycleBin* recycleBin() const; - bool onBeforeSetMessagesRead(RootItem* selected_item, const QList& messages, ReadStatus read); - bool onBeforeSwitchMessageImportance(RootItem* selected_item, const QList& changes); + void saveAllCachedData(); - // Access to network. - TtRssNetworkFactory* network() const; + bool onBeforeSetMessagesRead(RootItem* selected_item, const QList& messages, ReadStatus read); + bool onBeforeSwitchMessageImportance(RootItem* selected_item, const QList& changes); - void saveAccountDataToDatabase(); - void updateTitle(); + // Access to network. + TtRssNetworkFactory* network() const; - public slots: - void addNewFeed(const QString& url = QString()); - void addNewCategory(); + void saveAccountDataToDatabase(); + void updateTitle(); - private: - RootItem* obtainNewTreeForSyncIn() const; - QMap storeCustomFeedsData(); - void restoreCustomFeedsData(const QMap& data, const QHash& feeds); + public slots: + void addNewFeed(const QString& url = QString()); + void addNewCategory(); - void loadFromDatabase(); + private: + RootItem* obtainNewTreeForSyncIn() const; - TtRssRecycleBin* m_recycleBin; - QAction* m_actionSyncIn; - QList m_serviceMenu; - TtRssNetworkFactory* m_network; + QMap storeCustomFeedsData(); + void restoreCustomFeedsData(const QMap& data, const QHash& feeds); + + void loadFromDatabase(); + + TtRssRecycleBin* m_recycleBin; + QAction* m_actionSyncIn; + + QList m_serviceMenu; + TtRssNetworkFactory* m_network; }; #endif // TTRSSSERVICEROOT_H