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 #include <kinputdialog.h>
00041 #include <kio/netaccess.h>
00042 #include <kmessagebox.h>
00043 
00044 #include "kfiletreeview.h"
00045 #include "kdirselectdialog.h"
00046 
00047 // ### add mutator for treeview!
00048 
00049 class KDirSelectDialog::KDirSelectDialogPrivate
00050 {
00051 public:
00052     KDirSelectDialogPrivate()
00053     {
00054         urlCombo = 0L;
00055         branch = 0L;
00056         comboLocked = false;
00057     }
00058 
00059     KFileSpeedBar *speedBar;
00060     KHistoryCombo *urlCombo;
00061     KFileTreeBranch *branch;
00062     QString recentDirClass;
00063     KURL startURL;
00064     QValueStack<KURL> dirsToList;
00065 
00066     bool comboLocked : 1;
00067 };
00068 
00069 static KURL rootUrl(const KURL &url)
00070 {
00071     KURL root = url;
00072     root.setPath( "/" );
00073     
00074     if (!kapp->authorizeURLAction("list", KURL(), root))
00075     {
00076         root = KURL::fromPathOrURL( QDir::homeDirPath() );
00077         if (!kapp->authorizeURLAction("list", KURL(), root))
00078         {
00079             root = url;
00080         }
00081     }
00082     return root;
00083 }
00084 
00085 KDirSelectDialog::KDirSelectDialog(const QString &startDir, bool localOnly,
00086                                    QWidget *parent, const char *name,
00087                                    bool modal)
00088     : KDialogBase( parent, name, modal, i18n("Select Folder"), Ok|Cancel),
00089       m_localOnly( localOnly )
00090 {
00091     d = new KDirSelectDialogPrivate;
00092     d->branch = 0L;
00093 
00094     QFrame *page = makeMainWidget();
00095     QHBoxLayout *hlay = new QHBoxLayout( page, 0, spacingHint() );
00096     m_mainLayout = new QVBoxLayout();
00097     d->speedBar = new KFileSpeedBar( page, "speedbar" );
00098     connect( d->speedBar, SIGNAL( activated( const KURL& )),
00099              SLOT( setCurrentURL( const KURL& )) );
00100     hlay->addWidget( d->speedBar, 0 );
00101     hlay->addLayout( m_mainLayout, 1 );
00102 
00103     // Create dir list
00104     m_treeView = new KFileTreeView( page );
00105     m_treeView->addColumn( i18n("Folder") );
00106     m_treeView->setColumnWidthMode( 0, QListView::Maximum );
00107     m_treeView->setResizeMode( QListView::AllColumns );
00108 
00109     d->urlCombo = new KHistoryCombo( page, "url combo" );
00110     d->urlCombo->setTrapReturnKey( true );
00111     d->urlCombo->setPixmapProvider( new KURLPixmapProvider() );
00112     KURLCompletion *comp = new KURLCompletion();
00113     comp->setMode( KURLCompletion::DirCompletion );
00114     d->urlCombo->setCompletionObject( comp, true );
00115     d->urlCombo->setAutoDeleteCompletionObject( true );
00116     d->urlCombo->setDuplicatesEnabled( false );
00117     connect( d->urlCombo, SIGNAL( textChanged( const QString& ) ),
00118              SLOT( slotComboTextChanged( const QString& ) ));
00119 
00120     m_contextMenu = new QPopupMenu( this );
00121     KAction* newFolder = new KAction( i18n("New Folder..."), "folder_new", 0, this, SLOT( slotMkdir() ), this);
00122     newFolder->plug(m_contextMenu);
00123     m_contextMenu->insertSeparator();
00124     m_showHiddenFolders = new KToggleAction ( i18n( "Show Hidden Folders" ), 0, this,
00125                                         SLOT( slotShowHiddenFoldersToggled() ), this);
00126     m_showHiddenFolders->plug(m_contextMenu);
00127 
00128     d->startURL = KFileDialog::getStartURL( startDir, d->recentDirClass );
00129     if ( localOnly && !d->startURL.isLocalFile() )
00130     {
00131         d->startURL = KURL();
00132         QString docPath = KGlobalSettings::documentPath();
00133         if (QDir(docPath).exists())
00134             d->startURL.setPath( docPath );
00135         else
00136             d->startURL.setPath( QDir::homeDirPath() );
00137     }
00138 
00139     KURL root = rootUrl(d->startURL);
00140 
00141     m_startDir = d->startURL.url();
00142 
00143     d->branch = createBranch( root );
00144 
00145     readConfig( KGlobal::config(), "DirSelect Dialog" );
00146 
00147     m_mainLayout->addWidget( m_treeView, 1 );
00148     m_mainLayout->addWidget( d->urlCombo, 0 );
00149 
00150     connect( m_treeView, SIGNAL( currentChanged( QListViewItem * )),
00151              SLOT( slotCurrentChanged() ));
00152     connect( m_treeView, SIGNAL( contextMenu( KListView *, QListViewItem *, const QPoint & )),
00153              SLOT( slotContextMenu( KListView *, QListViewItem *, const QPoint & )));
00154 
00155     connect( d->urlCombo, SIGNAL( activated( const QString& )),
00156              SLOT( slotURLActivated( const QString& )));
00157     connect( d->urlCombo, SIGNAL( returnPressed( const QString& )),
00158              SLOT( slotURLActivated( const QString& )));
00159 
00160     setCurrentURL( d->startURL );
00161 }
00162 
00163 
00164 KDirSelectDialog::~KDirSelectDialog()
00165 {
00166     delete d;
00167 }
00168 
00169 void KDirSelectDialog::setCurrentURL( const KURL& url )
00170 {
00171     if ( !url.isValid() )
00172         return;
00173 
00174     KURL root = rootUrl(url);
00175 
00176     d->startURL = url;
00177     if ( !d->branch ||
00178          url.protocol() != d->branch->url().protocol() ||
00179          url.host() != d->branch->url().host() )
00180     {
00181         if ( d->branch )
00182         {
00183             // removing the root-item causes the currentChanged() signal to be
00184             // emitted, but we don't want to update the location-combo yet.
00185             d->comboLocked = true;
00186             view()->removeBranch( d->branch );
00187             d->comboLocked = false;
00188         }
00189 
00190         d->branch = createBranch( root );
00191     }
00192 
00193     d->branch->disconnect( SIGNAL( populateFinished( KFileTreeViewItem * )),
00194                            this, SLOT( slotNextDirToList( KFileTreeViewItem *)));
00195     connect( d->branch, SIGNAL( populateFinished( KFileTreeViewItem * )),
00196              SLOT( slotNextDirToList( KFileTreeViewItem * ) ));
00197 
00198     KURL dirToList = root;
00199     d->dirsToList.clear();
00200     QString path = url.path(+1);
00201     int pos = path.length();
00202 
00203     if ( path.isEmpty() ) // e.g. ftp://host.com/ -> just list the root dir
00204         d->dirsToList.push( root );
00205 
00206     else
00207     {
00208         while ( pos > 0 )
00209         {
00210             pos = path.findRev( '/', pos -1 );
00211             if ( pos >= 0 )
00212             {
00213                 dirToList.setPath( path.left( pos +1 ) );
00214                 d->dirsToList.push( dirToList );
00215 //                 qDebug( "List: %s", dirToList.url().latin1());
00216             }
00217         }
00218     }
00219 
00220     if ( !d->dirsToList.isEmpty() )
00221         openNextDir( d->branch->root() );
00222 }
00223 
00224 void KDirSelectDialog::openNextDir( KFileTreeViewItem * /*parent*/ )
00225 {
00226     if ( !d->branch )
00227         return;
00228 
00229     KURL url = d->dirsToList.pop();
00230 
00231     KFileTreeViewItem *item = view()->findItem( d->branch, url.path().mid(1));
00232     if ( item )
00233     {
00234         if ( !item->isOpen() )
00235             item->setOpen( true );
00236         else // already open -> go to next one
00237             slotNextDirToList( item );
00238     }
00239 //     else
00240 //         qDebug("###### openNextDir: item not found!");
00241 }
00242 
00243 void KDirSelectDialog::slotNextDirToList( KFileTreeViewItem *item )
00244 {
00245     // scroll to make item the topmost item
00246     view()->ensureItemVisible( item );
00247     QRect r = view()->itemRect( item );
00248     if ( r.isValid() )
00249     {
00250         int x, y;
00251         view()->viewportToContents( view()->contentsX(), r.y(), x, y );
00252         view()->setContentsPos( x, y );
00253     }
00254 
00255     if ( !d->dirsToList.isEmpty() )
00256         openNextDir( item );
00257     else
00258     {
00259         d->branch->disconnect( SIGNAL( populateFinished( KFileTreeViewItem * )),
00260                                this, SLOT( slotNextDirToList( KFileTreeViewItem *)));
00261         view()->setCurrentItem( item );
00262         item->setSelected( true );
00263     }
00264 }
00265 
00266 void KDirSelectDialog::readConfig( KConfig *config, const QString& group )
00267 {
00268     d->urlCombo->clear();
00269 
00270     KConfigGroup conf( config, group );
00271     d->urlCombo->setHistoryItems( conf.readPathListEntry( "History Items" ));
00272 
00273     QSize defaultSize( 400, 450 );
00274     resize( conf.readSizeEntry( "DirSelectDialog Size", &defaultSize ));
00275 }
00276 
00277 void KDirSelectDialog::saveConfig( KConfig *config, const QString& group )
00278 {
00279     KConfigGroup conf( config, group );
00280     conf.writePathEntry( "History Items", d->urlCombo->historyItems(), ',',
00281                      true, true);
00282     conf.writeEntry( "DirSelectDialog Size", size(), true, true );
00283 
00284     d->speedBar->save( config );
00285 
00286     config->sync();
00287 }
00288 
00289 void KDirSelectDialog::accept()
00290 {
00291     KFileTreeViewItem *item = m_treeView->currentKFileTreeViewItem();
00292     if ( !item )
00293         return;
00294 
00295     if ( !d->recentDirClass.isEmpty() )
00296     {
00297         KURL dir = item->url();
00298         if ( !item->isDir() )
00299             dir = dir.upURL();
00300 
00301         KRecentDirs::add(d->recentDirClass, dir.url());
00302     }
00303 
00304     d->urlCombo->addToHistory( item->url().prettyURL() );
00305     KFileDialog::setStartDir( url() );
00306 
00307     KDialogBase::accept();
00308     saveConfig( KGlobal::config(), "DirSelect Dialog" );
00309 }
00310 
00311 
00312 KURL KDirSelectDialog::url() const
00313 {
00314     return m_treeView->currentURL();
00315 }
00316 
00317 void KDirSelectDialog::slotCurrentChanged()
00318 {
00319     if ( d->comboLocked )
00320         return;
00321 
00322     KFileTreeViewItem *current = view()->currentKFileTreeViewItem();
00323     KURL u = current ? current->url() : (d->branch ? d->branch->rootUrl() : KURL());
00324 
00325     if ( u.isValid() )
00326     {
00327         if ( u.isLocalFile() )
00328             d->urlCombo->setEditText( u.path() );
00329 
00330         else // remote url
00331             d->urlCombo->setEditText( u.prettyURL() );
00332     }
00333     else
00334         d->urlCombo->setEditText( QString::null );
00335 }
00336 
00337 void KDirSelectDialog::slotURLActivated( const QString& text )
00338 {
00339     if ( text.isEmpty() )
00340         return;
00341 
00342     KURL url = KURL::fromPathOrURL( text );
00343     d->urlCombo->addToHistory( url.prettyURL() );
00344 
00345     if ( localOnly() && !url.isLocalFile() )
00346         return; // ### messagebox
00347 
00348     KURL oldURL = m_treeView->currentURL();
00349     if ( oldURL.isEmpty() )
00350         oldURL = KURL::fromPathOrURL( m_startDir );
00351 
00352     setCurrentURL( url );
00353 }
00354 
00355 KFileTreeBranch * KDirSelectDialog::createBranch( const KURL& url )
00356 {
00357     QString title = url.isLocalFile() ? url.path() : url.prettyURL();
00358     KFileTreeBranch *branch = view()->addBranch( url, title, m_showHiddenFolders->isChecked() );
00359     branch->setChildRecurse( false );
00360     view()->setDirOnlyMode( branch, true );
00361 
00362     return branch;
00363 }
00364 
00365 void KDirSelectDialog::slotComboTextChanged( const QString& text )
00366 {
00367     if ( d->branch )
00368     {
00369         KURL url = KURL::fromPathOrURL( text );
00370         KFileTreeViewItem *item = d->branch->findTVIByURL( url );
00371         if ( item )
00372         {
00373             view()->setCurrentItem( item );
00374             view()->setSelected( item, true );
00375             view()->ensureItemVisible( item );
00376             return;
00377         }
00378     }
00379 
00380     QListViewItem *item = view()->currentItem();
00381     if ( item )
00382     {
00383         item->setSelected( false );
00384         // 2002/12/27, deselected item is not repainted, so force it
00385         item->repaint();
00386     }
00387 }
00388 
00389 void KDirSelectDialog::slotContextMenu( KListView *, QListViewItem *, const QPoint& pos )
00390 {
00391     m_contextMenu->popup( pos );
00392 }
00393 
00394 void KDirSelectDialog::slotMkdir()
00395 {
00396     bool ok;
00397     QString where = url().prettyURL( +1, KURL::StripFileProtocol );
00398     QString directory = KIO::encodeFileName( KInputDialog::getText( i18n( "New Folder" ),
00399                                          i18n( "Create new folder in:\n%1" ).arg( where ),
00400                                          i18n("New Folder"), &ok, this));
00401     if (!ok)
00402       return;
00403       
00404     bool selectDirectory = true;
00405     bool writeOk = false;
00406     bool exists = false;
00407     KURL folderurl( url() );
00408 
00409     QStringList dirs = QStringList::split( QDir::separator(), directory );
00410     QStringList::ConstIterator it = dirs.begin();
00411 
00412     for ( ; it != dirs.end(); ++it )
00413     {
00414         folderurl.addPath( *it );
00415         exists = KIO::NetAccess::exists( folderurl, false, 0 );
00416         writeOk = !exists && KIO::NetAccess::mkdir( folderurl, topLevelWidget() );
00417     }
00418 
00419     if ( exists ) // url was already existant
00420     {
00421         QString which = folderurl.isLocalFile() ? folderurl.path() : folderurl.prettyURL();
00422         KMessageBox::sorry(this, i18n("A file or folder named %1 already exists.").arg(which));
00423         selectDirectory = false;
00424     }
00425     else if ( !writeOk ) {
00426         KMessageBox::sorry(this, i18n("You do not have permission to create that folder." ));
00427     }
00428     else if ( selectDirectory ) {
00429         setCurrentURL( folderurl );
00430     }
00431 }
00432 
00433 void KDirSelectDialog::slotShowHiddenFoldersToggled()
00434 {
00435     KURL currentURL = url();
00436 
00437     d->comboLocked = true;
00438     view()->removeBranch( d->branch );
00439     d->comboLocked = false;
00440 
00441     KURL root = rootUrl(d->startURL);
00442     d->branch = createBranch( root );
00443 
00444     setCurrentURL( currentURL );
00445 }
00446 
00447 // static
00448 KURL KDirSelectDialog::selectDirectory( const QString& startDir,
00449                                         bool localOnly,
00450                                         QWidget *parent,
00451                                         const QString& caption)
00452 {
00453     KDirSelectDialog myDialog( startDir, localOnly, parent,
00454                                "kdirselect dialog", true );
00455 
00456     if ( !caption.isNull() )
00457         myDialog.setCaption( caption );
00458 
00459     if ( myDialog.exec() == QDialog::Accepted )
00460         return myDialog.url();
00461     else
00462         return KURL();
00463 }
00464 
00465 void KDirSelectDialog::virtual_hook( int id, void* data )
00466 { KDialogBase::virtual_hook( id, data ); }
00467 
00468 #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 Thu Sep 23 17:12:21 2004 by doxygen 1.3.8-20040913 written by Dimitri van Heesch, © 1997-2003