Reformated using astyle, added some astyle scripts.

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

26
.astylerc Executable file
View File

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

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

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

View File

@ -27,152 +27,144 @@
#include <QString> #include <QString>
FeedDownloader::FeedDownloader(QObject *parent) FeedDownloader::FeedDownloader(QObject* parent)
: QObject(parent), m_feeds(QList<Feed*>()), m_mutex(new QMutex()), m_threadPool(new QThreadPool(this)), : QObject(parent), m_feeds(QList<Feed*>()), m_mutex(new QMutex()), m_threadPool(new QThreadPool(this)),
m_results(FeedDownloadResults()), m_feedsUpdated(0), m_results(FeedDownloadResults()), m_feedsUpdated(0),
m_feedsUpdating(0), m_feedsOriginalCount(0) { m_feedsUpdating(0), m_feedsOriginalCount(0) {
qRegisterMetaType<FeedDownloadResults>("FeedDownloadResults"); qRegisterMetaType<FeedDownloadResults>("FeedDownloadResults");
m_threadPool->setMaxThreadCount(FEED_DOWNLOADER_MAX_THREADS); m_threadPool->setMaxThreadCount(FEED_DOWNLOADER_MAX_THREADS);
} }
FeedDownloader::~FeedDownloader() { FeedDownloader::~FeedDownloader() {
m_mutex->tryLock(); m_mutex->tryLock();
m_mutex->unlock(); m_mutex->unlock();
delete m_mutex; delete m_mutex;
qDebug("Destroying FeedDownloader instance.");
qDebug("Destroying FeedDownloader instance.");
} }
bool FeedDownloader::isUpdateRunning() const { bool FeedDownloader::isUpdateRunning() const {
return !m_feeds.isEmpty() || m_feedsUpdating > 0; return !m_feeds.isEmpty() || m_feedsUpdating > 0;
} }
void FeedDownloader::updateAvailableFeeds() { void FeedDownloader::updateAvailableFeeds() {
while (!m_feeds.isEmpty()) { while (!m_feeds.isEmpty()) {
connect(m_feeds.first(), &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished, connect(m_feeds.first(), &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished,
(Qt::ConnectionType) (Qt::UniqueConnection | Qt::AutoConnection)); (Qt::ConnectionType)(Qt::UniqueConnection | Qt::AutoConnection));
if (m_threadPool->tryStart(m_feeds.first())) {
m_feeds.removeFirst(); if (m_threadPool->tryStart(m_feeds.first())) {
m_feedsUpdating++; m_feeds.removeFirst();
} m_feedsUpdating++;
else { }
// We want to start update of some feeds but all working threads are occupied.
break; else {
} // We want to start update of some feeds but all working threads are occupied.
} break;
}
}
} }
void FeedDownloader::updateFeeds(const QList<Feed*> &feeds) { void FeedDownloader::updateFeeds(const QList<Feed*>& feeds) {
QMutexLocker locker(m_mutex); QMutexLocker locker(m_mutex);
if (feeds.isEmpty()) { if (feeds.isEmpty()) {
qDebug("No feeds to update in worker thread, aborting update."); qDebug("No feeds to update in worker thread, aborting update.");
finalizeUpdate(); finalizeUpdate();
} }
else {
qDebug().nospace() << "Starting feed updates from worker in thread: \'" << QThread::currentThreadId() << "\'.";
m_feeds = feeds; else {
m_feedsOriginalCount = m_feeds.size(); qDebug().nospace() << "Starting feed updates from worker in thread: \'" << QThread::currentThreadId() << "\'.";
m_results.clear(); m_feeds = feeds;
m_feedsUpdated = m_feedsUpdating = 0; m_feedsOriginalCount = m_feeds.size();
m_results.clear();
// Job starts now. m_feedsUpdated = m_feedsUpdating = 0;
emit updateStarted(); // Job starts now.
updateAvailableFeeds(); emit updateStarted();
} updateAvailableFeeds();
}
} }
void FeedDownloader::stopRunningUpdate() { void FeedDownloader::stopRunningUpdate() {
m_threadPool->clear(); m_threadPool->clear();
m_feeds.clear(); m_feeds.clear();
} }
void FeedDownloader::oneFeedUpdateFinished(const QList<Message> &messages, bool error_during_obtaining) { void FeedDownloader::oneFeedUpdateFinished(const QList<Message>& messages, bool error_during_obtaining) {
QMutexLocker locker(m_mutex); QMutexLocker locker(m_mutex);
m_feedsUpdated++;
m_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);
m_feedsUpdated++; /*
m_feedsUpdating--; QMetaObject::invokeMethod(feed, "updateMessages", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(int, updated_messages),
Q_ARG(QList<Message>, messages));
*/
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. if (m_feeds.isEmpty() && m_feedsUpdating <= 0) {
updateAvailableFeeds(); 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() { void FeedDownloader::finalizeUpdate() {
qDebug().nospace() << "Finished feed updates in thread: \'" << QThread::currentThreadId() << "\'."; qDebug().nospace() << "Finished feed updates in thread: \'" << QThread::currentThreadId() << "\'.";
m_results.sort();
m_results.sort(); // Update of feeds has finished.
// NOTE: This means that now "update lock" can be unlocked
// Update of feeds has finished. // and feeds can be added/edited/deleted and application
// NOTE: This means that now "update lock" can be unlocked // can eventually quit.
// and feeds can be added/edited/deleted and application emit updateFinished(m_results);
// 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 { 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++) { 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)); 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) { if (m_updatedFeeds.size() > how_many_feeds) {
res_str += QObject::tr("\n\n+ %n other feeds.", 0, 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) { void FeedDownloadResults::appendUpdatedFeed(const QPair<QString, int>& feed) {
m_updatedFeeds.append(feed); m_updatedFeeds.append(feed);
} }
void FeedDownloadResults::sort() { 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) { 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() { void FeedDownloadResults::clear() {
m_updatedFeeds.clear(); m_updatedFeeds.clear();
} }
QList<QPair<QString,int> > FeedDownloadResults::updatedFeeds() const { QList<QPair<QString, int>> FeedDownloadResults::updatedFeeds() const {
return m_updatedFeeds; return m_updatedFeeds;
} }

View File

@ -31,74 +31,74 @@ class QMutex;
// Represents results of batch feed updates. // Represents results of batch feed updates.
class FeedDownloadResults { class FeedDownloadResults {
public: public:
explicit FeedDownloadResults(); explicit FeedDownloadResults();
QList<QPair<QString,int> > updatedFeeds() const; QList<QPair<QString, int>> updatedFeeds() const;
QString overview(int how_many_feeds) const; QString overview(int how_many_feeds) const;
void appendUpdatedFeed(const QPair<QString,int> &feed); void appendUpdatedFeed(const QPair<QString, int>& feed);
void sort(); void sort();
void clear(); void clear();
static bool lessThan(const QPair<QString,int> &lhs, const QPair<QString,int> &rhs); static bool lessThan(const QPair<QString, int>& lhs, const QPair<QString, int>& rhs);
private: private:
// QString represents title if the feed, int represents count of newly downloaded messages. // QString represents title if the feed, int represents count of newly downloaded messages.
QList<QPair<QString,int> > m_updatedFeeds; QList<QPair<QString, int>> m_updatedFeeds;
}; };
// This class offers means to "update" feeds and "special" categories. // This class offers means to "update" feeds and "special" categories.
// NOTE: This class is used within separate thread. // NOTE: This class is used within separate thread.
class FeedDownloader : public QObject { class FeedDownloader : public QObject {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedDownloader(QObject *parent = 0); explicit FeedDownloader(QObject* parent = 0);
virtual ~FeedDownloader(); virtual ~FeedDownloader();
bool isUpdateRunning() const; bool isUpdateRunning() const;
public slots: public slots:
// Performs update of all feeds from the "feeds" parameter. // Performs update of all feeds from the "feeds" parameter.
// New messages are downloaded for each feed and they // New messages are downloaded for each feed and they
// are stored persistently in the database. // are stored persistently in the database.
// Appropriate signals are emitted. // Appropriate signals are emitted.
void updateFeeds(const QList<Feed*> &feeds); void updateFeeds(const QList<Feed*>& feeds);
// Stops running update. // Stops running update.
void stopRunningUpdate(); void stopRunningUpdate();
private slots: private slots:
void oneFeedUpdateFinished(const QList<Message> &messages, bool error_during_obtaining); void oneFeedUpdateFinished(const QList<Message>& messages, bool error_during_obtaining);
signals: signals:
// Emitted if feed updates started. // Emitted if feed updates started.
void updateStarted(); void updateStarted();
// Emitted if all items from update queue are // Emitted if all items from update queue are
// processed. // processed.
void updateFinished(FeedDownloadResults updated_feeds); void updateFinished(FeedDownloadResults updated_feeds);
// Emitted if any item is processed. // Emitted if any item is processed.
// "Current" number indicates count of processed feeds // "Current" number indicates count of processed feeds
// and "total" number indicates total number of feeds // and "total" number indicates total number of feeds
// which were in the initial queue. // which were in the initial queue.
void updateProgress(const Feed *feed, int current, int total); void updateProgress(const Feed* feed, int current, int total);
private: private:
void updateAvailableFeeds(); void updateAvailableFeeds();
void finalizeUpdate(); void finalizeUpdate();
QList<Feed*> m_feeds; QList<Feed*> m_feeds;
QMutex *m_mutex; QMutex* m_mutex;
QThreadPool *m_threadPool; QThreadPool* m_threadPool;
FeedDownloadResults m_results; FeedDownloadResults m_results;
int m_feedsUpdated; int m_feedsUpdated;
int m_feedsUpdating; int m_feedsUpdating;
int m_feedsOriginalCount; int m_feedsOriginalCount;
}; };
#endif // FEEDDOWNLOADER_H #endif // FEEDDOWNLOADER_H

View File

@ -38,517 +38,507 @@
#include <algorithm> #include <algorithm>
FeedsModel::FeedsModel(QObject *parent) : QAbstractItemModel(parent) { FeedsModel::FeedsModel(QObject* parent) : QAbstractItemModel(parent) {
setObjectName(QSL("FeedsModel")); setObjectName(QSL("FeedsModel"));
// Create root item.
// Create root item. m_rootItem = new RootItem();
m_rootItem = new RootItem(); //: Name of root item of feed list which can be seen in feed add/edit dialog.
m_rootItem->setTitle(tr("Root"));
//: Name of root item of feed list which can be seen in feed add/edit dialog. m_rootItem->setIcon(qApp->icons()->fromTheme(QSL("folder")));
m_rootItem->setTitle(tr("Root")); // Setup icons.
m_rootItem->setIcon(qApp->icons()->fromTheme(QSL("folder"))); m_countsIcon = qApp->icons()->fromTheme(QSL("mail-mark-unread"));
//: Title text in the feed list header.
// Setup icons. m_headerData << tr("Title");
m_countsIcon = qApp->icons()->fromTheme(QSL("mail-mark-unread")); m_tooltipData << /*: Feed list header "titles" column tooltip.*/ tr("Titles of feeds/categories.") <<
/*: Feed list header "counts" column tooltip.*/ tr("Counts of unread/all mesages.");
//: Title text in the feed list header.
m_headerData << tr("Title");
m_tooltipData << /*: Feed list header "titles" column tooltip.*/ tr("Titles of feeds/categories.") <<
/*: Feed list header "counts" column tooltip.*/ tr("Counts of unread/all mesages.");
} }
FeedsModel::~FeedsModel() { FeedsModel::~FeedsModel() {
qDebug("Destroying FeedsModel instance."); qDebug("Destroying FeedsModel instance.");
// Delete all model items.
// Delete all model items. delete m_rootItem;
delete m_rootItem;
} }
QMimeData *FeedsModel::mimeData(const QModelIndexList &indexes) const { QMimeData* FeedsModel::mimeData(const QModelIndexList& indexes) const {
QMimeData *mime_data = new QMimeData(); QMimeData* mime_data = new QMimeData();
QByteArray encoded_data; QByteArray encoded_data;
QDataStream stream(&encoded_data, QIODevice::WriteOnly); QDataStream stream(&encoded_data, QIODevice::WriteOnly);
foreach (const QModelIndex &index, indexes) { foreach (const QModelIndex& index, indexes) {
if (index.column() != 0) { if (index.column() != 0) {
continue; continue;
} }
RootItem *item_for_index = itemForIndex(index); RootItem* item_for_index = itemForIndex(index);
if (item_for_index->kind() != RootItemKind::Root) { if (item_for_index->kind() != RootItemKind::Root) {
stream << (quintptr) item_for_index; stream << (quintptr) item_for_index;
} }
} }
mime_data->setData(QSL(MIME_TYPE_ITEM_POINTER), encoded_data); mime_data->setData(QSL(MIME_TYPE_ITEM_POINTER), encoded_data);
return mime_data; return mime_data;
} }
QStringList FeedsModel::mimeTypes() const { QStringList FeedsModel::mimeTypes() const {
return QStringList() << QSL(MIME_TYPE_ITEM_POINTER); return QStringList() << QSL(MIME_TYPE_ITEM_POINTER);
} }
bool FeedsModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { bool FeedsModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) {
Q_UNUSED(row) Q_UNUSED(row)
Q_UNUSED(column) Q_UNUSED(column)
if (action == Qt::IgnoreAction) { if (action == Qt::IgnoreAction) {
return true; return true;
} }
else if (action != Qt::MoveAction) {
return false;
}
QByteArray dragged_items_data = data->data(QSL(MIME_TYPE_ITEM_POINTER)); else if (action != Qt::MoveAction) {
return false;
}
if (dragged_items_data.isEmpty()) { QByteArray dragged_items_data = data->data(QSL(MIME_TYPE_ITEM_POINTER));
return false;
}
else {
QDataStream stream(&dragged_items_data, QIODevice::ReadOnly);
while (!stream.atEnd()) { if (dragged_items_data.isEmpty()) {
quintptr pointer_to_item; return false;
stream >> pointer_to_item; }
// We have item we want to drag, we also determine the target item. else {
RootItem *dragged_item = (RootItem*) pointer_to_item; QDataStream stream(&dragged_items_data, QIODevice::ReadOnly);
RootItem *target_item = itemForIndex(parent);
ServiceRoot *dragged_item_root = dragged_item->getParentServiceRoot();
ServiceRoot *target_item_root = target_item->getParentServiceRoot();
if (dragged_item == target_item || dragged_item->parent() == target_item) { while (!stream.atEnd()) {
qDebug("Dragged item is equal to target item or its parent is equal to target item. Cancelling drag-drop action."); quintptr pointer_to_item;
return false; stream >> pointer_to_item;
} // We have item we want to drag, we also determine the target item.
RootItem* dragged_item = (RootItem*) pointer_to_item;
RootItem* target_item = itemForIndex(parent);
ServiceRoot* dragged_item_root = dragged_item->getParentServiceRoot();
ServiceRoot* target_item_root = target_item->getParentServiceRoot();
if (dragged_item_root != target_item_root) { if (dragged_item == target_item || dragged_item->parent() == target_item) {
// Transferring of items between different accounts is not possible. qDebug("Dragged item is equal to target item or its parent is equal to target item. Cancelling drag-drop action.");
qApp->showGuiMessage(tr("Cannot perform drag & drop operation"), return false;
tr("You can't transfer dragged item into different account, this is not supported."), }
QSystemTrayIcon::Warning,
qApp->mainFormWidget(),
true);
qDebug("Dragged item cannot be dragged into different account. Cancelling drag-drop action."); if (dragged_item_root != target_item_root) {
return false; // Transferring of items between different accounts is not possible.
} qApp->showGuiMessage(tr("Cannot perform drag & drop operation"),
tr("You can't transfer dragged item into different account, this is not supported."),
QSystemTrayIcon::Warning,
qApp->mainFormWidget(),
true);
qDebug("Dragged item cannot be dragged into different account. Cancelling drag-drop action.");
return false;
}
if (dragged_item->performDragDropChange(target_item)) { if (dragged_item->performDragDropChange(target_item)) {
// Drag & drop is supported by the dragged item and was // Drag & drop is supported by the dragged item and was
// completed on data level and in item hierarchy. // completed on data level and in item hierarchy.
emit requireItemValidationAfterDragDrop(indexForItem(dragged_item)); emit requireItemValidationAfterDragDrop(indexForItem(dragged_item));
} }
} }
return true; return true;
} }
return false; return false;
} }
Qt::DropActions FeedsModel::supportedDropActions() const { Qt::DropActions FeedsModel::supportedDropActions() const {
return Qt::MoveAction; return Qt::MoveAction;
} }
Qt::ItemFlags FeedsModel::flags(const QModelIndex &index) const { Qt::ItemFlags FeedsModel::flags(const QModelIndex& index) const {
Qt::ItemFlags base_flags = QAbstractItemModel::flags(index); Qt::ItemFlags base_flags = QAbstractItemModel::flags(index);
const RootItem *item_for_index = itemForIndex(index); const RootItem* item_for_index = itemForIndex(index);
Qt::ItemFlags additional_flags = item_for_index->additionalFlags(); Qt::ItemFlags additional_flags = item_for_index->additionalFlags();
return base_flags | additional_flags;
return base_flags | additional_flags;
} }
QVariant FeedsModel::headerData(int section, Qt::Orientation orientation, int role) const { QVariant FeedsModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (orientation != Qt::Horizontal) { if (orientation != Qt::Horizontal) {
return QVariant(); return QVariant();
} }
switch (role) { switch (role) {
case Qt::DisplayRole: case Qt::DisplayRole:
if (section == FDS_MODEL_TITLE_INDEX) { if (section == FDS_MODEL_TITLE_INDEX) {
return m_headerData.at(FDS_MODEL_TITLE_INDEX); return m_headerData.at(FDS_MODEL_TITLE_INDEX);
} }
else {
return QVariant();
}
case Qt::ToolTipRole: else {
return m_tooltipData.at(section); return QVariant();
}
case Qt::DecorationRole: case Qt::ToolTipRole:
if (section == FDS_MODEL_COUNTS_INDEX) { return m_tooltipData.at(section);
return m_countsIcon;
}
else {
return QVariant();
}
default: case Qt::DecorationRole:
return QVariant(); if (section == FDS_MODEL_COUNTS_INDEX) {
} return m_countsIcon;
}
else {
return QVariant();
}
default:
return QVariant();
}
} }
QModelIndex FeedsModel::index(int row, int column, const QModelIndex &parent) const { QModelIndex FeedsModel::index(int row, int column, const QModelIndex& parent) const {
if (!hasIndex(row, column, parent)) { if (!hasIndex(row, column, parent)) {
return QModelIndex(); return QModelIndex();
} }
RootItem *parent_item = itemForIndex(parent); RootItem* parent_item = itemForIndex(parent);
RootItem *child_item = parent_item->child(row); RootItem* child_item = parent_item->child(row);
if (child_item) { if (child_item) {
return createIndex(row, column, child_item); return createIndex(row, column, child_item);
} }
else {
return QModelIndex(); else {
} return QModelIndex();
}
} }
QModelIndex FeedsModel::parent(const QModelIndex &child) const { QModelIndex FeedsModel::parent(const QModelIndex& child) const {
if (!child.isValid()) { if (!child.isValid()) {
return QModelIndex(); return QModelIndex();
} }
RootItem *child_item = itemForIndex(child); RootItem* child_item = itemForIndex(child);
RootItem *parent_item = child_item->parent(); RootItem* parent_item = child_item->parent();
if (parent_item == m_rootItem) { if (parent_item == m_rootItem) {
return QModelIndex(); return QModelIndex();
} }
else {
return createIndex(parent_item->row(), 0, parent_item); else {
} return createIndex(parent_item->row(), 0, parent_item);
}
} }
int FeedsModel::rowCount(const QModelIndex &parent) const { int FeedsModel::rowCount(const QModelIndex& parent) const {
if (parent.column() > 0) { if (parent.column() > 0) {
return 0; return 0;
} }
else {
return itemForIndex(parent)->childCount(); else {
} return itemForIndex(parent)->childCount();
}
} }
int FeedsModel::countOfAllMessages() const { int FeedsModel::countOfAllMessages() const {
return m_rootItem->countOfAllMessages(); return m_rootItem->countOfAllMessages();
} }
int FeedsModel::countOfUnreadMessages() const { int FeedsModel::countOfUnreadMessages() const {
return m_rootItem->countOfUnreadMessages(); return m_rootItem->countOfUnreadMessages();
} }
void FeedsModel::reloadCountsOfWholeModel() { void FeedsModel::reloadCountsOfWholeModel() {
m_rootItem->updateCounts(true); m_rootItem->updateCounts(true);
reloadWholeLayout(); reloadWholeLayout();
notifyWithCounts(); notifyWithCounts();
} }
void FeedsModel::removeItem(const QModelIndex &index) { void FeedsModel::removeItem(const QModelIndex& index) {
if (index.isValid()) { if (index.isValid()) {
RootItem *deleting_item = itemForIndex(index); RootItem* deleting_item = itemForIndex(index);
QModelIndex parent_index = index.parent(); QModelIndex parent_index = index.parent();
RootItem *parent_item = deleting_item->parent(); RootItem* parent_item = deleting_item->parent();
beginRemoveRows(parent_index, index.row(), index.row());
beginRemoveRows(parent_index, index.row(), index.row()); parent_item->removeChild(deleting_item);
parent_item->removeChild(deleting_item); endRemoveRows();
endRemoveRows(); deleting_item->deleteLater();
notifyWithCounts();
deleting_item->deleteLater(); }
notifyWithCounts();
}
} }
void FeedsModel::removeItem(RootItem *deleting_item) { void FeedsModel::removeItem(RootItem* deleting_item) {
if (deleting_item != nullptr) { if (deleting_item != nullptr) {
QModelIndex index = indexForItem(deleting_item); QModelIndex index = indexForItem(deleting_item);
QModelIndex parent_index = index.parent(); QModelIndex parent_index = index.parent();
RootItem *parent_item = deleting_item->parent(); RootItem* parent_item = deleting_item->parent();
beginRemoveRows(parent_index, index.row(), index.row());
beginRemoveRows(parent_index, index.row(), index.row()); parent_item->removeChild(deleting_item);
parent_item->removeChild(deleting_item); endRemoveRows();
endRemoveRows(); deleting_item->deleteLater();
notifyWithCounts();
deleting_item->deleteLater(); }
notifyWithCounts();
}
} }
void FeedsModel::reassignNodeToNewParent(RootItem *original_node, RootItem *new_parent) { void FeedsModel::reassignNodeToNewParent(RootItem* original_node, RootItem* new_parent) {
RootItem *original_parent = original_node->parent(); RootItem* original_parent = original_node->parent();
if (original_parent != new_parent) { if (original_parent != new_parent) {
if (original_parent != nullptr) { if (original_parent != nullptr) {
int original_index_of_item = original_parent->childItems().indexOf(original_node); int original_index_of_item = original_parent->childItems().indexOf(original_node);
if (original_index_of_item >= 0) { if (original_index_of_item >= 0) {
// Remove the original item from the model... // Remove the original item from the model...
beginRemoveRows(indexForItem(original_parent), original_index_of_item, original_index_of_item); beginRemoveRows(indexForItem(original_parent), original_index_of_item, original_index_of_item);
original_parent->removeChild(original_node); original_parent->removeChild(original_node);
endRemoveRows(); endRemoveRows();
} }
} }
int new_index_of_item = new_parent->childCount(); int new_index_of_item = new_parent->childCount();
// ... and insert it under the new parent.
// ... and insert it under the new parent. beginInsertRows(indexForItem(new_parent), new_index_of_item, new_index_of_item);
beginInsertRows(indexForItem(new_parent), new_index_of_item, new_index_of_item); new_parent->appendChild(original_node);
new_parent->appendChild(original_node); endInsertRows();
endInsertRows(); }
}
} }
QList<ServiceRoot*> FeedsModel::serviceRoots() const { QList<ServiceRoot*> FeedsModel::serviceRoots() const {
QList<ServiceRoot*> roots; QList<ServiceRoot*> roots;
foreach (RootItem *root, m_rootItem->childItems()) { foreach (RootItem* root, m_rootItem->childItems()) {
if (root->kind() == RootItemKind::ServiceRoot) { if (root->kind() == RootItemKind::ServiceRoot) {
roots.append(root->toServiceRoot()); roots.append(root->toServiceRoot());
} }
} }
return roots; return roots;
} }
bool FeedsModel::containsServiceRootFromEntryPoint(const ServiceEntryPoint *point) const { bool FeedsModel::containsServiceRootFromEntryPoint(const ServiceEntryPoint* point) const {
foreach (const ServiceRoot *root, serviceRoots()) { foreach (const ServiceRoot* root, serviceRoots()) {
if (root->code() == point->code()) { if (root->code() == point->code()) {
return true; return true;
} }
} }
return false; return false;
} }
StandardServiceRoot *FeedsModel::standardServiceRoot() const { StandardServiceRoot* FeedsModel::standardServiceRoot() const {
foreach (ServiceRoot *root, serviceRoots()) { foreach (ServiceRoot* root, serviceRoots()) {
StandardServiceRoot *std_service_root; StandardServiceRoot* std_service_root;
if ((std_service_root = dynamic_cast<StandardServiceRoot*>(root)) != nullptr) { if ((std_service_root = dynamic_cast<StandardServiceRoot*>(root)) != nullptr) {
return std_service_root; return std_service_root;
} }
} }
return nullptr; return nullptr;
} }
QList<Feed*> FeedsModel::feedsForScheduledUpdate(bool auto_update_now) { QList<Feed*> FeedsModel::feedsForScheduledUpdate(bool auto_update_now) {
QList<Feed*> feeds_for_update; QList<Feed*> feeds_for_update;
foreach (Feed *feed, m_rootItem->getSubTreeFeeds()) { foreach (Feed* feed, m_rootItem->getSubTreeFeeds()) {
switch (feed->autoUpdateType()) { switch (feed->autoUpdateType()) {
case Feed::DontAutoUpdate: case Feed::DontAutoUpdate:
// Do not auto-update this feed ever. // Do not auto-update this feed ever.
continue; continue;
case Feed::DefaultAutoUpdate: case Feed::DefaultAutoUpdate:
if (auto_update_now) { if (auto_update_now) {
feeds_for_update.append(feed); feeds_for_update.append(feed);
} }
break; break;
case Feed::SpecificAutoUpdate: case Feed::SpecificAutoUpdate:
default: default:
int remaining_interval = feed->autoUpdateRemainingInterval(); int remaining_interval = feed->autoUpdateRemainingInterval();
if (--remaining_interval <= 0) { if (--remaining_interval <= 0) {
// Interval of this feed passed, include this feed in the output list // Interval of this feed passed, include this feed in the output list
// and reset the interval. // and reset the interval.
feeds_for_update.append(feed); feeds_for_update.append(feed);
feed->setAutoUpdateRemainingInterval(feed->autoUpdateInitialInterval()); feed->setAutoUpdateRemainingInterval(feed->autoUpdateInitialInterval());
} }
else {
// Interval did not pass, set new decremented interval and do NOT
// include this feed in the output list.
feed->setAutoUpdateRemainingInterval(remaining_interval);
}
break; else {
} // Interval did not pass, set new decremented interval and do NOT
} // include this feed in the output list.
feed->setAutoUpdateRemainingInterval(remaining_interval);
}
return feeds_for_update; break;
}
}
return feeds_for_update;
} }
QList<Message> FeedsModel::messagesForItem(RootItem *item) const { QList<Message> FeedsModel::messagesForItem(RootItem* item) const {
return item->undeletedMessages(); return item->undeletedMessages();
} }
int FeedsModel::columnCount(const QModelIndex &parent) const { int FeedsModel::columnCount(const QModelIndex& parent) const {
Q_UNUSED(parent) Q_UNUSED(parent)
return FEEDS_VIEW_COLUMN_COUNT;
return FEEDS_VIEW_COLUMN_COUNT;
} }
RootItem *FeedsModel::itemForIndex(const QModelIndex &index) const { RootItem* FeedsModel::itemForIndex(const QModelIndex& index) const {
if (index.isValid() && index.model() == this) { if (index.isValid() && index.model() == this) {
return static_cast<RootItem*>(index.internalPointer()); return static_cast<RootItem*>(index.internalPointer());
} }
else {
return m_rootItem; else {
} return m_rootItem;
}
} }
QModelIndex FeedsModel::indexForItem(const RootItem *item) const { QModelIndex FeedsModel::indexForItem(const RootItem* item) const {
if (item == nullptr || item->kind() == RootItemKind::Root) { if (item == nullptr || item->kind() == RootItemKind::Root) {
// Root item lies on invalid index. // Root item lies on invalid index.
return QModelIndex(); return QModelIndex();
} }
QStack<const RootItem*> chain; QStack<const RootItem*> chain;
while (item->kind() != RootItemKind::Root) { while (item->kind() != RootItemKind::Root) {
chain.push(item); chain.push(item);
item = item->parent(); item = item->parent();
} }
// Now, we have complete chain list: parent --- ..... --- parent --- leaf (item). // Now, we have complete chain list: parent --- ..... --- parent --- leaf (item).
QModelIndex target_index = indexForItem(m_rootItem); QModelIndex target_index = indexForItem(m_rootItem);
// We go through the stack and create our target index. // We go through the stack and create our target index.
while (!chain.isEmpty()) { while (!chain.isEmpty()) {
const RootItem *parent_item = chain.pop(); const RootItem* parent_item = chain.pop();
target_index = index(parent_item->parent()->childItems().indexOf(const_cast<RootItem* const>(parent_item)), 0, target_index); target_index = index(parent_item->parent()->childItems().indexOf(const_cast<RootItem* const>(parent_item)), 0, target_index);
} }
return target_index; return target_index;
} }
bool FeedsModel::hasAnyFeedNewMessages() const { bool FeedsModel::hasAnyFeedNewMessages() const {
foreach (const Feed *feed, m_rootItem->getSubTreeFeeds()) { foreach (const Feed* feed, m_rootItem->getSubTreeFeeds()) {
if (feed->status() == Feed::NewMessages) { if (feed->status() == Feed::NewMessages) {
return true; return true;
} }
} }
return false; return false;
} }
RootItem *FeedsModel::rootItem() const { RootItem* FeedsModel::rootItem() const {
return m_rootItem; return m_rootItem;
} }
void FeedsModel::reloadChangedLayout(QModelIndexList list) { void FeedsModel::reloadChangedLayout(QModelIndexList list) {
while (!list.isEmpty()) { while (!list.isEmpty()) {
QModelIndex indx = list.takeFirst(); QModelIndex indx = list.takeFirst();
if (indx.isValid()) { if (indx.isValid()) {
QModelIndex indx_parent = indx.parent(); QModelIndex indx_parent = indx.parent();
// Underlying data are changed.
// Underlying data are changed. emit dataChanged(index(indx.row(), 0, indx_parent), index(indx.row(), FDS_MODEL_COUNTS_INDEX, indx_parent));
emit dataChanged(index(indx.row(), 0, indx_parent), index(indx.row(), FDS_MODEL_COUNTS_INDEX, indx_parent)); list.append(indx_parent);
}
list.append(indx_parent); }
}
}
} }
void FeedsModel::reloadChangedItem(RootItem *item) { void FeedsModel::reloadChangedItem(RootItem* item) {
QModelIndex index_item = indexForItem(item); QModelIndex index_item = indexForItem(item);
reloadChangedLayout(QModelIndexList() << index_item); reloadChangedLayout(QModelIndexList() << index_item);
} }
void FeedsModel::notifyWithCounts() { void FeedsModel::notifyWithCounts() {
emit messageCountsChanged(countOfUnreadMessages(), hasAnyFeedNewMessages()); emit messageCountsChanged(countOfUnreadMessages(), hasAnyFeedNewMessages());
} }
void FeedsModel::onItemDataChanged(const QList<RootItem *> &items) { void FeedsModel::onItemDataChanged(const QList<RootItem*>& items) {
if (items.size() > RELOAD_MODEL_BORDER_NUM) { if (items.size() > RELOAD_MODEL_BORDER_NUM) {
qDebug("There is request to reload feed model for more than %d items, reloading model fully.", RELOAD_MODEL_BORDER_NUM); qDebug("There is request to reload feed model for more than %d items, reloading model fully.", RELOAD_MODEL_BORDER_NUM);
reloadWholeLayout(); reloadWholeLayout();
} }
else {
qDebug("There is request to reload feed model, reloading the %d items individually.", items.size());
foreach (RootItem *item, items) { else {
reloadChangedItem(item); qDebug("There is request to reload feed model, reloading the %d items individually.", items.size());
}
}
notifyWithCounts(); foreach (RootItem* item, items) {
reloadChangedItem(item);
}
}
notifyWithCounts();
} }
void FeedsModel::reloadWholeLayout() { void FeedsModel::reloadWholeLayout() {
emit layoutAboutToBeChanged(); emit layoutAboutToBeChanged();
emit layoutChanged(); emit layoutChanged();
} }
bool FeedsModel::addServiceAccount(ServiceRoot *root, bool freshly_activated) { bool FeedsModel::addServiceAccount(ServiceRoot* root, bool freshly_activated) {
int new_row_index = m_rootItem->childCount(); int new_row_index = m_rootItem->childCount();
beginInsertRows(indexForItem(m_rootItem), new_row_index, new_row_index);
beginInsertRows(indexForItem(m_rootItem), new_row_index, new_row_index); m_rootItem->appendChild(root);
m_rootItem->appendChild(root); endInsertRows();
endInsertRows(); // Connect.
connect(root, &ServiceRoot::itemRemovalRequested, this, static_cast<void (FeedsModel::*)(RootItem*)>(&FeedsModel::removeItem));
// Connect. connect(root, &ServiceRoot::itemReassignmentRequested, this, &FeedsModel::reassignNodeToNewParent);
connect(root, &ServiceRoot::itemRemovalRequested, this, static_cast<void (FeedsModel::*)(RootItem*)>(&FeedsModel::removeItem)); connect(root, &ServiceRoot::dataChanged, this, &FeedsModel::onItemDataChanged);
connect(root, &ServiceRoot::itemReassignmentRequested, this, &FeedsModel::reassignNodeToNewParent); connect(root, &ServiceRoot::reloadMessageListRequested, this, &FeedsModel::reloadMessageListRequested);
connect(root, &ServiceRoot::dataChanged, this, &FeedsModel::onItemDataChanged); connect(root, &ServiceRoot::itemExpandRequested, this, &FeedsModel::itemExpandRequested);
connect(root, &ServiceRoot::reloadMessageListRequested, this, &FeedsModel::reloadMessageListRequested); connect(root, &ServiceRoot::itemExpandStateSaveRequested, this, &FeedsModel::itemExpandStateSaveRequested);
connect(root, &ServiceRoot::itemExpandRequested, this, &FeedsModel::itemExpandRequested); root->start(freshly_activated);
connect(root, &ServiceRoot::itemExpandStateSaveRequested, this, &FeedsModel::itemExpandStateSaveRequested); return true;
root->start(freshly_activated);
return true;
} }
bool FeedsModel::restoreAllBins() { bool FeedsModel::restoreAllBins() {
bool result = true; bool result = true;
foreach (ServiceRoot *root, serviceRoots()) { foreach (ServiceRoot* root, serviceRoots()) {
RecycleBin *bin_of_root = root->recycleBin(); RecycleBin* bin_of_root = root->recycleBin();
if (bin_of_root != nullptr) { if (bin_of_root != nullptr) {
result &= bin_of_root->restore(); result &= bin_of_root->restore();
} }
} }
return result; return result;
} }
bool FeedsModel::emptyAllBins() { bool FeedsModel::emptyAllBins() {
bool result = true; bool result = true;
foreach (ServiceRoot *root, serviceRoots()) { foreach (ServiceRoot* root, serviceRoots()) {
RecycleBin *bin_of_root = root->recycleBin(); RecycleBin* bin_of_root = root->recycleBin();
if (bin_of_root != nullptr) { if (bin_of_root != nullptr) {
result &= bin_of_root->empty(); result &= bin_of_root->empty();
} }
} }
return result; return result;
} }
void FeedsModel::loadActivatedServiceAccounts() { void FeedsModel::loadActivatedServiceAccounts() {
// Iterate all globally available feed "service plugins". // Iterate all globally available feed "service plugins".
foreach (const ServiceEntryPoint *entry_point, qApp->feedReader()->feedServices()) { foreach (const ServiceEntryPoint* entry_point, qApp->feedReader()->feedServices()) {
// Load all stored root nodes from the entry point and add those to the model. // Load all stored root nodes from the entry point and add those to the model.
QList<ServiceRoot*> roots = entry_point->initializeSubtree(); QList<ServiceRoot*> roots = entry_point->initializeSubtree();
foreach (ServiceRoot *root, roots) { foreach (ServiceRoot* root, roots) {
addServiceAccount(root, false); addServiceAccount(root, false);
} }
} }
} }
void FeedsModel::stopServiceAccounts() { void FeedsModel::stopServiceAccounts() {
foreach (ServiceRoot *account, serviceRoots()) { foreach (ServiceRoot* account, serviceRoots()) {
account->stop(); account->stop();
} }
} }
QList<Feed*> FeedsModel::feedsForIndex(const QModelIndex &index) const { QList<Feed*> FeedsModel::feedsForIndex(const QModelIndex& index) const {
return itemForIndex(index)->getSubTreeFeeds(); return itemForIndex(index)->getSubTreeFeeds();
} }
bool FeedsModel::markItemRead(RootItem *item, RootItem::ReadStatus read) { bool FeedsModel::markItemRead(RootItem* item, RootItem::ReadStatus read) {
return item->markAsReadUnread(read); return item->markAsReadUnread(read);
} }
bool FeedsModel::markItemCleared(RootItem *item, bool clean_read_only) { bool FeedsModel::markItemCleared(RootItem* item, bool clean_read_only) {
return item->cleanMessages(clean_read_only); return item->cleanMessages(clean_read_only);
} }

View File

@ -30,153 +30,153 @@ class ServiceEntryPoint;
class StandardServiceRoot; class StandardServiceRoot;
class FeedsModel : public QAbstractItemModel { class FeedsModel : public QAbstractItemModel {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedsModel(QObject *parent = 0); explicit FeedsModel(QObject* parent = 0);
virtual ~FeedsModel(); virtual ~FeedsModel();
// Model implementation. // Model implementation.
inline QVariant data(const QModelIndex &index, int role) const { inline QVariant data(const QModelIndex& index, int role) const {
// Return data according to item. // Return data according to item.
return itemForIndex(index)->data(index.column(), role); return itemForIndex(index)->data(index.column(), role);
} }
// Drag & drop. // Drag & drop.
QMimeData *mimeData(const QModelIndexList &indexes) const; QMimeData* mimeData(const QModelIndexList& indexes) const;
QStringList mimeTypes() const; QStringList mimeTypes() const;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent);
Qt::DropActions supportedDropActions() const; Qt::DropActions supportedDropActions() const;
Qt::ItemFlags flags(const QModelIndex &index) const; Qt::ItemFlags flags(const QModelIndex& index) const;
// Other subclassed methods. // Other subclassed methods.
QVariant headerData(int section, Qt::Orientation orientation, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QModelIndex index(int row, int column, const QModelIndex &parent) const; QModelIndex index(int row, int column, const QModelIndex& parent) const;
QModelIndex parent(const QModelIndex &child) const; QModelIndex parent(const QModelIndex& child) const;
int columnCount(const QModelIndex &parent) const; int columnCount(const QModelIndex& parent) const;
int rowCount(const QModelIndex &parent) const; int rowCount(const QModelIndex& parent) const;
// Returns counts of ALL/UNREAD (non-deleted) messages for the model. // Returns counts of ALL/UNREAD (non-deleted) messages for the model.
int countOfAllMessages() const; int countOfAllMessages() const;
int countOfUnreadMessages() const; int countOfUnreadMessages() const;
// Returns all activated service roots. // Returns all activated service roots.
// NOTE: Service root nodes are lying directly UNDER // NOTE: Service root nodes are lying directly UNDER
// the model root item. // the model root item.
QList<ServiceRoot*> serviceRoots() const; QList<ServiceRoot*> serviceRoots() const;
// Determines if there is any account activated from given entry point. // Determines if there is any account activated from given entry point.
bool containsServiceRootFromEntryPoint(const ServiceEntryPoint *point) const; bool containsServiceRootFromEntryPoint(const ServiceEntryPoint* point) const;
// Direct and the only global accessor to standard service root. // Direct and the only global accessor to standard service root.
StandardServiceRoot *standardServiceRoot() const; StandardServiceRoot* standardServiceRoot() const;
// Returns the list of feeds which should be updated // Returns the list of feeds which should be updated
// according to auto-update schedule. // according to auto-update schedule.
// Variable "auto_update_now" is true, when global timeout // Variable "auto_update_now" is true, when global timeout
// for scheduled auto-update was met and global auto-update strategy is enabled // for scheduled auto-update was met and global auto-update strategy is enabled
// so feeds with "default" auto-update strategy should be updated. // so feeds with "default" auto-update strategy should be updated.
// //
// This method might change some properties of some feeds. // This method might change some properties of some feeds.
QList<Feed*> feedsForScheduledUpdate(bool auto_update_now); QList<Feed*> feedsForScheduledUpdate(bool auto_update_now);
// Returns (undeleted) messages for given feeds. // Returns (undeleted) messages for given feeds.
// This is usually used for displaying whole feeds // This is usually used for displaying whole feeds
// in "newspaper" mode. // in "newspaper" mode.
QList<Message> messagesForItem(RootItem *item) const; QList<Message> messagesForItem(RootItem* item) const;
// Returns ALL RECURSIVE CHILD feeds contained within single index. // Returns ALL RECURSIVE CHILD feeds contained within single index.
QList<Feed*> feedsForIndex(const QModelIndex &index) const; QList<Feed*> feedsForIndex(const QModelIndex& index) const;
// Returns feed/category which lies at the specified index or // Returns feed/category which lies at the specified index or
// root item if index is invalid. // root item if index is invalid.
RootItem *itemForIndex(const QModelIndex &index) const; RootItem* itemForIndex(const QModelIndex& index) const;
// Returns source QModelIndex on which lies given item. // Returns source QModelIndex on which lies given item.
// NOTE: This goes through all available indexes and // NOTE: This goes through all available indexes and
// checks their bound items manually, there is no // checks their bound items manually, there is no
// other way to to this. // other way to to this.
QModelIndex indexForItem(const RootItem *item) const; QModelIndex indexForItem(const RootItem* item) const;
// Determines if any feed has any new messages. // Determines if any feed has any new messages.
bool hasAnyFeedNewMessages() const; bool hasAnyFeedNewMessages() const;
// Access to root item. // Access to root item.
RootItem *rootItem() const; RootItem* rootItem() const;
public slots: public slots:
// Loads feed/categories from the database. // Loads feed/categories from the database.
void loadActivatedServiceAccounts(); void loadActivatedServiceAccounts();
// Stops all accounts before exit. // Stops all accounts before exit.
void stopServiceAccounts(); void stopServiceAccounts();
// Reloads counts of all feeds/categories/whatever in the model. // Reloads counts of all feeds/categories/whatever in the model.
void reloadCountsOfWholeModel(); void reloadCountsOfWholeModel();
// Checks if new parent node is different from one used by original node. // Checks if new parent node is different from one used by original node.
// If it is, then it reassigns original_node to new parent. // If it is, then it reassigns original_node to new parent.
void reassignNodeToNewParent(RootItem *original_node, RootItem *new_parent); void reassignNodeToNewParent(RootItem* original_node, RootItem* new_parent);
// Adds given service root account. // Adds given service root account.
bool addServiceAccount(ServiceRoot *root, bool freshly_activated); bool addServiceAccount(ServiceRoot* root, bool freshly_activated);
// Removes item with given index. // Removes item with given index.
// NOTE: Also deletes item from memory. // NOTE: Also deletes item from memory.
void removeItem(const QModelIndex &index); void removeItem(const QModelIndex& index);
void removeItem(RootItem *deleting_item); void removeItem(RootItem* deleting_item);
// Recycle bins operations. // Recycle bins operations.
bool restoreAllBins(); bool restoreAllBins();
bool emptyAllBins(); bool emptyAllBins();
// Feeds operations. // Feeds operations.
bool markItemRead(RootItem *item, RootItem::ReadStatus read); bool markItemRead(RootItem* item, RootItem::ReadStatus read);
bool markItemCleared(RootItem *item, bool clean_read_only); bool markItemCleared(RootItem* item, bool clean_read_only);
// Signals that properties (probably counts) // Signals that properties (probably counts)
// of ALL items have changed. // of ALL items have changed.
void reloadWholeLayout(); void reloadWholeLayout();
// Signals that SOME data of this model need // Signals that SOME data of this model need
// to be reloaded by ALL attached views. // to be reloaded by ALL attached views.
// NOTE: This reloads all parent valid indexes too. // NOTE: This reloads all parent valid indexes too.
void reloadChangedLayout(QModelIndexList list); void reloadChangedLayout(QModelIndexList list);
// Invalidates data under index for the item. // Invalidates data under index for the item.
void reloadChangedItem(RootItem *item); void reloadChangedItem(RootItem* item);
// Notifies other components about messages // Notifies other components about messages
// counts. // counts.
void notifyWithCounts(); void notifyWithCounts();
private slots: private slots:
void onItemDataChanged(const QList<RootItem*> &items); void onItemDataChanged(const QList<RootItem*>& items);
signals: signals:
// Emitted if counts of messages are changed. // Emitted if counts of messages are changed.
void messageCountsChanged(int unread_messages, bool any_feed_has_unread_messages); void messageCountsChanged(int unread_messages, bool any_feed_has_unread_messages);
// Emitted if any item requested that any view should expand it. // Emitted if any item requested that any view should expand it.
void itemExpandRequested(QList<RootItem*> items, bool expand); void itemExpandRequested(QList<RootItem*> items, bool expand);
// Emitted if any item requested that its expand states should be explicitly saved. // Emitted if any item requested that its expand states should be explicitly saved.
// NOTE: Normally expand states are saved when application quits. // NOTE: Normally expand states are saved when application quits.
void itemExpandStateSaveRequested(RootItem *subtree_root); void itemExpandStateSaveRequested(RootItem* subtree_root);
// Emitted when there is a need of reloading of displayed messages. // Emitted when there is a need of reloading of displayed messages.
void reloadMessageListRequested(bool mark_selected_messages_read); void reloadMessageListRequested(bool mark_selected_messages_read);
// There was some drag/drop operation, notify view about this. // There was some drag/drop operation, notify view about this.
// NOTE: View will probably expand dropped index. // NOTE: View will probably expand dropped index.
void requireItemValidationAfterDragDrop(const QModelIndex &source_index); void requireItemValidationAfterDragDrop(const QModelIndex& source_index);
private: private:
RootItem *m_rootItem; RootItem* m_rootItem;
QList<QString> m_headerData; QList<QString> m_headerData;
QList<QString> m_tooltipData; QList<QString> m_tooltipData;
QIcon m_countsIcon; QIcon m_countsIcon;
}; };
#endif // FEEDSMODEL_H #endif // FEEDSMODEL_H

View File

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

View File

@ -25,46 +25,46 @@ class FeedsModel;
class RootItem; class RootItem;
class FeedsProxyModel : public QSortFilterProxyModel { class FeedsProxyModel : public QSortFilterProxyModel {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedsProxyModel(FeedsModel *source_model, QObject *parent = 0); explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = 0);
virtual ~FeedsProxyModel(); virtual ~FeedsProxyModel();
// Returns index list of items which "match" given value. // Returns index list of items which "match" given value.
// Used for finding items according to entered title text. // Used for finding items according to entered title text.
QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const; QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const;
// Maps list of indexes. // Maps list of indexes.
QModelIndexList mapListToSource(const QModelIndexList &indexes) const; QModelIndexList mapListToSource(const QModelIndexList& indexes) const;
bool showUnreadOnly() const; bool showUnreadOnly() const;
void setShowUnreadOnly(bool show_unread_only); void setShowUnreadOnly(bool show_unread_only);
const RootItem *selectedItem() const; const RootItem* selectedItem() const;
void setSelectedItem(const RootItem *selected_item); void setSelectedItem(const RootItem* selected_item);
public slots: public slots:
void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false); void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false);
private slots: private slots:
void invalidateFilter(); void invalidateFilter();
signals: signals:
void expandAfterFilterIn(QModelIndex idx) const; void expandAfterFilterIn(QModelIndex idx) const;
private: private:
// Compares two rows of data. // Compares two rows of data.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const; bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const; bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
bool filterAcceptsRowInternal(int source_row, const QModelIndex &source_parent) const; bool filterAcceptsRowInternal(int source_row, const QModelIndex& source_parent) const;
// Source model pointer. // Source model pointer.
FeedsModel *m_sourceModel; FeedsModel* m_sourceModel;
const RootItem *m_selectedItem; const RootItem* m_selectedItem;
bool m_showUnreadOnly; bool m_showUnreadOnly;
QList<QPair<int,QModelIndex> > m_hiddenIndices; QList<QPair<int, QModelIndex>> m_hiddenIndices;
}; };
#endif // FEEDSPROXYMODEL_H #endif // FEEDSPROXYMODEL_H

View File

@ -22,91 +22,91 @@
#include <QVariant> #include <QVariant>
Enclosure::Enclosure(const QString &url, const QString &mime) : m_url(url), m_mimeType(mime) { Enclosure::Enclosure(const QString& url, const QString& mime) : m_url(url), m_mimeType(mime) {
} }
QList<Enclosure> Enclosures::decodeEnclosuresFromString(const QString &enclosures_data) { QList<Enclosure> Enclosures::decodeEnclosuresFromString(const QString& enclosures_data) {
QList<Enclosure> enclosures; QList<Enclosure> enclosures;
foreach (const QString &single_enclosure, enclosures_data.split(ENCLOSURES_OUTER_SEPARATOR, QString::SkipEmptyParts)) { foreach (const QString& single_enclosure, enclosures_data.split(ENCLOSURES_OUTER_SEPARATOR, QString::SkipEmptyParts)) {
Enclosure enclosure; Enclosure enclosure;
if (single_enclosure.contains(ECNLOSURES_INNER_SEPARATOR)) { if (single_enclosure.contains(ECNLOSURES_INNER_SEPARATOR)) {
QStringList mime_url = single_enclosure.split(ECNLOSURES_INNER_SEPARATOR); QStringList mime_url = single_enclosure.split(ECNLOSURES_INNER_SEPARATOR);
enclosure.m_mimeType = QByteArray::fromBase64(mime_url.at(0).toLocal8Bit());
enclosure.m_url = QByteArray::fromBase64(mime_url.at(1).toLocal8Bit());
}
enclosure.m_mimeType = QByteArray::fromBase64(mime_url.at(0).toLocal8Bit()); else {
enclosure.m_url = QByteArray::fromBase64(mime_url.at(1).toLocal8Bit()); enclosure.m_url = QByteArray::fromBase64(single_enclosure.toLocal8Bit());
} }
else {
enclosure.m_url = QByteArray::fromBase64(single_enclosure.toLocal8Bit());
}
enclosures.append(enclosure); enclosures.append(enclosure);
} }
return enclosures; return enclosures;
} }
QString Enclosures::encodeEnclosuresToString(const QList<Enclosure> &enclosures) { QString Enclosures::encodeEnclosuresToString(const QList<Enclosure>& enclosures) {
QStringList enclosures_str; QStringList enclosures_str;
foreach (const Enclosure &enclosure, enclosures) { foreach (const Enclosure& enclosure, enclosures) {
if (enclosure.m_mimeType.isEmpty()) { if (enclosure.m_mimeType.isEmpty()) {
enclosures_str.append(enclosure.m_url.toLocal8Bit().toBase64()); enclosures_str.append(enclosure.m_url.toLocal8Bit().toBase64());
} }
else {
enclosures_str.append(QString(enclosure.m_mimeType.toLocal8Bit().toBase64()) +
ECNLOSURES_INNER_SEPARATOR +
enclosure.m_url.toLocal8Bit().toBase64());
}
}
return enclosures_str.join(QString(ENCLOSURES_OUTER_SEPARATOR)); 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));
} }
Message::Message() { Message::Message() {
m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = QSL(""); m_title = m_url = m_author = m_contents = m_feedId = m_customId = m_customHash = QSL("");
m_enclosures = QList<Enclosure>(); m_enclosures = QList<Enclosure>();
m_accountId = m_id = 0; m_accountId = m_id = 0;
m_isRead = m_isImportant = false; m_isRead = m_isImportant = false;
} }
Message Message::fromSqlRecord(const QSqlRecord &record, bool *result) { Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) {
if (record.count() != MSG_DB_CUSTOM_HASH_INDEX + 1) { if (record.count() != MSG_DB_CUSTOM_HASH_INDEX + 1) {
if (result != nullptr) { if (result != nullptr) {
*result = false; *result = false;
return Message(); return Message();
} }
} }
Message 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.m_id = record.value(MSG_DB_ID_INDEX).toInt(); if (result != nullptr) {
message.m_isRead = record.value(MSG_DB_READ_INDEX).toBool(); *result = true;
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) { return message;
*result = true;
}
return message;
} }
uint qHash(Message key, uint seed) { uint qHash(Message key, uint seed) {
Q_UNUSED(seed) Q_UNUSED(seed)
return (key.m_accountId * 10000) + key.m_id; return (key.m_accountId * 10000) + key.m_id;
} }
uint qHash(const Message &key) { uint qHash(const Message& key) {
return (key.m_accountId * 10000) + key.m_id; return (key.m_accountId * 10000) + key.m_id;
} }

View File

@ -27,59 +27,59 @@
// Represents single enclosure. // Represents single enclosure.
struct Enclosure { struct Enclosure {
public: public:
explicit Enclosure(const QString &url = QString(), const QString &mime = QString()); explicit Enclosure(const QString& url = QString(), const QString& mime = QString());
QString m_url; QString m_url;
QString m_mimeType; QString m_mimeType;
}; };
// Represents single enclosure. // Represents single enclosure.
class Enclosures { class Enclosures {
public: public:
static QList<Enclosure> decodeEnclosuresFromString(const QString &enclosures_data); static QList<Enclosure> decodeEnclosuresFromString(const QString& enclosures_data);
static QString encodeEnclosuresToString(const QList<Enclosure> &enclosures); static QString encodeEnclosuresToString(const QList<Enclosure>& enclosures);
}; };
// Represents single message. // Represents single message.
class Message { class Message {
public: public:
explicit Message(); explicit Message();
// Creates Message from given record, which contains // Creates Message from given record, which contains
// row from query SELECT * FROM Messages WHERE ....; // row from query SELECT * FROM Messages WHERE ....;
static Message fromSqlRecord(const QSqlRecord &record, bool *result = nullptr); static Message fromSqlRecord(const QSqlRecord& record, bool* result = nullptr);
QString m_title; QString m_title;
QString m_url; QString m_url;
QString m_author; QString m_author;
QString m_contents; QString m_contents;
QDateTime m_created; QDateTime m_created;
QString m_feedId; QString m_feedId;
int m_accountId; int m_accountId;
int m_id; int m_id;
QString m_customId; QString m_customId;
QString m_customHash; QString m_customHash;
bool m_isRead; bool m_isRead;
bool m_isImportant; bool m_isImportant;
QList<Enclosure> m_enclosures; QList<Enclosure> m_enclosures;
// Is true if "created" date was obtained directly // Is true if "created" date was obtained directly
// from the feed, otherwise is false // from the feed, otherwise is false
bool m_createdFromFeed; bool m_createdFromFeed;
friend inline bool operator==(const Message &lhs, const Message &rhs) { friend inline bool operator==(const Message& lhs, const Message& rhs) {
return lhs.m_accountId == rhs.m_accountId && lhs.m_id == rhs.m_id; return lhs.m_accountId == rhs.m_accountId && lhs.m_id == rhs.m_id;
} }
friend inline bool operator!=(const Message &lhs, const Message &rhs) { friend inline bool operator!=(const Message& lhs, const Message& rhs) {
return !(lhs == rhs); return !(lhs == rhs);
} }
}; };
uint qHash(Message key, uint seed); uint qHash(Message key, uint seed);
uint qHash(const Message &key); uint qHash(const Message& key);
#endif // MESSAGE_H #endif // MESSAGE_H

View File

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

View File

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

View File

@ -20,20 +20,20 @@
#include "miscellaneous/textfactory.h" #include "miscellaneous/textfactory.h"
MessagesModelCache::MessagesModelCache(QObject *parent) : QObject(parent), m_msgCache(QHash<int,QSqlRecord>()) { MessagesModelCache::MessagesModelCache(QObject* parent) : QObject(parent), m_msgCache(QHash<int, QSqlRecord>()) {
} }
MessagesModelCache::~MessagesModelCache() { MessagesModelCache::~MessagesModelCache() {
} }
void MessagesModelCache::setData(const QModelIndex &index, const QVariant &value, const QSqlRecord &record) { void MessagesModelCache::setData(const QModelIndex& index, const QVariant& value, const QSqlRecord& record) {
if (!m_msgCache.contains(index.row())) { if (!m_msgCache.contains(index.row())) {
m_msgCache[index.row()] = record; m_msgCache[index.row()] = record;
} }
m_msgCache[index.row()].setValue(index.column(), value); m_msgCache[index.row()].setValue(index.column(), value);
} }
QVariant MessagesModelCache::data(const QModelIndex &idx) { QVariant MessagesModelCache::data(const QModelIndex& idx) {
return m_msgCache[idx.row()].value(idx.column()); return m_msgCache[idx.row()].value(idx.column());
} }

View File

@ -27,29 +27,29 @@
class MessagesModelCache : public QObject { class MessagesModelCache : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit MessagesModelCache(QObject *parent = nullptr); explicit MessagesModelCache(QObject* parent = nullptr);
virtual ~MessagesModelCache(); virtual ~MessagesModelCache();
inline bool containsData(int row_idx) const { inline bool containsData(int row_idx) const {
return m_msgCache.contains(row_idx); return m_msgCache.contains(row_idx);
} }
inline QSqlRecord record(int row_idx) const { inline QSqlRecord record(int row_idx) const {
return m_msgCache.value(row_idx); return m_msgCache.value(row_idx);
} }
inline void clear() { inline void clear() {
m_msgCache.clear(); m_msgCache.clear();
} }
void setData(const QModelIndex &index, const QVariant &value, const QSqlRecord &record); void setData(const QModelIndex& index, const QVariant& value, const QSqlRecord& record);
QVariant data(const QModelIndex &idx); QVariant data(const QModelIndex& idx);
private: private:
QHash<int,QSqlRecord> m_msgCache; QHash<int, QSqlRecord> m_msgCache;
}; };
#endif // MESSAGESMODELCACHE_H #endif // MESSAGESMODELCACHE_H

View File

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

View File

@ -26,31 +26,31 @@
class MessagesModelSqlLayer { class MessagesModelSqlLayer {
public: public:
explicit MessagesModelSqlLayer(); explicit MessagesModelSqlLayer();
// Adds this new state to queue of sort states. // Adds this new state to queue of sort states.
void addSortState(int column, Qt::SortOrder order); void addSortState(int column, Qt::SortOrder order);
// Sets SQL WHERE clause, without "WHERE" keyword. // Sets SQL WHERE clause, without "WHERE" keyword.
void setFilter(const QString &filter); void setFilter(const QString& filter);
protected: protected:
QString orderByClause() const; QString orderByClause() const;
QString selectStatement() const; QString selectStatement() const;
QString formatFields() const; QString formatFields() const;
QSqlDatabase m_db; QSqlDatabase m_db;
private: private:
QString m_filter; QString m_filter;
// NOTE: These two lists contain data for multicolumn sorting. // NOTE: These two lists contain data for multicolumn sorting.
// They are always same length. Most important sort column/order // They are always same length. Most important sort column/order
// are located at the start of lists; // are located at the start of lists;
QMap<int,QString> m_fieldNames; QMap<int, QString> m_fieldNames;
QList<int> m_sortColumns; QList<int> m_sortColumns;
QList<Qt::SortOrder> m_sortOrders; QList<Qt::SortOrder> m_sortOrders;
}; };
#endif // MESSAGESMODELSQLLAYER_H #endif // MESSAGESMODELSQLLAYER_H

View File

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

View File

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

View File

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

View File

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

View File

@ -26,93 +26,85 @@
#include <QLabel> #include <QLabel>
DynamicShortcutsWidget::DynamicShortcutsWidget(QWidget *parent) : QWidget(parent) { DynamicShortcutsWidget::DynamicShortcutsWidget(QWidget* parent) : QWidget(parent) {
// Create layout for this control and set is as active. // Create layout for this control and set is as active.
m_layout = new QGridLayout(this); m_layout = new QGridLayout(this);
m_layout->setMargin(0); m_layout->setMargin(0);
setLayout(m_layout);
setLayout(m_layout);
} }
DynamicShortcutsWidget::~DynamicShortcutsWidget() { DynamicShortcutsWidget::~DynamicShortcutsWidget() {
delete m_layout; delete m_layout;
} }
bool DynamicShortcutsWidget::areShortcutsUnique() const { bool DynamicShortcutsWidget::areShortcutsUnique() const {
QList<QKeySequence> all_shortcuts; QList<QKeySequence> all_shortcuts;
// Obtain all shortcuts. // Obtain all shortcuts.
foreach (const ActionBinding &binding, m_actionBindings) { foreach (const ActionBinding& binding, m_actionBindings) {
const QKeySequence new_shortcut = binding.second->shortcut(); const QKeySequence new_shortcut = binding.second->shortcut();
if (!new_shortcut.isEmpty() && all_shortcuts.contains(new_shortcut)) { if (!new_shortcut.isEmpty() && all_shortcuts.contains(new_shortcut)) {
// Problem, two identical non-empty shortcuts found. // Problem, two identical non-empty shortcuts found.
return false; return false;
} }
else {
all_shortcuts.append(binding.second->shortcut());
}
}
return true; else {
all_shortcuts.append(binding.second->shortcut());
}
}
return true;
} }
void DynamicShortcutsWidget::updateShortcuts() { void DynamicShortcutsWidget::updateShortcuts() {
foreach (const ActionBinding &binding, m_actionBindings) { foreach (const ActionBinding& binding, m_actionBindings) {
binding.first->setShortcut(binding.second->shortcut()); binding.first->setShortcut(binding.second->shortcut());
} }
} }
void DynamicShortcutsWidget::populate(QList<QAction*> actions) { void DynamicShortcutsWidget::populate(QList<QAction*> actions) {
m_actionBindings.clear(); m_actionBindings.clear();
qSort(actions.begin(), actions.end(), DynamicShortcutsWidget::lessThan); qSort(actions.begin(), actions.end(), DynamicShortcutsWidget::lessThan);
int row_id = 0;
int row_id = 0; // FIXME: Maybe separate actions into "categories". Each category will start with label.
// I will assign each QAaction a property called "category" with some enum value.
// Like:
// File, FeedsCategories, Messages, Tools, WebBrowser, Help
// This will be setup in FormMain::allActions().
// Then here I will process actions into categories.
// FIXME: Maybe separate actions into "categories". Each category will start with label. foreach (QAction* action, actions) {
// I will assign each QAaction a property called "category" with some enum value. // Create shortcut catcher for this action and set default shortcut.
// Like: ShortcutCatcher* catcher = new ShortcutCatcher(this);
// File, FeedsCategories, Messages, Tools, WebBrowser, Help catcher->setDefaultShortcut(action->shortcut());
// This will be setup in FormMain::allActions(). // Store information for re-initialization of shortcuts
// Then here I will process actions into categories. // of actions when widget gets "confirmed".
QPair<QAction*, ShortcutCatcher*> new_binding;
new_binding.first = action;
new_binding.second = catcher;
m_actionBindings << new_binding;
// Add new catcher to our control.
QLabel* action_label = new QLabel(this);
action_label->setText(action->text().remove(QSL("&")));
action_label->setToolTip(action->toolTip());
action_label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
QLabel* action_icon = new QLabel(this);
action_icon->setPixmap(action->icon().pixmap(ICON_SIZE_SETTINGS, ICON_SIZE_SETTINGS));
action_icon->setToolTip(action->toolTip());
m_layout->addWidget(action_icon, row_id, 0);
m_layout->addWidget(action_label, row_id, 1);
m_layout->addWidget(catcher, row_id, 2);
row_id++;
connect(catcher, &ShortcutCatcher::shortcutChanged, this, &DynamicShortcutsWidget::setupChanged);
}
foreach (QAction *action, actions) { // Make sure that "spacer" is added.
// Create shortcut catcher for this action and set default shortcut. m_layout->setRowStretch(row_id, 1);
ShortcutCatcher *catcher = new ShortcutCatcher(this); m_layout->setColumnStretch(1, 1);
catcher->setDefaultShortcut(action->shortcut());
// Store information for re-initialization of shortcuts
// of actions when widget gets "confirmed".
QPair<QAction*,ShortcutCatcher*> new_binding;
new_binding.first = action;
new_binding.second = catcher;
m_actionBindings << new_binding;
// Add new catcher to our control.
QLabel *action_label = new QLabel(this);
action_label->setText(action->text().remove(QSL("&")));
action_label->setToolTip(action->toolTip());
action_label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
QLabel *action_icon = new QLabel(this);
action_icon->setPixmap(action->icon().pixmap(ICON_SIZE_SETTINGS, ICON_SIZE_SETTINGS));
action_icon->setToolTip(action->toolTip());
m_layout->addWidget(action_icon, row_id, 0);
m_layout->addWidget(action_label, row_id, 1);
m_layout->addWidget(catcher, row_id, 2);
row_id++;
connect(catcher, &ShortcutCatcher::shortcutChanged, this, &DynamicShortcutsWidget::setupChanged);
}
// Make sure that "spacer" is added.
m_layout->setRowStretch(row_id, 1);
m_layout->setColumnStretch(1, 1);
} }
bool DynamicShortcutsWidget::lessThan(QAction *lhs, QAction *rhs) { bool DynamicShortcutsWidget::lessThan(QAction* lhs, QAction* rhs) {
return QString::localeAwareCompare(lhs->text().replace(QL1S("&"), QString()), rhs->text().replace(QL1S("&"), QString())) < 0; return QString::localeAwareCompare(lhs->text().replace(QL1S("&"), QString()), rhs->text().replace(QL1S("&"), QString())) < 0;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -18,12 +18,12 @@
#include "exceptions/applicationexception.h" #include "exceptions/applicationexception.h"
ApplicationException::ApplicationException(const QString &message) : m_message(message) { ApplicationException::ApplicationException(const QString& message) : m_message(message) {
} }
ApplicationException::~ApplicationException() { ApplicationException::~ApplicationException() {
} }
QString ApplicationException::message() const { QString ApplicationException::message() const {
return m_message; return m_message;
} }

View File

@ -22,14 +22,14 @@
class ApplicationException { class ApplicationException {
public: public:
explicit ApplicationException(const QString &message = QString()); explicit ApplicationException(const QString& message = QString());
virtual ~ApplicationException(); virtual ~ApplicationException();
QString message() const; QString message() const;
private: private:
QString m_message; QString m_message;
}; };
#endif // APPLICATIONEXCEPTION_H #endif // APPLICATIONEXCEPTION_H

View File

@ -18,7 +18,7 @@
#include "exceptions/ioexception.h" #include "exceptions/ioexception.h"
IOException::IOException(const QString &message) : ApplicationException(message) { IOException::IOException(const QString& message) : ApplicationException(message) {
} }
IOException::~IOException() { IOException::~IOException() {

View File

@ -22,9 +22,9 @@
class IOException : public ApplicationException { class IOException : public ApplicationException {
public: public:
explicit IOException(const QString &message = QString()); explicit IOException(const QString& message = QString());
virtual ~IOException(); virtual ~IOException();
}; };
#endif // IOEXCEPTION_H #endif // IOEXCEPTION_H

View File

@ -20,22 +20,22 @@
#include <QKeyEvent> #include <QKeyEvent>
BaseLineEdit::BaseLineEdit(QWidget *parent) : QLineEdit(parent) { BaseLineEdit::BaseLineEdit(QWidget* parent) : QLineEdit(parent) {
} }
BaseLineEdit::~BaseLineEdit() { BaseLineEdit::~BaseLineEdit() {
} }
void BaseLineEdit::submit(const QString &text) { void BaseLineEdit::submit(const QString& text) {
setText(text); setText(text);
emit submitted(text); emit submitted(text);
} }
void BaseLineEdit::keyPressEvent(QKeyEvent *event) { void BaseLineEdit::keyPressEvent(QKeyEvent* event) {
if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
emit submitted(text()); emit submitted(text());
event->accept(); event->accept();
} }
QLineEdit::keyPressEvent(event); QLineEdit::keyPressEvent(event);
} }

View File

@ -22,22 +22,22 @@
class BaseLineEdit : public QLineEdit { class BaseLineEdit : public QLineEdit {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit BaseLineEdit(QWidget *parent = 0); explicit BaseLineEdit(QWidget* parent = 0);
virtual ~BaseLineEdit(); virtual ~BaseLineEdit();
public slots: public slots:
void submit(const QString &text); void submit(const QString& text);
protected: protected:
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent* event);
signals: signals:
// Emitted if user hits ENTER button. // Emitted if user hits ENTER button.
void submitted(const QString &text); void submitted(const QString& text);
}; };
#endif // BASELINEEDIT_H #endif // BASELINEEDIT_H

View File

@ -24,27 +24,27 @@
#include <QWidgetAction> #include <QWidgetAction>
BaseToolBar::BaseToolBar(const QString &title, QWidget *parent) : QToolBar(title, parent) { BaseToolBar::BaseToolBar(const QString& title, QWidget* parent) : QToolBar(title, parent) {
// Update right margin of filter textbox. // Update right margin of filter textbox.
QMargins margins = contentsMargins(); QMargins margins = contentsMargins();
margins.setRight(margins.right() + FILTER_RIGHT_MARGIN); margins.setRight(margins.right() + FILTER_RIGHT_MARGIN);
setContentsMargins(margins); setContentsMargins(margins);
} }
BaseToolBar::~BaseToolBar() { BaseToolBar::~BaseToolBar() {
qDebug("Destroying BaseToolBar instance."); qDebug("Destroying BaseToolBar instance.");
} }
void BaseBar::loadSavedActions() { void BaseBar::loadSavedActions() {
loadSpecificActions(getSpecificActions(savedActions())); loadSpecificActions(getSpecificActions(savedActions()));
} }
QAction *BaseBar::findMatchingAction(const QString &action, const QList<QAction*> &actions) const { QAction* BaseBar::findMatchingAction(const QString& action, const QList<QAction*>& actions) const {
foreach (QAction *act, actions) { foreach (QAction* act, actions) {
if (act->objectName() == action) { if (act->objectName() == action) {
return act; return act;
} }
} }
return nullptr; return nullptr;
} }

View File

@ -22,39 +22,39 @@
class BaseBar { class BaseBar {
public: public:
// Returns all actions which can be added to the toolbar. // Returns all actions which can be added to the toolbar.
virtual QList<QAction*> availableActions() const = 0; virtual QList<QAction*> availableActions() const = 0;
// Returns all changeable actions which are currently included // Returns all changeable actions which are currently included
// in the toolbar. // in the toolbar.
virtual QList<QAction*> changeableActions() const = 0; virtual QList<QAction*> changeableActions() const = 0;
// Sets new "actions" to the toolbar and perhaps saves the toolbar // Sets new "actions" to the toolbar and perhaps saves the toolbar
// state into the settings. // state into the settings.
virtual void saveChangeableActions(const QStringList &actions) = 0; virtual void saveChangeableActions(const QStringList& actions) = 0;
// Returns list of default actions. // Returns list of default actions.
virtual QStringList defaultActions() const = 0; virtual QStringList defaultActions() const = 0;
virtual QStringList savedActions() const = 0; virtual QStringList savedActions() const = 0;
// Loads the toolbar state from settings. // Loads the toolbar state from settings.
virtual void loadSavedActions(); virtual void loadSavedActions();
virtual QList<QAction*> getSpecificActions(const QStringList &actions) = 0; virtual QList<QAction*> getSpecificActions(const QStringList& actions) = 0;
virtual void loadSpecificActions(const QList<QAction*> &actions) = 0; virtual void loadSpecificActions(const QList<QAction*>& actions) = 0;
protected: protected:
QAction *findMatchingAction(const QString &action, const QList<QAction *> &actions) const; QAction* findMatchingAction(const QString& action, const QList<QAction*>& actions) const;
}; };
class BaseToolBar : public QToolBar, public BaseBar { class BaseToolBar : public QToolBar, public BaseBar {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit BaseToolBar(const QString &title, QWidget *parent = 0); explicit BaseToolBar(const QString& title, QWidget* parent = 0);
virtual ~BaseToolBar(); virtual ~BaseToolBar();
}; };
#endif // TOOLBAR_H #endif // TOOLBAR_H

View File

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

View File

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

View File

@ -21,23 +21,22 @@
#include <QPainter> #include <QPainter>
ColorLabel::ColorLabel(QWidget *parent) : QLabel(parent), m_color(QColor()) { ColorLabel::ColorLabel(QWidget* parent) : QLabel(parent), m_color(QColor()) {
setFixedWidth(20); setFixedWidth(20);
} }
ColorLabel::~ColorLabel() { ColorLabel::~ColorLabel() {
} }
QColor ColorLabel::color() const { QColor ColorLabel::color() const {
return m_color; return m_color;
} }
void ColorLabel::setColor(const QColor &color) { void ColorLabel::setColor(const QColor& color) {
m_color = color; m_color = color;
repaint();
repaint();
} }
void ColorLabel::paintEvent(QPaintEvent *event) { void ColorLabel::paintEvent(QPaintEvent* event) {
QPainter(this).fillRect(event->rect(), m_color); QPainter(this).fillRect(event->rect(), m_color);
} }

View File

@ -22,20 +22,20 @@
class ColorLabel : public QLabel { class ColorLabel : public QLabel {
Q_OBJECT Q_OBJECT
public: public:
explicit ColorLabel(QWidget *parent = 0); explicit ColorLabel(QWidget* parent = 0);
virtual ~ColorLabel(); virtual ~ColorLabel();
QColor color() const; QColor color() const;
void setColor(const QColor &color); void setColor(const QColor& color);
protected: protected:
void paintEvent(QPaintEvent *event); void paintEvent(QPaintEvent* event);
private: private:
QColor m_color; QColor m_color;
}; };
#endif // COLORLABEL_H #endif // COLORLABEL_H

View File

@ -22,17 +22,15 @@
#include <QHBoxLayout> #include <QHBoxLayout>
ComboBoxWithStatus::ComboBoxWithStatus(QWidget *parent) ComboBoxWithStatus::ComboBoxWithStatus(QWidget* parent)
: WidgetWithStatus(parent) { : WidgetWithStatus(parent) {
m_wdgInput = new QComboBox(this); m_wdgInput = new QComboBox(this);
// Set correct size for the tool button.
// Set correct size for the tool button. const int txt_input_height = m_wdgInput->sizeHint().height();
const int txt_input_height = m_wdgInput->sizeHint().height(); m_btnStatus->setFixedSize(txt_input_height, txt_input_height);
m_btnStatus->setFixedSize(txt_input_height, txt_input_height); // Compose the layout.
m_layout->addWidget(m_wdgInput);
// Compose the layout. m_layout->addWidget(m_btnStatus);
m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
} }
ComboBoxWithStatus::~ComboBoxWithStatus() { ComboBoxWithStatus::~ComboBoxWithStatus() {

View File

@ -24,16 +24,16 @@
class ComboBoxWithStatus : public WidgetWithStatus { class ComboBoxWithStatus : public WidgetWithStatus {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit ComboBoxWithStatus(QWidget *parent = 0); explicit ComboBoxWithStatus(QWidget* parent = 0);
virtual ~ComboBoxWithStatus(); virtual ~ComboBoxWithStatus();
inline QComboBox *comboBox() const { inline QComboBox* comboBox() const {
return static_cast<QComboBox*>(m_wdgInput); return static_cast<QComboBox*>(m_wdgInput);
} }
}; };
#endif // COMBOBOXWITHSTATUS_H #endif // COMBOBOXWITHSTATUS_H

View File

@ -25,98 +25,98 @@
#include <QTextStream> #include <QTextStream>
FormAbout::FormAbout(QWidget *parent) : QDialog(parent), m_ui(new Ui::FormAbout()) { FormAbout::FormAbout(QWidget* parent) : QDialog(parent), m_ui(new Ui::FormAbout()) {
m_ui->setupUi(this); m_ui->setupUi(this);
// Set flags and attributes.
// Set flags and attributes. setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); setWindowIcon(qApp->icons()->fromTheme(QSL("help-about")));
setWindowIcon(qApp->icons()->fromTheme(QSL("help-about"))); //: About RSS Guard dialog title.
setWindowTitle(tr("About %1").arg(APP_NAME));
//: About RSS Guard dialog title. m_ui->m_lblIcon->setPixmap(QPixmap(APP_ICON_PATH));
setWindowTitle(tr("About %1").arg(APP_NAME)); // Load information from embedded text files.
loadLicenseAndInformation();
m_ui->m_lblIcon->setPixmap(QPixmap(APP_ICON_PATH)); // Load additional paths information.
loadSettingsAndPaths();
// Load information from embedded text files.
loadLicenseAndInformation();
// Load additional paths information.
loadSettingsAndPaths();
} }
FormAbout::~FormAbout() { FormAbout::~FormAbout() {
qDebug("Destroying FormAbout instance."); qDebug("Destroying FormAbout instance.");
} }
void FormAbout::loadSettingsAndPaths() { void FormAbout::loadSettingsAndPaths() {
if (qApp->settings()->type() == SettingsProperties::Portable) { if (qApp->settings()->type() == SettingsProperties::Portable) {
m_ui->m_txtPathsSettingsType->setText(tr("FULLY portable")); m_ui->m_txtPathsSettingsType->setText(tr("FULLY portable"));
} }
else {
m_ui->m_txtPathsSettingsType->setText(tr("NOT portable"));
}
m_ui->m_txtPathsDatabaseRoot->setText(QDir::toNativeSeparators(qApp->getUserDataPath() + else {
QDir::separator() + m_ui->m_txtPathsSettingsType->setText(tr("NOT portable"));
QString(APP_DB_SQLITE_PATH))); }
m_ui->m_txtPathsSettingsFile->setText(QDir::toNativeSeparators(qApp->settings()->fileName()));
m_ui->m_txtPathsSkinsRoot->setText(QDir::toNativeSeparators(qApp->skins()->getUserSkinBaseFolder())); m_ui->m_txtPathsDatabaseRoot->setText(QDir::toNativeSeparators(qApp->getUserDataPath() +
QDir::separator() +
QString(APP_DB_SQLITE_PATH)));
m_ui->m_txtPathsSettingsFile->setText(QDir::toNativeSeparators(qApp->settings()->fileName()));
m_ui->m_txtPathsSkinsRoot->setText(QDir::toNativeSeparators(qApp->skins()->getUserSkinBaseFolder()));
} }
void FormAbout::loadLicenseAndInformation() { void FormAbout::loadLicenseAndInformation() {
QFile file; QFile file;
file.setFileName(APP_INFO_PATH + QL1S("/COPYING_GNU_GPL_HTML"));
file.setFileName(APP_INFO_PATH + QL1S("/COPYING_GNU_GPL_HTML")); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { m_ui->m_txtLicenseGnu->setText(QString::fromUtf8(file.readAll()));
m_ui->m_txtLicenseGnu->setText(QString::fromUtf8(file.readAll())); }
}
else {
m_ui->m_txtLicenseGnu->setText(tr("License not found."));
}
file.close();
file.setFileName(APP_INFO_PATH + QL1S("/COPYING_BSD")); else {
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { m_ui->m_txtLicenseGnu->setText(tr("License not found."));
m_ui->m_txtLicenseBsd->setText(QString::fromUtf8(file.readAll())); }
}
else {
m_ui->m_txtLicenseBsd->setText(tr("License not found."));
}
file.close();
file.setFileName(APP_INFO_PATH + QL1S("/CHANGELOG")); file.close();
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { file.setFileName(APP_INFO_PATH + QL1S("/COPYING_BSD"));
m_ui->m_txtChangelog->setText(QString::fromUtf8(file.readAll()));
}
else {
m_ui->m_txtChangelog->setText(tr("Changelog not found."));
}
file.close();
// Set other informative texts. if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
m_ui->m_lblDesc->setText(tr("<b>%8</b><br>" m_ui->m_txtLicenseBsd->setText(QString::fromUtf8(file.readAll()));
"<b>Version:</b> %1 (built on %2/%3)<br>" }
"<b>Revision:</b> %4<br>"
"<b>Build date:</b> %5<br>"
"<b>Qt:</b> %6 (compiled against %7)<br>").arg(qApp->applicationVersion(),
APP_SYSTEM_NAME,
APP_SYSTEM_VERSION,
APP_REVISION,
TextFactory::parseDateTime(QString("%1 %2").arg(__DATE__,
__TIME__)).toString(Qt::DefaultLocaleShortDate),
qVersion(),
QT_VERSION_STR,
APP_NAME));
m_ui->m_txtInfo->setText(tr("<body>%5 is a (very) tiny feed reader." else {
"<br><br>This software is distributed under the terms of GNU General Public License, version 3." m_ui->m_txtLicenseBsd->setText(tr("License not found."));
"<br><br>Contacts:" }
"<ul><li><a href=\"mailto://%1\">%1</a> ~e-mail</li>"
"<li><a href=\"%2\">%2</a> ~website</li></ul>" file.close();
"You can obtain source code for %5 from its website." file.setFileName(APP_INFO_PATH + QL1S("/CHANGELOG"));
"<br><br><br>Copyright (C) 2011-%3 %4</body>").arg(APP_EMAIL,
APP_URL, if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QString::number(QDateTime::currentDateTime().date().year()), m_ui->m_txtChangelog->setText(QString::fromUtf8(file.readAll()));
APP_AUTHOR, }
APP_NAME));
else {
m_ui->m_txtChangelog->setText(tr("Changelog not found."));
}
file.close();
// Set other informative texts.
m_ui->m_lblDesc->setText(tr("<b>%8</b><br>"
"<b>Version:</b> %1 (built on %2/%3)<br>"
"<b>Revision:</b> %4<br>"
"<b>Build date:</b> %5<br>"
"<b>Qt:</b> %6 (compiled against %7)<br>").arg(qApp->applicationVersion(),
APP_SYSTEM_NAME,
APP_SYSTEM_VERSION,
APP_REVISION,
TextFactory::parseDateTime(QString("%1 %2").arg(__DATE__,
__TIME__)).toString(Qt::DefaultLocaleShortDate),
qVersion(),
QT_VERSION_STR,
APP_NAME));
m_ui->m_txtInfo->setText(tr("<body>%5 is a (very) tiny feed reader."
"<br><br>This software is distributed under the terms of GNU General Public License, version 3."
"<br><br>Contacts:"
"<ul><li><a href=\"mailto://%1\">%1</a> ~e-mail</li>"
"<li><a href=\"%2\">%2</a> ~website</li></ul>"
"You can obtain source code for %5 from its website."
"<br><br><br>Copyright (C) 2011-%3 %4</body>").arg(APP_EMAIL,
APP_URL,
QString::number(QDateTime::currentDateTime().date().year()),
APP_AUTHOR,
APP_NAME));
} }

View File

@ -26,18 +26,18 @@
class FormAbout : public QDialog { class FormAbout : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FormAbout(QWidget *parent); explicit FormAbout(QWidget* parent);
virtual ~FormAbout(); virtual ~FormAbout();
private: private:
void loadLicenseAndInformation(); void loadLicenseAndInformation();
void loadSettingsAndPaths(); void loadSettingsAndPaths();
QScopedPointer<Ui::FormAbout> m_ui; QScopedPointer<Ui::FormAbout> m_ui;
}; };
#endif // FORMABOUT_H #endif // FORMABOUT_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,35 +26,35 @@
class FormDatabaseCleanup : public QDialog { class FormDatabaseCleanup : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors. // Constructors.
explicit FormDatabaseCleanup(QWidget *parent = 0); explicit FormDatabaseCleanup(QWidget* parent = 0);
virtual ~FormDatabaseCleanup(); virtual ~FormDatabaseCleanup();
void setCleaner(DatabaseCleaner *cleaner); void setCleaner(DatabaseCleaner* cleaner);
protected: protected:
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent* event);
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent* event);
private slots: private slots:
void updateDaysSuffix(int number); void updateDaysSuffix(int number);
void startPurging(); void startPurging();
void onPurgeStarted(); void onPurgeStarted();
void onPurgeProgress(int progress, const QString &description); void onPurgeProgress(int progress, const QString& description);
void onPurgeFinished(bool finished); void onPurgeFinished(bool finished);
signals: signals:
void purgeRequested(const CleanerOrders &which_data); void purgeRequested(const CleanerOrders& which_data);
private: private:
void loadDatabaseInfo(); void loadDatabaseInfo();
private: private:
QScopedPointer<Ui::FormDatabaseCleanup> m_ui; QScopedPointer<Ui::FormDatabaseCleanup> m_ui;
DatabaseCleaner *m_cleaner; DatabaseCleaner* m_cleaner;
}; };
#endif // FORMDATABASECLEANUP_H #endif // FORMDATABASECLEANUP_H

File diff suppressed because it is too large Load Diff

View File

@ -30,96 +30,96 @@ class AdBlockIcon;
class StatusBar; class StatusBar;
class FormMain : public QMainWindow { class FormMain : public QMainWindow {
Q_OBJECT Q_OBJECT
friend class TabWidget; friend class TabWidget;
friend class MessagesView; friend class MessagesView;
friend class FeedsView; friend class FeedsView;
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FormMain(QWidget *parent = 0, Qt::WindowFlags f = 0); explicit FormMain(QWidget* parent = 0, Qt::WindowFlags f = 0);
virtual ~FormMain(); virtual ~FormMain();
// Returns menu for the tray icon. // Returns menu for the tray icon.
QMenu *trayMenu() const; QMenu* trayMenu() const;
// Returns global tab widget. // Returns global tab widget.
TabWidget *tabWidget() const; TabWidget* tabWidget() const;
// Access to statusbar. // Access to statusbar.
StatusBar *statusBar() const; StatusBar* statusBar() const;
// Returns list of all globally available actions. // Returns list of all globally available actions.
// NOTE: This is used for setting dynamic shortcuts // NOTE: This is used for setting dynamic shortcuts
// for given actions. // for given actions.
QList<QAction*> allActions() const; QList<QAction*> allActions() const;
// Loads/saves visual state of the application. // Loads/saves visual state of the application.
void loadSize(); void loadSize();
void saveSize(); void saveSize();
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
AdBlockIcon *adblockIcon() const { AdBlockIcon* adblockIcon() const {
return m_adblockIcon; return m_adblockIcon;
} }
#endif #endif
public slots: public slots:
// Displays window on top or switches its visibility. // Displays window on top or switches its visibility.
void display(); void display();
// Switches visibility of main window. // Switches visibility of main window.
void switchVisibility(bool force_hide = false); void switchVisibility(bool force_hide = false);
// Turns on/off fullscreen mode // Turns on/off fullscreen mode
void switchFullscreenMode(); void switchFullscreenMode();
private slots: private slots:
void updateAddItemMenu(); void updateAddItemMenu();
void updateRecycleBinMenu(); void updateRecycleBinMenu();
void updateAccountsMenu(); void updateAccountsMenu();
void updateMessageButtonsAvailability(); void updateMessageButtonsAvailability();
void updateFeedButtonsAvailability(); void updateFeedButtonsAvailability();
void onFeedUpdatesStarted(); void onFeedUpdatesStarted();
void onFeedUpdatesProgress(const Feed *feed, int current, int total); void onFeedUpdatesProgress(const Feed* feed, int current, int total);
void onFeedUpdatesFinished(const FeedDownloadResults &results); void onFeedUpdatesFinished(const FeedDownloadResults& results);
// Displays various dialogs. // Displays various dialogs.
void backupDatabaseSettings(); void backupDatabaseSettings();
void restoreDatabaseSettings(); void restoreDatabaseSettings();
void showSettings(); void showSettings();
void showAbout(); void showAbout();
void showUpdates(); void showUpdates();
void showWiki(); void showWiki();
void showAddAccountDialog(); void showAddAccountDialog();
void showDbCleanupAssistant(); void showDbCleanupAssistant();
void reportABug(); void reportABug();
void donate(); void donate();
private: private:
// Event handler reimplementations. // Event handler reimplementations.
void changeEvent(QEvent *event); void changeEvent(QEvent* event);
// Creates all needed menus and sets them up. // Creates all needed menus and sets them up.
void prepareMenus(); void prepareMenus();
// Creates needed connections for this window. // Creates needed connections for this window.
void createConnections(); void createConnections();
// Sets up proper icons for this widget. // Sets up proper icons for this widget.
void setupIcons(); void setupIcons();
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
AdBlockIcon *m_adblockIcon; AdBlockIcon* m_adblockIcon;
QAction *m_adblockIconAction; QAction* m_adblockIconAction;
#endif #endif
QScopedPointer<Ui::FormMain> m_ui; QScopedPointer<Ui::FormMain> m_ui;
QMenu *m_trayMenu; QMenu* m_trayMenu;
StatusBar *m_statusBar; StatusBar* m_statusBar;
}; };
#endif // FORMMAIN_H #endif // FORMMAIN_H

View File

@ -25,115 +25,112 @@
#include "QFileDialog" #include "QFileDialog"
FormRestoreDatabaseSettings::FormRestoreDatabaseSettings(QWidget *parent) FormRestoreDatabaseSettings::FormRestoreDatabaseSettings(QWidget* parent)
: QDialog(parent), m_ui(new Ui::FormRestoreDatabaseSettings), m_shouldRestart(false) { : QDialog(parent), m_ui(new Ui::FormRestoreDatabaseSettings), m_shouldRestart(false) {
m_ui->setupUi(this); m_ui->setupUi(this);
m_btnRestart = m_ui->m_buttonBox->addButton(tr("Restart"), QDialogButtonBox::ActionRole);
m_btnRestart = m_ui->m_buttonBox->addButton(tr("Restart"), QDialogButtonBox::ActionRole); m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet."));
m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet.")); setWindowIcon(qApp->icons()->fromTheme(QSL("document-import")));
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("document-import"))); connect(m_btnRestart, &QPushButton::clicked, this, [ = ]() {
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint); m_shouldRestart = true;
close();
connect(m_btnRestart, &QPushButton::clicked, this, [=]() { });
m_shouldRestart = true; connect(m_ui->m_btnSelectFolder, SIGNAL(clicked()), this, SLOT(selectFolder()));
close(); connect(m_ui->m_groupDatabase, SIGNAL(toggled(bool)), this, SLOT(checkOkButton()));
}); connect(m_ui->m_groupSettings, SIGNAL(toggled(bool)), this, SLOT(checkOkButton()));
connect(m_ui->m_btnSelectFolder, SIGNAL(clicked()), this, SLOT(selectFolder())); connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(performRestoration()));
connect(m_ui->m_groupDatabase, SIGNAL(toggled(bool)), this, SLOT(checkOkButton())); selectFolder(qApp->getDocumentsFolderPath());
connect(m_ui->m_groupSettings, SIGNAL(toggled(bool)), this, SLOT(checkOkButton()));
connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(performRestoration()));
selectFolder(qApp->getDocumentsFolderPath());
} }
FormRestoreDatabaseSettings::~FormRestoreDatabaseSettings() { FormRestoreDatabaseSettings::~FormRestoreDatabaseSettings() {
qDebug("Destroying FormRestoreDatabaseSettings instance."); qDebug("Destroying FormRestoreDatabaseSettings instance.");
} }
void FormRestoreDatabaseSettings::performRestoration() { void FormRestoreDatabaseSettings::performRestoration() {
m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
try { try {
qApp->restoreDatabaseSettings(m_ui->m_groupDatabase->isChecked(), qApp->restoreDatabaseSettings(m_ui->m_groupDatabase->isChecked(),
m_ui->m_groupSettings->isChecked(), m_ui->m_groupSettings->isChecked(),
m_ui->m_listDatabase->currentRow() >= 0 ? m_ui->m_listDatabase->currentRow() >= 0 ?
m_ui->m_listDatabase->currentItem()->data(Qt::UserRole).toString() : m_ui->m_listDatabase->currentItem()->data(Qt::UserRole).toString() :
QString(), QString(),
m_ui->m_listSettings->currentRow() >= 0 ? m_ui->m_listSettings->currentRow() >= 0 ?
m_ui->m_listSettings->currentItem()->data(Qt::UserRole).toString() : m_ui->m_listSettings->currentItem()->data(Qt::UserRole).toString() :
QString()); QString());
m_btnRestart->setEnabled(true); m_btnRestart->setEnabled(true);
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Restoration was initiated. Restart to proceed."), m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Restoration was initiated. Restart to proceed."),
tr("You need to restart application for restoration process to finish.")); tr("You need to restart application for restoration process to finish."));
} }
catch (const ApplicationException &ex) {
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(), catch (const ApplicationException& ex) {
tr("Database and/or settings were not copied to restoration directory successully.")); m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, ex.message(),
} tr("Database and/or settings were not copied to restoration directory successully."));
}
} }
void FormRestoreDatabaseSettings::checkOkButton() { void FormRestoreDatabaseSettings::checkOkButton() {
m_btnRestart->setEnabled(false); m_btnRestart->setEnabled(false);
m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!m_ui->m_lblSelectFolder->label()->text().isEmpty() && m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!m_ui->m_lblSelectFolder->label()->text().isEmpty() &&
((m_ui->m_groupDatabase->isChecked() && ((m_ui->m_groupDatabase->isChecked() &&
m_ui->m_listDatabase->currentRow() >= 0) || m_ui->m_listDatabase->currentRow() >= 0) ||
(m_ui->m_groupSettings->isChecked() && (m_ui->m_groupSettings->isChecked() &&
m_ui->m_listSettings->currentRow() >= 0))); m_ui->m_listSettings->currentRow() >= 0)));
} }
void FormRestoreDatabaseSettings::selectFolderWithGui() { void FormRestoreDatabaseSettings::selectFolderWithGui() {
selectFolder(); selectFolder();
} }
void FormRestoreDatabaseSettings::selectFolder(QString folder) { void FormRestoreDatabaseSettings::selectFolder(QString folder) {
if (folder.isEmpty()) { if (folder.isEmpty()) {
folder = QFileDialog::getExistingDirectory(this, tr("Select source directory"), m_ui->m_lblSelectFolder->label()->text()); folder = QFileDialog::getExistingDirectory(this, tr("Select source directory"), m_ui->m_lblSelectFolder->label()->text());
} }
if (!folder.isEmpty()) { if (!folder.isEmpty()) {
m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(folder), m_ui->m_lblSelectFolder->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(folder),
tr("Good source directory is specified.")); tr("Good source directory is specified."));
} }
else {
return;
}
const QDir selected_folder(folder); else {
const QFileInfoList available_databases = selected_folder.entryInfoList(QStringList() return;
<< 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(); const QDir selected_folder(folder);
m_ui->m_listSettings->clear(); 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();
foreach (const QFileInfo &database_file, available_databases) { foreach (const QFileInfo& database_file, available_databases) {
QListWidgetItem *database_item = new QListWidgetItem(database_file.fileName(), m_ui->m_listDatabase); QListWidgetItem* database_item = new QListWidgetItem(database_file.fileName(), m_ui->m_listDatabase);
database_item->setData(Qt::UserRole, database_file.absoluteFilePath()); database_item->setData(Qt::UserRole, database_file.absoluteFilePath());
database_item->setToolTip(QDir::toNativeSeparators(database_file.absoluteFilePath())); database_item->setToolTip(QDir::toNativeSeparators(database_file.absoluteFilePath()));
} }
foreach (const QFileInfo &settings_file, available_settings) { foreach (const QFileInfo& settings_file, available_settings) {
QListWidgetItem *settings_item = new QListWidgetItem(settings_file.fileName(), m_ui->m_listSettings); QListWidgetItem* settings_item = new QListWidgetItem(settings_file.fileName(), m_ui->m_listSettings);
settings_item->setData(Qt::UserRole, settings_file.absoluteFilePath()); settings_item->setData(Qt::UserRole, settings_file.absoluteFilePath());
settings_item->setToolTip(QDir::toNativeSeparators(settings_file.absoluteFilePath())); settings_item->setToolTip(QDir::toNativeSeparators(settings_file.absoluteFilePath()));
} }
if (!available_databases.isEmpty()) { if (!available_databases.isEmpty()) {
m_ui->m_listDatabase->setCurrentRow(0); m_ui->m_listDatabase->setCurrentRow(0);
} }
if (!available_settings.isEmpty()) { if (!available_settings.isEmpty()) {
m_ui->m_listSettings->setCurrentRow(0); m_ui->m_listSettings->setCurrentRow(0);
} }
m_ui->m_groupDatabase->setChecked(!available_databases.isEmpty()); m_ui->m_groupDatabase->setChecked(!available_databases.isEmpty());
m_ui->m_groupSettings->setChecked(!available_settings.isEmpty()); m_ui->m_groupSettings->setChecked(!available_settings.isEmpty());
} }

View File

@ -24,28 +24,28 @@
class FormRestoreDatabaseSettings : public QDialog { class FormRestoreDatabaseSettings : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FormRestoreDatabaseSettings(QWidget *parent = 0); explicit FormRestoreDatabaseSettings(QWidget* parent = 0);
virtual ~FormRestoreDatabaseSettings(); virtual ~FormRestoreDatabaseSettings();
bool shouldRestart() const { bool shouldRestart() const {
return m_shouldRestart; return m_shouldRestart;
} }
private slots: private slots:
void performRestoration(); void performRestoration();
void checkOkButton(); void checkOkButton();
void selectFolderWithGui(); void selectFolderWithGui();
void selectFolder(QString folder = QString()); void selectFolder(QString folder = QString());
private: private:
QScopedPointer<Ui::FormRestoreDatabaseSettings> m_ui; QScopedPointer<Ui::FormRestoreDatabaseSettings> m_ui;
QPushButton *m_btnRestart; QPushButton* m_btnRestart;
bool m_shouldRestart; bool m_shouldRestart;
}; };
#endif // FORMRESTOREDATABASESETTINGS_H #endif // FORMRESTOREDATABASESETTINGS_H

View File

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

View File

@ -27,26 +27,26 @@ class Settings;
class SettingsPanel; class SettingsPanel;
class FormSettings : public QDialog { class FormSettings : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FormSettings(QWidget *parent = 0); explicit FormSettings(QWidget* parent = 0);
virtual ~FormSettings(); virtual ~FormSettings();
private slots: private slots:
// Saves settings into global configuration. // Saves settings into global configuration.
void saveSettings(); void saveSettings();
void applySettings(); void applySettings();
void cancelSettings(); void cancelSettings();
private: private:
void addSettingsPanel(SettingsPanel *panel); void addSettingsPanel(SettingsPanel* panel);
QList<SettingsPanel*> m_panels; QList<SettingsPanel*> m_panels;
QScopedPointer<Ui::FormSettings> m_ui; QScopedPointer<Ui::FormSettings> m_ui;
QPushButton *m_btnApply; QPushButton* m_btnApply;
Settings *m_settings; Settings* m_settings;
}; };
#endif // FORMSETTINGS_H #endif // FORMSETTINGS_H

View File

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

@ -31,36 +31,36 @@
class Downloader; class Downloader;
class FormUpdate : public QDialog { class FormUpdate : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FormUpdate(QWidget *parent = 0); explicit FormUpdate(QWidget* parent = 0);
virtual ~FormUpdate(); virtual ~FormUpdate();
// Returns true if application can self-update // Returns true if application can self-update
// on current platform. // on current platform.
bool isSelfUpdateSupported() const; bool isSelfUpdateSupported() const;
private slots: private slots:
// Check for updates and interprets the results. // Check for updates and interprets the results.
void checkForUpdates(); void checkForUpdates();
void startUpdate(); void startUpdate();
void updateProgress(qint64 bytes_received, qint64 bytes_total); void updateProgress(qint64 bytes_received, qint64 bytes_total);
void updateCompleted(QNetworkReply::NetworkError status, QByteArray contents); void updateCompleted(QNetworkReply::NetworkError status, QByteArray contents);
void saveUpdateFile(const QByteArray &file_contents); void saveUpdateFile(const QByteArray& file_contents);
private: private:
void loadAvailableFiles(); void loadAvailableFiles();
Downloader *m_downloader; Downloader* m_downloader;
bool m_readyToInstall; bool m_readyToInstall;
QString m_updateFilePath; QString m_updateFilePath;
QScopedPointer<Ui::FormUpdate> m_ui; QScopedPointer<Ui::FormUpdate> m_ui;
UpdateInfo m_updateInfo; UpdateInfo m_updateInfo;
QPushButton *m_btnUpdate; QPushButton* m_btnUpdate;
qint64 m_lastDownloadedBytes; qint64 m_lastDownloadedBytes;
}; };
#endif // FORMUPDATE_H #endif // FORMUPDATE_H

View File

@ -30,64 +30,64 @@
#include <QVariant> #include <QVariant>
DiscoverFeedsButton::DiscoverFeedsButton(QWidget *parent) : QToolButton(parent), m_addresses(QStringList()) { DiscoverFeedsButton::DiscoverFeedsButton(QWidget* parent) : QToolButton(parent), m_addresses(QStringList()) {
setEnabled(false); setEnabled(false);
setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml"))); setIcon(qApp->icons()->fromTheme(QSL("application-rss+xml")));
setPopupMode(QToolButton::InstantPopup); setPopupMode(QToolButton::InstantPopup);
} }
DiscoverFeedsButton::~DiscoverFeedsButton() { DiscoverFeedsButton::~DiscoverFeedsButton() {
} }
void DiscoverFeedsButton::clearFeedAddresses() { void DiscoverFeedsButton::clearFeedAddresses() {
setFeedAddresses(QStringList()); setFeedAddresses(QStringList());
} }
void DiscoverFeedsButton::setFeedAddresses(const QStringList &addresses) { void DiscoverFeedsButton::setFeedAddresses(const QStringList& addresses) {
setEnabled(!addresses.isEmpty()); setEnabled(!addresses.isEmpty());
setToolTip(addresses.isEmpty() ? setToolTip(addresses.isEmpty() ?
tr("This website does not contain any feeds.") : tr("This website does not contain any feeds.") :
tr("Click me to add feeds from this website.\nThis website contains %n feed(s).", 0, addresses.size())); tr("Click me to add feeds from this website.\nThis website contains %n feed(s).", 0, addresses.size()));
if (menu() == nullptr) { if (menu() == nullptr) {
// Initialize the menu. // Initialize the menu.
setMenu(new QMenu(this)); setMenu(new QMenu(this));
connect(menu(), &QMenu::triggered, this, &DiscoverFeedsButton::linkTriggered); connect(menu(), &QMenu::triggered, this, &DiscoverFeedsButton::linkTriggered);
connect(menu(), &QMenu::aboutToShow, this, &DiscoverFeedsButton::fillMenu); connect(menu(), &QMenu::aboutToShow, this, &DiscoverFeedsButton::fillMenu);
} }
menu()->hide(); menu()->hide();
m_addresses = addresses; m_addresses = addresses;
} }
void DiscoverFeedsButton::linkTriggered(QAction *action) { void DiscoverFeedsButton::linkTriggered(QAction* action) {
const QString url = action->property("url").toString(); const QString url = action->property("url").toString();
ServiceRoot *root = static_cast<ServiceRoot*>(action->property("root").value<void*>()); ServiceRoot* root = static_cast<ServiceRoot*>(action->property("root").value<void*>());
if (root->supportsFeedAdding()) { if (root->supportsFeedAdding()) {
root->addNewFeed(url); root->addNewFeed(url);
} }
else {
qApp->showGuiMessage(tr("Not supported"), else {
tr("Given account does not support adding feeds."), qApp->showGuiMessage(tr("Not supported"),
QSystemTrayIcon::Warning, tr("Given account does not support adding feeds."),
qApp->mainFormWidget(), true); QSystemTrayIcon::Warning,
} qApp->mainFormWidget(), true);
}
} }
void DiscoverFeedsButton::fillMenu() { void DiscoverFeedsButton::fillMenu() {
menu()->clear(); menu()->clear();
foreach (const ServiceRoot *root, qApp->feedReader()->feedsModel()->serviceRoots()) { foreach (const ServiceRoot* root, qApp->feedReader()->feedsModel()->serviceRoots()) {
QMenu *root_menu = menu()->addMenu(root->icon(), root->title()); QMenu* root_menu = menu()->addMenu(root->icon(), root->title());
foreach (const QString &url, m_addresses) { foreach (const QString& url, m_addresses) {
if (root->supportsFeedAdding()) { if (root->supportsFeedAdding()) {
QAction *url_action = root_menu->addAction(root->icon(), url); QAction* url_action = root_menu->addAction(root->icon(), url);
url_action->setProperty("url", url);
url_action->setProperty("url", url); url_action->setProperty("root", QVariant::fromValue((void*) root));
url_action->setProperty("root", QVariant::fromValue((void*) root)); }
} }
} }
}
} }

View File

@ -22,24 +22,24 @@
class DiscoverFeedsButton : public QToolButton { class DiscoverFeedsButton : public QToolButton {
Q_OBJECT Q_OBJECT
public: public:
// Constructors. // Constructors.
explicit DiscoverFeedsButton(QWidget *parent = 0); explicit DiscoverFeedsButton(QWidget* parent = 0);
virtual ~DiscoverFeedsButton(); virtual ~DiscoverFeedsButton();
// Feed addresses manipulators. // Feed addresses manipulators.
void clearFeedAddresses(); void clearFeedAddresses();
void setFeedAddresses(const QStringList &addresses); void setFeedAddresses(const QStringList& addresses);
private slots: private slots:
// User chose any of addresses. // User chose any of addresses.
void linkTriggered(QAction *action); void linkTriggered(QAction* action);
void fillMenu(); void fillMenu();
private: private:
QStringList m_addresses; QStringList m_addresses;
}; };
#endif // DISCOVERFEEDSBUTTON_H #endif // DISCOVERFEEDSBUTTON_H

View File

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

View File

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

View File

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

View File

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

View File

@ -24,82 +24,79 @@
#include <QWidgetAction> #include <QWidgetAction>
FeedsToolBar::FeedsToolBar(const QString &title, QWidget *parent) : BaseToolBar(title, parent) { FeedsToolBar::FeedsToolBar(const QString& title, QWidget* parent) : BaseToolBar(title, parent) {
// Update right margin of filter textbox. // Update right margin of filter textbox.
QMargins margins = contentsMargins(); QMargins margins = contentsMargins();
margins.setRight(margins.right() + FILTER_RIGHT_MARGIN); margins.setRight(margins.right() + FILTER_RIGHT_MARGIN);
setContentsMargins(margins); setContentsMargins(margins);
} }
FeedsToolBar::~FeedsToolBar() { FeedsToolBar::~FeedsToolBar() {
} }
QList<QAction*> FeedsToolBar::availableActions() const { QList<QAction*> FeedsToolBar::availableActions() const {
return qApp->userActions(); return qApp->userActions();
} }
QList<QAction*> FeedsToolBar::changeableActions() const { QList<QAction*> FeedsToolBar::changeableActions() const {
return actions(); return actions();
} }
void FeedsToolBar::saveChangeableActions(const QStringList &actions) { void FeedsToolBar::saveChangeableActions(const QStringList& actions) {
qApp->settings()->setValue(GROUP(GUI), GUI::FeedsToolbarActions, actions.join(QSL(","))); qApp->settings()->setValue(GROUP(GUI), GUI::FeedsToolbarActions, actions.join(QSL(",")));
loadSpecificActions(getSpecificActions(actions)); loadSpecificActions(getSpecificActions(actions));
} }
QList<QAction*> FeedsToolBar::getSpecificActions(const QStringList &actions) { QList<QAction*> FeedsToolBar::getSpecificActions(const QStringList& actions) {
QList<QAction*> available_actions = availableActions(); QList<QAction*> available_actions = availableActions();
QList<QAction*> spec_actions; QList<QAction*> spec_actions;
// Iterate action names and add respectable actions into the toolbar. // Iterate action names and add respectable actions into the toolbar.
foreach (const QString &action_name, actions) { foreach (const QString& action_name, actions) {
QAction *matching_action = findMatchingAction(action_name, available_actions); QAction* matching_action = findMatchingAction(action_name, available_actions);
if (matching_action != nullptr) { if (matching_action != nullptr) {
// Add existing standard action. // Add existing standard action.
spec_actions.append(matching_action); spec_actions.append(matching_action);
} }
else if (action_name == SEPARATOR_ACTION_NAME) {
// Add new separator.
QAction *act = new QAction(this);
act->setSeparator(true);
spec_actions.append(act); else if (action_name == SEPARATOR_ACTION_NAME) {
} // Add new separator.
else if (action_name == SPACER_ACTION_NAME) { QAction* act = new QAction(this);
// Add new spacer. act->setSeparator(true);
QWidget *spacer = new QWidget(this); spec_actions.append(act);
spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); }
QWidgetAction *action = new QWidgetAction(this); 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);
}
}
action->setDefaultWidget(spacer); return spec_actions;
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) { void FeedsToolBar::loadSpecificActions(const QList<QAction*>& actions) {
clear(); clear();
foreach (QAction *act, actions) { foreach (QAction* act, actions) {
addAction(act); addAction(act);
} }
} }
QStringList FeedsToolBar::defaultActions() const { QStringList FeedsToolBar::defaultActions() const {
return QString(GUI::FeedsToolbarActionsDef).split(',', return QString(GUI::FeedsToolbarActionsDef).split(',',
QString::SkipEmptyParts); QString::SkipEmptyParts);
} }
QStringList FeedsToolBar::savedActions() const { QStringList FeedsToolBar::savedActions() const {
return qApp->settings()->value(GROUP(GUI), SETTING(GUI::FeedsToolbarActions)).toString().split(',', return qApp->settings()->value(GROUP(GUI), SETTING(GUI::FeedsToolbarActions)).toString().split(',',
QString::SkipEmptyParts); QString::SkipEmptyParts);
} }

View File

@ -22,22 +22,22 @@
class FeedsToolBar : public BaseToolBar { class FeedsToolBar : public BaseToolBar {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedsToolBar(const QString &title, QWidget *parent = 0); explicit FeedsToolBar(const QString& title, QWidget* parent = 0);
virtual ~FeedsToolBar(); virtual ~FeedsToolBar();
QList<QAction*> availableActions() const; QList<QAction*> availableActions() const;
QList<QAction*> changeableActions() const; QList<QAction*> changeableActions() const;
void saveChangeableActions(const QStringList &actions); void saveChangeableActions(const QStringList& actions);
QList<QAction*> getSpecificActions(const QStringList &actions); QList<QAction*> getSpecificActions(const QStringList& actions);
void loadSpecificActions(const QList<QAction*> &actions); void loadSpecificActions(const QList<QAction*>& actions);
QStringList defaultActions() const; QStringList defaultActions() const;
QStringList savedActions() const; QStringList savedActions() const;
}; };
#endif // FEEDSTOOLBAR_H #endif // FEEDSTOOLBAR_H

View File

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

View File

@ -30,117 +30,117 @@ class Feed;
class Category; class Category;
class FeedsView : public QTreeView { class FeedsView : public QTreeView {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit FeedsView(QWidget *parent = 0); explicit FeedsView(QWidget* parent = 0);
virtual ~FeedsView(); virtual ~FeedsView();
// Fundamental accessors. // Fundamental accessors.
inline FeedsProxyModel *model() const { inline FeedsProxyModel* model() const {
return m_proxyModel; return m_proxyModel;
} }
inline FeedsModel *sourceModel() const { inline FeedsModel* sourceModel() const {
return m_sourceModel; return m_sourceModel;
} }
void setSortingEnabled(bool enable); void setSortingEnabled(bool enable);
// Returns list of selected/all feeds. // Returns list of selected/all feeds.
// NOTE: This is recursive method which returns all descendants. // NOTE: This is recursive method which returns all descendants.
QList<Feed*> selectedFeeds() const; QList<Feed*> selectedFeeds() const;
// Returns pointers to selected feed/category if they are really // Returns pointers to selected feed/category if they are really
// selected. // selected.
RootItem *selectedItem() const; RootItem* selectedItem() const;
// Saves/loads expand states of all nodes (feeds/categories) of the list to/from settings. // Saves/loads expand states of all nodes (feeds/categories) of the list to/from settings.
void saveAllExpandStates(); void saveAllExpandStates();
void loadAllExpandStates(); void loadAllExpandStates();
public slots: public slots:
void sortByColumn(int column, Qt::SortOrder order); void sortByColumn(int column, Qt::SortOrder order);
void addFeedIntoSelectedAccount(); void addFeedIntoSelectedAccount();
void addCategoryIntoSelectedAccount(); void addCategoryIntoSelectedAccount();
void expandCollapseCurrentItem(); void expandCollapseCurrentItem();
// Feed updating. // Feed updating.
void updateSelectedItems(); void updateSelectedItems();
// Feed read/unread manipulators. // Feed read/unread manipulators.
void markSelectedItemRead(); void markSelectedItemRead();
void markSelectedItemUnread(); void markSelectedItemUnread();
void markAllItemsRead(); void markAllItemsRead();
// Newspaper accessors. // Newspaper accessors.
void openSelectedItemsInNewspaperMode(); void openSelectedItemsInNewspaperMode();
// Feed clearers. // Feed clearers.
void clearSelectedFeeds(); void clearSelectedFeeds();
void clearAllFeeds(); void clearAllFeeds();
// Base manipulators. // Base manipulators.
void editSelectedItem(); void editSelectedItem();
void deleteSelectedItem(); void deleteSelectedItem();
// Selects next/previous item (feed/category) in the list. // Selects next/previous item (feed/category) in the list.
void selectNextItem(); void selectNextItem();
void selectPreviousItem(); void selectPreviousItem();
// Switches visibility of the widget. // Switches visibility of the widget.
void switchVisibility(); void switchVisibility();
signals: signals:
// Emitted if user selects new feeds. // Emitted if user selects new feeds.
void itemSelected(RootItem *item); void itemSelected(RootItem* item);
// Requests opening of given messages in newspaper mode. // Requests opening of given messages in newspaper mode.
void openMessagesInNewspaperView(RootItem *root, const QList<Message> &messages); void openMessagesInNewspaperView(RootItem* root, const QList<Message>& messages);
protected: protected:
// Handle selections. // Handle selections.
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
// React on "Del" key. // React on "Del" key.
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent* event);
// Show custom context menu. // Show custom context menu.
void contextMenuEvent(QContextMenuEvent *event); void contextMenuEvent(QContextMenuEvent* event);
void mouseDoubleClickEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent* event);
private slots: private slots:
void expandItemDelayed(const QModelIndex &idx); void expandItemDelayed(const QModelIndex& idx);
void markSelectedItemReadStatus(RootItem::ReadStatus read); void markSelectedItemReadStatus(RootItem::ReadStatus read);
void markAllItemsReadStatus(RootItem::ReadStatus read); void markAllItemsReadStatus(RootItem::ReadStatus read);
void saveSortState(int column, Qt::SortOrder order); void saveSortState(int column, Qt::SortOrder order);
void validateItemAfterDragDrop(const QModelIndex &source_index); void validateItemAfterDragDrop(const QModelIndex& source_index);
void onItemExpandRequested(const QList<RootItem*> &items, bool exp); void onItemExpandRequested(const QList<RootItem*>& items, bool exp);
void onItemExpandStateSaveRequested(RootItem *item); void onItemExpandStateSaveRequested(RootItem* item);
private: private:
// Initializes context menus. // Initializes context menus.
QMenu *initializeContextMenuCategories(RootItem *clicked_item); QMenu* initializeContextMenuCategories(RootItem* clicked_item);
QMenu *initializeContextMenuFeeds(RootItem *clicked_item); QMenu* initializeContextMenuFeeds(RootItem* clicked_item);
QMenu *initializeContextMenuEmptySpace(); QMenu* initializeContextMenuEmptySpace();
QMenu *initializeContextMenuOtherItem(RootItem *clicked_item); QMenu* initializeContextMenuOtherItem(RootItem* clicked_item);
// Sets up appearance of this widget. // Sets up appearance of this widget.
void setupAppearance(); void setupAppearance();
void saveExpandStates(RootItem *item); void saveExpandStates(RootItem* item);
QMenu *m_contextMenuCategories; QMenu* m_contextMenuCategories;
QMenu *m_contextMenuFeeds; QMenu* m_contextMenuFeeds;
QMenu *m_contextMenuEmptySpace; QMenu* m_contextMenuEmptySpace;
QMenu *m_contextMenuOtherItems; QMenu* m_contextMenuOtherItems;
FeedsModel *m_sourceModel; FeedsModel* m_sourceModel;
FeedsProxyModel *m_proxyModel; FeedsProxyModel* m_proxyModel;
}; };
#endif // FEEDSVIEW_H #endif // FEEDSVIEW_H

View File

@ -22,15 +22,16 @@
#include <QLabel> #include <QLabel>
void GuiUtilities::setLabelAsNotice(QLabel *label, bool is_warning) { void GuiUtilities::setLabelAsNotice(QLabel* label, bool is_warning) {
label->setMargin(6); label->setMargin(6);
if (is_warning) { if (is_warning) {
label->setStyleSheet(QSL("font-weight: bold; font-style: italic; color: red")); label->setStyleSheet(QSL("font-weight: bold; font-style: italic; color: red"));
} }
else {
label->setStyleSheet(QSL("font-style: italic;")); else {
} label->setStyleSheet(QSL("font-style: italic;"));
}
} }
GuiUtilities::GuiUtilities() { GuiUtilities::GuiUtilities() {

View File

@ -22,11 +22,11 @@
class QLabel; class QLabel;
class GuiUtilities { class GuiUtilities {
public: public:
static void setLabelAsNotice(QLabel *label, bool is_warning); static void setLabelAsNotice(QLabel* label, bool is_warning);
private: private:
explicit GuiUtilities(); explicit GuiUtilities();
}; };
#endif // GUIUTILITIES_H #endif // GUIUTILITIES_H

View File

@ -22,25 +22,23 @@
#include <QHBoxLayout> #include <QHBoxLayout>
LabelWithStatus::LabelWithStatus(QWidget *parent) LabelWithStatus::LabelWithStatus(QWidget* parent)
: WidgetWithStatus(parent) { : WidgetWithStatus(parent) {
m_wdgInput = new QLabel(this); m_wdgInput = new QLabel(this);
// Set correct size for the tool button.
// Set correct size for the tool button. int label_height = m_wdgInput->sizeHint().height();
int label_height = m_wdgInput->sizeHint().height(); m_btnStatus->setFixedSize(label_height, label_height);
m_btnStatus->setFixedSize(label_height, label_height); // Compose the layout.
m_layout->addWidget(m_wdgInput);
// Compose the layout. m_layout->addWidget(m_btnStatus);
m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
} }
LabelWithStatus::~LabelWithStatus() { LabelWithStatus::~LabelWithStatus() {
} }
void LabelWithStatus::setStatus(WidgetWithStatus::StatusType status, void LabelWithStatus::setStatus(WidgetWithStatus::StatusType status,
const QString &label_text, const QString& label_text,
const QString &status_text) { const QString& status_text) {
WidgetWithStatus::setStatus(status, status_text); WidgetWithStatus::setStatus(status, status_text);
label()->setText(label_text); label()->setText(label_text);
} }

View File

@ -24,19 +24,19 @@
class LabelWithStatus : public WidgetWithStatus { class LabelWithStatus : public WidgetWithStatus {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit LabelWithStatus(QWidget *parent = 0); explicit LabelWithStatus(QWidget* parent = 0);
virtual ~LabelWithStatus(); virtual ~LabelWithStatus();
void setStatus(StatusType status, const QString &label_text, const QString &status_text); void setStatus(StatusType status, const QString& label_text, const QString& status_text);
// Access to label. // Access to label.
inline QLabel *label() const { inline QLabel* label() const {
return static_cast<QLabel*>(m_wdgInput); return static_cast<QLabel*>(m_wdgInput);
} }
}; };
#endif // LABELWITHSTATUS_H #endif // LABELWITHSTATUS_H

View File

@ -23,19 +23,16 @@
#include <QHBoxLayout> #include <QHBoxLayout>
LineEditWithStatus::LineEditWithStatus(QWidget *parent) LineEditWithStatus::LineEditWithStatus(QWidget* parent)
: WidgetWithStatus(parent) { : WidgetWithStatus(parent) {
m_wdgInput = new BaseLineEdit(this); m_wdgInput = new BaseLineEdit(this);
setFocusProxy(m_wdgInput);
setFocusProxy(m_wdgInput); // Set correct size for the tool button.
const int txt_input_height = m_wdgInput->sizeHint().height();
// Set correct size for the tool button. m_btnStatus->setFixedSize(txt_input_height, txt_input_height);
const int txt_input_height = m_wdgInput->sizeHint().height(); // Compose the layout.
m_btnStatus->setFixedSize(txt_input_height, txt_input_height); m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
// Compose the layout.
m_layout->addWidget(m_wdgInput);
m_layout->addWidget(m_btnStatus);
} }
LineEditWithStatus::~LineEditWithStatus() { LineEditWithStatus::~LineEditWithStatus() {

View File

@ -24,17 +24,17 @@
class LineEditWithStatus : public WidgetWithStatus { class LineEditWithStatus : public WidgetWithStatus {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit LineEditWithStatus(QWidget *parent = 0); explicit LineEditWithStatus(QWidget* parent = 0);
virtual ~LineEditWithStatus(); virtual ~LineEditWithStatus();
// Access to line edit. // Access to line edit.
inline BaseLineEdit *lineEdit() const { inline BaseLineEdit* lineEdit() const {
return static_cast<BaseLineEdit*>(m_wdgInput); return static_cast<BaseLineEdit*>(m_wdgInput);
} }
}; };
#endif // LINEEDITWITHSTATUS_H #endif // LINEEDITWITHSTATUS_H

View File

@ -22,32 +22,31 @@
#include <QMouseEvent> #include <QMouseEvent>
LocationLineEdit::LocationLineEdit(QWidget *parent) LocationLineEdit::LocationLineEdit(QWidget* parent)
: BaseLineEdit(parent), m_mouseSelectsAllText(true), m_googleSuggest(new GoogleSuggest(this)) { : BaseLineEdit(parent), m_mouseSelectsAllText(true), m_googleSuggest(new GoogleSuggest(this)) {
setPlaceholderText(tr("Website address goes here")); setPlaceholderText(tr("Website address goes here"));
connect(this, &LocationLineEdit::submitted, m_googleSuggest, &GoogleSuggest::preventSuggest); connect(this, &LocationLineEdit::submitted, m_googleSuggest, &GoogleSuggest::preventSuggest);
} }
LocationLineEdit::~LocationLineEdit() { LocationLineEdit::~LocationLineEdit() {
} }
void LocationLineEdit::focusOutEvent(QFocusEvent *event) { void LocationLineEdit::focusOutEvent(QFocusEvent* event) {
BaseLineEdit::focusOutEvent(event); BaseLineEdit::focusOutEvent(event);
// User now left text box, when he enters it again and clicks,
// User now left text box, when he enters it again and clicks, // then all text should be selected.
// then all text should be selected. m_mouseSelectsAllText = true;
m_mouseSelectsAllText = true;
} }
void LocationLineEdit::mousePressEvent(QMouseEvent *event) { void LocationLineEdit::mousePressEvent(QMouseEvent* event) {
if (m_mouseSelectsAllText) { if (m_mouseSelectsAllText) {
event->ignore(); event->ignore();
selectAll(); selectAll();
// User clicked and all text was selected.
m_mouseSelectsAllText = false;
}
// User clicked and all text was selected. else {
m_mouseSelectsAllText = false; BaseLineEdit::mousePressEvent(event);
} }
else {
BaseLineEdit::mousePressEvent(event);
}
} }

View File

@ -25,20 +25,20 @@ class WebBrowser;
class GoogleSuggest; class GoogleSuggest;
class LocationLineEdit : public BaseLineEdit { class LocationLineEdit : public BaseLineEdit {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit LocationLineEdit(QWidget *parent = 0); explicit LocationLineEdit(QWidget* parent = 0);
virtual ~LocationLineEdit(); virtual ~LocationLineEdit();
protected: protected:
void focusOutEvent(QFocusEvent *event); void focusOutEvent(QFocusEvent* event);
void mousePressEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent* event);
private: private:
bool m_mouseSelectsAllText; bool m_mouseSelectsAllText;
GoogleSuggest *m_googleSuggest; GoogleSuggest* m_googleSuggest;
}; };
#endif // LOCATIONLINEEDIT_H #endif // LOCATIONLINEEDIT_H

View File

@ -28,83 +28,80 @@
#include <QCheckBox> #include <QCheckBox>
MessageBox::MessageBox(QWidget *parent) : QMessageBox(parent) { MessageBox::MessageBox(QWidget* parent) : QMessageBox(parent) {
} }
MessageBox::~MessageBox() { MessageBox::~MessageBox() {
} }
void MessageBox::setIcon(QMessageBox::Icon icon) { void MessageBox::setIcon(QMessageBox::Icon icon) {
// Determine correct status icon size. // Determine correct status icon size.
const int icon_size = qApp->style()->pixelMetric(QStyle::PM_MessageBoxIconSize, 0, this); const int icon_size = qApp->style()->pixelMetric(QStyle::PM_MessageBoxIconSize, 0, this);
// Setup status icon.
// Setup status icon. setIconPixmap(iconForStatus(icon).pixmap(icon_size, icon_size));
setIconPixmap(iconForStatus(icon).pixmap(icon_size, icon_size));
} }
void MessageBox::setCheckBox(QMessageBox *msg_box, const QString &text, bool *data) { void MessageBox::setCheckBox(QMessageBox* msg_box, const QString& text, bool* data) {
// Add "don't show this again checkbox. // Add "don't show this again checkbox.
QCheckBox *check_box = new QCheckBox(msg_box); QCheckBox* check_box = new QCheckBox(msg_box);
check_box->setChecked(*data);
check_box->setChecked(*data); check_box->setText(text);
check_box->setText(text); connect(check_box, &QCheckBox::toggled, [ = ](bool checked) {
connect(check_box, &QCheckBox::toggled, [=](bool checked) { *data = checked;
*data = checked; });
}); msg_box->setCheckBox(check_box);
msg_box->setCheckBox(check_box);
} }
QIcon MessageBox::iconForStatus(QMessageBox::Icon status) { QIcon MessageBox::iconForStatus(QMessageBox::Icon status) {
switch (status) { switch (status) {
case QMessageBox::Information: case QMessageBox::Information:
return qApp->icons()->fromTheme(QSL("dialog-information")); return qApp->icons()->fromTheme(QSL("dialog-information"));
case QMessageBox::Warning: case QMessageBox::Warning:
return qApp->icons()->fromTheme(QSL("dialog-warning")); return qApp->icons()->fromTheme(QSL("dialog-warning"));
case QMessageBox::Critical: case QMessageBox::Critical:
return qApp->icons()->fromTheme(QSL("dialog-error")); return qApp->icons()->fromTheme(QSL("dialog-error"));
case QMessageBox::Question: case QMessageBox::Question:
return qApp->icons()->fromTheme(QSL("dialog-question")); return qApp->icons()->fromTheme(QSL("dialog-question"));
case QMessageBox::NoIcon: case QMessageBox::NoIcon:
default: default:
return QIcon(); return QIcon();
} }
} }
QMessageBox::StandardButton MessageBox::show(QWidget *parent, QMessageBox::StandardButton MessageBox::show(QWidget* parent,
QMessageBox::Icon icon, QMessageBox::Icon icon,
const QString &title, const QString& title,
const QString &text, const QString& text,
const QString &informative_text, const QString& informative_text,
const QString &detailed_text, const QString& detailed_text,
QMessageBox::StandardButtons buttons, QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton default_button, QMessageBox::StandardButton default_button,
bool *dont_show_again) { bool* dont_show_again) {
// Create and find needed components. // Create and find needed components.
MessageBox msg_box(parent); MessageBox msg_box(parent);
// Initialize message box properties.
msg_box.setWindowTitle(title);
msg_box.setText(text);
msg_box.setInformativeText(informative_text);
msg_box.setDetailedText(detailed_text);
msg_box.setIcon(icon);
msg_box.setStandardButtons(buttons);
msg_box.setDefaultButton(default_button);
// Initialize message box properties. if (dont_show_again != nullptr) {
msg_box.setWindowTitle(title); MessageBox::setCheckBox(&msg_box, tr("Do not show this dialog again."), dont_show_again);
msg_box.setText(text); }
msg_box.setInformativeText(informative_text);
msg_box.setDetailedText(detailed_text);
msg_box.setIcon(icon);
msg_box.setStandardButtons(buttons);
msg_box.setDefaultButton(default_button);
if (dont_show_again != nullptr) { // Display it.
MessageBox::setCheckBox(&msg_box, tr("Do not show this dialog again."), dont_show_again); if (msg_box.exec() == -1) {
} return QMessageBox::Cancel;
}
// Display it. else {
if (msg_box.exec() == -1) { return msg_box.standardButton(msg_box.clickedButton());
return QMessageBox::Cancel; }
}
else {
return msg_box.standardButton(msg_box.clickedButton());
}
} }

View File

@ -23,30 +23,30 @@
class MessageBox : public QMessageBox { class MessageBox : public QMessageBox {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit MessageBox(QWidget *parent = 0); explicit MessageBox(QWidget* parent = 0);
virtual ~MessageBox(); virtual ~MessageBox();
// Custom icon setting. // Custom icon setting.
void setIcon(Icon icon); void setIcon(Icon icon);
static void setCheckBox(QMessageBox *msg_box, const QString &text, bool *data); static void setCheckBox(QMessageBox* msg_box, const QString& text, bool* data);
// Displays custom message box. // Displays custom message box.
static QMessageBox::StandardButton show(QWidget *parent, static QMessageBox::StandardButton show(QWidget* parent,
QMessageBox::Icon icon, QMessageBox::Icon icon,
const QString &title, const QString& title,
const QString &text, const QString& text,
const QString &informative_text = QString(), const QString& informative_text = QString(),
const QString &detailed_text = QString(), const QString& detailed_text = QString(),
QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton default_button = QMessageBox::Ok, QMessageBox::StandardButton default_button = QMessageBox::Ok,
bool *dont_show_again = nullptr); bool* dont_show_again = nullptr);
static QIcon iconForStatus(QMessageBox::Icon status); static QIcon iconForStatus(QMessageBox::Icon status);
}; };
#endif // MESSAGEBOX_H #endif // MESSAGEBOX_H

View File

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

@ -29,50 +29,50 @@
namespace Ui { namespace Ui {
class MessagePreviewer; class MessagePreviewer;
} }
class QToolBar; class QToolBar;
class MessagePreviewer : public QWidget { class MessagePreviewer : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit MessagePreviewer(QWidget *parent = 0); explicit MessagePreviewer(QWidget* parent = 0);
virtual ~MessagePreviewer(); virtual ~MessagePreviewer();
void reloadFontSettings(); void reloadFontSettings();
public slots: public slots:
void clear(); void clear();
void hideToolbar(); void hideToolbar();
void loadMessage(const Message &message, RootItem *root); void loadMessage(const Message& message, RootItem* root);
private slots: private slots:
void markMessageAsRead(); void markMessageAsRead();
void markMessageAsUnread(); void markMessageAsUnread();
void markMessageAsReadUnread(RootItem::ReadStatus read); void markMessageAsReadUnread(RootItem::ReadStatus read);
void switchMessageImportance(bool checked); void switchMessageImportance(bool checked);
signals: signals:
void markMessageRead(int id, RootItem::ReadStatus read); void markMessageRead(int id, RootItem::ReadStatus read);
void markMessageImportant(int id, RootItem::Importance important); void markMessageImportant(int id, RootItem::Importance important);
void requestMessageListReload(bool mark_current_as_read); void requestMessageListReload(bool mark_current_as_read);
private: private:
void createConnections(); void createConnections();
void updateButtons(); void updateButtons();
QString prepareHtmlForMessage(const Message &message); QString prepareHtmlForMessage(const Message& message);
QToolBar *m_toolBar; QToolBar* m_toolBar;
QScopedPointer<Ui::MessagePreviewer> m_ui; QScopedPointer<Ui::MessagePreviewer> m_ui;
Message m_message; Message m_message;
QStringList m_pictures; QStringList m_pictures;
QPointer<RootItem> m_root; QPointer<RootItem> m_root;
QAction *m_actionMarkRead; QAction* m_actionMarkRead;
QAction *m_actionMarkUnread; QAction* m_actionMarkUnread;
QAction *m_actionSwitchImportance; QAction* m_actionSwitchImportance;
}; };
#endif // MESSAGEPREVIEWER_H #endif // MESSAGEPREVIEWER_H

View File

@ -18,7 +18,7 @@
#include "gui/messagessearchlineedit.h" #include "gui/messagessearchlineedit.h"
MessagesSearchLineEdit::MessagesSearchLineEdit(QWidget *parent) : BaseLineEdit(parent) { MessagesSearchLineEdit::MessagesSearchLineEdit(QWidget* parent) : BaseLineEdit(parent) {
} }
MessagesSearchLineEdit::~MessagesSearchLineEdit() { MessagesSearchLineEdit::~MessagesSearchLineEdit() {

View File

@ -24,12 +24,12 @@
class PlainToolButton; class PlainToolButton;
class MessagesSearchLineEdit : public BaseLineEdit { class MessagesSearchLineEdit : public BaseLineEdit {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit MessagesSearchLineEdit(QWidget *parent = 0); explicit MessagesSearchLineEdit(QWidget* parent = 0);
virtual ~MessagesSearchLineEdit(); virtual ~MessagesSearchLineEdit();
}; };
#endif // MESSAGESEARCHLINEEDIT_H #endif // MESSAGESEARCHLINEEDIT_H

View File

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

View File

@ -29,54 +29,54 @@ class QToolButton;
class QMenu; class QMenu;
class MessagesToolBar : public BaseToolBar { class MessagesToolBar : public BaseToolBar {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit MessagesToolBar(const QString &title, QWidget *parent = 0); explicit MessagesToolBar(const QString& title, QWidget* parent = 0);
virtual ~MessagesToolBar(); virtual ~MessagesToolBar();
// External access to search line edit. // External access to search line edit.
inline MessagesSearchLineEdit *searchLineEdit() { inline MessagesSearchLineEdit* searchLineEdit() {
return m_txtSearchMessages; return m_txtSearchMessages;
} }
// Implementation of BaseToolBar interface. // Implementation of BaseToolBar interface.
QList<QAction*> availableActions() const; QList<QAction*> availableActions() const;
QList<QAction*> changeableActions() const; QList<QAction*> changeableActions() const;
void saveChangeableActions(const QStringList &actions); void saveChangeableActions(const QStringList& actions);
// Loads actions as specified by external actions list. // Loads actions as specified by external actions list.
// NOTE: This is used primarily for reloading actions // NOTE: This is used primarily for reloading actions
// when they are changed from settings. // when they are changed from settings.
void loadSpecificActions(const QList<QAction*> &actions); void loadSpecificActions(const QList<QAction*>& actions);
QList<QAction*> getSpecificActions(const QStringList &actions); QList<QAction*> getSpecificActions(const QStringList& actions);
QStringList defaultActions() const; QStringList defaultActions() const;
QStringList savedActions() const; QStringList savedActions() const;
signals: signals:
void messageSearchPatternChanged(const QString &pattern); void messageSearchPatternChanged(const QString& pattern);
// Emitted if message filter is changed. // Emitted if message filter is changed.
void messageFilterChanged(MessagesModel::MessageHighlighter filter); void messageFilterChanged(MessagesModel::MessageHighlighter filter);
private slots: private slots:
// Called when highlighter gets changed. // Called when highlighter gets changed.
void handleMessageHighlighterChange(QAction *action); void handleMessageHighlighterChange(QAction* action);
private: private:
void initializeSearchBox(); void initializeSearchBox();
void initializeHighlighter(); void initializeHighlighter();
private: private:
QWidgetAction *m_actionMessageHighlighter; QWidgetAction* m_actionMessageHighlighter;
QToolButton *m_btnMessageHighlighter; QToolButton* m_btnMessageHighlighter;
QMenu *m_menuMessageHighlighter; QMenu* m_menuMessageHighlighter;
QWidgetAction *m_actionSearchMessages; QWidgetAction* m_actionSearchMessages;
MessagesSearchLineEdit *m_txtSearchMessages; MessagesSearchLineEdit* m_txtSearchMessages;
}; };
#endif // NEWSTOOLBAR_H #endif // NEWSTOOLBAR_H

View File

@ -34,513 +34,499 @@
#include <QMenu> #include <QMenu>
MessagesView::MessagesView(QWidget *parent) MessagesView::MessagesView(QWidget* parent)
: QTreeView(parent), m_contextMenu(nullptr), m_columnsAdjusted(false) { : QTreeView(parent), m_contextMenu(nullptr), m_columnsAdjusted(false) {
m_sourceModel = qApp->feedReader()->messagesModel(); m_sourceModel = qApp->feedReader()->messagesModel();
m_proxyModel = qApp->feedReader()->messagesProxyModel(); m_proxyModel = qApp->feedReader()->messagesProxyModel();
// Forward count changes to the view.
// Forward count changes to the view. createConnections();
createConnections(); setModel(m_proxyModel);
setModel(m_proxyModel); setupAppearance();
setupAppearance(); header()->setContextMenuPolicy(Qt::CustomContextMenu);
connect(header(), &QHeaderView::customContextMenuRequested, [ = ](const QPoint & point) {
header()->setContextMenuPolicy(Qt::CustomContextMenu); TreeViewColumnsMenu mm(header());
connect(header(), &QHeaderView::customContextMenuRequested, [=](const QPoint &point) { mm.exec(header()->mapToGlobal(point));
TreeViewColumnsMenu mm(header()); });
mm.exec(header()->mapToGlobal(point));
});
} }
MessagesView::~MessagesView() { MessagesView::~MessagesView() {
qDebug("Destroying MessagesView instance."); qDebug("Destroying MessagesView instance.");
} }
void MessagesView::sort(int column, Qt::SortOrder order, bool repopulate_data, bool change_header, bool emit_changed_from_header) { void MessagesView::sort(int column, Qt::SortOrder order, bool repopulate_data, bool change_header, bool emit_changed_from_header) {
if (change_header && !emit_changed_from_header) { if (change_header && !emit_changed_from_header) {
header()->blockSignals(true); header()->blockSignals(true);
} }
m_sourceModel->addSortState(column, order); m_sourceModel->addSortState(column, order);
if (repopulate_data) { if (repopulate_data) {
m_sourceModel->repopulate(); m_sourceModel->repopulate();
} }
if (change_header) { if (change_header) {
header()->setSortIndicator(column, order); header()->setSortIndicator(column, order);
header()->blockSignals(false); header()->blockSignals(false);
} }
} }
void MessagesView::createConnections() { void MessagesView::createConnections() {
connect(this, &MessagesView::doubleClicked, this, &MessagesView::openSelectedSourceMessagesExternally); connect(this, &MessagesView::doubleClicked, this, &MessagesView::openSelectedSourceMessagesExternally);
// Adjust columns when layout gets changed.
// Adjust columns when layout gets changed. connect(header(), &QHeaderView::geometriesChanged, this, &MessagesView::adjustColumns);
connect(header(), &QHeaderView::geometriesChanged, this, &MessagesView::adjustColumns); connect(header(), &QHeaderView::sortIndicatorChanged, this, &MessagesView::onSortIndicatorChanged);
connect(header(), &QHeaderView::sortIndicatorChanged, this, &MessagesView::onSortIndicatorChanged);
} }
void MessagesView::keyboardSearch(const QString &search) { void MessagesView::keyboardSearch(const QString& search) {
// WARNING: This is quite hacky way how to force selection of next item even // WARNING: This is quite hacky way how to force selection of next item even
// with extended selection enabled. // with extended selection enabled.
setSelectionMode(QAbstractItemView::SingleSelection); setSelectionMode(QAbstractItemView::SingleSelection);
QTreeView::keyboardSearch(search); QTreeView::keyboardSearch(search);
setSelectionMode(QAbstractItemView::ExtendedSelection); setSelectionMode(QAbstractItemView::ExtendedSelection);
} }
void MessagesView::reloadSelections() { void MessagesView::reloadSelections() {
const QDateTime dt1 = QDateTime::currentDateTime(); const QDateTime dt1 = QDateTime::currentDateTime();
QModelIndex current_index = selectionModel()->currentIndex();
const QModelIndex mapped_current_index = m_proxyModel->mapToSource(current_index);
const Message selected_message = m_sourceModel->messageAt(mapped_current_index.row());
const int col = header()->sortIndicatorSection();
const Qt::SortOrder ord = header()->sortIndicatorOrder();
// Reload the model now.
sort(col, ord, true, false, false);
QModelIndex current_index = selectionModel()->currentIndex(); // Now, we must find the same previously focused message.
const QModelIndex mapped_current_index = m_proxyModel->mapToSource(current_index); if (selected_message.m_id > 0) {
const Message selected_message = m_sourceModel->messageAt(mapped_current_index.row()); if (m_proxyModel->rowCount() == 0) {
const int col = header()->sortIndicatorSection(); current_index = QModelIndex();
const Qt::SortOrder ord = header()->sortIndicatorOrder(); }
// Reload the model now. else {
sort(col, ord, true, false, false); for (int i = 0; i < m_proxyModel->rowCount(); i++) {
QModelIndex msg_idx = m_proxyModel->index(i, MSG_DB_TITLE_INDEX);
Message msg = m_sourceModel->messageAt(m_proxyModel->mapToSource(msg_idx).row());
// Now, we must find the same previously focused message. if (msg.m_id == selected_message.m_id) {
if (selected_message.m_id > 0) { current_index = msg_idx;
if (m_proxyModel->rowCount() == 0) { break;
current_index = QModelIndex(); }
}
else {
for (int i = 0; i < m_proxyModel->rowCount(); i++) {
QModelIndex msg_idx = m_proxyModel->index(i, MSG_DB_TITLE_INDEX);
Message msg = m_sourceModel->messageAt(m_proxyModel->mapToSource(msg_idx).row());
if (msg.m_id == selected_message.m_id) { if (i == m_proxyModel->rowCount() - 1) {
current_index = msg_idx; current_index = QModelIndex();
break; }
} }
}
}
if (i == m_proxyModel->rowCount() - 1) { if (current_index.isValid()) {
current_index = QModelIndex(); scrollTo(current_index);
} setCurrentIndex(current_index);
} reselectIndexes(QModelIndexList() << current_index);
} }
}
if (current_index.isValid()) { else {
scrollTo(current_index); // Messages were probably removed from the model, nothing can
setCurrentIndex(current_index); // be selected and no message can be displayed.
reselectIndexes(QModelIndexList() << current_index); emit currentMessageRemoved();
} }
else {
// Messages were probably removed from the model, nothing can
// be selected and no message can be displayed.
emit currentMessageRemoved();
}
const QDateTime dt2 = QDateTime::currentDateTime(); const QDateTime dt2 = QDateTime::currentDateTime();
qDebug("Reloading of msg selections took %lld miliseconds.", dt1.msecsTo(dt2));
qDebug("Reloading of msg selections took %lld miliseconds.", dt1.msecsTo(dt2));
} }
void MessagesView::setupAppearance() { void MessagesView::setupAppearance() {
setUniformRowHeights(true); setUniformRowHeights(true);
setAcceptDrops(false); setAcceptDrops(false);
setDragEnabled(false); setDragEnabled(false);
setDragDropMode(QAbstractItemView::NoDragDrop); setDragDropMode(QAbstractItemView::NoDragDrop);
setExpandsOnDoubleClick(false); setExpandsOnDoubleClick(false);
setRootIsDecorated(false); setRootIsDecorated(false);
setEditTriggers(QAbstractItemView::NoEditTriggers); setEditTriggers(QAbstractItemView::NoEditTriggers);
setItemsExpandable(false); setItemsExpandable(false);
setSortingEnabled(true); setSortingEnabled(true);
setAllColumnsShowFocus(false); setAllColumnsShowFocus(false);
setSelectionMode(QAbstractItemView::ExtendedSelection); setSelectionMode(QAbstractItemView::ExtendedSelection);
setItemDelegate(new StyledItemDelegateWithoutFocus(this)); setItemDelegate(new StyledItemDelegateWithoutFocus(this));
header()->setDefaultSectionSize(MESSAGES_VIEW_DEFAULT_COL);
header()->setDefaultSectionSize(MESSAGES_VIEW_DEFAULT_COL); header()->setMinimumSectionSize(MESSAGES_VIEW_MINIMUM_COL);
header()->setMinimumSectionSize(MESSAGES_VIEW_MINIMUM_COL); header()->setCascadingSectionResizes(false);
header()->setCascadingSectionResizes(false); header()->setStretchLastSection(true);
header()->setStretchLastSection(true); header()->setSortIndicatorShown(true);
header()->setSortIndicatorShown(true);
} }
void MessagesView::keyPressEvent(QKeyEvent *event) { void MessagesView::keyPressEvent(QKeyEvent* event) {
QTreeView::keyPressEvent(event); QTreeView::keyPressEvent(event);
if (event->key() == Qt::Key_Delete) { if (event->key() == Qt::Key_Delete) {
deleteSelectedMessages(); deleteSelectedMessages();
} }
} }
void MessagesView::contextMenuEvent(QContextMenuEvent *event) { void MessagesView::contextMenuEvent(QContextMenuEvent* event) {
const QModelIndex clicked_index = indexAt(event->pos()); const QModelIndex clicked_index = indexAt(event->pos());
if (!clicked_index.isValid()) { if (!clicked_index.isValid()) {
TreeViewColumnsMenu menu(header()); TreeViewColumnsMenu menu(header());
menu.exec(event->globalPos()); menu.exec(event->globalPos());
} }
else {
// Context menu is not initialized, initialize.
initializeContextMenu();
m_contextMenu->exec(event->globalPos()); else {
} // Context menu is not initialized, initialize.
initializeContextMenu();
m_contextMenu->exec(event->globalPos());
}
} }
void MessagesView::initializeContextMenu() { void MessagesView::initializeContextMenu() {
if (m_contextMenu == nullptr) { if (m_contextMenu == nullptr) {
m_contextMenu = new QMenu(tr("Context menu for messages"), this); m_contextMenu = new QMenu(tr("Context menu for messages"), this);
} }
m_contextMenu->clear(); m_contextMenu->clear();
m_contextMenu->addActions(QList<QAction*>() << m_contextMenu->addActions(QList<QAction*>() <<
qApp->mainForm()->m_ui->m_actionSendMessageViaEmail << qApp->mainForm()->m_ui->m_actionSendMessageViaEmail <<
qApp->mainForm()->m_ui->m_actionOpenSelectedSourceArticlesExternally << qApp->mainForm()->m_ui->m_actionOpenSelectedSourceArticlesExternally <<
qApp->mainForm()->m_ui->m_actionOpenSelectedMessagesInternally << qApp->mainForm()->m_ui->m_actionOpenSelectedMessagesInternally <<
qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsRead << qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsRead <<
qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsUnread << qApp->mainForm()->m_ui->m_actionMarkSelectedMessagesAsUnread <<
qApp->mainForm()->m_ui->m_actionSwitchImportanceOfSelectedMessages << qApp->mainForm()->m_ui->m_actionSwitchImportanceOfSelectedMessages <<
qApp->mainForm()->m_ui->m_actionDeleteSelectedMessages); qApp->mainForm()->m_ui->m_actionDeleteSelectedMessages);
if (m_sourceModel->loadedItem() != nullptr && m_sourceModel->loadedItem()->kind() == RootItemKind::Bin) { if (m_sourceModel->loadedItem() != nullptr && m_sourceModel->loadedItem()->kind() == RootItemKind::Bin) {
m_contextMenu->addAction(qApp->mainForm()->m_ui->m_actionRestoreSelectedMessages); m_contextMenu->addAction(qApp->mainForm()->m_ui->m_actionRestoreSelectedMessages);
} }
} }
void MessagesView::mousePressEvent(QMouseEvent *event) { void MessagesView::mousePressEvent(QMouseEvent* event) {
QTreeView::mousePressEvent(event); QTreeView::mousePressEvent(event);
switch (event->button()) { switch (event->button()) {
case Qt::LeftButton: { case Qt::LeftButton: {
// Make sure that message importance is switched when user // Make sure that message importance is switched when user
// clicks the "important" column. // clicks the "important" column.
const QModelIndex clicked_index = indexAt(event->pos()); const QModelIndex clicked_index = indexAt(event->pos());
if (clicked_index.isValid()) { if (clicked_index.isValid()) {
const QModelIndex mapped_index = m_proxyModel->mapToSource(clicked_index); const QModelIndex mapped_index = m_proxyModel->mapToSource(clicked_index);
if (mapped_index.column() == MSG_DB_IMPORTANT_INDEX) { if (mapped_index.column() == MSG_DB_IMPORTANT_INDEX) {
if (m_sourceModel->switchMessageImportance(mapped_index.row())) { if (m_sourceModel->switchMessageImportance(mapped_index.row())) {
emit currentMessageChanged(m_sourceModel->messageAt(mapped_index.row()), m_sourceModel->loadedItem()); emit currentMessageChanged(m_sourceModel->messageAt(mapped_index.row()), m_sourceModel->loadedItem());
} }
} }
} }
break; break;
} }
case Qt::MiddleButton: { case Qt::MiddleButton: {
// Make sure that message importance is switched when user // Make sure that message importance is switched when user
// clicks the "important" column. // clicks the "important" column.
const QModelIndex clicked_index = indexAt(event->pos()); const QModelIndex clicked_index = indexAt(event->pos());
if (clicked_index.isValid()) { if (clicked_index.isValid()) {
const QModelIndex mapped_index = m_proxyModel->mapToSource(clicked_index); const QModelIndex mapped_index = m_proxyModel->mapToSource(clicked_index);
const QString url = m_sourceModel->messageAt(mapped_index.row()).m_url; const QString url = m_sourceModel->messageAt(mapped_index.row()).m_url;
if (!url.isEmpty()) { if (!url.isEmpty()) {
qApp->mainForm()->tabWidget()->addLinkedBrowser(url); qApp->mainForm()->tabWidget()->addLinkedBrowser(url);
} }
} }
break;
}
break; default:
} break;
}
default:
break;
}
} }
void MessagesView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { void MessagesView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
const QModelIndexList selected_rows = selectionModel()->selectedRows(); const QModelIndexList selected_rows = selectionModel()->selectedRows();
const QModelIndex current_index = currentIndex(); const QModelIndex current_index = currentIndex();
const QModelIndex mapped_current_index = m_proxyModel->mapToSource(current_index); 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].", if (mapped_current_index.isValid() && selected_rows.count() > 0) {
current_index.row(), current_index.column(), Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row());
mapped_current_index.row(), mapped_current_index.column()); // Set this message as read only if current item
// wasn't changed by "mark selected messages unread" action.
m_sourceModel->setMessageRead(mapped_current_index.row(), RootItem::Read);
message.m_isRead = true;
emit currentMessageChanged(message, m_sourceModel->loadedItem());
}
if (mapped_current_index.isValid() && selected_rows.count() > 0) { else {
Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()); emit currentMessageRemoved();
}
// Set this message as read only if current item if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::KeepCursorInCenter)).toBool()) {
// wasn't changed by "mark selected messages unread" action. scrollTo(currentIndex(), QAbstractItemView::PositionAtCenter);
m_sourceModel->setMessageRead(mapped_current_index.row(), RootItem::Read); }
message.m_isRead = true;
emit currentMessageChanged(message, m_sourceModel->loadedItem()); QTreeView::selectionChanged(selected, deselected);
}
else {
emit currentMessageRemoved();
}
if (qApp->settings()->value(GROUP(Messages), SETTING(Messages::KeepCursorInCenter)).toBool()) {
scrollTo(currentIndex(), QAbstractItemView::PositionAtCenter);
}
QTreeView::selectionChanged(selected, deselected);
} }
void MessagesView::loadItem(RootItem *item) { void MessagesView::loadItem(RootItem* item) {
const int col = header()->sortIndicatorSection(); const int col = header()->sortIndicatorSection();
const Qt::SortOrder ord = header()->sortIndicatorOrder(); const Qt::SortOrder ord = header()->sortIndicatorOrder();
scrollToTop();
scrollToTop(); sort(col, ord, false, true, false);
sort(col, ord, false, true, false); m_sourceModel->loadMessages(item);
m_sourceModel->loadMessages(item); // Messages are loaded, make sure that previously
// active message is not shown in browser.
// Messages are loaded, make sure that previously // BUG: Qt 5 is probably bugged here. Selections
// active message is not shown in browser. // should be cleared automatically when SQL model is reset.
// BUG: Qt 5 is probably bugged here. Selections emit currentMessageRemoved();
// should be cleared automatically when SQL model is reset.
emit currentMessageRemoved();
} }
void MessagesView::openSelectedSourceMessagesExternally() { void MessagesView::openSelectedSourceMessagesExternally() {
foreach (const QModelIndex &index, selectionModel()->selectedRows()) { foreach (const QModelIndex& index, selectionModel()->selectedRows()) {
const QString link = m_sourceModel->messageAt(m_proxyModel->mapToSource(index).row()).m_url; const QString link = m_sourceModel->messageAt(m_proxyModel->mapToSource(index).row()).m_url;
if (!WebFactory::instance()->openUrlInExternalBrowser(link)) { if (!WebFactory::instance()->openUrlInExternalBrowser(link)) {
qApp->showGuiMessage(tr("Problem with starting external web browser"), qApp->showGuiMessage(tr("Problem with starting external web browser"),
tr("External web browser could not be started."), tr("External web browser could not be started."),
QSystemTrayIcon::Critical); QSystemTrayIcon::Critical);
return; return;
} }
} }
// Finally, mark opened messages as read. // Finally, mark opened messages as read.
if (!selectionModel()->selectedRows().isEmpty()) { if (!selectionModel()->selectedRows().isEmpty()) {
QTimer::singleShot(0, this, SLOT(markSelectedMessagesRead())); QTimer::singleShot(0, this, SLOT(markSelectedMessagesRead()));
} }
} }
void MessagesView::openSelectedMessagesInternally() { void MessagesView::openSelectedMessagesInternally() {
QList<Message> messages; QList<Message> messages;
foreach (const QModelIndex &index, selectionModel()->selectedRows()) { foreach (const QModelIndex& index, selectionModel()->selectedRows()) {
messages << m_sourceModel->messageAt(m_proxyModel->mapToSource(index).row()); messages << m_sourceModel->messageAt(m_proxyModel->mapToSource(index).row());
} }
if (!messages.isEmpty()) { if (!messages.isEmpty()) {
emit openMessagesInNewspaperView(m_sourceModel->loadedItem(), messages); emit openMessagesInNewspaperView(m_sourceModel->loadedItem(), messages);
} }
} }
void MessagesView::sendSelectedMessageViaEmail() { void MessagesView::sendSelectedMessageViaEmail() {
if (selectionModel()->selectedRows().size() == 1) { if (selectionModel()->selectedRows().size() == 1) {
const Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(selectionModel()->selectedRows().at(0)).row()); const Message message = m_sourceModel->messageAt(m_proxyModel->mapToSource(selectionModel()->selectedRows().at(0)).row());
if (!WebFactory::instance()->sendMessageViaEmail(message)) { if (!WebFactory::instance()->sendMessageViaEmail(message)) {
MessageBox::show(this, MessageBox::show(this,
QMessageBox::Critical, QMessageBox::Critical,
tr("Problem with starting external e-mail client"), tr("Problem with starting external e-mail client"),
tr("External e-mail client could not be started.")); tr("External e-mail client could not be started."));
} }
} }
} }
void MessagesView::markSelectedMessagesRead() { void MessagesView::markSelectedMessagesRead() {
setSelectedMessagesReadStatus(RootItem::Read); setSelectedMessagesReadStatus(RootItem::Read);
} }
void MessagesView::markSelectedMessagesUnread() { void MessagesView::markSelectedMessagesUnread() {
setSelectedMessagesReadStatus(RootItem::Unread); setSelectedMessagesReadStatus(RootItem::Unread);
} }
void MessagesView::setSelectedMessagesReadStatus(RootItem::ReadStatus read) { void MessagesView::setSelectedMessagesReadStatus(RootItem::ReadStatus read) {
QModelIndex current_index = selectionModel()->currentIndex(); QModelIndex current_index = selectionModel()->currentIndex();
if (!current_index.isValid()) { if (!current_index.isValid()) {
return; return;
} }
QModelIndexList selected_indexes = selectionModel()->selectedRows(); QModelIndexList selected_indexes = selectionModel()->selectedRows();
const QModelIndexList mapped_indexes = m_proxyModel->mapListToSource(selected_indexes); const QModelIndexList mapped_indexes = m_proxyModel->mapListToSource(selected_indexes);
m_sourceModel->setBatchMessagesRead(mapped_indexes, read);
current_index = m_proxyModel->index(current_index.row(), current_index.column());
m_sourceModel->setBatchMessagesRead(mapped_indexes, read); if (current_index.isValid()) {
current_index = m_proxyModel->index(current_index.row(), current_index.column()); emit currentMessageChanged(m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()), m_sourceModel->loadedItem());
}
if (current_index.isValid()) { else {
emit currentMessageChanged(m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()), m_sourceModel->loadedItem()); emit currentMessageRemoved();
} }
else {
emit currentMessageRemoved();
}
} }
void MessagesView::deleteSelectedMessages() { void MessagesView::deleteSelectedMessages() {
QModelIndex current_index = selectionModel()->currentIndex(); QModelIndex current_index = selectionModel()->currentIndex();
if (!current_index.isValid()) { if (!current_index.isValid()) {
return; return;
} }
const QModelIndexList selected_indexes = selectionModel()->selectedRows(); const QModelIndexList selected_indexes = selectionModel()->selectedRows();
const QModelIndexList mapped_indexes = m_proxyModel->mapListToSource(selected_indexes); const QModelIndexList mapped_indexes = m_proxyModel->mapListToSource(selected_indexes);
m_sourceModel->setBatchMessagesDeleted(mapped_indexes);
current_index = moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier);
m_sourceModel->setBatchMessagesDeleted(mapped_indexes); if (current_index.isValid()) {
current_index = moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier); setCurrentIndex(current_index);
emit currentMessageChanged(m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()), m_sourceModel->loadedItem());
}
if (current_index.isValid()) { else {
setCurrentIndex(current_index); emit currentMessageRemoved();
emit currentMessageChanged(m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()), m_sourceModel->loadedItem()); }
}
else {
emit currentMessageRemoved();
}
} }
void MessagesView::restoreSelectedMessages() { void MessagesView::restoreSelectedMessages() {
QModelIndex current_index = selectionModel()->currentIndex(); QModelIndex current_index = selectionModel()->currentIndex();
if (!current_index.isValid()) { if (!current_index.isValid()) {
return; return;
} }
const QModelIndexList selected_indexes = selectionModel()->selectedRows(); const QModelIndexList selected_indexes = selectionModel()->selectedRows();
const QModelIndexList mapped_indexes = m_proxyModel->mapListToSource(selected_indexes); const QModelIndexList mapped_indexes = m_proxyModel->mapListToSource(selected_indexes);
m_sourceModel->setBatchMessagesRestored(mapped_indexes);
current_index = m_proxyModel->index(current_index.row(), current_index.column());
m_sourceModel->setBatchMessagesRestored(mapped_indexes); if (current_index.isValid()) {
current_index = m_proxyModel->index(current_index.row(), current_index.column()); emit currentMessageChanged(m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()), m_sourceModel->loadedItem());
}
if (current_index.isValid()) { else {
emit currentMessageChanged(m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()), m_sourceModel->loadedItem()); emit currentMessageRemoved();
}
}
else {
emit currentMessageRemoved();
}
} }
void MessagesView::switchSelectedMessagesImportance() { void MessagesView::switchSelectedMessagesImportance() {
QModelIndex current_index = selectionModel()->currentIndex(); QModelIndex current_index = selectionModel()->currentIndex();
if (!current_index.isValid()) { if (!current_index.isValid()) {
return; return;
} }
QModelIndexList selected_indexes = selectionModel()->selectedRows(); QModelIndexList selected_indexes = selectionModel()->selectedRows();
const QModelIndexList mapped_indexes = m_proxyModel->mapListToSource(selected_indexes); const QModelIndexList mapped_indexes = m_proxyModel->mapListToSource(selected_indexes);
m_sourceModel->switchBatchMessageImportance(mapped_indexes);
current_index = m_proxyModel->index(current_index.row(), current_index.column());
m_sourceModel->switchBatchMessageImportance(mapped_indexes); if (current_index.isValid()) {
current_index = m_proxyModel->index(current_index.row(), current_index.column()); emit currentMessageChanged(m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()), m_sourceModel->loadedItem());
}
if (current_index.isValid()) { else {
emit currentMessageChanged(m_sourceModel->messageAt(m_proxyModel->mapToSource(current_index).row()), m_sourceModel->loadedItem()); // Messages were probably removed from the model, nothing can
} // be selected and no message can be displayed.
else { emit currentMessageRemoved();
// Messages were probably removed from the model, nothing can }
// be selected and no message can be displayed.
emit currentMessageRemoved();
}
} }
void MessagesView::reselectIndexes(const QModelIndexList &indexes) { void MessagesView::reselectIndexes(const QModelIndexList& indexes) {
if (indexes.size() < RESELECT_MESSAGE_THRESSHOLD) { if (indexes.size() < RESELECT_MESSAGE_THRESSHOLD) {
QItemSelection selection; QItemSelection selection;
foreach (const QModelIndex &index, indexes) { foreach (const QModelIndex& index, indexes) {
selection.merge(QItemSelection(index, index), QItemSelectionModel::Select); selection.merge(QItemSelection(index, index), QItemSelectionModel::Select);
} }
selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
} }
} }
void MessagesView::selectNextItem() { void MessagesView::selectNextItem() {
const QModelIndex index_next = moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier); const QModelIndex index_next = moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier);
if (index_next.isValid()) { if (index_next.isValid()) {
setCurrentIndex(index_next); setCurrentIndex(index_next);
selectionModel()->select(index_next, QItemSelectionModel::Select | QItemSelectionModel::Rows); selectionModel()->select(index_next, QItemSelectionModel::Select | QItemSelectionModel::Rows);
setFocus(); setFocus();
} }
} }
void MessagesView::selectPreviousItem() { void MessagesView::selectPreviousItem() {
const QModelIndex index_previous = moveCursor(QAbstractItemView::MoveUp, Qt::NoModifier); const QModelIndex index_previous = moveCursor(QAbstractItemView::MoveUp, Qt::NoModifier);
if (index_previous.isValid()) { if (index_previous.isValid()) {
setCurrentIndex(index_previous); setCurrentIndex(index_previous);
selectionModel()->select(index_previous, QItemSelectionModel::Select | QItemSelectionModel::Rows); selectionModel()->select(index_previous, QItemSelectionModel::Select | QItemSelectionModel::Rows);
setFocus(); setFocus();
} }
} }
void MessagesView::selectNextUnreadItem() { void MessagesView::selectNextUnreadItem() {
// FIXME: Use this to solve #112. // FIXME: Use this to solve #112.
const QModelIndexList selected_rows = selectionModel()->selectedRows();
int active_row;
const QModelIndexList selected_rows = selectionModel()->selectedRows(); if (!selected_rows.isEmpty()) {
int active_row; // Okay, something is selected, start from it.
active_row = selected_rows.at(0).row();
}
if (!selected_rows.isEmpty()) { else {
// Okay, something is selected, start from it. active_row = 0;
active_row = selected_rows.at(0).row(); }
}
else {
active_row = 0;
}
const QModelIndex next_unread = m_proxyModel->getNextPreviousUnreadItemIndex(active_row); const QModelIndex next_unread = m_proxyModel->getNextPreviousUnreadItemIndex(active_row);
if (next_unread.isValid()) { if (next_unread.isValid()) {
// We found unread message, mark it. // We found unread message, mark it.
setCurrentIndex(next_unread); setCurrentIndex(next_unread);
selectionModel()->select(next_unread, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); selectionModel()->select(next_unread, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
setFocus(); setFocus();
} }
} }
void MessagesView::searchMessages(const QString &pattern) { void MessagesView::searchMessages(const QString& pattern) {
m_proxyModel->setFilterRegExp(pattern); m_proxyModel->setFilterRegExp(pattern);
if (selectionModel()->selectedRows().size() == 0) { if (selectionModel()->selectedRows().size() == 0) {
emit currentMessageRemoved(); emit currentMessageRemoved();
} }
else {
// Scroll to selected message, it could become scrolled out due to filter change. else {
scrollTo(selectionModel()->selectedRows().at(0)); // Scroll to selected message, it could become scrolled out due to filter change.
} scrollTo(selectionModel()->selectedRows().at(0));
}
} }
void MessagesView::filterMessages(MessagesModel::MessageHighlighter filter) { void MessagesView::filterMessages(MessagesModel::MessageHighlighter filter) {
m_sourceModel->highlightMessages(filter); m_sourceModel->highlightMessages(filter);
} }
void MessagesView::adjustColumns() { void MessagesView::adjustColumns() {
if (header()->count() > 0 && !m_columnsAdjusted) { if (header()->count() > 0 && !m_columnsAdjusted) {
m_columnsAdjusted = true; m_columnsAdjusted = true;
// Setup column resize strategies.
// Setup column resize strategies. header()->setSectionResizeMode(MSG_DB_ID_INDEX, QHeaderView::Interactive);
header()->setSectionResizeMode(MSG_DB_ID_INDEX, QHeaderView::Interactive); header()->setSectionResizeMode(MSG_DB_READ_INDEX, QHeaderView::ResizeToContents);
header()->setSectionResizeMode(MSG_DB_READ_INDEX, QHeaderView::ResizeToContents); header()->setSectionResizeMode(MSG_DB_DELETED_INDEX, QHeaderView::Interactive);
header()->setSectionResizeMode(MSG_DB_DELETED_INDEX, QHeaderView::Interactive); header()->setSectionResizeMode(MSG_DB_IMPORTANT_INDEX, QHeaderView::ResizeToContents);
header()->setSectionResizeMode(MSG_DB_IMPORTANT_INDEX, QHeaderView::ResizeToContents); header()->setSectionResizeMode(MSG_DB_FEED_TITLE_INDEX, QHeaderView::Interactive);
header()->setSectionResizeMode(MSG_DB_FEED_TITLE_INDEX, QHeaderView::Interactive); header()->setSectionResizeMode(MSG_DB_TITLE_INDEX, QHeaderView::Interactive);
header()->setSectionResizeMode(MSG_DB_TITLE_INDEX, QHeaderView::Interactive); header()->setSectionResizeMode(MSG_DB_URL_INDEX, QHeaderView::Interactive);
header()->setSectionResizeMode(MSG_DB_URL_INDEX, QHeaderView::Interactive); header()->setSectionResizeMode(MSG_DB_AUTHOR_INDEX, QHeaderView::Interactive);
header()->setSectionResizeMode(MSG_DB_AUTHOR_INDEX, QHeaderView::Interactive); header()->setSectionResizeMode(MSG_DB_DCREATED_INDEX, QHeaderView::Interactive);
header()->setSectionResizeMode(MSG_DB_DCREATED_INDEX, QHeaderView::Interactive); header()->setSectionResizeMode(MSG_DB_CONTENTS_INDEX, QHeaderView::Interactive);
header()->setSectionResizeMode(MSG_DB_CONTENTS_INDEX, QHeaderView::Interactive); header()->setSectionResizeMode(MSG_DB_PDELETED_INDEX, QHeaderView::Interactive);
header()->setSectionResizeMode(MSG_DB_PDELETED_INDEX, QHeaderView::Interactive); //header()->resizeSection(MSG_DB_READ_INDEX, MESSAGES_VIEW_MINIMUM_COL);
//header()->resizeSection(MSG_DB_IMPORTANT_INDEX, MESSAGES_VIEW_MINIMUM_COL);
//header()->resizeSection(MSG_DB_READ_INDEX, MESSAGES_VIEW_MINIMUM_COL); // Hide columns.
//header()->resizeSection(MSG_DB_IMPORTANT_INDEX, MESSAGES_VIEW_MINIMUM_COL); hideColumn(MSG_DB_ID_INDEX);
hideColumn(MSG_DB_DELETED_INDEX);
// Hide columns. hideColumn(MSG_DB_URL_INDEX);
hideColumn(MSG_DB_ID_INDEX); hideColumn(MSG_DB_CONTENTS_INDEX);
hideColumn(MSG_DB_DELETED_INDEX); hideColumn(MSG_DB_PDELETED_INDEX);
hideColumn(MSG_DB_URL_INDEX); hideColumn(MSG_DB_ENCLOSURES_INDEX);
hideColumn(MSG_DB_CONTENTS_INDEX); hideColumn(MSG_DB_ACCOUNT_ID_INDEX);
hideColumn(MSG_DB_PDELETED_INDEX); hideColumn(MSG_DB_CUSTOM_ID_INDEX);
hideColumn(MSG_DB_ENCLOSURES_INDEX); hideColumn(MSG_DB_CUSTOM_HASH_INDEX);
hideColumn(MSG_DB_ACCOUNT_ID_INDEX); hideColumn(MSG_DB_FEED_CUSTOM_ID_INDEX);
hideColumn(MSG_DB_CUSTOM_ID_INDEX); qDebug("Adjusting column resize modes for MessagesView.");
hideColumn(MSG_DB_CUSTOM_HASH_INDEX); }
hideColumn(MSG_DB_FEED_CUSTOM_ID_INDEX);
qDebug("Adjusting column resize modes for MessagesView.");
}
} }
void MessagesView::onSortIndicatorChanged(int column, Qt::SortOrder order) { void MessagesView::onSortIndicatorChanged(int column, Qt::SortOrder order) {
// Repopulate the shit. // Repopulate the shit.
sort(column, order, true, false, false); sort(column, order, true, false, false);
emit currentMessageRemoved(); emit currentMessageRemoved();
} }

View File

@ -29,97 +29,97 @@
class MessagesProxyModel; class MessagesProxyModel;
class MessagesView : public QTreeView { class MessagesView : public QTreeView {
Q_OBJECT Q_OBJECT
public: public:
// Constructors and destructors. // Constructors and destructors.
explicit MessagesView(QWidget *parent = 0); explicit MessagesView(QWidget* parent = 0);
virtual ~MessagesView(); virtual ~MessagesView();
// Model accessors. // Model accessors.
inline MessagesProxyModel *model() const { inline MessagesProxyModel* model() const {
return m_proxyModel; return m_proxyModel;
} }
inline MessagesModel *sourceModel() const { inline MessagesModel* sourceModel() const {
return m_sourceModel; return m_sourceModel;
} }
public slots: public slots:
void keyboardSearch(const QString &search); void keyboardSearch(const QString& search);
// Called after data got changed externally // Called after data got changed externally
// and it needs to be reloaded to the view. // and it needs to be reloaded to the view.
void reloadSelections(); void reloadSelections();
// Loads un-deleted messages from selected feeds. // Loads un-deleted messages from selected feeds.
void loadItem(RootItem *item); void loadItem(RootItem* item);
// Message manipulators. // Message manipulators.
void openSelectedSourceMessagesExternally(); void openSelectedSourceMessagesExternally();
void openSelectedMessagesInternally(); void openSelectedMessagesInternally();
void sendSelectedMessageViaEmail(); void sendSelectedMessageViaEmail();
// Works with SELECTED messages only. // Works with SELECTED messages only.
void setSelectedMessagesReadStatus(RootItem::ReadStatus read); void setSelectedMessagesReadStatus(RootItem::ReadStatus read);
void markSelectedMessagesRead(); void markSelectedMessagesRead();
void markSelectedMessagesUnread(); void markSelectedMessagesUnread();
void switchSelectedMessagesImportance(); void switchSelectedMessagesImportance();
void deleteSelectedMessages(); void deleteSelectedMessages();
void restoreSelectedMessages(); void restoreSelectedMessages();
void selectNextItem(); void selectNextItem();
void selectPreviousItem(); void selectPreviousItem();
void selectNextUnreadItem(); void selectNextUnreadItem();
// Searchs the visible message according to given pattern. // Searchs the visible message according to given pattern.
void searchMessages(const QString &pattern); void searchMessages(const QString& pattern);
void filterMessages(MessagesModel::MessageHighlighter filter); void filterMessages(MessagesModel::MessageHighlighter filter);
private slots: private slots:
// Marks given indexes as selected. // Marks given indexes as selected.
void reselectIndexes(const QModelIndexList &indexes); void reselectIndexes(const QModelIndexList& indexes);
// Changes resize mode for all columns. // Changes resize mode for all columns.
void adjustColumns(); void adjustColumns();
// Saves current sort state. // Saves current sort state.
void onSortIndicatorChanged(int column, Qt::SortOrder order); void onSortIndicatorChanged(int column, Qt::SortOrder order);
signals: signals:
// Link/message openers. // Link/message openers.
void openLinkNewTab(const QString &link); void openLinkNewTab(const QString& link);
void openLinkMiniBrowser(const QString &link); void openLinkMiniBrowser(const QString& link);
void openMessagesInNewspaperView(RootItem *root, const QList<Message> &messages); void openMessagesInNewspaperView(RootItem* root, const QList<Message>& messages);
// Notify others about message selections. // Notify others about message selections.
void currentMessageChanged(const Message &message, RootItem *root); void currentMessageChanged(const Message& message, RootItem* root);
void currentMessageRemoved(); void currentMessageRemoved();
private: private:
void sort(int column, Qt::SortOrder order, bool repopulate_data, bool change_header, bool emit_changed_from_header); void sort(int column, Qt::SortOrder order, bool repopulate_data, bool change_header, bool emit_changed_from_header);
// Creates needed connections. // Creates needed connections.
void createConnections(); void createConnections();
// Initializes context menu. // Initializes context menu.
void initializeContextMenu(); void initializeContextMenu();
// Sets up appearance. // Sets up appearance.
void setupAppearance(); void setupAppearance();
// Event reimplementations. // Event reimplementations.
void contextMenuEvent(QContextMenuEvent *event); void contextMenuEvent(QContextMenuEvent* event);
void mousePressEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent* event);
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent* event);
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void selectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
QMenu *m_contextMenu; QMenu* m_contextMenu;
MessagesProxyModel *m_proxyModel; MessagesProxyModel* m_proxyModel;
MessagesModel *m_sourceModel; MessagesModel* m_sourceModel;
bool m_columnsAdjusted; bool m_columnsAdjusted;
}; };
#endif // MESSAGESVIEW_H #endif // MESSAGESVIEW_H

View File

@ -22,30 +22,30 @@
#include "network-web/networkfactory.h" #include "network-web/networkfactory.h"
MessageTextBrowser::MessageTextBrowser(QWidget *parent) : QTextBrowser(parent) { MessageTextBrowser::MessageTextBrowser(QWidget* parent) : QTextBrowser(parent) {
} }
MessageTextBrowser::~MessageTextBrowser() { MessageTextBrowser::~MessageTextBrowser() {
} }
QVariant MessageTextBrowser::loadResource(int type, const QUrl &name) { QVariant MessageTextBrowser::loadResource(int type, const QUrl& name) {
Q_UNUSED(name) Q_UNUSED(name)
switch (type) { switch (type) {
case QTextDocument::ImageResource: { case QTextDocument::ImageResource: {
if (m_imagePlaceholder.isNull()) { if (m_imagePlaceholder.isNull()) {
m_imagePlaceholder = qApp->icons()->miscPixmap(QSL("image-placeholder")).scaledToWidth(20, Qt::FastTransformation); m_imagePlaceholder = qApp->icons()->miscPixmap(QSL("image-placeholder")).scaledToWidth(20, Qt::FastTransformation);
} }
return m_imagePlaceholder; return m_imagePlaceholder;
} }
default: default:
return QTextBrowser::loadResource(type, name); return QTextBrowser::loadResource(type, name);
} }
} }
void MessageTextBrowser::wheelEvent(QWheelEvent *e) { void MessageTextBrowser::wheelEvent(QWheelEvent* e) {
QTextBrowser::wheelEvent(e); QTextBrowser::wheelEvent(e);
qApp->settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, font().toString()); qApp->settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, font().toString());
} }

View File

@ -22,19 +22,19 @@
class MessageTextBrowser : public QTextBrowser { class MessageTextBrowser : public QTextBrowser {
Q_OBJECT Q_OBJECT
public: public:
explicit MessageTextBrowser(QWidget *parent = 0); explicit MessageTextBrowser(QWidget* parent = 0);
virtual ~MessageTextBrowser(); virtual ~MessageTextBrowser();
QVariant loadResource(int type, const QUrl &name); QVariant loadResource(int type, const QUrl& name);
protected: protected:
void wheelEvent(QWheelEvent *e); void wheelEvent(QWheelEvent* e);
private: private:
QPixmap m_imagePlaceholder; QPixmap m_imagePlaceholder;
}; };
#endif // MESSAGETEXTBROWSER_H #endif // MESSAGETEXTBROWSER_H

View File

@ -24,42 +24,41 @@
#include <QScrollBar> #include <QScrollBar>
NewspaperPreviewer::NewspaperPreviewer(RootItem *root, QList<Message> messages, QWidget *parent) NewspaperPreviewer::NewspaperPreviewer(RootItem* root, QList<Message> messages, QWidget* parent)
: TabContent(parent), m_ui(new Ui::NewspaperPreviewer), m_root(root), m_messages(messages) { : TabContent(parent), m_ui(new Ui::NewspaperPreviewer), m_root(root), m_messages(messages) {
m_ui->setupUi(this); m_ui->setupUi(this);
connect(m_ui->m_btnShowMoreMessages, &QPushButton::clicked, this, &NewspaperPreviewer::showMoreMessages); connect(m_ui->m_btnShowMoreMessages, &QPushButton::clicked, this, &NewspaperPreviewer::showMoreMessages);
showMoreMessages(); showMoreMessages();
} }
NewspaperPreviewer::~NewspaperPreviewer() { NewspaperPreviewer::~NewspaperPreviewer() {
} }
void NewspaperPreviewer::showMoreMessages() { void NewspaperPreviewer::showMoreMessages() {
if (!m_root.isNull()) { if (!m_root.isNull()) {
int current_scroll = m_ui->scrollArea->verticalScrollBar()->value(); int current_scroll = m_ui->scrollArea->verticalScrollBar()->value();
for (int i = 0; i < 10 && !m_messages.isEmpty(); i++) { for (int i = 0; i < 10 && !m_messages.isEmpty(); i++) {
Message msg = m_messages.takeFirst(); Message msg = m_messages.takeFirst();
MessagePreviewer *prev = new MessagePreviewer(this); MessagePreviewer* prev = new MessagePreviewer(this);
QMargins margins = prev->layout()->contentsMargins(); QMargins margins = prev->layout()->contentsMargins();
connect(prev, &MessagePreviewer::requestMessageListReload, this, &NewspaperPreviewer::requestMessageListReload);
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);
}
connect(prev, &MessagePreviewer::requestMessageListReload, this, &NewspaperPreviewer::requestMessageListReload); 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);
}
margins.setRight(0); else {
prev->layout()->setContentsMargins(margins); qApp->showGuiMessage(tr("Cannot show more messages"),
prev->setFixedHeight(300); tr("Cannot show more messages because parent feed was removed."),
prev->loadMessage(msg, m_root); QSystemTrayIcon::Warning,
m_ui->m_layout->insertWidget(m_ui->m_layout->count() - 2, prev); qApp->mainForm(), true);
} }
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

@ -31,28 +31,28 @@
namespace Ui { namespace Ui {
class NewspaperPreviewer; class NewspaperPreviewer;
} }
class RootItem; class RootItem;
class NewspaperPreviewer : public TabContent { class NewspaperPreviewer : public TabContent {
Q_OBJECT Q_OBJECT
public: public:
explicit NewspaperPreviewer(RootItem *root, QList<Message> messages, QWidget *parent = 0); explicit NewspaperPreviewer(RootItem* root, QList<Message> messages, QWidget* parent = 0);
virtual ~NewspaperPreviewer(); virtual ~NewspaperPreviewer();
private slots: private slots:
void showMoreMessages(); void showMoreMessages();
signals: signals:
void requestMessageListReload(bool mark_current_as_read); void requestMessageListReload(bool mark_current_as_read);
private: private:
QScopedPointer<Ui::NewspaperPreviewer> m_ui; QScopedPointer<Ui::NewspaperPreviewer> m_ui;
QPointer<RootItem> m_root; QPointer<RootItem> m_root;
QList<Message> m_messages; QList<Message> m_messages;
}; };
#endif // NEWSPAPERPREVIEWER_H #endif // NEWSPAPERPREVIEWER_H

View File

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

View File

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

View File

@ -26,177 +26,160 @@
#include <QFileDialog> #include <QFileDialog>
SettingsBrowserMail::SettingsBrowserMail(Settings *settings, QWidget *parent) SettingsBrowserMail::SettingsBrowserMail(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsBrowserMail) { : SettingsPanel(settings, parent), m_ui(new Ui::SettingsBrowserMail) {
m_ui->setupUi(this); m_ui->setupUi(this);
GuiUtilities::setLabelAsNotice(m_ui->label, false);
GuiUtilities::setLabelAsNotice(m_ui->label, false); GuiUtilities::setLabelAsNotice(m_ui->m_lblExternalEmailInfo, false);
GuiUtilities::setLabelAsNotice(m_ui->m_lblExternalEmailInfo, false); GuiUtilities::setLabelAsNotice(m_ui->m_lblProxyInfo, false);
GuiUtilities::setLabelAsNotice(m_ui->m_lblProxyInfo, false);
#if defined(USE_WEBENGINE) #if defined(USE_WEBENGINE)
m_ui->m_checkOpenLinksInExternal->setVisible(false); m_ui->m_checkOpenLinksInExternal->setVisible(false);
#else #else
connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_checkOpenLinksInExternal, &QCheckBox::stateChanged, this, &SettingsBrowserMail::dirtifySettings);
#endif #endif
connect(m_ui->m_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::dirtifySettings);
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_txtProxyHost, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_txtProxyPassword, &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_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_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_grpCustomExternalBrowser, &QGroupBox::toggled, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_grpCustomExternalEmail, &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_txtExternalBrowserArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_txtExternalBrowserExecutable, &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_txtExternalEmailArguments, &QLineEdit::textChanged, this, &SettingsBrowserMail::dirtifySettings); connect(m_ui->m_txtExternalEmailExecutable, &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_cmbProxyType, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::onProxyTypeChanged); connect(m_ui->m_cmbExternalBrowserPreset, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::changeDefaultBrowserArguments);
connect(m_ui->m_checkShowPassword, &QCheckBox::stateChanged, this, &SettingsBrowserMail::displayProxyPassword); connect(m_ui->m_btnExternalBrowserExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectBrowserExecutable);
connect(m_ui->m_cmbExternalBrowserPreset, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::changeDefaultBrowserArguments); connect(m_ui->m_cmbExternalEmailPreset, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsBrowserMail::changeDefaultEmailArguments);
connect(m_ui->m_btnExternalBrowserExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectBrowserExecutable); connect(m_ui->m_btnExternalEmailExecutable, &QPushButton::clicked, this, &SettingsBrowserMail::selectEmailExecutable);
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);
} }
SettingsBrowserMail::~SettingsBrowserMail() { SettingsBrowserMail::~SettingsBrowserMail() {
delete m_ui; delete m_ui;
} }
void SettingsBrowserMail::changeDefaultBrowserArguments(int index) { void SettingsBrowserMail::changeDefaultBrowserArguments(int index) {
if (index != 0) { if (index != 0) {
m_ui->m_txtExternalBrowserArguments->setText(m_ui->m_cmbExternalBrowserPreset->itemData(index).toString()); m_ui->m_txtExternalBrowserArguments->setText(m_ui->m_cmbExternalBrowserPreset->itemData(index).toString());
} }
} }
void SettingsBrowserMail::selectBrowserExecutable() { void SettingsBrowserMail::selectBrowserExecutable() {
const QString executable_file = QFileDialog::getOpenFileName(this, const QString executable_file = QFileDialog::getOpenFileName(this,
tr("Select web browser executable"), tr("Select web browser executable"),
qApp->getHomeFolderPath(), qApp->getHomeFolderPath(),
//: File filter for external browser selection dialog. //: File filter for external browser selection dialog.
#if defined(Q_OS_LINUX) #if defined(Q_OS_LINUX)
tr("Executables (*)") tr("Executables (*)")
#else #else
tr("Executables (*.*)") tr("Executables (*.*)")
#endif #endif
); );
if (!executable_file.isEmpty()) { if (!executable_file.isEmpty()) {
m_ui->m_txtExternalBrowserExecutable->setText(QDir::toNativeSeparators(executable_file)); m_ui->m_txtExternalBrowserExecutable->setText(QDir::toNativeSeparators(executable_file));
} }
} }
void SettingsBrowserMail::displayProxyPassword(int state) { void SettingsBrowserMail::displayProxyPassword(int state) {
if (state == Qt::Checked) { if (state == Qt::Checked) {
m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::Normal); m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::Normal);
} }
else {
m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit); else {
} m_ui->m_txtProxyPassword->setEchoMode(QLineEdit::PasswordEchoOnEdit);
}
} }
void SettingsBrowserMail::onProxyTypeChanged(int index) { void SettingsBrowserMail::onProxyTypeChanged(int index) {
const QNetworkProxy::ProxyType selected_type = static_cast<QNetworkProxy::ProxyType>(m_ui->m_cmbProxyType->itemData(index).toInt()); 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; const bool is_proxy_selected = selected_type != QNetworkProxy::NoProxy && selected_type != QNetworkProxy::DefaultProxy;
m_ui->m_txtProxyHost->setEnabled(is_proxy_selected);
m_ui->m_txtProxyHost->setEnabled(is_proxy_selected); m_ui->m_txtProxyPassword->setEnabled(is_proxy_selected);
m_ui->m_txtProxyPassword->setEnabled(is_proxy_selected); m_ui->m_txtProxyUsername->setEnabled(is_proxy_selected);
m_ui->m_txtProxyUsername->setEnabled(is_proxy_selected); m_ui->m_spinProxyPort->setEnabled(is_proxy_selected);
m_ui->m_spinProxyPort->setEnabled(is_proxy_selected); m_ui->m_checkShowPassword->setEnabled(is_proxy_selected);
m_ui->m_checkShowPassword->setEnabled(is_proxy_selected); m_ui->m_lblProxyHost->setEnabled(is_proxy_selected);
m_ui->m_lblProxyHost->setEnabled(is_proxy_selected); m_ui->m_lblProxyInfo->setEnabled(is_proxy_selected);
m_ui->m_lblProxyInfo->setEnabled(is_proxy_selected); m_ui->m_lblProxyPassword->setEnabled(is_proxy_selected);
m_ui->m_lblProxyPassword->setEnabled(is_proxy_selected); m_ui->m_lblProxyPort->setEnabled(is_proxy_selected);
m_ui->m_lblProxyPort->setEnabled(is_proxy_selected); m_ui->m_lblProxyUsername->setEnabled(is_proxy_selected);
m_ui->m_lblProxyUsername->setEnabled(is_proxy_selected);
} }
void SettingsBrowserMail::changeDefaultEmailArguments(int index) { void SettingsBrowserMail::changeDefaultEmailArguments(int index) {
if (index != 0) { if (index != 0) {
m_ui->m_txtExternalEmailArguments->setText(m_ui->m_cmbExternalEmailPreset->itemData(index).toString()); m_ui->m_txtExternalEmailArguments->setText(m_ui->m_cmbExternalEmailPreset->itemData(index).toString());
} }
} }
void SettingsBrowserMail::selectEmailExecutable() { void SettingsBrowserMail::selectEmailExecutable() {
QString executable_file = QFileDialog::getOpenFileName(this, QString executable_file = QFileDialog::getOpenFileName(this,
tr("Select e-mail executable"), tr("Select e-mail executable"),
qApp->getHomeFolderPath(), qApp->getHomeFolderPath(),
//: File filter for external e-mail selection dialog. //: File filter for external e-mail selection dialog.
#if defined(Q_OS_LINUX) #if defined(Q_OS_LINUX)
tr("Executables (*)") tr("Executables (*)")
#else #else
tr("Executables (*.*)") tr("Executables (*.*)")
#endif #endif
); );
if (!executable_file.isEmpty()) { if (!executable_file.isEmpty()) {
m_ui->m_txtExternalEmailExecutable->setText(QDir::toNativeSeparators(executable_file)); m_ui->m_txtExternalEmailExecutable->setText(QDir::toNativeSeparators(executable_file));
} }
} }
void SettingsBrowserMail::loadSettings() { void SettingsBrowserMail::loadSettings() {
onBeginLoadSettings(); onBeginLoadSettings();
#if !defined(USE_WEBENGINE) #if !defined(USE_WEBENGINE)
m_ui->m_checkOpenLinksInExternal->setChecked(settings()->value(GROUP(Browser), m_ui->m_checkOpenLinksInExternal->setChecked(settings()->value(GROUP(Browser),
SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool()); SETTING(Browser::OpenLinksInExternalBrowserRightAway)).toBool());
#endif #endif
// Load settings of web browser GUI.
// Load settings of web browser GUI. m_ui->m_cmbExternalBrowserPreset->addItem(tr("Opera 12 or older"), QSL("-nosession %1"));
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_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_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_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'\""));
// Load settings of e-mail. m_ui->m_txtExternalEmailExecutable->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailExecutable)).toString());
m_ui->m_cmbExternalEmailPreset->addItem(tr("Mozilla Thunderbird"), QSL("-compose \"subject='%1',body='%2'\"")); m_ui->m_txtExternalEmailArguments->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString());
m_ui->m_txtExternalEmailExecutable->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailExecutable)).toString()); m_ui->m_grpCustomExternalEmail->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool());
m_ui->m_txtExternalEmailArguments->setText(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailArguments)).toString()); m_ui->m_cmbProxyType->addItem(tr("No proxy"), QNetworkProxy::NoProxy);
m_ui->m_grpCustomExternalEmail->setChecked(settings()->value(GROUP(Browser), SETTING(Browser::CustomExternalEmailEnabled)).toBool()); 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("No proxy"), QNetworkProxy::NoProxy); m_ui->m_cmbProxyType->addItem(tr("Http"), QNetworkProxy::HttpProxy);
m_ui->m_cmbProxyType->addItem(tr("System proxy"), QNetworkProxy::DefaultProxy); // Load the settings.
m_ui->m_cmbProxyType->addItem(tr("Socks5"), QNetworkProxy::Socks5Proxy); QNetworkProxy::ProxyType selected_proxy_type = static_cast<QNetworkProxy::ProxyType>(settings()->value(GROUP(Proxy), SETTING(Proxy::Type)).toInt());
m_ui->m_cmbProxyType->addItem(tr("Http"), QNetworkProxy::HttpProxy); 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());
// Load the settings. m_ui->m_txtProxyUsername->setText(settings()->value(GROUP(Proxy), SETTING(Proxy::Username)).toString());
QNetworkProxy::ProxyType selected_proxy_type = static_cast<QNetworkProxy::ProxyType>(settings()->value(GROUP(Proxy), SETTING(Proxy::Type)).toInt()); 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());
m_ui->m_cmbProxyType->setCurrentIndex(m_ui->m_cmbProxyType->findData(selected_proxy_type)); onEndLoadSettings();
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());
onEndLoadSettings();
} }
void SettingsBrowserMail::saveSettings() { void SettingsBrowserMail::saveSettings() {
onBeginSaveSettings(); onBeginSaveSettings();
#if !defined(USE_WEBENGINE) #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 #endif
// Save settings of GUI of web browser.
// Save settings of GUI of web browser. settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserEnabled, m_ui->m_grpCustomExternalBrowser->isChecked());
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::CustomExternalBrowserExecutable, m_ui->m_txtExternalBrowserExecutable->text()); settings()->setValue(GROUP(Browser), Browser::CustomExternalBrowserArguments, m_ui->m_txtExternalBrowserArguments->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());
// Save settings of e-mail. settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailArguments, m_ui->m_txtExternalEmailArguments->text());
settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailExecutable, m_ui->m_txtExternalEmailExecutable->text()); settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailEnabled, m_ui->m_grpCustomExternalEmail->isChecked());
settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailArguments, m_ui->m_txtExternalEmailArguments->text()); settings()->setValue(GROUP(Proxy), Proxy::Type, m_ui->m_cmbProxyType->itemData(m_ui->m_cmbProxyType->currentIndex()));
settings()->setValue(GROUP(Browser), Browser::CustomExternalEmailEnabled, m_ui->m_grpCustomExternalEmail->isChecked()); 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::Type, m_ui->m_cmbProxyType->itemData(m_ui->m_cmbProxyType->currentIndex())); settings()->setValue(GROUP(Proxy), Proxy::Password, TextFactory::encrypt(m_ui->m_txtProxyPassword->text()));
settings()->setValue(GROUP(Proxy), Proxy::Host, m_ui->m_txtProxyHost->text()); settings()->setValue(GROUP(Proxy), Proxy::Port, m_ui->m_spinProxyPort->value());
settings()->setValue(GROUP(Proxy), Proxy::Username, m_ui->m_txtProxyUsername->text()); // Reload settings for all network access managers.
settings()->setValue(GROUP(Proxy), Proxy::Password, TextFactory::encrypt(m_ui->m_txtProxyPassword->text())); SilentNetworkAccessManager::instance()->loadSettings();
settings()->setValue(GROUP(Proxy), Proxy::Port, m_ui->m_spinProxyPort->value()); onEndSaveSettings();
// Reload settings for all network access managers.
SilentNetworkAccessManager::instance()->loadSettings();
onEndSaveSettings();
} }

View File

@ -24,29 +24,29 @@
class SettingsBrowserMail : public SettingsPanel { class SettingsBrowserMail : public SettingsPanel {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsBrowserMail(Settings *settings, QWidget *parent = 0); explicit SettingsBrowserMail(Settings* settings, QWidget* parent = 0);
virtual ~SettingsBrowserMail(); virtual ~SettingsBrowserMail();
inline QString title() const { inline QString title() const {
return tr("Web browser & e-mail & proxy"); return tr("Web browser & e-mail & proxy");
} }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
private slots: private slots:
void changeDefaultBrowserArguments(int index); void changeDefaultBrowserArguments(int index);
void selectBrowserExecutable(); void selectBrowserExecutable();
void changeDefaultEmailArguments(int index); void changeDefaultEmailArguments(int index);
void selectEmailExecutable(); void selectEmailExecutable();
void displayProxyPassword(int state); void displayProxyPassword(int state);
void onProxyTypeChanged(int index); void onProxyTypeChanged(int index);
private: private:
Ui::SettingsBrowserMail *m_ui; Ui::SettingsBrowserMail* m_ui;
}; };
#endif // SETTINGSBROWSERMAIL_H #endif // SETTINGSBROWSERMAIL_H

View File

@ -24,193 +24,183 @@
#include "gui/guiutilities.h" #include "gui/guiutilities.h"
SettingsDatabase::SettingsDatabase(Settings *settings, QWidget *parent) SettingsDatabase::SettingsDatabase(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsDatabase) { : SettingsPanel(settings, parent), m_ui(new Ui::SettingsDatabase) {
m_ui->setupUi(this); m_ui->setupUi(this);
GuiUtilities::setLabelAsNotice(m_ui->m_lblDataStorageWarning, true);
GuiUtilities::setLabelAsNotice(m_ui->m_lblDataStorageWarning, true); GuiUtilities::setLabelAsNotice(m_ui->m_lblMysqlInfo, false);
GuiUtilities::setLabelAsNotice(m_ui->m_lblMysqlInfo, false); GuiUtilities::setLabelAsNotice(m_ui->m_lblSqliteInMemoryWarnings, true);
GuiUtilities::setLabelAsNotice(m_ui->m_lblSqliteInMemoryWarnings, true); connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_txtMysqlDatabase->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_txtMysqlHostname->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlDatabase->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_txtMysqlPassword->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_checkUseTransactions, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_txtMysqlUsername->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_checkUseTransactions, &QCheckBox::toggled, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_spinMysqlPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsDatabase::dirtifySettings);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &QLineEdit::textChanged, this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::selectSqlBackend);
connect(m_ui->m_spinMysqlPort, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &SettingsDatabase::dirtifySettings); connect(m_ui->m_checkMysqlShowPassword, &QCheckBox::toggled, this, &SettingsDatabase::switchMysqlPasswordVisiblity);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlUsernameChanged);
connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::selectSqlBackend); connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlHostnameChanged);
connect(m_ui->m_checkMysqlShowPassword, &QCheckBox::toggled, this, &SettingsDatabase::switchMysqlPasswordVisiblity); connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlPasswordChanged);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlUsernameChanged); connect(m_ui->m_txtMysqlDatabase->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlDatabaseChanged);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlHostnameChanged); connect(m_ui->m_btnMysqlTestSetup, &QPushButton::clicked, this, &SettingsDatabase::mysqlTestConnection);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlPasswordChanged); connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlDatabase->lineEdit(), &BaseLineEdit::textChanged, this, &SettingsDatabase::onMysqlDatabaseChanged); connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_btnMysqlTestSetup, &QPushButton::clicked, this, &SettingsDatabase::mysqlTestConnection); connect(m_ui->m_spinMysqlPort, &QSpinBox::editingFinished, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_cmbDatabaseDriver, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &SettingsDatabase::requireRestart); connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_checkSqliteUseInMemoryDatabase, &QCheckBox::toggled, this, &SettingsDatabase::requireRestart); connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_spinMysqlPort, &QSpinBox::editingFinished, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlHostname->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlPassword->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
connect(m_ui->m_txtMysqlUsername->lineEdit(), &BaseLineEdit::textEdited, this, &SettingsDatabase::requireRestart);
} }
SettingsDatabase::~SettingsDatabase() { SettingsDatabase::~SettingsDatabase() {
delete m_ui; delete m_ui;
} }
void SettingsDatabase::mysqlTestConnection() { void SettingsDatabase::mysqlTestConnection() {
const DatabaseFactory::MySQLError error_code = qApp->database()->mysqlTestConnection(m_ui->m_txtMysqlHostname->lineEdit()->text(), const DatabaseFactory::MySQLError error_code = qApp->database()->mysqlTestConnection(m_ui->m_txtMysqlHostname->lineEdit()->text(),
m_ui->m_spinMysqlPort->value(), m_ui->m_spinMysqlPort->value(),
m_ui->m_txtMysqlDatabase->lineEdit()->text(), m_ui->m_txtMysqlDatabase->lineEdit()->text(),
m_ui->m_txtMysqlUsername->lineEdit()->text(), m_ui->m_txtMysqlUsername->lineEdit()->text(),
m_ui->m_txtMysqlPassword->lineEdit()->text()); m_ui->m_txtMysqlPassword->lineEdit()->text());
const QString interpretation = qApp->database()->mysqlInterpretErrorCode(error_code); 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) { default:
case DatabaseFactory::MySQLOk: m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Error, interpretation, interpretation);
case DatabaseFactory::MySQLUnknownDatabase: break;
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Ok, interpretation, interpretation); }
break;
default:
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Error, interpretation, interpretation);
break;
}
} }
void SettingsDatabase::onMysqlHostnameChanged(const QString &new_hostname) { void SettingsDatabase::onMysqlHostnameChanged(const QString& new_hostname) {
if (new_hostname.isEmpty()) { if (new_hostname.isEmpty()) {
m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Warning, tr("Hostname is empty.")); m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Warning, tr("Hostname is empty."));
} }
else {
m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Ok, tr("Hostname looks ok.")); else {
} m_ui->m_txtMysqlHostname->setStatus(LineEditWithStatus::Ok, tr("Hostname looks ok."));
}
} }
void SettingsDatabase::onMysqlUsernameChanged(const QString &new_username) { void SettingsDatabase::onMysqlUsernameChanged(const QString& new_username) {
if (new_username.isEmpty()) { if (new_username.isEmpty()) {
m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Warning, tr("Username is empty.")); m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Warning, tr("Username is empty."));
} }
else {
m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Ok, tr("Username looks ok.")); else {
} m_ui->m_txtMysqlUsername->setStatus(LineEditWithStatus::Ok, tr("Username looks ok."));
}
} }
void SettingsDatabase::onMysqlPasswordChanged(const QString &new_password) { void SettingsDatabase::onMysqlPasswordChanged(const QString& new_password) {
if (new_password.isEmpty()) { if (new_password.isEmpty()) {
m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Warning, tr("Password is empty.")); m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Warning, tr("Password is empty."));
} }
else {
m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Ok, tr("Password looks ok.")); else {
} m_ui->m_txtMysqlPassword->setStatus(LineEditWithStatus::Ok, tr("Password looks ok."));
}
} }
void SettingsDatabase::onMysqlDatabaseChanged(const QString &new_database) { void SettingsDatabase::onMysqlDatabaseChanged(const QString& new_database) {
if (new_database.isEmpty()) { if (new_database.isEmpty()) {
m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Warning, tr("Working database is empty.")); 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.")); else {
} m_ui->m_txtMysqlDatabase->setStatus(LineEditWithStatus::Ok, tr("Working database is ok."));
}
} }
void SettingsDatabase::selectSqlBackend(int index) { void SettingsDatabase::selectSqlBackend(int index) {
const QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(index).toString(); const QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(index).toString();
if (selected_db_driver == APP_DB_SQLITE_DRIVER) { if (selected_db_driver == APP_DB_SQLITE_DRIVER) {
m_ui->m_stackedDatabaseDriver->setCurrentIndex(0); m_ui->m_stackedDatabaseDriver->setCurrentIndex(0);
} }
else if (selected_db_driver == APP_DB_MYSQL_DRIVER) {
m_ui->m_stackedDatabaseDriver->setCurrentIndex(1); 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));
} else {
qWarning("GUI for given database driver '%s' is not available.", qPrintable(selected_db_driver));
}
} }
void SettingsDatabase::switchMysqlPasswordVisiblity(bool visible) { 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() { void SettingsDatabase::loadSettings() {
onBeginLoadSettings(); 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());
m_ui->m_checkUseTransactions->setChecked(qApp->settings()->value(GROUP(Database), SETTING(Database::UseTransactions)).toBool()); if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::Information, tr("No connection test triggered so far."), tr("You did not executed any connection test yet.")); 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. int index_current_backend = m_ui->m_cmbDatabaseDriver->findData(settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString());
m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::SQLITE), APP_DB_SQLITE_DRIVER);
// Load in-memory database status. if (index_current_backend >= 0) {
m_ui->m_checkSqliteUseInMemoryDatabase->setChecked(settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool()); m_ui->m_cmbDatabaseDriver->setCurrentIndex(index_current_backend);
}
if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) { onEndLoadSettings();
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);
}
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() { void SettingsDatabase::saveSettings() {
onBeginSaveSettings(); 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);
// Setup in-memory database status. if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
const bool original_inmemory = settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool(); // Save MySQL.
const bool new_inmemory = m_ui->m_checkSqliteUseInMemoryDatabase->isChecked(); 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());
}
qApp->settings()->setValue(GROUP(Database), Database::UseTransactions, m_ui->m_checkUseTransactions->isChecked()); settings()->setValue(GROUP(Database), Database::ActiveDriver, selected_db_driver);
// Save data storage settings. if (original_db_driver != selected_db_driver || original_inmemory != new_inmemory) {
QString original_db_driver = settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString(); requireRestart();
QString selected_db_driver = m_ui->m_cmbDatabaseDriver->itemData(m_ui->m_cmbDatabaseDriver->currentIndex()).toString(); }
// Save SQLite. onEndSaveSettings();
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

@ -24,29 +24,29 @@
class SettingsDatabase : public SettingsPanel { class SettingsDatabase : public SettingsPanel {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsDatabase(Settings *settings, QWidget *parent = 0); explicit SettingsDatabase(Settings* settings, QWidget* parent = 0);
virtual ~SettingsDatabase(); virtual ~SettingsDatabase();
inline QString title() const { inline QString title() const {
return tr("Data storage"); return tr("Data storage");
} }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
private: private:
void mysqlTestConnection(); void mysqlTestConnection();
void onMysqlHostnameChanged(const QString &new_hostname); void onMysqlHostnameChanged(const QString& new_hostname);
void onMysqlUsernameChanged(const QString &new_username); void onMysqlUsernameChanged(const QString& new_username);
void onMysqlPasswordChanged(const QString &new_password); void onMysqlPasswordChanged(const QString& new_password);
void onMysqlDatabaseChanged(const QString &new_database); void onMysqlDatabaseChanged(const QString& new_database);
void selectSqlBackend(int index); void selectSqlBackend(int index);
void switchMysqlPasswordVisiblity(bool visible); void switchMysqlPasswordVisiblity(bool visible);
Ui::SettingsDatabase *m_ui; Ui::SettingsDatabase* m_ui;
}; };
#endif // SETTINGSDATABASE_H #endif // SETTINGSDATABASE_H

View File

@ -24,52 +24,46 @@
#include <QFileDialog> #include <QFileDialog>
SettingsDownloads::SettingsDownloads(Settings *settings, QWidget *parent) SettingsDownloads::SettingsDownloads(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsDownloads) { : SettingsPanel(settings, parent), m_ui(new Ui::SettingsDownloads) {
m_ui->setupUi(this); m_ui->setupUi(this);
connect(m_ui->m_checkOpenManagerWhenDownloadStarts, &QCheckBox::toggled, this, &SettingsDownloads::dirtifySettings);
connect(m_ui->m_checkOpenManagerWhenDownloadStarts, &QCheckBox::toggled, this, &SettingsDownloads::dirtifySettings); connect(m_ui->m_txtDownloadsTargetDirectory, &QLineEdit::textChanged, this, &SettingsDownloads::dirtifySettings);
connect(m_ui->m_txtDownloadsTargetDirectory, &QLineEdit::textChanged, this, &SettingsDownloads::dirtifySettings); connect(m_ui->m_rbDownloadsAskEachFile, &QRadioButton::toggled, this, &SettingsDownloads::dirtifySettings);
connect(m_ui->m_rbDownloadsAskEachFile, &QRadioButton::toggled, this, &SettingsDownloads::dirtifySettings); connect(m_ui->m_btnDownloadsTargetDirectory, &QPushButton::clicked, this, &SettingsDownloads::selectDownloadsDirectory);
connect(m_ui->m_btnDownloadsTargetDirectory, &QPushButton::clicked, this, &SettingsDownloads::selectDownloadsDirectory);
} }
SettingsDownloads::~SettingsDownloads() { SettingsDownloads::~SettingsDownloads() {
delete m_ui; delete m_ui;
} }
void SettingsDownloads::selectDownloadsDirectory() { void SettingsDownloads::selectDownloadsDirectory() {
const QString target_directory = QFileDialog::getExistingDirectory(this, const QString target_directory = QFileDialog::getExistingDirectory(this,
tr("Select downloads target directory"), tr("Select downloads target directory"),
m_ui->m_txtDownloadsTargetDirectory->text() m_ui->m_txtDownloadsTargetDirectory->text()
); );
if (!target_directory.isEmpty()) { if (!target_directory.isEmpty()) {
m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(target_directory)); m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(target_directory));
} }
} }
void SettingsDownloads::loadSettings() { void SettingsDownloads::loadSettings() {
onBeginLoadSettings(); onBeginLoadSettings();
m_ui->m_checkOpenManagerWhenDownloadStarts->setChecked(settings()->value(GROUP(Downloads),
m_ui->m_checkOpenManagerWhenDownloadStarts->setChecked(settings()->value(GROUP(Downloads), SETTING(Downloads::ShowDownloadsWhenNewDownloadStarts)).toBool());
SETTING(Downloads::ShowDownloadsWhenNewDownloadStarts)).toBool()); m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(settings()->value(GROUP(Downloads),
m_ui->m_txtDownloadsTargetDirectory->setText(QDir::toNativeSeparators(settings()->value(GROUP(Downloads), SETTING(Downloads::TargetDirectory)).toString()));
SETTING(Downloads::TargetDirectory)).toString())); m_ui->m_rbDownloadsAskEachFile->setChecked(settings()->value(GROUP(Downloads),
m_ui->m_rbDownloadsAskEachFile->setChecked(settings()->value(GROUP(Downloads), SETTING(Downloads::AlwaysPromptForFilename)).toBool());
SETTING(Downloads::AlwaysPromptForFilename)).toBool()); onEndLoadSettings();
onEndLoadSettings();
} }
void SettingsDownloads::saveSettings() { void SettingsDownloads::saveSettings() {
onBeginSaveSettings(); onBeginSaveSettings();
settings()->setValue(GROUP(Downloads), Downloads::ShowDownloadsWhenNewDownloadStarts, m_ui->m_checkOpenManagerWhenDownloadStarts->isChecked());
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::TargetDirectory, m_ui->m_txtDownloadsTargetDirectory->text()); settings()->setValue(GROUP(Downloads), Downloads::AlwaysPromptForFilename, m_ui->m_rbDownloadsAskEachFile->isChecked());
settings()->setValue(GROUP(Downloads), Downloads::AlwaysPromptForFilename, m_ui->m_rbDownloadsAskEachFile->isChecked()); qApp->downloadManager()->setDownloadDirectory(m_ui->m_txtDownloadsTargetDirectory->text());
qApp->downloadManager()->setDownloadDirectory(m_ui->m_txtDownloadsTargetDirectory->text()); onEndSaveSettings();
onEndSaveSettings();
} }

View File

@ -24,24 +24,24 @@
class SettingsDownloads : public SettingsPanel { class SettingsDownloads : public SettingsPanel {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsDownloads(Settings *settings, QWidget *parent = 0); explicit SettingsDownloads(Settings* settings, QWidget* parent = 0);
virtual ~SettingsDownloads(); virtual ~SettingsDownloads();
inline QString title() const { inline QString title() const {
return tr("Downloads"); return tr("Downloads");
} }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
private slots: private slots:
void selectDownloadsDirectory(); void selectDownloadsDirectory();
private: private:
Ui::SettingsDownloads *m_ui; Ui::SettingsDownloads* m_ui;
}; };
#endif // SETTINGSDOWNLOADS_H #endif // SETTINGSDOWNLOADS_H

View File

@ -30,121 +30,110 @@
#include <QFontDialog> #include <QFontDialog>
SettingsFeedsMessages::SettingsFeedsMessages(Settings *settings, QWidget *parent) SettingsFeedsMessages::SettingsFeedsMessages(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsFeedsMessages){ : SettingsPanel(settings, parent), m_ui(new Ui::SettingsFeedsMessages) {
m_ui->setupUi(this); m_ui->setupUi(this);
initializeMessageDateFormats(); initializeMessageDateFormats();
GuiUtilities::setLabelAsNotice(m_ui->label_9, false);
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);
GuiUtilities::setLabelAsNotice(m_ui->label_9, false); if (!m_ui->m_spinFeedUpdateTimeout->suffix().startsWith(' ')) {
m_ui->m_spinFeedUpdateTimeout->setSuffix(QSL(" ") + m_ui->m_spinFeedUpdateTimeout->suffix());
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());
}
} }
SettingsFeedsMessages::~SettingsFeedsMessages() { SettingsFeedsMessages::~SettingsFeedsMessages() {
delete m_ui; delete m_ui;
} }
void SettingsFeedsMessages::initializeMessageDateFormats() { void SettingsFeedsMessages::initializeMessageDateFormats() {
QStringList best_formats; best_formats << QSL("d/M/yyyy hh:mm:ss") << QSL("ddd, d. M. yy hh:mm:ss") << QStringList best_formats;
QSL("yyyy-MM-dd HH:mm:ss.z") << QSL("yyyy-MM-ddThh:mm:ss") << best_formats << QSL("d/M/yyyy hh:mm:ss") << QSL("ddd, d. M. yy hh:mm:ss") <<
QSL("MMM d yyyy hh:mm:ss");; QSL("yyyy-MM-dd HH:mm:ss.z") << QSL("yyyy-MM-ddThh:mm:ss") <<
const QLocale current_locale = qApp->localization()->loadedLocale(); QSL("MMM d yyyy hh:mm:ss");;
const QDateTime current_dt = QDateTime::currentDateTime(); const QLocale current_locale = qApp->localization()->loadedLocale();
const QDateTime current_dt = QDateTime::currentDateTime();
foreach (const QString &format, best_formats) { foreach (const QString& format, best_formats) {
m_ui->m_cmbMessagesDateTimeFormat->addItem(current_locale.toString(current_dt, format), format); m_ui->m_cmbMessagesDateTimeFormat->addItem(current_locale.toString(current_dt, format), format);
} }
} }
void SettingsFeedsMessages::changeMessagesFont() { void SettingsFeedsMessages::changeMessagesFont() {
bool ok; bool ok;
QFont new_font = QFontDialog::getFont(&ok, m_ui->m_lblMessagesFont->font(), QFont new_font = QFontDialog::getFont(&ok, m_ui->m_lblMessagesFont->font(),
this, tr("Select new font for message viewer"), this, tr("Select new font for message viewer"),
QFontDialog::DontUseNativeDialog); QFontDialog::DontUseNativeDialog);
if (ok) { if (ok) {
m_ui->m_lblMessagesFont->setFont(new_font); m_ui->m_lblMessagesFont->setFont(new_font);
dirtifySettings(); dirtifySettings();
} }
} }
void SettingsFeedsMessages::loadSettings() { void SettingsFeedsMessages::loadSettings() {
onBeginLoadSettings(); 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());
m_ui->m_checkAutoUpdateNotification->setChecked(settings()->value(GROUP(Feeds), SETTING(Feeds::EnableAutoUpdateNotification)).toBool()); if (index_format >= 0) {
m_ui->m_checkKeppMessagesInTheMiddle->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::KeepCursorInCenter)).toBool()); m_ui->m_cmbMessagesDateTimeFormat->setCurrentIndex(index_format);
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_lblMessagesFont->setText(tr("Font preview"));
QFont fon;
m_ui->m_checkMessagesDateTimeFormat->setChecked(settings()->value(GROUP(Messages), SETTING(Messages::UseCustomDate)).toBool()); fon.fromString(settings()->value(GROUP(Messages),
const int index_format = m_ui->m_cmbMessagesDateTimeFormat->findData(settings()->value(GROUP(Messages), SETTING(Messages::CustomDateFormat)).toString()); SETTING(Messages::PreviewerFontStandard)).toString());
m_ui->m_lblMessagesFont->setFont(fon);
if (index_format >= 0) { onEndLoadSettings();
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();
} }
void SettingsFeedsMessages::saveSettings() { void SettingsFeedsMessages::saveSettings() {
onBeginSaveSettings(); onBeginSaveSettings();
settings()->setValue(GROUP(Feeds), Feeds::EnableAutoUpdateNotification, m_ui->m_checkAutoUpdateNotification->isChecked());
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::KeepCursorInCenter, m_ui->m_checkKeppMessagesInTheMiddle->isChecked()); settings()->setValue(GROUP(Messages), Messages::ClearReadOnExit, m_ui->m_checkRemoveReadMessagesOnExit->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::AutoUpdateEnabled, m_ui->m_checkAutoUpdate->isChecked()); settings()->setValue(GROUP(Feeds), Feeds::AutoUpdateInterval, m_ui->m_spinAutoUpdateInterval->value());
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::UpdateTimeout, m_ui->m_spinFeedUpdateTimeout->value()); settings()->setValue(GROUP(Feeds), Feeds::FeedsUpdateOnStartup, m_ui->m_checkUpdateAllFeedsOnStartup->isChecked());
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(Feeds), Feeds::CountFormat, m_ui->m_cmbCountsFeedList->currentText()); settings()->setValue(GROUP(Messages), Messages::UseCustomDate, m_ui->m_checkMessagesDateTimeFormat->isChecked());
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::MessageHeadImageHeight, m_ui->m_spinHeightImageAttachments->value()); settings()->setValue(GROUP(Messages), Messages::CustomDateFormat,
settings()->setValue(GROUP(Messages), Messages::CustomDateFormat, m_ui->m_cmbMessagesDateTimeFormat->itemData(m_ui->m_cmbMessagesDateTimeFormat->currentIndex()).toString());
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());
// Save fonts. qApp->mainForm()->tabWidget()->feedMessageViewer()->loadMessageViewerFonts();
settings()->setValue(GROUP(Messages), Messages::PreviewerFontStandard, m_ui->m_lblMessagesFont->font().toString()); qApp->feedReader()->updateAutoUpdateStatus();
qApp->feedReader()->feedsModel()->reloadWholeLayout();
qApp->mainForm()->tabWidget()->feedMessageViewer()->loadMessageViewerFonts(); qApp->feedReader()->messagesModel()->updateDateFormat();
qApp->feedReader()->messagesModel()->reloadWholeLayout();
qApp->feedReader()->updateAutoUpdateStatus(); onEndSaveSettings();
qApp->feedReader()->feedsModel()->reloadWholeLayout();
qApp->feedReader()->messagesModel()->updateDateFormat();
qApp->feedReader()->messagesModel()->reloadWholeLayout();
onEndSaveSettings();
} }

View File

@ -24,26 +24,26 @@
class SettingsFeedsMessages : public SettingsPanel { class SettingsFeedsMessages : public SettingsPanel {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsFeedsMessages(Settings *settings, QWidget *parent = 0); explicit SettingsFeedsMessages(Settings* settings, QWidget* parent = 0);
virtual ~SettingsFeedsMessages(); virtual ~SettingsFeedsMessages();
inline QString title() const { inline QString title() const {
return tr("Feeds & messages"); return tr("Feeds & messages");
} }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
private slots: private slots:
void changeMessagesFont(); void changeMessagesFont();
private: private:
void initializeMessageDateFormats(); void initializeMessageDateFormats();
Ui::SettingsFeedsMessages *m_ui; Ui::SettingsFeedsMessages* m_ui;
}; };
#endif // SETTINGSFEEDSMESSAGES_H #endif // SETTINGSFEEDSMESSAGES_H

View File

@ -21,66 +21,62 @@
#include "miscellaneous/application.h" #include "miscellaneous/application.h"
SettingsGeneral::SettingsGeneral(Settings *settings, QWidget *parent) SettingsGeneral::SettingsGeneral(Settings* settings, QWidget* parent)
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsGeneral) { : SettingsPanel(settings, parent), m_ui(new Ui::SettingsGeneral) {
m_ui->setupUi(this); m_ui->setupUi(this);
m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text().arg(APP_NAME)); m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text().arg(APP_NAME));
connect(m_ui->m_checkAutostart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings);
connect(m_ui->m_checkAutostart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings); connect(m_ui->m_checkForUpdatesOnStart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings);
connect(m_ui->m_checkForUpdatesOnStart, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings); connect(m_ui->m_checkRemoveTrolltechJunk, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings);
connect(m_ui->m_checkRemoveTrolltechJunk, &QCheckBox::stateChanged, this, &SettingsGeneral::dirtifySettings);
} }
SettingsGeneral::~SettingsGeneral() { SettingsGeneral::~SettingsGeneral() {
delete m_ui; delete m_ui;
} }
void SettingsGeneral::loadSettings() { void SettingsGeneral::loadSettings() {
onBeginLoadSettings(); onBeginLoadSettings();
m_ui->m_checkForUpdatesOnStart->setChecked(settings()->value(GROUP(General), SETTING(General::UpdateOnStartup)).toBool());
// Load auto-start status.
const SystemFactory::AutoStartStatus autostart_status = qApp->system()->getAutoStartStatus();
m_ui->m_checkForUpdatesOnStart->setChecked(settings()->value(GROUP(General), SETTING(General::UpdateOnStartup)).toBool()); switch (autostart_status) {
case SystemFactory::Enabled:
m_ui->m_checkAutostart->setChecked(true);
break;
// Load auto-start status. case SystemFactory::Disabled:
const SystemFactory::AutoStartStatus autostart_status = qApp->system()->getAutoStartStatus(); m_ui->m_checkAutostart->setChecked(false);
break;
switch (autostart_status) { default:
case SystemFactory::Enabled: m_ui->m_checkAutostart->setEnabled(false);
m_ui->m_checkAutostart->setChecked(true); m_ui->m_checkAutostart->setText(m_ui->m_checkAutostart->text() + tr(" (not supported on this platform)"));
break; break;
}
case SystemFactory::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) #if defined(Q_OS_WIN)
m_ui->m_checkRemoveTrolltechJunk->setVisible(true); m_ui->m_checkRemoveTrolltechJunk->setVisible(true);
m_ui->m_checkRemoveTrolltechJunk->setChecked(settings()->value(GROUP(General), SETTING(General::RemoveTrolltechJunk)).toBool()); m_ui->m_checkRemoveTrolltechJunk->setChecked(settings()->value(GROUP(General), SETTING(General::RemoveTrolltechJunk)).toBool());
#else #else
m_ui->m_checkRemoveTrolltechJunk->setVisible(false); m_ui->m_checkRemoveTrolltechJunk->setVisible(false);
#endif #endif
onEndLoadSettings();
onEndLoadSettings();
} }
void SettingsGeneral::saveSettings() { void SettingsGeneral::saveSettings() {
onBeginSaveSettings(); onBeginSaveSettings();
// If auto-start feature is available and user wants to turn it on, then turn it on. // If auto-start feature is available and user wants to turn it on, then turn it on.
if (m_ui->m_checkAutostart->isChecked()) { if (m_ui->m_checkAutostart->isChecked()) {
qApp->system()->setAutoStartStatus(SystemFactory::Enabled); qApp->system()->setAutoStartStatus(SystemFactory::Enabled);
} }
else {
qApp->system()->setAutoStartStatus(SystemFactory::Disabled);
}
settings()->setValue(GROUP(General), General::UpdateOnStartup, m_ui->m_checkForUpdatesOnStart->isChecked()); else {
settings()->setValue(GROUP(General), General::RemoveTrolltechJunk, m_ui->m_checkRemoveTrolltechJunk->isChecked()); qApp->system()->setAutoStartStatus(SystemFactory::Disabled);
}
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

@ -24,21 +24,21 @@
class SettingsGeneral : public SettingsPanel { class SettingsGeneral : public SettingsPanel {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsGeneral(Settings *settings, QWidget *parent = 0); explicit SettingsGeneral(Settings* settings, QWidget* parent = 0);
virtual ~SettingsGeneral(); virtual ~SettingsGeneral();
inline QString title() const { inline QString title() const {
return tr("General"); return tr("General");
} }
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
private: private:
Ui::SettingsGeneral *m_ui; Ui::SettingsGeneral* m_ui;
}; };
#endif // SETTINGSGENERAL_H #endif // SETTINGSGENERAL_H

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