20 #include "konq_historymgr.h"
22 #include <dcopclient.h>
24 #include <tdeapplication.h>
26 #include <ksavefile.h>
27 #include <ksimpleconfig.h>
28 #include <kstandarddirs.h>
32 #include "konqbookmarkmanager.h"
34 const TQ_UINT32 KonqHistoryManager::s_historyVersion = 3;
36 KonqHistoryManager::KonqHistoryManager( TQObject *parent,
const char *name )
37 : KParts::HistoryProvider( parent, name ),
40 m_updateTimer =
new TQTimer(
this );
43 TDEConfig *config = TDEGlobal::config();
44 TDEConfigGroupSaver cs( config,
"HistorySettings" );
45 m_maxCount = config->readNumEntry(
"Maximum of History entries", 500 );
46 m_maxCount = TQMAX( 1, m_maxCount );
47 m_maxAgeDays = config->readNumEntry(
"Maximum age of History entries", 90);
49 m_history.setAutoDelete(
true );
50 m_filename = locateLocal(
"data",
51 TQString::fromLatin1(
"konqueror/konq_history" ));
53 if ( !kapp->dcopClient()->isAttached() )
54 kapp->dcopClient()->attach();
58 m_pCompletion =
new TDECompletion;
59 m_pCompletion->setOrder( TDECompletion::Weighted );
64 connect( m_updateTimer, TQ_SIGNAL( timeout() ), TQ_SLOT( slotEmitUpdated() ));
68 KonqHistoryManager::~KonqHistoryManager()
74 bool KonqHistoryManager::isSenderOfBroadcast()
76 DCOPClient *dc = callingDcopClient();
77 return !dc || (dc->senderId() == dc->appId());
85 m_pCompletion->clear();
87 TQFile file( m_filename );
88 if ( !file.open( IO_ReadOnly ) ) {
90 kdWarning() <<
"Can't open " << file.name() << endl;
93 bool ret = loadFallback();
98 TQDataStream fileStream( &file );
102 TQDataStream crcStream( data, IO_ReadOnly );
104 if ( !fileStream.atEnd() ) {
106 fileStream >> version;
108 TQDataStream *stream = &fileStream;
110 bool crcChecked =
false;
113 if ( version == 2 || version == 3) {
116 fileStream >> crc >> data;
117 crcOk = crc32( 0,
reinterpret_cast<unsigned char *
>( data.data() ), data.size() ) == crc;
124 KonqHistoryEntry::marshalURLAsStrings =
false;
127 if ( version != 0 && version < 3 )
130 KonqHistoryEntry::marshalURLAsStrings =
true;
143 if ( s_historyVersion != version || ( crcChecked && !crcOk ) ) {
144 kdWarning() <<
"The history version doesn't match, aborting loading" << endl;
151 while ( !stream->atEnd() ) {
152 KonqHistoryEntry *entry =
new KonqHistoryEntry;
153 TQ_CHECK_PTR( entry );
156 m_history.append( entry );
157 TQString urlString2 = entry->url.prettyURL();
159 addToCompletion( urlString2, entry->typedURL, entry->numberOfTimesVisited );
162 TQString urlString = entry->url.url();
163 KParts::HistoryProvider::insert( urlString );
167 if ( urlString != urlString2 )
168 KParts::HistoryProvider::insert( urlString2 );
171 kdDebug(1203) <<
"## loaded: " << m_history.count() <<
" entries." << endl;
182 KonqHistoryEntry::marshalURLAsStrings =
true;
202 KSaveFile file( m_filename );
203 if ( file.status() != 0 ) {
204 kdWarning() <<
"Can't open " << file.name() << endl;
208 TQDataStream *fileStream = file.dataStream();
209 *fileStream << s_historyVersion;
212 TQDataStream stream( data, IO_WriteOnly );
216 KonqHistoryEntry::marshalURLAsStrings =
false;
217 TQPtrListIterator<KonqHistoryEntry> it( m_history );
218 KonqHistoryEntry *entry;
219 while ( (entry = it.current()) ) {
225 KonqHistoryEntry::marshalURLAsStrings =
true;
227 TQ_UINT32 crc = crc32( 0,
reinterpret_cast<unsigned char *
>( data.data() ), data.size() );
228 *fileStream << crc << data;
238 KonqHistoryEntry *entry = m_history.getFirst();
240 while ( m_history.count() > m_maxCount ||
isExpired( entry ) ) {
241 removeFromCompletion( entry->url.prettyURL(), entry->typedURL );
243 TQString urlString = entry->url.url();
244 KParts::HistoryProvider::remove( urlString );
246 addToUpdateList( urlString );
249 m_history.removeFirst();
251 entry = m_history.getFirst();
257 const TQString& title )
263 const TQString& typedURL,
264 const TQString& title )
271 const TQString& typedURL,
272 const TQString& title )
274 kdDebug(1203) <<
"## addToHistory: " << _url.prettyURL() <<
" Typed URL: " << typedURL <<
", Title: " << title << endl;
280 if ( _url.path().isEmpty() && _url.protocol().startsWith(
"http") )
284 bool hasPass = url.hasPass();
285 url.setPass( TQString::null );
286 url.setHost( url.host().lower() );
287 KonqHistoryEntry entry;
288 TQString u = url.prettyURL();
290 if ( (u != typedURL) && !hasPass )
291 entry.typedURL = typedURL;
296 if ( !pending && u != title )
298 entry.firstVisited = TQDateTime::currentDateTime();
299 entry.lastVisited = entry.firstVisited;
303 TQMapIterator<TQString,KonqHistoryEntry*> it = m_pending.find( u );
304 if ( it != m_pending.end() ) {
306 m_pending.remove( it );
310 if ( it != m_pending.end() ) {
314 entry.numberOfTimesVisited = 0;
322 KonqHistoryEntry *oldEntry = findEntry( url );
323 m_pending.insert( u, oldEntry ?
324 new KonqHistoryEntry( *oldEntry ) : 0L );
339 if ( !
filterOut( u ) || u.protocol() ==
"about" ) {
343 KonqHistoryEntry entry;
345 entry.firstVisited = TQDateTime::currentDateTime();
346 entry.lastVisited = entry.firstVisited;
353 TQDataStream stream( data, IO_WriteOnly );
354 stream << entry << objId();
356 if ( data.size() > 4096 )
358 kapp->dcopClient()->send(
"konqueror*",
"KonqHistoryManager",
359 "notifyHistoryEntry(KonqHistoryEntry, TQCString)",
368 if ( url.isLocalFile() )
371 TQMapIterator<TQString,KonqHistoryEntry*> it = m_pending.find( url.prettyURL() );
372 if ( it != m_pending.end() ) {
373 KonqHistoryEntry *oldEntry = it.data();
380 m_pending.remove( it );
385 void KonqHistoryManager::clearPending()
387 TQMapIterator<TQString,KonqHistoryEntry*> it = m_pending.begin();
388 while ( it != m_pending.end() ) {
398 TQDataStream stream( data, IO_WriteOnly );
399 stream << url << objId();
400 kapp->dcopClient()->send(
"konqueror*",
"KonqHistoryManager",
401 "notifyRemove(KURL, TQCString)", data );
407 TQDataStream stream( data, IO_WriteOnly );
408 stream << urls << objId();
409 kapp->dcopClient()->send(
"konqueror*",
"KonqHistoryManager",
410 "notifyRemove(KURL::List, TQCString)", data );
416 TQDataStream stream( data, IO_WriteOnly );
418 kapp->dcopClient()->send(
"konqueror*",
"KonqHistoryManager",
419 "notifyClear(TQCString)", data );
425 TQDataStream stream( data, IO_WriteOnly );
426 stream << count << objId();
427 kapp->dcopClient()->send(
"konqueror*",
"KonqHistoryManager",
428 "notifyMaxCount(TQ_UINT32, TQCString)", data );
434 TQDataStream stream( data, IO_WriteOnly );
435 stream << days << objId();
436 kapp->dcopClient()->send(
"konqueror*",
"KonqHistoryManager",
437 "notifyMaxAge(TQ_UINT32, TQCString)", data );
448 KonqHistoryEntry *entry = findEntry( e.url );
449 TQString urlString = e.url.url();
452 entry =
new KonqHistoryEntry;
454 entry->firstVisited = e.firstVisited;
455 entry->numberOfTimesVisited = 0;
456 m_history.append( entry );
457 KParts::HistoryProvider::insert( urlString );
460 if ( !e.typedURL.isEmpty() )
461 entry->typedURL = e.typedURL;
462 if ( !e.title.isEmpty() )
463 entry->title = e.title;
464 entry->numberOfTimesVisited += e.numberOfTimesVisited;
465 entry->lastVisited = e.lastVisited;
467 addToCompletion( entry->url.prettyURL(), entry->typedURL );
476 bool updated = KonqBookmarkManager::self()->updateAccessMetadata( urlString );
478 if ( isSenderOfBroadcast() ) {
483 KonqBookmarkManager::self()->save();
486 addToUpdateList( urlString );
496 TDEConfig *config = TDEGlobal::config();
497 TDEConfigGroupSaver cs( config,
"HistorySettings" );
498 config->writeEntry(
"Maximum of History entries", m_maxCount );
500 if ( isSenderOfBroadcast() ) {
512 TDEConfig *config = TDEGlobal::config();
513 TDEConfigGroupSaver cs( config,
"HistorySettings" );
514 config->writeEntry(
"Maximum age of History entries", m_maxAgeDays );
516 if ( isSenderOfBroadcast() ) {
526 m_pCompletion->clear();
528 if ( isSenderOfBroadcast() )
531 KParts::HistoryProvider::clear();
536 kdDebug(1203) <<
"#### Broadcast: remove entry:: " << url.prettyURL() << endl;
539 KonqHistoryEntry *entry = m_history.findEntry( url );
542 removeFromCompletion( entry->url.prettyURL(), entry->typedURL );
544 TQString urlString = entry->url.url();
545 KParts::HistoryProvider::remove( urlString );
547 addToUpdateList( urlString );
553 if ( isSenderOfBroadcast() )
560 kdDebug(1203) <<
"#### Broadcast: removing list!" << endl;
563 KURL::List::Iterator it = urls.begin();
564 while ( it != urls.end() ) {
565 KonqHistoryEntry *entry = m_history.findEntry( *it );
568 removeFromCompletion( entry->url.prettyURL(), entry->typedURL );
570 TQString urlString = entry->url.url();
571 KParts::HistoryProvider::remove( urlString );
573 addToUpdateList( urlString );
584 if (doSave && isSenderOfBroadcast())
590 bool KonqHistoryManager::loadFallback()
592 TQString file = locateLocal(
"config", TQString::fromLatin1(
"konq_history"));
593 if ( file.isEmpty() )
596 KonqHistoryEntry *entry;
597 KSimpleConfig config( file );
598 config.setGroup(
"History");
599 TQStringList items = config.readListEntry(
"CompletionItems" );
600 TQStringList::Iterator it = items.begin();
602 while ( it != items.end() ) {
603 entry = createFallbackEntry( *it );
605 m_history.append( entry );
606 addToCompletion( entry->url.prettyURL(), TQString::null, entry->numberOfTimesVisited );
608 KParts::HistoryProvider::insert( entry->url.url() );
623 KonqHistoryEntry * KonqHistoryManager::createFallbackEntry(
const TQString& item)
const
626 uint len = item.length();
630 int index = item.findRev(
':');
633 weight = item.mid( index + 1 ).toUInt( &ok );
641 KonqHistoryEntry *entry = 0L;
642 KURL u( item.left( len ));
644 entry =
new KonqHistoryEntry;
647 entry->numberOfTimesVisited = weight;
649 entry->lastVisited = TQDateTime::currentDateTime();
655 KonqHistoryEntry * KonqHistoryManager::findEntry(
const KURL& url )
658 if ( !KParts::HistoryProvider::contains( url.url() ) )
661 return m_history.findEntry( url );
666 return ( url.isLocalFile() || url.host().isEmpty() );
669 void KonqHistoryManager::slotEmitUpdated()
678 KonqHistoryIterator it ( m_history );
679 for ( ; it.current(); ++it )
680 list.append( it.current()->url.url() );
685 void KonqHistoryManager::addToCompletion(
const TQString& url,
const TQString& typedURL,
686 int numberOfTimesVisited )
688 m_pCompletion->addItem( url, numberOfTimesVisited );
690 m_pCompletion->addItem( typedURL, numberOfTimesVisited +10 );
693 void KonqHistoryManager::removeFromCompletion(
const TQString& url,
const TQString& typedURL )
695 m_pCompletion->removeItem( url );
696 m_pCompletion->removeItem( typedURL );
702 KonqHistoryEntry * KonqHistoryList::findEntry(
const KURL& url )
705 KonqHistoryEntry *entry = last();
707 if ( entry->url == url )
717 int KonqHistoryList::compareItems( TQPtrCollection::Item item1,
718 TQPtrCollection::Item item2 )
720 KonqHistoryEntry *entry1 =
static_cast<KonqHistoryEntry *
>( item1 );
721 KonqHistoryEntry *entry2 =
static_cast<KonqHistoryEntry *
>( item2 );
723 if ( entry1->lastVisited > entry2->lastVisited )
725 else if ( entry1->lastVisited < entry2->lastVisited )
731 using namespace KParts;
733 #include "konq_historymgr.moc"
DCOP Methods for KonqHistoryManager.
void entryAdded(const KonqHistoryEntry *entry)
Emitted after a new entry was added.
void adjustSize()
Resizes the history list to contain less or equal than m_maxCount entries.
virtual void notifyClear(TQCString saveId)
Clears the history completely.
virtual bool filterOut(const KURL &url)
void emitAddToHistory(const KonqHistoryEntry &entry)
Notifes all running instances about a new HistoryEntry via DCOP.
void removePending(const KURL &url)
Removes a pending url from the history, e.g.
void addToHistory(bool pending, const KURL &url, const TQString &typedURL=TQString::null, const TQString &title=TQString::null)
Does the work for addPending() and confirmPending().
virtual TQStringList allURLs() const
virtual void notifyHistoryEntry(KonqHistoryEntry e, TQCString saveId)
Every konqueror instance broadcasts new history entries to the other konqueror instances.
bool isExpired(KonqHistoryEntry *entry)
virtual void notifyMaxCount(TQ_UINT32 count, TQCString saveId)
Called when the configuration of the maximum count changed.
virtual void notifyRemove(KURL url, TQCString saveId)
Notifes about a url that has to be removed from the history.
void loadingFinished()
Emitted after the entire history was loaded from disk.
TQStringList m_updateURLs
The list of urls that is going to be emitted in slotEmitUpdated.
void confirmPending(const KURL &url, const TQString &typedURL=TQString::null, const TQString &title=TQString::null)
Confirms and updates the entry for url.
void entryRemoved(const KonqHistoryEntry *entry)
Emitted after an entry was removed from the history Note, that this entry will be deleted immediately...
bool loadHistory()
Loads the history and fills the completion object.
virtual void insert(const TQString &)
Reimplemented in such a way that all URLs that would be filtered out normally (see filterOut()) will ...
void emitSetMaxAge(TQ_UINT32 days)
Sets a new maximum age of history entries and removes all entries that are older than days.
bool saveHistory()
Saves the entire history.
void addPending(const KURL &url, const TQString &typedURL=TQString::null, const TQString &title=TQString::null)
Adds a pending entry to the history.
void emitRemoveFromHistory(const KURL &url)
Removes the history entry for url, if existant.
void emitClear()
Clears the history and tells all other Konqueror instances via DCOP to do the same.
void emitSetMaxCount(TQ_UINT32 count)
Sets a new maximum size of history and truncates the current history if necessary.
virtual void notifyMaxAge(TQ_UINT32 days, TQCString saveId)
Called when the configuration of the maximum age of history-entries changed.