[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: Re: [patch] Native mode for KFileDialog
From: Jaroslaw Staniek <js () iidea ! pl>
Date: 2008-06-13 21:15:45
Message-ID: 4852E381.7090204 () iidea ! pl
[Download RAW message or body]
Updated patch for Christian's changes (r819160).
--
regards / pozdrawiam, Jaroslaw Staniek
Sponsored by OpenOffice Polska (http://www.openoffice.com.pl/en) to work on
Kexi & KOffice (http://www.kexi.pl/en, http://www.koffice.org/kexi)
KDE Libraries for MS Windows (http://windows.kde.org)
["native_kfiledialog2.patch" (text/plain)]
Index: kio/kfile/kfiledialog.h
===================================================================
--- kio/kfile/kfiledialog.h (wersja 820309)
+++ kio/kfile/kfiledialog.h (kopia robocza)
@@ -691,6 +691,11 @@
*/
static void setStartDir( const KUrl& directory );
+#ifdef Q_WS_WIN
+public Q_SLOTS:
+ int exec();
+#endif
+
Q_SIGNALS:
/**
* Emitted when the user selects a file. It is only emitted in single-
Index: kio/kfile/kfiledialog.cpp
===================================================================
--- kio/kfile/kfiledialog.cpp (wersja 820309)
+++ kio/kfile/kfiledialog.cpp (kopia robocza)
@@ -5,6 +5,7 @@
1998 Daniel Grana <grana@ie.iwi.unibe.ch>
1999,2000,2001,2002,2003 Carsten Pfeiffer <pfeiffer@kde.org>
2003 Clarence Dang <dang@kde.org>
+ 2008 Jaroslaw Staniek <js@iidea.pl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -23,7 +24,6 @@
*/
#include "kfiledialog.h"
-#include "kabstractfilewidget.h"
#include <QtGui/QCheckBox>
#include <QtGui/QKeyEvent>
@@ -37,8 +37,10 @@
#include <kimagefilepreview.h>
#include <kpluginloader.h>
#include <kpluginfactory.h>
+#include <kdebug.h>
+#include "kabstractfilewidget.h"
#include "kabstractfilemodule.h"
-#include <kdebug.h>
+#include "krecentdirs.h"
#ifdef Q_WS_X11
#include <qx11info_x11.h>
@@ -46,6 +48,76 @@
#include <fixx11h.h>
#endif
+#include <QtGui/QFileDialog>
+
+/** @return File dialog filter in Qt format for @a filters
+ * or "All files (*)" for empty list.
+ */
+static QString qtFilter(const QStringList& filters)
+{
+ QString converted;
+ foreach (const QString& current, filters) {
+ QString new_f; //filter part
+ QString new_name; //filter name part
+ int p = current.indexOf('|');
+ if (p==-1) {
+ new_f = current;
+ new_name = current; // nothing better found
+ }
+ else {
+ new_f = current.left(p);
+ new_name = current.mid(p+1);
+ }
+ //remove (.....) from name
+ p = new_name.indexOf('(');
+ int p2 = new_name.lastIndexOf(')');
+ QString new_name1, new_name2;
+ if (p!=-1)
+ new_name1 = new_name.left(p);
+ if (p2!=-1)
+ new_name2 = new_name.mid(p2+1);
+ if (!new_name1.isEmpty() || !new_name2.isEmpty())
+ new_name = new_name1.trimmed() + " " + new_name2.trimmed();
+ new_name.replace('(',"");
+ new_name.replace(')',"");
+ new_name = new_name.trimmed();
+
+ // make filters unique: remove uppercase extensions (case doesn't matter on \
win32, BTW) + QStringList allfiltersUnique;
+ const QStringList origList( new_f.split(' ', QString::SkipEmptyParts) );
+ foreach (const QString& origFilter, origList) {
+ if (origFilter == origFilter.toLower())
+ allfiltersUnique += origFilter;
+ }
+
+ if (!converted.isEmpty())
+ converted += ";;";
+
+ converted += (new_name + " (" + allfiltersUnique.join(" ") + ")");
+ } // foreach
+
+ // Strip escape characters from escaped '/' characters.
+ for (int pos = 0; (pos = converted.indexOf("\\/", pos)) != -1; ++pos)
+ converted.remove(pos, 1);
+
+ return converted;
+}
+
+/** @return File dialog filter in Qt format for @a filter in KDE format
+ * or "All files (*)" for empty filter.
+ */
+static QString qtFilter(const QString& filter)
+{
+ // Qt format: "some text (*.first *.second)" or "All files (*)" separated by ;;
+ // KDE format: "*.first *.second|Description" or "*|Description", separated by \
\n (Description is optional) + QStringList filters;
+ if (filter.isEmpty())
+ filters += i18n("*|All files");
+ else
+ filters = filter.split('\n', QString::SkipEmptyParts);
+ return qtFilter(filters);
+}
+
static KAbstractFileModule* s_module = 0;
static KAbstractFileModule* fileModule()
{
@@ -68,15 +140,48 @@
class KFileDialogPrivate
{
public:
- KFileDialogPrivate() : w(0)
+ class Native {
+ public:
+ Native()
+ : mode(KFile::File),
+ operationMode(KAbstractFileWidget::Opening)
+ {
+ }
+ static KUrl startDir;
+ QString filter;
+ QStringList mimeTypes;
+ KUrl::List selectedUrls;
+ KFile::Modes mode;
+ KAbstractFileWidget::OperationMode operationMode;
+ };
+
+ KFileDialogPrivate()
+ : native(0),
+ w(0),
+ cfgGroup(KGlobal::config(), ConfigGroup)
{
- cfgGroup = KConfigGroup(KGlobal::config(), ConfigGroup);
+ if (cfgGroup.readEntry("Native", false))
+ native = new Native;
}
+ static bool isNative()
+ {
+ KConfigGroup cfgGroup(KGlobal::config(), ConfigGroup);
+ return cfgGroup.readEntry("Native", false);
+ }
+
+ ~KFileDialogPrivate()
+ {
+ delete native;
+ }
+
+ Native* native;
KAbstractFileWidget* w;
KConfigGroup cfgGroup;
};
+KUrl KFileDialogPrivate::Native::startDir;
+
KFileDialog::KFileDialog( const KUrl& startDir, const QString& filter,
QWidget *parent, QWidget* customWidget)
#ifdef Q_WS_WIN
@@ -87,13 +192,21 @@
d( new KFileDialogPrivate )
{
- setButtons( KDialog::None );
- restoreDialogSize(d->cfgGroup); // call this before the fileQWidget is set as \
the main widget.
- // otherwise the sizes for the components are \
not obeyed (ereslibre) + if (!d->native) {
+ setButtons( KDialog::None );
+ restoreDialogSize(d->cfgGroup); // call this before the fileQWidget is set \
as the main widget. + // otherwise the sizes \
for the components are not obeyed (ereslibre) + }
// Dlopen the file widget from libkfilemodule
QWidget* fileQWidget = fileModule()->createFileWidget(startDir, this);
d->w = ::qobject_cast<KAbstractFileWidget *>(fileQWidget);
+
+ if (d->native) {
+ d->native->filter = filter;
+ return;
+ }
+
d->w->setFilter(filter);
setMainWidget(fileQWidget);
@@ -132,16 +245,24 @@
void KFileDialog::setLocationLabel(const QString& text)
{
+ if (d->native)
+ return; // not available
d->w->setLocationLabel(text);
}
void KFileDialog::setFilter(const QString& filter)
{
+ if (d->native) {
+ d->native->filter = filter;
+ return;
+ }
d->w->setFilter(filter);
}
QString KFileDialog::currentFilter() const
{
+ if (d->native)
+ return QString(); // not available
return d->w->currentFilter();
}
@@ -149,10 +270,24 @@
const QString& defaultType )
{
d->w->setMimeFilter(mimeTypes, defaultType);
+
+ if (d->native) {
+ QString kdeFilter;
+ foreach( const QString& mimeType, mimeTypes ) {
+ KMimeType::Ptr mime( KMimeType::mimeType(mimeType) );
+ if (mime)
+ kdeFilter += (mime->patterns().join(" ") + "|" + mime->comment());
+ }
+ d->native->filter = kdeFilter;
+ }
}
void KFileDialog::clearFilter()
{
+ if (d->native) {
+ d->native->filter.clear();
+ return;
+ }
d->w->clearFilter();
}
@@ -168,6 +303,8 @@
void KFileDialog::setPreviewWidget(KPreviewWidgetBase *w)
{
+ if (d->native)
+ return;
d->w->setPreviewWidget(w);
}
@@ -179,12 +316,16 @@
// This slot still exists mostly for compat purposes; for subclasses which \
reimplement slotOk void KFileDialog::slotOk()
{
+ if (d->native)
+ return;
d->w->slotOk();
}
// This slot still exists mostly for compat purposes; for subclasses which \
reimplement accept void KFileDialog::accept()
{
+ if (d->native)
+ return;
setResult( QDialog::Accepted ); // keep old behavior; probably not needed though
d->w->accept();
KConfigGroup cfgGroup(KGlobal::config(), ConfigGroup);
@@ -195,17 +336,25 @@
// This slot still exists mostly for compat purposes; for subclasses which \
reimplement slotCancel void KFileDialog::slotCancel()
{
+ if (d->native)
+ return;
d->w->slotCancel();
reject();
}
void KFileDialog::setUrl(const KUrl& url, bool clearforward)
{
+ if (d->native)
+ return;
d->w->setUrl(url, clearforward);
}
void KFileDialog::setSelection(const QString& name)
{
+ if (d->native) {
+//TODO
+ return;
+ }
d->w->setSelection(name);
}
@@ -213,6 +362,14 @@
const QString& filter,
QWidget *parent, const QString& caption)
{
+ if (KFileDialogPrivate::isNative() && (!startDir.isValid() || \
startDir.isLocalFile())) { + return QFileDialog::getOpenFileName(
+ parent,
+ caption.isEmpty() ? i18n("Open") : caption,
+ startDir.path(),
+ qtFilter(filter) );
+//TODO QString * selectedFilter = 0, Options options = 0
+ }
KFileDialog dlg(startDir, filter, parent);
dlg.setOperationMode( Opening );
@@ -229,6 +386,8 @@
const QString& filter,
WId parent_id, const QString& caption)
{
+ if (KFileDialogPrivate::isNative() && (!startDir.isValid() || \
startDir.isLocalFile())) + return KFileDialog::getOpenFileName(startDir, \
filter, 0, caption); // everything we can do... QWidget* parent = QWidget::find( \
parent_id ); KFileDialog dlg(startDir, filter, parent);
#ifdef Q_WS_X11
@@ -254,6 +413,14 @@
QWidget *parent,
const QString& caption)
{
+ if (KFileDialogPrivate::isNative() && (!startDir.isValid() || \
startDir.isLocalFile())) { + return QFileDialog::getOpenFileNames(
+ parent,
+ caption.isEmpty() ? i18n("Open") : caption,
+ startDir.path(),
+ qtFilter(filter) );
+//TODO //QString * selectedFilter = 0, Options options = 0
+ }
KFileDialog dlg(startDir, filter, parent);
dlg.setOperationMode( Opening );
@@ -268,6 +435,11 @@
KUrl KFileDialog::getOpenUrl(const KUrl& startDir, const QString& filter,
QWidget *parent, const QString& caption)
{
+ if (KFileDialogPrivate::isNative() && (!startDir.isValid() || \
startDir.isLocalFile())) { + const QString fileName( \
KFileDialog::getOpenFileName( + startDir, filter, parent, caption) );
+ return fileName.isEmpty() ? KUrl() : KUrl::fromPath(fileName);
+ }
KFileDialog dlg(startDir, filter, parent);
dlg.setOperationMode( Opening );
@@ -284,6 +456,11 @@
QWidget *parent,
const QString& caption)
{
+ if (KFileDialogPrivate::isNative() && (!startDir.isValid() || \
startDir.isLocalFile())) { + const QStringList fileNames( \
KFileDialog::getOpenFileNames( + startDir, filter, parent, caption) );
+ return KUrl::List(fileNames);
+ }
KFileDialog dlg(startDir, filter, parent);
dlg.setOperationMode( Opening );
@@ -299,6 +476,11 @@
QWidget *parent,
const QString& caption)
{
+ if (KFileDialogPrivate::isNative() && (!startDir.isValid() || \
startDir.isLocalFile())) { + QString result( \
QFileDialog::getExistingDirectory(parent, caption, + \
startDir.path(), QFileDialog::ShowDirsOnly) ); + return result.isEmpty() ? \
KUrl() : KUrl::fromPath(result); + }
return fileModule()->selectDirectory(startDir, false, parent, caption);
}
@@ -306,20 +488,23 @@
QWidget *parent,
const QString& caption)
{
-#ifdef Q_WS_WIN
- return QFileDialog::getExistingDirectory(parent, caption,
- startDir.path(), \
QFileDialog::ShowDirsOnly);
-#else
+ if (KFileDialogPrivate::isNative() && (!startDir.isValid() || \
startDir.isLocalFile())) { + return QFileDialog::getExistingDirectory(parent, \
caption, + startDir.path(), \
QFileDialog::ShowDirsOnly); + }
KUrl url = fileModule()->selectDirectory(startDir, true, parent, caption);
if ( url.isValid() )
return url.path();
return QString();
-#endif
}
KUrl KFileDialog::getImageOpenUrl( const KUrl& startDir, QWidget *parent,
const QString& caption)
{
+ if (KFileDialogPrivate::isNative() && (!startDir.isValid() || \
startDir.isLocalFile())) { // everything we can do... + const QStringList \
mimetypes( KImageIO::mimeTypes( KImageIO::Reading ) ); + return \
KFileDialog::getOpenUrl(startDir, mimetypes.join(" "), parent, caption); + }
QStringList mimetypes = KImageIO::mimeTypes( KImageIO::Reading );
KFileDialog dlg(startDir,
mimetypes.join(" "),
@@ -337,26 +522,36 @@
KUrl KFileDialog::selectedUrl() const
{
+ if (d->native)
+ return d->native->selectedUrls.isEmpty() ? KUrl() : \
d->native->selectedUrls.first(); return d->w->selectedUrl();
}
KUrl::List KFileDialog::selectedUrls() const
{
+ if (d->native)
+ return d->native->selectedUrls;
return d->w->selectedUrls();
}
QString KFileDialog::selectedFile() const
{
+ if (d->native)
+ return selectedUrl().path();
return d->w->selectedFile();
}
QStringList KFileDialog::selectedFiles() const
{
+ if (d->native)
+ return selectedUrls().toStringList();
return d->w->selectedFiles();
}
KUrl KFileDialog::baseUrl() const
{
+ if (d->native)
+ return selectedUrl().isEmpty() ? KUrl() : \
KUrl::fromPath(selectedUrl().path()); return d->w->baseUrl();
}
@@ -364,6 +559,33 @@
QWidget *parent,
const QString& caption)
{
+ if (KFileDialogPrivate::isNative()) {
+ bool defaultDir = dir.isEmpty();
+ bool specialDir = !defaultDir && dir.protocol() == "kfiledialog";
+ QString startDir;
+ QString recentDirClass;
+ if (specialDir) {
+ startDir = KFileDialog::getStartUrl(dir, recentDirClass).path();
+ }
+ else if ( !specialDir && !defaultDir ) {
+ if (!dir.isLocalFile())
+ kWarning() << "non-local start dir " << dir;
+ startDir = dir.path();
+ }
+
+ const QString result = QFileDialog::getSaveFileName(
+ parent,
+ caption.isEmpty() ? i18n("Save As") : caption,
+ dir.path(),
+ qtFilter(filter) );
+//TODO QString * selectedFilter = 0, Options options = 0
+ if (!result.isEmpty()) {
+ if (!recentDirClass.isEmpty())
+ KRecentDirs::add(recentDirClass, KUrl::fromPath(result).url());
+ KRecentDocument::add(result);
+ }
+ return result;
+ }
bool defaultDir = dir.isEmpty();
bool specialDir = !defaultDir && dir.protocol() == "kfiledialog";
KFileDialog dlg( specialDir ? dir : KUrl(), filter, parent);
@@ -390,6 +612,9 @@
WId parent_id,
const QString& caption)
{
+ if (KFileDialogPrivate::isNative()) {
+ return KFileDialog::getSaveFileName(dir, filter, 0, caption); // everything \
we can do... + }
bool defaultDir = dir.isEmpty();
bool specialDir = !defaultDir && dir.protocol() == "kfiledialog";
QWidget* parent = QWidget::find( parent_id );
@@ -423,6 +648,11 @@
KUrl KFileDialog::getSaveUrl(const KUrl& dir, const QString& filter,
QWidget *parent, const QString& caption)
{
+ if (KFileDialogPrivate::isNative() && (!dir.isValid() || dir.isLocalFile())) {
+ const QString fileName( KFileDialog::getSaveFileName(
+ dir.path(), filter, parent, caption) );
+ return fileName.isEmpty() ? KUrl() : KUrl::fromPath(fileName);
+ }
bool defaultDir = dir.isEmpty();
bool specialDir = !defaultDir && dir.protocol() == "kfiledialog";
KFileDialog dlg(specialDir ? dir : KUrl(), filter, parent);
@@ -444,11 +674,16 @@
void KFileDialog::setMode( KFile::Modes m )
{
- d->w->setMode(m);
+ if (d->native)
+ d->native->mode = m;
+ else
+ d->w->setMode(m);
}
KFile::Modes KFileDialog::mode() const
{
+ if (d->native)
+ return d->native->mode;
return d->w->mode();
}
@@ -479,26 +714,38 @@
void KFileDialog::setKeepLocation( bool keep )
{
+ if (d->native)
+ return;
d->w->setKeepLocation(keep);
}
bool KFileDialog::keepsLocation() const
{
+ if (d->native)
+ return false;
return d->w->keepsLocation();
}
void KFileDialog::setOperationMode( OperationMode mode )
{
- d->w->setOperationMode(static_cast<KAbstractFileWidget::OperationMode>(mode));
+ if (d->native)
+ d->native->operationMode = \
static_cast<KAbstractFileWidget::OperationMode>(mode); + else
+ d->w->setOperationMode(static_cast<KAbstractFileWidget::OperationMode>(mode));
}
KFileDialog::OperationMode KFileDialog::operationMode() const
{
+ if (d->native)
+ return static_cast<KFileDialog::OperationMode>(d->native->operationMode);
return static_cast<KFileDialog::OperationMode>(d->w->operationMode());
}
void KFileDialog::keyPressEvent( QKeyEvent *e )
{
+ if (d->native)
+ return;
+
if ( e->key() == Qt::Key_Escape )
{
e->accept();
@@ -510,6 +757,9 @@
void KFileDialog::hideEvent( QHideEvent *e )
{
+ if (d->native)
+ return;
+
saveDialogSize(d->cfgGroup, KConfigBase::Persistent);
KDialog::hideEvent( e );
@@ -524,6 +774,8 @@
void KFileDialog::setStartDir( const KUrl& directory )
{
+ if (KFileDialogPrivate::isNative())
+ KFileDialogPrivate::Native::startDir = directory;
fileModule()->setStartDir(directory);
}
@@ -538,17 +790,74 @@
}
#ifdef Q_WS_WIN
+int KFileDialog::exec()
+{
+ if (!d->native)
+ return QDialog::exec();
+
+ d->native->selectedUrls.clear();
+ switch (d->native->operationMode) {
+ case KAbstractFileWidget::Opening:
+ case KAbstractFileWidget::Other:
+ if (d->native->mode & KFile::File) {
+ KUrl url( KFileDialog::getOpenUrl(
+ KFileDialogPrivate::Native::startDir, d->native->filter, \
parentWidget(), windowTitle()) ); + if (url.isEmpty() || !url.isValid())
+ return QDialog::Rejected;
+ d->native->selectedUrls.append(url);
+ return QDialog::Accepted;
+ }
+ else if (d->native->mode & KFile::Files) {
+ KUrl::List urls( KFileDialog::getOpenUrls(
+ KFileDialogPrivate::Native::startDir, d->native->filter, \
parentWidget(), windowTitle()) ); + if (urls.isEmpty())
+ return QDialog::Rejected;
+ d->native->selectedUrls = urls;
+ return QDialog::Accepted;
+ }
+ else if (d->native->mode & KFile::Directory) {
+ KUrl url( KFileDialog::getExistingDirectoryUrl(
+ KFileDialogPrivate::Native::startDir, parentWidget(), windowTitle()) \
); + if (url.isEmpty() || !url.isValid())
+ return QDialog::Rejected;
+ d->native->selectedUrls.append(url);
+ return QDialog::Accepted;
+ }
+ break;
+ case KAbstractFileWidget::Saving:
+ if (d->native->mode & KFile::File) {
+ KUrl url( KFileDialog::getSaveUrl(
+ KFileDialogPrivate::Native::startDir, d->native->filter, \
parentWidget(), windowTitle()) ); + if (url.isEmpty() || !url.isValid())
+ return QDialog::Rejected;
+ d->native->selectedUrls.append(url);
+ return QDialog::Accepted;
+ }
+ else if (d->native->mode & KFile::Directory) {
+ KUrl url( KFileDialog::getExistingDirectoryUrl(
+ KFileDialogPrivate::Native::startDir, parentWidget(), windowTitle()) \
); + if (url.isEmpty() || !url.isValid())
+ return QDialog::Rejected;
+ d->native->selectedUrls.append(url);
+ return QDialog::Accepted;
+ }
+ break;
+ default:;
+ }
+ return QDialog::Rejected;
+}
+#endif // Q_WS_WIN
+
+#ifdef Q_WS_WIN
#define KF_EXTERN extern __declspec(dllimport)
#else
#define KF_EXTERN extern
#endif
-#ifndef Q_WS_WIN
typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const \
QString &caption,
const QString &dir,
QFileDialog::Options \
options); KF_EXTERN _qt_filedialog_existing_directory_hook \
qt_filedialog_existing_directory_hook;
-#endif
typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString \
&caption,
const QString &dir, const \
QString &filter, @@ -573,15 +882,15 @@
* This is necessary because QPrintDialog calls QFileDialog::getSaveFileName() for
* the print to file function.
*/
-
-struct KFileDialogQtOverride
+class KFileDialogQtOverride
{
+public:
KFileDialogQtOverride()
{
-#ifndef Q_WS_WIN
+ if (KFileDialogPrivate::isNative())
+ return;
if(!qt_filedialog_existing_directory_hook)
qt_filedialog_existing_directory_hook=&getExistingDirectory;
-#endif
if(!qt_filedialog_open_filename_hook)
qt_filedialog_open_filename_hook=&getOpenFileName;
if(!qt_filedialog_open_filenames_hook)
@@ -644,7 +953,6 @@
}
}
-#ifndef Q_WS_WIN
static QString getExistingDirectory(QWidget *parent, const QString &caption, \
const QString &dir, QFileDialog::Options)
{
@@ -655,7 +963,6 @@
else
return QString();
}
-#endif
static QString getOpenFileName(QWidget *parent, const QString &caption, const \
QString &dir,
const QString &filter, QString *selectedFilter,
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic