• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • applications API Reference
  • KDE Home
  • Contact Us
 

libkonq

  • sources
  • kde-4.12
  • applications
  • kde-baseapps
  • lib
  • konq
konq_historyprovider.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2  Copyright 2000,2001 Carsten Pfeiffer <pfeiffer@kde.org>
3  Copyright 2007-2009 David Faure <faure@kde.org>
4 
5  This library is free software; you can redistribute it and/or modify
6  it under the terms of the GNU Library General Public License as published
7  by the Free Software Foundation; either version 2 of the License or
8  ( at your option ) version 3 or, at the discretion of KDE e.V.
9  ( which shall act as a proxy as in section 14 of the GPLv3 ), any later version.
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 "konq_historyprovider.h"
23 #include <ksavefile.h>
24 #include <kstandarddirs.h>
25 #include <kdebug.h>
26 #include <kconfiggroup.h>
27 #include <ksharedconfig.h>
28 #include "konq_historyloader.h"
29 #include <zlib.h> // for crc32
30 #include <QtDBus/QtDBus>
31 
32 class KonqHistoryProviderPrivate : public QObject, QDBusContext
33 {
34  Q_OBJECT
35  Q_CLASSINFO("D-Bus Interface", "org.kde.Konqueror.HistoryManager")
36 public:
37  KonqHistoryProviderPrivate(KonqHistoryProvider* qq);
38 
43  void adjustSize();
44 
48  bool saveHistory();
49 
50 Q_SIGNALS: // DBUS methods/signals, they have to match org.kde.Konqueror.HistoryManager.xml
51  friend class KonqHistoryProvider;
61  void notifyHistoryEntry(const QByteArray & historyEntry);
62 
67  void notifyMaxCount(int count);
68 
73  void notifyMaxAge(int days);
74 
78  void notifyClear();
79 
84  void notifyRemove(const QString& url);
85 
90  void notifyRemoveList(const QStringList& urls);
91 
92 private Q_SLOTS: // connected to DBUS signals
93  void slotNotifyHistoryEntry(const QByteArray& historyEntry);
94  void slotNotifyMaxCount(int count);
95  void slotNotifyMaxAge(int days);
96  void slotNotifyClear();
97  void slotNotifyRemove(const QString& url);
98  void slotNotifyRemoveList(const QStringList& urls);
99 
100 public:
101  KSharedConfig::Ptr konqConfig() {
102  // We want to use konquerorrc even when this class isn't used in konqueror,
103  // this is why this doesn't say KGlobal::config().
104  return KSharedConfig::openConfig("konquerorrc");
105  }
106 
107  KonqHistoryList m_history;
108  int m_maxCount; // maximum of history entries
109  int m_maxAgeDays; // maximum age of a history entry
110  KonqHistoryProvider* q;
111 };
112 
113 KonqHistoryProviderPrivate::KonqHistoryProviderPrivate(KonqHistoryProvider* qq)
114  : QObject(), QDBusContext(), q(qq)
115 {
116  // defaults
117  KConfigGroup cs(konqConfig(), "HistorySettings");
118  m_maxCount = cs.readEntry("Maximum of History entries", 500);
119  m_maxCount = qMax(1, m_maxCount);
120  m_maxAgeDays = cs.readEntry("Maximum age of History entries", 90);
121 
122  const QString dbusPath = "/KonqHistoryManager";
123  const QString dbusInterface = "org.kde.Konqueror.HistoryManager";
124 
125  QDBusConnection dbus = QDBusConnection::sessionBus();
126  dbus.registerObject(dbusPath, this, QDBusConnection::ExportAllSignals);
127  dbus.connect(QString(), dbusPath, dbusInterface, "notifyClear", this, SLOT(slotNotifyClear()));
128  dbus.connect(QString(), dbusPath, dbusInterface, "notifyHistoryEntry", this, SLOT(slotNotifyHistoryEntry(QByteArray)));
129  dbus.connect(QString(), dbusPath, dbusInterface, "notifyMaxAge", this, SLOT(slotNotifyMaxAge(int)));
130  dbus.connect(QString(), dbusPath, dbusInterface, "notifyMaxCount", this, SLOT(slotNotifyMaxCount(int)));
131  dbus.connect(QString(), dbusPath, dbusInterface, "notifyRemove", this, SLOT(slotNotifyRemove(QString)));
132  dbus.connect(QString(), dbusPath, dbusInterface, "notifyRemoveList", this, SLOT(slotNotifyRemoveList(QStringList)));
133 }
134 
136 
137 KonqHistoryProvider::KonqHistoryProvider(QObject* parent)
138  : KParts::HistoryProvider(parent), d(new KonqHistoryProviderPrivate(this))
139 {
140 }
141 
142 KonqHistoryProvider::~KonqHistoryProvider()
143 {
144  delete d;
145 }
146 
147 const KonqHistoryList& KonqHistoryProvider::entries() const
148 {
149  return d->m_history;
150 }
151 
152 bool KonqHistoryProvider::loadHistory()
153 {
154  KonqHistoryLoader loader;
155  if (!loader.loadHistory()) {
156  return false;
157  }
158 
159  d->m_history = loader.entries();
160 
161  d->adjustSize();
162 
163  QListIterator<KonqHistoryEntry> it(d->m_history);
164  while (it.hasNext()) {
165  const KonqHistoryEntry& entry = it.next();
166 
167  // Fill the entries into KParts::HistoryProvider.
168  const QString urlString = entry.url.url();
169  KParts::HistoryProvider::insert(urlString);
170  // DF: also insert the "pretty" version if different
171  // This helps getting 'visited' links on websites which don't use fully-escaped urls.
172  const QString prettyUrlString = entry.url.prettyUrl();
173  if (urlString != prettyUrlString)
174  KParts::HistoryProvider::insert(prettyUrlString);
175  }
176 
177  return true;
178 }
179 
180 void KonqHistoryProviderPrivate::adjustSize()
181 {
182  if (m_history.isEmpty())
183  return;
184 
185  KonqHistoryEntry entry = m_history.first();
186  const QDateTime expirationDate(QDate::currentDate().addDays(-m_maxAgeDays));
187 
188  while (m_history.count() > (qint32)m_maxCount ||
189  (m_maxAgeDays > 0 && entry.lastVisited.isValid() && entry.lastVisited < expirationDate)) // i.e. entry is expired
190  {
191  q->removeEntry(m_history.begin());
192 
193  if (m_history.isEmpty())
194  break;
195  entry = m_history.first();
196  }
197 }
198 
199 static QString dbusService()
200 {
201  return QDBusConnection::sessionBus().baseService();
202 }
203 
204 void KonqHistoryProvider::emitAddToHistory(const KonqHistoryEntry& entry)
205 {
206  QByteArray data;
207  QDataStream stream(&data, QIODevice::WriteOnly);
208  entry.save(stream, KonqHistoryEntry::MarshalUrlAsStrings);
209  stream << dbusService();
210  // Protection against very long urls (like data:)
211  if (data.size() > 4096)
212  return;
213  emit d->notifyHistoryEntry(data);
214 }
215 
216 void KonqHistoryProvider::emitRemoveFromHistory(const KUrl& url)
217 {
218  emit d->notifyRemove(url.url());
219 }
220 
221 void KonqHistoryProvider::emitRemoveListFromHistory(const KUrl::List& urls)
222 {
223  emit d->notifyRemoveList(urls.toStringList());
224 }
225 
226 void KonqHistoryProvider::emitClear()
227 {
228  emit d->notifyClear();
229 }
230 
231 void KonqHistoryProvider::emitSetMaxCount(int count)
232 {
233  emit d->notifyMaxCount(count);
234 }
235 
236 void KonqHistoryProvider::emitSetMaxAge(int days)
237 {
238  emit d->notifyMaxAge(days);
239 }
240 
244 static bool isSenderOfSignal(const QDBusMessage& msg)
245 {
246  return dbusService() == msg.service();
247 }
248 
249 void KonqHistoryProviderPrivate::slotNotifyHistoryEntry(const QByteArray& data)
250 {
251  KonqHistoryEntry e;
252  QDataStream stream(const_cast<QByteArray *>(&data), QIODevice::ReadOnly);
253 
254  //This is important - we need to switch to a consistent marshalling format for
255  //communicating between different konqueror instances. Since during an upgrade
256  //some "old" copies may still running, we use the old format for the DBUS transfers.
257  //This doesn't make that much difference performance-wise for single entries anyway.
258  e.load(stream, KonqHistoryEntry::MarshalUrlAsStrings);
259  //kDebug(1202) << "Got new entry from Broadcast:" << e.url;
260 
261  KonqHistoryList::iterator existingEntry = q->findEntry(e.url);
262  QString urlString = e.url.url();
263  const bool newEntry = existingEntry == m_history.end();
264 
265  KonqHistoryEntry entry;
266 
267  if (!newEntry) {
268  entry = *existingEntry;
269  } else { // create a new history entry
270  entry.url = e.url;
271  entry.firstVisited = e.firstVisited;
272  entry.numberOfTimesVisited = 0; // will get set to 1 below
273  q->KParts::HistoryProvider::insert(urlString);
274  }
275 
276  if (!e.typedUrl.isEmpty())
277  entry.typedUrl = e.typedUrl;
278  if (!e.title.isEmpty())
279  entry.title = e.title;
280  entry.numberOfTimesVisited += e.numberOfTimesVisited;
281  entry.lastVisited = e.lastVisited;
282 
283  if (newEntry)
284  m_history.append(entry);
285  else {
286  *existingEntry = entry;
287  }
288 
289  adjustSize();
290 
291  q->finishAddingEntry(entry, isSenderOfSignal(message()));
292 
293  emit q->entryAdded(entry);
294 }
295 
296 void KonqHistoryProviderPrivate::slotNotifyMaxCount(int count)
297 {
298  m_maxCount = count;
299  // TODO clearPending();
300  adjustSize();
301 
302  KConfigGroup cs(konqConfig(), "HistorySettings");
303  cs.writeEntry("Maximum of History entries", m_maxCount);
304 
305  if (isSenderOfSignal(message())) {
306  saveHistory();
307  cs.sync();
308  }
309 }
310 
311 void KonqHistoryProviderPrivate::slotNotifyMaxAge(int days)
312 {
313  m_maxAgeDays = days;
314  // TODO clearPending();
315  adjustSize();
316 
317  KConfigGroup cs(konqConfig(), "HistorySettings");
318  cs.writeEntry("Maximum age of History entries", m_maxAgeDays);
319 
320  if (isSenderOfSignal(message())) {
321  saveHistory();
322  cs.sync();
323  }
324 }
325 
326 void KonqHistoryProviderPrivate::slotNotifyClear()
327 {
328  m_history.clear();
329 
330  if (isSenderOfSignal(message()))
331  saveHistory();
332 
333  q->KParts::HistoryProvider::clear(); // also emits the cleared() signal
334 }
335 
336 void KonqHistoryProviderPrivate::slotNotifyRemove(const QString& urlStr)
337 {
338  KUrl url(urlStr);
339 
340  KonqHistoryList::iterator existingEntry = q->findEntry(url);
341  if (existingEntry != m_history.end()) {
342  q->removeEntry(existingEntry);
343  if (isSenderOfSignal(message())) {
344  saveHistory();
345  }
346  }
347 }
348 
349 void KonqHistoryProviderPrivate::slotNotifyRemoveList(const QStringList& urls)
350 {
351  bool doSave = false;
352  QStringList::const_iterator it = urls.begin();
353  for (; it != urls.end(); ++it) {
354  KUrl url(*it);
355  KonqHistoryList::iterator existingEntry = m_history.findEntry(url);
356  if (existingEntry != m_history.end()) {
357  q->removeEntry(existingEntry);
358  doSave = true;
359  }
360  }
361 
362  if (doSave && isSenderOfSignal(message())) {
363  saveHistory();
364  }
365 }
366 
367 void KonqHistoryProvider::removeEntry(KonqHistoryList::iterator existingEntry)
368 {
369  const KonqHistoryEntry entry = *existingEntry; // make copy, due to erase call below
370  const QString urlString = entry.url.url();
371 
372  KParts::HistoryProvider::remove(urlString);
373 
374  d->m_history.erase(existingEntry);
375  emit entryRemoved(entry);
376 }
377 
378 int KonqHistoryProvider::maxCount() const
379 {
380  return d->m_maxCount;
381 }
382 
383 int KonqHistoryProvider::maxAge() const
384 {
385  return d->m_maxAgeDays;
386 }
387 
388 bool KonqHistoryProviderPrivate::saveHistory()
389 {
390  const QString filename = KStandardDirs::locateLocal("data", QLatin1String("konqueror/konq_history"));
391  KSaveFile file(filename);
392  if (!file.open()) {
393  kWarning() << "Can't open " << file.fileName() ;
394  return false;
395  }
396 
397  QDataStream fileStream (&file);
398  fileStream << KonqHistoryLoader::historyVersion();
399 
400  QByteArray data;
401  QDataStream stream(&data, QIODevice::WriteOnly);
402 
403  QListIterator<KonqHistoryEntry> it(m_history);
404  while (it.hasNext()) {
405  //We use QUrl for marshalling URLs in entries in the V4
406  //file format
407  it.next().save(stream, KonqHistoryEntry::NoFlags);
408  }
409 
410  quint32 crc = crc32(0, reinterpret_cast<unsigned char *>(data.data()), data.size());
411  fileStream << crc << data;
412 
413  file.finalize(); //check for error here?
414 
415  return true;
416 }
417 
418 KonqHistoryList::iterator KonqHistoryProvider::findEntry(const KUrl& url)
419 {
420  // small optimization (dict lookup) for items _not_ in our history
421  if (!KParts::HistoryProvider::contains(url.url()))
422  return d->m_history.end();
423  return d->m_history.findEntry(url);
424 }
425 
426 KonqHistoryList::const_iterator KonqHistoryProvider::constFindEntry(const KUrl& url) const
427 {
428  // small optimization (dict lookup) for items _not_ in our history
429  if (!KParts::HistoryProvider::contains(url.url()))
430  return d->m_history.constEnd();
431  return d->m_history.constFindEntry(url);
432 }
433 
434 void KonqHistoryProvider::finishAddingEntry(const KonqHistoryEntry& entry, bool isSender)
435 {
436  Q_UNUSED(entry); // this arg is used by konq's reimplementation
437  if (isSender) {
438  // we are the sender of the broadcast, so we save
439  d->saveHistory();
440  }
441 }
442 
443 #include "moc_konq_historyprovider.cpp"
444 #include "konq_historyprovider.moc"
KonqHistoryProvider::emitSetMaxCount
void emitSetMaxCount(int count)
Sets a new maximum size of history and truncates the current history if necessary.
Definition: konq_historyprovider.cpp:231
KonqHistoryLoader::historyVersion
static int historyVersion()
Definition: konq_historyloader.cpp:143
loader
static const KCatalogLoader loader("libkonq")
KonqHistoryEntry::MarshalUrlAsStrings
Definition: konq_historyentry.h:47
KonqHistoryEntry::firstVisited
QDateTime firstVisited
Definition: konq_historyentry.h:39
konq_historyprovider.h
KonqHistoryProvider::findEntry
KonqHistoryList::iterator findEntry(const KUrl &url)
a little optimization for KonqHistoryList::findEntry(), checking the dict of KParts::HistoryProvider ...
Definition: konq_historyprovider.cpp:418
KonqHistoryProvider::removeEntry
virtual void removeEntry(KonqHistoryList::iterator it)
Definition: konq_historyprovider.cpp:367
KonqHistoryProvider::maxCount
int maxCount() const
Definition: konq_historyprovider.cpp:378
KonqHistoryEntry::numberOfTimesVisited
quint32 numberOfTimesVisited
Definition: konq_historyentry.h:38
isSenderOfSignal
static bool isSenderOfSignal(const QDBusMessage &msg)
Returns whether the D-Bus call we are handling was a call from us self.
Definition: konq_historyprovider.cpp:244
KonqHistoryLoader::entries
const KonqHistoryList & entries() const
Definition: konq_historyloader.cpp:138
dbusService
static QString dbusService()
Definition: konq_historyprovider.cpp:199
KonqHistoryProvider::~KonqHistoryProvider
virtual ~KonqHistoryProvider()
Definition: konq_historyprovider.cpp:142
KonqHistoryEntry::url
KUrl url
Definition: konq_historyentry.h:35
KonqHistoryProvider::entries
const KonqHistoryList & entries() const
Definition: konq_historyprovider.cpp:147
QObject
KonqHistoryProvider
This class maintains and manages a history of all URLs visited by Konqueror.
Definition: konq_historyprovider.h:40
konq_historyloader.h
KonqHistoryProvider::constFindEntry
KonqHistoryList::const_iterator constFindEntry(const KUrl &url) const
Definition: konq_historyprovider.cpp:426
KonqHistoryEntry::save
void save(QDataStream &s, Flags flags) const
Definition: konq_historyentry.cpp:59
KonqHistoryEntry::title
QString title
Definition: konq_historyentry.h:37
KonqHistoryProvider::entryRemoved
void entryRemoved(const KonqHistoryEntry &entry)
Emitted after an entry was removed from the history Note, that this entry will be deleted immediately...
KonqHistoryEntry::load
void load(QDataStream &s, Flags flags)
Definition: konq_historyentry.cpp:43
KonqHistoryProvider::emitAddToHistory
void emitAddToHistory(const KonqHistoryEntry &entry)
Notifies all running instances about a new HistoryEntry via D-Bus.
Definition: konq_historyprovider.cpp:204
KonqHistoryProvider::KonqHistoryProvider
KonqHistoryProvider(QObject *parent=0)
Definition: konq_historyprovider.cpp:137
KonqHistoryProvider::maxAge
int maxAge() const
Definition: konq_historyprovider.cpp:383
KonqHistoryLoader::loadHistory
bool loadHistory()
Load the history.
Definition: konq_historyloader.cpp:53
KonqHistoryEntry::NoFlags
Definition: konq_historyentry.h:47
KonqHistoryList
Definition: konq_historyentry.h:62
KonqHistoryProvider::emitSetMaxAge
void emitSetMaxAge(int days)
Sets a new maximum age of history entries and removes all entries that are older than days...
Definition: konq_historyprovider.cpp:236
KonqHistoryProvider::emitRemoveFromHistory
void emitRemoveFromHistory(const KUrl &url)
Removes the history entry for url, if existent.
Definition: konq_historyprovider.cpp:216
KonqHistoryLoader
Definition: konq_historyloader.h:35
KonqHistoryProvider::finishAddingEntry
virtual void finishAddingEntry(const KonqHistoryEntry &entry, bool isSender)
Definition: konq_historyprovider.cpp:434
KonqHistoryProvider::emitRemoveListFromHistory
void emitRemoveListFromHistory(const KUrl::List &urls)
Removes the history entries for the given list of urls.
Definition: konq_historyprovider.cpp:221
KonqHistoryEntry::typedUrl
QString typedUrl
Definition: konq_historyentry.h:36
KonqHistoryProvider::loadHistory
bool loadHistory()
Load the whole history from disk.
Definition: konq_historyprovider.cpp:152
KonqHistoryEntry::lastVisited
QDateTime lastVisited
Definition: konq_historyentry.h:40
KonqHistoryProvider::emitClear
void emitClear()
Clears the history and tells all other Konqueror instances via D-Bus to do the same.
Definition: konq_historyprovider.cpp:226
KonqHistoryEntry
Definition: konq_historyentry.h:29
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:31:18 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libkonq

Skip menu "libkonq"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Applications
  •   Libraries
  •     libkonq
  • Konsole

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal