20#include "konq_historymgr.h" 
   22#include <dcopclient.h> 
   24#include <tdeapplication.h> 
   27#include <tdesimpleconfig.h> 
   28#include <tdestandarddirs.h> 
   32#include "konqbookmarkmanager.h" 
   34const TQ_UINT32 KonqHistoryManager::s_historyVersion = 3;
 
   36KonqHistoryManager::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 ( !tdeApp->dcopClient()->isAttached() )
 
   54    tdeApp->dcopClient()->attach();
 
   58    m_pCompletion = 
new TDECompletion;
 
   59    m_pCompletion->setOrder( TDECompletion::Weighted );
 
   64    connect( m_updateTimer, TQ_SIGNAL( timeout() ), TQ_SLOT( slotEmitUpdated() ));
 
   68KonqHistoryManager::~KonqHistoryManager()
 
   74bool 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    tdeApp->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 );
 
  385void 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    tdeApp->dcopClient()->send( 
"konqueror*", 
"KonqHistoryManager",
 
  401                  "notifyRemove(KURL, TQCString)", data );
 
  407    TQDataStream stream( data, IO_WriteOnly );
 
  408    stream << urls << objId();
 
  409    tdeApp->dcopClient()->send( 
"konqueror*", 
"KonqHistoryManager",
 
  410                  "notifyRemove(KURL::List, TQCString)", data );
 
  416    TQDataStream stream( data, IO_WriteOnly );
 
  418    tdeApp->dcopClient()->send( 
"konqueror*", 
"KonqHistoryManager",
 
  419                  "notifyClear(TQCString)", data );
 
  425    TQDataStream stream( data, IO_WriteOnly );
 
  426    stream << count << objId();
 
  427    tdeApp->dcopClient()->send( 
"konqueror*", 
"KonqHistoryManager",
 
  428                  "notifyMaxCount(TQ_UINT32, TQCString)", data );
 
  434    TQDataStream stream( data, IO_WriteOnly );
 
  435    stream << days << objId();
 
  436    tdeApp->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())
 
  590bool KonqHistoryManager::loadFallback()
 
  592    TQString file = locateLocal( 
"config", TQString::fromLatin1(
"konq_history"));
 
  593    if ( file.isEmpty() )
 
  596    KonqHistoryEntry *entry;
 
  597    TDESimpleConfig 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() );
 
  623KonqHistoryEntry * 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();
 
  655KonqHistoryEntry * 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() );
 
  669void KonqHistoryManager::slotEmitUpdated()
 
  678    KonqHistoryIterator it ( m_history );
 
  679    for ( ; it.current(); ++it )
 
  680        list.append( it.current()->url.url() );
 
  685void KonqHistoryManager::addToCompletion( 
const TQString& url, 
const TQString& typedURL, 
 
  686                                          int numberOfTimesVisited )
 
  688    m_pCompletion->addItem( url, numberOfTimesVisited );
 
  690    m_pCompletion->addItem( typedURL, numberOfTimesVisited +10 );
 
  693void KonqHistoryManager::removeFromCompletion( 
const TQString& url, 
const TQString& typedURL )
 
  695    m_pCompletion->removeItem( url );
 
  696    m_pCompletion->removeItem( typedURL );
 
  702KonqHistoryEntry * KonqHistoryList::findEntry( 
const KURL& url )
 
  705    KonqHistoryEntry *entry = last();
 
  707    if ( entry->url == url )
 
  717int 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 )
 
  731using 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.