| 1 | // Copyright (C) 2016 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
| 3 | |
| 4 | #include "globalactions.h" |
| 5 | |
| 6 | #include "centralwidget.h" |
| 7 | #include "helpviewer.h" |
| 8 | #include "tracer.h" |
| 9 | |
| 10 | #include <QtWidgets/QMenu> |
| 11 | |
| 12 | #include <QtGui/QAction> |
| 13 | |
| 14 | #if defined(BROWSER_QTWEBKIT) |
| 15 | # include <QWebHistory> |
| 16 | #endif |
| 17 | |
| 18 | using namespace Qt::StringLiterals; |
| 19 | |
| 20 | GlobalActions *GlobalActions::instance(QObject *parent) |
| 21 | { |
| 22 | Q_ASSERT(!m_instance != !parent); |
| 23 | if (!m_instance) |
| 24 | m_instance = new GlobalActions(parent); |
| 25 | return m_instance; |
| 26 | } |
| 27 | |
| 28 | GlobalActions::GlobalActions(QObject *parent) : QObject(parent) |
| 29 | { |
| 30 | TRACE_OBJ |
| 31 | |
| 32 | // TODO: Put resource path in misc class |
| 33 | QString resourcePath = ":/qt-project.org/assistant/images/"_L1 ; |
| 34 | #ifdef Q_OS_MAC |
| 35 | resourcePath.append("mac"_L1 ); |
| 36 | #else |
| 37 | resourcePath.append(s: "win"_L1 ); |
| 38 | #endif |
| 39 | CentralWidget *centralWidget = CentralWidget::instance(); |
| 40 | |
| 41 | m_backAction = new QAction(tr(s: "&Back" ), parent); |
| 42 | m_backAction->setEnabled(false); |
| 43 | m_backAction->setShortcuts(QKeySequence::Back); |
| 44 | m_backAction->setIcon(QIcon(resourcePath + "/previous.png"_L1 )); |
| 45 | connect(sender: m_backAction, signal: &QAction::triggered, context: centralWidget, slot: &CentralWidget::backward); |
| 46 | m_actionList << m_backAction; |
| 47 | |
| 48 | m_nextAction = new QAction(tr(s: "&Forward" ), parent); |
| 49 | m_nextAction->setPriority(QAction::LowPriority); |
| 50 | m_nextAction->setEnabled(false); |
| 51 | m_nextAction->setShortcuts(QKeySequence::Forward); |
| 52 | m_nextAction->setIcon(QIcon(resourcePath + "/next.png"_L1 )); |
| 53 | connect(sender: m_nextAction, signal: &QAction::triggered, context: centralWidget, slot: &CentralWidget::forward); |
| 54 | m_actionList << m_nextAction; |
| 55 | |
| 56 | setupNavigationMenus(back: m_backAction, next: m_nextAction, parent: centralWidget); |
| 57 | |
| 58 | m_homeAction = new QAction(tr(s: "&Home" ), parent); |
| 59 | m_homeAction->setShortcut(tr(s: "ALT+Home" )); |
| 60 | m_homeAction->setIcon(QIcon(resourcePath + "/home.png"_L1 )); |
| 61 | connect(sender: m_homeAction, signal: &QAction::triggered, context: centralWidget, slot: &CentralWidget::home); |
| 62 | m_actionList << m_homeAction; |
| 63 | |
| 64 | QAction *separator = new QAction(parent); |
| 65 | separator->setSeparator(true); |
| 66 | m_actionList << separator; |
| 67 | |
| 68 | m_zoomInAction = new QAction(tr(s: "Zoom &in" ), parent); |
| 69 | m_zoomInAction->setPriority(QAction::LowPriority); |
| 70 | m_zoomInAction->setIcon(QIcon(resourcePath + "/zoomin.png"_L1 )); |
| 71 | m_zoomInAction->setShortcut(QKeySequence::ZoomIn); |
| 72 | connect(sender: m_zoomInAction, signal: &QAction::triggered, context: centralWidget, slot: &CentralWidget::zoomIn); |
| 73 | m_actionList << m_zoomInAction; |
| 74 | |
| 75 | m_zoomOutAction = new QAction(tr(s: "Zoom &out" ), parent); |
| 76 | m_zoomOutAction->setPriority(QAction::LowPriority); |
| 77 | m_zoomOutAction->setIcon(QIcon(resourcePath + "/zoomout.png"_L1 )); |
| 78 | m_zoomOutAction->setShortcut(QKeySequence::ZoomOut); |
| 79 | connect(sender: m_zoomOutAction, signal: &QAction::triggered, context: centralWidget, slot: &CentralWidget::zoomOut); |
| 80 | m_actionList << m_zoomOutAction; |
| 81 | |
| 82 | separator = new QAction(parent); |
| 83 | separator->setSeparator(true); |
| 84 | m_actionList << separator; |
| 85 | |
| 86 | #if QT_CONFIG(clipboard) |
| 87 | m_copyAction = new QAction(tr(s: "&Copy selected Text" ), parent); |
| 88 | m_copyAction->setPriority(QAction::LowPriority); |
| 89 | m_copyAction->setIconText("&Copy" ); |
| 90 | m_copyAction->setIcon(QIcon(resourcePath + "/editcopy.png"_L1 )); |
| 91 | m_copyAction->setShortcuts(QKeySequence::Copy); |
| 92 | m_copyAction->setEnabled(false); |
| 93 | connect(sender: m_copyAction, signal: &QAction::triggered, context: centralWidget, slot: &CentralWidget::copy); |
| 94 | m_actionList << m_copyAction; |
| 95 | #endif |
| 96 | |
| 97 | m_printAction = new QAction(tr(s: "&Print..." ), parent); |
| 98 | m_printAction->setPriority(QAction::LowPriority); |
| 99 | m_printAction->setIcon(QIcon(resourcePath + "/print.png"_L1 )); |
| 100 | m_printAction->setShortcut(QKeySequence::Print); |
| 101 | connect(sender: m_printAction, signal: &QAction::triggered, context: centralWidget, slot: &CentralWidget::print); |
| 102 | m_actionList << m_printAction; |
| 103 | |
| 104 | m_findAction = new QAction(tr(s: "&Find in Text..." ), parent); |
| 105 | m_findAction->setIconText(tr(s: "&Find" )); |
| 106 | m_findAction->setIcon(QIcon(resourcePath + "/find.png"_L1 )); |
| 107 | m_findAction->setShortcuts(QKeySequence::Find); |
| 108 | connect(sender: m_findAction, signal: &QAction::triggered, context: centralWidget, slot: &CentralWidget::showTextSearch); |
| 109 | m_actionList << m_findAction; |
| 110 | |
| 111 | #if defined (Q_OS_UNIX) && !defined(Q_OS_MAC) |
| 112 | m_backAction->setIcon(QIcon::fromTheme(icon: QIcon::ThemeIcon::GoPrevious, |
| 113 | fallback: m_backAction->icon())); |
| 114 | m_nextAction->setIcon(QIcon::fromTheme(icon: QIcon::ThemeIcon::GoNext, |
| 115 | fallback: m_nextAction->icon())); |
| 116 | m_zoomInAction->setIcon(QIcon::fromTheme(icon: QIcon::ThemeIcon::ZoomIn, |
| 117 | fallback: m_zoomInAction->icon())); |
| 118 | m_zoomOutAction->setIcon(QIcon::fromTheme(icon: QIcon::ThemeIcon::ZoomOut, |
| 119 | fallback: m_zoomOutAction->icon())); |
| 120 | #if QT_CONFIG(clipboard) |
| 121 | m_copyAction->setIcon(QIcon::fromTheme(icon: QIcon::ThemeIcon::EditCopy, |
| 122 | fallback: m_copyAction->icon())); |
| 123 | #endif |
| 124 | m_findAction->setIcon(QIcon::fromTheme(icon: QIcon::ThemeIcon::EditFind, |
| 125 | fallback: m_findAction->icon())); |
| 126 | m_homeAction->setIcon(QIcon::fromTheme(icon: QIcon::ThemeIcon::GoHome, |
| 127 | fallback: m_homeAction->icon())); |
| 128 | m_printAction->setIcon(QIcon::fromTheme(icon: QIcon::ThemeIcon::DocumentPrint, |
| 129 | fallback: m_printAction->icon())); |
| 130 | #endif |
| 131 | } |
| 132 | |
| 133 | void GlobalActions::updateActions() |
| 134 | { |
| 135 | TRACE_OBJ |
| 136 | CentralWidget *centralWidget = CentralWidget::instance(); |
| 137 | #if QT_CONFIG(clipboard) |
| 138 | m_copyAction->setEnabled(centralWidget->hasSelection()); |
| 139 | #endif |
| 140 | m_nextAction->setEnabled(centralWidget->isForwardAvailable()); |
| 141 | m_backAction->setEnabled(centralWidget->isBackwardAvailable()); |
| 142 | } |
| 143 | |
| 144 | #if QT_CONFIG(clipboard) |
| 145 | void GlobalActions::setCopyAvailable(bool available) |
| 146 | { |
| 147 | TRACE_OBJ |
| 148 | m_copyAction->setEnabled(available); |
| 149 | } |
| 150 | #endif |
| 151 | |
| 152 | #if defined(BROWSER_QTWEBKIT) |
| 153 | |
| 154 | void GlobalActions::slotAboutToShowBackMenu() |
| 155 | { |
| 156 | TRACE_OBJ |
| 157 | m_backMenu->clear(); |
| 158 | if (QWebHistory *history = CentralWidget::instance()->currentHelpViewer()->history()) { |
| 159 | const int currentItemIndex = history->currentItemIndex(); |
| 160 | QList<QWebHistoryItem> items = history->backItems(history->count()); |
| 161 | for (int i = items.count() - 1; i >= 0; --i) { |
| 162 | QAction *action = new QAction(this); |
| 163 | action->setText(items.at(i).title()); |
| 164 | action->setData(-1 * (currentItemIndex - i)); |
| 165 | m_backMenu->addAction(action); |
| 166 | } |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | void GlobalActions::slotAboutToShowNextMenu() |
| 171 | { |
| 172 | TRACE_OBJ |
| 173 | m_nextMenu->clear(); |
| 174 | if (QWebHistory *history = CentralWidget::instance()->currentHelpViewer()->history()) { |
| 175 | const int count = history->count(); |
| 176 | QList<QWebHistoryItem> items = history->forwardItems(count); |
| 177 | for (int i = 0; i < items.count(); ++i) { |
| 178 | QAction *action = new QAction(this); |
| 179 | action->setData(count - i); |
| 180 | action->setText(items.at(i).title()); |
| 181 | m_nextMenu->addAction(action); |
| 182 | } |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | void GlobalActions::slotOpenActionUrl(QAction *action) |
| 187 | { |
| 188 | TRACE_OBJ |
| 189 | if (HelpViewer* viewer = CentralWidget::instance()->currentHelpViewer()) { |
| 190 | const int offset = action->data().toInt(); |
| 191 | QWebHistory *history = viewer->history(); |
| 192 | if (offset > 0) { |
| 193 | history->goToItem(history->forwardItems(history->count() |
| 194 | - offset + 1).back()); // forward |
| 195 | } else if (offset < 0) { |
| 196 | history->goToItem(history->backItems(-1 * offset).first()); // back |
| 197 | } |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | #endif // BROWSER_QTWEBKIT |
| 202 | |
| 203 | void GlobalActions::(QAction *back, QAction *next, |
| 204 | QWidget *parent) |
| 205 | { |
| 206 | #if defined(BROWSER_QTWEBKIT) |
| 207 | m_backMenu = new QMenu(parent); |
| 208 | connect(m_backMenu, &QMenu::aboutToShow, |
| 209 | this, &GlobalActions::slotAboutToShowBackMenu); |
| 210 | connect(m_backMenu, &QMenu::triggered, |
| 211 | this, &GlobalActions::slotOpenActionUrl); |
| 212 | back->setMenu(m_backMenu); |
| 213 | |
| 214 | m_nextMenu = new QMenu(parent); |
| 215 | connect(m_nextMenu, &QMenu::aboutToShow, |
| 216 | this, &GlobalActions::slotAboutToShowNextMenu); |
| 217 | connect(m_nextMenu, &QMenu::triggered, |
| 218 | this, &GlobalActions::slotOpenActionUrl); |
| 219 | next->setMenu(m_nextMenu); |
| 220 | #else |
| 221 | Q_UNUSED(back); |
| 222 | Q_UNUSED(next); |
| 223 | Q_UNUSED(parent); |
| 224 | #endif |
| 225 | } |
| 226 | |
| 227 | GlobalActions *GlobalActions::m_instance = nullptr; |
| 228 | |