KBookmarks

kbookmarkmanager.cpp
1 // -*- c-basic-offset:4; indent-tabs-mode:nil -*-
2 /*
3  This file is part of the KDE libraries
4  SPDX-FileCopyrightText: 2000 David Faure <[email protected]>
5  SPDX-FileCopyrightText: 2003 Alexander Kellett <[email protected]>
6  SPDX-FileCopyrightText: 2008 Norbert Frese <[email protected]>
7 
8  SPDX-License-Identifier: LGPL-2.0-only
9 */
10 
11 #include "kbookmarkmanager.h"
12 #include "kbookmarkdialog.h"
13 #include "kbookmarkimporter.h"
14 #include "kbookmarkmenu.h"
15 #include "kbookmarkmenu_p.h"
16 #include "kbookmarks_debug.h"
17 #ifndef KBOOKMARKS_NO_DBUS
18 #include "kbookmarkmanageradaptor_p.h"
19 #endif
20 
21 #include <QDir>
22 #include <QFile>
23 #include <QFileInfo>
24 #include <QProcess>
25 #include <QRegularExpression>
26 #include <QTextCodec>
27 #include <QTextStream>
28 #ifndef KBOOKMARKS_NO_DBUS
29 #include <QDBusConnection>
30 #include <QDBusMessage>
31 #endif
32 #include <QApplication>
33 #include <QMessageBox>
34 #include <QReadWriteLock>
35 #include <QThread>
36 
37 #include <KBackup>
38 #include <KConfig>
39 #include <KConfigGroup>
40 #include <KDirWatch>
41 #include <QSaveFile>
42 #include <QStandardPaths>
43 
44 namespace
45 {
46 namespace Strings
47 {
48 QString bookmarkChangeNotifyInterface()
49 {
50  return QStringLiteral("org.kde.KIO.KBookmarkManager");
51 }
52 QString piData()
53 {
54  return QStringLiteral("version=\"1.0\" encoding=\"UTF-8\"");
55 }
56 }
57 }
58 
59 class KBookmarkManagerList : public QList<KBookmarkManager *>
60 {
61 public:
62  KBookmarkManagerList();
63  ~KBookmarkManagerList()
64  {
65  cleanup();
66  }
67  void cleanup()
68  {
70  qDeleteAll(copy); // auto-delete functionality
71  clear();
72  }
73 
74  QReadWriteLock lock;
75 };
76 
77 Q_GLOBAL_STATIC(KBookmarkManagerList, s_pSelf)
78 
79 static void deleteManagers()
80 {
81  if (s_pSelf.exists()) {
82  s_pSelf->cleanup();
83  }
84 }
85 
86 KBookmarkManagerList::KBookmarkManagerList()
87 {
88  // Delete the KBookmarkManagers while qApp exists, since we interact with the DBus thread
89  qAddPostRoutine(deleteManagers);
90 }
91 
92 class KBookmarkMap : private KBookmarkGroupTraverser
93 {
94 public:
95  KBookmarkMap()
96  : m_mapNeedsUpdate(true)
97  {
98  }
99  void setNeedsUpdate()
100  {
101  m_mapNeedsUpdate = true;
102  }
103  void update(KBookmarkManager *);
104  QList<KBookmark> find(const QString &url) const
105  {
106  return m_bk_map.value(url);
107  }
108 
109 private:
110  void visit(const KBookmark &) override;
111  void visitEnter(const KBookmarkGroup &) override
112  {
113  ;
114  }
115  void visitLeave(const KBookmarkGroup &) override
116  {
117  ;
118  }
119 
120 private:
121  typedef QList<KBookmark> KBookmarkList;
123  bool m_mapNeedsUpdate;
124 };
125 
126 void KBookmarkMap::update(KBookmarkManager *manager)
127 {
128  if (m_mapNeedsUpdate) {
129  m_mapNeedsUpdate = false;
130 
131  m_bk_map.clear();
132  KBookmarkGroup root = manager->root();
133  traverse(root);
134  }
135 }
136 
137 void KBookmarkMap::visit(const KBookmark &bk)
138 {
139  if (!bk.isSeparator()) {
140  // add bookmark to url map
141  m_bk_map[bk.internalElement().attribute(QStringLiteral("href"))].append(bk);
142  }
143 }
144 
145 // #########################
146 // KBookmarkManagerPrivate
147 class KBookmarkManagerPrivate
148 {
149 public:
150  KBookmarkManagerPrivate(bool bDocIsloaded, const QString &dbusObjectName = QString())
151  : m_doc(QStringLiteral("xbel"))
152  , m_dbusObjectName(dbusObjectName)
153  , m_docIsLoaded(bDocIsloaded)
154  , m_update(false)
155  , m_dialogAllowed(true)
156  , m_dialogParent(nullptr)
157  , m_browserEditor(false)
158  , m_typeExternal(false)
159  , m_dirWatch(nullptr)
160  {
161  }
162 
163  ~KBookmarkManagerPrivate()
164  {
165  delete m_dirWatch;
166  }
167 
168  mutable QDomDocument m_doc;
169  mutable QDomDocument m_toolbarDoc;
170  QString m_bookmarksFile;
171  QString m_dbusObjectName;
172  mutable bool m_docIsLoaded;
173  bool m_update;
174  bool m_dialogAllowed;
175  QWidget *m_dialogParent;
176 
177  bool m_browserEditor;
178  QString m_editorCaption;
179 
180  bool m_typeExternal;
181  KDirWatch *m_dirWatch; // for external bookmark files
182 
183  KBookmarkMap m_map;
184 };
185 
186 // ################
187 // KBookmarkManager
188 
189 static KBookmarkManager *lookupExisting(const QString &bookmarksFile)
190 {
191  for (KBookmarkManagerList::ConstIterator bmit = s_pSelf()->constBegin(), bmend = s_pSelf()->constEnd(); bmit != bmend; ++bmit) {
192  if ((*bmit)->path() == bookmarksFile) {
193  return *bmit;
194  }
195  }
196  return nullptr;
197 }
198 
199 KBookmarkManager *KBookmarkManager::managerForFile(const QString &bookmarksFile, const QString &dbusObjectName)
200 {
201  KBookmarkManager *mgr(nullptr);
202  {
203  QReadLocker readLock(&s_pSelf()->lock);
204  mgr = lookupExisting(bookmarksFile);
205  if (mgr) {
206  return mgr;
207  }
208  }
209 
210  QWriteLocker writeLock(&s_pSelf()->lock);
211  mgr = lookupExisting(bookmarksFile);
212  if (mgr) {
213  return mgr;
214  }
215 
216  mgr = new KBookmarkManager(bookmarksFile, dbusObjectName);
217  s_pSelf()->append(mgr);
218  return mgr;
219 }
220 
222 {
223  KBookmarkManager *mgr(nullptr);
224  {
225  QReadLocker readLock(&s_pSelf()->lock);
226  mgr = lookupExisting(bookmarksFile);
227  if (mgr) {
228  return mgr;
229  }
230  }
231 
232  QWriteLocker writeLock(&s_pSelf()->lock);
233  mgr = lookupExisting(bookmarksFile);
234  if (mgr) {
235  return mgr;
236  }
237 
238  mgr = new KBookmarkManager(bookmarksFile);
239  s_pSelf()->append(mgr);
240  return mgr;
241 }
242 
243 // principally used for filtered toolbars
245 {
246  KBookmarkManager *mgr = new KBookmarkManager();
247  s_pSelf()->append(mgr);
248  return mgr;
249 }
250 
251 static QDomElement createXbelTopLevelElement(QDomDocument &doc)
252 {
253  QDomElement topLevel = doc.createElement(QStringLiteral("xbel"));
254  topLevel.setAttribute(QStringLiteral("xmlns:mime"), QStringLiteral("http://www.freedesktop.org/standards/shared-mime-info"));
255  topLevel.setAttribute(QStringLiteral("xmlns:bookmark"), QStringLiteral("http://www.freedesktop.org/standards/desktop-bookmarks"));
256  topLevel.setAttribute(QStringLiteral("xmlns:kdepriv"), QStringLiteral("http://www.kde.org/kdepriv"));
257  doc.appendChild(topLevel);
258  doc.insertBefore(doc.createProcessingInstruction(QStringLiteral("xml"), Strings::piData()), topLevel);
259  return topLevel;
260 }
261 
262 KBookmarkManager::KBookmarkManager(const QString &bookmarksFile, const QString &dbusObjectName)
263  : d(new KBookmarkManagerPrivate(false, dbusObjectName))
264 {
265  if (dbusObjectName.isNull()) { // get dbusObjectName from file
266  if (QFile::exists(d->m_bookmarksFile)) {
267  parse(); // sets d->m_dbusObjectName
268  }
269  }
270 
271  init(QLatin1String("/KBookmarkManager/") + d->m_dbusObjectName);
272 
273  d->m_update = true;
274 
275  Q_ASSERT(!bookmarksFile.isEmpty());
276  d->m_bookmarksFile = bookmarksFile;
277 
278  if (!QFile::exists(d->m_bookmarksFile)) {
279  QDomElement topLevel = createXbelTopLevelElement(d->m_doc);
280  topLevel.setAttribute(QStringLiteral("dbusName"), dbusObjectName);
281  d->m_docIsLoaded = true;
282  }
283 }
284 
285 KBookmarkManager::KBookmarkManager(const QString &bookmarksFile)
286  : d(new KBookmarkManagerPrivate(false))
287 {
288  // use QFileSystemWatcher to monitor this bookmarks file
289  d->m_typeExternal = true;
290  d->m_update = true;
291 
292  Q_ASSERT(!bookmarksFile.isEmpty());
293  d->m_bookmarksFile = bookmarksFile;
294 
295  if (!QFile::exists(d->m_bookmarksFile)) {
296  createXbelTopLevelElement(d->m_doc);
297  } else {
298  parse();
299  }
300  d->m_docIsLoaded = true;
301 
302  // start KDirWatch
303  d->m_dirWatch = new KDirWatch;
304  d->m_dirWatch->addFile(d->m_bookmarksFile);
305  QObject::connect(d->m_dirWatch, &KDirWatch::dirty, this, &KBookmarkManager::slotFileChanged);
306  QObject::connect(d->m_dirWatch, &KDirWatch::created, this, &KBookmarkManager::slotFileChanged);
307  QObject::connect(d->m_dirWatch, &KDirWatch::deleted, this, &KBookmarkManager::slotFileChanged);
308 
309  // qCDebug(KBOOKMARKS_LOG) << "starting KDirWatch for" << d->m_bookmarksFile;
310 }
311 
312 KBookmarkManager::KBookmarkManager()
313  : d(new KBookmarkManagerPrivate(true))
314 {
315  init(QStringLiteral("/KBookmarkManager/generated"));
316  d->m_update = false; // TODO - make it read/write
317 
318  createXbelTopLevelElement(d->m_doc);
319 }
320 
321 void KBookmarkManager::init(const QString &dbusPath)
322 {
323 #ifndef KBOOKMARKS_NO_DBUS
324  // A KBookmarkManager without a dbus name is a temporary one, like those used by importers;
325  // no need to register them to dbus
326  if (dbusPath != QLatin1String("/KBookmarkManager/") && dbusPath != QLatin1String("/KBookmarkManager/generated")) {
327  new KBookmarkManagerAdaptor(this);
329 
331  dbusPath,
332  Strings::bookmarkChangeNotifyInterface(),
333  QStringLiteral("bookmarksChanged"),
334  this,
337  .connect(QString(), dbusPath, Strings::bookmarkChangeNotifyInterface(), QStringLiteral("bookmarkConfigChanged"), this, SLOT(notifyConfigChanged()));
338  }
339 #endif
340 }
341 
342 void KBookmarkManager::startKEditBookmarks(const QStringList &args)
343 {
344  bool success = false;
345  const QString exec = QStandardPaths::findExecutable(QStringLiteral(KEDITBOOKMARKS_BINARY));
346  if (!exec.isEmpty()) {
347  success = QProcess::startDetached(exec, args);
348  }
349 
350  if (!success) {
351  QString err =
352  tr("Cannot launch keditbookmarks.\n\n"
353  "Most likely you do not have keditbookmarks currently installed");
354 
355  if (d->m_dialogAllowed && qobject_cast<QApplication *>(qApp) && QThread::currentThread() == qApp->thread()) {
357  }
358 
359  qCWarning(KBOOKMARKS_LOG) << QStringLiteral("Failed to start keditbookmarks");
360  Q_EMIT this->error(err);
361  }
362 }
363 
364 void KBookmarkManager::slotFileChanged(const QString &path)
365 {
366  if (path == d->m_bookmarksFile) {
367  // qCDebug(KBOOKMARKS_LOG) << "file changed (KDirWatch) " << path ;
368  // Reparse
369  parse();
370  // Tell our GUI
371  // (emit where group is "" to directly mark the root menu as dirty)
373  }
374 }
375 
377 {
378  if (!s_pSelf.isDestroyed()) {
379  s_pSelf()->removeAll(this);
380  }
381 }
382 
384 {
385  return d->m_dialogAllowed;
386 }
387 
389 {
390  d->m_dialogAllowed = enable;
391  d->m_dialogParent = parent;
392 }
393 
395 {
396  d->m_update = update;
397 }
398 
400 {
401  if (!d->m_docIsLoaded) {
402  parse();
403  d->m_toolbarDoc.clear();
404  }
405  return d->m_doc;
406 }
407 
408 void KBookmarkManager::parse() const
409 {
410  d->m_docIsLoaded = true;
411  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::parse " << d->m_bookmarksFile;
412  QFile file(d->m_bookmarksFile);
413  if (!file.open(QIODevice::ReadOnly)) {
414  qCWarning(KBOOKMARKS_LOG) << "Can't open" << d->m_bookmarksFile;
415  d->m_doc = QDomDocument(QStringLiteral("xbel"));
416  createXbelTopLevelElement(d->m_doc);
417  return;
418  }
419  d->m_doc = QDomDocument(QStringLiteral("xbel"));
420  d->m_doc.setContent(&file);
421 
422  if (d->m_doc.documentElement().isNull()) {
423  qCWarning(KBOOKMARKS_LOG) << "KBookmarkManager::parse : main tag is missing, creating default " << d->m_bookmarksFile;
424  QDomElement element = d->m_doc.createElement(QStringLiteral("xbel"));
425  d->m_doc.appendChild(element);
426  }
427 
428  QDomElement docElem = d->m_doc.documentElement();
429 
430  QString mainTag = docElem.tagName();
431  if (mainTag != QLatin1String("xbel")) {
432  qCWarning(KBOOKMARKS_LOG) << "KBookmarkManager::parse : unknown main tag " << mainTag;
433  }
434 
435  if (d->m_dbusObjectName.isNull()) {
436  d->m_dbusObjectName = docElem.attribute(QStringLiteral("dbusName"));
437  } else if (docElem.attribute(QStringLiteral("dbusName")) != d->m_dbusObjectName) {
438  docElem.setAttribute(QStringLiteral("dbusName"), d->m_dbusObjectName);
439  save();
440  }
441 
442  QDomNode n = d->m_doc.documentElement().previousSibling();
443  if (n.isProcessingInstruction()) {
445  pi.parentNode().removeChild(pi);
446  }
447 
449  pi = d->m_doc.createProcessingInstruction(QStringLiteral("xml"), Strings::piData());
450  d->m_doc.insertBefore(pi, docElem);
451 
452  file.close();
453 
454  d->m_map.setNeedsUpdate();
455 }
456 
457 bool KBookmarkManager::save(bool toolbarCache) const
458 {
459  return saveAs(d->m_bookmarksFile, toolbarCache);
460 }
461 
462 bool KBookmarkManager::saveAs(const QString &filename, bool toolbarCache) const
463 {
464  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::save " << filename;
465 
466  // Save the bookmark toolbar folder for quick loading
467  // but only when it will actually make things quicker
468  const QString cacheFilename = filename + QLatin1String(".tbcache");
469  if (toolbarCache && !root().isToolbarGroup()) {
470  QSaveFile cacheFile(cacheFilename);
471  if (cacheFile.open(QIODevice::WriteOnly)) {
472  QString str;
473  QTextStream stream(&str, QIODevice::WriteOnly);
474  stream << root().findToolbar();
475  const QByteArray cstr = str.toUtf8();
476  cacheFile.write(cstr.data(), cstr.length());
477  cacheFile.commit();
478  }
479  } else { // remove any (now) stale cache
480  QFile::remove(cacheFilename);
481  }
482 
483  // Create parent dirs
484  QFileInfo info(filename);
485  QDir().mkpath(info.absolutePath());
486 
487  QSaveFile file(filename);
488  if (file.open(QIODevice::WriteOnly)) {
489  KBackup::simpleBackupFile(file.fileName(), QString(), QStringLiteral(".bak"));
490  QTextStream stream(&file);
491  // In Qt6 it's UTF-8 by default
492 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
493  stream.setCodec(QTextCodec::codecForName("UTF-8"));
494 #endif
495  stream << internalDocument().toString();
496  stream.flush();
497  if (file.commit()) {
498  return true;
499  }
500  }
501 
502  static int hadSaveError = false;
503  if (!hadSaveError) {
504  QString err = tr("Unable to save bookmarks in %1. Reported error was: %2. "
505  "This error message will only be shown once. The cause "
506  "of the error needs to be fixed as quickly as possible, "
507  "which is most likely a full hard drive.")
508  .arg(filename, file.errorString());
509 
510  if (d->m_dialogAllowed && qobject_cast<QApplication *>(qApp) && QThread::currentThread() == qApp->thread()) {
512  }
513 
514  qCCritical(KBOOKMARKS_LOG)
515  << QStringLiteral("Unable to save bookmarks in %1. File reported the following error-code: %2.").arg(filename).arg(file.error());
516  Q_EMIT const_cast<KBookmarkManager *>(this)->error(err);
517  }
518  hadSaveError = true;
519  return false;
520 }
521 
523 {
524  return d->m_bookmarksFile;
525 }
526 
528 {
529  return KBookmarkGroup(internalDocument().documentElement());
530 }
531 
533 {
534  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::toolbar begin";
535  // Only try to read from a toolbar cache if the full document isn't loaded
536  if (!d->m_docIsLoaded) {
537  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::toolbar trying cache";
538  const QString cacheFilename = d->m_bookmarksFile + QLatin1String(".tbcache");
539  QFileInfo bmInfo(d->m_bookmarksFile);
540  QFileInfo cacheInfo(cacheFilename);
541  if (d->m_toolbarDoc.isNull() && QFile::exists(cacheFilename) && bmInfo.lastModified() < cacheInfo.lastModified()) {
542  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::toolbar reading file";
543  QFile file(cacheFilename);
544 
545  if (file.open(QIODevice::ReadOnly)) {
546  d->m_toolbarDoc = QDomDocument(QStringLiteral("cache"));
547  d->m_toolbarDoc.setContent(&file);
548  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::toolbar opened";
549  }
550  }
551  if (!d->m_toolbarDoc.isNull()) {
552  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::toolbar returning element";
553  QDomElement elem = d->m_toolbarDoc.firstChild().toElement();
554  return KBookmarkGroup(elem);
555  }
556  }
557 
558  // Fallback to the normal way if there is no cache or if the bookmark file
559  // is already loaded
560  QDomElement elem = root().findToolbar();
561  if (elem.isNull()) {
562  // Root is the bookmark toolbar if none has been set.
563  // Make it explicit to speed up invocations of findToolbar()
564  root().internalElement().setAttribute(QStringLiteral("toolbar"), QStringLiteral("yes"));
565  return root();
566  } else {
567  return KBookmarkGroup(elem);
568  }
569 }
570 
572 {
573  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::findByAddress " << address;
574  KBookmark result = root();
575  // The address is something like /5/10/2+
576  static const QRegularExpression separator(QStringLiteral("[/+]"));
577  const QStringList addresses = address.split(separator, Qt::SkipEmptyParts);
578  // qCWarning(KBOOKMARKS_LOG) << addresses.join(",");
579  for (QStringList::const_iterator it = addresses.begin(); it != addresses.end();) {
580  bool append = ((*it) == QLatin1String("+"));
581  uint number = (*it).toUInt();
582  Q_ASSERT(result.isGroup());
583  KBookmarkGroup group = result.toGroup();
584  KBookmark bk = group.first();
585  KBookmark lbk = bk; // last non-null bookmark
586  for (uint i = 0; ((i < number) || append) && !bk.isNull(); ++i) {
587  lbk = bk;
588  bk = group.next(bk);
589  // qCWarning(KBOOKMARKS_LOG) << i;
590  }
591  it++;
592  // qCWarning(KBOOKMARKS_LOG) << "found section";
593  result = bk;
594  }
595  if (result.isNull()) {
596  qCWarning(KBOOKMARKS_LOG) << "KBookmarkManager::findByAddress: couldn't find item " << address;
597  }
598  // qCWarning(KBOOKMARKS_LOG) << "found " << result.address();
599  return result;
600 }
601 
603 {
604  emitChanged(root());
605 }
606 
608 {
609  (void)save(); // KDE5 TODO: emitChanged should return a bool? Maybe rename it to saveAndEmitChanged?
610 
611  // Tell the other processes too
612  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::emitChanged : broadcasting change " << group.address();
613 
615 
616  // We do get our own broadcast, so no need for this anymore
617  // emit changed( group );
618 }
619 
620 void KBookmarkManager::emitConfigChanged()
621 {
623 }
624 
625 void KBookmarkManager::notifyCompleteChange(const QString &caller) // DBUS call
626 {
627  if (!d->m_update) {
628  return;
629  }
630 
631  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::notifyCompleteChange";
632  // The bk editor tells us we should reload everything
633  // Reparse
634  parse();
635  // Tell our GUI
636  // (emit where group is "" to directly mark the root menu as dirty)
637  Q_EMIT changed(QLatin1String(""), caller);
638 }
639 
640 void KBookmarkManager::notifyConfigChanged() // DBUS call
641 {
642  // qCDebug(KBOOKMARKS_LOG) << "reloaded bookmark config!";
643  KBookmarkSettings::self()->readSettings();
644  parse(); // reload, and thusly recreate the menus
646 }
647 
648 #ifndef KBOOKMARKS_NO_DBUS
649 void KBookmarkManager::notifyChanged(const QString &groupAddress, const QDBusMessage &msg) // DBUS call
650 {
651  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::notifyChanged ( "<<groupAddress<<")";
652  if (!d->m_update) {
653  return;
654  }
655 
656  // Reparse (the whole file, no other choice)
657  // if someone else notified us
659  parse();
660  }
661 
662  // qCDebug(KBOOKMARKS_LOG) << "KBookmarkManager::notifyChanged " << groupAddress;
663  // KBookmarkGroup group = findByAddress( groupAddress ).toGroup();
664  // Q_ASSERT(!group.isNull());
665  Q_EMIT changed(groupAddress, QString());
666 }
667 #endif
668 
669 void KBookmarkManager::setEditorOptions(const QString &caption, bool browser)
670 {
671  d->m_editorCaption = caption;
672  d->m_browserEditor = browser;
673 }
674 
675 void KBookmarkManager::slotEditBookmarks()
676 {
677  QStringList args;
678  if (!d->m_editorCaption.isEmpty()) {
679  args << QStringLiteral("--customcaption") << d->m_editorCaption;
680  }
681  if (!d->m_browserEditor) {
682  args << QStringLiteral("--nobrowser");
683  }
684  if (!d->m_dbusObjectName.isEmpty()) {
685  args << QStringLiteral("--dbusObjectName") << d->m_dbusObjectName;
686  }
687  args << d->m_bookmarksFile;
688  startKEditBookmarks(args);
689 }
690 
691 void KBookmarkManager::slotEditBookmarksAtAddress(const QString &address)
692 {
693  QStringList args;
694  if (!d->m_editorCaption.isEmpty()) {
695  args << QStringLiteral("--customcaption") << d->m_editorCaption;
696  }
697  if (!d->m_browserEditor) {
698  args << QStringLiteral("--nobrowser");
699  }
700  if (!d->m_dbusObjectName.isEmpty()) {
701  args << QStringLiteral("--dbusObjectName") << d->m_dbusObjectName;
702  }
703  args << QStringLiteral("--address") << address << d->m_bookmarksFile;
704  startKEditBookmarks(args);
705 }
706 
707 ///////
709 {
710  d->m_map.update(this);
711  QList<KBookmark> list = d->m_map.find(url);
712  if (list.isEmpty()) {
713  return false;
714  }
715 
716  for (QList<KBookmark>::iterator it = list.begin(); it != list.end(); ++it) {
717  (*it).updateAccessMetadata();
718  }
719 
720  return true;
721 }
722 
723 void KBookmarkManager::updateFavicon(const QString &url, const QString & /*faviconurl*/)
724 {
725  d->m_map.update(this);
726  QList<KBookmark> list = d->m_map.find(url);
727  for (QList<KBookmark>::iterator it = list.begin(); it != list.end(); ++it) {
728  // TODO - update favicon data based on faviconurl
729  // but only when the previously used icon
730  // isn't a manually set one.
731  }
732 }
733 
735 {
736  const QString bookmarksFile =
738  KBookmarkManager *bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile, QStringLiteral("konqueror"));
740  if (caption.isEmpty()) {
742  }
743  bookmarkManager->setEditorOptions(caption, true);
744  return bookmarkManager;
745 }
746 
747 KBookmarkSettings *KBookmarkSettings::s_self = nullptr;
748 
749 void KBookmarkSettings::readSettings()
750 {
751  KConfig config(QStringLiteral("kbookmarkrc"), KConfig::NoGlobals);
752  KConfigGroup cg(&config, "Bookmarks");
753 
754  // add bookmark dialog usage - no reparse
755  s_self->m_advancedaddbookmark = cg.readEntry("AdvancedAddBookmarkDialog", false);
756 
757  // this one alters the menu, therefore it needs a reparse
758  s_self->m_contextmenu = cg.readEntry("ContextMenuActions", true);
759 }
760 
761 KBookmarkSettings *KBookmarkSettings::self()
762 {
763  if (!s_self) {
764  s_self = new KBookmarkSettings;
765  readSettings();
766  }
767  return s_self;
768 }
769 
770 #include "moc_kbookmarkmanager.cpp"
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
QString toString(int indent) const const
bool isNull() const const
KBookmark findByAddress(const QString &address)
QString errorString() const const
bool autoErrorHandlingEnabled() const
Check whether auto error handling is enabled.
void error(const QString &errorMessage)
Emitted when an error occurs.
static KBookmarkManager * managerForExternalFile(const QString &bookmarksFile)
Returns a KBookmarkManager, which will use QFileSystemWatcher for change detection This is important ...
QDomProcessingInstruction createProcessingInstruction(const QString &target, const QString &data)
bool isProcessingInstruction() const const
QDomProcessingInstruction toProcessingInstruction() const const
bool remove()
Q_EMITQ_EMIT
QString tagName() const const
QDomNode parentNode() const const
virtual bool open(QIODevice::OpenMode mode) override
void clear()
void emitChanged()
Saves the bookmark file and notifies everyone.
QDomNode removeChild(const QDomNode &oldChild)
bool isNull() const const
bool isSeparator() const
Whether the bookmark is a separator.
Definition: kbookmark.cpp:294
QDomDocument internalDocument() const
void changed(const QString &groupAddress, const QString &caller)
Signals that the group (or any of its children) with the address groupAddress (e.g.
KBookmarkGroup toolbar()
This returns the root of the toolbar menu.
bool commit()
static KBookmarkManager * userBookmarksManager()
Returns a pointer to the user's main (konqueror) bookmark collection.
QWidget * activeWindow()
QString writableLocation(QStandardPaths::StandardLocation type)
KBookmark first() const
Return the first child bookmark of this group.
Definition: kbookmark.cpp:121
bool registerObject(const QString &path, QObject *object, QDBusConnection::RegisterOptions options)
QDomElement internalElement() const
Definition: kbookmark.cpp:502
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QDomElement createElement(const QString &tagName)
QString caption()
virtual bool open(QIODevice::OpenMode mode) override
bool exists() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QThread * thread() const const
QString baseService() const const
QString address() const
Return the "address" of this bookmark in the whole tree.
Definition: kbookmark.cpp:479
Q_GLOBAL_STATIC(Internal::StaticControl, s_instance) class ControlPrivate
QString findExecutable(const QString &executableName, const QStringList &paths)
void setAttribute(const QString &name, const QString &value)
QString path() const
This will return the path that this manager is using to read the bookmarks.
virtual QString fileName() const const override
void flush()
bool saveAs(const QString &filename, bool toolbarCache=true) const
Save the bookmarks to the given XML file on disk.
QAction * copy(const QObject *recvr, const char *slot, QObject *parent)
void notifyCompleteChange(const QString &caller)
Reparse the whole bookmarks file and notify about the change Doesn't send signal over D-Bus to the ot...
KBookmark next(const KBookmark &current) const
Return the next sibling of a child bookmark of this group.
Definition: kbookmark.cpp:131
QDBusConnection sessionBus()
KBookmarkGroup root() const
This will return the root bookmark.
A class to traverse bookarm groups.
Definition: kbookmark.h:433
KBookmarkGroup toGroup() const
Convert this to a group - do this only if isGroup() returns true.
Definition: kbookmark.cpp:473
SkipEmptyParts
bool isEmpty() const const
QByteArray toUtf8() const const
void setAutoErrorHandlingEnabled(bool enable, QWidget *parent)
Enable or disable auto error handling is enabled.
QTextCodec * codecForName(const QByteArray &name)
bool isNull() const
Definition: kbookmark.cpp:299
bool mkpath(const QString &dirPath) const const
QThread * currentThread()
bool isEmpty() const const
PostalAddress address(const QVariant &location)
QDomNode insertBefore(const QDomNode &newChild, const QDomNode &refChild)
KSharedConfigPtr config()
bool save(bool toolbarCache=true) const
Save the bookmarks to an XML file on disk.
QAction * find(const QObject *recvr, const char *slot, QObject *parent)
uint toUInt(bool *ok, int base) const const
QString absolutePath() const const
bool startDetached(qint64 *pid)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QDomNode appendChild(const QDomNode &newChild)
QFileDevice::FileError error() const const
void dirty(const QString &path)
static KBookmarkManager * managerForFile(const QString &bookmarksFile, const QString &dbusObjectName)
This static function will return an instance of the KBookmarkManager, responsible for the given bookm...
void update(Part *part, const QByteArray &data, qint64 dataSize)
void deleted(const QString &path)
void clear()
QList::iterator begin()
~KBookmarkManager() override
Destructor.
QString service() const const
bool simpleBackupFile(const QString &filename, const QString &backupDir=QString(), const QString &backupExtension=QStringLiteral("~"))
void setUpdate(bool update)
Set the update flag.
QDomElement findToolbar() const
Definition: kbookmark.cpp:250
void created(const QString &path)
int length() const const
bool isGroup() const
Whether the bookmark is a group or a normal bookmark.
Definition: kbookmark.cpp:287
QString attribute(const QString &name, const QString &defValue) const const
void setEditorOptions(const QString &caption, bool browser)
Set options with which slotEditBookmarks called keditbookmarks this can be used to change the appeara...
QDateTime lastModified() const const
QList::iterator end()
void bookmarkConfigChanged()
Signal send over D-Bus.
bool updateAccessMetadata(const QString &url)
Update access time stamps for a given url.
QString tr(const char *sourceText, const char *disambiguation, int n)
void notifyChanged(const QString &groupAddress, const QDBusMessage &msg)
Emit the changed signal for the group whose address is given.
void setCodec(QTextCodec *codec)
void configChanged()
Signals that the config changed.
QMessageBox::StandardButton critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
static KBookmarkManager * createTempManager()
only used for KBookmarkBar
QObject * parent() const const
void bookmarksChanged(QString groupAddress)
Signal send over D-Bus.
char * data()
qint64 write(const char *data, qint64 maxSize)
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 Mon Dec 11 2023 03:57:16 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.