diff --git a/src/librssguard/core/feedsmodel.cpp b/src/librssguard/core/feedsmodel.cpp index 3a76989ee..d786424e3 100644 --- a/src/librssguard/core/feedsmodel.cpp +++ b/src/librssguard/core/feedsmodel.cpp @@ -22,8 +22,6 @@ #include #include -using RootItemPtr = RootItem*; - FeedsModel::FeedsModel(QObject* parent) : QAbstractItemModel(parent), m_rootItem(new RootItem()) { setObjectName(QSL("FeedsModel")); @@ -75,69 +73,6 @@ QStringList FeedsModel::mimeTypes() const { 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 { return Qt::DropAction::MoveAction; } @@ -368,7 +303,6 @@ RootItem* FeedsModel::itemForIndex(const QModelIndex& index) const { QModelIndex FeedsModel::indexForItem(const RootItem* item) const { if (item == nullptr || item->kind() == RootItem::Kind::Root) { - // Root item lies on invalid index. return QModelIndex(); } @@ -598,6 +532,5 @@ QVariant FeedsModel::data(const QModelIndex& index, int role) const { default: return itemForIndex(index)->data(index.column(), role); - ; } } diff --git a/src/librssguard/core/feedsmodel.h b/src/librssguard/core/feedsmodel.h index a3e2abad0..39e0c65c0 100644 --- a/src/librssguard/core/feedsmodel.h +++ b/src/librssguard/core/feedsmodel.h @@ -14,29 +14,27 @@ class ServiceEntryPoint; class StandardServiceRoot; class RSSGUARD_DLLSPEC FeedsModel : public QAbstractItemModel { - Q_OBJECT + Q_OBJECT public: explicit FeedsModel(QObject* parent = nullptr); virtual ~FeedsModel(); // Model implementation. - QVariant data(const QModelIndex& index, int role) const; + virtual QVariant data(const QModelIndex& index, int role) const; // Drag & drop. - QMimeData* mimeData(const QModelIndexList& indexes) const; - - QStringList mimeTypes() const; - bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent); - Qt::DropActions supportedDropActions() const; - Qt::ItemFlags flags(const QModelIndex& index) const; + virtual QMimeData* mimeData(const QModelIndexList& indexes) const; + virtual QStringList mimeTypes() const; + virtual Qt::DropActions supportedDropActions() const; + virtual Qt::ItemFlags flags(const QModelIndex& index) const; // Other subclassed methods. - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QModelIndex index(int row, int column, const QModelIndex& parent) const; - QModelIndex parent(const QModelIndex& child) const; - int columnCount(const QModelIndex& parent) const; - int rowCount(const QModelIndex& parent) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; + virtual QModelIndex index(int row, int column, const QModelIndex& parent) const; + virtual QModelIndex parent(const QModelIndex& child) const; + virtual int columnCount(const QModelIndex& parent) const; + virtual int rowCount(const QModelIndex& parent) const; // Returns counts of ALL/UNREAD (non-deleted) messages for the model. int countOfAllMessages() const; @@ -136,7 +134,7 @@ class RSSGUARD_DLLSPEC FeedsModel : public QAbstractItemModel { void messageCountsChanged(int unread_messages, bool any_feed_has_unread_messages); // Emitted if any item requested that any view should expand it. - void itemExpandRequested(QListitems, bool expand); + void itemExpandRequested(QList items, bool expand); // Emitted if any item requested that its expand states should be explicitly saved. // NOTE: Normally expand states are saved when application quits. @@ -145,9 +143,6 @@ class RSSGUARD_DLLSPEC FeedsModel : public QAbstractItemModel { // Emitted when there is a need of reloading of displayed messages. void reloadMessageListRequested(bool mark_selected_messages_read); - // There was some drag/drop operation, notify view about this. - void requireItemValidationAfterDragDrop(const QModelIndex& source_index); - private: RootItem* m_rootItem; QList m_headerData; diff --git a/src/librssguard/core/feedsproxymodel.cpp b/src/librssguard/core/feedsproxymodel.cpp index 9fd4fc531..63c788bd3 100644 --- a/src/librssguard/core/feedsproxymodel.cpp +++ b/src/librssguard/core/feedsproxymodel.cpp @@ -3,17 +3,21 @@ #include "core/feedsproxymodel.h" #include "core/feedsmodel.h" +#include "database/databasequeries.h" #include "definitions/definitions.h" #include "gui/feedsview.h" #include "miscellaneous/application.h" #include "miscellaneous/regexfactory.h" #include "services/abstract/rootitem.h" +#include #include +using RootItemPtr = RootItem*; + FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent) - : QSortFilterProxyModel(parent), m_sourceModel(source_model), m_view(nullptr), - m_selectedItem(nullptr), m_showUnreadOnly(false), m_sortAlphabetically(true) { + : QSortFilterProxyModel(parent), m_sourceModel(source_model), m_view(nullptr), m_selectedItem(nullptr), + m_showUnreadOnly(false), m_sortAlphabetically(true) { setObjectName(QSL("FeedsProxyModel")); setSortRole(Qt::ItemDataRole::EditRole); @@ -28,26 +32,28 @@ FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent) // Smaller index means that item is "smaller" which // means it should be more on top when sorting // in ascending order. - m_priorities = { - RootItem::Kind::Category, - RootItem::Kind::Feed, - RootItem::Kind::Labels, - RootItem::Kind::Important, - RootItem::Kind::Unread, - RootItem::Kind::Bin - }; + m_priorities = {RootItem::Kind::Category, + RootItem::Kind::Feed, + RootItem::Kind::Labels, + RootItem::Kind::Important, + RootItem::Kind::Unread, + RootItem::Kind::Bin}; } FeedsProxyModel::~FeedsProxyModel() { 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; const int match_type = flags & 0x0F; const Qt::CaseSensitivity cs = Qt::CaseSensitivity::CaseInsensitive; - const bool recurse = (flags& Qt::MatchFlag::MatchRecursive) > 0; - const bool wrap = (flags& Qt::MatchFlag::MatchWrap) > 0; + const bool recurse = (flags & Qt::MatchFlag::MatchRecursive) > 0; + const bool wrap = (flags & Qt::MatchFlag::MatchWrap) > 0; const bool all_hits = (hits == -1); QString entered_text; const QModelIndex p = parent(start); @@ -88,7 +94,9 @@ QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const #endif if (QRegularExpression(entered_text, QRegularExpression::PatternOption::CaseInsensitiveOption | - QRegularExpression::PatternOption::UseUnicodePropertiesOption).match(item_text).hasMatch()) { + QRegularExpression::PatternOption::UseUnicodePropertiesOption) + .match(item_text) + .hasMatch()) { result.append(idx); } @@ -97,7 +105,9 @@ QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const case Qt::MatchFlag::MatchWildcard: if (QRegularExpression(RegexFactory::wildcardToRegularExpression(entered_text), QRegularExpression::PatternOption::CaseInsensitiveOption | - QRegularExpression::PatternOption::UseUnicodePropertiesOption).match(item_text).hasMatch()) { + QRegularExpression::PatternOption::UseUnicodePropertiesOption) + .match(item_text) + .hasMatch()) { result.append(idx); } @@ -135,9 +145,11 @@ QModelIndexList FeedsProxyModel::match(const QModelIndex& start, int role, const } if (recurse && hasChildren(idx)) { - result += - match(index(0, idx.column(), idx), role, (entered_text.isEmpty() ? value : entered_text), - (all_hits ? -1 : hits - result.count()), flags); + result += match(index(0, idx.column(), idx), + role, + (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; } +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 { if (left.isValid() && right.isValid()) { // Make necessary castings. @@ -183,14 +273,13 @@ bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right case RootItem::Kind::Feed: case RootItem::Kind::Category: case RootItem::Kind::ServiceRoot: - return sortOrder() == Qt::SortOrder::AscendingOrder - ? left_item->sortOrder() < right_item->sortOrder() - : left_item->sortOrder() > right_item->sortOrder(); + return sortOrder() == Qt::SortOrder::AscendingOrder ? left_item->sortOrder() < right_item->sortOrder() + : left_item->sortOrder() > right_item->sortOrder(); default: return sortOrder() == Qt::SortOrder::AscendingOrder - ? QString::localeAwareCompare(left_item->title().toLower(), right_item->title().toLower()) < 0 - : QString::localeAwareCompare(left_item->title().toLower(), right_item->title().toLower()) > 0; + ? QString::localeAwareCompare(left_item->title().toLower(), right_item->title().toLower()) < 0 + : QString::localeAwareCompare(left_item->title().toLower(), right_item->title().toLower()) > 0; } } } @@ -199,9 +288,8 @@ bool FeedsProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right auto left_priority = m_priorities.indexOf(left_item->kind()); auto right_priority = m_priorities.indexOf(right_item->kind()); - return sortOrder() == Qt::SortOrder::AscendingOrder - ? left_priority < right_priority - : right_priority < left_priority; + return sortOrder() == Qt::SortOrder::AscendingOrder ? left_priority < right_priority + : right_priority < left_priority; } } else { @@ -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 should_show = filterAcceptsRowInternal(source_row, source_parent); - qDebugNN << LOGSEC_CORE - << "Filter accepts row" + qDebugNN << LOGSEC_CORE << "Filter accepts row" << QUOTE_W_SPACE(m_sourceModel->itemForIndex(m_sourceModel->index(source_row, 0, source_parent))->title()) - << "and filter result is:" - << QUOTE_W_SPACE_DOT(should_show); + << "and filter result is:" << QUOTE_W_SPACE_DOT(should_show); /* 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); - if (item->kind() != RootItem::Kind::Category && - item->kind() != RootItem::Kind::Feed && + if (item->kind() != RootItem::Kind::Category && item->kind() != RootItem::Kind::Feed && item->kind() != RootItem::Kind::Label) { // Some items are always visible. 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 // "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. - return - m_selectedItem == item || (item->countOfUnreadMessages() != 0 && - QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent)); + return m_selectedItem == item || + (item->countOfUnreadMessages() != 0 && QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent)); } } +bool FeedsProxyModel::sortAlphabetically() const { + return m_sortAlphabetically; +} + void FeedsProxyModel::sort(int column, Qt::SortOrder order) { QSortFilterProxyModel::sort(column, order); } diff --git a/src/librssguard/core/feedsproxymodel.h b/src/librssguard/core/feedsproxymodel.h index d78a46053..c5959a474 100644 --- a/src/librssguard/core/feedsproxymodel.h +++ b/src/librssguard/core/feedsproxymodel.h @@ -11,17 +11,27 @@ class FeedsModel; class FeedsView; class FeedsProxyModel : public QSortFilterProxyModel { - Q_OBJECT + Q_OBJECT public: explicit FeedsProxyModel(FeedsModel* source_model, QObject* parent = nullptr); 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); // Returns index list of items which "match" given value. // 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. QModelIndexList mapListToSource(const QModelIndexList& indexes) const; @@ -34,6 +44,7 @@ class FeedsProxyModel : public QSortFilterProxyModel { void setSelectedItem(const RootItem* selected_item); void setView(FeedsView* newView); + bool sortAlphabetically() const; void setSortAlphabetically(bool sort_alphabetically); public slots: @@ -42,6 +53,9 @@ class FeedsProxyModel : public QSortFilterProxyModel { signals: void expandAfterFilterIn(QModelIndex source_idx) const; + // There was some drag/drop operation, notify view about this. + void requireItemValidationAfterDragDrop(const QModelIndex& source_index); + protected: virtual bool lessThan(const QModelIndex& left, const QModelIndex& right) const; virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const; diff --git a/src/librssguard/gui/feedsview.cpp b/src/librssguard/gui/feedsview.cpp index 1c6c768f4..e2410760a 100644 --- a/src/librssguard/gui/feedsview.cpp +++ b/src/librssguard/gui/feedsview.cpp @@ -29,8 +29,8 @@ FeedsView::FeedsView(QWidget* parent) : BaseTreeView(parent), m_contextMenuService(nullptr), m_contextMenuBin(nullptr), m_contextMenuCategories(nullptr), - m_contextMenuFeeds(nullptr), m_contextMenuImportant(nullptr), m_contextMenuEmptySpace(nullptr), m_contextMenuOtherItems(nullptr), - m_contextMenuLabel(nullptr), m_dontSaveExpandState(false) { + m_contextMenuFeeds(nullptr), m_contextMenuImportant(nullptr), m_contextMenuEmptySpace(nullptr), + m_contextMenuOtherItems(nullptr), m_contextMenuLabel(nullptr), m_dontSaveExpandState(false) { setObjectName(QSL("FeedsView")); // Allocate models. @@ -40,10 +40,13 @@ FeedsView::FeedsView(QWidget* parent) m_proxyModel->setView(this); // Connections. - connect(m_sourceModel, &FeedsModel::requireItemValidationAfterDragDrop, this, &FeedsView::validateItemAfterDragDrop); connect(m_sourceModel, &FeedsModel::itemExpandRequested, this, &FeedsView::onItemExpandRequested); connect(m_sourceModel, &FeedsModel::itemExpandStateSaveRequested, this, &FeedsView::onItemExpandStateSaveRequested); connect(header(), &QHeaderView::sortIndicatorChanged, this, &FeedsView::saveSortState); + connect(m_proxyModel, + &FeedsProxyModel::requireItemValidationAfterDragDrop, + this, + &FeedsView::validateItemAfterDragDrop); connect(m_proxyModel, &FeedsProxyModel::expandAfterFilterIn, this, &FeedsView::expandItemDelayed); connect(this, &FeedsView::expanded, this, &FeedsView::onIndexExpanded); connect(this, &FeedsView::collapsed, this, &FeedsView::onIndexCollapsed); @@ -127,10 +130,10 @@ void FeedsView::addFeedIntoSelectedAccount() { root->addNewFeed(selected, QGuiApplication::clipboard()->text(QClipboard::Mode::Clipboard)); } else { - qApp->showGuiMessage(Notification::Event::GeneralEvent, { - tr("Not supported by account"), - tr("Selected account does not support adding of new feeds."), - QSystemTrayIcon::MessageIcon::Warning }); + qApp->showGuiMessage(Notification::Event::GeneralEvent, + {tr("Not supported by account"), + tr("Selected account does not support adding of new feeds."), + QSystemTrayIcon::MessageIcon::Warning}); } } } @@ -145,10 +148,10 @@ void FeedsView::addCategoryIntoSelectedAccount() { root->addNewCategory(selectedItem()); } else { - qApp->showGuiMessage(Notification::Event::GeneralEvent, { - tr("Not supported by account"), - tr("Selected account does not support adding of new categories."), - QSystemTrayIcon::MessageIcon::Warning }); + qApp->showGuiMessage(Notification::Event::GeneralEvent, + {tr("Not supported by account"), + tr("Selected account does not support adding of new categories."), + QSystemTrayIcon::MessageIcon::Warning}); } } } @@ -163,7 +166,7 @@ void FeedsView::expandCollapseCurrentItem(bool recursive) { } if (recursive) { - QList to_process = { index }; + QList to_process = {index}; bool expa = !isExpanded(index); while (!to_process.isEmpty()) { @@ -208,10 +211,10 @@ void FeedsView::editSelectedItem() { // Lock was not obtained because // it is used probably by feed updater or application // is quitting. - qApp->showGuiMessage(Notification::Event::GeneralEvent, { - tr("Cannot edit item"), - tr("Selected item cannot be edited because another critical operation is ongoing."), - QSystemTrayIcon::MessageIcon::Warning }); + qApp->showGuiMessage(Notification::Event::GeneralEvent, + {tr("Cannot edit item"), + tr("Selected item cannot be edited because another critical operation is ongoing."), + QSystemTrayIcon::MessageIcon::Warning}); // Thus, cannot delete and quit the method. return; @@ -221,10 +224,10 @@ void FeedsView::editSelectedItem() { selectedItem()->editViaGui(); } else { - qApp->showGuiMessage(Notification::Event::GeneralEvent, { - tr("Cannot edit item"), - tr("Selected item cannot be edited, this is not (yet?) supported."), - QSystemTrayIcon::MessageIcon::Warning }); + qApp->showGuiMessage(Notification::Event::GeneralEvent, + {tr("Cannot edit item"), + tr("Selected item cannot be edited, this is not (yet?) supported."), + QSystemTrayIcon::MessageIcon::Warning}); } // Changes are done, unlock the update master lock. @@ -236,10 +239,10 @@ void FeedsView::deleteSelectedItem() { // Lock was not obtained because // it is used probably by feed updater or application // is quitting. - qApp->showGuiMessage(Notification::Event::GeneralEvent, { - tr("Cannot delete item"), - tr("Selected item cannot be deleted because another critical operation is ongoing."), - QSystemTrayIcon::MessageIcon::Warning }); + qApp->showGuiMessage(Notification::Event::GeneralEvent, + {tr("Cannot delete item"), + tr("Selected item cannot be deleted because another critical operation is ongoing."), + QSystemTrayIcon::MessageIcon::Warning}); // Thus, cannot delete and quit the method. return; @@ -261,7 +264,8 @@ void FeedsView::deleteSelectedItem() { tr("Deleting \"%1\"").arg(selected_item->title()), tr("You are about to completely delete item \"%1\".").arg(selected_item->title()), tr("Are you sure?"), - QString(), QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, + QString(), + QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::Yes) == QMessageBox::StandardButton::No) { // User refused. qApp->feedUpdateLock()->unlock(); @@ -272,17 +276,18 @@ void FeedsView::deleteSelectedItem() { if (!selected_item->deleteViaGui()) { m_proxyModel->invalidate(); - qApp->showGuiMessage(Notification::Event::GeneralEvent, { - tr("Cannot delete \"%1\"").arg(selected_item->title()), - tr("This item cannot be deleted because something critically failed. Submit bug report."), - QSystemTrayIcon::MessageIcon::Critical }); + qApp->showGuiMessage(Notification::Event::GeneralEvent, + {tr("Cannot delete \"%1\"").arg(selected_item->title()), + tr("This item cannot be deleted because something critically failed. Submit bug report."), + QSystemTrayIcon::MessageIcon::Critical}); } } else { - qApp->showGuiMessage(Notification::Event::GeneralEvent, { - tr("Cannot delete \"%1\"").arg(selected_item->title()), - tr("This item cannot be deleted, because it does not support it\nor this functionality is not implemented yet."), - QSystemTrayIcon::MessageIcon::Critical }); + qApp->showGuiMessage(Notification::Event::GeneralEvent, + {tr("Cannot delete \"%1\"").arg(selected_item->title()), + tr("This item cannot be deleted, because it does not support it\nor this functionality is " + "not implemented yet."), + QSystemTrayIcon::MessageIcon::Critical}); } } @@ -395,7 +400,8 @@ QModelIndex FeedsView::nextUnreadItem(const QModelIndex& default_row) { const QModelIndex starting_row = default_row; 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 (m_proxyModel->hasChildren(nconst_default_row)) { @@ -435,10 +441,9 @@ QMenu* FeedsView::initializeContextMenuBin(RootItem* clicked_item) { QList specific_actions = clicked_item->contextMenuFeedsList(); - m_contextMenuBin->addActions(QList() << - qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode << - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead << - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread); + m_contextMenuBin->addActions(QList() << qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode + << qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead + << qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread); if (!specific_actions.isEmpty()) { m_contextMenuBin->addSeparator(); @@ -458,15 +463,15 @@ QMenu* FeedsView::initializeContextMenuService(RootItem* clicked_item) { QList specific_actions = clicked_item->contextMenuFeedsList(); - m_contextMenuService->addActions({ qApp->mainForm()->m_ui->m_actionUpdateSelectedItems, - qApp->mainForm()->m_ui->m_actionEditSelectedItem, - qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed, - qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode, - qApp->mainForm()->m_ui->m_actionExpandCollapseItem, - qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively, - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead, - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread, - qApp->mainForm()->m_ui->m_actionDeleteSelectedItem }); + m_contextMenuService->addActions({qApp->mainForm()->m_ui->m_actionUpdateSelectedItems, + qApp->mainForm()->m_ui->m_actionEditSelectedItem, + qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed, + qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode, + qApp->mainForm()->m_ui->m_actionExpandCollapseItem, + qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively, + qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead, + qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread, + qApp->mainForm()->m_ui->m_actionDeleteSelectedItem}); auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding(); 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); } - if (!qApp->settings()->value(GROUP(Feeds), - SETTING(Feeds::SortAlphabetically)).toBool()) { + if (!qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::SortAlphabetically)).toBool()) { m_contextMenuService->addSeparator(); m_contextMenuService->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveUp); m_contextMenuService->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveDown); @@ -521,7 +525,8 @@ void FeedsView::focusInEvent(QFocusEvent* event) { QTreeView::focusInEvent(event); 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)); - if (it != nullptr && (int(it->kind()) & int(RootItem::Kind::Category | - RootItem::Kind::ServiceRoot | - RootItem::Kind::Labels)) > 0) { + if (it != nullptr && + (int(it->kind()) & int(RootItem::Kind::Category | RootItem::Kind::ServiceRoot | RootItem::Kind::Labels)) > 0) { const QString setting_name = it->hashCode(); - qApp->settings()->setValue(GROUP(CategoriesExpandStates), - setting_name, - true); + qApp->settings()->setValue(GROUP(CategoriesExpandStates), setting_name, true); } } @@ -575,14 +577,11 @@ void FeedsView::onIndexCollapsed(const QModelIndex& idx) { RootItem* it = m_sourceModel->itemForIndex(m_proxyModel->mapToSource(idx)); - if (it != nullptr && (int(it->kind()) & int(RootItem::Kind::Category | - RootItem::Kind::ServiceRoot | - RootItem::Kind::Labels)) > 0) { + if (it != nullptr && + (int(it->kind()) & int(RootItem::Kind::Category | RootItem::Kind::ServiceRoot | RootItem::Kind::Labels)) > 0) { const QString setting_name = it->hashCode(); - qApp->settings()->setValue(GROUP(CategoriesExpandStates), - setting_name, - false); + qApp->settings()->setValue(GROUP(CategoriesExpandStates), setting_name, false); } } @@ -596,9 +595,8 @@ void FeedsView::saveAllExpandStates() { void FeedsView::saveExpandStates(RootItem* item) { Settings* settings = qApp->settings(); - QList items = item->getSubTree(RootItem::Kind::Category | - RootItem::Kind::ServiceRoot | - RootItem::Kind::Labels); + QList items = + item->getSubTree(RootItem::Kind::Category | RootItem::Kind::ServiceRoot | RootItem::Kind::Labels); // Iterate all categories and save their expand statuses. for (const RootItem* it : items) { @@ -606,9 +604,7 @@ void FeedsView::saveExpandStates(RootItem* item) { QModelIndex source_index = sourceModel()->indexForItem(it); QModelIndex visible_index = model()->mapFromSource(source_index); - settings->setValue(GROUP(CategoriesExpandStates), - setting_name, - isExpanded(visible_index)); + settings->setValue(GROUP(CategoriesExpandStates), setting_name, isExpanded(visible_index)); } } @@ -616,8 +612,7 @@ void FeedsView::loadAllExpandStates() { const Settings* settings = qApp->settings(); QList expandable_items; - expandable_items.append(sourceModel()->rootItem()->getSubTree(RootItem::Kind::Category | - RootItem::Kind::ServiceRoot | + expandable_items.append(sourceModel()->rootItem()->getSubTree(RootItem::Kind::Category | RootItem::Kind::ServiceRoot | RootItem::Kind::Labels)); // Iterate all categories and save their expand statuses. @@ -629,13 +624,15 @@ void FeedsView::loadAllExpandStates() { } sortByColumn(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortColumnFeeds)).toInt(), - static_cast(qApp->settings()->value(GROUP(GUI), SETTING(GUI::DefaultSortOrderFeeds)).toInt())); + static_cast(qApp->settings() + ->value(GROUP(GUI), SETTING(GUI::DefaultSortOrderFeeds)) + .toInt())); } void FeedsView::expandItemDelayed(const QModelIndex& source_idx) { - //QTimer::singleShot(100, this, [=] { - // Model requests to expand some items as they are visible and there is - // a filter active, so they maybe were not visible before. + // QTimer::singleShot(100, this, [=] { + // Model requests to expand some items as they are visible and there is + // a filter active, so they maybe were not visible before. QModelIndex pidx = m_proxyModel->mapFromSource(source_idx); // NOTE: These changes are caused by filtering mechanisms @@ -663,15 +660,15 @@ QMenu* FeedsView::initializeContextMenuCategories(RootItem* clicked_item) { QList specific_actions = clicked_item->contextMenuFeedsList(); - m_contextMenuCategories->addActions({ qApp->mainForm()->m_ui->m_actionUpdateSelectedItems, - qApp->mainForm()->m_ui->m_actionEditSelectedItem, - qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed, - qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode, - qApp->mainForm()->m_ui->m_actionExpandCollapseItem, - qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively, - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead, - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread, - qApp->mainForm()->m_ui->m_actionDeleteSelectedItem }); + m_contextMenuCategories->addActions({qApp->mainForm()->m_ui->m_actionUpdateSelectedItems, + qApp->mainForm()->m_ui->m_actionEditSelectedItem, + qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed, + qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode, + qApp->mainForm()->m_ui->m_actionExpandCollapseItem, + qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively, + qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead, + qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread, + qApp->mainForm()->m_ui->m_actionDeleteSelectedItem}); auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding(); 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); } - if (!qApp->settings()->value(GROUP(Feeds), - SETTING(Feeds::SortAlphabetically)).toBool()) { + if (!qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::SortAlphabetically)).toBool()) { m_contextMenuCategories->addSeparator(); m_contextMenuCategories->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveUp); m_contextMenuCategories->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveDown); @@ -715,14 +711,13 @@ QMenu* FeedsView::initializeContextMenuFeeds(RootItem* clicked_item) { QList specific_actions = clicked_item->contextMenuFeedsList(); - m_contextMenuFeeds->addActions(QList() << - qApp->mainForm()->m_ui->m_actionUpdateSelectedItems << - qApp->mainForm()->m_ui->m_actionEditSelectedItem << - qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed << - qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode << - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead << - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread << - qApp->mainForm()->m_ui->m_actionDeleteSelectedItem); + m_contextMenuFeeds->addActions(QList() << qApp->mainForm()->m_ui->m_actionUpdateSelectedItems + << qApp->mainForm()->m_ui->m_actionEditSelectedItem + << qApp->mainForm()->m_ui->m_actionCopyUrlSelectedFeed + << qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode + << qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead + << qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread + << qApp->mainForm()->m_ui->m_actionDeleteSelectedItem); auto cat_add = clicked_item->getParentServiceRoot()->supportsCategoryAdding(); 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); } - if (!qApp->settings()->value(GROUP(Feeds), - SETTING(Feeds::SortAlphabetically)).toBool()) { + if (!qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::SortAlphabetically)).toBool()) { m_contextMenuFeeds->addSeparator(); m_contextMenuFeeds->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveUp); m_contextMenuFeeds->addAction(qApp->mainForm()->m_ui->m_actionFeedMoveDown); @@ -766,10 +760,9 @@ QMenu* FeedsView::initializeContextMenuImportant(RootItem* clicked_item) { QList specific_actions = clicked_item->contextMenuFeedsList(); - m_contextMenuImportant->addActions(QList() << - qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode << - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead << - qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread); + m_contextMenuImportant->addActions(QList() << qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode + << qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead + << qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread); if (!specific_actions.isEmpty()) { m_contextMenuImportant->addSeparator(); @@ -849,15 +842,17 @@ void FeedsView::setupAppearance() { setExpandsOnDoubleClick(true); setEditTriggers(QAbstractItemView::EditTrigger::NoEditTriggers); setIndentation(FEEDS_VIEW_INDENTATION); - setAcceptDrops(false); + setAcceptDrops(true); + viewport()->setAcceptDrops(true); setDragEnabled(true); setDropIndicatorShown(true); setDragDropMode(QAbstractItemView::DragDropMode::InternalMove); setAllColumnsShowFocus(false); setRootIsDecorated(false); setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); - setItemDelegate(new StyledItemDelegateWithoutFocus(qApp->settings()->value(GROUP(GUI), - SETTING(GUI::HeightRowFeeds)).toInt(), + setItemDelegate(new StyledItemDelegateWithoutFocus(qApp->settings() + ->value(GROUP(GUI), SETTING(GUI::HeightRowFeeds)) + .toInt(), -1, this)); } @@ -904,8 +899,7 @@ void FeedsView::contextMenuEvent(QContextMenuEvent* event) { // Display context menu for feeds. initializeContextMenuFeeds(clicked_item)->exec(event->globalPos()); } - else if (clicked_item->kind() == RootItem::Kind::Important || - clicked_item->kind() == RootItem::Kind::Unread) { + else if (clicked_item->kind() == RootItem::Kind::Important || clicked_item->kind() == RootItem::Kind::Unread) { initializeContextMenuImportant(clicked_item)->exec(event->globalPos()); } else if (clicked_item->kind() == RootItem::Kind::Bin) {