diff --git a/src/librssguard/core/feedsmodel.cpp b/src/librssguard/core/feedsmodel.cpp index a29e9fed8..b95758d01 100644 --- a/src/librssguard/core/feedsmodel.cpp +++ b/src/librssguard/core/feedsmodel.cpp @@ -455,6 +455,18 @@ void FeedsModel::changeSortOrder(RootItem* item, bool move_top, bool move_bottom DatabaseQueries::moveItem(item, move_top, move_bottom, new_sort_order, db); } +void FeedsModel::sortDirectDescendants(RootItem* item, RootItem::Kind kind_to_sort) { + auto childs = item->childItems(kind_to_sort); + + std::sort(childs.begin(), childs.end(), [](RootItem* lhs, RootItem* rhs) { + return lhs->title().compare(rhs->title(), Qt::CaseSensitivity::CaseInsensitive) < 0; + }); + + for (RootItem* it : childs) { + changeSortOrder(it, false, true); + } +} + void FeedsModel::loadActivatedServiceAccounts() { auto serv = qApp->feedReader()->feedServices(); diff --git a/src/librssguard/core/feedsmodel.h b/src/librssguard/core/feedsmodel.h index 39e0c65c0..540f9b92d 100644 --- a/src/librssguard/core/feedsmodel.h +++ b/src/librssguard/core/feedsmodel.h @@ -107,6 +107,10 @@ class RSSGUARD_DLLSPEC FeedsModel : public QAbstractItemModel { void changeSortOrder(RootItem* item, bool move_top, bool move_bottom, int new_sort_order = {}); + // Takes direct descendants (but only categories or feeds) + // and rearranges them alphabetically. + void sortDirectDescendants(RootItem* item, RootItem::Kind kind_to_sort); + // Feeds operations. bool markItemRead(RootItem* item, RootItem::ReadStatus read); bool markItemCleared(RootItem* item, bool clean_read_only); diff --git a/src/librssguard/gui/dialogs/formmain.cpp b/src/librssguard/gui/dialogs/formmain.cpp index ccdb3c961..1e7028bb3 100644 --- a/src/librssguard/gui/dialogs/formmain.cpp +++ b/src/librssguard/gui/dialogs/formmain.cpp @@ -480,6 +480,8 @@ void FormMain::updateFeedButtonsAvailability() { const bool service_selected = anything_selected && selected_item->kind() == RootItem::Kind::ServiceRoot; const bool manual_feed_sort = !m_ui->m_actionSortFeedsAlphabetically->isChecked(); + m_ui->m_actionRearrangeFeeds->setEnabled(manual_feed_sort && (service_selected || category_selected)); + m_ui->m_actionRearrangeCategories->setEnabled(manual_feed_sort && (service_selected || category_selected)); m_ui->m_actionStopRunningItemsUpdate->setEnabled(is_update_running); m_ui->m_actionBackupDatabaseSettings->setEnabled(!critical_action_running); m_ui->m_actionCleanupDatabase->setEnabled(!critical_action_running); @@ -892,6 +894,15 @@ void FormMain::createConnections() { &QAction::triggered, tabWidget()->feedMessageViewer()->feedsView(), &FeedsView::updateSelectedItems); + connect(m_ui->m_actionRearrangeCategories, + &QAction::triggered, + tabWidget()->feedMessageViewer()->feedsView(), + &FeedsView::rearrangeCategoriesOfSelectedItem); + connect(m_ui->m_actionRearrangeFeeds, + &QAction::triggered, + tabWidget()->feedMessageViewer()->feedsView(), + &FeedsView::rearrangeFeedsOfSelectedItem); + connect(m_ui->m_actionUpdateAllItems, &QAction::triggered, qApp->feedReader(), &FeedReader::updateAllFeeds); connect(m_ui->m_actionUpdateSelectedItemsWithCustomTimers, &QAction::triggered, diff --git a/src/librssguard/gui/dialogs/formmain.ui b/src/librssguard/gui/dialogs/formmain.ui old mode 100644 new mode 100755 index 5c857a368..16cebce67 --- a/src/librssguard/gui/dialogs/formmain.ui +++ b/src/librssguard/gui/dialogs/formmain.ui @@ -128,6 +128,9 @@ + + + @@ -918,6 +921,16 @@ Scroll &down browser + + + Rearrange &subcategories alphabetically + + + + + Rearrange &feeds alphabetically + + diff --git a/src/librssguard/gui/feedsview.cpp b/src/librssguard/gui/feedsview.cpp index c93dff8ce..2af3cf463 100644 --- a/src/librssguard/gui/feedsview.cpp +++ b/src/librssguard/gui/feedsview.cpp @@ -315,6 +315,16 @@ void FeedsView::moveSelectedItemDown() { m_proxyModel->invalidate(); } +void FeedsView::rearrangeCategoriesOfSelectedItem() { + m_sourceModel->sortDirectDescendants(selectedItem(), RootItem::Kind::Category); + m_proxyModel->invalidate(); +} + +void FeedsView::rearrangeFeedsOfSelectedItem() { + m_sourceModel->sortDirectDescendants(selectedItem(), RootItem::Kind::Feed); + m_proxyModel->invalidate(); +} + void FeedsView::markSelectedItemReadStatus(RootItem::ReadStatus read) { m_sourceModel->markItemRead(selectedItem(), read); } @@ -469,6 +479,8 @@ QMenu* FeedsView::initializeContextMenuService(RootItem* clicked_item) { qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode, qApp->mainForm()->m_ui->m_actionExpandCollapseItem, qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively, + qApp->mainForm()->m_ui->m_actionRearrangeCategories, + qApp->mainForm()->m_ui->m_actionRearrangeFeeds, qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead, qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread, qApp->mainForm()->m_ui->m_actionDeleteSelectedItem}); @@ -691,6 +703,8 @@ QMenu* FeedsView::initializeContextMenuCategories(RootItem* clicked_item) { qApp->mainForm()->m_ui->m_actionViewSelectedItemsNewspaperMode, qApp->mainForm()->m_ui->m_actionExpandCollapseItem, qApp->mainForm()->m_ui->m_actionExpandCollapseItemRecursively, + qApp->mainForm()->m_ui->m_actionRearrangeCategories, + qApp->mainForm()->m_ui->m_actionRearrangeFeeds, qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsRead, qApp->mainForm()->m_ui->m_actionMarkSelectedItemsAsUnread, qApp->mainForm()->m_ui->m_actionDeleteSelectedItem}); diff --git a/src/librssguard/gui/feedsview.h b/src/librssguard/gui/feedsview.h index 02ebfd87c..eae1fc1ef 100644 --- a/src/librssguard/gui/feedsview.h +++ b/src/librssguard/gui/feedsview.h @@ -72,6 +72,8 @@ class RSSGUARD_DLLSPEC FeedsView : public BaseTreeView { void moveSelectedItemTop(); void moveSelectedItemBottom(); void moveSelectedItemDown(); + void rearrangeCategoriesOfSelectedItem(); + void rearrangeFeedsOfSelectedItem(); // Selects next/previous item (feed/category) in the list. void selectNextItem(); diff --git a/src/librssguard/services/abstract/rootitem.cpp b/src/librssguard/services/abstract/rootitem.cpp index 52f6df9d7..ca7fb431f 100644 --- a/src/librssguard/services/abstract/rootitem.cpp +++ b/src/librssguard/services/abstract/rootitem.cpp @@ -639,3 +639,13 @@ RootItem::Kind operator|(RootItem::Kind a, RootItem::Kind b) { RootItem::Kind operator&(RootItem::Kind a, RootItem::Kind b) { return static_cast(static_cast(a) & static_cast(b)); } + +QList RootItem::childItems(Kind kind) const { + auto linq = boolinq::from(m_childItems) + .where([=](RootItem* it) { + return it->kind() == kind; + }) + .toStdList(); + + return FROM_STD_LIST(QList, linq); +} diff --git a/src/librssguard/services/abstract/rootitem.h b/src/librssguard/services/abstract/rootitem.h index de0fdf681..2a5a39a1a 100644 --- a/src/librssguard/services/abstract/rootitem.h +++ b/src/librssguard/services/abstract/rootitem.h @@ -112,6 +112,8 @@ class RSSGUARD_DLLSPEC RootItem : public QObject { RootItem* child(int row); int childCount() const; void appendChild(RootItem* child); + + QList childItems(RootItem::Kind kind) const; QList childItems() const; QList& childItems();