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