File indexing completed on 2024-05-12 05:12:50

0001 /*
0002     This file is part of Akregator.
0003 
0004     SPDX-FileCopyrightText: 2005 Frank Osterfeld <osterfeld@kde.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0
0007 */
0008 
0009 #include "actionmanagerimpl.h"
0010 #include "akregator_part.h"
0011 #include "akregatorconfig.h"
0012 #include "articlelistview.h"
0013 #include "feed.h"
0014 #include "fetchqueue.h"
0015 #include "folder.h"
0016 #include "kernel.h"
0017 #include "mainwidget.h"
0018 #include "subscriptionlistview.h"
0019 #include "tabwidget.h"
0020 #include "trayicon.h"
0021 #include "treenode.h"
0022 #include "treenodevisitor.h"
0023 
0024 #include <WebEngineViewer/ZoomActionMenu>
0025 
0026 #include "akregator_debug.h"
0027 #include <KActionCollection>
0028 #include <KActionMenu>
0029 #include <KColorSchemeMenu>
0030 #include <KGuiItem>
0031 #include <KLocalizedString>
0032 #include <KStandardAction>
0033 #include <KStandardShortcut>
0034 #include <KToggleAction>
0035 #include <QAction>
0036 #include <QActionGroup>
0037 #include <QKeySequence>
0038 #include <QMenu>
0039 #include <kxmlguifactory.h>
0040 
0041 #include <KColorSchemeManager>
0042 #include <QWidget>
0043 
0044 using namespace Akregator;
0045 
0046 class ActionManagerImpl::NodeSelectVisitor : public TreeNodeVisitor
0047 {
0048 public:
0049     NodeSelectVisitor(ActionManagerImpl *manager)
0050         : m_manager(manager)
0051     {
0052     }
0053 
0054     bool visitFeed(Feed *node) override
0055     {
0056         QAction *remove = m_manager->action(QStringLiteral("feed_remove"));
0057         if (remove) {
0058             remove->setEnabled(true);
0059         }
0060         QAction *hp = m_manager->action(QStringLiteral("feed_homepage"));
0061         if (hp) {
0062             hp->setEnabled(!node->htmlUrl().isEmpty());
0063         }
0064         m_manager->action(QStringLiteral("feed_fetch"))->setText(i18n("&Fetch Feed"));
0065         m_manager->action(QStringLiteral("feed_remove"))->setText(i18n("&Delete Feed"));
0066         m_manager->action(QStringLiteral("feed_modify"))->setText(i18n("&Edit Feed..."));
0067         m_manager->action(QStringLiteral("feed_mark_all_as_read"))->setText(i18n("&Mark Feed as Read"));
0068 
0069         return true;
0070     }
0071 
0072     bool visitFolder(Folder *node) override
0073     {
0074         QAction *remove = m_manager->action(QStringLiteral("feed_remove"));
0075         if (remove) {
0076             remove->setEnabled(node->parent()); // root nodes must not be deleted
0077         }
0078         QAction *hp = m_manager->action(QStringLiteral("feed_homepage"));
0079         if (hp) {
0080             hp->setEnabled(false);
0081         }
0082 
0083         m_manager->action(QStringLiteral("feed_fetch"))->setText(i18n("&Fetch Feeds"));
0084         m_manager->action(QStringLiteral("feed_remove"))->setText(i18n("&Delete Folder"));
0085         m_manager->action(QStringLiteral("feed_modify"))->setText(i18n("&Rename Folder"));
0086         m_manager->action(QStringLiteral("feed_mark_all_as_read"))->setText(i18n("&Mark Feeds as Read"));
0087 
0088         return true;
0089     }
0090 
0091 private:
0092     ActionManagerImpl *const m_manager;
0093 };
0094 
0095 class ActionManagerImpl::ActionManagerImplPrivate
0096 {
0097 public:
0098     [[nodiscard]] QString quickSearchLineText() const;
0099     NodeSelectVisitor *nodeSelectVisitor = nullptr;
0100     ArticleListView *articleList = nullptr;
0101     SubscriptionListView *subscriptionListView = nullptr;
0102     MainWidget *mainWidget = nullptr;
0103     Part *part = nullptr;
0104     TrayIcon *trayIcon = nullptr;
0105     KActionMenu *tagMenu = nullptr;
0106     KActionCollection *actionCollection = nullptr;
0107     TabWidget *tabWidget = nullptr;
0108     PimCommon::ShareServiceUrlManager *shareServiceManager = nullptr;
0109     WebEngineViewer::ZoomActionMenu *zoomActionMenu = nullptr;
0110     QAction *mQuickSearchAction = nullptr;
0111 };
0112 
0113 void ActionManagerImpl::slotSettingsChanged()
0114 {
0115     QAction *a = action(QStringLiteral("feed_hide_read"));
0116     if (!a) {
0117         qCCritical(AKREGATOR_LOG) << "Action not found";
0118         return;
0119     }
0120     a->setChecked(Settings::hideReadFeeds());
0121 
0122     a = action(QStringLiteral("feed_lock_in_place"));
0123     if (!a) {
0124         qCCritical(AKREGATOR_LOG) << "Action not found";
0125         return;
0126     }
0127     a->setChecked(Settings::lockFeedsInPlace());
0128 
0129     a = action(QStringLiteral("auto_expand_folders"));
0130     if (!a) {
0131         qCCritical(AKREGATOR_LOG) << "Action not found";
0132         return;
0133     }
0134     a->setChecked(Settings::autoExpandFolders());
0135 }
0136 
0137 void ActionManagerImpl::slotNodeSelected(TreeNode *node)
0138 {
0139     if (node) {
0140         d->nodeSelectVisitor->visit(node);
0141     }
0142 }
0143 
0144 ActionManagerImpl::ActionManagerImpl(Part *part, QObject *parent)
0145     : ActionManager(parent)
0146     , d(new ActionManagerImplPrivate)
0147 {
0148     d->nodeSelectVisitor = new NodeSelectVisitor(this);
0149     d->part = part;
0150     d->subscriptionListView = nullptr;
0151     d->articleList = nullptr;
0152     d->trayIcon = nullptr;
0153     d->mainWidget = nullptr;
0154     d->tabWidget = nullptr;
0155     d->tagMenu = nullptr;
0156     d->actionCollection = part->actionCollection();
0157     d->shareServiceManager = new PimCommon::ShareServiceUrlManager(this);
0158     initPart();
0159 }
0160 
0161 ActionManagerImpl::~ActionManagerImpl()
0162 {
0163     delete d->nodeSelectVisitor;
0164 }
0165 
0166 void ActionManagerImpl::setTrayIcon(TrayIcon *trayIcon)
0167 {
0168     if (trayIcon == nullptr) {
0169         d->trayIcon = nullptr;
0170         return;
0171     }
0172     if (d->trayIcon) {
0173         return;
0174     } else {
0175         d->trayIcon = trayIcon;
0176     }
0177 
0178     QMenu *traypop = trayIcon->contextMenu();
0179 
0180     if (QAction *act = actionCollection()->action(QStringLiteral("feed_fetch_all"))) {
0181         traypop->addAction(act);
0182     }
0183     if (QAction *act = actionCollection()->action(QStringLiteral("options_configure"))) {
0184         traypop->addAction(act);
0185     }
0186 }
0187 
0188 void ActionManagerImpl::initPart()
0189 {
0190     QAction *action = d->actionCollection->addAction(QStringLiteral("file_import"));
0191     action->setText(i18n("&Import Feeds..."));
0192     action->setIcon(QIcon::fromTheme(QStringLiteral("document-import")));
0193     connect(action, &QAction::triggered, d->part, &Part::fileImport);
0194     action = d->actionCollection->addAction(QStringLiteral("file_export"));
0195     action->setText(i18n("&Export Feeds..."));
0196     action->setIcon(QIcon::fromTheme(QStringLiteral("document-export")));
0197     connect(action, &QAction::triggered, d->part, &Part::fileExport);
0198 
0199     QAction *configure = d->actionCollection->addAction(QStringLiteral("options_configure"));
0200     configure->setText(i18n("&Configure Akregator..."));
0201     configure->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
0202     connect(configure, &QAction::triggered, d->part, &Part::showOptions);
0203 
0204     KStandardAction::configureNotifications(d->part, &Part::showNotificationOptions, d->actionCollection); // options_configure_notifications
0205 }
0206 
0207 void ActionManagerImpl::initMainWidget(MainWidget *mainWidget)
0208 {
0209     if (d->mainWidget) {
0210         return;
0211     }
0212 
0213     d->mainWidget = mainWidget;
0214 
0215     KActionCollection *coll = actionCollection();
0216 
0217     // Feed/Feed Group popup menu
0218     QAction *action = coll->addAction(QStringLiteral("feed_homepage"));
0219     action->setText(i18n("&Open Homepage"));
0220     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotOpenHomepage);
0221     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_H));
0222 
0223     action = coll->addAction(QStringLiteral("reload_all_tabs"));
0224     action->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
0225     action->setText(i18n("Reload All Tabs"));
0226     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotReloadAllTabs);
0227     coll->setDefaultShortcut(action, QKeySequence(Qt::SHIFT | Qt::Key_F5));
0228 
0229     action = coll->addAction(QStringLiteral("feed_add"));
0230     action->setIcon(QIcon::fromTheme(QStringLiteral("feed-subscribe")));
0231     action->setText(i18n("&Add Feed..."));
0232     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotFeedAdd);
0233     coll->setDefaultShortcut(action, QKeySequence(Qt::Key_Insert));
0234 
0235     action = coll->addAction(QStringLiteral("feed_add_group"));
0236     action->setIcon(QIcon::fromTheme(QStringLiteral("folder-new")));
0237     action->setText(i18n("Ne&w Folder..."));
0238     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotFeedAddGroup);
0239     coll->setDefaultShortcut(action, QKeySequence(Qt::SHIFT | Qt::Key_Insert));
0240 
0241     action = coll->addAction(QStringLiteral("feed_remove"));
0242     action->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")));
0243     action->setText(i18n("&Delete Feed"));
0244     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotFeedRemove);
0245     coll->setDefaultShortcut(action, QKeySequence(Qt::ALT | Qt::Key_Delete));
0246 
0247     action = coll->addAction(QStringLiteral("feed_modify"));
0248     action->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
0249     action->setText(i18n("&Edit Feed..."));
0250     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotFeedModify);
0251     coll->setDefaultShortcut(action, QKeySequence(Qt::Key_F2));
0252 
0253     // toolbar / View
0254 
0255     const auto viewMode = static_cast<MainWidget::ViewMode>(Settings::viewMode());
0256     auto group = new QActionGroup(this);
0257     action = coll->addAction(QStringLiteral("normal_view"));
0258     action->setCheckable(true);
0259     action->setChecked(viewMode == MainWidget::NormalView);
0260     group->addAction(action);
0261     action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-top-bottom")));
0262     action->setText(i18n("&Normal View"));
0263     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotNormalView);
0264     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_1));
0265 
0266     action = coll->addAction(QStringLiteral("widescreen_view"));
0267     action->setCheckable(true);
0268     action->setChecked(viewMode == MainWidget::WidescreenView);
0269     group->addAction(action);
0270     action->setIcon(QIcon::fromTheme(QStringLiteral("view-split-left-right")));
0271     action->setText(i18n("&Widescreen View"));
0272     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotWidescreenView);
0273     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_2));
0274 
0275     action = coll->addAction(QStringLiteral("combined_view"));
0276     action->setCheckable(true);
0277     action->setChecked(viewMode == MainWidget::CombinedView);
0278     group->addAction(action);
0279     action->setIcon(QIcon::fromTheme(QStringLiteral("view-list-text")));
0280     action->setText(i18n("C&ombined View"));
0281     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotCombinedView);
0282     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_3));
0283 
0284     // toolbar / feed menu
0285     action = coll->addAction(QStringLiteral("feed_fetch"));
0286     action->setIcon(QIcon::fromTheme(QStringLiteral("go-down")));
0287     action->setText(i18n("&Fetch Feed"));
0288     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotFetchCurrentFeed);
0289     coll->setDefaultShortcuts(action, KStandardShortcut::shortcut(KStandardShortcut::Reload));
0290 
0291     action = coll->addAction(QStringLiteral("feed_fetch_all"));
0292     action->setIcon(QIcon::fromTheme(QStringLiteral("go-bottom")));
0293     action->setText(i18n("Fe&tch All Feeds"));
0294     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotFetchAllFeeds);
0295     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_L));
0296 
0297     QAction *stopAction = coll->addAction(QStringLiteral("feed_stop"));
0298     stopAction->setIcon(QIcon::fromTheme(QStringLiteral("process-stop")));
0299     stopAction->setText(i18n("C&ancel Feed Fetches"));
0300     connect(stopAction, &QAction::triggered, Kernel::self()->fetchQueue(), &FetchQueue::slotAbort);
0301     coll->setDefaultShortcut(stopAction, QKeySequence(Qt::Key_Escape));
0302     stopAction->setEnabled(false);
0303 
0304     action = coll->addAction(QStringLiteral("feed_mark_all_as_read"));
0305     action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-read")));
0306     action->setText(i18n("&Mark Feed as Read"));
0307     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotMarkAllRead);
0308     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_R));
0309 
0310     action = coll->addAction(QStringLiteral("feed_mark_all_feeds_as_read"));
0311     action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-read")));
0312     action->setText(i18n("Ma&rk All Feeds as Read"));
0313     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotMarkAllFeedsRead);
0314     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_R));
0315 
0316     // Settings menu
0317     auto sqf = coll->add<KToggleAction>(QStringLiteral("show_quick_filter"));
0318     sqf->setText(i18n("Show Quick Filter"));
0319     connect(sqf, &QAction::triggered, d->mainWidget, &MainWidget::slotToggleShowQuickFilter);
0320     sqf->setChecked(Settings::showQuickFilter());
0321 
0322     action = coll->addAction(QStringLiteral("article_open"));
0323     action->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
0324     action->setText(i18n("Open in Tab"));
0325     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotOpenSelectedArticles);
0326     coll->setDefaultShortcut(action, QKeySequence(Qt::SHIFT | Qt::Key_Return));
0327 
0328     action = coll->addAction(QStringLiteral("article_open_in_background"));
0329     action->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
0330     action->setText(i18n("Open in Background Tab"));
0331     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotOpenSelectedArticlesInBackground);
0332     coll->setDefaultShortcut(action, QKeySequence(Qt::Key_Return));
0333 
0334     action = coll->addAction(QStringLiteral("article_open_external"));
0335     action->setIcon(QIcon::fromTheme(QStringLiteral("window-new")));
0336     action->setText(i18n("Open in External Browser"));
0337     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotOpenSelectedArticlesInBrowser);
0338     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_Return));
0339 
0340     action = coll->addAction(QStringLiteral("article_copy_link_address"));
0341     action->setText(i18n("Copy Link Address"));
0342     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotCopyLinkAddress);
0343 
0344     action = coll->addAction(QStringLiteral("go_prev_unread_article"));
0345     action->setIcon(QIcon::fromTheme(QStringLiteral("go-previous")));
0346     action->setText(i18n("Pre&vious Unread Article"));
0347     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotPrevUnreadArticle);
0348     coll->setDefaultShortcuts(action, QList<QKeySequence>() << QKeySequence(Qt::Key_Minus) << QKeySequence(Qt::Key_Minus | Qt::KeypadModifier));
0349 
0350     action = coll->addAction(QStringLiteral("go_next_unread_article"));
0351     action->setIcon(QIcon::fromTheme(QStringLiteral("go-next")));
0352     action->setText(i18n("Ne&xt Unread Article"));
0353     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotNextUnreadArticle);
0354     coll->setDefaultShortcuts(action,
0355                               QList<QKeySequence>() << QKeySequence(Qt::Key_Plus) << QKeySequence(Qt::Key_Plus | Qt::KeypadModifier)
0356                                                     << QKeySequence(Qt::Key_Equal) << QKeySequence(Qt::Key_Equal | Qt::KeypadModifier));
0357 
0358     action = coll->addAction(QStringLiteral("article_delete"));
0359     action->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")));
0360     action->setText(i18n("&Delete"));
0361     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotArticleDelete);
0362     coll->setDefaultShortcut(action, QKeySequence(Qt::Key_Delete));
0363 
0364     auto statusMenu = coll->add<KActionMenu>(QStringLiteral("article_set_status"));
0365     statusMenu->setText(i18n("&Mark As"));
0366     statusMenu->setEnabled(false);
0367 
0368     action = coll->addAction(QStringLiteral("article_set_status_read"));
0369     action->setText(i18nc("as in: mark as read", "&Read"));
0370     action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-read")));
0371     action->setToolTip(i18n("Mark selected article as read"));
0372     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_E));
0373     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotSetSelectedArticleRead);
0374     statusMenu->addAction(action);
0375 
0376     action = coll->addAction(QStringLiteral("article_set_status_new"));
0377     action->setText(i18nc("as in: mark as new", "&New"));
0378     action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-unread-new")));
0379     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_N));
0380     action->setToolTip(i18n("Mark selected article as new"));
0381     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotSetSelectedArticleNew);
0382     statusMenu->addAction(action);
0383 
0384     action = coll->addAction(QStringLiteral("article_set_status_unread"));
0385     action->setText(i18nc("as in: mark as unread", "&Unread"));
0386     action->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-unread")));
0387     action->setToolTip(i18n("Mark selected article as unread"));
0388     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_U));
0389     connect(action, &QAction::triggered, d->mainWidget, &MainWidget::slotSetSelectedArticleUnread);
0390     statusMenu->addAction(action);
0391 
0392     auto importantAction = coll->add<KToggleAction>(QStringLiteral("article_set_status_important"));
0393     importantAction->setText(i18n("&Mark as Important"));
0394     importantAction->setIcon(QIcon::fromTheme(QStringLiteral("mail-mark-important")));
0395     const QList<QKeySequence> importantSC = {QKeySequence(Qt::CTRL | Qt::Key_I), QKeySequence(Qt::Key_I)};
0396     coll->setDefaultShortcuts(importantAction, importantSC);
0397     importantAction->setCheckedState(KGuiItem(i18n("Remove &Important Mark")));
0398     connect(importantAction, &QAction::triggered, d->mainWidget, &MainWidget::slotArticleToggleKeepFlag);
0399 
0400     action = coll->addAction(QStringLiteral("feedstree_move_up"));
0401     action->setText(i18n("Move Node Up"));
0402     connect(action, &QAction::triggered, mainWidget, &MainWidget::slotMoveCurrentNodeUp);
0403     coll->setDefaultShortcut(action, QKeySequence(Qt::SHIFT | Qt::ALT | Qt::Key_Up));
0404 
0405     action = coll->addAction(QStringLiteral("feedstree_move_down"));
0406     action->setText(i18n("Move Node Down"));
0407     connect(action, &QAction::triggered, mainWidget, &MainWidget::slotMoveCurrentNodeDown);
0408     coll->setDefaultShortcut(action, QKeySequence(Qt::SHIFT | Qt::ALT | Qt::Key_Down));
0409 
0410     action = coll->addAction(QStringLiteral("move_node_left"));
0411     action->setText(i18n("Move Node Left"));
0412     connect(action, &QAction::triggered, mainWidget, &MainWidget::slotMoveCurrentNodeLeft);
0413     coll->setDefaultShortcut(action, QKeySequence(Qt::SHIFT | Qt::ALT | Qt::Key_Left));
0414 
0415     action = coll->addAction(QStringLiteral("feedstree_move_right"));
0416     action->setText(i18n("Move Node Right"));
0417     connect(action, &QAction::triggered, mainWidget, &MainWidget::slotMoveCurrentNodeRight);
0418     coll->setDefaultShortcut(action, QKeySequence(Qt::SHIFT | Qt::ALT | Qt::Key_Right));
0419 
0420     action = coll->addAction(QStringLiteral("file_sendlink"));
0421     action->setIcon(QIcon::fromTheme(QStringLiteral("mail-message-new")));
0422     action->setText(i18n("Send &Link Address..."));
0423     connect(action, &QAction::triggered, mainWidget, &MainWidget::slotSendLink);
0424 
0425     action = coll->addAction(QStringLiteral("file_sendfile"));
0426     action->setIcon(QIcon::fromTheme(QStringLiteral("mail-message-new")));
0427     action->setText(i18n("Send &File..."));
0428     connect(action, &QAction::triggered, mainWidget, &MainWidget::slotSendFile);
0429 
0430     coll->addAction(QStringLiteral("share_serviceurl"), d->shareServiceManager->menu());
0431     connect(d->shareServiceManager, &PimCommon::ShareServiceUrlManager::serviceUrlSelected, this, &ActionManagerImpl::slotServiceUrlSelected);
0432 
0433     d->mQuickSearchAction = new QAction(i18n("Set Focus to Quick Search"), this);
0434     // If change shortcut change Panel::setQuickSearchClickMessage(...) message
0435     coll->setDefaultShortcut(d->mQuickSearchAction, QKeySequence(Qt::ALT | Qt::Key_Q));
0436     coll->addAction(QStringLiteral("focus_to_quickseach"), d->mQuickSearchAction);
0437     connect(d->mQuickSearchAction, &QAction::triggered, mainWidget, &MainWidget::slotFocusQuickSearch);
0438 
0439     auto manager = new KColorSchemeManager(this);
0440     coll->addAction(QStringLiteral("colorscheme_menu"), KColorSchemeMenu::createMenu(manager, this));
0441 
0442     setArticleActionsEnabled(false);
0443 }
0444 
0445 void ActionManagerImpl::slotServiceUrlSelected(PimCommon::ShareServiceUrlManager::ServiceType type)
0446 {
0447     if (d->mainWidget) {
0448         QString title;
0449         QString link;
0450         d->mainWidget->currentArticleInfo(link, title);
0451         const QUrl url = d->shareServiceManager->generateServiceUrl(link, title, type);
0452         d->shareServiceManager->openUrl(url);
0453     }
0454 }
0455 
0456 void ActionManagerImpl::initArticleListView(ArticleListView *articleList)
0457 {
0458     if (d->articleList) {
0459         return;
0460     } else {
0461         d->articleList = articleList;
0462     }
0463 
0464     QAction *action = actionCollection()->addAction(QStringLiteral("go_previous_article"));
0465     action->setText(i18n("&Previous Article"));
0466     connect(action, &QAction::triggered, articleList, &ArticleListView::slotPreviousArticle);
0467     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::Key_Left));
0468     action = actionCollection()->addAction(QStringLiteral("go_next_article"));
0469     action->setText(i18n("&Next Article"));
0470     connect(action, &QAction::triggered, articleList, &ArticleListView::slotNextArticle);
0471     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::Key_Right));
0472 }
0473 
0474 void ActionManagerImpl::initSubscriptionListView(SubscriptionListView *subscriptionListView)
0475 {
0476     if (d->subscriptionListView) {
0477         return;
0478     } else {
0479         d->subscriptionListView = subscriptionListView;
0480     }
0481 
0482     KActionCollection *coll = actionCollection();
0483 
0484     QAction *action = coll->addAction(QStringLiteral("go_prev_feed"));
0485     action->setText(i18n("&Previous Feed"));
0486     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotPrevFeed);
0487     coll->setDefaultShortcut(action, QKeySequence(Qt::Key_P));
0488 
0489     action = coll->addAction(QStringLiteral("go_next_feed"));
0490     action->setText(i18n("&Next Feed"));
0491     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotNextFeed);
0492     coll->setDefaultShortcut(action, QKeySequence(Qt::Key_N));
0493 
0494     action = coll->addAction(QStringLiteral("go_next_unread_feed"));
0495     action->setIcon(QIcon::fromTheme(QStringLiteral("go-down")));
0496     action->setText(i18n("N&ext Unread Feed"));
0497     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotNextUnreadFeed);
0498     coll->setDefaultShortcut(action, QKeySequence(Qt::ALT | Qt::Key_Plus));
0499 
0500     action = coll->addAction(QStringLiteral("go_prev_unread_feed"));
0501     action->setIcon(QIcon::fromTheme(QStringLiteral("go-up")));
0502     action->setText(i18n("Prev&ious Unread Feed"));
0503     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotPrevUnreadFeed);
0504     coll->setDefaultShortcut(action, QKeySequence(Qt::ALT | Qt::Key_Minus));
0505 
0506     action = coll->addAction(QStringLiteral("feedstree_home"));
0507     action->setText(i18n("Go to Top of Tree"));
0508     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotItemBegin);
0509     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_Home));
0510 
0511     action = coll->addAction(QStringLiteral("feedstree_end"));
0512     action->setText(i18n("Go to Bottom of Tree"));
0513     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotItemEnd);
0514     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_End));
0515 
0516     action = coll->addAction(QStringLiteral("feedstree_left"));
0517     action->setText(i18n("Go Left in Tree"));
0518     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotItemLeft);
0519     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_Left));
0520 
0521     action = coll->addAction(QStringLiteral("feedstree_right"));
0522     action->setText(i18n("Go Right in Tree"));
0523     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotItemRight);
0524     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_Right));
0525 
0526     action = coll->addAction(QStringLiteral("feedstree_up"));
0527     action->setText(i18n("Go Up in Tree"));
0528     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotItemUp);
0529     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_Up));
0530 
0531     action = coll->addAction(QStringLiteral("feedstree_down"));
0532     action->setText(i18n("Go Down in Tree"));
0533     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotItemDown);
0534     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_Down));
0535 
0536     action = coll->addAction(QStringLiteral("feed_hide_read"));
0537     action->setCheckable(true);
0538     action->setText(i18n("Hide Read Feeds"));
0539     action->setChecked(Settings::hideReadFeeds());
0540     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotSetHideReadFeeds);
0541 
0542     action = coll->addAction(QStringLiteral("feed_lock_in_place"));
0543     action->setCheckable(true);
0544     action->setText(i18n("Lock Feeds In Place"));
0545     action->setChecked(Settings::lockFeedsInPlace());
0546     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotSetLockFeedsInPlace);
0547 
0548     action = coll->addAction(QStringLiteral("auto_expand_folders"));
0549     action->setCheckable(true);
0550     action->setText(i18n("Auto-expand folders with unread articles"));
0551     action->setChecked(Settings::autoExpandFolders());
0552     connect(action, &QAction::triggered, subscriptionListView, &SubscriptionListView::slotSetAutoExpandFolders);
0553 }
0554 
0555 void ActionManagerImpl::initTabWidget(TabWidget *tabWidget)
0556 {
0557     if (d->tabWidget) {
0558         return;
0559     } else {
0560         d->tabWidget = tabWidget;
0561     }
0562 
0563     KActionCollection *coll = actionCollection();
0564 
0565     QAction *action = coll->addAction(QStringLiteral("select_next_tab"));
0566     action->setText(i18n("Select Next Tab"));
0567     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotNextTab);
0568     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_Period));
0569 
0570     action = coll->addAction(QStringLiteral("select_previous_tab"));
0571     action->setText(i18n("Select Previous Tab"));
0572     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotPreviousTab);
0573     coll->setDefaultShortcut(action, QKeySequence(Qt::Key_Comma | Qt::CTRL));
0574 
0575     action = coll->addAction(QStringLiteral("tab_detach"));
0576     action->setIcon(QIcon::fromTheme(QStringLiteral("tab-detach")));
0577     action->setText(i18n("Detach Tab"));
0578     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotDetachTab);
0579     coll->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_B));
0580 
0581     action = KStandardAction::copy(d->tabWidget, &TabWidget::slotCopy, coll);
0582     coll->addAction(QStringLiteral("viewer_copy"), action);
0583 
0584     action = KStandardAction::print(d->tabWidget, &TabWidget::slotPrint, coll);
0585     coll->addAction(QStringLiteral("viewer_print"), action);
0586 
0587     action = KStandardAction::printPreview(d->tabWidget, &TabWidget::slotPrintPreview, coll);
0588     coll->addAction(QStringLiteral("viewer_printpreview"), action);
0589 
0590     action = coll->addAction(QStringLiteral("tab_mute"));
0591     action->setText(i18n("Mute"));
0592     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotMute);
0593 
0594     action = coll->addAction(QStringLiteral("tab_unmute"));
0595     action->setText(i18n("Unmute"));
0596     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotUnMute);
0597 
0598     action = new QAction(i18n("Speak Text"), this);
0599     action->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-text-to-speech")));
0600     coll->addAction(QStringLiteral("speak_text"), action);
0601     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotTextToSpeech);
0602 
0603     action = new QAction(QIcon::fromTheme(QStringLiteral("edit-find")), i18n("&Find in Message..."), this);
0604     coll->addAction(QStringLiteral("find_in_messages"), action);
0605     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotFindTextInHtml);
0606     coll->setDefaultShortcut(action, KStandardShortcut::find().first());
0607 
0608     action = coll->addAction(QStringLiteral("tab_copylinkaddress"));
0609     action->setText(i18n("Copy Link Address"));
0610     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotCopyLinkAddress);
0611 
0612     action = coll->addAction(QStringLiteral("tab_remove"));
0613     action->setIcon(QIcon::fromTheme(QStringLiteral("tab-close")));
0614     action->setText(i18n("Close Tab"));
0615     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotCloseTab);
0616     coll->setDefaultShortcuts(action, KStandardShortcut::close());
0617 
0618     d->zoomActionMenu = new WebEngineViewer::ZoomActionMenu(this);
0619     connect(d->zoomActionMenu, &WebEngineViewer::ZoomActionMenu::zoomChanged, d->tabWidget, &TabWidget::slotZoomChanged);
0620 
0621     d->zoomActionMenu->setActionCollection(coll);
0622     d->zoomActionMenu->createZoomActions();
0623 
0624     QString actionname;
0625     for (int i = 1; i < 10; ++i) {
0626         actionname = QString::asprintf("activate_tab_%02d", i);
0627         action = new QAction(i18n("Activate Tab %1", i), this);
0628         coll->addAction(actionname, action);
0629         coll->setDefaultShortcut(action, QKeySequence(QStringLiteral("Alt+%1").arg(i)));
0630         connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotActivateTab);
0631     }
0632     action = coll->addAction(QStringLiteral("savelinkas"));
0633     action->setText(i18n("&Save Link As..."));
0634     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotSaveLinkAs);
0635 
0636     action = coll->addAction(QStringLiteral("copylinkaddress"));
0637     action->setText(i18n("Copy &Link Address"));
0638     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotCopyLinkAddress);
0639 
0640     action = new QAction(i18n("Copy Image Location"), this);
0641     action->setIcon(QIcon::fromTheme(QStringLiteral("view-media-visualization")));
0642     coll->addAction(QStringLiteral("copy_image_location"), action);
0643     coll->setShortcutsConfigurable(action, false);
0644     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotCopyImageLocation);
0645 
0646     // save Image On Disk
0647     action = new QAction(i18n("Save Image On Disk..."), this);
0648     coll->addAction(QStringLiteral("saveas_imageurl"), action);
0649     coll->setShortcutsConfigurable(action, false);
0650     connect(action, &QAction::triggered, d->tabWidget, &TabWidget::slotSaveImageOnDisk);
0651 }
0652 
0653 QWidget *ActionManagerImpl::container(const QString &name)
0654 {
0655     if (d->part->factory()) {
0656         return d->part->factory()->container(name, d->part);
0657     } else {
0658         return nullptr;
0659     }
0660 }
0661 
0662 KActionCollection *ActionManagerImpl::actionCollection() const
0663 {
0664     return d->actionCollection;
0665 }
0666 
0667 QAction *ActionManagerImpl::action(const QString &name)
0668 {
0669     return d->actionCollection ? d->actionCollection->action(name) : nullptr;
0670 }
0671 
0672 void ActionManagerImpl::setArticleActionsEnabled(bool enabled){
0673 #undef setActionEnabled
0674 #define setActionEnabled(name)                                                                                                                                 \
0675     {                                                                                                                                                          \
0676         QAction *const a = action(name);                                                                                                                       \
0677         if (a) {                                                                                                                                               \
0678             a->setEnabled(enabled);                                                                                                                            \
0679         }                                                                                                                                                      \
0680     }
0681     setActionEnabled(QStringLiteral("article_open")) setActionEnabled(QStringLiteral("article_open_external"))
0682         setActionEnabled(QStringLiteral("article_set_status_important")) setActionEnabled(QStringLiteral("article_set_status"))
0683             setActionEnabled(QStringLiteral("article_delete")) setActionEnabled(QStringLiteral("file_sendlink"))
0684                 setActionEnabled(QStringLiteral("file_sendfile")) setActionEnabled(QStringLiteral("article_open_in_background"))
0685                     setActionEnabled(QStringLiteral("share_serviceurl"))
0686 #undef setActionEnabled
0687 }
0688 
0689 WebEngineViewer::ZoomActionMenu *ActionManagerImpl::zoomActionMenu() const
0690 {
0691     return d->zoomActionMenu;
0692 }
0693 
0694 QString ActionManagerImpl::quickSearchLineText() const
0695 {
0696     return d->quickSearchLineText();
0697 }
0698 
0699 QString ActionManagerImpl::ActionManagerImplPrivate::quickSearchLineText() const
0700 {
0701     return mQuickSearchAction->shortcut().toString();
0702 }
0703 
0704 #include "moc_actionmanagerimpl.cpp"