• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KIO

kfiledialog.cpp

Go to the documentation of this file.
00001 // -*- c++ -*-
00002 /* This file is part of the KDE libraries
00003     Copyright (C) 1997, 1998 Richard Moore <rich@kde.org>
00004                   1998 Stephan Kulow <coolo@kde.org>
00005                   1998 Daniel Grana <grana@ie.iwi.unibe.ch>
00006                   1999,2000,2001,2002,2003 Carsten Pfeiffer <pfeiffer@kde.org>
00007                   2003 Clarence Dang <dang@kde.org>
00008                   2008 Jarosław Staniek <staniek@kde.org>
00009 
00010     This library is free software; you can redistribute it and/or
00011     modify it under the terms of the GNU Library General Public
00012     License as published by the Free Software Foundation; either
00013     version 2 of the License, or (at your option) any later version.
00014 
00015     This library is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018     Library General Public License for more details.
00019 
00020     You should have received a copy of the GNU Library General Public License
00021     along with this library; see the file COPYING.LIB.  If not, write to
00022     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00023     Boston, MA 02110-1301, USA.
00024 */
00025 
00026 #include "kfiledialog.h"
00027 
00028 #include <QtGui/QCheckBox>
00029 #include <QtGui/QKeyEvent>
00030 #include <QtGui/QFileDialog>
00031 
00032 #include <kimageio.h>
00033 #include <klocale.h>
00034 #include <kpushbutton.h>
00035 #include <config-kfile.h>
00036 #include <krecentdocument.h>
00037 #include <kimagefilepreview.h>
00038 #include <kpluginloader.h>
00039 #include <kpluginfactory.h>
00040 #include <kdebug.h>
00041 #include <kwindowsystem.h>
00042 #include "kabstractfilewidget.h"
00043 #include "kabstractfilemodule.h"
00044 #include "krecentdirs.h"
00045 
00047 #ifdef Q_WS_WIN
00048 const bool NATIVE_FILEDIALOGS_BY_DEFAULT = true;
00049 #else
00050 const bool NATIVE_FILEDIALOGS_BY_DEFAULT = false;
00051 #endif
00052 
00053 static QStringList mime2KdeFilter( const QStringList &mimeTypes, QString *allExtensions = 0 )
00054 {
00055   const KUrl emptyUrl;
00056   QStringList kdeFilter;
00057   QStringList allExt;
00058   foreach( const QString& mimeType, mimeTypes ) {
00059     KMimeType::Ptr mime( KMimeType::mimeType(mimeType) );
00060     if (mime) {
00061       allExt += mime->patterns();
00062       kdeFilter.append(mime->patterns().join(QLatin1String(" ")) +
00063                        QLatin1Char('|') +
00064                        mime->comment(emptyUrl));
00065     }
00066   }
00067   if (allExtensions) {
00068       allExt.sort();
00069       *allExtensions = allExt.join(QLatin1String(" "));
00070   }
00071   return kdeFilter;
00072 }
00076 static QString qtFilter(const QStringList& _filters)
00077 {
00078     QString converted;
00079     QStringList filters = _filters;
00080 
00081     foreach (const QString& current, filters) {
00082         QString new_f; //filter part
00083         QString new_name; //filter name part
00084         int p = current.indexOf('|');
00085         if (p==-1) {
00086             new_f = current;
00087             new_name = current; // nothing better found
00088         }
00089         else {
00090             new_f = current.left(p);
00091             new_name = current.mid(p+1);
00092         }
00093     //Qt filters assume anything in () is the file extension list
00094     new_name = new_name.replace('(', '[').replace(')',']').trimmed();
00095 
00096         //convert everything to lower case and remove dupes (doesn't matter on win32)
00097         QStringList allfiltersUnique;
00098         const QStringList origList( new_f.split(' ', QString::SkipEmptyParts) );
00099         foreach (const QString& origFilter, origList) {
00100     if (!allfiltersUnique.contains(origFilter, Qt::CaseInsensitive))
00101                 allfiltersUnique += origFilter.toLower();
00102         }
00103 
00104         if (!converted.isEmpty())
00105             converted += ";;";
00106 
00107         converted += (new_name + " (" + allfiltersUnique.join(" ") + QLatin1Char(')'));
00108     }
00109 
00110     // Strip escape characters from escaped '/' characters.
00111     converted.replace("\\/","/");
00112 
00113     return converted;
00114 }
00115 
00119 static QString qtFilter(const QString& filter)
00120 {
00121     // Qt format: "some text (*.first *.second)" or "All files (*)" separated by ;;
00122     // KDE format: "*.first *.second|Description" or "*|Description", separated by \n (Description is optional)
00123     QStringList filters;
00124     if (filter.isEmpty())
00125         filters += i18n("*|All files");
00126     else {
00127       // check if it's a mimefilter
00128       int pos = filter.indexOf('/');
00129       if (pos > 0 && filter[pos - 1] != '\\')
00130           filters = mime2KdeFilter(filter.split(QLatin1Char(' '), QString::SkipEmptyParts));
00131       else
00132           filters = filter.split('\n', QString::SkipEmptyParts);
00133     }
00134     return qtFilter(filters);
00135 }
00136 
00137 static KAbstractFileModule* s_module = 0;
00138 static KAbstractFileModule* fileModule()
00139 {
00140     if (!s_module) {
00141         // TODO fix memleak -- qApp post routine for deleting the module ?
00142         KPluginLoader loader("libkfilemodule");
00143         KPluginFactory *factory = loader.factory();
00144         if (!factory) {
00145             kWarning() << "KFileDialog wasn't able to find libkfilemodule: " << loader.errorString();
00146         } else {
00147             s_module = factory->create<KAbstractFileModule>();
00148             if (!s_module) {
00149                 kWarning() << "An error occurred while loading libkfilemodule";
00150             }
00151         }
00152     }
00153     return s_module;
00154 }
00155 
00156 class KFileDialogPrivate
00157 {
00158 public:
00160     class Native {
00161     public:
00162         Native()
00163           : mode(KFile::File),
00164             operationMode(KAbstractFileWidget::Opening)
00165         {
00166         }
00169         KUrl startDir() const
00170         {
00171             if (!s_startDir.isEmpty())
00172                 return s_startDir;
00173             if (!selectedUrls.isEmpty())
00174                 return selectedUrls.first();
00175             return KUrl();
00176         }
00179         static KUrl staticStartDir( const KUrl& defaultDir )
00180         {
00181             if ( s_startDir.isEmpty() )
00182               return defaultDir;
00183             return s_startDir;
00184         }
00185         static KUrl s_startDir;
00186         static bool s_allowNative;  // as fallback when we can't use natie dialog
00187         QString filter;
00188         QStringList mimeTypes;
00189         KUrl::List selectedUrls;
00190         KFile::Modes mode;
00191         KAbstractFileWidget::OperationMode operationMode;
00192     };
00193 
00194     KFileDialogPrivate()
00195       : native(0),
00196         w(0),
00197         cfgGroup(KGlobal::config(), ConfigGroup)
00198     {
00199         if (cfgGroup.readEntry("Native", NATIVE_FILEDIALOGS_BY_DEFAULT) &&
00200             KFileDialogPrivate::Native::s_allowNative)
00201             native = new Native;
00202     }
00203 
00204     static bool isNative()
00205     {
00206         if(!KFileDialogPrivate::Native::s_allowNative)
00207             return false;
00208         KConfigGroup cfgGroup(KGlobal::config(), ConfigGroup);
00209         return cfgGroup.readEntry("Native", NATIVE_FILEDIALOGS_BY_DEFAULT);
00210     }
00211 
00212     ~KFileDialogPrivate()
00213     {
00214         delete native;
00215     }
00216 
00217     Native* native;
00218     KAbstractFileWidget* w;
00219     KConfigGroup cfgGroup;
00220 };
00221 
00222 KUrl KFileDialogPrivate::Native::s_startDir;
00223 bool KFileDialogPrivate::Native::s_allowNative = true;
00224 
00225 KFileDialog::KFileDialog( const KUrl& startDir, const QString& filter,
00226                           QWidget *parent, QWidget* customWidget)
00227 #ifdef Q_WS_WIN
00228     : KDialog( parent , Qt::WindowMinMaxButtonsHint),
00229 #else
00230     : KDialog( parent ),
00231 #endif
00232       d( new KFileDialogPrivate )
00233 
00234 {
00235     // It would be nice to have this behind d->native but it doesn't work
00236     // because of derived classes like KEncodingDialog...
00237     // Dlopen the file widget from libkfilemodule
00238     QWidget* fileQWidget = fileModule()->createFileWidget(startDir, this);
00239     d->w = ::qobject_cast<KAbstractFileWidget *>(fileQWidget);
00240 
00241     if (d->native) {
00242         KFileDialogPrivate::Native::s_startDir = startDir;
00243         // check if it's a mimefilter
00244         int pos = filter.indexOf('/');
00245         if (pos > 0 && filter[pos - 1] != '\\')
00246           setMimeFilter(filter.split(QLatin1Char(' '), QString::SkipEmptyParts));
00247         else
00248           setFilter(filter);
00249         return;
00250     }
00251 
00252     setButtons( KDialog::None );
00253     restoreDialogSize(d->cfgGroup); // call this before the fileQWidget is set as the main widget.
00254                                    // otherwise the sizes for the components are not obeyed (ereslibre)
00255 
00256     d->w->setFilter(filter);
00257     setMainWidget(fileQWidget);
00258 
00259     d->w->okButton()->show();
00260     connect(d->w->okButton(), SIGNAL(clicked()), SLOT(slotOk()));
00261     d->w->cancelButton()->show();
00262     connect(d->w->cancelButton(), SIGNAL( clicked() ), SLOT( slotCancel() ));
00263 
00264     // Publish signals
00265     // TODO: Move the relevant signal declarations from KFileWidget to the
00266     //       KAbstractFileWidget interface?
00267     //
00268     //       Else, all of these connects (including "accepted") are not typesafe.
00269     kDebug (kfile_area) << "KFileDialog connecting signals";
00270     connect(fileQWidget, SIGNAL(fileSelected(const QString&)),
00271                          SIGNAL(fileSelected(const QString&)));
00272     connect(fileQWidget, SIGNAL(fileHighlighted(const QString&)),
00273                          SIGNAL(fileHighlighted(const QString&)));
00274     connect(fileQWidget, SIGNAL(selectionChanged()),
00275                          SIGNAL(selectionChanged()));
00276     connect(fileQWidget, SIGNAL(filterChanged(const QString&)),
00277                          SIGNAL(filterChanged(const QString&)));
00278 
00279     connect(fileQWidget, SIGNAL(accepted()), SLOT(accept()));
00280     //connect(fileQWidget, SIGNAL(canceled()), SLOT(slotCancel()));
00281 
00282     if (customWidget)
00283      d->w->setCustomWidget(QString(), customWidget);
00284 }
00285 
00286 
00287 KFileDialog::~KFileDialog()
00288 {
00289     delete d;
00290 }
00291 
00292 void KFileDialog::setLocationLabel(const QString& text)
00293 {
00294     if (d->native)
00295         return; // not available
00296     d->w->setLocationLabel(text);
00297 }
00298 
00299 void KFileDialog::setFilter(const QString& filter)
00300 {
00301     if (d->native) {
00302         d->native->filter = filter;
00303         return;
00304     }
00305     d->w->setFilter(filter);
00306 }
00307 
00308 QString KFileDialog::currentFilter() const
00309 {
00310     if (d->native)
00311         return QString(); // not available
00312     return d->w->currentFilter();
00313 }
00314 
00315 void KFileDialog::setMimeFilter( const QStringList& mimeTypes,
00316                                  const QString& defaultType )
00317 {
00318     d->w->setMimeFilter(mimeTypes, defaultType);
00319 
00320     if (d->native) {
00321         QString allExtensions;
00322         QStringList filters = mime2KdeFilter(mimeTypes, &allExtensions);
00323         if (defaultType.isEmpty() && (mimeTypes.count() > 1)) {
00324             filters.prepend(allExtensions + QLatin1Char('|') + i18n("All Supported Files"));
00325         }
00326         d->native->filter = filters.join(QLatin1String("\n"));
00327     }
00328 }
00329 
00330 void KFileDialog::clearFilter()
00331 {
00332     if (d->native) {
00333         d->native->filter.clear();
00334         return;
00335     }
00336     d->w->clearFilter();
00337 }
00338 
00339 QString KFileDialog::currentMimeFilter() const
00340 {
00341     return d->w->currentMimeFilter();
00342 }
00343 
00344 KMimeType::Ptr KFileDialog::currentFilterMimeType()
00345 {
00346     return KMimeType::mimeType( currentMimeFilter() );
00347 }
00348 
00349 void KFileDialog::setPreviewWidget(KPreviewWidgetBase *w)
00350 {
00351     if (d->native)
00352       return;
00353     d->w->setPreviewWidget(w);
00354 }
00355 
00356 void KFileDialog::setInlinePreviewShown(bool show)
00357 {
00358     if (d->native) {
00359         return;
00360     }
00361     d->w->setInlinePreviewShown(show);
00362 }
00363 
00364 QSize KFileDialog::sizeHint() const
00365 {
00366     return QSize(700, 450);
00367 }
00368 
00369 // This slot still exists mostly for compat purposes; for subclasses which reimplement slotOk
00370 void KFileDialog::slotOk()
00371 {
00372     if (d->native)
00373         return;
00374     d->w->slotOk();
00375 }
00376 
00377 // This slot still exists mostly for compat purposes; for subclasses which reimplement accept
00378 void KFileDialog::accept()
00379 {
00380     if (d->native)
00381         return;
00382     setResult( QDialog::Accepted ); // keep old behavior; probably not needed though
00383     d->w->accept();
00384     KConfigGroup cfgGroup(KGlobal::config(), ConfigGroup);
00385     KDialog::accept();
00386     emit okClicked();
00387 }
00388 
00389 // This slot still exists mostly for compat purposes; for subclasses which reimplement slotCancel
00390 void KFileDialog::slotCancel()
00391 {
00392     if (d->native)
00393         return;
00394     d->w->slotCancel();
00395     reject();
00396 }
00397 
00398 void KFileDialog::setUrl(const KUrl& url, bool clearforward)
00399 {
00400     if (d->native) {
00401          d->native->selectedUrls.clear();
00402          d->native->selectedUrls.append(url);
00403         return;
00404     }
00405     d->w->setUrl(url, clearforward);
00406 }
00407 
00408 void KFileDialog::setSelection(const QString& name)
00409 {
00410     if (d->native) {
00411          d->native->selectedUrls.clear();
00412          d->native->selectedUrls.append( KUrl(name) );
00413          return;
00414     }
00415     d->w->setSelection(name);
00416 }
00417 
00418 QString KFileDialog::getOpenFileName(const KUrl& startDir,
00419                                      const QString& filter,
00420                                      QWidget *parent, const QString& caption)
00421 {
00422     if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
00423         return QFileDialog::getOpenFileName(
00424             parent,
00425             caption.isEmpty() ? i18n("Open") : caption,
00426             KFileDialogPrivate::Native::staticStartDir( startDir ).toLocalFile(),
00427             qtFilter(filter) );
00428 // TODO use extra args?     QString * selectedFilter = 0, Options options = 0
00429     }
00430     KFileDialog dlg(startDir, filter, parent);
00431     dlg.setOperationMode( Opening );
00432 
00433     dlg.setMode( KFile::File | KFile::LocalOnly | KFile::ExistingOnly );
00434     dlg.setCaption(caption.isEmpty() ? i18n("Open") : caption);
00435 
00436     //dlg.d->ops->clearHistory();
00437     dlg.exec();
00438 
00439     return dlg.selectedFile();
00440 }
00441 
00442 QString KFileDialog::getOpenFileNameWId(const KUrl& startDir,
00443                                         const QString& filter,
00444                                         WId parent_id, const QString& caption)
00445 {
00446     if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile()))
00447         return KFileDialog::getOpenFileName(startDir, filter, 0, caption); // everything we can do...
00448     QWidget* parent = QWidget::find( parent_id );
00449     KFileDialogPrivate::Native::s_allowNative = false;
00450     KFileDialog dlg(startDir, filter, parent);
00451     if( parent == NULL && parent_id != 0 )
00452         KWindowSystem::setMainWindow( &dlg, parent_id );
00453 
00454     dlg.setOperationMode( KFileDialog::Opening );
00455 
00456     dlg.setMode( KFile::File | KFile::LocalOnly | KFile::ExistingOnly );
00457     dlg.setCaption(caption.isEmpty() ? i18n("Open") : caption);
00458 
00459     //dlg.d->ops->clearHistory();
00460     dlg.exec();
00461 
00462     return dlg.selectedFile();
00463 }
00464 
00465 QStringList KFileDialog::getOpenFileNames(const KUrl& startDir,
00466                                           const QString& filter,
00467                                           QWidget *parent,
00468                                           const QString& caption)
00469 {
00470     if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
00471         return QFileDialog::getOpenFileNames(
00472             parent,
00473             caption.isEmpty() ? i18n("Open") : caption,
00474             KFileDialogPrivate::Native::staticStartDir( startDir ).toLocalFile(),
00475             qtFilter( filter ) );
00476 // TODO use extra args?  QString * selectedFilter = 0, Options options = 0
00477     }
00478     KFileDialogPrivate::Native::s_allowNative = false;
00479     KFileDialog dlg(startDir, filter, parent);
00480     dlg.setOperationMode( Opening );
00481 
00482     dlg.setCaption(caption.isEmpty() ? i18n("Open") : caption);
00483     dlg.setMode(KFile::Files | KFile::LocalOnly | KFile::ExistingOnly);
00484     //dlg.d->ops->clearHistory();
00485     dlg.exec();
00486 
00487     return dlg.selectedFiles();
00488 }
00489 
00490 KUrl KFileDialog::getOpenUrl(const KUrl& startDir, const QString& filter,
00491                                 QWidget *parent, const QString& caption)
00492 {
00493     if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
00494         const QString fileName( KFileDialog::getOpenFileName(
00495             startDir, filter, parent, caption) );
00496         return fileName.isEmpty() ? KUrl() : KUrl::fromPath(fileName);
00497     }
00498     KFileDialogPrivate::Native::s_allowNative = false;
00499     KFileDialog dlg(startDir, filter, parent);
00500     dlg.setOperationMode( Opening );
00501 
00502     dlg.setCaption(caption.isEmpty() ? i18n("Open") : caption);
00503     dlg.setMode( KFile::File | KFile::ExistingOnly );
00504     //dlg.d->ops->clearHistory();
00505     dlg.exec();
00506 
00507     return dlg.selectedUrl();
00508 }
00509 
00510 KUrl::List KFileDialog::getOpenUrls(const KUrl& startDir,
00511                                           const QString& filter,
00512                                           QWidget *parent,
00513                                           const QString& caption)
00514 {
00515     if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
00516         const QStringList fileNames( KFileDialog::getOpenFileNames(
00517             startDir, filter, parent, caption) );
00518         return KUrl::List(fileNames);
00519     }
00520     KFileDialogPrivate::Native::s_allowNative = false;
00521     KFileDialog dlg(startDir, filter, parent);
00522     dlg.setOperationMode( Opening );
00523 
00524     dlg.setCaption(caption.isEmpty() ? i18n("Open") : caption);
00525     dlg.setMode(KFile::Files | KFile::ExistingOnly);
00526     //dlg.d->ops->clearHistory();
00527     dlg.exec();
00528 
00529     return dlg.selectedUrls();
00530 }
00531 
00532 void KFileDialog::setConfirmOverwrite(bool enable)
00533 {
00534     if (operationMode() == KFileDialog::Saving) {
00535         d->w->setConfirmOverwrite(enable);
00536     }
00537 }
00538 
00539 KUrl KFileDialog::getExistingDirectoryUrl(const KUrl& startDir,
00540                                           QWidget *parent,
00541                                           const QString& caption)
00542 {
00543     if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
00544         QString result( QFileDialog::getExistingDirectory(parent, caption,
00545             KFileDialogPrivate::Native::staticStartDir( startDir ).toLocalFile(),
00546             QFileDialog::ShowDirsOnly) );
00547         return result.isEmpty() ? KUrl() : KUrl::fromPath(result);
00548     }
00549     return fileModule()->selectDirectory(startDir, false, parent, caption);
00550 }
00551 
00552 QString KFileDialog::getExistingDirectory(const KUrl& startDir,
00553                                           QWidget *parent,
00554                                           const QString& caption)
00555 {
00556     if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
00557         return QFileDialog::getExistingDirectory(parent, caption,
00558             KFileDialogPrivate::Native::staticStartDir( startDir ).toLocalFile(),
00559             QFileDialog::ShowDirsOnly);
00560     }
00561     KUrl url = fileModule()->selectDirectory(startDir, true, parent, caption);
00562     if ( url.isValid() )
00563         return url.path();
00564     return QString();
00565 }
00566 
00567 KUrl KFileDialog::getImageOpenUrl( const KUrl& startDir, QWidget *parent,
00568                                    const QString& caption)
00569 {
00570     if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) { // everything we can do...
00571         const QStringList mimetypes( KImageIO::mimeTypes( KImageIO::Reading ) );
00572         return KFileDialog::getOpenUrl(startDir, mimetypes.join(" "), parent, caption);
00573     }
00574     QStringList mimetypes = KImageIO::mimeTypes( KImageIO::Reading );
00575     KFileDialogPrivate::Native::s_allowNative = false;
00576     KFileDialog dlg(startDir,
00577                     mimetypes.join(" "),
00578                     parent);
00579     dlg.setOperationMode( Opening );
00580     dlg.setCaption( caption.isEmpty() ? i18n("Open") : caption );
00581     dlg.setMode( KFile::File );
00582     dlg.setInlinePreviewShown( true );
00583 
00584     dlg.exec();
00585 
00586     return dlg.selectedUrl();
00587 }
00588 
00589 KUrl KFileDialog::selectedUrl() const
00590 {
00591     if (d->native)
00592         return d->native->selectedUrls.isEmpty() ? KUrl() : d->native->selectedUrls.first();
00593     return d->w->selectedUrl();
00594 }
00595 
00596 KUrl::List KFileDialog::selectedUrls() const
00597 {
00598     if (d->native)
00599         return d->native->selectedUrls;
00600     return d->w->selectedUrls();
00601 }
00602 
00603 QString KFileDialog::selectedFile() const
00604 {
00605     if (d->native)
00606         return selectedUrl().toLocalFile();
00607     return d->w->selectedFile();
00608 }
00609 
00610 QStringList KFileDialog::selectedFiles() const
00611 {
00612     if (d->native)
00613         return selectedUrls().toStringList();
00614     return d->w->selectedFiles();
00615 }
00616 
00617 KUrl KFileDialog::baseUrl() const
00618 {
00619     if (d->native)
00620         return selectedUrl().isEmpty() ? KUrl() : KUrl::fromPath(selectedUrl().path());
00621     return d->w->baseUrl();
00622 }
00623 
00624 QString KFileDialog::getSaveFileName(const KUrl& dir, const QString& filter,
00625                                      QWidget *parent,
00626                                      const QString& caption)
00627 {
00628     if (KFileDialogPrivate::isNative()) {
00629         bool defaultDir = dir.isEmpty();
00630         bool specialDir = !defaultDir && dir.protocol() == "kfiledialog";
00631         KUrl startDir;
00632         QString recentDirClass;
00633         if (specialDir) {
00634           startDir = KFileDialog::getStartUrl(dir, recentDirClass);
00635         }
00636         else if ( !specialDir && !defaultDir ) {
00637           if (!dir.isLocalFile())
00638               kWarning() << "non-local start dir " << dir;
00639           startDir = dir;
00640         }
00641 
00642         const QString result = QFileDialog::getSaveFileName(
00643             parent,
00644             caption.isEmpty() ? i18n("Save As") : caption,
00645             KFileDialogPrivate::Native::staticStartDir( startDir ).toLocalFile(),
00646             qtFilter(filter) );
00647 // TODO use extra args?     QString * selectedFilter = 0, Options options = 0
00648         if (!result.isEmpty()) {
00649             if (!recentDirClass.isEmpty())
00650                 KRecentDirs::add(recentDirClass, KUrl::fromPath(result).url());
00651             KRecentDocument::add(result);
00652         }
00653         return result;
00654     }
00655     bool defaultDir = dir.isEmpty();
00656     bool specialDir = !defaultDir && dir.protocol() == "kfiledialog";
00657     KFileDialog dlg( specialDir ? dir : KUrl(), filter, parent);
00658     if ( !specialDir && !defaultDir ) {
00659         if (!dir.isLocalFile())
00660             kWarning() << "KFileDialog::getSaveFileName called with non-local start dir " << dir;
00661         dlg.setSelection( dir.toLocalFile() ); // may also be a filename
00662     }
00663 
00664     dlg.setOperationMode( Saving );
00665     dlg.setMode( KFile::File );
00666     dlg.setCaption(caption.isEmpty() ? i18n("Save As") : caption);
00667 
00668     dlg.exec();
00669 
00670     QString filename = dlg.selectedFile();
00671     if (!filename.isEmpty())
00672         KRecentDocument::add(filename);
00673 
00674     return filename;
00675 }
00676 
00677 QString KFileDialog::getSaveFileNameWId(const KUrl& dir, const QString& filter,
00678                                      WId parent_id,
00679                                      const QString& caption)
00680 {
00681     if (KFileDialogPrivate::isNative()) {
00682         return KFileDialog::getSaveFileName(dir, filter, 0, caption); // everything we can do...
00683     }
00684     bool defaultDir = dir.isEmpty();
00685     bool specialDir = !defaultDir && dir.protocol() == "kfiledialog";
00686     QWidget* parent = QWidget::find( parent_id );
00687     KFileDialog dlg( specialDir ? dir : KUrl(), filter, parent);
00688     if( parent == NULL && parent_id != 0 )
00689         KWindowSystem::setMainWindow( &dlg, parent_id);
00690 
00691     if ( !specialDir && !defaultDir ) {
00692         if (!dir.isLocalFile())
00693             kWarning() << "KFileDialog::getSaveFileNameWId called with non-local start dir " << dir;
00694         dlg.setSelection( dir.toLocalFile() ); // may also be a filename
00695     }
00696 
00697     dlg.setOperationMode( Saving );
00698     dlg.setMode( KFile::File );
00699     dlg.setCaption(caption.isEmpty() ? i18n("Save As") : caption);
00700 
00701     dlg.exec();
00702 
00703     QString filename = dlg.selectedFile();
00704     if (!filename.isEmpty())
00705         KRecentDocument::add(filename);
00706 
00707     return filename;
00708 }
00709 
00710 KUrl KFileDialog::getSaveUrl(const KUrl& dir, const QString& filter,
00711                              QWidget *parent, const QString& caption)
00712 {
00713     if (KFileDialogPrivate::isNative() && (!dir.isValid() || dir.isLocalFile())) {
00714         const QString fileName( KFileDialog::getSaveFileName(
00715             dir, filter, parent, caption) );
00716         return fileName.isEmpty() ? KUrl() : KUrl::fromPath(fileName);
00717     }
00718     bool defaultDir = dir.isEmpty();
00719     bool specialDir = !defaultDir && dir.protocol() == "kfiledialog";
00720     KFileDialogPrivate::Native::s_allowNative = false;
00721     KFileDialog dlg(specialDir ? dir : KUrl(), filter, parent);
00722     if ( !specialDir && !defaultDir )
00723         dlg.setSelection( dir.url() ); // may also be a filename
00724 
00725     dlg.setCaption(caption.isEmpty() ? i18n("Save As") : caption);
00726     dlg.setOperationMode( Saving );
00727     dlg.setMode( KFile::File );
00728 
00729     dlg.exec();
00730 
00731     KUrl url = dlg.selectedUrl();
00732     if (url.isValid())
00733         KRecentDocument::add( url );
00734 
00735     return url;
00736 }
00737 
00738 void KFileDialog::setMode( KFile::Modes m )
00739 {
00740     if (d->native)
00741         d->native->mode = m;
00742     else
00743         d->w->setMode(m);
00744 }
00745 
00746 KFile::Modes KFileDialog::mode() const
00747 {
00748     if (d->native)
00749         return d->native->mode;
00750     return d->w->mode();
00751 }
00752 
00753 KPushButton * KFileDialog::okButton() const
00754 {
00755     return d->w->okButton();
00756 }
00757 
00758 KPushButton * KFileDialog::cancelButton() const
00759 {
00760     return d->w->cancelButton();
00761 }
00762 
00763 KUrlComboBox* KFileDialog::locationEdit() const
00764 {
00765     return d->w->locationEdit();
00766 }
00767 
00768 KFileFilterCombo* KFileDialog::filterWidget() const
00769 {
00770     return d->w->filterWidget();
00771 }
00772 
00773 KActionCollection * KFileDialog::actionCollection() const
00774 {
00775     return d->w->actionCollection();
00776 }
00777 
00778 void KFileDialog::setKeepLocation( bool keep )
00779 {
00780     if (d->native)
00781         return;
00782     d->w->setKeepLocation(keep);
00783 }
00784 
00785 bool KFileDialog::keepsLocation() const
00786 {
00787     if (d->native)
00788         return false;
00789     return d->w->keepsLocation();
00790 }
00791 
00792 void KFileDialog::setOperationMode( OperationMode mode )
00793 {
00794     if (d->native)
00795         d->native->operationMode = static_cast<KAbstractFileWidget::OperationMode>(mode);
00796     else
00797         d->w->setOperationMode(static_cast<KAbstractFileWidget::OperationMode>(mode));
00798 }
00799 
00800 KFileDialog::OperationMode KFileDialog::operationMode() const
00801 {
00802     if (d->native)
00803         return static_cast<KFileDialog::OperationMode>(d->native->operationMode);
00804     return static_cast<KFileDialog::OperationMode>(d->w->operationMode());
00805 }
00806 
00807 void KFileDialog::keyPressEvent( QKeyEvent *e )
00808 {
00809     if (d->native)
00810         return;
00811 
00812     if ( e->key() == Qt::Key_Escape )
00813     {
00814         e->accept();
00815         d->w->cancelButton()->animateClick();
00816     }
00817     else
00818         KDialog::keyPressEvent( e );
00819 }
00820 
00821 void KFileDialog::hideEvent( QHideEvent *e )
00822 {
00823     if (d->native)
00824         return;
00825 
00826     saveDialogSize(d->cfgGroup, KConfigBase::Persistent);
00827 
00828     KDialog::hideEvent( e );
00829 }
00830 
00831 // static
00832 KUrl KFileDialog::getStartUrl( const KUrl& startDir,
00833                                QString& recentDirClass )
00834 {
00835     return fileModule()->getStartUrl(startDir, recentDirClass);
00836 }
00837 
00838 void KFileDialog::setStartDir( const KUrl& directory )
00839 {
00840     if (KFileDialogPrivate::isNative())
00841         KFileDialogPrivate::Native::s_startDir = directory;
00842     fileModule()->setStartDir(directory);
00843 }
00844 
00845 KToolBar * KFileDialog::toolBar() const
00846 {
00847     return d->w->toolBar();
00848 }
00849 
00850 KAbstractFileWidget* KFileDialog::fileWidget()
00851 {
00852     return d->w;
00853 }
00854 
00855 #ifdef Q_WS_WIN
00856 int KFileDialog::exec()
00857 {
00858     if (!d->native || !KFileDialogPrivate::Native::s_allowNative) {
00859         KFileDialogPrivate::Native::s_allowNative = true;
00860         return KDialog::exec();
00861     }
00862 
00863 // not clear here to let KFileDialogPrivate::Native::startDir() return a useful value
00864 // d->native->selectedUrls.clear();
00865     switch (d->native->operationMode) {
00866     case KAbstractFileWidget::Opening:
00867     case KAbstractFileWidget::Other:
00868         if (d->native->mode & KFile::File) {
00869             KUrl url( KFileDialog::getOpenUrl(
00870                d->native->startDir(), d->native->filter, parentWidget(), windowTitle()) );
00871             if (url.isEmpty() || !url.isValid())
00872                 return QDialog::Rejected;
00873             d->native->selectedUrls.clear();
00874             d->native->selectedUrls.append(url);
00875             return QDialog::Accepted;
00876         }
00877         else if (d->native->mode & KFile::Files) {
00878             KUrl::List urls( KFileDialog::getOpenUrls(
00879                 d->native->startDir(), d->native->filter, parentWidget(), windowTitle()) );
00880             if (urls.isEmpty())
00881                 return QDialog::Rejected;
00882             d->native->selectedUrls = urls;
00883             return QDialog::Accepted;
00884         }
00885         else if (d->native->mode & KFile::Directory) {
00886             KUrl url( KFileDialog::getExistingDirectoryUrl(
00887                 d->native->startDir(), parentWidget(), windowTitle()) );
00888             if (url.isEmpty() || !url.isValid())
00889                 return QDialog::Rejected;
00890             d->native->selectedUrls.clear();
00891             d->native->selectedUrls.append(url);
00892             return QDialog::Accepted;
00893         }
00894         break;
00895     case KAbstractFileWidget::Saving:
00896         if (d->native->mode & KFile::File) {
00897             KUrl url( KFileDialog::getSaveUrl(
00898                 d->native->startDir(), d->native->filter, parentWidget(), windowTitle()) );
00899             if (url.isEmpty() || !url.isValid())
00900                 return QDialog::Rejected;
00901             d->native->selectedUrls.clear();
00902             d->native->selectedUrls.append(url);
00903             return QDialog::Accepted;
00904         }
00905         else if (d->native->mode & KFile::Directory) {
00906             KUrl url( KFileDialog::getExistingDirectoryUrl(
00907                 d->native->startDir(), parentWidget(), windowTitle()) );
00908             if (url.isEmpty() || !url.isValid())
00909                 return QDialog::Rejected;
00910             d->native->selectedUrls.clear();
00911             d->native->selectedUrls.append(url);
00912             return QDialog::Accepted;
00913         }
00914         break;
00915     default:;
00916     }
00917     return QDialog::Rejected;
00918 }
00919 #endif // Q_WS_WIN
00920 
00921 #ifdef Q_WS_WIN
00922 #define KF_EXTERN extern __declspec(dllimport)
00923 #else
00924 #define KF_EXTERN extern
00925 #endif
00926 
00927 typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption,
00928                                                           const QString &dir,
00929                                                           QFileDialog::Options options);
00930 KF_EXTERN _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook;
00931 
00932 typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString &caption,
00933                                                      const QString &dir, const QString &filter,
00934                                                      QString *selectedFilter,
00935                                                      QFileDialog::Options options);
00936 KF_EXTERN _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook;
00937 
00938 typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption,
00939                                                           const QString &dir, const QString &filter,
00940                                                           QString *selectedFilter,
00941                                                           QFileDialog::Options options);
00942 KF_EXTERN _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook;
00943 
00944 typedef QString (*_qt_filedialog_save_filename_hook)(QWidget * parent, const QString &caption,
00945                                                      const QString &dir, const QString &filter,
00946                                                      QString *selectedFilter,
00947                                                      QFileDialog::Options options);
00948 KF_EXTERN _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook;
00949 
00950 /*
00951  * This class is used to override Qt's QFileDialog calls with KFileDialog ones.
00952  * This is necessary because QPrintDialog calls QFileDialog::getSaveFileName() for
00953  * the print to file function.
00954  */
00955 class KFileDialogQtOverride
00956 {
00957 public:
00958     KFileDialogQtOverride()
00959     {
00960         if(!qt_filedialog_existing_directory_hook)
00961             qt_filedialog_existing_directory_hook=&getExistingDirectory;
00962         if(!qt_filedialog_open_filename_hook)
00963             qt_filedialog_open_filename_hook=&getOpenFileName;
00964         if(!qt_filedialog_open_filenames_hook)
00965             qt_filedialog_open_filenames_hook=&getOpenFileNames;
00966         if(!qt_filedialog_save_filename_hook)
00967             qt_filedialog_save_filename_hook=&getSaveFileName;
00968     }
00969 
00970     ~KFileDialogQtOverride() {
00971         if(qt_filedialog_existing_directory_hook == &getExistingDirectory)
00972             qt_filedialog_existing_directory_hook = 0;
00973         if(qt_filedialog_open_filename_hook == &getOpenFileName)
00974             qt_filedialog_open_filename_hook = 0;
00975         if(qt_filedialog_open_filenames_hook == &getOpenFileNames)
00976             qt_filedialog_open_filenames_hook=0;
00977         if(qt_filedialog_save_filename_hook == &getSaveFileName)
00978             qt_filedialog_save_filename_hook=0;
00979     }
00980 
00981     /*
00982      * Map a Qt filter string into a KDE one.
00983      */
00984     static QString qt2KdeFilter(const QString &f)
00985     {
00986         QString               filter;
00987         QTextStream           str(&filter, QIODevice::WriteOnly);
00988         QStringList           list(f.split(";;").replaceInStrings("/", "\\/"));
00989         QStringList::const_iterator it(list.begin()),
00990                               end(list.end());
00991         bool                  first=true;
00992 
00993         for(; it!=end; ++it)
00994         {
00995             int ob=(*it).lastIndexOf('('),
00996                 cb=(*it).lastIndexOf(')');
00997 
00998             if(-1!=cb && ob<cb)
00999             {
01000                 if(first)
01001                     first=false;
01002                 else
01003                     str << '\n';
01004                 str << (*it).mid(ob+1, (cb-ob)-1) << '|' << (*it).mid(0, ob);
01005             }
01006         }
01007 
01008         return filter;
01009     }
01010 
01011     /*
01012      * Map a KDE filter string into a Qt one.
01013      */
01014     static void kde2QtFilter(const QString &orig, const QString &kde, QString *sel)
01015     {
01016         if(sel)
01017         {
01018             QStringList           list(orig.split(";;"));
01019             QStringList::const_iterator it(list.begin()),
01020                                   end(list.end());
01021             int                   pos;
01022 
01023             for(; it!=end; ++it)
01024                 if(-1!=(pos=(*it).indexOf(kde)) && pos>0 &&
01025                    ('('==(*it)[pos-1] || ' '==(*it)[pos-1]) &&
01026                    (*it).length()>=kde.length()+pos &&
01027                    (')'==(*it)[pos+kde.length()] || ' '==(*it)[pos+kde.length()]))
01028                 {
01029                     *sel=*it;
01030                     return;
01031                 }
01032         }
01033     }
01034 
01035     static QString getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir,
01036                                         QFileDialog::Options options)
01037     {
01038         if (KFileDialogPrivate::isNative()) {
01039             if(qt_filedialog_existing_directory_hook)
01040                 qt_filedialog_existing_directory_hook=0; // do not override
01041             return QFileDialog::getExistingDirectory(parent, caption, dir, options);
01042         }
01043 
01044         KUrl url(KFileDialog::getExistingDirectory(KUrl(dir), parent, caption));
01045 
01046         if(url.isLocalFile())
01047             return url.pathOrUrl();
01048         else
01049             return QString();
01050     }
01051 
01052     static QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir,
01053                                    const QString &filter, QString *selectedFilter,
01054                                    QFileDialog::Options options)
01055     {
01056         if (KFileDialogPrivate::isNative()) {
01057             if(qt_filedialog_open_filename_hook)
01058                 qt_filedialog_open_filename_hook=0; // do not override
01059             return QFileDialog::getOpenFileName(parent, caption, dir, filter, selectedFilter, options);
01060         }
01061 
01062         KFileDialog dlg(KUrl(dir), qt2KdeFilter(filter), parent);
01063 
01064         dlg.setOperationMode(KFileDialog::Opening);
01065         dlg.setMode(KFile::File|KFile::LocalOnly);
01066         dlg.setCaption(caption);
01067         dlg.exec();
01068 
01069         QString rv(dlg.selectedFile());
01070 
01071         if(!rv.isEmpty())
01072             kde2QtFilter(filter, dlg.currentFilter(), selectedFilter);
01073 
01074         return rv;
01075     }
01076 
01077     static QStringList getOpenFileNames(QWidget *parent, const QString &caption, const QString &dir,
01078                                         const QString &filter, QString *selectedFilter,
01079                                         QFileDialog::Options options)
01080     {
01081         if (KFileDialogPrivate::isNative()) {
01082             if(qt_filedialog_open_filenames_hook)
01083                 qt_filedialog_open_filenames_hook=0; // do not override
01084             return QFileDialog::getOpenFileNames(parent, caption, dir, filter, selectedFilter, options);
01085         }
01086 
01087         KFileDialog dlg(KUrl(dir), qt2KdeFilter(filter), parent);
01088 
01089         dlg.setOperationMode(KFileDialog::Opening);
01090         dlg.setMode(KFile::Files|KFile::LocalOnly);
01091         dlg.setCaption(caption);
01092         dlg.exec();
01093 
01094         QStringList rv(dlg.selectedFiles());
01095 
01096         if(rv.count())
01097             kde2QtFilter(filter, dlg.currentFilter(), selectedFilter);
01098 
01099         return rv;
01100     }
01101 
01102     static QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
01103                                    const QString &filter, QString *selectedFilter,
01104                                    QFileDialog::Options options)
01105     {
01106         if (KFileDialogPrivate::isNative()) {
01107             if(qt_filedialog_save_filename_hook)
01108                 qt_filedialog_save_filename_hook=0; // do not override
01109             return QFileDialog::getSaveFileName(parent, caption, dir, filter, selectedFilter, options);
01110         }
01111 
01112         KFileDialog dlg(KUrl(dir), qt2KdeFilter(filter), parent);
01113 
01114         dlg.setOperationMode(KFileDialog::Saving);
01115         dlg.setMode(KFile::File|KFile::LocalOnly);
01116         dlg.setCaption(caption);
01117         dlg.setConfirmOverwrite(!(options & QFileDialog::DontConfirmOverwrite));
01118         dlg.exec();
01119 
01120         QString rv(dlg.selectedFile());
01121 
01122         if(!rv.isEmpty())
01123             kde2QtFilter(filter, dlg.currentFilter(), selectedFilter);
01124 
01125         return rv;
01126     }
01127 
01128 };
01129 
01130 static KFileDialogQtOverride qtOverride;
01131 
01132 #include "kfiledialog.moc"

KIO

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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