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.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:09:09 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003