KBookmarks

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

KDE's Doxygen guidelines are available online.