kio Library API Documentation

kdirselectdialog.cpp

00001 /*
00002     Copyright (C) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org>
00003     Copyright (C) 2001 Michael Jarrett <michaelj@corel.com>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License version 2 as published by the Free Software Foundation.
00008 
00009     This library 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     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  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 <qdir.h>
00021 #include <qlayout.h>
00022 #include <qpopupmenu.h>
00023 #include <qstringlist.h>
00024 #include <qvaluestack.h>
00025 
00026 #include <kactionclasses.h>
00027 #include <kapplication.h>
00028 #include <kcombobox.h>
00029 #include <kconfig.h>
00030 #include <kfiledialog.h>
00031 #include <kfilespeedbar.h>
00032 #include <kglobalsettings.h>
00033 #include <kiconloader.h>
00034 #include <klocale.h>
00035 #include <kprotocolinfo.h>
00036 #include <krecentdirs.h>
00037 #include <kurl.h>
00038 #include <kurlcompletion.h>
00039 #include <kurlpixmapprovider.h>
00040 
00041 #include "kfiletreeview.h"
00042 #include "kdirselectdialog.h"
00043 
00044 // ### add mutator for treeview!
00045 
00046 class KDirSelectDialog::KDirSelectDialogPrivate
00047 {
00048 public:
00049     KDirSelectDialogPrivate()
00050     {
00051         urlCombo = 0L;
00052         branch = 0L;
00053         comboLocked = false;
00054     }
00055 
00056     KFileSpeedBar *speedBar;
00057     KHistoryCombo *urlCombo;
00058     KFileTreeBranch *branch;
00059     QString recentDirClass;
00060     KURL startURL;
00061     QValueStack<KURL> dirsToList;
00062 
00063     bool comboLocked : 1;
00064 };
00065 
00066 static KURL rootUrl(const KURL &url)
00067 {
00068     KURL root = url;
00069     root.setPath( "/" );
00070     
00071     if (!kapp->authorizeURLAction("list", KURL(), root))
00072     {
00073         root = KURL::fromPathOrURL( QDir::homeDirPath() );
00074         if (!kapp->authorizeURLAction("list", KURL(), root))
00075         {
00076             root = url;
00077         }
00078     }
00079     return root;
00080 }
00081 
00082 KDirSelectDialog::KDirSelectDialog(const QString &startDir, bool localOnly,
00083                                    QWidget *parent, const char *name,
00084                                    bool modal)
00085     : KDialogBase( parent, name, modal, i18n("Select Folder"), Ok|Cancel),
00086       m_localOnly( localOnly )
00087 {
00088     d = new KDirSelectDialogPrivate;
00089     d->branch = 0L;
00090 
00091     QFrame *page = makeMainWidget();
00092     QHBoxLayout *hlay = new QHBoxLayout( page, 0, spacingHint() );
00093     m_mainLayout = new QVBoxLayout();
00094     d->speedBar = new KFileSpeedBar( page, "speedbar" );
00095     connect( d->speedBar, SIGNAL( activated( const KURL& )),
00096              SLOT( setCurrentURL( const KURL& )) );
00097     hlay->addWidget( d->speedBar, 0 );
00098     hlay->addLayout( m_mainLayout, 1 );
00099 
00100     // Create dir list
00101     m_treeView = new KFileTreeView( page );
00102     m_treeView->addColumn( i18n("Folder") );
00103     m_treeView->setColumnWidthMode( 0, QListView::Maximum );
00104     m_treeView->setResizeMode( QListView::AllColumns );
00105 
00106     d->urlCombo = new KHistoryCombo( page, "url combo" );
00107     d->urlCombo->setTrapReturnKey( true );
00108     d->urlCombo->setPixmapProvider( new KURLPixmapProvider() );
00109     KURLCompletion *comp = new KURLCompletion();
00110     comp->setMode( KURLCompletion::DirCompletion );
00111     d->urlCombo->setCompletionObject( comp, true );
00112     d->urlCombo->setAutoDeleteCompletionObject( true );
00113     d->urlCombo->setDuplicatesEnabled( false );
00114     connect( d->urlCombo, SIGNAL( textChanged( const QString& ) ),
00115              SLOT( slotComboTextChanged( const QString& ) ));
00116 
00117     m_contextMenu = new QPopupMenu( this );
00118     m_showHiddenFolders = new KToggleAction ( i18n( "Show Hidden Folders" ), 0, this,
00119                                         SLOT( slotShowHiddenFoldersToggled() ), this);
00120 //    m_showHiddenFolders->setCheckedState( i18n("Hide Hidden Folders") );
00121     m_showHiddenFolders->plug(m_contextMenu);
00122 
00123     d->startURL = KFileDialog::getStartURL( startDir, d->recentDirClass );
00124     if ( localOnly && !d->startURL.isLocalFile() )
00125     {
00126         d->startURL = KURL();
00127         QString docPath = KGlobalSettings::documentPath();
00128         if (QDir(docPath).exists())
00129             d->startURL.setPath( docPath );
00130         else
00131             d->startURL.setPath( QDir::homeDirPath() );
00132     }
00133 
00134     KURL root = rootUrl(d->startURL);
00135 
00136     m_startDir = d->startURL.url();
00137 
00138     d->branch = createBranch( root );
00139 
00140     readConfig( KGlobal::config(), "DirSelect Dialog" );
00141 
00142     m_mainLayout->addWidget( m_treeView, 1 );
00143     m_mainLayout->addWidget( d->urlCombo, 0 );
00144 
00145     connect( m_treeView, SIGNAL( currentChanged( QListViewItem * )),
00146              SLOT( slotCurrentChanged() ));
00147     connect( m_treeView, SIGNAL( contextMenu( KListView *, QListViewItem *, const QPoint & )),
00148              SLOT( slotContextMenu( KListView *, QListViewItem *, const QPoint & )));
00149 
00150     connect( d->urlCombo, SIGNAL( activated( const QString& )),
00151              SLOT( slotURLActivated( const QString& )));
00152     connect( d->urlCombo, SIGNAL( returnPressed( const QString& )),
00153              SLOT( slotURLActivated( const QString& )));
00154 
00155     setCurrentURL( d->startURL );
00156 }
00157 
00158 
00159 KDirSelectDialog::~KDirSelectDialog()
00160 {
00161     delete d;
00162 }
00163 
00164 void KDirSelectDialog::setCurrentURL( const KURL& url )
00165 {
00166     if ( !url.isValid() )
00167         return;
00168 
00169     KURL root = rootUrl(url);
00170 
00171     d->startURL = url;
00172     if ( !d->branch ||
00173          url.protocol() != d->branch->url().protocol() ||
00174          url.host() != d->branch->url().host() )
00175     {
00176         if ( d->branch )
00177         {
00178             // removing the root-item causes the currentChanged() signal to be
00179             // emitted, but we don't want to update the location-combo yet.
00180             d->comboLocked = true;
00181             view()->removeBranch( d->branch );
00182             d->comboLocked = false;
00183         }
00184 
00185         d->branch = createBranch( root );
00186     }
00187 
00188     d->branch->disconnect( SIGNAL( populateFinished( KFileTreeViewItem * )),
00189                            this, SLOT( slotNextDirToList( KFileTreeViewItem *)));
00190     connect( d->branch, SIGNAL( populateFinished( KFileTreeViewItem * )),
00191              SLOT( slotNextDirToList( KFileTreeViewItem * ) ));
00192 
00193     KURL dirToList = root;
00194     d->dirsToList.clear();
00195     QString path = url.path(+1);
00196     int pos = path.length();
00197 
00198     if ( path.isEmpty() ) // e.g. ftp://host.com/ -> just list the root dir
00199         d->dirsToList.push( root );
00200 
00201     else
00202     {
00203         while ( pos > 0 )
00204         {
00205             pos = path.findRev( '/', pos -1 );
00206             if ( pos >= 0 )
00207             {
00208                 dirToList.setPath( path.left( pos +1 ) );
00209                 d->dirsToList.push( dirToList );
00210 //                 qDebug( "List: %s", dirToList.url().latin1());
00211             }
00212         }
00213     }
00214 
00215     if ( !d->dirsToList.isEmpty() )
00216         openNextDir( d->branch->root() );
00217 }
00218 
00219 void KDirSelectDialog::openNextDir( KFileTreeViewItem * /*parent*/ )
00220 {
00221     if ( !d->branch )
00222         return;
00223 
00224     KURL url = d->dirsToList.pop();
00225 
00226     KFileTreeViewItem *item = view()->findItem( d->branch, url.path().mid(1));
00227     if ( item )
00228     {
00229         if ( !item->isOpen() )
00230             item->setOpen( true );
00231         else // already open -> go to next one
00232             slotNextDirToList( item );
00233     }
00234 //     else
00235 //         qDebug("###### openNextDir: item not found!");
00236 }
00237 
00238 void KDirSelectDialog::slotNextDirToList( KFileTreeViewItem *item )
00239 {
00240     // scroll to make item the topmost item
00241     view()->ensureItemVisible( item );
00242     QRect r = view()->itemRect( item );
00243     if ( r.isValid() )
00244     {
00245         int x, y;
00246         view()->viewportToContents( view()->contentsX(), r.y(), x, y );
00247         view()->setContentsPos( x, y );
00248     }
00249 
00250     if ( !d->dirsToList.isEmpty() )
00251         openNextDir( item );
00252     else
00253     {
00254         d->branch->disconnect( SIGNAL( populateFinished( KFileTreeViewItem * )),
00255                                this, SLOT( slotNextDirToList( KFileTreeViewItem *)));
00256         view()->setCurrentItem( item );
00257         item->setSelected( true );
00258     }
00259 }
00260 
00261 void KDirSelectDialog::readConfig( KConfig *config, const QString& group )
00262 {
00263     d->urlCombo->clear();
00264 
00265     KConfigGroup conf( config, group );
00266     d->urlCombo->setHistoryItems( conf.readPathListEntry( "History Items" ));
00267 
00268     QSize defaultSize( 400, 450 );
00269     resize( conf.readSizeEntry( "DirSelectDialog Size", &defaultSize ));
00270 }
00271 
00272 void KDirSelectDialog::saveConfig( KConfig *config, const QString& group )
00273 {
00274     KConfigGroup conf( config, group );
00275     conf.writePathEntry( "History Items", d->urlCombo->historyItems(), ',',
00276                      true, true);
00277     conf.writeEntry( "DirSelectDialog Size", size(), true, true );
00278 
00279     d->speedBar->save( config );
00280 
00281     config->sync();
00282 }
00283 
00284 void KDirSelectDialog::accept()
00285 {
00286     KFileTreeViewItem *item = m_treeView->currentKFileTreeViewItem();
00287     if ( !item )
00288         return;
00289 
00290     if ( !d->recentDirClass.isEmpty() )
00291     {
00292         KURL dir = item->url();
00293         if ( !item->isDir() )
00294             dir = dir.upURL();
00295 
00296         KRecentDirs::add(d->recentDirClass, dir.url());
00297     }
00298 
00299     d->urlCombo->addToHistory( item->url().prettyURL() );
00300     KFileDialog::setStartDir( url() );
00301 
00302     KDialogBase::accept();
00303     saveConfig( KGlobal::config(), "DirSelect Dialog" );
00304 }
00305 
00306 
00307 KURL KDirSelectDialog::url() const
00308 {
00309     return m_treeView->currentURL();
00310 }
00311 
00312 void KDirSelectDialog::slotCurrentChanged()
00313 {
00314     if ( d->comboLocked )
00315         return;
00316 
00317     KFileTreeViewItem *current = view()->currentKFileTreeViewItem();
00318     KURL u = current ? current->url() : (d->branch ? d->branch->rootUrl() : KURL());
00319 
00320     if ( u.isValid() )
00321     {
00322         if ( u.isLocalFile() )
00323             d->urlCombo->setEditText( u.path() );
00324 
00325         else // remote url
00326             d->urlCombo->setEditText( u.prettyURL() );
00327     }
00328     else
00329         d->urlCombo->setEditText( QString::null );
00330 }
00331 
00332 void KDirSelectDialog::slotURLActivated( const QString& text )
00333 {
00334     if ( text.isEmpty() )
00335         return;
00336 
00337     KURL url = KURL::fromPathOrURL( text );
00338     d->urlCombo->addToHistory( url.prettyURL() );
00339 
00340     if ( localOnly() && !url.isLocalFile() )
00341         return; // ### messagebox
00342 
00343     KURL oldURL = m_treeView->currentURL();
00344     if ( oldURL.isEmpty() )
00345         oldURL = KURL::fromPathOrURL( m_startDir );
00346 
00347     setCurrentURL( url );
00348 }
00349 
00350 KFileTreeBranch * KDirSelectDialog::createBranch( const KURL& url )
00351 {
00352     QString title = url.isLocalFile() ? url.path() : url.prettyURL();
00353     KFileTreeBranch *branch = view()->addBranch( url, title, m_showHiddenFolders->isChecked() );
00354     branch->setChildRecurse( false );
00355     view()->setDirOnlyMode( branch, true );
00356 
00357     return branch;
00358 }
00359 
00360 void KDirSelectDialog::slotComboTextChanged( const QString& text )
00361 {
00362     if ( d->branch )
00363     {
00364         KURL url = KURL::fromPathOrURL( text );
00365         KFileTreeViewItem *item = d->branch->findTVIByURL( url );
00366         if ( item )
00367         {
00368             view()->setCurrentItem( item );
00369             view()->setSelected( item, true );
00370             view()->ensureItemVisible( item );
00371             return;
00372         }
00373     }
00374 
00375     QListViewItem *item = view()->currentItem();
00376     if ( item )
00377     {
00378         item->setSelected( false );
00379         // 2002/12/27, deselected item is not repainted, so force it
00380         item->repaint();
00381     }
00382 }
00383 
00384 void KDirSelectDialog::slotContextMenu( KListView *, QListViewItem *, const QPoint& pos )
00385 {
00386     m_contextMenu->popup( pos );
00387 }
00388 
00389 void KDirSelectDialog::slotShowHiddenFoldersToggled()
00390 {
00391     KURL currentURL = url();
00392 
00393     d->comboLocked = true;
00394     view()->removeBranch( d->branch );
00395     d->comboLocked = false;
00396 
00397     KURL root = rootUrl(d->startURL);
00398     d->branch = createBranch( root );
00399 
00400     setCurrentURL( currentURL );
00401 }
00402 
00403 // static
00404 KURL KDirSelectDialog::selectDirectory( const QString& startDir,
00405                                         bool localOnly,
00406                                         QWidget *parent,
00407                                         const QString& caption)
00408 {
00409     KDirSelectDialog myDialog( startDir, localOnly, parent,
00410                                "kdirselect dialog", true );
00411 
00412     if ( !caption.isNull() )
00413         myDialog.setCaption( caption );
00414 
00415     if ( myDialog.exec() == QDialog::Accepted )
00416         return myDialog.url();
00417     else
00418         return KURL();
00419 }
00420 
00421 void KDirSelectDialog::virtual_hook( int id, void* data )
00422 { KDialogBase::virtual_hook( id, data ); }
00423 
00424 #include "kdirselectdialog.moc"
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Nov 27 13:45:22 2004 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003