items are now sortable with drag/drop
This commit is contained in:
parent
3d93a40284
commit
f63af3a051
@ -22,8 +22,6 @@
|
|||||||
#include <QStack>
|
#include <QStack>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
using RootItemPtr = RootItem*;
|
|
||||||
|
|
||||||
FeedsModel::FeedsModel(QObject* parent) : QAbstractItemModel(parent), m_rootItem(new RootItem()) {
|
FeedsModel::FeedsModel(QObject* parent) : QAbstractItemModel(parent), m_rootItem(new RootItem()) {
|
||||||
setObjectName(QSL("FeedsModel"));
|
setObjectName(QSL("FeedsModel"));
|
||||||
|
|
||||||
@ -75,69 +73,6 @@ 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)
|
|
||||||
|
|
||||||
if (action == Qt::DropAction::IgnoreAction) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (action != Qt::DropAction::MoveAction) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray dragged_items_data = data->data(QSL(MIME_TYPE_ITEM_POINTER));
|
|
||||||
|
|
||||||
if (dragged_items_data.isEmpty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
QDataStream stream(&dragged_items_data, QIODevice::OpenModeFlag::ReadOnly);
|
|
||||||
|
|
||||||
while (!stream.atEnd()) {
|
|
||||||
quintptr pointer_to_item;
|
|
||||||
stream >> pointer_to_item;
|
|
||||||
|
|
||||||
// We have item we want to drag, we also determine the target item.
|
|
||||||
auto* dragged_item = RootItemPtr(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 == 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dragged_item_root != target_item_root) {
|
|
||||||
// Transferring of items between different accounts is not possible.
|
|
||||||
qApp->showGuiMessage(Notification::Event::GeneralEvent,
|
|
||||||
{tr("Cannot perform drag & drop operation"),
|
|
||||||
tr("You can't transfer dragged item into different account, this is not supported."),
|
|
||||||
QSystemTrayIcon::MessageIcon::Critical});
|
|
||||||
qDebugNN << LOGSEC_FEEDMODEL
|
|
||||||
<< "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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::DropActions FeedsModel::supportedDropActions() const {
|
Qt::DropActions FeedsModel::supportedDropActions() const {
|
||||||
return Qt::DropAction::MoveAction;
|
return Qt::DropAction::MoveAction;
|
||||||
}
|
}
|
||||||
@ -368,7 +303,6 @@ RootItem* FeedsModel::itemForIndex(const QModelIndex& index) const {
|
|||||||
|
|
||||||
QModelIndex FeedsModel::indexForItem(const RootItem* item) const {
|
QModelIndex FeedsModel::indexForItem(const RootItem* item) const {
|
||||||
if (item == nullptr || item->kind() == RootItem::Kind::Root) {
|
if (item == nullptr || item->kind() == RootItem::Kind::Root) {
|
||||||
|
|
||||||
// Root item lies on invalid index.
|
// Root item lies on invalid index.
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
@ -598,6 +532,5 @@ QVariant FeedsModel::data(const QModelIndex& index, int role) const {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
return itemForIndex(index)->data(index.column(), role);
|
return itemForIndex(index)->data(index.column(), role);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,22 +21,20 @@ class RSSGUARD_DLLSPEC FeedsModel : public QAbstractItemModel {
|
|||||||
virtual ~FeedsModel();
|
virtual ~FeedsModel();
|
||||||
|
|
||||||
// Model implementation.
|
// Model implementation.
|
||||||
QVariant data(const QModelIndex& index, int role) const;
|
virtual QVariant data(const QModelIndex& index, int role) const;
|
||||||
|
|
||||||
// Drag & drop.
|
// Drag & drop.
|
||||||
QMimeData* mimeData(const QModelIndexList& indexes) const;
|
virtual QMimeData* mimeData(const QModelIndexList& indexes) const;
|
||||||
|
virtual QStringList mimeTypes() const;
|
||||||
QStringList mimeTypes() const;
|
virtual Qt::DropActions supportedDropActions() const;
|
||||||
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent);
|
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||||
Qt::DropActions supportedDropActions() const;
|
|
||||||
Qt::ItemFlags flags(const QModelIndex& index) const;
|
|
||||||
|
|
||||||
// Other subclassed methods.
|
// Other subclassed methods.
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||||
QModelIndex index(int row, int column, const QModelIndex& parent) const;
|
virtual QModelIndex index(int row, int column, const QModelIndex& parent) const;
|
||||||
QModelIndex parent(const QModelIndex& child) const;
|
virtual QModelIndex parent(const QModelIndex& child) const;
|
||||||
int columnCount(const QModelIndex& parent) const;
|
virtual int columnCount(const QModelIndex& parent) const;
|
||||||
int rowCount(const QModelIndex& parent) const;
|
virtual int rowCount(const QModelIndex& parent) const;
|
||||||
|
|
||||||
// Returns counts of ALL/UNREAD (non-deleted) messages for the model.
|
// Returns counts of ALL/UNREAD (non-deleted) messages for the model.
|
||||||
int countOfAllMessages() const;
|
int countOfAllMessages() const;
|
||||||
@ -136,7 +134,7 @@ class RSSGUARD_DLLSPEC FeedsModel : public QAbstractItemModel {
|
|||||||
void messageCountsChanged(int unread_messages, bool any_feed_has_unread_messages);
|
void messageCountsChanged(int unread_messages, bool any_feed_has_unread_messages);
|
||||||
|
|
||||||
// Emitted if any item requested that any view should expand it.
|
// Emitted if any item requested that any view should expand it.
|
||||||
void itemExpandRequested(QList<RootItem*>items, bool expand);
|
void itemExpandRequested(QList<RootItem*> items, bool expand);
|
||||||
|
|
||||||
// Emitted if any item requested that its expand states should be explicitly saved.
|
// Emitted if any item requested that its expand states should be explicitly saved.
|
||||||
// NOTE: Normally expand states are saved when application quits.
|
// NOTE: Normally expand states are saved when application quits.
|
||||||
@ -145,9 +143,6 @@ class RSSGUARD_DLLSPEC FeedsModel : public QAbstractItemModel {
|
|||||||
// Emitted when there is a need of reloading of displayed messages.
|
// Emitted when there is a need of reloading of displayed messages.
|
||||||
void reloadMessageListRequested(bool mark_selected_messages_read);
|
void reloadMessageListRequested(bool mark_selected_messages_read);
|
||||||
|
|
||||||
// There was some drag/drop operation, notify view about this.
|
|
||||||
void requireItemValidationAfterDragDrop(const QModelIndex& source_index);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RootItem* m_rootItem;
|
RootItem* m_rootItem;
|
||||||
QList<QString> m_headerData;
|
QList<QString> m_headerData;
|
||||||
|
@ -3,17 +3,21 @@
|
|||||||
#include "core/feedsproxymodel.h"
|
#include "core/feedsproxymodel.h"
|
||||||
|
|
||||||
#include "core/feedsmodel.h"
|
#include "core/feedsmodel.h"
|
||||||
|
#include "database/databasequeries.h"
|
||||||
#include "definitions/definitions.h"
|
#include "definitions/definitions.h"
|
||||||
#include "gui/feedsview.h"
|
#include "gui/feedsview.h"
|
||||||
#include "miscellaneous/application.h"
|
#include "miscellaneous/application.h"
|
||||||
#include "miscellaneous/regexfactory.h"
|
#include "miscellaneous/regexfactory.h"
|
||||||
#include "services/abstract/rootitem.h"
|
#include "services/abstract/rootitem.h"
|
||||||
|
|
||||||
|
#include <QMimeData>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
using RootItemPtr = RootItem*;
|
||||||
|
|
||||||
FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent)
|
FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent)
|
||||||
: QSortFilterProxyModel(parent), m_sourceModel(source_model), m_view(nullptr),
|
: QSortFilterProxyModel(parent), m_sourceModel(source_model), m_view(nullptr), m_selectedItem(nullptr),
|
||||||
m_selectedItem(nullptr), m_showUnreadOnly(false), m_sortAlphabetically(true) {
|
m_showUnreadOnly(false), m_sortAlphabetically(true) {
|
||||||
setObjectName(QSL("FeedsProxyModel"));
|
setObjectName(QSL("FeedsProxyModel"));
|
||||||
|
|
||||||
setSortRole(Qt::ItemDataRole::EditRole);
|
setSortRole(Qt::ItemDataRole::EditRole);
|
||||||
@ -28,26 +32,28 @@ FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent)
|
|||||||
// Smaller index means that item is "smaller" which
|
// Smaller index means that item is "smaller" which
|
||||||
// means it should be more on top when sorting
|
// means it should be more on top when sorting
|
||||||
// in ascending order.
|
// in ascending order.
|
||||||
m_priorities = {
|
m_priorities = {RootItem::Kind::Category,
|
||||||
RootItem::Kind::Category,
|
|
||||||
RootItem::Kind::Feed,
|
RootItem::Kind::Feed,
|
||||||
RootItem::Kind::Labels,
|
RootItem::Kind::Labels,
|
||||||
RootItem::Kind::Important,
|
RootItem::Kind::Important,
|
||||||
RootItem::Kind::Unread,
|
RootItem::Kind::Unread,
|
||||||
RootItem::Kind::Bin
|
RootItem::Kind::Bin};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FeedsProxyModel::~FeedsProxyModel() {
|
FeedsProxyModel::~FeedsProxyModel() {
|
||||||
qDebugNN << LOGSEC_FEEDMODEL << "Destroying FeedsProxyModel instance";
|
qDebugNN << LOGSEC_FEEDMODEL << "Destroying FeedsProxyModel instance";
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const {
|
QModelIndexList FeedsProxyModel::match(const QModelIndex& start,
|
||||||
|
int role,
|
||||||
|
const QVariant& value,
|
||||||
|
int hits,
|
||||||
|
Qt::MatchFlags flags) const {
|
||||||
QModelIndexList result;
|
QModelIndexList result;
|
||||||
const int match_type = flags & 0x0F;
|
const int match_type = flags & 0x0F;
|
||||||
const Qt::CaseSensitivity cs = Qt::CaseSensitivity::CaseInsensitive;
|
const Qt::CaseSensitivity cs = Qt::CaseSensitivity::CaseInsensitive;
|
||||||
const bool recurse = (flags& Qt::MatchFlag::MatchRecursive) > 0;
|
const bool recurse = (flags & Qt::MatchFlag::MatchRecursive) > 0;
|
||||||
const bool wrap = (flags& Qt::MatchFlag::MatchWrap) > 0;
|
const bool wrap = (flags & Qt::MatchFlag::MatchWrap) > 0;
|
||||||
const bool all_hits = (hits == -1);
|
const bool all_hits = (hits == -1);
|
||||||
QString entered_text;
|
QString entered_text;
|
||||||
const QModelIndex p = parent(start);
|
const QModelIndex p = parent(start);
|
||||||
@ -88,7 +94,9 @@ QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const
|
|||||||
#endif
|
#endif
|
||||||
if (QRegularExpression(entered_text,
|
if (QRegularExpression(entered_text,
|
||||||
QRegularExpression::PatternOption::CaseInsensitiveOption |
|
QRegularExpression::PatternOption::CaseInsensitiveOption |
|
||||||
QRegularExpression::PatternOption::UseUnicodePropertiesOption).match(item_text).hasMatch()) {
|
QRegularExpression::PatternOption::UseUnicodePropertiesOption)
|
||||||
|
.match(item_text)
|
||||||
|
.hasMatch()) {
|
||||||
result.append(idx);
|
result.append(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +105,9 @@ QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const
|
|||||||
case Qt::MatchFlag::MatchWildcard:
|
case Qt::MatchFlag::MatchWildcard:
|
||||||
if (QRegularExpression(RegexFactory::wildcardToRegularExpression(entered_text),
|
if (QRegularExpression(RegexFactory::wildcardToRegularExpression(entered_text),
|
||||||
QRegularExpression::PatternOption::CaseInsensitiveOption |
|
QRegularExpression::PatternOption::CaseInsensitiveOption |
|
||||||
QRegularExpression::PatternOption::UseUnicodePropertiesOption).match(item_text).hasMatch()) {
|
QRegularExpression::PatternOption::UseUnicodePropertiesOption)
|
||||||
|
.match(item_text)
|
||||||
|
.hasMatch()) {
|
||||||
result.append(idx);
|
result.append(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,9 +145,11 @@ QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (recurse && hasChildren(idx)) {
|
if (recurse && hasChildren(idx)) {
|
||||||
result +=
|
result += match(index(0, idx.column(), idx),
|
||||||
match(index(0, idx.column(), idx), role, (entered_text.isEmpty() ? value : entered_text),
|
role,
|
||||||
(all_hits ? -1 : hits - result.count()), flags);
|
(entered_text.isEmpty() ? value : entered_text),
|
||||||
|
(all_hits ? -1 : hits - result.count()),
|
||||||
|
flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +160,84 @@ QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FeedsProxyModel::dropMimeData(const QMimeData* data,
|
||||||
|
Qt::DropAction action,
|
||||||
|
int row,
|
||||||
|
int column,
|
||||||
|
const QModelIndex& parent) {
|
||||||
|
Q_UNUSED(column)
|
||||||
|
|
||||||
|
if (action == Qt::DropAction::IgnoreAction) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (action != Qt::DropAction::MoveAction) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray dragged_items_data = data->data(QSL(MIME_TYPE_ITEM_POINTER));
|
||||||
|
|
||||||
|
if (dragged_items_data.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QDataStream stream(&dragged_items_data, QIODevice::OpenModeFlag::ReadOnly);
|
||||||
|
const bool order_change = row >= 0 && !m_sortAlphabetically;
|
||||||
|
const QModelIndex source_parent = mapToSource(parent);
|
||||||
|
|
||||||
|
while (!stream.atEnd()) {
|
||||||
|
quintptr pointer_to_item;
|
||||||
|
stream >> pointer_to_item;
|
||||||
|
|
||||||
|
// We have item we want to drag, we also determine the target item.
|
||||||
|
auto* dragged_item = RootItemPtr(pointer_to_item);
|
||||||
|
RootItem* target_item = m_sourceModel->itemForIndex(source_parent);
|
||||||
|
ServiceRoot* dragged_item_root = dragged_item->getParentServiceRoot();
|
||||||
|
ServiceRoot* target_item_root = target_item->getParentServiceRoot();
|
||||||
|
|
||||||
|
if ((dragged_item == target_item || dragged_item->parent() == target_item) && !order_change) {
|
||||||
|
qDebugNN << LOGSEC_FEEDMODEL
|
||||||
|
<< "Dragged item is equal to target item or its parent is equal to target item. Cancelling drag-drop "
|
||||||
|
"action.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dragged_item_root != target_item_root) {
|
||||||
|
// Transferring of items between different accounts is not possible.
|
||||||
|
qApp->showGuiMessage(Notification::Event::GeneralEvent,
|
||||||
|
{tr("Cannot perform drag & drop operation"),
|
||||||
|
tr("You can't transfer dragged item into different account, this is not supported."),
|
||||||
|
QSystemTrayIcon::MessageIcon::Critical});
|
||||||
|
qDebugNN << LOGSEC_FEEDMODEL
|
||||||
|
<< "Dragged item cannot be dragged into different account. Cancelling drag-drop action.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dragged_item != target_item && dragged_item->parent() != target_item &&
|
||||||
|
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(m_sourceModel->indexForItem(dragged_item));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (order_change) {
|
||||||
|
auto db = qApp->database()->driver()->connection(metaObject()->className());
|
||||||
|
|
||||||
|
if (row > dragged_item->sortOrder()) {
|
||||||
|
row--;
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabaseQueries::moveItem(dragged_item, false, false, row, db);
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const {
|
bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const {
|
||||||
if (left.isValid() && right.isValid()) {
|
if (left.isValid() && right.isValid()) {
|
||||||
// Make necessary castings.
|
// Make necessary castings.
|
||||||
@ -183,8 +273,7 @@ bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right
|
|||||||
case RootItem::Kind::Feed:
|
case RootItem::Kind::Feed:
|
||||||
case RootItem::Kind::Category:
|
case RootItem::Kind::Category:
|
||||||
case RootItem::Kind::ServiceRoot:
|
case RootItem::Kind::ServiceRoot:
|
||||||
return sortOrder() == Qt::SortOrder::AscendingOrder
|
return sortOrder() == Qt::SortOrder::AscendingOrder ? left_item->sortOrder() < right_item->sortOrder()
|
||||||
? left_item->sortOrder() < right_item->sortOrder()
|
|
||||||
: left_item->sortOrder() > right_item->sortOrder();
|
: left_item->sortOrder() > right_item->sortOrder();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -199,8 +288,7 @@ bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right
|
|||||||
auto left_priority = m_priorities.indexOf(left_item->kind());
|
auto left_priority = m_priorities.indexOf(left_item->kind());
|
||||||
auto right_priority = m_priorities.indexOf(right_item->kind());
|
auto right_priority = m_priorities.indexOf(right_item->kind());
|
||||||
|
|
||||||
return sortOrder() == Qt::SortOrder::AscendingOrder
|
return sortOrder() == Qt::SortOrder::AscendingOrder ? left_priority < right_priority
|
||||||
? left_priority < right_priority
|
|
||||||
: right_priority < left_priority;
|
: right_priority < left_priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,11 +300,9 @@ bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right
|
|||||||
bool FeedsProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const {
|
bool FeedsProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const {
|
||||||
bool should_show = filterAcceptsRowInternal(source_row, source_parent);
|
bool should_show = filterAcceptsRowInternal(source_row, source_parent);
|
||||||
|
|
||||||
qDebugNN << LOGSEC_CORE
|
qDebugNN << LOGSEC_CORE << "Filter accepts row"
|
||||||
<< "Filter accepts row"
|
|
||||||
<< QUOTE_W_SPACE(m_sourceModel->itemForIndex(m_sourceModel->index(source_row, 0, source_parent))->title())
|
<< QUOTE_W_SPACE(m_sourceModel->itemForIndex(m_sourceModel->index(source_row, 0, source_parent))->title())
|
||||||
<< "and filter result is:"
|
<< "and filter result is:" << QUOTE_W_SPACE_DOT(should_show);
|
||||||
<< QUOTE_W_SPACE_DOT(should_show);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (should_show && (!filterRegularExpression().pattern().isEmpty() ||
|
if (should_show && (!filterRegularExpression().pattern().isEmpty() ||
|
||||||
@ -251,8 +337,7 @@ bool FeedsProxyModel::filterAcceptsRowInternal(int source_row, const QModelIndex
|
|||||||
|
|
||||||
const RootItem* item = m_sourceModel->itemForIndex(idx);
|
const RootItem* item = m_sourceModel->itemForIndex(idx);
|
||||||
|
|
||||||
if (item->kind() != RootItem::Kind::Category &&
|
if (item->kind() != RootItem::Kind::Category && item->kind() != RootItem::Kind::Feed &&
|
||||||
item->kind() != RootItem::Kind::Feed &&
|
|
||||||
item->kind() != RootItem::Kind::Label) {
|
item->kind() != RootItem::Kind::Label) {
|
||||||
// Some items are always visible.
|
// Some items are always visible.
|
||||||
return true;
|
return true;
|
||||||
@ -271,12 +356,15 @@ bool FeedsProxyModel::filterAcceptsRowInternal(int source_row, const QModelIndex
|
|||||||
// particularly manifests itself if user uses "next unread item" action and
|
// particularly manifests itself if user uses "next unread item" action and
|
||||||
// "show unread only" is enabled too and user for example selects last unread
|
// "show unread only" is enabled too and user for example selects last unread
|
||||||
// article in a feed -> then the feed would disappear from list suddenly.
|
// article in a feed -> then the feed would disappear from list suddenly.
|
||||||
return
|
return m_selectedItem == item ||
|
||||||
m_selectedItem == item || (item->countOfUnreadMessages() != 0 &&
|
(item->countOfUnreadMessages() != 0 && QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent));
|
||||||
QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FeedsProxyModel::sortAlphabetically() const {
|
||||||
|
return m_sortAlphabetically;
|
||||||
|
}
|
||||||
|
|
||||||
void FeedsProxyModel::sort(int column, Qt::SortOrder order) {
|
void FeedsProxyModel::sort(int column, Qt::SortOrder order) {
|
||||||
QSortFilterProxyModel::sort(column, order);
|
QSortFilterProxyModel::sort(column, order);
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,21 @@ class FeedsProxyModel : public QSortFilterProxyModel {
|
|||||||
explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = nullptr);
|
explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = nullptr);
|
||||||
virtual ~FeedsProxyModel();
|
virtual ~FeedsProxyModel();
|
||||||
|
|
||||||
|
virtual bool dropMimeData(const QMimeData* data,
|
||||||
|
Qt::DropAction action,
|
||||||
|
int row,
|
||||||
|
int column,
|
||||||
|
const QModelIndex& parent);
|
||||||
|
|
||||||
virtual void sort(int column, Qt::SortOrder order = Qt::SortOrder::AscendingOrder);
|
virtual void sort(int column, Qt::SortOrder order = Qt::SortOrder::AscendingOrder);
|
||||||
|
|
||||||
// Returns index list of items which "match" given value.
|
// Returns index list of items which "match" given value.
|
||||||
// Used for finding items according to entered title text.
|
// Used for finding items according to entered title text.
|
||||||
virtual QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits, Qt::MatchFlags flags) const;
|
virtual QModelIndexList match(const QModelIndex& start,
|
||||||
|
int role,
|
||||||
|
const QVariant& value,
|
||||||
|
int hits,
|
||||||
|
Qt::MatchFlags flags) const;
|
||||||
|
|
||||||
// Maps list of indexes.
|
// Maps list of indexes.
|
||||||
QModelIndexList mapListToSource(const QModelIndexList& indexes) const;
|
QModelIndexList mapListToSource(const QModelIndexList& indexes) const;
|
||||||
@ -34,6 +44,7 @@ class FeedsProxyModel : public QSortFilterProxyModel {
|
|||||||
void setSelectedItem(const RootItem* selected_item);
|
void setSelectedItem(const RootItem* selected_item);
|
||||||
void setView(FeedsView* newView);
|
void setView(FeedsView* newView);
|
||||||
|
|
||||||
|
bool sortAlphabetically() const;
|
||||||
void setSortAlphabetically(bool sort_alphabetically);
|
void setSortAlphabetically(bool sort_alphabetically);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@ -42,6 +53,9 @@ class FeedsProxyModel : public QSortFilterProxyModel {
|
|||||||
signals:
|
signals:
|
||||||
void expandAfterFilterIn(QModelIndex source_idx) const;
|
void expandAfterFilterIn(QModelIndex source_idx) const;
|
||||||
|
|
||||||
|
// There was some drag/drop operation, notify view about this.
|
||||||
|
void requireItemValidationAfterDragDrop(const QModelIndex& source_index);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
|
virtual bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
|
||||||
virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
|
virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
|
|
||||||
FeedsView::FeedsView(QWidget* parent)
|
FeedsView::FeedsView(QWidget* parent)
|
||||||
: BaseTreeView(parent), m_contextMenuService(nullptr), m_contextMenuBin(nullptr), m_contextMenuCategories(nullptr),
|
: BaseTreeView(parent), m_contextMenuService(nullptr), m_contextMenuBin(nullptr), m_contextMenuCategories(nullptr),
|
||||||
m_contextMenuFeeds(nullptr), m_contextMenuImportant(nullptr), m_contextMenuEmptySpace(nullptr), m_contextMenuOtherItems(nullptr),
|
m_contextMenuFeeds(nullptr), m_contextMenuImportant(nullptr), m_contextMenuEmptySpace(nullptr),
|
||||||
m_contextMenuLabel(nullptr), m_dontSaveExpandState(false) {
|
m_contextMenuOtherItems(nullptr), m_contextMenuLabel(nullptr), m_dontSaveExpandState(false) {
|
||||||
setObjectName(QSL("FeedsView"));
|
setObjectName(QSL("FeedsView"));
|
||||||
|
|
||||||
// Allocate models.
|
// Allocate models.
|
||||||
@ -40,10 +40,13 @@ FeedsView::FeedsView(QWidget* parent)
|
|||||||
m_proxyModel->setView(this);
|
m_proxyModel->setView(this);
|
||||||
|
|
||||||
// Connections.
|
// Connections.
|
||||||
connect(m_sourceModel, &FeedsModel::requireItemValidationAfterDragDrop, this, &FeedsView::validateItemAfterDragDrop);
|
|
||||||
connect(m_sourceModel, &FeedsModel::itemExpandRequested, this, &FeedsView::onItemExpandRequested);
|
connect(m_sourceModel, &FeedsModel::itemExpandRequested, this, &FeedsView::onItemExpandRequested);
|
||||||
connect(m_sourceModel, &FeedsModel::itemExpandStateSaveRequested, this, &FeedsView::onItemExpandStateSaveRequested);
|
connect(m_sourceModel, &FeedsModel::itemExpandStateSaveRequested, this, &FeedsView::onItemExpandStateSaveRequested);
|
||||||
connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState);
|
connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState);
|
||||||
|
connect(m_proxyModel,
|
||||||
|
&FeedsProxyModel::requireItemValidationAfterDragDrop,
|
||||||
|
this,
|
||||||
|
&FeedsView::validateItemAfterDragDrop);
|
||||||
connect(m_proxyModel, &FeedsProxyModel::expandAfterFilterIn, this, &FeedsView::expandItemDelayed);
|
connect(m_proxyModel, &FeedsProxyModel::expandAfterFilterIn, this, &FeedsView::expandItemDelayed);
|
||||||
connect(this, &FeedsView::expanded, this, &FeedsView::onIndexExpanded);
|
connect(this, &FeedsView::expanded, this, &FeedsView::onIndexExpanded);
|
||||||
connect(this, &FeedsView::collapsed, this, &FeedsView::onIndexCollapsed);
|
connect(this, &FeedsView::collapsed, this, &FeedsView::onIndexCollapsed);
|
||||||
@ -127,10 +130,10 @@ void FeedsView::addFeedIntoSelectedAccount() {
|
|||||||
root->addNewFeed(selected, QGuiApplication::clipboard()->text(QClipboard::Mode::Clipboard));
|
root->addNewFeed(selected, QGuiApplication::clipboard()->text(QClipboard::Mode::Clipboard));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qApp->showGuiMessage(Notification::Event::GeneralEvent, {
|
qApp->showGuiMessage(Notification::Event::GeneralEvent,
|
||||||
tr("Not supported by account"),
|
{tr("Not supported by account"),
|
||||||
tr("Selected account does not support adding of new feeds."),
|
tr("Selected account does not support adding of new feeds."),
|
||||||
QSystemTrayIcon::MessageIcon::Warning });
|
QSystemTrayIcon::MessageIcon::Warning});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,10 +148,10 @@ void FeedsView::addCategoryIntoSelectedAccount() {
|
|||||||
root->addNewCategory(selectedItem());
|
root->addNewCategory(selectedItem());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qApp->showGuiMessage(Notification::Event::GeneralEvent, {
|
qApp->showGuiMessage(Notification::Event::GeneralEvent,
|
||||||
tr("Not supported by account"),
|
{tr("Not supported by account"),
|
||||||
tr("Selected account does not support adding of new categories."),
|
tr("Selected account does not support adding of new categories."),
|
||||||
QSystemTrayIcon::MessageIcon::Warning });
|
QSystemTrayIcon::MessageIcon::Warning});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,7 +166,7 @@ void FeedsView::expandCollapseCurrentItem(bool recursive) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
QList<QModelIndex> to_process = { index };
|
QList<QModelIndex> to_process = {index};
|
||||||
bool expa = !isExpanded(index);
|
bool expa = !isExpanded(index);
|
||||||
|
|
||||||
while (!to_process.isEmpty()) {
|
while (!to_process.isEmpty()) {
|
||||||
@ -208,10 +211,10 @@ void FeedsView::editSelectedItem() {
|
|||||||
// Lock was not obtained because
|
// Lock was not obtained because
|
||||||
// it is used probably by feed updater or application
|
// it is used probably by feed updater or application
|
||||||
// is quitting.
|
// is quitting.
|
||||||
qApp->showGuiMessage(Notification::Event::GeneralEvent, {
|
qApp->showGuiMessage(Notification::Event::GeneralEvent,
|
||||||
tr("Cannot edit item"),
|
{tr("Cannot edit item"),
|
||||||
tr("Selected item cannot be edited because another critical operation is ongoing."),
|
tr("Selected item cannot be edited because another critical operation is ongoing."),
|
||||||
QSystemTrayIcon::MessageIcon::Warning });
|
QSystemTrayIcon::MessageIcon::Warning});
|
||||||
|
|
||||||
// Thus, cannot delete and quit the method.
|
// Thus, cannot delete and quit the method.
|
||||||
return;
|
return;
|
||||||
@ -221,10 +224,10 @@ void FeedsView::editSelectedItem() {
|
|||||||
selectedItem()->editViaGui();
|
selectedItem()->editViaGui();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qApp->showGuiMessage(Notification::Event::GeneralEvent, {
|
qApp->showGuiMessage(Notification::Event::GeneralEvent,
|
||||||
tr("Cannot edit item"),
|
{tr("Cannot edit item"),
|
||||||
tr("Selected item cannot be edited, this is not (yet?) supported."),
|
tr("Selected item cannot be edited, this is not (yet?) supported."),
|
||||||
QSystemTrayIcon::MessageIcon::Warning });
|
QSystemTrayIcon::MessageIcon::Warning});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changes are done, unlock the update master lock.
|
// Changes are done, unlock the update master lock.
|
||||||
@ -236,10 +239,10 @@ void FeedsView::deleteSelectedItem() {
|
|||||||
// Lock was not obtained because
|
// Lock was not obtained because
|
||||||
// it is used probably by feed updater or application
|
// it is used probably by feed updater or application
|
||||||
// is quitting.
|
// is quitting.
|
||||||
qApp->showGuiMessage(Notification::Event::GeneralEvent, {
|
qApp->showGuiMessage(Notification::Event::GeneralEvent,
|
||||||
tr("Cannot delete item"),
|
{tr("Cannot delete item"),
|
||||||
tr("Selected item cannot be deleted because another critical operation is ongoing."),
|
tr("Selected item cannot be deleted because another critical operation is ongoing."),
|
||||||
QSystemTrayIcon::MessageIcon::Warning });
|
QSystemTrayIcon::MessageIcon::Warning});
|
||||||
|
|
||||||
// Thus, cannot delete and quit the method.
|
// Thus, cannot delete and quit the method.
|
||||||
return;
|
return;
|
||||||
@ -261,7 +264,8 @@ void FeedsView::deleteSelectedItem() {
|
|||||||
tr("Deleting \"%1\"").arg(selected_item->title()),
|
tr("Deleting \"%1\"").arg(selected_item->title()),
|
||||||
tr("You are about to completely delete item \"%1\".").arg(selected_item->title()),
|
tr("You are about to completely delete item \"%1\".").arg(selected_item->title()),
|
||||||
tr("Are you sure?"),
|
tr("Are you sure?"),
|
||||||
QString(), QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No,
|
QString(),
|
||||||
|
QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No,
|
||||||
QMessageBox::StandardButton::Yes) == QMessageBox::StandardButton::No) {
|
QMessageBox::StandardButton::Yes) == QMessageBox::StandardButton::No) {
|
||||||
// User refused.
|
// User refused.
|
||||||
qApp->feedUpdateLock()->unlock();
|
qApp->feedUpdateLock()->unlock();
|
||||||
@ -272,17 +276,18 @@ void FeedsView::deleteSelectedItem() {
|
|||||||
if (!selected_item->deleteViaGui()) {
|
if (!selected_item->deleteViaGui()) {
|
||||||
m_proxyModel->invalidate();
|
m_proxyModel->invalidate();
|
||||||
|
|
||||||
qApp->showGuiMessage(Notification::Event::GeneralEvent, {
|
qApp->showGuiMessage(Notification::Event::GeneralEvent,
|
||||||
tr("Cannot delete \"%1\"").arg(selected_item->title()),
|
{tr("Cannot delete \"%1\"").arg(selected_item->title()),
|
||||||
tr("This item cannot be deleted because something critically failed. Submit bug report."),
|
tr("This item cannot be deleted because something critically failed. Submit bug report."),
|
||||||
QSystemTrayIcon::MessageIcon::Critical });
|
QSystemTrayIcon::MessageIcon::Critical});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qApp->showGuiMessage(Notification::Event::GeneralEvent, {
|
qApp->showGuiMessage(Notification::Event::GeneralEvent,
|
||||||
tr("Cannot delete \"%1\"").arg(selected_item->title()),
|
{tr("Cannot delete \"%1\"").arg(selected_item->title()),
|
||||||
tr("This item cannot be deleted, because it does not support it\nor this functionality is not implemented yet."),
|
tr("This item cannot be deleted, because it does not support it\nor this functionality is "
|
||||||
QSystemTrayIcon::MessageIcon::Critical });
|
"not implemented yet."),
|
||||||
|
QSystemTrayIcon::MessageIcon::Critical});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,7 +400,8 @@ QModelIndex FeedsView::nextUnreadItem(const QModelIndex& default_row) {
|
|||||||
const QModelIndex starting_row = default_row;
|
const QModelIndex starting_row = default_row;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
bool has_unread = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(nconst_default_row))->countOfUnreadMessages() > 0;
|
bool has_unread =
|
||||||
|
m_sourceModel->itemForIndex(m_proxyModel->mapToSource(nconst_default_row))->countOfUnreadMessages() > 0;
|
||||||
|
|
||||||
if (has_unread) {
|
if (has_unread) {
|
||||||
if (m_proxyModel->hasChildren(nconst_default_row)) {
|
if (m_proxyModel->hasChildren(nconst_default_row)) {
|
||||||
@ -435,10 +441,9 @@ QMenu* FeedsView::initializeContextMenuBin(RootItem* clicked_item) {
|
|||||||
|
|
||||||
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
|
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
|
||||||
|
|
||||||
m_contextMenuBin->addActions(QList<QAction*>() <<
|
m_contextMenuBin->addActions(QList<QAction*>() << qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode
|
||||||
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode <<
|
<< qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead
|
||||||
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead <<
|
<< qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread);
|
||||||
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread);
|
|
||||||
|
|
||||||
if (!specific_actions.isEmpty()) {
|
if (!specific_actions.isEmpty()) {
|
||||||
m_contextMenuBin->addSeparator();
|
m_contextMenuBin->addSeparator();
|
||||||
@ -458,7 +463,7 @@ QMenu* FeedsView::initializeContextMenuService(RootItem* clicked_item) {
|
|||||||
|
|
||||||
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
|
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
|
||||||
|
|
||||||
m_contextMenuService->addActions({ qApp->mainForm()->m_ui->m_actionUpdateSelectedItems,
|
m_contextMenuService->addActions({qApp->mainForm()->m_ui->m_actionUpdateSelectedItems,
|
||||||
qApp->mainForm()->m_ui->m_actionEditSelectedItem,
|
qApp->mainForm()->m_ui->m_actionEditSelectedItem,
|
||||||
qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed,
|
qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed,
|
||||||
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode,
|
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode,
|
||||||
@ -466,7 +471,7 @@ QMenu* FeedsView::initializeContextMenuService(RootItem* clicked_item) {
|
|||||||
qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively,
|
qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively,
|
||||||
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead,
|
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead,
|
||||||
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread,
|
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread,
|
||||||
qApp->mainForm()->m_ui->m_actionDeleteSelectedItem });
|
qApp->mainForm()->m_ui->m_actionDeleteSelectedItem});
|
||||||
|
|
||||||
auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding();
|
auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding();
|
||||||
auto feed_add = clicked_item->getParentServiceRoot()->supportsFeedAdding();
|
auto feed_add = clicked_item->getParentServiceRoot()->supportsFeedAdding();
|
||||||
@ -483,8 +488,7 @@ QMenu* FeedsView::initializeContextMenuService(RootItem* clicked_item) {
|
|||||||
m_contextMenuService->addAction(qApp->mainForm()->m_ui->m_actionAddFeedIntoSelectedItem);
|
m_contextMenuService->addAction(qApp->mainForm()->m_ui->m_actionAddFeedIntoSelectedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qApp->settings()->value(GROUP(Feeds),
|
if (!qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::SortAlphabetically)).toBool()) {
|
||||||
SETTING(Feeds::SortAlphabetically)).toBool()) {
|
|
||||||
m_contextMenuService->addSeparator();
|
m_contextMenuService->addSeparator();
|
||||||
m_contextMenuService->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveUp);
|
m_contextMenuService->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveUp);
|
||||||
m_contextMenuService->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveDown);
|
m_contextMenuService->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveDown);
|
||||||
@ -521,7 +525,8 @@ void FeedsView::focusInEvent(QFocusEvent* event) {
|
|||||||
QTreeView::focusInEvent(event);
|
QTreeView::focusInEvent(event);
|
||||||
|
|
||||||
if (currentIndex().isValid()) {
|
if (currentIndex().isValid()) {
|
||||||
selectionModel()->select(currentIndex(), QItemSelectionModel::SelectionFlag::Select | QItemSelectionModel::SelectionFlag::Rows);
|
selectionModel()->select(currentIndex(),
|
||||||
|
QItemSelectionModel::SelectionFlag::Select | QItemSelectionModel::SelectionFlag::Rows);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,14 +559,11 @@ void FeedsView::onIndexExpanded(const QModelIndex& idx) {
|
|||||||
|
|
||||||
const RootItem* it = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(idx));
|
const RootItem* it = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(idx));
|
||||||
|
|
||||||
if (it != nullptr && (int(it->kind()) & int(RootItem::Kind::Category |
|
if (it != nullptr &&
|
||||||
RootItem::Kind::ServiceRoot |
|
(int(it->kind()) & int(RootItem::Kind::Category | RootItem::Kind::ServiceRoot | RootItem::Kind::Labels)) > 0) {
|
||||||
RootItem::Kind::Labels)) > 0) {
|
|
||||||
const QString setting_name = it->hashCode();
|
const QString setting_name = it->hashCode();
|
||||||
|
|
||||||
qApp->settings()->setValue(GROUP(CategoriesExpandStates),
|
qApp->settings()->setValue(GROUP(CategoriesExpandStates), setting_name, true);
|
||||||
setting_name,
|
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,14 +577,11 @@ void FeedsView::onIndexCollapsed(const QModelIndex& idx) {
|
|||||||
|
|
||||||
RootItem* it = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(idx));
|
RootItem* it = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(idx));
|
||||||
|
|
||||||
if (it != nullptr && (int(it->kind()) & int(RootItem::Kind::Category |
|
if (it != nullptr &&
|
||||||
RootItem::Kind::ServiceRoot |
|
(int(it->kind()) & int(RootItem::Kind::Category | RootItem::Kind::ServiceRoot | RootItem::Kind::Labels)) > 0) {
|
||||||
RootItem::Kind::Labels)) > 0) {
|
|
||||||
const QString setting_name = it->hashCode();
|
const QString setting_name = it->hashCode();
|
||||||
|
|
||||||
qApp->settings()->setValue(GROUP(CategoriesExpandStates),
|
qApp->settings()->setValue(GROUP(CategoriesExpandStates), setting_name, false);
|
||||||
setting_name,
|
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,9 +595,8 @@ void FeedsView::saveAllExpandStates() {
|
|||||||
|
|
||||||
void FeedsView::saveExpandStates(RootItem* item) {
|
void FeedsView::saveExpandStates(RootItem* item) {
|
||||||
Settings* settings = qApp->settings();
|
Settings* settings = qApp->settings();
|
||||||
QList<RootItem*> items = item->getSubTree(RootItem::Kind::Category |
|
QList<RootItem*> items =
|
||||||
RootItem::Kind::ServiceRoot |
|
item->getSubTree(RootItem::Kind::Category | RootItem::Kind::ServiceRoot | RootItem::Kind::Labels);
|
||||||
RootItem::Kind::Labels);
|
|
||||||
|
|
||||||
// Iterate all categories and save their expand statuses.
|
// Iterate all categories and save their expand statuses.
|
||||||
for (const RootItem* it : items) {
|
for (const RootItem* it : items) {
|
||||||
@ -606,9 +604,7 @@ void FeedsView::saveExpandStates(RootItem* item) {
|
|||||||
QModelIndex source_index = sourceModel()->indexForItem(it);
|
QModelIndex source_index = sourceModel()->indexForItem(it);
|
||||||
QModelIndex visible_index = model()->mapFromSource(source_index);
|
QModelIndex visible_index = model()->mapFromSource(source_index);
|
||||||
|
|
||||||
settings->setValue(GROUP(CategoriesExpandStates),
|
settings->setValue(GROUP(CategoriesExpandStates), setting_name, isExpanded(visible_index));
|
||||||
setting_name,
|
|
||||||
isExpanded(visible_index));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -616,8 +612,7 @@ void FeedsView::loadAllExpandStates() {
|
|||||||
const Settings* settings = qApp->settings();
|
const Settings* settings = qApp->settings();
|
||||||
QList<RootItem*> expandable_items;
|
QList<RootItem*> expandable_items;
|
||||||
|
|
||||||
expandable_items.append(sourceModel()->rootItem()->getSubTree(RootItem::Kind::Category |
|
expandable_items.append(sourceModel()->rootItem()->getSubTree(RootItem::Kind::Category | RootItem::Kind::ServiceRoot |
|
||||||
RootItem::Kind::ServiceRoot |
|
|
||||||
RootItem::Kind::Labels));
|
RootItem::Kind::Labels));
|
||||||
|
|
||||||
// Iterate all categories and save their expand statuses.
|
// Iterate all categories and save their expand statuses.
|
||||||
@ -629,11 +624,13 @@ void FeedsView::loadAllExpandStates() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sortByColumn(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortColumnFeeds)).toInt(),
|
sortByColumn(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortColumnFeeds)).toInt(),
|
||||||
static_cast<Qt::SortOrder>(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortOrderFeeds)).toInt()));
|
static_cast<Qt::SortOrder>(qApp->settings()
|
||||||
|
->value(GROUP(GUI), SETTING(GUI::DefaultSortOrderFeeds))
|
||||||
|
.toInt()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedsView::expandItemDelayed(const QModelIndex& source_idx) {
|
void FeedsView::expandItemDelayed(const QModelIndex& source_idx) {
|
||||||
//QTimer::singleShot(100, this, [=] {
|
// QTimer::singleShot(100, this, [=] {
|
||||||
// Model requests to expand some items as they are visible and there is
|
// Model requests to expand some items as they are visible and there is
|
||||||
// a filter active, so they maybe were not visible before.
|
// a filter active, so they maybe were not visible before.
|
||||||
QModelIndex pidx = m_proxyModel->mapFromSource(source_idx);
|
QModelIndex pidx = m_proxyModel->mapFromSource(source_idx);
|
||||||
@ -663,7 +660,7 @@ QMenu* FeedsView::initializeContextMenuCategories(RootItem* clicked_item) {
|
|||||||
|
|
||||||
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
|
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
|
||||||
|
|
||||||
m_contextMenuCategories->addActions({ qApp->mainForm()->m_ui->m_actionUpdateSelectedItems,
|
m_contextMenuCategories->addActions({qApp->mainForm()->m_ui->m_actionUpdateSelectedItems,
|
||||||
qApp->mainForm()->m_ui->m_actionEditSelectedItem,
|
qApp->mainForm()->m_ui->m_actionEditSelectedItem,
|
||||||
qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed,
|
qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed,
|
||||||
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode,
|
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode,
|
||||||
@ -671,7 +668,7 @@ QMenu* FeedsView::initializeContextMenuCategories(RootItem* clicked_item) {
|
|||||||
qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively,
|
qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively,
|
||||||
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead,
|
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead,
|
||||||
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread,
|
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread,
|
||||||
qApp->mainForm()->m_ui->m_actionDeleteSelectedItem });
|
qApp->mainForm()->m_ui->m_actionDeleteSelectedItem});
|
||||||
|
|
||||||
auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding();
|
auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding();
|
||||||
auto feed_add = clicked_item->getParentServiceRoot()->supportsFeedAdding();
|
auto feed_add = clicked_item->getParentServiceRoot()->supportsFeedAdding();
|
||||||
@ -688,8 +685,7 @@ QMenu* FeedsView::initializeContextMenuCategories(RootItem* clicked_item) {
|
|||||||
m_contextMenuCategories->addAction(qApp->mainForm()->m_ui->m_actionAddFeedIntoSelectedItem);
|
m_contextMenuCategories->addAction(qApp->mainForm()->m_ui->m_actionAddFeedIntoSelectedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qApp->settings()->value(GROUP(Feeds),
|
if (!qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::SortAlphabetically)).toBool()) {
|
||||||
SETTING(Feeds::SortAlphabetically)).toBool()) {
|
|
||||||
m_contextMenuCategories->addSeparator();
|
m_contextMenuCategories->addSeparator();
|
||||||
m_contextMenuCategories->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveUp);
|
m_contextMenuCategories->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveUp);
|
||||||
m_contextMenuCategories->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveDown);
|
m_contextMenuCategories->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveDown);
|
||||||
@ -715,14 +711,13 @@ QMenu* FeedsView::initializeContextMenuFeeds(RootItem* clicked_item) {
|
|||||||
|
|
||||||
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
|
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
|
||||||
|
|
||||||
m_contextMenuFeeds->addActions(QList<QAction*>() <<
|
m_contextMenuFeeds->addActions(QList<QAction*>() << qApp->mainForm()->m_ui->m_actionUpdateSelectedItems
|
||||||
qApp->mainForm()->m_ui->m_actionUpdateSelectedItems <<
|
<< qApp->mainForm()->m_ui->m_actionEditSelectedItem
|
||||||
qApp->mainForm()->m_ui->m_actionEditSelectedItem <<
|
<< qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed
|
||||||
qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed <<
|
<< qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode
|
||||||
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode <<
|
<< qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead
|
||||||
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead <<
|
<< qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread
|
||||||
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread <<
|
<< qApp->mainForm()->m_ui->m_actionDeleteSelectedItem);
|
||||||
qApp->mainForm()->m_ui->m_actionDeleteSelectedItem);
|
|
||||||
|
|
||||||
auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding();
|
auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding();
|
||||||
auto feed_add = clicked_item->getParentServiceRoot()->supportsFeedAdding();
|
auto feed_add = clicked_item->getParentServiceRoot()->supportsFeedAdding();
|
||||||
@ -739,8 +734,7 @@ QMenu* FeedsView::initializeContextMenuFeeds(RootItem* clicked_item) {
|
|||||||
m_contextMenuFeeds->addAction(qApp->mainForm()->m_ui->m_actionAddFeedIntoSelectedItem);
|
m_contextMenuFeeds->addAction(qApp->mainForm()->m_ui->m_actionAddFeedIntoSelectedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qApp->settings()->value(GROUP(Feeds),
|
if (!qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::SortAlphabetically)).toBool()) {
|
||||||
SETTING(Feeds::SortAlphabetically)).toBool()) {
|
|
||||||
m_contextMenuFeeds->addSeparator();
|
m_contextMenuFeeds->addSeparator();
|
||||||
m_contextMenuFeeds->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveUp);
|
m_contextMenuFeeds->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveUp);
|
||||||
m_contextMenuFeeds->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveDown);
|
m_contextMenuFeeds->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveDown);
|
||||||
@ -766,10 +760,9 @@ QMenu* FeedsView::initializeContextMenuImportant(RootItem* clicked_item) {
|
|||||||
|
|
||||||
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
|
QList<QAction*> specific_actions = clicked_item->contextMenuFeedsList();
|
||||||
|
|
||||||
m_contextMenuImportant->addActions(QList<QAction*>() <<
|
m_contextMenuImportant->addActions(QList<QAction*>() << qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode
|
||||||
qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode <<
|
<< qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead
|
||||||
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead <<
|
<< qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread);
|
||||||
qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread);
|
|
||||||
|
|
||||||
if (!specific_actions.isEmpty()) {
|
if (!specific_actions.isEmpty()) {
|
||||||
m_contextMenuImportant->addSeparator();
|
m_contextMenuImportant->addSeparator();
|
||||||
@ -849,15 +842,17 @@ void FeedsView::setupAppearance() {
|
|||||||
setExpandsOnDoubleClick(true);
|
setExpandsOnDoubleClick(true);
|
||||||
setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers);
|
setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers);
|
||||||
setIndentation(FEEDS_VIEW_INDENTATION);
|
setIndentation(FEEDS_VIEW_INDENTATION);
|
||||||
setAcceptDrops(false);
|
setAcceptDrops(true);
|
||||||
|
viewport()->setAcceptDrops(true);
|
||||||
setDragEnabled(true);
|
setDragEnabled(true);
|
||||||
setDropIndicatorShown(true);
|
setDropIndicatorShown(true);
|
||||||
setDragDropMode(QAbstractItemView::DragDropMode::InternalMove);
|
setDragDropMode(QAbstractItemView::DragDropMode::InternalMove);
|
||||||
setAllColumnsShowFocus(false);
|
setAllColumnsShowFocus(false);
|
||||||
setRootIsDecorated(false);
|
setRootIsDecorated(false);
|
||||||
setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
|
setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
|
||||||
setItemDelegate(new StyledItemDelegateWithoutFocus(qApp->settings()->value(GROUP(GUI),
|
setItemDelegate(new StyledItemDelegateWithoutFocus(qApp->settings()
|
||||||
SETTING(GUI::HeightRowFeeds)).toInt(),
|
->value(GROUP(GUI), SETTING(GUI::HeightRowFeeds))
|
||||||
|
.toInt(),
|
||||||
-1,
|
-1,
|
||||||
this));
|
this));
|
||||||
}
|
}
|
||||||
@ -904,8 +899,7 @@ void FeedsView::contextMenuEvent(QContextMenuEvent* event) {
|
|||||||
// Display context menu for feeds.
|
// Display context menu for feeds.
|
||||||
initializeContextMenuFeeds(clicked_item)->exec(event->globalPos());
|
initializeContextMenuFeeds(clicked_item)->exec(event->globalPos());
|
||||||
}
|
}
|
||||||
else if (clicked_item->kind() == RootItem::Kind::Important ||
|
else if (clicked_item->kind() == RootItem::Kind::Important || clicked_item->kind() == RootItem::Kind::Unread) {
|
||||||
clicked_item->kind() == RootItem::Kind::Unread) {
|
|
||||||
initializeContextMenuImportant(clicked_item)->exec(event->globalPos());
|
initializeContextMenuImportant(clicked_item)->exec(event->globalPos());
|
||||||
}
|
}
|
||||||
else if (clicked_item->kind() == RootItem::Kind::Bin) {
|
else if (clicked_item->kind() == RootItem::Kind::Bin) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user