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 <kmessagebox.h> 00043 00044 #include "kfiletreeview.h" 00045 #include "kdirselectdialog.h" 00046 00047 // ### add mutator for treeview! 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 // Create dir list 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 // removing the root-item causes the currentChanged() signal to be 00184 // emitted, but we don't want to update the location-combo yet. 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() ) // e.g. ftp://host.com/ -> just list the root dir 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 // qDebug( "List: %s", dirToList.url().latin1()); 00216 } 00217 } 00218 } 00219 00220 if ( !d->dirsToList.isEmpty() ) 00221 openNextDir( d->branch->root() ); 00222 } 00223 00224 void KDirSelectDialog::openNextDir( KFileTreeViewItem * /*parent*/ ) 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 // already open -> go to next one 00237 slotNextDirToList( item ); 00238 } 00239 // else 00240 // qDebug("###### openNextDir: item not found!"); 00241 } 00242 00243 void KDirSelectDialog::slotNextDirToList( KFileTreeViewItem *item ) 00244 { 00245 // scroll to make item the topmost item 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 // remote url 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; // ### messagebox 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 // 2002/12/27, deselected item is not repainted, so force it 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 ) // url was already existant 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 // static 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"
KDE Logo
This file is part of the documentation for kio Library Version 3.3.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 17 11:29:24 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003