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