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