Reformated using astyle, added some astyle scripts.

This commit is contained in:
Martin Rotter 2017-07-21 06:53:23 +02:00
parent 14473722b0
commit 208284e80d
304 changed files with 34084 additions and 34464 deletions

26
.astylerc Executable file
View file

@ -0,0 +1,26 @@
--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=all
--unpad-paren
--delete-empty-lines
--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=200
--lineend=linux
-t -p
-M60Ucv

64
astyle-format-all.sh Executable file
View file

@ -0,0 +1,64 @@
#!/bin/bash
#
# This file is part of RSS Guard.
#
# Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
# Copyright (C) 2010-2014 by David Rosca <nowrep@gmail.com>
#
# RSS Guard is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# RSS Guard is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RSS Guard. If not, see <http:#www.gnu.org/licenses/>.
function usage {
echo "Usage: $0 \"root-directory\"..."
exit 1
}
if [ $# -eq 0 ]; then
usage
fi
ASTYLE_CMD="astyle"
ASTYLE_RC=".astylerc"
# Check all args.
for dir in "$@"; do
if [ ! -d "${dir}" ]; then
echo "\"${dir}\" is not a directory..."
usage
fi
done
# Run the thing.
for dir in "$@"; do
pushd "${dir}"
if [ ! -r "$ASTYLE_RC" ]; then
echo "No $ASTYLE_RC in pwd \"$PWD\"..."
continue
fi
for f in $(find . \
-name '*.c' \
-o -name '*.cc' \
-o -name '*.cpp' \
-o -name '*.h' \
-o -name '*.hh' \
-o -name '*.hpp'); do
"${ASTYLE_CMD}" --options="$ASTYLE_RC" "${f}"
done
# Remove backup files.
find . -name "*.orig" | xargs --no-run-if-empty rm -v
popd
done

View file

@ -1,178 +1,170 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "core/feeddownloader.h" #include "core/feeddownloader.h"
#include "services/abstract/feed.h" #include "services/abstract/feed.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include <QThread> #include <QThread>
#include <QDebug> #include <QDebug>
#include <QThreadPool> #include <QThreadPool>
#include <QMutexLocker> #include <QMutexLocker>
#include <QString> #include <QString>
FeedDownloader::FeedDownloader(QObject *parent) FeedDownloader::FeedDownloader(QObject* parent)
: QObject(parent), m_feeds(QList<Feed*>()), m_mutex(new QMutex()), m_threadPool(new QThreadPool(this)), : QObject(parent), m_feeds(QList<Feed*>()), m_mutex(new QMutex()), m_threadPool(new QThreadPool(this)),
m_results(FeedDownloadResults()), m_feedsUpdated(0), m_results(FeedDownloadResults()), m_feedsUpdated(0),
m_feedsUpdating(0), m_feedsOriginalCount(0) { m_feedsUpdating(0), m_feedsOriginalCount(0) {
qRegisterMetaType<FeedDownloadResults>("FeedDownloadResults"); qRegisterMetaType<FeedDownloadResults>("FeedDownloadResults");
m_threadPool->setMaxThreadCount(FEED_DOWNLOADER_MAX_THREADS); m_threadPool->setMaxThreadCount(FEED_DOWNLOADER_MAX_THREADS);
} }
FeedDownloader::~FeedDownloader() { FeedDownloader::~FeedDownloader() {
m_mutex->tryLock(); m_mutex->tryLock();
m_mutex->unlock(); m_mutex->unlock();
delete m_mutex; delete m_mutex;
qDebug("Destroying FeedDownloader instance.");
qDebug("Destroying FeedDownloader instance."); }
}
bool FeedDownloader::isUpdateRunning() const {
bool FeedDownloader::isUpdateRunning() const { return !m_feeds.isEmpty() || m_feedsUpdating > 0;
return !m_feeds.isEmpty() || m_feedsUpdating > 0; }
}
void FeedDownloader::updateAvailableFeeds() {
void FeedDownloader::updateAvailableFeeds() { while (!m_feeds.isEmpty()) {
while (!m_feeds.isEmpty()) { connect(m_feeds.first(), &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished,
connect(m_feeds.first(), &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished, (Qt::ConnectionType)(Qt::UniqueConnection | Qt::AutoConnection));
(Qt::ConnectionType) (Qt::UniqueConnection | Qt::AutoConnection));
if (m_threadPool->tryStart(m_feeds.first())) { if (m_threadPool->tryStart(m_feeds.first())) {
m_feeds.removeFirst(); m_feeds.removeFirst();
m_feedsUpdating++; m_feedsUpdating++;
} }
else {
// We want to start update of some feeds but all working threads are occupied. else {
break; // We want to start update of some feeds but all working threads are occupied.
} break;
} }
} }
}
void FeedDownloader::updateFeeds(const QList<Feed*> &feeds) {
QMutexLocker locker(m_mutex); void FeedDownloader::updateFeeds(const QList<Feed*>& feeds) {
QMutexLocker locker(m_mutex);
if (feeds.isEmpty()) {
qDebug("No feeds to update in worker thread, aborting update."); if (feeds.isEmpty()) {
finalizeUpdate(); qDebug("No feeds to update in worker thread, aborting update.");
} finalizeUpdate();
else { }
qDebug().nospace() << "Starting feed updates from worker in thread: \'" << QThread::currentThreadId() << "\'.";
else {
m_feeds = feeds; qDebug().nospace() << "Starting feed updates from worker in thread: \'" << QThread::currentThreadId() << "\'.";
m_feedsOriginalCount = m_feeds.size(); m_feeds = feeds;
m_results.clear(); m_feedsOriginalCount = m_feeds.size();
m_feedsUpdated = m_feedsUpdating = 0; m_results.clear();
m_feedsUpdated = m_feedsUpdating = 0;
// Job starts now. // Job starts now.
emit updateStarted(); emit updateStarted();
updateAvailableFeeds(); updateAvailableFeeds();
} }
} }
void FeedDownloader::stopRunningUpdate() { void FeedDownloader::stopRunningUpdate() {
m_threadPool->clear(); m_threadPool->clear();
m_feeds.clear(); m_feeds.clear();
} }
void FeedDownloader::oneFeedUpdateFinished(const QList<Message> &messages, bool error_during_obtaining) { void FeedDownloader::oneFeedUpdateFinished(const QList<Message>& messages, bool error_during_obtaining) {
QMutexLocker locker(m_mutex); QMutexLocker locker(m_mutex);
m_feedsUpdated++;
m_feedsUpdated++; m_feedsUpdating--;
m_feedsUpdating--; Feed* feed = qobject_cast<Feed*>(sender());
disconnect(feed, &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished);
Feed *feed = qobject_cast<Feed*>(sender()); // Now, we check if there are any feeds we would like to update too.
updateAvailableFeeds();
disconnect(feed, &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished); // Now make sure, that messages are actually stored to SQL in a locked state.
qDebug().nospace() << "Saving messages of feed "
// Now, we check if there are any feeds we would like to update too. << feed->id() << " in thread: \'"
updateAvailableFeeds(); << QThread::currentThreadId() << "\'.";
int updated_messages = feed->updateMessages(messages, error_during_obtaining);
// Now make sure, that messages are actually stored to SQL in a locked state.
qDebug().nospace() << "Saving messages of feed " /*
<< feed->id() << " in thread: \'" QMetaObject::invokeMethod(feed, "updateMessages", Qt::BlockingQueuedConnection,
<< QThread::currentThreadId() << "\'."; Q_RETURN_ARG(int, updated_messages),
Q_ARG(QList<Message>, messages));
int updated_messages = feed->updateMessages(messages, error_during_obtaining); */
/* if (updated_messages > 0) {
QMetaObject::invokeMethod(feed, "updateMessages", Qt::BlockingQueuedConnection, m_results.appendUpdatedFeed(QPair<QString, int>(feed->title(), updated_messages));
Q_RETURN_ARG(int, updated_messages), }
Q_ARG(QList<Message>, 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 (updated_messages > 0) {
m_results.appendUpdatedFeed(QPair<QString,int>(feed->title(), updated_messages)); if (m_feeds.isEmpty() && m_feedsUpdating <= 0) {
} finalizeUpdate();
}
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);
void FeedDownloader::finalizeUpdate() {
if (m_feeds.isEmpty() && m_feedsUpdating <= 0) { qDebug().nospace() << "Finished feed updates in thread: \'" << QThread::currentThreadId() << "\'.";
finalizeUpdate(); 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
void FeedDownloader::finalizeUpdate() { // can eventually quit.
qDebug().nospace() << "Finished feed updates in thread: \'" << QThread::currentThreadId() << "\'."; emit updateFinished(m_results);
}
m_results.sort();
FeedDownloadResults::FeedDownloadResults() : m_updatedFeeds(QList<QPair<QString, int>>()) {
// Update of feeds has finished. }
// NOTE: This means that now "update lock" can be unlocked
// and feeds can be added/edited/deleted and application QString FeedDownloadResults::overview(int how_many_feeds) const {
// can eventually quit. QStringList result;
emit updateFinished(m_results);
} 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));
FeedDownloadResults::FeedDownloadResults() : m_updatedFeeds(QList<QPair<QString,int> >()) { }
}
QString res_str = result.join(QSL("\n"));
QString FeedDownloadResults::overview(int how_many_feeds) const {
QStringList result; if (m_updatedFeeds.size() > how_many_feeds) {
res_str += QObject::tr("\n\n+ %n other feeds.", 0, m_updatedFeeds.size() - how_many_feeds);
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));
} return res_str;
}
QString res_str = result.join(QSL("\n"));
void FeedDownloadResults::appendUpdatedFeed(const QPair<QString, int>& feed) {
if (m_updatedFeeds.size() > how_many_feeds) { m_updatedFeeds.append(feed);
res_str += QObject::tr("\n\n+ %n other feeds.", 0, m_updatedFeeds.size() - how_many_feeds); }
}
void FeedDownloadResults::sort() {
return res_str; qSort(m_updatedFeeds.begin(), m_updatedFeeds.end(), FeedDownloadResults::lessThan);
} }
void FeedDownloadResults::appendUpdatedFeed(const QPair<QString,int> &feed) { bool FeedDownloadResults::lessThan(const QPair<QString, int>& lhs, const QPair<QString, int>& rhs) {
m_updatedFeeds.append(feed); return lhs.second > rhs.second;
} }
void FeedDownloadResults::sort() { void FeedDownloadResults::clear() {
qSort(m_updatedFeeds.begin(), m_updatedFeeds.end(), FeedDownloadResults::lessThan); m_updatedFeeds.clear();
} }
bool FeedDownloadResults::lessThan(const QPair<QString, int> &lhs, const QPair<QString, int> &rhs) { QList<QPair<QString, int>> FeedDownloadResults::updatedFeeds() const {
return lhs.second > rhs.second; return m_updatedFeeds;
} }
void FeedDownloadResults::clear() {
m_updatedFeeds.clear();
}
QList<QPair<QString,int> > FeedDownloadResults::updatedFeeds() const {
return m_updatedFeeds;
}

View file

@ -1,104 +1,104 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FEEDDOWNLOADER_H #ifndef FEEDDOWNLOADER_H
#define FEEDDOWNLOADER_H #define FEEDDOWNLOADER_H
#include <QObject> #include <QObject>
#include <QPair> #include <QPair>
#include "core/message.h" #include "core/message.h"
class Feed; class Feed;
class QThreadPool; class QThreadPool;
class QMutex; class QMutex;
// Represents results of batch feed updates. // Represents results of batch feed updates.
class FeedDownloadResults { class FeedDownloadResults {
public: public:
explicit FeedDownloadResults(); explicit FeedDownloadResults();
QList<QPair<QString,int> > updatedFeeds() const; QList<QPair<QString, int>> updatedFeeds() const;
QString overview(int how_many_feeds) const; QString overview(int how_many_feeds) const;
void appendUpdatedFeed(const QPair<QString,int> &feed); void appendUpdatedFeed(const QPair<QString, int>& feed);
void sort(); void sort();
void clear(); void clear();
static bool lessThan(const QPair<QString,int> &lhs, const QPair<QString,int> &rhs); static bool lessThan(const QPair<QString, int>& lhs, const QPair<QString, int>& rhs);
private: private:
// QString represents title if the feed, int represents count of newly downloaded messages. // QString represents title if the feed, int represents count of newly downloaded messages.
QList<QPair<QString,int> > m_updatedFeeds; QList<QPair<QString, int>> m_updatedFeeds;
}; };
// This class offers means to "update" feeds and "special" categories. // This class offers means to "update" feeds and "special" categories.
// NOTE: This class is used within separate thread. // NOTE: This class is used within separate thread.
class FeedDownloader : public QObject { class FeedDownloader : public QObject {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedDownloader(QObject *parent = 0); explicit FeedDownloader(QObject* parent = 0);
virtual ~FeedDownloader(); virtual ~FeedDownloader();
bool isUpdateRunning() const; bool isUpdateRunning() const;
public slots: public slots:
// Performs update of all feeds from the "feeds" parameter. // Performs update of all feeds from the "feeds" parameter.
// New messages are downloaded for each feed and they // New messages are downloaded for each feed and they
// are stored persistently in the database. // are stored persistently in the database.
// Appropriate signals are emitted. // Appropriate signals are emitted.
void updateFeeds(const QList<Feed*> &feeds); void updateFeeds(const QList<Feed*>& feeds);
// Stops running update. // Stops running update.
void stopRunningUpdate(); void stopRunningUpdate();
private slots: private slots:
void oneFeedUpdateFinished(const QList<Message> &messages, bool error_during_obtaining); void oneFeedUpdateFinished(const QList<Message>& messages, bool error_during_obtaining);
signals: signals:
// Emitted if feed updates started. // Emitted if feed updates started.
void updateStarted(); void updateStarted();
// Emitted if all items from update queue are // Emitted if all items from update queue are
// processed. // processed.
void updateFinished(FeedDownloadResults updated_feeds); void updateFinished(FeedDownloadResults updated_feeds);
// Emitted if any item is processed. // Emitted if any item is processed.
// "Current" number indicates count of processed feeds // "Current" number indicates count of processed feeds
// and "total" number indicates total number of feeds // and "total" number indicates total number of feeds
// which were in the initial queue. // which were in the initial queue.
void updateProgress(const Feed *feed, int current, int total); void updateProgress(const Feed* feed, int current, int total);
private: private:
void updateAvailableFeeds(); void updateAvailableFeeds();
void finalizeUpdate(); void finalizeUpdate();
QList<Feed*> m_feeds; QList<Feed*> m_feeds;
QMutex *m_mutex; QMutex* m_mutex;
QThreadPool *m_threadPool; QThreadPool* m_threadPool;
FeedDownloadResults m_results; FeedDownloadResults m_results;
int m_feedsUpdated; int m_feedsUpdated;
int m_feedsUpdating; int m_feedsUpdating;
int m_feedsOriginalCount; int m_feedsOriginalCount;
}; };
#endif // FEEDDOWNLOADER_H #endif // FEEDDOWNLOADER_H

File diff suppressed because it is too large Load diff

View file

@ -1,182 +1,182 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FEEDSMODEL_H #ifndef FEEDSMODEL_H
#define FEEDSMODEL_H #define FEEDSMODEL_H
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include "core/message.h" #include "core/message.h"
#include "services/abstract/rootitem.h" #include "services/abstract/rootitem.h"
class Category; class Category;
class Feed; class Feed;
class ServiceRoot; class ServiceRoot;
class ServiceEntryPoint; class ServiceEntryPoint;
class StandardServiceRoot; class StandardServiceRoot;
class FeedsModel : public QAbstractItemModel { class FeedsModel : public QAbstractItemModel {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedsModel(QObject *parent = 0); explicit FeedsModel(QObject* parent = 0);
virtual ~FeedsModel(); virtual ~FeedsModel();
// Model implementation. // Model implementation.
inline QVariant data(const QModelIndex &index, int role) const { inline QVariant data(const QModelIndex& index, int role) const {
// Return data according to item. // Return data according to item.
return itemForIndex(index)->data(index.column(), role); return itemForIndex(index)->data(index.column(), role);
} }
// Drag & drop. // Drag & drop.
QMimeData *mimeData(const QModelIndexList &indexes) const; QMimeData* mimeData(const QModelIndexList& indexes) const;
QStringList mimeTypes() const; QStringList mimeTypes() const;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent);
Qt::DropActions supportedDropActions() const; Qt::DropActions supportedDropActions() const;
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex& index) const;
// Other subclassed methods. // Other subclassed methods.
QVariant headerData(int section, Qt::Orientation orientation, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QModelIndex index(int row, int column, const QModelIndex &parent) const; QModelIndex index(int row, int column, const QModelIndex& parent) const;
QModelIndex parent(const QModelIndex &child) const; QModelIndex parent(const QModelIndex& child) const;
int columnCount(const QModelIndex &parent) const; int columnCount(const QModelIndex& parent) const;
int rowCount(const QModelIndex &parent) const; int rowCount(const QModelIndex& parent) const;
// Returns counts of ALL/UNREAD (non-deleted) messages for the model. // Returns counts of ALL/UNREAD (non-deleted) messages for the model.
int countOfAllMessages() const; int countOfAllMessages() const;
int countOfUnreadMessages() const; int countOfUnreadMessages() const;
// Returns all activated service roots. // Returns all activated service roots.
// NOTE: Service root nodes are lying directly UNDER // NOTE: Service root nodes are lying directly UNDER
// the model root item. // the model root item.
QList<ServiceRoot*> serviceRoots() const; QList<ServiceRoot*> serviceRoots() const;
// Determines if there is any account activated from given entry point. // Determines if there is any account activated from given entry point.
bool containsServiceRootFromEntryPoint(const ServiceEntryPoint *point) const; bool containsServiceRootFromEntryPoint(const ServiceEntryPoint* point) const;
// Direct and the only global accessor to standard service root. // Direct and the only global accessor to standard service root.
StandardServiceRoot *standardServiceRoot() const; StandardServiceRoot* standardServiceRoot() const;
// Returns the list of feeds which should be updated // Returns the list of feeds which should be updated
// according to auto-update schedule. // according to auto-update schedule.
// Variable "auto_update_now" is true, when global timeout // Variable "auto_update_now" is true, when global timeout
// for scheduled auto-update was met and global auto-update strategy is enabled // for scheduled auto-update was met and global auto-update strategy is enabled
// so feeds with "default" auto-update strategy should be updated. // so feeds with "default" auto-update strategy should be updated.
// //
// This method might change some properties of some feeds. // This method might change some properties of some feeds.
QList<Feed*> feedsForScheduledUpdate(bool auto_update_now); QList<Feed*> feedsForScheduledUpdate(bool auto_update_now);
// Returns (undeleted) messages for given feeds. // Returns (undeleted) messages for given feeds.
// This is usually used for displaying whole feeds // This is usually used for displaying whole feeds
// in "newspaper" mode. // in "newspaper" mode.
QList<Message> messagesForItem(RootItem *item) const; QList<Message> messagesForItem(RootItem* item) const;
// Returns ALL RECURSIVE CHILD feeds contained within single index. // Returns ALL RECURSIVE CHILD feeds contained within single index.
QList<Feed*> feedsForIndex(const QModelIndex &index) const; QList<Feed*> feedsForIndex(const QModelIndex& index) const;
// Returns feed/category which lies at the specified index or // Returns feed/category which lies at the specified index or
// root item if index is invalid. // root item if index is invalid.
RootItem *itemForIndex(const QModelIndex &index) const; RootItem* itemForIndex(const QModelIndex& index) const;
// Returns source QModelIndex on which lies given item. // Returns source QModelIndex on which lies given item.
// NOTE: This goes through all available indexes and // NOTE: This goes through all available indexes and
// checks their bound items manually, there is no // checks their bound items manually, there is no
// other way to to this. // other way to to this.
QModelIndex indexForItem(const RootItem *item) const; QModelIndex indexForItem(const RootItem* item) const;
// Determines if any feed has any new messages. // Determines if any feed has any new messages.
bool hasAnyFeedNewMessages() const; bool hasAnyFeedNewMessages() const;
// Access to root item. // Access to root item.
RootItem *rootItem() const; RootItem* rootItem() const;
public slots: public slots:
// Loads feed/categories from the database. // Loads feed/categories from the database.
void loadActivatedServiceAccounts(); void loadActivatedServiceAccounts();
// Stops all accounts before exit. // Stops all accounts before exit.
void stopServiceAccounts(); void stopServiceAccounts();
// Reloads counts of all feeds/categories/whatever in the model. // Reloads counts of all feeds/categories/whatever in the model.
void reloadCountsOfWholeModel(); void reloadCountsOfWholeModel();
// Checks if new parent node is different from one used by original node. // Checks if new parent node is different from one used by original node.
// If it is, then it reassigns original_node to new parent. // If it is, then it reassigns original_node to new parent.
void reassignNodeToNewParent(RootItem *original_node, RootItem *new_parent); void reassignNodeToNewParent(RootItem* original_node, RootItem* new_parent);
// Adds given service root account. // Adds given service root account.
bool addServiceAccount(ServiceRoot *root, bool freshly_activated); bool addServiceAccount(ServiceRoot* root, bool freshly_activated);
// Removes item with given index. // Removes item with given index.
// NOTE: Also deletes item from memory. // NOTE: Also deletes item from memory.
void removeItem(const QModelIndex &index); void removeItem(const QModelIndex& index);
void removeItem(RootItem *deleting_item); void removeItem(RootItem* deleting_item);
// Recycle bins operations. // Recycle bins operations.
bool restoreAllBins(); bool restoreAllBins();
bool emptyAllBins(); bool emptyAllBins();
// Feeds operations. // Feeds operations.
bool markItemRead(RootItem *item, RootItem::ReadStatus read); bool markItemRead(RootItem* item, RootItem::ReadStatus read);
bool markItemCleared(RootItem *item, bool clean_read_only); bool markItemCleared(RootItem* item, bool clean_read_only);
// Signals that properties (probably counts) // Signals that properties (probably counts)
// of ALL items have changed. // of ALL items have changed.
void reloadWholeLayout(); void reloadWholeLayout();
// Signals that SOME data of this model need // Signals that SOME data of this model need
// to be reloaded by ALL attached views. // to be reloaded by ALL attached views.
// NOTE: This reloads all parent valid indexes too. // NOTE: This reloads all parent valid indexes too.
void reloadChangedLayout(QModelIndexList list); void reloadChangedLayout(QModelIndexList list);
// Invalidates data under index for the item. // Invalidates data under index for the item.
void reloadChangedItem(RootItem *item); void reloadChangedItem(RootItem* item);
// Notifies other components about messages // Notifies other components about messages
// counts. // counts.
void notifyWithCounts(); void notifyWithCounts();
private slots: private slots:
void onItemDataChanged(const QList<RootItem*> &items); void onItemDataChanged(const QList<RootItem*>& items);
signals: signals:
// Emitted if counts of messages are changed. // Emitted if counts of messages are changed.
void messageCountsChanged(int unread_messages, bool any_feed_has_unread_messages); void messageCountsChanged(int unread_messages, bool any_feed_has_unread_messages);
// Emitted if any item requested that any view should expand it. // Emitted if any item requested that any view should expand it.
void itemExpandRequested(QList<RootItem*> items, bool expand); void itemExpandRequested(QList<RootItem*> items, bool expand);
// Emitted if any item requested that its expand states should be explicitly saved. // Emitted if any item requested that its expand states should be explicitly saved.
// NOTE: Normally expand states are saved when application quits. // NOTE: Normally expand states are saved when application quits.
void itemExpandStateSaveRequested(RootItem *subtree_root); void itemExpandStateSaveRequested(RootItem* subtree_root);
// Emitted when there is a need of reloading of displayed messages. // Emitted when there is a need of reloading of displayed messages.
void reloadMessageListRequested(bool mark_selected_messages_read); void reloadMessageListRequested(bool mark_selected_messages_read);
// There was some drag/drop operation, notify view about this. // There was some drag/drop operation, notify view about this.
// NOTE: View will probably expand dropped index. // NOTE: View will probably expand dropped index.
void requireItemValidationAfterDragDrop(const QModelIndex &source_index); void requireItemValidationAfterDragDrop(const QModelIndex& source_index);
private: private:
RootItem *m_rootItem; RootItem* m_rootItem;
QList<QString> m_headerData; QList<QString> m_headerData;
QList<QString> m_tooltipData; QList<QString> m_tooltipData;
QIcon m_countsIcon; QIcon m_countsIcon;
}; };
#endif // FEEDSMODEL_H #endif // FEEDSMODEL_H

View file

@ -1,264 +1,278 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "core/feedsproxymodel.h" #include "core/feedsproxymodel.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "core/feedsmodel.h" #include "core/feedsmodel.h"
#include "services/abstract/rootitem.h" #include "services/abstract/rootitem.h"
#include <QTimer> #include <QTimer>
FeedsProxyModel::FeedsProxyModel(FeedsModel *source_model, QObject *parent) FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent)
: QSortFilterProxyModel(parent), m_sourceModel(source_model), m_selectedItem(nullptr), : QSortFilterProxyModel(parent), m_sourceModel(source_model), m_selectedItem(nullptr),
m_showUnreadOnly(false), m_hiddenIndices(QList<QPair<int,QModelIndex> >()) { m_showUnreadOnly(false), m_hiddenIndices(QList<QPair<int, QModelIndex>>()) {
setObjectName(QSL("FeedsProxyModel")); setObjectName(QSL("FeedsProxyModel"));
setSortRole(Qt::EditRole); setSortRole(Qt::EditRole);
setSortCaseSensitivity(Qt::CaseInsensitive); setSortCaseSensitivity(Qt::CaseInsensitive);
setFilterCaseSensitivity(Qt::CaseInsensitive); setFilterCaseSensitivity(Qt::CaseInsensitive);
setFilterKeyColumn(-1); setFilterKeyColumn(-1);
setFilterRole(Qt::EditRole); setFilterRole(Qt::EditRole);
setDynamicSortFilter(true); setDynamicSortFilter(true);
setSourceModel(m_sourceModel); setSourceModel(m_sourceModel);
} }
FeedsProxyModel::~FeedsProxyModel() { 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 FeedsProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const {
QModelIndexList result; QModelIndexList result;
const uint match_type = flags & 0x0F; const uint match_type = flags & 0x0F;
const Qt::CaseSensitivity cs = Qt::CaseInsensitive; const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
const bool recurse = flags & Qt::MatchRecursive; const bool recurse = flags & Qt::MatchRecursive;
const bool wrap = flags & Qt::MatchWrap; const bool wrap = flags & Qt::MatchWrap;
const bool all_hits = (hits == -1); const bool all_hits = (hits == -1);
QString entered_text; QString entered_text;
const QModelIndex p = parent(start); const QModelIndex p = parent(start);
int from = start.row(); int from = start.row();
int to = rowCount(p); int to = rowCount(p);
for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) { for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
for (int r = from; (r < to) && (all_hits || result.count() < hits); ++r) { for (int r = from; (r < to) && (all_hits || result.count() < hits); ++r) {
QModelIndex idx = index(r, start.column(), p); QModelIndex idx = index(r, start.column(), p);
if (!idx.isValid()) { if (!idx.isValid()) {
continue; continue;
} }
QModelIndex mapped_idx = mapToSource(idx); QModelIndex mapped_idx = mapToSource(idx);
QVariant item_value = m_sourceModel->itemForIndex(mapped_idx)->title(); QVariant item_value = m_sourceModel->itemForIndex(mapped_idx)->title();
// QVariant based matching. // QVariant based matching.
if (match_type == Qt::MatchExactly) { if (match_type == Qt::MatchExactly) {
if (value == item_value) { if (value == item_value) {
result.append(idx); result.append(idx);
} }
} }
// QString based matching.
else { // QString based matching.
if (entered_text.isEmpty()) { else {
entered_text = value.toString(); if (entered_text.isEmpty()) {
} entered_text = value.toString();
}
QString item_text = item_value.toString();
QString item_text = item_value.toString();
switch (match_type) {
case Qt::MatchRegExp: switch (match_type) {
if (QRegExp(entered_text, cs).exactMatch(item_text)) { case Qt::MatchRegExp:
result.append(idx); if (QRegExp(entered_text, cs).exactMatch(item_text)) {
} result.append(idx);
break; }
case Qt::MatchWildcard: break;
if (QRegExp(entered_text, cs, QRegExp::Wildcard).exactMatch(item_text)) {
result.append(idx); case Qt::MatchWildcard:
} if (QRegExp(entered_text, cs, QRegExp::Wildcard).exactMatch(item_text)) {
break; result.append(idx);
}
case Qt::MatchStartsWith:
if (item_text.startsWith(entered_text, cs)) { break;
result.append(idx);
} case Qt::MatchStartsWith:
break; 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)) {
case Qt::MatchFixedString: result.append(idx);
if (item_text.compare(entered_text, cs) == 0) { }
result.append(idx);
} break;
break;
case Qt::MatchFixedString:
case Qt::MatchContains: if (item_text.compare(entered_text, cs) == 0) {
default: result.append(idx);
if (item_text.contains(entered_text, cs)) { }
result.append(idx);
} break;
break;
} case Qt::MatchContains:
} default:
if (item_text.contains(entered_text, cs)) {
if (recurse && hasChildren(idx)) { result.append(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; }
} }
bool FeedsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { from = 0;
if (left.isValid() && right.isValid()) { to = start.row();
// Make necessary castings. }
const RootItem *left_item = m_sourceModel->itemForIndex(left);
const RootItem *right_item = m_sourceModel->itemForIndex(right); return result;
}
// NOTE: Here we want to accomplish that ALL
// categories are queued one after another and all bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const {
// feeds are queued one after another too. if (left.isValid() && right.isValid()) {
// Moreover, sort everything alphabetically or // Make necessary castings.
// by item counts, depending on the sort column. const RootItem* left_item = m_sourceModel->itemForIndex(left);
const RootItem* right_item = m_sourceModel->itemForIndex(right);
if (left_item->kind() == right_item->kind()) {
// Both items are feeds or both items are categories. // NOTE: Here we want to accomplish that ALL
if (left.column() == FDS_MODEL_COUNTS_INDEX) { // categories are queued one after another and all
// User wants to sort according to counts. // feeds are queued one after another too.
return left_item->countOfUnreadMessages() < right_item->countOfUnreadMessages(); // Moreover, sort everything alphabetically or
} // by item counts, depending on the sort column.
else {
// In other cases, sort by title. if (left_item->kind() == right_item->kind()) {
return QString::localeAwareCompare(left_item->title(), right_item->title()) < 0; // Both items are feeds or both items are categories.
} if (left.column() == FDS_MODEL_COUNTS_INDEX) {
} // User wants to sort according to counts.
else if (left_item->kind() == RootItemKind::Bin) { return left_item->countOfUnreadMessages() < right_item->countOfUnreadMessages();
// Left item is recycle bin. Make sure it is "biggest" item if we have selected ascending order. }
return sortOrder() == Qt::DescendingOrder;
} else {
else if (right_item->kind() == RootItemKind::Bin) { // In other cases, sort by title.
// Right item is recycle bin. Make sure it is "smallest" item if we have selected descending order. return QString::localeAwareCompare(left_item->title(), right_item->title()) < 0;
return sortOrder() == Qt::AscendingOrder; }
} }
else if (left_item->kind() == RootItemKind::Feed) {
// Left item is feed, right item is category. else if (left_item->kind() == RootItemKind::Bin) {
return false; // Left item is recycle bin. Make sure it is "biggest" item if we have selected ascending order.
} return sortOrder() == Qt::DescendingOrder;
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" else if (right_item->kind() == RootItemKind::Bin) {
// above the "smalles" feed when ascending sort is used. // Right item is recycle bin. Make sure it is "smallest" item if we have selected descending order.
// NOTE: We need to keep recycle bin in first position. return sortOrder() == Qt::AscendingOrder;
return true; }
}
} else if (left_item->kind() == RootItemKind::Feed) {
else { // Left item is feed, right item is category.
return false; return false;
} }
}
else {
bool FeedsProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { // Left item is category, right item is feed.
bool should_show = filterAcceptsRowInternal(source_row, source_parent); // 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.
if (should_show && m_hiddenIndices.contains(QPair<int,QModelIndex>(source_row, source_parent))) { // NOTE: We need to keep recycle bin in first position.
const_cast<FeedsProxyModel*>(this)->m_hiddenIndices.removeAll(QPair<int,QModelIndex>(source_row, source_parent)); return true;
}
// Load status. }
emit expandAfterFilterIn(m_sourceModel->index(source_row, 0, source_parent));
} else {
return false;
if (!should_show) { }
const_cast<FeedsProxyModel*>(this)->m_hiddenIndices.append(QPair<int,QModelIndex>(source_row, source_parent)); }
}
bool FeedsProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const {
return should_show; bool should_show = filterAcceptsRowInternal(source_row, source_parent);
}
if (should_show && m_hiddenIndices.contains(QPair<int, QModelIndex>(source_row, source_parent))) {
bool FeedsProxyModel::filterAcceptsRowInternal(int source_row, const QModelIndex &source_parent) const { const_cast<FeedsProxyModel*>(this)->m_hiddenIndices.removeAll(QPair<int, QModelIndex>(source_row, source_parent));
if (!m_showUnreadOnly) { // Load status.
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); emit expandAfterFilterIn(m_sourceModel->index(source_row, 0, source_parent));
} }
const QModelIndex idx = m_sourceModel->index(source_row, 0, source_parent); if (!should_show) {
const_cast<FeedsProxyModel*>(this)->m_hiddenIndices.append(QPair<int, QModelIndex>(source_row, source_parent));
if (!idx.isValid()) { }
return false;
} return should_show;
}
const RootItem *item = m_sourceModel->itemForIndex(idx);
bool FeedsProxyModel::filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const {
if (item->kind() == RootItemKind::Bin || item->kind() == RootItemKind::ServiceRoot) { if (!m_showUnreadOnly) {
// Recycle bin is always displayed. return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
return true; }
}
else if (item->isParentOf(m_selectedItem)/* || item->isChildOf(m_selectedItem)*/ || m_selectedItem == item) { const QModelIndex idx = m_sourceModel->index(source_row, 0, source_parent);
// Currently selected item and all its parents and children must be displayed.
return true; if (!idx.isValid()) {
} return false;
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. const RootItem* item = m_sourceModel->itemForIndex(idx);
return item->countOfUnreadMessages() != 0;
} if (item->kind() == RootItemKind::Bin || item->kind() == RootItemKind::ServiceRoot) {
} // Recycle bin is always displayed.
return true;
const RootItem *FeedsProxyModel::selectedItem() const { }
return m_selectedItem;
} 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.
void FeedsProxyModel::setSelectedItem(const RootItem *selected_item) { return true;
m_selectedItem = selected_item; }
}
else {
bool FeedsProxyModel::showUnreadOnly() const { // NOTE: If item has < 0 of unread message it may mean, that the count
return m_showUnreadOnly; // of unread messages is not (yet) known, display that item too.
} return item->countOfUnreadMessages() != 0;
}
void FeedsProxyModel::invalidateReadFeedsFilter(bool set_new_value, bool show_unread_only) { }
if (set_new_value) {
setShowUnreadOnly(show_unread_only); const RootItem* FeedsProxyModel::selectedItem() const {
} return m_selectedItem;
}
QTimer::singleShot(0, this, &FeedsProxyModel::invalidateFilter);
} void FeedsProxyModel::setSelectedItem(const RootItem* selected_item) {
m_selectedItem = selected_item;
void FeedsProxyModel::setShowUnreadOnly(bool show_unread_only) { }
m_showUnreadOnly = show_unread_only;
qApp->settings()->setValue(GROUP(Feeds), Feeds::ShowOnlyUnreadFeeds, show_unread_only); bool FeedsProxyModel::showUnreadOnly() const {
} return m_showUnreadOnly;
}
QModelIndexList FeedsProxyModel::mapListToSource(const QModelIndexList &indexes) const {
QModelIndexList source_indexes; void FeedsProxyModel::invalidateReadFeedsFilter(bool set_new_value, bool show_unread_only) {
if (set_new_value) {
foreach (const QModelIndex &index, indexes) { setShowUnreadOnly(show_unread_only);
source_indexes << mapToSource(index); }
}
QTimer::singleShot(0, this, &FeedsProxyModel::invalidateFilter);
return source_indexes; }
}
void FeedsProxyModel::setShowUnreadOnly(bool show_unread_only) {
void FeedsProxyModel::invalidateFilter() { m_showUnreadOnly = show_unread_only;
QSortFilterProxyModel::invalidateFilter(); qApp->settings()->setValue(GROUP(Feeds), Feeds::ShowOnlyUnreadFeeds, show_unread_only);
} }
QModelIndexList FeedsProxyModel::mapListToSource(const QModelIndexList& indexes) const {
QModelIndexList source_indexes;
foreach (const QModelIndex& index, indexes) {
source_indexes << mapToSource(index);
}
return source_indexes;
}
void FeedsProxyModel::invalidateFilter() {
QSortFilterProxyModel::invalidateFilter();
}

View file

@ -1,70 +1,70 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FEEDSPROXYMODEL_H #ifndef FEEDSPROXYMODEL_H
#define FEEDSPROXYMODEL_H #define FEEDSPROXYMODEL_H
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
class FeedsModel; class FeedsModel;
class RootItem; class RootItem;
class FeedsProxyModel : public QSortFilterProxyModel { class FeedsProxyModel : public QSortFilterProxyModel {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedsProxyModel(FeedsModel *source_model, QObject *parent = 0); explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = 0);
virtual ~FeedsProxyModel(); virtual ~FeedsProxyModel();
// Returns index list of items which "match" given value. // Returns index list of items which "match" given value.
// Used for finding items according to entered title text. // 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; QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const;
// Maps list of indexes. // Maps list of indexes.
QModelIndexList mapListToSource(const QModelIndexList &indexes) const; QModelIndexList mapListToSource(const QModelIndexList& indexes) const;
bool showUnreadOnly() const; bool showUnreadOnly() const;
void setShowUnreadOnly(bool show_unread_only); void setShowUnreadOnly(bool show_unread_only);
const RootItem *selectedItem() const; const RootItem* selectedItem() const;
void setSelectedItem(const RootItem *selected_item); void setSelectedItem(const RootItem* selected_item);
public slots: public slots:
void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false); void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false);
private slots: private slots:
void invalidateFilter(); void invalidateFilter();
signals: signals:
void expandAfterFilterIn(QModelIndex idx) const; void expandAfterFilterIn(QModelIndex idx) const;
private: private:
// Compares two rows of data. // Compares two rows of data.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const; bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
bool filterAcceptsRowInternal(int source_row, const QModelIndex &source_parent) const; bool filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const;
// Source model pointer. // Source model pointer.
FeedsModel *m_sourceModel; FeedsModel* m_sourceModel;
const RootItem *m_selectedItem; const RootItem* m_selectedItem;
bool m_showUnreadOnly; bool m_showUnreadOnly;
QList<QPair<int,QModelIndex> > m_hiddenIndices; QList<QPair<int, QModelIndex>> m_hiddenIndices;
}; };
#endif // FEEDSPROXYMODEL_H #endif // FEEDSPROXYMODEL_H

View file

@ -1,112 +1,112 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "core/message.h" #include "core/message.h"
#include "miscellaneous/textfactory.h" #include "miscellaneous/textfactory.h"
#include <QVariant> #include <QVariant>
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<Enclosure> Enclosures::decodeEnclosuresFromString(const QString &enclosures_data) { QList<Enclosure> Enclosures::decodeEnclosuresFromString(const QString& enclosures_data) {
QList<Enclosure> enclosures; QList<Enclosure> enclosures;
foreach (const QString &single_enclosure, enclosures_data.split(ENCLOSURES_OUTER_SEPARATOR, QString::SkipEmptyParts)) { foreach (const QString& single_enclosure, enclosures_data.split(ENCLOSURES_OUTER_SEPARATOR, QString::SkipEmptyParts)) {
Enclosure enclosure; Enclosure enclosure;
if (single_enclosure.contains(ECNLOSURES_INNER_SEPARATOR)) { if (single_enclosure.contains(ECNLOSURES_INNER_SEPARATOR)) {
QStringList mime_url = single_enclosure.split(ECNLOSURES_INNER_SEPARATOR); QStringList mime_url = single_enclosure.split(ECNLOSURES_INNER_SEPARATOR);
enclosure.m_mimeType = QByteArray::fromBase64(mime_url.at(0).toLocal8Bit());
enclosure.m_mimeType = QByteArray::fromBase64(mime_url.at(0).toLocal8Bit()); enclosure.m_url = QByteArray::fromBase64(mime_url.at(1).toLocal8Bit());
enclosure.m_url = QByteArray::fromBase64(mime_url.at(1).toLocal8Bit()); }
}
else { else {
enclosure.m_url = QByteArray::fromBase64(single_enclosure.toLocal8Bit()); enclosure.m_url = QByteArray::fromBase64(single_enclosure.toLocal8Bit());
} }
enclosures.append(enclosure); enclosures.append(enclosure);
} }
return enclosures; return enclosures;
} }
QString Enclosures::encodeEnclosuresToString(const QList<Enclosure> &enclosures) { QString Enclosures::encodeEnclosuresToString(const QList<Enclosure>& enclosures) {
QStringList enclosures_str; QStringList enclosures_str;
foreach (const Enclosure &enclosure, enclosures) { foreach (const Enclosure& enclosure, enclosures) {
if (enclosure.m_mimeType.isEmpty()) { if (enclosure.m_mimeType.isEmpty()) {
enclosures_str.append(enclosure.m_url.toLocal8Bit().toBase64()); enclosures_str.append(enclosure.m_url.toLocal8Bit().toBase64());
} }
else {
enclosures_str.append(QString(enclosure.m_mimeType.toLocal8Bit().toBase64()) + else {
ECNLOSURES_INNER_SEPARATOR + enclosures_str.append(QString(enclosure.m_mimeType.toLocal8Bit().toBase64()) +
enclosure.m_url.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(""); Message::Message() {
m_enclosures = QList<Enclosure>(); m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = QSL("");
m_accountId = m_id = 0; m_enclosures = QList<Enclosure>();
m_isRead = m_isImportant = false; 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) { Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) {
if (result != nullptr) { if (record.count() != MSG_DB_CUSTOM_HASH_INDEX + 1) {
*result = false; if (result != nullptr) {
return Message(); *result = false;
} return Message();
} }
}
Message message;
Message message;
message.m_id = record.value(MSG_DB_ID_INDEX).toInt(); message.m_id = record.value(MSG_DB_ID_INDEX).toInt();
message.m_isRead = record.value(MSG_DB_READ_INDEX).toBool(); message.m_isRead = record.value(MSG_DB_READ_INDEX).toBool();
message.m_isImportant = record.value(MSG_DB_IMPORTANT_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_feedId = record.value(MSG_DB_FEED_CUSTOM_ID_INDEX).toString();
message.m_title = record.value(MSG_DB_TITLE_INDEX).toString(); message.m_title = record.value(MSG_DB_TITLE_INDEX).toString();
message.m_url = record.value(MSG_DB_URL_INDEX).toString(); message.m_url = record.value(MSG_DB_URL_INDEX).toString();
message.m_author = record.value(MSG_DB_AUTHOR_INDEX).toString(); message.m_author = record.value(MSG_DB_AUTHOR_INDEX).toString();
message.m_created = TextFactory::parseDateTime(record.value(MSG_DB_DCREATED_INDEX).value<qint64>()); message.m_created = TextFactory::parseDateTime(record.value(MSG_DB_DCREATED_INDEX).value<qint64>());
message.m_contents = record.value(MSG_DB_CONTENTS_INDEX).toString(); message.m_contents = record.value(MSG_DB_CONTENTS_INDEX).toString();
message.m_enclosures = Enclosures::decodeEnclosuresFromString(record.value(MSG_DB_ENCLOSURES_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_accountId = record.value(MSG_DB_ACCOUNT_ID_INDEX).toInt();
message.m_customId = record.value(MSG_DB_CUSTOM_ID_INDEX).toString(); message.m_customId = record.value(MSG_DB_CUSTOM_ID_INDEX).toString();
message.m_customHash = record.value(MSG_DB_CUSTOM_HASH_INDEX).toString(); message.m_customHash = record.value(MSG_DB_CUSTOM_HASH_INDEX).toString();
if (result != nullptr) { if (result != nullptr) {
*result = true; *result = true;
} }
return message; return message;
} }
uint qHash(Message key, uint seed) { uint qHash(Message key, uint seed) {
Q_UNUSED(seed) Q_UNUSED(seed)
return (key.m_accountId * 10000) + key.m_id; return (key.m_accountId * 10000) + key.m_id;
} }
uint qHash(const Message &key) { uint qHash(const Message& key) {
return (key.m_accountId * 10000) + key.m_id; return (key.m_accountId * 10000) + key.m_id;
} }

View file

@ -1,85 +1,85 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef MESSAGE_H #ifndef MESSAGE_H
#define MESSAGE_H #define MESSAGE_H
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include <QDateTime> #include <QDateTime>
#include <QStringList> #include <QStringList>
#include <QSqlRecord> #include <QSqlRecord>
// Represents single enclosure. // Represents single enclosure.
struct Enclosure { struct Enclosure {
public: public:
explicit Enclosure(const QString &url = QString(), const QString &mime = QString()); explicit Enclosure(const QString& url = QString(), const QString& mime = QString());
QString m_url; QString m_url;
QString m_mimeType; QString m_mimeType;
}; };
// Represents single enclosure. // Represents single enclosure.
class Enclosures { class Enclosures {
public: public:
static QList<Enclosure> decodeEnclosuresFromString(const QString &enclosures_data); static QList<Enclosure> decodeEnclosuresFromString(const QString& enclosures_data);
static QString encodeEnclosuresToString(const QList<Enclosure> &enclosures); static QString encodeEnclosuresToString(const QList<Enclosure>& enclosures);
}; };
// Represents single message. // Represents single message.
class Message { class Message {
public: public:
explicit Message(); explicit Message();
// Creates Message from given record, which contains // Creates Message from given record, which contains
// row from query SELECT * FROM Messages WHERE ....; // row from query SELECT * FROM Messages WHERE ....;
static Message fromSqlRecord(const QSqlRecord &record, bool *result = nullptr); static Message fromSqlRecord(const QSqlRecord& record, bool* result = nullptr);
QString m_title; QString m_title;
QString m_url; QString m_url;
QString m_author; QString m_author;
QString m_contents; QString m_contents;
QDateTime m_created; QDateTime m_created;
QString m_feedId; QString m_feedId;
int m_accountId; int m_accountId;
int m_id; int m_id;
QString m_customId; QString m_customId;
QString m_customHash; QString m_customHash;
bool m_isRead; bool m_isRead;
bool m_isImportant; bool m_isImportant;
QList<Enclosure> m_enclosures; QList<Enclosure> m_enclosures;
// Is true if "created" date was obtained directly // Is true if "created" date was obtained directly
// from the feed, otherwise is false // from the feed, otherwise is false
bool m_createdFromFeed; bool m_createdFromFeed;
friend inline bool operator==(const Message &lhs, const Message &rhs) { friend inline bool operator==(const Message& lhs, const Message& rhs) {
return lhs.m_accountId == rhs.m_accountId && lhs.m_id == rhs.m_id; return lhs.m_accountId == rhs.m_accountId && lhs.m_id == rhs.m_id;
} }
friend inline bool operator!=(const Message &lhs, const Message &rhs) { friend inline bool operator!=(const Message& lhs, const Message& rhs) {
return !(lhs == rhs); return !(lhs == rhs);
} }
}; };
uint qHash(Message key, uint seed); uint qHash(Message key, uint seed);
uint qHash(const Message &key); uint qHash(const Message& key);
#endif // MESSAGE_H #endif // MESSAGE_H

View file

@ -30,524 +30,525 @@
#include <QSqlField> #include <QSqlField>
MessagesModel::MessagesModel(QObject *parent) MessagesModel::MessagesModel(QObject* parent)
: QSqlQueryModel(parent), MessagesModelSqlLayer(), : QSqlQueryModel(parent), MessagesModelSqlLayer(),
m_cache(new MessagesModelCache(this)), m_messageHighlighter(NoHighlighting), m_customDateFormat(QString()) { m_cache(new MessagesModelCache(this)), m_messageHighlighter(NoHighlighting), m_customDateFormat(QString()) {
setupFonts(); setupFonts();
setupIcons(); setupIcons();
setupHeaderData(); setupHeaderData();
updateDateFormat(); updateDateFormat();
loadMessages(nullptr);
loadMessages(nullptr);
} }
MessagesModel::~MessagesModel() { MessagesModel::~MessagesModel() {
qDebug("Destroying MessagesModel instance."); qDebug("Destroying MessagesModel instance.");
} }
void MessagesModel::setupIcons() { void MessagesModel::setupIcons() {
m_favoriteIcon = qApp->icons()->fromTheme(QSL("mail-mark-important")); m_favoriteIcon = qApp->icons()->fromTheme(QSL("mail-mark-important"));
m_readIcon = qApp->icons()->fromTheme(QSL("mail-mark-read")); m_readIcon = qApp->icons()->fromTheme(QSL("mail-mark-read"));
m_unreadIcon = qApp->icons()->fromTheme(QSL("mail-mark-unread")); m_unreadIcon = qApp->icons()->fromTheme(QSL("mail-mark-unread"));
} }
void MessagesModel::repopulate() { void MessagesModel::repopulate() {
m_cache->clear(); m_cache->clear();
setQuery(selectStatement(), m_db); setQuery(selectStatement(), m_db);
while (canFetchMore()) { while (canFetchMore()) {
fetchMore(); fetchMore();
} }
} }
bool MessagesModel::setData(const QModelIndex &index, const QVariant &value, int role) { bool MessagesModel::setData(const QModelIndex& index, const QVariant& value, int role) {
Q_UNUSED(role) Q_UNUSED(role)
m_cache->setData(index, value, record(index.row()));
m_cache->setData(index, value, record(index.row())); return true;
return true;
} }
void MessagesModel::setupFonts() { void MessagesModel::setupFonts() {
m_normalFont = Application::font("MessagesView"); m_normalFont = Application::font("MessagesView");
m_boldFont = m_normalFont; m_boldFont = m_normalFont;
m_boldFont.setBold(true); m_boldFont.setBold(true);
m_normalStrikedFont = m_normalFont;
m_normalStrikedFont = m_normalFont; m_boldStrikedFont = m_boldFont;
m_boldStrikedFont = m_boldFont; m_normalStrikedFont.setStrikeOut(true);
m_normalStrikedFont.setStrikeOut(true); m_boldStrikedFont.setStrikeOut(true);
m_boldStrikedFont.setStrikeOut(true);
} }
void MessagesModel::loadMessages(RootItem *item) { void MessagesModel::loadMessages(RootItem* item) {
m_selectedItem = item; m_selectedItem = item;
if (item == nullptr) { if (item == nullptr) {
setFilter(QSL(DEFAULT_SQL_MESSAGES_FILTER)); 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(); 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();
} }
bool MessagesModel::setMessageImportantById(int id, RootItem::Importance important) { bool MessagesModel::setMessageImportantById(int id, RootItem::Importance important) {
for (int i = 0; i < rowCount(); i++) { for (int i = 0; i < rowCount(); i++) {
int found_id = data(i, MSG_DB_ID_INDEX, Qt::EditRole).toInt(); int found_id = data(i, MSG_DB_ID_INDEX, Qt::EditRole).toInt();
if (found_id == id) { if (found_id == id) {
bool set = setData(index(i, MSG_DB_IMPORTANT_INDEX), important); bool set = setData(index(i, MSG_DB_IMPORTANT_INDEX), important);
if (set) { if (set) {
emit dataChanged(index(i, 0), index(i, MSG_DB_CUSTOM_HASH_INDEX)); 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) { void MessagesModel::highlightMessages(MessagesModel::MessageHighlighter highlight) {
m_messageHighlighter = highlight; m_messageHighlighter = highlight;
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
emit layoutChanged(); emit layoutChanged();
} }
int MessagesModel::messageId(int row_index) const { 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 { 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 { RootItem* MessagesModel::loadedItem() const {
return m_selectedItem; return m_selectedItem;
} }
void MessagesModel::updateDateFormat() { void MessagesModel::updateDateFormat() {
if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool()) { if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool()) {
m_customDateFormat = qApp->settings()->value(GROUP(Messages), SETTING(Messages::CustomDateFormat)).toString(); m_customDateFormat = qApp->settings()->value(GROUP(Messages), SETTING(Messages::CustomDateFormat)).toString();
} }
else {
m_customDateFormat = QString(); else {
} m_customDateFormat = QString();
}
} }
void MessagesModel::reloadWholeLayout() { void MessagesModel::reloadWholeLayout() {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
emit layoutChanged(); emit layoutChanged();
} }
Message MessagesModel::messageAt(int row_index) const { 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() { void MessagesModel::setupHeaderData() {
m_headerData << /*: Tooltip for ID of message.*/ tr("Id") << m_headerData << /*: Tooltip for ID of message.*/ tr("Id") <<
/*: Tooltip for "read" column in msg list.*/ tr("Read") << /*: Tooltip for "read" column in msg list.*/ tr("Read") <<
/*: Tooltip for "deleted" column in msg list.*/ tr("Deleted") << /*: Tooltip for "deleted" column in msg list.*/ tr("Deleted") <<
/*: Tooltip for "important" column in msg list.*/ tr("Important") << /*: Tooltip for "important" column in msg list.*/ tr("Important") <<
/*: Tooltip for name of feed for message.*/ tr("Feed") << /*: Tooltip for name of feed for message.*/ tr("Feed") <<
/*: Tooltip for title of message.*/ tr("Title") << /*: Tooltip for title of message.*/ tr("Title") <<
/*: Tooltip for url of message.*/ tr("Url") << /*: Tooltip for url of message.*/ tr("Url") <<
/*: Tooltip for author of message.*/ tr("Author") << /*: Tooltip for author of message.*/ tr("Author") <<
/*: Tooltip for creation date of message.*/ tr("Created on") << /*: Tooltip for creation date of message.*/ tr("Created on") <<
/*: Tooltip for contents of message.*/ tr("Contents") << /*: Tooltip for contents of message.*/ tr("Contents") <<
/*: Tooltip for "pdeleted" column in msg list.*/ tr("Permanently deleted") << /*: Tooltip for "pdeleted" column in msg list.*/ tr("Permanently deleted") <<
/*: Tooltip for attachments of message.*/ tr("Attachments") << /*: Tooltip for attachments of message.*/ tr("Attachments") <<
/*: Tooltip for account ID of message.*/ tr("Account ID") << /*: Tooltip for account ID of message.*/ tr("Account ID") <<
/*: Tooltip for custom ID of message.*/ tr("Custom ID") << /*: Tooltip for custom ID of message.*/ tr("Custom ID") <<
/*: Tooltip for custom hash string of message.*/ tr("Custom hash") << /*: Tooltip for custom hash string of message.*/ tr("Custom hash") <<
/*: Tooltip for custom ID of feed of message.*/ tr("Feed ID");; /*: Tooltip for custom ID of feed of message.*/ tr("Feed ID");;
m_tooltipData << tr("Id of the message.") << tr("Is message read?") <<
m_tooltipData << tr("Id of the message.") << tr("Is message read?") << tr("Is message deleted?") << tr("Is message important?") <<
tr("Is message deleted?") << tr("Is message important?") << tr("Id of feed which this message belongs to.") <<
tr("Id of feed which this message belongs to.") << tr("Title of the message.") << tr("Url of the message.") <<
tr("Title of the message.") << tr("Url of the message.") << tr("Author of the message.") << tr("Creation date 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("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("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.");
tr("Custom hash of the message.") << tr("Custom ID of feed of the message.");
} }
Qt::ItemFlags MessagesModel::flags(const QModelIndex &index) const { Qt::ItemFlags MessagesModel::flags(const QModelIndex& index) const {
Q_UNUSED(index) Q_UNUSED(index)
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemNeverHasChildren;
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemNeverHasChildren;
} }
QVariant MessagesModel::data(int row, int column, int role) const { 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 { QVariant MessagesModel::data(const QModelIndex& idx, int role) const {
// This message is not in cache, return real data from live query. // This message is not in cache, return real data from live query.
switch (role) { switch (role) {
// Human readable data for viewing. // Human readable data for viewing.
case Qt::DisplayRole: { case Qt::DisplayRole: {
int index_column = idx.column(); int index_column = idx.column();
if (index_column == MSG_DB_DCREATED_INDEX) { if (index_column == MSG_DB_DCREATED_INDEX) {
QDateTime dt = TextFactory::parseDateTime(QSqlQueryModel::data(idx, role).value<qint64>()).toLocalTime(); QDateTime dt = TextFactory::parseDateTime(QSqlQueryModel::data(idx, role).value<qint64>()).toLocalTime();
if (m_customDateFormat.isEmpty()) { if (m_customDateFormat.isEmpty()) {
return dt.toString(Qt::DefaultLocaleShortDate); 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 {
} return dt.toString(m_customDateFormat);
else if (index_column != MSG_DB_IMPORTANT_INDEX && index_column != MSG_DB_READ_INDEX) { }
return QSqlQueryModel::data(idx, role); }
}
else {
return QVariant();
}
}
case Qt::EditRole: else if (index_column == MSG_DB_AUTHOR_INDEX) {
return m_cache->containsData(idx.row()) ? m_cache->data(idx) : QSqlQueryModel::data(idx, role); const QString author_name = QSqlQueryModel::data(idx, role).toString();
return author_name.isEmpty() ? QSL("-") : author_name;
}
case Qt::FontRole: { else if (index_column != MSG_DB_IMPORTANT_INDEX && index_column != MSG_DB_READ_INDEX) {
QModelIndex idx_read = index(idx.row(), MSG_DB_READ_INDEX); return QSqlQueryModel::data(idx, role);
QVariant data_read = data(idx_read, Qt::EditRole); }
const bool is_bin = qobject_cast<RecycleBin*>(loadedItem()) != nullptr; else {
bool is_deleted; return QVariant();
}
}
if (is_bin) { case Qt::EditRole:
QModelIndex idx_del = index(idx.row(), MSG_DB_PDELETED_INDEX); return m_cache->containsData(idx.row()) ? m_cache->data(idx) : QSqlQueryModel::data(idx, role);
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();
}
const bool striked = is_deleted; 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<RecycleBin*>(loadedItem()) != nullptr;
bool is_deleted;
if (data_read.toBool()) { if (is_bin) {
return striked ? m_normalStrikedFont : m_normalFont; QModelIndex idx_del = index(idx.row(), MSG_DB_PDELETED_INDEX);
} is_deleted = data(idx_del, Qt::EditRole).toBool();
else { }
return striked ? m_boldStrikedFont : m_boldFont;
}
}
case Qt::ForegroundRole: else {
switch (m_messageHighlighter) { QModelIndex idx_del = index(idx.row(), MSG_DB_DELETED_INDEX);
case HighlightImportant: { is_deleted = data(idx_del, Qt::EditRole).toBool();
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(); const bool striked = is_deleted;
}
case HighlightUnread: { if (data_read.toBool()) {
QModelIndex idx_read = index(idx.row(), MSG_DB_READ_INDEX); return striked ? m_normalStrikedFont : m_normalFont;
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(); else {
} return striked ? m_boldStrikedFont : m_boldFont;
}
}
case NoHighlighting: case Qt::ForegroundRole:
default: switch (m_messageHighlighter) {
return QVariant(); 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();
}
case Qt::DecorationRole: { case HighlightUnread: {
const int index_column = idx.column(); 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();
}
if (index_column == MSG_DB_READ_INDEX) { case NoHighlighting:
QModelIndex idx_read = index(idx.row(), MSG_DB_READ_INDEX); default:
QVariant dta = m_cache->containsData(idx_read.row()) ? m_cache->data(idx_read) : QSqlQueryModel::data(idx_read); return QVariant();
}
return dta.toInt() == 1 ? m_readIcon : m_unreadIcon; case Qt::DecorationRole: {
} const int index_column = idx.column();
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(); if (index_column == MSG_DB_READ_INDEX) {
} QModelIndex idx_read = index(idx.row(), MSG_DB_READ_INDEX);
else { QVariant dta = m_cache->containsData(idx_read.row()) ? m_cache->data(idx_read) : QSqlQueryModel::data(idx_read);
return QVariant(); return dta.toInt() == 1 ? m_readIcon : m_unreadIcon;
} }
}
default: else if (index_column == MSG_DB_IMPORTANT_INDEX) {
return QVariant(); 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) { bool MessagesModel::setMessageRead(int row_index, RootItem::ReadStatus read) {
if (data(row_index, MSG_DB_READ_INDEX, Qt::EditRole).toInt() == read) { if (data(row_index, MSG_DB_READ_INDEX, Qt::EditRole).toInt() == read) {
// Read status is the same is the one currently set. // Read status is the same is the one currently set.
// In that case, no extra work is needed. // In that case, no extra work is needed.
return true; return true;
} }
Message message = messageAt(row_index); Message message = messageAt(row_index);
if (!m_selectedItem->getParentServiceRoot()->onBeforeSetMessagesRead(m_selectedItem, QList<Message>() << message, read)) { if (!m_selectedItem->getParentServiceRoot()->onBeforeSetMessagesRead(m_selectedItem, QList<Message>() << message, read)) {
// Cannot change read status of the item. Abort. // Cannot change read status of the item. Abort.
return false; return false;
} }
// Rewrite "visible" data in the model. // Rewrite "visible" data in the model.
bool working_change = setData(index(row_index, MSG_DB_READ_INDEX), read); bool working_change = setData(index(row_index, MSG_DB_READ_INDEX), read);
if (!working_change) { if (!working_change) {
// If rewriting in the model failed, then cancel all actions. // If rewriting in the model failed, then cancel all actions.
qDebug("Setting of new data to the model failed for message read change."); qDebug("Setting of new data to the model failed for message read change.");
return false; return false;
} }
if (DatabaseQueries::markMessagesReadUnread(m_db, QStringList() << QString::number(message.m_id), read)) { if (DatabaseQueries::markMessagesReadUnread(m_db, QStringList() << QString::number(message.m_id), read)) {
return m_selectedItem->getParentServiceRoot()->onAfterSetMessagesRead(m_selectedItem, QList<Message>() << message, read); return m_selectedItem->getParentServiceRoot()->onAfterSetMessagesRead(m_selectedItem, QList<Message>() << message, read);
} }
else {
return false; else {
} return false;
}
} }
bool MessagesModel::setMessageReadById(int id, RootItem::ReadStatus read) { bool MessagesModel::setMessageReadById(int id, RootItem::ReadStatus read) {
for (int i = 0; i < rowCount(); i++) { for (int i = 0; i < rowCount(); i++) {
int found_id = data(i, MSG_DB_ID_INDEX, Qt::EditRole).toInt(); int found_id = data(i, MSG_DB_ID_INDEX, Qt::EditRole).toInt();
if (found_id == id) { if (found_id == id) {
bool set = setData(index(i, MSG_DB_READ_INDEX), read); bool set = setData(index(i, MSG_DB_READ_INDEX), read);
if (set) { if (set) {
emit dataChanged(index(i, 0), index(i, MSG_DB_CUSTOM_HASH_INDEX)); 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) { bool MessagesModel::switchMessageImportance(int row_index) {
const QModelIndex target_index = index(row_index, MSG_DB_IMPORTANT_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 current_importance = (RootItem::Importance) data(target_index, Qt::EditRole).toInt();
const RootItem::Importance next_importance = current_importance == RootItem::Important ? const RootItem::Importance next_importance = current_importance == RootItem::Important ?
RootItem::NotImportant : RootItem::Important; RootItem::NotImportant : RootItem::Important;
const Message message = messageAt(row_index); const Message message = messageAt(row_index);
const QPair<Message,RootItem::Importance> pair(message, next_importance); const QPair<Message, RootItem::Importance> pair(message, next_importance);
if (!m_selectedItem->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_selectedItem, if (!m_selectedItem->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_selectedItem,
QList<QPair<Message,RootItem::Importance> >() << pair)) { QList<QPair<Message, RootItem::Importance>>() << pair)) {
return false; return false;
} }
// Rewrite "visible" data in the model. // Rewrite "visible" data in the model.
const bool working_change = setData(target_index, next_importance); const bool working_change = setData(target_index, next_importance);
if (!working_change) { if (!working_change) {
// If rewriting in the model failed, then cancel all actions. // If rewriting in the model failed, then cancel all actions.
qDebug("Setting of new data to the model failed for message importance change."); qDebug("Setting of new data to the model failed for message importance change.");
return false; return false;
} }
// Commit changes. // Commit changes.
if (DatabaseQueries::markMessageImportant(m_db, message.m_id, next_importance)) { 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<int>() << Qt::FontRole); emit dataChanged(index(row_index, 0), index(row_index, MSG_DB_FEED_CUSTOM_ID_INDEX), QVector<int>() << Qt::FontRole);
return m_selectedItem->getParentServiceRoot()->onAfterSwitchMessageImportance(m_selectedItem,
QList<QPair<Message, RootItem::Importance>>() << pair);
}
return m_selectedItem->getParentServiceRoot()->onAfterSwitchMessageImportance(m_selectedItem, else {
QList<QPair<Message,RootItem::Importance> >() << pair); return false;
} }
else {
return false;
}
} }
bool MessagesModel::switchBatchMessageImportance(const QModelIndexList &messages) { bool MessagesModel::switchBatchMessageImportance(const QModelIndexList& messages) {
QStringList message_ids; QStringList message_ids;
QList<QPair<Message,RootItem::Importance> > message_states; QList<QPair<Message, RootItem::Importance>> message_states;
// Obtain IDs of all desired messages. // Obtain IDs of all desired messages.
foreach (const QModelIndex &message, messages) { foreach (const QModelIndex& message, messages) {
const Message msg = messageAt(message.row()); const Message msg = messageAt(message.row());
RootItem::Importance message_importance = messageImportance((message.row())); RootItem::Importance message_importance = messageImportance((message.row()));
message_states.append(QPair<Message, RootItem::Importance>(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);
}
message_states.append(QPair<Message,RootItem::Importance>(msg, message_importance == RootItem::Important ? reloadWholeLayout();
RootItem::NotImportant :
RootItem::Important));
message_ids.append(QString::number(msg.m_id));
QModelIndex idx_msg_imp = index(message.row(), MSG_DB_IMPORTANT_INDEX); if (!m_selectedItem->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_selectedItem, message_states)) {
setData(idx_msg_imp, message_importance == RootItem::Important ? return false;
(int) RootItem::NotImportant : }
(int) RootItem::Important);
}
reloadWholeLayout(); if (DatabaseQueries::switchMessagesImportance(m_db, message_ids)) {
return m_selectedItem->getParentServiceRoot()->onAfterSwitchMessageImportance(m_selectedItem, message_states);
}
if (!m_selectedItem->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_selectedItem, message_states)) { else {
return false; 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) { bool MessagesModel::setBatchMessagesDeleted(const QModelIndexList& messages) {
QStringList message_ids; QStringList message_ids;
QList<Message> msgs; QList<Message> msgs;
// Obtain IDs of all desired messages. // Obtain IDs of all desired messages.
foreach (const QModelIndex &message, messages) { foreach (const QModelIndex& message, messages) {
const Message msg = messageAt(message.row()); const Message msg = messageAt(message.row());
msgs.append(msg);
message_ids.append(QString::number(msg.m_id));
msgs.append(msg); if (qobject_cast<RecycleBin*>(m_selectedItem) != nullptr) {
message_ids.append(QString::number(msg.m_id)); setData(index(message.row(), MSG_DB_PDELETED_INDEX), 1);
}
if (qobject_cast<RecycleBin*>(m_selectedItem) != nullptr) { else {
setData(index(message.row(), MSG_DB_PDELETED_INDEX), 1); setData(index(message.row(), MSG_DB_DELETED_INDEX), 1);
} }
else { }
setData(index(message.row(), MSG_DB_DELETED_INDEX), 1);
}
}
reloadWholeLayout(); reloadWholeLayout();
if (!m_selectedItem->getParentServiceRoot()->onBeforeMessagesDelete(m_selectedItem, msgs)) { if (!m_selectedItem->getParentServiceRoot()->onBeforeMessagesDelete(m_selectedItem, msgs)) {
return false; return false;
} }
bool deleted; bool deleted;
if (m_selectedItem->kind() != RootItemKind::Bin) { if (m_selectedItem->kind() != RootItemKind::Bin) {
deleted = DatabaseQueries::deleteOrRestoreMessagesToFromBin(m_db, message_ids, true); deleted = DatabaseQueries::deleteOrRestoreMessagesToFromBin(m_db, message_ids, true);
} }
else {
deleted = DatabaseQueries::permanentlyDeleteMessages(m_db, message_ids);
}
if (deleted) { else {
return m_selectedItem->getParentServiceRoot()->onAfterMessagesDelete(m_selectedItem, msgs); deleted = DatabaseQueries::permanentlyDeleteMessages(m_db, message_ids);
} }
else {
return false; if (deleted) {
} return m_selectedItem->getParentServiceRoot()->onAfterMessagesDelete(m_selectedItem, msgs);
}
else {
return false;
}
} }
bool MessagesModel::setBatchMessagesRead(const QModelIndexList &messages, RootItem::ReadStatus read) { bool MessagesModel::setBatchMessagesRead(const QModelIndexList& messages, RootItem::ReadStatus read) {
QStringList message_ids; QStringList message_ids;
QList<Message> msgs; QList<Message> msgs;
// Obtain IDs of all desired messages. // Obtain IDs of all desired messages.
foreach (const QModelIndex &message, messages) { foreach (const QModelIndex& message, messages) {
Message msg = messageAt(message.row()); 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);
}
msgs.append(msg); reloadWholeLayout();
message_ids.append(QString::number(msg.m_id));
setData(index(message.row(), MSG_DB_READ_INDEX), (int) read); if (!m_selectedItem->getParentServiceRoot()->onBeforeSetMessagesRead(m_selectedItem, msgs, read)) {
} return false;
}
reloadWholeLayout(); if (DatabaseQueries::markMessagesReadUnread(m_db, message_ids, read)) {
return m_selectedItem->getParentServiceRoot()->onAfterSetMessagesRead(m_selectedItem, msgs, read);
}
if (!m_selectedItem->getParentServiceRoot()->onBeforeSetMessagesRead(m_selectedItem, msgs, read)) { else {
return false; 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) { bool MessagesModel::setBatchMessagesRestored(const QModelIndexList& messages) {
QStringList message_ids; QStringList message_ids;
QList<Message> msgs; QList<Message> msgs;
// Obtain IDs of all desired messages. // Obtain IDs of all desired messages.
foreach (const QModelIndex &message, messages) { foreach (const QModelIndex& message, messages) {
const Message msg = messageAt(message.row()); 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);
}
msgs.append(msg); reloadWholeLayout();
message_ids.append(QString::number(msg.m_id));
setData(index(message.row(), MSG_DB_PDELETED_INDEX), 0); if (!m_selectedItem->getParentServiceRoot()->onBeforeMessagesRestoredFromBin(m_selectedItem, msgs)) {
setData(index(message.row(), MSG_DB_DELETED_INDEX), 0); return false;
} }
reloadWholeLayout(); if (DatabaseQueries::deleteOrRestoreMessagesToFromBin(m_db, message_ids, false)) {
return m_selectedItem->getParentServiceRoot()->onAfterMessagesRestoredFromBin(m_selectedItem, msgs);
}
if (!m_selectedItem->getParentServiceRoot()->onBeforeMessagesRestoredFromBin(m_selectedItem, msgs)) { else {
return false; 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 { QVariant MessagesModel::headerData(int section, Qt::Orientation orientation, int role) const {
Q_UNUSED(orientation) Q_UNUSED(orientation)
switch (role) { switch (role) {
case Qt::DisplayRole: 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();
}
case Qt::ToolTipRole: // Display textual headers for all columns except "read" and
return m_tooltipData.at(section); // "important" columns.
if (section != MSG_DB_READ_INDEX && section != MSG_DB_IMPORTANT_INDEX) {
return m_headerData.at(section);
}
case Qt::EditRole: else {
return m_headerData.at(section); return QVariant();
}
// Display icons for "read" and "important" columns. case Qt::ToolTipRole:
case Qt::DecorationRole: { return m_tooltipData.at(section);
switch (section) {
case MSG_DB_READ_INDEX:
return m_readIcon;
case MSG_DB_IMPORTANT_INDEX: case Qt::EditRole:
return m_favoriteIcon; return m_headerData.at(section);
default: // Display icons for "read" and "important" columns.
return QVariant(); case Qt::DecorationRole: {
} switch (section) {
} case MSG_DB_READ_INDEX:
return m_readIcon;
default: case MSG_DB_IMPORTANT_INDEX:
return QVariant(); return m_favoriteIcon;
}
default:
return QVariant();
}
}
default:
return QVariant();
}
} }

View file

@ -32,84 +32,84 @@
class MessagesModelCache; class MessagesModelCache;
class MessagesModel : public QSqlQueryModel, public MessagesModelSqlLayer { class MessagesModel : public QSqlQueryModel, public MessagesModelSqlLayer {
Q_OBJECT Q_OBJECT
public: public:
// Enum which describes basic filtering schemes // Enum which describes basic filtering schemes
// for messages. // for messages.
enum MessageHighlighter { enum MessageHighlighter {
NoHighlighting = 100, NoHighlighting = 100,
HighlightUnread = 101, HighlightUnread = 101,
HighlightImportant = 102 HighlightImportant = 102
}; };
// Constructors and destructors. // Constructors and destructors.
explicit MessagesModel(QObject *parent = 0); explicit MessagesModel(QObject* parent = 0);
virtual ~MessagesModel(); virtual ~MessagesModel();
// Fetches ALL available data to the model. // Fetches ALL available data to the model.
// NOTE: This activates the SQL query and populates the model with new data. // NOTE: This activates the SQL query and populates the model with new data.
void repopulate(); void repopulate();
// Model implementation. // Model implementation.
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
QVariant data(int row, int column, 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; QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex& index) const;
// Returns message at given index. // Returns message at given index.
Message messageAt(int row_index) const; Message messageAt(int row_index) const;
int messageId(int row_index) const; int messageId(int row_index) const;
RootItem::Importance messageImportance(int row_index) const; RootItem::Importance messageImportance(int row_index) const;
RootItem *loadedItem() const; RootItem* loadedItem() const;
void updateDateFormat(); void updateDateFormat();
void reloadWholeLayout(); void reloadWholeLayout();
// SINGLE message manipulators. // SINGLE message manipulators.
bool switchMessageImportance(int row_index); bool switchMessageImportance(int row_index);
bool setMessageRead(int row_index, RootItem::ReadStatus read); bool setMessageRead(int row_index, RootItem::ReadStatus read);
// BATCH messages manipulators. // BATCH messages manipulators.
bool switchBatchMessageImportance(const QModelIndexList &messages); bool switchBatchMessageImportance(const QModelIndexList& messages);
bool setBatchMessagesDeleted(const QModelIndexList &messages); bool setBatchMessagesDeleted(const QModelIndexList& messages);
bool setBatchMessagesRead(const QModelIndexList &messages, RootItem::ReadStatus read); bool setBatchMessagesRead(const QModelIndexList& messages, RootItem::ReadStatus read);
bool setBatchMessagesRestored(const QModelIndexList &messages); bool setBatchMessagesRestored(const QModelIndexList& messages);
// Highlights messages. // Highlights messages.
void highlightMessages(MessageHighlighter highlight); void highlightMessages(MessageHighlighter highlight);
// Loads messages of given feeds. // Loads messages of given feeds.
void loadMessages(RootItem *item); void loadMessages(RootItem* item);
public slots: public slots:
// NOTE: These methods DO NOT actually change data in the DB, just in the model. // NOTE: These methods DO NOT actually change data in the DB, just in the model.
// These are particularly used by msg browser. // These are particularly used by msg browser.
bool setMessageImportantById(int id, RootItem::Importance important); bool setMessageImportantById(int id, RootItem::Importance important);
bool setMessageReadById(int id, RootItem::ReadStatus read); bool setMessageReadById(int id, RootItem::ReadStatus read);
private: private:
void setupHeaderData(); void setupHeaderData();
void setupFonts(); void setupFonts();
void setupIcons(); void setupIcons();
MessagesModelCache *m_cache; MessagesModelCache* m_cache;
MessageHighlighter m_messageHighlighter; MessageHighlighter m_messageHighlighter;
QString m_customDateFormat; QString m_customDateFormat;
RootItem *m_selectedItem; RootItem* m_selectedItem;
QList<QString> m_headerData; QList<QString> m_headerData;
QList<QString> m_tooltipData; QList<QString> m_tooltipData;
QFont m_normalFont; QFont m_normalFont;
QFont m_boldFont; QFont m_boldFont;
QFont m_normalStrikedFont; QFont m_normalStrikedFont;
QFont m_boldStrikedFont; QFont m_boldStrikedFont;
QIcon m_favoriteIcon; QIcon m_favoriteIcon;
QIcon m_readIcon; QIcon m_readIcon;
QIcon m_unreadIcon; QIcon m_unreadIcon;
}; };
Q_DECLARE_METATYPE(MessagesModel::MessageHighlighter) Q_DECLARE_METATYPE(MessagesModel::MessageHighlighter)

View file

@ -1,39 +1,39 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "core/messagesmodelcache.h" #include "core/messagesmodelcache.h"
#include "miscellaneous/textfactory.h" #include "miscellaneous/textfactory.h"
MessagesModelCache::MessagesModelCache(QObject *parent) : QObject(parent), m_msgCache(QHash<int,QSqlRecord>()) { MessagesModelCache::MessagesModelCache(QObject* parent) : QObject(parent), m_msgCache(QHash<int, QSqlRecord>()) {
} }
MessagesModelCache::~MessagesModelCache() { MessagesModelCache::~MessagesModelCache() {
} }
void MessagesModelCache::setData(const QModelIndex &index, const QVariant &value, const QSqlRecord &record) { void MessagesModelCache::setData(const QModelIndex& index, const QVariant& value, const QSqlRecord& record) {
if (!m_msgCache.contains(index.row())) { if (!m_msgCache.contains(index.row())) {
m_msgCache[index.row()] = record; 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) { QVariant MessagesModelCache::data(const QModelIndex& idx) {
return m_msgCache[idx.row()].value(idx.column()); return m_msgCache[idx.row()].value(idx.column());
} }

View file

@ -1,55 +1,55 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef MESSAGESMODELCACHE_H #ifndef MESSAGESMODELCACHE_H
#define MESSAGESMODELCACHE_H #define MESSAGESMODELCACHE_H
#include <QObject> #include <QObject>
#include "core/message.h" #include "core/message.h"
#include <QVariant> #include <QVariant>
#include <QModelIndex> #include <QModelIndex>
class MessagesModelCache : public QObject { class MessagesModelCache : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit MessagesModelCache(QObject *parent = nullptr); explicit MessagesModelCache(QObject* parent = nullptr);
virtual ~MessagesModelCache(); virtual ~MessagesModelCache();
inline bool containsData(int row_idx) const { inline bool containsData(int row_idx) const {
return m_msgCache.contains(row_idx); return m_msgCache.contains(row_idx);
} }
inline QSqlRecord record(int row_idx) const { inline QSqlRecord record(int row_idx) const {
return m_msgCache.value(row_idx); return m_msgCache.value(row_idx);
} }
inline void clear() { inline void clear() {
m_msgCache.clear(); m_msgCache.clear();
} }
void setData(const QModelIndex &index, const QVariant &value, const QSqlRecord &record); void setData(const QModelIndex& index, const QVariant& value, const QSqlRecord& record);
QVariant data(const QModelIndex &idx); QVariant data(const QModelIndex& idx);
private: private:
QHash<int,QSqlRecord> m_msgCache; QHash<int, QSqlRecord> m_msgCache;
}; };
#endif // MESSAGESMODELCACHE_H #endif // MESSAGESMODELCACHE_H

View file

@ -1,105 +1,105 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "core/messagesmodelsqllayer.h" #include "core/messagesmodelsqllayer.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
MessagesModelSqlLayer::MessagesModelSqlLayer() MessagesModelSqlLayer::MessagesModelSqlLayer()
: m_filter(QSL(DEFAULT_SQL_MESSAGES_FILTER)), m_fieldNames(QMap<int,QString>()), : m_filter(QSL(DEFAULT_SQL_MESSAGES_FILTER)), m_fieldNames(QMap<int, QString>()),
m_sortColumns(QList<int>()), m_sortOrders(QList<Qt::SortOrder>()){ m_sortColumns(QList<int>()), m_sortOrders(QList<Qt::SortOrder>()) {
m_db = qApp->database()->connection(QSL("MessagesModel"), DatabaseFactory::FromSettings); m_db = qApp->database()->connection(QSL("MessagesModel"), DatabaseFactory::FromSettings);
m_fieldNames[MSG_DB_ID_INDEX] = "Messages.id";
m_fieldNames[MSG_DB_ID_INDEX] = "Messages.id"; m_fieldNames[MSG_DB_READ_INDEX] = "Messages.is_read";
m_fieldNames[MSG_DB_READ_INDEX] = "Messages.is_read"; m_fieldNames[MSG_DB_DELETED_INDEX] = "Messages.is_deleted";
m_fieldNames[MSG_DB_DELETED_INDEX] = "Messages.is_deleted"; m_fieldNames[MSG_DB_IMPORTANT_INDEX] = "Messages.is_important";
m_fieldNames[MSG_DB_IMPORTANT_INDEX] = "Messages.is_important"; m_fieldNames[MSG_DB_FEED_TITLE_INDEX] = "Feeds.title";
m_fieldNames[MSG_DB_FEED_TITLE_INDEX] = "Feeds.title"; m_fieldNames[MSG_DB_TITLE_INDEX] = "Messages.title";
m_fieldNames[MSG_DB_TITLE_INDEX] = "Messages.title"; m_fieldNames[MSG_DB_URL_INDEX] = "Messages.url";
m_fieldNames[MSG_DB_URL_INDEX] = "Messages.url"; m_fieldNames[MSG_DB_AUTHOR_INDEX] = "Messages.author";
m_fieldNames[MSG_DB_AUTHOR_INDEX] = "Messages.author"; m_fieldNames[MSG_DB_DCREATED_INDEX] = "Messages.date_created";
m_fieldNames[MSG_DB_DCREATED_INDEX] = "Messages.date_created"; m_fieldNames[MSG_DB_CONTENTS_INDEX] = "Messages.contents";
m_fieldNames[MSG_DB_CONTENTS_INDEX] = "Messages.contents"; m_fieldNames[MSG_DB_PDELETED_INDEX] = "Messages.is_pdeleted";
m_fieldNames[MSG_DB_PDELETED_INDEX] = "Messages.is_pdeleted"; m_fieldNames[MSG_DB_ENCLOSURES_INDEX] = "Messages.enclosures";
m_fieldNames[MSG_DB_ENCLOSURES_INDEX] = "Messages.enclosures"; m_fieldNames[MSG_DB_ACCOUNT_ID_INDEX] = "Messages.account_id";
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_ID_INDEX] = "Messages.custom_id"; m_fieldNames[MSG_DB_CUSTOM_HASH_INDEX] = "Messages.custom_hash";
m_fieldNames[MSG_DB_CUSTOM_HASH_INDEX] = "Messages.custom_hash"; m_fieldNames[MSG_DB_FEED_CUSTOM_ID_INDEX] = "Messages.feed";
m_fieldNames[MSG_DB_FEED_CUSTOM_ID_INDEX] = "Messages.feed"; }
}
void MessagesModelSqlLayer::addSortState(int column, Qt::SortOrder order) {
void MessagesModelSqlLayer::addSortState(int column, Qt::SortOrder order) { int existing = m_sortColumns.indexOf(column);
int existing = m_sortColumns.indexOf(column); bool is_ctrl_pressed = (QApplication::queryKeyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier;
bool is_ctrl_pressed = (QApplication::queryKeyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier;
if (existing >= 0) {
if (existing >= 0) { m_sortColumns.removeAt(existing);
m_sortColumns.removeAt(existing); m_sortOrders.removeAt(existing);
m_sortOrders.removeAt(existing); }
}
if (m_sortColumns.size() > MAX_MULTICOLUMN_SORT_STATES) {
if (m_sortColumns.size() > MAX_MULTICOLUMN_SORT_STATES) { // We support only limited number of sort states
// We support only limited number of sort states // due to DB performance.
// due to DB performance. m_sortColumns.removeAt(0);
m_sortColumns.removeAt(0); m_sortOrders.removeAt(0);
m_sortOrders.removeAt(0); }
}
if (is_ctrl_pressed) {
if (is_ctrl_pressed) { // User is activating the multicolumn sort mode.
// User is activating the multicolumn sort mode. m_sortColumns.append(column);
m_sortColumns.append(column); m_sortOrders.append(order);
m_sortOrders.append(order); }
}
else { else {
m_sortColumns.prepend(column); m_sortColumns.prepend(column);
m_sortOrders.prepend(order); 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) { void MessagesModelSqlLayer::setFilter(const QString& filter) {
m_filter = filter; m_filter = filter;
} }
QString MessagesModelSqlLayer::formatFields() const { QString MessagesModelSqlLayer::formatFields() const {
return m_fieldNames.values().join(QSL(", ")); return m_fieldNames.values().join(QSL(", "));
} }
QString MessagesModelSqlLayer::selectStatement() const { QString MessagesModelSqlLayer::selectStatement() const {
return QL1S("SELECT ") + formatFields() + return QL1S("SELECT ") + formatFields() +
QSL(" FROM Messages LEFT JOIN Feeds ON Messages.feed = Feeds.custom_id AND Messages.account_id = Feeds.account_id WHERE ") + QSL(" FROM Messages LEFT JOIN Feeds ON Messages.feed = Feeds.custom_id AND Messages.account_id = Feeds.account_id WHERE ") +
m_filter + orderByClause() + QL1C(';'); m_filter + orderByClause() + QL1C(';');
} }
QString MessagesModelSqlLayer::orderByClause() const { QString MessagesModelSqlLayer::orderByClause() const {
if (m_sortColumns.isEmpty()) { if (m_sortColumns.isEmpty()) {
return QString(); return QString();
} }
else {
QStringList sorts; else {
QStringList sorts;
for (int i = 0; i < m_sortColumns.size(); i++) {
QString field_name(m_fieldNames[m_sortColumns[i]]); 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"))); sorts.append(field_name + (m_sortOrders[i] == Qt::AscendingOrder ? QSL(" ASC") : QSL(" DESC")));
} }
return QL1S(" ORDER BY ") + sorts.join(QSL(", ")); return QL1S(" ORDER BY ") + sorts.join(QSL(", "));
} }
} }

View file

@ -1,56 +1,56 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef MESSAGESMODELSQLLAYER_H #ifndef MESSAGESMODELSQLLAYER_H
#define MESSAGESMODELSQLLAYER_H #define MESSAGESMODELSQLLAYER_H
#include <QSqlDatabase> #include <QSqlDatabase>
#include <QMap> #include <QMap>
#include <QList> #include <QList>
class MessagesModelSqlLayer { class MessagesModelSqlLayer {
public: public:
explicit MessagesModelSqlLayer(); explicit MessagesModelSqlLayer();
// Adds this new state to queue of sort states. // Adds this new state to queue of sort states.
void addSortState(int column, Qt::SortOrder order); void addSortState(int column, Qt::SortOrder order);
// Sets SQL WHERE clause, without "WHERE" keyword. // Sets SQL WHERE clause, without "WHERE" keyword.
void setFilter(const QString &filter); void setFilter(const QString& filter);
protected: protected:
QString orderByClause() const; QString orderByClause() const;
QString selectStatement() const; QString selectStatement() const;
QString formatFields() const; QString formatFields() const;
QSqlDatabase m_db; QSqlDatabase m_db;
private: private:
QString m_filter; QString m_filter;
// NOTE: These two lists contain data for multicolumn sorting. // NOTE: These two lists contain data for multicolumn sorting.
// They are always same length. Most important sort column/order // They are always same length. Most important sort column/order
// are located at the start of lists; // are located at the start of lists;
QMap<int,QString> m_fieldNames; QMap<int, QString> m_fieldNames;
QList<int> m_sortColumns; QList<int> m_sortColumns;
QList<Qt::SortOrder> m_sortOrders; QList<Qt::SortOrder> m_sortOrders;
}; };
#endif // MESSAGESMODELSQLLAYER_H #endif // MESSAGESMODELSQLLAYER_H

View file

@ -20,174 +20,181 @@
#include "core/messagesmodel.h" #include "core/messagesmodel.h"
MessagesProxyModel::MessagesProxyModel(MessagesModel *source_model, QObject *parent) MessagesProxyModel::MessagesProxyModel(MessagesModel* source_model, QObject* parent)
: QSortFilterProxyModel(parent), m_sourceModel(source_model) { : QSortFilterProxyModel(parent), m_sourceModel(source_model) {
setObjectName(QSL("MessagesProxyModel"));
setObjectName(QSL("MessagesProxyModel")); setSortRole(Qt::EditRole);
setSortRole(Qt::EditRole); setSortCaseSensitivity(Qt::CaseInsensitive);
setSortCaseSensitivity(Qt::CaseInsensitive); setFilterCaseSensitivity(Qt::CaseInsensitive);
setFilterCaseSensitivity(Qt::CaseInsensitive); setFilterKeyColumn(-1);
setFilterKeyColumn(-1); setFilterRole(Qt::EditRole);
setFilterRole(Qt::EditRole); setDynamicSortFilter(false);
setDynamicSortFilter(false); setSourceModel(m_sourceModel);
setSourceModel(m_sourceModel);
} }
MessagesProxyModel::~MessagesProxyModel() { MessagesProxyModel::~MessagesProxyModel() {
qDebug("Destroying MessagesProxyModel instance."); qDebug("Destroying MessagesProxyModel instance.");
} }
QModelIndex MessagesProxyModel::getNextPreviousUnreadItemIndex(int default_row) { QModelIndex MessagesProxyModel::getNextPreviousUnreadItemIndex(int default_row) {
const bool started_from_zero = default_row == 0; const bool started_from_zero = default_row == 0;
QModelIndex next_index = getNextUnreadItemIndex(default_row, rowCount() - 1); QModelIndex next_index = getNextUnreadItemIndex(default_row, rowCount() - 1);
// There is no next message, check previous. // There is no next message, check previous.
if (!next_index.isValid() && !started_from_zero) { if (!next_index.isValid() && !started_from_zero) {
next_index = getNextUnreadItemIndex(0, default_row - 1); next_index = getNextUnreadItemIndex(0, default_row - 1);
} }
return next_index; return next_index;
} }
QModelIndex MessagesProxyModel::getNextUnreadItemIndex(int default_row, int max_row) const { QModelIndex MessagesProxyModel::getNextUnreadItemIndex(int default_row, int max_row) const {
while (default_row <= max_row) { while (default_row <= max_row) {
// Get info if the message is read or not. // Get info if the message is read or not.
const QModelIndex proxy_index = index(default_row, MSG_DB_READ_INDEX); const QModelIndex proxy_index = index(default_row, MSG_DB_READ_INDEX);
const bool is_read = m_sourceModel->data(mapToSource(proxy_index).row(), const bool is_read = m_sourceModel->data(mapToSource(proxy_index).row(),
MSG_DB_READ_INDEX, Qt::EditRole).toInt() == 1; MSG_DB_READ_INDEX, Qt::EditRole).toInt() == 1;
if (!is_read) { if (!is_read) {
// We found unread message, mark it. // We found unread message, mark it.
return proxy_index; return proxy_index;
} }
else {
default_row++;
}
}
return QModelIndex(); else {
default_row++;
}
}
return QModelIndex();
} }
bool MessagesProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { bool MessagesProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const {
Q_UNUSED(left) Q_UNUSED(left)
Q_UNUSED(right) Q_UNUSED(right)
// NOTE: Comparisons are done by SQL servers itself, not client-side.
// NOTE: Comparisons are done by SQL servers itself, not client-side. return false;
return false;
} }
QModelIndexList MessagesProxyModel::mapListFromSource(const QModelIndexList &indexes, bool deep) const { QModelIndexList MessagesProxyModel::mapListFromSource(const QModelIndexList& indexes, bool deep) const {
QModelIndexList mapped_indexes; QModelIndexList mapped_indexes;
foreach (const QModelIndex &index, indexes) { foreach (const QModelIndex& index, indexes) {
if (deep) { if (deep) {
// Construct new source index. // Construct new source index.
mapped_indexes << mapFromSource(m_sourceModel->index(index.row(), index.column())); mapped_indexes << mapFromSource(m_sourceModel->index(index.row(), index.column()));
} }
else {
mapped_indexes << mapFromSource(index);
}
}
return mapped_indexes; else {
mapped_indexes << mapFromSource(index);
}
}
return mapped_indexes;
} }
QModelIndexList MessagesProxyModel::match(const QModelIndex &start, int role, QModelIndexList MessagesProxyModel::match(const QModelIndex& start, int role,
const QVariant &entered_value, int hits, Qt::MatchFlags flags) const { const QVariant& entered_value, int hits, Qt::MatchFlags flags) const {
QModelIndexList result; QModelIndexList result;
const uint match_type = flags & 0x0F; const uint match_type = flags & 0x0F;
const Qt::CaseSensitivity case_sensitivity = Qt::CaseInsensitive; const Qt::CaseSensitivity case_sensitivity = Qt::CaseInsensitive;
const bool wrap = flags & Qt::MatchWrap; const bool wrap = flags & Qt::MatchWrap;
const bool all_hits = (hits == -1); const bool all_hits = (hits == -1);
QString entered_text; QString entered_text;
int from = start.row(); int from = start.row();
int to = rowCount(); int to = rowCount();
for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); i++) { for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); i++) {
for (int r = from; (r < to) && (all_hits || result.count() < hits); r++) { for (int r = from; (r < to) && (all_hits || result.count() < hits); r++) {
QModelIndex idx = index(r, start.column()); QModelIndex idx = index(r, start.column());
if (!idx.isValid()) { if (!idx.isValid()) {
continue; 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. // QVariant based matching.
if (match_type == Qt::MatchExactly) { if (match_type == Qt::MatchExactly) {
if (entered_value == item_value) { if (entered_value == item_value) {
result.append(idx); result.append(idx);
} }
} }
// QString based matching.
else {
if (entered_text.isEmpty()) {
entered_text = entered_value.toString();
}
QString item_text = item_value.toString(); // QString based matching.
else {
if (entered_text.isEmpty()) {
entered_text = entered_value.toString();
}
switch (match_type) { QString item_text = item_value.toString();
case Qt::MatchRegExp:
if (QRegExp(entered_text, case_sensitivity).exactMatch(item_text)) {
result.append(idx);
}
break;
case Qt::MatchWildcard: switch (match_type) {
if (QRegExp(entered_text, case_sensitivity, QRegExp::Wildcard).exactMatch(item_text)) { case Qt::MatchRegExp:
result.append(idx); if (QRegExp(entered_text, case_sensitivity).exactMatch(item_text)) {
} result.append(idx);
break; }
case Qt::MatchStartsWith: break;
if (item_text.startsWith(entered_text, case_sensitivity)) {
result.append(idx);
}
break;
case Qt::MatchEndsWith: case Qt::MatchWildcard:
if (item_text.endsWith(entered_text, case_sensitivity)) { if (QRegExp(entered_text, case_sensitivity, QRegExp::Wildcard).exactMatch(item_text)) {
result.append(idx); result.append(idx);
} }
break;
case Qt::MatchFixedString: break;
if (item_text.compare(entered_text, case_sensitivity) == 0) {
result.append(idx);
}
break;
case Qt::MatchContains: case Qt::MatchStartsWith:
default: if (item_text.startsWith(entered_text, case_sensitivity)) {
if (item_text.contains(entered_text, case_sensitivity)) { result.append(idx);
result.append(idx); }
}
break;
}
}
}
// Prepare for the next iteration. break;
from = 0;
to = start.row();
}
return result; case Qt::MatchEndsWith:
if (item_text.endsWith(entered_text, case_sensitivity)) {
result.append(idx);
}
break;
case Qt::MatchFixedString:
if (item_text.compare(entered_text, case_sensitivity) == 0) {
result.append(idx);
}
break;
case Qt::MatchContains:
default:
if (item_text.contains(entered_text, case_sensitivity)) {
result.append(idx);
}
break;
}
}
}
// Prepare for the next iteration.
from = 0;
to = start.row();
}
return result;
} }
void MessagesProxyModel::sort(int column, Qt::SortOrder order) { void MessagesProxyModel::sort(int column, Qt::SortOrder order) {
// NOTE: Ignore here, sort is done elsewhere (server-side). // NOTE: Ignore here, sort is done elsewhere (server-side).
Q_UNUSED(column) Q_UNUSED(column)
Q_UNUSED(order) Q_UNUSED(order)
} }
QModelIndexList MessagesProxyModel::mapListToSource(const QModelIndexList &indexes) const { QModelIndexList MessagesProxyModel::mapListToSource(const QModelIndexList& indexes) const {
QModelIndexList source_indexes; QModelIndexList source_indexes;
foreach (const QModelIndex &index, indexes) { foreach (const QModelIndex& index, indexes) {
source_indexes << mapToSource(index); source_indexes << mapToSource(index);
} }
return source_indexes; return source_indexes;
} }

View file

@ -24,33 +24,33 @@
class MessagesModel; class MessagesModel;
class MessagesProxyModel : public QSortFilterProxyModel { class MessagesProxyModel : public QSortFilterProxyModel {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit MessagesProxyModel(MessagesModel *source_model, QObject *parent = 0); explicit MessagesProxyModel(MessagesModel* source_model, QObject* parent = 0);
virtual ~MessagesProxyModel(); virtual ~MessagesProxyModel();
QModelIndex getNextPreviousUnreadItemIndex(int default_row); QModelIndex getNextPreviousUnreadItemIndex(int default_row);
// Maps list of indexes. // Maps list of indexes.
QModelIndexList mapListToSource(const QModelIndexList &indexes) const; QModelIndexList mapListToSource(const QModelIndexList& indexes) const;
QModelIndexList mapListFromSource(const QModelIndexList &indexes, bool deep = false) const; QModelIndexList mapListFromSource(const QModelIndexList& indexes, bool deep = false) const;
// Fix for matching indexes with respect to specifics of the message model. // 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; QModelIndexList match(const QModelIndex& start, int role, const QVariant& entered_value, int hits, Qt::MatchFlags flags) const;
// Performs sort of items. // Performs sort of items.
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
private: private:
QModelIndex getNextUnreadItemIndex(int default_row, int max_row) const; QModelIndex getNextUnreadItemIndex(int default_row, int max_row) const;
// Compares two rows of data. // Compares two rows of data.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const; bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
// Source model pointer. // Source model pointer.
MessagesModel *m_sourceModel; MessagesModel* m_sourceModel;
}; };
#endif // MESSAGESPROXYMODEL_H #endif // MESSAGESPROXYMODEL_H

View file

@ -1,258 +1,258 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef DEFINITIONS_H #ifndef DEFINITIONS_H
#define DEFINITIONS_H #define DEFINITIONS_H
#include <QtGlobal> #include <QtGlobal>
#define SERVICE_CODE_STD_RSS "std-rss" #define SERVICE_CODE_STD_RSS "std-rss"
#define SERVICE_CODE_TT_RSS "tt-rss" #define SERVICE_CODE_TT_RSS "tt-rss"
#define SERVICE_CODE_OWNCLOUD "owncloud" #define SERVICE_CODE_OWNCLOUD "owncloud"
#define ARGUMENTS_LIST_SEPARATOR "\n" #define ARGUMENTS_LIST_SEPARATOR "\n"
#define ADBLOCK_UPDATE_DAYS_INTERVAL 5 #define ADBLOCK_UPDATE_DAYS_INTERVAL 5
#define ADBLOCK_ICON_ACTIVE "adblock" #define ADBLOCK_ICON_ACTIVE "adblock"
#define ADBLOCK_ICON_DISABLED "adblock-disabled" #define ADBLOCK_ICON_DISABLED "adblock-disabled"
#define IS_IN_ARRAY(offset, array) ((offset >= 0) && (offset < array.count())) #define IS_IN_ARRAY(offset, array) ((offset >= 0) && (offset < array.count()))
#define ADBLOCK_CUSTOMLIST_NAME "customlist.txt" #define ADBLOCK_CUSTOMLIST_NAME "customlist.txt"
#define ADBLOCK_LISTS_SUBDIRECTORY "adblock" #define ADBLOCK_LISTS_SUBDIRECTORY "adblock"
#define ADBLOCK_EASYLIST_URL "https://easylist-downloads.adblockplus.org/easylist.txt" #define ADBLOCK_EASYLIST_URL "https://easylist-downloads.adblockplus.org/easylist.txt"
#define DEFAULT_SQL_MESSAGES_FILTER "0 > 1" #define DEFAULT_SQL_MESSAGES_FILTER "0 > 1"
#define MAX_MULTICOLUMN_SORT_STATES 3 #define MAX_MULTICOLUMN_SORT_STATES 3
#define ENCLOSURES_OUTER_SEPARATOR '#' #define ENCLOSURES_OUTER_SEPARATOR '#'
#define ECNLOSURES_INNER_SEPARATOR '&' #define ECNLOSURES_INNER_SEPARATOR '&'
#define URI_SCHEME_FEED_SHORT "feed:" #define URI_SCHEME_FEED_SHORT "feed:"
#define URI_SCHEME_FEED "feed://" #define URI_SCHEME_FEED "feed://"
#define URI_SCHEME_HTTP "http://" #define URI_SCHEME_HTTP "http://"
#define RELEASES_LIST "https://api.github.com/repos/martinrotter/rssguard/releases" #define RELEASES_LIST "https://api.github.com/repos/martinrotter/rssguard/releases"
#define DEFAULT_LOCALE "en" #define DEFAULT_LOCALE "en"
#define DEFAULT_FEED_ENCODING "UTF-8" #define DEFAULT_FEED_ENCODING "UTF-8"
#define DEFAULT_FEED_TYPE "RSS" #define DEFAULT_FEED_TYPE "RSS"
#define URL_REGEXP "^(http|https|feed|ftp):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&amp;:/~\\+#]*[\\w\\-\\@?^=%&amp;/~\\+#])?$" #define URL_REGEXP "^(http|https|feed|ftp):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&amp;:/~\\+#]*[\\w\\-\\@?^=%&amp;/~\\+#])?$"
#define USER_AGENT_HTTP_HEADER "User-Agent" #define USER_AGENT_HTTP_HEADER "User-Agent"
#define TEXT_TITLE_LIMIT 30 #define TEXT_TITLE_LIMIT 30
#define RESELECT_MESSAGE_THRESSHOLD 500 #define RESELECT_MESSAGE_THRESSHOLD 500
#define ICON_SIZE_SETTINGS 16 #define ICON_SIZE_SETTINGS 16
#define NO_PARENT_CATEGORY -1 #define NO_PARENT_CATEGORY -1
#define ID_RECYCLE_BIN -2 #define ID_RECYCLE_BIN -2
#define TRAY_ICON_BUBBLE_TIMEOUT 20000 #define TRAY_ICON_BUBBLE_TIMEOUT 20000
#define CLOSE_LOCK_TIMEOUT 500 #define CLOSE_LOCK_TIMEOUT 500
#define DOWNLOAD_TIMEOUT 5000 #define DOWNLOAD_TIMEOUT 5000
#define MESSAGES_VIEW_DEFAULT_COL 170 #define MESSAGES_VIEW_DEFAULT_COL 170
#define MESSAGES_VIEW_MINIMUM_COL 36 #define MESSAGES_VIEW_MINIMUM_COL 36
#define FEEDS_VIEW_COLUMN_COUNT 2 #define FEEDS_VIEW_COLUMN_COUNT 2
#define FEED_DOWNLOADER_MAX_THREADS 6 #define FEED_DOWNLOADER_MAX_THREADS 6
#define DEFAULT_DAYS_TO_DELETE_MSG 14 #define DEFAULT_DAYS_TO_DELETE_MSG 14
#define ELLIPSIS_LENGTH 3 #define ELLIPSIS_LENGTH 3
#define MIN_CATEGORY_NAME_LENGTH 1 #define MIN_CATEGORY_NAME_LENGTH 1
#define DEFAULT_AUTO_UPDATE_INTERVAL 15 #define DEFAULT_AUTO_UPDATE_INTERVAL 15
#define AUTO_UPDATE_INTERVAL 60000 #define AUTO_UPDATE_INTERVAL 60000
#define STARTUP_UPDATE_DELAY 30000 #define STARTUP_UPDATE_DELAY 30000
#define TIMEZONE_OFFSET_LIMIT 6 #define TIMEZONE_OFFSET_LIMIT 6
#define CHANGE_EVENT_DELAY 250 #define CHANGE_EVENT_DELAY 250
#define FLAG_ICON_SUBFOLDER "flags" #define FLAG_ICON_SUBFOLDER "flags"
#define SEACRH_MESSAGES_ACTION_NAME "search" #define SEACRH_MESSAGES_ACTION_NAME "search"
#define HIGHLIGHTER_ACTION_NAME "highlighter" #define HIGHLIGHTER_ACTION_NAME "highlighter"
#define SPACER_ACTION_NAME "spacer" #define SPACER_ACTION_NAME "spacer"
#define SEPARATOR_ACTION_NAME "separator" #define SEPARATOR_ACTION_NAME "separator"
#define FILTER_WIDTH 150 #define FILTER_WIDTH 150
#define FILTER_RIGHT_MARGIN 5 #define FILTER_RIGHT_MARGIN 5
#define FEEDS_VIEW_INDENTATION 10 #define FEEDS_VIEW_INDENTATION 10
#define ACCEPT_HEADER_FOR_FEED_DOWNLOADER "application/atom+xml,application/xml;q=0.9,text/xml;q=0.8,*/*;q=0.7" #define ACCEPT_HEADER_FOR_FEED_DOWNLOADER "application/atom+xml,application/xml;q=0.9,text/xml;q=0.8,*/*;q=0.7"
#define MIME_TYPE_ITEM_POINTER "rssguard/itempointer" #define MIME_TYPE_ITEM_POINTER "rssguard/itempointer"
#define DOWNLOADER_ICON_SIZE 48 #define DOWNLOADER_ICON_SIZE 48
#define NOTIFICATION_ICON_SIZE 32 #define NOTIFICATION_ICON_SIZE 32
#define GOOGLE_SEARCH_URL "https://www.google.com/search?q=%1&ie=utf-8&oe=utf-8" #define GOOGLE_SEARCH_URL "https://www.google.com/search?q=%1&ie=utf-8&oe=utf-8"
#define GOOGLE_SUGGEST_URL "http://suggestqueries.google.com/complete/search?output=toolbar&hl=en&q=%1" #define GOOGLE_SUGGEST_URL "http://suggestqueries.google.com/complete/search?output=toolbar&hl=en&q=%1"
#define ENCRYPTION_FILE_NAME "key.private" #define ENCRYPTION_FILE_NAME "key.private"
#define RELOAD_MODEL_BORDER_NUM 10 #define RELOAD_MODEL_BORDER_NUM 10
#define MAX_ZOOM_FACTOR 5.0f #define MAX_ZOOM_FACTOR 5.0f
#define MIN_ZOOM_FACTOR 0.25f #define MIN_ZOOM_FACTOR 0.25f
#define DEFAULT_ZOOM_FACTOR 1.0f #define DEFAULT_ZOOM_FACTOR 1.0f
#define ZOOM_FACTOR_STEP 0.1f #define ZOOM_FACTOR_STEP 0.1f
#define INTERNAL_URL_MESSAGE "http://rssguard.message" #define INTERNAL_URL_MESSAGE "http://rssguard.message"
#define INTERNAL_URL_BLANK "http://rssguard.blank" #define INTERNAL_URL_BLANK "http://rssguard.blank"
#define INTERNAL_URL_MESSAGE_HOST "rssguard.message" #define INTERNAL_URL_MESSAGE_HOST "rssguard.message"
#define INTERNAL_URL_BLANK_HOST "rssguard.blank" #define INTERNAL_URL_BLANK_HOST "rssguard.blank"
#define FEED_INITIAL_OPML_PATTERN "feeds-%1.opml" #define FEED_INITIAL_OPML_PATTERN "feeds-%1.opml"
#define FEED_REGEX_MATCHER "<link[^>]+type=\\\"application/(atom|rss)\\+xml\\\"[^>]*>" #define FEED_REGEX_MATCHER "<link[^>]+type=\\\"application/(atom|rss)\\+xml\\\"[^>]*>"
#define FEED_HREF_REGEX_MATCHER "href\\=\\\"[^\\\"]+\\\"" #define FEED_HREF_REGEX_MATCHER "href\\=\\\"[^\\\"]+\\\""
#define PLACEHOLDER_UNREAD_COUNTS "%unread" #define PLACEHOLDER_UNREAD_COUNTS "%unread"
#define PLACEHOLDER_ALL_COUNTS "%all" #define PLACEHOLDER_ALL_COUNTS "%all"
#define BACKUP_NAME_SETTINGS "config" #define BACKUP_NAME_SETTINGS "config"
#define BACKUP_SUFFIX_SETTINGS ".ini.backup" #define BACKUP_SUFFIX_SETTINGS ".ini.backup"
#define BACKUP_NAME_DATABASE "database" #define BACKUP_NAME_DATABASE "database"
#define BACKUP_SUFFIX_DATABASE ".db.backup" #define BACKUP_SUFFIX_DATABASE ".db.backup"
#define APP_DB_MYSQL_DRIVER "QMYSQL" #define APP_DB_MYSQL_DRIVER "QMYSQL"
#define APP_DB_MYSQL_INIT "db_init_mysql.sql" #define APP_DB_MYSQL_INIT "db_init_mysql.sql"
#define APP_DB_MYSQL_TEST "MySQLTest" #define APP_DB_MYSQL_TEST "MySQLTest"
#define APP_DB_MYSQL_PORT 3306 #define APP_DB_MYSQL_PORT 3306
#define APP_DB_SQLITE_DRIVER "QSQLITE" #define APP_DB_SQLITE_DRIVER "QSQLITE"
#define APP_DB_SQLITE_INIT "db_init_sqlite.sql" #define APP_DB_SQLITE_INIT "db_init_sqlite.sql"
#define APP_DB_SQLITE_PATH "database/local" #define APP_DB_SQLITE_PATH "database/local"
#define APP_DB_SQLITE_FILE "database.db" #define APP_DB_SQLITE_FILE "database.db"
// Keep this in sync with schema versions declared in SQL initialization code. // Keep this in sync with schema versions declared in SQL initialization code.
#define APP_DB_SCHEMA_VERSION "8" #define APP_DB_SCHEMA_VERSION "8"
#define APP_DB_UPDATE_FILE_PATTERN "db_update_%1_%2_%3.sql" #define APP_DB_UPDATE_FILE_PATTERN "db_update_%1_%2_%3.sql"
#define APP_DB_COMMENT_SPLIT "-- !\n" #define APP_DB_COMMENT_SPLIT "-- !\n"
#define APP_DB_NAME_PLACEHOLDER "##" #define APP_DB_NAME_PLACEHOLDER "##"
#define APP_CFG_PATH "config" #define APP_CFG_PATH "config"
#define APP_CFG_FILE "config.ini" #define APP_CFG_FILE "config.ini"
#define APP_QUIT_INSTANCE "-q" #define APP_QUIT_INSTANCE "-q"
#define APP_IS_RUNNING "app_is_running" #define APP_IS_RUNNING "app_is_running"
#define APP_SKIN_USER_FOLDER "skins" #define APP_SKIN_USER_FOLDER "skins"
#define APP_SKIN_DEFAULT "vergilius" #define APP_SKIN_DEFAULT "vergilius"
#define APP_SKIN_METADATA_FILE "metadata.xml" #define APP_SKIN_METADATA_FILE "metadata.xml"
#define APP_STYLE_DEFAULT "Fusion" #define APP_STYLE_DEFAULT "Fusion"
#define APP_THEME_DEFAULT "Faenza" #define APP_THEME_DEFAULT "Faenza"
#define APP_NO_THEME "" #define APP_NO_THEME ""
#define APP_THEME_SUFFIX ".png" #define APP_THEME_SUFFIX ".png"
#ifndef QSL #ifndef QSL
// Thin macro wrapper for literal strings. // Thin macro wrapper for literal strings.
// They are much more memory efficient and faster. // They are much more memory efficient and faster.
// Use it for all literals except for two cases: // Use it for all literals except for two cases:
// a) Methods which take QLatin1String (use QLatin1String for literal argument too), // a) Methods which take QLatin1String (use QLatin1String for literal argument too),
// b) Construction of empty literals "", use QString() instead of QStringLiteral(""). // b) Construction of empty literals "", use QString() instead of QStringLiteral("").
#define QSL(x) QStringLiteral(x) #define QSL(x) QStringLiteral(x)
#endif #endif
#ifndef QL1S #ifndef QL1S
// Macro for latin strings. Latin strings are // Macro for latin strings. Latin strings are
// faster than QStrings created from literals. // faster than QStrings created from literals.
#define QL1S(x) QLatin1String(x) #define QL1S(x) QLatin1String(x)
#endif #endif
#ifndef QL1C #ifndef QL1C
// Macro for latin chars. // Macro for latin chars.
#define QL1C(x) QLatin1Char(x) #define QL1C(x) QLatin1Char(x)
#endif #endif
// Indexes of columns as they are DEFINED IN THE TABLE for MESSAGES. // Indexes of columns as they are DEFINED IN THE TABLE for MESSAGES.
#define MSG_DB_ID_INDEX 0 #define MSG_DB_ID_INDEX 0
#define MSG_DB_READ_INDEX 1 #define MSG_DB_READ_INDEX 1
#define MSG_DB_DELETED_INDEX 2 #define MSG_DB_DELETED_INDEX 2
#define MSG_DB_IMPORTANT_INDEX 3 #define MSG_DB_IMPORTANT_INDEX 3
#define MSG_DB_FEED_TITLE_INDEX 4 #define MSG_DB_FEED_TITLE_INDEX 4
#define MSG_DB_TITLE_INDEX 5 #define MSG_DB_TITLE_INDEX 5
#define MSG_DB_URL_INDEX 6 #define MSG_DB_URL_INDEX 6
#define MSG_DB_AUTHOR_INDEX 7 #define MSG_DB_AUTHOR_INDEX 7
#define MSG_DB_DCREATED_INDEX 8 #define MSG_DB_DCREATED_INDEX 8
#define MSG_DB_CONTENTS_INDEX 9 #define MSG_DB_CONTENTS_INDEX 9
#define MSG_DB_PDELETED_INDEX 10 #define MSG_DB_PDELETED_INDEX 10
#define MSG_DB_ENCLOSURES_INDEX 11 #define MSG_DB_ENCLOSURES_INDEX 11
#define MSG_DB_ACCOUNT_ID_INDEX 12 #define MSG_DB_ACCOUNT_ID_INDEX 12
#define MSG_DB_CUSTOM_ID_INDEX 13 #define MSG_DB_CUSTOM_ID_INDEX 13
#define MSG_DB_CUSTOM_HASH_INDEX 14 #define MSG_DB_CUSTOM_HASH_INDEX 14
#define MSG_DB_FEED_CUSTOM_ID_INDEX 15 #define MSG_DB_FEED_CUSTOM_ID_INDEX 15
// Indexes of columns as they are DEFINED IN THE TABLE for CATEGORIES. // Indexes of columns as they are DEFINED IN THE TABLE for CATEGORIES.
#define CAT_DB_ID_INDEX 0 #define CAT_DB_ID_INDEX 0
#define CAT_DB_PARENT_ID_INDEX 1 #define CAT_DB_PARENT_ID_INDEX 1
#define CAT_DB_TITLE_INDEX 2 #define CAT_DB_TITLE_INDEX 2
#define CAT_DB_DESCRIPTION_INDEX 3 #define CAT_DB_DESCRIPTION_INDEX 3
#define CAT_DB_DCREATED_INDEX 4 #define CAT_DB_DCREATED_INDEX 4
#define CAT_DB_ICON_INDEX 5 #define CAT_DB_ICON_INDEX 5
#define CAT_DB_ACCOUNT_ID_INDEX 6 #define CAT_DB_ACCOUNT_ID_INDEX 6
#define CAT_DB_CUSTOM_ID_INDEX 7 #define CAT_DB_CUSTOM_ID_INDEX 7
// Indexes of columns as they are DEFINED IN THE TABLE for FEEDS. // Indexes of columns as they are DEFINED IN THE TABLE for FEEDS.
#define FDS_DB_ID_INDEX 0 #define FDS_DB_ID_INDEX 0
#define FDS_DB_TITLE_INDEX 1 #define FDS_DB_TITLE_INDEX 1
#define FDS_DB_DESCRIPTION_INDEX 2 #define FDS_DB_DESCRIPTION_INDEX 2
#define FDS_DB_DCREATED_INDEX 3 #define FDS_DB_DCREATED_INDEX 3
#define FDS_DB_ICON_INDEX 4 #define FDS_DB_ICON_INDEX 4
#define FDS_DB_CATEGORY_INDEX 5 #define FDS_DB_CATEGORY_INDEX 5
#define FDS_DB_ENCODING_INDEX 6 #define FDS_DB_ENCODING_INDEX 6
#define FDS_DB_URL_INDEX 7 #define FDS_DB_URL_INDEX 7
#define FDS_DB_PROTECTED_INDEX 8 #define FDS_DB_PROTECTED_INDEX 8
#define FDS_DB_USERNAME_INDEX 9 #define FDS_DB_USERNAME_INDEX 9
#define FDS_DB_PASSWORD_INDEX 10 #define FDS_DB_PASSWORD_INDEX 10
#define FDS_DB_UPDATE_TYPE_INDEX 11 #define FDS_DB_UPDATE_TYPE_INDEX 11
#define FDS_DB_UPDATE_INTERVAL_INDEX 12 #define FDS_DB_UPDATE_INTERVAL_INDEX 12
#define FDS_DB_TYPE_INDEX 13 #define FDS_DB_TYPE_INDEX 13
#define FDS_DB_ACCOUNT_ID_INDEX 14 #define FDS_DB_ACCOUNT_ID_INDEX 14
#define FDS_DB_CUSTOM_ID_INDEX 15 #define FDS_DB_CUSTOM_ID_INDEX 15
// Indexes of columns for feed models. // Indexes of columns for feed models.
#define FDS_MODEL_TITLE_INDEX 0 #define FDS_MODEL_TITLE_INDEX 0
#define FDS_MODEL_COUNTS_INDEX 1 #define FDS_MODEL_COUNTS_INDEX 1
#if defined(Q_OS_LINUX) #if defined(Q_OS_LINUX)
#define OS_ID "Linux" #define OS_ID "Linux"
#elif defined(Q_OS_OSX) #elif defined(Q_OS_OSX)
#define OS_ID "Mac OS X" #define OS_ID "Mac OS X"
#elif defined(Q_OS_WIN) #elif defined(Q_OS_WIN)
#define OS_ID "Windows" #define OS_ID "Windows"
#else #else
#define OS_ID "" #define OS_ID ""
#endif #endif
#if defined(Q_OS_LINUX) #if defined(Q_OS_LINUX)
#define APP_DESKTOP_SOURCE_ENTRY_FILE "rssguard.desktop.autostart" #define APP_DESKTOP_SOURCE_ENTRY_FILE "rssguard.desktop.autostart"
#define APP_DESKTOP_ENTRY_FILE "rssguard.desktop" #define APP_DESKTOP_ENTRY_FILE "rssguard.desktop"
#define APP_DESKTOP_ENTRY_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/autostart") #define APP_DESKTOP_ENTRY_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/autostart")
#define APP_LANG_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/translations") #define APP_LANG_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/translations")
#define APP_SKIN_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/skins") #define APP_SKIN_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/skins")
#define APP_INFO_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/information") #define APP_INFO_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/information")
#define APP_THEME_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/icons") #define APP_THEME_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/icons")
#define APP_SQL_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/sql") #define APP_SQL_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/sql")
#define APP_ICON_PATH QApplication::applicationDirPath() + QString("/../share/pixmaps/rssguard.png") #define APP_ICON_PATH QApplication::applicationDirPath() + QString("/../share/pixmaps/rssguard.png")
#define APP_ICON_PLAIN_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/icons/rssguard_plain.png") #define APP_ICON_PLAIN_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/icons/rssguard_plain.png")
#define APP_INITIAL_FEEDS_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/initial_feeds") #define APP_INITIAL_FEEDS_PATH QApplication::applicationDirPath() + QString("/../share/rssguard/initial_feeds")
#elif defined(Q_OS_OSX) #elif defined(Q_OS_OSX)
#define APP_LANG_PATH QApplication::applicationDirPath() + QString("/../Resources/translations") #define APP_LANG_PATH QApplication::applicationDirPath() + QString("/../Resources/translations")
#define APP_SKIN_PATH QApplication::applicationDirPath() + QString("/../Resources/skins") #define APP_SKIN_PATH QApplication::applicationDirPath() + QString("/../Resources/skins")
#define APP_INFO_PATH QApplication::applicationDirPath() + QString("/../Resources/information") #define APP_INFO_PATH QApplication::applicationDirPath() + QString("/../Resources/information")
#define APP_THEME_PATH QApplication::applicationDirPath() + QString("/../Resources/icons") #define APP_THEME_PATH QApplication::applicationDirPath() + QString("/../Resources/icons")
#define APP_SQL_PATH QApplication::applicationDirPath() + QString("/../Resources/sql") #define APP_SQL_PATH QApplication::applicationDirPath() + QString("/../Resources/sql")
#define APP_ICON_PATH QApplication::applicationDirPath() + QString("/../Resources/icons/rssguard.png") #define APP_ICON_PATH QApplication::applicationDirPath() + QString("/../Resources/icons/rssguard.png")
#define APP_INFO_PATH QApplication::applicationDirPath() + QString("/../Resources/information") #define APP_INFO_PATH QApplication::applicationDirPath() + QString("/../Resources/information")
#define APP_ICON_PLAIN_PATH QApplication::applicationDirPath() + QString("/../Resources/icons/rssguard_plain.png") #define APP_ICON_PLAIN_PATH QApplication::applicationDirPath() + QString("/../Resources/icons/rssguard_plain.png")
#define APP_INITIAL_FEEDS_PATH QApplication::applicationDirPath() + QString("/../Resources/initial_feeds") #define APP_INITIAL_FEEDS_PATH QApplication::applicationDirPath() + QString("/../Resources/initial_feeds")
#elif defined(Q_OS_WIN) #elif defined(Q_OS_WIN)
#define APP_LANG_PATH QApplication::applicationDirPath() + QString("/translations") #define APP_LANG_PATH QApplication::applicationDirPath() + QString("/translations")
#define APP_SKIN_PATH QApplication::applicationDirPath() + QString("/skins") #define APP_SKIN_PATH QApplication::applicationDirPath() + QString("/skins")
#define APP_INFO_PATH QApplication::applicationDirPath() #define APP_INFO_PATH QApplication::applicationDirPath()
#define APP_THEME_PATH QApplication::applicationDirPath() + QString("/icons") #define APP_THEME_PATH QApplication::applicationDirPath() + QString("/icons")
#define APP_SQL_PATH QApplication::applicationDirPath() + QString("/sql") #define APP_SQL_PATH QApplication::applicationDirPath() + QString("/sql")
#define APP_ICON_PATH QApplication::applicationDirPath() + QString("/rssguard.png") #define APP_ICON_PATH QApplication::applicationDirPath() + QString("/rssguard.png")
#define APP_ICON_PLAIN_PATH QApplication::applicationDirPath() + QString("/rssguard_plain.png") #define APP_ICON_PLAIN_PATH QApplication::applicationDirPath() + QString("/rssguard_plain.png")
#define APP_INITIAL_FEEDS_PATH QApplication::applicationDirPath() + QString("/initial_feeds") #define APP_INITIAL_FEEDS_PATH QApplication::applicationDirPath() + QString("/initial_feeds")
#endif #endif
#endif // DEFINITIONS_H #endif // DEFINITIONS_H

View file

@ -27,21 +27,21 @@
DynamicShortcuts::DynamicShortcuts() { DynamicShortcuts::DynamicShortcuts() {
} }
void DynamicShortcuts::save(const QList<QAction*> &actions) { void DynamicShortcuts::save(const QList<QAction*>& actions) {
Settings *settings = qApp->settings(); Settings* settings = qApp->settings();
foreach (const QAction *action, actions) { foreach (const QAction* action, actions) {
settings->setValue(GROUP(Keyboard), action->objectName(), action->shortcut().toString(QKeySequence::PortableText)); settings->setValue(GROUP(Keyboard), action->objectName(), action->shortcut().toString(QKeySequence::PortableText));
} }
} }
void DynamicShortcuts::load(const QList<QAction *> &actions) { void DynamicShortcuts::load(const QList<QAction*>& actions) {
Settings *settings = qApp->settings(); Settings* settings = qApp->settings();
foreach (QAction *action, actions) { foreach (QAction* action, actions) {
QString shortcut_for_action = settings->value(GROUP(Keyboard), QString shortcut_for_action = settings->value(GROUP(Keyboard),
action->objectName(), action->objectName(),
action->shortcut().toString(QKeySequence::PortableText)).toString(); action->shortcut().toString(QKeySequence::PortableText)).toString();
action->setShortcut(QKeySequence::fromString(shortcut_for_action, QKeySequence::PortableText)); action->setShortcut(QKeySequence::fromString(shortcut_for_action, QKeySequence::PortableText));
} }
} }

View file

@ -24,18 +24,18 @@
class QAction; class QAction;
class DynamicShortcuts { class DynamicShortcuts {
public: public:
// Checks the application settings and then initializes shortcut of // Checks the application settings and then initializes shortcut of
// each action from actions from the settings. // each action from actions from the settings.
static void load(const QList<QAction*> &actions); static void load(const QList<QAction*>& actions);
// Stores shortcut of each action from actions into the application // Stores shortcut of each action from actions into the application
// settings. // settings.
static void save(const QList<QAction*> &actions); static void save(const QList<QAction*>& actions);
private: private:
// Constructor. // Constructor.
explicit DynamicShortcuts(); explicit DynamicShortcuts();
}; };
#endif // DYNAMICSHORTCUTS_H #endif // DYNAMICSHORTCUTS_H

View file

@ -26,93 +26,85 @@
#include <QLabel> #include <QLabel>
DynamicShortcutsWidget::DynamicShortcutsWidget(QWidget *parent) : QWidget(parent) { DynamicShortcutsWidget::DynamicShortcutsWidget(QWidget* parent) : QWidget(parent) {
// Create layout for this control and set is as active. // Create layout for this control and set is as active.
m_layout = new QGridLayout(this); m_layout = new QGridLayout(this);
m_layout->setMargin(0); m_layout->setMargin(0);
setLayout(m_layout);
setLayout(m_layout);
} }
DynamicShortcutsWidget::~DynamicShortcutsWidget() { DynamicShortcutsWidget::~DynamicShortcutsWidget() {
delete m_layout; delete m_layout;
} }
bool DynamicShortcutsWidget::areShortcutsUnique() const { bool DynamicShortcutsWidget::areShortcutsUnique() const {
QList<QKeySequence> all_shortcuts; QList<QKeySequence> all_shortcuts;
// Obtain all shortcuts. // Obtain all shortcuts.
foreach (const ActionBinding &binding, m_actionBindings) { foreach (const ActionBinding& binding, m_actionBindings) {
const QKeySequence new_shortcut = binding.second->shortcut(); const QKeySequence new_shortcut = binding.second->shortcut();
if (!new_shortcut.isEmpty() && all_shortcuts.contains(new_shortcut)) { if (!new_shortcut.isEmpty() && all_shortcuts.contains(new_shortcut)) {
// Problem, two identical non-empty shortcuts found. // Problem, two identical non-empty shortcuts found.
return false; return false;
} }
else {
all_shortcuts.append(binding.second->shortcut());
}
}
return true; else {
all_shortcuts.append(binding.second->shortcut());
}
}
return true;
} }
void DynamicShortcutsWidget::updateShortcuts() { void DynamicShortcutsWidget::updateShortcuts() {
foreach (const ActionBinding &binding, m_actionBindings) { foreach (const ActionBinding& binding, m_actionBindings) {
binding.first->setShortcut(binding.second->shortcut()); binding.first->setShortcut(binding.second->shortcut());
} }
} }
void DynamicShortcutsWidget::populate(QList<QAction*> actions) { void DynamicShortcutsWidget::populate(QList<QAction*> actions) {
m_actionBindings.clear(); m_actionBindings.clear();
qSort(actions.begin(), actions.end(), DynamicShortcutsWidget::lessThan); qSort(actions.begin(), actions.end(), DynamicShortcutsWidget::lessThan);
int row_id = 0;
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. foreach (QAction* action, actions) {
// I will assign each QAaction a property called "category" with some enum value. // Create shortcut catcher for this action and set default shortcut.
// Like: ShortcutCatcher* catcher = new ShortcutCatcher(this);
// File, FeedsCategories, Messages, Tools, WebBrowser, Help catcher->setDefaultShortcut(action->shortcut());
// This will be setup in FormMain::allActions(). // Store information for re-initialization of shortcuts
// Then here I will process actions into categories. // of actions when widget gets "confirmed".
QPair<QAction*, ShortcutCatcher*> 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) { // Make sure that "spacer" is added.
// Create shortcut catcher for this action and set default shortcut. m_layout->setRowStretch(row_id, 1);
ShortcutCatcher *catcher = new ShortcutCatcher(this); m_layout->setColumnStretch(1, 1);
catcher->setDefaultShortcut(action->shortcut());
// Store information for re-initialization of shortcuts
// of actions when widget gets "confirmed".
QPair<QAction*,ShortcutCatcher*> 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) { 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;
} }

View file

@ -27,38 +27,38 @@ class ShortcutCatcher;
typedef QPair<QAction*, ShortcutCatcher*> ActionBinding; typedef QPair<QAction*, ShortcutCatcher*> ActionBinding;
class DynamicShortcutsWidget : public QWidget { class DynamicShortcutsWidget : public QWidget {
Q_OBJECT Q_OBJECT
public:
// Constructors and destructors.
explicit DynamicShortcutsWidget(QWidget *parent = 0);
virtual ~DynamicShortcutsWidget();
// Updates shortcuts of all actions according to changes. public:
// NOTE: No access to settings is done here. // Constructors and destructors.
// Shortcuts are fetched from settings when applications starts explicit DynamicShortcutsWidget(QWidget* parent = 0);
// and stored back to settings when application quits. virtual ~DynamicShortcutsWidget();
void updateShortcuts();
// Returns true if all shortcuts are unique, // Updates shortcuts of all actions according to changes.
// otherwise false. // NOTE: No access to settings is done here.
bool areShortcutsUnique() const; // 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. // Returns true if all shortcuts are unique,
// NOTE: This gets initial shortcut for each action from its properties, NOT from // otherwise false.
// the application settings, so shortcuts from settings need to be bool areShortcutsUnique() const;
// assigned to actions before calling this method.
void populate(QList<QAction*> actions);
signals: // Populates this widget with shortcut widgets for given actions.
void setupChanged(); // 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<QAction*> actions);
private: signals:
static bool lessThan(QAction *lhs, QAction *rhs); void setupChanged();
private: private:
QGridLayout *m_layout; static bool lessThan(QAction* lhs, QAction* rhs);
QList<ActionBinding> m_actionBindings;
private:
QGridLayout* m_layout;
QList<ActionBinding> m_actionBindings;
}; };
#endif // DYNAMICSHORTCUTSOVERVIEW_H #endif // DYNAMICSHORTCUTSOVERVIEW_H

View file

@ -50,93 +50,94 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QKeyEvent> #include <QKeyEvent>
ShortcutButton::ShortcutButton(ShortcutCatcher *catcher, QWidget *parent) ShortcutButton::ShortcutButton(ShortcutCatcher* catcher, QWidget* parent)
: QPushButton(parent), m_catcher(catcher) { : QPushButton(parent), m_catcher(catcher) {
setMinimumWidth(100); setMinimumWidth(100);
} }
ShortcutButton::~ShortcutButton() { ShortcutButton::~ShortcutButton() {
} }
void ShortcutButton::keyPressEvent(QKeyEvent *event) { void ShortcutButton::keyPressEvent(QKeyEvent* event) {
int pressed_key = event->key(); int pressed_key = event->key();
if (pressed_key == -1) { if (pressed_key == -1) {
m_catcher->doneRecording(); 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)) { if (!m_catcher->m_isRecording && (pressed_key == Qt::Key_Return || pressed_key == Qt::Key_Space)) {
return; return;
} }
if (!m_catcher->m_isRecording) { if (!m_catcher->m_isRecording) {
QPushButton::keyPressEvent(event); QPushButton::keyPressEvent(event);
return; return;
} }
event->accept(); event->accept();
m_catcher->m_modifierKeys = new_modifiers; m_catcher->m_modifierKeys = new_modifiers;
switch(pressed_key) { switch (pressed_key) {
case Qt::Key_AltGr: case Qt::Key_AltGr:
return; return;
case Qt::Key_Shift: case Qt::Key_Shift:
case Qt::Key_Control: case Qt::Key_Control:
case Qt::Key_Alt: case Qt::Key_Alt:
case Qt::Key_Meta: case Qt::Key_Meta:
case Qt::Key_Menu: case Qt::Key_Menu:
m_catcher->controlModifierlessTimout(); m_catcher->controlModifierlessTimout();
m_catcher->updateDisplayShortcut(); m_catcher->updateDisplayShortcut();
break; 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;
}
if (m_catcher->m_numKey == 0) { // We now have a valid key press.
m_catcher->m_currentSequence = QKeySequence(pressed_key); if (pressed_key) {
} if ((pressed_key == Qt::Key_Backtab) && (m_catcher->m_modifierKeys & Qt::SHIFT)) {
pressed_key = Qt::Key_Tab | m_catcher->m_modifierKeys;
}
m_catcher->m_numKey++; else {
pressed_key |= m_catcher->m_modifierKeys;
}
if (m_catcher->m_numKey >= 4) { if (m_catcher->m_numKey == 0) {
m_catcher->doneRecording(); m_catcher->m_currentSequence = QKeySequence(pressed_key);
return; }
}
m_catcher->controlModifierlessTimout(); m_catcher->m_numKey++;
m_catcher->updateDisplayShortcut();
} if (m_catcher->m_numKey >= 4) {
} m_catcher->doneRecording();
return;
}
m_catcher->controlModifierlessTimout();
m_catcher->updateDisplayShortcut();
}
}
} }
void ShortcutButton::keyReleaseEvent(QKeyEvent *event) { void ShortcutButton::keyReleaseEvent(QKeyEvent* event) {
if (event->key() == -1){ if (event->key() == -1) {
return; return;
} }
if (!m_catcher->m_isRecording) { if (!m_catcher->m_isRecording) {
QPushButton::keyReleaseEvent(event); QPushButton::keyReleaseEvent(event);
return; return;
} }
event->accept(); event->accept();
const Qt::KeyboardModifiers new_modifiers = event->modifiers() &
(Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META);
const Qt::KeyboardModifiers new_modifiers = event->modifiers() & if (((uint) new_modifiers & m_catcher->m_modifierKeys) < m_catcher->m_modifierKeys) {
(Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META); m_catcher->m_modifierKeys = new_modifiers;
m_catcher->controlModifierlessTimout();
if (((uint) new_modifiers & m_catcher->m_modifierKeys) < m_catcher->m_modifierKeys) { m_catcher->updateDisplayShortcut();
m_catcher->m_modifierKeys = new_modifiers; }
m_catcher->controlModifierlessTimout();
m_catcher->updateDisplayShortcut();
}
} }

View file

@ -52,19 +52,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class ShortcutCatcher; class ShortcutCatcher;
class ShortcutButton : public QPushButton { class ShortcutButton : public QPushButton {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit ShortcutButton(ShortcutCatcher *catcher, QWidget *parent = 0); explicit ShortcutButton(ShortcutCatcher* catcher, QWidget* parent = 0);
virtual ~ShortcutButton(); virtual ~ShortcutButton();
protected: protected:
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent* event);
void keyReleaseEvent(QKeyEvent *event); void keyReleaseEvent(QKeyEvent* event);
private: private:
ShortcutCatcher *m_catcher; ShortcutCatcher* m_catcher;
}; };
#endif // SHORTCUTBUTTON_H #endif // SHORTCUTBUTTON_H

View file

@ -52,123 +52,118 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QHBoxLayout> #include <QHBoxLayout>
ShortcutCatcher::ShortcutCatcher(QWidget *parent) ShortcutCatcher::ShortcutCatcher(QWidget* parent)
: QWidget(parent) { : QWidget(parent) {
// Setup layout of the control // Setup layout of the control
m_layout = new QHBoxLayout(this); m_layout = new QHBoxLayout(this);
m_layout->setMargin(0); m_layout->setMargin(0);
m_layout->setSpacing(1); m_layout->setSpacing(1);
// Create reset button.
// Create reset button. m_btnReset = new PlainToolButton(this);
m_btnReset = new PlainToolButton(this); m_btnReset->setIcon(qApp->icons()->fromTheme(QSL("document-revert")));
m_btnReset->setIcon(qApp->icons()->fromTheme(QSL("document-revert"))); m_btnReset->setFocusPolicy(Qt::NoFocus);
m_btnReset->setFocusPolicy(Qt::NoFocus); m_btnReset->setToolTip(tr("Reset to original shortcut."));
m_btnReset->setToolTip(tr("Reset to original shortcut.")); // Create clear button.
m_btnClear = new PlainToolButton(this);
// Create clear button. m_btnClear->setIcon(qApp->icons()->fromTheme(QSL("list-remove")));
m_btnClear = new PlainToolButton(this); m_btnClear->setFocusPolicy(Qt::NoFocus);
m_btnClear->setIcon(qApp->icons()->fromTheme(QSL("list-remove"))); m_btnClear->setToolTip(tr("Clear current shortcut."));
m_btnClear->setFocusPolicy(Qt::NoFocus); // Clear main shortcut catching button.
m_btnClear->setToolTip(tr("Clear current shortcut.")); m_btnChange = new ShortcutButton(this);
m_btnChange->setFocusPolicy(Qt::StrongFocus);
// Clear main shortcut catching button. m_btnChange->setToolTip(tr("Click and hit new shortcut."));
m_btnChange = new ShortcutButton(this); // Add both buttons to the layout.
m_btnChange->setFocusPolicy(Qt::StrongFocus); m_layout->addWidget(m_btnChange);
m_btnChange->setToolTip(tr("Click and hit new shortcut.")); m_layout->addWidget(m_btnReset);
m_layout->addWidget(m_btnClear);
// Add both buttons to the layout. // Establish needed connections.
m_layout->addWidget(m_btnChange); connect(m_btnReset, &QToolButton::clicked, this, &ShortcutCatcher::resetShortcut);
m_layout->addWidget(m_btnReset); connect(m_btnClear, &QToolButton::clicked, this, &ShortcutCatcher::clearShortcut);
m_layout->addWidget(m_btnClear); connect(m_btnChange, &QToolButton::clicked, this, &ShortcutCatcher::startRecording);
// Prepare initial state of the control.
// Establish needed connections. updateDisplayShortcut();
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() { ShortcutCatcher::~ShortcutCatcher() {
delete m_btnReset; delete m_btnReset;
delete m_btnChange; delete m_btnChange;
delete m_btnClear; delete m_btnClear;
delete m_layout; delete m_layout;
} }
void ShortcutCatcher::startRecording() { void ShortcutCatcher::startRecording() {
m_numKey = 0; m_numKey = 0;
m_modifierKeys = 0; m_modifierKeys = 0;
m_currentSequence = QKeySequence(); m_currentSequence = QKeySequence();
m_isRecording = true; m_isRecording = true;
m_btnChange->setDown(true); m_btnChange->setDown(true);
m_btnChange->grabKeyboard(); m_btnChange->grabKeyboard();
updateDisplayShortcut();
updateDisplayShortcut();
} }
void ShortcutCatcher::doneRecording() { void ShortcutCatcher::doneRecording() {
m_isRecording = false; m_isRecording = false;
m_btnChange->releaseKeyboard(); m_btnChange->releaseKeyboard();
m_btnChange->setDown(false); m_btnChange->setDown(false);
updateDisplayShortcut();
updateDisplayShortcut(); emit shortcutChanged(m_currentSequence);
emit shortcutChanged(m_currentSequence);
} }
void ShortcutCatcher::controlModifierlessTimout() { void ShortcutCatcher::controlModifierlessTimout() {
if (m_numKey && !m_modifierKeys) { if (m_numKey && !m_modifierKeys) {
doneRecording(); doneRecording();
} }
} }
void ShortcutCatcher::updateDisplayShortcut() { void ShortcutCatcher::updateDisplayShortcut() {
QString str = m_currentSequence.toString(QKeySequence::NativeText); QString str = m_currentSequence.toString(QKeySequence::NativeText);
str.replace(QL1S("&"), QL1S("&&")); str.replace(QL1S("&"), QL1S("&&"));
if (m_isRecording) { if (m_isRecording) {
if (m_modifierKeys) { if (m_modifierKeys) {
if (!str.isEmpty()) { if (!str.isEmpty()) {
str.append(QSL(",")); str.append(QSL(","));
} }
if (m_modifierKeys & Qt::META) {
str += QL1S("Meta + ");
}
if (m_modifierKeys & Qt::CTRL) {
str += QL1S("Ctrl + ");
}
if (m_modifierKeys & Qt::ALT) {
str += QL1S("Alt + ");
}
if (m_modifierKeys & Qt::SHIFT) {
str += QL1S("Shift + ");
}
}
}
m_btnChange->setText(str); if (m_modifierKeys & Qt::META) {
str += QL1S("Meta + ");
}
if (m_modifierKeys & Qt::CTRL) {
str += QL1S("Ctrl + ");
}
if (m_modifierKeys & Qt::ALT) {
str += QL1S("Alt + ");
}
if (m_modifierKeys & Qt::SHIFT) {
str += QL1S("Shift + ");
}
}
}
m_btnChange->setText(str);
} }
QKeySequence ShortcutCatcher::shortcut() const { QKeySequence ShortcutCatcher::shortcut() const {
return m_currentSequence; return m_currentSequence;
} }
void ShortcutCatcher::setDefaultShortcut(const QKeySequence &key) { void ShortcutCatcher::setDefaultShortcut(const QKeySequence& key) {
m_defaultSequence = key; m_defaultSequence = key;
setShortcut(key); setShortcut(key);
} }
void ShortcutCatcher::setShortcut(const QKeySequence &key) { void ShortcutCatcher::setShortcut(const QKeySequence& key) {
m_currentSequence = key; m_currentSequence = key;
doneRecording(); doneRecording();
} }
void ShortcutCatcher::resetShortcut() { void ShortcutCatcher::resetShortcut() {
setShortcut(m_defaultSequence); setShortcut(m_defaultSequence);
} }
void ShortcutCatcher::clearShortcut() { void ShortcutCatcher::clearShortcut() {
setShortcut(QKeySequence()); setShortcut(QKeySequence());
} }

View file

@ -54,45 +54,45 @@ class QToolButton;
class ShortcutButton; class ShortcutButton;
class ShortcutCatcher : public QWidget { class ShortcutCatcher : public QWidget {
Q_OBJECT Q_OBJECT
friend class ShortcutButton; friend class ShortcutButton;
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit ShortcutCatcher(QWidget *parent = 0); explicit ShortcutCatcher(QWidget* parent = 0);
virtual ~ShortcutCatcher(); virtual ~ShortcutCatcher();
void controlModifierlessTimout(); void controlModifierlessTimout();
void updateDisplayShortcut(); void updateDisplayShortcut();
QKeySequence shortcut() const; QKeySequence shortcut() const;
void setDefaultShortcut(const QKeySequence &key); void setDefaultShortcut(const QKeySequence& key);
void setShortcut(const QKeySequence &key); void setShortcut(const QKeySequence& key);
public slots: public slots:
void resetShortcut(); void resetShortcut();
void clearShortcut(); void clearShortcut();
private slots: private slots:
void startRecording(); void startRecording();
void doneRecording(); void doneRecording();
signals: signals:
void shortcutChanged(const QKeySequence &seguence); void shortcutChanged(const QKeySequence& seguence);
private: private:
QToolButton *m_btnReset; QToolButton* m_btnReset;
QToolButton *m_btnClear; QToolButton* m_btnClear;
ShortcutButton *m_btnChange; ShortcutButton* m_btnChange;
QHBoxLayout *m_layout; QHBoxLayout* m_layout;
QKeySequence m_currentSequence; QKeySequence m_currentSequence;
QKeySequence m_defaultSequence; QKeySequence m_defaultSequence;
bool m_isRecording; bool m_isRecording;
int m_numKey; int m_numKey;
uint m_modifierKeys; uint m_modifierKeys;
}; };
#endif // KEYSEQUENCECATCHER_H #endif // KEYSEQUENCECATCHER_H

View file

@ -1,29 +1,29 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "exceptions/applicationexception.h" #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 { QString ApplicationException::message() const {
return m_message; return m_message;
} }

View file

@ -1,35 +1,35 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef APPLICATIONEXCEPTION_H #ifndef APPLICATIONEXCEPTION_H
#define APPLICATIONEXCEPTION_H #define APPLICATIONEXCEPTION_H
#include <QString> #include <QString>
class ApplicationException { class ApplicationException {
public: public:
explicit ApplicationException(const QString &message = QString()); explicit ApplicationException(const QString& message = QString());
virtual ~ApplicationException(); virtual ~ApplicationException();
QString message() const; QString message() const;
private: private:
QString m_message; QString m_message;
}; };
#endif // APPLICATIONEXCEPTION_H #endif // APPLICATIONEXCEPTION_H

View file

@ -1,25 +1,25 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "exceptions/ioexception.h" #include "exceptions/ioexception.h"
IOException::IOException(const QString &message) : ApplicationException(message) { IOException::IOException(const QString& message) : ApplicationException(message) {
} }
IOException::~IOException() { IOException::~IOException() {
} }

View file

@ -1,30 +1,30 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef IOEXCEPTION_H #ifndef IOEXCEPTION_H
#define IOEXCEPTION_H #define IOEXCEPTION_H
#include "exceptions/applicationexception.h" #include "exceptions/applicationexception.h"
class IOException : public ApplicationException { class IOException : public ApplicationException {
public: public:
explicit IOException(const QString &message = QString()); explicit IOException(const QString& message = QString());
virtual ~IOException(); virtual ~IOException();
}; };
#endif // IOEXCEPTION_H #endif // IOEXCEPTION_H

View file

@ -1,41 +1,41 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/baselineedit.h" #include "gui/baselineedit.h"
#include <QKeyEvent> #include <QKeyEvent>
BaseLineEdit::BaseLineEdit(QWidget *parent) : QLineEdit(parent) { BaseLineEdit::BaseLineEdit(QWidget* parent) : QLineEdit(parent) {
} }
BaseLineEdit::~BaseLineEdit() { BaseLineEdit::~BaseLineEdit() {
} }
void BaseLineEdit::submit(const QString &text) { void BaseLineEdit::submit(const QString& text) {
setText(text); setText(text);
emit submitted(text); emit submitted(text);
} }
void BaseLineEdit::keyPressEvent(QKeyEvent *event) { void BaseLineEdit::keyPressEvent(QKeyEvent* event) {
if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
emit submitted(text()); emit submitted(text());
event->accept(); event->accept();
} }
QLineEdit::keyPressEvent(event); QLineEdit::keyPressEvent(event);
} }

View file

@ -1,43 +1,43 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef BASELINEEDIT_H #ifndef BASELINEEDIT_H
#define BASELINEEDIT_H #define BASELINEEDIT_H
#include <QLineEdit> #include <QLineEdit>
class BaseLineEdit : public QLineEdit { class BaseLineEdit : public QLineEdit {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit BaseLineEdit(QWidget *parent = 0); explicit BaseLineEdit(QWidget* parent = 0);
virtual ~BaseLineEdit(); virtual ~BaseLineEdit();
public slots: public slots:
void submit(const QString &text); void submit(const QString& text);
protected: protected:
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent* event);
signals: signals:
// Emitted if user hits ENTER button. // Emitted if user hits ENTER button.
void submitted(const QString &text); void submitted(const QString& text);
}; };
#endif // BASELINEEDIT_H #endif // BASELINEEDIT_H

View file

@ -1,50 +1,50 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/basetoolbar.h" #include "gui/basetoolbar.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include "gui/dialogs/formmain.h" #include "gui/dialogs/formmain.h"
#include "miscellaneous/settings.h" #include "miscellaneous/settings.h"
#include <QWidgetAction> #include <QWidgetAction>
BaseToolBar::BaseToolBar(const QString &title, QWidget *parent) : QToolBar(title, parent) { BaseToolBar::BaseToolBar(const QString& title, QWidget* parent) : QToolBar(title, parent) {
// Update right margin of filter textbox. // Update right margin of filter textbox.
QMargins margins = contentsMargins(); QMargins margins = contentsMargins();
margins.setRight(margins.right() + FILTER_RIGHT_MARGIN); margins.setRight(margins.right() + FILTER_RIGHT_MARGIN);
setContentsMargins(margins); setContentsMargins(margins);
} }
BaseToolBar::~BaseToolBar() { BaseToolBar::~BaseToolBar() {
qDebug("Destroying BaseToolBar instance."); qDebug("Destroying BaseToolBar instance.");
} }
void BaseBar::loadSavedActions() { void BaseBar::loadSavedActions() {
loadSpecificActions(getSpecificActions(savedActions())); loadSpecificActions(getSpecificActions(savedActions()));
} }
QAction *BaseBar::findMatchingAction(const QString &action, const QList<QAction*> &actions) const { QAction* BaseBar::findMatchingAction(const QString& action, const QList<QAction*>& actions) const {
foreach (QAction *act, actions) { foreach (QAction* act, actions) {
if (act->objectName() == action) { if (act->objectName() == action) {
return act; return act;
} }
} }
return nullptr; return nullptr;
} }

View file

@ -1,60 +1,60 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef TOOLBAR_H #ifndef TOOLBAR_H
#define TOOLBAR_H #define TOOLBAR_H
#include <QToolBar> #include <QToolBar>
class BaseBar { class BaseBar {
public: public:
// Returns all actions which can be added to the toolbar. // Returns all actions which can be added to the toolbar.
virtual QList<QAction*> availableActions() const = 0; virtual QList<QAction*> availableActions() const = 0;
// Returns all changeable actions which are currently included // Returns all changeable actions which are currently included
// in the toolbar. // in the toolbar.
virtual QList<QAction*> changeableActions() const = 0; virtual QList<QAction*> changeableActions() const = 0;
// Sets new "actions" to the toolbar and perhaps saves the toolbar // Sets new "actions" to the toolbar and perhaps saves the toolbar
// state into the settings. // state into the settings.
virtual void saveChangeableActions(const QStringList &actions) = 0; virtual void saveChangeableActions(const QStringList& actions) = 0;
// Returns list of default actions. // Returns list of default actions.
virtual QStringList defaultActions() const = 0; virtual QStringList defaultActions() const = 0;
virtual QStringList savedActions() const = 0; virtual QStringList savedActions() const = 0;
// Loads the toolbar state from settings. // Loads the toolbar state from settings.
virtual void loadSavedActions(); virtual void loadSavedActions();
virtual QList<QAction*> getSpecificActions(const QStringList &actions) = 0; virtual QList<QAction*> getSpecificActions(const QStringList& actions) = 0;
virtual void loadSpecificActions(const QList<QAction*> &actions) = 0; virtual void loadSpecificActions(const QList<QAction*>& actions) = 0;
protected: protected:
QAction *findMatchingAction(const QString &action, const QList<QAction *> &actions) const; QAction* findMatchingAction(const QString& action, const QList<QAction*>& actions) const;
}; };
class BaseToolBar : public QToolBar, public BaseBar { class BaseToolBar : public QToolBar, public BaseBar {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit BaseToolBar(const QString &title, QWidget *parent = 0); explicit BaseToolBar(const QString& title, QWidget* parent = 0);
virtual ~BaseToolBar(); virtual ~BaseToolBar();
}; };
#endif // TOOLBAR_H #endif // TOOLBAR_H

View file

@ -25,61 +25,63 @@
ClickableLabel::ClickableLabel(QWidget* parent) ClickableLabel::ClickableLabel(QWidget* parent)
: QLabel(parent) { : QLabel(parent) {
} }
QString ClickableLabel::themeIcon() const { QString ClickableLabel::themeIcon() const {
return m_themeIcon; return m_themeIcon;
} }
void ClickableLabel::setThemeIcon(const QString &name) { void ClickableLabel::setThemeIcon(const QString& name) {
m_themeIcon = name; m_themeIcon = name;
updateIcon(); updateIcon();
} }
QIcon ClickableLabel::fallbackIcon() const { QIcon ClickableLabel::fallbackIcon() const {
return m_fallbackIcon; return m_fallbackIcon;
} }
void ClickableLabel::setFallbackIcon(const QIcon &fallbackIcon) { void ClickableLabel::setFallbackIcon(const QIcon& fallbackIcon) {
m_fallbackIcon = fallbackIcon; m_fallbackIcon = fallbackIcon;
updateIcon(); updateIcon();
} }
void ClickableLabel::updateIcon() { void ClickableLabel::updateIcon() {
if (!m_themeIcon.isEmpty()) { if (!m_themeIcon.isEmpty()) {
const QIcon icon = qApp->icons()->fromTheme(m_themeIcon);
const QIcon icon = qApp->icons()->fromTheme(m_themeIcon); if (!icon.isNull()) {
setPixmap(icon.pixmap(size()));
return;
}
}
if (!icon.isNull()) { if (!m_fallbackIcon.isNull()) {
setPixmap(icon.pixmap(size())); setPixmap(m_fallbackIcon.pixmap(size()));
return; }
}
}
if (!m_fallbackIcon.isNull()) {
setPixmap(m_fallbackIcon.pixmap(size()));
}
} }
void ClickableLabel::resizeEvent(QResizeEvent *ev) { void ClickableLabel::resizeEvent(QResizeEvent* ev) {
QLabel::resizeEvent(ev); QLabel::resizeEvent(ev);
updateIcon(); updateIcon();
} }
void ClickableLabel::mouseReleaseEvent(QMouseEvent* ev) { void ClickableLabel::mouseReleaseEvent(QMouseEvent* ev) {
if (ev->button() == Qt::LeftButton && rect().contains(ev->pos())) { if (ev->button() == Qt::LeftButton && rect().contains(ev->pos())) {
if (ev->modifiers() == Qt::ControlModifier) { if (ev->modifiers() == Qt::ControlModifier) {
emit middleClicked(ev->globalPos()); emit middleClicked(ev->globalPos());
} }
else {
emit clicked(ev->globalPos()); else {
} emit clicked(ev->globalPos());
} }
else if (ev->button() == Qt::MiddleButton && rect().contains(ev->pos())) { }
emit middleClicked(ev->globalPos());
} else if (ev->button() == Qt::MiddleButton && rect().contains(ev->pos())) {
else { emit middleClicked(ev->globalPos());
QLabel::mouseReleaseEvent(ev); }
}
else {
QLabel::mouseReleaseEvent(ev);
}
} }

View file

@ -25,35 +25,35 @@
class QMouseEvent; class QMouseEvent;
class ClickableLabel : public QLabel{ class ClickableLabel : public QLabel {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QSize fixedsize READ size WRITE setFixedSize) Q_PROPERTY(QSize fixedsize READ size WRITE setFixedSize)
Q_PROPERTY(int fixedwidth READ width WRITE setFixedWidth) Q_PROPERTY(int fixedwidth READ width WRITE setFixedWidth)
Q_PROPERTY(int fixedheight READ height WRITE setFixedHeight) Q_PROPERTY(int fixedheight READ height WRITE setFixedHeight)
Q_PROPERTY(QString themeIcon READ themeIcon WRITE setThemeIcon) Q_PROPERTY(QString themeIcon READ themeIcon WRITE setThemeIcon)
Q_PROPERTY(QIcon fallbackIcon READ fallbackIcon WRITE setFallbackIcon) Q_PROPERTY(QIcon fallbackIcon READ fallbackIcon WRITE setFallbackIcon)
public: public:
explicit ClickableLabel(QWidget *parent = 0); explicit ClickableLabel(QWidget* parent = 0);
QString themeIcon() const; QString themeIcon() const;
void setThemeIcon(const QString &name); void setThemeIcon(const QString& name);
QIcon fallbackIcon() const; QIcon fallbackIcon() const;
void setFallbackIcon(const QIcon &fallbackIcon); void setFallbackIcon(const QIcon& fallbackIcon);
signals: signals:
void clicked(QPoint); void clicked(QPoint);
void middleClicked(QPoint); void middleClicked(QPoint);
private: private:
void updateIcon(); void updateIcon();
void resizeEvent(QResizeEvent *ev); void resizeEvent(QResizeEvent* ev);
void mouseReleaseEvent(QMouseEvent* ev); void mouseReleaseEvent(QMouseEvent* ev);
QString m_themeIcon; QString m_themeIcon;
QIcon m_fallbackIcon; QIcon m_fallbackIcon;
}; };

View file

@ -1,43 +1,42 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/colorlabel.h" #include "gui/colorlabel.h"
#include <QPaintEvent> #include <QPaintEvent>
#include <QPainter> #include <QPainter>
ColorLabel::ColorLabel(QWidget *parent) : QLabel(parent), m_color(QColor()) { ColorLabel::ColorLabel(QWidget* parent) : QLabel(parent), m_color(QColor()) {
setFixedWidth(20); setFixedWidth(20);
} }
ColorLabel::~ColorLabel() { ColorLabel::~ColorLabel() {
} }
QColor ColorLabel::color() const { QColor ColorLabel::color() const {
return m_color; return m_color;
} }
void ColorLabel::setColor(const QColor &color) { void ColorLabel::setColor(const QColor& color) {
m_color = color; m_color = color;
repaint();
repaint(); }
}
void ColorLabel::paintEvent(QPaintEvent* event) {
void ColorLabel::paintEvent(QPaintEvent *event) { QPainter(this).fillRect(event->rect(), m_color);
QPainter(this).fillRect(event->rect(), m_color); }
}

View file

@ -1,41 +1,41 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef COLORLABEL_H #ifndef COLORLABEL_H
#define COLORLABEL_H #define COLORLABEL_H
#include <QLabel> #include <QLabel>
class ColorLabel : public QLabel { class ColorLabel : public QLabel {
Q_OBJECT Q_OBJECT
public: public:
explicit ColorLabel(QWidget *parent = 0); explicit ColorLabel(QWidget* parent = 0);
virtual ~ColorLabel(); virtual ~ColorLabel();
QColor color() const; QColor color() const;
void setColor(const QColor &color); void setColor(const QColor& color);
protected: protected:
void paintEvent(QPaintEvent *event); void paintEvent(QPaintEvent* event);
private: private:
QColor m_color; QColor m_color;
}; };
#endif // COLORLABEL_H #endif // COLORLABEL_H

View file

@ -1,39 +1,37 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/comboboxwithstatus.h" #include "gui/comboboxwithstatus.h"
#include "gui/plaintoolbutton.h" #include "gui/plaintoolbutton.h"
#include <QHBoxLayout> #include <QHBoxLayout>
ComboBoxWithStatus::ComboBoxWithStatus(QWidget *parent) ComboBoxWithStatus::ComboBoxWithStatus(QWidget* parent)
: WidgetWithStatus(parent) { : WidgetWithStatus(parent) {
m_wdgInput = new QComboBox(this); m_wdgInput = new QComboBox(this);
// Set correct size for the tool button.
// Set correct size for the tool button. const int txt_input_height = m_wdgInput->sizeHint().height();
const int txt_input_height = m_wdgInput->sizeHint().height(); m_btnStatus->setFixedSize(txt_input_height, txt_input_height);
m_btnStatus->setFixedSize(txt_input_height, txt_input_height); // Compose the layout.
m_layout->addWidget(m_wdgInput);
// Compose the layout. m_layout->addWidget(m_btnStatus);
m_layout->addWidget(m_wdgInput); }
m_layout->addWidget(m_btnStatus);
} ComboBoxWithStatus::~ComboBoxWithStatus() {
}
ComboBoxWithStatus::~ComboBoxWithStatus() {
}

View file

@ -1,39 +1,39 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef COMBOBOXWITHSTATUS_H #ifndef COMBOBOXWITHSTATUS_H
#define COMBOBOXWITHSTATUS_H #define COMBOBOXWITHSTATUS_H
#include "gui/widgetwithstatus.h" #include "gui/widgetwithstatus.h"
#include <QComboBox> #include <QComboBox>
class ComboBoxWithStatus : public WidgetWithStatus { class ComboBoxWithStatus : public WidgetWithStatus {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit ComboBoxWithStatus(QWidget *parent = 0); explicit ComboBoxWithStatus(QWidget* parent = 0);
virtual ~ComboBoxWithStatus(); virtual ~ComboBoxWithStatus();
inline QComboBox *comboBox() const { inline QComboBox* comboBox() const {
return static_cast<QComboBox*>(m_wdgInput); return static_cast<QComboBox*>(m_wdgInput);
} }
}; };
#endif // COMBOBOXWITHSTATUS_H #endif // COMBOBOXWITHSTATUS_H

View file

@ -1,122 +1,122 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/dialogs/formabout.h" #include "gui/dialogs/formabout.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "miscellaneous/textfactory.h" #include "miscellaneous/textfactory.h"
#include "miscellaneous/settingsproperties.h" #include "miscellaneous/settingsproperties.h"
#include <QFile> #include <QFile>
#include <QTextStream> #include <QTextStream>
FormAbout::FormAbout(QWidget *parent) : QDialog(parent), m_ui(new Ui::FormAbout()) { FormAbout::FormAbout(QWidget* parent) : QDialog(parent), m_ui(new Ui::FormAbout()) {
m_ui->setupUi(this); m_ui->setupUi(this);
// Set flags and attributes.
// Set flags and attributes. setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); setWindowIcon(qApp->icons()->fromTheme(QSL("help-about")));
setWindowIcon(qApp->icons()->fromTheme(QSL("help-about"))); //: About RSS Guard dialog title.
setWindowTitle(tr("About %1").arg(APP_NAME));
//: About RSS Guard dialog title. m_ui->m_lblIcon->setPixmap(QPixmap(APP_ICON_PATH));
setWindowTitle(tr("About %1").arg(APP_NAME)); // Load information from embedded text files.
loadLicenseAndInformation();
m_ui->m_lblIcon->setPixmap(QPixmap(APP_ICON_PATH)); // Load additional paths information.
loadSettingsAndPaths();
// Load information from embedded text files. }
loadLicenseAndInformation();
FormAbout::~FormAbout() {
// Load additional paths information. qDebug("Destroying FormAbout instance.");
loadSettingsAndPaths(); }
}
void FormAbout::loadSettingsAndPaths() {
FormAbout::~FormAbout() { if (qApp->settings()->type() == SettingsProperties::Portable) {
qDebug("Destroying FormAbout instance."); m_ui->m_txtPathsSettingsType->setText(tr("FULLY portable"));
} }
void FormAbout::loadSettingsAndPaths() { else {
if (qApp->settings()->type() == SettingsProperties::Portable) { m_ui->m_txtPathsSettingsType->setText(tr("NOT portable"));
m_ui->m_txtPathsSettingsType->setText(tr("FULLY portable")); }
}
else { m_ui->m_txtPathsDatabaseRoot->setText(QDir::toNativeSeparators(qApp->getUserDataPath() +
m_ui->m_txtPathsSettingsType->setText(tr("NOT portable")); QDir::separator() +
} QString(APP_DB_SQLITE_PATH)));
m_ui->m_txtPathsSettingsFile->setText(QDir::toNativeSeparators(qApp->settings()->fileName()));
m_ui->m_txtPathsDatabaseRoot->setText(QDir::toNativeSeparators(qApp->getUserDataPath() + m_ui->m_txtPathsSkinsRoot->setText(QDir::toNativeSeparators(qApp->skins()->getUserSkinBaseFolder()));
QDir::separator() + }
QString(APP_DB_SQLITE_PATH)));
m_ui->m_txtPathsSettingsFile->setText(QDir::toNativeSeparators(qApp->settings()->fileName())); void FormAbout::loadLicenseAndInformation() {
m_ui->m_txtPathsSkinsRoot->setText(QDir::toNativeSeparators(qApp->skins()->getUserSkinBaseFolder())); QFile file;
} file.setFileName(APP_INFO_PATH + QL1S("/COPYING_GNU_GPL_HTML"));
void FormAbout::loadLicenseAndInformation() { if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QFile file; m_ui->m_txtLicenseGnu->setText(QString::fromUtf8(file.readAll()));
}
file.setFileName(APP_INFO_PATH + QL1S("/COPYING_GNU_GPL_HTML"));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { else {
m_ui->m_txtLicenseGnu->setText(QString::fromUtf8(file.readAll())); m_ui->m_txtLicenseGnu->setText(tr("License not found."));
} }
else {
m_ui->m_txtLicenseGnu->setText(tr("License not found.")); file.close();
} file.setFileName(APP_INFO_PATH + QL1S("/COPYING_BSD"));
file.close();
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
file.setFileName(APP_INFO_PATH + QL1S("/COPYING_BSD")); m_ui->m_txtLicenseBsd->setText(QString::fromUtf8(file.readAll()));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { }
m_ui->m_txtLicenseBsd->setText(QString::fromUtf8(file.readAll()));
} else {
else { m_ui->m_txtLicenseBsd->setText(tr("License not found."));
m_ui->m_txtLicenseBsd->setText(tr("License not found.")); }
}
file.close(); file.close();
file.setFileName(APP_INFO_PATH + QL1S("/CHANGELOG"));
file.setFileName(APP_INFO_PATH + QL1S("/CHANGELOG"));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
m_ui->m_txtChangelog->setText(QString::fromUtf8(file.readAll())); m_ui->m_txtChangelog->setText(QString::fromUtf8(file.readAll()));
} }
else {
m_ui->m_txtChangelog->setText(tr("Changelog not found.")); else {
} m_ui->m_txtChangelog->setText(tr("Changelog not found."));
file.close(); }
// Set other informative texts. file.close();
m_ui->m_lblDesc->setText(tr("<b>%8</b><br>" // Set other informative texts.
"<b>Version:</b> %1 (built on %2/%3)<br>" m_ui->m_lblDesc->setText(tr("<b>%8</b><br>"
"<b>Revision:</b> %4<br>" "<b>Version:</b> %1 (built on %2/%3)<br>"
"<b>Build date:</b> %5<br>" "<b>Revision:</b> %4<br>"
"<b>Qt:</b> %6 (compiled against %7)<br>").arg(qApp->applicationVersion(), "<b>Build date:</b> %5<br>"
APP_SYSTEM_NAME, "<b>Qt:</b> %6 (compiled against %7)<br>").arg(qApp->applicationVersion(),
APP_SYSTEM_VERSION, APP_SYSTEM_NAME,
APP_REVISION, APP_SYSTEM_VERSION,
TextFactory::parseDateTime(QString("%1 %2").arg(__DATE__, APP_REVISION,
__TIME__)).toString(Qt::DefaultLocaleShortDate), TextFactory::parseDateTime(QString("%1 %2").arg(__DATE__,
qVersion(), __TIME__)).toString(Qt::DefaultLocaleShortDate),
QT_VERSION_STR, qVersion(),
APP_NAME)); QT_VERSION_STR,
APP_NAME));
m_ui->m_txtInfo->setText(tr("<body>%5 is a (very) tiny feed reader." m_ui->m_txtInfo->setText(tr("<body>%5 is a (very) tiny feed reader."
"<br><br>This software is distributed under the terms of GNU General Public License, version 3." "<br><br>This software is distributed under the terms of GNU General Public License, version 3."
"<br><br>Contacts:" "<br><br>Contacts:"
"<ul><li><a href=\"mailto://%1\">%1</a> ~e-mail</li>" "<ul><li><a href=\"mailto://%1\">%1</a> ~e-mail</li>"
"<li><a href=\"%2\">%2</a> ~website</li></ul>" "<li><a href=\"%2\">%2</a> ~website</li></ul>"
"You can obtain source code for %5 from its website." "You can obtain source code for %5 from its website."
"<br><br><br>Copyright (C) 2011-%3 %4</body>").arg(APP_EMAIL, "<br><br><br>Copyright (C) 2011-%3 %4</body>").arg(APP_EMAIL,
APP_URL, APP_URL,
QString::number(QDateTime::currentDateTime().date().year()), QString::number(QDateTime::currentDateTime().date().year()),
APP_AUTHOR, APP_AUTHOR,
APP_NAME)); APP_NAME));
} }

View file

@ -1,43 +1,43 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FORMABOUT_H #ifndef FORMABOUT_H
#define FORMABOUT_H #define FORMABOUT_H
#include <QDialog> #include <QDialog>
#include "ui_formabout.h" #include "ui_formabout.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
class FormAbout : public QDialog { class FormAbout : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FormAbout(QWidget *parent); explicit FormAbout(QWidget* parent);
virtual ~FormAbout(); virtual ~FormAbout();
private: private:
void loadLicenseAndInformation(); void loadLicenseAndInformation();
void loadSettingsAndPaths(); void loadSettingsAndPaths();
QScopedPointer<Ui::FormAbout> m_ui; QScopedPointer<Ui::FormAbout> m_ui;
}; };
#endif // FORMABOUT_H #endif // FORMABOUT_H

View file

@ -26,61 +26,58 @@
#include <QDialogButtonBox> #include <QDialogButtonBox>
FormAddAccount::FormAddAccount(const QList<ServiceEntryPoint*> &entry_points, FeedsModel *model, QWidget *parent) FormAddAccount::FormAddAccount(const QList<ServiceEntryPoint*>& entry_points, FeedsModel* model, QWidget* parent)
: QDialog(parent), m_ui(new Ui::FormAddAccount), m_model(model), m_entryPoints(entry_points) { : QDialog(parent), m_ui(new Ui::FormAddAccount), m_model(model), m_entryPoints(entry_points) {
m_ui->setupUi(this); m_ui->setupUi(this);
// Set flags and attributes.
// Set flags and attributes. setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); setWindowIcon(qApp->icons()->fromTheme(QSL("document-new")));
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::itemDoubleClicked, this, &FormAddAccount::addSelectedAccount); connect(m_ui->m_listEntryPoints, &QListWidget::itemSelectionChanged, this, &FormAddAccount::displayActiveEntryPointDetails);
connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormAddAccount::addSelectedAccount); loadEntryPoints();
connect(m_ui->m_listEntryPoints, &QListWidget::itemSelectionChanged, this, &FormAddAccount::displayActiveEntryPointDetails);
loadEntryPoints();
} }
FormAddAccount::~FormAddAccount() { FormAddAccount::~FormAddAccount() {
qDebug("Destroying FormAddAccount instance."); qDebug("Destroying FormAddAccount instance.");
} }
void FormAddAccount::addSelectedAccount() { void FormAddAccount::addSelectedAccount() {
accept(); accept();
ServiceEntryPoint* point = selectedEntryPoint();
ServiceRoot* new_root = point->createNewRoot();
ServiceEntryPoint *point = selectedEntryPoint(); if (new_root != nullptr) {
ServiceRoot *new_root = point->createNewRoot(); m_model->addServiceAccount(new_root, true);
}
if (new_root != nullptr) { else {
m_model->addServiceAccount(new_root, true); qCritical("Cannot create new account.");
} }
else {
qCritical("Cannot create new account.");
}
} }
void FormAddAccount::displayActiveEntryPointDetails() { void FormAddAccount::displayActiveEntryPointDetails() {
const ServiceEntryPoint *point = selectedEntryPoint(); const ServiceEntryPoint* point = selectedEntryPoint();
m_ui->m_txtAuthor->setText(point->author());
m_ui->m_txtAuthor->setText(point->author()); m_ui->m_txtDescription->setText(point->description());
m_ui->m_txtDescription->setText(point->description()); m_ui->m_txtName->setText(point->name());
m_ui->m_txtName->setText(point->name()); m_ui->m_txtVersion->setText(point->version());
m_ui->m_txtVersion->setText(point->version());
} }
ServiceEntryPoint *FormAddAccount::selectedEntryPoint() const { 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() { void FormAddAccount::loadEntryPoints() {
foreach (const ServiceEntryPoint *entry_point, m_entryPoints) { foreach (const ServiceEntryPoint* entry_point, m_entryPoints) {
QListWidgetItem *item = new QListWidgetItem(entry_point->icon(), entry_point->name(), m_ui->m_listEntryPoints); QListWidgetItem* item = new QListWidgetItem(entry_point->icon(), entry_point->name(), m_ui->m_listEntryPoints);
if (entry_point->isSingleInstanceService() && m_model->containsServiceRootFromEntryPoint(entry_point)) { if (entry_point->isSingleInstanceService() && m_model->containsServiceRootFromEntryPoint(entry_point)) {
// Oops, this item cannot be added, it is single instance and is already added. // Oops, this item cannot be added, it is single instance and is already added.
item->setFlags(Qt::NoItemFlags); item->setFlags(Qt::NoItemFlags);
item->setToolTip(tr("This account can be added only once.")); 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);
} }

View file

@ -27,23 +27,23 @@ class ServiceEntryPoint;
class FeedsModel; class FeedsModel;
class FormAddAccount : public QDialog { class FormAddAccount : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit FormAddAccount(const QList<ServiceEntryPoint*> &entry_points, FeedsModel *model, QWidget *parent = 0); explicit FormAddAccount(const QList<ServiceEntryPoint*>& entry_points, FeedsModel* model, QWidget* parent = 0);
virtual ~FormAddAccount(); virtual ~FormAddAccount();
private slots: private slots:
void addSelectedAccount(); void addSelectedAccount();
void displayActiveEntryPointDetails(); void displayActiveEntryPointDetails();
private: private:
ServiceEntryPoint *selectedEntryPoint() const; ServiceEntryPoint* selectedEntryPoint() const;
void loadEntryPoints(); void loadEntryPoints();
QScopedPointer<Ui::FormAddAccount> m_ui; QScopedPointer<Ui::FormAddAccount> m_ui;
FeedsModel *m_model; FeedsModel* m_model;
QList<ServiceEntryPoint*> m_entryPoints; QList<ServiceEntryPoint*> m_entryPoints;
}; };
#endif // FORMADDACCOUNT_H #endif // FORMADDACCOUNT_H

View file

@ -28,74 +28,73 @@
#include <QDateTime> #include <QDateTime>
FormBackupDatabaseSettings::FormBackupDatabaseSettings(QWidget *parent) : QDialog(parent), m_ui(new Ui::FormBackupDatabaseSettings) { FormBackupDatabaseSettings::FormBackupDatabaseSettings(QWidget* parent) : QDialog(parent), m_ui(new Ui::FormBackupDatabaseSettings) {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->m_txtBackupName->lineEdit()->setPlaceholderText(tr("Common name for backup files")); 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->getDocumentsFolderPath());
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."));
setWindowIcon(qApp->icons()->fromTheme(QSL("document-export"))); if (qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE &&
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE_MEMORY) {
m_ui->m_checkBackupDatabase->setDisabled(true);
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->getDocumentsFolderPath());
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);
}
} }
FormBackupDatabaseSettings::~FormBackupDatabaseSettings() { FormBackupDatabaseSettings::~FormBackupDatabaseSettings() {
qDebug("Destroying FormBackupDatabaseSettings instance."); qDebug("Destroying FormBackupDatabaseSettings instance.");
} }
void FormBackupDatabaseSettings::performBackup() { void FormBackupDatabaseSettings::performBackup() {
try { try {
qApp->backupDatabaseSettings(m_ui->m_checkBackupDatabase->isChecked(), m_ui->m_checkBackupSettings->isChecked(), 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_lblSelectFolder->label()->text(), m_ui->m_txtBackupName->lineEdit()->text());
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok,
tr("Backup was created successfully and stored in target directory."), tr("Backup was created successfully and stored in target directory."),
tr("Backup was created successfully.")); tr("Backup was created successfully."));
} }
catch (const ApplicationException &ex) {
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(), tr("Backup failed.")); catch (const ApplicationException& ex) {
} m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(), tr("Backup failed."));
}
} }
void FormBackupDatabaseSettings::selectFolderInitial() { void FormBackupDatabaseSettings::selectFolderInitial() {
selectFolder(); selectFolder();
} }
void FormBackupDatabaseSettings::selectFolder(QString path) { void FormBackupDatabaseSettings::selectFolder(QString path) {
if (path.isEmpty()) { if (path.isEmpty()) {
path = QFileDialog::getExistingDirectory(this, tr("Select destination directory"), m_ui->m_lblSelectFolder->label()->text()); path = QFileDialog::getExistingDirectory(this, tr("Select destination directory"), m_ui->m_lblSelectFolder->label()->text());
} }
if (!path.isEmpty()) { if (!path.isEmpty()) {
m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(path), m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(path),
tr("Good destination directory is specified.")); tr("Good destination directory is specified."));
} }
} }
void FormBackupDatabaseSettings::checkBackupNames(const QString &name) { void FormBackupDatabaseSettings::checkBackupNames(const QString& name) {
if (name.simplified().isEmpty()) { if (name.simplified().isEmpty()) {
m_ui->m_txtBackupName->setStatus(WidgetWithStatus::Error, tr("Backup name cannot be empty.")); 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.")); else {
} m_ui->m_txtBackupName->setStatus(WidgetWithStatus::Ok, tr("Backup name looks okay."));
}
} }
void FormBackupDatabaseSettings::checkOkButton() { void FormBackupDatabaseSettings::checkOkButton() {
m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setDisabled(m_ui->m_txtBackupName->lineEdit()->text().simplified().isEmpty() || 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_lblSelectFolder->label()->text().simplified().isEmpty() ||
(!m_ui->m_checkBackupDatabase->isChecked() && (!m_ui->m_checkBackupDatabase->isChecked() &&
!m_ui->m_checkBackupSettings->isChecked())); !m_ui->m_checkBackupSettings->isChecked()));
} }

View file

@ -24,23 +24,23 @@
class FormBackupDatabaseSettings : public QDialog { class FormBackupDatabaseSettings : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors // Constructors and destructors
explicit FormBackupDatabaseSettings(QWidget *parent = 0); explicit FormBackupDatabaseSettings(QWidget* parent = 0);
virtual ~FormBackupDatabaseSettings(); virtual ~FormBackupDatabaseSettings();
private slots: private slots:
void performBackup(); void performBackup();
void selectFolderInitial(); void selectFolderInitial();
void selectFolder(QString path = QString()); void selectFolder(QString path = QString());
void checkBackupNames(const QString &name); void checkBackupNames(const QString& name);
void checkOkButton(); void checkOkButton();
private: private:
QScopedPointer<Ui::FormBackupDatabaseSettings> m_ui; QScopedPointer<Ui::FormBackupDatabaseSettings> m_ui;
}; };
#endif // FORMBACKUPDATABASECONFIG_H #endif // FORMBACKUPDATABASECONFIG_H

View file

@ -1,135 +1,131 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/dialogs/formdatabasecleanup.h" #include "gui/dialogs/formdatabasecleanup.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "miscellaneous/databasefactory.h" #include "miscellaneous/databasefactory.h"
#include <QCloseEvent> #include <QCloseEvent>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QPushButton> #include <QPushButton>
FormDatabaseCleanup::FormDatabaseCleanup(QWidget *parent) : QDialog(parent), m_ui(new Ui::FormDatabaseCleanup), m_cleaner(nullptr) { FormDatabaseCleanup::FormDatabaseCleanup(QWidget* parent) : QDialog(parent), m_ui(new Ui::FormDatabaseCleanup), m_cleaner(nullptr) {
m_ui->setupUi(this); m_ui->setupUi(this);
// Set flags and attributes.
// Set flags and attributes. setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); setWindowIcon(qApp->icons()->fromTheme(QSL("edit-clear")));
setWindowIcon(qApp->icons()->fromTheme(QSL("edit-clear"))); connect(m_ui->m_spinDays, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &FormDatabaseCleanup::updateDaysSuffix);
m_ui->m_spinDays->setValue(DEFAULT_DAYS_TO_DELETE_MSG);
connect(m_ui->m_spinDays, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &FormDatabaseCleanup::updateDaysSuffix); m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("I am ready."), tr("I am ready."));
m_ui->m_spinDays->setValue(DEFAULT_DAYS_TO_DELETE_MSG); loadDatabaseInfo();
m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("I am ready."), tr("I am ready.")); }
loadDatabaseInfo();
} FormDatabaseCleanup::~FormDatabaseCleanup() {
qDebug("Destroying FormDatabaseCleanup instance.");
FormDatabaseCleanup::~FormDatabaseCleanup() { }
qDebug("Destroying FormDatabaseCleanup instance.");
} void FormDatabaseCleanup::setCleaner(DatabaseCleaner* cleaner) {
if (m_cleaner != nullptr) {
void FormDatabaseCleanup::setCleaner(DatabaseCleaner *cleaner) { disconnect(this, 0, m_cleaner, 0);
if (m_cleaner != nullptr) { disconnect(m_cleaner, 0, this, 0);
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);
m_cleaner = cleaner; connect(this, &FormDatabaseCleanup::purgeRequested, m_cleaner, &DatabaseCleaner::purgeDatabaseData);
connect(m_cleaner, &DatabaseCleaner::purgeStarted, this, &FormDatabaseCleanup::onPurgeStarted);
connect(m_ui->m_btnBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormDatabaseCleanup::startPurging); connect(m_cleaner, &DatabaseCleaner::purgeProgress, this, &FormDatabaseCleanup::onPurgeProgress);
connect(this, &FormDatabaseCleanup::purgeRequested, m_cleaner, &DatabaseCleaner::purgeDatabaseData); connect(m_cleaner, &DatabaseCleaner::purgeFinished, this, &FormDatabaseCleanup::onPurgeFinished);
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();
void FormDatabaseCleanup::closeEvent(QCloseEvent *event) { }
if (m_ui->m_progressBar->isEnabled()) {
event->ignore(); else {
} QDialog::closeEvent(event);
else { }
QDialog::closeEvent(event); }
}
} void FormDatabaseCleanup::keyPressEvent(QKeyEvent* event) {
if (m_ui->m_progressBar->isEnabled()) {
void FormDatabaseCleanup::keyPressEvent(QKeyEvent *event) { event->ignore();
if (m_ui->m_progressBar->isEnabled()) { }
event->ignore();
} else {
else { QDialog::keyPressEvent(event);
QDialog::keyPressEvent(event); }
} }
}
void FormDatabaseCleanup::updateDaysSuffix(int number) {
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() {
void FormDatabaseCleanup::startPurging() { CleanerOrders orders;
CleanerOrders orders; orders.m_removeRecycleBin = m_ui->m_checkRemoveRecycleBin->isChecked();
orders.m_removeOldMessages = m_ui->m_checkRemoveOldMessages->isChecked();
orders.m_removeRecycleBin = m_ui->m_checkRemoveRecycleBin->isChecked(); orders.m_barrierForRemovingOldMessagesInDays = m_ui->m_spinDays->value();
orders.m_removeOldMessages = m_ui->m_checkRemoveOldMessages->isChecked(); orders.m_removeReadMessages = m_ui->m_checkRemoveReadMessages->isChecked();
orders.m_barrierForRemovingOldMessagesInDays = m_ui->m_spinDays->value(); orders.m_shrinkDatabase = m_ui->m_checkShrink->isEnabled() && m_ui->m_checkShrink->isChecked();
orders.m_removeReadMessages = m_ui->m_checkRemoveReadMessages->isChecked(); orders.m_removeStarredMessages = m_ui->m_checkRemoveStarredMessages->isChecked();
orders.m_shrinkDatabase = m_ui->m_checkShrink->isEnabled() && m_ui->m_checkShrink->isChecked(); emit purgeRequested(orders);
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);
void FormDatabaseCleanup::onPurgeStarted() { m_ui->m_btnBox->setEnabled(false);
m_ui->m_progressBar->setValue(0); m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("Database cleanup is running."), tr("Database cleanup is running."));
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);
void FormDatabaseCleanup::onPurgeProgress(int progress, const QString &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);
void FormDatabaseCleanup::onPurgeFinished(bool finished) { m_ui->m_btnBox->setEnabled(true);
m_ui->m_progressBar->setEnabled(false);
m_ui->m_progressBar->setValue(0); if (finished) {
m_ui->m_btnBox->setEnabled(true); m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Database cleanup is completed."), tr("Database cleanup is completed."));
}
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."));
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();
void FormDatabaseCleanup::loadDatabaseInfo() { qint64 data_size = qApp->database()->getDatabaseDataSize();
qint64 file_size = qApp->database()->getDatabaseFileSize(); QString file_size_str = file_size > 0 ? QString::number(file_size / 1000000.0) + QL1S(" MB") : tr("unknown");
qint64 data_size = qApp->database()->getDatabaseDataSize(); 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));
QString file_size_str = file_size > 0 ? QString::number(file_size / 1000000.0) + QL1S(" MB") : tr("unknown"); m_ui->m_txtDatabaseType->setText(qApp->database()->humanDriverName(qApp->database()->activeDatabaseDriver()));
QString data_size_str = data_size > 0 ? QString::number(data_size / 1000000.0) + QL1S(" MB") : tr("unknown"); m_ui->m_checkShrink->setEnabled(qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE ||
qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE_MEMORY);
m_ui->m_txtFileSize->setText(tr("file: %1, data: %2").arg(file_size_str, data_size_str)); m_ui->m_checkShrink->setChecked(m_ui->m_checkShrink->isEnabled());
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());
}

View file

@ -1,60 +1,60 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FORMDATABASECLEANUP_H #ifndef FORMDATABASECLEANUP_H
#define FORMDATABASECLEANUP_H #define FORMDATABASECLEANUP_H
#include <QDialog> #include <QDialog>
#include "ui_formdatabasecleanup.h" #include "ui_formdatabasecleanup.h"
#include "miscellaneous/databasecleaner.h" #include "miscellaneous/databasecleaner.h"
class FormDatabaseCleanup : public QDialog { class FormDatabaseCleanup : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors. // Constructors.
explicit FormDatabaseCleanup(QWidget *parent = 0); explicit FormDatabaseCleanup(QWidget* parent = 0);
virtual ~FormDatabaseCleanup(); virtual ~FormDatabaseCleanup();
void setCleaner(DatabaseCleaner *cleaner); void setCleaner(DatabaseCleaner* cleaner);
protected: protected:
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent* event);
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent* event);
private slots: private slots:
void updateDaysSuffix(int number); void updateDaysSuffix(int number);
void startPurging(); void startPurging();
void onPurgeStarted(); void onPurgeStarted();
void onPurgeProgress(int progress, const QString &description); void onPurgeProgress(int progress, const QString& description);
void onPurgeFinished(bool finished); void onPurgeFinished(bool finished);
signals: signals:
void purgeRequested(const CleanerOrders &which_data); void purgeRequested(const CleanerOrders& which_data);
private: private:
void loadDatabaseInfo(); void loadDatabaseInfo();
private: private:
QScopedPointer<Ui::FormDatabaseCleanup> m_ui; QScopedPointer<Ui::FormDatabaseCleanup> m_ui;
DatabaseCleaner *m_cleaner; DatabaseCleaner* m_cleaner;
}; };
#endif // FORMDATABASECLEANUP_H #endif // FORMDATABASECLEANUP_H

File diff suppressed because it is too large Load diff

View file

@ -1,125 +1,125 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FORMMAIN_H #ifndef FORMMAIN_H
#define FORMMAIN_H #define FORMMAIN_H
#include <QMainWindow> #include <QMainWindow>
#include "ui_formmain.h" #include "ui_formmain.h"
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
class AdBlockIcon; class AdBlockIcon;
#endif #endif
class StatusBar; class StatusBar;
class FormMain : public QMainWindow { class FormMain : public QMainWindow {
Q_OBJECT Q_OBJECT
friend class TabWidget; friend class TabWidget;
friend class MessagesView; friend class MessagesView;
friend class FeedsView; friend class FeedsView;
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FormMain(QWidget *parent = 0, Qt::WindowFlags f = 0); explicit FormMain(QWidget* parent = 0, Qt::WindowFlags f = 0);
virtual ~FormMain(); virtual ~FormMain();
// Returns menu for the tray icon. // Returns menu for the tray icon.
QMenu *trayMenu() const; QMenu* trayMenu() const;
// Returns global tab widget. // Returns global tab widget.
TabWidget *tabWidget() const; TabWidget* tabWidget() const;
// Access to statusbar. // Access to statusbar.
StatusBar *statusBar() const; StatusBar* statusBar() const;
// Returns list of all globally available actions. // Returns list of all globally available actions.
// NOTE: This is used for setting dynamic shortcuts // NOTE: This is used for setting dynamic shortcuts
// for given actions. // for given actions.
QList<QAction*> allActions() const; QList<QAction*> allActions() const;
// Loads/saves visual state of the application. // Loads/saves visual state of the application.
void loadSize(); void loadSize();
void saveSize(); void saveSize();
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
AdBlockIcon *adblockIcon() const { AdBlockIcon* adblockIcon() const {
return m_adblockIcon; return m_adblockIcon;
} }
#endif #endif
public slots: public slots:
// Displays window on top or switches its visibility. // Displays window on top or switches its visibility.
void display(); void display();
// Switches visibility of main window. // Switches visibility of main window.
void switchVisibility(bool force_hide = false); void switchVisibility(bool force_hide = false);
// Turns on/off fullscreen mode // Turns on/off fullscreen mode
void switchFullscreenMode(); void switchFullscreenMode();
private slots: private slots:
void updateAddItemMenu(); void updateAddItemMenu();
void updateRecycleBinMenu(); void updateRecycleBinMenu();
void updateAccountsMenu(); void updateAccountsMenu();
void updateMessageButtonsAvailability(); void updateMessageButtonsAvailability();
void updateFeedButtonsAvailability(); void updateFeedButtonsAvailability();
void onFeedUpdatesStarted(); void onFeedUpdatesStarted();
void onFeedUpdatesProgress(const Feed *feed, int current, int total); void onFeedUpdatesProgress(const Feed* feed, int current, int total);
void onFeedUpdatesFinished(const FeedDownloadResults &results); void onFeedUpdatesFinished(const FeedDownloadResults& results);
// Displays various dialogs. // Displays various dialogs.
void backupDatabaseSettings(); void backupDatabaseSettings();
void restoreDatabaseSettings(); void restoreDatabaseSettings();
void showSettings(); void showSettings();
void showAbout(); void showAbout();
void showUpdates(); void showUpdates();
void showWiki(); void showWiki();
void showAddAccountDialog(); void showAddAccountDialog();
void showDbCleanupAssistant(); void showDbCleanupAssistant();
void reportABug(); void reportABug();
void donate(); void donate();
private: private:
// Event handler reimplementations. // Event handler reimplementations.
void changeEvent(QEvent *event); void changeEvent(QEvent* event);
// Creates all needed menus and sets them up. // Creates all needed menus and sets them up.
void prepareMenus(); void prepareMenus();
// Creates needed connections for this window. // Creates needed connections for this window.
void createConnections(); void createConnections();
// Sets up proper icons for this widget. // Sets up proper icons for this widget.
void setupIcons(); void setupIcons();
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
AdBlockIcon *m_adblockIcon; AdBlockIcon* m_adblockIcon;
QAction *m_adblockIconAction; QAction* m_adblockIconAction;
#endif #endif
QScopedPointer<Ui::FormMain> m_ui; QScopedPointer<Ui::FormMain> m_ui;
QMenu *m_trayMenu; QMenu* m_trayMenu;
StatusBar *m_statusBar; StatusBar* m_statusBar;
}; };
#endif // FORMMAIN_H #endif // FORMMAIN_H

View file

@ -1,139 +1,136 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/dialogs/formrestoredatabasesettings.h" #include "gui/dialogs/formrestoredatabasesettings.h"
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include "gui/dialogs/formmain.h" #include "gui/dialogs/formmain.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "exceptions/applicationexception.h" #include "exceptions/applicationexception.h"
#include "QFileDialog" #include "QFileDialog"
FormRestoreDatabaseSettings::FormRestoreDatabaseSettings(QWidget *parent) FormRestoreDatabaseSettings::FormRestoreDatabaseSettings(QWidget* parent)
: QDialog(parent), m_ui(new Ui::FormRestoreDatabaseSettings), m_shouldRestart(false) { : QDialog(parent), m_ui(new Ui::FormRestoreDatabaseSettings), m_shouldRestart(false) {
m_ui->setupUi(this); m_ui->setupUi(this);
m_btnRestart = m_ui->m_buttonBox->addButton(tr("Restart"), QDialogButtonBox::ActionRole);
m_btnRestart = m_ui->m_buttonBox->addButton(tr("Restart"), QDialogButtonBox::ActionRole); m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet."));
m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet.")); setWindowIcon(qApp->icons()->fromTheme(QSL("document-import")));
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("document-import"))); connect(m_btnRestart, &QPushButton::clicked, this, [ = ]() {
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); m_shouldRestart = true;
close();
connect(m_btnRestart, &QPushButton::clicked, this, [=]() { });
m_shouldRestart = true; connect(m_ui->m_btnSelectFolder, SIGNAL(clicked()), this, SLOT(selectFolder()));
close(); connect(m_ui->m_groupDatabase, SIGNAL(toggled(bool)), this, SLOT(checkOkButton()));
}); connect(m_ui->m_groupSettings, SIGNAL(toggled(bool)), this, SLOT(checkOkButton()));
connect(m_ui->m_btnSelectFolder, SIGNAL(clicked()), this, SLOT(selectFolder())); connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(performRestoration()));
connect(m_ui->m_groupDatabase, SIGNAL(toggled(bool)), this, SLOT(checkOkButton())); selectFolder(qApp->getDocumentsFolderPath());
connect(m_ui->m_groupSettings, SIGNAL(toggled(bool)), this, SLOT(checkOkButton())); }
connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(performRestoration()));
FormRestoreDatabaseSettings::~FormRestoreDatabaseSettings() {
selectFolder(qApp->getDocumentsFolderPath()); qDebug("Destroying FormRestoreDatabaseSettings instance.");
} }
FormRestoreDatabaseSettings::~FormRestoreDatabaseSettings() { void FormRestoreDatabaseSettings::performRestoration() {
qDebug("Destroying FormRestoreDatabaseSettings instance."); m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
}
try {
void FormRestoreDatabaseSettings::performRestoration() { qApp->restoreDatabaseSettings(m_ui->m_groupDatabase->isChecked(),
m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); m_ui->m_groupSettings->isChecked(),
m_ui->m_listDatabase->currentRow() >= 0 ?
try { m_ui->m_listDatabase->currentItem()->data(Qt::UserRole).toString() :
qApp->restoreDatabaseSettings(m_ui->m_groupDatabase->isChecked(), QString(),
m_ui->m_groupSettings->isChecked(), m_ui->m_listSettings->currentRow() >= 0 ?
m_ui->m_listDatabase->currentRow() >= 0 ? m_ui->m_listSettings->currentItem()->data(Qt::UserRole).toString() :
m_ui->m_listDatabase->currentItem()->data(Qt::UserRole).toString() : QString());
QString(), m_btnRestart->setEnabled(true);
m_ui->m_listSettings->currentRow() >= 0 ? m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Restoration was initiated. Restart to proceed."),
m_ui->m_listSettings->currentItem()->data(Qt::UserRole).toString() : tr("You need to restart application for restoration process to finish."));
QString()); }
m_btnRestart->setEnabled(true);
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Restoration was initiated. Restart to proceed."), catch (const ApplicationException& ex) {
tr("You need to restart application for restoration process to finish.")); m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(),
} tr("Database and/or settings were not copied to restoration directory successully."));
catch (const ApplicationException &ex) { }
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(), }
tr("Database and/or settings were not copied to restoration directory successully."));
} void FormRestoreDatabaseSettings::checkOkButton() {
} m_btnRestart->setEnabled(false);
m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!m_ui->m_lblSelectFolder->label()->text().isEmpty() &&
void FormRestoreDatabaseSettings::checkOkButton() { ((m_ui->m_groupDatabase->isChecked() &&
m_btnRestart->setEnabled(false); m_ui->m_listDatabase->currentRow() >= 0) ||
m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!m_ui->m_lblSelectFolder->label()->text().isEmpty() && (m_ui->m_groupSettings->isChecked() &&
((m_ui->m_groupDatabase->isChecked() && m_ui->m_listSettings->currentRow() >= 0)));
m_ui->m_listDatabase->currentRow() >= 0) || }
(m_ui->m_groupSettings->isChecked() &&
m_ui->m_listSettings->currentRow() >= 0))); void FormRestoreDatabaseSettings::selectFolderWithGui() {
} selectFolder();
}
void FormRestoreDatabaseSettings::selectFolderWithGui() {
selectFolder(); void FormRestoreDatabaseSettings::selectFolder(QString folder) {
} if (folder.isEmpty()) {
folder = QFileDialog::getExistingDirectory(this, tr("Select source directory"), m_ui->m_lblSelectFolder->label()->text());
void FormRestoreDatabaseSettings::selectFolder(QString folder) { }
if (folder.isEmpty()) {
folder = QFileDialog::getExistingDirectory(this, tr("Select source directory"), m_ui->m_lblSelectFolder->label()->text()); if (!folder.isEmpty()) {
} m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(folder),
tr("Good source directory is specified."));
if (!folder.isEmpty()) { }
m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(folder),
tr("Good source directory is specified.")); else {
} return;
else { }
return;
} const QDir selected_folder(folder);
const QFileInfoList available_databases = selected_folder.entryInfoList(QStringList()
const QDir selected_folder(folder); << QString("*") + BACKUP_SUFFIX_DATABASE,
const QFileInfoList available_databases = selected_folder.entryInfoList(QStringList() QDir::Files | QDir::NoDotAndDotDot | QDir::Readable |
<< QString("*") + BACKUP_SUFFIX_DATABASE , QDir::CaseSensitive | QDir::NoSymLinks,
QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::Name);
QDir::CaseSensitive | QDir::NoSymLinks, const QFileInfoList available_settings = selected_folder.entryInfoList(QStringList()
QDir::Name); << QString("*") + BACKUP_SUFFIX_SETTINGS,
const QFileInfoList available_settings = selected_folder.entryInfoList(QStringList() QDir::Files | QDir::NoDotAndDotDot | QDir::Readable |
<< QString("*") + BACKUP_SUFFIX_SETTINGS , QDir::CaseSensitive | QDir::NoSymLinks,
QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::Name);
QDir::CaseSensitive | QDir::NoSymLinks, m_ui->m_listDatabase->clear();
QDir::Name); m_ui->m_listSettings->clear();
m_ui->m_listDatabase->clear(); foreach (const QFileInfo& database_file, available_databases) {
m_ui->m_listSettings->clear(); QListWidgetItem* database_item = new QListWidgetItem(database_file.fileName(), m_ui->m_listDatabase);
database_item->setData(Qt::UserRole, database_file.absoluteFilePath());
foreach (const QFileInfo &database_file, available_databases) { database_item->setToolTip(QDir::toNativeSeparators(database_file.absoluteFilePath()));
QListWidgetItem *database_item = new QListWidgetItem(database_file.fileName(), m_ui->m_listDatabase); }
database_item->setData(Qt::UserRole, database_file.absoluteFilePath());
database_item->setToolTip(QDir::toNativeSeparators(database_file.absoluteFilePath())); foreach (const QFileInfo& settings_file, available_settings) {
} QListWidgetItem* settings_item = new QListWidgetItem(settings_file.fileName(), m_ui->m_listSettings);
settings_item->setData(Qt::UserRole, settings_file.absoluteFilePath());
foreach (const QFileInfo &settings_file, available_settings) { settings_item->setToolTip(QDir::toNativeSeparators(settings_file.absoluteFilePath()));
QListWidgetItem *settings_item = new QListWidgetItem(settings_file.fileName(), m_ui->m_listSettings); }
settings_item->setData(Qt::UserRole, settings_file.absoluteFilePath());
settings_item->setToolTip(QDir::toNativeSeparators(settings_file.absoluteFilePath())); if (!available_databases.isEmpty()) {
} m_ui->m_listDatabase->setCurrentRow(0);
}
if (!available_databases.isEmpty()) {
m_ui->m_listDatabase->setCurrentRow(0); if (!available_settings.isEmpty()) {
} m_ui->m_listSettings->setCurrentRow(0);
}
if (!available_settings.isEmpty()) {
m_ui->m_listSettings->setCurrentRow(0); m_ui->m_groupDatabase->setChecked(!available_databases.isEmpty());
} m_ui->m_groupSettings->setChecked(!available_settings.isEmpty());
}
m_ui->m_groupDatabase->setChecked(!available_databases.isEmpty());
m_ui->m_groupSettings->setChecked(!available_settings.isEmpty());
}

View file

@ -1,51 +1,51 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FORMRESTOREDATABASESETTINGS_H #ifndef FORMRESTOREDATABASESETTINGS_H
#define FORMRESTOREDATABASESETTINGS_H #define FORMRESTOREDATABASESETTINGS_H
#include <QDialog> #include <QDialog>
#include "ui_formrestoredatabasesettings.h" #include "ui_formrestoredatabasesettings.h"
class FormRestoreDatabaseSettings : public QDialog { class FormRestoreDatabaseSettings : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FormRestoreDatabaseSettings(QWidget *parent = 0); explicit FormRestoreDatabaseSettings(QWidget* parent = 0);
virtual ~FormRestoreDatabaseSettings(); virtual ~FormRestoreDatabaseSettings();
bool shouldRestart() const { bool shouldRestart() const {
return m_shouldRestart; return m_shouldRestart;
} }
private slots: private slots:
void performRestoration(); void performRestoration();
void checkOkButton(); void checkOkButton();
void selectFolderWithGui(); void selectFolderWithGui();
void selectFolder(QString folder = QString()); void selectFolder(QString folder = QString());
private: private:
QScopedPointer<Ui::FormRestoreDatabaseSettings> m_ui; QScopedPointer<Ui::FormRestoreDatabaseSettings> m_ui;
QPushButton *m_btnRestart; QPushButton* m_btnRestart;
bool m_shouldRestart; bool m_shouldRestart;
}; };
#endif // FORMRESTOREDATABASESETTINGS_H #endif // FORMRESTOREDATABASESETTINGS_H

View file

@ -1,146 +1,139 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/dialogs/formsettings.h" #include "gui/dialogs/formsettings.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/settings.h" #include "miscellaneous/settings.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include "gui/settings/settingsbrowsermail.h" #include "gui/settings/settingsbrowsermail.h"
#include "gui/settings/settingsdatabase.h" #include "gui/settings/settingsdatabase.h"
#include "gui/settings/settingsdownloads.h" #include "gui/settings/settingsdownloads.h"
#include "gui/settings/settingsfeedsmessages.h" #include "gui/settings/settingsfeedsmessages.h"
#include "gui/settings/settingsgeneral.h" #include "gui/settings/settingsgeneral.h"
#include "gui/settings/settingsgui.h" #include "gui/settings/settingsgui.h"
#include "gui/settings/settingslocalization.h" #include "gui/settings/settingslocalization.h"
#include "gui/settings/settingsshortcuts.h" #include "gui/settings/settingsshortcuts.h"
FormSettings::FormSettings(QWidget *parent) : QDialog(parent), m_panels(QList<SettingsPanel*>()), m_ui(new Ui::FormSettings), m_settings(qApp->settings()) { FormSettings::FormSettings(QWidget* parent) : QDialog(parent), m_panels(QList<SettingsPanel*>()), m_ui(new Ui::FormSettings), m_settings(qApp->settings()) {
m_ui->setupUi(this); m_ui->setupUi(this);
// Set flags and attributes.
// Set flags and attributes. setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); setWindowIcon(qApp->icons()->fromTheme(QSL("emblem-system")));
setWindowIcon(qApp->icons()->fromTheme(QSL("emblem-system"))); m_btnApply = m_ui->m_buttonBox->button(QDialogButtonBox::Apply);
m_btnApply->setEnabled(false);
m_btnApply = m_ui->m_buttonBox->button(QDialogButtonBox::Apply); // Establish needed connections.
m_btnApply->setEnabled(false); connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormSettings::saveSettings);
connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &FormSettings::cancelSettings);
// Establish needed connections. connect(m_btnApply, &QPushButton::clicked, this, &FormSettings::applySettings);
connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormSettings::saveSettings); addSettingsPanel(new SettingsGeneral(m_settings, this));
connect(m_ui->m_buttonBox, &QDialogButtonBox::rejected, this, &FormSettings::cancelSettings); addSettingsPanel(new SettingsDatabase(m_settings, this));
connect(m_btnApply, &QPushButton::clicked, this, &FormSettings::applySettings); addSettingsPanel(new SettingsGui(m_settings, this));
addSettingsPanel(new SettingsLocalization(m_settings, this));
addSettingsPanel(new SettingsGeneral(m_settings, this)); addSettingsPanel(new SettingsShortcuts(m_settings, this));
addSettingsPanel(new SettingsDatabase(m_settings, this)); addSettingsPanel(new SettingsBrowserMail(m_settings, this));
addSettingsPanel(new SettingsGui(m_settings, this)); addSettingsPanel(new SettingsDownloads(m_settings, this));
addSettingsPanel(new SettingsLocalization(m_settings, this)); addSettingsPanel(new SettingsFeedsMessages(m_settings, this));
addSettingsPanel(new SettingsShortcuts(m_settings, this)); m_ui->m_listSettings->setCurrentRow(0);
addSettingsPanel(new SettingsBrowserMail(m_settings, this)); }
addSettingsPanel(new SettingsDownloads(m_settings, this));
addSettingsPanel(new SettingsFeedsMessages(m_settings, this)); FormSettings::~FormSettings() {
qDebug("Destroying FormSettings distance.");
m_ui->m_listSettings->setCurrentRow(0); }
}
void FormSettings::saveSettings() {
FormSettings::~FormSettings() { applySettings();
qDebug("Destroying FormSettings distance."); accept();
} }
void FormSettings::saveSettings() { void FormSettings::applySettings() {
applySettings(); // Save all settings.
accept(); m_settings->checkSettings();
} QStringList panels_for_restart;
void FormSettings::applySettings() { foreach (SettingsPanel* panel, m_panels) {
// Save all settings. if (panel->isDirty()) {
m_settings->checkSettings(); panel->saveSettings();
}
QStringList panels_for_restart;
if (panel->requiresRestart()) {
foreach (SettingsPanel *panel, m_panels) { panels_for_restart.append(panel->title().toLower());
if (panel->isDirty()) { panel->setRequiresRestart(false);
panel->saveSettings(); }
} }
if (panel->requiresRestart()) { if (!panels_for_restart.isEmpty()) {
panels_for_restart.append(panel->title().toLower()); const QStringList changed_settings_description = panels_for_restart.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8(""));
panel->setRequiresRestart(false); 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. "
if (!panels_for_restart.isEmpty()) { "\n\nYou have to restart manually."),
const QStringList changed_settings_description = panels_for_restart.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8("")); tr("Do you want to restart now?"),
tr("Changed categories of settings:\n%1.").arg(changed_settings_description .join(QSL(",\n"))),
const QMessageBox::StandardButton clicked_button = MessageBox::show(this, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
QMessageBox::Question,
tr("Critical settings were changed"), if (clicked_button == QMessageBox::Yes) {
tr("Some critical settings were changed and will be applied after the application gets restarted. " qApp->restart();
"\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); m_btnApply->setEnabled(false);
}
if (clicked_button == QMessageBox::Yes) {
qApp->restart(); void FormSettings::cancelSettings() {
} QStringList changed_panels;
}
foreach (SettingsPanel* panel, m_panels) {
m_btnApply->setEnabled(false); if (panel->isDirty()) {
} changed_panels.append(panel->title().toLower());
}
void FormSettings::cancelSettings() { }
QStringList changed_panels;
if (changed_panels.isEmpty()) {
foreach (SettingsPanel *panel, m_panels) { reject();
if (panel->isDirty()) { }
changed_panels.append(panel->title().toLower());
} else {
} const QStringList changed_settings_description = changed_panels.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8(""));
if (changed_panels.isEmpty()) { if (MessageBox::show(this,
reject(); QMessageBox::Critical,
} tr("Some settings are changed and will be lost"),
else { tr("Some settings were changed and by cancelling this dialog, you would lose these changes."),
const QStringList changed_settings_description = changed_panels.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8("")); 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"))),
if (MessageBox::show(this, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) ==
QMessageBox::Critical, QMessageBox::Yes) {
tr("Some settings are changed and will be lost"), reject();
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) { void FormSettings::addSettingsPanel(SettingsPanel* panel) {
reject(); m_ui->m_listSettings->addItem(panel->title());
} m_panels.append(panel);
} m_ui->m_stackedSettings->addWidget(panel);
} panel->loadSettings();
connect(panel, &SettingsPanel::settingsChanged, [this]() {
void FormSettings::addSettingsPanel(SettingsPanel *panel) { 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);
});
}

View file

@ -1,52 +1,52 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FORMSETTINGS_H #ifndef FORMSETTINGS_H
#define FORMSETTINGS_H #define FORMSETTINGS_H
#include <QDialog> #include <QDialog>
#include "ui_formsettings.h" #include "ui_formsettings.h"
class Settings; class Settings;
class SettingsPanel; class SettingsPanel;
class FormSettings : public QDialog { class FormSettings : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FormSettings(QWidget *parent = 0); explicit FormSettings(QWidget* parent = 0);
virtual ~FormSettings(); virtual ~FormSettings();
private slots: private slots:
// Saves settings into global configuration. // Saves settings into global configuration.
void saveSettings(); void saveSettings();
void applySettings(); void applySettings();
void cancelSettings(); void cancelSettings();
private: private:
void addSettingsPanel(SettingsPanel *panel); void addSettingsPanel(SettingsPanel* panel);
QList<SettingsPanel*> m_panels; QList<SettingsPanel*> m_panels;
QScopedPointer<Ui::FormSettings> m_ui; QScopedPointer<Ui::FormSettings> m_ui;
QPushButton *m_btnApply; QPushButton* m_btnApply;
Settings *m_settings; Settings* m_settings;
}; };
#endif // FORMSETTINGS_H #endif // FORMSETTINGS_H

View file

@ -1,259 +1,259 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/dialogs/formupdate.h" #include "gui/dialogs/formupdate.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "miscellaneous/iofactory.h" #include "miscellaneous/iofactory.h"
#include "network-web/networkfactory.h" #include "network-web/networkfactory.h"
#include "network-web/webfactory.h" #include "network-web/webfactory.h"
#include "network-web/downloader.h" #include "network-web/downloader.h"
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include <QNetworkReply> #include <QNetworkReply>
#include <QProcess> #include <QProcess>
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
#include <windows.h> #include <windows.h>
#endif #endif
FormUpdate::FormUpdate(QWidget *parent) FormUpdate::FormUpdate(QWidget* parent)
: QDialog(parent), m_downloader(nullptr), m_readyToInstall(false), m_ui(new Ui::FormUpdate), m_lastDownloadedBytes(0) { : QDialog(parent), m_downloader(nullptr), m_readyToInstall(false), m_ui(new Ui::FormUpdate), m_lastDownloadedBytes(0) {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->m_lblCurrentRelease->setText(APP_VERSION); m_ui->m_lblCurrentRelease->setText(APP_VERSION);
m_ui->m_tabInfo->removeTab(1); m_ui->m_tabInfo->removeTab(1);
// Set flags and attributes.
// Set flags and attributes. setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint); setWindowIcon(qApp->icons()->fromTheme(QSL("help-about")));
setWindowIcon(qApp->icons()->fromTheme(QSL("help-about")));
if (isSelfUpdateSupported()) {
if (isSelfUpdateSupported()) { m_btnUpdate = m_ui->m_buttonBox->addButton(tr("Download selected update"), QDialogButtonBox::ActionRole);
m_btnUpdate = m_ui->m_buttonBox->addButton(tr("Download selected update"), QDialogButtonBox::ActionRole); m_btnUpdate->setToolTip(tr("Download new installation files."));
m_btnUpdate->setToolTip(tr("Download new installation files.")); }
}
else { else {
m_btnUpdate = m_ui->m_buttonBox->addButton(tr("Go to application website"), QDialogButtonBox::ActionRole); 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->setToolTip(tr("Go to application website to get update packages manually."));
} }
m_btnUpdate->setVisible(false); m_btnUpdate->setVisible(false);
connect(m_btnUpdate, &QPushButton::clicked, this, &FormUpdate::startUpdate); connect(m_btnUpdate, &QPushButton::clicked, this, &FormUpdate::startUpdate);
checkForUpdates(); checkForUpdates();
} }
FormUpdate::~FormUpdate() { FormUpdate::~FormUpdate() {
} }
bool FormUpdate::isSelfUpdateSupported() const { bool FormUpdate::isSelfUpdateSupported() const {
#if defined(Q_OS_WIN) || defined(Q_OS_MAC) #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
return true; return true;
#else #else
return false; return false;
#endif #endif
} }
void FormUpdate::checkForUpdates() { void FormUpdate::checkForUpdates() {
const QPair<QList<UpdateInfo>, QNetworkReply::NetworkError> update = qApp->system()->checkForUpdates(); const QPair<QList<UpdateInfo>, QNetworkReply::NetworkError> update = qApp->system()->checkForUpdates();
if (update.second != QNetworkReply::NoError) { if (update.second != QNetworkReply::NoError) {
m_updateInfo = UpdateInfo(); m_updateInfo = UpdateInfo();
m_ui->m_tabInfo->setEnabled(false); m_ui->m_tabInfo->setEnabled(false);
//: Unknown release.
//: Unknown release. m_ui->m_lblAvailableRelease->setText(tr("unknown"));
m_ui->m_lblAvailableRelease->setText(tr("unknown")); m_ui->m_txtChanges->clear();
m_ui->m_txtChanges->clear(); m_ui->m_lblStatus->setStatus(WidgetWithStatus::Error,
m_ui->m_lblStatus->setStatus(WidgetWithStatus::Error, tr("Error: '%1'.").arg(NetworkFactory::networkErrorText(update.second)),
tr("Error: '%1'.").arg(NetworkFactory::networkErrorText(update.second)), tr("List with updates was not\ndownloaded successfully."));
tr("List with updates was not\ndownloaded successfully.")); }
}
else { else {
const bool self_update_supported = isSelfUpdateSupported(); const bool self_update_supported = isSelfUpdateSupported();
m_updateInfo = update.first.at(0);
m_updateInfo = update.first.at(0); m_ui->m_tabInfo->setEnabled(true);
m_ui->m_tabInfo->setEnabled(true); m_ui->m_lblAvailableRelease->setText(m_updateInfo.m_availableVersion);
m_ui->m_lblAvailableRelease->setText(m_updateInfo.m_availableVersion); m_ui->m_txtChanges->setText(m_updateInfo.m_changes);
m_ui->m_txtChanges->setText(m_updateInfo.m_changes);
if (SystemFactory::isVersionNewer(m_updateInfo.m_availableVersion, APP_VERSION)) {
if (SystemFactory::isVersionNewer(m_updateInfo.m_availableVersion, APP_VERSION)) { m_btnUpdate->setVisible(true);
m_btnUpdate->setVisible(true); m_ui->m_lblStatus->setStatus(WidgetWithStatus::Ok,
m_ui->m_lblStatus->setStatus(WidgetWithStatus::Ok, tr("New release available."),
tr("New release available."), tr("This is new version which can be\ndownloaded."));
tr("This is new version which can be\ndownloaded."));
if (self_update_supported) {
if (self_update_supported) { loadAvailableFiles();
loadAvailableFiles(); }
} }
}
else { else {
m_ui->m_lblStatus->setStatus(WidgetWithStatus::Warning, m_ui->m_lblStatus->setStatus(WidgetWithStatus::Warning,
tr("No new release available."), tr("No new release available."),
tr("This release is not newer than\ncurrently installed one.")); tr("This release is not newer than\ncurrently installed one."));
} }
} }
} }
void FormUpdate::updateProgress(qint64 bytes_received, qint64 bytes_total) { void FormUpdate::updateProgress(qint64 bytes_received, qint64 bytes_total) {
if (bytes_received - m_lastDownloadedBytes > 500000 || m_lastDownloadedBytes == 0) { if (bytes_received - m_lastDownloadedBytes > 500000 || m_lastDownloadedBytes == 0) {
m_ui->m_lblStatus->setStatus(WidgetWithStatus::Information, 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, tr("Downloaded %1% (update size is %2 kB).").arg(QString::number(bytes_total == 0 ? 0 : (bytes_received * 100.0) / bytes_total,
'f', 'f',
2), 2),
QString::number(bytes_total / 1000, QString::number(bytes_total / 1000,
'f', 'f',
2)), 2)),
tr("Downloading update...")); tr("Downloading update..."));
m_ui->m_lblStatus->repaint(); m_ui->m_lblStatus->repaint();
m_lastDownloadedBytes = bytes_received;
m_lastDownloadedBytes = bytes_received; }
} }
}
void FormUpdate::saveUpdateFile(const QByteArray& file_contents) {
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->getTempFolderPath();
const QString temp_directory = qApp->getTempFolderPath();
if (!temp_directory.isEmpty()) {
if (!temp_directory.isEmpty()) { const QString output_file_name = url_file.mid(url_file.lastIndexOf('/') + 1);
const QString output_file_name = url_file.mid(url_file.lastIndexOf('/') + 1); QFile output_file(temp_directory + QDir::separator() + output_file_name);
QFile output_file(temp_directory + QDir::separator() + output_file_name);
if (output_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
if (output_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { qDebug("Storing update file to temporary location '%s'.",
qDebug("Storing update file to temporary location '%s'.", qPrintable(QDir::toNativeSeparators(output_file.fileName())));
qPrintable(QDir::toNativeSeparators(output_file.fileName()))); output_file.write(file_contents);
output_file.flush();
output_file.write(file_contents); output_file.close();
output_file.flush(); qDebug("Update file contents was successfuly saved.");
output_file.close(); m_updateFilePath = output_file.fileName();
m_readyToInstall = true;
qDebug("Update file contents was successfuly saved."); }
m_updateFilePath = output_file.fileName(); else {
m_readyToInstall = true; 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 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.");
else { }
qDebug("Cannot save downloaded update file because no TEMP directory is available."); }
}
} void FormUpdate::loadAvailableFiles() {
m_ui->m_listFiles->clear();
void FormUpdate::loadAvailableFiles() {
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(")"));
foreach (const UpdateUrl &url, m_updateInfo.m_urls) { item->setData(Qt::UserRole, url.m_fileUrl);
QListWidgetItem *item = new QListWidgetItem(url.m_name + tr(" (size ") + url.m_size + QSL(")")); item->setToolTip(url.m_fileUrl);
item->setData(Qt::UserRole, url.m_fileUrl); m_ui->m_listFiles->addItem(item);
item->setToolTip(url.m_fileUrl); }
m_ui->m_listFiles->addItem(item);
} if (m_ui->m_listFiles->count() > 0) {
m_ui->m_listFiles->setCurrentRow(0);
if (m_ui->m_listFiles->count() > 0) { }
m_ui->m_listFiles->setCurrentRow(0);
} else {
else { m_btnUpdate->setEnabled(false);
m_btnUpdate->setEnabled(false); }
}
m_ui->m_tabInfo->addTab(m_ui->tabFiles, tr("Available update files"));
m_ui->m_tabInfo->addTab(m_ui->tabFiles, tr("Available update files")); m_ui->m_tabInfo->setCurrentIndex(1);
m_ui->m_tabInfo->setCurrentIndex(1); }
}
void FormUpdate::updateCompleted(QNetworkReply::NetworkError status, QByteArray contents) {
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) {
switch (status) { case QNetworkReply::NoError:
case QNetworkReply::NoError: saveUpdateFile(contents);
saveUpdateFile(contents); m_ui->m_lblStatus->setStatus(WidgetWithStatus::Ok, tr("Downloaded successfully"), tr("Package was downloaded successfully.\nYou can install it now."));
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->setText(tr("Install")); m_btnUpdate->setEnabled(true);
m_btnUpdate->setEnabled(true); break;
break;
default:
default: m_ui->m_lblStatus->setStatus(WidgetWithStatus::Error, tr("Error occured"), tr("Error occured during downloading of the package."));
m_ui->m_lblStatus->setStatus(WidgetWithStatus::Error, tr("Error occured"), tr("Error occured during downloading of the package.")); m_btnUpdate->setText(tr("Error occured"));
m_btnUpdate->setText(tr("Error occured")); break;
break; }
} }
}
void FormUpdate::startUpdate() {
void FormUpdate::startUpdate() { QString url_file;
QString url_file; const bool update_for_this_system = isSelfUpdateSupported();
const bool update_for_this_system = isSelfUpdateSupported();
if (update_for_this_system && m_ui->m_listFiles->currentItem() != nullptr) {
if (update_for_this_system && m_ui->m_listFiles->currentItem() != nullptr) { url_file = m_ui->m_listFiles->currentItem()->data(Qt::UserRole).toString();
url_file = m_ui->m_listFiles->currentItem()->data(Qt::UserRole).toString(); m_ui->m_listFiles->setEnabled(false);
m_ui->m_listFiles->setEnabled(false); }
}
else { else {
url_file = APP_URL; url_file = APP_URL;
} }
if (m_readyToInstall) { if (m_readyToInstall) {
close(); close();
qDebug("Preparing to launch external installer '%s'.", qPrintable(QDir::toNativeSeparators(m_updateFilePath))); qDebug("Preparing to launch external installer '%s'.", qPrintable(QDir::toNativeSeparators(m_updateFilePath)));
#if defined(Q_OS_WIN)
#if defined(Q_OS_WIN) HINSTANCE exec_result = ShellExecute(nullptr,
HINSTANCE exec_result = ShellExecute(nullptr, nullptr,
nullptr, reinterpret_cast<const WCHAR*>(QDir::toNativeSeparators(m_updateFilePath).utf16()),
reinterpret_cast<const WCHAR*>(QDir::toNativeSeparators(m_updateFilePath).utf16()), nullptr,
nullptr, nullptr,
nullptr, SW_NORMAL);
SW_NORMAL);
if (((int)exec_result) <= 32) {
if (((int)exec_result) <= 32) { qDebug("External updater was not launched due to error.");
qDebug("External updater was not launched due to error."); qApp->showGuiMessage(tr("Cannot update application"),
tr("Cannot launch external updater. Update application manually."),
qApp->showGuiMessage(tr("Cannot update application"), QSystemTrayIcon::Warning, this);
tr("Cannot launch external updater. Update application manually."), }
QSystemTrayIcon::Warning, this);
} else {
else { qApp->quit();
qApp->quit(); }
}
#endif #endif
} }
else if (update_for_this_system) {
// Nothing is downloaded yet, but update for this system else if (update_for_this_system) {
// is available and self-update feature is present. // Nothing is downloaded yet, but update for this system
// is available and self-update feature is present.
if (m_downloader == nullptr) { if (m_downloader == nullptr) {
// Initialie downloader. // Initialie downloader.
m_downloader = new Downloader(this); m_downloader = new Downloader(this);
connect(m_downloader, &Downloader::progress, this, &FormUpdate::updateProgress);
connect(m_downloader, &Downloader::progress, this, &FormUpdate::updateProgress); connect(m_downloader, &Downloader::completed, this, &FormUpdate::updateCompleted);
connect(m_downloader, &Downloader::completed, this, &FormUpdate::updateCompleted); updateProgress(0, 100);
updateProgress(0, 100); }
}
m_btnUpdate->setText(tr("Downloading update..."));
m_btnUpdate->setText(tr("Downloading update...")); m_btnUpdate->setEnabled(false);
m_btnUpdate->setEnabled(false); m_downloader->downloadFile(url_file);
m_downloader->downloadFile(url_file); }
}
else { else {
// Self-update and package are not available. // Self-update and package are not available.
if (!WebFactory::instance()->openUrlInExternalBrowser(url_file)) { if (!WebFactory::instance()->openUrlInExternalBrowser(url_file)) {
qApp->showGuiMessage(tr("Cannot update application"), qApp->showGuiMessage(tr("Cannot update application"),
tr("Cannot navigate to installation file. Check new installation downloads manually on project website."), tr("Cannot navigate to installation file. Check new installation downloads manually on project website."),
QSystemTrayIcon::Warning, QSystemTrayIcon::Warning,
this, true); this, true);
} }
} }
} }

View file

@ -1,66 +1,66 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FORMUPDATE_H #ifndef FORMUPDATE_H
#define FORMUPDATE_H #define FORMUPDATE_H
#include <QDialog> #include <QDialog>
#include "ui_formupdate.h" #include "ui_formupdate.h"
#include "miscellaneous/systemfactory.h" #include "miscellaneous/systemfactory.h"
#include <QPushButton> #include <QPushButton>
#include <QNetworkReply> #include <QNetworkReply>
class Downloader; class Downloader;
class FormUpdate : public QDialog { class FormUpdate : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FormUpdate(QWidget *parent = 0); explicit FormUpdate(QWidget* parent = 0);
virtual ~FormUpdate(); virtual ~FormUpdate();
// Returns true if application can self-update // Returns true if application can self-update
// on current platform. // on current platform.
bool isSelfUpdateSupported() const; bool isSelfUpdateSupported() const;
private slots: private slots:
// Check for updates and interprets the results. // Check for updates and interprets the results.
void checkForUpdates(); void checkForUpdates();
void startUpdate(); void startUpdate();
void updateProgress(qint64 bytes_received, qint64 bytes_total); void updateProgress(qint64 bytes_received, qint64 bytes_total);
void updateCompleted(QNetworkReply::NetworkError status, QByteArray contents); void updateCompleted(QNetworkReply::NetworkError status, QByteArray contents);
void saveUpdateFile(const QByteArray &file_contents); void saveUpdateFile(const QByteArray& file_contents);
private: private:
void loadAvailableFiles(); void loadAvailableFiles();
Downloader *m_downloader; Downloader* m_downloader;
bool m_readyToInstall; bool m_readyToInstall;
QString m_updateFilePath; QString m_updateFilePath;
QScopedPointer<Ui::FormUpdate> m_ui; QScopedPointer<Ui::FormUpdate> m_ui;
UpdateInfo m_updateInfo; UpdateInfo m_updateInfo;
QPushButton *m_btnUpdate; QPushButton* m_btnUpdate;
qint64 m_lastDownloadedBytes; qint64 m_lastDownloadedBytes;
}; };
#endif // FORMUPDATE_H #endif // FORMUPDATE_H

View file

@ -1,93 +1,93 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/discoverfeedsbutton.h" #include "gui/discoverfeedsbutton.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "miscellaneous/feedreader.h" #include "miscellaneous/feedreader.h"
#include "gui/dialogs/formmain.h" #include "gui/dialogs/formmain.h"
#include "gui/tabwidget.h" #include "gui/tabwidget.h"
#include "gui/feedmessageviewer.h" #include "gui/feedmessageviewer.h"
#include "gui/feedsview.h" #include "gui/feedsview.h"
#include "core/feedsmodel.h" #include "core/feedsmodel.h"
#include "services/abstract/serviceroot.h" #include "services/abstract/serviceroot.h"
#include <QVariant> #include <QVariant>
DiscoverFeedsButton::DiscoverFeedsButton(QWidget *parent) : QToolButton(parent), m_addresses(QStringList()) { DiscoverFeedsButton::DiscoverFeedsButton(QWidget* parent) : QToolButton(parent), m_addresses(QStringList()) {
setEnabled(false); setEnabled(false);
setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml"))); setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml")));
setPopupMode(QToolButton::InstantPopup); setPopupMode(QToolButton::InstantPopup);
} }
DiscoverFeedsButton::~DiscoverFeedsButton() { DiscoverFeedsButton::~DiscoverFeedsButton() {
} }
void DiscoverFeedsButton::clearFeedAddresses() { void DiscoverFeedsButton::clearFeedAddresses() {
setFeedAddresses(QStringList()); setFeedAddresses(QStringList());
} }
void DiscoverFeedsButton::setFeedAddresses(const QStringList &addresses) { void DiscoverFeedsButton::setFeedAddresses(const QStringList& addresses) {
setEnabled(!addresses.isEmpty()); setEnabled(!addresses.isEmpty());
setToolTip(addresses.isEmpty() ? setToolTip(addresses.isEmpty() ?
tr("This website does not contain any feeds.") : 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())); tr("Click me to add feeds from this website.\nThis website contains %n feed(s).", 0, addresses.size()));
if (menu() == nullptr) { if (menu() == nullptr) {
// Initialize the menu. // Initialize the menu.
setMenu(new QMenu(this)); setMenu(new QMenu(this));
connect(menu(), &QMenu::triggered, this, &DiscoverFeedsButton::linkTriggered); connect(menu(), &QMenu::triggered, this, &DiscoverFeedsButton::linkTriggered);
connect(menu(), &QMenu::aboutToShow, this, &DiscoverFeedsButton::fillMenu); connect(menu(), &QMenu::aboutToShow, this, &DiscoverFeedsButton::fillMenu);
} }
menu()->hide(); menu()->hide();
m_addresses = addresses; m_addresses = addresses;
} }
void DiscoverFeedsButton::linkTriggered(QAction *action) { void DiscoverFeedsButton::linkTriggered(QAction* action) {
const QString url = action->property("url").toString(); const QString url = action->property("url").toString();
ServiceRoot *root = static_cast<ServiceRoot*>(action->property("root").value<void*>()); ServiceRoot* root = static_cast<ServiceRoot*>(action->property("root").value<void*>());
if (root->supportsFeedAdding()) { if (root->supportsFeedAdding()) {
root->addNewFeed(url); root->addNewFeed(url);
} }
else {
qApp->showGuiMessage(tr("Not supported"), else {
tr("Given account does not support adding feeds."), qApp->showGuiMessage(tr("Not supported"),
QSystemTrayIcon::Warning, tr("Given account does not support adding feeds."),
qApp->mainFormWidget(), true); QSystemTrayIcon::Warning,
} qApp->mainFormWidget(), true);
} }
}
void DiscoverFeedsButton::fillMenu() {
menu()->clear(); void DiscoverFeedsButton::fillMenu() {
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()) { foreach (const QString& url, m_addresses) {
QAction *url_action = root_menu->addAction(root->icon(), url); if (root->supportsFeedAdding()) {
QAction* url_action = root_menu->addAction(root->icon(), url);
url_action->setProperty("url", url); url_action->setProperty("url", url);
url_action->setProperty("root", QVariant::fromValue((void*) root)); url_action->setProperty("root", QVariant::fromValue((void*) root));
} }
} }
} }
} }

View file

@ -1,45 +1,45 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef DISCOVERFEEDSBUTTON_H #ifndef DISCOVERFEEDSBUTTON_H
#define DISCOVERFEEDSBUTTON_H #define DISCOVERFEEDSBUTTON_H
#include <QToolButton> #include <QToolButton>
class DiscoverFeedsButton : public QToolButton { class DiscoverFeedsButton : public QToolButton {
Q_OBJECT Q_OBJECT
public: public:
// Constructors. // Constructors.
explicit DiscoverFeedsButton(QWidget *parent = 0); explicit DiscoverFeedsButton(QWidget* parent = 0);
virtual ~DiscoverFeedsButton(); virtual ~DiscoverFeedsButton();
// Feed addresses manipulators. // Feed addresses manipulators.
void clearFeedAddresses(); void clearFeedAddresses();
void setFeedAddresses(const QStringList &addresses); void setFeedAddresses(const QStringList& addresses);
private slots: private slots:
// User chose any of addresses. // User chose any of addresses.
void linkTriggered(QAction *action); void linkTriggered(QAction* action);
void fillMenu(); void fillMenu();
private: private:
QStringList m_addresses; QStringList m_addresses;
}; };
#endif // DISCOVERFEEDSBUTTON_H #endif // DISCOVERFEEDSBUTTON_H

View file

@ -20,49 +20,50 @@
#include <QKeyEvent> #include <QKeyEvent>
EditTableView::EditTableView(QWidget *parent) : QTableView(parent) { EditTableView::EditTableView(QWidget* parent) : QTableView(parent) {
} }
void EditTableView::keyPressEvent(QKeyEvent *event) { void EditTableView::keyPressEvent(QKeyEvent* event) {
if (model() && event->key() == Qt::Key_Delete) { if (model() && event->key() == Qt::Key_Delete) {
removeSelected(); removeSelected();
event->accept(); event->accept();
} }
else {
QAbstractItemView::keyPressEvent(event); else {
} QAbstractItemView::keyPressEvent(event);
}
} }
void EditTableView::removeSelected() { void EditTableView::removeSelected() {
if (!model() || !selectionModel() || !selectionModel()->hasSelection()) { if (!model() || !selectionModel() || !selectionModel()->hasSelection()) {
return; return;
} }
const QModelIndexList selected_rows = selectionModel()->selectedRows(); const QModelIndexList selected_rows = selectionModel()->selectedRows();
if (selected_rows.isEmpty()) { if (selected_rows.isEmpty()) {
return; 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--) { for (int i = selected_rows.count() - 1; i >= 0; i--) {
QModelIndex idx = selected_rows.at(i); QModelIndex idx = selected_rows.at(i);
model()->removeRow(idx.row(), rootIndex()); model()->removeRow(idx.row(), rootIndex());
} }
QModelIndex new_selected_index = model()->index(new_selected_row, 0, rootIndex()); QModelIndex new_selected_index = model()->index(new_selected_row, 0, rootIndex());
if (!new_selected_index.isValid()) { if (!new_selected_index.isValid()) {
new_selected_index = model()->index(new_selected_row - 1, 0, rootIndex()); new_selected_index = model()->index(new_selected_row - 1, 0, rootIndex());
} }
selectionModel()->select(new_selected_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows); selectionModel()->select(new_selected_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
setCurrentIndex(new_selected_index); setCurrentIndex(new_selected_index);
} }
void EditTableView::removeAll() { void EditTableView::removeAll() {
if (model() != nullptr) { if (model() != nullptr) {
model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex()); model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex());
} }
} }

View file

@ -22,17 +22,17 @@
class EditTableView : public QTableView { class EditTableView : public QTableView {
Q_OBJECT Q_OBJECT
public: public:
explicit EditTableView(QWidget *parent = 0); explicit EditTableView(QWidget* parent = 0);
public slots: public slots:
void removeSelected(); void removeSelected();
void removeAll(); void removeAll();
private: private:
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent* event);
}; };
#endif // EDITTABLEVIEW_H #endif // EDITTABLEVIEW_H

View file

@ -63,240 +63,220 @@
#include <QPointer> #include <QPointer>
FeedMessageViewer::FeedMessageViewer(QWidget *parent) FeedMessageViewer::FeedMessageViewer(QWidget* parent)
: TabContent(parent), : TabContent(parent),
m_toolBarsEnabled(true), m_toolBarsEnabled(true),
m_listHeadersEnabled(true), m_listHeadersEnabled(true),
m_toolBarFeeds(new FeedsToolBar(tr("Toolbar for feeds"), this)), m_toolBarFeeds(new FeedsToolBar(tr("Toolbar for feeds"), this)),
m_toolBarMessages(new MessagesToolBar(tr("Toolbar for messages"), this)), m_toolBarMessages(new MessagesToolBar(tr("Toolbar for messages"), this)),
m_messagesView(new MessagesView(this)), m_messagesView(new MessagesView(this)),
m_feedsView(new FeedsView(this)), m_feedsView(new FeedsView(this)),
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
m_messagesBrowser(new WebBrowser(this)) { m_messagesBrowser(new WebBrowser(this)) {
#else #else
m_messagesBrowser(new MessagePreviewer(this)) { m_messagesBrowser(new MessagePreviewer(this)) {
#endif #endif
initialize(); initialize();
initializeViews(); initializeViews();
loadMessageViewerFonts(); loadMessageViewerFonts();
createConnections(); createConnections();
} }
FeedMessageViewer::~FeedMessageViewer() { FeedMessageViewer::~FeedMessageViewer() {
qDebug("Destroying FeedMessageViewer instance."); qDebug("Destroying FeedMessageViewer instance.");
} }
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
WebBrowser *FeedMessageViewer::webBrowser() const { WebBrowser* FeedMessageViewer::webBrowser() const {
return m_messagesBrowser; return m_messagesBrowser;
} }
#endif #endif
FeedsView *FeedMessageViewer::feedsView() const { FeedsView* FeedMessageViewer::feedsView() const {
return m_feedsView; return m_feedsView;
} }
MessagesView *FeedMessageViewer::messagesView() const { MessagesView* FeedMessageViewer::messagesView() const {
return m_messagesView; return m_messagesView;
} }
MessagesToolBar *FeedMessageViewer::messagesToolBar() const { MessagesToolBar* FeedMessageViewer::messagesToolBar() const {
return m_toolBarMessages; return m_toolBarMessages;
} }
FeedsToolBar *FeedMessageViewer::feedsToolBar() const { FeedsToolBar* FeedMessageViewer::feedsToolBar() const {
return m_toolBarFeeds; return m_toolBarFeeds;
} }
void FeedMessageViewer::saveSize() { void FeedMessageViewer::saveSize() {
Settings *settings = qApp->settings(); Settings* settings = qApp->settings();
m_feedsView->saveAllExpandStates();
m_feedsView->saveAllExpandStates(); // Store offsets of splitters.
settings->setValue(GROUP(GUI), GUI::SplitterFeeds, QString(m_feedSplitter->saveState().toBase64()));
settings->setValue(GROUP(GUI), GUI::SplitterMessages, QString(m_messageSplitter->saveState().toBase64()));
// Store offsets of splitters. settings->setValue(GROUP(GUI), GUI::MessageViewState, QString(m_messagesView->header()->saveState().toBase64()));
settings->setValue(GROUP(GUI), GUI::SplitterFeeds, QString(m_feedSplitter->saveState().toBase64())); // Store "visibility" of toolbars and list headers.
settings->setValue(GROUP(GUI), GUI::SplitterMessages, QString(m_messageSplitter->saveState().toBase64())); settings->setValue(GROUP(GUI), GUI::ToolbarsVisible, m_toolBarsEnabled);
settings->setValue(GROUP(GUI), GUI::MessageViewState, QString(m_messagesView->header()->saveState().toBase64())); settings->setValue(GROUP(GUI), GUI::ListHeadersVisible, m_listHeadersEnabled);
// Store "visibility" of toolbars and list headers.
settings->setValue(GROUP(GUI), GUI::ToolbarsVisible, m_toolBarsEnabled);
settings->setValue(GROUP(GUI), GUI::ListHeadersVisible, m_listHeadersEnabled);
} }
void FeedMessageViewer::loadSize() { void FeedMessageViewer::loadSize() {
const Settings *settings = qApp->settings(); const Settings* settings = qApp->settings();
// Restore offsets of splitters.
// Restore offsets of splitters. m_feedSplitter->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::SplitterFeeds)).toString().toLocal8Bit()));
m_feedSplitter->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::SplitterFeeds)).toString().toLocal8Bit())); m_messageSplitter->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::SplitterMessages)).toString().toLocal8Bit()));
m_messageSplitter->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::SplitterMessages)).toString().toLocal8Bit())); m_messagesView->header()->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::MessageViewState)).toString().toLocal8Bit()));
m_messagesView->header()->restoreState(QByteArray::fromBase64(settings->value(GROUP(GUI), SETTING(GUI::MessageViewState)).toString().toLocal8Bit()));
} }
void FeedMessageViewer::loadMessageViewerFonts() { void FeedMessageViewer::loadMessageViewerFonts() {
m_messagesBrowser->reloadFontSettings(); m_messagesBrowser->reloadFontSettings();
} }
bool FeedMessageViewer::areToolBarsEnabled() const { bool FeedMessageViewer::areToolBarsEnabled() const {
return m_toolBarsEnabled; return m_toolBarsEnabled;
} }
bool FeedMessageViewer::areListHeadersEnabled() const { bool FeedMessageViewer::areListHeadersEnabled() const {
return m_listHeadersEnabled; return m_listHeadersEnabled;
} }
void FeedMessageViewer::switchMessageSplitterOrientation() { void FeedMessageViewer::switchMessageSplitterOrientation() {
if (m_messageSplitter->orientation() == Qt::Vertical) { if (m_messageSplitter->orientation() == Qt::Vertical) {
m_messageSplitter->setOrientation(Qt::Horizontal); m_messageSplitter->setOrientation(Qt::Horizontal);
} }
else {
m_messageSplitter->setOrientation(Qt::Vertical); else {
} m_messageSplitter->setOrientation(Qt::Vertical);
}
} }
void FeedMessageViewer::setToolBarsEnabled(bool enable) { void FeedMessageViewer::setToolBarsEnabled(bool enable) {
m_toolBarsEnabled = enable; m_toolBarsEnabled = enable;
m_toolBarFeeds->setVisible(enable); m_toolBarFeeds->setVisible(enable);
m_toolBarMessages->setVisible(enable); m_toolBarMessages->setVisible(enable);
} }
void FeedMessageViewer::setListHeadersEnabled(bool enable) { void FeedMessageViewer::setListHeadersEnabled(bool enable) {
m_listHeadersEnabled = enable; m_listHeadersEnabled = enable;
m_feedsView->header()->setVisible(enable); m_feedsView->header()->setVisible(enable);
m_messagesView->header()->setVisible(enable); m_messagesView->header()->setVisible(enable);
} }
void FeedMessageViewer::switchFeedComponentVisibility() { void FeedMessageViewer::switchFeedComponentVisibility() {
QAction *sen = qobject_cast<QAction*>(sender()); QAction* sen = qobject_cast<QAction*>(sender());
if (sen != nullptr) { if (sen != nullptr) {
m_feedsWidget->setVisible(sen->isChecked()); m_feedsWidget->setVisible(sen->isChecked());
} }
else {
m_feedsWidget->setVisible(!m_feedsWidget->isVisible()); else {
} m_feedsWidget->setVisible(!m_feedsWidget->isVisible());
}
} }
void FeedMessageViewer::toggleShowOnlyUnreadFeeds() { void FeedMessageViewer::toggleShowOnlyUnreadFeeds() {
const QAction *origin = qobject_cast<QAction*>(sender()); const QAction* origin = qobject_cast<QAction*>(sender());
if (origin == nullptr) { if (origin == nullptr) {
m_feedsView->model()->invalidateReadFeedsFilter(true, false); m_feedsView->model()->invalidateReadFeedsFilter(true, false);
} }
else {
m_feedsView->model()->invalidateReadFeedsFilter(true, origin->isChecked()); else {
} m_feedsView->model()->invalidateReadFeedsFilter(true, origin->isChecked());
}
} }
void FeedMessageViewer::createConnections() { void FeedMessageViewer::createConnections() {
// Filtering & searching. // Filtering & searching.
connect(m_toolBarMessages, &MessagesToolBar::messageSearchPatternChanged, m_messagesView, &MessagesView::searchMessages); connect(m_toolBarMessages, &MessagesToolBar::messageSearchPatternChanged, m_messagesView, &MessagesView::searchMessages);
connect(m_toolBarMessages, &MessagesToolBar::messageFilterChanged, m_messagesView, &MessagesView::filterMessages); connect(m_toolBarMessages, &MessagesToolBar::messageFilterChanged, m_messagesView, &MessagesView::filterMessages);
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
connect(m_messagesView, &MessagesView::currentMessageRemoved, m_messagesBrowser, &WebBrowser::clear); connect(m_messagesView, &MessagesView::currentMessageRemoved, m_messagesBrowser, &WebBrowser::clear);
connect(m_messagesView, &MessagesView::currentMessageChanged, m_messagesBrowser, &WebBrowser::loadMessage); connect(m_messagesView, &MessagesView::currentMessageChanged, m_messagesBrowser, &WebBrowser::loadMessage);
connect(m_messagesBrowser, &WebBrowser::markMessageRead, connect(m_messagesBrowser, &WebBrowser::markMessageRead,
m_messagesView->sourceModel(), &MessagesModel::setMessageReadById); m_messagesView->sourceModel(), &MessagesModel::setMessageReadById);
connect(m_messagesBrowser, &WebBrowser::markMessageImportant, connect(m_messagesBrowser, &WebBrowser::markMessageImportant,
m_messagesView->sourceModel(), &MessagesModel::setMessageImportantById); m_messagesView->sourceModel(), &MessagesModel::setMessageImportantById);
#else #else
connect(m_messagesView, &MessagesView::currentMessageRemoved, m_messagesBrowser, &MessagePreviewer::clear); connect(m_messagesView, &MessagesView::currentMessageRemoved, m_messagesBrowser, &MessagePreviewer::clear);
connect(m_messagesView, &MessagesView::currentMessageChanged, m_messagesBrowser, &MessagePreviewer::loadMessage); connect(m_messagesView, &MessagesView::currentMessageChanged, m_messagesBrowser, &MessagePreviewer::loadMessage);
connect(m_messagesBrowser, &MessagePreviewer::markMessageRead, connect(m_messagesBrowser, &MessagePreviewer::markMessageRead,
m_messagesView->sourceModel(), &MessagesModel::setMessageReadById); m_messagesView->sourceModel(), &MessagesModel::setMessageReadById);
connect(m_messagesBrowser, &MessagePreviewer::markMessageImportant, connect(m_messagesBrowser, &MessagePreviewer::markMessageImportant,
m_messagesView->sourceModel(), &MessagesModel::setMessageImportantById); m_messagesView->sourceModel(), &MessagesModel::setMessageImportantById);
#endif #endif
// If user selects feeds, load their messages.
// If user selects feeds, load their messages. connect(m_feedsView, &FeedsView::itemSelected, m_messagesView, &MessagesView::loadItem);
connect(m_feedsView, &FeedsView::itemSelected, m_messagesView, &MessagesView::loadItem); // State of many messages is changed, then we need
// to reload selections.
// State of many messages is changed, then we need connect(m_feedsView->sourceModel(), &FeedsModel::reloadMessageListRequested,
// to reload selections. m_messagesView, &MessagesView::reloadSelections);
connect(m_feedsView->sourceModel(), &FeedsModel::reloadMessageListRequested,
m_messagesView, &MessagesView::reloadSelections);
} }
void FeedMessageViewer::initialize() { void FeedMessageViewer::initialize() {
// Initialize/populate toolbars. // Initialize/populate toolbars.
m_toolBarFeeds->setFloatable(false); m_toolBarFeeds->setFloatable(false);
m_toolBarFeeds->setMovable(false); m_toolBarFeeds->setMovable(false);
m_toolBarFeeds->setAllowedAreas(Qt::TopToolBarArea); m_toolBarFeeds->setAllowedAreas(Qt::TopToolBarArea);
m_toolBarMessages->setFloatable(false);
m_toolBarMessages->setFloatable(false); m_toolBarMessages->setMovable(false);
m_toolBarMessages->setMovable(false); m_toolBarMessages->setAllowedAreas(Qt::TopToolBarArea);
m_toolBarMessages->setAllowedAreas(Qt::TopToolBarArea); m_toolBarFeeds->loadSavedActions();
m_toolBarMessages->loadSavedActions();
m_toolBarFeeds->loadSavedActions(); m_messagesBrowser->clear();
m_toolBarMessages->loadSavedActions(); // Now refresh visual setup.
refreshVisualProperties();
m_messagesBrowser->clear();
// Now refresh visual setup.
refreshVisualProperties();
} }
void FeedMessageViewer::initializeViews() { void FeedMessageViewer::initializeViews() {
m_feedsWidget = new QWidget(this); m_feedsWidget = new QWidget(this);
m_messagesWidget = new QWidget(this); m_messagesWidget = new QWidget(this);
m_feedSplitter = new QSplitter(Qt::Horizontal, this); m_feedSplitter = new QSplitter(Qt::Horizontal, this);
m_messageSplitter = new QSplitter(Qt::Vertical, this); m_messageSplitter = new QSplitter(Qt::Vertical, this);
// Instantiate needed components.
// Instantiate needed components. QVBoxLayout* central_layout = new QVBoxLayout(this);
QVBoxLayout *central_layout = new QVBoxLayout(this); QVBoxLayout* feed_layout = new QVBoxLayout(m_feedsWidget);
QVBoxLayout *feed_layout = new QVBoxLayout(m_feedsWidget); QVBoxLayout* message_layout = new QVBoxLayout(m_messagesWidget);
QVBoxLayout *message_layout = new QVBoxLayout(m_messagesWidget); // Set layout properties.
central_layout->setMargin(0);
// Set layout properties. central_layout->setSpacing(0);
central_layout->setMargin(0); feed_layout->setMargin(0);
central_layout->setSpacing(0); feed_layout->setSpacing(0);
feed_layout->setMargin(0); message_layout->setMargin(0);
feed_layout->setSpacing(0); message_layout->setSpacing(0);
message_layout->setMargin(0); // Set views.
message_layout->setSpacing(0); m_feedsView->setFrameStyle(QFrame::NoFrame);
m_messagesView->setFrameStyle(QFrame::NoFrame);
// Set views. // Setup message splitter.
m_feedsView->setFrameStyle(QFrame::NoFrame); m_messageSplitter->setObjectName(QSL("MessageSplitter"));
m_messagesView->setFrameStyle(QFrame::NoFrame); m_messageSplitter->setHandleWidth(1);
m_messageSplitter->setOpaqueResize(false);
// Setup message splitter. m_messageSplitter->setChildrenCollapsible(false);
m_messageSplitter->setObjectName(QSL("MessageSplitter")); m_messageSplitter->addWidget(m_messagesView);
m_messageSplitter->setHandleWidth(1); m_messageSplitter->addWidget(m_messagesBrowser);
m_messageSplitter->setOpaqueResize(false); // Assemble message-related components to single widget.
m_messageSplitter->setChildrenCollapsible(false); message_layout->addWidget(m_toolBarMessages);
m_messageSplitter->addWidget(m_messagesView); message_layout->addWidget(m_messageSplitter);
m_messageSplitter->addWidget(m_messagesBrowser); // Assemble feed-related components to another widget.
feed_layout->addWidget(m_toolBarFeeds);
// Assemble message-related components to single widget. feed_layout->addWidget(m_feedsView);
message_layout->addWidget(m_toolBarMessages); // Assembler everything together.
message_layout->addWidget(m_messageSplitter); m_feedSplitter->setHandleWidth(1);
m_feedSplitter->setOpaqueResize(false);
// Assemble feed-related components to another widget. m_feedSplitter->setChildrenCollapsible(false);
feed_layout->addWidget(m_toolBarFeeds); m_feedSplitter->addWidget(m_feedsWidget);
feed_layout->addWidget(m_feedsView); m_feedSplitter->addWidget(m_messagesWidget);
// Add toolbar and main feeds/messages widget to main layout.
// Assembler everything together. central_layout->addWidget(m_feedSplitter);
m_feedSplitter->setHandleWidth(1); setTabOrder(m_feedsView, m_messagesView);
m_feedSplitter->setOpaqueResize(false); setTabOrder(m_messagesView, m_toolBarFeeds);
m_feedSplitter->setChildrenCollapsible(false); setTabOrder(m_toolBarFeeds, m_toolBarMessages);
m_feedSplitter->addWidget(m_feedsWidget); setTabOrder(m_toolBarMessages, m_messagesBrowser);
m_feedSplitter->addWidget(m_messagesWidget);
// Add toolbar and main feeds/messages widget to main layout.
central_layout->addWidget(m_feedSplitter);
setTabOrder(m_feedsView, m_messagesView);
setTabOrder(m_messagesView, m_toolBarFeeds);
setTabOrder(m_toolBarFeeds, m_toolBarMessages);
setTabOrder(m_toolBarMessages, m_messagesBrowser);
} }
void FeedMessageViewer::refreshVisualProperties() { void FeedMessageViewer::refreshVisualProperties() {
const Qt::ToolButtonStyle button_style = static_cast<Qt::ToolButtonStyle>(qApp->settings()->value(GROUP(GUI), const Qt::ToolButtonStyle button_style = static_cast<Qt::ToolButtonStyle>(qApp->settings()->value(GROUP(GUI),
SETTING(GUI::ToolbarStyle)).toInt()); SETTING(GUI::ToolbarStyle)).toInt());
m_toolBarFeeds->setToolButtonStyle(button_style);
m_toolBarFeeds->setToolButtonStyle(button_style); m_toolBarMessages->setToolButtonStyle(button_style);
m_toolBarMessages->setToolButtonStyle(button_style);
} }

View file

@ -41,79 +41,79 @@ class QSplitter;
class QProgressBar; class QProgressBar;
class FeedMessageViewer : public TabContent { class FeedMessageViewer : public TabContent {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedMessageViewer(QWidget *parent = 0); explicit FeedMessageViewer(QWidget* parent = 0);
virtual ~FeedMessageViewer(); virtual ~FeedMessageViewer();
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
WebBrowser *webBrowser() const; WebBrowser* webBrowser() const;
#endif #endif
FeedsView *feedsView() const; FeedsView* feedsView() const;
MessagesView *messagesView() const; MessagesView* messagesView() const;
MessagesToolBar *messagesToolBar() const; MessagesToolBar* messagesToolBar() const;
FeedsToolBar *feedsToolBar() const; FeedsToolBar* feedsToolBar() const;
bool areToolBarsEnabled() const; bool areToolBarsEnabled() const;
bool areListHeadersEnabled() const; bool areListHeadersEnabled() const;
public slots: public slots:
// Loads/saves sizes and states of ALL // Loads/saves sizes and states of ALL
// underlying widgets, this contains primarily // underlying widgets, this contains primarily
// splitters, toolbar and views. // splitters, toolbar and views.
void saveSize(); void saveSize();
void loadSize(); void loadSize();
void loadMessageViewerFonts(); void loadMessageViewerFonts();
// Switches orientation horizontal/vertical. // Switches orientation horizontal/vertical.
void switchMessageSplitterOrientation(); void switchMessageSplitterOrientation();
// Enables/disables main toolbars or list headers. // Enables/disables main toolbars or list headers.
void setToolBarsEnabled(bool enable); void setToolBarsEnabled(bool enable);
void setListHeadersEnabled(bool enable); void setListHeadersEnabled(bool enable);
// Reloads some changeable visual settings. // Reloads some changeable visual settings.
void refreshVisualProperties(); void refreshVisualProperties();
// Switches visibility of feed list and related // Switches visibility of feed list and related
// toolbar. // toolbar.
void switchFeedComponentVisibility(); void switchFeedComponentVisibility();
// Toggles displayed feeds. // Toggles displayed feeds.
void toggleShowOnlyUnreadFeeds(); void toggleShowOnlyUnreadFeeds();
protected: protected:
// Initializes some properties of the widget. // Initializes some properties of the widget.
void initialize(); void initialize();
// Initializes both messages/feeds views. // Initializes both messages/feeds views.
void initializeViews(); void initializeViews();
// Sets up connections. // Sets up connections.
void createConnections(); void createConnections();
private: private:
bool m_toolBarsEnabled; bool m_toolBarsEnabled;
bool m_listHeadersEnabled; bool m_listHeadersEnabled;
FeedsToolBar *m_toolBarFeeds; FeedsToolBar* m_toolBarFeeds;
MessagesToolBar *m_toolBarMessages; MessagesToolBar* m_toolBarMessages;
QSplitter *m_feedSplitter; QSplitter* m_feedSplitter;
QSplitter *m_messageSplitter; QSplitter* m_messageSplitter;
MessagesView *m_messagesView; MessagesView* m_messagesView;
FeedsView *m_feedsView; FeedsView* m_feedsView;
QWidget *m_feedsWidget; QWidget* m_feedsWidget;
QWidget *m_messagesWidget; QWidget* m_messagesWidget;
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
WebBrowser *m_messagesBrowser; WebBrowser* m_messagesBrowser;
#else #else
MessagePreviewer *m_messagesBrowser; MessagePreviewer* m_messagesBrowser;
#endif #endif
}; };

View file

@ -1,105 +1,102 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/feedstoolbar.h" #include "gui/feedstoolbar.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/settings.h" #include "miscellaneous/settings.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include <QWidgetAction> #include <QWidgetAction>
FeedsToolBar::FeedsToolBar(const QString &title, QWidget *parent) : BaseToolBar(title, parent) { FeedsToolBar::FeedsToolBar(const QString& title, QWidget* parent) : BaseToolBar(title, parent) {
// Update right margin of filter textbox. // Update right margin of filter textbox.
QMargins margins = contentsMargins(); QMargins margins = contentsMargins();
margins.setRight(margins.right() + FILTER_RIGHT_MARGIN); margins.setRight(margins.right() + FILTER_RIGHT_MARGIN);
setContentsMargins(margins); setContentsMargins(margins);
} }
FeedsToolBar::~FeedsToolBar() { FeedsToolBar::~FeedsToolBar() {
} }
QList<QAction*> FeedsToolBar::availableActions() const { QList<QAction*> FeedsToolBar::availableActions() const {
return qApp->userActions(); return qApp->userActions();
} }
QList<QAction*> FeedsToolBar::changeableActions() const { QList<QAction*> FeedsToolBar::changeableActions() const {
return actions(); return actions();
} }
void FeedsToolBar::saveChangeableActions(const QStringList &actions) { void FeedsToolBar::saveChangeableActions(const QStringList& actions) {
qApp->settings()->setValue(GROUP(GUI), GUI::FeedsToolbarActions, actions.join(QSL(","))); qApp->settings()->setValue(GROUP(GUI), GUI::FeedsToolbarActions, actions.join(QSL(",")));
loadSpecificActions(getSpecificActions(actions)); loadSpecificActions(getSpecificActions(actions));
} }
QList<QAction*> FeedsToolBar::getSpecificActions(const QStringList &actions) { QList<QAction*> FeedsToolBar::getSpecificActions(const QStringList& actions) {
QList<QAction*> available_actions = availableActions(); QList<QAction*> available_actions = availableActions();
QList<QAction*> spec_actions; QList<QAction*> spec_actions;
// Iterate action names and add respectable actions into the toolbar. // Iterate action names and add respectable actions into the toolbar.
foreach (const QString &action_name, actions) { foreach (const QString& action_name, actions) {
QAction *matching_action = findMatchingAction(action_name, available_actions); QAction* matching_action = findMatchingAction(action_name, available_actions);
if (matching_action != nullptr) { if (matching_action != nullptr) {
// Add existing standard action. // Add existing standard action.
spec_actions.append(matching_action); spec_actions.append(matching_action);
} }
else if (action_name == SEPARATOR_ACTION_NAME) {
// Add new separator. else if (action_name == SEPARATOR_ACTION_NAME) {
QAction *act = new QAction(this); // Add new separator.
act->setSeparator(true); QAction* act = new QAction(this);
act->setSeparator(true);
spec_actions.append(act); spec_actions.append(act);
} }
else if (action_name == SPACER_ACTION_NAME) {
// Add new spacer. else if (action_name == SPACER_ACTION_NAME) {
QWidget *spacer = new QWidget(this); // Add new spacer.
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QWidget* spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QWidgetAction *action = new QWidgetAction(this); QWidgetAction* action = new QWidgetAction(this);
action->setDefaultWidget(spacer);
action->setDefaultWidget(spacer); action->setIcon(qApp->icons()->fromTheme(QSL("system-search")));
action->setIcon(qApp->icons()->fromTheme(QSL("system-search"))); action->setProperty("type", SPACER_ACTION_NAME);
action->setProperty("type", SPACER_ACTION_NAME); action->setProperty("name", tr("Toolbar spacer"));
action->setProperty("name", tr("Toolbar spacer")); spec_actions.append(action);
}
spec_actions.append(action); }
}
} return spec_actions;
}
return spec_actions;
} void FeedsToolBar::loadSpecificActions(const QList<QAction*>& actions) {
clear();
void FeedsToolBar::loadSpecificActions(const QList<QAction*> &actions) {
clear(); foreach (QAction* act, actions) {
addAction(act);
foreach (QAction *act, actions) { }
addAction(act); }
}
} QStringList FeedsToolBar::defaultActions() const {
return QString(GUI::FeedsToolbarActionsDef).split(',',
QStringList FeedsToolBar::defaultActions() const { QString::SkipEmptyParts);
return QString(GUI::FeedsToolbarActionsDef).split(',', }
QString::SkipEmptyParts);
} QStringList FeedsToolBar::savedActions() const {
return qApp->settings()->value(GROUP(GUI), SETTING(GUI::FeedsToolbarActions)).toString().split(',',
QStringList FeedsToolBar::savedActions() const { QString::SkipEmptyParts);
return qApp->settings()->value(GROUP(GUI), SETTING(GUI::FeedsToolbarActions)).toString().split(',', }
QString::SkipEmptyParts);
}

View file

@ -1,43 +1,43 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FEEDSTOOLBAR_H #ifndef FEEDSTOOLBAR_H
#define FEEDSTOOLBAR_H #define FEEDSTOOLBAR_H
#include "gui/basetoolbar.h" #include "gui/basetoolbar.h"
class FeedsToolBar : public BaseToolBar { class FeedsToolBar : public BaseToolBar {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedsToolBar(const QString &title, QWidget *parent = 0); explicit FeedsToolBar(const QString& title, QWidget* parent = 0);
virtual ~FeedsToolBar(); virtual ~FeedsToolBar();
QList<QAction*> availableActions() const; QList<QAction*> availableActions() const;
QList<QAction*> changeableActions() const; QList<QAction*> changeableActions() const;
void saveChangeableActions(const QStringList &actions); void saveChangeableActions(const QStringList& actions);
QList<QAction*> getSpecificActions(const QStringList &actions); QList<QAction*> getSpecificActions(const QStringList& actions);
void loadSpecificActions(const QList<QAction*> &actions); void loadSpecificActions(const QList<QAction*>& actions);
QStringList defaultActions() const; QStringList defaultActions() const;
QStringList savedActions() const; QStringList savedActions() const;
}; };
#endif // FEEDSTOOLBAR_H #endif // FEEDSTOOLBAR_H

File diff suppressed because it is too large Load diff

View file

@ -1,146 +1,146 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef FEEDSVIEW_H #ifndef FEEDSVIEW_H
#define FEEDSVIEW_H #define FEEDSVIEW_H
#include <QTreeView> #include <QTreeView>
#include "core/feedsmodel.h" #include "core/feedsmodel.h"
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
class FeedsProxyModel; class FeedsProxyModel;
class Feed; class Feed;
class Category; class Category;
class FeedsView : public QTreeView { class FeedsView : public QTreeView {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedsView(QWidget *parent = 0); explicit FeedsView(QWidget* parent = 0);
virtual ~FeedsView(); virtual ~FeedsView();
// Fundamental accessors. // Fundamental accessors.
inline FeedsProxyModel *model() const { inline FeedsProxyModel* model() const {
return m_proxyModel; return m_proxyModel;
} }
inline FeedsModel *sourceModel() const { inline FeedsModel* sourceModel() const {
return m_sourceModel; return m_sourceModel;
} }
void setSortingEnabled(bool enable); void setSortingEnabled(bool enable);
// Returns list of selected/all feeds. // Returns list of selected/all feeds.
// NOTE: This is recursive method which returns all descendants. // NOTE: This is recursive method which returns all descendants.
QList<Feed*> selectedFeeds() const; QList<Feed*> selectedFeeds() const;
// Returns pointers to selected feed/category if they are really // Returns pointers to selected feed/category if they are really
// selected. // selected.
RootItem *selectedItem() const; RootItem* selectedItem() const;
// Saves/loads expand states of all nodes (feeds/categories) of the list to/from settings. // Saves/loads expand states of all nodes (feeds/categories) of the list to/from settings.
void saveAllExpandStates(); void saveAllExpandStates();
void loadAllExpandStates(); void loadAllExpandStates();
public slots: public slots:
void sortByColumn(int column, Qt::SortOrder order); void sortByColumn(int column, Qt::SortOrder order);
void addFeedIntoSelectedAccount(); void addFeedIntoSelectedAccount();
void addCategoryIntoSelectedAccount(); void addCategoryIntoSelectedAccount();
void expandCollapseCurrentItem(); void expandCollapseCurrentItem();
// Feed updating. // Feed updating.
void updateSelectedItems(); void updateSelectedItems();
// Feed read/unread manipulators. // Feed read/unread manipulators.
void markSelectedItemRead(); void markSelectedItemRead();
void markSelectedItemUnread(); void markSelectedItemUnread();
void markAllItemsRead(); void markAllItemsRead();
// Newspaper accessors. // Newspaper accessors.
void openSelectedItemsInNewspaperMode(); void openSelectedItemsInNewspaperMode();
// Feed clearers. // Feed clearers.
void clearSelectedFeeds(); void clearSelectedFeeds();
void clearAllFeeds(); void clearAllFeeds();
// Base manipulators. // Base manipulators.
void editSelectedItem(); void editSelectedItem();
void deleteSelectedItem(); void deleteSelectedItem();
// Selects next/previous item (feed/category) in the list. // Selects next/previous item (feed/category) in the list.
void selectNextItem(); void selectNextItem();
void selectPreviousItem(); void selectPreviousItem();
// Switches visibility of the widget. // Switches visibility of the widget.
void switchVisibility(); void switchVisibility();
signals: signals:
// Emitted if user selects new feeds. // Emitted if user selects new feeds.
void itemSelected(RootItem *item); void itemSelected(RootItem* item);
// Requests opening of given messages in newspaper mode. // Requests opening of given messages in newspaper mode.
void openMessagesInNewspaperView(RootItem *root, const QList<Message> &messages); void openMessagesInNewspaperView(RootItem* root, const QList<Message>& messages);
protected: protected:
// Handle selections. // Handle selections.
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
// React on "Del" key. // React on "Del" key.
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent* event);
// Show custom context menu. // Show custom context menu.
void contextMenuEvent(QContextMenuEvent *event); void contextMenuEvent(QContextMenuEvent* event);
void mouseDoubleClickEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent* event);
private slots: private slots:
void expandItemDelayed(const QModelIndex &idx); void expandItemDelayed(const QModelIndex& idx);
void markSelectedItemReadStatus(RootItem::ReadStatus read); void markSelectedItemReadStatus(RootItem::ReadStatus read);
void markAllItemsReadStatus(RootItem::ReadStatus read); void markAllItemsReadStatus(RootItem::ReadStatus read);
void saveSortState(int column, Qt::SortOrder order); void saveSortState(int column, Qt::SortOrder order);
void validateItemAfterDragDrop(const QModelIndex &source_index); void validateItemAfterDragDrop(const QModelIndex& source_index);
void onItemExpandRequested(const QList<RootItem*> &items, bool exp); void onItemExpandRequested(const QList<RootItem*>& items, bool exp);
void onItemExpandStateSaveRequested(RootItem *item); void onItemExpandStateSaveRequested(RootItem* item);
private: private:
// Initializes context menus. // Initializes context menus.
QMenu *initializeContextMenuCategories(RootItem *clicked_item); QMenu* initializeContextMenuCategories(RootItem* clicked_item);
QMenu *initializeContextMenuFeeds(RootItem *clicked_item); QMenu* initializeContextMenuFeeds(RootItem* clicked_item);
QMenu *initializeContextMenuEmptySpace(); QMenu* initializeContextMenuEmptySpace();
QMenu *initializeContextMenuOtherItem(RootItem *clicked_item); QMenu* initializeContextMenuOtherItem(RootItem* clicked_item);
// Sets up appearance of this widget. // Sets up appearance of this widget.
void setupAppearance(); void setupAppearance();
void saveExpandStates(RootItem *item); void saveExpandStates(RootItem* item);
QMenu *m_contextMenuCategories; QMenu* m_contextMenuCategories;
QMenu *m_contextMenuFeeds; QMenu* m_contextMenuFeeds;
QMenu *m_contextMenuEmptySpace; QMenu* m_contextMenuEmptySpace;
QMenu *m_contextMenuOtherItems; QMenu* m_contextMenuOtherItems;
FeedsModel *m_sourceModel; FeedsModel* m_sourceModel;
FeedsProxyModel *m_proxyModel; FeedsProxyModel* m_proxyModel;
}; };
#endif // FEEDSVIEW_H #endif // FEEDSVIEW_H

View file

@ -1,37 +1,38 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/guiutilities.h" #include "gui/guiutilities.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include <QLabel> #include <QLabel>
void GuiUtilities::setLabelAsNotice(QLabel *label, bool is_warning) { void GuiUtilities::setLabelAsNotice(QLabel* label, bool is_warning) {
label->setMargin(6); label->setMargin(6);
if (is_warning) { if (is_warning) {
label->setStyleSheet(QSL("font-weight: bold; font-style: italic; color: red")); label->setStyleSheet(QSL("font-weight: bold; font-style: italic; color: red"));
} }
else {
label->setStyleSheet(QSL("font-style: italic;")); else {
} label->setStyleSheet(QSL("font-style: italic;"));
} }
}
GuiUtilities::GuiUtilities() {
} GuiUtilities::GuiUtilities() {
}

View file

@ -1,32 +1,32 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef GUIUTILITIES_H #ifndef GUIUTILITIES_H
#define GUIUTILITIES_H #define GUIUTILITIES_H
class QLabel; class QLabel;
class GuiUtilities { class GuiUtilities {
public: public:
static void setLabelAsNotice(QLabel *label, bool is_warning); static void setLabelAsNotice(QLabel* label, bool is_warning);
private: private:
explicit GuiUtilities(); explicit GuiUtilities();
}; };
#endif // GUIUTILITIES_H #endif // GUIUTILITIES_H

View file

@ -1,46 +1,44 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/labelwithstatus.h" #include "gui/labelwithstatus.h"
#include "gui/plaintoolbutton.h" #include "gui/plaintoolbutton.h"
#include <QHBoxLayout> #include <QHBoxLayout>
LabelWithStatus::LabelWithStatus(QWidget *parent) LabelWithStatus::LabelWithStatus(QWidget* parent)
: WidgetWithStatus(parent) { : WidgetWithStatus(parent) {
m_wdgInput = new QLabel(this); m_wdgInput = new QLabel(this);
// Set correct size for the tool button.
// Set correct size for the tool button. int label_height = m_wdgInput->sizeHint().height();
int label_height = m_wdgInput->sizeHint().height(); m_btnStatus->setFixedSize(label_height, label_height);
m_btnStatus->setFixedSize(label_height, label_height); // Compose the layout.
m_layout->addWidget(m_wdgInput);
// Compose the layout. m_layout->addWidget(m_btnStatus);
m_layout->addWidget(m_wdgInput); }
m_layout->addWidget(m_btnStatus);
} LabelWithStatus::~LabelWithStatus() {
}
LabelWithStatus::~LabelWithStatus() {
} void LabelWithStatus::setStatus(WidgetWithStatus::StatusType status,
const QString& label_text,
void LabelWithStatus::setStatus(WidgetWithStatus::StatusType status, const QString& status_text) {
const QString &label_text, WidgetWithStatus::setStatus(status, status_text);
const QString &status_text) { label()->setText(label_text);
WidgetWithStatus::setStatus(status, status_text); }
label()->setText(label_text);
}

View file

@ -1,42 +1,42 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef LABELWITHSTATUS_H #ifndef LABELWITHSTATUS_H
#define LABELWITHSTATUS_H #define LABELWITHSTATUS_H
#include "gui/widgetwithstatus.h" #include "gui/widgetwithstatus.h"
#include <QLabel> #include <QLabel>
class LabelWithStatus : public WidgetWithStatus { class LabelWithStatus : public WidgetWithStatus {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit LabelWithStatus(QWidget *parent = 0); explicit LabelWithStatus(QWidget* parent = 0);
virtual ~LabelWithStatus(); virtual ~LabelWithStatus();
void setStatus(StatusType status, const QString &label_text, const QString &status_text); void setStatus(StatusType status, const QString& label_text, const QString& status_text);
// Access to label. // Access to label.
inline QLabel *label() const { inline QLabel* label() const {
return static_cast<QLabel*>(m_wdgInput); return static_cast<QLabel*>(m_wdgInput);
} }
}; };
#endif // LABELWITHSTATUS_H #endif // LABELWITHSTATUS_H

View file

@ -1,42 +1,39 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/lineeditwithstatus.h" #include "gui/lineeditwithstatus.h"
#include "gui/plaintoolbutton.h" #include "gui/plaintoolbutton.h"
#include "gui/baselineedit.h" #include "gui/baselineedit.h"
#include <QHBoxLayout> #include <QHBoxLayout>
LineEditWithStatus::LineEditWithStatus(QWidget *parent) LineEditWithStatus::LineEditWithStatus(QWidget* parent)
: WidgetWithStatus(parent) { : WidgetWithStatus(parent) {
m_wdgInput = new BaseLineEdit(this); m_wdgInput = new BaseLineEdit(this);
setFocusProxy(m_wdgInput);
setFocusProxy(m_wdgInput); // Set correct size for the tool button.
const int txt_input_height = m_wdgInput->sizeHint().height();
// Set correct size for the tool button. m_btnStatus->setFixedSize(txt_input_height, txt_input_height);
const int txt_input_height = m_wdgInput->sizeHint().height(); // Compose the layout.
m_btnStatus->setFixedSize(txt_input_height, txt_input_height); m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
// Compose the layout. }
m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus); LineEditWithStatus::~LineEditWithStatus() {
} }
LineEditWithStatus::~LineEditWithStatus() {
}

View file

@ -1,40 +1,40 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef LINEEDITWITHSTATUS_H #ifndef LINEEDITWITHSTATUS_H
#define LINEEDITWITHSTATUS_H #define LINEEDITWITHSTATUS_H
#include "gui/widgetwithstatus.h" #include "gui/widgetwithstatus.h"
#include "gui/baselineedit.h" #include "gui/baselineedit.h"
class LineEditWithStatus : public WidgetWithStatus { class LineEditWithStatus : public WidgetWithStatus {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit LineEditWithStatus(QWidget *parent = 0); explicit LineEditWithStatus(QWidget* parent = 0);
virtual ~LineEditWithStatus(); virtual ~LineEditWithStatus();
// Access to line edit. // Access to line edit.
inline BaseLineEdit *lineEdit() const { inline BaseLineEdit* lineEdit() const {
return static_cast<BaseLineEdit*>(m_wdgInput); return static_cast<BaseLineEdit*>(m_wdgInput);
} }
}; };
#endif // LINEEDITWITHSTATUS_H #endif // LINEEDITWITHSTATUS_H

View file

@ -1,53 +1,52 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/locationlineedit.h" #include "gui/locationlineedit.h"
#include "network-web/googlesuggest.h" #include "network-web/googlesuggest.h"
#include <QMouseEvent> #include <QMouseEvent>
LocationLineEdit::LocationLineEdit(QWidget *parent) LocationLineEdit::LocationLineEdit(QWidget* parent)
: BaseLineEdit(parent), m_mouseSelectsAllText(true), m_googleSuggest(new GoogleSuggest(this)) { : BaseLineEdit(parent), m_mouseSelectsAllText(true), m_googleSuggest(new GoogleSuggest(this)) {
setPlaceholderText(tr("Website address goes here")); setPlaceholderText(tr("Website address goes here"));
connect(this, &LocationLineEdit::submitted, m_googleSuggest, &GoogleSuggest::preventSuggest); connect(this, &LocationLineEdit::submitted, m_googleSuggest, &GoogleSuggest::preventSuggest);
} }
LocationLineEdit::~LocationLineEdit() { LocationLineEdit::~LocationLineEdit() {
} }
void LocationLineEdit::focusOutEvent(QFocusEvent *event) { void LocationLineEdit::focusOutEvent(QFocusEvent* event) {
BaseLineEdit::focusOutEvent(event); BaseLineEdit::focusOutEvent(event);
// User now left text box, when he enters it again and clicks,
// User now left text box, when he enters it again and clicks, // then all text should be selected.
// then all text should be selected. m_mouseSelectsAllText = true;
m_mouseSelectsAllText = true; }
}
void LocationLineEdit::mousePressEvent(QMouseEvent* event) {
void LocationLineEdit::mousePressEvent(QMouseEvent *event) { if (m_mouseSelectsAllText) {
if (m_mouseSelectsAllText) { event->ignore();
event->ignore(); selectAll();
selectAll(); // User clicked and all text was selected.
m_mouseSelectsAllText = false;
// User clicked and all text was selected. }
m_mouseSelectsAllText = false;
} else {
else { BaseLineEdit::mousePressEvent(event);
BaseLineEdit::mousePressEvent(event); }
} }
}

View file

@ -1,44 +1,44 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef LOCATIONLINEEDIT_H #ifndef LOCATIONLINEEDIT_H
#define LOCATIONLINEEDIT_H #define LOCATIONLINEEDIT_H
#include "gui/baselineedit.h" #include "gui/baselineedit.h"
class WebBrowser; class WebBrowser;
class GoogleSuggest; class GoogleSuggest;
class LocationLineEdit : public BaseLineEdit { class LocationLineEdit : public BaseLineEdit {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit LocationLineEdit(QWidget *parent = 0); explicit LocationLineEdit(QWidget* parent = 0);
virtual ~LocationLineEdit(); virtual ~LocationLineEdit();
protected: protected:
void focusOutEvent(QFocusEvent *event); void focusOutEvent(QFocusEvent* event);
void mousePressEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent* event);
private: private:
bool m_mouseSelectsAllText; bool m_mouseSelectsAllText;
GoogleSuggest *m_googleSuggest; GoogleSuggest* m_googleSuggest;
}; };
#endif // LOCATIONLINEEDIT_H #endif // LOCATIONLINEEDIT_H

View file

@ -1,110 +1,107 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include <QtGlobal> #include <QtGlobal>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QPushButton> #include <QPushButton>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QStyle> #include <QStyle>
#include <QCheckBox> #include <QCheckBox>
MessageBox::MessageBox(QWidget *parent) : QMessageBox(parent) { MessageBox::MessageBox(QWidget* parent) : QMessageBox(parent) {
} }
MessageBox::~MessageBox() { MessageBox::~MessageBox() {
} }
void MessageBox::setIcon(QMessageBox::Icon icon) { void MessageBox::setIcon(QMessageBox::Icon icon) {
// Determine correct status icon size. // Determine correct status icon size.
const int icon_size = qApp->style()->pixelMetric(QStyle::PM_MessageBoxIconSize, 0, this); const int icon_size = qApp->style()->pixelMetric(QStyle::PM_MessageBoxIconSize, 0, this);
// Setup status icon.
// Setup status icon. setIconPixmap(iconForStatus(icon).pixmap(icon_size, icon_size));
setIconPixmap(iconForStatus(icon).pixmap(icon_size, icon_size)); }
}
void MessageBox::setCheckBox(QMessageBox* msg_box, const QString& text, bool* data) {
void MessageBox::setCheckBox(QMessageBox *msg_box, const QString &text, bool *data) { // Add "don't show this again checkbox.
// Add "don't show this again checkbox. QCheckBox* check_box = new QCheckBox(msg_box);
QCheckBox *check_box = new QCheckBox(msg_box); check_box->setChecked(*data);
check_box->setText(text);
check_box->setChecked(*data); connect(check_box, &QCheckBox::toggled, [ = ](bool checked) {
check_box->setText(text); *data = checked;
connect(check_box, &QCheckBox::toggled, [=](bool checked) { });
*data = checked; msg_box->setCheckBox(check_box);
}); }
msg_box->setCheckBox(check_box); QIcon MessageBox::iconForStatus(QMessageBox::Icon status) {
} switch (status) {
case QMessageBox::Information:
QIcon MessageBox::iconForStatus(QMessageBox::Icon status) { return qApp->icons()->fromTheme(QSL("dialog-information"));
switch (status) {
case QMessageBox::Information: case QMessageBox::Warning:
return qApp->icons()->fromTheme(QSL("dialog-information")); return qApp->icons()->fromTheme(QSL("dialog-warning"));
case QMessageBox::Warning: case QMessageBox::Critical:
return qApp->icons()->fromTheme(QSL("dialog-warning")); return qApp->icons()->fromTheme(QSL("dialog-error"));
case QMessageBox::Critical: case QMessageBox::Question:
return qApp->icons()->fromTheme(QSL("dialog-error")); return qApp->icons()->fromTheme(QSL("dialog-question"));
case QMessageBox::Question: case QMessageBox::NoIcon:
return qApp->icons()->fromTheme(QSL("dialog-question")); default:
return QIcon();
case QMessageBox::NoIcon: }
default: }
return QIcon();
} QMessageBox::StandardButton MessageBox::show(QWidget* parent,
} QMessageBox::Icon icon,
const QString& title,
QMessageBox::StandardButton MessageBox::show(QWidget *parent, const QString& text,
QMessageBox::Icon icon, const QString& informative_text,
const QString &title, const QString& detailed_text,
const QString &text, QMessageBox::StandardButtons buttons,
const QString &informative_text, QMessageBox::StandardButton default_button,
const QString &detailed_text, bool* dont_show_again) {
QMessageBox::StandardButtons buttons, // Create and find needed components.
QMessageBox::StandardButton default_button, MessageBox msg_box(parent);
bool *dont_show_again) { // Initialize message box properties.
// Create and find needed components. msg_box.setWindowTitle(title);
MessageBox msg_box(parent); msg_box.setText(text);
msg_box.setInformativeText(informative_text);
// Initialize message box properties. msg_box.setDetailedText(detailed_text);
msg_box.setWindowTitle(title); msg_box.setIcon(icon);
msg_box.setText(text); msg_box.setStandardButtons(buttons);
msg_box.setInformativeText(informative_text); msg_box.setDefaultButton(default_button);
msg_box.setDetailedText(detailed_text);
msg_box.setIcon(icon); if (dont_show_again != nullptr) {
msg_box.setStandardButtons(buttons); MessageBox::setCheckBox(&msg_box, tr("Do not show this dialog again."), dont_show_again);
msg_box.setDefaultButton(default_button); }
if (dont_show_again != nullptr) { // Display it.
MessageBox::setCheckBox(&msg_box, tr("Do not show this dialog again."), dont_show_again); if (msg_box.exec() == -1) {
} return QMessageBox::Cancel;
}
// Display it.
if (msg_box.exec() == -1) { else {
return QMessageBox::Cancel; return msg_box.standardButton(msg_box.clickedButton());
} }
else { }
return msg_box.standardButton(msg_box.clickedButton());
}
}

View file

@ -1,52 +1,52 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef MESSAGEBOX_H #ifndef MESSAGEBOX_H
#define MESSAGEBOX_H #define MESSAGEBOX_H
#include <QMessageBox> #include <QMessageBox>
#include <QDialogButtonBox> #include <QDialogButtonBox>
class MessageBox : public QMessageBox { class MessageBox : public QMessageBox {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit MessageBox(QWidget *parent = 0); explicit MessageBox(QWidget* parent = 0);
virtual ~MessageBox(); virtual ~MessageBox();
// Custom icon setting. // Custom icon setting.
void setIcon(Icon icon); void setIcon(Icon icon);
static void setCheckBox(QMessageBox *msg_box, const QString &text, bool *data); static void setCheckBox(QMessageBox* msg_box, const QString& text, bool* data);
// Displays custom message box. // Displays custom message box.
static QMessageBox::StandardButton show(QWidget *parent, static QMessageBox::StandardButton show(QWidget* parent,
QMessageBox::Icon icon, QMessageBox::Icon icon,
const QString &title, const QString& title,
const QString &text, const QString& text,
const QString &informative_text = QString(), const QString& informative_text = QString(),
const QString &detailed_text = QString(), const QString& detailed_text = QString(),
QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton default_button = QMessageBox::Ok, QMessageBox::StandardButton default_button = QMessageBox::Ok,
bool *dont_show_again = nullptr); bool* dont_show_again = nullptr);
static QIcon iconForStatus(QMessageBox::Icon status); static QIcon iconForStatus(QMessageBox::Icon status);
}; };
#endif // MESSAGEBOX_H #endif // MESSAGEBOX_H

View file

@ -1,234 +1,219 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/messagepreviewer.h" #include "gui/messagepreviewer.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "network-web/webfactory.h" #include "network-web/webfactory.h"
#include "miscellaneous/databasequeries.h" #include "miscellaneous/databasequeries.h"
#include "gui/messagebox.h" #include "gui/messagebox.h"
#include "gui/dialogs/formmain.h" #include "gui/dialogs/formmain.h"
#include "services/abstract/serviceroot.h" #include "services/abstract/serviceroot.h"
#include <QScrollBar> #include <QScrollBar>
#include <QToolBar> #include <QToolBar>
#include <QToolTip> #include <QToolTip>
void MessagePreviewer::createConnections() { void MessagePreviewer::createConnections() {
connect(m_ui->m_txtMessage, &QTextBrowser::anchorClicked, [=](const QUrl &url) { connect(m_ui->m_txtMessage, &QTextBrowser::anchorClicked, [ = ](const QUrl & url) {
if (!url.isEmpty()) { if (!url.isEmpty()) {
bool open_externally_now = qApp->settings()->value(GROUP(Browser), bool open_externally_now = qApp->settings()->value(GROUP(Browser),
SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool(); SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool();
if (open_externally_now) { if (open_externally_now) {
WebFactory::instance()->openUrlInExternalBrowser(url.toString()); WebFactory::instance()->openUrlInExternalBrowser(url.toString());
} }
else {
// User clicked some URL. Open it in external browser or download? else {
MessageBox box(qApp->mainForm()); // 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.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.setInformativeText(tr("What action do you want to take?"));
box.setDetailedText(url.toString()); box.setDetailedText(url.toString());
QAbstractButton *btn_open = box.addButton(tr("Open in external browser"), QMessageBox::ActionRole); QAbstractButton* btn_open = box.addButton(tr("Open in external browser"), QMessageBox::ActionRole);
QAbstractButton *btn_download = box.addButton(tr("Download"), QMessageBox::ActionRole); QAbstractButton* btn_download = box.addButton(tr("Download"), QMessageBox::ActionRole);
QAbstractButton *btn_cancel = box.addButton(QMessageBox::Cancel); QAbstractButton* btn_cancel = box.addButton(QMessageBox::Cancel);
bool always;
bool always; MessageBox::setCheckBox(&box, tr("Always open links in external browser."), &always);
MessageBox::setCheckBox(&box, tr("Always open links in external browser."), &always); box.setDefaultButton(QMessageBox::Cancel);
box.exec();
box.setDefaultButton(QMessageBox::Cancel);
box.exec(); if (box.clickedButton() != box.button(QMessageBox::Cancel)) {
// Store selected checkbox value.
if (box.clickedButton() != box.button(QMessageBox::Cancel)) { qApp->settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, always);
// Store selected checkbox value. }
qApp->settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, always);
} if (box.clickedButton() == btn_open) {
WebFactory::instance()->openUrlInExternalBrowser(url.toString());
if (box.clickedButton() == btn_open) { }
WebFactory::instance()->openUrlInExternalBrowser(url.toString());
} else if (box.clickedButton() == btn_download) {
else if (box.clickedButton() == btn_download) { qApp->downloadManager()->download(url);
qApp->downloadManager()->download(url); }
}
btn_download->deleteLater();
btn_download->deleteLater(); btn_open->deleteLater();
btn_open->deleteLater(); btn_cancel->deleteLater();
btn_cancel->deleteLater(); }
} }
}
else { else {
MessageBox::show(qApp->mainForm(), QMessageBox::Warning, tr("Incorrect link"), MessageBox::show(qApp->mainForm(), QMessageBox::Warning, tr("Incorrect link"),
tr("Selected hyperlink is invalid.")); tr("Selected hyperlink is invalid."));
} }
}); });
connect(m_actionMarkRead = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-read"), tr("Mark message as read")), connect(m_actionMarkRead = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-read"), tr("Mark message as read")),
&QAction::triggered, &QAction::triggered,
this, this,
&MessagePreviewer::markMessageAsRead); &MessagePreviewer::markMessageAsRead);
connect(m_actionMarkUnread = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-unread"), tr("Mark message as unread")), connect(m_actionMarkUnread = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-unread"), tr("Mark message as unread")),
&QAction::triggered, &QAction::triggered,
this, this,
&MessagePreviewer::markMessageAsUnread); &MessagePreviewer::markMessageAsUnread);
connect(m_actionSwitchImportance = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-important"), tr("Switch message importance")), connect(m_actionSwitchImportance = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-important"), tr("Switch message importance")),
&QAction::triggered, &QAction::triggered,
this, this,
&MessagePreviewer::switchMessageImportance); &MessagePreviewer::switchMessageImportance);
connect(m_ui->m_txtMessage, connect(m_ui->m_txtMessage,
static_cast<void (QTextBrowser::*)(const QString&)>(&QTextBrowser::highlighted), static_cast<void (QTextBrowser::*)(const QString&)>(&QTextBrowser::highlighted),
[=](const QString &text) { [ = ](const QString & text) {
Q_UNUSED(text) Q_UNUSED(text)
QToolTip::showText(QCursor::pos(), tr("Click this link to download it or open it with external browser."), this);
QToolTip::showText(QCursor::pos(), tr("Click this link to download it or open it with external browser."), this); });
}); }
}
MessagePreviewer::MessagePreviewer(QWidget* parent) : QWidget(parent),
MessagePreviewer::MessagePreviewer(QWidget *parent) : QWidget(parent), m_ui(new Ui::MessagePreviewer), m_pictures(QStringList()) {
m_ui(new Ui::MessagePreviewer), m_pictures(QStringList()) { m_ui->setupUi(this);
m_ui->setupUi(this); m_ui->m_txtMessage->viewport()->setAutoFillBackground(true);
m_ui->m_txtMessage->viewport()->setAutoFillBackground(true); m_toolBar = new QToolBar(this);
m_toolBar = new QToolBar(this); m_toolBar->setOrientation(Qt::Vertical);
m_toolBar->setOrientation(Qt::Vertical); m_ui->m_layout->addWidget(m_toolBar, 0, 0, -1, 1);
m_ui->m_layout->addWidget(m_toolBar, 0, 0, -1, 1); createConnections();
m_actionSwitchImportance->setCheckable(true);
createConnections(); reloadFontSettings();
clear();
m_actionSwitchImportance->setCheckable(true); }
reloadFontSettings(); MessagePreviewer::~MessagePreviewer() {
clear(); }
}
void MessagePreviewer::reloadFontSettings() {
MessagePreviewer::~MessagePreviewer() { const Settings* settings = qApp->settings();
} QFont fon;
fon.fromString(settings->value(GROUP(Messages),
void MessagePreviewer::reloadFontSettings() { SETTING(Messages::PreviewerFontStandard)).toString());
const Settings *settings = qApp->settings(); m_ui->m_txtMessage->setFont(fon);
QFont fon; }
fon.fromString(settings->value(GROUP(Messages), void MessagePreviewer::clear() {
SETTING(Messages::PreviewerFontStandard)).toString()); m_ui->m_txtMessage->clear();
m_pictures.clear();
m_ui->m_txtMessage->setFont(fon); hide();
} }
void MessagePreviewer::clear() { void MessagePreviewer::hideToolbar() {
m_ui->m_txtMessage->clear(); m_toolBar->setVisible(false);
m_pictures.clear(); }
hide();
} void MessagePreviewer::loadMessage(const Message& message, RootItem* root) {
m_message = message;
void MessagePreviewer::hideToolbar() { m_root = root;
m_toolBar->setVisible(false);
} if (!m_root.isNull()) {
m_actionSwitchImportance->setChecked(m_message.m_isImportant);
void MessagePreviewer::loadMessage(const Message &message, RootItem *root) { m_ui->m_txtMessage->setHtml(prepareHtmlForMessage(m_message));
m_message = message; updateButtons();
m_root = root; 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));
void MessagePreviewer::markMessageAsRead() {
updateButtons(); markMessageAsReadUnread(RootItem::Read);
show(); }
m_ui->m_txtMessage->verticalScrollBar()->triggerAction(QScrollBar::SliderToMinimum); void MessagePreviewer::markMessageAsUnread() {
} markMessageAsReadUnread(RootItem::Unread);
} }
void MessagePreviewer::markMessageAsRead() { void MessagePreviewer::markMessageAsReadUnread(RootItem::ReadStatus read) {
markMessageAsReadUnread(RootItem::Read); if (!m_root.isNull()) {
} if (m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(),
QList<Message>() << m_message,
void MessagePreviewer::markMessageAsUnread() { read)) {
markMessageAsReadUnread(RootItem::Unread); DatabaseQueries::markMessagesReadUnread(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings),
} QStringList() << QString::number(m_message.m_id),
read);
void MessagePreviewer::markMessageAsReadUnread(RootItem::ReadStatus read) { m_root->getParentServiceRoot()->onAfterSetMessagesRead(m_root.data(),
if (!m_root.isNull()) { QList<Message>() << m_message,
if (m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(), read);
QList<Message>() << m_message, m_message.m_isRead = read == RootItem::Read;
read)) { emit markMessageRead(m_message.m_id, read);
DatabaseQueries::markMessagesReadUnread(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), updateButtons();
QStringList() << QString::number(m_message.m_id), }
read); }
m_root->getParentServiceRoot()->onAfterSetMessagesRead(m_root.data(), }
QList<Message>() << m_message,
read); void MessagePreviewer::switchMessageImportance(bool checked) {
m_message.m_isRead = read == RootItem::Read; if (!m_root.isNull()) {
if (m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(),
emit markMessageRead(m_message.m_id, read); QList<ImportanceChange>() << ImportanceChange(m_message,
updateButtons(); m_message.m_isImportant ?
} RootItem::NotImportant :
} RootItem::Important))) {
} DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings),
QStringList() << QString::number(m_message.m_id));
void MessagePreviewer::switchMessageImportance(bool checked) { m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(),
if (!m_root.isNull()) { QList<ImportanceChange>() << ImportanceChange(m_message,
if (m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(), m_message.m_isImportant ?
QList<ImportanceChange>() << ImportanceChange(m_message, RootItem::NotImportant :
m_message.m_isImportant ? RootItem::Important));
RootItem::NotImportant : emit markMessageImportant(m_message.m_id, checked ? RootItem::Important : RootItem::NotImportant);
RootItem::Important))) { m_message.m_isImportant = checked;
DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings), }
QStringList() << QString::number(m_message.m_id)); }
}
m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(),
QList<ImportanceChange>() << ImportanceChange(m_message, void MessagePreviewer::updateButtons() {
m_message.m_isImportant ? m_actionMarkRead->setEnabled(!m_message.m_isRead);
RootItem::NotImportant : m_actionMarkUnread->setEnabled(m_message.m_isRead);
RootItem::Important)); }
emit markMessageImportant(m_message.m_id, checked ? RootItem::Important : RootItem::NotImportant); QString MessagePreviewer::prepareHtmlForMessage(const Message& message) {
m_message.m_isImportant = checked; QString html = QString("<h2 align=\"center\">%1</h2>").arg(message.m_title);
} html += QString("[url] <a href=\"%1\">%1</a><br/>").arg(message.m_url);
}
} foreach (const Enclosure& enc, message.m_enclosures) {
html += QString("[%2] <a href=\"%1\">%1</a><br/>").arg(enc.m_url, enc.m_mimeType);
void MessagePreviewer::updateButtons() { }
m_actionMarkRead->setEnabled(!m_message.m_isRead);
m_actionMarkUnread->setEnabled(m_message.m_isRead); int offset = 0;
} QRegExp imgTagRegex("\\<img[^\\>]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive);
imgTagRegex.setMinimal(true);
QString MessagePreviewer::prepareHtmlForMessage(const Message &message) {
QString html = QString("<h2 align=\"center\">%1</h2>").arg(message.m_title); while ((offset = imgTagRegex.indexIn(message.m_contents, offset)) != -1) {
m_pictures.append(imgTagRegex.cap(1));
html += QString("[url] <a href=\"%1\">%1</a><br/>").arg(message.m_url); offset += imgTagRegex.matchedLength();
html += QString("[%2] <a href=\"%1\">%1</a><br/>").arg(imgTagRegex.cap(1), tr("image"));
foreach (const Enclosure &enc, message.m_enclosures) { }
html += QString("[%2] <a href=\"%1\">%1</a><br/>").arg(enc.m_url, enc.m_mimeType);
} html += "<br/>";
html += message.m_contents;
int offset = 0; return html;
QRegExp imgTagRegex("\\<img[^\\>]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive); }
imgTagRegex.setMinimal(true);
while( (offset = imgTagRegex.indexIn(message.m_contents, offset)) != -1){
m_pictures.append(imgTagRegex.cap(1));
offset += imgTagRegex.matchedLength();
html += QString("[%2] <a href=\"%1\">%1</a><br/>").arg(imgTagRegex.cap(1), tr("image"));
}
html += "<br/>";
html += message.m_contents;
return html;
}

View file

@ -1,78 +1,78 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef MESSAGEPREVIEWER_H #ifndef MESSAGEPREVIEWER_H
#define MESSAGEPREVIEWER_H #define MESSAGEPREVIEWER_H
#include <QWidget> #include <QWidget>
#include "ui_messagepreviewer.h" #include "ui_messagepreviewer.h"
#include "core/message.h" #include "core/message.h"
#include "services/abstract/rootitem.h" #include "services/abstract/rootitem.h"
#include <QPointer> #include <QPointer>
namespace Ui { namespace Ui {
class MessagePreviewer; class MessagePreviewer;
} }
class QToolBar; class QToolBar;
class MessagePreviewer : public QWidget { class MessagePreviewer : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit MessagePreviewer(QWidget *parent = 0); explicit MessagePreviewer(QWidget* parent = 0);
virtual ~MessagePreviewer(); virtual ~MessagePreviewer();
void reloadFontSettings(); void reloadFontSettings();
public slots: public slots:
void clear(); void clear();
void hideToolbar(); void hideToolbar();
void loadMessage(const Message &message, RootItem *root); void loadMessage(const Message& message, RootItem* root);
private slots: private slots:
void markMessageAsRead(); void markMessageAsRead();
void markMessageAsUnread(); void markMessageAsUnread();
void markMessageAsReadUnread(RootItem::ReadStatus read); void markMessageAsReadUnread(RootItem::ReadStatus read);
void switchMessageImportance(bool checked); void switchMessageImportance(bool checked);
signals: signals:
void markMessageRead(int id, RootItem::ReadStatus read); void markMessageRead(int id, RootItem::ReadStatus read);
void markMessageImportant(int id, RootItem::Importance important); void markMessageImportant(int id, RootItem::Importance important);
void requestMessageListReload(bool mark_current_as_read); void requestMessageListReload(bool mark_current_as_read);
private: private:
void createConnections(); void createConnections();
void updateButtons(); void updateButtons();
QString prepareHtmlForMessage(const Message &message); QString prepareHtmlForMessage(const Message& message);
QToolBar *m_toolBar; QToolBar* m_toolBar;
QScopedPointer<Ui::MessagePreviewer> m_ui; QScopedPointer<Ui::MessagePreviewer> m_ui;
Message m_message; Message m_message;
QStringList m_pictures; QStringList m_pictures;
QPointer<RootItem> m_root; QPointer<RootItem> m_root;
QAction *m_actionMarkRead; QAction* m_actionMarkRead;
QAction *m_actionMarkUnread; QAction* m_actionMarkUnread;
QAction *m_actionSwitchImportance; QAction* m_actionSwitchImportance;
}; };
#endif // MESSAGEPREVIEWER_H #endif // MESSAGEPREVIEWER_H

View file

@ -1,25 +1,25 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/messagessearchlineedit.h" #include "gui/messagessearchlineedit.h"
MessagesSearchLineEdit::MessagesSearchLineEdit(QWidget *parent) : BaseLineEdit(parent) { MessagesSearchLineEdit::MessagesSearchLineEdit(QWidget* parent) : BaseLineEdit(parent) {
} }
MessagesSearchLineEdit::~MessagesSearchLineEdit() { MessagesSearchLineEdit::~MessagesSearchLineEdit() {
} }

View file

@ -1,35 +1,35 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef MESSAGESEARCHLINEEDIT_H #ifndef MESSAGESEARCHLINEEDIT_H
#define MESSAGESEARCHLINEEDIT_H #define MESSAGESEARCHLINEEDIT_H
#include "gui/baselineedit.h" #include "gui/baselineedit.h"
class PlainToolButton; class PlainToolButton;
class MessagesSearchLineEdit : public BaseLineEdit { class MessagesSearchLineEdit : public BaseLineEdit {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit MessagesSearchLineEdit(QWidget *parent = 0); explicit MessagesSearchLineEdit(QWidget* parent = 0);
virtual ~MessagesSearchLineEdit(); virtual ~MessagesSearchLineEdit();
}; };
#endif // MESSAGESEARCHLINEEDIT_H #endif // MESSAGESEARCHLINEEDIT_H

View file

@ -1,173 +1,165 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/messagestoolbar.h" #include "gui/messagestoolbar.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include "gui/baselineedit.h" #include "gui/baselineedit.h"
#include "gui/messagessearchlineedit.h" #include "gui/messagessearchlineedit.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "miscellaneous/settings.h" #include "miscellaneous/settings.h"
#include <QWidgetAction> #include <QWidgetAction>
#include <QToolButton> #include <QToolButton>
#include <QMenu> #include <QMenu>
MessagesToolBar::MessagesToolBar(const QString &title, QWidget *parent) MessagesToolBar::MessagesToolBar(const QString& title, QWidget* parent)
: BaseToolBar(title, parent) { : BaseToolBar(title, parent) {
initializeSearchBox(); initializeSearchBox();
initializeHighlighter(); initializeHighlighter();
} }
MessagesToolBar::~MessagesToolBar() { MessagesToolBar::~MessagesToolBar() {
} }
QList<QAction*> MessagesToolBar::availableActions() const { QList<QAction*> MessagesToolBar::availableActions() const {
QList<QAction*> available_actions = qApp->userActions(); QList<QAction*> available_actions = qApp->userActions();
available_actions.append(m_actionSearchMessages);
available_actions.append(m_actionSearchMessages); available_actions.append(m_actionMessageHighlighter);
available_actions.append(m_actionMessageHighlighter); return available_actions;
}
return available_actions;
} QList<QAction*> MessagesToolBar::changeableActions() const {
return actions();
QList<QAction*> MessagesToolBar::changeableActions() const { }
return actions();
} void MessagesToolBar::saveChangeableActions(const QStringList& actions) {
qApp->settings()->setValue(GROUP(GUI), GUI::MessagesToolbarDefaultButtons, actions.join(QSL(",")));
void MessagesToolBar::saveChangeableActions(const QStringList& actions) { 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)) {
// If user hidden search messages box, then remove the filter. m_txtSearchMessages->clear();
if (!changeableActions().contains(m_actionSearchMessages)) { }
m_txtSearchMessages->clear(); }
}
} QList<QAction*> MessagesToolBar::getSpecificActions(const QStringList& actions) {
QList<QAction*> available_actions = availableActions();
QList<QAction*> MessagesToolBar::getSpecificActions(const QStringList &actions) { QList<QAction*> spec_actions;
QList<QAction*> available_actions = availableActions();
QList<QAction*> spec_actions; // Iterate action names and add respectable actions into the toolbar.
foreach (const QString& action_name, actions) {
// Iterate action names and add respectable actions into the toolbar. QAction* matching_action = findMatchingAction(action_name, available_actions);
foreach (const QString &action_name, actions) {
QAction *matching_action = findMatchingAction(action_name, available_actions); if (matching_action != nullptr) {
// Add existing standard action.
if (matching_action != nullptr) { spec_actions.append(matching_action);
// Add existing standard action. }
spec_actions.append(matching_action);
} else if (action_name == SEPARATOR_ACTION_NAME) {
else if (action_name == SEPARATOR_ACTION_NAME) { // Add new separator.
// Add new separator. QAction* act = new QAction(this);
QAction *act = new QAction(this); act->setSeparator(true);
act->setSeparator(true); spec_actions.append(act);
}
spec_actions.append(act);
} else if (action_name == SEACRH_MESSAGES_ACTION_NAME) {
else if (action_name == SEACRH_MESSAGES_ACTION_NAME) { // Add search box.
// Add search box. spec_actions.append(m_actionSearchMessages);
spec_actions.append(m_actionSearchMessages); }
}
else if (action_name == HIGHLIGHTER_ACTION_NAME) { else if (action_name == HIGHLIGHTER_ACTION_NAME) {
// Add filter button. // Add filter button.
spec_actions.append(m_actionMessageHighlighter); spec_actions.append(m_actionMessageHighlighter);
} }
else if (action_name == SPACER_ACTION_NAME) {
// Add new spacer. else if (action_name == SPACER_ACTION_NAME) {
QWidget *spacer = new QWidget(this); // Add new spacer.
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QWidget* spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QWidgetAction *action = new QWidgetAction(this); QWidgetAction* action = new QWidgetAction(this);
action->setDefaultWidget(spacer);
action->setDefaultWidget(spacer); action->setIcon(qApp->icons()->fromTheme(QSL("go-jump")));
action->setIcon(qApp->icons()->fromTheme(QSL("go-jump"))); action->setProperty("type", SPACER_ACTION_NAME);
action->setProperty("type", SPACER_ACTION_NAME); action->setProperty("name", tr("Toolbar spacer"));
action->setProperty("name", tr("Toolbar spacer")); spec_actions.append(action);
}
spec_actions.append(action); }
}
} return spec_actions;
}
return spec_actions;
} void MessagesToolBar::loadSpecificActions(const QList<QAction*>& actions) {
clear();
void MessagesToolBar::loadSpecificActions(const QList<QAction*> &actions) {
clear(); foreach (QAction* act, actions) {
addAction(act);
foreach (QAction *act, actions) { }
addAction(act); }
}
} void MessagesToolBar::handleMessageHighlighterChange(QAction* action) {
m_btnMessageHighlighter->setIcon(action->icon());
void MessagesToolBar::handleMessageHighlighterChange(QAction *action) { m_btnMessageHighlighter->setToolTip(action->text());
m_btnMessageHighlighter->setIcon(action->icon()); emit messageFilterChanged(action->data().value<MessagesModel::MessageHighlighter>());
m_btnMessageHighlighter->setToolTip(action->text()); }
emit messageFilterChanged(action->data().value<MessagesModel::MessageHighlighter>()); void MessagesToolBar::initializeSearchBox() {
} m_txtSearchMessages = new MessagesSearchLineEdit(this);
m_txtSearchMessages->setFixedWidth(FILTER_WIDTH);
void MessagesToolBar::initializeSearchBox() { m_txtSearchMessages->setPlaceholderText(tr("Search messages"));
m_txtSearchMessages = new MessagesSearchLineEdit(this); // Setup wrapping action for search box.
m_txtSearchMessages->setFixedWidth(FILTER_WIDTH); m_actionSearchMessages = new QWidgetAction(this);
m_txtSearchMessages->setPlaceholderText(tr("Search messages")); m_actionSearchMessages->setDefaultWidget(m_txtSearchMessages);
m_actionSearchMessages->setIcon(qApp->icons()->fromTheme(QSL("system-search")));
// Setup wrapping action for search box. m_actionSearchMessages->setProperty("type", SEACRH_MESSAGES_ACTION_NAME);
m_actionSearchMessages = new QWidgetAction(this); m_actionSearchMessages->setProperty("name", tr("Message search box"));
m_actionSearchMessages->setDefaultWidget(m_txtSearchMessages); connect(m_txtSearchMessages, &MessagesSearchLineEdit::textChanged, this, &MessagesToolBar::messageSearchPatternChanged);
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")); void MessagesToolBar::initializeHighlighter() {
m_menuMessageHighlighter = new QMenu(tr("Menu for highlighting messages"), this);
connect(m_txtSearchMessages, &MessagesSearchLineEdit::textChanged, this, &MessagesToolBar::messageSearchPatternChanged); 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")),
void MessagesToolBar::initializeHighlighter() { tr("Highlight unread messages"))->setData(QVariant::fromValue(MessagesModel::HighlightUnread));
m_menuMessageHighlighter = new QMenu(tr("Menu for highlighting messages"), this); m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-important")),
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-read")), tr("Highlight important messages"))->setData(QVariant::fromValue(MessagesModel::HighlightImportant));
tr("No extra highlighting"))->setData(QVariant::fromValue(MessagesModel::NoHighlighting)); m_btnMessageHighlighter = new QToolButton(this);
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-unread")), m_btnMessageHighlighter->setToolTip(tr("Display all messages"));
tr("Highlight unread messages"))->setData(QVariant::fromValue(MessagesModel::HighlightUnread)); m_btnMessageHighlighter->setMenu(m_menuMessageHighlighter);
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-important")), m_btnMessageHighlighter->setPopupMode(QToolButton::MenuButtonPopup);
tr("Highlight important messages"))->setData(QVariant::fromValue(MessagesModel::HighlightImportant)); m_btnMessageHighlighter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read")));
m_actionMessageHighlighter = new QWidgetAction(this);
m_btnMessageHighlighter = new QToolButton(this); m_actionMessageHighlighter->setDefaultWidget(m_btnMessageHighlighter);
m_btnMessageHighlighter->setToolTip(tr("Display all messages")); m_actionMessageHighlighter->setIcon(m_btnMessageHighlighter->icon());
m_btnMessageHighlighter->setMenu(m_menuMessageHighlighter); m_actionMessageHighlighter->setProperty("type", HIGHLIGHTER_ACTION_NAME);
m_btnMessageHighlighter->setPopupMode(QToolButton::MenuButtonPopup); m_actionMessageHighlighter->setProperty("name", tr("Message highlighter"));
m_btnMessageHighlighter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read"))); connect(m_menuMessageHighlighter, SIGNAL(triggered(QAction*)),
this, SLOT(handleMessageHighlighterChange(QAction*)));
m_actionMessageHighlighter = new QWidgetAction(this); }
m_actionMessageHighlighter->setDefaultWidget(m_btnMessageHighlighter);
m_actionMessageHighlighter->setIcon(m_btnMessageHighlighter->icon()); QStringList MessagesToolBar::defaultActions() const {
m_actionMessageHighlighter->setProperty("type", HIGHLIGHTER_ACTION_NAME); return QString(GUI::MessagesToolbarDefaultButtonsDef).split(',',
m_actionMessageHighlighter->setProperty("name", tr("Message highlighter")); QString::SkipEmptyParts);
}
connect(m_menuMessageHighlighter, SIGNAL(triggered(QAction*)),
this, SLOT(handleMessageHighlighterChange(QAction*))); QStringList MessagesToolBar::savedActions() const {
} return qApp->settings()->value(GROUP(GUI),
SETTING(GUI::MessagesToolbarDefaultButtons)).toString().split(',',
QStringList MessagesToolBar::defaultActions() const { 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);
}

View file

@ -1,82 +1,82 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef NEWSTOOLBAR_H #ifndef NEWSTOOLBAR_H
#define NEWSTOOLBAR_H #define NEWSTOOLBAR_H
#include "gui/basetoolbar.h" #include "gui/basetoolbar.h"
#include "core/messagesmodel.h" #include "core/messagesmodel.h"
class MessagesSearchLineEdit; class MessagesSearchLineEdit;
class QWidgetAction; class QWidgetAction;
class QToolButton; class QToolButton;
class QMenu; class QMenu;
class MessagesToolBar : public BaseToolBar { class MessagesToolBar : public BaseToolBar {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit MessagesToolBar(const QString &title, QWidget *parent = 0); explicit MessagesToolBar(const QString& title, QWidget* parent = 0);
virtual ~MessagesToolBar(); virtual ~MessagesToolBar();
// External access to search line edit. // External access to search line edit.
inline MessagesSearchLineEdit *searchLineEdit() { inline MessagesSearchLineEdit* searchLineEdit() {
return m_txtSearchMessages; return m_txtSearchMessages;
} }
// Implementation of BaseToolBar interface. // Implementation of BaseToolBar interface.
QList<QAction*> availableActions() const; QList<QAction*> availableActions() const;
QList<QAction*> changeableActions() const; QList<QAction*> changeableActions() const;
void saveChangeableActions(const QStringList &actions); void saveChangeableActions(const QStringList& actions);
// Loads actions as specified by external actions list. // Loads actions as specified by external actions list.
// NOTE: This is used primarily for reloading actions // NOTE: This is used primarily for reloading actions
// when they are changed from settings. // when they are changed from settings.
void loadSpecificActions(const QList<QAction*> &actions); void loadSpecificActions(const QList<QAction*>& actions);
QList<QAction*> getSpecificActions(const QStringList &actions); QList<QAction*> getSpecificActions(const QStringList& actions);
QStringList defaultActions() const; QStringList defaultActions() const;
QStringList savedActions() const; QStringList savedActions() const;
signals: signals:
void messageSearchPatternChanged(const QString &pattern); void messageSearchPatternChanged(const QString& pattern);
// Emitted if message filter is changed. // Emitted if message filter is changed.
void messageFilterChanged(MessagesModel::MessageHighlighter filter); void messageFilterChanged(MessagesModel::MessageHighlighter filter);
private slots: private slots:
// Called when highlighter gets changed. // Called when highlighter gets changed.
void handleMessageHighlighterChange(QAction *action); void handleMessageHighlighterChange(QAction* action);
private: private:
void initializeSearchBox(); void initializeSearchBox();
void initializeHighlighter(); void initializeHighlighter();
private: private:
QWidgetAction *m_actionMessageHighlighter; QWidgetAction* m_actionMessageHighlighter;
QToolButton *m_btnMessageHighlighter; QToolButton* m_btnMessageHighlighter;
QMenu *m_menuMessageHighlighter; QMenu* m_menuMessageHighlighter;
QWidgetAction *m_actionSearchMessages; QWidgetAction* m_actionSearchMessages;
MessagesSearchLineEdit *m_txtSearchMessages; MessagesSearchLineEdit* m_txtSearchMessages;
}; };
#endif // NEWSTOOLBAR_H #endif // NEWSTOOLBAR_H

File diff suppressed because it is too large Load diff

View file

@ -1,125 +1,125 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef MESSAGESVIEW_H #ifndef MESSAGESVIEW_H
#define MESSAGESVIEW_H #define MESSAGESVIEW_H
#include "core/messagesmodel.h" #include "core/messagesmodel.h"
#include "services/abstract/rootitem.h" #include "services/abstract/rootitem.h"
#include <QTreeView> #include <QTreeView>
#include <QHeaderView> #include <QHeaderView>
class MessagesProxyModel; class MessagesProxyModel;
class MessagesView : public QTreeView { class MessagesView : public QTreeView {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit MessagesView(QWidget *parent = 0); explicit MessagesView(QWidget* parent = 0);
virtual ~MessagesView(); virtual ~MessagesView();
// Model accessors. // Model accessors.
inline MessagesProxyModel *model() const { inline MessagesProxyModel* model() const {
return m_proxyModel; return m_proxyModel;
} }
inline MessagesModel *sourceModel() const { inline MessagesModel* sourceModel() const {
return m_sourceModel; return m_sourceModel;
} }
public slots: public slots:
void keyboardSearch(const QString &search); void keyboardSearch(const QString& search);
// Called after data got changed externally // Called after data got changed externally
// and it needs to be reloaded to the view. // and it needs to be reloaded to the view.
void reloadSelections(); void reloadSelections();
// Loads un-deleted messages from selected feeds. // Loads un-deleted messages from selected feeds.
void loadItem(RootItem *item); void loadItem(RootItem* item);
// Message manipulators. // Message manipulators.
void openSelectedSourceMessagesExternally(); void openSelectedSourceMessagesExternally();
void openSelectedMessagesInternally(); void openSelectedMessagesInternally();
void sendSelectedMessageViaEmail(); void sendSelectedMessageViaEmail();
// Works with SELECTED messages only. // Works with SELECTED messages only.
void setSelectedMessagesReadStatus(RootItem::ReadStatus read); void setSelectedMessagesReadStatus(RootItem::ReadStatus read);
void markSelectedMessagesRead(); void markSelectedMessagesRead();
void markSelectedMessagesUnread(); void markSelectedMessagesUnread();
void switchSelectedMessagesImportance(); void switchSelectedMessagesImportance();
void deleteSelectedMessages(); void deleteSelectedMessages();
void restoreSelectedMessages(); void restoreSelectedMessages();
void selectNextItem(); void selectNextItem();
void selectPreviousItem(); void selectPreviousItem();
void selectNextUnreadItem(); void selectNextUnreadItem();
// Searchs the visible message according to given pattern. // Searchs the visible message according to given pattern.
void searchMessages(const QString &pattern); void searchMessages(const QString& pattern);
void filterMessages(MessagesModel::MessageHighlighter filter); void filterMessages(MessagesModel::MessageHighlighter filter);
private slots: private slots:
// Marks given indexes as selected. // Marks given indexes as selected.
void reselectIndexes(const QModelIndexList &indexes); void reselectIndexes(const QModelIndexList& indexes);
// Changes resize mode for all columns. // Changes resize mode for all columns.
void adjustColumns(); void adjustColumns();
// Saves current sort state. // Saves current sort state.
void onSortIndicatorChanged(int column, Qt::SortOrder order); void onSortIndicatorChanged(int column, Qt::SortOrder order);
signals: signals:
// Link/message openers. // Link/message openers.
void openLinkNewTab(const QString &link); void openLinkNewTab(const QString& link);
void openLinkMiniBrowser(const QString &link); void openLinkMiniBrowser(const QString& link);
void openMessagesInNewspaperView(RootItem *root, const QList<Message> &messages); void openMessagesInNewspaperView(RootItem* root, const QList<Message>& messages);
// Notify others about message selections. // Notify others about message selections.
void currentMessageChanged(const Message &message, RootItem *root); void currentMessageChanged(const Message& message, RootItem* root);
void currentMessageRemoved(); void currentMessageRemoved();
private: private:
void sort(int column, Qt::SortOrder order, bool repopulate_data, bool change_header, bool emit_changed_from_header); void sort(int column, Qt::SortOrder order, bool repopulate_data, bool change_header, bool emit_changed_from_header);
// Creates needed connections. // Creates needed connections.
void createConnections(); void createConnections();
// Initializes context menu. // Initializes context menu.
void initializeContextMenu(); void initializeContextMenu();
// Sets up appearance. // Sets up appearance.
void setupAppearance(); void setupAppearance();
// Event reimplementations. // Event reimplementations.
void contextMenuEvent(QContextMenuEvent *event); void contextMenuEvent(QContextMenuEvent* event);
void mousePressEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent* event);
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent* event);
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
QMenu *m_contextMenu; QMenu* m_contextMenu;
MessagesProxyModel *m_proxyModel; MessagesProxyModel* m_proxyModel;
MessagesModel *m_sourceModel; MessagesModel* m_sourceModel;
bool m_columnsAdjusted; bool m_columnsAdjusted;
}; };
#endif // MESSAGESVIEW_H #endif // MESSAGESVIEW_H

View file

@ -1,51 +1,51 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/messagetextbrowser.h" #include "gui/messagetextbrowser.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h" #include "miscellaneous/iconfactory.h"
#include "network-web/networkfactory.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) { QVariant MessageTextBrowser::loadResource(int type, const QUrl& name) {
Q_UNUSED(name) Q_UNUSED(name)
switch (type) { switch (type) {
case QTextDocument::ImageResource: { case QTextDocument::ImageResource: {
if (m_imagePlaceholder.isNull()) { if (m_imagePlaceholder.isNull()) {
m_imagePlaceholder = qApp->icons()->miscPixmap(QSL("image-placeholder")).scaledToWidth(20, Qt::FastTransformation); m_imagePlaceholder = qApp->icons()->miscPixmap(QSL("image-placeholder")).scaledToWidth(20, Qt::FastTransformation);
} }
return m_imagePlaceholder; return m_imagePlaceholder;
} }
default: default:
return QTextBrowser::loadResource(type, name); return QTextBrowser::loadResource(type, name);
} }
} }
void MessageTextBrowser::wheelEvent(QWheelEvent *e) { void MessageTextBrowser::wheelEvent(QWheelEvent* e) {
QTextBrowser::wheelEvent(e); QTextBrowser::wheelEvent(e);
qApp->settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, font().toString()); qApp->settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, font().toString());
} }

View file

@ -1,40 +1,40 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef MESSAGETEXTBROWSER_H #ifndef MESSAGETEXTBROWSER_H
#define MESSAGETEXTBROWSER_H #define MESSAGETEXTBROWSER_H
#include <QTextBrowser> #include <QTextBrowser>
class MessageTextBrowser : public QTextBrowser { class MessageTextBrowser : public QTextBrowser {
Q_OBJECT Q_OBJECT
public: public:
explicit MessageTextBrowser(QWidget *parent = 0); explicit MessageTextBrowser(QWidget* parent = 0);
virtual ~MessageTextBrowser(); virtual ~MessageTextBrowser();
QVariant loadResource(int type, const QUrl &name); QVariant loadResource(int type, const QUrl& name);
protected: protected:
void wheelEvent(QWheelEvent *e); void wheelEvent(QWheelEvent* e);
private: private:
QPixmap m_imagePlaceholder; QPixmap m_imagePlaceholder;
}; };
#endif // MESSAGETEXTBROWSER_H #endif // MESSAGETEXTBROWSER_H

View file

@ -1,65 +1,64 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/newspaperpreviewer.h" #include "gui/newspaperpreviewer.h"
#include "gui/messagepreviewer.h" #include "gui/messagepreviewer.h"
#include "gui/dialogs/formmain.h" #include "gui/dialogs/formmain.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include <QScrollBar> #include <QScrollBar>
NewspaperPreviewer::NewspaperPreviewer(RootItem *root, QList<Message> messages, QWidget *parent) NewspaperPreviewer::NewspaperPreviewer(RootItem* root, QList<Message> messages, QWidget* parent)
: TabContent(parent), m_ui(new Ui::NewspaperPreviewer), m_root(root), m_messages(messages) { : TabContent(parent), m_ui(new Ui::NewspaperPreviewer), m_root(root), m_messages(messages) {
m_ui->setupUi(this); m_ui->setupUi(this);
connect(m_ui->m_btnShowMoreMessages, &QPushButton::clicked, this, &NewspaperPreviewer::showMoreMessages); connect(m_ui->m_btnShowMoreMessages, &QPushButton::clicked, this, &NewspaperPreviewer::showMoreMessages);
showMoreMessages(); showMoreMessages();
} }
NewspaperPreviewer::~NewspaperPreviewer() { NewspaperPreviewer::~NewspaperPreviewer() {
} }
void NewspaperPreviewer::showMoreMessages() { void NewspaperPreviewer::showMoreMessages() {
if (!m_root.isNull()) { if (!m_root.isNull()) {
int current_scroll = m_ui->scrollArea->verticalScrollBar()->value(); int current_scroll = m_ui->scrollArea->verticalScrollBar()->value();
for (int i = 0; i < 10 && !m_messages.isEmpty(); i++) { for (int i = 0; i < 10 && !m_messages.isEmpty(); i++) {
Message msg = m_messages.takeFirst(); Message msg = m_messages.takeFirst();
MessagePreviewer *prev = new MessagePreviewer(this); MessagePreviewer* prev = new MessagePreviewer(this);
QMargins margins = prev->layout()->contentsMargins(); QMargins margins = prev->layout()->contentsMargins();
connect(prev, &MessagePreviewer::requestMessageListReload, this, &NewspaperPreviewer::requestMessageListReload);
connect(prev, &MessagePreviewer::requestMessageListReload, this, &NewspaperPreviewer::requestMessageListReload); margins.setRight(0);
prev->layout()->setContentsMargins(margins);
margins.setRight(0); prev->setFixedHeight(300);
prev->layout()->setContentsMargins(margins); prev->loadMessage(msg, m_root);
prev->setFixedHeight(300); m_ui->m_layout->insertWidget(m_ui->m_layout->count() - 2, prev);
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->m_btnShowMoreMessages->setText(tr("Show more messages (%n remaining)", "", m_messages.size())); m_ui->scrollArea->verticalScrollBar()->setValue(current_scroll);
m_ui->m_btnShowMoreMessages->setEnabled(!m_messages.isEmpty()); }
m_ui->scrollArea->verticalScrollBar()->setValue(current_scroll);
} else {
else { qApp->showGuiMessage(tr("Cannot show more messages"),
qApp->showGuiMessage(tr("Cannot show more messages"), tr("Cannot show more messages because parent feed was removed."),
tr("Cannot show more messages because parent feed was removed."), QSystemTrayIcon::Warning,
QSystemTrayIcon::Warning, qApp->mainForm(), true);
qApp->mainForm(), true); }
} }
}

View file

@ -1,58 +1,58 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef NEWSPAPERPREVIEWER_H #ifndef NEWSPAPERPREVIEWER_H
#define NEWSPAPERPREVIEWER_H #define NEWSPAPERPREVIEWER_H
#include <QWidget> #include <QWidget>
#include "gui/tabcontent.h" #include "gui/tabcontent.h"
#include "ui_newspaperpreviewer.h" #include "ui_newspaperpreviewer.h"
#include "core/message.h" #include "core/message.h"
#include "services/abstract/rootitem.h" #include "services/abstract/rootitem.h"
#include <QPointer> #include <QPointer>
namespace Ui { namespace Ui {
class NewspaperPreviewer; class NewspaperPreviewer;
} }
class RootItem; class RootItem;
class NewspaperPreviewer : public TabContent { class NewspaperPreviewer : public TabContent {
Q_OBJECT Q_OBJECT
public: public:
explicit NewspaperPreviewer(RootItem *root, QList<Message> messages, QWidget *parent = 0); explicit NewspaperPreviewer(RootItem* root, QList<Message> messages, QWidget* parent = 0);
virtual ~NewspaperPreviewer(); virtual ~NewspaperPreviewer();
private slots: private slots:
void showMoreMessages(); void showMoreMessages();
signals: signals:
void requestMessageListReload(bool mark_current_as_read); void requestMessageListReload(bool mark_current_as_read);
private: private:
QScopedPointer<Ui::NewspaperPreviewer> m_ui; QScopedPointer<Ui::NewspaperPreviewer> m_ui;
QPointer<RootItem> m_root; QPointer<RootItem> m_root;
QList<Message> m_messages; QList<Message> m_messages;
}; };
#endif // NEWSPAPERPREVIEWER_H #endif // NEWSPAPERPREVIEWER_H

View file

@ -25,57 +25,56 @@
#include <QAction> #include <QAction>
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) { void PlainToolButton::paintEvent(QPaintEvent* e) {
Q_UNUSED(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);
QPainter p(this); if (isEnabled()) {
QRect rect(QPoint(0, 0), size()); if (underMouse() || isChecked()) {
p.setOpacity(0.7);
}
}
// Set padding. else {
rect.adjust(m_padding, m_padding, -m_padding, -m_padding); p.setOpacity(0.3);
}
if (isEnabled()) { icon().paint(&p, rect);
if (underMouse() || isChecked()) {
p.setOpacity(0.7);
}
}
else {
p.setOpacity(0.3);
}
icon().paint(&p, rect);
} }
int PlainToolButton::padding() const { int PlainToolButton::padding() const {
return m_padding; return m_padding;
} }
void PlainToolButton::setPadding(int padding) { void PlainToolButton::setPadding(int padding) {
m_padding = padding; m_padding = padding;
repaint(); repaint();
} }
void PlainToolButton::setChecked(bool checked) { void PlainToolButton::setChecked(bool checked) {
QToolButton::setChecked(checked); QToolButton::setChecked(checked);
repaint(); repaint();
} }
void PlainToolButton::reactOnActionChange(QAction *action) { void PlainToolButton::reactOnActionChange(QAction* action) {
if (action != nullptr) { if (action != nullptr) {
setEnabled(action->isEnabled()); setEnabled(action->isEnabled());
setCheckable(action->isCheckable()); setCheckable(action->isCheckable());
setChecked(action->isChecked()); setChecked(action->isChecked());
setIcon(action->icon()); setIcon(action->icon());
setToolTip(action->toolTip()); setToolTip(action->toolTip());
} }
} }
void PlainToolButton::reactOnSenderActionChange() { void PlainToolButton::reactOnSenderActionChange() {
reactOnActionChange(qobject_cast<QAction*>(sender())); reactOnActionChange(qobject_cast<QAction*>(sender()));
} }

View file

@ -22,28 +22,28 @@
class PlainToolButton : public QToolButton { class PlainToolButton : public QToolButton {
Q_OBJECT Q_OBJECT
public: public:
// Contructors and destructors. // Contructors and destructors.
explicit PlainToolButton(QWidget *parent = 0); explicit PlainToolButton(QWidget* parent = 0);
virtual ~PlainToolButton(); virtual ~PlainToolButton();
// Padding changers. // Padding changers.
int padding() const; int padding() const;
void setPadding(int padding); void setPadding(int padding);
public slots: public slots:
void setChecked(bool checked); void setChecked(bool checked);
void reactOnActionChange(QAction *action); void reactOnActionChange(QAction* action);
void reactOnSenderActionChange(); void reactOnSenderActionChange();
protected: protected:
// Custom look. // Custom look.
void paintEvent(QPaintEvent *e); void paintEvent(QPaintEvent* e);
private: private:
int m_padding; int m_padding;
}; };
#endif // CLOSEBUTTON_H #endif // CLOSEBUTTON_H

View file

@ -1,202 +1,185 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/settings/settingsbrowsermail.h" #include "gui/settings/settingsbrowsermail.h"
#include "network-web/silentnetworkaccessmanager.h" #include "network-web/silentnetworkaccessmanager.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/textfactory.h" #include "miscellaneous/textfactory.h"
#include "gui/guiutilities.h" #include "gui/guiutilities.h"
#include <QNetworkProxy> #include <QNetworkProxy>
#include <QFileDialog> #include <QFileDialog>
SettingsBrowserMail::SettingsBrowserMail(Settings *settings, QWidget *parent) SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsBrowserMail) { : 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->label, false); GuiUtilities::setLabelAsNotice(m_ui->m_lblExternalEmailInfo, false);
GuiUtilities::setLabelAsNotice(m_ui->m_lblExternalEmailInfo, false); GuiUtilities::setLabelAsNotice(m_ui->m_lblProxyInfo, false);
GuiUtilities::setLabelAsNotice(m_ui->m_lblProxyInfo, false); #if defined(USE_WEBENGINE)
m_ui->m_checkOpenLinksInExternal->setVisible(false);
#if defined(USE_WEBENGINE) #else
m_ui->m_checkOpenLinksInExternal->setVisible(false); connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings);
#else #endif
connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::dirtifySettings);
#endif connect(m_ui->m_txtProxyHost, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyPassword, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_txtProxyUsername, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyHost, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_spinProxyPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyPassword, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_grpCustomExternalBrowser, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyUsername, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_grpCustomExternalEmail, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_spinProxyPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_txtExternalBrowserArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_grpCustomExternalBrowser, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_txtExternalBrowserExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_grpCustomExternalEmail, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_txtExternalEmailArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtExternalBrowserArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_txtExternalEmailExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtExternalBrowserExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::onProxyTypeChanged);
connect(m_ui->m_txtExternalEmailArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_checkShowPassword, &QCheckBox::stateChanged, this, &SettingsBrowserMail::displayProxyPassword);
connect(m_ui->m_txtExternalEmailExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_cmbExternalBrowserPreset, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::changeDefaultBrowserArguments);
connect(m_ui->m_btnExternalBrowserExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectBrowserExecutable);
connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::onProxyTypeChanged); connect(m_ui->m_cmbExternalEmailPreset, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::changeDefaultEmailArguments);
connect(m_ui->m_checkShowPassword, &QCheckBox::stateChanged, this, &SettingsBrowserMail::displayProxyPassword); connect(m_ui->m_btnExternalEmailExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectEmailExecutable);
connect(m_ui->m_cmbExternalBrowserPreset, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::changeDefaultBrowserArguments); }
connect(m_ui->m_btnExternalBrowserExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectBrowserExecutable);
connect(m_ui->m_cmbExternalEmailPreset, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::changeDefaultEmailArguments); SettingsBrowserMail::~SettingsBrowserMail() {
connect(m_ui->m_btnExternalEmailExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectEmailExecutable); delete m_ui;
} }
SettingsBrowserMail::~SettingsBrowserMail() { void SettingsBrowserMail::changeDefaultBrowserArguments(int index) {
delete m_ui; if (index != 0) {
} m_ui->m_txtExternalBrowserArguments->setText(m_ui->m_cmbExternalBrowserPreset->itemData(index).toString());
}
void SettingsBrowserMail::changeDefaultBrowserArguments(int index) { }
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->getHomeFolderPath(),
void SettingsBrowserMail::selectBrowserExecutable() { //: File filter for external browser selection dialog.
const QString executable_file = QFileDialog::getOpenFileName(this, #if defined(Q_OS_LINUX)
tr("Select web browser executable"), tr("Executables (*)")
qApp->getHomeFolderPath(), #else
//: File filter for external browser selection dialog. tr("Executables (*.*)")
#if defined(Q_OS_LINUX) #endif
tr("Executables (*)") );
#else
tr("Executables (*.*)") if (!executable_file.isEmpty()) {
#endif 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);
}
void SettingsBrowserMail::displayProxyPassword(int state) {
if (state == Qt::Checked) { else {
m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::Normal); m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit);
} }
else { }
m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit);
} void SettingsBrowserMail::onProxyTypeChanged(int index) {
} const QNetworkProxy::ProxyType selected_type = static_cast<QNetworkProxy::ProxyType>(m_ui->m_cmbProxyType->itemData(index).toInt());
const bool is_proxy_selected = selected_type != QNetworkProxy::NoProxy && selected_type != QNetworkProxy::DefaultProxy;
void SettingsBrowserMail::onProxyTypeChanged(int index) { m_ui->m_txtProxyHost->setEnabled(is_proxy_selected);
const QNetworkProxy::ProxyType selected_type = static_cast<QNetworkProxy::ProxyType>(m_ui->m_cmbProxyType->itemData(index).toInt()); m_ui->m_txtProxyPassword->setEnabled(is_proxy_selected);
const bool is_proxy_selected = selected_type != QNetworkProxy::NoProxy && selected_type != QNetworkProxy::DefaultProxy; m_ui->m_txtProxyUsername->setEnabled(is_proxy_selected);
m_ui->m_spinProxyPort->setEnabled(is_proxy_selected);
m_ui->m_txtProxyHost->setEnabled(is_proxy_selected); m_ui->m_checkShowPassword->setEnabled(is_proxy_selected);
m_ui->m_txtProxyPassword->setEnabled(is_proxy_selected); m_ui->m_lblProxyHost->setEnabled(is_proxy_selected);
m_ui->m_txtProxyUsername->setEnabled(is_proxy_selected); m_ui->m_lblProxyInfo->setEnabled(is_proxy_selected);
m_ui->m_spinProxyPort->setEnabled(is_proxy_selected); m_ui->m_lblProxyPassword->setEnabled(is_proxy_selected);
m_ui->m_checkShowPassword->setEnabled(is_proxy_selected); m_ui->m_lblProxyPort->setEnabled(is_proxy_selected);
m_ui->m_lblProxyHost->setEnabled(is_proxy_selected); m_ui->m_lblProxyUsername->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); void SettingsBrowserMail::changeDefaultEmailArguments(int index) {
m_ui->m_lblProxyUsername->setEnabled(is_proxy_selected); if (index != 0) {
} m_ui->m_txtExternalEmailArguments->setText(m_ui->m_cmbExternalEmailPreset->itemData(index).toString());
}
void SettingsBrowserMail::changeDefaultEmailArguments(int index) { }
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->getHomeFolderPath(),
void SettingsBrowserMail::selectEmailExecutable() { //: File filter for external e-mail selection dialog.
QString executable_file = QFileDialog::getOpenFileName(this, #if defined(Q_OS_LINUX)
tr("Select e-mail executable"), tr("Executables (*)")
qApp->getHomeFolderPath(), #else
//: File filter for external e-mail selection dialog. tr("Executables (*.*)")
#if defined(Q_OS_LINUX) #endif
tr("Executables (*)") );
#else
tr("Executables (*.*)") if (!executable_file.isEmpty()) {
#endif 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();
} #if !defined(USE_WEBENGINE)
m_ui->m_checkOpenLinksInExternal->setChecked(settings()->value(GROUP(Browser),
void SettingsBrowserMail::loadSettings() { SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool());
onBeginLoadSettings(); #endif
// Load settings of web browser GUI.
#if !defined(USE_WEBENGINE) m_ui->m_cmbExternalBrowserPreset->addItem(tr("Opera 12 or older"), QSL("-nosession %1"));
m_ui->m_checkOpenLinksInExternal->setChecked(settings()->value(GROUP(Browser), m_ui->m_txtExternalBrowserExecutable->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserExecutable)).toString());
SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool()); m_ui->m_txtExternalBrowserArguments->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserArguments)).toString());
#endif m_ui->m_grpCustomExternalBrowser->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserEnabled)).toBool());
// Load settings of e-mail.
// Load settings of web browser GUI. m_ui->m_cmbExternalEmailPreset->addItem(tr("Mozilla Thunderbird"), QSL("-compose \"subject='%1',body='%2'\""));
m_ui->m_cmbExternalBrowserPreset->addItem(tr("Opera 12 or older"), QSL("-nosession %1")); m_ui->m_txtExternalEmailExecutable->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailExecutable)).toString());
m_ui->m_txtExternalBrowserExecutable->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserExecutable)).toString()); m_ui->m_txtExternalEmailArguments->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString());
m_ui->m_txtExternalBrowserArguments->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserArguments)).toString()); m_ui->m_grpCustomExternalEmail->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool());
m_ui->m_grpCustomExternalBrowser->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserEnabled)).toBool()); m_ui->m_cmbProxyType->addItem(tr("No proxy"), QNetworkProxy::NoProxy);
m_ui->m_cmbProxyType->addItem(tr("System proxy"), QNetworkProxy::DefaultProxy);
// Load settings of e-mail. m_ui->m_cmbProxyType->addItem(tr("Socks5"), QNetworkProxy::Socks5Proxy);
m_ui->m_cmbExternalEmailPreset->addItem(tr("Mozilla Thunderbird"), QSL("-compose \"subject='%1',body='%2'\"")); m_ui->m_cmbProxyType->addItem(tr("Http"), QNetworkProxy::HttpProxy);
m_ui->m_txtExternalEmailExecutable->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailExecutable)).toString()); // Load the settings.
m_ui->m_txtExternalEmailArguments->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString()); QNetworkProxy::ProxyType selected_proxy_type = static_cast<QNetworkProxy::ProxyType>(settings()->value(GROUP(Proxy), SETTING(Proxy::Type)).toInt());
m_ui->m_grpCustomExternalEmail->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool()); 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_cmbProxyType->addItem(tr("No proxy"), QNetworkProxy::NoProxy); m_ui->m_txtProxyUsername->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Username)).toString());
m_ui->m_cmbProxyType->addItem(tr("System proxy"), QNetworkProxy::DefaultProxy); m_ui->m_txtProxyPassword->setText(TextFactory::decrypt(settings()->value(GROUP(Proxy), SETTING(Proxy::Password)).toString()));
m_ui->m_cmbProxyType->addItem(tr("Socks5"), QNetworkProxy::Socks5Proxy); m_ui->m_spinProxyPort->setValue(settings()->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt());
m_ui->m_cmbProxyType->addItem(tr("Http"), QNetworkProxy::HttpProxy); onEndLoadSettings();
}
// Load the settings.
QNetworkProxy::ProxyType selected_proxy_type = static_cast<QNetworkProxy::ProxyType>(settings()->value(GROUP(Proxy), SETTING(Proxy::Type)).toInt()); void SettingsBrowserMail::saveSettings() {
onBeginSaveSettings();
m_ui->m_cmbProxyType->setCurrentIndex(m_ui->m_cmbProxyType->findData(selected_proxy_type)); #if !defined(USE_WEBENGINE)
m_ui->m_txtProxyHost->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Host)).toString()); settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, m_ui->m_checkOpenLinksInExternal->isChecked());
m_ui->m_txtProxyUsername->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Username)).toString()); #endif
m_ui->m_txtProxyPassword->setText(TextFactory::decrypt(settings()->value(GROUP(Proxy), SETTING(Proxy::Password)).toString())); // Save settings of GUI of web browser.
m_ui->m_spinProxyPort->setValue(settings()->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt()); settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserEnabled, m_ui->m_grpCustomExternalBrowser->isChecked());
settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserExecutable, m_ui->m_txtExternalBrowserExecutable->text());
onEndLoadSettings(); 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());
void SettingsBrowserMail::saveSettings() { settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailArguments, m_ui->m_txtExternalEmailArguments->text());
onBeginSaveSettings(); 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()));
#if !defined(USE_WEBENGINE) settings()->setValue(GROUP(Proxy), Proxy::Host, m_ui->m_txtProxyHost->text());
settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, m_ui->m_checkOpenLinksInExternal->isChecked()); settings()->setValue(GROUP(Proxy), Proxy::Username, m_ui->m_txtProxyUsername->text());
#endif settings()->setValue(GROUP(Proxy), Proxy::Password, TextFactory::encrypt(m_ui->m_txtProxyPassword->text()));
settings()->setValue(GROUP(Proxy), Proxy::Port, m_ui->m_spinProxyPort->value());
// Save settings of GUI of web browser. // Reload settings for all network access managers.
settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserEnabled, m_ui->m_grpCustomExternalBrowser->isChecked()); SilentNetworkAccessManager::instance()->loadSettings();
settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserExecutable, m_ui->m_txtExternalBrowserExecutable->text()); onEndSaveSettings();
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());
// Reload settings for all network access managers.
SilentNetworkAccessManager::instance()->loadSettings();
onEndSaveSettings();
}

View file

@ -1,52 +1,52 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef SETTINGSBROWSERMAIL_H #ifndef SETTINGSBROWSERMAIL_H
#define SETTINGSBROWSERMAIL_H #define SETTINGSBROWSERMAIL_H
#include "gui/settings/settingspanel.h" #include "gui/settings/settingspanel.h"
#include "ui_settingsbrowsermail.h" #include "ui_settingsbrowsermail.h"
class SettingsBrowserMail : public SettingsPanel { class SettingsBrowserMail : public SettingsPanel {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsBrowserMail(Settings *settings, QWidget *parent = 0); explicit SettingsBrowserMail(Settings* settings, QWidget* parent = 0);
virtual ~SettingsBrowserMail(); virtual ~SettingsBrowserMail();
inline QString title() const { inline QString title() const {
return tr("Web browser & e-mail & proxy"); return tr("Web browser & e-mail & proxy");
} }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
private slots: private slots:
void changeDefaultBrowserArguments(int index); void changeDefaultBrowserArguments(int index);
void selectBrowserExecutable(); void selectBrowserExecutable();
void changeDefaultEmailArguments(int index); void changeDefaultEmailArguments(int index);
void selectEmailExecutable(); void selectEmailExecutable();
void displayProxyPassword(int state); void displayProxyPassword(int state);
void onProxyTypeChanged(int index); void onProxyTypeChanged(int index);
private: private:
Ui::SettingsBrowserMail *m_ui; Ui::SettingsBrowserMail* m_ui;
}; };
#endif // SETTINGSBROWSERMAIL_H #endif // SETTINGSBROWSERMAIL_H

View file

@ -1,216 +1,206 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/settings/settingsdatabase.h" #include "gui/settings/settingsdatabase.h"
#include "miscellaneous/databasefactory.h" #include "miscellaneous/databasefactory.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/textfactory.h" #include "miscellaneous/textfactory.h"
#include "gui/guiutilities.h" #include "gui/guiutilities.h"
SettingsDatabase::SettingsDatabase(Settings *settings, QWidget *parent) SettingsDatabase::SettingsDatabase(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsDatabase) { : SettingsPanel(settings, parent), m_ui(new Ui::SettingsDatabase) {
m_ui->setupUi(this); m_ui->setupUi(this);
GuiUtilities::setLabelAsNotice(m_ui->m_lblDataStorageWarning, true);
GuiUtilities::setLabelAsNotice(m_ui->m_lblDataStorageWarning, true); GuiUtilities::setLabelAsNotice(m_ui->m_lblMysqlInfo, false);
GuiUtilities::setLabelAsNotice(m_ui->m_lblMysqlInfo, false); GuiUtilities::setLabelAsNotice(m_ui->m_lblSqliteInMemoryWarnings, true);
GuiUtilities::setLabelAsNotice(m_ui->m_lblSqliteInMemoryWarnings, true); connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_txtMysqlDatabase->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_txtMysqlHostname->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlDatabase->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_txtMysqlPassword->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_checkUseTransactions, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_txtMysqlUsername->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_checkUseTransactions, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_spinMysqlPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::selectSqlBackend);
connect(m_ui->m_spinMysqlPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsDatabase::dirtifySettings); 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_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::selectSqlBackend); connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlHostnameChanged);
connect(m_ui->m_checkMysqlShowPassword, &QCheckBox::toggled, this, &SettingsDatabase::switchMysqlPasswordVisiblity); connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlPasswordChanged);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlUsernameChanged); connect(m_ui->m_txtMysqlDatabase->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlDatabaseChanged);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlHostnameChanged); connect(m_ui->m_btnMysqlTestSetup, &QPushButton::clicked, this, &SettingsDatabase::mysqlTestConnection);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlPasswordChanged); connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlDatabase->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlDatabaseChanged); connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_btnMysqlTestSetup, &QPushButton::clicked, this, &SettingsDatabase::mysqlTestConnection); 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_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::requireRestart); connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::requireRestart); connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textEdited, 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); SettingsDatabase::~SettingsDatabase() {
connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart); delete m_ui;
} }
SettingsDatabase::~SettingsDatabase() { void SettingsDatabase::mysqlTestConnection() {
delete m_ui; 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(),
void SettingsDatabase::mysqlTestConnection() { m_ui->m_txtMysqlUsername->lineEdit()->text(),
const DatabaseFactory::MySQLError error_code = qApp->database()->mysqlTestConnection(m_ui->m_txtMysqlHostname->lineEdit()->text(), m_ui->m_txtMysqlPassword->lineEdit()->text());
m_ui->m_spinMysqlPort->value(), const QString interpretation = qApp->database()->mysqlInterpretErrorCode(error_code);
m_ui->m_txtMysqlDatabase->lineEdit()->text(),
m_ui->m_txtMysqlUsername->lineEdit()->text(), switch (error_code) {
m_ui->m_txtMysqlPassword->lineEdit()->text()); case DatabaseFactory::MySQLOk:
const QString interpretation = qApp->database()->mysqlInterpretErrorCode(error_code); case DatabaseFactory::MySQLUnknownDatabase:
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Ok, interpretation, interpretation);
break;
switch (error_code) {
case DatabaseFactory::MySQLOk: default:
case DatabaseFactory::MySQLUnknownDatabase: m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Error, interpretation, interpretation);
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Ok, interpretation, interpretation); break;
break; }
}
default:
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Error, interpretation, interpretation); void SettingsDatabase::onMysqlHostnameChanged(const QString& new_hostname) {
break; if (new_hostname.isEmpty()) {
} m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Warning, tr("Hostname is empty."));
} }
void SettingsDatabase::onMysqlHostnameChanged(const QString &new_hostname) { else {
if (new_hostname.isEmpty()) { m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Ok, tr("Hostname looks ok."));
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."));
}
void SettingsDatabase::onMysqlUsernameChanged(const QString &new_username) {
if (new_username.isEmpty()) { else {
m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Warning, tr("Username is empty.")); m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Ok, tr("Username looks ok."));
} }
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."));
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."));
else { }
m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Ok, tr("Password looks ok.")); }
}
} void SettingsDatabase::onMysqlDatabaseChanged(const QString& new_database) {
if (new_database.isEmpty()) {
void SettingsDatabase::onMysqlDatabaseChanged(const QString &new_database) { m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Warning, tr("Working database is empty."));
if (new_database.isEmpty()) { }
m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Warning, tr("Working database is empty."));
} else {
else { m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Ok, tr("Working database is ok."));
m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Ok, tr("Working database is ok.")); }
} }
}
void SettingsDatabase::selectSqlBackend(int index) {
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) {
if (selected_db_driver == APP_DB_SQLITE_DRIVER) { m_ui->m_stackedDatabaseDriver->setCurrentIndex(0);
m_ui->m_stackedDatabaseDriver->setCurrentIndex(0); }
}
else if (selected_db_driver == APP_DB_MYSQL_DRIVER) { else if (selected_db_driver == APP_DB_MYSQL_DRIVER) {
m_ui->m_stackedDatabaseDriver->setCurrentIndex(1); m_ui->m_stackedDatabaseDriver->setCurrentIndex(1);
} }
else {
qWarning("GUI for given database driver '%s' is not available.", qPrintable(selected_db_driver)); 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); void SettingsDatabase::switchMysqlPasswordVisiblity(bool visible) {
} m_ui->m_txtMysqlPassword->lineEdit()->setEchoMode(visible ? QLineEdit::Normal : QLineEdit::Password);
}
void SettingsDatabase::loadSettings() {
onBeginLoadSettings(); void SettingsDatabase::loadSettings() {
onBeginLoadSettings();
m_ui->m_checkUseTransactions->setChecked(qApp->settings()->value(GROUP(Database), SETTING(Database::UseTransactions)).toBool()); 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.")); 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.
// Load SQLite. m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::SQLITE), APP_DB_SQLITE_DRIVER);
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());
// Load in-memory database status.
m_ui->m_checkSqliteUseInMemoryDatabase->setChecked(settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool()); if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
onMysqlHostnameChanged(QString());
if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) { onMysqlUsernameChanged(QString());
onMysqlHostnameChanged(QString()); onMysqlPasswordChanged(QString());
onMysqlUsernameChanged(QString()); onMysqlDatabaseChanged(QString());
onMysqlPasswordChanged(QString()); // Load MySQL.
onMysqlDatabaseChanged(QString()); m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::MYSQL), APP_DB_MYSQL_DRIVER);
// Setup placeholders.
// Load MySQL. m_ui->m_txtMysqlHostname->lineEdit()->setPlaceholderText(tr("Hostname of your MySQL server"));
m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::MYSQL), APP_DB_MYSQL_DRIVER); m_ui->m_txtMysqlUsername->lineEdit()->setPlaceholderText(tr("Username to login with"));
m_ui->m_txtMysqlPassword->lineEdit()->setPlaceholderText(tr("Password for your username"));
// Setup placeholders. m_ui->m_txtMysqlDatabase->lineEdit()->setPlaceholderText(tr("Working database which you have full access to."));
m_ui->m_txtMysqlHostname->lineEdit()->setPlaceholderText(tr("Hostname of your MySQL server")); m_ui->m_txtMysqlHostname->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString());
m_ui->m_txtMysqlUsername->lineEdit()->setPlaceholderText(tr("Username to login with")); m_ui->m_txtMysqlUsername->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString());
m_ui->m_txtMysqlPassword->lineEdit()->setPlaceholderText(tr("Password for your username")); m_ui->m_txtMysqlPassword->lineEdit()->setText(TextFactory::decrypt(settings()->value(GROUP(Database), SETTING(Database::MySQLPassword)).toString()));
m_ui->m_txtMysqlDatabase->lineEdit()->setPlaceholderText(tr("Working database which you have full access to.")); 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_txtMysqlHostname->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString()); m_ui->m_checkMysqlShowPassword->setChecked(false);
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()); int index_current_backend = m_ui->m_cmbDatabaseDriver->findData(settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString());
m_ui->m_spinMysqlPort->setValue(settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
if (index_current_backend >= 0) {
m_ui->m_checkMysqlShowPassword->setChecked(false); m_ui->m_cmbDatabaseDriver->setCurrentIndex(index_current_backend);
} }
int index_current_backend = m_ui->m_cmbDatabaseDriver->findData(settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString()); onEndLoadSettings();
}
if (index_current_backend >= 0) {
m_ui->m_cmbDatabaseDriver->setCurrentIndex(index_current_backend); void SettingsDatabase::saveSettings() {
} onBeginSaveSettings();
// Setup in-memory database status.
onEndLoadSettings(); 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());
void SettingsDatabase::saveSettings() { // Save data storage settings.
onBeginSaveSettings(); 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();
// Setup in-memory database status. // Save SQLite.
const bool original_inmemory = settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool(); settings()->setValue(GROUP(Database), Database::UseInMemory, new_inmemory);
const bool new_inmemory = m_ui->m_checkSqliteUseInMemoryDatabase->isChecked();
if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
qApp->settings()->setValue(GROUP(Database), Database::UseTransactions, m_ui->m_checkUseTransactions->isChecked()); // Save MySQL.
settings()->setValue(GROUP(Database), Database::MySQLHostname, m_ui->m_txtMysqlHostname->lineEdit()->text());
// Save data storage settings. settings()->setValue(GROUP(Database), Database::MySQLUsername, m_ui->m_txtMysqlUsername->lineEdit()->text());
QString original_db_driver = settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString(); settings()->setValue(GROUP(Database), Database::MySQLPassword, TextFactory::encrypt(m_ui->m_txtMysqlPassword->lineEdit()->text()));
QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(m_ui->m_cmbDatabaseDriver->currentIndex()).toString(); settings()->setValue(GROUP(Database), Database::MySQLDatabase, m_ui->m_txtMysqlDatabase->lineEdit()->text());
settings()->setValue(GROUP(Database), Database::MySQLPort, m_ui->m_spinMysqlPort->value());
// Save SQLite. }
settings()->setValue(GROUP(Database), Database::UseInMemory, new_inmemory);
settings()->setValue(GROUP(Database), Database::ActiveDriver, selected_db_driver);
if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
// Save MySQL. if (original_db_driver != selected_db_driver || original_inmemory != new_inmemory) {
settings()->setValue(GROUP(Database), Database::MySQLHostname, m_ui->m_txtMysqlHostname->lineEdit()->text()); requireRestart();
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()); onEndSaveSettings();
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();
}

View file

@ -1,52 +1,52 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef SETTINGSDATABASE_H #ifndef SETTINGSDATABASE_H
#define SETTINGSDATABASE_H #define SETTINGSDATABASE_H
#include "gui/settings/settingspanel.h" #include "gui/settings/settingspanel.h"
#include "ui_settingsdatabase.h" #include "ui_settingsdatabase.h"
class SettingsDatabase : public SettingsPanel { class SettingsDatabase : public SettingsPanel {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsDatabase(Settings *settings, QWidget *parent = 0); explicit SettingsDatabase(Settings* settings, QWidget* parent = 0);
virtual ~SettingsDatabase(); virtual ~SettingsDatabase();
inline QString title() const { inline QString title() const {
return tr("Data storage"); return tr("Data storage");
} }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
private: private:
void mysqlTestConnection(); void mysqlTestConnection();
void onMysqlHostnameChanged(const QString &new_hostname); void onMysqlHostnameChanged(const QString& new_hostname);
void onMysqlUsernameChanged(const QString &new_username); void onMysqlUsernameChanged(const QString& new_username);
void onMysqlPasswordChanged(const QString &new_password); void onMysqlPasswordChanged(const QString& new_password);
void onMysqlDatabaseChanged(const QString &new_database); void onMysqlDatabaseChanged(const QString& new_database);
void selectSqlBackend(int index); void selectSqlBackend(int index);
void switchMysqlPasswordVisiblity(bool visible); void switchMysqlPasswordVisiblity(bool visible);
Ui::SettingsDatabase *m_ui; Ui::SettingsDatabase* m_ui;
}; };
#endif // SETTINGSDATABASE_H #endif // SETTINGSDATABASE_H

View file

@ -1,75 +1,69 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/settings/settingsdownloads.h" #include "gui/settings/settingsdownloads.h"
#include "miscellaneous/settings.h" #include "miscellaneous/settings.h"
#include "network-web/downloadmanager.h" #include "network-web/downloadmanager.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include <QFileDialog> #include <QFileDialog>
SettingsDownloads::SettingsDownloads(Settings *settings, QWidget *parent) SettingsDownloads::SettingsDownloads(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsDownloads) { : SettingsPanel(settings, parent), m_ui(new Ui::SettingsDownloads) {
m_ui->setupUi(this); m_ui->setupUi(this);
connect(m_ui->m_checkOpenManagerWhenDownloadStarts, &QCheckBox::toggled, this, &SettingsDownloads::dirtifySettings);
connect(m_ui->m_checkOpenManagerWhenDownloadStarts, &QCheckBox::toggled, this, &SettingsDownloads::dirtifySettings); connect(m_ui->m_txtDownloadsTargetDirectory, &QLineEdit::textChanged, 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_rbDownloadsAskEachFile, &QRadioButton::toggled, this, &SettingsDownloads::dirtifySettings); connect(m_ui->m_btnDownloadsTargetDirectory, &QPushButton::clicked, this, &SettingsDownloads::selectDownloadsDirectory);
}
connect(m_ui->m_btnDownloadsTargetDirectory, &QPushButton::clicked, this, &SettingsDownloads::selectDownloadsDirectory);
} SettingsDownloads::~SettingsDownloads() {
delete m_ui;
SettingsDownloads::~SettingsDownloads() { }
delete m_ui;
} void SettingsDownloads::selectDownloadsDirectory() {
const QString target_directory = QFileDialog::getExistingDirectory(this,
void SettingsDownloads::selectDownloadsDirectory() { tr("Select downloads target directory"),
const QString target_directory = QFileDialog::getExistingDirectory(this, m_ui->m_txtDownloadsTargetDirectory->text()
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();
void SettingsDownloads::loadSettings() { m_ui->m_checkOpenManagerWhenDownloadStarts->setChecked(settings()->value(GROUP(Downloads),
onBeginLoadSettings(); SETTING(Downloads::ShowDownloadsWhenNewDownloadStarts)).toBool());
m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(settings()->value(GROUP(Downloads),
m_ui->m_checkOpenManagerWhenDownloadStarts->setChecked(settings()->value(GROUP(Downloads), SETTING(Downloads::TargetDirectory)).toString()));
SETTING(Downloads::ShowDownloadsWhenNewDownloadStarts)).toBool()); m_ui->m_rbDownloadsAskEachFile->setChecked(settings()->value(GROUP(Downloads),
m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(settings()->value(GROUP(Downloads), SETTING(Downloads::AlwaysPromptForFilename)).toBool());
SETTING(Downloads::TargetDirectory)).toString())); onEndLoadSettings();
m_ui->m_rbDownloadsAskEachFile->setChecked(settings()->value(GROUP(Downloads), }
SETTING(Downloads::AlwaysPromptForFilename)).toBool());
void SettingsDownloads::saveSettings() {
onEndLoadSettings(); onBeginSaveSettings();
} settings()->setValue(GROUP(Downloads), Downloads::ShowDownloadsWhenNewDownloadStarts, m_ui->m_checkOpenManagerWhenDownloadStarts->isChecked());
settings()->setValue(GROUP(Downloads), Downloads::TargetDirectory, m_ui->m_txtDownloadsTargetDirectory->text());
void SettingsDownloads::saveSettings() { settings()->setValue(GROUP(Downloads), Downloads::AlwaysPromptForFilename, m_ui->m_rbDownloadsAskEachFile->isChecked());
onBeginSaveSettings(); qApp->downloadManager()->setDownloadDirectory(m_ui->m_txtDownloadsTargetDirectory->text());
onEndSaveSettings();
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();
}

View file

@ -1,47 +1,47 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef SETTINGSDOWNLOADS_H #ifndef SETTINGSDOWNLOADS_H
#define SETTINGSDOWNLOADS_H #define SETTINGSDOWNLOADS_H
#include "gui/settings/settingspanel.h" #include "gui/settings/settingspanel.h"
#include "ui_settingsdownloads.h" #include "ui_settingsdownloads.h"
class SettingsDownloads : public SettingsPanel { class SettingsDownloads : public SettingsPanel {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsDownloads(Settings *settings, QWidget *parent = 0); explicit SettingsDownloads(Settings* settings, QWidget* parent = 0);
virtual ~SettingsDownloads(); virtual ~SettingsDownloads();
inline QString title() const { inline QString title() const {
return tr("Downloads"); return tr("Downloads");
} }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
private slots: private slots:
void selectDownloadsDirectory(); void selectDownloadsDirectory();
private: private:
Ui::SettingsDownloads *m_ui; Ui::SettingsDownloads* m_ui;
}; };
#endif // SETTINGSDOWNLOADS_H #endif // SETTINGSDOWNLOADS_H

View file

@ -1,150 +1,139 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/settings/settingsfeedsmessages.h" #include "gui/settings/settingsfeedsmessages.h"
#include "definitions/definitions.h" #include "definitions/definitions.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
#include "miscellaneous/feedreader.h" #include "miscellaneous/feedreader.h"
#include "gui/dialogs/formmain.h" #include "gui/dialogs/formmain.h"
#include "gui/feedmessageviewer.h" #include "gui/feedmessageviewer.h"
#include "gui/feedsview.h" #include "gui/feedsview.h"
#include "gui/messagesview.h" #include "gui/messagesview.h"
#include "gui/timespinbox.h" #include "gui/timespinbox.h"
#include "gui/guiutilities.h" #include "gui/guiutilities.h"
#include <QFontDialog> #include <QFontDialog>
SettingsFeedsMessages::SettingsFeedsMessages(Settings *settings, QWidget *parent) SettingsFeedsMessages::SettingsFeedsMessages(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsFeedsMessages){ : SettingsPanel(settings, parent), m_ui(new Ui::SettingsFeedsMessages) {
m_ui->setupUi(this); m_ui->setupUi(this);
initializeMessageDateFormats(); initializeMessageDateFormats();
GuiUtilities::setLabelAsNotice(m_ui->label_9, false);
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_checkAutoUpdateNotification, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_checkKeppMessagesInTheMiddle, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_checkMessagesDateTimeFormat, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkKeppMessagesInTheMiddle, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_checkRemoveReadMessagesOnExit, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkMessagesDateTimeFormat, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_checkUpdateAllFeedsOnStartup, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkRemoveReadMessagesOnExit, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_spinAutoUpdateInterval, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
connect(m_ui->m_checkUpdateAllFeedsOnStartup, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings); this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_spinAutoUpdateInterval, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), connect(m_ui->m_spinHeightImageAttachments, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
this, &SettingsFeedsMessages::dirtifySettings); this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_spinHeightImageAttachments, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, m_ui->m_spinAutoUpdateInterval, &TimeSpinBox::setEnabled);
this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_spinFeedUpdateTimeout, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, m_ui->m_spinAutoUpdateInterval, &TimeSpinBox::setEnabled); connect(m_ui->m_cmbMessagesDateTimeFormat, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_spinFeedUpdateTimeout, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_cmbCountsFeedList, &QComboBox::currentTextChanged, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_cmbMessagesDateTimeFormat, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_cmbCountsFeedList, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_cmbCountsFeedList, &QComboBox::currentTextChanged, this, &SettingsFeedsMessages::dirtifySettings); connect(m_ui->m_btnChangeMessagesFont, &QPushButton::clicked, this, &SettingsFeedsMessages::changeMessagesFont);
connect(m_ui->m_cmbCountsFeedList, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsFeedsMessages::dirtifySettings);
if (!m_ui->m_spinFeedUpdateTimeout->suffix().startsWith(' ')) {
connect(m_ui->m_btnChangeMessagesFont, &QPushButton::clicked, this, &SettingsFeedsMessages::changeMessagesFont); 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;
}
SettingsFeedsMessages::~SettingsFeedsMessages() {
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") <<
void SettingsFeedsMessages::initializeMessageDateFormats() { QSL("yyyy-MM-dd HH:mm:ss.z") << QSL("yyyy-MM-ddThh:mm:ss") <<
QStringList best_formats; best_formats << QSL("d/M/yyyy hh:mm:ss") << QSL("ddd, d. M. yy hh:mm:ss") << QSL("MMM d yyyy hh:mm:ss");;
QSL("yyyy-MM-dd HH:mm:ss.z") << QSL("yyyy-MM-ddThh:mm:ss") << const QLocale current_locale = qApp->localization()->loadedLocale();
QSL("MMM d yyyy hh:mm:ss");; const QDateTime current_dt = QDateTime::currentDateTime();
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);
foreach (const QString &format, best_formats) { }
m_ui->m_cmbMessagesDateTimeFormat->addItem(current_locale.toString(current_dt, format), format); }
}
} void SettingsFeedsMessages::changeMessagesFont() {
bool ok;
void SettingsFeedsMessages::changeMessagesFont() { QFont new_font = QFontDialog::getFont(&ok, m_ui->m_lblMessagesFont->font(),
bool ok; this, tr("Select new font for message viewer"),
QFont new_font = QFontDialog::getFont(&ok, m_ui->m_lblMessagesFont->font(), QFontDialog::DontUseNativeDialog);
this, tr("Select new font for message viewer"),
QFontDialog::DontUseNativeDialog); if (ok) {
m_ui->m_lblMessagesFont->setFont(new_font);
if (ok) { dirtifySettings();
m_ui->m_lblMessagesFont->setFont(new_font); }
dirtifySettings(); }
}
} void SettingsFeedsMessages::loadSettings() {
onBeginLoadSettings();
void SettingsFeedsMessages::loadSettings() { m_ui->m_checkAutoUpdateNotification->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::EnableAutoUpdateNotification)).toBool());
onBeginLoadSettings(); 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_checkAutoUpdateNotification->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::EnableAutoUpdateNotification)).toBool()); m_ui->m_checkAutoUpdate->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateEnabled)).toBool());
m_ui->m_checkKeppMessagesInTheMiddle->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::KeepCursorInCenter)).toBool()); m_ui->m_spinAutoUpdateInterval->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateInterval)).toInt());
m_ui->m_checkRemoveReadMessagesOnExit->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool()); m_ui->m_spinFeedUpdateTimeout->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt());
m_ui->m_checkAutoUpdate->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateEnabled)).toBool()); m_ui->m_checkUpdateAllFeedsOnStartup->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool());
m_ui->m_spinAutoUpdateInterval->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateInterval)).toInt()); m_ui->m_cmbCountsFeedList->addItems(QStringList() << "(%unread)" << "[%unread]" << "%unread/%all" << "%unread-%all" << "[%unread|%all]");
m_ui->m_spinFeedUpdateTimeout->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt()); m_ui->m_cmbCountsFeedList->setEditText(settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString());
m_ui->m_checkUpdateAllFeedsOnStartup->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool()); m_ui->m_spinHeightImageAttachments->setValue(settings()->value(GROUP(Messages), SETTING(Messages::MessageHeadImageHeight)).toInt());
m_ui->m_cmbCountsFeedList->addItems(QStringList() << "(%unread)" << "[%unread]" << "%unread/%all" << "%unread-%all" << "[%unread|%all]"); initializeMessageDateFormats();
m_ui->m_cmbCountsFeedList->setEditText(settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString()); m_ui->m_checkMessagesDateTimeFormat->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool());
m_ui->m_spinHeightImageAttachments->setValue(settings()->value(GROUP(Messages), SETTING(Messages::MessageHeadImageHeight)).toInt()); const int index_format = m_ui->m_cmbMessagesDateTimeFormat->findData(settings()->value(GROUP(Messages), SETTING(Messages::CustomDateFormat)).toString());
initializeMessageDateFormats(); if (index_format >= 0) {
m_ui->m_cmbMessagesDateTimeFormat->setCurrentIndex(index_format);
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());
m_ui->m_lblMessagesFont->setText(tr("Font preview"));
if (index_format >= 0) { QFont fon;
m_ui->m_cmbMessagesDateTimeFormat->setCurrentIndex(index_format); fon.fromString(settings()->value(GROUP(Messages),
} SETTING(Messages::PreviewerFontStandard)).toString());
m_ui->m_lblMessagesFont->setFont(fon);
m_ui->m_lblMessagesFont->setText(tr("Font preview")); onEndLoadSettings();
QFont fon; }
fon.fromString(settings()->value(GROUP(Messages),
SETTING(Messages::PreviewerFontStandard)).toString()); void SettingsFeedsMessages::saveSettings() {
m_ui->m_lblMessagesFont->setFont(fon); onBeginSaveSettings();
settings()->setValue(GROUP(Feeds), Feeds::EnableAutoUpdateNotification, m_ui->m_checkAutoUpdateNotification->isChecked());
onEndLoadSettings(); 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());
void SettingsFeedsMessages::saveSettings() { settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateInterval, m_ui->m_spinAutoUpdateInterval->value());
onBeginSaveSettings(); 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::EnableAutoUpdateNotification, m_ui->m_checkAutoUpdateNotification->isChecked()); settings()->setValue(GROUP(Feeds), Feeds::CountFormat, m_ui->m_cmbCountsFeedList->currentText());
settings()->setValue(GROUP(Messages), Messages::KeepCursorInCenter, m_ui->m_checkKeppMessagesInTheMiddle->isChecked()); settings()->setValue(GROUP(Messages), Messages::UseCustomDate, m_ui->m_checkMessagesDateTimeFormat->isChecked());
settings()->setValue(GROUP(Messages), Messages::ClearReadOnExit, m_ui->m_checkRemoveReadMessagesOnExit->isChecked()); settings()->setValue(GROUP(Messages), Messages::MessageHeadImageHeight, m_ui->m_spinHeightImageAttachments->value());
settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateEnabled, m_ui->m_checkAutoUpdate->isChecked()); settings()->setValue(GROUP(Messages), Messages::CustomDateFormat,
settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateInterval, m_ui->m_spinAutoUpdateInterval->value()); m_ui->m_cmbMessagesDateTimeFormat->itemData(m_ui->m_cmbMessagesDateTimeFormat->currentIndex()).toString());
settings()->setValue(GROUP(Feeds), Feeds::UpdateTimeout, m_ui->m_spinFeedUpdateTimeout->value()); // Save fonts.
settings()->setValue(GROUP(Feeds), Feeds::FeedsUpdateOnStartup, m_ui->m_checkUpdateAllFeedsOnStartup->isChecked()); settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, m_ui->m_lblMessagesFont->font().toString());
settings()->setValue(GROUP(Feeds), Feeds::CountFormat, m_ui->m_cmbCountsFeedList->currentText()); qApp->mainForm()->tabWidget()->feedMessageViewer()->loadMessageViewerFonts();
settings()->setValue(GROUP(Messages), Messages::UseCustomDate, m_ui->m_checkMessagesDateTimeFormat->isChecked()); qApp->feedReader()->updateAutoUpdateStatus();
settings()->setValue(GROUP(Messages), Messages::MessageHeadImageHeight, m_ui->m_spinHeightImageAttachments->value()); qApp->feedReader()->feedsModel()->reloadWholeLayout();
settings()->setValue(GROUP(Messages), Messages::CustomDateFormat, qApp->feedReader()->messagesModel()->updateDateFormat();
m_ui->m_cmbMessagesDateTimeFormat->itemData(m_ui->m_cmbMessagesDateTimeFormat->currentIndex()).toString()); qApp->feedReader()->messagesModel()->reloadWholeLayout();
onEndSaveSettings();
// 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();
}

View file

@ -1,49 +1,49 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef SETTINGSFEEDSMESSAGES_H #ifndef SETTINGSFEEDSMESSAGES_H
#define SETTINGSFEEDSMESSAGES_H #define SETTINGSFEEDSMESSAGES_H
#include "gui/settings/settingspanel.h" #include "gui/settings/settingspanel.h"
#include "ui_settingsfeedsmessages.h" #include "ui_settingsfeedsmessages.h"
class SettingsFeedsMessages : public SettingsPanel { class SettingsFeedsMessages : public SettingsPanel {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsFeedsMessages(Settings *settings, QWidget *parent = 0); explicit SettingsFeedsMessages(Settings* settings, QWidget* parent = 0);
virtual ~SettingsFeedsMessages(); virtual ~SettingsFeedsMessages();
inline QString title() const { inline QString title() const {
return tr("Feeds & messages"); return tr("Feeds & messages");
} }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
private slots: private slots:
void changeMessagesFont(); void changeMessagesFont();
private: private:
void initializeMessageDateFormats(); void initializeMessageDateFormats();
Ui::SettingsFeedsMessages *m_ui; Ui::SettingsFeedsMessages* m_ui;
}; };
#endif // SETTINGSFEEDSMESSAGES_H #endif // SETTINGSFEEDSMESSAGES_H

View file

@ -1,86 +1,82 @@
// This file is part of RSS Guard. // This file is part of RSS Guard.
// //
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com> // Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
// //
// RSS Guard is free software: you can redistribute it and/or modify // RSS Guard is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
// //
// RSS Guard is distributed in the hope that it will be useful, // RSS Guard is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details. // GNU General Public License for more details.
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>. // along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#include "gui/settings/settingsgeneral.h" #include "gui/settings/settingsgeneral.h"
#include "miscellaneous/systemfactory.h" #include "miscellaneous/systemfactory.h"
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
SettingsGeneral::SettingsGeneral(Settings *settings, QWidget *parent) SettingsGeneral::SettingsGeneral(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsGeneral) { : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGeneral) {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text().arg(APP_NAME)); 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_checkAutostart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings); connect(m_ui->m_checkForUpdatesOnStart, &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);
connect(m_ui->m_checkRemoveTrolltechJunk, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings); }
}
SettingsGeneral::~SettingsGeneral() {
SettingsGeneral::~SettingsGeneral() { delete m_ui;
delete m_ui; }
}
void SettingsGeneral::loadSettings() {
void SettingsGeneral::loadSettings() { onBeginLoadSettings();
onBeginLoadSettings(); m_ui->m_checkForUpdatesOnStart->setChecked(settings()->value(GROUP(General), SETTING(General::UpdateOnStartup)).toBool());
// Load auto-start status.
m_ui->m_checkForUpdatesOnStart->setChecked(settings()->value(GROUP(General), SETTING(General::UpdateOnStartup)).toBool()); const SystemFactory::AutoStartStatus autostart_status = qApp->system()->getAutoStartStatus();
// Load auto-start status. switch (autostart_status) {
const SystemFactory::AutoStartStatus autostart_status = qApp->system()->getAutoStartStatus(); case SystemFactory::Enabled:
m_ui->m_checkAutostart->setChecked(true);
switch (autostart_status) { break;
case SystemFactory::Enabled:
m_ui->m_checkAutostart->setChecked(true); case SystemFactory::Disabled:
break; m_ui->m_checkAutostart->setChecked(false);
break;
case SystemFactory::Disabled:
m_ui->m_checkAutostart->setChecked(false); default:
break; m_ui->m_checkAutostart->setEnabled(false);
m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text() + tr(" (not supported on this platform)"));
default: break;
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());
#if defined(Q_OS_WIN) #else
m_ui->m_checkRemoveTrolltechJunk->setVisible(true); m_ui->m_checkRemoveTrolltechJunk->setVisible(false);
m_ui->m_checkRemoveTrolltechJunk->setChecked(settings()->value(GROUP(General), SETTING(General::RemoveTrolltechJunk)).toBool()); #endif
#else onEndLoadSettings();
m_ui->m_checkRemoveTrolltechJunk->setVisible(false); }
#endif
void SettingsGeneral::saveSettings() {
onEndLoadSettings(); onBeginSaveSettings();
}
// If auto-start feature is available and user wants to turn it on, then turn it on.
void SettingsGeneral::saveSettings() { if (m_ui->m_checkAutostart->isChecked()) {
onBeginSaveSettings(); qApp->system()->setAutoStartStatus(SystemFactory::Enabled);
}
// If auto-start feature is available and user wants to turn it on, then turn it on.
if (m_ui->m_checkAutostart->isChecked()) { else {
qApp->system()->setAutoStartStatus(SystemFactory::Enabled); qApp->system()->setAutoStartStatus(SystemFactory::Disabled);
} }
else {
qApp->system()->setAutoStartStatus(SystemFactory::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();
}

Some files were not shown because too many files have changed in this diff Show more