libkonq Library API Documentation

konq_dirpart.cc

00001 /* This file is part of the KDE projects
00002    Copyright (C) 2000 David Faure <faure@kde.org>
00003 
00004    This program is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     General Public License for more details.
00013 
00014    You should have received a copy of the GNU General Public License
00015    along with this program; see the file COPYING.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include "konq_dirpart.h"
00021 #include "konq_bgnddlg.h"
00022 #include "konq_propsview.h"
00023 #include "konq_settings.h"
00024 
00025 #include <kaction.h>
00026 #include <kdatastream.h>
00027 #include <kcolordialog.h>
00028 #include <kdebug.h>
00029 #include <kiconloader.h>
00030 #include <klocale.h>
00031 #include <kmessagebox.h>
00032 #include <konq_drag.h>
00033 #include <kparts/browserextension.h>
00034 #include <kurldrag.h>
00035 #include <kuserprofile.h>
00036 #include <kurifilter.h>
00037 #include <kglobalsettings.h>
00038 
00039 #include <qapplication.h>
00040 #include <qclipboard.h>
00041 #include <qfile.h>
00042 #include <assert.h>
00043 
00044 class KonqDirPart::KonqDirPartPrivate
00045 {
00046 public:
00047     QStringList mimeFilters;
00048 };
00049 
00050 KonqDirPart::KonqDirPart( QObject *parent, const char *name )
00051             :KParts::ReadOnlyPart( parent, name ),
00052     m_pProps( 0L ),
00053     m_findPart( 0L )
00054 {
00055     d = new KonqDirPartPrivate;
00056     m_lDirSize = 0;
00057     m_lFileCount = 0;
00058     m_lDirCount = 0;
00059     //m_bMultipleItemsSelected = false;
00060 
00061     connect( QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(slotClipboardDataChanged()) );
00062 
00063     actionCollection()->setHighlightingEnabled( true );
00064 
00065     m_paIncIconSize = new KAction( i18n( "Increase Icon Size" ), "viewmag+", 0, this, SLOT( slotIncIconSize() ), actionCollection(), "incIconSize" );
00066     m_paDecIconSize = new KAction( i18n( "Decrease Icon Size" ), "viewmag-", 0, this, SLOT( slotDecIconSize() ), actionCollection(), "decIconSize" );
00067 
00068     m_paDefaultIcons = new KRadioAction( i18n( "&Default Size" ), 0, actionCollection(), "modedefault" );
00069     m_paHugeIcons = new KRadioAction( i18n( "&Huge" ), 0, actionCollection(), "modehuge" );
00070     m_paLargeIcons = new KRadioAction( i18n( "&Large" ), 0, actionCollection(), "modelarge" );
00071     m_paMediumIcons = new KRadioAction( i18n( "&Medium" ), 0, actionCollection(), "modemedium" );
00072     m_paSmallIcons = new KRadioAction( i18n( "&Small" ), 0, actionCollection(), "modesmall" );
00073 
00074     m_paDefaultIcons->setExclusiveGroup( "ViewMode" );
00075     m_paHugeIcons->setExclusiveGroup( "ViewMode" );
00076     m_paLargeIcons->setExclusiveGroup( "ViewMode" );
00077     m_paMediumIcons->setExclusiveGroup( "ViewMode" );
00078     m_paSmallIcons->setExclusiveGroup( "ViewMode" );
00079 
00080     connect( m_paDefaultIcons, SIGNAL( toggled( bool ) ), this, SLOT( slotIconSizeToggled( bool ) ) );
00081     connect( m_paHugeIcons, SIGNAL( toggled( bool ) ), this, SLOT( slotIconSizeToggled( bool ) ) );
00082     connect( m_paLargeIcons, SIGNAL( toggled( bool ) ), this, SLOT( slotIconSizeToggled( bool ) ) );
00083     connect( m_paMediumIcons, SIGNAL( toggled( bool ) ), this, SLOT( slotIconSizeToggled( bool ) ) );
00084     connect( m_paSmallIcons, SIGNAL( toggled( bool ) ), this, SLOT( slotIconSizeToggled( bool ) ) );
00085 
00086     // Extract 4 icon sizes from the icon theme. Use 16,32,48,64 as default.
00087     int i;
00088     m_iIconSize[0] = 0; // Default value
00089     m_iIconSize[1] = KIcon::SizeSmall; // 16
00090     m_iIconSize[2] = KIcon::SizeMedium; // 32
00091     m_iIconSize[3] = KIcon::SizeLarge; // 48
00092     m_iIconSize[4] = KIcon::SizeHuge; // 64
00093     KIconTheme *root = KGlobal::instance()->iconLoader()->theme();
00094     if (root)
00095     {
00096       QValueList<int> avSizes = root->querySizes(KIcon::Desktop);
00097       QValueList<int>::Iterator it;
00098       for (i=1, it=avSizes.begin(); (it!=avSizes.end()) && (i<5); it++, i++)
00099       {
00100         m_iIconSize[i] = *it;
00101         //kdDebug(1203) << "m_iIconSize[" << i << "] = " << *it << endl;
00102       }
00103     }
00104 
00105     KAction *a = new KAction( i18n( "Background Color..." ), 0, this, SLOT( slotBackgroundColor() ),
00106                               actionCollection(), "bgcolor" );
00107 
00108     a->setStatusText( i18n( "Allows choosing of a background color for this view" ) );
00109 
00110     a = new KAction( i18n( "Background Image..." ), "background", 0,
00111                      this, SLOT( slotBackgroundImage() ),
00112                      actionCollection(), "bgimage" );
00113 
00114     a->setStatusText( i18n( "Allows choosing a background image for this view" ) );
00115 }
00116 
00117 KonqDirPart::~KonqDirPart()
00118 {
00119     // Close the find part with us
00120     delete m_findPart;
00121     delete d;
00122 }
00123 
00124 void KonqDirPart::setMimeFilter (const QStringList& mime)
00125 {
00126     QString u = url().url();
00127 
00128     if ( u.isEmpty () )
00129         return;
00130 
00131     if ( mime.isEmpty() )
00132         d->mimeFilters.clear();
00133     else
00134         d->mimeFilters = mime;
00135 }
00136 
00137 QStringList KonqDirPart::mimeFilter() const
00138 {
00139     return d->mimeFilters;
00140 }
00141 
00142 QScrollView * KonqDirPart::scrollWidget()
00143 {
00144     return static_cast<QScrollView *>(widget());
00145 }
00146 
00147 void KonqDirPart::slotBackgroundColor()
00148 {
00149     QColor bgndColor = m_pProps->bgColor( widget() );
00150     QColor defaultColor = KGlobalSettings::baseColor();
00151     if ( KColorDialog::getColor( bgndColor,defaultColor ) == KColorDialog::Accepted )
00152     {
00153         if ( bgndColor.isValid() )
00154             m_pProps->setBgColor( bgndColor );
00155         else
00156             m_pProps->setBgColor( defaultColor );
00157         m_pProps->setBgPixmapFile( "" );
00158         m_pProps->applyColors( scrollWidget()->viewport() );
00159         scrollWidget()->viewport()->repaint();
00160     }
00161 }
00162 
00163 void KonqDirPart::slotBackgroundImage()
00164 {
00165     KonqBgndDialog dlg( m_pProps->bgPixmapFile(), instance() );
00166     if ( dlg.exec() == KonqBgndDialog::Accepted )
00167     {
00168         m_pProps->setBgPixmapFile( dlg.pixmapFile() );
00169         m_pProps->applyColors( scrollWidget()->viewport() );
00170         scrollWidget()->viewport()->repaint();
00171     }
00172 }
00173 
00174 void KonqDirPart::lmbClicked( KFileItem * fileItem )
00175 {
00176     KURL url = fileItem->url();
00177     if ( !fileItem->isReadable() )
00178     {
00179         // No permissions or local file that doesn't exist - need to find out which
00180         if ( ( !fileItem->isLocalFile() ) || QFile::exists( url.path() ) )
00181         {
00182             KMessageBox::error( widget(), i18n("<p>You do not have enough permissions to read <b>%1</b></p>").arg(url.prettyURL()) );
00183             return;
00184         }
00185         KMessageBox::error( widget(), i18n("<p><b>%1</b> doesn't seem to exist anymore</p>").arg(url.prettyURL()) );
00186         return;
00187     }
00188 
00189     KParts::URLArgs args;
00190     fileItem->determineMimeType();
00191     if ( fileItem->isMimeTypeKnown() )
00192         args.serviceType = fileItem->mimetype();
00193     args.trustedSource = true;
00194 
00195     if ( fileItem->isLink() && fileItem->isLocalFile() ) // see KFileItem::run
00196         url = KURL( url, KURL::encode_string( fileItem->linkDest() ) );
00197 
00198     if (KonqFMSettings::settings()->alwaysNewWin() && fileItem->isDir()) {
00199         //args.frameName = "_blank"; // open new window
00200         // We tried the other option, passing the path as framename so that
00201         // an existing window for that dir is reused (like MSWindows does when
00202         // the similar option is activated and the sidebar is hidden (!)).
00203         // But this requires some work, including changing the framename
00204         // when navigating, etc. Not very much requested yet, in addition.
00205         KParts::WindowArgs wargs;
00206         KParts::ReadOnlyPart* dummy;
00207         emit m_extension->createNewWindow( url, args, wargs, dummy );
00208     }
00209     else
00210     {
00211         kdDebug() << "emit m_extension->openURLRequest( " << url.url() << "," << args.serviceType << ")" << endl;
00212         emit m_extension->openURLRequest( url, args );
00213     }
00214 }
00215 
00216 void KonqDirPart::mmbClicked( KFileItem * fileItem )
00217 {
00218     if ( fileItem )
00219     {
00220         // Optimisation to avoid KRun to call kfmclient that then tells us
00221         // to open a window :-)
00222         KService::Ptr offer = KServiceTypeProfile::preferredService(fileItem->mimetype(), "Application");
00223         //if (offer) kdDebug(1203) << "KonqDirPart::mmbClicked: got service " << offer->desktopEntryName() << endl;
00224         if ( offer && offer->desktopEntryName().startsWith("kfmclient") )
00225         {
00226             KParts::URLArgs args;
00227             args.serviceType = fileItem->mimetype();
00228             emit m_extension->createNewWindow( fileItem->url(), args );
00229         }
00230         else
00231             fileItem->run();
00232     }
00233     else
00234     {
00235         m_extension->pasteRequest();
00236     }
00237 }
00238 
00239 void KonqDirPart::saveState( QDataStream& stream )
00240 {
00241     stream << m_nameFilter;
00242 }
00243 
00244 void KonqDirPart::restoreState( QDataStream& stream )
00245 {
00246     stream >> m_nameFilter;
00247 }
00248 
00249 void KonqDirPart::saveFindState( QDataStream& stream )
00250 {
00251     // assert only doable in KDE4.
00252     //assert( m_findPart ); // test done by caller.
00253     if ( !m_findPart )
00254         return;
00255 
00256     // When we have a find part, our own URL wasn't saved (see KonqDirPartBrowserExtension)
00257     // So let's do it here
00258     stream << m_url;
00259 
00260     KParts::BrowserExtension* ext = KParts::BrowserExtension::childObject( m_findPart );
00261     if( !ext )
00262         return;
00263 
00264     ext->saveState( stream );
00265 }
00266 
00267 void KonqDirPart::restoreFindState( QDataStream& stream )
00268 {
00269     // Restore our own URL
00270     stream >> m_url;
00271 
00272     emit findOpen( this );
00273 
00274     KParts::BrowserExtension* ext = KParts::BrowserExtension::childObject( m_findPart );
00275     slotClear();
00276 
00277     if( !ext )
00278         return;
00279 
00280     ext->restoreState( stream );
00281 }
00282 
00283 void KonqDirPart::slotClipboardDataChanged()
00284 {
00285     // This is very related to KDIconView::slotClipboardDataChanged
00286 
00287     KURL::List lst;
00288     QMimeSource *data = QApplication::clipboard()->data();
00289     if ( data->provides( "application/x-kde-cutselection" ) && data->provides( "text/uri-list" ) )
00290         if ( KonqDrag::decodeIsCutSelection( data ) )
00291             (void) KURLDrag::decode( data, lst );
00292 
00293     disableIcons( lst );
00294 
00295     updatePasteAction();
00296 }
00297 
00298 void KonqDirPart::updatePasteAction()
00299 {
00300     QMimeSource *data = QApplication::clipboard()->data();
00301     bool paste = ( data->format() != 0 );
00302 
00303     emit m_extension->enableAction( "paste", paste ); // TODO : if only one url, check that it's a dir
00304 }
00305 
00306 void KonqDirPart::newItems( const KFileItemList & entries )
00307 {
00308     for (KFileItemListIterator it(entries); it.current(); ++it)
00309     {
00310         if ( !it.current()->isDir() )
00311         {
00312             if (!it.current()->isLink()) // ignore symlinks
00313                 m_lDirSize += it.current()->size();
00314             m_lFileCount++;
00315         }
00316         else
00317             m_lDirCount++;
00318     }
00319     if ( m_findPart )
00320         emitTotalCount();
00321 
00322     emit itemsAdded( entries );
00323 }
00324 
00325 void KonqDirPart::deleteItem( KFileItem * fileItem )
00326 {
00327     if ( !fileItem->isDir() )
00328     {
00329         if ( !fileItem->isLink() )
00330             m_lDirSize -= fileItem->size();
00331         m_lFileCount--;
00332     }
00333     else
00334         m_lDirCount--;
00335 
00336     emit itemRemoved( fileItem );
00337 }
00338 
00339 void KonqDirPart::emitTotalCount()
00340 {
00341     QString summary =
00342         KIO::itemsSummaryString(m_lFileCount + m_lDirCount,
00343                                   m_lFileCount,
00344                                   m_lDirCount,
00345                                   m_lDirSize,
00346                                   true);
00347     bool bShowsResult = false;
00348     if (m_findPart)
00349     {
00350         QVariant prop = m_findPart->property( "showsResult" );
00351         bShowsResult = prop.isValid() && prop.toBool();
00352     }
00353     //kdDebug(1203) << "KonqDirPart::emitTotalCount bShowsResult=" << bShowsResult << endl;
00354     emit setStatusBarText( bShowsResult ? i18n("Search result: %1").arg(summary) : summary );
00355 }
00356 
00357 void KonqDirPart::emitCounts( const KFileItemList & lst, bool selectionChanged )
00358 {
00359     // Compare the new value with our cache
00360     /*bool multiple = lst.count()>1;
00361     if (multiple != m_bMultipleItemsSelected)
00362     {
00363         m_bMultipleItemsSelected = multiple;
00364         updatePasteAction();
00365     }*/
00366 
00367     if ( lst.count()==1)
00368     {
00369         emit setStatusBarText( ((KFileItemList)lst).first()->getStatusBarInfo() );
00370     }
00371     else if ( lst.count()>1)
00372     {
00373         long long fileSizeSum = 0;
00374         uint fileCount = 0;
00375         uint dirCount = 0;
00376 
00377         for (KFileItemListIterator it( lst ); it.current(); ++it )
00378             if ( it.current()->isDir() )
00379                 dirCount++;
00380             else
00381             {
00382                 if (!it.current()->isLink()) // ignore symlinks
00383                     fileSizeSum += it.current()->size();
00384                 fileCount++;
00385             }
00386 
00387         emit setStatusBarText( KIO::itemsSummaryString(fileCount + dirCount,
00388                                                          fileCount,
00389                                                          dirCount,
00390                                                          fileSizeSum,
00391                                                          true));
00392     }
00393     else
00394         emitTotalCount();
00395 
00396     // Yes, the caller could do that too :)
00397     // But this bool could also be used to cache the QString for the last
00398     // selection, as long as selectionChanged is false.
00399     // Not sure it's worth it though.
00400     if ( selectionChanged )
00401         emit m_extension->selectionInfo( lst );
00402 }
00403 
00404 void KonqDirPart::emitMouseOver( const KFileItem* item )
00405 {
00406     emit m_extension->mouseOverInfo( item );
00407 }
00408 
00409 void KonqDirPart::slotIconSizeToggled( bool )
00410 {
00411     //kdDebug(1203) << "KonqDirPart::slotIconSizeToggled" << endl;
00412     if ( m_paDefaultIcons->isChecked() )
00413         setIconSize(0);
00414     else if ( m_paHugeIcons->isChecked() )
00415         setIconSize(m_iIconSize[4]);
00416     else if ( m_paLargeIcons->isChecked() )
00417         setIconSize(m_iIconSize[3]);
00418     else if ( m_paMediumIcons->isChecked() )
00419         setIconSize(m_iIconSize[2]);
00420     else if ( m_paSmallIcons->isChecked() )
00421         setIconSize(m_iIconSize[1]);
00422 }
00423 
00424 void KonqDirPart::slotIncIconSize()
00425 {
00426     int s = m_pProps->iconSize();
00427     s = s ? s : KGlobal::iconLoader()->currentSize( KIcon::Desktop );
00428     int sizeIndex = 0;
00429     for ( int idx=1; idx < 5 ; ++idx )
00430         if (s == m_iIconSize[idx])
00431             sizeIndex = idx;
00432     if ( sizeIndex > 0 && sizeIndex < 4 )
00433     {
00434         setIconSize( m_iIconSize[sizeIndex + 1] );
00435     }
00436 }
00437 
00438 void KonqDirPart::slotDecIconSize()
00439 {
00440     int s = m_pProps->iconSize();
00441     s = s ? s : KGlobal::iconLoader()->currentSize( KIcon::Desktop );
00442     int sizeIndex = 0;
00443     for ( int idx=1; idx < 5 ; ++idx )
00444         if (s == m_iIconSize[idx])
00445             sizeIndex = idx;
00446     if ( sizeIndex > 1 )
00447     {
00448         setIconSize( m_iIconSize[sizeIndex - 1] );
00449     }
00450 }
00451 
00452 // Only updates the GUI (that's the one that is reimplemented by the views, too)
00453 void KonqDirPart::newIconSize( int size /*0=default, or 16,32,48....*/ )
00454 {
00455     int realSize = (size==0) ? KGlobal::iconLoader()->currentSize( KIcon::Desktop ) : size;
00456     m_paDecIconSize->setEnabled(realSize > m_iIconSize[1]);
00457     m_paIncIconSize->setEnabled(realSize < m_iIconSize[4]);
00458 
00459     m_paDefaultIcons->setChecked( size == 0 );
00460     m_paHugeIcons->setChecked( size == m_iIconSize[4] );
00461     m_paLargeIcons->setChecked( size == m_iIconSize[3] );
00462     m_paMediumIcons->setChecked( size == m_iIconSize[2] );
00463     m_paSmallIcons->setChecked( size == m_iIconSize[1] );
00464 }
00465 
00466 // Stores the new icon size and updates the GUI
00467 void KonqDirPart::setIconSize( int size )
00468 {
00469     //kdDebug(1203) << "KonqDirPart::setIconSize " << size << " -> updating props and GUI" << endl;
00470     m_pProps->setIconSize( size );
00471     newIconSize( size );
00472 }
00473 
00474 bool KonqDirPart::closeURL()
00475 {
00476     // Tell all the childern objects to clean themselves up for dinner :)
00477     return doCloseURL();
00478 }
00479 
00480 bool KonqDirPart::openURL(const KURL& url)
00481 {
00482     if ( m_findPart )
00483     {
00484         kdDebug(1203) << "KonqDirPart::openURL -> emit findClosed " << this << endl;
00485         delete m_findPart;
00486         m_findPart = 0L;
00487         emit findClosed( this );
00488     }
00489 
00490     m_url = url;
00491     emit aboutToOpenURL ();
00492 
00493     return doOpenURL(url);
00494 }
00495 
00496 void KonqDirPart::setFindPart( KParts::ReadOnlyPart * part )
00497 {
00498     assert(part);
00499     m_findPart = part;
00500     connect( m_findPart, SIGNAL( started() ),
00501              this, SLOT( slotStarted() ) );
00502     connect( m_findPart, SIGNAL( started() ),
00503              this, SLOT( slotStartAnimationSearching() ) );
00504     connect( m_findPart, SIGNAL( clear() ),
00505              this, SLOT( slotClear() ) );
00506     connect( m_findPart, SIGNAL( newItems( const KFileItemList & ) ),
00507              this, SLOT( slotNewItems( const KFileItemList & ) ) );
00508     connect( m_findPart, SIGNAL( finished() ), // can't name it completed, it conflicts with a KROP signal
00509              this, SLOT( slotCompleted() ) );
00510     connect( m_findPart, SIGNAL( finished() ),
00511              this, SLOT( slotStopAnimationSearching() ) );
00512     connect( m_findPart, SIGNAL( canceled() ),
00513              this, SLOT( slotCanceled() ) );
00514     connect( m_findPart, SIGNAL( canceled() ),
00515              this, SLOT( slotStopAnimationSearching() ) );
00516 
00517     connect( m_findPart, SIGNAL( findClosed() ),
00518              this, SLOT( slotFindClosed() ) );
00519 
00520     emit findOpened( this );
00521 
00522     // set the initial URL in the find part
00523     m_findPart->openURL( url() );
00524 }
00525 
00526 void KonqDirPart::slotFindClosed()
00527 {
00528     kdDebug(1203) << "KonqDirPart::slotFindClosed -> emit findClosed " << this << endl;
00529     delete m_findPart;
00530     m_findPart = 0L;
00531     emit findClosed( this );
00532     // reload where we were before
00533     openURL( url() );
00534 }
00535 
00536 void KonqDirPart::slotStartAnimationSearching()
00537 {
00538   started(0);
00539 }
00540 
00541 void KonqDirPart::slotStopAnimationSearching()
00542 {
00543   completed();
00544 }
00545 
00546 void KonqDirPartBrowserExtension::saveState( QDataStream &stream )
00547 {
00548     m_dirPart->saveState( stream );
00549     bool hasFindPart = m_dirPart->findPart();
00550     stream << hasFindPart;
00551     assert( ! ( hasFindPart && m_dirPart->className() == "KFindPart" ) );
00552     if ( !hasFindPart )
00553         KParts::BrowserExtension::saveState( stream );
00554     else {
00555         m_dirPart->saveFindState( stream );
00556     }
00557 }
00558 
00559 void KonqDirPartBrowserExtension::restoreState( QDataStream &stream )
00560 {
00561     m_dirPart->restoreState( stream );
00562     bool hasFindPart;
00563     stream >> hasFindPart;
00564     assert( ! ( hasFindPart && m_dirPart->className() == "KFindPart" ) );
00565     if ( !hasFindPart )
00566         // This calls openURL, that's why we don't want to call it in case of a find part
00567         KParts::BrowserExtension::restoreState( stream );
00568     else {
00569         m_dirPart->restoreFindState( stream );
00570     }
00571 }
00572 
00573 
00574 #include "konq_dirpart.moc"
KDE Logo
This file is part of the documentation for libkonq Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Apr 11 13:44:46 2004 by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2003