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