items are now sortable with drag/drop

This commit is contained in:
Martin Rotter 2022-08-26 13:50:41 +02:00
parent 3d93a40284
commit f63af3a051
5 changed files with 249 additions and 225 deletions

View File

@ -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);
;
} }
} }

View File

@ -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;

View File

@ -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);
} }

View File

@ -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;

View File

@ -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) {