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 #include <kinputdialog.h>
00041 #include <kio/netaccess.h>
00042 #include <kmessagebox.h>
00043
00044 #include "kfiletreeview.h"
00045 #include "kdirselectdialog.h"
00046
00047
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
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
00184
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() )
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
00216 }
00217 }
00218 }
00219
00220 if ( !d->dirsToList.isEmpty() )
00221 openNextDir( d->branch->root() );
00222 }
00223
00224 void KDirSelectDialog::openNextDir( KFileTreeViewItem * )
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
00237 slotNextDirToList( item );
00238 }
00239
00240
00241 }
00242
00243 void KDirSelectDialog::slotNextDirToList( KFileTreeViewItem *item )
00244 {
00245
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
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;
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
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 )
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
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"