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>
FeedDownloader::FeedDownloader(QObject *parent)
: QObject(parent), m_feeds(QList<Feed*>()), m_mutex(new QMutex()), m_threadPool(new QThreadPool(this)),
m_results(FeedDownloadResults()), m_feedsUpdated(0),
m_feedsUpdating(0), m_feedsOriginalCount(0) {
qRegisterMetaType<FeedDownloadResults>("FeedDownloadResults");
m_threadPool->setMaxThreadCount(FEED_DOWNLOADER_MAX_THREADS);
FeedDownloader::FeedDownloader(QObject* parent)
: QObject(parent), m_feeds(QList<Feed*>()), m_mutex(new QMutex()), m_threadPool(new QThreadPool(this)),
m_results(FeedDownloadResults()), m_feedsUpdated(0),
m_feedsUpdating(0), m_feedsOriginalCount(0) {
qRegisterMetaType<FeedDownloadResults>("FeedDownloadResults");
m_threadPool->setMaxThreadCount(FEED_DOWNLOADER_MAX_THREADS);
}
FeedDownloader::~FeedDownloader() {
m_mutex->tryLock();
m_mutex->unlock();
delete m_mutex;
qDebug("Destroying FeedDownloader instance.");
m_mutex->tryLock();
m_mutex->unlock();
delete m_mutex;
qDebug("Destroying FeedDownloader instance.");
}
bool FeedDownloader::isUpdateRunning() const {
return !m_feeds.isEmpty() || m_feedsUpdating > 0;
return !m_feeds.isEmpty() || m_feedsUpdating > 0;
}
void FeedDownloader::updateAvailableFeeds() {
while (!m_feeds.isEmpty()) {
connect(m_feeds.first(), &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished,
(Qt::ConnectionType) (Qt::UniqueConnection | Qt::AutoConnection));
if (m_threadPool->tryStart(m_feeds.first())) {
m_feeds.removeFirst();
m_feedsUpdating++;
}
else {
// We want to start update of some feeds but all working threads are occupied.
break;
}
}
while (!m_feeds.isEmpty()) {
connect(m_feeds.first(), &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished,
(Qt::ConnectionType)(Qt::UniqueConnection | Qt::AutoConnection));
if (m_threadPool->tryStart(m_feeds.first())) {
m_feeds.removeFirst();
m_feedsUpdating++;
}
else {
// We want to start update of some feeds but all working threads are occupied.
break;
}
}
}
void FeedDownloader::updateFeeds(const QList<Feed*> &feeds) {
QMutexLocker locker(m_mutex);
void FeedDownloader::updateFeeds(const QList<Feed*>& feeds) {
QMutexLocker locker(m_mutex);
if (feeds.isEmpty()) {
qDebug("No feeds to update in worker thread, aborting update.");
finalizeUpdate();
}
else {
qDebug().nospace() << "Starting feed updates from worker in thread: \'" << QThread::currentThreadId() << "\'.";
if (feeds.isEmpty()) {
qDebug("No feeds to update in worker thread, aborting update.");
finalizeUpdate();
}
m_feeds = feeds;
m_feedsOriginalCount = m_feeds.size();
m_results.clear();
m_feedsUpdated = m_feedsUpdating = 0;
// Job starts now.
emit updateStarted();
updateAvailableFeeds();
}
else {
qDebug().nospace() << "Starting feed updates from worker in thread: \'" << QThread::currentThreadId() << "\'.";
m_feeds = feeds;
m_feedsOriginalCount = m_feeds.size();
m_results.clear();
m_feedsUpdated = m_feedsUpdating = 0;
// Job starts now.
emit updateStarted();
updateAvailableFeeds();
}
}
void FeedDownloader::stopRunningUpdate() {
m_threadPool->clear();
m_feeds.clear();
m_threadPool->clear();
m_feeds.clear();
}
void FeedDownloader::oneFeedUpdateFinished(const QList<Message> &messages, bool error_during_obtaining) {
QMutexLocker locker(m_mutex);
void FeedDownloader::oneFeedUpdateFinished(const QList<Message>& messages, bool error_during_obtaining) {
QMutexLocker locker(m_mutex);
m_feedsUpdated++;
m_feedsUpdating--;
Feed* feed = qobject_cast<Feed*>(sender());
disconnect(feed, &Feed::messagesObtained, this, &FeedDownloader::oneFeedUpdateFinished);
// Now, we check if there are any feeds we would like to update too.
updateAvailableFeeds();
// Now make sure, that messages are actually stored to SQL in a locked state.
qDebug().nospace() << "Saving messages of feed "
<< feed->id() << " in thread: \'"
<< QThread::currentThreadId() << "\'.";
int updated_messages = feed->updateMessages(messages, error_during_obtaining);
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.
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);
/*
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();
}
if (m_feeds.isEmpty() && m_feedsUpdating <= 0) {
finalizeUpdate();
}
}
void FeedDownloader::finalizeUpdate() {
qDebug().nospace() << "Finished feed updates in thread: \'" << QThread::currentThreadId() << "\'.";
m_results.sort();
// Update of feeds has finished.
// NOTE: This means that now "update lock" can be unlocked
// and feeds can be added/edited/deleted and application
// can eventually quit.
emit updateFinished(m_results);
qDebug().nospace() << "Finished feed updates in thread: \'" << QThread::currentThreadId() << "\'.";
m_results.sort();
// Update of feeds has finished.
// NOTE: This means that now "update lock" can be unlocked
// and feeds can be added/edited/deleted and application
// can eventually quit.
emit updateFinished(m_results);
}
FeedDownloadResults::FeedDownloadResults() : m_updatedFeeds(QList<QPair<QString,int> >()) {
FeedDownloadResults::FeedDownloadResults() : m_updatedFeeds(QList<QPair<QString, int>>()) {
}
QString FeedDownloadResults::overview(int how_many_feeds) const {
QStringList result;
QStringList result;
for (int i = 0, number_items_output = qMin(how_many_feeds, m_updatedFeeds.size()); i < number_items_output; i++) {
result.append(m_updatedFeeds.at(i).first + QSL(": ") + QString::number(m_updatedFeeds.at(i).second));
}
for (int i = 0, number_items_output = qMin(how_many_feeds, m_updatedFeeds.size()); i < number_items_output; i++) {
result.append(m_updatedFeeds.at(i).first + QSL(": ") + QString::number(m_updatedFeeds.at(i).second));
}
QString res_str = result.join(QSL("\n"));
QString res_str = result.join(QSL("\n"));
if (m_updatedFeeds.size() > how_many_feeds) {
res_str += QObject::tr("\n\n+ %n other feeds.", 0, m_updatedFeeds.size() - how_many_feeds);
}
if (m_updatedFeeds.size() > how_many_feeds) {
res_str += QObject::tr("\n\n+ %n other feeds.", 0, m_updatedFeeds.size() - how_many_feeds);
}
return res_str;
return res_str;
}
void FeedDownloadResults::appendUpdatedFeed(const QPair<QString,int> &feed) {
m_updatedFeeds.append(feed);
void FeedDownloadResults::appendUpdatedFeed(const QPair<QString, int>& feed) {
m_updatedFeeds.append(feed);
}
void FeedDownloadResults::sort() {
qSort(m_updatedFeeds.begin(), m_updatedFeeds.end(), FeedDownloadResults::lessThan);
qSort(m_updatedFeeds.begin(), m_updatedFeeds.end(), FeedDownloadResults::lessThan);
}
bool FeedDownloadResults::lessThan(const QPair<QString, int> &lhs, const QPair<QString, int> &rhs) {
return lhs.second > rhs.second;
bool FeedDownloadResults::lessThan(const QPair<QString, int>& lhs, const QPair<QString, int>& rhs) {
return lhs.second > rhs.second;
}
void FeedDownloadResults::clear() {
m_updatedFeeds.clear();
m_updatedFeeds.clear();
}
QList<QPair<QString,int> > FeedDownloadResults::updatedFeeds() const {
return m_updatedFeeds;
QList<QPair<QString, int>> FeedDownloadResults::updatedFeeds() const {
return m_updatedFeeds;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,20 +20,20 @@
#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() {
}
void MessagesModelCache::setData(const QModelIndex &index, const QVariant &value, const QSqlRecord &record) {
if (!m_msgCache.contains(index.row())) {
m_msgCache[index.row()] = record;
}
void MessagesModelCache::setData(const QModelIndex& index, const QVariant& value, const QSqlRecord& record) {
if (!m_msgCache.contains(index.row())) {
m_msgCache[index.row()] = record;
}
m_msgCache[index.row()].setValue(index.column(), value);
m_msgCache[index.row()].setValue(index.column(), value);
}
QVariant MessagesModelCache::data(const QModelIndex &idx) {
return m_msgCache[idx.row()].value(idx.column());
QVariant MessagesModelCache::data(const QModelIndex& idx) {
return m_msgCache[idx.row()].value(idx.column());
}

View File

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

View File

@ -22,84 +22,84 @@
MessagesModelSqlLayer::MessagesModelSqlLayer()
: m_filter(QSL(DEFAULT_SQL_MESSAGES_FILTER)), m_fieldNames(QMap<int,QString>()),
m_sortColumns(QList<int>()), m_sortOrders(QList<Qt::SortOrder>()){
m_db = qApp->database()->connection(QSL("MessagesModel"), DatabaseFactory::FromSettings);
m_fieldNames[MSG_DB_ID_INDEX] = "Messages.id";
m_fieldNames[MSG_DB_READ_INDEX] = "Messages.is_read";
m_fieldNames[MSG_DB_DELETED_INDEX] = "Messages.is_deleted";
m_fieldNames[MSG_DB_IMPORTANT_INDEX] = "Messages.is_important";
m_fieldNames[MSG_DB_FEED_TITLE_INDEX] = "Feeds.title";
m_fieldNames[MSG_DB_TITLE_INDEX] = "Messages.title";
m_fieldNames[MSG_DB_URL_INDEX] = "Messages.url";
m_fieldNames[MSG_DB_AUTHOR_INDEX] = "Messages.author";
m_fieldNames[MSG_DB_DCREATED_INDEX] = "Messages.date_created";
m_fieldNames[MSG_DB_CONTENTS_INDEX] = "Messages.contents";
m_fieldNames[MSG_DB_PDELETED_INDEX] = "Messages.is_pdeleted";
m_fieldNames[MSG_DB_ENCLOSURES_INDEX] = "Messages.enclosures";
m_fieldNames[MSG_DB_ACCOUNT_ID_INDEX] = "Messages.account_id";
m_fieldNames[MSG_DB_CUSTOM_ID_INDEX] = "Messages.custom_id";
m_fieldNames[MSG_DB_CUSTOM_HASH_INDEX] = "Messages.custom_hash";
m_fieldNames[MSG_DB_FEED_CUSTOM_ID_INDEX] = "Messages.feed";
: m_filter(QSL(DEFAULT_SQL_MESSAGES_FILTER)), m_fieldNames(QMap<int, QString>()),
m_sortColumns(QList<int>()), m_sortOrders(QList<Qt::SortOrder>()) {
m_db = qApp->database()->connection(QSL("MessagesModel"), DatabaseFactory::FromSettings);
m_fieldNames[MSG_DB_ID_INDEX] = "Messages.id";
m_fieldNames[MSG_DB_READ_INDEX] = "Messages.is_read";
m_fieldNames[MSG_DB_DELETED_INDEX] = "Messages.is_deleted";
m_fieldNames[MSG_DB_IMPORTANT_INDEX] = "Messages.is_important";
m_fieldNames[MSG_DB_FEED_TITLE_INDEX] = "Feeds.title";
m_fieldNames[MSG_DB_TITLE_INDEX] = "Messages.title";
m_fieldNames[MSG_DB_URL_INDEX] = "Messages.url";
m_fieldNames[MSG_DB_AUTHOR_INDEX] = "Messages.author";
m_fieldNames[MSG_DB_DCREATED_INDEX] = "Messages.date_created";
m_fieldNames[MSG_DB_CONTENTS_INDEX] = "Messages.contents";
m_fieldNames[MSG_DB_PDELETED_INDEX] = "Messages.is_pdeleted";
m_fieldNames[MSG_DB_ENCLOSURES_INDEX] = "Messages.enclosures";
m_fieldNames[MSG_DB_ACCOUNT_ID_INDEX] = "Messages.account_id";
m_fieldNames[MSG_DB_CUSTOM_ID_INDEX] = "Messages.custom_id";
m_fieldNames[MSG_DB_CUSTOM_HASH_INDEX] = "Messages.custom_hash";
m_fieldNames[MSG_DB_FEED_CUSTOM_ID_INDEX] = "Messages.feed";
}
void MessagesModelSqlLayer::addSortState(int column, Qt::SortOrder order) {
int existing = m_sortColumns.indexOf(column);
bool is_ctrl_pressed = (QApplication::queryKeyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier;
int existing = m_sortColumns.indexOf(column);
bool is_ctrl_pressed = (QApplication::queryKeyboardModifiers() & Qt::ControlModifier) == Qt::ControlModifier;
if (existing >= 0) {
m_sortColumns.removeAt(existing);
m_sortOrders.removeAt(existing);
}
if (existing >= 0) {
m_sortColumns.removeAt(existing);
m_sortOrders.removeAt(existing);
}
if (m_sortColumns.size() > MAX_MULTICOLUMN_SORT_STATES) {
// We support only limited number of sort states
// due to DB performance.
m_sortColumns.removeAt(0);
m_sortOrders.removeAt(0);
}
if (m_sortColumns.size() > MAX_MULTICOLUMN_SORT_STATES) {
// We support only limited number of sort states
// due to DB performance.
m_sortColumns.removeAt(0);
m_sortOrders.removeAt(0);
}
if (is_ctrl_pressed) {
// User is activating the multicolumn sort mode.
m_sortColumns.append(column);
m_sortOrders.append(order);
}
else {
m_sortColumns.prepend(column);
m_sortOrders.prepend(order);
}
if (is_ctrl_pressed) {
// User is activating the multicolumn sort mode.
m_sortColumns.append(column);
m_sortOrders.append(order);
}
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) {
m_filter = filter;
void MessagesModelSqlLayer::setFilter(const QString& filter) {
m_filter = filter;
}
QString MessagesModelSqlLayer::formatFields() const {
return m_fieldNames.values().join(QSL(", "));
return m_fieldNames.values().join(QSL(", "));
}
QString MessagesModelSqlLayer::selectStatement() const {
return QL1S("SELECT ") + formatFields() +
QSL(" FROM Messages LEFT JOIN Feeds ON Messages.feed = Feeds.custom_id AND Messages.account_id = Feeds.account_id WHERE ") +
m_filter + orderByClause() + QL1C(';');
return QL1S("SELECT ") + formatFields() +
QSL(" FROM Messages LEFT JOIN Feeds ON Messages.feed = Feeds.custom_id AND Messages.account_id = Feeds.account_id WHERE ") +
m_filter + orderByClause() + QL1C(';');
}
QString MessagesModelSqlLayer::orderByClause() const {
if (m_sortColumns.isEmpty()) {
return QString();
}
else {
QStringList sorts;
if (m_sortColumns.isEmpty()) {
return QString();
}
for (int i = 0; i < m_sortColumns.size(); i++) {
QString field_name(m_fieldNames[m_sortColumns[i]]);
else {
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 {
public:
explicit MessagesModelSqlLayer();
public:
explicit MessagesModelSqlLayer();
// Adds this new state to queue of sort states.
void addSortState(int column, Qt::SortOrder order);
// Adds this new state to queue of sort states.
void addSortState(int column, Qt::SortOrder order);
// Sets SQL WHERE clause, without "WHERE" keyword.
void setFilter(const QString &filter);
// Sets SQL WHERE clause, without "WHERE" keyword.
void setFilter(const QString& filter);
protected:
QString orderByClause() const;
QString selectStatement() const;
QString formatFields() const;
protected:
QString orderByClause() const;
QString selectStatement() const;
QString formatFields() const;
QSqlDatabase m_db;
QSqlDatabase m_db;
private:
QString m_filter;
private:
QString m_filter;
// NOTE: These two lists contain data for multicolumn sorting.
// They are always same length. Most important sort column/order
// are located at the start of lists;
QMap<int,QString> m_fieldNames;
QList<int> m_sortColumns;
QList<Qt::SortOrder> m_sortOrders;
// NOTE: These two lists contain data for multicolumn sorting.
// They are always same length. Most important sort column/order
// are located at the start of lists;
QMap<int, QString> m_fieldNames;
QList<int> m_sortColumns;
QList<Qt::SortOrder> m_sortOrders;
};
#endif // MESSAGESMODELSQLLAYER_H

View File

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

View File

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

View File

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

View File

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

View File

@ -26,93 +26,85 @@
#include <QLabel>
DynamicShortcutsWidget::DynamicShortcutsWidget(QWidget *parent) : QWidget(parent) {
// Create layout for this control and set is as active.
m_layout = new QGridLayout(this);
m_layout->setMargin(0);
setLayout(m_layout);
DynamicShortcutsWidget::DynamicShortcutsWidget(QWidget* parent) : QWidget(parent) {
// Create layout for this control and set is as active.
m_layout = new QGridLayout(this);
m_layout->setMargin(0);
setLayout(m_layout);
}
DynamicShortcutsWidget::~DynamicShortcutsWidget() {
delete m_layout;
delete m_layout;
}
bool DynamicShortcutsWidget::areShortcutsUnique() const {
QList<QKeySequence> all_shortcuts;
QList<QKeySequence> all_shortcuts;
// Obtain all shortcuts.
foreach (const ActionBinding &binding, m_actionBindings) {
const QKeySequence new_shortcut = binding.second->shortcut();
// Obtain all shortcuts.
foreach (const ActionBinding& binding, m_actionBindings) {
const QKeySequence new_shortcut = binding.second->shortcut();
if (!new_shortcut.isEmpty() && all_shortcuts.contains(new_shortcut)) {
// Problem, two identical non-empty shortcuts found.
return false;
}
else {
all_shortcuts.append(binding.second->shortcut());
}
}
if (!new_shortcut.isEmpty() && all_shortcuts.contains(new_shortcut)) {
// Problem, two identical non-empty shortcuts found.
return false;
}
return true;
else {
all_shortcuts.append(binding.second->shortcut());
}
}
return true;
}
void DynamicShortcutsWidget::updateShortcuts() {
foreach (const ActionBinding &binding, m_actionBindings) {
binding.first->setShortcut(binding.second->shortcut());
}
foreach (const ActionBinding& binding, m_actionBindings) {
binding.first->setShortcut(binding.second->shortcut());
}
}
void DynamicShortcutsWidget::populate(QList<QAction*> actions) {
m_actionBindings.clear();
qSort(actions.begin(), actions.end(), DynamicShortcutsWidget::lessThan);
m_actionBindings.clear();
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.
// I will assign each QAaction a property called "category" with some enum value.
// Like:
// File, FeedsCategories, Messages, Tools, WebBrowser, Help
// This will be setup in FormMain::allActions().
// Then here I will process actions into categories.
foreach (QAction* action, actions) {
// Create shortcut catcher for this action and set default shortcut.
ShortcutCatcher* catcher = new ShortcutCatcher(this);
catcher->setDefaultShortcut(action->shortcut());
// Store information for re-initialization of shortcuts
// of actions when widget gets "confirmed".
QPair<QAction*, ShortcutCatcher*> new_binding;
new_binding.first = action;
new_binding.second = catcher;
m_actionBindings << new_binding;
// Add new catcher to our control.
QLabel* action_label = new QLabel(this);
action_label->setText(action->text().remove(QSL("&")));
action_label->setToolTip(action->toolTip());
action_label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
QLabel* action_icon = new QLabel(this);
action_icon->setPixmap(action->icon().pixmap(ICON_SIZE_SETTINGS, ICON_SIZE_SETTINGS));
action_icon->setToolTip(action->toolTip());
m_layout->addWidget(action_icon, row_id, 0);
m_layout->addWidget(action_label, row_id, 1);
m_layout->addWidget(catcher, row_id, 2);
row_id++;
connect(catcher, &ShortcutCatcher::shortcutChanged, this, &DynamicShortcutsWidget::setupChanged);
}
foreach (QAction *action, actions) {
// Create shortcut catcher for this action and set default shortcut.
ShortcutCatcher *catcher = new ShortcutCatcher(this);
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);
// Make sure that "spacer" is added.
m_layout->setRowStretch(row_id, 1);
m_layout->setColumnStretch(1, 1);
}
bool DynamicShortcutsWidget::lessThan(QAction *lhs, QAction *rhs) {
return QString::localeAwareCompare(lhs->text().replace(QL1S("&"), QString()), rhs->text().replace(QL1S("&"), QString())) < 0;
bool DynamicShortcutsWidget::lessThan(QAction* lhs, QAction* rhs) {
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;
class DynamicShortcutsWidget : public QWidget {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit DynamicShortcutsWidget(QWidget *parent = 0);
virtual ~DynamicShortcutsWidget();
public:
// Constructors and destructors.
explicit DynamicShortcutsWidget(QWidget* parent = 0);
virtual ~DynamicShortcutsWidget();
// Updates shortcuts of all actions according to changes.
// NOTE: No access to settings is done here.
// Shortcuts are fetched from settings when applications starts
// and stored back to settings when application quits.
void updateShortcuts();
// Updates shortcuts of all actions according to changes.
// NOTE: No access to settings is done here.
// Shortcuts are fetched from settings when applications starts
// and stored back to settings when application quits.
void updateShortcuts();
// Returns true if all shortcuts are unique,
// otherwise false.
bool areShortcutsUnique() const;
// Returns true if all shortcuts are unique,
// otherwise false.
bool areShortcutsUnique() const;
// Populates this widget with shortcut widgets for given actions.
// NOTE: This gets initial shortcut for each action from its properties, NOT from
// the application settings, so shortcuts from settings need to be
// assigned to actions before calling this method.
void populate(QList<QAction*> actions);
// Populates this widget with shortcut widgets for given actions.
// NOTE: This gets initial shortcut for each action from its properties, NOT from
// the application settings, so shortcuts from settings need to be
// assigned to actions before calling this method.
void populate(QList<QAction*> actions);
signals:
void setupChanged();
signals:
void setupChanged();
private:
static bool lessThan(QAction *lhs, QAction *rhs);
private:
static bool lessThan(QAction* lhs, QAction* rhs);
private:
QGridLayout *m_layout;
QList<ActionBinding> m_actionBindings;
private:
QGridLayout* m_layout;
QList<ActionBinding> m_actionBindings;
};
#endif // DYNAMICSHORTCUTSOVERVIEW_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -25,98 +25,98 @@
#include <QTextStream>
FormAbout::FormAbout(QWidget *parent) : QDialog(parent), m_ui(new Ui::FormAbout()) {
m_ui->setupUi(this);
// Set flags and attributes.
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("help-about")));
//: About RSS Guard dialog title.
setWindowTitle(tr("About %1").arg(APP_NAME));
m_ui->m_lblIcon->setPixmap(QPixmap(APP_ICON_PATH));
// Load information from embedded text files.
loadLicenseAndInformation();
// Load additional paths information.
loadSettingsAndPaths();
FormAbout::FormAbout(QWidget* parent) : QDialog(parent), m_ui(new Ui::FormAbout()) {
m_ui->setupUi(this);
// Set flags and attributes.
setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint);
setWindowIcon(qApp->icons()->fromTheme(QSL("help-about")));
//: About RSS Guard dialog title.
setWindowTitle(tr("About %1").arg(APP_NAME));
m_ui->m_lblIcon->setPixmap(QPixmap(APP_ICON_PATH));
// Load information from embedded text files.
loadLicenseAndInformation();
// Load additional paths information.
loadSettingsAndPaths();
}
FormAbout::~FormAbout() {
qDebug("Destroying FormAbout instance.");
qDebug("Destroying FormAbout instance.");
}
void FormAbout::loadSettingsAndPaths() {
if (qApp->settings()->type() == SettingsProperties::Portable) {
m_ui->m_txtPathsSettingsType->setText(tr("FULLY portable"));
}
else {
m_ui->m_txtPathsSettingsType->setText(tr("NOT portable"));
}
if (qApp->settings()->type() == SettingsProperties::Portable) {
m_ui->m_txtPathsSettingsType->setText(tr("FULLY portable"));
}
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()));
else {
m_ui->m_txtPathsSettingsType->setText(tr("NOT portable"));
}
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() {
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)) {
m_ui->m_txtLicenseGnu->setText(QString::fromUtf8(file.readAll()));
}
else {
m_ui->m_txtLicenseGnu->setText(tr("License not found."));
}
file.close();
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
m_ui->m_txtLicenseGnu->setText(QString::fromUtf8(file.readAll()));
}
file.setFileName(APP_INFO_PATH + QL1S("/COPYING_BSD"));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
m_ui->m_txtLicenseBsd->setText(QString::fromUtf8(file.readAll()));
}
else {
m_ui->m_txtLicenseBsd->setText(tr("License not found."));
}
file.close();
else {
m_ui->m_txtLicenseGnu->setText(tr("License not found."));
}
file.setFileName(APP_INFO_PATH + QL1S("/CHANGELOG"));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
m_ui->m_txtChangelog->setText(QString::fromUtf8(file.readAll()));
}
else {
m_ui->m_txtChangelog->setText(tr("Changelog not found."));
}
file.close();
file.close();
file.setFileName(APP_INFO_PATH + QL1S("/COPYING_BSD"));
// 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));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
m_ui->m_txtLicenseBsd->setText(QString::fromUtf8(file.readAll()));
}
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));
else {
m_ui->m_txtLicenseBsd->setText(tr("License not found."));
}
file.close();
file.setFileName(APP_INFO_PATH + QL1S("/CHANGELOG"));
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
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.
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 {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit FormAbout(QWidget *parent);
virtual ~FormAbout();
public:
// Constructors and destructors.
explicit FormAbout(QWidget* parent);
virtual ~FormAbout();
private:
void loadLicenseAndInformation();
void loadSettingsAndPaths();
private:
void loadLicenseAndInformation();
void loadSettingsAndPaths();
QScopedPointer<Ui::FormAbout> m_ui;
QScopedPointer<Ui::FormAbout> m_ui;
};
#endif // FORMABOUT_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,19 +24,19 @@
class LabelWithStatus : public WidgetWithStatus {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit LabelWithStatus(QWidget *parent = 0);
virtual ~LabelWithStatus();
public:
// Constructors and destructors.
explicit LabelWithStatus(QWidget* parent = 0);
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.
inline QLabel *label() const {
return static_cast<QLabel*>(m_wdgInput);
}
// Access to label.
inline QLabel* label() const {
return static_cast<QLabel*>(m_wdgInput);
}
};
#endif // LABELWITHSTATUS_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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