• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KFile

kdirselectdialog.cpp
Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2001,2002 Carsten Pfeiffer <pfeiffer@kde.org>
00003     Copyright (C) 2001 Michael Jarrett <michaelj@corel.com>
00004     Copyright (C) 2009 Shaun Reich <shaun.reich@kdemail.net>
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License version 2 as published by the Free Software Foundation.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kdirselectdialog.h"
00022 
00023 #include <QtCore/QDir>
00024 #include <QtCore/QStringList>
00025 #include <QtGui/QLayout>
00026 
00027 #include <kactioncollection.h>
00028 #include <kapplication.h>
00029 #include <kauthorized.h>
00030 #include <kconfig.h>
00031 #include <kconfiggroup.h>
00032 #include <khistorycombobox.h>
00033 #include <kfiledialog.h>
00034 #include <kfiletreeview.h>
00035 #include <kfileitemdelegate.h>
00036 #include <kglobalsettings.h>
00037 #include <kicon.h>
00038 #include <kinputdialog.h>
00039 #include <kio/job.h>
00040 #include <kio/deletejob.h>
00041 #include <kio/copyjob.h>
00042 #include <kio/netaccess.h>
00043 #include <kio/renamedialog.h>
00044 #include <jobuidelegate.h>
00045 #include <klocale.h>
00046 #include <kmessagebox.h>
00047 #include <krecentdirs.h>
00048 #include <ktoggleaction.h>
00049 #include <kurlcompletion.h>
00050 #include <kurlpixmapprovider.h>
00051 #include <kdebug.h>
00052 #include <kpropertiesdialog.h>
00053 #include <kpushbutton.h>
00054 #include <kmenu.h>
00055 
00056 #include "kfileplacesview.h"
00057 #include "kfileplacesmodel.h"
00058 // ### add mutator for treeview!
00059 
00060 
00061 
00062 class KDirSelectDialog::Private
00063 {
00064 public:
00065     Private( bool localOnly, KDirSelectDialog *parent )
00066         : m_parent( parent ),
00067           m_localOnly( localOnly ),
00068           m_comboLocked( false ),
00069           m_urlCombo(0)
00070     {
00071     }
00072 
00073     void readConfig(const KSharedConfigPtr &config, const QString& group);
00074     void saveConfig(KSharedConfigPtr config, const QString& group);
00075     void slotMkdir();
00076 
00077     void slotCurrentChanged();
00078     void slotExpand(const QModelIndex&);
00079     void slotUrlActivated(const QString&);
00080     void slotComboTextChanged(const QString&);
00081     void slotContextMenuRequested(const QPoint&);
00082     void slotNewFolder();
00083     void slotMoveToTrash();
00084     void slotDelete();
00085     void slotProperties();
00086 
00087     KDirSelectDialog *m_parent;
00088     bool m_localOnly : 1;
00089     bool m_comboLocked : 1;
00090     KUrl m_rootUrl;
00091     KUrl m_startDir;
00092     KFileTreeView *m_treeView;
00093     KMenu *m_contextMenu;
00094     KActionCollection *m_actions;
00095     KFilePlacesView *m_placesView;
00096     KHistoryComboBox *m_urlCombo;
00097     QString m_recentDirClass;
00098     KUrl m_startURL;
00099     KAction* moveToTrash;
00100     KAction* deleteAction;
00101     KAction* showHiddenFoldersAction;
00102 };
00103 
00104 void KDirSelectDialog::Private::readConfig(const KSharedConfig::Ptr &config, const QString& group)
00105 {
00106     m_urlCombo->clear();
00107 
00108     KConfigGroup conf( config, group );
00109     m_urlCombo->setHistoryItems( conf.readPathEntry( "History Items", QStringList() ));
00110 
00111     const QSize size = conf.readEntry("DirSelectDialog Size", QSize());
00112     if (size.isValid()) {
00113         m_parent->resize(size);
00114     }
00115 }
00116 
00117 void KDirSelectDialog::Private::saveConfig(KSharedConfig::Ptr config, const QString& group)
00118 {
00119     KConfigGroup conf( config, group );
00120     KConfigGroup::WriteConfigFlags flags(KConfigGroup::Persistent|KConfigGroup::Global);
00121     conf.writePathEntry( "History Items", m_urlCombo->historyItems(), flags );
00122     conf.writeEntry( "DirSelectDialog Size", m_parent->size(), flags );
00123 
00124     config->sync();
00125 }
00126 
00127 void KDirSelectDialog::Private::slotMkdir()
00128 {
00129     bool ok;
00130     QString where = m_parent->url().pathOrUrl();
00131     QString name = i18nc("folder name", "New Folder" );
00132     if ( m_parent->url().isLocalFile() && QFileInfo( m_parent->url().path(KUrl::AddTrailingSlash) + name ).exists() )
00133         name = KIO::RenameDialog::suggestName( m_parent->url(), name );
00134 
00135     QString directory = KIO::encodeFileName( KInputDialog::getText( i18nc("@title:window", "New Folder" ),
00136                                          i18nc("@label:textbox", "Create new folder in:\n%1" ,  where ),
00137                                          name, &ok, m_parent));
00138     if (!ok)
00139       return;
00140 
00141     bool selectDirectory = true;
00142     bool writeOk = false;
00143     bool exists = false;
00144     KUrl folderurl( m_parent->url() );
00145 
00146     const QStringList dirs = directory.split( '/', QString::SkipEmptyParts );
00147     QStringList::ConstIterator it = dirs.begin();
00148 
00149     for ( ; it != dirs.end(); ++it )
00150     {
00151         folderurl.addPath( *it );
00152         exists = KIO::NetAccess::exists( folderurl, KIO::NetAccess::DestinationSide, 0 );
00153         writeOk = !exists && KIO::NetAccess::mkdir( folderurl, m_parent->topLevelWidget() );
00154     }
00155 
00156     if ( exists ) // url was already existent
00157     {
00158         QString which = folderurl.isLocalFile() ? folderurl.path() : folderurl.prettyUrl();
00159         KMessageBox::sorry(m_parent, i18n("A file or folder named %1 already exists.", which));
00160         selectDirectory = false;
00161     }
00162     else if ( !writeOk ) {
00163         KMessageBox::sorry(m_parent, i18n("You do not have permission to create that folder." ));
00164     }
00165     else if ( selectDirectory ) {
00166         m_parent->setCurrentUrl( folderurl );
00167     }
00168 }
00169 
00170 void KDirSelectDialog::Private::slotCurrentChanged()
00171 {
00172     if ( m_comboLocked )
00173         return;
00174 
00175     const KUrl u = m_treeView->currentUrl();
00176 
00177     if ( u.isValid() )
00178     {
00179         if ( u.isLocalFile() )
00180             m_urlCombo->setEditText( u.toLocalFile() );
00181 
00182         else // remote url
00183             m_urlCombo->setEditText( u.prettyUrl() );
00184     }
00185     else
00186         m_urlCombo->setEditText( QString() );
00187 }
00188 
00189 void KDirSelectDialog::Private::slotUrlActivated( const QString& text )
00190 {
00191     if ( text.isEmpty() )
00192         return;
00193 
00194     KUrl url( text );
00195     m_urlCombo->addToHistory( url.prettyUrl() );
00196 
00197     if ( m_parent->localOnly() && !url.isLocalFile() )
00198         return; //FIXME: messagebox for the user
00199 
00200     KUrl oldUrl = m_treeView->currentUrl();
00201     if ( oldUrl.isEmpty() )
00202         oldUrl = m_startDir;
00203 
00204     m_parent->setCurrentUrl( oldUrl );
00205 }
00206 
00207 void KDirSelectDialog::Private::slotComboTextChanged( const QString& text )
00208 {
00209     m_treeView->blockSignals(true);
00210     KUrl url( text );
00211 #ifdef Q_OS_WIN
00212     if( url.isLocalFile() && !m_treeView->rootUrl().isParentOf( url ) )
00213     {
00214         KUrl tmp = url.upUrl();
00215         while(tmp != KUrl("file:///")) {
00216             url = tmp;
00217             tmp = url.upUrl();
00218         }
00219         m_treeView->setRootUrl( url );
00220     }
00221 #endif
00222     m_treeView->setCurrentUrl( url );
00223     m_treeView->blockSignals( false );
00224 }
00225 
00226 void KDirSelectDialog::Private::slotContextMenuRequested( const QPoint& pos )
00227 {
00228     m_contextMenu->popup( m_treeView->viewport()->mapToGlobal(pos) );
00229 }
00230 
00231 void KDirSelectDialog::Private::slotExpand(const QModelIndex &index)
00232 {
00233     m_treeView->setExpanded(index, !m_treeView->isExpanded(index));
00234 }
00235 
00236 void KDirSelectDialog::Private::slotNewFolder()
00237 {
00238     slotMkdir();
00239 }
00240 
00241 void KDirSelectDialog::Private::slotMoveToTrash()
00242 {
00243     const KUrl url = m_treeView->selectedUrl();
00244     KIO::JobUiDelegate job;
00245     if (job.askDeleteConfirmation(KUrl::List() << url, KIO::JobUiDelegate::Trash, KIO::JobUiDelegate::DefaultConfirmation)) {
00246         KIO::CopyJob* copyJob = KIO::trash(url);
00247         copyJob->ui()->setWindow(this->m_parent);
00248         copyJob->ui()->setAutoErrorHandlingEnabled(true);
00249     }
00250 }
00251 
00252 void KDirSelectDialog::Private::slotDelete()
00253 {
00254     const KUrl url = m_treeView->selectedUrl();
00255     KIO::JobUiDelegate job;
00256     if (job.askDeleteConfirmation(KUrl::List() << url, KIO::JobUiDelegate::Delete, KIO::JobUiDelegate::DefaultConfirmation)) {
00257         KIO::DeleteJob* deleteJob = KIO::del(url);
00258         deleteJob->ui()->setWindow(this->m_parent);
00259         deleteJob->ui()->setAutoErrorHandlingEnabled(true);
00260     }
00261 }
00262 
00263 void KDirSelectDialog::Private::slotProperties()
00264 {
00265     KPropertiesDialog* dialog = 0;
00266     dialog = new KPropertiesDialog(m_treeView->selectedUrl(), this->m_parent);
00267     dialog->setAttribute(Qt::WA_DeleteOnClose);
00268     dialog->show();
00269 }
00270 
00271 
00272 KDirSelectDialog::KDirSelectDialog(const KUrl &startDir, bool localOnly,
00273                                    QWidget *parent)
00274 #ifdef Q_WS_WIN
00275     : KDialog( parent , Qt::WindowMinMaxButtonsHint),
00276 #else
00277     : KDialog( parent ),
00278 #endif
00279       d( new Private( localOnly, this ) )
00280 {
00281     setCaption( i18nc("@title:window","Select Folder") );
00282     setButtons( Ok | Cancel | User1 );
00283     setButtonGuiItem( User1, KGuiItem( i18nc("@action:button","New Folder..."), "folder-new" ) );
00284     setDefaultButton(Ok);
00285     button(Ok)->setFocus();
00286 
00287     QFrame *page = new QFrame(this);
00288     setMainWidget(page);
00289     QHBoxLayout *hlay = new QHBoxLayout( page);
00290     hlay->setMargin(0);
00291     QVBoxLayout *mainLayout = new QVBoxLayout();
00292     d->m_actions=new KActionCollection(this);
00293     d->m_actions->addAssociatedWidget(this);
00294     d->m_placesView = new KFilePlacesView( page );
00295     d->m_placesView->setModel(new KFilePlacesModel(d->m_placesView));
00296     d->m_placesView->setObjectName( QLatin1String( "speedbar" ) );
00297     d->m_placesView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
00298     d->m_placesView->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
00299     connect( d->m_placesView, SIGNAL( urlChanged( const KUrl& )),
00300              SLOT( setCurrentUrl( const KUrl& )) );
00301     hlay->addWidget( d->m_placesView );
00302     hlay->addLayout( mainLayout );
00303 
00304     d->m_treeView = new KFileTreeView(page);
00305     d->m_treeView->setDirOnlyMode(true);
00306     d->m_treeView->setContextMenuPolicy(Qt::CustomContextMenu);
00307 
00308     for (int i = 1; i < d->m_treeView->model()->columnCount(); ++i)
00309         d->m_treeView->hideColumn(i);
00310 
00311     d->m_urlCombo = new KHistoryComboBox( page);
00312     d->m_urlCombo->setLayoutDirection( Qt::LeftToRight );
00313     d->m_urlCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
00314     d->m_urlCombo->setTrapReturnKey( true );
00315     d->m_urlCombo->setPixmapProvider( new KUrlPixmapProvider() );
00316     KUrlCompletion *comp = new KUrlCompletion();
00317     comp->setMode( KUrlCompletion::DirCompletion );
00318     d->m_urlCombo->setCompletionObject( comp, true );
00319     d->m_urlCombo->setAutoDeleteCompletionObject( true );
00320     d->m_urlCombo->setDuplicatesEnabled( false );
00321 
00322     d->m_contextMenu = new KMenu( this );
00323 
00324     KAction* newFolder = new KAction( i18nc("@action:inmenu","New Folder..."), this);
00325     d->m_actions->addAction( newFolder->objectName(), newFolder );
00326     newFolder->setIcon( KIcon( "folder-new" ) );
00327     newFolder->setShortcut( Qt::Key_F10);
00328     connect( newFolder, SIGNAL( triggered( bool ) ), this, SLOT( slotNewFolder() ) );
00329     d->m_contextMenu->addAction( newFolder );
00330 
00331     d->moveToTrash = new KAction( i18nc( "@action:inmenu","Move to Trash" ), this );
00332     d->m_actions->addAction( d->moveToTrash->objectName(), d->moveToTrash );
00333     d->moveToTrash->setIcon( KIcon( "user-trash" ) );
00334     d->moveToTrash->setShortcut(KShortcut(Qt::Key_Delete));
00335     connect( d->moveToTrash, SIGNAL( triggered( bool ) ), this, SLOT( slotMoveToTrash() ) );
00336     d->m_contextMenu->addAction( d->moveToTrash );
00337 
00338     d->deleteAction = new KAction( i18nc("@action:inmenu","Delete"), this );
00339     d->m_actions->addAction( d->deleteAction->objectName(), d->deleteAction );
00340     d->deleteAction->setIcon( KIcon( "edit-delete" ) );
00341     d->deleteAction->setShortcut( KShortcut( Qt::SHIFT + Qt::Key_Delete ) );
00342     connect( d->deleteAction, SIGNAL( triggered( bool ) ), this, SLOT( slotDelete() ) );
00343     d->m_contextMenu->addAction( d->deleteAction );
00344 
00345     d->m_contextMenu->addSeparator();
00346 
00347     d->showHiddenFoldersAction = new KToggleAction( i18nc("@option:check", "Show Hidden Folders"), this );
00348     d->m_actions->addAction( d->showHiddenFoldersAction->objectName(), d->showHiddenFoldersAction );
00349     d->showHiddenFoldersAction->setShortcut( Qt::Key_F8 );
00350     connect( d->showHiddenFoldersAction, SIGNAL( triggered( bool ) ), d->m_treeView, SLOT( setShowHiddenFiles( bool ) ) );
00351     d->m_contextMenu->addAction( d->showHiddenFoldersAction );
00352     d->m_contextMenu->addSeparator();
00353 
00354     KAction* propertiesAction = new KAction( i18nc("@action:inmenu","Properties"), this);
00355     d->m_actions->addAction(propertiesAction->objectName(), propertiesAction);
00356     propertiesAction->setIcon(KIcon("document-properties"));
00357     propertiesAction->setShortcut(KShortcut(Qt::ALT + Qt::Key_Return));
00358     connect( propertiesAction, SIGNAL( triggered( bool ) ), this, SLOT( slotProperties() ) );
00359     d->m_contextMenu->addAction( propertiesAction );
00360 
00361     d->m_startURL = KFileDialog::getStartUrl( startDir, d->m_recentDirClass );
00362     if ( localOnly && !d->m_startURL.isLocalFile() )
00363     {
00364         d->m_startURL = KUrl();
00365         QString docPath = KGlobalSettings::documentPath();
00366         if (QDir(docPath).exists())
00367             d->m_startURL.setPath( docPath );
00368         else
00369             d->m_startURL.setPath( QDir::homePath() );
00370     }
00371 
00372     d->m_startDir = d->m_startURL;
00373     d->m_rootUrl = d->m_treeView->rootUrl();
00374 
00375     d->readConfig( KGlobal::config(), "DirSelect Dialog" );
00376 
00377     mainLayout->addWidget( d->m_treeView, 1 );
00378     mainLayout->addWidget( d->m_urlCombo, 0 );
00379 
00380     connect( d->m_treeView, SIGNAL( currentChanged(const KUrl&)),
00381              SLOT( slotCurrentChanged() ));
00382     connect( d->m_treeView, SIGNAL( activated(const QModelIndex&)),
00383              SLOT( slotExpand(const QModelIndex&) ));
00384     connect( d->m_treeView, SIGNAL( customContextMenuRequested( const QPoint & )),
00385              SLOT( slotContextMenuRequested( const QPoint & )));
00386 
00387     connect( d->m_urlCombo, SIGNAL( editTextChanged( const QString& ) ),
00388              SLOT( slotComboTextChanged( const QString& ) ));
00389     connect( d->m_urlCombo, SIGNAL( activated( const QString& )),
00390              SLOT( slotUrlActivated( const QString& )));
00391     connect( d->m_urlCombo, SIGNAL( returnPressed( const QString& )),
00392              SLOT( slotUrlActivated( const QString& )));
00393 
00394     connect(this, SIGNAL(user1Clicked()), this, SLOT(slotNewFolder()));
00395 
00396     setCurrentUrl(d->m_startURL);
00397 }
00398 
00399 
00400 KDirSelectDialog::~KDirSelectDialog()
00401 {
00402     delete d;
00403 }
00404 
00405 KUrl KDirSelectDialog::url() const
00406 {
00407     KUrl comboUrl(d->m_urlCombo->currentText());
00408 
00409     if ( comboUrl.isValid() ) {
00410        KIO::StatJob *statJob = KIO::stat(comboUrl, KIO::HideProgressInfo);
00411        const bool ok = KIO::NetAccess::synchronousRun(statJob, 0);
00412        if (ok && statJob->statResult().isDir()) {
00413            return comboUrl;
00414        }
00415     }
00416 
00417     kDebug() << comboUrl.path() << " is not an accessible directory";
00418     return d->m_treeView->currentUrl();
00419 }
00420 
00421 QAbstractItemView* KDirSelectDialog::view() const
00422 {
00423     return d->m_treeView;
00424 }
00425 
00426 bool KDirSelectDialog::localOnly() const
00427 {
00428     return d->m_localOnly;
00429 }
00430 
00431 KUrl KDirSelectDialog::startDir() const
00432 {
00433     return d->m_startDir;
00434 }
00435 
00436 void KDirSelectDialog::setCurrentUrl( const KUrl& url )
00437 {
00438     if ( !url.isValid() )
00439         return;
00440 
00441     if (url.protocol() != d->m_rootUrl.protocol()) {
00442         KUrl u( url );
00443         u.cd("/");//NOTE portability?
00444         d->m_treeView->setRootUrl( u );
00445         d->m_rootUrl = u;
00446     }
00447 
00448     //Check if url represents a hidden folder and enable showing them
00449     QString fileName = url.fileName();
00450     //TODO a better hidden file check?
00451     bool isHidden = fileName.length() > 1 && fileName[0] == '.' &&
00452                                                 (fileName.length() > 2 ? fileName[1] != '.' : true);
00453     bool showHiddenFiles = isHidden && !d->m_treeView->showHiddenFiles();
00454     if (showHiddenFiles) {
00455         d->showHiddenFoldersAction->setChecked(true);
00456         d->m_treeView->setShowHiddenFiles(true);
00457     }
00458 
00459     d->m_treeView->setCurrentUrl( url );
00460 }
00461 
00462 void KDirSelectDialog::accept()
00463 {
00464     KUrl selectedUrl = url();
00465     if (!selectedUrl.isValid()) {
00466         return;
00467     }
00468 
00469     if (!d->m_recentDirClass.isEmpty()) {
00470         KRecentDirs::add(d->m_recentDirClass, selectedUrl.url());
00471     }
00472 
00473     d->m_urlCombo->addToHistory( selectedUrl.prettyUrl() );
00474     KFileDialog::setStartDir( url() );
00475 
00476     KDialog::accept();
00477 }
00478 
00479 void KDirSelectDialog::hideEvent( QHideEvent *event )
00480 {
00481     d->saveConfig( KGlobal::config(), "DirSelect Dialog" );
00482 
00483     KDialog::hideEvent(event);
00484 }
00485 
00486 // static
00487 KUrl KDirSelectDialog::selectDirectory( const KUrl& startDir,
00488                                         bool localOnly,
00489                                         QWidget *parent,
00490                                         const QString& caption)
00491 {
00492     KDirSelectDialog myDialog( startDir, localOnly, parent);
00493 
00494     if ( !caption.isNull() )
00495         myDialog.setCaption( caption );
00496 
00497     if ( myDialog.exec() == QDialog::Accepted )
00498         return KIO::NetAccess::mostLocalUrl(myDialog.url(),parent);
00499     else
00500         return KUrl();
00501 }
00502 
00503 #include "kdirselectdialog.moc"

KFile

Skip menu "KFile"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal