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, TQT_SIGNAL( timeout() ), TQT_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();
167 if ( urlString != 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 );
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 );
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"