KBookmarks

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

KDE's Doxygen guidelines are available online.