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"