diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 4aed2c8219774f5d797760606b8489a92ddc5163 (patch) | |
tree | 3f8c130f7d269626bf6a9447407ef6c35954426a /konqueror/sidebar/trees/dirtree_module/dirtree_module.cpp | |
download | tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.tar.gz tdebase-4aed2c8219774f5d797760606b8489a92ddc5163.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'konqueror/sidebar/trees/dirtree_module/dirtree_module.cpp')
-rw-r--r-- | konqueror/sidebar/trees/dirtree_module/dirtree_module.cpp | 649 |
1 files changed, 649 insertions, 0 deletions
diff --git a/konqueror/sidebar/trees/dirtree_module/dirtree_module.cpp b/konqueror/sidebar/trees/dirtree_module/dirtree_module.cpp new file mode 100644 index 000000000..725927362 --- /dev/null +++ b/konqueror/sidebar/trees/dirtree_module/dirtree_module.cpp @@ -0,0 +1,649 @@ +/* This file is part of the KDE project + Copyright (C) 2000 David Faure <[email protected]> + 2002 Michael Brade <[email protected]> + Copyright (C) 2003 Waldo Bastian <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "dirtree_module.h" +#include "dirtree_item.h" +#include <kdebug.h> +#include <kprotocolinfo.h> +#include <kdesktopfile.h> +#include <kmessagebox.h> +#include <kiconloader.h> +#include <kdirlister.h> +#include "konqsidebariface_p.h" + + +KonqSidebarDirTreeModule::KonqSidebarDirTreeModule( KonqSidebarTree * parentTree , bool showHidden) + : KonqSidebarTreeModule( parentTree, showHidden ), m_dirLister(0L), m_topLevelItem(0L) +{ + bool universalMode=false; + /* Doesn't work reliable :-( + + KonqSidebarPlugin * plugin = parentTree->part(); + // KonqSidebarPlugin::universalMode() is protected :-| + if ( plugin->parent() ) { + KonqSidebarIface * ksi = static_cast<KonqSidebarIface*>( plugin->parent()->qt_cast( "KonqSidebarIface" ) ); + universalMode = ksi ? ksi->universalMode() : false; + } */ + + KConfig * config = new KConfig( universalMode ? "konqsidebartng_kicker.rc" : "konqsidebartng.rc" ); + config->setGroup(""); + m_showArchivesAsFolders = config->readBoolEntry("ShowArchivesAsFolders",true); + delete config; +} + +KonqSidebarDirTreeModule::~KonqSidebarDirTreeModule() +{ + // KDirLister may still emit canceled while being deleted. + if (m_dirLister) + { + disconnect( m_dirLister, SIGNAL( canceled( const KURL & ) ), + this, SLOT( slotListingStopped( const KURL & ) ) ); + delete m_dirLister; + } +} + +KURL::List KonqSidebarDirTreeModule::selectedUrls() +{ + KURL::List lst; + KonqSidebarDirTreeItem *selection = static_cast<KonqSidebarDirTreeItem *>( m_pTree->selectedItem() ); + if( !selection ) + { + kdError() << "KonqSidebarDirTreeModule::selectedUrls: no selection!" << endl; + return lst; + } + lst.append(selection->fileItem()->url()); + return lst; +} + +void KonqSidebarDirTreeModule::addTopLevelItem( KonqSidebarTreeTopLevelItem * item ) +{ + if(m_topLevelItem) // We can handle only one at a time ! + kdError() << "KonqSidebarDirTreeModule::addTopLevelItem: Impossible, we can have only one toplevel item !" << endl; + + KDesktopFile cfg( item->path(), true ); + cfg.setDollarExpansion(true); + + KURL targetURL; + targetURL.setPath(item->path()); + + if ( cfg.hasLinkType() ) + { + targetURL = cfg.readURL(); + // some services might want to make their URL configurable in kcontrol + QString configured = cfg.readEntry("X-KDE-ConfiguredURL"); + if (!configured.isEmpty()) { + QStringList list = QStringList::split(':', configured); + KConfig config(list[0]); + if (list[1] != "noGroup") config.setGroup(list[1]); + QString conf_url = config.readEntry(list[2]); + if (!conf_url.isEmpty()) { + targetURL = conf_url; + } + } + } + else if ( cfg.hasDeviceType() ) + { + // Determine the mountpoint + QString mp = cfg.readEntry("MountPoint"); + if ( mp.isEmpty() ) + return; + + targetURL.setPath(mp); + } + else + return; + + bool bListable = KProtocolInfo::supportsListing( targetURL ); + //kdDebug(1201) << targetURL.prettyURL() << " listable : " << bListable << endl; + + if ( !bListable ) + { + item->setExpandable( false ); + item->setListable( false ); + } + + item->setExternalURL( targetURL ); + addSubDir( item ); + + m_topLevelItem = item; +} + +void KonqSidebarDirTreeModule::openTopLevelItem( KonqSidebarTreeTopLevelItem * item ) +{ + if ( !item->childCount() && item->isListable() ) + openSubFolder( item ); +} + +void KonqSidebarDirTreeModule::addSubDir( KonqSidebarTreeItem *item ) +{ + QString id = item->externalURL().url(-1); + kdDebug(1201) << this << " KonqSidebarDirTreeModule::addSubDir " << id << endl; + m_dictSubDirs.insert(id, item ); + + KonqSidebarDirTreeItem *ditem = dynamic_cast<KonqSidebarDirTreeItem*>(item); + if (ditem) + m_ptrdictSubDirs.insert(ditem->fileItem(), item); +} + +// Remove <key, item> from dict, taking into account that there maybe +// other items with the same key. +static void remove(QDict<KonqSidebarTreeItem> &dict, const QString &key, KonqSidebarTreeItem *item) +{ + QPtrList<KonqSidebarTreeItem> *otherItems = 0; + while(true) { + KonqSidebarTreeItem *takeItem = dict.take(key); + if (!takeItem || (takeItem == item)) + { + if (!otherItems) + return; + + // Insert the otherItems back in + for(KonqSidebarTreeItem *otherItem; (otherItem = otherItems->take(0));) + { + dict.insert(key, otherItem); + } + delete otherItems; + return; + } + // Not the item we are looking for + if (!otherItems) + otherItems = new QPtrList<KonqSidebarTreeItem>(); + + otherItems->prepend(takeItem); + } +} + +// Looks up key in dict and returns it in item, if there are multiple items +// with the same key, additional items are returned in itemList which should +// be deleted by the caller. +static void lookupItems(QDict<KonqSidebarTreeItem> &dict, const QString &key, KonqSidebarTreeItem *&item, QPtrList<KonqSidebarTreeItem> *&itemList) +{ + itemList = 0; + item = dict.take(key); + if (!item) + return; + + while(true) + { + KonqSidebarTreeItem *takeItem = dict.take(key); + if (!takeItem) + { + // + // Insert itemList back in + if (itemList) + { + for(KonqSidebarTreeItem *otherItem = itemList->first(); otherItem; otherItem = itemList->next()) + dict.insert(key, otherItem); + } + dict.insert(key, item); + return; + } + if (!itemList) + itemList = new QPtrList<KonqSidebarTreeItem>(); + + itemList->prepend(takeItem); + } +} + +// Remove <key, item> from dict, taking into account that there maybe +// other items with the same key. +static void remove(QPtrDict<KonqSidebarTreeItem> &dict, void *key, KonqSidebarTreeItem *item) +{ + QPtrList<KonqSidebarTreeItem> *otherItems = 0; + while(true) { + KonqSidebarTreeItem *takeItem = dict.take(key); + if (!takeItem || (takeItem == item)) + { + if (!otherItems) + return; + + // Insert the otherItems back in + for(KonqSidebarTreeItem *otherItem; (otherItem = otherItems->take(0));) + { + dict.insert(key, otherItem); + } + delete otherItems; + return; + } + // Not the item we are looking for + if (!otherItems) + otherItems = new QPtrList<KonqSidebarTreeItem>(); + + otherItems->prepend(takeItem); + } +} + +// Looks up key in dict and returns it in item, if there are multiple items +// with the same key, additional items are returned in itemList which should +// be deleted by the caller. +static void lookupItems(QPtrDict<KonqSidebarTreeItem> &dict, void *key, KonqSidebarTreeItem *&item, QPtrList<KonqSidebarTreeItem> *&itemList) +{ + itemList = 0; + item = dict.take(key); + if (!item) + return; + + while(true) + { + KonqSidebarTreeItem *takeItem = dict.take(key); + if (!takeItem) + { + // + // Insert itemList back in + if (itemList) + { + for(KonqSidebarTreeItem *otherItem = itemList->first(); otherItem; otherItem = itemList->next()) + dict.insert(key, otherItem); + } + dict.insert(key, item); + return; + } + if (!itemList) + itemList = new QPtrList<KonqSidebarTreeItem>(); + + itemList->prepend(takeItem); + } +} + + +void KonqSidebarDirTreeModule::removeSubDir( KonqSidebarTreeItem *item, bool childrenOnly ) +{ + kdDebug(1201) << this << " KonqSidebarDirTreeModule::removeSubDir item=" << item << endl; + if ( item->firstChild() ) + { + KonqSidebarTreeItem * it = static_cast<KonqSidebarTreeItem *>(item->firstChild()); + KonqSidebarTreeItem * next = 0L; + while ( it ) { + next = static_cast<KonqSidebarTreeItem *>(it->nextSibling()); + removeSubDir( it ); + delete it; + it = next; + } + } + + if ( !childrenOnly ) + { + QString id = item->externalURL().url(-1); + remove(m_dictSubDirs, id, item); + while (!(item->alias.isEmpty())) + { + remove(m_dictSubDirs, item->alias.front(), item); + item->alias.pop_front(); + } + + KonqSidebarDirTreeItem *ditem = dynamic_cast<KonqSidebarDirTreeItem*>(item); + if (ditem) + remove(m_ptrdictSubDirs, ditem->fileItem(), item); + } +} + + +void KonqSidebarDirTreeModule::openSubFolder( KonqSidebarTreeItem *item ) +{ + kdDebug(1201) << this << " openSubFolder( " << item->externalURL().prettyURL() << " )" << endl; + + if ( !m_dirLister ) // created on demand + { + m_dirLister = new KDirLister( true ); + //m_dirLister->setDirOnlyMode( true ); +// QStringList mimetypes; +// mimetypes<<QString("inode/directory"); +// m_dirLister->setMimeFilter(mimetypes); + + connect( m_dirLister, SIGNAL( newItems( const KFileItemList & ) ), + this, SLOT( slotNewItems( const KFileItemList & ) ) ); + connect( m_dirLister, SIGNAL( refreshItems( const KFileItemList & ) ), + this, SLOT( slotRefreshItems( const KFileItemList & ) ) ); + connect( m_dirLister, SIGNAL( deleteItem( KFileItem * ) ), + this, SLOT( slotDeleteItem( KFileItem * ) ) ); + connect( m_dirLister, SIGNAL( completed( const KURL & ) ), + this, SLOT( slotListingStopped( const KURL & ) ) ); + connect( m_dirLister, SIGNAL( canceled( const KURL & ) ), + this, SLOT( slotListingStopped( const KURL & ) ) ); + connect( m_dirLister, SIGNAL( redirection( const KURL &, const KURL & ) ), + this, SLOT( slotRedirection( const KURL &, const KURL & ) ) ); + } + + + if ( !item->isTopLevelItem() && + static_cast<KonqSidebarDirTreeItem *>(item)->hasStandardIcon() ) + { + int size = KGlobal::iconLoader()->currentSize( KIcon::Small ); + QPixmap pix = DesktopIcon( "folder_open", size ); + m_pTree->startAnimation( item, "kde", 6, &pix ); + } + else + m_pTree->startAnimation( item ); + + listDirectory( item ); +} + +void KonqSidebarDirTreeModule::listDirectory( KonqSidebarTreeItem *item ) +{ + // This causes a reparsing, but gets rid of the trailing slash + QString strUrl = item->externalURL().url(-1); + KURL url( strUrl ); + + QPtrList<KonqSidebarTreeItem> *itemList; + KonqSidebarTreeItem * openItem; + lookupItems(m_dictSubDirs, strUrl, openItem, itemList); + + while(openItem) + { + if (openItem->childCount()) + break; + + openItem = itemList ? itemList->take(0) : 0; + } + delete itemList; + + if (openItem) + { + // We have this directory listed already, just copy the entries as we + // can't use the dirlister, it would invalidate the old entries + int size = KGlobal::iconLoader()->currentSize( KIcon::Small ); + KonqSidebarTreeItem * parentItem = item; + KonqSidebarDirTreeItem *oldItem = static_cast<KonqSidebarDirTreeItem *> (openItem->firstChild()); + while(oldItem) + { + KFileItem * fileItem = oldItem->fileItem(); + if (! fileItem->isDir() ) + { + KMimeType::Ptr ptr; + + if ( fileItem->url().isLocalFile() && (((ptr=fileItem->determineMimeType())!=0) && (ptr->is("inode/directory") || m_showArchivesAsFolders) && ((!ptr->property("X-KDE-LocalProtocol").toString().isEmpty()) ))) { + kdDebug()<<"Something not really a directory"<<endl; + } else { +// kdError() << "Item " << fileItem->url().prettyURL() << " is not a directory!" << endl; + continue; + } + } + + KonqSidebarDirTreeItem *dirTreeItem = new KonqSidebarDirTreeItem( parentItem, m_topLevelItem, fileItem ); + dirTreeItem->setPixmap( 0, fileItem->pixmap( size ) ); + dirTreeItem->setText( 0, KIO::decodeFileName( fileItem->name() ) ); + + oldItem = static_cast<KonqSidebarDirTreeItem *> (oldItem->nextSibling()); + } + m_pTree->stopAnimation( item ); + + return; + } + + m_dirLister->setShowingDotFiles( showHidden()); + + if (tree()->isOpeningFirstChild()) m_dirLister->setAutoErrorHandlingEnabled(false,0); + else m_dirLister->setAutoErrorHandlingEnabled(true,tree()); + + m_dirLister->openURL( url, true /*keep*/ ); +} + +void KonqSidebarDirTreeModule::slotNewItems( const KFileItemList& entries ) +{ + kdDebug(1201) << this << " KonqSidebarDirTreeModule::slotNewItems " << entries.count() << endl; + + Q_ASSERT(entries.count()); + KFileItem * firstItem = const_cast<KFileItemList&>(entries).first(); // qlist sucks for constness + + // Find parent item - it's the same for all the items + KURL dir( firstItem->url().url(-1) ); + dir.setFileName( "" ); + kdDebug(1201) << this << " KonqSidebarDirTreeModule::slotNewItems dir=" << dir.url(-1) << endl; + + QPtrList<KonqSidebarTreeItem> *parentItemList; + KonqSidebarTreeItem * parentItem; + lookupItems(m_dictSubDirs, dir.url(-1), parentItem, parentItemList); + + if ( !parentItem ) // hack for dnssd://domain/type/service listed in dnssd:/type/ dir + { + dir.setHost( QString::null ); + lookupItems( m_dictSubDirs, dir.url(-1), parentItem, parentItemList ); + } + + if( !parentItem ) + { + KMessageBox::error( tree(), i18n("Cannot find parent item %1 in the tree. Internal error.").arg( dir.url(-1) ) ); + return; + } + + kdDebug()<<"number of additional parent items:"<< (parentItemList?parentItemList->count():0)<<endl; + int size = KGlobal::iconLoader()->currentSize( KIcon::Small ); + do + { + kdDebug()<<"Parent Item URL:"<<parentItem->externalURL()<<endl; + QPtrListIterator<KFileItem> kit ( entries ); + for( ; kit.current(); ++kit ) + { + KFileItem * fileItem = *kit; + + if (! fileItem->isDir() ) + { + KMimeType::Ptr ptr; + + if ( fileItem->url().isLocalFile() && (( (ptr=fileItem->determineMimeType())!=0) && (ptr->is("inode/directory") || m_showArchivesAsFolders) && ((!ptr->property("X-KDE-LocalProtocol").toString().isEmpty()) ))) { + kdDebug()<<"Something really a directory"<<endl; + } else { + //kdError() << "Item " << fileItem->url().prettyURL() << " is not a directory!" << endl; + continue; + } + } + + KonqSidebarDirTreeItem *dirTreeItem = new KonqSidebarDirTreeItem( parentItem, m_topLevelItem, fileItem ); + dirTreeItem->setPixmap( 0, fileItem->pixmap( size ) ); + dirTreeItem->setText( 0, KIO::decodeFileName( fileItem->name() ) ); + } + + } while ((parentItem = parentItemList ? parentItemList->take(0) : 0)); + delete parentItemList; +} + +void KonqSidebarDirTreeModule::slotRefreshItems( const KFileItemList &entries ) +{ + int size = KGlobal::iconLoader()->currentSize( KIcon::Small ); + + QPtrListIterator<KFileItem> kit ( entries ); + kdDebug(1201) << "KonqSidebarDirTreeModule::slotRefreshItems " << entries.count() << " entries. First: " << kit.current()->url().url() << endl; + for( ; kit.current(); ++kit ) + { + KFileItem *fileItem = kit.current(); + + QPtrList<KonqSidebarTreeItem> *itemList; + KonqSidebarTreeItem * item; + lookupItems(m_ptrdictSubDirs, fileItem, item, itemList); + + if (!item) + { + if ( fileItem->isDir() ) // don't warn for files + kdWarning(1201) << "KonqSidebarDirTreeModule::slotRefreshItems can't find old entry for " << kit.current()->url().url(-1) << endl; + continue; + } + + do + { + if ( item->isTopLevelItem() ) // we only have dirs and one toplevel item in the dict + { + kdWarning(1201) << "KonqSidebarDirTreeModule::slotRefreshItems entry for " << kit.current()->url().url(-1) << " matches against toplevel." << endl; + break; + } + + KonqSidebarDirTreeItem * dirTreeItem = static_cast<KonqSidebarDirTreeItem *>(item); + // Item renamed ? + if ( dirTreeItem->id != fileItem->url().url( -1 ) ) + { + // We need to update the URL in m_dictSubDirs, and to get rid of the child items, so remove and add. + // Then remove + delete + removeSubDir( dirTreeItem, true /*children only*/ ); + remove(m_dictSubDirs, dirTreeItem->id, dirTreeItem); + + dirTreeItem->reset(); // Reset id + dirTreeItem->setPixmap( 0, fileItem->pixmap( size ) ); + dirTreeItem->setText( 0, KIO::decodeFileName( fileItem->name() ) ); + + // Make sure the item doesn't get inserted twice! + // dirTreeItem->id points to the new name + remove(m_dictSubDirs, dirTreeItem->id, dirTreeItem); + m_dictSubDirs.insert(dirTreeItem->id, dirTreeItem); + } + else + { + dirTreeItem->setPixmap( 0, fileItem->pixmap( size ) ); + dirTreeItem->setText( 0, KIO::decodeFileName( fileItem->name() ) ); + } + + } while ((item = itemList ? itemList->take(0) : 0)); + delete itemList; + } +} + +void KonqSidebarDirTreeModule::slotDeleteItem( KFileItem *fileItem ) +{ + kdDebug(1201) << "KonqSidebarDirTreeModule::slotDeleteItem( " << fileItem->url().url(-1) << " )" << endl; + + // All items are in m_ptrdictSubDirs, so look it up fast + QPtrList<KonqSidebarTreeItem> *itemList; + KonqSidebarTreeItem * item; + lookupItems(m_ptrdictSubDirs, fileItem, item, itemList); + while(item) + { + removeSubDir( item ); + delete item; + + item = itemList ? itemList->take(0) : 0; + } + delete itemList; +} + +void KonqSidebarDirTreeModule::slotRedirection( const KURL & oldUrl, const KURL & newUrl ) +{ + kdDebug(1201) << "******************************KonqSidebarDirTreeModule::slotRedirection(" << newUrl.prettyURL() << ")" << endl; + + QString oldUrlStr = oldUrl.url(-1); + QString newUrlStr = newUrl.url(-1); + + QPtrList<KonqSidebarTreeItem> *itemList; + KonqSidebarTreeItem * item; + lookupItems(m_dictSubDirs, oldUrlStr, item, itemList); + + if (!item) + { + kdWarning(1201) << "NOT FOUND oldUrl=" << oldUrlStr << endl; + return; + } + + do + { + if (item->alias.contains(newUrlStr)) continue; + kdDebug()<<"Redirectiong element"<<endl; + // We need to update the URL in m_dictSubDirs + m_dictSubDirs.insert( newUrlStr, item ); + item->alias << newUrlStr; + + kdDebug(1201) << "Updating url of " << item << " to " << newUrlStr << endl; + + } while ((item = itemList ? itemList->take(0) : 0)); + delete itemList; +} + +void KonqSidebarDirTreeModule::slotListingStopped( const KURL & url ) +{ + kdDebug(1201) << "KonqSidebarDirTree::slotListingStopped " << url.url(-1) << endl; + + QPtrList<KonqSidebarTreeItem> *itemList; + KonqSidebarTreeItem * item; + lookupItems(m_dictSubDirs, url.url(-1), item, itemList); + + while(item) + { + if ( item->childCount() == 0 ) + { + item->setExpandable( false ); + item->repaint(); + } + m_pTree->stopAnimation( item ); + + item = itemList ? itemList->take(0) : 0; + } + delete itemList; + + kdDebug(1201) << "m_selectAfterOpening " << m_selectAfterOpening.prettyURL() << endl; + if ( !m_selectAfterOpening.isEmpty() && url.isParentOf( m_selectAfterOpening ) ) + { + KURL theURL( m_selectAfterOpening ); + m_selectAfterOpening = KURL(); + followURL( theURL ); + } +} + +void KonqSidebarDirTreeModule::followURL( const KURL & url ) +{ + // Check if we already know this URL + KonqSidebarTreeItem * item = m_dictSubDirs[ url.url(-1) ]; + if (item) // found it -> ensure visible, select, return. + { + m_pTree->ensureItemVisible( item ); + m_pTree->setSelected( item, true ); + return; + } + + KURL uParent( url ); + KonqSidebarTreeItem * parentItem = 0L; + // Go up to the first known parent + do + { + uParent = uParent.upURL(); + parentItem = m_dictSubDirs[ uParent.url(-1) ]; + } while ( !parentItem && !uParent.path().isEmpty() && uParent.path() != "/" ); + + // Not found !?! + if (!parentItem) + { + kdDebug() << "No parent found for url " << url.prettyURL() << endl; + return; + } + kdDebug(1202) << "Found parent " << uParent.prettyURL() << endl; + + // That's the parent directory we found. Open if not open... + if ( !parentItem->isOpen() ) + { + parentItem->setOpen( true ); + if ( parentItem->childCount() && m_dictSubDirs[ url.url(-1) ] ) + { + // Immediate opening, if the dir was already listed + followURL( url ); // equivalent to a goto-beginning-of-method + } else + { + m_selectAfterOpening = url; + kdDebug(1202) << "KonqSidebarDirTreeModule::followURL: m_selectAfterOpening=" << m_selectAfterOpening.url() << endl; + } + } +} + + +extern "C" +{ + KDE_EXPORT KonqSidebarTreeModule *create_konq_sidebartree_dirtree(KonqSidebarTree* par,const bool showHidden) + { + return new KonqSidebarDirTreeModule(par,showHidden); + } +} + + + +#include "dirtree_module.moc" |