00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
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
00179
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() )
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
00211 }
00212 }
00213 }
00214
00215 if ( !d->dirsToList.isEmpty() )
00216 openNextDir( d->branch->root() );
00217 }
00218
00219 void KDirSelectDialog::openNextDir( KFileTreeViewItem * )
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
00232 slotNextDirToList( item );
00233 }
00234
00235
00236 }
00237
00238 void KDirSelectDialog::slotNextDirToList( KFileTreeViewItem *item )
00239 {
00240
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
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;
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
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
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"