KBookmarks

kbookmarkmenu.cpp
1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 1998, 1999 Torben Weis <weis@kde.org>
4 SPDX-FileCopyrightText: 2006 Daniel Teske <teske@squorn.de>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#include "kbookmarkmenu.h"
10#include "kbookmarkmenu_p.h"
11
12#include "../kbookmarksettings_p.h"
13#include "kbookmarkaction.h"
14#include "kbookmarkactionmenu.h"
15#include "kbookmarkcontextmenu.h"
16#include "kbookmarkdialog.h"
17#include "kbookmarkmanager.h"
18#include "kbookmarkowner.h"
19#include "kbookmarkswidgets_debug.h"
20#include "keditbookmarks_p.h"
21
22#include <KAuthorized>
23#include <KStandardActions>
24
25#include <QApplication>
26#include <QMenu>
27#include <QMessageBox>
28#include <QStandardPaths>
29
30/********************************************************************/
31/********************************************************************/
32/********************************************************************/
33class KBookmarkMenuPrivate
34{
35public:
36 QAction *newBookmarkFolderAction = nullptr;
37 QAction *addBookmarkAction = nullptr;
38 QAction *bookmarksToFolderAction = nullptr;
39 QAction *editBookmarksAction = nullptr;
40 bool browserMode = false;
41 bool isRoot;
42 bool dirty;
43 KBookmarkManager *manager;
44 KBookmarkOwner *owner;
45 QMenu *parentMenu;
46 QString parentAddress;
47};
48
50 : QObject()
51 , d(new KBookmarkMenuPrivate())
52{
53 d->isRoot = true;
54 d->manager = manager;
55 d->owner = _owner;
56 d->parentMenu = _parentMenu;
57 d->parentAddress = QString(); // TODO KBookmarkAdress::root
58 // TODO KDE5 find a QMenu equvalnet for this one
59 // m_parentMenu->setKeyboardShortcutsEnabled( true );
60
61 init();
62}
63
64void KBookmarkMenu::init()
65{
66 connect(d->parentMenu, &QMenu::aboutToShow, this, &KBookmarkMenu::slotAboutToShow);
67
68 if (KBookmarkSettings::self()->m_contextmenu) {
69 d->parentMenu->setContextMenuPolicy(Qt::CustomContextMenu);
70 connect(d->parentMenu, &QWidget::customContextMenuRequested, this, &KBookmarkMenu::slotCustomContextMenu);
71 }
72
73 connect(d->manager, &KBookmarkManager::changed, this, &KBookmarkMenu::slotBookmarksChanged);
74
75 d->dirty = true;
76 addActions();
77}
78
79void KBookmarkMenu::addActions()
80{
81 if (d->isRoot) {
82 addAddBookmark();
83 addAddBookmarksList();
84 addNewFolder();
85 addEditBookmarks();
86 } else {
87 if (!d->parentMenu->actions().isEmpty()) {
88 d->parentMenu->addSeparator();
89 }
90
91 addOpenInTabs();
92 addAddBookmark();
93 addAddBookmarksList();
94 addNewFolder();
95 }
96}
97
98KBookmarkMenu::KBookmarkMenu(KBookmarkManager *mgr, KBookmarkOwner *_owner, QMenu *_parentMenu, const QString &parentAddress)
99 : QObject()
100 , d(new KBookmarkMenuPrivate())
101{
102 d->isRoot = false;
103 d->manager = mgr;
104 d->owner = _owner;
105 d->parentMenu = _parentMenu;
106 d->parentAddress = parentAddress;
107
108 connect(_parentMenu, &QMenu::aboutToShow, this, &KBookmarkMenu::slotAboutToShow);
109 if (KBookmarkSettings::self()->m_contextmenu) {
110 d->parentMenu->setContextMenuPolicy(Qt::CustomContextMenu);
111 connect(d->parentMenu, &QWidget::customContextMenuRequested, this, &KBookmarkMenu::slotCustomContextMenu);
112 }
113 d->dirty = true;
114}
115
116KBookmarkMenu::~KBookmarkMenu()
117{
118 qDeleteAll(m_lstSubMenus);
119 qDeleteAll(m_actions);
120}
121
123{
124 slotAboutToShow();
125}
126
127void KBookmarkMenu::slotAboutToShow()
128{
129 // Did the bookmarks change since the last time we showed them ?
130 if (d->dirty) {
131 d->dirty = false;
132 clear();
133 refill();
134 d->parentMenu->adjustSize();
135 }
136}
137
138void KBookmarkMenu::slotCustomContextMenu(const QPoint &pos)
139{
140 QAction *action = d->parentMenu->actionAt(pos);
141 QMenu *menu = contextMenu(action);
142 if (!menu) {
143 return;
144 }
146 menu->popup(d->parentMenu->mapToGlobal(pos));
147}
148
149QMenu *KBookmarkMenu::contextMenu(QAction *action)
150{
151 KBookmarkActionInterface *act = dynamic_cast<KBookmarkActionInterface *>(action);
152 if (!act) {
153 return nullptr;
154 }
155 return new KBookmarkContextMenu(act->bookmark(), d->manager, d->owner);
156}
157
158bool KBookmarkMenu::isRoot() const
159{
160 return d->isRoot;
161}
162
163bool KBookmarkMenu::isDirty() const
164{
165 return d->dirty;
166}
167
169{
170 return d->parentAddress;
171}
172
173KBookmarkManager *KBookmarkMenu::manager() const
174{
175 return d->manager;
176}
177
178KBookmarkOwner *KBookmarkMenu::owner() const
179{
180 return d->owner;
181}
182
184{
185 return d->parentMenu;
186}
187
188/********************************************************************/
189/********************************************************************/
190/********************************************************************/
191
192/********************************************************************/
193/********************************************************************/
194/********************************************************************/
195
196void KBookmarkMenu::slotBookmarksChanged(const QString &groupAddress)
197{
198 qCDebug(KBOOKMARKSWIDGETS_LOG) << "KBookmarkMenu::slotBookmarksChanged groupAddress: " << groupAddress;
199 if (groupAddress == d->parentAddress) {
200 // qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::slotBookmarksChanged -> setting m_bDirty on " << groupAddress;
201 d->dirty = true;
202 } else {
203 // Iterate recursively into child menus
204 for (QList<KBookmarkMenu *>::iterator it = m_lstSubMenus.begin(), end = m_lstSubMenus.end(); it != end; ++it) {
205 (*it)->slotBookmarksChanged(groupAddress);
206 }
207 }
208}
209
210void KBookmarkMenu::clear()
211{
212 qDeleteAll(m_lstSubMenus);
214
215 for (QList<QAction *>::iterator it = m_actions.begin(), end = m_actions.end(); it != end; ++it) {
216 d->parentMenu->removeAction(*it);
217 delete *it;
218 }
219
220 d->parentMenu->clear();
222}
223
224void KBookmarkMenu::refill()
225{
226 // qCDebug(KBOOKMARKS_LOG) << "KBookmarkMenu::refill()";
227 if (d->isRoot) {
228 addActions();
229 }
230 fillBookmarks();
231 if (!d->isRoot) {
232 addActions();
233 }
234}
235
236void KBookmarkMenu::addOpenInTabs()
237{
238 if (!d->owner || !d->owner->supportsTabs() || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) {
239 return;
240 }
241
242 const QString title = tr("Open Folder in Tabs", "@action:inmenu");
243
244 QAction *paOpenFolderInTabs = new QAction(title, this);
245 paOpenFolderInTabs->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
246 paOpenFolderInTabs->setToolTip(tr("Open all bookmarks in this folder as a new tab", "@info:tooltip"));
247 paOpenFolderInTabs->setStatusTip(paOpenFolderInTabs->toolTip());
248 connect(paOpenFolderInTabs, &QAction::triggered, this, &KBookmarkMenu::slotOpenFolderInTabs);
249
250 d->parentMenu->addAction(paOpenFolderInTabs);
251 m_actions.append(paOpenFolderInTabs);
252}
253
254void KBookmarkMenu::addAddBookmarksList()
255{
256 if (!d->owner || !d->owner->enableOption(KBookmarkOwner::ShowAddBookmark) || !d->owner->supportsTabs()
257 || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) {
258 return;
259 }
260
261 if (!d->bookmarksToFolderAction) {
262 const QString title = tr("Bookmark Tabs as Folder…", "@action:inmenu");
263 d->bookmarksToFolderAction = new QAction(title, this);
264
265 if (d->isRoot) {
266 d->bookmarksToFolderAction->setObjectName(QStringLiteral("add_bookmarks_list"));
267 }
268
269 d->bookmarksToFolderAction->setIcon(QIcon::fromTheme(QStringLiteral("bookmark-new-list")));
270 d->bookmarksToFolderAction->setToolTip(tr("Add a folder of bookmarks for all open tabs", "@info:tooltip"));
271 d->bookmarksToFolderAction->setStatusTip(d->bookmarksToFolderAction->toolTip());
272 connect(d->bookmarksToFolderAction, &QAction::triggered, this, &KBookmarkMenu::slotAddBookmarksList);
273 }
274
275 d->parentMenu->addAction(d->bookmarksToFolderAction);
276}
277
278void KBookmarkMenu::addAddBookmark()
279{
280 if (!d->owner || !d->owner->enableOption(KBookmarkOwner::ShowAddBookmark) || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) {
281 return;
282 }
283
284 if (!d->addBookmarkAction) {
285 d->addBookmarkAction = KStandardActions::addBookmark(this, &KBookmarkMenu::slotAddBookmark, this);
286 if (d->isRoot) {
287 d->addBookmarkAction->setObjectName(QStringLiteral("add_bookmark"));
288 }
289
290 if (!d->isRoot) {
291 d->addBookmarkAction->setShortcut(QKeySequence());
292 }
293 }
294
295 d->parentMenu->addAction(d->addBookmarkAction);
296}
297
298void KBookmarkMenu::addEditBookmarks()
299{
300 if ((d->owner && !d->owner->enableOption(KBookmarkOwner::ShowEditBookmark))
301 || QStandardPaths::findExecutable(QStringLiteral(KEDITBOOKMARKS_BINARY)).isEmpty() || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) {
302 return;
303 }
304
305 d->editBookmarksAction = KStandardActions::editBookmarks(this, &KBookmarkMenu::slotEditBookmarks, this);
306 d->editBookmarksAction->setObjectName(QStringLiteral("edit_bookmarks"));
307
308 d->parentMenu->addAction(d->editBookmarksAction);
309 d->editBookmarksAction->setToolTip(tr("Edit your bookmark collection in a separate window", "@info:tooltip"));
310 d->editBookmarksAction->setStatusTip(d->editBookmarksAction->toolTip());
311}
312
313void KBookmarkMenu::slotEditBookmarks()
314{
315 KEditBookmarks editBookmarks;
316 editBookmarks.setBrowserMode(d->browserMode);
317 auto result = editBookmarks.openForFile(d->manager->path());
318
319 if (!result.sucess()) {
321 }
322}
323
324void KBookmarkMenu::addNewFolder()
325{
326 if (!d->owner || !d->owner->enableOption(KBookmarkOwner::ShowAddBookmark) || !KAuthorized::authorizeAction(QStringLiteral("bookmarks"))) {
327 return;
328 }
329
330 if (!d->newBookmarkFolderAction) {
331 d->newBookmarkFolderAction = new QAction(tr("New Bookmark Folder…", "@action:inmenu"), this);
332 d->newBookmarkFolderAction->setIcon(QIcon::fromTheme(QStringLiteral("folder-new")));
333 d->newBookmarkFolderAction->setToolTip(tr("Create a new bookmark folder in this menu", "@info:tooltip"));
334 d->newBookmarkFolderAction->setStatusTip(d->newBookmarkFolderAction->toolTip());
335
336 if (d->isRoot) {
337 d->newBookmarkFolderAction->setObjectName(QStringLiteral("new_bookmark_folder"));
338 }
339
340 connect(d->newBookmarkFolderAction, &QAction::triggered, this, &KBookmarkMenu::slotNewFolder);
341 }
342
343 d->parentMenu->addAction(d->newBookmarkFolderAction);
344}
345
346void KBookmarkMenu::fillBookmarks()
347{
348 KBookmarkGroup parentBookmark = d->manager->findByAddress(d->parentAddress).toGroup();
349 Q_ASSERT(!parentBookmark.isNull());
350
351 if (d->isRoot && !parentBookmark.first().isNull()) { // at least one bookmark
352 d->parentMenu->addSeparator();
353 }
354
355 for (KBookmark bm = parentBookmark.first(); !bm.isNull(); bm = parentBookmark.next(bm)) {
356 d->parentMenu->addAction(actionForBookmark(bm));
357 }
358}
359
360QAction *KBookmarkMenu::actionForBookmark(const KBookmark &bm)
361{
362 if (bm.isGroup()) {
363 // qCDebug(KBOOKMARKS_LOG) << "Creating bookmark submenu named " << bm.text();
364 KActionMenu *actionMenu = new KBookmarkActionMenu(bm, this);
365 m_actions.append(actionMenu);
366 KBookmarkMenu *subMenu = new KBookmarkMenu(d->manager, d->owner, actionMenu->menu(), bm.address());
367 m_lstSubMenus.append(subMenu);
368 return actionMenu;
369 } else if (bm.isSeparator()) {
370 QAction *sa = new QAction(this);
371 sa->setSeparator(true);
372 m_actions.append(sa);
373 return sa;
374 } else {
375 // qCDebug(KBOOKMARKS_LOG) << "Creating bookmark menu item for " << bm.text();
376 QAction *action = new KBookmarkAction(bm, d->owner, this);
377 m_actions.append(action);
378 return action;
379 }
380}
381
382void KBookmarkMenu::slotAddBookmarksList()
383{
384 if (!d->owner || !d->owner->supportsTabs()) {
385 return;
386 }
387
388 KBookmarkGroup parentBookmark = d->manager->findByAddress(d->parentAddress).toGroup();
389
391 dlg->addBookmarks(d->owner->currentBookmarkList(), QLatin1String(""), parentBookmark);
392 delete dlg;
393}
394
395void KBookmarkMenu::slotAddBookmark()
396{
397 if (!d->owner) {
398 return;
399 }
400 if (d->owner->currentTitle().isEmpty() && d->owner->currentUrl().isEmpty()) {
401 return;
402 }
403 KBookmarkGroup parentBookmark = d->manager->findByAddress(d->parentAddress).toGroup();
404
405 if (KBookmarkSettings::self()->m_advancedaddbookmark) {
407 dlg->addBookmark(d->owner->currentTitle(), d->owner->currentUrl(), d->owner->currentIcon(), parentBookmark);
408 delete dlg;
409 } else {
410 parentBookmark.addBookmark(d->owner->currentTitle(), d->owner->currentUrl(), d->owner->currentIcon());
411 d->manager->emitChanged(parentBookmark);
412 }
413}
414
415void KBookmarkMenu::slotOpenFolderInTabs()
416{
417 d->owner->openFolderinTabs(d->manager->findByAddress(d->parentAddress).toGroup());
418}
419
420void KBookmarkMenu::slotNewFolder()
421{
422 if (!d->owner) {
423 return; // this view doesn't handle bookmarks...
424 }
425 KBookmarkGroup parentBookmark = d->manager->findByAddress(d->parentAddress).toGroup();
426 Q_ASSERT(!parentBookmark.isNull());
428 dlg->createNewFolder(QLatin1String(""), parentBookmark);
429 delete dlg;
430}
431
433{
434 return d->addBookmarkAction;
435}
436
438{
439 return d->bookmarksToFolderAction;
440}
441
443{
444 return d->newBookmarkFolderAction;
445}
446
448{
449 return d->editBookmarksAction;
450}
451
452void KBookmarkMenu::setBrowserMode(bool browserMode)
453{
454 d->browserMode = browserMode;
455}
456
458{
459 return d->browserMode;
460}
461
462#include "moc_kbookmarkmenu.cpp"
static Q_INVOKABLE bool authorizeAction(const QString &action)
The interface to implement by actions and menus which represent a bookimark.
A wrapper around KActionMenu to provide a nice constructor for bookmark groups.
This class is a QAction for bookmarks.
A context menu for a bookmark.
This class provides a Dialog for editing properties, adding Bookmarks and creating new folders.
KBookmarkGroup addBookmarks(const QList< KBookmarkOwner::FutureBookmark > &list, const QString &name=QString(), KBookmarkGroup parent=KBookmarkGroup())
Creates a folder from a list of bookmarks Note: this updates the bookmark and calls KBookmarkManager:...
KBookmarkGroup createNewFolder(const QString &name, KBookmark parent=KBookmark())
Shows a dialog to create a new folder.
KBookmark addBookmark(const QString &title, const QUrl &url, const QString &icon, KBookmark parent=KBookmark())
Shows a "Add Bookmark" dialog Note: this updates the bookmark and calls KBookmarkManager::emitChanged...
A group of bookmarks.
Definition kbookmark.h:316
KBookmark next(const KBookmark &current) const
Return the next sibling of a child bookmark of this group.
KBookmark first() const
Return the first child bookmark of this group.
KBookmark addBookmark(const KBookmark &bm)
Create a new bookmark, as the last child of this group Don't forget to use KBookmarkManager::self()->...
This class implements the reading/writing of bookmarks in XML.
void changed(const QString &groupAddress)
Signals that the group (or any of its children) with the address groupAddress (e.g.
This class provides a bookmark menu.
QAction * editBookmarksAction() const
Returns the action for editing bookmarks.
KBookmarkMenu(KBookmarkManager *manager, KBookmarkOwner *owner, QMenu *parentMenu)
Fills a bookmark menu (one instance of KBookmarkMenu is created for the toplevel menu,...
bool browserMode() const
Whether any "Edit Bookmarks" dialog shows UI elements that are specific to browsers.
QList< QAction * > m_actions
List of our actions.
QAction * bookmarkTabsAsFolderAction() const
Returns the action for adding all current tabs as bookmarks.
void setBrowserMode(bool browserMode)
Set this to true to make any "Edit Bookmarks" dialog show UI elements that are specific to browsers.
QAction * addBookmarkAction() const
Returns the action for adding a bookmark.
void ensureUpToDate()
Call ensureUpToDate() if you need KBookmarkMenu to adjust to its final size before it is executed.
QMenu * parentMenu() const
The menu in which we insert our actions Supplied in the constructor.
QAction * newBookmarkFolderAction() const
Returns the action for adding a new bookmarks folder.
QString parentAddress() const
Parent bookmark for this menu.
QList< KBookmarkMenu * > m_lstSubMenus
List of our sub menus.
The KBookmarkMenu and KBookmarkBar classes gives the user the ability to either edit bookmarks or add...
A class representing a bookmark.
Definition kbookmark.h:27
bool isNull() const
bool isGroup() const
Whether the bookmark is a group or a normal bookmark.
bool isSeparator() const
Whether the bookmark is a separator.
QString address() const
Return the "address" of this bookmark in the whole tree.
QAction * editBookmarks(const QObject *recvr, const char *slot, QObject *parent)
void setIcon(const QIcon &icon)
QMenu * menu() const const
void setSeparator(bool b)
void setStatusTip(const QString &statusTip)
void setToolTip(const QString &tip)
void triggered(bool checked)
QWidget * activeWindow()
QIcon fromTheme(const QString &name)
void append(QList< T > &&value)
iterator begin()
void clear()
iterator end()
void aboutToShow()
void popup(const QPoint &p, QAction *atAction)
StandardButton critical(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString tr(const char *sourceText, const char *disambiguation, int n)
QString findExecutable(const QString &executableName, const QStringList &paths)
CustomContextMenu
WA_DeleteOnClose
void customContextMenuRequested(const QPoint &pos)
void setAttribute(Qt::WidgetAttribute attribute, bool on)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:10:11 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.