File indexing completed on 2023-09-24 07:58:42
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org> 0004 SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include "kbookmarkmenu.h" 0010 #include "kbookmarkmenu_p.h" 0011 0012 #include "kbookmarkaction.h" 0013 #include "kbookmarkactionmenu.h" 0014 #include "kbookmarkcontextmenu.h" 0015 #include "kbookmarkdialog.h" 0016 #include "kbookmarkowner.h" 0017 #include "kbookmarks_debug.h" 0018 0019 #if KBOOKMARKS_BUILD_DEPRECATED_SINCE(5, 69) 0020 #include <KActionCollection> 0021 #endif 0022 #include <KAuthorized> 0023 #include <KStandardAction> 0024 0025 #include <QApplication> 0026 #include <QMenu> 0027 #include <QStandardPaths> 0028 0029 /********************************************************************/ 0030 /********************************************************************/ 0031 /********************************************************************/ 0032 class KBookmarkMenuPrivate 0033 { 0034 public: 0035 QAction *newBookmarkFolderAction = nullptr; 0036 QAction *addBookmarkAction = nullptr; 0037 QAction *bookmarksToFolderAction = nullptr; 0038 QAction *editBookmarksAction = nullptr; 0039 int numberOfOpenTabs = 2; 0040 }; 0041 0042 #if KBOOKMARKS_BUILD_DEPRECATED_SINCE(5, 69) 0043 KBookmarkMenu::KBookmarkMenu(KBookmarkManager *mgr, KBookmarkOwner *_owner, QMenu *_parentMenu, KActionCollection *actionCollection) 0044 : QObject() 0045 , m_actionCollection(actionCollection) 0046 , d(new KBookmarkMenuPrivate()) 0047 , m_bIsRoot(true) 0048 , m_pManager(mgr) 0049 , m_pOwner(_owner) 0050 , m_parentMenu(_parentMenu) 0051 , m_parentAddress(QString()) // TODO KBookmarkAdress::root 0052 { 0053 init(); 0054 } 0055 0056 #endif 0057 0058 KBookmarkMenu::KBookmarkMenu(KBookmarkManager *manager, KBookmarkOwner *_owner, QMenu *_parentMenu) 0059 : QObject() 0060 #if KBOOKMARKS_BUILD_DEPRECATED_SINCE(5, 69) 0061 , m_actionCollection(new KActionCollection(this)) 0062 #endif 0063 , d(new KBookmarkMenuPrivate()) 0064 , m_bIsRoot(true) 0065 , m_pManager(manager) 0066 , m_pOwner(_owner) 0067 , m_parentMenu(_parentMenu) 0068 , m_parentAddress(QString()) // TODO KBookmarkAdress::root 0069 { 0070 // TODO KDE5 find a QMenu equvalnet for this one 0071 // m_parentMenu->setKeyboardShortcutsEnabled( true ); 0072 0073 init(); 0074 } 0075 0076 void KBookmarkMenu::init() 0077 { 0078 connect(m_parentMenu, &QMenu::aboutToShow, this, &KBookmarkMenu::slotAboutToShow); 0079 0080 if (KBookmarkSettings::self()->m_contextmenu) { 0081 m_parentMenu->setContextMenuPolicy(Qt::CustomContextMenu); 0082 connect(m_parentMenu, &QWidget::customContextMenuRequested, this, &KBookmarkMenu::slotCustomContextMenu); 0083 } 0084 0085 connect(m_pManager, &KBookmarkManager::changed, this, &KBookmarkMenu::slotBookmarksChanged); 0086 0087 m_bDirty = true; 0088 addActions(); 0089 } 0090 0091 void KBookmarkMenu::addActions() 0092 { 0093 if (m_bIsRoot) { 0094 addAddBookmark(); 0095 addAddBookmarksList(); 0096 addNewFolder(); 0097 addEditBookmarks(); 0098 } else { 0099 if (!m_parentMenu->actions().isEmpty()) { 0100 m_parentMenu->addSeparator(); 0101 } 0102 0103 addOpenInTabs(); 0104 addAddBookmark(); 0105 addAddBookmarksList(); 0106 addNewFolder(); 0107 } 0108 } 0109 0110 KBookmarkMenu::KBookmarkMenu(KBookmarkManager *mgr, KBookmarkOwner *_owner, QMenu *_parentMenu, const QString &parentAddress) 0111 : QObject() 0112 #if KBOOKMARKS_BUILD_DEPRECATED_SINCE(5, 69) 0113 , m_actionCollection(new KActionCollection(this)) 0114 #endif 0115 , d(new KBookmarkMenuPrivate()) 0116 , m_bIsRoot(false) 0117 , m_pManager(mgr) 0118 , m_pOwner(_owner) 0119 , m_parentMenu(_parentMenu) 0120 , m_parentAddress(parentAddress) 0121 { 0122 connect(_parentMenu, &QMenu::aboutToShow, this, &KBookmarkMenu::slotAboutToShow); 0123 if (KBookmarkSettings::self()->m_contextmenu) { 0124 m_parentMenu->setContextMenuPolicy(Qt::CustomContextMenu); 0125 connect(m_parentMenu, &QWidget::customContextMenuRequested, this, &KBookmarkMenu::slotCustomContextMenu); 0126 } 0127 m_bDirty = true; 0128 } 0129 0130 KBookmarkMenu::~KBookmarkMenu() 0131 { 0132 qDeleteAll(m_lstSubMenus); 0133 qDeleteAll(m_actions); 0134 } 0135 0136 void KBookmarkMenu::ensureUpToDate() 0137 { 0138 slotAboutToShow(); 0139 } 0140 0141 void KBookmarkMenu::setNumberOfOpenTabs(int numberOfOpenTabs) 0142 { 0143 if (numberOfOpenTabs == d->numberOfOpenTabs) { 0144 return; 0145 } 0146 m_bDirty = (d->numberOfOpenTabs < 2) != (numberOfOpenTabs < 2); 0147 d->numberOfOpenTabs = numberOfOpenTabs; 0148 } 0149 0150 int KBookmarkMenu::numberOfOpenTabs() const 0151 { 0152 return d->numberOfOpenTabs; 0153 } 0154 0155 void KBookmarkMenu::slotAboutToShow() 0156 { 0157 // Did the bookmarks change since the last time we showed them ? 0158 if (m_bDirty) { 0159 m_bDirty = false; 0160 clear(); 0161 refill(); 0162 m_parentMenu->adjustSize(); 0163 } 0164 } 0165 0166 void KBookmarkMenu::slotCustomContextMenu(const QPoint &pos) 0167 { 0168 QAction *action = m_parentMenu->actionAt(pos); 0169 QMenu *menu = contextMenu(action); 0170 if (!menu) { 0171 return; 0172 } 0173 menu->setAttribute(Qt::WA_DeleteOnClose); 0174 menu->popup(m_parentMenu->mapToGlobal(pos)); 0175 } 0176 0177 QMenu *KBookmarkMenu::contextMenu(QAction *action) 0178 { 0179 KBookmarkActionInterface *act = dynamic_cast<KBookmarkActionInterface *>(action); 0180 if (!act) { 0181 return nullptr; 0182 } 0183 return new KBookmarkContextMenu(act->bookmark(), m_pManager, m_pOwner); 0184 } 0185 0186 bool KBookmarkMenu::isRoot() const 0187 { 0188 return m_bIsRoot; 0189 } 0190 0191 bool KBookmarkMenu::isDirty() const 0192 { 0193 return m_bDirty; 0194 } 0195 0196 QString KBookmarkMenu::parentAddress() const 0197 { 0198 return m_parentAddress; 0199 } 0200 0201 KBookmarkManager *KBookmarkMenu::manager() const 0202 { 0203 return m_pManager; 0204 } 0205 0206 KBookmarkOwner *KBookmarkMenu::owner() const 0207 { 0208 return m_pOwner; 0209 } 0210 0211 QMenu *KBookmarkMenu::parentMenu() const 0212 { 0213 return m_parentMenu; 0214 } 0215 0216 /********************************************************************/ 0217 /********************************************************************/ 0218 /********************************************************************/ 0219 0220 /********************************************************************/ 0221 /********************************************************************/ 0222 /********************************************************************/ 0223 0224 void KBookmarkMenu::slotBookmarksChanged(const QString &groupAddress) 0225 { 0226 qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::slotBookmarksChanged groupAddress: " << groupAddress; 0227 if (groupAddress == m_parentAddress) { 0228 // qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::slotBookmarksChanged -> setting m_bDirty on " << groupAddress; 0229 m_bDirty = true; 0230 } else { 0231 // Iterate recursively into child menus 0232 for (QList<KBookmarkMenu *>::iterator it = m_lstSubMenus.begin(), end = m_lstSubMenus.end(); it != end; ++it) { 0233 (*it)->slotBookmarksChanged(groupAddress); 0234 } 0235 } 0236 } 0237 0238 void KBookmarkMenu::clear() 0239 { 0240 qDeleteAll(m_lstSubMenus); 0241 m_lstSubMenus.clear(); 0242 0243 for (QList<QAction *>::iterator it = m_actions.begin(), end = m_actions.end(); it != end; ++it) { 0244 m_parentMenu->removeAction(*it); 0245 delete *it; 0246 } 0247 0248 m_parentMenu->clear(); 0249 m_actions.clear(); 0250 } 0251 0252 void KBookmarkMenu::refill() 0253 { 0254 // qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::refill()"; 0255 if (m_bIsRoot) { 0256 addActions(); 0257 } 0258 fillBookmarks(); 0259 if (!m_bIsRoot) { 0260 addActions(); 0261 } 0262 } 0263 0264 void KBookmarkMenu::addOpenInTabs() 0265 { 0266 if (!m_pOwner || !m_pOwner->supportsTabs() || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) { 0267 return; 0268 } 0269 0270 const QString title = tr("Open Folder in Tabs", "@action:inmenu"); 0271 0272 QAction *paOpenFolderInTabs = new QAction(title, this); 0273 paOpenFolderInTabs->setIcon(QIcon::fromTheme(QStringLiteral("tab-new"))); 0274 paOpenFolderInTabs->setToolTip(tr("Open all bookmarks in this folder as a new tab", "@info:tooltip")); 0275 paOpenFolderInTabs->setStatusTip(paOpenFolderInTabs->toolTip()); 0276 connect(paOpenFolderInTabs, &QAction::triggered, this, &KBookmarkMenu::slotOpenFolderInTabs); 0277 0278 m_parentMenu->addAction(paOpenFolderInTabs); 0279 m_actions.append(paOpenFolderInTabs); 0280 } 0281 0282 void KBookmarkMenu::addAddBookmarksList() 0283 { 0284 if (!m_pOwner || !m_pOwner->enableOption(KBookmarkOwner::ShowAddBookmark) || !m_pOwner->supportsTabs() || (d->numberOfOpenTabs < 2) 0285 || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) { 0286 return; 0287 } 0288 0289 if (!d->bookmarksToFolderAction) { 0290 const QString title = tr("Bookmark Tabs as Folder...", "@action:inmenu"); 0291 d->bookmarksToFolderAction = new QAction(title, this); 0292 0293 if (m_bIsRoot) { 0294 d->bookmarksToFolderAction->setObjectName(QStringLiteral("add_bookmarks_list")); 0295 } 0296 0297 d->bookmarksToFolderAction->setIcon(QIcon::fromTheme(QStringLiteral("bookmark-new-list"))); 0298 d->bookmarksToFolderAction->setToolTip(tr("Add a folder of bookmarks for all open tabs", "@info:tooltip")); 0299 d->bookmarksToFolderAction->setStatusTip(d->bookmarksToFolderAction->toolTip()); 0300 connect(d->bookmarksToFolderAction, &QAction::triggered, this, &KBookmarkMenu::slotAddBookmarksList); 0301 0302 #if KBOOKMARKS_BUILD_DEPRECATED_SINCE(5, 69) 0303 if (m_actionCollection) { 0304 m_actionCollection->addAction(d->bookmarksToFolderAction->objectName(), d->bookmarksToFolderAction); 0305 } 0306 #endif 0307 } 0308 0309 m_parentMenu->addAction(d->bookmarksToFolderAction); 0310 } 0311 0312 void KBookmarkMenu::addAddBookmark() 0313 { 0314 if (!m_pOwner || !m_pOwner->enableOption(KBookmarkOwner::ShowAddBookmark) || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) { 0315 return; 0316 } 0317 0318 if (!d->addBookmarkAction) { 0319 d->addBookmarkAction = KStandardAction::addBookmark(this, SLOT(slotAddBookmark()), this); 0320 if (m_bIsRoot) { 0321 d->addBookmarkAction->setObjectName(QStringLiteral("add_bookmark")); 0322 } 0323 0324 #if KBOOKMARKS_BUILD_DEPRECATED_SINCE(5, 69) 0325 if (m_actionCollection) { 0326 m_actionCollection->addAction(d->addBookmarkAction->objectName(), d->addBookmarkAction); 0327 } 0328 #endif 0329 0330 if (!m_bIsRoot) { 0331 d->addBookmarkAction->setShortcut(QKeySequence()); 0332 } 0333 } 0334 0335 m_parentMenu->addAction(d->addBookmarkAction); 0336 } 0337 0338 void KBookmarkMenu::addEditBookmarks() 0339 { 0340 if ((m_pOwner && !m_pOwner->enableOption(KBookmarkOwner::ShowEditBookmark)) 0341 || QStandardPaths::findExecutable(QStringLiteral(KEDITBOOKMARKS_BINARY)).isEmpty() || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) { 0342 return; 0343 } 0344 0345 d->editBookmarksAction = KStandardAction::editBookmarks(m_pManager, SLOT(slotEditBookmarks()), this); 0346 d->editBookmarksAction->setObjectName(QStringLiteral("edit_bookmarks")); 0347 0348 m_parentMenu->addAction(d->editBookmarksAction); 0349 d->editBookmarksAction->setToolTip(tr("Edit your bookmark collection in a separate window", "@info:tooltip")); 0350 d->editBookmarksAction->setStatusTip(d->editBookmarksAction->toolTip()); 0351 0352 #if KBOOKMARKS_BUILD_DEPRECATED_SINCE(5, 69) 0353 if (m_actionCollection) { 0354 m_actionCollection->addAction(d->editBookmarksAction->objectName(), d->editBookmarksAction); 0355 } 0356 #endif 0357 } 0358 0359 void KBookmarkMenu::addNewFolder() 0360 { 0361 if (!m_pOwner || !m_pOwner->enableOption(KBookmarkOwner::ShowAddBookmark) || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) { 0362 return; 0363 } 0364 0365 if (!d->newBookmarkFolderAction) { 0366 d->newBookmarkFolderAction = new QAction(tr("New Bookmark Folder...", "@action:inmenu"), this); 0367 d->newBookmarkFolderAction->setIcon(QIcon::fromTheme(QStringLiteral("folder-new"))); 0368 d->newBookmarkFolderAction->setToolTip(tr("Create a new bookmark folder in this menu", "@info:tooltip")); 0369 d->newBookmarkFolderAction->setStatusTip(d->newBookmarkFolderAction->toolTip()); 0370 0371 if (m_bIsRoot) { 0372 d->newBookmarkFolderAction->setObjectName(QStringLiteral("new_bookmark_folder")); 0373 } 0374 0375 connect(d->newBookmarkFolderAction, &QAction::triggered, this, &KBookmarkMenu::slotNewFolder); 0376 } 0377 0378 m_parentMenu->addAction(d->newBookmarkFolderAction); 0379 } 0380 0381 void KBookmarkMenu::fillBookmarks() 0382 { 0383 KBookmarkGroup parentBookmark = m_pManager->findByAddress(m_parentAddress).toGroup(); 0384 Q_ASSERT(!parentBookmark.isNull()); 0385 0386 if (m_bIsRoot && !parentBookmark.first().isNull()) { // at least one bookmark 0387 m_parentMenu->addSeparator(); 0388 } 0389 0390 for (KBookmark bm = parentBookmark.first(); !bm.isNull(); bm = parentBookmark.next(bm)) { 0391 m_parentMenu->addAction(actionForBookmark(bm)); 0392 } 0393 } 0394 0395 QAction *KBookmarkMenu::actionForBookmark(const KBookmark &bm) 0396 { 0397 if (bm.isGroup()) { 0398 // qCDebug(KBOOKMARKS_LOG) << "Creating bookmark submenu named " << bm.text(); 0399 KActionMenu *actionMenu = new KBookmarkActionMenu(bm, this); 0400 m_actions.append(actionMenu); 0401 KBookmarkMenu *subMenu = new KBookmarkMenu(m_pManager, m_pOwner, actionMenu->menu(), bm.address()); 0402 m_lstSubMenus.append(subMenu); 0403 return actionMenu; 0404 } else if (bm.isSeparator()) { 0405 QAction *sa = new QAction(this); 0406 sa->setSeparator(true); 0407 m_actions.append(sa); 0408 return sa; 0409 } else { 0410 // qCDebug(KBOOKMARKS_LOG) << "Creating bookmark menu item for " << bm.text(); 0411 QAction *action = new KBookmarkAction(bm, m_pOwner, this); 0412 m_actions.append(action); 0413 return action; 0414 } 0415 } 0416 0417 void KBookmarkMenu::slotAddBookmarksList() 0418 { 0419 if (!m_pOwner || !m_pOwner->supportsTabs()) { 0420 return; 0421 } 0422 0423 KBookmarkGroup parentBookmark = m_pManager->findByAddress(m_parentAddress).toGroup(); 0424 0425 KBookmarkDialog *dlg = m_pOwner->bookmarkDialog(m_pManager, QApplication::activeWindow()); 0426 dlg->addBookmarks(m_pOwner->currentBookmarkList(), QLatin1String(""), parentBookmark); 0427 delete dlg; 0428 } 0429 0430 void KBookmarkMenu::slotAddBookmark() 0431 { 0432 if (!m_pOwner) { 0433 return; 0434 } 0435 if (m_pOwner->currentTitle().isEmpty() && m_pOwner->currentUrl().isEmpty()) { 0436 return; 0437 } 0438 KBookmarkGroup parentBookmark = m_pManager->findByAddress(m_parentAddress).toGroup(); 0439 0440 if (KBookmarkSettings::self()->m_advancedaddbookmark) { 0441 KBookmarkDialog *dlg = m_pOwner->bookmarkDialog(m_pManager, QApplication::activeWindow()); 0442 dlg->addBookmark(m_pOwner->currentTitle(), m_pOwner->currentUrl(), m_pOwner->currentIcon(), parentBookmark); 0443 delete dlg; 0444 } else { 0445 parentBookmark.addBookmark(m_pOwner->currentTitle(), m_pOwner->currentUrl(), m_pOwner->currentIcon()); 0446 m_pManager->emitChanged(parentBookmark); 0447 } 0448 } 0449 0450 void KBookmarkMenu::slotOpenFolderInTabs() 0451 { 0452 m_pOwner->openFolderinTabs(m_pManager->findByAddress(m_parentAddress).toGroup()); 0453 } 0454 0455 void KBookmarkMenu::slotNewFolder() 0456 { 0457 if (!m_pOwner) { 0458 return; // this view doesn't handle bookmarks... 0459 } 0460 KBookmarkGroup parentBookmark = m_pManager->findByAddress(m_parentAddress).toGroup(); 0461 Q_ASSERT(!parentBookmark.isNull()); 0462 KBookmarkDialog *dlg = m_pOwner->bookmarkDialog(m_pManager, QApplication::activeWindow()); 0463 dlg->createNewFolder(QLatin1String(""), parentBookmark); 0464 delete dlg; 0465 } 0466 0467 QAction *KBookmarkMenu::addBookmarkAction() const 0468 { 0469 return d->addBookmarkAction; 0470 } 0471 0472 QAction *KBookmarkMenu::bookmarkTabsAsFolderAction() const 0473 { 0474 return d->bookmarksToFolderAction; 0475 } 0476 0477 QAction *KBookmarkMenu::newBookmarkFolderAction() const 0478 { 0479 return d->newBookmarkFolderAction; 0480 } 0481 0482 QAction *KBookmarkMenu::editBookmarksAction() const 0483 { 0484 return d->editBookmarksAction; 0485 } 0486 0487 #include "moc_kbookmarkmenu.cpp"