Uncrustify reformat.

This commit is contained in:
Martin Rotter 2017-09-19 10:18:21 +02:00
parent dd4a96f51f
commit 0fe6b3e686
297 changed files with 21045 additions and 20234 deletions

View File

@ -1,27 +0,0 @@
--style=java
--indent=spaces=2
--indent-classes
--indent-namespaces
--indent-switches
--indent-labels
--indent-preproc-define
--indent-col1-comments
--max-continuation-indent=100
--break-blocks
--unpad-paren
--pad-oper
--pad-comma
--pad-header
--align-pointer=type
--align-reference=type
--break-closing-braces
--break-one-line-headers
--add-braces
--convert-tabs
--close-templates
--max-code-length=140
--lineend=linux
#--delete-empty-lines
--mode=c
-t -p
-M60Ucv

View File

@ -27,16 +27,14 @@ if [ $# -eq 0 ]; then
usage
fi
ASTYLE_CMD="astyle"
ASTYLE_CMD="uncrustify"
if [[ "$(uname -o)" == "Cygwin" ]]; then
ASTYLE_RC="$(cygpath -w $(realpath $(dirname $0)))/.astylerc"
ASTYLE_RC="$(cygpath -w $(realpath $(dirname $0)))/uncrustify.cfg"
else
ASTYLE_RC="$(realpath $(dirname $0))/.astylerc"
ASTYLE_RC="$(realpath $(dirname $0))/uncrustify.cfg"
fi
ASTYLE_RC="$(cygpath -w $(realpath $(dirname $0)))/.astylerc"
echo "ASTYLE config file: $ASTYLE_RC"
# Check all args.
@ -58,11 +56,11 @@ for dir in "$@"; do
-o -name '*.h' \
-o -name '*.hh' \
-o -name '*.hpp'); do
"${ASTYLE_CMD}" --options="$ASTYLE_RC" "${f}"
"${ASTYLE_CMD}" -c "$ASTYLE_RC" --replace "${f}"
done
# Remove backup files.
find . -name "*.orig" | xargs --no-run-if-empty rm -v
find . -name "*-backup*~*" | xargs --no-run-if-empty rm -v
popd
done

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,152 +18,157 @@
#include "core/feeddownloader.h"
#include "services/abstract/feed.h"
#include "definitions/definitions.h"
#include "services/abstract/feed.h"
#include <QThread>
#include <QDebug>
#include <QThreadPool>
#include <QMutexLocker>
#include <QString>
#include <QThread>
#include <QThreadPool>
FeedDownloader::FeedDownloader(QObject* parent)
: QObject(parent), m_feeds(QList<Feed*>()), m_mutex(new QMutex()), m_threadPool(new QThreadPool(this)),
m_results(FeedDownloadResults()), m_feedsUpdated(0),
m_feedsUpdating(0), m_feedsOriginalCount(0) {
qRegisterMetaType<FeedDownloadResults>("FeedDownloadResults");
m_threadPool->setMaxThreadCount(FEED_DOWNLOADER_MAX_THREADS);
: QObject(parent), m_feeds(QList<Feed*>()), m_mutex(new QMutex()), m_threadPool(new QThreadPool(this)),
m_results(FeedDownloadResults()), m_feedsUpdated(0),
m_feedsUpdating(0), m_feedsOriginalCount(0) {
qRegisterMetaType<FeedDownloadResults>("FeedDownloadResults");
m_threadPool->setMaxThreadCount(FEED_DOWNLOADER_MAX_THREADS);
}
FeedDownloader::~FeedDownloader() {
m_mutex->tryLock();
m_mutex->unlock();
delete m_mutex;
qDebug("Destroying FeedDownloader instance.");
m_mutex->tryLock();
m_mutex->unlock();
delete m_mutex;
qDebug("Destroying FeedDownloader instance.");
}
bool FeedDownloader::isUpdateRunning() const {
return !m_feeds.isEmpty() || m_feedsUpdating > 0;
return !m_feeds.isEmpty() || m_feedsUpdating > 0;
}
void FeedDownloader::updateAvailableFeeds() {
while (!m_feeds.isEmpty()) {
connect(m_feeds.first(), &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished,
(Qt::ConnectionType)(Qt::UniqueConnection | Qt::AutoConnection));
while (!m_feeds.isEmpty()) {
connect(m_feeds.first(), &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished,
(Qt::ConnectionType)(Qt::UniqueConnection | Qt::AutoConnection));
if (m_threadPool->tryStart(m_feeds.first())) {
m_feeds.removeFirst();
m_feedsUpdating++;
}
else {
// We want to start update of some feeds but all working threads are occupied.
break;
}
}
if (m_threadPool->tryStart(m_feeds.first())) {
m_feeds.removeFirst();
m_feedsUpdating++;
}
else {
// We want to start update of some feeds but all working threads are occupied.
break;
}
}
}
void FeedDownloader::updateFeeds(const QList<Feed*>& feeds) {
QMutexLocker locker(m_mutex);
QMutexLocker locker(m_mutex);
if (feeds.isEmpty()) {
qDebug("No feeds to update in worker thread, aborting update.");
finalizeUpdate();
}
else {
qDebug().nospace() << "Starting feed updates from worker in thread: \'" << QThread::currentThreadId() << "\'.";
m_feeds = feeds;
m_feedsOriginalCount = m_feeds.size();
m_results.clear();
m_feedsUpdated = m_feedsUpdating = 0;
// Job starts now.
emit updateStarted();
updateAvailableFeeds();
}
if (feeds.isEmpty()) {
qDebug("No feeds to update in worker thread, aborting update.");
finalizeUpdate();
}
else {
qDebug().nospace() << "Starting feed updates from worker in thread: \'" << QThread::currentThreadId() << "\'.";
m_feeds = feeds;
m_feedsOriginalCount = m_feeds.size();
m_results.clear();
m_feedsUpdated = m_feedsUpdating = 0;
// Job starts now.
emit updateStarted();
updateAvailableFeeds();
}
}
void FeedDownloader::stopRunningUpdate() {
m_threadPool->clear();
m_feeds.clear();
m_threadPool->clear();
m_feeds.clear();
}
void FeedDownloader::oneFeedUpdateFinished(const QList<Message>& messages, bool error_during_obtaining) {
QMutexLocker locker(m_mutex);
m_feedsUpdated++;
m_feedsUpdating--;
Feed* feed = qobject_cast<Feed*>(sender());
disconnect(feed, &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished);
// Now, we check if there are any feeds we would like to update too.
updateAvailableFeeds();
// Now make sure, that messages are actually stored to SQL in a locked state.
qDebug().nospace() << "Saving messages of feed "
<< feed->id() << " in thread: \'"
<< QThread::currentThreadId() << "\'.";
int updated_messages = feed->updateMessages(messages, error_during_obtaining);
QMutexLocker locker(m_mutex);
/*
QMetaObject::invokeMethod(feed, "updateMessages", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(int, updated_messages),
Q_ARG(QList<Message>, messages));
*/
m_feedsUpdated++;
m_feedsUpdating--;
Feed* feed = qobject_cast<Feed*>(sender());
if (updated_messages > 0) {
m_results.appendUpdatedFeed(QPair<QString, int>(feed->title(), updated_messages));
}
disconnect(feed, &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished);
qDebug("Made progress in feed updates, total feeds count %d/%d (id of feed is %d).", m_feedsUpdated, m_feedsOriginalCount, feed->id());
emit updateProgress(feed, m_feedsUpdated, m_feedsOriginalCount);
// Now, we check if there are any feeds we would like to update too.
updateAvailableFeeds();
if (m_feeds.isEmpty() && m_feedsUpdating <= 0) {
finalizeUpdate();
}
// Now make sure, that messages are actually stored to SQL in a locked state.
qDebug().nospace() << "Saving messages of feed "
<< feed->id() << " in thread: \'"
<< QThread::currentThreadId() << "\'.";
int updated_messages = feed->updateMessages(messages, error_during_obtaining);
/*
QMetaObject::invokeMethod(feed, "updateMessages", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(int, updated_messages),
Q_ARG(QList<Message>, messages));
*/
if (updated_messages > 0) {
m_results.appendUpdatedFeed(QPair<QString, int>(feed->title(), updated_messages));
}
qDebug("Made progress in feed updates, total feeds count %d/%d (id of feed is %d).", m_feedsUpdated, m_feedsOriginalCount, feed->id());
emit updateProgress(feed, m_feedsUpdated, m_feedsOriginalCount);
if (m_feeds.isEmpty() && m_feedsUpdating <= 0) {
finalizeUpdate();
}
}
void FeedDownloader::finalizeUpdate() {
qDebug().nospace() << "Finished feed updates in thread: \'" << QThread::currentThreadId() << "\'.";
m_results.sort();
// Update of feeds has finished.
// NOTE: This means that now "update lock" can be unlocked
// and feeds can be added/edited/deleted and application
// can eventually quit.
emit updateFinished(m_results);
qDebug().nospace() << "Finished feed updates in thread: \'" << QThread::currentThreadId() << "\'.";
m_results.sort();
// Update of feeds has finished.
// NOTE: This means that now "update lock" can be unlocked
// and feeds can be added/edited/deleted and application
// can eventually quit.
emit updateFinished(m_results);
}
FeedDownloadResults::FeedDownloadResults() : m_updatedFeeds(QList<QPair<QString, int>>()) {
}
FeedDownloadResults::FeedDownloadResults() : m_updatedFeeds(QList<QPair<QString, int>>()) {}
QString FeedDownloadResults::overview(int how_many_feeds) const {
QStringList result;
QStringList result;
for (int i = 0, number_items_output = qMin(how_many_feeds, m_updatedFeeds.size()); i < number_items_output; i++) {
result.append(m_updatedFeeds.at(i).first + QSL(": ") + QString::number(m_updatedFeeds.at(i).second));
}
for (int i = 0, number_items_output = qMin(how_many_feeds, m_updatedFeeds.size()); i < number_items_output; i++) {
result.append(m_updatedFeeds.at(i).first + QSL(": ") + QString::number(m_updatedFeeds.at(i).second));
}
QString res_str = result.join(QSL("\n"));
QString res_str = result.join(QSL("\n"));
if (m_updatedFeeds.size() > how_many_feeds) {
res_str += QObject::tr("\n\n+ %n other feeds.", 0, m_updatedFeeds.size() - how_many_feeds);
}
if (m_updatedFeeds.size() > how_many_feeds) {
res_str += QObject::tr("\n\n+ %n other feeds.", 0, m_updatedFeeds.size() - how_many_feeds);
}
return res_str;
return res_str;
}
void FeedDownloadResults::appendUpdatedFeed(const QPair<QString, int>& feed) {
m_updatedFeeds.append(feed);
m_updatedFeeds.append(feed);
}
void FeedDownloadResults::sort() {
qSort(m_updatedFeeds.begin(), m_updatedFeeds.end(), FeedDownloadResults::lessThan);
qSort(m_updatedFeeds.begin(), m_updatedFeeds.end(), FeedDownloadResults::lessThan);
}
bool FeedDownloadResults::lessThan(const QPair<QString, int>& lhs, const QPair<QString, int>& rhs) {
return lhs.second > rhs.second;
return lhs.second > rhs.second;
}
void FeedDownloadResults::clear() {
m_updatedFeeds.clear();
m_updatedFeeds.clear();
}
QList<QPair<QString, int>> FeedDownloadResults::updatedFeeds() const {
return m_updatedFeeds;
return m_updatedFeeds;
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -24,81 +25,83 @@
#include "core/message.h"
class Feed;
class QThreadPool;
class QMutex;
// Represents results of batch feed updates.
class FeedDownloadResults {
public:
explicit FeedDownloadResults();
public:
explicit FeedDownloadResults();
QList<QPair<QString, int>> updatedFeeds() const;
QString overview(int how_many_feeds) const;
QList<QPair<QString, int>> updatedFeeds() const;
QString overview(int how_many_feeds) const;
void appendUpdatedFeed(const QPair<QString, int>& feed);
void sort();
void clear();
void appendUpdatedFeed(const QPair<QString, int>& feed);
void sort();
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:
// QString represents title if the feed, int represents count of newly downloaded messages.
QList<QPair<QString, int>> m_updatedFeeds;
private:
// QString represents title if the feed, int represents count of newly downloaded messages.
QList<QPair<QString, int>> m_updatedFeeds;
};
// This class offers means to "update" feeds and "special" categories.
// NOTE: This class is used within separate thread.
class FeedDownloader : public QObject {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit FeedDownloader(QObject* parent = 0);
virtual ~FeedDownloader();
public:
bool isUpdateRunning() const;
// Constructors and destructors.
explicit FeedDownloader(QObject* parent = 0);
virtual ~FeedDownloader();
public slots:
// Performs update of all feeds from the "feeds" parameter.
// New messages are downloaded for each feed and they
// are stored persistently in the database.
// Appropriate signals are emitted.
void updateFeeds(const QList<Feed*>& feeds);
bool isUpdateRunning() const;
// Stops running update.
void stopRunningUpdate();
public slots:
private slots:
void oneFeedUpdateFinished(const QList<Message>& messages, bool error_during_obtaining);
// Performs update of all feeds from the "feeds" parameter.
// New messages are downloaded for each feed and they
// are stored persistently in the database.
// Appropriate signals are emitted.
void updateFeeds(const QList<Feed*>& feeds);
signals:
// Emitted if feed updates started.
void updateStarted();
// Stops running update.
void stopRunningUpdate();
// Emitted if all items from update queue are
// processed.
void updateFinished(FeedDownloadResults updated_feeds);
private slots:
void oneFeedUpdateFinished(const QList<Message>& messages, bool error_during_obtaining);
// Emitted if any item is processed.
// "Current" number indicates count of processed feeds
// and "total" number indicates total number of feeds
// which were in the initial queue.
void updateProgress(const Feed* feed, int current, int total);
signals:
private:
void updateAvailableFeeds();
void finalizeUpdate();
// Emitted if feed updates started.
void updateStarted();
QList<Feed*> m_feeds;
QMutex* m_mutex;
QThreadPool* m_threadPool;
FeedDownloadResults m_results;
// Emitted if all items from update queue are
// processed.
void updateFinished(FeedDownloadResults updated_feeds);
int m_feedsUpdated;
int m_feedsUpdating;
int m_feedsOriginalCount;
// Emitted if any item is processed.
// "Current" number indicates count of processed feeds
// and "total" number indicates total number of feeds
// which were in the initial queue.
void updateProgress(const Feed* feed, int current, int total);
private:
void updateAvailableFeeds();
void finalizeUpdate();
QList<Feed*> m_feeds;
QMutex* m_mutex;
QThreadPool* m_threadPool;
FeedDownloadResults m_results;
int m_feedsUpdated;
int m_feedsUpdating;
int m_feedsOriginalCount;
};
#endif // FEEDDOWNLOADER_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,254 +18,256 @@
#include "core/feedsproxymodel.h"
#include "core/feedsmodel.h"
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
#include "core/feedsmodel.h"
#include "services/abstract/rootitem.h"
#include <QTimer>
FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent)
: QSortFilterProxyModel(parent), m_sourceModel(source_model), m_selectedItem(nullptr),
m_showUnreadOnly(false), m_hiddenIndices(QList<QPair<int, QModelIndex>>()) {
setObjectName(QSL("FeedsProxyModel"));
setSortRole(Qt::EditRole);
setSortCaseSensitivity(Qt::CaseInsensitive);
setFilterCaseSensitivity(Qt::CaseInsensitive);
setFilterKeyColumn(-1);
setFilterRole(Qt::EditRole);
setDynamicSortFilter(true);
setSourceModel(m_sourceModel);
: QSortFilterProxyModel(parent), m_sourceModel(source_model), m_selectedItem(nullptr),
m_showUnreadOnly(false), m_hiddenIndices(QList<QPair<int, QModelIndex>>()) {
setObjectName(QSL("FeedsProxyModel"));
setSortRole(Qt::EditRole);
setSortCaseSensitivity(Qt::CaseInsensitive);
setFilterCaseSensitivity(Qt::CaseInsensitive);
setFilterKeyColumn(-1);
setFilterRole(Qt::EditRole);
setDynamicSortFilter(true);
setSourceModel(m_sourceModel);
}
FeedsProxyModel::~FeedsProxyModel() {
qDebug("Destroying FeedsProxyModel instance");
qDebug("Destroying FeedsProxyModel instance");
}
QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const {
QModelIndexList result;
const uint match_type = flags & 0x0F;
const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
const bool recurse = flags & Qt::MatchRecursive;
const bool wrap = flags & Qt::MatchWrap;
const bool all_hits = (hits == -1);
QString entered_text;
const QModelIndex p = parent(start);
int from = start.row();
int to = rowCount(p);
QModelIndexList result;
const uint match_type = flags & 0x0F;
const Qt::CaseSensitivity cs = Qt::CaseInsensitive;
const bool recurse = flags & Qt::MatchRecursive;
const bool wrap = flags & Qt::MatchWrap;
const bool all_hits = (hits == -1);
QString entered_text;
const QModelIndex p = parent(start);
int from = start.row();
int to = rowCount(p);
for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
for (int r = from; (r < to) && (all_hits || result.count() < hits); ++r) {
QModelIndex idx = index(r, start.column(), p);
for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
for (int r = from; (r < to) && (all_hits || result.count() < hits); ++r) {
QModelIndex idx = index(r, start.column(), p);
if (!idx.isValid()) {
continue;
}
if (!idx.isValid()) {
continue;
}
QModelIndex mapped_idx = mapToSource(idx);
QVariant item_value = m_sourceModel->itemForIndex(mapped_idx)->title();
QModelIndex mapped_idx = mapToSource(idx);
QVariant item_value = m_sourceModel->itemForIndex(mapped_idx)->title();
// QVariant based matching.
if (match_type == Qt::MatchExactly) {
if (value == item_value) {
result.append(idx);
}
}
// QString based matching.
else {
if (entered_text.isEmpty()) {
entered_text = value.toString();
}
// QVariant based matching.
if (match_type == Qt::MatchExactly) {
if (value == item_value) {
result.append(idx);
}
}
QString item_text = item_value.toString();
// QString based matching.
else {
if (entered_text.isEmpty()) {
entered_text = value.toString();
}
switch (match_type) {
case Qt::MatchRegExp:
if (QRegExp(entered_text, cs).exactMatch(item_text)) {
result.append(idx);
}
QString item_text = item_value.toString();
break;
switch (match_type) {
case Qt::MatchRegExp:
if (QRegExp(entered_text, cs).exactMatch(item_text)) {
result.append(idx);
}
case Qt::MatchWildcard:
if (QRegExp(entered_text, cs, QRegExp::Wildcard).exactMatch(item_text)) {
result.append(idx);
}
break;
break;
case Qt::MatchWildcard:
if (QRegExp(entered_text, cs, QRegExp::Wildcard).exactMatch(item_text)) {
result.append(idx);
}
case Qt::MatchStartsWith:
if (item_text.startsWith(entered_text, cs)) {
result.append(idx);
}
break;
break;
case Qt::MatchStartsWith:
if (item_text.startsWith(entered_text, cs)) {
result.append(idx);
}
case Qt::MatchEndsWith:
if (item_text.endsWith(entered_text, cs)) {
result.append(idx);
}
break;
break;
case Qt::MatchEndsWith:
if (item_text.endsWith(entered_text, cs)) {
result.append(idx);
}
case Qt::MatchFixedString:
if (item_text.compare(entered_text, cs) == 0) {
result.append(idx);
}
break;
break;
case Qt::MatchFixedString:
if (item_text.compare(entered_text, cs) == 0) {
result.append(idx);
}
case Qt::MatchContains:
default:
if (item_text.contains(entered_text, cs)) {
result.append(idx);
}
break;
break;
}
}
case Qt::MatchContains:
default:
if (item_text.contains(entered_text, cs)) {
result.append(idx);
}
if (recurse && hasChildren(idx)) {
result += match(index(0, idx.column(), idx), role, (entered_text.isEmpty() ? value : entered_text), (all_hits ? -1 : hits - result.count()),
flags);
}
}
break;
}
}
from = 0;
to = start.row();
}
if (recurse && hasChildren(idx)) {
result +=
match(index(0, idx.column(), idx), role, (entered_text.isEmpty() ? value : entered_text), (all_hits ? -1 : hits - result.count()),
flags);
}
}
return result;
from = 0;
to = start.row();
}
return result;
}
bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const {
if (left.isValid() && right.isValid()) {
// Make necessary castings.
const RootItem* left_item = m_sourceModel->itemForIndex(left);
const RootItem* right_item = m_sourceModel->itemForIndex(right);
if (left.isValid() && right.isValid()) {
// Make necessary castings.
const RootItem* left_item = m_sourceModel->itemForIndex(left);
const RootItem* right_item = m_sourceModel->itemForIndex(right);
// NOTE: Here we want to accomplish that ALL
// categories are queued one after another and all
// feeds are queued one after another too.
// Moreover, sort everything alphabetically or
// by item counts, depending on the sort column.
// NOTE: Here we want to accomplish that ALL
// categories are queued one after another and all
// feeds are queued one after another too.
// Moreover, sort everything alphabetically or
// by item counts, depending on the sort column.
if (left_item->kind() == right_item->kind()) {
// Both items are feeds or both items are categories.
if (left.column() == FDS_MODEL_COUNTS_INDEX) {
// User wants to sort according to counts.
return left_item->countOfUnreadMessages() < right_item->countOfUnreadMessages();
}
else {
// In other cases, sort by title.
return QString::localeAwareCompare(left_item->title(), right_item->title()) < 0;
}
}
else if (left_item->kind() == RootItemKind::Bin) {
// Left item is recycle bin. Make sure it is "biggest" item if we have selected ascending order.
return sortOrder() == Qt::DescendingOrder;
}
else if (right_item->kind() == RootItemKind::Bin) {
// Right item is recycle bin. Make sure it is "smallest" item if we have selected descending order.
return sortOrder() == Qt::AscendingOrder;
}
else if (left_item->kind() == RootItemKind::Feed) {
// Left item is feed, right item is category.
return false;
}
else {
// Left item is category, right item is feed.
// NOTE: Category is in fact "more" than feed but we consider it to be "less" because it should be "placed"
// above the "smalles" feed when ascending sort is used.
// NOTE: We need to keep recycle bin in first position.
return true;
}
}
else {
return false;
}
if (left_item->kind() == right_item->kind()) {
// Both items are feeds or both items are categories.
if (left.column() == FDS_MODEL_COUNTS_INDEX) {
// User wants to sort according to counts.
return left_item->countOfUnreadMessages() < right_item->countOfUnreadMessages();
}
else {
// In other cases, sort by title.
return QString::localeAwareCompare(left_item->title(), right_item->title()) < 0;
}
}
else if (left_item->kind() == RootItemKind::Bin) {
// Left item is recycle bin. Make sure it is "biggest" item if we have selected ascending order.
return sortOrder() == Qt::DescendingOrder;
}
else if (right_item->kind() == RootItemKind::Bin) {
// Right item is recycle bin. Make sure it is "smallest" item if we have selected descending order.
return sortOrder() == Qt::AscendingOrder;
}
else if (left_item->kind() == RootItemKind::Feed) {
// Left item is feed, right item is category.
return false;
}
else {
// Left item is category, right item is feed.
// NOTE: Category is in fact "more" than feed but we consider it to be "less" because it should be "placed"
// above the "smalles" feed when ascending sort is used.
// NOTE: We need to keep recycle bin in first position.
return true;
}
}
else {
return false;
}
}
bool FeedsProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const {
bool should_show = filterAcceptsRowInternal(source_row, source_parent);
bool should_show = filterAcceptsRowInternal(source_row, source_parent);
if (should_show && m_hiddenIndices.contains(QPair<int, QModelIndex>(source_row, source_parent))) {
const_cast<FeedsProxyModel*>(this)->m_hiddenIndices.removeAll(QPair<int, QModelIndex>(source_row, source_parent));
// Load status.
emit expandAfterFilterIn(m_sourceModel->index(source_row, 0, source_parent));
}
if (should_show && m_hiddenIndices.contains(QPair<int, QModelIndex>(source_row, source_parent))) {
const_cast<FeedsProxyModel*>(this)->m_hiddenIndices.removeAll(QPair<int, QModelIndex>(source_row, source_parent));
if (!should_show) {
const_cast<FeedsProxyModel*>(this)->m_hiddenIndices.append(QPair<int, QModelIndex>(source_row, source_parent));
}
// Load status.
emit expandAfterFilterIn(m_sourceModel->index(source_row, 0, source_parent));
}
return should_show;
if (!should_show) {
const_cast<FeedsProxyModel*>(this)->m_hiddenIndices.append(QPair<int, QModelIndex>(source_row, source_parent));
}
return should_show;
}
bool FeedsProxyModel::filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const {
if (!m_showUnreadOnly) {
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
if (!m_showUnreadOnly) {
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
const QModelIndex idx = m_sourceModel->index(source_row, 0, source_parent);
const QModelIndex idx = m_sourceModel->index(source_row, 0, source_parent);
if (!idx.isValid()) {
return false;
}
if (!idx.isValid()) {
return false;
}
const RootItem* item = m_sourceModel->itemForIndex(idx);
const RootItem* item = m_sourceModel->itemForIndex(idx);
if (item->kind() == RootItemKind::Bin || item->kind() == RootItemKind::ServiceRoot) {
// Recycle bin is always displayed.
return true;
}
else if (item->isParentOf(m_selectedItem)/* || item->isChildOf(m_selectedItem)*/ || m_selectedItem == item) {
// Currently selected item and all its parents and children must be displayed.
return true;
}
else {
// NOTE: If item has < 0 of unread message it may mean, that the count
// of unread messages is not (yet) known, display that item too.
return item->countOfUnreadMessages() != 0;
}
if (item->kind() == RootItemKind::Bin || item->kind() == RootItemKind::ServiceRoot) {
// Recycle bin is always displayed.
return true;
}
else if (item->isParentOf(m_selectedItem) /* || item->isChildOf(m_selectedItem)*/ || m_selectedItem == item) {
// Currently selected item and all its parents and children must be displayed.
return true;
}
else {
// NOTE: If item has < 0 of unread message it may mean, that the count
// of unread messages is not (yet) known, display that item too.
return item->countOfUnreadMessages() != 0;
}
}
const RootItem* FeedsProxyModel::selectedItem() const {
return m_selectedItem;
return m_selectedItem;
}
void FeedsProxyModel::setSelectedItem(const RootItem* selected_item) {
m_selectedItem = selected_item;
m_selectedItem = selected_item;
}
bool FeedsProxyModel::showUnreadOnly() const {
return m_showUnreadOnly;
return m_showUnreadOnly;
}
void FeedsProxyModel::invalidateReadFeedsFilter(bool set_new_value, bool show_unread_only) {
if (set_new_value) {
setShowUnreadOnly(show_unread_only);
}
if (set_new_value) {
setShowUnreadOnly(show_unread_only);
}
QTimer::singleShot(0, this, &FeedsProxyModel::invalidateFilter);
QTimer::singleShot(0, this, &FeedsProxyModel::invalidateFilter);
}
void FeedsProxyModel::setShowUnreadOnly(bool show_unread_only) {
m_showUnreadOnly = show_unread_only;
qApp->settings()->setValue(GROUP(Feeds), Feeds::ShowOnlyUnreadFeeds, show_unread_only);
m_showUnreadOnly = show_unread_only;
qApp->settings()->setValue(GROUP(Feeds), Feeds::ShowOnlyUnreadFeeds, show_unread_only);
}
QModelIndexList FeedsProxyModel::mapListToSource(const QModelIndexList& indexes) const {
QModelIndexList source_indexes;
QModelIndexList source_indexes;
foreach (const QModelIndex& index, indexes) {
source_indexes << mapToSource(index);
}
foreach (const QModelIndex& index, indexes) {
source_indexes << mapToSource(index);
}
return source_indexes;
return source_indexes;
}
void FeedsProxyModel::invalidateFilter() {
QSortFilterProxyModel::invalidateFilter();
QSortFilterProxyModel::invalidateFilter();
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,51 +21,54 @@
#include <QSortFilterProxyModel>
class FeedsModel;
class RootItem;
class FeedsProxyModel : public QSortFilterProxyModel {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = 0);
virtual ~FeedsProxyModel();
public:
// Returns index list of items which "match" given value.
// Used for finding items according to entered title text.
QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const;
// Constructors and destructors.
explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = 0);
virtual ~FeedsProxyModel();
// Maps list of indexes.
QModelIndexList mapListToSource(const QModelIndexList& indexes) const;
// Returns index list of items which "match" given value.
// Used for finding items according to entered title text.
QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const;
bool showUnreadOnly() const;
void setShowUnreadOnly(bool show_unread_only);
// Maps list of indexes.
QModelIndexList mapListToSource(const QModelIndexList& indexes) const;
const RootItem* selectedItem() const;
void setSelectedItem(const RootItem* selected_item);
bool showUnreadOnly() const;
void setShowUnreadOnly(bool show_unread_only);
public slots:
void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false);
const RootItem* selectedItem() const;
private slots:
void invalidateFilter();
void setSelectedItem(const RootItem* selected_item);
signals:
void expandAfterFilterIn(QModelIndex idx) const;
public slots:
void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false);
private:
// Compares two rows of data.
bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
bool filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const;
private slots:
void invalidateFilter();
// Source model pointer.
FeedsModel* m_sourceModel;
const RootItem* m_selectedItem;
bool m_showUnreadOnly;
QList<QPair<int, QModelIndex>> m_hiddenIndices;
signals:
void expandAfterFilterIn(QModelIndex idx) const;
private:
// Compares two rows of data.
bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
bool filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const;
// Source model pointer.
FeedsModel* m_sourceModel;
const RootItem* m_selectedItem;
bool m_showUnreadOnly;
QList<QPair<int, QModelIndex>> m_hiddenIndices;
};
#endif // FEEDSPROXYMODEL_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -21,81 +22,81 @@
#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;
QList<Enclosure> enclosures;
foreach (const QString& single_enclosure, enclosures_data.split(ENCLOSURES_OUTER_SEPARATOR, QString::SkipEmptyParts)) {
Enclosure enclosure;
foreach (const QString& single_enclosure, enclosures_data.split(ENCLOSURES_OUTER_SEPARATOR, QString::SkipEmptyParts)) {
Enclosure enclosure;
if (single_enclosure.contains(ECNLOSURES_INNER_SEPARATOR)) {
QStringList mime_url = single_enclosure.split(ECNLOSURES_INNER_SEPARATOR);
enclosure.m_mimeType = QByteArray::fromBase64(mime_url.at(0).toLocal8Bit());
enclosure.m_url = QByteArray::fromBase64(mime_url.at(1).toLocal8Bit());
}
else {
enclosure.m_url = QByteArray::fromBase64(single_enclosure.toLocal8Bit());
}
if (single_enclosure.contains(ECNLOSURES_INNER_SEPARATOR)) {
QStringList mime_url = single_enclosure.split(ECNLOSURES_INNER_SEPARATOR);
enclosures.append(enclosure);
}
enclosure.m_mimeType = QByteArray::fromBase64(mime_url.at(0).toLocal8Bit());
enclosure.m_url = QByteArray::fromBase64(mime_url.at(1).toLocal8Bit());
}
else {
enclosure.m_url = QByteArray::fromBase64(single_enclosure.toLocal8Bit());
}
return enclosures;
enclosures.append(enclosure);
}
return enclosures;
}
QString Enclosures::encodeEnclosuresToString(const QList<Enclosure>& enclosures) {
QStringList enclosures_str;
QStringList enclosures_str;
foreach (const Enclosure& enclosure, enclosures) {
if (enclosure.m_mimeType.isEmpty()) {
enclosures_str.append(enclosure.m_url.toLocal8Bit().toBase64());
}
else {
enclosures_str.append(QString(enclosure.m_mimeType.toLocal8Bit().toBase64()) +
ECNLOSURES_INNER_SEPARATOR +
enclosure.m_url.toLocal8Bit().toBase64());
}
}
foreach (const Enclosure& enclosure, enclosures) {
if (enclosure.m_mimeType.isEmpty()) {
enclosures_str.append(enclosure.m_url.toLocal8Bit().toBase64());
}
else {
enclosures_str.append(QString(enclosure.m_mimeType.toLocal8Bit().toBase64()) +
ECNLOSURES_INNER_SEPARATOR +
enclosure.m_url.toLocal8Bit().toBase64());
}
}
return enclosures_str.join(QString(ENCLOSURES_OUTER_SEPARATOR));
return enclosures_str.join(QString(ENCLOSURES_OUTER_SEPARATOR));
}
Message::Message() {
m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = QSL("");
m_enclosures = QList<Enclosure>();
m_accountId = m_id = 0;
m_isRead = m_isImportant = false;
m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = QSL("");
m_enclosures = QList<Enclosure>();
m_accountId = m_id = 0;
m_isRead = m_isImportant = false;
}
Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) {
if (record.count() != MSG_DB_CUSTOM_HASH_INDEX + 1) {
if (result != nullptr) {
*result = false;
return Message();
}
}
if (record.count() != MSG_DB_CUSTOM_HASH_INDEX + 1) {
if (result != nullptr) {
*result = false;
return Message();
}
}
Message message;
message.m_id = record.value(MSG_DB_ID_INDEX).toInt();
message.m_isRead = record.value(MSG_DB_READ_INDEX).toBool();
message.m_isImportant = record.value(MSG_DB_IMPORTANT_INDEX).toBool();
message.m_feedId = record.value(MSG_DB_FEED_CUSTOM_ID_INDEX).toString();
message.m_title = record.value(MSG_DB_TITLE_INDEX).toString();
message.m_url = record.value(MSG_DB_URL_INDEX).toString();
message.m_author = record.value(MSG_DB_AUTHOR_INDEX).toString();
message.m_created = TextFactory::parseDateTime(record.value(MSG_DB_DCREATED_INDEX).value<qint64>());
message.m_contents = record.value(MSG_DB_CONTENTS_INDEX).toString();
message.m_enclosures = Enclosures::decodeEnclosuresFromString(record.value(MSG_DB_ENCLOSURES_INDEX).toString());
message.m_accountId = record.value(MSG_DB_ACCOUNT_ID_INDEX).toInt();
message.m_customId = record.value(MSG_DB_CUSTOM_ID_INDEX).toString();
message.m_customHash = record.value(MSG_DB_CUSTOM_HASH_INDEX).toString();
Message message;
if (result != nullptr) {
*result = true;
}
message.m_id = record.value(MSG_DB_ID_INDEX).toInt();
message.m_isRead = record.value(MSG_DB_READ_INDEX).toBool();
message.m_isImportant = record.value(MSG_DB_IMPORTANT_INDEX).toBool();
message.m_feedId = record.value(MSG_DB_FEED_CUSTOM_ID_INDEX).toString();
message.m_title = record.value(MSG_DB_TITLE_INDEX).toString();
message.m_url = record.value(MSG_DB_URL_INDEX).toString();
message.m_author = record.value(MSG_DB_AUTHOR_INDEX).toString();
message.m_created = TextFactory::parseDateTime(record.value(MSG_DB_DCREATED_INDEX).value<qint64>());
message.m_contents = record.value(MSG_DB_CONTENTS_INDEX).toString();
message.m_enclosures = Enclosures::decodeEnclosuresFromString(record.value(MSG_DB_ENCLOSURES_INDEX).toString());
message.m_accountId = record.value(MSG_DB_ACCOUNT_ID_INDEX).toInt();
message.m_customId = record.value(MSG_DB_CUSTOM_ID_INDEX).toString();
message.m_customHash = record.value(MSG_DB_CUSTOM_HASH_INDEX).toString();
if (result != nullptr) {
*result = true;
}
return message;
}
@ -135,10 +136,10 @@ QDataStream& operator>>(QDataStream& in, Message& myObj) {
}
uint qHash(Message key, uint seed) {
Q_UNUSED(seed)
return (key.m_accountId * 10000) + key.m_id;
Q_UNUSED(seed)
return (key.m_accountId * 10000) + key.m_id;
}
uint qHash(const Message& key) {
return (key.m_accountId * 10000) + key.m_id;
return (key.m_accountId * 10000) + key.m_id;
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,64 +21,62 @@
#include "definitions/definitions.h"
#include <QDateTime>
#include <QStringList>
#include <QSqlRecord>
#include <QDataStream>
#include <QDateTime>
#include <QSqlRecord>
#include <QStringList>
// Represents single enclosure.
struct Enclosure {
public:
explicit Enclosure(const QString& url = QString(), const QString& mime = QString());
public:
explicit Enclosure(const QString& url = QString(), const QString& mime = QString());
QString m_url;
QString m_mimeType;
QString m_url;
QString m_mimeType;
};
// Represents single enclosure.
class Enclosures {
public:
static QList<Enclosure> decodeEnclosuresFromString(const QString& enclosures_data);
static QString encodeEnclosuresToString(const QList<Enclosure>& enclosures);
public:
static QList<Enclosure> decodeEnclosuresFromString(const QString& enclosures_data);
static QString encodeEnclosuresToString(const QList<Enclosure>& enclosures);
};
// Represents single message.
class Message {
public:
explicit Message();
public:
explicit Message();
// Creates Message from given record, which contains
// row from query SELECT * FROM Messages WHERE ....;
static Message fromSqlRecord(const QSqlRecord& record, bool* result = nullptr);
// Creates Message from given record, which contains
// row from query SELECT * FROM Messages WHERE ....;
static Message fromSqlRecord(const QSqlRecord& record, bool* result = nullptr);
QString m_title;
QString m_url;
QString m_author;
QString m_contents;
QDateTime m_created;
QString m_feedId;
int m_accountId;
int m_id;
QString m_customId;
QString m_customHash;
bool m_isRead;
bool m_isImportant;
QString m_title;
QString m_url;
QString m_author;
QString m_contents;
QDateTime m_created;
QString m_feedId;
int m_accountId;
int m_id;
QString m_customId;
QString m_customHash;
QList<Enclosure> m_enclosures;
bool m_isRead;
bool m_isImportant;
// Is true if "created" date was obtained directly
// from the feed, otherwise is false
bool m_createdFromFeed;
QList<Enclosure> m_enclosures;
friend inline bool operator==(const Message& lhs, const Message& rhs) {
return lhs.m_accountId == rhs.m_accountId && lhs.m_id == rhs.m_id;
}
// Is true if "created" date was obtained directly
// from the feed, otherwise is false
bool m_createdFromFeed;
friend inline bool operator!=(const Message& lhs, const Message& rhs) {
return !(lhs == rhs);
}
friend inline bool operator==(const Message& lhs, const Message& rhs) {
return lhs.m_accountId == rhs.m_accountId && lhs.m_id == rhs.m_id;
}
friend inline bool operator!=(const Message& lhs, const Message& rhs) {
return !(lhs == rhs);
}
};
// Serialize message state.

View File

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

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -18,98 +19,99 @@
#ifndef MESSAGESMODEL_H
#define MESSAGESMODEL_H
#include <QSqlQueryModel>
#include "core/messagesmodelsqllayer.h"
#include <QSqlQueryModel>
#include "definitions/definitions.h"
#include "core/message.h"
#include "definitions/definitions.h"
#include "services/abstract/rootitem.h"
#include <QFont>
#include <QIcon>
class MessagesModelCache;
class MessagesModel : public QSqlQueryModel, public MessagesModelSqlLayer {
Q_OBJECT
Q_OBJECT
public:
// Enum which describes basic filtering schemes
// for messages.
enum MessageHighlighter {
NoHighlighting = 100,
HighlightUnread = 101,
HighlightImportant = 102
};
public:
// Constructors and destructors.
explicit MessagesModel(QObject* parent = 0);
virtual ~MessagesModel();
// Enum which describes basic filtering schemes
// for messages.
enum MessageHighlighter {
NoHighlighting = 100,
HighlightUnread = 101,
HighlightImportant = 102
};
// Fetches ALL available data to the model.
// NOTE: This activates the SQL query and populates the model with new data.
void repopulate();
// Constructors and destructors.
explicit MessagesModel(QObject* parent = 0);
virtual ~MessagesModel();
// Model implementation.
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
QVariant data(int row, int column, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex& index) const;
// Fetches ALL available data to the model.
// NOTE: This activates the SQL query and populates the model with new data.
void repopulate();
// Returns message at given index.
Message messageAt(int row_index) const;
int messageId(int row_index) const;
RootItem::Importance messageImportance(int row_index) const;
// Model implementation.
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
QVariant data(int row, int column, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex& index) const;
RootItem* loadedItem() const;
void updateDateFormat();
void reloadWholeLayout();
// Returns message at given index.
Message messageAt(int row_index) const;
int messageId(int row_index) const;
RootItem::Importance messageImportance(int row_index) const;
// SINGLE message manipulators.
bool switchMessageImportance(int row_index);
bool setMessageRead(int row_index, RootItem::ReadStatus read);
RootItem* loadedItem() const;
// BATCH messages manipulators.
bool switchBatchMessageImportance(const QModelIndexList& messages);
bool setBatchMessagesDeleted(const QModelIndexList& messages);
bool setBatchMessagesRead(const QModelIndexList& messages, RootItem::ReadStatus read);
bool setBatchMessagesRestored(const QModelIndexList& messages);
void updateDateFormat();
void reloadWholeLayout();
// Highlights messages.
void highlightMessages(MessageHighlighter highlight);
// SINGLE message manipulators.
bool switchMessageImportance(int row_index);
bool setMessageRead(int row_index, RootItem::ReadStatus read);
// Loads messages of given feeds.
void loadMessages(RootItem* item);
// BATCH messages manipulators.
bool switchBatchMessageImportance(const QModelIndexList& messages);
bool setBatchMessagesDeleted(const QModelIndexList& messages);
bool setBatchMessagesRead(const QModelIndexList& messages, RootItem::ReadStatus read);
bool setBatchMessagesRestored(const QModelIndexList& messages);
public slots:
// NOTE: These methods DO NOT actually change data in the DB, just in the model.
// These are particularly used by msg browser.
bool setMessageImportantById(int id, RootItem::Importance important);
bool setMessageReadById(int id, RootItem::ReadStatus read);
// Highlights messages.
void highlightMessages(MessageHighlighter highlight);
private:
void setupHeaderData();
void setupFonts();
void setupIcons();
// Loads messages of given feeds.
void loadMessages(RootItem* item);
MessagesModelCache* m_cache;
MessageHighlighter m_messageHighlighter;
public slots:
QString m_customDateFormat;
RootItem* m_selectedItem;
QList<QString> m_headerData;
QList<QString> m_tooltipData;
// NOTE: These methods DO NOT actually change data in the DB, just in the model.
// These are particularly used by msg browser.
bool setMessageImportantById(int id, RootItem::Importance important);
bool setMessageReadById(int id, RootItem::ReadStatus read);
QFont m_normalFont;
QFont m_boldFont;
QFont m_normalStrikedFont;
QFont m_boldStrikedFont;
private:
void setupHeaderData();
void setupFonts();
void setupIcons();
QIcon m_favoriteIcon;
QIcon m_readIcon;
QIcon m_unreadIcon;
MessagesModelCache* m_cache;
MessageHighlighter m_messageHighlighter;
QString m_customDateFormat;
RootItem* m_selectedItem;
QList<QString> m_headerData;
QList<QString> m_tooltipData;
QFont m_normalFont;
QFont m_boldFont;
QFont m_normalStrikedFont;
QFont m_boldStrikedFont;
QIcon m_favoriteIcon;
QIcon m_readIcon;
QIcon m_unreadIcon;
};
Q_DECLARE_METATYPE(MessagesModel::MessageHighlighter)

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -19,21 +20,18 @@
#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) {
if (!m_msgCache.contains(index.row())) {
m_msgCache[index.row()] = record;
}
if (!m_msgCache.contains(index.row())) {
m_msgCache[index.row()] = record;
}
m_msgCache[index.row()].setValue(index.column(), value);
m_msgCache[index.row()].setValue(index.column(), value);
}
QVariant MessagesModelCache::data(const QModelIndex& idx) {
return m_msgCache[idx.row()].value(idx.column());
return m_msgCache[idx.row()].value(idx.column());
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,34 +23,34 @@
#include "core/message.h"
#include <QVariant>
#include <QModelIndex>
#include <QVariant>
class MessagesModelCache : public QObject {
Q_OBJECT
Q_OBJECT
public:
explicit MessagesModelCache(QObject* parent = nullptr);
virtual ~MessagesModelCache();
public:
explicit MessagesModelCache(QObject* parent = nullptr);
virtual ~MessagesModelCache();
inline bool containsData(int row_idx) const {
return m_msgCache.contains(row_idx);
}
inline bool containsData(int row_idx) const {
return m_msgCache.contains(row_idx);
}
inline QSqlRecord record(int row_idx) const {
return m_msgCache.value(row_idx);
}
inline QSqlRecord record(int row_idx) const {
return m_msgCache.value(row_idx);
}
inline void clear() {
m_msgCache.clear();
}
inline void clear() {
m_msgCache.clear();
}
void setData(const QModelIndex& index, const QVariant& value, const QSqlRecord& record);
QVariant data(const QModelIndex& idx);
void setData(const QModelIndex& index, const QVariant& value, const QSqlRecord& record);
private:
QHash<int, QSqlRecord> m_msgCache;
QVariant data(const QModelIndex& idx);
private:
QHash<int, QSqlRecord> m_msgCache;
};
#endif // MESSAGESMODELCACHE_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,84 +21,84 @@
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
MessagesModelSqlLayer::MessagesModelSqlLayer()
: m_filter(QSL(DEFAULT_SQL_MESSAGES_FILTER)), m_fieldNames(QMap<int, QString>()),
m_sortColumns(QList<int>()), m_sortOrders(QList<Qt::SortOrder>()) {
m_db = qApp->database()->connection(QSL("MessagesModel"), DatabaseFactory::FromSettings);
m_fieldNames[MSG_DB_ID_INDEX] = "Messages.id";
m_fieldNames[MSG_DB_READ_INDEX] = "Messages.is_read";
m_fieldNames[MSG_DB_DELETED_INDEX] = "Messages.is_deleted";
m_fieldNames[MSG_DB_IMPORTANT_INDEX] = "Messages.is_important";
m_fieldNames[MSG_DB_FEED_TITLE_INDEX] = "Feeds.title";
m_fieldNames[MSG_DB_TITLE_INDEX] = "Messages.title";
m_fieldNames[MSG_DB_URL_INDEX] = "Messages.url";
m_fieldNames[MSG_DB_AUTHOR_INDEX] = "Messages.author";
m_fieldNames[MSG_DB_DCREATED_INDEX] = "Messages.date_created";
m_fieldNames[MSG_DB_CONTENTS_INDEX] = "Messages.contents";
m_fieldNames[MSG_DB_PDELETED_INDEX] = "Messages.is_pdeleted";
m_fieldNames[MSG_DB_ENCLOSURES_INDEX] = "Messages.enclosures";
m_fieldNames[MSG_DB_ACCOUNT_ID_INDEX] = "Messages.account_id";
m_fieldNames[MSG_DB_CUSTOM_ID_INDEX] = "Messages.custom_id";
m_fieldNames[MSG_DB_CUSTOM_HASH_INDEX] = "Messages.custom_hash";
m_fieldNames[MSG_DB_FEED_CUSTOM_ID_INDEX] = "Messages.feed";
: m_filter(QSL(DEFAULT_SQL_MESSAGES_FILTER)), m_fieldNames(QMap<int, QString>()),
m_sortColumns(QList<int>()), m_sortOrders(QList<Qt::SortOrder>()) {
m_db = qApp->database()->connection(QSL("MessagesModel"), DatabaseFactory::FromSettings);
m_fieldNames[MSG_DB_ID_INDEX] = "Messages.id";
m_fieldNames[MSG_DB_READ_INDEX] = "Messages.is_read";
m_fieldNames[MSG_DB_DELETED_INDEX] = "Messages.is_deleted";
m_fieldNames[MSG_DB_IMPORTANT_INDEX] = "Messages.is_important";
m_fieldNames[MSG_DB_FEED_TITLE_INDEX] = "Feeds.title";
m_fieldNames[MSG_DB_TITLE_INDEX] = "Messages.title";
m_fieldNames[MSG_DB_URL_INDEX] = "Messages.url";
m_fieldNames[MSG_DB_AUTHOR_INDEX] = "Messages.author";
m_fieldNames[MSG_DB_DCREATED_INDEX] = "Messages.date_created";
m_fieldNames[MSG_DB_CONTENTS_INDEX] = "Messages.contents";
m_fieldNames[MSG_DB_PDELETED_INDEX] = "Messages.is_pdeleted";
m_fieldNames[MSG_DB_ENCLOSURES_INDEX] = "Messages.enclosures";
m_fieldNames[MSG_DB_ACCOUNT_ID_INDEX] = "Messages.account_id";
m_fieldNames[MSG_DB_CUSTOM_ID_INDEX] = "Messages.custom_id";
m_fieldNames[MSG_DB_CUSTOM_HASH_INDEX] = "Messages.custom_hash";
m_fieldNames[MSG_DB_FEED_CUSTOM_ID_INDEX] = "Messages.feed";
}
void MessagesModelSqlLayer::addSortState(int column, Qt::SortOrder order) {
int existing = m_sortColumns.indexOf(column);
bool is_ctrl_pressed = (QApplication::queryKeyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier;
int existing = m_sortColumns.indexOf(column);
bool is_ctrl_pressed = (QApplication::queryKeyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier;
if (existing >= 0) {
m_sortColumns.removeAt(existing);
m_sortOrders.removeAt(existing);
}
if (existing >= 0) {
m_sortColumns.removeAt(existing);
m_sortOrders.removeAt(existing);
}
if (m_sortColumns.size() > MAX_MULTICOLUMN_SORT_STATES) {
// We support only limited number of sort states
// due to DB performance.
m_sortColumns.removeAt(0);
m_sortOrders.removeAt(0);
}
if (m_sortColumns.size() > MAX_MULTICOLUMN_SORT_STATES) {
// We support only limited number of sort states
// due to DB performance.
m_sortColumns.removeAt(0);
m_sortOrders.removeAt(0);
}
if (is_ctrl_pressed) {
// User is activating the multicolumn sort mode.
m_sortColumns.append(column);
m_sortOrders.append(order);
}
else {
m_sortColumns.prepend(column);
m_sortOrders.prepend(order);
}
if (is_ctrl_pressed) {
// User is activating the multicolumn sort mode.
m_sortColumns.append(column);
m_sortOrders.append(order);
}
else {
m_sortColumns.prepend(column);
m_sortOrders.prepend(order);
}
qDebug("Added sort state, select statement is now:\n'%s'", qPrintable(selectStatement()));
qDebug("Added sort state, select statement is now:\n'%s'", qPrintable(selectStatement()));
}
void MessagesModelSqlLayer::setFilter(const QString& filter) {
m_filter = filter;
m_filter = filter;
}
QString MessagesModelSqlLayer::formatFields() const {
return m_fieldNames.values().join(QSL(", "));
return m_fieldNames.values().join(QSL(", "));
}
QString MessagesModelSqlLayer::selectStatement() const {
return QL1S("SELECT ") + formatFields() +
QSL(" FROM Messages LEFT JOIN Feeds ON Messages.feed = Feeds.custom_id AND Messages.account_id = Feeds.account_id WHERE ") +
m_filter + orderByClause() + QL1C(';');
return QL1S("SELECT ") + formatFields() +
QSL(" FROM Messages LEFT JOIN Feeds ON Messages.feed = Feeds.custom_id AND Messages.account_id = Feeds.account_id WHERE ") +
m_filter + orderByClause() + QL1C(';');
}
QString MessagesModelSqlLayer::orderByClause() const {
if (m_sortColumns.isEmpty()) {
return QString();
}
else {
QStringList sorts;
if (m_sortColumns.isEmpty()) {
return QString();
}
else {
QStringList sorts;
for (int i = 0; i < m_sortColumns.size(); i++) {
QString field_name(m_fieldNames[m_sortColumns[i]]);
sorts.append(field_name + (m_sortOrders[i] == Qt::AscendingOrder ? QSL(" ASC") : QSL(" DESC")));
}
for (int i = 0; i < m_sortColumns.size(); i++) {
QString field_name(m_fieldNames[m_sortColumns[i]]);
return QL1S(" ORDER BY ") + sorts.join(QSL(", "));
}
sorts.append(field_name + (m_sortOrders[i] == Qt::AscendingOrder ? QSL(" ASC") : QSL(" DESC")));
}
return QL1S(" ORDER BY ") + sorts.join(QSL(", "));
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -15,42 +16,40 @@
// You should have received a copy of the GNU General Public License
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
#ifndef MESSAGESMODELSQLLAYER_H
#define MESSAGESMODELSQLLAYER_H
#include <QSqlDatabase>
#include <QMap>
#include <QList>
#include <QMap>
class MessagesModelSqlLayer {
public:
explicit MessagesModelSqlLayer();
public:
explicit MessagesModelSqlLayer();
// Adds this new state to queue of sort states.
void addSortState(int column, Qt::SortOrder order);
// Adds this new state to queue of sort states.
void addSortState(int column, Qt::SortOrder order);
// Sets SQL WHERE clause, without "WHERE" keyword.
void setFilter(const QString& filter);
// Sets SQL WHERE clause, without "WHERE" keyword.
void setFilter(const QString& filter);
protected:
QString orderByClause() const;
QString selectStatement() const;
QString formatFields() const;
protected:
QString orderByClause() const;
QString selectStatement() const;
QString formatFields() const;
QSqlDatabase m_db;
QSqlDatabase m_db;
private:
QString m_filter;
private:
QString m_filter;
// NOTE: These two lists contain data for multicolumn sorting.
// They are always same length. Most important sort column/order
// are located at the start of lists;
QMap<int, QString> m_fieldNames;
QList<int> m_sortColumns;
QList<Qt::SortOrder> m_sortOrders;
// NOTE: These two lists contain data for multicolumn sorting.
// They are always same length. Most important sort column/order
// are located at the start of lists;
QMap<int, QString> m_fieldNames;
QList<int> m_sortColumns;
QList<Qt::SortOrder> m_sortOrders;
};
#endif // MESSAGESMODELSQLLAYER_H

View File

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

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,37 +21,37 @@
#include <QSortFilterProxyModel>
class MessagesModel;
class MessagesProxyModel : public QSortFilterProxyModel {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit MessagesProxyModel(MessagesModel* source_model, QObject* parent = 0);
virtual ~MessagesProxyModel();
public:
QModelIndex getNextPreviousUnreadItemIndex(int default_row);
// Constructors and destructors.
explicit MessagesProxyModel(MessagesModel* source_model, QObject* parent = 0);
virtual ~MessagesProxyModel();
// Maps list of indexes.
QModelIndexList mapListToSource(const QModelIndexList& indexes) const;
QModelIndexList mapListFromSource(const QModelIndexList& indexes, bool deep = false) const;
QModelIndex getNextPreviousUnreadItemIndex(int default_row);
// Fix for matching indexes with respect to specifics of the message model.
QModelIndexList match(const QModelIndex& start, int role, const QVariant& entered_value, int hits, Qt::MatchFlags flags) const;
// Maps list of indexes.
QModelIndexList mapListToSource(const QModelIndexList& indexes) const;
QModelIndexList mapListFromSource(const QModelIndexList& indexes, bool deep = false) const;
// Performs sort of items.
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
// Fix for matching indexes with respect to specifics of the message model.
QModelIndexList match(const QModelIndex& start, int role, const QVariant& entered_value, int hits, Qt::MatchFlags flags) const;
private:
QModelIndex getNextUnreadItemIndex(int default_row, int max_row) const;
// Performs sort of items.
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
// Compares two rows of data.
bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
private:
QModelIndex getNextUnreadItemIndex(int default_row, int max_row) const;
// Source model pointer.
MessagesModel* m_sourceModel;
// Compares two rows of data.
bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
// Source model pointer.
MessagesModel* m_sourceModel;
};
#endif // MESSAGESPROXYMODEL_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -46,7 +47,8 @@
#define DEFAULT_LOCALE "en"
#define DEFAULT_FEED_ENCODING "UTF-8"
#define DEFAULT_FEED_TYPE "RSS"
#define URL_REGEXP "^(http|https|feed|ftp):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&amp;:/~\\+#]*[\\w\\-\\@?^=%&amp;/~\\+#])?$"
#define URL_REGEXP \
"^(http|https|feed|ftp):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&amp;:/~\\+#]*[\\w\\-\\@?^=%&amp;/~\\+#])?$"
#define USER_AGENT_HTTP_HEADER "User-Agent"
#define TEXT_TITLE_LIMIT 30
#define RESELECT_MESSAGE_THRESSHOLD 500
@ -140,6 +142,7 @@
#define APP_THEME_SUFFIX ".png"
#ifndef QSL
// Thin macro wrapper for literal strings.
// They are much more memory efficient and faster.
// Use it for all literals except for two cases:
@ -149,12 +152,14 @@
#endif
#ifndef QL1S
// Macro for latin strings. Latin strings are
// faster than QStrings created from literals.
#define QL1S(x) QLatin1String(x)
#endif
#ifndef QL1C
// Macro for latin chars.
#define QL1C(x) QLatin1Char(x)
#endif

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -23,25 +24,24 @@
#include <QAction>
DynamicShortcuts::DynamicShortcuts() {
}
DynamicShortcuts::DynamicShortcuts() {}
void DynamicShortcuts::save(const QList<QAction*>& actions) {
Settings* settings = qApp->settings();
Settings* settings = qApp->settings();
foreach (const QAction* action, actions) {
settings->setValue(GROUP(Keyboard), action->objectName(), action->shortcut().toString(QKeySequence::PortableText));
}
foreach (const QAction* action, actions) {
settings->setValue(GROUP(Keyboard), action->objectName(), action->shortcut().toString(QKeySequence::PortableText));
}
}
void DynamicShortcuts::load(const QList<QAction*>& actions) {
Settings* settings = qApp->settings();
Settings* settings = qApp->settings();
foreach (QAction* action, actions) {
QString shortcut_for_action = settings->value(GROUP(Keyboard),
action->objectName(),
action->shortcut().toString(QKeySequence::PortableText)).toString();
action->setShortcut(QKeySequence::fromString(shortcut_for_action, QKeySequence::PortableText));
}
foreach (QAction* action, actions) {
QString shortcut_for_action = settings->value(GROUP(Keyboard),
action->objectName(),
action->shortcut().toString(QKeySequence::PortableText)).toString();
action->setShortcut(QKeySequence::fromString(shortcut_for_action, QKeySequence::PortableText));
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,22 +21,23 @@
#include <QList>
class QAction;
class DynamicShortcuts {
public:
// Checks the application settings and then initializes shortcut of
// each action from actions from the settings.
static void load(const QList<QAction*>& actions);
public:
// Stores shortcut of each action from actions into the application
// settings.
static void save(const QList<QAction*>& actions);
// Checks the application settings and then initializes shortcut of
// each action from actions from the settings.
static void load(const QList<QAction*>& actions);
private:
// Constructor.
explicit DynamicShortcuts();
// Stores shortcut of each action from actions into the application
// settings.
static void save(const QList<QAction*>& actions);
private:
// Constructor.
explicit DynamicShortcuts();
};
#endif // DYNAMICSHORTCUTS_H

View File

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

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,45 +21,46 @@
#include <QWidget>
class QGridLayout;
class ShortcutCatcher;
typedef QPair<QAction*, ShortcutCatcher*> ActionBinding;
class DynamicShortcutsWidget : public QWidget {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit DynamicShortcutsWidget(QWidget* parent = 0);
virtual ~DynamicShortcutsWidget();
public:
// Updates shortcuts of all actions according to changes.
// NOTE: No access to settings is done here.
// Shortcuts are fetched from settings when applications starts
// and stored back to settings when application quits.
void updateShortcuts();
// Constructors and destructors.
explicit DynamicShortcutsWidget(QWidget* parent = 0);
virtual ~DynamicShortcutsWidget();
// Returns true if all shortcuts are unique,
// otherwise false.
bool areShortcutsUnique() const;
// Updates shortcuts of all actions according to changes.
// NOTE: No access to settings is done here.
// Shortcuts are fetched from settings when applications starts
// and stored back to settings when application quits.
void updateShortcuts();
// Populates this widget with shortcut widgets for given actions.
// NOTE: This gets initial shortcut for each action from its properties, NOT from
// the application settings, so shortcuts from settings need to be
// assigned to actions before calling this method.
void populate(QList<QAction*> actions);
// Returns true if all shortcuts are unique,
// otherwise false.
bool areShortcutsUnique() const;
signals:
void setupChanged();
// Populates this widget with shortcut widgets for given actions.
// NOTE: This gets initial shortcut for each action from its properties, NOT from
// the application settings, so shortcuts from settings need to be
// assigned to actions before calling this method.
void populate(QList<QAction*> actions);
private:
static bool lessThan(QAction* lhs, QAction* rhs);
signals:
void setupChanged();
private:
QGridLayout* m_layout;
QList<ActionBinding> m_actionBindings;
private:
static bool lessThan(QAction* lhs, QAction* rhs);
private:
QGridLayout* m_layout;
QList<ActionBinding> m_actionBindings;
};
#endif // DYNAMICSHORTCUTSOVERVIEW_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -16,32 +17,32 @@
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/******************************************************************************
Copyright (c) 2010, Artem Galichkin <doomer3d@gmail.com>
All rights reserved.
Copyright (c) 2010, Artem Galichkin <doomer3d@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include "dynamic-shortcuts/shortcutbutton.h"
@ -49,94 +50,92 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QKeyEvent>
ShortcutButton::ShortcutButton(ShortcutCatcher* catcher, QWidget* parent)
: QPushButton(parent), m_catcher(catcher) {
setMinimumWidth(100);
: QPushButton(parent), m_catcher(catcher) {
setMinimumWidth(100);
}
ShortcutButton::~ShortcutButton() {
}
ShortcutButton::~ShortcutButton() {}
void ShortcutButton::keyPressEvent(QKeyEvent* event) {
int pressed_key = event->key();
int pressed_key = event->key();
if (pressed_key == -1) {
m_catcher->doneRecording();
}
if (pressed_key == -1) {
m_catcher->doneRecording();
}
const Qt::KeyboardModifiers new_modifiers = event->modifiers() & (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META);
const Qt::KeyboardModifiers new_modifiers = event->modifiers() & (Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META);
if (!m_catcher->m_isRecording && (pressed_key == Qt::Key_Return || pressed_key == Qt::Key_Space)) {
return;
}
if (!m_catcher->m_isRecording && (pressed_key == Qt::Key_Return || pressed_key == Qt::Key_Space)) {
return;
}
if (!m_catcher->m_isRecording) {
QPushButton::keyPressEvent(event);
return;
}
if (!m_catcher->m_isRecording) {
QPushButton::keyPressEvent(event);
return;
}
event->accept();
m_catcher->m_modifierKeys = new_modifiers;
event->accept();
m_catcher->m_modifierKeys = new_modifiers;
switch (pressed_key) {
case Qt::Key_AltGr:
return;
switch (pressed_key) {
case Qt::Key_AltGr:
return;
case Qt::Key_Shift:
case Qt::Key_Control:
case Qt::Key_Alt:
case Qt::Key_Meta:
case Qt::Key_Menu:
m_catcher->controlModifierlessTimout();
m_catcher->updateDisplayShortcut();
break;
case Qt::Key_Shift:
case Qt::Key_Control:
case Qt::Key_Alt:
case Qt::Key_Meta:
case Qt::Key_Menu:
m_catcher->controlModifierlessTimout();
m_catcher->updateDisplayShortcut();
break;
default:
default:
// We now have a valid key press.
if (pressed_key) {
if ((pressed_key == Qt::Key_Backtab) && (m_catcher->m_modifierKeys & Qt::SHIFT)) {
pressed_key = Qt::Key_Tab | m_catcher->m_modifierKeys;
}
else {
pressed_key |= m_catcher->m_modifierKeys;
}
// We now have a valid key press.
if (pressed_key) {
if ((pressed_key == Qt::Key_Backtab) && (m_catcher->m_modifierKeys & Qt::SHIFT)) {
pressed_key = Qt::Key_Tab | m_catcher->m_modifierKeys;
}
else {
pressed_key |= m_catcher->m_modifierKeys;
}
if (m_catcher->m_numKey == 0) {
m_catcher->m_currentSequence = QKeySequence(pressed_key);
}
if (m_catcher->m_numKey == 0) {
m_catcher->m_currentSequence = QKeySequence(pressed_key);
}
m_catcher->m_numKey++;
m_catcher->m_numKey++;
if (m_catcher->m_numKey >= 4) {
m_catcher->doneRecording();
return;
}
if (m_catcher->m_numKey >= 4) {
m_catcher->doneRecording();
return;
}
m_catcher->controlModifierlessTimout();
m_catcher->updateDisplayShortcut();
}
}
m_catcher->controlModifierlessTimout();
m_catcher->updateDisplayShortcut();
}
}
}
void ShortcutButton::keyReleaseEvent(QKeyEvent* event) {
if (event->key() == -1) {
return;
}
if (event->key() == -1) {
return;
}
if (!m_catcher->m_isRecording) {
QPushButton::keyReleaseEvent(event);
return;
}
if (!m_catcher->m_isRecording) {
QPushButton::keyReleaseEvent(event);
return;
}
event->accept();
const Qt::KeyboardModifiers new_modifiers = event->modifiers() &
(Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META);
event->accept();
const Qt::KeyboardModifiers new_modifiers = event->modifiers() &
(Qt::SHIFT | Qt::CTRL | Qt::ALT | Qt::META);
if (((uint) new_modifiers & m_catcher->m_modifierKeys) < m_catcher->m_modifierKeys) {
m_catcher->m_modifierKeys = new_modifiers;
m_catcher->controlModifierlessTimout();
m_catcher->updateDisplayShortcut();
}
if (((uint) new_modifiers & m_catcher->m_modifierKeys) < m_catcher->m_modifierKeys) {
m_catcher->m_modifierKeys = new_modifiers;
m_catcher->controlModifierlessTimout();
m_catcher->updateDisplayShortcut();
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -16,55 +17,55 @@
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/******************************************************************************
Copyright (c) 2010, Artem Galichkin <doomer3d@gmail.com>
All rights reserved.
Copyright (c) 2010, Artem Galichkin <doomer3d@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#ifndef SHORTCUTBUTTON_H
#define SHORTCUTBUTTON_H
#include <QPushButton>
class ShortcutCatcher;
class ShortcutButton : public QPushButton {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit ShortcutButton(ShortcutCatcher* catcher, QWidget* parent = 0);
virtual ~ShortcutButton();
public:
protected:
void keyPressEvent(QKeyEvent* event);
void keyReleaseEvent(QKeyEvent* event);
// Constructors and destructors.
explicit ShortcutButton(ShortcutCatcher* catcher, QWidget* parent = 0);
virtual ~ShortcutButton();
private:
ShortcutCatcher* m_catcher;
protected:
void keyPressEvent(QKeyEvent* event);
void keyReleaseEvent(QKeyEvent* event);
private:
ShortcutCatcher* m_catcher;
};
#endif // SHORTCUTBUTTON_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -16,32 +17,32 @@
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/******************************************************************************
Copyright (c) 2010, Artem Galichkin <doomer3d@gmail.com>
All rights reserved.
Copyright (c) 2010, Artem Galichkin <doomer3d@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include "dynamic-shortcuts/shortcutcatcher.h"
@ -51,119 +52,125 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <QHBoxLayout>
ShortcutCatcher::ShortcutCatcher(QWidget* parent)
: QWidget(parent) {
// Setup layout of the control
m_layout = new QHBoxLayout(this);
m_layout->setMargin(0);
m_layout->setSpacing(1);
// Create reset button.
m_btnReset = new PlainToolButton(this);
m_btnReset->setIcon(qApp->icons()->fromTheme(QSL("document-revert")));
m_btnReset->setFocusPolicy(Qt::NoFocus);
m_btnReset->setToolTip(tr("Reset to original shortcut."));
// Create clear button.
m_btnClear = new PlainToolButton(this);
m_btnClear->setIcon(qApp->icons()->fromTheme(QSL("list-remove")));
m_btnClear->setFocusPolicy(Qt::NoFocus);
m_btnClear->setToolTip(tr("Clear current shortcut."));
// Clear main shortcut catching button.
m_btnChange = new ShortcutButton(this);
m_btnChange->setFocusPolicy(Qt::StrongFocus);
m_btnChange->setToolTip(tr("Click and hit new shortcut."));
// Add both buttons to the layout.
m_layout->addWidget(m_btnChange);
m_layout->addWidget(m_btnReset);
m_layout->addWidget(m_btnClear);
// Establish needed connections.
connect(m_btnReset, &QToolButton::clicked, this, &ShortcutCatcher::resetShortcut);
connect(m_btnClear, &QToolButton::clicked, this, &ShortcutCatcher::clearShortcut);
connect(m_btnChange, &QToolButton::clicked, this, &ShortcutCatcher::startRecording);
// Prepare initial state of the control.
updateDisplayShortcut();
: QWidget(parent) {
// Setup layout of the control
m_layout = new QHBoxLayout(this);
m_layout->setMargin(0);
m_layout->setSpacing(1);
// Create reset button.
m_btnReset = new PlainToolButton(this);
m_btnReset->setIcon(qApp->icons()->fromTheme(QSL("document-revert")));
m_btnReset->setFocusPolicy(Qt::NoFocus);
m_btnReset->setToolTip(tr("Reset to original shortcut."));
// Create clear button.
m_btnClear = new PlainToolButton(this);
m_btnClear->setIcon(qApp->icons()->fromTheme(QSL("list-remove")));
m_btnClear->setFocusPolicy(Qt::NoFocus);
m_btnClear->setToolTip(tr("Clear current shortcut."));
// Clear main shortcut catching button.
m_btnChange = new ShortcutButton(this);
m_btnChange->setFocusPolicy(Qt::StrongFocus);
m_btnChange->setToolTip(tr("Click and hit new shortcut."));
// Add both buttons to the layout.
m_layout->addWidget(m_btnChange);
m_layout->addWidget(m_btnReset);
m_layout->addWidget(m_btnClear);
// Establish needed connections.
connect(m_btnReset, &QToolButton::clicked, this, &ShortcutCatcher::resetShortcut);
connect(m_btnClear, &QToolButton::clicked, this, &ShortcutCatcher::clearShortcut);
connect(m_btnChange, &QToolButton::clicked, this, &ShortcutCatcher::startRecording);
// Prepare initial state of the control.
updateDisplayShortcut();
}
ShortcutCatcher::~ShortcutCatcher() {
delete m_btnReset;
delete m_btnChange;
delete m_btnClear;
delete m_layout;
delete m_btnReset;
delete m_btnChange;
delete m_btnClear;
delete m_layout;
}
void ShortcutCatcher::startRecording() {
m_numKey = 0;
m_modifierKeys = 0;
m_currentSequence = QKeySequence();
m_isRecording = true;
m_btnChange->setDown(true);
m_btnChange->grabKeyboard();
updateDisplayShortcut();
m_numKey = 0;
m_modifierKeys = 0;
m_currentSequence = QKeySequence();
m_isRecording = true;
m_btnChange->setDown(true);
m_btnChange->grabKeyboard();
updateDisplayShortcut();
}
void ShortcutCatcher::doneRecording() {
m_isRecording = false;
m_btnChange->releaseKeyboard();
m_btnChange->setDown(false);
updateDisplayShortcut();
emit shortcutChanged(m_currentSequence);
m_isRecording = false;
m_btnChange->releaseKeyboard();
m_btnChange->setDown(false);
updateDisplayShortcut();
emit shortcutChanged(m_currentSequence);
}
void ShortcutCatcher::controlModifierlessTimout() {
if (m_numKey && !m_modifierKeys) {
doneRecording();
}
if (m_numKey && !m_modifierKeys) {
doneRecording();
}
}
void ShortcutCatcher::updateDisplayShortcut() {
QString str = m_currentSequence.toString(QKeySequence::NativeText);
str.replace(QL1S("&"), QL1S("&&"));
QString str = m_currentSequence.toString(QKeySequence::NativeText);
if (m_isRecording) {
if (m_modifierKeys) {
if (!str.isEmpty()) {
str.append(QSL(","));
}
str.replace(QL1S("&"), QL1S("&&"));
if (m_modifierKeys & Qt::META) {
str += QL1S("Meta + ");
}
if (m_isRecording) {
if (m_modifierKeys) {
if (!str.isEmpty()) {
str.append(QSL(","));
}
if (m_modifierKeys & Qt::CTRL) {
str += QL1S("Ctrl + ");
}
if (m_modifierKeys & Qt::META) {
str += QL1S("Meta + ");
}
if (m_modifierKeys & Qt::ALT) {
str += QL1S("Alt + ");
}
if (m_modifierKeys & Qt::CTRL) {
str += QL1S("Ctrl + ");
}
if (m_modifierKeys & Qt::SHIFT) {
str += QL1S("Shift + ");
}
}
}
if (m_modifierKeys & Qt::ALT) {
str += QL1S("Alt + ");
}
m_btnChange->setText(str);
if (m_modifierKeys & Qt::SHIFT) {
str += QL1S("Shift + ");
}
}
}
m_btnChange->setText(str);
}
QKeySequence ShortcutCatcher::shortcut() const {
return m_currentSequence;
return m_currentSequence;
}
void ShortcutCatcher::setDefaultShortcut(const QKeySequence& key) {
m_defaultSequence = key;
setShortcut(key);
m_defaultSequence = key;
setShortcut(key);
}
void ShortcutCatcher::setShortcut(const QKeySequence& key) {
m_currentSequence = key;
doneRecording();
m_currentSequence = key;
doneRecording();
}
void ShortcutCatcher::resetShortcut() {
setShortcut(m_defaultSequence);
setShortcut(m_defaultSequence);
}
void ShortcutCatcher::clearShortcut() {
setShortcut(QKeySequence());
setShortcut(QKeySequence());
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -16,83 +17,81 @@
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
/******************************************************************************
Copyright (c) 2010, Artem Galichkin <doomer3d@gmail.com>
All rights reserved.
Copyright (c) 2010, Artem Galichkin <doomer3d@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#ifndef SHORTCUTCATCHER_H
#define SHORTCUTCATCHER_H
#include <QWidget>
class QHBoxLayout;
class QToolButton;
class ShortcutButton;
class ShortcutCatcher : public QWidget {
Q_OBJECT
Q_OBJECT
friend class ShortcutButton;
friend class ShortcutButton;
public:
// Constructors and destructors.
explicit ShortcutCatcher(QWidget* parent = 0);
virtual ~ShortcutCatcher();
public:
void controlModifierlessTimout();
void updateDisplayShortcut();
// Constructors and destructors.
explicit ShortcutCatcher(QWidget* parent = 0);
virtual ~ShortcutCatcher();
QKeySequence shortcut() const;
void setDefaultShortcut(const QKeySequence& key);
void setShortcut(const QKeySequence& key);
void controlModifierlessTimout();
void updateDisplayShortcut();
public slots:
void resetShortcut();
void clearShortcut();
QKeySequence shortcut() const;
void setDefaultShortcut(const QKeySequence& key);
void setShortcut(const QKeySequence& key);
private slots:
void startRecording();
void doneRecording();
public slots:
void resetShortcut();
void clearShortcut();
signals:
void shortcutChanged(const QKeySequence& seguence);
private slots:
void startRecording();
void doneRecording();
private:
QToolButton* m_btnReset;
QToolButton* m_btnClear;
ShortcutButton* m_btnChange;
QHBoxLayout* m_layout;
signals:
void shortcutChanged(const QKeySequence& seguence);
QKeySequence m_currentSequence;
QKeySequence m_defaultSequence;
bool m_isRecording;
int m_numKey;
uint m_modifierKeys;
private:
QToolButton* m_btnReset;
QToolButton* m_btnClear;
ShortcutButton* m_btnChange;
QHBoxLayout* m_layout;
QKeySequence m_currentSequence;
QKeySequence m_defaultSequence;
bool m_isRecording;
int m_numKey;
uint m_modifierKeys;
};
#endif // KEYSEQUENCECATCHER_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,13 +18,10 @@
#include "exceptions/applicationexception.h"
ApplicationException::ApplicationException(const QString& message) : m_message(message) {}
ApplicationException::ApplicationException(const QString& message) : m_message(message) {
}
ApplicationException::~ApplicationException() {
}
ApplicationException::~ApplicationException() {}
QString ApplicationException::message() const {
return m_message;
return m_message;
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,16 +21,15 @@
#include <QString>
class ApplicationException {
public:
explicit ApplicationException(const QString& message = QString());
virtual ~ApplicationException();
public:
explicit ApplicationException(const QString& message = QString());
virtual ~ApplicationException();
QString message() const;
QString message() const;
private:
QString m_message;
private:
QString m_message;
};
#endif // APPLICATIONEXCEPTION_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,9 +18,6 @@
#include "exceptions/ioexception.h"
IOException::IOException(const QString& message) : ApplicationException(message) {}
IOException::IOException(const QString& message) : ApplicationException(message) {
}
IOException::~IOException() {
}
IOException::~IOException() {}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,11 +21,10 @@
#include "exceptions/applicationexception.h"
class IOException : public ApplicationException {
public:
explicit IOException(const QString& message = QString());
virtual ~IOException();
public:
explicit IOException(const QString& message = QString());
virtual ~IOException();
};
#endif // IOEXCEPTION_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -19,23 +20,21 @@
#include <QKeyEvent>
BaseLineEdit::BaseLineEdit(QWidget* parent) : QLineEdit(parent) {}
BaseLineEdit::BaseLineEdit(QWidget* parent) : QLineEdit(parent) {
}
BaseLineEdit::~BaseLineEdit() {
}
BaseLineEdit::~BaseLineEdit() {}
void BaseLineEdit::submit(const QString& text) {
setText(text);
emit submitted(text);
setText(text);
emit submitted(text);
}
void BaseLineEdit::keyPressEvent(QKeyEvent* event) {
if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
emit submitted(text());
event->accept();
}
if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
emit submitted(text());
QLineEdit::keyPressEvent(event);
event->accept();
}
QLineEdit::keyPressEvent(event);
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,24 +21,25 @@
#include <QLineEdit>
class BaseLineEdit : public QLineEdit {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit BaseLineEdit(QWidget* parent = 0);
virtual ~BaseLineEdit();
public:
public slots:
void submit(const QString& text);
// Constructors and destructors.
explicit BaseLineEdit(QWidget* parent = 0);
virtual ~BaseLineEdit();
protected:
void keyPressEvent(QKeyEvent* event);
public slots:
void submit(const QString& text);
signals:
// Emitted if user hits ENTER button.
void submitted(const QString& text);
protected:
void keyPressEvent(QKeyEvent* event);
signals:
// Emitted if user hits ENTER button.
void submitted(const QString& text);
};
#endif // BASELINEEDIT_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -23,28 +24,28 @@
#include <QWidgetAction>
BaseToolBar::BaseToolBar(const QString& title, QWidget* parent) : QToolBar(title, parent) {
// Update right margin of filter textbox.
QMargins margins = contentsMargins();
margins.setRight(margins.right() + FILTER_RIGHT_MARGIN);
setContentsMargins(margins);
// Update right margin of filter textbox.
QMargins margins = contentsMargins();
margins.setRight(margins.right() + FILTER_RIGHT_MARGIN);
setContentsMargins(margins);
}
BaseToolBar::~BaseToolBar() {
qDebug("Destroying BaseToolBar instance.");
qDebug("Destroying BaseToolBar instance.");
}
void BaseBar::loadSavedActions() {
loadSpecificActions(getSpecificActions(savedActions()));
loadSpecificActions(getSpecificActions(savedActions()));
}
QAction* BaseBar::findMatchingAction(const QString& action, const QList<QAction*>& actions) const {
foreach (QAction* act, actions) {
if (act->objectName() == action) {
return act;
}
}
foreach (QAction* act, actions) {
if (act->objectName() == action) {
return act;
}
}
return nullptr;
return nullptr;
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,41 +21,41 @@
#include <QToolBar>
class BaseBar {
public:
// Returns all actions which can be added to the toolbar.
virtual QList<QAction*> availableActions() const = 0;
public:
// Returns all changeable actions which are currently included
// in the toolbar.
virtual QList<QAction*> changeableActions() const = 0;
// Returns all actions which can be added to the toolbar.
virtual QList<QAction*> availableActions() const = 0;
// Sets new "actions" to the toolbar and perhaps saves the toolbar
// state into the settings.
virtual void saveChangeableActions(const QStringList& actions) = 0;
// Returns all changeable actions which are currently included
// in the toolbar.
virtual QList<QAction*> changeableActions() const = 0;
// Returns list of default actions.
virtual QStringList defaultActions() const = 0;
virtual QStringList savedActions() const = 0;
// Sets new "actions" to the toolbar and perhaps saves the toolbar
// state into the settings.
virtual void saveChangeableActions(const QStringList& actions) = 0;
// Loads the toolbar state from settings.
virtual void loadSavedActions();
// Returns list of default actions.
virtual QStringList defaultActions() const = 0;
virtual QStringList savedActions() const = 0;
virtual QList<QAction*> getSpecificActions(const QStringList& actions) = 0;
virtual void loadSpecificActions(const QList<QAction*>& actions) = 0;
// Loads the toolbar state from settings.
virtual void loadSavedActions();
virtual QList<QAction*> getSpecificActions(const QStringList& actions) = 0;
virtual void loadSpecificActions(const QList<QAction*>& actions) = 0;
protected:
QAction* findMatchingAction(const QString& action, const QList<QAction*>& actions) const;
protected:
QAction* findMatchingAction(const QString& action, const QList<QAction*>& actions) const;
};
class BaseToolBar : public QToolBar, public BaseBar {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit BaseToolBar(const QString& title, QWidget* parent = 0);
virtual ~BaseToolBar();
public:
// Constructors and destructors.
explicit BaseToolBar(const QString& title, QWidget* parent = 0);
virtual ~BaseToolBar();
};
#endif // TOOLBAR_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,26 +18,24 @@
#include "gui/colorlabel.h"
#include <QPaintEvent>
#include <QPainter>
#include <QPaintEvent>
ColorLabel::ColorLabel(QWidget* parent) : QLabel(parent), m_color(QColor()) {
setFixedWidth(20);
setFixedWidth(20);
}
ColorLabel::~ColorLabel() {
}
ColorLabel::~ColorLabel() {}
QColor ColorLabel::color() const {
return m_color;
return m_color;
}
void ColorLabel::setColor(const QColor& color) {
m_color = color;
repaint();
m_color = color;
repaint();
}
void ColorLabel::paintEvent(QPaintEvent* event) {
QPainter(this).fillRect(event->rect(), m_color);
QPainter(this).fillRect(event->rect(), m_color);
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,22 +21,21 @@
#include <QLabel>
class ColorLabel : public QLabel {
Q_OBJECT
Q_OBJECT
public:
explicit ColorLabel(QWidget* parent = 0);
virtual ~ColorLabel();
public:
explicit ColorLabel(QWidget* parent = 0);
virtual ~ColorLabel();
QColor color() const;
void setColor(const QColor& color);
QColor color() const;
void setColor(const QColor& color);
protected:
void paintEvent(QPaintEvent* event);
protected:
void paintEvent(QPaintEvent* event);
private:
QColor m_color;
private:
QColor m_color;
};
#endif // COLORLABEL_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -21,17 +22,18 @@
#include <QHBoxLayout>
ComboBoxWithStatus::ComboBoxWithStatus(QWidget* parent)
: WidgetWithStatus(parent) {
m_wdgInput = new QComboBox(this);
// Set correct size for the tool button.
const int txt_input_height = m_wdgInput->sizeHint().height();
m_btnStatus->setFixedSize(txt_input_height, txt_input_height);
// Compose the layout.
m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
: WidgetWithStatus(parent) {
m_wdgInput = new QComboBox(this);
// Set correct size for the tool button.
const int txt_input_height = m_wdgInput->sizeHint().height();
m_btnStatus->setFixedSize(txt_input_height, txt_input_height);
// Compose the layout.
m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
}
ComboBoxWithStatus::~ComboBoxWithStatus() {
}
ComboBoxWithStatus::~ComboBoxWithStatus() {}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,18 +23,19 @@
#include <QComboBox>
class ComboBoxWithStatus : public WidgetWithStatus {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit ComboBoxWithStatus(QWidget* parent = 0);
virtual ~ComboBoxWithStatus();
public:
// Constructors and destructors.
explicit ComboBoxWithStatus(QWidget* parent = 0);
virtual ~ComboBoxWithStatus();
inline QComboBox* comboBox() const {
return static_cast<QComboBox*>(m_wdgInput);
}
inline QComboBox* comboBox() const {
return static_cast<QComboBox*>(m_wdgInput);
}
};
#endif // COMBOBOXWITHSTATUS_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -24,20 +25,20 @@
#include "definitions/definitions.h"
class FormAbout : public QDialog {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit FormAbout(QWidget* parent);
virtual ~FormAbout();
public:
private:
void loadLicenseAndInformation();
void loadSettingsAndPaths();
// Constructors and destructors.
explicit FormAbout(QWidget* parent);
virtual ~FormAbout();
Ui::FormAbout m_ui;
private:
void loadLicenseAndInformation();
void loadSettingsAndPaths();
Ui::FormAbout m_ui;
};
#endif // FORMABOUT_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,66 +18,67 @@
#include "gui/dialogs/formaddaccount.h"
#include "core/feedsmodel.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "core/feedsmodel.h"
#include "services/standard/standardserviceentrypoint.h"
#include <QListWidget>
#include <QDialogButtonBox>
#include <QListWidget>
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) {
m_ui->setupUi(this);
// Set flags and attributes.
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("document-new")));
connect(m_ui->m_listEntryPoints, &QListWidget::itemDoubleClicked, this, &FormAddAccount::addSelectedAccount);
connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormAddAccount::addSelectedAccount);
connect(m_ui->m_listEntryPoints, &QListWidget::itemSelectionChanged, this, &FormAddAccount::displayActiveEntryPointDetails);
loadEntryPoints();
: QDialog(parent), m_ui(new Ui::FormAddAccount), m_model(model), m_entryPoints(entry_points) {
m_ui->setupUi(this);
// Set flags and attributes.
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("document-new")));
connect(m_ui->m_listEntryPoints, &QListWidget::itemDoubleClicked, this, &FormAddAccount::addSelectedAccount);
connect(m_ui->m_buttonBox, &QDialogButtonBox::accepted, this, &FormAddAccount::addSelectedAccount);
connect(m_ui->m_listEntryPoints, &QListWidget::itemSelectionChanged, this, &FormAddAccount::displayActiveEntryPointDetails);
loadEntryPoints();
}
FormAddAccount::~FormAddAccount() {
qDebug("Destroying FormAddAccount instance.");
qDebug("Destroying FormAddAccount instance.");
}
void FormAddAccount::addSelectedAccount() {
accept();
ServiceEntryPoint* point = selectedEntryPoint();
ServiceRoot* new_root = point->createNewRoot();
accept();
ServiceEntryPoint* point = selectedEntryPoint();
ServiceRoot* new_root = point->createNewRoot();
if (new_root != nullptr) {
m_model->addServiceAccount(new_root, true);
}
else {
qCritical("Cannot create new account.");
}
if (new_root != nullptr) {
m_model->addServiceAccount(new_root, true);
}
else {
qCritical("Cannot create new account.");
}
}
void FormAddAccount::displayActiveEntryPointDetails() {
const ServiceEntryPoint* point = selectedEntryPoint();
m_ui->m_txtAuthor->setText(point->author());
m_ui->m_txtDescription->setText(point->description());
m_ui->m_txtName->setText(point->name());
m_ui->m_txtVersion->setText(point->version());
const ServiceEntryPoint* point = selectedEntryPoint();
m_ui->m_txtAuthor->setText(point->author());
m_ui->m_txtDescription->setText(point->description());
m_ui->m_txtName->setText(point->name());
m_ui->m_txtVersion->setText(point->version());
}
ServiceEntryPoint* FormAddAccount::selectedEntryPoint() const {
return m_entryPoints.at(m_ui->m_listEntryPoints->currentRow());
return m_entryPoints.at(m_ui->m_listEntryPoints->currentRow());
}
void FormAddAccount::loadEntryPoints() {
foreach (const ServiceEntryPoint* entry_point, m_entryPoints) {
QListWidgetItem* item = new QListWidgetItem(entry_point->icon(), entry_point->name(), m_ui->m_listEntryPoints);
foreach (const ServiceEntryPoint* entry_point, m_entryPoints) {
QListWidgetItem* item = new QListWidgetItem(entry_point->icon(), entry_point->name(), m_ui->m_listEntryPoints);
if (entry_point->isSingleInstanceService() && m_model->containsServiceRootFromEntryPoint(entry_point)) {
// Oops, this item cannot be added, it is single instance and is already added.
item->setFlags(Qt::NoItemFlags);
item->setToolTip(tr("This account can be added only once."));
}
}
if (entry_point->isSingleInstanceService() && m_model->containsServiceRootFromEntryPoint(entry_point)) {
// Oops, this item cannot be added, it is single instance and is already added.
item->setFlags(Qt::NoItemFlags);
item->setToolTip(tr("This account can be added only once."));
}
}
m_ui->m_listEntryPoints->setCurrentRow(m_entryPoints.size() - 1);
m_ui->m_listEntryPoints->setCurrentRow(m_entryPoints.size() - 1);
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,28 +23,29 @@
#include "ui_formaddaccount.h"
class ServiceEntryPoint;
class FeedsModel;
class FormAddAccount : public QDialog {
Q_OBJECT
Q_OBJECT
public:
explicit FormAddAccount(const QList<ServiceEntryPoint*>& entry_points, FeedsModel* model, QWidget* parent = 0);
virtual ~FormAddAccount();
public:
explicit FormAddAccount(const QList<ServiceEntryPoint*>& entry_points, FeedsModel* model, QWidget* parent = 0);
virtual ~FormAddAccount();
private slots:
void addSelectedAccount();
void displayActiveEntryPointDetails();
private slots:
void addSelectedAccount();
void displayActiveEntryPointDetails();
private:
ServiceEntryPoint* selectedEntryPoint() const;
void loadEntryPoints();
private:
ServiceEntryPoint* selectedEntryPoint() const;
QScopedPointer<Ui::FormAddAccount> m_ui;
FeedsModel* m_model;
QList<ServiceEntryPoint*> m_entryPoints;
void loadEntryPoints();
QScopedPointer<Ui::FormAddAccount> m_ui;
FeedsModel* m_model;
QList<ServiceEntryPoint*> m_entryPoints;
};
#endif // FORMADDACCOUNT_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,82 +18,82 @@
#include "gui/dialogs/formbackupdatabasesettings.h"
#include "exceptions/applicationexception.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "exceptions/applicationexception.h"
#include <QDialogButtonBox>
#include <QPushButton>
#include <QCheckBox>
#include <QFileDialog>
#include <QDateTime>
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QPushButton>
FormBackupDatabaseSettings::FormBackupDatabaseSettings(QWidget* parent) : QDialog(parent), m_ui(new Ui::FormBackupDatabaseSettings) {
m_ui->setupUi(this);
m_ui->m_txtBackupName->lineEdit()->setPlaceholderText(tr("Common name for backup files"));
setWindowIcon(qApp->icons()->fromTheme(QSL("document-export")));
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
connect(m_ui->m_checkBackupDatabase, &QCheckBox::toggled, this, &FormBackupDatabaseSettings::checkOkButton);
connect(m_ui->m_checkBackupSettings, &QCheckBox::toggled, this, &FormBackupDatabaseSettings::checkOkButton);
connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormBackupDatabaseSettings::performBackup);
connect(m_ui->m_txtBackupName->lineEdit(), &BaseLineEdit::textChanged, this, &FormBackupDatabaseSettings::checkBackupNames);
connect(m_ui->m_txtBackupName->lineEdit(), &BaseLineEdit::textChanged, this, &FormBackupDatabaseSettings::checkOkButton);
connect(m_ui->m_btnSelectFolder, &QPushButton::clicked, this, &FormBackupDatabaseSettings::selectFolderInitial);
selectFolder(qApp->documentsFolder());
m_ui->m_txtBackupName->lineEdit()->setText(QString(APP_LOW_NAME) + QL1S("_") + QDateTime::currentDateTime().toString(QSL("yyyyMMddHHmm")));
m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet."));
m_ui->setupUi(this);
m_ui->m_txtBackupName->lineEdit()->setPlaceholderText(tr("Common name for backup files"));
setWindowIcon(qApp->icons()->fromTheme(QSL("document-export")));
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
connect(m_ui->m_checkBackupDatabase, &QCheckBox::toggled, this, &FormBackupDatabaseSettings::checkOkButton);
connect(m_ui->m_checkBackupSettings, &QCheckBox::toggled, this, &FormBackupDatabaseSettings::checkOkButton);
connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormBackupDatabaseSettings::performBackup);
connect(m_ui->m_txtBackupName->lineEdit(), &BaseLineEdit::textChanged, this, &FormBackupDatabaseSettings::checkBackupNames);
connect(m_ui->m_txtBackupName->lineEdit(), &BaseLineEdit::textChanged, this, &FormBackupDatabaseSettings::checkOkButton);
connect(m_ui->m_btnSelectFolder, &QPushButton::clicked, this, &FormBackupDatabaseSettings::selectFolderInitial);
selectFolder(qApp->documentsFolder());
m_ui->m_txtBackupName->lineEdit()->setText(QString(APP_LOW_NAME) + QL1S("_") +
QDateTime::currentDateTime().toString(QSL("yyyyMMddHHmm")));
m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet."));
if (qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE &&
qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE_MEMORY) {
m_ui->m_checkBackupDatabase->setDisabled(true);
}
if (qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE &&
qApp->database()->activeDatabaseDriver() != DatabaseFactory::SQLITE_MEMORY) {
m_ui->m_checkBackupDatabase->setDisabled(true);
}
}
FormBackupDatabaseSettings::~FormBackupDatabaseSettings() {
qDebug("Destroying FormBackupDatabaseSettings instance.");
qDebug("Destroying FormBackupDatabaseSettings instance.");
}
void FormBackupDatabaseSettings::performBackup() {
try {
qApp->backupDatabaseSettings(m_ui->m_checkBackupDatabase->isChecked(), m_ui->m_checkBackupSettings->isChecked(),
m_ui->m_lblSelectFolder->label()->text(), m_ui->m_txtBackupName->lineEdit()->text());
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok,
tr("Backup was created successfully and stored in target directory."),
tr("Backup was created successfully."));
}
catch (const ApplicationException& ex) {
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(), tr("Backup failed."));
}
try {
qApp->backupDatabaseSettings(m_ui->m_checkBackupDatabase->isChecked(), m_ui->m_checkBackupSettings->isChecked(),
m_ui->m_lblSelectFolder->label()->text(), m_ui->m_txtBackupName->lineEdit()->text());
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok,
tr("Backup was created successfully and stored in target directory."),
tr("Backup was created successfully."));
}
catch (const ApplicationException& ex) {
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(), tr("Backup failed."));
}
}
void FormBackupDatabaseSettings::selectFolderInitial() {
selectFolder();
selectFolder();
}
void FormBackupDatabaseSettings::selectFolder(QString path) {
if (path.isEmpty()) {
path = QFileDialog::getExistingDirectory(this, tr("Select destination directory"), m_ui->m_lblSelectFolder->label()->text());
}
if (path.isEmpty()) {
path = QFileDialog::getExistingDirectory(this, tr("Select destination directory"), m_ui->m_lblSelectFolder->label()->text());
}
if (!path.isEmpty()) {
m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(path),
tr("Good destination directory is specified."));
}
if (!path.isEmpty()) {
m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(path),
tr("Good destination directory is specified."));
}
}
void FormBackupDatabaseSettings::checkBackupNames(const QString& name) {
if (name.simplified().isEmpty()) {
m_ui->m_txtBackupName->setStatus(WidgetWithStatus::Error, tr("Backup name cannot be empty."));
}
else {
m_ui->m_txtBackupName->setStatus(WidgetWithStatus::Ok, tr("Backup name looks okay."));
}
if (name.simplified().isEmpty()) {
m_ui->m_txtBackupName->setStatus(WidgetWithStatus::Error, tr("Backup name cannot be empty."));
}
else {
m_ui->m_txtBackupName->setStatus(WidgetWithStatus::Ok, tr("Backup name looks okay."));
}
}
void FormBackupDatabaseSettings::checkOkButton() {
m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setDisabled(m_ui->m_txtBackupName->lineEdit()->text().simplified().isEmpty() ||
m_ui->m_lblSelectFolder->label()->text().simplified().isEmpty() ||
(!m_ui->m_checkBackupDatabase->isChecked() &&
!m_ui->m_checkBackupSettings->isChecked()));
m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setDisabled(m_ui->m_txtBackupName->lineEdit()->text().simplified().isEmpty() ||
m_ui->m_lblSelectFolder->label()->text().simplified().isEmpty() ||
(!m_ui->m_checkBackupDatabase->isChecked() &&
!m_ui->m_checkBackupSettings->isChecked()));
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,25 +23,24 @@
#include "ui_formbackupdatabasesettings.h"
class FormBackupDatabaseSettings : public QDialog {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors
explicit FormBackupDatabaseSettings(QWidget* parent = 0);
virtual ~FormBackupDatabaseSettings();
public:
// Constructors and destructors
explicit FormBackupDatabaseSettings(QWidget* parent = 0);
virtual ~FormBackupDatabaseSettings();
private slots:
void performBackup();
void selectFolderInitial();
void selectFolder(QString path = QString());
void checkBackupNames(const QString& name);
void checkOkButton();
private slots:
void performBackup();
void selectFolderInitial();
void selectFolder(QString path = QString());
void checkBackupNames(const QString& name);
void checkOkButton();
private:
QScopedPointer<Ui::FormBackupDatabaseSettings> m_ui;
private:
QScopedPointer<Ui::FormBackupDatabaseSettings> m_ui;
};
#endif // FORMBACKUPDATABASECONFIG_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -18,111 +19,113 @@
#include "gui/dialogs/formdatabasecleanup.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/databasefactory.h"
#include "miscellaneous/iconfactory.h"
#include <QCloseEvent>
#include <QDialogButtonBox>
#include <QPushButton>
FormDatabaseCleanup::FormDatabaseCleanup(QWidget* parent) : QDialog(parent), m_ui(new Ui::FormDatabaseCleanup), m_cleaner(nullptr) {
m_ui->setupUi(this);
// Set flags and attributes.
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("edit-clear")));
connect(m_ui->m_spinDays, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &FormDatabaseCleanup::updateDaysSuffix);
m_ui->m_spinDays->setValue(DEFAULT_DAYS_TO_DELETE_MSG);
m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("I am ready."), tr("I am ready."));
loadDatabaseInfo();
m_ui->setupUi(this);
// Set flags and attributes.
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("edit-clear")));
connect(m_ui->m_spinDays, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &FormDatabaseCleanup::updateDaysSuffix);
m_ui->m_spinDays->setValue(DEFAULT_DAYS_TO_DELETE_MSG);
m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("I am ready."), tr("I am ready."));
loadDatabaseInfo();
}
FormDatabaseCleanup::~FormDatabaseCleanup() {
qDebug("Destroying FormDatabaseCleanup instance.");
qDebug("Destroying FormDatabaseCleanup instance.");
}
void FormDatabaseCleanup::setCleaner(DatabaseCleaner* cleaner) {
if (m_cleaner != nullptr) {
disconnect(this, 0, m_cleaner, 0);
disconnect(m_cleaner, 0, this, 0);
}
if (m_cleaner != nullptr) {
disconnect(this, 0, m_cleaner, 0);
disconnect(m_cleaner, 0, this, 0);
}
m_cleaner = cleaner;
connect(m_ui->m_btnBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormDatabaseCleanup::startPurging);
connect(this, &FormDatabaseCleanup::purgeRequested, m_cleaner, &DatabaseCleaner::purgeDatabaseData);
connect(m_cleaner, &DatabaseCleaner::purgeStarted, this, &FormDatabaseCleanup::onPurgeStarted);
connect(m_cleaner, &DatabaseCleaner::purgeProgress, this, &FormDatabaseCleanup::onPurgeProgress);
connect(m_cleaner, &DatabaseCleaner::purgeFinished, this, &FormDatabaseCleanup::onPurgeFinished);
m_cleaner = cleaner;
connect(m_ui->m_btnBox->button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &FormDatabaseCleanup::startPurging);
connect(this, &FormDatabaseCleanup::purgeRequested, m_cleaner, &DatabaseCleaner::purgeDatabaseData);
connect(m_cleaner, &DatabaseCleaner::purgeStarted, this, &FormDatabaseCleanup::onPurgeStarted);
connect(m_cleaner, &DatabaseCleaner::purgeProgress, this, &FormDatabaseCleanup::onPurgeProgress);
connect(m_cleaner, &DatabaseCleaner::purgeFinished, this, &FormDatabaseCleanup::onPurgeFinished);
}
void FormDatabaseCleanup::closeEvent(QCloseEvent* event) {
if (m_ui->m_progressBar->isEnabled()) {
event->ignore();
}
else {
QDialog::closeEvent(event);
}
if (m_ui->m_progressBar->isEnabled()) {
event->ignore();
}
else {
QDialog::closeEvent(event);
}
}
void FormDatabaseCleanup::keyPressEvent(QKeyEvent* event) {
if (m_ui->m_progressBar->isEnabled()) {
event->ignore();
}
else {
QDialog::keyPressEvent(event);
}
if (m_ui->m_progressBar->isEnabled()) {
event->ignore();
}
else {
QDialog::keyPressEvent(event);
}
}
void FormDatabaseCleanup::updateDaysSuffix(int number) {
m_ui->m_spinDays->setSuffix(tr(" day(s)", 0, number));
m_ui->m_spinDays->setSuffix(tr(" day(s)", 0, number));
}
void FormDatabaseCleanup::startPurging() {
CleanerOrders orders;
orders.m_removeRecycleBin = m_ui->m_checkRemoveRecycleBin->isChecked();
orders.m_removeOldMessages = m_ui->m_checkRemoveOldMessages->isChecked();
orders.m_barrierForRemovingOldMessagesInDays = m_ui->m_spinDays->value();
orders.m_removeReadMessages = m_ui->m_checkRemoveReadMessages->isChecked();
orders.m_shrinkDatabase = m_ui->m_checkShrink->isEnabled() && m_ui->m_checkShrink->isChecked();
orders.m_removeStarredMessages = m_ui->m_checkRemoveStarredMessages->isChecked();
emit purgeRequested(orders);
CleanerOrders orders;
orders.m_removeRecycleBin = m_ui->m_checkRemoveRecycleBin->isChecked();
orders.m_removeOldMessages = m_ui->m_checkRemoveOldMessages->isChecked();
orders.m_barrierForRemovingOldMessagesInDays = m_ui->m_spinDays->value();
orders.m_removeReadMessages = m_ui->m_checkRemoveReadMessages->isChecked();
orders.m_shrinkDatabase = m_ui->m_checkShrink->isEnabled() && m_ui->m_checkShrink->isChecked();
orders.m_removeStarredMessages = m_ui->m_checkRemoveStarredMessages->isChecked();
emit purgeRequested(orders);
}
void FormDatabaseCleanup::onPurgeStarted() {
m_ui->m_progressBar->setValue(0);
m_ui->m_progressBar->setEnabled(true);
m_ui->m_btnBox->setEnabled(false);
m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("Database cleanup is running."), tr("Database cleanup is running."));
m_ui->m_progressBar->setValue(0);
m_ui->m_progressBar->setEnabled(true);
m_ui->m_btnBox->setEnabled(false);
m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, tr("Database cleanup is running."), tr("Database cleanup is running."));
}
void FormDatabaseCleanup::onPurgeProgress(int progress, const QString& description) {
m_ui->m_progressBar->setValue(progress);
m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, description, description);
m_ui->m_progressBar->setValue(progress);
m_ui->m_lblResult->setStatus(WidgetWithStatus::Information, description, description);
}
void FormDatabaseCleanup::onPurgeFinished(bool finished) {
m_ui->m_progressBar->setEnabled(false);
m_ui->m_progressBar->setValue(0);
m_ui->m_btnBox->setEnabled(true);
m_ui->m_progressBar->setEnabled(false);
m_ui->m_progressBar->setValue(0);
m_ui->m_btnBox->setEnabled(true);
if (finished) {
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Database cleanup is completed."), tr("Database cleanup is completed."));
}
else {
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Database cleanup failed."), tr("Database cleanup failed."));
}
if (finished) {
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Database cleanup is completed."), tr("Database cleanup is completed."));
}
else {
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Database cleanup failed."), tr("Database cleanup failed."));
}
loadDatabaseInfo();
loadDatabaseInfo();
}
void FormDatabaseCleanup::loadDatabaseInfo() {
qint64 file_size = qApp->database()->getDatabaseFileSize();
qint64 data_size = qApp->database()->getDatabaseDataSize();
QString file_size_str = file_size > 0 ? QString::number(file_size / 1000000.0) + QL1S(" MB") : tr("unknown");
QString data_size_str = data_size > 0 ? QString::number(data_size / 1000000.0) + QL1S(" MB") : tr("unknown");
m_ui->m_txtFileSize->setText(tr("file: %1, data: %2").arg(file_size_str, data_size_str));
m_ui->m_txtDatabaseType->setText(qApp->database()->humanDriverName(qApp->database()->activeDatabaseDriver()));
m_ui->m_checkShrink->setEnabled(qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE ||
qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE_MEMORY);
m_ui->m_checkShrink->setChecked(m_ui->m_checkShrink->isEnabled());
qint64 file_size = qApp->database()->getDatabaseFileSize();
qint64 data_size = qApp->database()->getDatabaseDataSize();
QString file_size_str = file_size > 0 ? QString::number(file_size / 1000000.0) + QL1S(" MB") : tr("unknown");
QString data_size_str = data_size > 0 ? QString::number(data_size / 1000000.0) + QL1S(" MB") : tr("unknown");
m_ui->m_txtFileSize->setText(tr("file: %1, data: %2").arg(file_size_str, data_size_str));
m_ui->m_txtDatabaseType->setText(qApp->database()->humanDriverName(qApp->database()->activeDatabaseDriver()));
m_ui->m_checkShrink->setEnabled(qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE ||
qApp->database()->activeDatabaseDriver() == DatabaseFactory::SQLITE_MEMORY);
m_ui->m_checkShrink->setChecked(m_ui->m_checkShrink->isEnabled());
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -24,37 +25,37 @@
#include "miscellaneous/databasecleaner.h"
class FormDatabaseCleanup : public QDialog {
Q_OBJECT
Q_OBJECT
public:
// Constructors.
explicit FormDatabaseCleanup(QWidget* parent = 0);
virtual ~FormDatabaseCleanup();
public:
void setCleaner(DatabaseCleaner* cleaner);
// Constructors.
explicit FormDatabaseCleanup(QWidget* parent = 0);
virtual ~FormDatabaseCleanup();
protected:
void closeEvent(QCloseEvent* event);
void keyPressEvent(QKeyEvent* event);
void setCleaner(DatabaseCleaner* cleaner);
private slots:
void updateDaysSuffix(int number);
void startPurging();
void onPurgeStarted();
void onPurgeProgress(int progress, const QString& description);
void onPurgeFinished(bool finished);
protected:
void closeEvent(QCloseEvent* event);
void keyPressEvent(QKeyEvent* event);
signals:
void purgeRequested(const CleanerOrders& which_data);
private slots:
void updateDaysSuffix(int number);
void startPurging();
void onPurgeStarted();
void onPurgeProgress(int progress, const QString& description);
void onPurgeFinished(bool finished);
private:
void loadDatabaseInfo();
signals:
void purgeRequested(const CleanerOrders& which_data);
private:
QScopedPointer<Ui::FormDatabaseCleanup> m_ui;
DatabaseCleaner* m_cleaner;
private:
void loadDatabaseInfo();
private:
QScopedPointer<Ui::FormDatabaseCleanup> m_ui;
DatabaseCleaner* m_cleaner;
};
#endif // FORMDATABASECLEANUP_H

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,86 +23,88 @@
#include "ui_formmain.h"
class StatusBar;
class FormMain : public QMainWindow {
Q_OBJECT
Q_OBJECT
friend class TabWidget;
friend class MessagesView;
friend class FeedsView;
friend class TabWidget;
friend class MessagesView;
friend class FeedsView;
public:
// Constructors and destructors.
explicit FormMain(QWidget* parent = 0, Qt::WindowFlags f = 0);
virtual ~FormMain();
public:
// Returns menu for the tray icon.
QMenu* trayMenu() const;
// Constructors and destructors.
explicit FormMain(QWidget* parent = 0, Qt::WindowFlags f = 0);
virtual ~FormMain();
// Returns global tab widget.
TabWidget* tabWidget() const;
// Returns menu for the tray icon.
QMenu* trayMenu() const;
// Access to statusbar.
StatusBar* statusBar() const;
// Returns global tab widget.
TabWidget* tabWidget() const;
// Returns list of all globally available actions.
// NOTE: This is used for setting dynamic shortcuts
// for given actions.
QList<QAction*> allActions() const;
// Access to statusbar.
StatusBar* statusBar() const;
// Loads/saves visual state of the application.
void loadSize();
void saveSize();
// Returns list of all globally available actions.
// NOTE: This is used for setting dynamic shortcuts
// for given actions.
QList<QAction*> allActions() const;
public slots:
// Displays window on top or switches its visibility.
void display();
// Loads/saves visual state of the application.
void loadSize();
void saveSize();
// Switches visibility of main window.
void switchVisibility(bool force_hide = false);
public slots:
// Turns on/off fullscreen mode
void switchFullscreenMode();
// Displays window on top or switches its visibility.
void display();
private slots:
void updateAddItemMenu();
void updateRecycleBinMenu();
void updateAccountsMenu();
// Switches visibility of main window.
void switchVisibility(bool force_hide = false);
void updateMessageButtonsAvailability();
void updateFeedButtonsAvailability();
// Turns on/off fullscreen mode
void switchFullscreenMode();
void onFeedUpdatesStarted();
void onFeedUpdatesProgress(const Feed* feed, int current, int total);
void onFeedUpdatesFinished(const FeedDownloadResults& results);
private slots:
void updateAddItemMenu();
void updateRecycleBinMenu();
void updateAccountsMenu();
// Displays various dialogs.
void backupDatabaseSettings();
void restoreDatabaseSettings();
void showWiki();
void showAddAccountDialog();
void showDbCleanupAssistant();
void reportABug();
void donate();
void updateMessageButtonsAvailability();
void updateFeedButtonsAvailability();
private:
// Event handler reimplementations.
void changeEvent(QEvent* event);
void onFeedUpdatesStarted();
void onFeedUpdatesProgress(const Feed* feed, int current, int total);
void onFeedUpdatesFinished(const FeedDownloadResults& results);
// Creates all needed menus and sets them up.
void prepareMenus();
// Displays various dialogs.
void backupDatabaseSettings();
void restoreDatabaseSettings();
void showWiki();
void showAddAccountDialog();
void showDbCleanupAssistant();
void reportABug();
void donate();
// Creates needed connections for this window.
void createConnections();
private:
// Sets up proper icons for this widget.
void setupIcons();
// Event handler reimplementations.
void changeEvent(QEvent* event);
QScopedPointer<Ui::FormMain> m_ui;
QMenu* m_trayMenu;
StatusBar* m_statusBar;
// Creates all needed menus and sets them up.
void prepareMenus();
// Creates needed connections for this window.
void createConnections();
// Sets up proper icons for this widget.
void setupIcons();
QScopedPointer<Ui::FormMain> m_ui;
QMenu* m_trayMenu;
StatusBar* m_statusBar;
};
#endif // FORMMAIN_H

View File

@ -93,12 +93,14 @@ void FormRestoreDatabaseSettings::selectFolder(QString folder) {
}
const QDir selected_folder(folder);
const QFileInfoList available_databases = selected_folder.entryInfoList(QStringList() << QString("*") + BACKUP_SUFFIX_DATABASE,
QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::CaseSensitive | QDir::NoSymLinks,
QDir::Name);
const QFileInfoList available_settings = selected_folder.entryInfoList(QStringList() << QString("*") + BACKUP_SUFFIX_SETTINGS,
QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::CaseSensitive | QDir::NoSymLinks,
QDir::Name);
const QFileInfoList available_databases = selected_folder.entryInfoList(QStringList() << QString(
"*") + BACKUP_SUFFIX_DATABASE,
QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::CaseSensitive | QDir::NoSymLinks,
QDir::Name);
const QFileInfoList available_settings = selected_folder.entryInfoList(QStringList() << QString(
"*") + BACKUP_SUFFIX_SETTINGS,
QDir::Files | QDir::NoDotAndDotDot | QDir::Readable | QDir::CaseSensitive | QDir::NoSymLinks,
QDir::Name);
m_ui.m_listDatabase->clear();
m_ui.m_listSettings->clear();

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,30 +23,29 @@
#include "ui_formrestoredatabasesettings.h"
class FormRestoreDatabaseSettings : public QDialog {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit FormRestoreDatabaseSettings(QWidget& parent);
virtual ~FormRestoreDatabaseSettings();
public:
bool shouldRestart() const {
return m_shouldRestart;
}
// Constructors and destructors.
explicit FormRestoreDatabaseSettings(QWidget& parent);
virtual ~FormRestoreDatabaseSettings();
private slots:
void performRestoration();
void checkOkButton();
void selectFolderWithGui();
void selectFolder(QString folder = QString());
bool shouldRestart() const {
return m_shouldRestart;
}
private:
Ui::FormRestoreDatabaseSettings m_ui;
QPushButton* m_btnRestart;
private slots:
void performRestoration();
void checkOkButton();
void selectFolderWithGui();
void selectFolder(QString folder = QString());
bool m_shouldRestart;
private:
Ui::FormRestoreDatabaseSettings m_ui;
QPushButton* m_btnRestart;
bool m_shouldRestart;
};
#endif // FORMRESTOREDATABASESETTINGS_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -18,10 +19,10 @@
#include "gui/dialogs/formsettings.h"
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
#include "miscellaneous/settings.h"
#include "miscellaneous/iconfactory.h"
#include "gui/messagebox.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/settings.h"
#include "gui/settings/settingsbrowsermail.h"
#include "gui/settings/settingsdatabase.h"
@ -32,108 +33,111 @@
#include "gui/settings/settingslocalization.h"
#include "gui/settings/settingsshortcuts.h"
FormSettings::FormSettings(QWidget& parent)
: QDialog(&parent), m_panels(QList<SettingsPanel*>()), m_settings(*qApp->settings()) {
m_ui.setupUi(this);
// Set flags and attributes.
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("emblem-system")));
m_btnApply = m_ui.m_buttonBox->button(QDialogButtonBox::Apply);
m_btnApply->setEnabled(false);
// Establish needed connections.
connect(m_ui.m_buttonBox, &QDialogButtonBox::accepted, this, &FormSettings::saveSettings);
connect(m_ui.m_buttonBox, &QDialogButtonBox::rejected, this, &FormSettings::cancelSettings);
connect(m_btnApply, &QPushButton::clicked, this, &FormSettings::applySettings);
addSettingsPanel(new SettingsGeneral(&m_settings, this));
addSettingsPanel(new SettingsDatabase(&m_settings, this));
addSettingsPanel(new SettingsGui(&m_settings, this));
addSettingsPanel(new SettingsLocalization(&m_settings, this));
addSettingsPanel(new SettingsShortcuts(&m_settings, this));
addSettingsPanel(new SettingsBrowserMail(&m_settings, this));
addSettingsPanel(new SettingsDownloads(&m_settings, this));
addSettingsPanel(new SettingsFeedsMessages(&m_settings, this));
m_ui.m_listSettings->setCurrentRow(0);
: QDialog(&parent), m_panels(QList<SettingsPanel*>()), m_settings(*qApp->settings()) {
m_ui.setupUi(this);
// Set flags and attributes.
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("emblem-system")));
m_btnApply = m_ui.m_buttonBox->button(QDialogButtonBox::Apply);
m_btnApply->setEnabled(false);
// Establish needed connections.
connect(m_ui.m_buttonBox, &QDialogButtonBox::accepted, this, &FormSettings::saveSettings);
connect(m_ui.m_buttonBox, &QDialogButtonBox::rejected, this, &FormSettings::cancelSettings);
connect(m_btnApply, &QPushButton::clicked, this, &FormSettings::applySettings);
addSettingsPanel(new SettingsGeneral(&m_settings, this));
addSettingsPanel(new SettingsDatabase(&m_settings, this));
addSettingsPanel(new SettingsGui(&m_settings, this));
addSettingsPanel(new SettingsLocalization(&m_settings, this));
addSettingsPanel(new SettingsShortcuts(&m_settings, this));
addSettingsPanel(new SettingsBrowserMail(&m_settings, this));
addSettingsPanel(new SettingsDownloads(&m_settings, this));
addSettingsPanel(new SettingsFeedsMessages(&m_settings, this));
m_ui.m_listSettings->setCurrentRow(0);
}
FormSettings::~FormSettings() {
qDebug("Destroying FormSettings distance.");
qDebug("Destroying FormSettings distance.");
}
void FormSettings::saveSettings() {
applySettings();
accept();
applySettings();
accept();
}
void FormSettings::applySettings() {
// Save all settings.
m_settings.checkSettings();
QStringList panels_for_restart;
// Save all settings.
m_settings.checkSettings();
QStringList panels_for_restart;
foreach (SettingsPanel* panel, m_panels) {
if (panel->isDirty()) {
panel->saveSettings();
}
foreach (SettingsPanel* panel, m_panels) {
if (panel->isDirty()) {
panel->saveSettings();
}
if (panel->requiresRestart()) {
panels_for_restart.append(panel->title().toLower());
panel->setRequiresRestart(false);
}
}
if (panel->requiresRestart()) {
panels_for_restart.append(panel->title().toLower());
panel->setRequiresRestart(false);
}
}
if (!panels_for_restart.isEmpty()) {
const QStringList changed_settings_description = panels_for_restart.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8(""));
const QMessageBox::StandardButton clicked_button = MessageBox::show(this,
QMessageBox::Question,
tr("Critical settings were changed"),
tr("Some critical settings were changed and will be applied after the application gets restarted. "
"\n\nYou have to restart manually."),
tr("Do you want to restart now?"),
tr("Changed categories of settings:\n%1.").arg(changed_settings_description .join(QSL(",\n"))),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (!panels_for_restart.isEmpty()) {
const QStringList changed_settings_description = panels_for_restart.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8(""));
const QMessageBox::StandardButton clicked_button = MessageBox::show(this,
QMessageBox::Question,
tr("Critical settings were changed"),
tr(
"Some critical settings were changed and will be applied after the application gets restarted. "
"\n\nYou have to restart manually."),
tr("Do you want to restart now?"),
tr("Changed categories of settings:\n%1.").arg(
changed_settings_description.join(QSL(",\n"))),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (clicked_button == QMessageBox::Yes) {
qApp->restart();
}
}
if (clicked_button == QMessageBox::Yes) {
qApp->restart();
}
}
m_btnApply->setEnabled(false);
m_btnApply->setEnabled(false);
}
void FormSettings::cancelSettings() {
QStringList changed_panels;
QStringList changed_panels;
foreach (SettingsPanel* panel, m_panels) {
if (panel->isDirty()) {
changed_panels.append(panel->title().toLower());
}
}
foreach (SettingsPanel* panel, m_panels) {
if (panel->isDirty()) {
changed_panels.append(panel->title().toLower());
}
}
if (changed_panels.isEmpty()) {
reject();
}
else {
const QStringList changed_settings_description = changed_panels.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8(""));
if (changed_panels.isEmpty()) {
reject();
}
else {
const QStringList changed_settings_description = changed_panels.replaceInStrings(QRegExp(QSL("^")), QString::fromUtf8(""));
if (MessageBox::show(this,
QMessageBox::Critical,
tr("Some settings are changed and will be lost"),
tr("Some settings were changed and by cancelling this dialog, you would lose these changes."),
tr("Do you really want to close this dialog without saving any settings?"),
tr("Changed categories of settings:\n%1.").arg(changed_settings_description .join(QSL(",\n"))),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) ==
QMessageBox::Yes) {
reject();
}
}
if (MessageBox::show(this,
QMessageBox::Critical,
tr("Some settings are changed and will be lost"),
tr("Some settings were changed and by cancelling this dialog, you would lose these changes."),
tr("Do you really want to close this dialog without saving any settings?"),
tr("Changed categories of settings:\n%1.").arg(changed_settings_description.join(QSL(",\n"))),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) ==
QMessageBox::Yes) {
reject();
}
}
}
void FormSettings::addSettingsPanel(SettingsPanel* panel) {
m_ui.m_listSettings->addItem(panel->title());
m_panels.append(panel);
m_ui.m_stackedSettings->addWidget(panel);
panel->loadSettings();
connect(panel, &SettingsPanel::settingsChanged, [this]() {
m_btnApply->setEnabled(true);
});
m_ui.m_listSettings->addItem(panel->title());
m_panels.append(panel);
m_ui.m_stackedSettings->addWidget(panel);
panel->loadSettings();
connect(panel, &SettingsPanel::settingsChanged, [this]() {
m_btnApply->setEnabled(true);
});
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,32 +23,33 @@
#include "ui_formsettings.h"
class Settings;
class SettingsPanel;
class FormSettings : public QDialog {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit FormSettings(QWidget& parent);
virtual ~FormSettings();
public:
private slots:
// Saves settings into global configuration.
void saveSettings();
void applySettings();
void cancelSettings();
// Constructors and destructors.
explicit FormSettings(QWidget& parent);
virtual ~FormSettings();
private:
void addSettingsPanel(SettingsPanel* panel);
private slots:
Ui::FormSettings m_ui;
QPushButton* m_btnApply;
// Saves settings into global configuration.
void saveSettings();
void applySettings();
void cancelSettings();
QList<SettingsPanel*> m_panels;
Settings& m_settings;
private:
void addSettingsPanel(SettingsPanel* panel);
Ui::FormSettings m_ui;
QPushButton* m_btnApply;
QList<SettingsPanel*> m_panels;
Settings& m_settings;
};
#endif // FORMSETTINGS_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -18,13 +19,13 @@
#include "gui/dialogs/formupdate.h"
#include "definitions/definitions.h"
#include "gui/guiutilities.h"
#include "gui/messagebox.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/iofactory.h"
#include "network-web/downloader.h"
#include "network-web/networkfactory.h"
#include "network-web/webfactory.h"
#include "network-web/downloader.h"
#include "gui/messagebox.h"
#include "gui/guiutilities.h"
#include <QNetworkReply>
@ -32,216 +33,218 @@
#include <windows.h>
#endif
FormUpdate::FormUpdate(QWidget* parent)
: QDialog(parent) {
m_ui.setupUi(this);
m_ui.m_lblCurrentRelease->setText(APP_VERSION);
m_ui.m_tabInfo->removeTab(1);
m_ui.m_buttonBox->setEnabled(false);
// Set flags and attributes.
GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("help-about")));
connect(&m_downloader, &Downloader::progress, this, &FormUpdate::updateProgress);
connect(&m_downloader, &Downloader::completed, this, &FormUpdate::updateCompleted);
: QDialog(parent) {
m_ui.setupUi(this);
m_ui.m_lblCurrentRelease->setText(APP_VERSION);
m_ui.m_tabInfo->removeTab(1);
m_ui.m_buttonBox->setEnabled(false);
if (isSelfUpdateSupported()) {
m_btnUpdate = m_ui.m_buttonBox->addButton(tr("Download selected update"), QDialogButtonBox::ActionRole);
m_btnUpdate->setToolTip(tr("Download new installation files."));
}
else {
m_btnUpdate = m_ui.m_buttonBox->addButton(tr("Go to application website"), QDialogButtonBox::ActionRole);
m_btnUpdate->setToolTip(tr("Go to application website to get update packages manually."));
}
// Set flags and attributes.
GuiUtilities::applyDialogProperties(*this, qApp->icons()->fromTheme(QSL("help-about")));
connect(&m_downloader, &Downloader::progress, this, &FormUpdate::updateProgress);
connect(&m_downloader, &Downloader::completed, this, &FormUpdate::updateCompleted);
m_btnUpdate->setVisible(false);
connect(m_btnUpdate, &QPushButton::clicked, this, &FormUpdate::startUpdate);
checkForUpdates();
if (isSelfUpdateSupported()) {
m_btnUpdate = m_ui.m_buttonBox->addButton(tr("Download selected update"), QDialogButtonBox::ActionRole);
m_btnUpdate->setToolTip(tr("Download new installation files."));
}
else {
m_btnUpdate = m_ui.m_buttonBox->addButton(tr("Go to application website"), QDialogButtonBox::ActionRole);
m_btnUpdate->setToolTip(tr("Go to application website to get update packages manually."));
}
m_btnUpdate->setVisible(false);
connect(m_btnUpdate, &QPushButton::clicked, this, &FormUpdate::startUpdate);
checkForUpdates();
}
FormUpdate::~FormUpdate() {
}
FormUpdate::~FormUpdate() {}
bool FormUpdate::isSelfUpdateSupported() const {
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
return true;
return true;
#else
return false;
return false;
#endif
}
void FormUpdate::checkForUpdates() {
connect(qApp->system(), &SystemFactory::updatesChecked, [this](QPair<QList<UpdateInfo>, QNetworkReply::NetworkError> update) {
m_ui.m_buttonBox->setEnabled(true);
disconnect(qApp->system(), &SystemFactory::updatesChecked, nullptr, nullptr);
connect(qApp->system(), &SystemFactory::updatesChecked, [this](QPair<QList<UpdateInfo>, QNetworkReply::NetworkError> update) {
m_ui.m_buttonBox->setEnabled(true);
disconnect(qApp->system(), &SystemFactory::updatesChecked, nullptr, nullptr);
if (update.second != QNetworkReply::NoError) {
m_updateInfo = UpdateInfo();
m_ui.m_tabInfo->setEnabled(false);
//: Unknown release.
m_ui.m_lblAvailableRelease->setText(tr("unknown"));
m_ui.m_txtChanges->clear();
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Error,
tr("Error: '%1'.").arg(NetworkFactory::networkErrorText(update.second)),
tr("List with updates was not\ndownloaded successfully."));
}
else {
const bool self_update_supported = isSelfUpdateSupported();
m_updateInfo = update.first.at(0);
m_ui.m_tabInfo->setEnabled(true);
m_ui.m_lblAvailableRelease->setText(m_updateInfo.m_availableVersion);
m_ui.m_txtChanges->setText(m_updateInfo.m_changes);
if (update.second != QNetworkReply::NoError) {
m_updateInfo = UpdateInfo();
m_ui.m_tabInfo->setEnabled(false);
if (SystemFactory::isVersionNewer(m_updateInfo.m_availableVersion, APP_VERSION)) {
m_btnUpdate->setVisible(true);
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Ok,
tr("New release available."),
tr("This is new version which can be\ndownloaded."));
//: Unknown release.
m_ui.m_lblAvailableRelease->setText(tr("unknown"));
m_ui.m_txtChanges->clear();
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Error,
tr("Error: '%1'.").arg(NetworkFactory::networkErrorText(update.second)),
tr("List with updates was not\ndownloaded successfully."));
}
else {
const bool self_update_supported = isSelfUpdateSupported();
m_updateInfo = update.first.at(0);
m_ui.m_tabInfo->setEnabled(true);
m_ui.m_lblAvailableRelease->setText(m_updateInfo.m_availableVersion);
m_ui.m_txtChanges->setText(m_updateInfo.m_changes);
if (self_update_supported) {
loadAvailableFiles();
}
}
else {
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Warning,
tr("No new release available."),
tr("This release is not newer than\ncurrently installed one."));
}
}
});
qApp->system()->checkForUpdates();
if (SystemFactory::isVersionNewer(m_updateInfo.m_availableVersion, APP_VERSION)) {
m_btnUpdate->setVisible(true);
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Ok,
tr("New release available."),
tr("This is new version which can be\ndownloaded."));
if (self_update_supported) {
loadAvailableFiles();
}
}
else {
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Warning,
tr("No new release available."),
tr("This release is not newer than\ncurrently installed one."));
}
}
});
qApp->system()->checkForUpdates();
}
void FormUpdate::updateProgress(qint64 bytes_received, qint64 bytes_total) {
if (bytes_received - m_lastDownloadedBytes > 500000 || m_lastDownloadedBytes == 0) {
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Information,
tr("Downloaded %1% (update size is %2 kB).").arg(QString::number(bytes_total == 0 ? 0 : (bytes_received * 100.0) / bytes_total,
'f',
2),
QString::number(bytes_total / 1000,
'f',
2)),
tr("Downloading update..."));
m_ui.m_lblStatus->repaint();
m_lastDownloadedBytes = bytes_received;
}
if (bytes_received - m_lastDownloadedBytes > 500000 || m_lastDownloadedBytes == 0) {
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Information,
tr("Downloaded %1% (update size is %2 kB).").arg(QString::number(bytes_total ==
0 ? 0 : (bytes_received * 100.0) /
bytes_total,
'f',
2),
QString::number(bytes_total / 1000,
'f',
2)),
tr("Downloading update..."));
m_ui.m_lblStatus->repaint();
m_lastDownloadedBytes = bytes_received;
}
}
void FormUpdate::saveUpdateFile(const QByteArray& file_contents) {
const QString url_file = m_ui.m_listFiles->currentItem()->data(Qt::UserRole).toString();
const QString url_file = m_ui.m_listFiles->currentItem()->data(Qt::UserRole).toString();
const QString temp_directory = qApp->tempFolder();
if (!temp_directory.isEmpty()) {
const QString output_file_name = url_file.mid(url_file.lastIndexOf('/') + 1);
QFile output_file(temp_directory + QDir::separator() + output_file_name);
if (!temp_directory.isEmpty()) {
const QString output_file_name = url_file.mid(url_file.lastIndexOf('/') + 1);
QFile output_file(temp_directory + QDir::separator() + output_file_name);
if (output_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug("Storing update file to temporary location '%s'.",
qPrintable(QDir::toNativeSeparators(output_file.fileName())));
output_file.write(file_contents);
output_file.flush();
output_file.close();
qDebug("Update file contents was successfuly saved.");
m_updateFilePath = output_file.fileName();
m_readyToInstall = true;
}
else {
qDebug("Cannot save downloaded update file because target temporary file '%s' cannot be "
"opened for writing.", qPrintable(output_file_name));
}
}
else {
qDebug("Cannot save downloaded update file because no TEMP directory is available.");
}
if (output_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qDebug("Storing update file to temporary location '%s'.",
qPrintable(QDir::toNativeSeparators(output_file.fileName())));
output_file.write(file_contents);
output_file.flush();
output_file.close();
qDebug("Update file contents was successfuly saved.");
m_updateFilePath = output_file.fileName();
m_readyToInstall = true;
}
else {
qDebug("Cannot save downloaded update file because target temporary file '%s' cannot be "
"opened for writing.", qPrintable(output_file_name));
}
}
else {
qDebug("Cannot save downloaded update file because no TEMP directory is available.");
}
}
void FormUpdate::loadAvailableFiles() {
m_ui.m_listFiles->clear();
m_ui.m_listFiles->clear();
foreach (const UpdateUrl& url, m_updateInfo.m_urls) {
QListWidgetItem* item = new QListWidgetItem(url.m_name + tr(" (size ") + url.m_size + QSL(")"));
item->setData(Qt::UserRole, url.m_fileUrl);
item->setToolTip(url.m_fileUrl);
m_ui.m_listFiles->addItem(item);
}
foreach (const UpdateUrl& url, m_updateInfo.m_urls) {
QListWidgetItem* item = new QListWidgetItem(url.m_name + tr(" (size ") + url.m_size + QSL(")"));
if (m_ui.m_listFiles->count() > 0) {
m_ui.m_listFiles->setCurrentRow(0);
}
else {
m_btnUpdate->setEnabled(false);
}
item->setData(Qt::UserRole, url.m_fileUrl);
item->setToolTip(url.m_fileUrl);
m_ui.m_listFiles->addItem(item);
}
m_ui.m_tabInfo->addTab(m_ui.tabFiles, tr("Available update files"));
m_ui.m_tabInfo->setCurrentIndex(1);
if (m_ui.m_listFiles->count() > 0) {
m_ui.m_listFiles->setCurrentRow(0);
}
else {
m_btnUpdate->setEnabled(false);
}
m_ui.m_tabInfo->addTab(m_ui.tabFiles, tr("Available update files"));
m_ui.m_tabInfo->setCurrentIndex(1);
}
void FormUpdate::updateCompleted(QNetworkReply::NetworkError status, QByteArray contents) {
qDebug("Download of application update file was completed with code '%d'.", status);
qDebug("Download of application update file was completed with code '%d'.", status);
switch (status) {
case QNetworkReply::NoError:
saveUpdateFile(contents);
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Ok, tr("Downloaded successfully"),
tr("Package was downloaded successfully.\nYou can install it now."));
m_btnUpdate->setText(tr("Install"));
m_btnUpdate->setEnabled(true);
break;
switch (status) {
case QNetworkReply::NoError:
saveUpdateFile(contents);
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Ok, tr("Downloaded successfully"),
tr("Package was downloaded successfully.\nYou can install it now."));
m_btnUpdate->setText(tr("Install"));
m_btnUpdate->setEnabled(true);
break;
default:
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Error, tr("Error occured"), tr("Error occured during downloading of the package."));
m_btnUpdate->setText(tr("Error occured"));
break;
}
default:
m_ui.m_lblStatus->setStatus(WidgetWithStatus::Error, tr("Error occured"), tr("Error occured during downloading of the package."));
m_btnUpdate->setText(tr("Error occured"));
break;
}
}
void FormUpdate::startUpdate() {
QString url_file;
const bool update_for_this_system = isSelfUpdateSupported();
QString url_file;
const bool update_for_this_system = isSelfUpdateSupported();
if (update_for_this_system && m_ui.m_listFiles->currentItem() != nullptr) {
url_file = m_ui.m_listFiles->currentItem()->data(Qt::UserRole).toString();
m_ui.m_listFiles->setEnabled(false);
}
else {
url_file = APP_URL;
}
if (update_for_this_system && m_ui.m_listFiles->currentItem() != nullptr) {
url_file = m_ui.m_listFiles->currentItem()->data(Qt::UserRole).toString();
m_ui.m_listFiles->setEnabled(false);
}
else {
url_file = APP_URL;
}
if (m_readyToInstall) {
close();
qDebug("Preparing to launch external installer '%s'.", qPrintable(QDir::toNativeSeparators(m_updateFilePath)));
if (m_readyToInstall) {
close();
qDebug("Preparing to launch external installer '%s'.", qPrintable(QDir::toNativeSeparators(m_updateFilePath)));
#if defined(Q_OS_WIN)
HINSTANCE exec_result = ShellExecute(nullptr,
nullptr,
reinterpret_cast<const WCHAR*>(QDir::toNativeSeparators(m_updateFilePath).utf16()),
nullptr,
nullptr,
SW_NORMAL);
if (exec_result <= (HINSTANCE)32) {
qDebug("External updater was not launched due to error.");
qApp->showGuiMessage(tr("Cannot update application"),
tr("Cannot launch external updater. Update application manually."),
QSystemTrayIcon::Warning, this);
}
else {
qApp->quit();
}
HINSTANCE exec_result = ShellExecute(nullptr,
nullptr,
reinterpret_cast<const WCHAR*>(QDir::toNativeSeparators(m_updateFilePath).utf16()),
nullptr,
nullptr,
SW_NORMAL);
if (exec_result <= (HINSTANCE)32) {
qDebug("External updater was not launched due to error.");
qApp->showGuiMessage(tr("Cannot update application"),
tr("Cannot launch external updater. Update application manually."),
QSystemTrayIcon::Warning, this);
}
else {
qApp->quit();
}
#endif
}
else if (update_for_this_system) {
updateProgress(0, 100);
m_btnUpdate->setText(tr("Downloading update..."));
m_btnUpdate->setEnabled(false);
m_downloader.downloadFile(url_file);
}
else {
// Self-update and package are not available.
if (!qApp->web()->openUrlInExternalBrowser(url_file)) {
qApp->showGuiMessage(tr("Cannot update application"),
tr("Cannot navigate to installation file. Check new installation downloads manually on project website."),
QSystemTrayIcon::Warning,
this, true);
}
}
}
else if (update_for_this_system) {
updateProgress(0, 100);
m_btnUpdate->setText(tr("Downloading update..."));
m_btnUpdate->setEnabled(false);
m_downloader.downloadFile(url_file);
}
else {
// Self-update and package are not available.
if (!qApp->web()->openUrlInExternalBrowser(url_file)) {
qApp->showGuiMessage(tr("Cannot update application"),
tr("Cannot navigate to installation file. Check new installation downloads manually on project website."),
QSystemTrayIcon::Warning,
this, true);
}
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -25,42 +26,42 @@
#include "miscellaneous/systemfactory.h"
#include "network-web/downloader.h"
#include <QPushButton>
#include <QNetworkReply>
#include <QPushButton>
class FormUpdate : public QDialog {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit FormUpdate(QWidget* parent);
virtual ~FormUpdate();
public:
// Returns true if application can self-update
// on current platform.
bool isSelfUpdateSupported() const;
// Constructors and destructors.
explicit FormUpdate(QWidget* parent);
virtual ~FormUpdate();
private slots:
// Check for updates and interprets the results.
void checkForUpdates();
void startUpdate();
// Returns true if application can self-update
// on current platform.
bool isSelfUpdateSupported() const;
void updateProgress(qint64 bytes_received, qint64 bytes_total);
void updateCompleted(QNetworkReply::NetworkError status, QByteArray contents);
void saveUpdateFile(const QByteArray& file_contents);
private slots:
private:
void loadAvailableFiles();
// Check for updates and interprets the results.
void checkForUpdates();
void startUpdate();
Ui::FormUpdate m_ui;
QPushButton* m_btnUpdate;
void updateProgress(qint64 bytes_received, qint64 bytes_total);
void updateCompleted(QNetworkReply::NetworkError status, QByteArray contents);
void saveUpdateFile(const QByteArray& file_contents);
Downloader m_downloader;
QString m_updateFilePath;
UpdateInfo m_updateInfo;
bool m_readyToInstall = false;
qint64 m_lastDownloadedBytes = 0;
private:
void loadAvailableFiles();
Ui::FormUpdate m_ui;
QPushButton* m_btnUpdate;
Downloader m_downloader;
QString m_updateFilePath;
UpdateInfo m_updateInfo;
bool m_readyToInstall = false;
qint64 m_lastDownloadedBytes = 0;
};
#endif // FORMUPDATE_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,76 +18,75 @@
#include "gui/discoverfeedsbutton.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/feedreader.h"
#include "core/feedsmodel.h"
#include "gui/dialogs/formmain.h"
#include "gui/tabwidget.h"
#include "gui/feedmessageviewer.h"
#include "gui/feedsview.h"
#include "core/feedsmodel.h"
#include "gui/tabwidget.h"
#include "miscellaneous/application.h"
#include "miscellaneous/feedreader.h"
#include "miscellaneous/iconfactory.h"
#include "services/abstract/serviceroot.h"
#include <QVariant>
DiscoverFeedsButton::DiscoverFeedsButton(QWidget* parent) : QToolButton(parent), m_addresses(QStringList()) {
setEnabled(false);
setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml")));
setPopupMode(QToolButton::InstantPopup);
setEnabled(false);
setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml")));
setPopupMode(QToolButton::InstantPopup);
}
DiscoverFeedsButton::~DiscoverFeedsButton() {
}
DiscoverFeedsButton::~DiscoverFeedsButton() {}
void DiscoverFeedsButton::clearFeedAddresses() {
setFeedAddresses(QStringList());
setFeedAddresses(QStringList());
}
void DiscoverFeedsButton::setFeedAddresses(const QStringList& addresses) {
setEnabled(!addresses.isEmpty());
setToolTip(addresses.isEmpty() ?
tr("This website does not contain any feeds.") :
tr("Click me to add feeds from this website.\nThis website contains %n feed(s).", 0, addresses.size()));
setEnabled(!addresses.isEmpty());
setToolTip(addresses.isEmpty() ?
tr("This website does not contain any feeds.") :
tr("Click me to add feeds from this website.\nThis website contains %n feed(s).", 0, addresses.size()));
if (menu() == nullptr) {
// Initialize the menu.
setMenu(new QMenu(this));
connect(menu(), &QMenu::triggered, this, &DiscoverFeedsButton::linkTriggered);
connect(menu(), &QMenu::aboutToShow, this, &DiscoverFeedsButton::fillMenu);
}
if (menu() == nullptr) {
// Initialize the menu.
setMenu(new QMenu(this));
connect(menu(), &QMenu::triggered, this, &DiscoverFeedsButton::linkTriggered);
connect(menu(), &QMenu::aboutToShow, this, &DiscoverFeedsButton::fillMenu);
}
menu()->hide();
m_addresses = addresses;
menu()->hide();
m_addresses = addresses;
}
void DiscoverFeedsButton::linkTriggered(QAction* action) {
const QString url = action->property("url").toString();
ServiceRoot* root = static_cast<ServiceRoot*>(action->property("root").value<void*>());
const QString url = action->property("url").toString();
ServiceRoot* root = static_cast<ServiceRoot*>(action->property("root").value<void*>());
if (root->supportsFeedAdding()) {
root->addNewFeed(url);
}
else {
qApp->showGuiMessage(tr("Not supported"),
tr("Given account does not support adding feeds."),
QSystemTrayIcon::Warning,
qApp->mainFormWidget(), true);
}
if (root->supportsFeedAdding()) {
root->addNewFeed(url);
}
else {
qApp->showGuiMessage(tr("Not supported"),
tr("Given account does not support adding feeds."),
QSystemTrayIcon::Warning,
qApp->mainFormWidget(), true);
}
}
void DiscoverFeedsButton::fillMenu() {
menu()->clear();
menu()->clear();
foreach (const ServiceRoot* root, qApp->feedReader()->feedsModel()->serviceRoots()) {
QMenu* root_menu = menu()->addMenu(root->icon(), root->title());
foreach (const ServiceRoot* root, qApp->feedReader()->feedsModel()->serviceRoots()) {
QMenu* root_menu = menu()->addMenu(root->icon(), root->title());
foreach (const QString& url, m_addresses) {
if (root->supportsFeedAdding()) {
QAction* url_action = root_menu->addAction(root->icon(), url);
url_action->setProperty("url", url);
url_action->setProperty("root", QVariant::fromValue((void*) root));
}
}
}
foreach (const QString& url, m_addresses) {
if (root->supportsFeedAdding()) {
QAction* url_action = root_menu->addAction(root->icon(), url);
url_action->setProperty("url", url);
url_action->setProperty("root", QVariant::fromValue((void*) root));
}
}
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,26 +21,27 @@
#include <QToolButton>
class DiscoverFeedsButton : public QToolButton {
Q_OBJECT
Q_OBJECT
public:
// Constructors.
explicit DiscoverFeedsButton(QWidget* parent = 0);
virtual ~DiscoverFeedsButton();
public:
// Feed addresses manipulators.
void clearFeedAddresses();
void setFeedAddresses(const QStringList& addresses);
// Constructors.
explicit DiscoverFeedsButton(QWidget* parent = 0);
virtual ~DiscoverFeedsButton();
private slots:
// User chose any of addresses.
void linkTriggered(QAction* action);
void fillMenu();
// Feed addresses manipulators.
void clearFeedAddresses();
void setFeedAddresses(const QStringList& addresses);
private:
QStringList m_addresses;
private slots:
// User chose any of addresses.
void linkTriggered(QAction* action);
void fillMenu();
private:
QStringList m_addresses;
};
#endif // DISCOVERFEEDSBUTTON_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -19,50 +20,49 @@
#include <QKeyEvent>
EditTableView::EditTableView(QWidget* parent) : QTableView(parent) {
}
EditTableView::EditTableView(QWidget* parent) : QTableView(parent) {}
void EditTableView::keyPressEvent(QKeyEvent* event) {
if (model() && event->key() == Qt::Key_Delete) {
removeSelected();
event->accept();
}
else {
QAbstractItemView::keyPressEvent(event);
}
if (model() && event->key() == Qt::Key_Delete) {
removeSelected();
event->accept();
}
else {
QAbstractItemView::keyPressEvent(event);
}
}
void EditTableView::removeSelected() {
if (!model() || !selectionModel() || !selectionModel()->hasSelection()) {
return;
}
if (!model() || !selectionModel() || !selectionModel()->hasSelection()) {
return;
}
const QModelIndexList selected_rows = selectionModel()->selectedRows();
const QModelIndexList selected_rows = selectionModel()->selectedRows();
if (selected_rows.isEmpty()) {
return;
}
if (selected_rows.isEmpty()) {
return;
}
const int new_selected_row = selected_rows.at(0).row();
const int new_selected_row = selected_rows.at(0).row();
for (int i = selected_rows.count() - 1; i >= 0; i--) {
QModelIndex idx = selected_rows.at(i);
model()->removeRow(idx.row(), rootIndex());
}
for (int i = selected_rows.count() - 1; i >= 0; i--) {
QModelIndex idx = selected_rows.at(i);
QModelIndex new_selected_index = model()->index(new_selected_row, 0, rootIndex());
model()->removeRow(idx.row(), rootIndex());
}
if (!new_selected_index.isValid()) {
new_selected_index = model()->index(new_selected_row - 1, 0, rootIndex());
}
QModelIndex new_selected_index = model()->index(new_selected_row, 0, rootIndex());
selectionModel()->select(new_selected_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
setCurrentIndex(new_selected_index);
if (!new_selected_index.isValid()) {
new_selected_index = model()->index(new_selected_row - 1, 0, rootIndex());
}
selectionModel()->select(new_selected_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
setCurrentIndex(new_selected_index);
}
void EditTableView::removeAll() {
if (model() != nullptr) {
model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex());
}
if (model() != nullptr) {
model()->removeRows(0, model()->rowCount(rootIndex()), rootIndex());
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,19 +21,18 @@
#include <QTableView>
class EditTableView : public QTableView {
Q_OBJECT
Q_OBJECT
public:
explicit EditTableView(QWidget* parent = 0);
public:
explicit EditTableView(QWidget* parent = 0);
public slots:
void removeSelected();
void removeAll();
public slots:
void removeSelected();
void removeAll();
private:
void keyPressEvent(QKeyEvent* event);
private:
void keyPressEvent(QKeyEvent* event);
};
#endif // EDITTABLEVIEW_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -18,83 +19,85 @@
#include "gui/feedstoolbar.h"
#include "miscellaneous/application.h"
#include "miscellaneous/settings.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/settings.h"
#include <QWidgetAction>
FeedsToolBar::FeedsToolBar(const QString& title, QWidget* parent) : BaseToolBar(title, parent) {
// Update right margin of filter textbox.
QMargins margins = contentsMargins();
margins.setRight(margins.right() + FILTER_RIGHT_MARGIN);
setContentsMargins(margins);
// Update right margin of filter textbox.
QMargins margins = contentsMargins();
margins.setRight(margins.right() + FILTER_RIGHT_MARGIN);
setContentsMargins(margins);
}
FeedsToolBar::~FeedsToolBar() {
}
FeedsToolBar::~FeedsToolBar() {}
QList<QAction*> FeedsToolBar::availableActions() const {
return qApp->userActions();
return qApp->userActions();
}
QList<QAction*> FeedsToolBar::changeableActions() const {
return actions();
return actions();
}
void FeedsToolBar::saveChangeableActions(const QStringList& actions) {
qApp->settings()->setValue(GROUP(GUI), GUI::FeedsToolbarActions, actions.join(QSL(",")));
loadSpecificActions(getSpecificActions(actions));
qApp->settings()->setValue(GROUP(GUI), GUI::FeedsToolbarActions, actions.join(QSL(",")));
loadSpecificActions(getSpecificActions(actions));
}
QList<QAction*> FeedsToolBar::getSpecificActions(const QStringList& actions) {
QList<QAction*> available_actions = availableActions();
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) {
QAction* matching_action = findMatchingAction(action_name, available_actions);
// Iterate action names and add respectable actions into the toolbar.
foreach (const QString& action_name, actions) {
QAction* matching_action = findMatchingAction(action_name, available_actions);
if (matching_action != nullptr) {
// Add existing standard action.
spec_actions.append(matching_action);
}
else if (action_name == SEPARATOR_ACTION_NAME) {
// Add new separator.
QAction* act = new QAction(this);
act->setSeparator(true);
spec_actions.append(act);
}
else if (action_name == SPACER_ACTION_NAME) {
// Add new spacer.
QWidget* spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QWidgetAction* action = new QWidgetAction(this);
action->setDefaultWidget(spacer);
action->setIcon(qApp->icons()->fromTheme(QSL("system-search")));
action->setProperty("type", SPACER_ACTION_NAME);
action->setProperty("name", tr("Toolbar spacer"));
spec_actions.append(action);
}
}
if (matching_action != nullptr) {
// Add existing standard action.
spec_actions.append(matching_action);
}
else if (action_name == SEPARATOR_ACTION_NAME) {
// Add new separator.
QAction* act = new QAction(this);
return spec_actions;
act->setSeparator(true);
spec_actions.append(act);
}
else if (action_name == SPACER_ACTION_NAME) {
// Add new spacer.
QWidget* spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QWidgetAction* action = new QWidgetAction(this);
action->setDefaultWidget(spacer);
action->setIcon(qApp->icons()->fromTheme(QSL("system-search")));
action->setProperty("type", SPACER_ACTION_NAME);
action->setProperty("name", tr("Toolbar spacer"));
spec_actions.append(action);
}
}
return spec_actions;
}
void FeedsToolBar::loadSpecificActions(const QList<QAction*>& actions) {
clear();
clear();
foreach (QAction* act, actions) {
addAction(act);
}
foreach (QAction* act, actions) {
addAction(act);
}
}
QStringList FeedsToolBar::defaultActions() const {
return QString(GUI::FeedsToolbarActionsDef).split(',',
QString::SkipEmptyParts);
return QString(GUI::FeedsToolbarActionsDef).split(',',
QString::SkipEmptyParts);
}
QStringList FeedsToolBar::savedActions() const {
return qApp->settings()->value(GROUP(GUI), SETTING(GUI::FeedsToolbarActions)).toString().split(',',
QString::SkipEmptyParts);
return qApp->settings()->value(GROUP(GUI), SETTING(GUI::FeedsToolbarActions)).toString().split(',',
QString::SkipEmptyParts);
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,24 +21,24 @@
#include "gui/basetoolbar.h"
class FeedsToolBar : public BaseToolBar {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit FeedsToolBar(const QString& title, QWidget* parent = 0);
virtual ~FeedsToolBar();
public:
QList<QAction*> availableActions() const;
QList<QAction*> changeableActions() const;
void saveChangeableActions(const QStringList& actions);
// Constructors and destructors.
explicit FeedsToolBar(const QString& title, QWidget* parent = 0);
virtual ~FeedsToolBar();
QList<QAction*> getSpecificActions(const QStringList& actions);
void loadSpecificActions(const QList<QAction*>& actions);
QList<QAction*> availableActions() const;
QList<QAction*> changeableActions() const;
void saveChangeableActions(const QStringList& actions);
QStringList defaultActions() const;
QStringList savedActions() const;
QList<QAction*> getSpecificActions(const QStringList& actions);
void loadSpecificActions(const QList<QAction*>& actions);
QStringList defaultActions() const;
QStringList savedActions() const;
};
#endif // FEEDSTOOLBAR_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,338 +18,344 @@
#include "gui/feedsview.h"
#include "definitions/definitions.h"
#include "core/feedsmodel.h"
#include "core/feedsproxymodel.h"
#include "services/abstract/rootitem.h"
#include "miscellaneous/systemfactory.h"
#include "miscellaneous/feedreader.h"
#include "miscellaneous/mutex.h"
#include "gui/systemtrayicon.h"
#include "definitions/definitions.h"
#include "gui/dialogs/formmain.h"
#include "gui/messagebox.h"
#include "gui/styleditemdelegatewithoutfocus.h"
#include "gui/dialogs/formmain.h"
#include "gui/systemtrayicon.h"
#include "miscellaneous/feedreader.h"
#include "miscellaneous/mutex.h"
#include "miscellaneous/systemfactory.h"
#include "services/abstract/feed.h"
#include "services/abstract/rootitem.h"
#include "services/abstract/serviceroot.h"
#include "services/standard/gui/formstandardcategorydetails.h"
#include "services/standard/standardcategory.h"
#include "services/standard/standardfeed.h"
#include "services/standard/gui/formstandardcategorydetails.h"
#include <QMenu>
#include <QHeaderView>
#include <QContextMenuEvent>
#include <QPointer>
#include <QHeaderView>
#include <QMenu>
#include <QPainter>
#include <QPointer>
#include <QTimer>
FeedsView::FeedsView(QWidget* parent)
: QTreeView(parent),
m_contextMenuCategories(nullptr),
m_contextMenuFeeds(nullptr),
m_contextMenuEmptySpace(nullptr),
m_contextMenuOtherItems(nullptr) {
setObjectName(QSL("FeedsView"));
: QTreeView(parent),
m_contextMenuCategories(nullptr),
m_contextMenuFeeds(nullptr),
m_contextMenuEmptySpace(nullptr),
m_contextMenuOtherItems(nullptr) {
setObjectName(QSL("FeedsView"));
// Allocate models.
m_sourceModel = qApp->feedReader()->feedsModel();
m_proxyModel = qApp->feedReader()->feedsProxyModel();
// Allocate models.
m_sourceModel = qApp->feedReader()->feedsModel();
m_proxyModel = qApp->feedReader()->feedsProxyModel();
// Connections.
connect(m_sourceModel, &FeedsModel::requireItemValidationAfterDragDrop, this, &FeedsView::validateItemAfterDragDrop);
connect(m_sourceModel, &FeedsModel::itemExpandRequested, this, &FeedsView::onItemExpandRequested);
connect(m_sourceModel, &FeedsModel::itemExpandStateSaveRequested, this, &FeedsView::onItemExpandStateSaveRequested);
connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState);
connect(m_proxyModel, &FeedsProxyModel::expandAfterFilterIn, this, &FeedsView::expandItemDelayed);
connect(m_sourceModel, &FeedsModel::requireItemValidationAfterDragDrop, this, &FeedsView::validateItemAfterDragDrop);
connect(m_sourceModel, &FeedsModel::itemExpandRequested, this, &FeedsView::onItemExpandRequested);
connect(m_sourceModel, &FeedsModel::itemExpandStateSaveRequested, this, &FeedsView::onItemExpandStateSaveRequested);
connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState);
connect(m_proxyModel, &FeedsProxyModel::expandAfterFilterIn, this, &FeedsView::expandItemDelayed);
setModel(m_proxyModel);
setupAppearance();
setupAppearance();
}
FeedsView::~FeedsView() {
qDebug("Destroying FeedsView instance.");
qDebug("Destroying FeedsView instance.");
}
void FeedsView::setSortingEnabled(bool enable) {
disconnect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState);
QTreeView::setSortingEnabled(enable);
connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState);
disconnect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState);
QTreeView::setSortingEnabled(enable);
connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState);
}
QList<Feed*> FeedsView::selectedFeeds() const {
const QModelIndex current_index = currentIndex();
const QModelIndex current_index = currentIndex();
if (current_index.isValid()) {
return m_sourceModel->feedsForIndex(m_proxyModel->mapToSource(current_index));
}
else {
return QList<Feed*>();
}
if (current_index.isValid()) {
return m_sourceModel->feedsForIndex(m_proxyModel->mapToSource(current_index));
}
else {
return QList<Feed*>();
}
}
RootItem* FeedsView::selectedItem() const {
const QModelIndexList selected_rows = selectionModel()->selectedRows();
const QModelIndexList selected_rows = selectionModel()->selectedRows();
if (selected_rows.isEmpty()) {
return nullptr;
}
else {
RootItem* selected_item = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(selected_rows.at(0)));
return selected_item == m_sourceModel->rootItem() ? nullptr : selected_item;
}
if (selected_rows.isEmpty()) {
return nullptr;
}
else {
RootItem* selected_item = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(selected_rows.at(0)));
return selected_item == m_sourceModel->rootItem() ? nullptr : selected_item;
}
}
void FeedsView::onItemExpandStateSaveRequested(RootItem* item) {
saveExpandStates(item);
saveExpandStates(item);
}
void FeedsView::saveAllExpandStates() {
saveExpandStates(sourceModel()->rootItem());
saveExpandStates(sourceModel()->rootItem());
}
void FeedsView::saveExpandStates(RootItem* item) {
Settings* settings = qApp->settings();
QList<RootItem*> items = item->getSubTree(RootItemKind::Category | RootItemKind::ServiceRoot);
Settings* settings = qApp->settings();
// Iterate all categories and save their expand statuses.
foreach (const RootItem* item, items) {
const QString setting_name = item->hashCode();
QModelIndex source_index = sourceModel()->indexForItem(item);
QModelIndex visible_index = model()->mapFromSource(source_index);
settings->setValue(GROUP(CategoriesExpandStates),
setting_name,
isExpanded(visible_index));
}
QList<RootItem*> items = item->getSubTree(RootItemKind::Category | RootItemKind::ServiceRoot);
// Iterate all categories and save their expand statuses.
foreach (const RootItem* item, items) {
const QString setting_name = item->hashCode();
QModelIndex source_index = sourceModel()->indexForItem(item);
QModelIndex visible_index = model()->mapFromSource(source_index);
settings->setValue(GROUP(CategoriesExpandStates),
setting_name,
isExpanded(visible_index));
}
}
void FeedsView::loadAllExpandStates() {
const Settings* settings = qApp->settings();
QList<RootItem*> expandable_items;
expandable_items.append(sourceModel()->rootItem()->getSubTree(RootItemKind::Category | RootItemKind::ServiceRoot));
const Settings* settings = qApp->settings();
// Iterate all categories and save their expand statuses.
foreach (const RootItem* item, expandable_items) {
const QString setting_name = item->hashCode();
setExpanded(model()->mapFromSource(sourceModel()->indexForItem(item)),
settings->value(GROUP(CategoriesExpandStates), setting_name, item->childCount() > 0).toBool());
}
QList<RootItem*> expandable_items;
expandable_items.append(sourceModel()->rootItem()->getSubTree(RootItemKind::Category | RootItemKind::ServiceRoot));
sortByColumn(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortColumnFeeds)).toInt(),
static_cast<Qt::SortOrder>(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortOrderFeeds)).toInt()));
// Iterate all categories and save their expand statuses.
foreach (const RootItem* item, expandable_items) {
const QString setting_name = item->hashCode();
setExpanded(model()->mapFromSource(sourceModel()->indexForItem(item)),
settings->value(GROUP(CategoriesExpandStates), setting_name, item->childCount() > 0).toBool());
}
sortByColumn(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortColumnFeeds)).toInt(),
static_cast<Qt::SortOrder>(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortOrderFeeds)).toInt()));
}
void FeedsView::sortByColumn(int column, Qt::SortOrder order) {
const int old_column = header()->sortIndicatorSection();
const Qt::SortOrder old_order = header()->sortIndicatorOrder();
const int old_column = header()->sortIndicatorSection();
const Qt::SortOrder old_order = header()->sortIndicatorOrder();
if (column == old_column && order == old_order) {
m_proxyModel->sort(column, order);
}
else {
QTreeView::sortByColumn(column, order);
}
if (column == old_column && order == old_order) {
m_proxyModel->sort(column, order);
}
else {
QTreeView::sortByColumn(column, order);
}
}
void FeedsView::addFeedIntoSelectedAccount() {
const RootItem* selected = selectedItem();
const RootItem* selected = selectedItem();
if (selected != nullptr) {
ServiceRoot* root = selected->getParentServiceRoot();
if (selected != nullptr) {
ServiceRoot* root = selected->getParentServiceRoot();
if (root->supportsFeedAdding()) {
root->addNewFeed();
}
else {
qApp->showGuiMessage(tr("Not supported"),
tr("Selected account does not support adding of new feeds."),
QSystemTrayIcon::Warning,
qApp->mainFormWidget(), true);
}
}
if (root->supportsFeedAdding()) {
root->addNewFeed();
}
else {
qApp->showGuiMessage(tr("Not supported"),
tr("Selected account does not support adding of new feeds."),
QSystemTrayIcon::Warning,
qApp->mainFormWidget(), true);
}
}
}
void FeedsView::addCategoryIntoSelectedAccount() {
const RootItem* selected = selectedItem();
const RootItem* selected = selectedItem();
if (selected != nullptr) {
ServiceRoot* root = selected->getParentServiceRoot();
if (selected != nullptr) {
ServiceRoot* root = selected->getParentServiceRoot();
if (root->supportsCategoryAdding()) {
root->addNewCategory();
}
else {
qApp->showGuiMessage(tr("Not supported"),
tr("Selected account does not support adding of new categories."),
QSystemTrayIcon::Warning,
qApp->mainFormWidget(), true);
}
}
if (root->supportsCategoryAdding()) {
root->addNewCategory();
}
else {
qApp->showGuiMessage(tr("Not supported"),
tr("Selected account does not support adding of new categories."),
QSystemTrayIcon::Warning,
qApp->mainFormWidget(), true);
}
}
}
void FeedsView::expandCollapseCurrentItem() {
if (selectionModel()->selectedRows().size() == 1) {
QModelIndex index = selectionModel()->selectedRows().at(0);
if (selectionModel()->selectedRows().size() == 1) {
QModelIndex index = selectionModel()->selectedRows().at(0);
if (!index.child(0, 0).isValid() && index.parent().isValid()) {
setCurrentIndex(index.parent());
index = index.parent();
}
if (!index.child(0, 0).isValid() && index.parent().isValid()) {
setCurrentIndex(index.parent());
index = index.parent();
}
isExpanded(index) ? collapse(index) : expand(index);
}
isExpanded(index) ? collapse(index) : expand(index);
}
}
void FeedsView::updateSelectedItems() {
qApp->feedReader()->updateFeeds(selectedFeeds());
qApp->feedReader()->updateFeeds(selectedFeeds());
}
void FeedsView::clearSelectedFeeds() {
m_sourceModel->markItemCleared(selectedItem(), false);
m_sourceModel->markItemCleared(selectedItem(), false);
}
void FeedsView::clearAllFeeds() {
m_sourceModel->markItemCleared(m_sourceModel->rootItem(), false);
m_sourceModel->markItemCleared(m_sourceModel->rootItem(), false);
}
void FeedsView::editSelectedItem() {
if (!qApp->feedUpdateLock()->tryLock()) {
// Lock was not obtained because
// it is used probably by feed updater or application
// is quitting.
qApp->showGuiMessage(tr("Cannot edit item"),
tr("Selected item cannot be edited because another critical operation is ongoing."),
QSystemTrayIcon::Warning, qApp->mainFormWidget(), true);
// Thus, cannot delete and quit the method.
return;
}
if (!qApp->feedUpdateLock()->tryLock()) {
// Lock was not obtained because
// it is used probably by feed updater or application
// is quitting.
qApp->showGuiMessage(tr("Cannot edit item"),
tr("Selected item cannot be edited because another critical operation is ongoing."),
QSystemTrayIcon::Warning, qApp->mainFormWidget(), true);
if (selectedItem()->canBeEdited()) {
selectedItem()->editViaGui();
}
else {
qApp->showGuiMessage(tr("Cannot edit item"),
tr("Selected item cannot be edited, this is not (yet?) supported."),
QSystemTrayIcon::Warning,
qApp->mainFormWidget(),
true);
}
// Thus, cannot delete and quit the method.
return;
}
// Changes are done, unlock the update master lock.
qApp->feedUpdateLock()->unlock();
if (selectedItem()->canBeEdited()) {
selectedItem()->editViaGui();
}
else {
qApp->showGuiMessage(tr("Cannot edit item"),
tr("Selected item cannot be edited, this is not (yet?) supported."),
QSystemTrayIcon::Warning,
qApp->mainFormWidget(),
true);
}
// Changes are done, unlock the update master lock.
qApp->feedUpdateLock()->unlock();
}
void FeedsView::deleteSelectedItem() {
if (!qApp->feedUpdateLock()->tryLock()) {
// Lock was not obtained because
// it is used probably by feed updater or application
// is quitting.
qApp->showGuiMessage(tr("Cannot delete item"),
tr("Selected item cannot be deleted because another critical operation is ongoing."),
QSystemTrayIcon::Warning, qApp->mainFormWidget(), true);
// Thus, cannot delete and quit the method.
return;
}
if (!qApp->feedUpdateLock()->tryLock()) {
// Lock was not obtained because
// it is used probably by feed updater or application
// is quitting.
qApp->showGuiMessage(tr("Cannot delete item"),
tr("Selected item cannot be deleted because another critical operation is ongoing."),
QSystemTrayIcon::Warning, qApp->mainFormWidget(), true);
if (!currentIndex().isValid()) {
// Changes are done, unlock the update master lock and exit.
qApp->feedUpdateLock()->unlock();
return;
}
// Thus, cannot delete and quit the method.
return;
}
RootItem* selected_item = selectedItem();
if (!currentIndex().isValid()) {
// Changes are done, unlock the update master lock and exit.
qApp->feedUpdateLock()->unlock();
return;
}
if (selected_item != nullptr) {
if (selected_item->canBeDeleted()) {
// Ask user first.
if (MessageBox::show(qApp->mainFormWidget(),
QMessageBox::Question,
tr("Deleting \"%1\"").arg(selected_item->title()),
tr("You are about to completely delete item \"%1\".").arg(selected_item->title()),
tr("Are you sure?"),
QString(), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::No) {
// User refused.
qApp->feedUpdateLock()->unlock();
return;
}
RootItem* selected_item = selectedItem();
// We have deleteable item selected, remove it via GUI.
if (!selected_item->deleteViaGui()) {
qApp->showGuiMessage(tr("Cannot delete \"%1\"").arg(selected_item->title()),
tr("This item cannot be deleted because something critically failed. Submit bug report."),
QSystemTrayIcon::Critical,
qApp->mainFormWidget(),
true);
}
}
else {
qApp->showGuiMessage(tr("Cannot delete \"%1\"").arg(selected_item->title()),
tr("This item cannot be deleted, because it does not support it\nor this functionality is not implemented yet."),
QSystemTrayIcon::Critical,
qApp->mainFormWidget(),
true);
}
}
if (selected_item != nullptr) {
if (selected_item->canBeDeleted()) {
// Ask user first.
if (MessageBox::show(qApp->mainFormWidget(),
QMessageBox::Question,
tr("Deleting \"%1\"").arg(selected_item->title()),
tr("You are about to completely delete item \"%1\".").arg(selected_item->title()),
tr("Are you sure?"),
QString(), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::No) {
// User refused.
qApp->feedUpdateLock()->unlock();
return;
}
// Changes are done, unlock the update master lock.
qApp->feedUpdateLock()->unlock();
// We have deleteable item selected, remove it via GUI.
if (!selected_item->deleteViaGui()) {
qApp->showGuiMessage(tr("Cannot delete \"%1\"").arg(selected_item->title()),
tr("This item cannot be deleted because something critically failed. Submit bug report."),
QSystemTrayIcon::Critical,
qApp->mainFormWidget(),
true);
}
}
else {
qApp->showGuiMessage(tr("Cannot delete \"%1\"").arg(selected_item->title()),
tr("This item cannot be deleted, because it does not support it\nor this functionality is not implemented yet."),
QSystemTrayIcon::Critical,
qApp->mainFormWidget(),
true);
}
}
// Changes are done, unlock the update master lock.
qApp->feedUpdateLock()->unlock();
}
void FeedsView::markSelectedItemReadStatus(RootItem::ReadStatus read) {
m_sourceModel->markItemRead(selectedItem(), read);
m_sourceModel->markItemRead(selectedItem(), read);
}
void FeedsView::markSelectedItemRead() {
markSelectedItemReadStatus(RootItem::Read);
markSelectedItemReadStatus(RootItem::Read);
}
void FeedsView::markSelectedItemUnread() {
markSelectedItemReadStatus(RootItem::Unread);
markSelectedItemReadStatus(RootItem::Unread);
}
void FeedsView::markAllItemsReadStatus(RootItem::ReadStatus read) {
m_sourceModel->markItemRead(m_sourceModel->rootItem(), read);
m_sourceModel->markItemRead(m_sourceModel->rootItem(), read);
}
void FeedsView::markAllItemsRead() {
markAllItemsReadStatus(RootItem::Read);
markAllItemsReadStatus(RootItem::Read);
}
void FeedsView::openSelectedItemsInNewspaperMode() {
RootItem* selected_item = selectedItem();
const QList<Message> messages = m_sourceModel->messagesForItem(selected_item);
RootItem* selected_item = selectedItem();
const QList<Message> messages = m_sourceModel->messagesForItem(selected_item);
if (!messages.isEmpty()) {
emit openMessagesInNewspaperView(selected_item, messages);
}
if (!messages.isEmpty()) {
emit openMessagesInNewspaperView(selected_item, messages);
}
}
void FeedsView::selectNextItem() {
const QModelIndex& curr_idx = currentIndex();
const QModelIndex& curr_idx = currentIndex();
if (m_proxyModel->hasChildren(curr_idx) && !isExpanded(curr_idx)) {
expand(curr_idx);
}
if (m_proxyModel->hasChildren(curr_idx) && !isExpanded(curr_idx)) {
expand(curr_idx);
}
const QModelIndex& index_next = moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier);
const QModelIndex& index_next = moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier);
if (index_next.isValid()) {
setCurrentIndex(index_next);
setFocus();
}
if (index_next.isValid()) {
setCurrentIndex(index_next);
setFocus();
}
}
void FeedsView::selectPreviousItem() {
const QModelIndex& curr_idx = currentIndex();
const QModelIndex& curr_idx = currentIndex();
if (m_proxyModel->hasChildren(curr_idx) && !isExpanded(curr_idx)) {
expand(curr_idx);
}
if (m_proxyModel->hasChildren(curr_idx) && !isExpanded(curr_idx)) {
expand(curr_idx);
}
const QModelIndex& index_previous = moveCursor(QAbstractItemView::MoveUp, Qt::NoModifier);
const QModelIndex& index_previous = moveCursor(QAbstractItemView::MoveUp, Qt::NoModifier);
if (index_previous.isValid()) {
setCurrentIndex(index_previous);
setFocus();
if (index_previous.isValid()) {
setCurrentIndex(index_previous);
setFocus();
}
}
@ -416,197 +423,200 @@ QModelIndex FeedsView::nextUnreadItem(QModelIndex default_row) {
}
void FeedsView::switchVisibility() {
setVisible(!isVisible());
setVisible(!isVisible());
}
void FeedsView::expandItemDelayed(const QModelIndex& idx) {
QTimer::singleShot(100, this, [ = ] {
setExpanded(m_proxyModel->mapFromSource(idx), true);
});
setExpanded(m_proxyModel->mapFromSource(idx), true);
});
}
QMenu* FeedsView::initializeContextMenuCategories(RootItem* clicked_item) {
if (m_contextMenuCategories == nullptr) {
m_contextMenuCategories = new QMenu(tr("Context menu for categories"), this);
}
else {
m_contextMenuCategories->clear();
}
if (m_contextMenuCategories == nullptr) {
m_contextMenuCategories = new QMenu(tr("Context menu for categories"), this);
}
else {
m_contextMenuCategories->clear();
}
QList<QAction*> specific_actions = clicked_item->contextMenu();
m_contextMenuCategories->addActions(QList<QAction*>() <<
qApp->mainForm()->m_ui->m_actionUpdateSelectedItems <<
qApp->mainForm()->m_ui->m_actionEditSelectedItem <<
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode <<
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead <<
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread <<
qApp->mainForm()->m_ui->m_actionDeleteSelectedItem);
QList<QAction*> specific_actions = clicked_item->contextMenu();
m_contextMenuCategories->addActions(QList<QAction*>() <<
qApp->mainForm()->m_ui->m_actionUpdateSelectedItems <<
qApp->mainForm()->m_ui->m_actionEditSelectedItem <<
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode <<
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead <<
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread <<
qApp->mainForm()->m_ui->m_actionDeleteSelectedItem);
if (!specific_actions.isEmpty()) {
m_contextMenuCategories->addSeparator();
m_contextMenuCategories->addActions(specific_actions);
}
if (!specific_actions.isEmpty()) {
m_contextMenuCategories->addSeparator();
m_contextMenuCategories->addActions(specific_actions);
}
return m_contextMenuCategories;
return m_contextMenuCategories;
}
QMenu* FeedsView::initializeContextMenuFeeds(RootItem* clicked_item) {
if (m_contextMenuFeeds == nullptr) {
m_contextMenuFeeds = new QMenu(tr("Context menu for categories"), this);
}
else {
m_contextMenuFeeds->clear();
}
if (m_contextMenuFeeds == nullptr) {
m_contextMenuFeeds = new QMenu(tr("Context menu for categories"), this);
}
else {
m_contextMenuFeeds->clear();
}
QList<QAction*> specific_actions = clicked_item->contextMenu();
m_contextMenuFeeds->addActions(QList<QAction*>() <<
qApp->mainForm()->m_ui->m_actionUpdateSelectedItems <<
qApp->mainForm()->m_ui->m_actionEditSelectedItem <<
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode <<
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead <<
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread <<
qApp->mainForm()->m_ui->m_actionDeleteSelectedItem);
QList<QAction*> specific_actions = clicked_item->contextMenu();
m_contextMenuFeeds->addActions(QList<QAction*>() <<
qApp->mainForm()->m_ui->m_actionUpdateSelectedItems <<
qApp->mainForm()->m_ui->m_actionEditSelectedItem <<
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode <<
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead <<
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread <<
qApp->mainForm()->m_ui->m_actionDeleteSelectedItem);
if (!specific_actions.isEmpty()) {
m_contextMenuFeeds->addSeparator();
m_contextMenuFeeds->addActions(specific_actions);
}
if (!specific_actions.isEmpty()) {
m_contextMenuFeeds->addSeparator();
m_contextMenuFeeds->addActions(specific_actions);
}
return m_contextMenuFeeds;
return m_contextMenuFeeds;
}
QMenu* FeedsView::initializeContextMenuEmptySpace() {
if (m_contextMenuEmptySpace == nullptr) {
m_contextMenuEmptySpace = new QMenu(tr("Context menu for empty space"), this);
m_contextMenuEmptySpace->addAction(qApp->mainForm()->m_ui->m_actionUpdateAllItems);
m_contextMenuEmptySpace->addSeparator();
}
if (m_contextMenuEmptySpace == nullptr) {
m_contextMenuEmptySpace = new QMenu(tr("Context menu for empty space"), this);
m_contextMenuEmptySpace->addAction(qApp->mainForm()->m_ui->m_actionUpdateAllItems);
m_contextMenuEmptySpace->addSeparator();
}
return m_contextMenuEmptySpace;
return m_contextMenuEmptySpace;
}
QMenu* FeedsView::initializeContextMenuOtherItem(RootItem* clicked_item) {
if (m_contextMenuOtherItems == nullptr) {
m_contextMenuOtherItems = new QMenu(tr("Context menu for other items"), this);
}
else {
m_contextMenuOtherItems->clear();
}
if (m_contextMenuOtherItems == nullptr) {
m_contextMenuOtherItems = new QMenu(tr("Context menu for other items"), this);
}
else {
m_contextMenuOtherItems->clear();
}
QList<QAction*> specific_actions = clicked_item->contextMenu();
QList<QAction*> specific_actions = clicked_item->contextMenu();
if (!specific_actions.isEmpty()) {
m_contextMenuOtherItems->addSeparator();
m_contextMenuOtherItems->addActions(specific_actions);
}
else {
m_contextMenuOtherItems->addAction(qApp->mainForm()->m_ui->m_actionNoActions);
}
if (!specific_actions.isEmpty()) {
m_contextMenuOtherItems->addSeparator();
m_contextMenuOtherItems->addActions(specific_actions);
}
else {
m_contextMenuOtherItems->addAction(qApp->mainForm()->m_ui->m_actionNoActions);
}
return m_contextMenuOtherItems;
return m_contextMenuOtherItems;
}
void FeedsView::setupAppearance() {
// Setup column resize strategies.
header()->setSectionResizeMode(FDS_MODEL_TITLE_INDEX, QHeaderView::Stretch);
header()->setSectionResizeMode(FDS_MODEL_COUNTS_INDEX, QHeaderView::ResizeToContents);
// Setup column resize strategies.
header()->setSectionResizeMode(FDS_MODEL_TITLE_INDEX, QHeaderView::Stretch);
header()->setSectionResizeMode(FDS_MODEL_COUNTS_INDEX, QHeaderView::ResizeToContents);
header()->setStretchLastSection(false);
header()->setSortIndicatorShown(false);
setUniformRowHeights(true);
setAnimated(true);
setSortingEnabled(true);
setItemsExpandable(true);
setExpandsOnDoubleClick(true);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setIndentation(FEEDS_VIEW_INDENTATION);
setAcceptDrops(false);
setDragEnabled(true);
setDropIndicatorShown(true);
setDragDropMode(QAbstractItemView::InternalMove);
setAllColumnsShowFocus(false);
setRootIsDecorated(false);
setSelectionMode(QAbstractItemView::SingleSelection);
setItemDelegate(new StyledItemDelegateWithoutFocus(this));
setUniformRowHeights(true);
setAnimated(true);
setSortingEnabled(true);
setItemsExpandable(true);
setExpandsOnDoubleClick(true);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setIndentation(FEEDS_VIEW_INDENTATION);
setAcceptDrops(false);
setDragEnabled(true);
setDropIndicatorShown(true);
setDragDropMode(QAbstractItemView::InternalMove);
setAllColumnsShowFocus(false);
setRootIsDecorated(false);
setSelectionMode(QAbstractItemView::SingleSelection);
setItemDelegate(new StyledItemDelegateWithoutFocus(this));
}
void FeedsView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
RootItem* selected_item = selectedItem();
m_proxyModel->setSelectedItem(selected_item);
QTreeView::selectionChanged(selected, deselected);
emit itemSelected(selected_item);
m_proxyModel->invalidateReadFeedsFilter();
RootItem* selected_item = selectedItem();
m_proxyModel->setSelectedItem(selected_item);
QTreeView::selectionChanged(selected, deselected);
emit itemSelected(selected_item);
m_proxyModel->invalidateReadFeedsFilter();
}
void FeedsView::keyPressEvent(QKeyEvent* event) {
QTreeView::keyPressEvent(event);
QTreeView::keyPressEvent(event);
if (event->key() == Qt::Key_Delete) {
deleteSelectedItem();
}
if (event->key() == Qt::Key_Delete) {
deleteSelectedItem();
}
}
void FeedsView::contextMenuEvent(QContextMenuEvent* event) {
const QModelIndex clicked_index = indexAt(event->pos());
const QModelIndex clicked_index = indexAt(event->pos());
if (clicked_index.isValid()) {
const QModelIndex mapped_index = model()->mapToSource(clicked_index);
RootItem* clicked_item = sourceModel()->itemForIndex(mapped_index);
if (clicked_index.isValid()) {
const QModelIndex mapped_index = model()->mapToSource(clicked_index);
RootItem* clicked_item = sourceModel()->itemForIndex(mapped_index);
if (clicked_item->kind() == RootItemKind::Category) {
// Display context menu for categories.
initializeContextMenuCategories(clicked_item)->exec(event->globalPos());
}
else if (clicked_item->kind() == RootItemKind::Feed) {
// Display context menu for feeds.
initializeContextMenuFeeds(clicked_item)->exec(event->globalPos());
}
else {
initializeContextMenuOtherItem(clicked_item)->exec(event->globalPos());
}
}
else {
// Display menu for empty space.
initializeContextMenuEmptySpace()->exec(event->globalPos());
}
if (clicked_item->kind() == RootItemKind::Category) {
// Display context menu for categories.
initializeContextMenuCategories(clicked_item)->exec(event->globalPos());
}
else if (clicked_item->kind() == RootItemKind::Feed) {
// Display context menu for feeds.
initializeContextMenuFeeds(clicked_item)->exec(event->globalPos());
}
else {
initializeContextMenuOtherItem(clicked_item)->exec(event->globalPos());
}
}
else {
// Display menu for empty space.
initializeContextMenuEmptySpace()->exec(event->globalPos());
}
}
void FeedsView::mouseDoubleClickEvent(QMouseEvent* event) {
QModelIndex idx = indexAt(event->pos());
QModelIndex idx = indexAt(event->pos());
if (idx.isValid()) {
RootItem* item = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(idx));
if (idx.isValid()) {
RootItem* item = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(idx));
if (item->kind() == RootItemKind::Feed || item->kind() == RootItemKind::Bin) {
const QList<Message> messages = m_sourceModel->messagesForItem(item);
if (item->kind() == RootItemKind::Feed || item->kind() == RootItemKind::Bin) {
const QList<Message> messages = m_sourceModel->messagesForItem(item);
if (!messages.isEmpty()) {
emit openMessagesInNewspaperView(item, messages);
}
}
}
if (!messages.isEmpty()) {
emit openMessagesInNewspaperView(item, messages);
}
}
}
QTreeView::mouseDoubleClickEvent(event);
QTreeView::mouseDoubleClickEvent(event);
}
void FeedsView::saveSortState(int column, Qt::SortOrder order) {
qApp->settings()->setValue(GROUP(GUI), GUI::DefaultSortColumnFeeds, column);
qApp->settings()->setValue(GROUP(GUI), GUI::DefaultSortOrderFeeds, order);
qApp->settings()->setValue(GROUP(GUI), GUI::DefaultSortColumnFeeds, column);
qApp->settings()->setValue(GROUP(GUI), GUI::DefaultSortOrderFeeds, order);
}
void FeedsView::validateItemAfterDragDrop(const QModelIndex& source_index) {
const QModelIndex mapped = m_proxyModel->mapFromSource(source_index);
const QModelIndex mapped = m_proxyModel->mapFromSource(source_index);
if (mapped.isValid()) {
expand(mapped);
setCurrentIndex(mapped);
}
if (mapped.isValid()) {
expand(mapped);
setCurrentIndex(mapped);
}
}
void FeedsView::onItemExpandRequested(const QList<RootItem*>& items, bool exp) {
foreach (const RootItem* item, items) {
QModelIndex source_index = m_sourceModel->indexForItem(item);
QModelIndex proxy_index = m_proxyModel->mapFromSource(source_index);
setExpanded(proxy_index, exp);
}
foreach (const RootItem* item, items) {
QModelIndex source_index = m_sourceModel->indexForItem(item);
QModelIndex proxy_index = m_proxyModel->mapFromSource(source_index);
setExpanded(proxy_index, exp);
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -24,120 +25,119 @@
#include <QStyledItemDelegate>
class FeedsProxyModel;
class Feed;
class Category;
class FeedsView : public QTreeView {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit FeedsView(QWidget* parent = 0);
virtual ~FeedsView();
public:
// Fundamental accessors.
inline FeedsProxyModel* model() const {
return m_proxyModel;
}
// Constructors and destructors.
explicit FeedsView(QWidget* parent = 0);
virtual ~FeedsView();
inline FeedsModel* sourceModel() const {
return m_sourceModel;
}
// Fundamental accessors.
inline FeedsProxyModel* model() const {
return m_proxyModel;
}
void setSortingEnabled(bool enable);
inline FeedsModel* sourceModel() const {
return m_sourceModel;
}
// Returns list of selected/all feeds.
// NOTE: This is recursive method which returns all descendants.
QList<Feed*> selectedFeeds() const;
void setSortingEnabled(bool enable);
// Returns pointers to selected feed/category if they are really
// selected.
RootItem* selectedItem() const;
// Returns list of selected/all feeds.
// NOTE: This is recursive method which returns all descendants.
QList<Feed*> selectedFeeds() const;
// Saves/loads expand states of all nodes (feeds/categories) of the list to/from settings.
void saveAllExpandStates();
void loadAllExpandStates();
// Returns pointers to selected feed/category if they are really
// selected.
RootItem* selectedItem() const;
public slots:
void sortByColumn(int column, Qt::SortOrder order);
// Saves/loads expand states of all nodes (feeds/categories) of the list to/from settings.
void saveAllExpandStates();
void loadAllExpandStates();
void addFeedIntoSelectedAccount();
void addCategoryIntoSelectedAccount();
void expandCollapseCurrentItem();
public slots:
void sortByColumn(int column, Qt::SortOrder order);
// Feed updating.
void updateSelectedItems();
void addFeedIntoSelectedAccount();
void addCategoryIntoSelectedAccount();
void expandCollapseCurrentItem();
// Feed read/unread manipulators.
void markSelectedItemRead();
void markSelectedItemUnread();
void markAllItemsRead();
// Feed updating.
void updateSelectedItems();
// Newspaper accessors.
void openSelectedItemsInNewspaperMode();
// Feed read/unread manipulators.
void markSelectedItemRead();
void markSelectedItemUnread();
void markAllItemsRead();
// Feed clearers.
void clearSelectedFeeds();
void clearAllFeeds();
// Newspaper accessors.
void openSelectedItemsInNewspaperMode();
// Base manipulators.
void editSelectedItem();
void deleteSelectedItem();
// Feed clearers.
void clearSelectedFeeds();
void clearAllFeeds();
// Selects next/previous item (feed/category) in the list.
void selectNextItem();
void selectPreviousItem();
// Base manipulators.
void editSelectedItem();
void deleteSelectedItem();
// Selects next/previous item (feed/category) in the list.
void selectNextItem();
void selectPreviousItem();
void selectNextUnreadItem();
// Switches visibility of the widget.
void switchVisibility();
// Switches visibility of the widget.
void switchVisibility();
signals:
void itemSelected(RootItem* item);
signals:
void itemSelected(RootItem* item);
void requestViewNextUnreadMessage();
void openMessagesInNewspaperView(RootItem* root, const QList<Message>& messages);
void openMessagesInNewspaperView(RootItem* root, const QList<Message>& messages);
protected:
void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
void keyPressEvent(QKeyEvent* event);
void contextMenuEvent(QContextMenuEvent* event);
void mouseDoubleClickEvent(QMouseEvent* event);
protected:
void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
void keyPressEvent(QKeyEvent* event);
void contextMenuEvent(QContextMenuEvent* event);
void mouseDoubleClickEvent(QMouseEvent* event);
private slots:
void expandItemDelayed(const QModelIndex& idx);
void markSelectedItemReadStatus(RootItem::ReadStatus read);
void markAllItemsReadStatus(RootItem::ReadStatus read);
private slots:
void expandItemDelayed(const QModelIndex& idx);
void markSelectedItemReadStatus(RootItem::ReadStatus read);
void markAllItemsReadStatus(RootItem::ReadStatus read);
void saveSortState(int column, Qt::SortOrder order);
void validateItemAfterDragDrop(const QModelIndex& source_index);
void onItemExpandRequested(const QList<RootItem*>& items, bool exp);
void onItemExpandStateSaveRequested(RootItem* item);
void saveSortState(int column, Qt::SortOrder order);
void validateItemAfterDragDrop(const QModelIndex& source_index);
void onItemExpandRequested(const QList<RootItem*>& items, bool exp);
void onItemExpandStateSaveRequested(RootItem* item);
private:
private:
QModelIndex nextPreviousUnreadItem(QModelIndex default_row);
QModelIndex nextUnreadItem(QModelIndex default_row);
// Initializes context menus.
QMenu* initializeContextMenuCategories(RootItem* clicked_item);
QMenu* initializeContextMenuFeeds(RootItem* clicked_item);
QMenu* initializeContextMenuEmptySpace();
QMenu* initializeContextMenuOtherItem(RootItem* clicked_item);
// Initializes context menus.
QMenu* initializeContextMenuCategories(RootItem* clicked_item);
QMenu* initializeContextMenuFeeds(RootItem* clicked_item);
QMenu* initializeContextMenuEmptySpace();
QMenu* initializeContextMenuOtherItem(RootItem* clicked_item);
// Sets up appearance of this widget.
void setupAppearance();
// Sets up appearance of this widget.
void setupAppearance();
void saveExpandStates(RootItem* item);
void saveExpandStates(RootItem* item);
QMenu* m_contextMenuCategories;
QMenu* m_contextMenuFeeds;
QMenu* m_contextMenuEmptySpace;
QMenu* m_contextMenuOtherItems;
FeedsModel* m_sourceModel;
FeedsProxyModel* m_proxyModel;
QMenu* m_contextMenuCategories;
QMenu* m_contextMenuFeeds;
QMenu* m_contextMenuEmptySpace;
QMenu* m_contextMenuOtherItems;
FeedsModel* m_sourceModel;
FeedsProxyModel* m_proxyModel;
};
#endif // FEEDSVIEW_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -19,23 +20,22 @@
#include "definitions/definitions.h"
void GuiUtilities::setLabelAsNotice(QLabel& label, bool is_warning) {
label.setMargin(6);
label.setMargin(6);
if (is_warning) {
label.setStyleSheet(QSL("font-weight: bold; font-style: italic; color: red"));
}
else {
label.setStyleSheet(QSL("font-style: italic;"));
}
if (is_warning) {
label.setStyleSheet(QSL("font-weight: bold; font-style: italic; color: red"));
}
else {
label.setStyleSheet(QSL("font-style: italic;"));
}
}
void GuiUtilities::applyDialogProperties(QWidget& widget, const QIcon& icon, const QString& title) {
widget.setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
widget.setWindowIcon(icon);
widget.setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
widget.setWindowIcon(icon);
if (!title.isEmpty()) {
widget.setWindowTitle(title);
}
if (!title.isEmpty()) {
widget.setWindowTitle(title);
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -18,17 +19,16 @@
#ifndef GUIUTILITIES_H
#define GUIUTILITIES_H
#include <QWidget>
#include <QLabel>
#include <QWidget>
class GuiUtilities {
public:
static void setLabelAsNotice(QLabel& label, bool is_warning);
static void applyDialogProperties(QWidget& widget, const QIcon& icon, const QString& title = QString());
public:
static void setLabelAsNotice(QLabel& label, bool is_warning);
static void applyDialogProperties(QWidget& widget, const QIcon& icon, const QString& title = QString());
private:
explicit GuiUtilities();
private:
explicit GuiUtilities();
};
inline GuiUtilities::GuiUtilities() {}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -21,24 +22,25 @@
#include <QHBoxLayout>
LabelWithStatus::LabelWithStatus(QWidget* parent)
: WidgetWithStatus(parent) {
m_wdgInput = new QLabel(this);
// Set correct size for the tool button.
int label_height = m_wdgInput->sizeHint().height();
m_btnStatus->setFixedSize(label_height, label_height);
// Compose the layout.
m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
: WidgetWithStatus(parent) {
m_wdgInput = new QLabel(this);
// Set correct size for the tool button.
int label_height = m_wdgInput->sizeHint().height();
m_btnStatus->setFixedSize(label_height, label_height);
// Compose the layout.
m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
}
LabelWithStatus::~LabelWithStatus() {
}
LabelWithStatus::~LabelWithStatus() {}
void LabelWithStatus::setStatus(WidgetWithStatus::StatusType status,
const QString& label_text,
const QString& status_text) {
WidgetWithStatus::setStatus(status, status_text);
label()->setText(label_text);
WidgetWithStatus::setStatus(status, status_text);
label()->setText(label_text);
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,21 +23,22 @@
#include <QLabel>
class LabelWithStatus : public WidgetWithStatus {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit LabelWithStatus(QWidget* parent = 0);
virtual ~LabelWithStatus();
public:
void setStatus(StatusType status, const QString& label_text, const QString& status_text);
// Constructors and destructors.
explicit LabelWithStatus(QWidget* parent = 0);
virtual ~LabelWithStatus();
void setStatus(StatusType status, const QString& label_text, const QString& status_text);
// Access to label.
inline QLabel* label() const {
return static_cast<QLabel*>(m_wdgInput);
}
// Access to label.
inline QLabel* label() const {
return static_cast<QLabel*>(m_wdgInput);
}
};
#endif // LABELWITHSTATUS_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,23 +18,24 @@
#include "gui/lineeditwithstatus.h"
#include "gui/plaintoolbutton.h"
#include "gui/baselineedit.h"
#include "gui/plaintoolbutton.h"
#include <QHBoxLayout>
LineEditWithStatus::LineEditWithStatus(QWidget* parent)
: WidgetWithStatus(parent) {
m_wdgInput = new BaseLineEdit(this);
setFocusProxy(m_wdgInput);
// Set correct size for the tool button.
const int txt_input_height = m_wdgInput->sizeHint().height();
m_btnStatus->setFixedSize(txt_input_height, txt_input_height);
// Compose the layout.
m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
: WidgetWithStatus(parent) {
m_wdgInput = new BaseLineEdit(this);
setFocusProxy(m_wdgInput);
// Set correct size for the tool button.
const int txt_input_height = m_wdgInput->sizeHint().height();
m_btnStatus->setFixedSize(txt_input_height, txt_input_height);
// Compose the layout.
m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
}
LineEditWithStatus::~LineEditWithStatus() {
}
LineEditWithStatus::~LineEditWithStatus() {}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,19 +23,20 @@
#include "gui/baselineedit.h"
class LineEditWithStatus : public WidgetWithStatus {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit LineEditWithStatus(QWidget* parent = 0);
virtual ~LineEditWithStatus();
public:
// Constructors and destructors.
explicit LineEditWithStatus(QWidget* parent = 0);
virtual ~LineEditWithStatus();
// Access to line edit.
inline BaseLineEdit* lineEdit() const {
return static_cast<BaseLineEdit*>(m_wdgInput);
}
// Access to line edit.
inline BaseLineEdit* lineEdit() const {
return static_cast<BaseLineEdit*>(m_wdgInput);
}
};
#endif // LINEEDITWITHSTATUS_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -21,31 +22,31 @@
#include <QMouseEvent>
LocationLineEdit::LocationLineEdit(QWidget* parent)
: BaseLineEdit(parent), m_mouseSelectsAllText(true), m_googleSuggest(new GoogleSuggest(this)) {
setPlaceholderText(tr("Website address goes here"));
connect(this, &LocationLineEdit::submitted, m_googleSuggest, &GoogleSuggest::preventSuggest);
: BaseLineEdit(parent), m_mouseSelectsAllText(true), m_googleSuggest(new GoogleSuggest(this)) {
setPlaceholderText(tr("Website address goes here"));
connect(this, &LocationLineEdit::submitted, m_googleSuggest, &GoogleSuggest::preventSuggest);
}
LocationLineEdit::~LocationLineEdit() {
}
LocationLineEdit::~LocationLineEdit() {}
void LocationLineEdit::focusOutEvent(QFocusEvent* event) {
BaseLineEdit::focusOutEvent(event);
// User now left text box, when he enters it again and clicks,
// then all text should be selected.
m_mouseSelectsAllText = true;
BaseLineEdit::focusOutEvent(event);
// User now left text box, when he enters it again and clicks,
// then all text should be selected.
m_mouseSelectsAllText = true;
}
void LocationLineEdit::mousePressEvent(QMouseEvent* event) {
if (m_mouseSelectsAllText) {
event->ignore();
selectAll();
// User clicked and all text was selected.
m_mouseSelectsAllText = false;
}
else {
BaseLineEdit::mousePressEvent(event);
}
if (m_mouseSelectsAllText) {
event->ignore();
selectAll();
// User clicked and all text was selected.
m_mouseSelectsAllText = false;
}
else {
BaseLineEdit::mousePressEvent(event);
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,25 +21,25 @@
#include "gui/baselineedit.h"
class WebBrowser;
class GoogleSuggest;
class LocationLineEdit : public BaseLineEdit {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit LocationLineEdit(QWidget* parent = 0);
virtual ~LocationLineEdit();
public:
protected:
void focusOutEvent(QFocusEvent* event);
void mousePressEvent(QMouseEvent* event);
// Constructors and destructors.
explicit LocationLineEdit(QWidget* parent = 0);
virtual ~LocationLineEdit();
private:
bool m_mouseSelectsAllText;
GoogleSuggest* m_googleSuggest;
protected:
void focusOutEvent(QFocusEvent* event);
void mousePressEvent(QMouseEvent* event);
private:
bool m_mouseSelectsAllText;
GoogleSuggest* m_googleSuggest;
};
#endif // LOCATIONLINEEDIT_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -27,7 +28,6 @@
#include <QStyle>
#include <QtGlobal>
MessageBox::MessageBox(QWidget* parent) : QMessageBox(parent) {}
MessageBox::~MessageBox() {}
@ -72,9 +72,15 @@ QIcon MessageBox::iconForStatus(QMessageBox::Icon status) {
}
}
QMessageBox::StandardButton MessageBox::show(QWidget* parent, QMessageBox::Icon icon, const QString& title, const QString& text,
const QString& informative_text, const QString& detailed_text, QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button, bool* dont_show_again) {
QMessageBox::StandardButton MessageBox::show(QWidget* parent,
QMessageBox::Icon icon,
const QString& title,
const QString& text,
const QString& informative_text,
const QString& detailed_text,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button,
bool* dont_show_again) {
// Create and find needed components.
MessageBox msg_box(parent);

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -18,35 +19,34 @@
#ifndef MESSAGEBOX_H
#define MESSAGEBOX_H
#include <QMessageBox>
#include <QDialogButtonBox>
#include <QMessageBox>
class MessageBox : public QMessageBox {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit MessageBox(QWidget* parent = 0);
virtual ~MessageBox();
public:
// Custom icon setting.
void setIcon(Icon icon);
// Constructors and destructors.
explicit MessageBox(QWidget* parent = 0);
virtual ~MessageBox();
static void setCheckBox(QMessageBox* msg_box, const QString& text, bool* data);
// Custom icon setting.
void setIcon(Icon icon);
// Displays custom message box.
static QMessageBox::StandardButton show(QWidget* parent,
QMessageBox::Icon icon,
const QString& title,
const QString& text,
const QString& informative_text = QString(),
const QString& detailed_text = QString(),
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton default_button = QMessageBox::Ok,
bool* dont_show_again = nullptr);
static void setCheckBox(QMessageBox* msg_box, const QString& text, bool* data);
static QIcon iconForStatus(QMessageBox::Icon status);
// Displays custom message box.
static QMessageBox::StandardButton show(QWidget* parent,
QMessageBox::Icon icon,
const QString& title,
const QString& text,
const QString& informative_text = QString(),
const QString& detailed_text = QString(),
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton default_button = QMessageBox::Ok,
bool* dont_show_again = nullptr);
static QIcon iconForStatus(QMessageBox::Icon status);
};
#endif // MESSAGEBOX_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,200 +18,206 @@
#include "gui/messagepreviewer.h"
#include "miscellaneous/application.h"
#include "network-web/webfactory.h"
#include "miscellaneous/databasequeries.h"
#include "gui/messagebox.h"
#include "gui/dialogs/formmain.h"
#include "gui/messagebox.h"
#include "miscellaneous/application.h"
#include "miscellaneous/databasequeries.h"
#include "network-web/webfactory.h"
#include "services/abstract/serviceroot.h"
#include <QScrollBar>
#include <QToolBar>
#include <QToolTip>
void MessagePreviewer::createConnections() {
connect(m_ui->m_txtMessage, &QTextBrowser::anchorClicked, [ = ](const QUrl & url) {
if (!url.isEmpty()) {
bool open_externally_now = qApp->settings()->value(GROUP(Browser),
SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool();
connect(m_ui->m_txtMessage, &QTextBrowser::anchorClicked, [=](const QUrl& url) {
if (!url.isEmpty()) {
bool open_externally_now = qApp->settings()->value(GROUP(Browser),
SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool();
if (open_externally_now) {
qApp->web()->openUrlInExternalBrowser(url.toString());
}
else {
// User clicked some URL. Open it in external browser or download?
MessageBox box(qApp->mainForm());
box.setText(tr("You clicked some link. You can download the link contents or open it in external web browser."));
box.setInformativeText(tr("What action do you want to take?"));
box.setDetailedText(url.toString());
QAbstractButton* btn_open = box.addButton(tr("Open in external browser"), QMessageBox::ActionRole);
QAbstractButton* btn_download = box.addButton(tr("Download"), QMessageBox::ActionRole);
QAbstractButton* btn_cancel = box.addButton(QMessageBox::Cancel);
bool always;
MessageBox::setCheckBox(&box, tr("Always open links in external browser."), &always);
box.setDefaultButton(QMessageBox::Cancel);
box.exec();
if (open_externally_now) {
qApp->web()->openUrlInExternalBrowser(url.toString());
}
else {
// User clicked some URL. Open it in external browser or download?
MessageBox box(qApp->mainForm());
box.setText(tr("You clicked some link. You can download the link contents or open it in external web browser."));
box.setInformativeText(tr("What action do you want to take?"));
box.setDetailedText(url.toString());
QAbstractButton* btn_open = box.addButton(tr("Open in external browser"), QMessageBox::ActionRole);
QAbstractButton* btn_download = box.addButton(tr("Download"), QMessageBox::ActionRole);
QAbstractButton* btn_cancel = box.addButton(QMessageBox::Cancel);
bool always;
MessageBox::setCheckBox(&box, tr("Always open links in external browser."), &always);
box.setDefaultButton(QMessageBox::Cancel);
box.exec();
if (box.clickedButton() != box.button(QMessageBox::Cancel)) {
// Store selected checkbox value.
qApp->settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, always);
}
if (box.clickedButton() != box.button(QMessageBox::Cancel)) {
// Store selected checkbox value.
qApp->settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, always);
}
if (box.clickedButton() == btn_open) {
qApp->web()->openUrlInExternalBrowser(url.toString());
}
else if (box.clickedButton() == btn_download) {
qApp->downloadManager()->download(url);
}
if (box.clickedButton() == btn_open) {
qApp->web()->openUrlInExternalBrowser(url.toString());
}
else if (box.clickedButton() == btn_download) {
qApp->downloadManager()->download(url);
}
btn_download->deleteLater();
btn_open->deleteLater();
btn_cancel->deleteLater();
}
}
else {
MessageBox::show(qApp->mainForm(), QMessageBox::Warning, tr("Incorrect link"),
tr("Selected hyperlink is invalid."));
}
});
connect(m_actionMarkRead = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-read"), tr("Mark message as read")),
&QAction::triggered,
this,
&MessagePreviewer::markMessageAsRead);
connect(m_actionMarkUnread = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-unread"), tr("Mark message as unread")),
&QAction::triggered,
this,
&MessagePreviewer::markMessageAsUnread);
connect(m_actionSwitchImportance = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-important"), tr("Switch message importance")),
&QAction::triggered,
this,
&MessagePreviewer::switchMessageImportance);
connect(m_ui->m_txtMessage,
static_cast<void (QTextBrowser::*)(const QString&)>(&QTextBrowser::highlighted),
[ = ](const QString & text) {
Q_UNUSED(text)
QToolTip::showText(QCursor::pos(), tr("Click this link to download it or open it with external browser."), this);
});
btn_download->deleteLater();
btn_open->deleteLater();
btn_cancel->deleteLater();
}
}
else {
MessageBox::show(qApp->mainForm(), QMessageBox::Warning, tr("Incorrect link"),
tr("Selected hyperlink is invalid."));
}
});
connect(m_actionMarkRead = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-read"), tr("Mark message as read")),
&QAction::triggered,
this,
&MessagePreviewer::markMessageAsRead);
connect(m_actionMarkUnread = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-unread"), tr("Mark message as unread")),
&QAction::triggered,
this,
&MessagePreviewer::markMessageAsUnread);
connect(m_actionSwitchImportance = m_toolBar->addAction(qApp->icons()->fromTheme("mail-mark-important"), tr("Switch message importance")),
&QAction::triggered,
this,
&MessagePreviewer::switchMessageImportance);
connect(m_ui->m_txtMessage,
static_cast<void (QTextBrowser::*)(const QString&)>(&QTextBrowser::highlighted),
[=](const QString& text) {
Q_UNUSED(text)
QToolTip::showText(QCursor::pos(), tr("Click this link to download it or open it with external browser."), this);
});
}
MessagePreviewer::MessagePreviewer(QWidget* parent) : QWidget(parent),
m_ui(new Ui::MessagePreviewer), m_pictures(QStringList()) {
m_ui->setupUi(this);
m_ui->m_txtMessage->viewport()->setAutoFillBackground(true);
m_toolBar = new QToolBar(this);
m_toolBar->setOrientation(Qt::Vertical);
m_ui->m_layout->addWidget(m_toolBar, 0, 0, -1, 1);
createConnections();
m_actionSwitchImportance->setCheckable(true);
reloadFontSettings();
clear();
m_ui(new Ui::MessagePreviewer), m_pictures(QStringList()) {
m_ui->setupUi(this);
m_ui->m_txtMessage->viewport()->setAutoFillBackground(true);
m_toolBar = new QToolBar(this);
m_toolBar->setOrientation(Qt::Vertical);
m_ui->m_layout->addWidget(m_toolBar, 0, 0, -1, 1);
createConnections();
m_actionSwitchImportance->setCheckable(true);
reloadFontSettings();
clear();
}
MessagePreviewer::~MessagePreviewer() {
}
MessagePreviewer::~MessagePreviewer() {}
void MessagePreviewer::reloadFontSettings() {
const Settings* settings = qApp->settings();
QFont fon;
fon.fromString(settings->value(GROUP(Messages),
SETTING(Messages::PreviewerFontStandard)).toString());
m_ui->m_txtMessage->setFont(fon);
const Settings* settings = qApp->settings();
QFont fon;
fon.fromString(settings->value(GROUP(Messages),
SETTING(Messages::PreviewerFontStandard)).toString());
m_ui->m_txtMessage->setFont(fon);
}
void MessagePreviewer::clear() {
m_ui->m_txtMessage->clear();
m_pictures.clear();
hide();
m_ui->m_txtMessage->clear();
m_pictures.clear();
hide();
}
void MessagePreviewer::hideToolbar() {
m_toolBar->setVisible(false);
m_toolBar->setVisible(false);
}
void MessagePreviewer::loadMessage(const Message& message, RootItem* root) {
m_message = message;
m_root = root;
m_message = message;
m_root = root;
if (!m_root.isNull()) {
m_actionSwitchImportance->setChecked(m_message.m_isImportant);
m_ui->m_txtMessage->setHtml(prepareHtmlForMessage(m_message));
updateButtons();
show();
m_ui->m_txtMessage->verticalScrollBar()->triggerAction(QScrollBar::SliderToMinimum);
}
if (!m_root.isNull()) {
m_actionSwitchImportance->setChecked(m_message.m_isImportant);
m_ui->m_txtMessage->setHtml(prepareHtmlForMessage(m_message));
updateButtons();
show();
m_ui->m_txtMessage->verticalScrollBar()->triggerAction(QScrollBar::SliderToMinimum);
}
}
void MessagePreviewer::markMessageAsRead() {
markMessageAsReadUnread(RootItem::Read);
markMessageAsReadUnread(RootItem::Read);
}
void MessagePreviewer::markMessageAsUnread() {
markMessageAsReadUnread(RootItem::Unread);
markMessageAsReadUnread(RootItem::Unread);
}
void MessagePreviewer::markMessageAsReadUnread(RootItem::ReadStatus read) {
if (!m_root.isNull()) {
if (m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(),
QList<Message>() << m_message,
read)) {
DatabaseQueries::markMessagesReadUnread(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings),
QStringList() << QString::number(m_message.m_id),
read);
m_root->getParentServiceRoot()->onAfterSetMessagesRead(m_root.data(),
QList<Message>() << m_message,
read);
m_message.m_isRead = read == RootItem::Read;
emit markMessageRead(m_message.m_id, read);
updateButtons();
}
}
if (!m_root.isNull()) {
if (m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(),
QList<Message>() << m_message,
read)) {
DatabaseQueries::markMessagesReadUnread(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings),
QStringList() << QString::number(m_message.m_id),
read);
m_root->getParentServiceRoot()->onAfterSetMessagesRead(m_root.data(),
QList<Message>() << m_message,
read);
m_message.m_isRead = read == RootItem::Read;
emit markMessageRead(m_message.m_id, read);
updateButtons();
}
}
}
void MessagePreviewer::switchMessageImportance(bool checked) {
if (!m_root.isNull()) {
if (m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(),
QList<ImportanceChange>() << ImportanceChange(m_message,
m_message.m_isImportant ?
RootItem::NotImportant :
RootItem::Important))) {
if (!m_root.isNull()) {
if (m_root->getParentServiceRoot()->onBeforeSwitchMessageImportance(m_root.data(),
QList<ImportanceChange>() << ImportanceChange(m_message,
m_message.
m_isImportant ?
RootItem::NotImportant
:
RootItem::Important)))
{
DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::FromSettings),
QStringList() << QString::number(m_message.m_id));
m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(),
QList<ImportanceChange>() << ImportanceChange(m_message,
m_message.m_isImportant ?
RootItem::NotImportant :
RootItem::Important));
emit markMessageImportant(m_message.m_id, checked ? RootItem::Important : RootItem::NotImportant);
m_message.m_isImportant = checked;
}
}
QStringList() << QString::number(m_message.m_id));
m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(),
QList<ImportanceChange>() << ImportanceChange(m_message,
m_message.m_isImportant ?
RootItem::NotImportant :
RootItem::Important));
emit markMessageImportant(m_message.m_id, checked ? RootItem::Important : RootItem::NotImportant);
m_message.m_isImportant = checked;
}
}
}
void MessagePreviewer::updateButtons() {
m_actionMarkRead->setEnabled(!m_message.m_isRead);
m_actionMarkUnread->setEnabled(m_message.m_isRead);
m_actionMarkRead->setEnabled(!m_message.m_isRead);
m_actionMarkUnread->setEnabled(m_message.m_isRead);
}
QString MessagePreviewer::prepareHtmlForMessage(const Message& message) {
QString html = QString("<h2 align=\"center\">%1</h2>").arg(message.m_title);
html += QString("[url] <a href=\"%1\">%1</a><br/>").arg(message.m_url);
QString html = QString("<h2 align=\"center\">%1</h2>").arg(message.m_title);
foreach (const Enclosure& enc, message.m_enclosures) {
html += QString("[%2] <a href=\"%1\">%1</a><br/>").arg(enc.m_url, enc.m_mimeType);
}
html += QString("[url] <a href=\"%1\">%1</a><br/>").arg(message.m_url);
int offset = 0;
QRegExp imgTagRegex("\\<img[^\\>]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive);
imgTagRegex.setMinimal(true);
foreach (const Enclosure& enc, message.m_enclosures) {
html += QString("[%2] <a href=\"%1\">%1</a><br/>").arg(enc.m_url, enc.m_mimeType);
}
while ((offset = imgTagRegex.indexIn(message.m_contents, offset)) != -1) {
m_pictures.append(imgTagRegex.cap(1));
offset += imgTagRegex.matchedLength();
html += QString("[%2] <a href=\"%1\">%1</a><br/>").arg(imgTagRegex.cap(1), tr("image"));
}
int offset = 0;
QRegExp imgTagRegex("\\<img[^\\>]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive);
html += "<br/>";
html += message.m_contents;
return html;
imgTagRegex.setMinimal(true);
while ((offset = imgTagRegex.indexIn(message.m_contents, offset)) != -1) {
m_pictures.append(imgTagRegex.cap(1));
offset += imgTagRegex.matchedLength();
html += QString("[%2] <a href=\"%1\">%1</a><br/>").arg(imgTagRegex.cap(1), tr("image"));
}
html += "<br/>";
html += message.m_contents;
return html;
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -27,52 +28,53 @@
#include <QPointer>
namespace Ui {
class MessagePreviewer;
class MessagePreviewer;
}
class QToolBar;
class MessagePreviewer : public QWidget {
Q_OBJECT
Q_OBJECT
public:
explicit MessagePreviewer(QWidget* parent = 0);
virtual ~MessagePreviewer();
public:
explicit MessagePreviewer(QWidget* parent = 0);
virtual ~MessagePreviewer();
void reloadFontSettings();
void reloadFontSettings();
public slots:
void clear();
void hideToolbar();
void loadMessage(const Message& message, RootItem* root);
public slots:
void clear();
void hideToolbar();
void loadMessage(const Message& message, RootItem* root);
private slots:
void markMessageAsRead();
void markMessageAsUnread();
void markMessageAsReadUnread(RootItem::ReadStatus read);
void switchMessageImportance(bool checked);
private slots:
void markMessageAsRead();
void markMessageAsUnread();
void markMessageAsReadUnread(RootItem::ReadStatus read);
void switchMessageImportance(bool checked);
signals:
void markMessageRead(int id, RootItem::ReadStatus read);
void markMessageImportant(int id, RootItem::Importance important);
void requestMessageListReload(bool mark_current_as_read);
signals:
void markMessageRead(int id, RootItem::ReadStatus read);
void markMessageImportant(int id, RootItem::Importance important);
void requestMessageListReload(bool mark_current_as_read);
private:
void createConnections();
void updateButtons();
QString prepareHtmlForMessage(const Message& message);
private:
void createConnections();
void updateButtons();
QString prepareHtmlForMessage(const Message& message);
QToolBar* m_toolBar;
QScopedPointer<Ui::MessagePreviewer> m_ui;
Message m_message;
QStringList m_pictures;
QPointer<RootItem> m_root;
QToolBar* m_toolBar;
QAction* m_actionMarkRead;
QAction* m_actionMarkUnread;
QAction* m_actionSwitchImportance;
QScopedPointer<Ui::MessagePreviewer> m_ui;
Message m_message;
QStringList m_pictures;
QPointer<RootItem> m_root;
QAction* m_actionMarkRead;
QAction* m_actionMarkUnread;
QAction* m_actionSwitchImportance;
};
#endif // MESSAGEPREVIEWER_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,9 +18,6 @@
#include "gui/messagessearchlineedit.h"
MessagesSearchLineEdit::MessagesSearchLineEdit(QWidget* parent) : BaseLineEdit(parent) {}
MessagesSearchLineEdit::MessagesSearchLineEdit(QWidget* parent) : BaseLineEdit(parent) {
}
MessagesSearchLineEdit::~MessagesSearchLineEdit() {
}
MessagesSearchLineEdit::~MessagesSearchLineEdit() {}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,16 +21,16 @@
#include "gui/baselineedit.h"
class PlainToolButton;
class MessagesSearchLineEdit : public BaseLineEdit {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit MessagesSearchLineEdit(QWidget* parent = 0);
virtual ~MessagesSearchLineEdit();
public:
// Constructors and destructors.
explicit MessagesSearchLineEdit(QWidget* parent = 0);
virtual ~MessagesSearchLineEdit();
};
#endif // MESSAGESEARCHLINEEDIT_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -23,139 +24,141 @@
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/settings.h"
#include <QWidgetAction>
#include <QToolButton>
#include <QMenu>
#include <QToolButton>
#include <QWidgetAction>
MessagesToolBar::MessagesToolBar(const QString& title, QWidget* parent)
: BaseToolBar(title, parent) {
initializeSearchBox();
initializeHighlighter();
: BaseToolBar(title, parent) {
initializeSearchBox();
initializeHighlighter();
}
MessagesToolBar::~MessagesToolBar() {
}
MessagesToolBar::~MessagesToolBar() {}
QList<QAction*> MessagesToolBar::availableActions() const {
QList<QAction*> available_actions = qApp->userActions();
available_actions.append(m_actionSearchMessages);
available_actions.append(m_actionMessageHighlighter);
return available_actions;
QList<QAction*> available_actions = qApp->userActions();
available_actions.append(m_actionSearchMessages);
available_actions.append(m_actionMessageHighlighter);
return available_actions;
}
QList<QAction*> MessagesToolBar::changeableActions() const {
return actions();
return actions();
}
void MessagesToolBar::saveChangeableActions(const QStringList& actions) {
qApp->settings()->setValue(GROUP(GUI), GUI::MessagesToolbarDefaultButtons, actions.join(QSL(",")));
loadSpecificActions(getSpecificActions(actions));
qApp->settings()->setValue(GROUP(GUI), GUI::MessagesToolbarDefaultButtons, actions.join(QSL(",")));
loadSpecificActions(getSpecificActions(actions));
// If user hidden search messages box, then remove the filter.
if (!changeableActions().contains(m_actionSearchMessages)) {
m_txtSearchMessages->clear();
}
// If user hidden search messages box, then remove the filter.
if (!changeableActions().contains(m_actionSearchMessages)) {
m_txtSearchMessages->clear();
}
}
QList<QAction*> MessagesToolBar::getSpecificActions(const QStringList& actions) {
QList<QAction*> available_actions = availableActions();
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) {
QAction* matching_action = findMatchingAction(action_name, available_actions);
// Iterate action names and add respectable actions into the toolbar.
foreach (const QString& action_name, actions) {
QAction* matching_action = findMatchingAction(action_name, available_actions);
if (matching_action != nullptr) {
// Add existing standard action.
spec_actions.append(matching_action);
}
else if (action_name == SEPARATOR_ACTION_NAME) {
// Add new separator.
QAction* act = new QAction(this);
act->setSeparator(true);
spec_actions.append(act);
}
else if (action_name == SEACRH_MESSAGES_ACTION_NAME) {
// Add search box.
spec_actions.append(m_actionSearchMessages);
}
else if (action_name == HIGHLIGHTER_ACTION_NAME) {
// Add filter button.
spec_actions.append(m_actionMessageHighlighter);
}
else if (action_name == SPACER_ACTION_NAME) {
// Add new spacer.
QWidget* spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QWidgetAction* action = new QWidgetAction(this);
action->setDefaultWidget(spacer);
action->setIcon(qApp->icons()->fromTheme(QSL("go-jump")));
action->setProperty("type", SPACER_ACTION_NAME);
action->setProperty("name", tr("Toolbar spacer"));
spec_actions.append(action);
}
}
if (matching_action != nullptr) {
// Add existing standard action.
spec_actions.append(matching_action);
}
else if (action_name == SEPARATOR_ACTION_NAME) {
// Add new separator.
QAction* act = new QAction(this);
return spec_actions;
act->setSeparator(true);
spec_actions.append(act);
}
else if (action_name == SEACRH_MESSAGES_ACTION_NAME) {
// Add search box.
spec_actions.append(m_actionSearchMessages);
}
else if (action_name == HIGHLIGHTER_ACTION_NAME) {
// Add filter button.
spec_actions.append(m_actionMessageHighlighter);
}
else if (action_name == SPACER_ACTION_NAME) {
// Add new spacer.
QWidget* spacer = new QWidget(this);
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QWidgetAction* action = new QWidgetAction(this);
action->setDefaultWidget(spacer);
action->setIcon(qApp->icons()->fromTheme(QSL("go-jump")));
action->setProperty("type", SPACER_ACTION_NAME);
action->setProperty("name", tr("Toolbar spacer"));
spec_actions.append(action);
}
}
return spec_actions;
}
void MessagesToolBar::loadSpecificActions(const QList<QAction*>& actions) {
clear();
clear();
foreach (QAction* act, actions) {
addAction(act);
}
foreach (QAction* act, actions) {
addAction(act);
}
}
void MessagesToolBar::handleMessageHighlighterChange(QAction* action) {
m_btnMessageHighlighter->setIcon(action->icon());
m_btnMessageHighlighter->setToolTip(action->text());
emit messageFilterChanged(action->data().value<MessagesModel::MessageHighlighter>());
m_btnMessageHighlighter->setIcon(action->icon());
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);
m_txtSearchMessages->setPlaceholderText(tr("Search messages"));
// Setup wrapping action for search box.
m_actionSearchMessages = new QWidgetAction(this);
m_actionSearchMessages->setDefaultWidget(m_txtSearchMessages);
m_actionSearchMessages->setIcon(qApp->icons()->fromTheme(QSL("system-search")));
m_actionSearchMessages->setProperty("type", SEACRH_MESSAGES_ACTION_NAME);
m_actionSearchMessages->setProperty("name", tr("Message search box"));
connect(m_txtSearchMessages, &MessagesSearchLineEdit::textChanged, this, &MessagesToolBar::messageSearchPatternChanged);
m_txtSearchMessages = new MessagesSearchLineEdit(this);
m_txtSearchMessages->setFixedWidth(FILTER_WIDTH);
m_txtSearchMessages->setPlaceholderText(tr("Search messages"));
// Setup wrapping action for search box.
m_actionSearchMessages = new QWidgetAction(this);
m_actionSearchMessages->setDefaultWidget(m_txtSearchMessages);
m_actionSearchMessages->setIcon(qApp->icons()->fromTheme(QSL("system-search")));
m_actionSearchMessages->setProperty("type", SEACRH_MESSAGES_ACTION_NAME);
m_actionSearchMessages->setProperty("name", tr("Message search box"));
connect(m_txtSearchMessages, &MessagesSearchLineEdit::textChanged, this, &MessagesToolBar::messageSearchPatternChanged);
}
void MessagesToolBar::initializeHighlighter() {
m_menuMessageHighlighter = new QMenu(tr("Menu for highlighting messages"), this);
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("No extra highlighting"))->setData(QVariant::fromValue(MessagesModel::NoHighlighting));
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-unread")),
tr("Highlight unread messages"))->setData(QVariant::fromValue(MessagesModel::HighlightUnread));
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-important")),
tr("Highlight important messages"))->setData(QVariant::fromValue(MessagesModel::HighlightImportant));
m_btnMessageHighlighter = new QToolButton(this);
m_btnMessageHighlighter->setToolTip(tr("Display all messages"));
m_btnMessageHighlighter->setMenu(m_menuMessageHighlighter);
m_btnMessageHighlighter->setPopupMode(QToolButton::MenuButtonPopup);
m_btnMessageHighlighter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read")));
m_actionMessageHighlighter = new QWidgetAction(this);
m_actionMessageHighlighter->setDefaultWidget(m_btnMessageHighlighter);
m_actionMessageHighlighter->setIcon(m_btnMessageHighlighter->icon());
m_actionMessageHighlighter->setProperty("type", HIGHLIGHTER_ACTION_NAME);
m_actionMessageHighlighter->setProperty("name", tr("Message highlighter"));
connect(m_menuMessageHighlighter, SIGNAL(triggered(QAction*)),
this, SLOT(handleMessageHighlighterChange(QAction*)));
m_menuMessageHighlighter = new QMenu(tr("Menu for highlighting messages"), this);
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-read")),
tr("No extra highlighting"))->setData(QVariant::fromValue(MessagesModel::NoHighlighting));
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-unread")),
tr("Highlight unread messages"))->setData(QVariant::fromValue(MessagesModel::HighlightUnread));
m_menuMessageHighlighter->addAction(qApp->icons()->fromTheme(QSL("mail-mark-important")),
tr("Highlight important messages"))->setData(QVariant::fromValue(MessagesModel::HighlightImportant));
m_btnMessageHighlighter = new QToolButton(this);
m_btnMessageHighlighter->setToolTip(tr("Display all messages"));
m_btnMessageHighlighter->setMenu(m_menuMessageHighlighter);
m_btnMessageHighlighter->setPopupMode(QToolButton::MenuButtonPopup);
m_btnMessageHighlighter->setIcon(qApp->icons()->fromTheme(QSL("mail-mark-read")));
m_actionMessageHighlighter = new QWidgetAction(this);
m_actionMessageHighlighter->setDefaultWidget(m_btnMessageHighlighter);
m_actionMessageHighlighter->setIcon(m_btnMessageHighlighter->icon());
m_actionMessageHighlighter->setProperty("type", HIGHLIGHTER_ACTION_NAME);
m_actionMessageHighlighter->setProperty("name", tr("Message highlighter"));
connect(m_menuMessageHighlighter, SIGNAL(triggered(QAction*)),
this, SLOT(handleMessageHighlighterChange(QAction*)));
}
QStringList MessagesToolBar::defaultActions() const {
return QString(GUI::MessagesToolbarDefaultButtonsDef).split(',',
QString::SkipEmptyParts);
return QString(GUI::MessagesToolbarDefaultButtonsDef).split(',',
QString::SkipEmptyParts);
}
QStringList MessagesToolBar::savedActions() const {
return qApp->settings()->value(GROUP(GUI),
SETTING(GUI::MessagesToolbarDefaultButtons)).toString().split(',',
QString::SkipEmptyParts);
return qApp->settings()->value(GROUP(GUI),
SETTING(GUI::MessagesToolbarDefaultButtons)).toString().split(',',
QString::SkipEmptyParts);
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,61 +23,62 @@
#include "core/messagesmodel.h"
class MessagesSearchLineEdit;
class QWidgetAction;
class QToolButton;
class QMenu;
class MessagesToolBar : public BaseToolBar {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit MessagesToolBar(const QString& title, QWidget* parent = 0);
virtual ~MessagesToolBar();
public:
// External access to search line edit.
inline MessagesSearchLineEdit* searchLineEdit() {
return m_txtSearchMessages;
}
// Constructors and destructors.
explicit MessagesToolBar(const QString& title, QWidget* parent = 0);
virtual ~MessagesToolBar();
// Implementation of BaseToolBar interface.
QList<QAction*> availableActions() const;
QList<QAction*> changeableActions() const;
void saveChangeableActions(const QStringList& actions);
// External access to search line edit.
inline MessagesSearchLineEdit* searchLineEdit() {
return m_txtSearchMessages;
}
// Loads actions as specified by external actions list.
// NOTE: This is used primarily for reloading actions
// when they are changed from settings.
void loadSpecificActions(const QList<QAction*>& actions);
// Implementation of BaseToolBar interface.
QList<QAction*> availableActions() const;
QList<QAction*> getSpecificActions(const QStringList& actions);
QList<QAction*> changeableActions() const;
void saveChangeableActions(const QStringList& actions);
QStringList defaultActions() const;
QStringList savedActions() const;
// Loads actions as specified by external actions list.
// NOTE: This is used primarily for reloading actions
// when they are changed from settings.
void loadSpecificActions(const QList<QAction*>& actions);
signals:
void messageSearchPatternChanged(const QString& pattern);
QList<QAction*> getSpecificActions(const QStringList& actions);
// Emitted if message filter is changed.
void messageFilterChanged(MessagesModel::MessageHighlighter filter);
QStringList defaultActions() const;
QStringList savedActions() const;
private slots:
// Called when highlighter gets changed.
void handleMessageHighlighterChange(QAction* action);
signals:
void messageSearchPatternChanged(const QString& pattern);
private:
void initializeSearchBox();
void initializeHighlighter();
// Emitted if message filter is changed.
void messageFilterChanged(MessagesModel::MessageHighlighter filter);
private:
QWidgetAction* m_actionMessageHighlighter;
QToolButton* m_btnMessageHighlighter;
QMenu* m_menuMessageHighlighter;
private slots:
QWidgetAction* m_actionSearchMessages;
MessagesSearchLineEdit* m_txtSearchMessages;
// Called when highlighter gets changed.
void handleMessageHighlighterChange(QAction* action);
private:
void initializeSearchBox();
void initializeHighlighter();
private:
QWidgetAction* m_actionMessageHighlighter;
QToolButton* m_btnMessageHighlighter;
QMenu* m_menuMessageHighlighter;
QWidgetAction* m_actionSearchMessages;
MessagesSearchLineEdit* m_txtSearchMessages;
};
#endif // NEWSTOOLBAR_H

View File

@ -211,7 +211,9 @@ void MessagesView::initializeContextMenu() {
}
m_contextMenu->addMenu(menu);
m_contextMenu->addActions(QList<QAction*>() << qApp->mainForm()->m_ui->m_actionSendMessageViaEmail << qApp->mainForm()->m_ui->m_actionOpenSelectedSourceArticlesExternally << qApp->mainForm()->m_ui->m_actionOpenSelectedMessagesInternally << qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsRead << qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsUnread << qApp->mainForm()->m_ui->m_actionSwitchImportanceOfSelectedMessages << qApp->mainForm()->m_ui->m_actionDeleteSelectedMessages);
m_contextMenu->addActions(
QList<QAction*>() << qApp->mainForm()->m_ui->m_actionSendMessageViaEmail << qApp->mainForm()->m_ui->m_actionOpenSelectedSourceArticlesExternally << qApp->mainForm()->m_ui->m_actionOpenSelectedMessagesInternally << qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsRead << qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsUnread << qApp->mainForm()->m_ui->m_actionSwitchImportanceOfSelectedMessages <<
qApp->mainForm()->m_ui->m_actionDeleteSelectedMessages);
if (m_sourceModel->loadedItem() != nullptr && m_sourceModel->loadedItem()->kind() == RootItemKind::Bin) {
m_contextMenu->addAction(qApp->mainForm()->m_ui->m_actionRestoreSelectedMessages);
@ -267,7 +269,11 @@ void MessagesView::selectionChanged(const QItemSelection& selected, const QItemS
const QModelIndex current_index = currentIndex();
const QModelIndex mapped_current_index = m_proxyModel->mapToSource(current_index);
qDebug("Current row changed - row [%d,%d] source [%d, %d].",current_index.row(), current_index.column(),mapped_current_index.row(), mapped_current_index.column());
qDebug("Current row changed - row [%d,%d] source [%d, %d].",
current_index.row(),
current_index.column(),
mapped_current_index.row(),
mapped_current_index.column());
if (mapped_current_index.isValid() && selected_rows.count() > 0) {
Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row());
@ -310,7 +316,9 @@ void MessagesView::openSelectedSourceMessagesExternally() {
const QString link = m_sourceModel->messageAt(m_proxyModel->mapToSource(index).row()).m_url;
if (!qApp->web()->openUrlInExternalBrowser(link)) {
qApp->showGuiMessage(tr("Problem with starting external web browser"),tr("External web browser could not be started."),QSystemTrayIcon::Critical);
qApp->showGuiMessage(tr("Problem with starting external web browser"),
tr("External web browser could not be started."),
QSystemTrayIcon::Critical);
return;
}
}
@ -338,7 +346,8 @@ void MessagesView::sendSelectedMessageViaEmail() {
const Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(selectionModel()->selectedRows().at(0)).row());
if (!qApp->web()->sendMessageViaEmail(message)) {
MessageBox::show(this,QMessageBox::Critical,tr("Problem with starting external e-mail client"),tr("External e-mail client could not be started."));
MessageBox::show(this, QMessageBox::Critical, tr("Problem with starting external e-mail client"),
tr("External e-mail client could not be started."));
}
}
}
@ -520,7 +529,9 @@ void MessagesView::openSelectedMessagesWithExternalTool() {
if (!link.isEmpty()) {
if (!QProcess::startDetached(tool.executable(), QStringList() << tool.parameters() << link)) {
qApp->showGuiMessage(tr("Cannot run external tool"), tr("External tool '%1' could not be started.").arg(tool.executable()),QSystemTrayIcon::Critical);
qApp->showGuiMessage(tr("Cannot run external tool"),
tr("External tool '%1' could not be started.").arg(tool.executable()),
QSystemTrayIcon::Critical);
}
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -21,31 +22,28 @@
#include "miscellaneous/iconfactory.h"
#include "network-web/networkfactory.h"
MessageTextBrowser::MessageTextBrowser(QWidget* parent) : QTextBrowser(parent) {}
MessageTextBrowser::MessageTextBrowser(QWidget* parent) : QTextBrowser(parent) {
}
MessageTextBrowser::~MessageTextBrowser() {
}
MessageTextBrowser::~MessageTextBrowser() {}
QVariant MessageTextBrowser::loadResource(int type, const QUrl& name) {
Q_UNUSED(name)
Q_UNUSED(name)
switch (type) {
case QTextDocument::ImageResource: {
if (m_imagePlaceholder.isNull()) {
m_imagePlaceholder = qApp->icons()->miscPixmap(QSL("image-placeholder")).scaledToWidth(20, Qt::FastTransformation);
}
switch (type) {
case QTextDocument::ImageResource: {
if (m_imagePlaceholder.isNull()) {
m_imagePlaceholder = qApp->icons()->miscPixmap(QSL("image-placeholder")).scaledToWidth(20, Qt::FastTransformation);
}
return m_imagePlaceholder;
}
return m_imagePlaceholder;
}
default:
return QTextBrowser::loadResource(type, name);
}
default:
return QTextBrowser::loadResource(type, name);
}
}
void MessageTextBrowser::wheelEvent(QWheelEvent* e) {
QTextBrowser::wheelEvent(e);
qApp->settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, font().toString());
QTextBrowser::wheelEvent(e);
qApp->settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, font().toString());
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,21 +21,20 @@
#include <QTextBrowser>
class MessageTextBrowser : public QTextBrowser {
Q_OBJECT
Q_OBJECT
public:
explicit MessageTextBrowser(QWidget* parent = 0);
virtual ~MessageTextBrowser();
public:
explicit MessageTextBrowser(QWidget* parent = 0);
virtual ~MessageTextBrowser();
QVariant loadResource(int type, const QUrl& name);
QVariant loadResource(int type, const QUrl& name);
protected:
void wheelEvent(QWheelEvent* e);
protected:
void wheelEvent(QWheelEvent* e);
private:
QPixmap m_imagePlaceholder;
private:
QPixmap m_imagePlaceholder;
};
#endif // MESSAGETEXTBROWSER_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,47 +18,46 @@
#include "gui/newspaperpreviewer.h"
#include "gui/messagepreviewer.h"
#include "gui/dialogs/formmain.h"
#include "gui/messagepreviewer.h"
#include "miscellaneous/application.h"
#include <QScrollBar>
NewspaperPreviewer::NewspaperPreviewer(RootItem* root, QList<Message> messages, QWidget* parent)
: TabContent(parent), m_ui(new Ui::NewspaperPreviewer), m_root(root), m_messages(messages) {
m_ui->setupUi(this);
connect(m_ui->m_btnShowMoreMessages, &QPushButton::clicked, this, &NewspaperPreviewer::showMoreMessages);
showMoreMessages();
: TabContent(parent), m_ui(new Ui::NewspaperPreviewer), m_root(root), m_messages(messages) {
m_ui->setupUi(this);
connect(m_ui->m_btnShowMoreMessages, &QPushButton::clicked, this, &NewspaperPreviewer::showMoreMessages);
showMoreMessages();
}
NewspaperPreviewer::~NewspaperPreviewer() {
}
NewspaperPreviewer::~NewspaperPreviewer() {}
void NewspaperPreviewer::showMoreMessages() {
if (!m_root.isNull()) {
int current_scroll = m_ui->scrollArea->verticalScrollBar()->value();
if (!m_root.isNull()) {
int current_scroll = m_ui->scrollArea->verticalScrollBar()->value();
for (int i = 0; i < 10 && !m_messages.isEmpty(); i++) {
Message msg = m_messages.takeFirst();
MessagePreviewer* prev = new MessagePreviewer(this);
QMargins margins = prev->layout()->contentsMargins();
connect(prev, &MessagePreviewer::requestMessageListReload, this, &NewspaperPreviewer::requestMessageListReload);
margins.setRight(0);
prev->layout()->setContentsMargins(margins);
prev->setFixedHeight(300);
prev->loadMessage(msg, m_root);
m_ui->m_layout->insertWidget(m_ui->m_layout->count() - 2, prev);
}
for (int i = 0; i < 10 && !m_messages.isEmpty(); i++) {
Message msg = m_messages.takeFirst();
MessagePreviewer* prev = new MessagePreviewer(this);
QMargins margins = prev->layout()->contentsMargins();
m_ui->m_btnShowMoreMessages->setText(tr("Show more messages (%n remaining)", "", m_messages.size()));
m_ui->m_btnShowMoreMessages->setEnabled(!m_messages.isEmpty());
m_ui->scrollArea->verticalScrollBar()->setValue(current_scroll);
}
else {
qApp->showGuiMessage(tr("Cannot show more messages"),
tr("Cannot show more messages because parent feed was removed."),
QSystemTrayIcon::Warning,
qApp->mainForm(), true);
}
connect(prev, &MessagePreviewer::requestMessageListReload, this, &NewspaperPreviewer::requestMessageListReload);
margins.setRight(0);
prev->layout()->setContentsMargins(margins);
prev->setFixedHeight(300);
prev->loadMessage(msg, m_root);
m_ui->m_layout->insertWidget(m_ui->m_layout->count() - 2, prev);
}
m_ui->m_btnShowMoreMessages->setText(tr("Show more messages (%n remaining)", "", m_messages.size()));
m_ui->m_btnShowMoreMessages->setEnabled(!m_messages.isEmpty());
m_ui->scrollArea->verticalScrollBar()->setValue(current_scroll);
}
else {
qApp->showGuiMessage(tr("Cannot show more messages"),
tr("Cannot show more messages because parent feed was removed."),
QSystemTrayIcon::Warning,
qApp->mainForm(), true);
}
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -29,30 +30,29 @@
#include <QPointer>
namespace Ui {
class NewspaperPreviewer;
class NewspaperPreviewer;
}
class RootItem;
class NewspaperPreviewer : public TabContent {
Q_OBJECT
Q_OBJECT
public:
explicit NewspaperPreviewer(RootItem* root, QList<Message> messages, QWidget* parent = 0);
virtual ~NewspaperPreviewer();
public:
explicit NewspaperPreviewer(RootItem* root, QList<Message> messages, QWidget* parent = 0);
virtual ~NewspaperPreviewer();
private slots:
void showMoreMessages();
private slots:
void showMoreMessages();
signals:
void requestMessageListReload(bool mark_current_as_read);
signals:
void requestMessageListReload(bool mark_current_as_read);
private:
QScopedPointer<Ui::NewspaperPreviewer> m_ui;
QPointer<RootItem> m_root;
QList<Message> m_messages;
private:
QScopedPointer<Ui::NewspaperPreviewer> m_ui;
QPointer<RootItem> m_root;
QList<Message> m_messages;
};
#endif // NEWSPAPERPREVIEWER_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,63 +18,61 @@
#include "gui/plaintoolbutton.h"
#include <QToolButton>
#include <QStyle>
#include <QAction>
#include <QPainter>
#include <QPaintEvent>
#include <QStyle>
#include <QStyleOption>
#include <QAction>
#include <QToolButton>
PlainToolButton::PlainToolButton(QWidget* parent) : QToolButton(parent), m_padding(0) {}
PlainToolButton::PlainToolButton(QWidget* parent) : QToolButton(parent), m_padding(0) {
}
PlainToolButton::~PlainToolButton() {
}
PlainToolButton::~PlainToolButton() {}
void PlainToolButton::paintEvent(QPaintEvent* e) {
Q_UNUSED(e)
QPainter p(this);
QRect rect(QPoint(0, 0), size());
// Set padding.
rect.adjust(m_padding, m_padding, -m_padding, -m_padding);
Q_UNUSED(e)
QPainter p(this);
QRect rect(QPoint(0, 0), size());
if (isEnabled()) {
if (underMouse() || isChecked()) {
p.setOpacity(0.7);
}
}
else {
p.setOpacity(0.3);
}
// Set padding.
rect.adjust(m_padding, m_padding, -m_padding, -m_padding);
icon().paint(&p, rect);
if (isEnabled()) {
if (underMouse() || isChecked()) {
p.setOpacity(0.7);
}
}
else {
p.setOpacity(0.3);
}
icon().paint(&p, rect);
}
int PlainToolButton::padding() const {
return m_padding;
return m_padding;
}
void PlainToolButton::setPadding(int padding) {
m_padding = padding;
repaint();
m_padding = padding;
repaint();
}
void PlainToolButton::setChecked(bool checked) {
QToolButton::setChecked(checked);
repaint();
QToolButton::setChecked(checked);
repaint();
}
void PlainToolButton::reactOnActionChange(QAction* action) {
if (action != nullptr) {
setEnabled(action->isEnabled());
setCheckable(action->isCheckable());
setChecked(action->isChecked());
setIcon(action->icon());
setToolTip(action->toolTip());
}
if (action != nullptr) {
setEnabled(action->isEnabled());
setCheckable(action->isCheckable());
setChecked(action->isChecked());
setIcon(action->icon());
setToolTip(action->toolTip());
}
}
void PlainToolButton::reactOnSenderActionChange() {
reactOnActionChange(qobject_cast<QAction*>(sender()));
reactOnActionChange(qobject_cast<QAction*>(sender()));
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,30 +21,31 @@
#include <QToolButton>
class PlainToolButton : public QToolButton {
Q_OBJECT
Q_OBJECT
public:
// Contructors and destructors.
explicit PlainToolButton(QWidget* parent = 0);
virtual ~PlainToolButton();
public:
// Padding changers.
int padding() const;
void setPadding(int padding);
// Contructors and destructors.
explicit PlainToolButton(QWidget* parent = 0);
virtual ~PlainToolButton();
public slots:
void setChecked(bool checked);
void reactOnActionChange(QAction* action);
void reactOnSenderActionChange();
// Padding changers.
int padding() const;
void setPadding(int padding);
protected:
// Custom look.
void paintEvent(QPaintEvent* e);
public slots:
void setChecked(bool checked);
void reactOnActionChange(QAction* action);
void reactOnSenderActionChange();
private:
int m_padding;
protected:
// Custom look.
void paintEvent(QPaintEvent* e);
private:
int m_padding;
};
#endif // CLOSEBUTTON_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,61 +18,61 @@
#include "gui/settings/settingsbrowsermail.h"
#include "network-web/silentnetworkaccessmanager.h"
#include "miscellaneous/application.h"
#include "miscellaneous/textfactory.h"
#include "gui/guiutilities.h"
#include "miscellaneous/application.h"
#include "miscellaneous/externaltool.h"
#include "miscellaneous/textfactory.h"
#include "network-web/silentnetworkaccessmanager.h"
#include <QNetworkProxy>
#include <QFileDialog>
#include <QInputDialog>
#include <QNetworkProxy>
SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsBrowserMail) {
m_ui->setupUi(this);
m_ui->setupUi(this);
GuiUtilities::setLabelAsNotice(*m_ui->label, false);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblExternalEmailInfo, false);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblProxyInfo, false);
GuiUtilities::setLabelAsNotice(*m_ui->label, false);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblExternalEmailInfo, false);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblProxyInfo, false);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblToolInfo, false);
#if defined(USE_WEBENGINE)
m_ui->m_checkOpenLinksInExternal->setVisible(false);
m_ui->m_checkOpenLinksInExternal->setVisible(false);
#else
connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings);
#endif
m_ui->m_listTools->setHeaderLabels(QStringList() << tr("Executable") << tr("Parameters"));
m_ui->m_listTools->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyHost, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyPassword, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyUsername, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_spinProxyPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_grpCustomExternalBrowser, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_grpCustomExternalEmail, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtExternalBrowserArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtExternalBrowserExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtExternalEmailArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtExternalEmailExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsBrowserMail::onProxyTypeChanged);
connect(m_ui->m_checkShowPassword, &QCheckBox::stateChanged, this, &SettingsBrowserMail::displayProxyPassword);
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);
connect(m_ui->m_btnExternalEmailExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectEmailExecutable);
connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyHost, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyPassword, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtProxyUsername, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_spinProxyPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
&SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_grpCustomExternalBrowser, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_grpCustomExternalEmail, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtExternalBrowserArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtExternalBrowserExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtExternalEmailArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_txtExternalEmailExecutable, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsBrowserMail::onProxyTypeChanged);
connect(m_ui->m_checkShowPassword, &QCheckBox::stateChanged, this, &SettingsBrowserMail::displayProxyPassword);
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);
connect(m_ui->m_btnExternalEmailExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectEmailExecutable);
connect(m_ui->m_btnAddTool, &QPushButton::clicked, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_btnDeleteTool, &QPushButton::clicked, this, &SettingsBrowserMail::dirtifySettings);
connect(m_ui->m_btnAddTool, &QPushButton::clicked, this, &SettingsBrowserMail::addExternalTool);
connect(m_ui->m_btnDeleteTool, &QPushButton::clicked, this, &SettingsBrowserMail::deleteSelectedExternalTool);
connect(m_ui->m_listTools, &QTreeWidget::currentItemChanged, [this](QTreeWidgetItem * current, QTreeWidgetItem * previous) {
connect(m_ui->m_listTools, &QTreeWidget::currentItemChanged, [this](QTreeWidgetItem* current, QTreeWidgetItem* previous) {
Q_UNUSED(previous)
m_ui->m_btnDeleteTool->setEnabled(current != nullptr);
@ -79,52 +80,54 @@ SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent)
}
SettingsBrowserMail::~SettingsBrowserMail() {
delete m_ui;
delete m_ui;
}
void SettingsBrowserMail::changeDefaultBrowserArguments(int index) {
if (index != 0) {
m_ui->m_txtExternalBrowserArguments->setText(m_ui->m_cmbExternalBrowserPreset->itemData(index).toString());
}
if (index != 0) {
m_ui->m_txtExternalBrowserArguments->setText(m_ui->m_cmbExternalBrowserPreset->itemData(index).toString());
}
}
void SettingsBrowserMail::selectBrowserExecutable() {
const QString executable_file = QFileDialog::getOpenFileName(this,
tr("Select web browser executable"),
qApp->homeFolder(),
//: File filter for external browser selection dialog.
const QString executable_file = QFileDialog::getOpenFileName(this,
tr("Select web browser executable"),
qApp->homeFolder(),
//: File filter for external browser selection dialog.
#if defined(Q_OS_LINUX)
tr("Executables (*)"));
tr("Executables (*)"));
#else
tr("Executables (*.*)"));
tr("Executables (*.*)"));
#endif
if (!executable_file.isEmpty()) {
m_ui->m_txtExternalBrowserExecutable->setText(QDir::toNativeSeparators(executable_file));
}
if (!executable_file.isEmpty()) {
m_ui->m_txtExternalBrowserExecutable->setText(QDir::toNativeSeparators(executable_file));
}
}
void SettingsBrowserMail::displayProxyPassword(int state) {
if (state == Qt::Checked) {
m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::Normal);
}
else {
m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit);
}
if (state == Qt::Checked) {
m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::Normal);
}
else {
m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit);
}
}
void SettingsBrowserMail::onProxyTypeChanged(int index) {
const QNetworkProxy::ProxyType selected_type = static_cast<QNetworkProxy::ProxyType>(m_ui->m_cmbProxyType->itemData(index).toInt());
const bool is_proxy_selected = selected_type != QNetworkProxy::NoProxy && selected_type != QNetworkProxy::DefaultProxy;
m_ui->m_txtProxyHost->setEnabled(is_proxy_selected);
m_ui->m_txtProxyPassword->setEnabled(is_proxy_selected);
m_ui->m_txtProxyUsername->setEnabled(is_proxy_selected);
m_ui->m_spinProxyPort->setEnabled(is_proxy_selected);
m_ui->m_checkShowPassword->setEnabled(is_proxy_selected);
m_ui->m_lblProxyHost->setEnabled(is_proxy_selected);
m_ui->m_lblProxyInfo->setEnabled(is_proxy_selected);
m_ui->m_lblProxyPassword->setEnabled(is_proxy_selected);
m_ui->m_lblProxyPort->setEnabled(is_proxy_selected);
const QNetworkProxy::ProxyType selected_type = static_cast<QNetworkProxy::ProxyType>(m_ui->m_cmbProxyType->itemData(index).toInt());
const bool is_proxy_selected = selected_type != QNetworkProxy::NoProxy && selected_type != QNetworkProxy::DefaultProxy;
m_ui->m_txtProxyHost->setEnabled(is_proxy_selected);
m_ui->m_txtProxyPassword->setEnabled(is_proxy_selected);
m_ui->m_txtProxyUsername->setEnabled(is_proxy_selected);
m_ui->m_spinProxyPort->setEnabled(is_proxy_selected);
m_ui->m_checkShowPassword->setEnabled(is_proxy_selected);
m_ui->m_lblProxyHost->setEnabled(is_proxy_selected);
m_ui->m_lblProxyInfo->setEnabled(is_proxy_selected);
m_ui->m_lblProxyPassword->setEnabled(is_proxy_selected);
m_ui->m_lblProxyPort->setEnabled(is_proxy_selected);
m_ui->m_lblProxyUsername->setEnabled(is_proxy_selected);
}
@ -142,6 +145,7 @@ void SettingsBrowserMail::setExternalTools(const QList<ExternalTool>& list) {
foreach (const ExternalTool& tool, list) {
QTreeWidgetItem* item = new QTreeWidgetItem(m_ui->m_listTools,
QStringList() << tool.executable() << tool.parameters().join(QL1C(' ')));
item->setData(0, Qt::UserRole, QVariant::fromValue(tool));
m_ui->m_listTools->addTopLevelItem(item);
@ -149,94 +153,96 @@ void SettingsBrowserMail::setExternalTools(const QList<ExternalTool>& list) {
}
void SettingsBrowserMail::changeDefaultEmailArguments(int index) {
if (index != 0) {
m_ui->m_txtExternalEmailArguments->setText(m_ui->m_cmbExternalEmailPreset->itemData(index).toString());
}
if (index != 0) {
m_ui->m_txtExternalEmailArguments->setText(m_ui->m_cmbExternalEmailPreset->itemData(index).toString());
}
}
void SettingsBrowserMail::selectEmailExecutable() {
QString executable_file = QFileDialog::getOpenFileName(this,
tr("Select e-mail executable"),
qApp->homeFolder(),
//: File filter for external e-mail selection dialog.
QString executable_file = QFileDialog::getOpenFileName(this,
tr("Select e-mail executable"),
qApp->homeFolder(),
//: File filter for external e-mail selection dialog.
#if defined(Q_OS_LINUX)
tr("Executables (*)"));
tr("Executables (*)"));
#else
tr("Executables (*.*)"));
tr("Executables (*.*)"));
#endif
if (!executable_file.isEmpty()) {
m_ui->m_txtExternalEmailExecutable->setText(QDir::toNativeSeparators(executable_file));
}
if (!executable_file.isEmpty()) {
m_ui->m_txtExternalEmailExecutable->setText(QDir::toNativeSeparators(executable_file));
}
}
void SettingsBrowserMail::loadSettings() {
onBeginLoadSettings();
onBeginLoadSettings();
#if !defined(USE_WEBENGINE)
m_ui->m_checkOpenLinksInExternal->setChecked(settings()->value(GROUP(Browser),
SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool());
m_ui->m_checkOpenLinksInExternal->setChecked(settings()->value(GROUP(Browser),
SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool());
#endif
// Load settings of web browser GUI.
m_ui->m_cmbExternalBrowserPreset->addItem(tr("Opera 12 or older"), QSL("-nosession %1"));
m_ui->m_txtExternalBrowserExecutable->setText(settings()->value(GROUP(Browser),
SETTING(Browser::CustomExternalBrowserExecutable)).toString());
m_ui->m_txtExternalBrowserArguments->setText(settings()->value(GROUP(Browser),
SETTING(Browser::CustomExternalBrowserArguments)).toString());
m_ui->m_grpCustomExternalBrowser->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserEnabled)).toBool());
m_ui->m_cmbExternalBrowserPreset->addItem(tr("Opera 12 or older"), QSL("-nosession %1"));
m_ui->m_txtExternalBrowserExecutable->setText(settings()->value(GROUP(Browser),
SETTING(Browser::CustomExternalBrowserExecutable)).toString());
m_ui->m_txtExternalBrowserArguments->setText(settings()->value(GROUP(Browser),
SETTING(Browser::CustomExternalBrowserArguments)).toString());
m_ui->m_grpCustomExternalBrowser->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalBrowserEnabled)).toBool());
// Load settings of e-mail.
m_ui->m_cmbExternalEmailPreset->addItem(tr("Mozilla Thunderbird"), QSL("-compose \"subject='%1',body='%2'\""));
m_ui->m_txtExternalEmailExecutable->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailExecutable)).toString());
m_ui->m_txtExternalEmailArguments->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString());
m_ui->m_grpCustomExternalEmail->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool());
m_ui->m_cmbProxyType->addItem(tr("No proxy"), QNetworkProxy::NoProxy);
m_ui->m_cmbProxyType->addItem(tr("System proxy"), QNetworkProxy::DefaultProxy);
m_ui->m_cmbProxyType->addItem(tr("Socks5"), QNetworkProxy::Socks5Proxy);
m_ui->m_cmbProxyType->addItem(tr("Http"), QNetworkProxy::HttpProxy);
m_ui->m_cmbExternalEmailPreset->addItem(tr("Mozilla Thunderbird"), QSL("-compose \"subject='%1',body='%2'\""));
m_ui->m_txtExternalEmailExecutable->setText(settings()->value(GROUP(Browser),
SETTING(Browser::CustomExternalEmailExecutable)).toString());
m_ui->m_txtExternalEmailArguments->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString());
m_ui->m_grpCustomExternalEmail->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool());
m_ui->m_cmbProxyType->addItem(tr("No proxy"), QNetworkProxy::NoProxy);
m_ui->m_cmbProxyType->addItem(tr("System proxy"), QNetworkProxy::DefaultProxy);
m_ui->m_cmbProxyType->addItem(tr("Socks5"), QNetworkProxy::Socks5Proxy);
m_ui->m_cmbProxyType->addItem(tr("Http"), QNetworkProxy::HttpProxy);
// Load the settings.
QNetworkProxy::ProxyType selected_proxy_type = static_cast<QNetworkProxy::ProxyType>(settings()->value(GROUP(Proxy),
SETTING(Proxy::Type)).toInt());
m_ui->m_cmbProxyType->setCurrentIndex(m_ui->m_cmbProxyType->findData(selected_proxy_type));
m_ui->m_txtProxyHost->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Host)).toString());
m_ui->m_txtProxyUsername->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Username)).toString());
m_ui->m_txtProxyPassword->setText(TextFactory::decrypt(settings()->value(GROUP(Proxy), SETTING(Proxy::Password)).toString()));
m_ui->m_spinProxyPort->setValue(settings()->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt());
QNetworkProxy::ProxyType selected_proxy_type = static_cast<QNetworkProxy::ProxyType>(settings()->value(GROUP(Proxy),
SETTING(Proxy::Type)).toInt());
m_ui->m_cmbProxyType->setCurrentIndex(m_ui->m_cmbProxyType->findData(selected_proxy_type));
m_ui->m_txtProxyHost->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Host)).toString());
m_ui->m_txtProxyUsername->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Username)).toString());
m_ui->m_txtProxyPassword->setText(TextFactory::decrypt(settings()->value(GROUP(Proxy), SETTING(Proxy::Password)).toString()));
m_ui->m_spinProxyPort->setValue(settings()->value(GROUP(Proxy), SETTING(Proxy::Port)).toInt());
setExternalTools(ExternalTool::toolsFromSettings());
onEndLoadSettings();
onEndLoadSettings();
}
void SettingsBrowserMail::saveSettings() {
onBeginSaveSettings();
onBeginSaveSettings();
#if !defined(USE_WEBENGINE)
settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, m_ui->m_checkOpenLinksInExternal->isChecked());
settings()->setValue(GROUP(Browser), Browser::OpenLinksInExternalBrowserRightAway, m_ui->m_checkOpenLinksInExternal->isChecked());
#endif
// Save settings of GUI of web browser.
settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserEnabled, m_ui->m_grpCustomExternalBrowser->isChecked());
settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserExecutable, m_ui->m_txtExternalBrowserExecutable->text());
settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserArguments, m_ui->m_txtExternalBrowserArguments->text());
settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserEnabled, m_ui->m_grpCustomExternalBrowser->isChecked());
settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserExecutable, m_ui->m_txtExternalBrowserExecutable->text());
settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserArguments, m_ui->m_txtExternalBrowserArguments->text());
// Save settings of e-mail.
settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailExecutable, m_ui->m_txtExternalEmailExecutable->text());
settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailArguments, m_ui->m_txtExternalEmailArguments->text());
settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailEnabled, m_ui->m_grpCustomExternalEmail->isChecked());
settings()->setValue(GROUP(Proxy), Proxy::Type, m_ui->m_cmbProxyType->itemData(m_ui->m_cmbProxyType->currentIndex()));
settings()->setValue(GROUP(Proxy), Proxy::Host, m_ui->m_txtProxyHost->text());
settings()->setValue(GROUP(Proxy), Proxy::Username, m_ui->m_txtProxyUsername->text());
settings()->setValue(GROUP(Proxy), Proxy::Password, TextFactory::encrypt(m_ui->m_txtProxyPassword->text()));
settings()->setValue(GROUP(Proxy), Proxy::Port, m_ui->m_spinProxyPort->value());
settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailExecutable, m_ui->m_txtExternalEmailExecutable->text());
settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailArguments, m_ui->m_txtExternalEmailArguments->text());
settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailEnabled, m_ui->m_grpCustomExternalEmail->isChecked());
settings()->setValue(GROUP(Proxy), Proxy::Type, m_ui->m_cmbProxyType->itemData(m_ui->m_cmbProxyType->currentIndex()));
settings()->setValue(GROUP(Proxy), Proxy::Host, m_ui->m_txtProxyHost->text());
settings()->setValue(GROUP(Proxy), Proxy::Username, m_ui->m_txtProxyUsername->text());
settings()->setValue(GROUP(Proxy), Proxy::Password, TextFactory::encrypt(m_ui->m_txtProxyPassword->text()));
settings()->setValue(GROUP(Proxy), Proxy::Port, m_ui->m_spinProxyPort->value());
auto tools = externalTools();
ExternalTool::setToolsToSettings(tools);
// Reload settings for all network access managers.
SilentNetworkAccessManager::instance()->loadSettings();
SilentNetworkAccessManager::instance()->loadSettings();
onEndSaveSettings();
}
@ -244,6 +250,7 @@ void SettingsBrowserMail::addExternalTool() {
QString executable_file = QFileDialog::getOpenFileName(this,
tr("Select external tool"),
qApp->homeFolder(),
//: File filter for external tool selection dialog.
#if defined(Q_OS_LINUX)
tr("Executables (*)"));
@ -254,13 +261,18 @@ void SettingsBrowserMail::addExternalTool() {
if (!executable_file.isEmpty()) {
executable_file = QDir::toNativeSeparators(executable_file);
bool ok;
QString parameters = QInputDialog::getText(this, tr("Enter parameters"),
tr("Enter (optional) parameters separated by single space to send to executable when opening URLs."),
QLineEdit::Normal, QString(), &ok);
QString parameters = QInputDialog::getText(this,
tr("Enter parameters"),
tr(
"Enter (optional) parameters separated by single space to send to executable when opening URLs."),
QLineEdit::Normal,
QString(),
&ok);
if (ok) {
QTreeWidgetItem* item = new QTreeWidgetItem(m_ui->m_listTools,
QStringList() << QDir::toNativeSeparators(executable_file) << parameters);
item->setData(0, Qt::UserRole, QVariant::fromValue(ExternalTool(executable_file, parameters.split(QSL(" ")))));
m_ui->m_listTools->addTopLevelItem(item);
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -23,36 +24,36 @@
#include "miscellaneous/externaltool.h"
#include "ui_settingsbrowsermail.h"
class SettingsBrowserMail : public SettingsPanel {
Q_OBJECT
Q_OBJECT
public:
explicit SettingsBrowserMail(Settings* settings, QWidget* parent = 0);
virtual ~SettingsBrowserMail();
public:
explicit SettingsBrowserMail(Settings* settings, QWidget* parent = 0);
virtual ~SettingsBrowserMail();
inline QString title() const {
return tr("Web browser & e-mail & proxy");
}
inline QString title() const {
return tr("Web browser & e-mail & proxy");
}
void loadSettings();
void saveSettings();
private slots:
void saveSettings();
private slots:
void addExternalTool();
void deleteSelectedExternalTool();
void changeDefaultBrowserArguments(int index);
void selectBrowserExecutable();
void changeDefaultEmailArguments(int index);
void selectEmailExecutable();
void displayProxyPassword(int state);
void onProxyTypeChanged(int index);
void changeDefaultBrowserArguments(int index);
void selectBrowserExecutable();
void changeDefaultEmailArguments(int index);
void selectEmailExecutable();
void displayProxyPassword(int state);
void onProxyTypeChanged(int index);
private:
private:
QList<ExternalTool> externalTools() const;
void setExternalTools(const QList<ExternalTool>& list);
Ui::SettingsBrowserMail* m_ui;
Ui::SettingsBrowserMail* m_ui;
};
#endif // SETTINGSBROWSERMAIL_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,190 +18,197 @@
#include "gui/settings/settingsdatabase.h"
#include "miscellaneous/databasefactory.h"
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
#include "miscellaneous/textfactory.h"
#include "gui/guiutilities.h"
#include "miscellaneous/application.h"
#include "miscellaneous/databasefactory.h"
#include "miscellaneous/textfactory.h"
SettingsDatabase::SettingsDatabase(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsDatabase) {
m_ui->setupUi(this);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblDataStorageWarning, true);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblMysqlInfo, false);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblSqliteInMemoryWarnings, true);
connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsDatabase::dirtifySettings);
connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlDatabase->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_checkUseTransactions, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_spinMysqlPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsDatabase::selectSqlBackend);
connect(m_ui->m_checkMysqlShowPassword, &QCheckBox::toggled, this, &SettingsDatabase::switchMysqlPasswordVisiblity);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlUsernameChanged);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlHostnameChanged);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlPasswordChanged);
connect(m_ui->m_txtMysqlDatabase->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlDatabaseChanged);
connect(m_ui->m_btnMysqlTestSetup, &QPushButton::clicked, this, &SettingsDatabase::mysqlTestConnection);
connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsDatabase::requireRestart);
connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_spinMysqlPort, &QSpinBox::editingFinished, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsDatabase) {
m_ui->setupUi(this);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblDataStorageWarning, true);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblMysqlInfo, false);
GuiUtilities::setLabelAsNotice(*m_ui->m_lblSqliteInMemoryWarnings, true);
connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsDatabase::dirtifySettings);
connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlDatabase->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_checkUseTransactions, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_spinMysqlPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsDatabase::selectSqlBackend);
connect(m_ui->m_checkMysqlShowPassword, &QCheckBox::toggled, this, &SettingsDatabase::switchMysqlPasswordVisiblity);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlUsernameChanged);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlHostnameChanged);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlPasswordChanged);
connect(m_ui->m_txtMysqlDatabase->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlDatabaseChanged);
connect(m_ui->m_btnMysqlTestSetup, &QPushButton::clicked, this, &SettingsDatabase::mysqlTestConnection);
connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsDatabase::requireRestart);
connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_spinMysqlPort, &QSpinBox::editingFinished, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
}
SettingsDatabase::~SettingsDatabase() {
delete m_ui;
delete m_ui;
}
void SettingsDatabase::mysqlTestConnection() {
const DatabaseFactory::MySQLError error_code = qApp->database()->mysqlTestConnection(m_ui->m_txtMysqlHostname->lineEdit()->text(),
m_ui->m_spinMysqlPort->value(),
m_ui->m_txtMysqlDatabase->lineEdit()->text(),
m_ui->m_txtMysqlUsername->lineEdit()->text(),
m_ui->m_txtMysqlPassword->lineEdit()->text());
const QString interpretation = qApp->database()->mysqlInterpretErrorCode(error_code);
const DatabaseFactory::MySQLError error_code = qApp->database()->mysqlTestConnection(m_ui->m_txtMysqlHostname->lineEdit()->text(),
m_ui->m_spinMysqlPort->value(),
m_ui->m_txtMysqlDatabase->lineEdit()->text(),
m_ui->m_txtMysqlUsername->lineEdit()->text(),
m_ui->m_txtMysqlPassword->lineEdit()->text());
const QString interpretation = qApp->database()->mysqlInterpretErrorCode(error_code);
switch (error_code) {
case DatabaseFactory::MySQLOk:
case DatabaseFactory::MySQLUnknownDatabase:
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Ok, interpretation, interpretation);
break;
switch (error_code) {
case DatabaseFactory::MySQLOk:
case DatabaseFactory::MySQLUnknownDatabase:
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Ok, interpretation, interpretation);
break;
default:
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Error, interpretation, interpretation);
break;
}
default:
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Error, interpretation, interpretation);
break;
}
}
void SettingsDatabase::onMysqlHostnameChanged(const QString& new_hostname) {
if (new_hostname.isEmpty()) {
m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Warning, tr("Hostname is empty."));
}
else {
m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Ok, tr("Hostname looks ok."));
}
if (new_hostname.isEmpty()) {
m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Warning, tr("Hostname is empty."));
}
else {
m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Ok, tr("Hostname looks ok."));
}
}
void SettingsDatabase::onMysqlUsernameChanged(const QString& new_username) {
if (new_username.isEmpty()) {
m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Warning, tr("Username is empty."));
}
else {
m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Ok, tr("Username looks ok."));
}
if (new_username.isEmpty()) {
m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Warning, tr("Username is empty."));
}
else {
m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Ok, tr("Username looks ok."));
}
}
void SettingsDatabase::onMysqlPasswordChanged(const QString& new_password) {
if (new_password.isEmpty()) {
m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Warning, tr("Password is empty."));
}
else {
m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Ok, tr("Password looks ok."));
}
if (new_password.isEmpty()) {
m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Warning, tr("Password is empty."));
}
else {
m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Ok, tr("Password looks ok."));
}
}
void SettingsDatabase::onMysqlDatabaseChanged(const QString& new_database) {
if (new_database.isEmpty()) {
m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Warning, tr("Working database is empty."));
}
else {
m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Ok, tr("Working database is ok."));
}
if (new_database.isEmpty()) {
m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Warning, tr("Working database is empty."));
}
else {
m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Ok, tr("Working database is ok."));
}
}
void SettingsDatabase::selectSqlBackend(int index) {
const QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(index).toString();
const QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(index).toString();
if (selected_db_driver == APP_DB_SQLITE_DRIVER) {
m_ui->m_stackedDatabaseDriver->setCurrentIndex(0);
}
else if (selected_db_driver == APP_DB_MYSQL_DRIVER) {
m_ui->m_stackedDatabaseDriver->setCurrentIndex(1);
}
else {
qWarning("GUI for given database driver '%s' is not available.", qPrintable(selected_db_driver));
}
if (selected_db_driver == APP_DB_SQLITE_DRIVER) {
m_ui->m_stackedDatabaseDriver->setCurrentIndex(0);
}
else if (selected_db_driver == APP_DB_MYSQL_DRIVER) {
m_ui->m_stackedDatabaseDriver->setCurrentIndex(1);
}
else {
qWarning("GUI for given database driver '%s' is not available.", qPrintable(selected_db_driver));
}
}
void SettingsDatabase::switchMysqlPasswordVisiblity(bool visible) {
m_ui->m_txtMysqlPassword->lineEdit()->setEchoMode(visible ? QLineEdit::Normal : QLineEdit::Password);
m_ui->m_txtMysqlPassword->lineEdit()->setEchoMode(visible ? QLineEdit::Normal : QLineEdit::Password);
}
void SettingsDatabase::loadSettings() {
onBeginLoadSettings();
m_ui->m_checkUseTransactions->setChecked(qApp->settings()->value(GROUP(Database), SETTING(Database::UseTransactions)).toBool());
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Information, tr("No connection test triggered so far."),
tr("You did not executed any connection test yet."));
// Load SQLite.
m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::SQLITE), APP_DB_SQLITE_DRIVER);
// Load in-memory database status.
m_ui->m_checkSqliteUseInMemoryDatabase->setChecked(settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool());
onBeginLoadSettings();
m_ui->m_checkUseTransactions->setChecked(qApp->settings()->value(GROUP(Database), SETTING(Database::UseTransactions)).toBool());
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Information, tr("No connection test triggered so far."),
tr("You did not executed any connection test yet."));
if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
onMysqlHostnameChanged(QString());
onMysqlUsernameChanged(QString());
onMysqlPasswordChanged(QString());
onMysqlDatabaseChanged(QString());
// Load MySQL.
m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::MYSQL), APP_DB_MYSQL_DRIVER);
// Setup placeholders.
m_ui->m_txtMysqlHostname->lineEdit()->setPlaceholderText(tr("Hostname of your MySQL server"));
m_ui->m_txtMysqlUsername->lineEdit()->setPlaceholderText(tr("Username to login with"));
m_ui->m_txtMysqlPassword->lineEdit()->setPlaceholderText(tr("Password for your username"));
m_ui->m_txtMysqlDatabase->lineEdit()->setPlaceholderText(tr("Working database which you have full access to."));
m_ui->m_txtMysqlHostname->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString());
m_ui->m_txtMysqlUsername->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString());
m_ui->m_txtMysqlPassword->lineEdit()->setText(TextFactory::decrypt(settings()->value(GROUP(Database),
SETTING(Database::MySQLPassword)).toString()));
m_ui->m_txtMysqlDatabase->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString());
m_ui->m_spinMysqlPort->setValue(settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
m_ui->m_checkMysqlShowPassword->setChecked(false);
}
// Load SQLite.
m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::SQLITE), APP_DB_SQLITE_DRIVER);
int index_current_backend = m_ui->m_cmbDatabaseDriver->findData(settings()->value(GROUP(Database),
SETTING(Database::ActiveDriver)).toString());
// Load in-memory database status.
m_ui->m_checkSqliteUseInMemoryDatabase->setChecked(settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool());
if (index_current_backend >= 0) {
m_ui->m_cmbDatabaseDriver->setCurrentIndex(index_current_backend);
}
if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
onMysqlHostnameChanged(QString());
onMysqlUsernameChanged(QString());
onMysqlPasswordChanged(QString());
onMysqlDatabaseChanged(QString());
onEndLoadSettings();
// Load MySQL.
m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::MYSQL), APP_DB_MYSQL_DRIVER);
// Setup placeholders.
m_ui->m_txtMysqlHostname->lineEdit()->setPlaceholderText(tr("Hostname of your MySQL server"));
m_ui->m_txtMysqlUsername->lineEdit()->setPlaceholderText(tr("Username to login with"));
m_ui->m_txtMysqlPassword->lineEdit()->setPlaceholderText(tr("Password for your username"));
m_ui->m_txtMysqlDatabase->lineEdit()->setPlaceholderText(tr("Working database which you have full access to."));
m_ui->m_txtMysqlHostname->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString());
m_ui->m_txtMysqlUsername->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString());
m_ui->m_txtMysqlPassword->lineEdit()->setText(TextFactory::decrypt(settings()->value(GROUP(Database),
SETTING(Database::MySQLPassword)).toString()));
m_ui->m_txtMysqlDatabase->lineEdit()->setText(settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString());
m_ui->m_spinMysqlPort->setValue(settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
m_ui->m_checkMysqlShowPassword->setChecked(false);
}
int index_current_backend = m_ui->m_cmbDatabaseDriver->findData(settings()->value(GROUP(Database),
SETTING(Database::ActiveDriver)).toString());
if (index_current_backend >= 0) {
m_ui->m_cmbDatabaseDriver->setCurrentIndex(index_current_backend);
}
onEndLoadSettings();
}
void SettingsDatabase::saveSettings() {
onBeginSaveSettings();
// Setup in-memory database status.
const bool original_inmemory = settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool();
const bool new_inmemory = m_ui->m_checkSqliteUseInMemoryDatabase->isChecked();
qApp->settings()->setValue(GROUP(Database), Database::UseTransactions, m_ui->m_checkUseTransactions->isChecked());
// Save data storage settings.
QString original_db_driver = settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString();
QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(m_ui->m_cmbDatabaseDriver->currentIndex()).toString();
// Save SQLite.
settings()->setValue(GROUP(Database), Database::UseInMemory, new_inmemory);
onBeginSaveSettings();
if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
// Save MySQL.
settings()->setValue(GROUP(Database), Database::MySQLHostname, m_ui->m_txtMysqlHostname->lineEdit()->text());
settings()->setValue(GROUP(Database), Database::MySQLUsername, m_ui->m_txtMysqlUsername->lineEdit()->text());
settings()->setValue(GROUP(Database), Database::MySQLPassword, TextFactory::encrypt(m_ui->m_txtMysqlPassword->lineEdit()->text()));
settings()->setValue(GROUP(Database), Database::MySQLDatabase, m_ui->m_txtMysqlDatabase->lineEdit()->text());
settings()->setValue(GROUP(Database), Database::MySQLPort, m_ui->m_spinMysqlPort->value());
}
// Setup in-memory database status.
const bool original_inmemory = settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool();
const bool new_inmemory = m_ui->m_checkSqliteUseInMemoryDatabase->isChecked();
settings()->setValue(GROUP(Database), Database::ActiveDriver, selected_db_driver);
qApp->settings()->setValue(GROUP(Database), Database::UseTransactions, m_ui->m_checkUseTransactions->isChecked());
if (original_db_driver != selected_db_driver || original_inmemory != new_inmemory) {
requireRestart();
}
// Save data storage settings.
QString original_db_driver = settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString();
QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(m_ui->m_cmbDatabaseDriver->currentIndex()).toString();
onEndSaveSettings();
// Save SQLite.
settings()->setValue(GROUP(Database), Database::UseInMemory, new_inmemory);
if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
// Save MySQL.
settings()->setValue(GROUP(Database), Database::MySQLHostname, m_ui->m_txtMysqlHostname->lineEdit()->text());
settings()->setValue(GROUP(Database), Database::MySQLUsername, m_ui->m_txtMysqlUsername->lineEdit()->text());
settings()->setValue(GROUP(Database), Database::MySQLPassword, TextFactory::encrypt(m_ui->m_txtMysqlPassword->lineEdit()->text()));
settings()->setValue(GROUP(Database), Database::MySQLDatabase, m_ui->m_txtMysqlDatabase->lineEdit()->text());
settings()->setValue(GROUP(Database), Database::MySQLPort, m_ui->m_spinMysqlPort->value());
}
settings()->setValue(GROUP(Database), Database::ActiveDriver, selected_db_driver);
if (original_db_driver != selected_db_driver || original_inmemory != new_inmemory) {
requireRestart();
}
onEndSaveSettings();
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,31 +23,31 @@
#include "ui_settingsdatabase.h"
class SettingsDatabase : public SettingsPanel {
Q_OBJECT
Q_OBJECT
public:
explicit SettingsDatabase(Settings* settings, QWidget* parent = 0);
virtual ~SettingsDatabase();
public:
explicit SettingsDatabase(Settings* settings, QWidget* parent = 0);
virtual ~SettingsDatabase();
inline QString title() const {
return tr("Data storage");
}
inline QString title() const {
return tr("Data storage");
}
void loadSettings();
void saveSettings();
void loadSettings();
private:
void mysqlTestConnection();
void onMysqlHostnameChanged(const QString& new_hostname);
void onMysqlUsernameChanged(const QString& new_username);
void onMysqlPasswordChanged(const QString& new_password);
void onMysqlDatabaseChanged(const QString& new_database);
void selectSqlBackend(int index);
void switchMysqlPasswordVisiblity(bool visible);
void saveSettings();
Ui::SettingsDatabase* m_ui;
private:
void mysqlTestConnection();
void onMysqlHostnameChanged(const QString& new_hostname);
void onMysqlUsernameChanged(const QString& new_username);
void onMysqlPasswordChanged(const QString& new_password);
void onMysqlDatabaseChanged(const QString& new_database);
void selectSqlBackend(int index);
void switchMysqlPasswordVisiblity(bool visible);
Ui::SettingsDatabase* m_ui;
};
#endif // SETTINGSDATABASE_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,54 +18,53 @@
#include "gui/settings/settingsdownloads.h"
#include "miscellaneous/application.h"
#include "miscellaneous/settings.h"
#include "network-web/downloadmanager.h"
#include "miscellaneous/application.h"
#include <QFileDialog>
SettingsDownloads::SettingsDownloads(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsDownloads) {
m_ui->setupUi(this);
connect(m_ui->m_checkOpenManagerWhenDownloadStarts, &QCheckBox::toggled, this, &SettingsDownloads::dirtifySettings);
connect(m_ui->m_txtDownloadsTargetDirectory, &QLineEdit::textChanged, this, &SettingsDownloads::dirtifySettings);
connect(m_ui->m_rbDownloadsAskEachFile, &QRadioButton::toggled, this, &SettingsDownloads::dirtifySettings);
connect(m_ui->m_btnDownloadsTargetDirectory, &QPushButton::clicked, this, &SettingsDownloads::selectDownloadsDirectory);
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsDownloads) {
m_ui->setupUi(this);
connect(m_ui->m_checkOpenManagerWhenDownloadStarts, &QCheckBox::toggled, this, &SettingsDownloads::dirtifySettings);
connect(m_ui->m_txtDownloadsTargetDirectory, &QLineEdit::textChanged, this, &SettingsDownloads::dirtifySettings);
connect(m_ui->m_rbDownloadsAskEachFile, &QRadioButton::toggled, this, &SettingsDownloads::dirtifySettings);
connect(m_ui->m_btnDownloadsTargetDirectory, &QPushButton::clicked, this, &SettingsDownloads::selectDownloadsDirectory);
}
SettingsDownloads::~SettingsDownloads() {
delete m_ui;
delete m_ui;
}
void SettingsDownloads::selectDownloadsDirectory() {
const QString target_directory = QFileDialog::getExistingDirectory(this,
tr("Select downloads target directory"),
m_ui->m_txtDownloadsTargetDirectory->text()
);
const QString target_directory = QFileDialog::getExistingDirectory(this,
tr("Select downloads target directory"),
m_ui->m_txtDownloadsTargetDirectory->text()
);
if (!target_directory.isEmpty()) {
m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(target_directory));
}
if (!target_directory.isEmpty()) {
m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(target_directory));
}
}
void SettingsDownloads::loadSettings() {
onBeginLoadSettings();
m_ui->m_checkOpenManagerWhenDownloadStarts->setChecked(settings()->value(GROUP(Downloads),
SETTING(Downloads::ShowDownloadsWhenNewDownloadStarts)).toBool());
m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(settings()->value(GROUP(Downloads),
SETTING(Downloads::TargetDirectory)).toString()));
m_ui->m_rbDownloadsAskEachFile->setChecked(settings()->value(GROUP(Downloads),
SETTING(Downloads::AlwaysPromptForFilename)).toBool());
onEndLoadSettings();
onBeginLoadSettings();
m_ui->m_checkOpenManagerWhenDownloadStarts->setChecked(settings()->value(GROUP(Downloads),
SETTING(Downloads::ShowDownloadsWhenNewDownloadStarts)).toBool());
m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(settings()->value(GROUP(Downloads),
SETTING(Downloads::TargetDirectory)).toString()));
m_ui->m_rbDownloadsAskEachFile->setChecked(settings()->value(GROUP(Downloads),
SETTING(Downloads::AlwaysPromptForFilename)).toBool());
onEndLoadSettings();
}
void SettingsDownloads::saveSettings() {
onBeginSaveSettings();
settings()->setValue(GROUP(Downloads), Downloads::ShowDownloadsWhenNewDownloadStarts,
m_ui->m_checkOpenManagerWhenDownloadStarts->isChecked());
settings()->setValue(GROUP(Downloads), Downloads::TargetDirectory, m_ui->m_txtDownloadsTargetDirectory->text());
settings()->setValue(GROUP(Downloads), Downloads::AlwaysPromptForFilename, m_ui->m_rbDownloadsAskEachFile->isChecked());
qApp->downloadManager()->setDownloadDirectory(m_ui->m_txtDownloadsTargetDirectory->text());
onEndSaveSettings();
onBeginSaveSettings();
settings()->setValue(GROUP(Downloads), Downloads::ShowDownloadsWhenNewDownloadStarts,
m_ui->m_checkOpenManagerWhenDownloadStarts->isChecked());
settings()->setValue(GROUP(Downloads), Downloads::TargetDirectory, m_ui->m_txtDownloadsTargetDirectory->text());
settings()->setValue(GROUP(Downloads), Downloads::AlwaysPromptForFilename, m_ui->m_rbDownloadsAskEachFile->isChecked());
qApp->downloadManager()->setDownloadDirectory(m_ui->m_txtDownloadsTargetDirectory->text());
onEndSaveSettings();
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,26 +23,26 @@
#include "ui_settingsdownloads.h"
class SettingsDownloads : public SettingsPanel {
Q_OBJECT
Q_OBJECT
public:
explicit SettingsDownloads(Settings* settings, QWidget* parent = 0);
virtual ~SettingsDownloads();
public:
explicit SettingsDownloads(Settings* settings, QWidget* parent = 0);
virtual ~SettingsDownloads();
inline QString title() const {
return tr("Downloads");
}
inline QString title() const {
return tr("Downloads");
}
void loadSettings();
void saveSettings();
void loadSettings();
private slots:
void selectDownloadsDirectory();
void saveSettings();
private:
Ui::SettingsDownloads* m_ui;
private slots:
void selectDownloadsDirectory();
private:
Ui::SettingsDownloads* m_ui;
};
#endif // SETTINGSDOWNLOADS_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -18,126 +19,128 @@
#include "gui/settings/settingsfeedsmessages.h"
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
#include "miscellaneous/feedreader.h"
#include "gui/dialogs/formmain.h"
#include "gui/feedmessageviewer.h"
#include "gui/feedsview.h"
#include "gui/guiutilities.h"
#include "gui/messagesview.h"
#include "gui/timespinbox.h"
#include "gui/guiutilities.h"
#include "miscellaneous/application.h"
#include "miscellaneous/feedreader.h"
#include <QFontDialog>
SettingsFeedsMessages::SettingsFeedsMessages(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsFeedsMessages) {
m_ui->setupUi(this);
initializeMessageDateFormats();
GuiUtilities::setLabelAsNotice(*m_ui->label_9, false);
connect(m_ui->m_checkAutoUpdateNotification, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkKeppMessagesInTheMiddle, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkMessagesDateTimeFormat, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkRemoveReadMessagesOnExit, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkUpdateAllFeedsOnStartup, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_spinAutoUpdateInterval, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_spinHeightImageAttachments, 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_spinFeedUpdateTimeout, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
&SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_cmbMessagesDateTimeFormat, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_cmbCountsFeedList, &QComboBox::currentTextChanged, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_cmbCountsFeedList, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_btnChangeMessagesFont, &QPushButton::clicked, this, &SettingsFeedsMessages::changeMessagesFont);
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsFeedsMessages) {
m_ui->setupUi(this);
initializeMessageDateFormats();
GuiUtilities::setLabelAsNotice(*m_ui->label_9, false);
connect(m_ui->m_checkAutoUpdateNotification, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkAutoUpdate, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkKeppMessagesInTheMiddle, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkMessagesDateTimeFormat, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkRemoveReadMessagesOnExit, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_checkUpdateAllFeedsOnStartup, &QCheckBox::toggled, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_spinAutoUpdateInterval, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_spinHeightImageAttachments, 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_spinFeedUpdateTimeout, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
&SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_cmbMessagesDateTimeFormat, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_cmbCountsFeedList, &QComboBox::currentTextChanged, this, &SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_cmbCountsFeedList, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsFeedsMessages::dirtifySettings);
connect(m_ui->m_btnChangeMessagesFont, &QPushButton::clicked, this, &SettingsFeedsMessages::changeMessagesFont);
if (!m_ui->m_spinFeedUpdateTimeout->suffix().startsWith(' ')) {
m_ui->m_spinFeedUpdateTimeout->setSuffix(QSL(" ") + m_ui->m_spinFeedUpdateTimeout->suffix());
}
if (!m_ui->m_spinFeedUpdateTimeout->suffix().startsWith(' ')) {
m_ui->m_spinFeedUpdateTimeout->setSuffix(QSL(" ") + m_ui->m_spinFeedUpdateTimeout->suffix());
}
}
SettingsFeedsMessages::~SettingsFeedsMessages() {
delete m_ui;
delete m_ui;
}
void SettingsFeedsMessages::initializeMessageDateFormats() {
QStringList best_formats;
best_formats << QSL("d/M/yyyy hh:mm:ss") << QSL("ddd, d. M. yy hh:mm:ss") <<
QSL("yyyy-MM-dd HH:mm:ss.z") << QSL("yyyy-MM-ddThh:mm:ss") <<
QSL("MMM d yyyy hh:mm:ss");;
const QLocale current_locale = qApp->localization()->loadedLocale();
const QDateTime current_dt = QDateTime::currentDateTime();
QStringList best_formats;
foreach (const QString& format, best_formats) {
m_ui->m_cmbMessagesDateTimeFormat->addItem(current_locale.toString(current_dt, format), format);
}
best_formats << QSL("d/M/yyyy hh:mm:ss") << QSL("ddd, d. M. yy hh:mm:ss") <<
QSL("yyyy-MM-dd HH:mm:ss.z") << QSL("yyyy-MM-ddThh:mm:ss") <<
QSL("MMM d yyyy hh:mm:ss");;
const QLocale current_locale = qApp->localization()->loadedLocale();
const QDateTime current_dt = QDateTime::currentDateTime();
foreach (const QString& format, best_formats) {
m_ui->m_cmbMessagesDateTimeFormat->addItem(current_locale.toString(current_dt, format), format);
}
}
void SettingsFeedsMessages::changeMessagesFont() {
bool ok;
QFont new_font = QFontDialog::getFont(&ok, m_ui->m_lblMessagesFont->font(),
this, tr("Select new font for message viewer"),
QFontDialog::DontUseNativeDialog);
bool ok;
QFont new_font = QFontDialog::getFont(&ok, m_ui->m_lblMessagesFont->font(),
this, tr("Select new font for message viewer"),
QFontDialog::DontUseNativeDialog);
if (ok) {
m_ui->m_lblMessagesFont->setFont(new_font);
dirtifySettings();
}
if (ok) {
m_ui->m_lblMessagesFont->setFont(new_font);
dirtifySettings();
}
}
void SettingsFeedsMessages::loadSettings() {
onBeginLoadSettings();
m_ui->m_checkAutoUpdateNotification->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::EnableAutoUpdateNotification)).toBool());
m_ui->m_checkKeppMessagesInTheMiddle->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::KeepCursorInCenter)).toBool());
m_ui->m_checkRemoveReadMessagesOnExit->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool());
m_ui->m_checkAutoUpdate->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateEnabled)).toBool());
m_ui->m_spinAutoUpdateInterval->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateInterval)).toInt());
m_ui->m_spinFeedUpdateTimeout->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt());
m_ui->m_checkUpdateAllFeedsOnStartup->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool());
m_ui->m_cmbCountsFeedList->addItems(QStringList() << "(%unread)" << "[%unread]" << "%unread/%all" << "%unread-%all" << "[%unread|%all]");
m_ui->m_cmbCountsFeedList->setEditText(settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString());
m_ui->m_spinHeightImageAttachments->setValue(settings()->value(GROUP(Messages), SETTING(Messages::MessageHeadImageHeight)).toInt());
initializeMessageDateFormats();
m_ui->m_checkMessagesDateTimeFormat->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool());
const int index_format = m_ui->m_cmbMessagesDateTimeFormat->findData(settings()->value(GROUP(Messages),
SETTING(Messages::CustomDateFormat)).toString());
onBeginLoadSettings();
m_ui->m_checkAutoUpdateNotification->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::EnableAutoUpdateNotification)).toBool());
m_ui->m_checkKeppMessagesInTheMiddle->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::KeepCursorInCenter)).toBool());
m_ui->m_checkRemoveReadMessagesOnExit->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::ClearReadOnExit)).toBool());
m_ui->m_checkAutoUpdate->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateEnabled)).toBool());
m_ui->m_spinAutoUpdateInterval->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::AutoUpdateInterval)).toInt());
m_ui->m_spinFeedUpdateTimeout->setValue(settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt());
m_ui->m_checkUpdateAllFeedsOnStartup->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::FeedsUpdateOnStartup)).toBool());
m_ui->m_cmbCountsFeedList->addItems(QStringList() << "(%unread)" << "[%unread]" << "%unread/%all" << "%unread-%all" << "[%unread|%all]");
m_ui->m_cmbCountsFeedList->setEditText(settings()->value(GROUP(Feeds), SETTING(Feeds::CountFormat)).toString());
m_ui->m_spinHeightImageAttachments->setValue(settings()->value(GROUP(Messages), SETTING(Messages::MessageHeadImageHeight)).toInt());
initializeMessageDateFormats();
m_ui->m_checkMessagesDateTimeFormat->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool());
const int index_format = m_ui->m_cmbMessagesDateTimeFormat->findData(settings()->value(GROUP(Messages),
SETTING(Messages::CustomDateFormat)).toString());
if (index_format >= 0) {
m_ui->m_cmbMessagesDateTimeFormat->setCurrentIndex(index_format);
}
if (index_format >= 0) {
m_ui->m_cmbMessagesDateTimeFormat->setCurrentIndex(index_format);
}
m_ui->m_lblMessagesFont->setText(tr("Font preview"));
QFont fon;
fon.fromString(settings()->value(GROUP(Messages),
SETTING(Messages::PreviewerFontStandard)).toString());
m_ui->m_lblMessagesFont->setFont(fon);
onEndLoadSettings();
m_ui->m_lblMessagesFont->setText(tr("Font preview"));
QFont fon;
fon.fromString(settings()->value(GROUP(Messages),
SETTING(Messages::PreviewerFontStandard)).toString());
m_ui->m_lblMessagesFont->setFont(fon);
onEndLoadSettings();
}
void SettingsFeedsMessages::saveSettings() {
onBeginSaveSettings();
settings()->setValue(GROUP(Feeds), Feeds::EnableAutoUpdateNotification, m_ui->m_checkAutoUpdateNotification->isChecked());
settings()->setValue(GROUP(Messages), Messages::KeepCursorInCenter, m_ui->m_checkKeppMessagesInTheMiddle->isChecked());
settings()->setValue(GROUP(Messages), Messages::ClearReadOnExit, m_ui->m_checkRemoveReadMessagesOnExit->isChecked());
settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateEnabled, m_ui->m_checkAutoUpdate->isChecked());
settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateInterval, m_ui->m_spinAutoUpdateInterval->value());
settings()->setValue(GROUP(Feeds), Feeds::UpdateTimeout, m_ui->m_spinFeedUpdateTimeout->value());
settings()->setValue(GROUP(Feeds), Feeds::FeedsUpdateOnStartup, m_ui->m_checkUpdateAllFeedsOnStartup->isChecked());
settings()->setValue(GROUP(Feeds), Feeds::CountFormat, m_ui->m_cmbCountsFeedList->currentText());
settings()->setValue(GROUP(Messages), Messages::UseCustomDate, m_ui->m_checkMessagesDateTimeFormat->isChecked());
settings()->setValue(GROUP(Messages), Messages::MessageHeadImageHeight, m_ui->m_spinHeightImageAttachments->value());
settings()->setValue(GROUP(Messages), Messages::CustomDateFormat,
m_ui->m_cmbMessagesDateTimeFormat->itemData(m_ui->m_cmbMessagesDateTimeFormat->currentIndex()).toString());
// Save fonts.
settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, m_ui->m_lblMessagesFont->font().toString());
qApp->mainForm()->tabWidget()->feedMessageViewer()->loadMessageViewerFonts();
qApp->feedReader()->updateAutoUpdateStatus();
qApp->feedReader()->feedsModel()->reloadWholeLayout();
qApp->feedReader()->messagesModel()->updateDateFormat();
qApp->feedReader()->messagesModel()->reloadWholeLayout();
onEndSaveSettings();
onBeginSaveSettings();
settings()->setValue(GROUP(Feeds), Feeds::EnableAutoUpdateNotification, m_ui->m_checkAutoUpdateNotification->isChecked());
settings()->setValue(GROUP(Messages), Messages::KeepCursorInCenter, m_ui->m_checkKeppMessagesInTheMiddle->isChecked());
settings()->setValue(GROUP(Messages), Messages::ClearReadOnExit, m_ui->m_checkRemoveReadMessagesOnExit->isChecked());
settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateEnabled, m_ui->m_checkAutoUpdate->isChecked());
settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateInterval, m_ui->m_spinAutoUpdateInterval->value());
settings()->setValue(GROUP(Feeds), Feeds::UpdateTimeout, m_ui->m_spinFeedUpdateTimeout->value());
settings()->setValue(GROUP(Feeds), Feeds::FeedsUpdateOnStartup, m_ui->m_checkUpdateAllFeedsOnStartup->isChecked());
settings()->setValue(GROUP(Feeds), Feeds::CountFormat, m_ui->m_cmbCountsFeedList->currentText());
settings()->setValue(GROUP(Messages), Messages::UseCustomDate, m_ui->m_checkMessagesDateTimeFormat->isChecked());
settings()->setValue(GROUP(Messages), Messages::MessageHeadImageHeight, m_ui->m_spinHeightImageAttachments->value());
settings()->setValue(GROUP(Messages), Messages::CustomDateFormat,
m_ui->m_cmbMessagesDateTimeFormat->itemData(m_ui->m_cmbMessagesDateTimeFormat->currentIndex()).toString());
// Save fonts.
settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, m_ui->m_lblMessagesFont->font().toString());
qApp->mainForm()->tabWidget()->feedMessageViewer()->loadMessageViewerFonts();
qApp->feedReader()->updateAutoUpdateStatus();
qApp->feedReader()->feedsModel()->reloadWholeLayout();
qApp->feedReader()->messagesModel()->updateDateFormat();
qApp->feedReader()->messagesModel()->reloadWholeLayout();
onEndSaveSettings();
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,28 +23,28 @@
#include "ui_settingsfeedsmessages.h"
class SettingsFeedsMessages : public SettingsPanel {
Q_OBJECT
Q_OBJECT
public:
explicit SettingsFeedsMessages(Settings* settings, QWidget* parent = 0);
virtual ~SettingsFeedsMessages();
public:
explicit SettingsFeedsMessages(Settings* settings, QWidget* parent = 0);
virtual ~SettingsFeedsMessages();
inline QString title() const {
return tr("Feeds & messages");
}
inline QString title() const {
return tr("Feeds & messages");
}
void loadSettings();
void saveSettings();
void loadSettings();
private slots:
void changeMessagesFont();
void saveSettings();
private:
void initializeMessageDateFormats();
private slots:
void changeMessagesFont();
Ui::SettingsFeedsMessages* m_ui;
private:
void initializeMessageDateFormats();
Ui::SettingsFeedsMessages* m_ui;
};
#endif // SETTINGSFEEDSMESSAGES_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,65 +18,65 @@
#include "gui/settings/settingsgeneral.h"
#include "miscellaneous/systemfactory.h"
#include "miscellaneous/application.h"
#include "miscellaneous/systemfactory.h"
SettingsGeneral::SettingsGeneral(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsGeneral) {
m_ui->setupUi(this);
m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text().arg(APP_NAME));
connect(m_ui->m_checkAutostart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings);
connect(m_ui->m_checkForUpdatesOnStart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings);
connect(m_ui->m_checkRemoveTrolltechJunk, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings);
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsGeneral) {
m_ui->setupUi(this);
m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text().arg(APP_NAME));
connect(m_ui->m_checkAutostart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings);
connect(m_ui->m_checkForUpdatesOnStart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings);
connect(m_ui->m_checkRemoveTrolltechJunk, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings);
}
SettingsGeneral::~SettingsGeneral() {
delete m_ui;
delete m_ui;
}
void SettingsGeneral::loadSettings() {
onBeginLoadSettings();
m_ui->m_checkForUpdatesOnStart->setChecked(settings()->value(GROUP(General), SETTING(General::UpdateOnStartup)).toBool());
// Load auto-start status.
const SystemFactory::AutoStartStatus autostart_status = qApp->system()->autoStartStatus();
onBeginLoadSettings();
m_ui->m_checkForUpdatesOnStart->setChecked(settings()->value(GROUP(General), SETTING(General::UpdateOnStartup)).toBool());
switch (autostart_status) {
case SystemFactory::AutoStartStatus::Enabled:
m_ui->m_checkAutostart->setChecked(true);
break;
// Load auto-start status.
const SystemFactory::AutoStartStatus autostart_status = qApp->system()->autoStartStatus();
case SystemFactory::AutoStartStatus::Disabled:
m_ui->m_checkAutostart->setChecked(false);
break;
switch (autostart_status) {
case SystemFactory::AutoStartStatus::Enabled:
m_ui->m_checkAutostart->setChecked(true);
break;
default:
m_ui->m_checkAutostart->setEnabled(false);
m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text() + tr(" (not supported on this platform)"));
break;
}
case SystemFactory::AutoStartStatus::Disabled:
m_ui->m_checkAutostart->setChecked(false);
break;
default:
m_ui->m_checkAutostart->setEnabled(false);
m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text() + tr(" (not supported on this platform)"));
break;
}
#if defined(Q_OS_WIN)
m_ui->m_checkRemoveTrolltechJunk->setVisible(true);
m_ui->m_checkRemoveTrolltechJunk->setChecked(settings()->value(GROUP(General), SETTING(General::RemoveTrolltechJunk)).toBool());
m_ui->m_checkRemoveTrolltechJunk->setVisible(true);
m_ui->m_checkRemoveTrolltechJunk->setChecked(settings()->value(GROUP(General), SETTING(General::RemoveTrolltechJunk)).toBool());
#else
m_ui->m_checkRemoveTrolltechJunk->setVisible(false);
m_ui->m_checkRemoveTrolltechJunk->setVisible(false);
#endif
onEndLoadSettings();
onEndLoadSettings();
}
void SettingsGeneral::saveSettings() {
onBeginSaveSettings();
onBeginSaveSettings();
// If auto-start feature is available and user wants to turn it on, then turn it on.
if (m_ui->m_checkAutostart->isChecked()) {
qApp->system()->setAutoStartStatus(SystemFactory::AutoStartStatus::Enabled);
}
else {
qApp->system()->setAutoStartStatus(SystemFactory::AutoStartStatus::Disabled);
}
// If auto-start feature is available and user wants to turn it on, then turn it on.
if (m_ui->m_checkAutostart->isChecked()) {
qApp->system()->setAutoStartStatus(SystemFactory::AutoStartStatus::Enabled);
}
else {
qApp->system()->setAutoStartStatus(SystemFactory::AutoStartStatus::Disabled);
}
settings()->setValue(GROUP(General), General::UpdateOnStartup, m_ui->m_checkForUpdatesOnStart->isChecked());
settings()->setValue(GROUP(General), General::RemoveTrolltechJunk, m_ui->m_checkRemoveTrolltechJunk->isChecked());
onEndSaveSettings();
settings()->setValue(GROUP(General), General::UpdateOnStartup, m_ui->m_checkForUpdatesOnStart->isChecked());
settings()->setValue(GROUP(General), General::RemoveTrolltechJunk, m_ui->m_checkRemoveTrolltechJunk->isChecked());
onEndSaveSettings();
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,23 +23,23 @@
#include "ui_settingsgeneral.h"
class SettingsGeneral : public SettingsPanel {
Q_OBJECT
Q_OBJECT
public:
explicit SettingsGeneral(Settings* settings, QWidget* parent = 0);
virtual ~SettingsGeneral();
public:
explicit SettingsGeneral(Settings* settings, QWidget* parent = 0);
virtual ~SettingsGeneral();
inline QString title() const {
return tr("General");
}
inline QString title() const {
return tr("General");
}
void loadSettings();
void saveSettings();
void loadSettings();
private:
Ui::SettingsGeneral* m_ui;
void saveSettings();
private:
Ui::SettingsGeneral* m_ui;
};
#endif // SETTINGSGENERAL_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,239 +18,252 @@
#include "gui/settings/settingsgui.h"
#include "gui/systemtrayicon.h"
#include "miscellaneous/settings.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "gui/dialogs/formmain.h"
#include "gui/tabwidget.h"
#include "gui/feedmessageviewer.h"
#include "gui/feedstoolbar.h"
#include "gui/messagestoolbar.h"
#include "gui/statusbar.h"
#include "gui/systemtrayicon.h"
#include "gui/tabwidget.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/settings.h"
#include <QDropEvent>
#include <QStyleFactory>
SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGui) {
m_ui->setupUi(this);
m_ui->m_editorMessagesToolbar->activeItemsWidget()->viewport()->installEventFilter(this);
m_ui->m_editorFeedsToolbar->activeItemsWidget()->viewport()->installEventFilter(this);
m_ui->m_editorMessagesToolbar->availableItemsWidget()->viewport()->installEventFilter(this);
m_ui->m_editorFeedsToolbar->availableItemsWidget()->viewport()->installEventFilter(this);
m_ui->m_treeSkins->setColumnCount(4);
m_ui->m_treeSkins->setHeaderHidden(false);
m_ui->m_treeSkins->setHeaderLabels(QStringList()
<< /*: Skin list name column. */ tr("Name")
<< /*: Version column of skin list. */ tr("Version")
<< tr("Author")
<< tr("E-mail"));
SettingsGui::SettingsGui(Settings* settings, QWidget* parent) : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGui) {
m_ui->setupUi(this);
m_ui->m_editorMessagesToolbar->activeItemsWidget()->viewport()->installEventFilter(this);
m_ui->m_editorFeedsToolbar->activeItemsWidget()->viewport()->installEventFilter(this);
m_ui->m_editorMessagesToolbar->availableItemsWidget()->viewport()->installEventFilter(this);
m_ui->m_editorFeedsToolbar->availableItemsWidget()->viewport()->installEventFilter(this);
m_ui->m_treeSkins->setColumnCount(4);
m_ui->m_treeSkins->setHeaderHidden(false);
m_ui->m_treeSkins->setHeaderLabels(QStringList()
<< /*: Skin list name column. */ tr("Name")
<< /*: Version column of skin list. */ tr("Version")
<< tr("Author")
<< tr("E-mail"));
// Setup skins.
m_ui->m_treeSkins->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
connect(m_ui->m_cmbIconTheme, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsGui::requireRestart);
connect(m_ui->m_cmbIconTheme, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsGui::dirtifySettings);
connect(m_ui->m_treeSkins, &QTreeWidget::currentItemChanged, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_grpTray, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkEnableNotifications, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkHidden, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkHideWhenMinimized, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkHideTabBarIfOneTabVisible, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkCloseTabsDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkCloseTabsMiddleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkNewTabDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_grbCloseTabs, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_cmbToolbarButtonStyle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsGui::dirtifySettings);
connect(m_ui->m_editorFeedsToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_editorMessagesToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_editorStatusbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_listStyles, &QListWidget::currentItemChanged, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_cmbSelectToolBar, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), m_ui->m_stackedToolbars,
&QStackedWidget::setCurrentIndex);
// Setup skins.
m_ui->m_treeSkins->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
connect(m_ui->m_cmbIconTheme, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsGui::requireRestart);
connect(m_ui->m_cmbIconTheme, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsGui::dirtifySettings);
connect(m_ui->m_treeSkins, &QTreeWidget::currentItemChanged, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_grpTray, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkEnableNotifications, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkHidden, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkHideWhenMinimized, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkHideTabBarIfOneTabVisible, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkCloseTabsDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkCloseTabsMiddleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_checkNewTabDoubleClick, &QCheckBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_grbCloseTabs, &QGroupBox::toggled, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_cmbToolbarButtonStyle, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
&SettingsGui::dirtifySettings);
connect(m_ui->m_editorFeedsToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_editorMessagesToolbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_editorStatusbar, &ToolBarEditor::setupChanged, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_listStyles, &QListWidget::currentItemChanged, this, &SettingsGui::dirtifySettings);
connect(m_ui->m_cmbSelectToolBar, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), m_ui->m_stackedToolbars,
&QStackedWidget::setCurrentIndex);
}
SettingsGui::~SettingsGui() {
delete m_ui;
delete m_ui;
}
bool SettingsGui::eventFilter(QObject* obj, QEvent* e) {
Q_UNUSED(obj)
Q_UNUSED(obj)
if (e->type() == QEvent::Drop) {
QDropEvent* drop_event = static_cast<QDropEvent*>(e);
if (e->type() == QEvent::Drop) {
QDropEvent* drop_event = static_cast<QDropEvent*>(e);
if (drop_event->keyboardModifiers() != Qt::NoModifier) {
drop_event->setDropAction(Qt::MoveAction);
}
}
if (drop_event->keyboardModifiers() != Qt::NoModifier) {
drop_event->setDropAction(Qt::MoveAction);
}
}
return false;
return false;
}
void SettingsGui::loadSettings() {
onBeginLoadSettings();
onBeginLoadSettings();
// Load settings of tray icon.
if (SystemTrayIcon::isSystemTrayAvailable()) {
m_ui->m_grpTray->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UseTrayIcon)).toBool());
}
// Tray icon is not supported on this machine.
else {
m_ui->m_grpTray->setTitle(m_ui->m_grpTray->title() + QL1C(' ') + tr("(Tray icon is not available.)"));
m_ui->m_grpTray->setChecked(false);
}
// Load settings of tray icon.
if (SystemTrayIcon::isSystemTrayAvailable()) {
m_ui->m_grpTray->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::UseTrayIcon)).toBool());
}
m_ui->m_checkHidden->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool());
m_ui->m_checkHideWhenMinimized->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool());
// Load fancy notification settings.
m_ui->m_checkEnableNotifications->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::EnableNotifications)).toBool());
// Load settings of icon theme.
const QString current_theme = qApp->icons()->currentIconTheme();
// Tray icon is not supported on this machine.
else {
m_ui->m_grpTray->setTitle(m_ui->m_grpTray->title() + QL1C(' ') + tr("(Tray icon is not available.)"));
m_ui->m_grpTray->setChecked(false);
}
foreach (const QString& icon_theme_name, qApp->icons()->installedIconThemes()) {
if (icon_theme_name == APP_NO_THEME) {
// Add just "no theme" on other systems.
//: Label for disabling icon theme.
m_ui->m_cmbIconTheme->addItem(tr("no icon theme/system icon theme"), APP_NO_THEME);
}
else {
m_ui->m_cmbIconTheme->addItem(icon_theme_name, icon_theme_name);
}
}
m_ui->m_checkHidden->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::MainWindowStartsHidden)).toBool());
m_ui->m_checkHideWhenMinimized->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideMainWindowWhenMinimized)).toBool());
// Mark active theme.
if (current_theme == QSL(APP_NO_THEME)) {
// Because "no icon theme" lies at the index 0.
m_ui->m_cmbIconTheme->setCurrentIndex(0);
}
else {
m_ui->m_cmbIconTheme->setCurrentText(current_theme);
}
// Load fancy notification settings.
m_ui->m_checkEnableNotifications->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::EnableNotifications)).toBool());
// Load skin.
const QString selected_skin = qApp->skins()->selectedSkinName();
// Load settings of icon theme.
const QString current_theme = qApp->icons()->currentIconTheme();
foreach (const Skin& skin, qApp->skins()->installedSkins()) {
QTreeWidgetItem* new_item = new QTreeWidgetItem(QStringList() <<
skin.m_visibleName <<
skin.m_version <<
skin.m_author <<
skin.m_email);
new_item->setData(0, Qt::UserRole, QVariant::fromValue(skin));
// Add this skin and mark it as active if its active now.
m_ui->m_treeSkins->addTopLevelItem(new_item);
foreach (const QString& icon_theme_name, qApp->icons()->installedIconThemes()) {
if (icon_theme_name == APP_NO_THEME) {
// Add just "no theme" on other systems.
//: Label for disabling icon theme.
m_ui->m_cmbIconTheme->addItem(tr("no icon theme/system icon theme"), APP_NO_THEME);
}
else {
m_ui->m_cmbIconTheme->addItem(icon_theme_name, icon_theme_name);
}
}
if (skin.m_baseName == selected_skin) {
m_ui->m_treeSkins->setCurrentItem(new_item);
}
}
// Mark active theme.
if (current_theme == QSL(APP_NO_THEME)) {
// Because "no icon theme" lies at the index 0.
m_ui->m_cmbIconTheme->setCurrentIndex(0);
}
else {
m_ui->m_cmbIconTheme->setCurrentText(current_theme);
}
if (m_ui->m_treeSkins->currentItem() == nullptr &&
m_ui->m_treeSkins->topLevelItemCount() > 0) {
// Currently active skin is NOT available, select another one as selected
// if possible.
m_ui->m_treeSkins->setCurrentItem(m_ui->m_treeSkins->topLevelItem(0));
}
// Load skin.
const QString selected_skin = qApp->skins()->selectedSkinName();
// Load styles.
foreach (const QString& style_name, QStyleFactory::keys()) {
m_ui->m_listStyles->addItem(style_name);
}
foreach (const Skin& skin, qApp->skins()->installedSkins()) {
QTreeWidgetItem* new_item = new QTreeWidgetItem(QStringList() <<
skin.m_visibleName <<
skin.m_version <<
skin.m_author <<
skin.m_email);
QList<QListWidgetItem*> items = m_ui->m_listStyles->findItems(settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString(),
Qt::MatchFixedString);
new_item->setData(0, Qt::UserRole, QVariant::fromValue(skin));
if (!items.isEmpty()) {
m_ui->m_listStyles->setCurrentItem(items.at(0));
}
// Add this skin and mark it as active if its active now.
m_ui->m_treeSkins->addTopLevelItem(new_item);
// Load tab settings.
m_ui->m_checkCloseTabsMiddleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool());
m_ui->m_checkCloseTabsDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool());
m_ui->m_checkNewTabDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabNewDoubleClick)).toBool());
m_ui->m_checkHideTabBarIfOneTabVisible->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideTabBarIfOnlyOneTab)).toBool());
// Load toolbar button style.
m_ui->m_cmbToolbarButtonStyle->addItem(tr("Icon only"), Qt::ToolButtonIconOnly);
m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text only"), Qt::ToolButtonTextOnly);
m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text beside icon"), Qt::ToolButtonTextBesideIcon);
m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text under icon"), Qt::ToolButtonTextUnderIcon);
m_ui->m_cmbToolbarButtonStyle->addItem(tr("Follow OS style"), Qt::ToolButtonFollowStyle);
m_ui->m_cmbToolbarButtonStyle->setCurrentIndex(m_ui->m_cmbToolbarButtonStyle->findData(settings()->value(GROUP(GUI),
SETTING(GUI::ToolbarStyle)).toInt()));
// Load toolbars.
m_ui->m_editorFeedsToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsToolBar());
m_ui->m_editorMessagesToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->messagesToolBar());
m_ui->m_editorStatusbar->loadFromToolBar(qApp->mainForm()->statusBar());
onEndLoadSettings();
if (skin.m_baseName == selected_skin) {
m_ui->m_treeSkins->setCurrentItem(new_item);
}
}
if (m_ui->m_treeSkins->currentItem() == nullptr &&
m_ui->m_treeSkins->topLevelItemCount() > 0) {
// Currently active skin is NOT available, select another one as selected
// if possible.
m_ui->m_treeSkins->setCurrentItem(m_ui->m_treeSkins->topLevelItem(0));
}
// Load styles.
foreach (const QString& style_name, QStyleFactory::keys()) {
m_ui->m_listStyles->addItem(style_name);
}
QList<QListWidgetItem*> items = m_ui->m_listStyles->findItems(settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString(),
Qt::MatchFixedString);
if (!items.isEmpty()) {
m_ui->m_listStyles->setCurrentItem(items.at(0));
}
// Load tab settings.
m_ui->m_checkCloseTabsMiddleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseMiddleClick)).toBool());
m_ui->m_checkCloseTabsDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabCloseDoubleClick)).toBool());
m_ui->m_checkNewTabDoubleClick->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::TabNewDoubleClick)).toBool());
m_ui->m_checkHideTabBarIfOneTabVisible->setChecked(settings()->value(GROUP(GUI), SETTING(GUI::HideTabBarIfOnlyOneTab)).toBool());
// Load toolbar button style.
m_ui->m_cmbToolbarButtonStyle->addItem(tr("Icon only"), Qt::ToolButtonIconOnly);
m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text only"), Qt::ToolButtonTextOnly);
m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text beside icon"), Qt::ToolButtonTextBesideIcon);
m_ui->m_cmbToolbarButtonStyle->addItem(tr("Text under icon"), Qt::ToolButtonTextUnderIcon);
m_ui->m_cmbToolbarButtonStyle->addItem(tr("Follow OS style"), Qt::ToolButtonFollowStyle);
m_ui->m_cmbToolbarButtonStyle->setCurrentIndex(m_ui->m_cmbToolbarButtonStyle->findData(settings()->value(GROUP(GUI),
SETTING(
GUI::ToolbarStyle)).toInt()));
// Load toolbars.
m_ui->m_editorFeedsToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsToolBar());
m_ui->m_editorMessagesToolbar->loadFromToolBar(qApp->mainForm()->tabWidget()->feedMessageViewer()->messagesToolBar());
m_ui->m_editorStatusbar->loadFromToolBar(qApp->mainForm()->statusBar());
onEndLoadSettings();
}
void SettingsGui::saveSettings() {
onBeginSaveSettings();
// Save toolbar.
settings()->setValue(GROUP(GUI), GUI::ToolbarStyle, m_ui->m_cmbToolbarButtonStyle->itemData(m_ui->m_cmbToolbarButtonStyle->currentIndex()));
onBeginSaveSettings();
// Save tray icon.
if (SystemTrayIcon::isSystemTrayAvailable()) {
settings()->setValue(GROUP(GUI), GUI::UseTrayIcon, m_ui->m_grpTray->isChecked());
// Save toolbar.
settings()->setValue(GROUP(GUI), GUI::ToolbarStyle,
m_ui->m_cmbToolbarButtonStyle->itemData(m_ui->m_cmbToolbarButtonStyle->currentIndex()));
if (m_ui->m_grpTray->isChecked()) {
qApp->showTrayIcon();
}
else {
qApp->deleteTrayIcon();
}
}
// Save tray icon.
if (SystemTrayIcon::isSystemTrayAvailable()) {
settings()->setValue(GROUP(GUI), GUI::UseTrayIcon, m_ui->m_grpTray->isChecked());
settings()->setValue(GROUP(GUI), GUI::MainWindowStartsHidden, m_ui->m_checkHidden->isChecked());
settings()->setValue(GROUP(GUI), GUI::HideMainWindowWhenMinimized, m_ui->m_checkHideWhenMinimized->isChecked());
// Save notifications.
settings()->setValue(GROUP(GUI), GUI::EnableNotifications, m_ui->m_checkEnableNotifications->isChecked());
// Save selected icon theme.
QString selected_icon_theme = m_ui->m_cmbIconTheme->itemData(m_ui->m_cmbIconTheme->currentIndex()).toString();
QString original_icon_theme = qApp->icons()->currentIconTheme();
qApp->icons()->setCurrentIconTheme(selected_icon_theme);
if (m_ui->m_grpTray->isChecked()) {
qApp->showTrayIcon();
}
else {
qApp->deleteTrayIcon();
}
}
// Check if icon theme was changed.
if (selected_icon_theme != original_icon_theme) {
requireRestart();
}
settings()->setValue(GROUP(GUI), GUI::MainWindowStartsHidden, m_ui->m_checkHidden->isChecked());
settings()->setValue(GROUP(GUI), GUI::HideMainWindowWhenMinimized, m_ui->m_checkHideWhenMinimized->isChecked());
// Save and activate new skin.
if (!m_ui->m_treeSkins->selectedItems().isEmpty()) {
const Skin active_skin = m_ui->m_treeSkins->currentItem()->data(0, Qt::UserRole).value<Skin>();
// Save notifications.
settings()->setValue(GROUP(GUI), GUI::EnableNotifications, m_ui->m_checkEnableNotifications->isChecked());
if (qApp->skins()->selectedSkinName() != active_skin.m_baseName) {
qApp->skins()->setCurrentSkinName(active_skin.m_baseName);
requireRestart();
}
}
// Save selected icon theme.
QString selected_icon_theme = m_ui->m_cmbIconTheme->itemData(m_ui->m_cmbIconTheme->currentIndex()).toString();
QString original_icon_theme = qApp->icons()->currentIconTheme();
// Set new style.
if (!m_ui->m_listStyles->selectedItems().isEmpty()) {
const QString new_style = m_ui->m_listStyles->currentItem()->text();
const QString old_style = qApp->settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString();
qApp->icons()->setCurrentIconTheme(selected_icon_theme);
if (old_style != new_style) {
requireRestart();
}
// Check if icon theme was changed.
if (selected_icon_theme != original_icon_theme) {
requireRestart();
}
qApp->settings()->setValue(GROUP(GUI), GUI::Style, new_style);
}
// Save and activate new skin.
if (!m_ui->m_treeSkins->selectedItems().isEmpty()) {
const Skin active_skin = m_ui->m_treeSkins->currentItem()->data(0, Qt::UserRole).value<Skin>();
// Save tab settings.
settings()->setValue(GROUP(GUI), GUI::TabCloseMiddleClick, m_ui->m_checkCloseTabsMiddleClick->isChecked());
settings()->setValue(GROUP(GUI), GUI::TabCloseDoubleClick, m_ui->m_checkCloseTabsDoubleClick->isChecked());
settings()->setValue(GROUP(GUI), GUI::TabNewDoubleClick, m_ui->m_checkNewTabDoubleClick->isChecked());
settings()->setValue(GROUP(GUI), GUI::HideTabBarIfOnlyOneTab, m_ui->m_checkHideTabBarIfOneTabVisible->isChecked());
m_ui->m_editorFeedsToolbar->saveToolBar();
m_ui->m_editorMessagesToolbar->saveToolBar();
m_ui->m_editorStatusbar->saveToolBar();
qApp->mainForm()->tabWidget()->checkTabBarVisibility();
qApp->mainForm()->tabWidget()->feedMessageViewer()->refreshVisualProperties();
onEndSaveSettings();
if (qApp->skins()->selectedSkinName() != active_skin.m_baseName) {
qApp->skins()->setCurrentSkinName(active_skin.m_baseName);
requireRestart();
}
}
// Set new style.
if (!m_ui->m_listStyles->selectedItems().isEmpty()) {
const QString new_style = m_ui->m_listStyles->currentItem()->text();
const QString old_style = qApp->settings()->value(GROUP(GUI), SETTING(GUI::Style)).toString();
if (old_style != new_style) {
requireRestart();
}
qApp->settings()->setValue(GROUP(GUI), GUI::Style, new_style);
}
// Save tab settings.
settings()->setValue(GROUP(GUI), GUI::TabCloseMiddleClick, m_ui->m_checkCloseTabsMiddleClick->isChecked());
settings()->setValue(GROUP(GUI), GUI::TabCloseDoubleClick, m_ui->m_checkCloseTabsDoubleClick->isChecked());
settings()->setValue(GROUP(GUI), GUI::TabNewDoubleClick, m_ui->m_checkNewTabDoubleClick->isChecked());
settings()->setValue(GROUP(GUI), GUI::HideTabBarIfOnlyOneTab, m_ui->m_checkHideTabBarIfOneTabVisible->isChecked());
m_ui->m_editorFeedsToolbar->saveToolBar();
m_ui->m_editorMessagesToolbar->saveToolBar();
m_ui->m_editorStatusbar->saveToolBar();
qApp->mainForm()->tabWidget()->checkTabBarVisibility();
qApp->mainForm()->tabWidget()->feedMessageViewer()->refreshVisualProperties();
onEndSaveSettings();
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,27 +23,28 @@
#include "ui_settingsgui.h"
class SettingsGui : public SettingsPanel {
Q_OBJECT
Q_OBJECT
public:
explicit SettingsGui(Settings* settings, QWidget* parent = 0);
virtual ~SettingsGui();
public:
explicit SettingsGui(Settings* settings, QWidget* parent = 0);
virtual ~SettingsGui();
inline QString title() const {
return tr("User interface");
}
inline QString title() const {
return tr("User interface");
}
void loadSettings();
void saveSettings();
void loadSettings();
protected:
// Does check of controls before dialog can be submitted.
bool eventFilter(QObject* obj, QEvent* e);
void saveSettings();
private:
Ui::SettingsGui* m_ui;
protected:
// Does check of controls before dialog can be submitted.
bool eventFilter(QObject* obj, QEvent* e);
private:
Ui::SettingsGui* m_ui;
};
#endif // SETTINGSGUI_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,70 +18,71 @@
#include "gui/settings/settingslocalization.h"
#include "miscellaneous/localization.h"
#include "miscellaneous/settings.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/localization.h"
#include "miscellaneous/settings.h"
SettingsLocalization::SettingsLocalization(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsLocalization) {
m_ui->setupUi(this);
m_ui->m_treeLanguages->setColumnCount(3);
m_ui->m_treeLanguages->setHeaderHidden(false);
m_ui->m_treeLanguages->setHeaderLabels(QStringList()
<< /*: Language column of language list. */ tr("Language")
<< /*: Lang. code column of language list. */ tr("Code")
<< tr("Author"));
// Setup languages.
m_ui->m_treeLanguages->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
connect(m_ui->m_treeLanguages, &QTreeWidget::currentItemChanged, this, &SettingsLocalization::requireRestart);
connect(m_ui->m_treeLanguages, &QTreeWidget::currentItemChanged, this, &SettingsLocalization::dirtifySettings);
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsLocalization) {
m_ui->setupUi(this);
m_ui->m_treeLanguages->setColumnCount(3);
m_ui->m_treeLanguages->setHeaderHidden(false);
m_ui->m_treeLanguages->setHeaderLabels(QStringList()
<< /*: Language column of language list. */ tr("Language")
<< /*: Lang. code column of language list. */ tr("Code")
<< tr("Author"));
// Setup languages.
m_ui->m_treeLanguages->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
connect(m_ui->m_treeLanguages, &QTreeWidget::currentItemChanged, this, &SettingsLocalization::requireRestart);
connect(m_ui->m_treeLanguages, &QTreeWidget::currentItemChanged, this, &SettingsLocalization::dirtifySettings);
}
SettingsLocalization::~SettingsLocalization() {
delete m_ui;
delete m_ui;
}
void SettingsLocalization::loadSettings() {
onBeginLoadSettings();
onBeginLoadSettings();
foreach (const Language& language, qApp->localization()->installedLanguages()) {
QTreeWidgetItem* item = new QTreeWidgetItem(m_ui->m_treeLanguages);
item->setText(0, language.m_name);
item->setText(1, language.m_code);
item->setText(2, language.m_author);
item->setIcon(0, qApp->icons()->miscIcon(QString(FLAG_ICON_SUBFOLDER) + QDir::separator() + language.m_code));
}
foreach (const Language& language, qApp->localization()->installedLanguages()) {
QTreeWidgetItem* item = new QTreeWidgetItem(m_ui->m_treeLanguages);
m_ui->m_treeLanguages->sortByColumn(0, Qt::AscendingOrder);
QList<QTreeWidgetItem*> matching_items = m_ui->m_treeLanguages->findItems(qApp->localization()->loadedLanguage(), Qt::MatchContains, 1);
item->setText(0, language.m_name);
item->setText(1, language.m_code);
item->setText(2, language.m_author);
item->setIcon(0, qApp->icons()->miscIcon(QString(FLAG_ICON_SUBFOLDER) + QDir::separator() + language.m_code));
}
if (!matching_items.isEmpty()) {
m_ui->m_treeLanguages->setCurrentItem(matching_items[0]);
}
m_ui->m_treeLanguages->sortByColumn(0, Qt::AscendingOrder);
QList<QTreeWidgetItem*> matching_items = m_ui->m_treeLanguages->findItems(qApp->localization()->loadedLanguage(), Qt::MatchContains, 1);
onEndLoadSettings();
if (!matching_items.isEmpty()) {
m_ui->m_treeLanguages->setCurrentItem(matching_items[0]);
}
onEndLoadSettings();
}
void SettingsLocalization::saveSettings() {
onBeginSaveSettings();
onBeginSaveSettings();
if (m_ui->m_treeLanguages->currentItem() == nullptr) {
qDebug("No localizations loaded in settings dialog, so no saving for them.");
return;
}
if (m_ui->m_treeLanguages->currentItem() == nullptr) {
qDebug("No localizations loaded in settings dialog, so no saving for them.");
return;
}
const QString actual_lang = qApp->localization()->loadedLanguage();
const QString new_lang = m_ui->m_treeLanguages->currentItem()->text(1);
const QString actual_lang = qApp->localization()->loadedLanguage();
const QString new_lang = m_ui->m_treeLanguages->currentItem()->text(1);
// Save prompt for restart if language has changed.
if (new_lang != actual_lang) {
requireRestart();
settings()->setValue(GROUP(General), General::Language, new_lang);
}
// Save prompt for restart if language has changed.
if (new_lang != actual_lang) {
requireRestart();
settings()->setValue(GROUP(General), General::Language, new_lang);
}
onEndSaveSettings();
onEndSaveSettings();
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -22,23 +23,23 @@
#include "ui_settingslocalization.h"
class SettingsLocalization : public SettingsPanel {
Q_OBJECT
Q_OBJECT
public:
explicit SettingsLocalization(Settings* settings, QWidget* parent = 0);
virtual ~SettingsLocalization();
public:
explicit SettingsLocalization(Settings* settings, QWidget* parent = 0);
virtual ~SettingsLocalization();
inline QString title() const {
return tr("Language");
}
inline QString title() const {
return tr("Language");
}
void loadSettings();
void saveSettings();
void loadSettings();
private:
Ui::SettingsLocalization* m_ui;
void saveSettings();
private:
Ui::SettingsLocalization* m_ui;
};
#endif // SETTINGSLOCALIZATION_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -19,55 +20,52 @@
#include "miscellaneous/settings.h"
SettingsPanel::SettingsPanel(Settings* settings, QWidget* parent)
: QWidget(parent), m_requiresRestart(false), m_isDirty(false), m_isLoading(false), m_settings(settings) {
}
: QWidget(parent), m_requiresRestart(false), m_isDirty(false), m_isLoading(false), m_settings(settings) {}
void SettingsPanel::onBeginLoadSettings() {
m_isLoading = true;
m_isLoading = true;
}
void SettingsPanel::onEndLoadSettings() {
m_isLoading = false;
setRequiresRestart(false);
setIsDirty(false);
m_isLoading = false;
setRequiresRestart(false);
setIsDirty(false);
}
void SettingsPanel::onBeginSaveSettings() {
}
void SettingsPanel::onBeginSaveSettings() {}
void SettingsPanel::onEndSaveSettings() {
setIsDirty(false);
setIsDirty(false);
}
void SettingsPanel::dirtifySettings() {
if (!m_isLoading) {
setIsDirty(true);
emit settingsChanged();
}
if (!m_isLoading) {
setIsDirty(true);
emit settingsChanged();
}
}
bool SettingsPanel::requiresRestart() const {
return m_requiresRestart;
return m_requiresRestart;
}
void SettingsPanel::setRequiresRestart(bool requiresRestart) {
m_requiresRestart = requiresRestart;
m_requiresRestart = requiresRestart;
}
void SettingsPanel::requireRestart() {
setRequiresRestart(true);
setRequiresRestart(true);
}
bool SettingsPanel::isDirty() const {
return m_isDirty;
return m_isDirty;
}
void SettingsPanel::setIsDirty(bool is_dirty) {
m_isDirty = is_dirty;
m_isDirty = is_dirty;
}
Settings* SettingsPanel::settings() const {
return m_settings;
return m_settings;
}

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -20,50 +21,49 @@
#include <QWidget>
class Settings;
class SettingsPanel : public QWidget {
Q_OBJECT
Q_OBJECT
public:
explicit SettingsPanel(Settings* settings, QWidget* parent = 0);
public:
explicit SettingsPanel(Settings* settings, QWidget* parent = 0);
virtual QString title() const = 0;
virtual QString title() const = 0;
virtual void loadSettings() = 0;
virtual void saveSettings() = 0;
virtual void loadSettings() = 0;
virtual void saveSettings() = 0;
bool requiresRestart() const;
bool isDirty() const;
bool requiresRestart() const;
bool isDirty() const;
void setIsDirty(bool is_dirty);
void setRequiresRestart(bool requiresRestart);
void setIsDirty(bool is_dirty);
void setRequiresRestart(bool requiresRestart);
protected:
void onBeginLoadSettings();
void onEndLoadSettings();
void onBeginSaveSettings();
void onEndSaveSettings();
protected:
void onBeginLoadSettings();
void onEndLoadSettings();
void onBeginSaveSettings();
void onEndSaveSettings();
// Settings to use to save/load.
Settings* settings() const;
// Settings to use to save/load.
Settings* settings() const;
protected slots:
protected slots:
// Sets this settings panel as dirty (some settings are changed) and emits the signal.
// NOTE: This will be probably called by subclasses when user changes some stuff.
void dirtifySettings();
// Sets this settings panel as dirty (some settings are changed) and emits the signal.
// NOTE: This will be probably called by subclasses when user changes some stuff.
void dirtifySettings();
void requireRestart();
void requireRestart();
signals:
void settingsChanged();
signals:
void settingsChanged();
private:
bool m_requiresRestart;
bool m_isDirty;
bool m_isLoading;
Settings* m_settings;
private:
bool m_requiresRestart;
bool m_isDirty;
bool m_isLoading;
Settings* m_settings;
};
#endif // SETTINGSPANEL_H

View File

@ -1,4 +1,5 @@
// This file is part of RSS Guard.
//
// Copyright (C) 2011-2017 by Martin Rotter <rotter.martinos@gmail.com>
//
@ -17,29 +18,28 @@
#include "gui/settings/settingsshortcuts.h"
#include "miscellaneous/application.h"
#include "dynamic-shortcuts/dynamicshortcuts.h"
#include "miscellaneous/application.h"
SettingsShortcuts::SettingsShortcuts(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsShortcuts) {
m_ui->setupUi(this);
connect(m_ui->m_shortcuts, &DynamicShortcutsWidget::setupChanged, this, &SettingsShortcuts::dirtifySettings);
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsShortcuts) {
m_ui->setupUi(this);
connect(m_ui->m_shortcuts, &DynamicShortcutsWidget::setupChanged, this, &SettingsShortcuts::dirtifySettings);
}
SettingsShortcuts::~SettingsShortcuts() {
delete m_ui;
delete m_ui;
}
void SettingsShortcuts::loadSettings() {
onBeginLoadSettings();
m_ui->m_shortcuts->populate(qApp->userActions());
onEndLoadSettings();
onBeginLoadSettings();
m_ui->m_shortcuts->populate(qApp->userActions());
onEndLoadSettings();
}
void SettingsShortcuts::saveSettings() {
onBeginSaveSettings();
m_ui->m_shortcuts->updateShortcuts();
DynamicShortcuts::save(qApp->userActions());
onEndSaveSettings();
onBeginSaveSettings();
m_ui->m_shortcuts->updateShortcuts();
DynamicShortcuts::save(qApp->userActions());
onEndSaveSettings();
}

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