mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-24 10:52:49 +00:00
1135 lines
39 KiB
C++
1135 lines
39 KiB
C++
// -*- c++ -*-
|
|
/* This file is part of the KDE libraries
|
|
Copyright (C) 1997, 1998 Richard Moore <rich@kde.org>
|
|
1998 Stephan Kulow <coolo@kde.org>
|
|
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 Jarosław Staniek <staniek@kde.org>
|
|
2009 David Jarvie <djarvie@kde.org>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "kfiledialog.h"
|
|
|
|
#include <QtGui/QCheckBox>
|
|
#include <QtGui/qevent.h>
|
|
#include <QtGui/QFileDialog>
|
|
#include <QtGui/QApplication>
|
|
#include <QtGui/QDesktopWidget>
|
|
|
|
#include <kimageio.h>
|
|
#include <klocale.h>
|
|
#include <kpushbutton.h>
|
|
#include <config-kfile.h>
|
|
#include <krecentdocument.h>
|
|
#include <kdebug.h>
|
|
#include <kwindowsystem.h>
|
|
#include "kabstractfilewidget.h"
|
|
#include "kabstractfilemodule.h"
|
|
#include "krecentdirs.h"
|
|
#include "kservice.h"
|
|
|
|
static QStringList mime2KdeFilter( const QStringList &mimeTypes, QString *allExtensions = 0 )
|
|
{
|
|
const KUrl emptyUrl;
|
|
QStringList kdeFilter;
|
|
QStringList allExt;
|
|
foreach (const QString& mimeType, mimeTypes) {
|
|
KMimeType::Ptr mime( KMimeType::mimeType(mimeType) );
|
|
if (mime) {
|
|
allExt += mime->patterns();
|
|
kdeFilter.append(mime->patterns().join(QLatin1String(" ")) +
|
|
QLatin1Char('|') +
|
|
mime->comment(emptyUrl));
|
|
}
|
|
}
|
|
if (allExtensions) {
|
|
allExt.sort();
|
|
*allExtensions = allExt.join(QLatin1String(" "));
|
|
}
|
|
return kdeFilter;
|
|
}
|
|
/** @return File dialog filter in Qt format for @a filters
|
|
* or "All files (*)" for empty list.
|
|
*/
|
|
static QString qtFilter(const QStringList& _filters)
|
|
{
|
|
QString converted;
|
|
const QStringList filters = _filters;
|
|
|
|
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);
|
|
}
|
|
//Qt filters assume anything in () is the file extension list
|
|
new_name = new_name.replace('(', '[').replace(')',']').trimmed();
|
|
|
|
//convert everything to lower case and remove dupes (doesn't matter on win32)
|
|
QStringList allfiltersUnique;
|
|
const QStringList origList( new_f.split(' ', QString::SkipEmptyParts) );
|
|
foreach (const QString& origFilter, origList) {
|
|
if (!allfiltersUnique.contains(origFilter, Qt::CaseInsensitive))
|
|
allfiltersUnique += origFilter.toLower();
|
|
}
|
|
|
|
if (!converted.isEmpty())
|
|
converted += ";;";
|
|
|
|
converted += (new_name + " (" + allfiltersUnique.join(" ") + QLatin1Char(')'));
|
|
}
|
|
|
|
// Strip escape characters from escaped '/' characters.
|
|
converted.replace("\\/","/");
|
|
|
|
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 {
|
|
// check if it's a mimefilter
|
|
int pos = filter.indexOf('/');
|
|
if (pos > 0 && filter[pos - 1] != '\\')
|
|
filters = mime2KdeFilter(filter.split(QLatin1Char(' '), QString::SkipEmptyParts));
|
|
else
|
|
filters = filter.split('\n', QString::SkipEmptyParts);
|
|
}
|
|
return qtFilter(filters);
|
|
}
|
|
|
|
static KAbstractFileModule* s_module = 0;
|
|
static KAbstractFileModule* loadFileModule( const QString& moduleName )
|
|
{
|
|
KService::Ptr fileModuleService = KService::serviceByDesktopName(moduleName);
|
|
if(fileModuleService)
|
|
return fileModuleService->createInstance<KAbstractFileModule>();
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static const char s_defaultFileModuleName[] = "kfilemodule";
|
|
static KAbstractFileModule* fileModule()
|
|
{
|
|
if(!s_module) {
|
|
QString moduleName = KConfig("kdeglobals").group(ConfigGroup).readEntry("file module", s_defaultFileModuleName);
|
|
if(!(s_module = loadFileModule(moduleName))) {
|
|
kDebug() << "Failed to load configured file module" << moduleName;
|
|
if(moduleName != s_defaultFileModuleName) {
|
|
kDebug() << "Falling back to default file module.";
|
|
s_module = loadFileModule(s_defaultFileModuleName);
|
|
}
|
|
}
|
|
}
|
|
return s_module;
|
|
}
|
|
|
|
class KFileDialogPrivate
|
|
{
|
|
public:
|
|
/** Data used for native mode. */
|
|
class Native {
|
|
public:
|
|
Native()
|
|
: mode(KFile::File),
|
|
operationMode(KAbstractFileWidget::Opening)
|
|
{
|
|
}
|
|
/** @return previously set (global) start dir or the first url
|
|
selected using setSelection() or setUrl() if the start dir is empty. */
|
|
KUrl startDir() const
|
|
{
|
|
if (!s_startDir.isEmpty())
|
|
return s_startDir;
|
|
if (!selectedUrls.isEmpty())
|
|
return selectedUrls.first();
|
|
return KUrl();
|
|
}
|
|
/** @return previously set (global) start dir or @p defaultDir
|
|
if the start dir is empty. */
|
|
static KUrl staticStartDir( const KUrl& defaultDir )
|
|
{
|
|
if ( s_startDir.isEmpty() )
|
|
return defaultDir;
|
|
return s_startDir;
|
|
}
|
|
static KUrl s_startDir;
|
|
static bool s_allowNative; // as fallback when we can't use native dialog
|
|
QString filter;
|
|
QString selectedFilter;
|
|
QStringList mimeTypes;
|
|
KUrl::List selectedUrls;
|
|
KFile::Modes mode;
|
|
KAbstractFileWidget::OperationMode operationMode;
|
|
};
|
|
|
|
KFileDialogPrivate()
|
|
: native(0),
|
|
w(0),
|
|
cfgGroup(KGlobal::config(), ConfigGroup)
|
|
{
|
|
if (cfgGroup.readEntry("Native", false) &&
|
|
KFileDialogPrivate::Native::s_allowNative)
|
|
native = new Native;
|
|
}
|
|
|
|
static bool isNative()
|
|
{
|
|
if(!KFileDialogPrivate::Native::s_allowNative)
|
|
return false;
|
|
KConfigGroup cfgGroup(KGlobal::config(), ConfigGroup);
|
|
return cfgGroup.readEntry("Native", false);
|
|
}
|
|
|
|
static QString getOpenFileName(const KUrl& startDir, const QString& filter,
|
|
QWidget *parent, const QString& caption,
|
|
QString *selectedFilter);
|
|
static KUrl getOpenUrl(const KUrl& startDir, const QString& filter,
|
|
QWidget *parent, const QString& caption,
|
|
QString *selectedFilter);
|
|
static QStringList getOpenFileNames(const KUrl& startDir, const QString& filter,
|
|
QWidget *parent, const QString& caption,
|
|
QString *selectedFilter);
|
|
static KUrl::List getOpenUrls(const KUrl& startDir, const QString& filter,
|
|
QWidget *parent, const QString& caption,
|
|
QString *selectedFilter);
|
|
static QString getSaveFileName(const KUrl& dir, const QString& filter,
|
|
QWidget *parent, const QString& caption,
|
|
KFileDialog::Options options, QString *selectedFilter);
|
|
static KUrl getSaveUrl(const KUrl& dir, const QString& filter,
|
|
QWidget *parent, const QString& caption,
|
|
KFileDialog::Options options, QString *selectedFilter);
|
|
|
|
~KFileDialogPrivate()
|
|
{
|
|
delete native;
|
|
}
|
|
|
|
Native* native;
|
|
KAbstractFileWidget* w;
|
|
KConfigGroup cfgGroup;
|
|
};
|
|
|
|
KUrl KFileDialogPrivate::Native::s_startDir;
|
|
bool KFileDialogPrivate::Native::s_allowNative = true;
|
|
|
|
KFileDialog::KFileDialog( const KUrl& startDir, const QString& filter,
|
|
QWidget *parent, QWidget* customWidget)
|
|
: KDialog( parent ),
|
|
d( new KFileDialogPrivate )
|
|
|
|
{
|
|
// It would be nice to have this behind d->native but it doesn't work
|
|
// because of derived classes like KEncodingDialog...
|
|
// Dlopen the file widget from libkfilemodule
|
|
QWidget* fileQWidget = fileModule()->createFileWidget(startDir, this);
|
|
d->w = ::qobject_cast<KAbstractFileWidget *>(fileQWidget);
|
|
|
|
if (d->native) {
|
|
KFileDialogPrivate::Native::s_startDir = startDir;
|
|
// check if it's a mimefilter
|
|
int pos = filter.indexOf('/');
|
|
if (pos > 0 && filter[pos - 1] != '\\')
|
|
setMimeFilter(filter.split(QLatin1Char(' '), QString::SkipEmptyParts));
|
|
else
|
|
setFilter(filter);
|
|
return;
|
|
}
|
|
|
|
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)
|
|
|
|
d->w->setFilter(filter);
|
|
setMainWidget(fileQWidget);
|
|
|
|
d->w->okButton()->show();
|
|
connect(d->w->okButton(), SIGNAL(clicked()), SLOT(slotOk()));
|
|
d->w->cancelButton()->show();
|
|
connect(d->w->cancelButton(), SIGNAL(clicked()), SLOT(slotCancel()));
|
|
|
|
// Publish signals
|
|
// TODO: Move the relevant signal declarations from KFileWidget to the
|
|
// KAbstractFileWidget interface?
|
|
// Else, all of these connects (including "accepted") are not typesafe.
|
|
// Answer: you cannot define signals in a non-qobject base class (DF).
|
|
// I simply documentde them in kabstractfilewidget.h now.
|
|
kDebug (kfile_area) << "KFileDialog connecting signals";
|
|
connect(fileQWidget, SIGNAL(fileSelected(KUrl)),
|
|
SIGNAL(fileSelected(KUrl)));
|
|
connect(fileQWidget, SIGNAL(fileHighlighted(KUrl)),
|
|
SIGNAL(fileHighlighted(KUrl)));
|
|
connect(fileQWidget, SIGNAL(selectionChanged()),
|
|
SIGNAL(selectionChanged()));
|
|
connect(fileQWidget, SIGNAL(filterChanged(QString)),
|
|
SIGNAL(filterChanged(QString)));
|
|
|
|
connect(fileQWidget, SIGNAL(accepted()), SLOT(accept()));
|
|
//connect(fileQWidget, SIGNAL(canceled()), SLOT(slotCancel()));
|
|
|
|
if (customWidget)
|
|
d->w->setCustomWidget(QString(), customWidget);
|
|
}
|
|
|
|
|
|
KFileDialog::~KFileDialog()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
void KFileDialog::setMimeFilter( const QStringList& mimeTypes,
|
|
const QString& defaultType )
|
|
{
|
|
d->w->setMimeFilter(mimeTypes, defaultType);
|
|
|
|
if (d->native) {
|
|
QString allExtensions;
|
|
QStringList filters = mime2KdeFilter(mimeTypes, &allExtensions);
|
|
if (defaultType.isEmpty() && (mimeTypes.count() > 1)) {
|
|
filters.prepend(allExtensions + QLatin1Char('|') + i18n("All Supported Files"));
|
|
}
|
|
d->native->filter = filters.join(QLatin1String("\n"));
|
|
}
|
|
}
|
|
|
|
void KFileDialog::clearFilter()
|
|
{
|
|
if (d->native) {
|
|
d->native->filter.clear();
|
|
return;
|
|
}
|
|
d->w->clearFilter();
|
|
}
|
|
|
|
QString KFileDialog::currentMimeFilter() const
|
|
{
|
|
if (d->native) {
|
|
// adapted from qt2KdeFilter
|
|
QString filter = d->native->selectedFilter.split(";;").replaceInStrings("/", "\\/")[0];
|
|
filter = filter.mid(filter.indexOf('(') + 1, filter.indexOf(')') - filter.indexOf('(') - 1);
|
|
QString mimetype = KMimeType::findByPath("test" + filter.mid(1).split(' ')[0])->name();
|
|
return mimetype;
|
|
}
|
|
return d->w->currentMimeFilter();
|
|
}
|
|
|
|
KMimeType::Ptr KFileDialog::currentFilterMimeType()
|
|
{
|
|
return KMimeType::mimeType( currentMimeFilter() );
|
|
}
|
|
|
|
void KFileDialog::setPreviewWidget(KPreviewWidgetBase *w)
|
|
{
|
|
if (d->native)
|
|
return;
|
|
d->w->setPreviewWidget(w);
|
|
}
|
|
|
|
void KFileDialog::setInlinePreviewShown(bool show)
|
|
{
|
|
if (d->native) {
|
|
return;
|
|
}
|
|
d->w->setInlinePreviewShown(show);
|
|
}
|
|
|
|
// This is only used for the initial size when no configuration has been saved
|
|
QSize KFileDialog::sizeHint() const
|
|
{
|
|
int fontSize = fontMetrics().height();
|
|
QSize goodSize(48 * fontSize, 30 * fontSize);
|
|
QSize screenSize = QApplication::desktop()->availableGeometry(this).size();
|
|
QSize minSize(screenSize / 2);
|
|
QSize maxSize(screenSize * qreal(0.9));
|
|
return (goodSize.expandedTo(minSize).boundedTo(maxSize));
|
|
}
|
|
|
|
// 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);
|
|
KDialog::accept();
|
|
emit okClicked();
|
|
}
|
|
|
|
// 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) {
|
|
d->native->selectedUrls.clear();
|
|
d->native->selectedUrls.append(url);
|
|
return;
|
|
}
|
|
d->w->setUrl(url, clearforward);
|
|
}
|
|
|
|
void KFileDialog::setSelection(const QString& name)
|
|
{
|
|
if (d->native) {
|
|
d->native->selectedUrls.clear();
|
|
d->native->selectedUrls.append( KUrl(name) );
|
|
return;
|
|
}
|
|
d->w->setSelection(name);
|
|
}
|
|
|
|
QString KFileDialog::getOpenFileName(const KUrl& startDir,
|
|
const QString& filter,
|
|
QWidget *parent, const QString& caption)
|
|
{
|
|
return KFileDialogPrivate::getOpenFileName(startDir, filter, parent, caption, 0);
|
|
}
|
|
|
|
QString KFileDialogPrivate::getOpenFileName(const KUrl& startDir,
|
|
const QString& filter,
|
|
QWidget *parent,
|
|
const QString& caption,
|
|
QString *selectedFilter)
|
|
{
|
|
if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
|
|
return QFileDialog::getOpenFileName(
|
|
parent,
|
|
caption.isEmpty() ? i18n("Open") : caption,
|
|
KFileDialogPrivate::Native::staticStartDir( startDir ).toLocalFile(),
|
|
qtFilter(filter),
|
|
selectedFilter );
|
|
// TODO use extra args? QString * selectedFilter = 0, Options options = 0
|
|
}
|
|
KFileDialog dlg(startDir, filter, parent);
|
|
|
|
dlg.setOperationMode( KFileDialog::Opening );
|
|
dlg.setMode( KFile::File | KFile::LocalOnly | KFile::ExistingOnly );
|
|
dlg.setCaption(caption.isEmpty() ? i18n("Open") : caption);
|
|
|
|
dlg.exec();
|
|
if(selectedFilter) *selectedFilter = dlg.currentMimeFilter();
|
|
return dlg.selectedFile();
|
|
}
|
|
|
|
QString KFileDialog::getOpenFileNameWId(const KUrl& startDir,
|
|
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 );
|
|
KFileDialogPrivate::Native::s_allowNative = false;
|
|
KFileDialog dlg(startDir, filter, parent);
|
|
if( parent == NULL && parent_id != 0 )
|
|
KWindowSystem::setMainWindow( &dlg, parent_id );
|
|
|
|
dlg.setOperationMode( KFileDialog::Opening );
|
|
dlg.setMode( KFile::File | KFile::LocalOnly | KFile::ExistingOnly );
|
|
dlg.setCaption(caption.isEmpty() ? i18n("Open") : caption);
|
|
|
|
dlg.exec();
|
|
|
|
return dlg.selectedFile();
|
|
}
|
|
|
|
QStringList KFileDialog::getOpenFileNames(const KUrl& startDir,
|
|
const QString& filter,
|
|
QWidget *parent,
|
|
const QString& caption)
|
|
{
|
|
return KFileDialogPrivate::getOpenFileNames(startDir, filter, parent, caption, 0);
|
|
}
|
|
|
|
QStringList KFileDialogPrivate::getOpenFileNames(const KUrl& startDir,
|
|
const QString& filter,
|
|
QWidget *parent,
|
|
const QString& caption,
|
|
QString *selectedFilter)
|
|
{
|
|
if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
|
|
return QFileDialog::getOpenFileNames(
|
|
parent,
|
|
caption.isEmpty() ? i18n("Open") : caption,
|
|
KFileDialogPrivate::Native::staticStartDir( startDir ).toLocalFile(),
|
|
qtFilter( filter ), selectedFilter );
|
|
// TODO use extra args? QString * selectedFilter = 0, Options options = 0
|
|
}
|
|
KFileDialogPrivate::Native::s_allowNative = false;
|
|
KFileDialog dlg(startDir, filter, parent);
|
|
|
|
dlg.setOperationMode( KFileDialog::Opening );
|
|
dlg.setMode(KFile::Files | KFile::LocalOnly | KFile::ExistingOnly);
|
|
dlg.setCaption(caption.isEmpty() ? i18n("Open") : caption);
|
|
|
|
dlg.exec();
|
|
if(selectedFilter) *selectedFilter = dlg.currentMimeFilter();
|
|
return dlg.selectedFiles();
|
|
}
|
|
|
|
KUrl KFileDialog::getOpenUrl(const KUrl& startDir, const QString& filter,
|
|
QWidget *parent, const QString& caption)
|
|
{
|
|
return KFileDialogPrivate::getOpenUrl(startDir, filter, parent, caption, 0);
|
|
}
|
|
KUrl KFileDialogPrivate::getOpenUrl(const KUrl& startDir, const QString& filter,
|
|
QWidget *parent, const QString& caption,
|
|
QString *selectedFilter)
|
|
{
|
|
if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
|
|
const QString fileName( KFileDialogPrivate::getOpenFileName(
|
|
startDir, filter, parent, caption, selectedFilter) );
|
|
return fileName.isEmpty() ? KUrl() : KUrl::fromPath(fileName);
|
|
}
|
|
KFileDialogPrivate::Native::s_allowNative = false;
|
|
KFileDialog dlg(startDir, filter, parent);
|
|
|
|
dlg.setOperationMode( KFileDialog::Opening );
|
|
dlg.setMode( KFile::File | KFile::ExistingOnly );
|
|
dlg.setCaption(caption.isEmpty() ? i18n("Open") : caption);
|
|
|
|
dlg.exec();
|
|
if(selectedFilter) *selectedFilter = dlg.currentMimeFilter();
|
|
return dlg.selectedUrl();
|
|
}
|
|
|
|
KUrl::List KFileDialog::getOpenUrls(const KUrl& startDir,
|
|
const QString& filter,
|
|
QWidget *parent,
|
|
const QString& caption)
|
|
{
|
|
return KFileDialogPrivate::getOpenUrls(startDir, filter, parent, caption, 0);
|
|
}
|
|
|
|
KUrl::List KFileDialogPrivate::getOpenUrls(const KUrl& startDir,
|
|
const QString& filter,
|
|
QWidget *parent,
|
|
const QString& caption,
|
|
QString *selectedFilter)
|
|
{
|
|
if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
|
|
const QStringList fileNames( KFileDialogPrivate::getOpenFileNames(
|
|
startDir, filter, parent, caption, selectedFilter) );
|
|
return KUrl::List(fileNames);
|
|
}
|
|
KFileDialogPrivate::Native::s_allowNative = false;
|
|
|
|
KFileDialog dlg(startDir, filter, parent);
|
|
|
|
dlg.setOperationMode( KFileDialog::Opening );
|
|
dlg.setMode( KFile::Files | KFile::ExistingOnly );
|
|
dlg.setCaption(caption.isEmpty() ? i18n("Open") : caption);
|
|
|
|
dlg.exec();
|
|
if(selectedFilter) *selectedFilter = dlg.currentMimeFilter();
|
|
return dlg.selectedUrls();
|
|
}
|
|
|
|
void KFileDialog::setConfirmOverwrite(bool enable)
|
|
{
|
|
if (operationMode() == KFileDialog::Saving) {
|
|
d->w->setConfirmOverwrite(enable);
|
|
}
|
|
}
|
|
|
|
KUrl KFileDialog::getExistingDirectoryUrl(const KUrl& startDir,
|
|
QWidget *parent,
|
|
const QString& caption)
|
|
{
|
|
if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
|
|
QString result( QFileDialog::getExistingDirectory(parent, caption,
|
|
KFileDialogPrivate::Native::staticStartDir( startDir ).toLocalFile(),
|
|
QFileDialog::ShowDirsOnly) );
|
|
return result.isEmpty() ? KUrl() : KUrl::fromPath(result);
|
|
}
|
|
return fileModule()->selectDirectory(startDir, false, parent, caption);
|
|
}
|
|
|
|
QString KFileDialog::getExistingDirectory(const KUrl& startDir,
|
|
QWidget *parent,
|
|
const QString& caption)
|
|
{
|
|
if (KFileDialogPrivate::isNative() && (!startDir.isValid() || startDir.isLocalFile())) {
|
|
return QFileDialog::getExistingDirectory(parent, caption,
|
|
KFileDialogPrivate::Native::staticStartDir( startDir ).toLocalFile(),
|
|
QFileDialog::ShowDirsOnly);
|
|
}
|
|
KUrl url = fileModule()->selectDirectory(startDir, true, parent, caption);
|
|
if ( url.isValid() )
|
|
return url.toLocalFile();
|
|
return QString();
|
|
}
|
|
|
|
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);
|
|
}
|
|
const QStringList mimetypes = KImageIO::mimeTypes( KImageIO::Reading );
|
|
KFileDialogPrivate::Native::s_allowNative = false;
|
|
KFileDialog dlg(startDir, mimetypes.join(" "), parent);
|
|
|
|
dlg.setOperationMode( KFileDialog::Opening );
|
|
dlg.setMode( KFile::File | KFile::ExistingOnly );
|
|
dlg.setCaption( caption.isEmpty() ? i18n("Open") : caption );
|
|
dlg.setInlinePreviewShown( true );
|
|
|
|
dlg.exec();
|
|
|
|
return dlg.selectedUrl();
|
|
}
|
|
|
|
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().toLocalFile();
|
|
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();
|
|
}
|
|
|
|
QString KFileDialog::getSaveFileName(const KUrl& dir, const QString& filter,
|
|
QWidget *parent,
|
|
const QString& caption, Options options)
|
|
{
|
|
return KFileDialogPrivate::getSaveFileName(dir, filter, parent, caption, options, 0);
|
|
}
|
|
|
|
QString KFileDialogPrivate::getSaveFileName(const KUrl& dir, const QString& filter,
|
|
QWidget *parent, const QString& caption,
|
|
KFileDialog::Options options, QString *selectedFilter)
|
|
{
|
|
if (KFileDialogPrivate::isNative()) {
|
|
bool defaultDir = dir.isEmpty();
|
|
bool specialDir = !defaultDir && dir.protocol() == "kfiledialog";
|
|
KUrl startDir;
|
|
QString recentDirClass;
|
|
if (specialDir) {
|
|
startDir = KFileDialog::getStartUrl(dir, recentDirClass);
|
|
}
|
|
else if ( !specialDir && !defaultDir ) {
|
|
if (!dir.isLocalFile())
|
|
kWarning() << "non-local start dir " << dir;
|
|
startDir = dir;
|
|
}
|
|
|
|
QFileDialog::Options opts = (options & KFileDialog::ConfirmOverwrite) ? QFileDialog::Options(0) : QFileDialog::DontConfirmOverwrite;
|
|
const QString result = QFileDialog::getSaveFileName(
|
|
parent,
|
|
caption.isEmpty() ? i18n("Save As") : caption,
|
|
KFileDialogPrivate::Native::staticStartDir( startDir ).toLocalFile(),
|
|
qtFilter(filter),
|
|
// TODO use extra args? QString * selectedFilter = 0, Options opts = 0
|
|
selectedFilter, opts );
|
|
if (!result.isEmpty()) {
|
|
if (!recentDirClass.isEmpty())
|
|
KRecentDirs::add(recentDirClass, KUrl::fromPath(result).url());
|
|
KRecentDocument::add(result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
KFileDialog dlg(dir, filter, parent);
|
|
|
|
dlg.setOperationMode( KFileDialog::Saving );
|
|
dlg.setMode( KFile::File | KFile::LocalOnly );
|
|
dlg.setConfirmOverwrite(options & KFileDialog::ConfirmOverwrite);
|
|
dlg.setInlinePreviewShown(options & KFileDialog::ShowInlinePreview);
|
|
dlg.setCaption(caption.isEmpty() ? i18n("Save As") : caption);
|
|
|
|
dlg.exec();
|
|
|
|
QString filename = dlg.selectedFile();
|
|
if (!filename.isEmpty())
|
|
KRecentDocument::add(filename);
|
|
|
|
return filename;
|
|
}
|
|
|
|
QString KFileDialog::getSaveFileNameWId(const KUrl& dir, const QString& filter,
|
|
WId parent_id,
|
|
const QString& caption, Options options)
|
|
{
|
|
if (KFileDialogPrivate::isNative()) {
|
|
return KFileDialog::getSaveFileName(dir, filter, 0, caption, options); // everything we can do...
|
|
}
|
|
|
|
QWidget* parent = QWidget::find( parent_id );
|
|
KFileDialog dlg(dir, filter, parent);
|
|
if( parent == NULL && parent_id != 0 )
|
|
KWindowSystem::setMainWindow( &dlg, parent_id);
|
|
|
|
dlg.setOperationMode( KFileDialog::Saving );
|
|
dlg.setMode( KFile::File | KFile::LocalOnly );
|
|
dlg.setConfirmOverwrite(options & ConfirmOverwrite);
|
|
dlg.setInlinePreviewShown(options & ShowInlinePreview);
|
|
dlg.setCaption(caption.isEmpty() ? i18n("Save As") : caption);
|
|
|
|
dlg.exec();
|
|
|
|
QString filename = dlg.selectedFile();
|
|
if (!filename.isEmpty())
|
|
KRecentDocument::add(filename);
|
|
|
|
return filename;
|
|
}
|
|
|
|
KUrl KFileDialog::getSaveUrl(const KUrl& dir, const QString& filter,
|
|
QWidget *parent, const QString& caption, Options options)
|
|
{
|
|
return KFileDialogPrivate::getSaveUrl(dir, filter, parent, caption, options, 0);
|
|
}
|
|
KUrl KFileDialogPrivate::getSaveUrl(const KUrl& dir, const QString& filter,
|
|
QWidget *parent, const QString& caption,
|
|
KFileDialog::Options options, QString *selectedFilter)
|
|
{
|
|
if (KFileDialogPrivate::isNative() && (!dir.isValid() || dir.isLocalFile())) {
|
|
const QString fileName( KFileDialogPrivate::getSaveFileName(
|
|
dir, filter, parent, caption, options, selectedFilter) );
|
|
return fileName.isEmpty() ? KUrl() : KUrl::fromPath(fileName);
|
|
}
|
|
|
|
KFileDialogPrivate::Native::s_allowNative = false;
|
|
|
|
KFileDialog dlg(dir, filter, parent);
|
|
|
|
dlg.setOperationMode( KFileDialog::Saving );
|
|
dlg.setMode( KFile::File );
|
|
dlg.setConfirmOverwrite(options & KFileDialog::ConfirmOverwrite);
|
|
dlg.setInlinePreviewShown(options & KFileDialog::ShowInlinePreview);
|
|
dlg.setCaption(caption.isEmpty() ? i18n("Save As") : caption);
|
|
|
|
dlg.exec();
|
|
if(selectedFilter) *selectedFilter = dlg.currentMimeFilter();
|
|
KUrl url = dlg.selectedUrl();
|
|
if (url.isValid())
|
|
KRecentDocument::add( url );
|
|
|
|
return url;
|
|
}
|
|
|
|
void KFileDialog::setMode( KFile::Modes 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();
|
|
}
|
|
|
|
KPushButton * KFileDialog::okButton() const
|
|
{
|
|
return d->w->okButton();
|
|
}
|
|
|
|
KPushButton * KFileDialog::cancelButton() const
|
|
{
|
|
return d->w->cancelButton();
|
|
}
|
|
|
|
KUrlComboBox* KFileDialog::locationEdit() const
|
|
{
|
|
return d->w->locationEdit();
|
|
}
|
|
|
|
KFileFilterCombo* KFileDialog::filterWidget() const
|
|
{
|
|
return d->w->filterWidget();
|
|
}
|
|
|
|
KActionCollection * KFileDialog::actionCollection() const
|
|
{
|
|
return d->w->actionCollection();
|
|
}
|
|
|
|
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 )
|
|
{
|
|
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();
|
|
d->w->cancelButton()->animateClick();
|
|
}
|
|
else
|
|
KDialog::keyPressEvent( e );
|
|
}
|
|
|
|
void KFileDialog::hideEvent( QHideEvent *e )
|
|
{
|
|
if (d->native)
|
|
return;
|
|
|
|
saveDialogSize(d->cfgGroup, KConfigBase::Persistent);
|
|
|
|
KDialog::hideEvent( e );
|
|
}
|
|
|
|
// static
|
|
KUrl KFileDialog::getStartUrl( const KUrl& startDir,
|
|
QString& recentDirClass )
|
|
{
|
|
return fileModule()->getStartUrl(startDir, recentDirClass);
|
|
}
|
|
|
|
void KFileDialog::setStartDir( const KUrl& directory )
|
|
{
|
|
if (KFileDialogPrivate::isNative())
|
|
KFileDialogPrivate::Native::s_startDir = directory;
|
|
fileModule()->setStartDir(directory);
|
|
}
|
|
|
|
KToolBar * KFileDialog::toolBar() const
|
|
{
|
|
return d->w->toolBar();
|
|
}
|
|
|
|
KAbstractFileWidget* KFileDialog::fileWidget()
|
|
{
|
|
return d->w;
|
|
}
|
|
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption,
|
|
const QString &dir,
|
|
QFileDialog::Options options);
|
|
extern _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook;
|
|
|
|
typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString &caption,
|
|
const QString &dir, const QString &filter,
|
|
QString *selectedFilter,
|
|
QFileDialog::Options options);
|
|
extern _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook;
|
|
|
|
typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption,
|
|
const QString &dir, const QString &filter,
|
|
QString *selectedFilter,
|
|
QFileDialog::Options options);
|
|
extern _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook;
|
|
|
|
typedef QString (*_qt_filedialog_save_filename_hook)(QWidget * parent, const QString &caption,
|
|
const QString &dir, const QString &filter,
|
|
QString *selectedFilter,
|
|
QFileDialog::Options options);
|
|
extern _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook;
|
|
QT_END_NAMESPACE
|
|
|
|
/*
|
|
* This class is used to override Qt's QFileDialog calls with KFileDialog ones.
|
|
* This is necessary because QPrintDialog calls QFileDialog::getSaveFileName() for
|
|
* the print to file function.
|
|
*/
|
|
class KFileDialogQtOverride
|
|
{
|
|
public:
|
|
KFileDialogQtOverride()
|
|
{
|
|
if(!qt_filedialog_existing_directory_hook)
|
|
qt_filedialog_existing_directory_hook=&getExistingDirectory;
|
|
if(!qt_filedialog_open_filename_hook)
|
|
qt_filedialog_open_filename_hook=&getOpenFileName;
|
|
if(!qt_filedialog_open_filenames_hook)
|
|
qt_filedialog_open_filenames_hook=&getOpenFileNames;
|
|
if(!qt_filedialog_save_filename_hook)
|
|
qt_filedialog_save_filename_hook=&getSaveFileName;
|
|
}
|
|
|
|
~KFileDialogQtOverride() {
|
|
if(qt_filedialog_existing_directory_hook == &getExistingDirectory)
|
|
qt_filedialog_existing_directory_hook = 0;
|
|
if(qt_filedialog_open_filename_hook == &getOpenFileName)
|
|
qt_filedialog_open_filename_hook = 0;
|
|
if(qt_filedialog_open_filenames_hook == &getOpenFileNames)
|
|
qt_filedialog_open_filenames_hook=0;
|
|
if(qt_filedialog_save_filename_hook == &getSaveFileName)
|
|
qt_filedialog_save_filename_hook=0;
|
|
}
|
|
|
|
/*
|
|
* Map a Qt filter string into a KDE one.
|
|
*/
|
|
static QString qt2KdeFilter(const QString &f)
|
|
{
|
|
QString filter;
|
|
QTextStream str(&filter, QIODevice::WriteOnly);
|
|
QStringList list(f.split(";;").replaceInStrings("/", "\\/"));
|
|
QStringList::const_iterator it(list.begin()),
|
|
end(list.end());
|
|
bool first=true;
|
|
|
|
for(; it!=end; ++it)
|
|
{
|
|
int ob=(*it).lastIndexOf('('),
|
|
cb=(*it).lastIndexOf(')');
|
|
|
|
if(-1!=cb && ob<cb)
|
|
{
|
|
if(first)
|
|
first=false;
|
|
else
|
|
str << '\n';
|
|
str << (*it).mid(ob+1, (cb-ob)-1) << '|' << (*it).mid(0, ob);
|
|
}
|
|
}
|
|
|
|
return filter;
|
|
}
|
|
|
|
/*
|
|
* Map a KDE filter string into a Qt one.
|
|
*/
|
|
static void kde2QtFilter(const QString &orig, const QString &kde, QString *sel)
|
|
{
|
|
if(sel)
|
|
{
|
|
QStringList list(orig.split(";;"));
|
|
QStringList::const_iterator it(list.begin()),
|
|
end(list.end());
|
|
int pos;
|
|
|
|
for(; it!=end; ++it)
|
|
if(-1!=(pos=(*it).indexOf(kde)) && pos>0 &&
|
|
('('==(*it)[pos-1] || ' '==(*it)[pos-1]) &&
|
|
(*it).length()>=kde.length()+pos &&
|
|
(')'==(*it)[pos+kde.length()] || ' '==(*it)[pos+kde.length()]))
|
|
{
|
|
*sel=*it;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static QString getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir,
|
|
QFileDialog::Options options)
|
|
{
|
|
if (KFileDialogPrivate::isNative()) {
|
|
if(qt_filedialog_existing_directory_hook)
|
|
qt_filedialog_existing_directory_hook=0; // do not override
|
|
return QFileDialog::getExistingDirectory(parent, caption, dir, options);
|
|
}
|
|
|
|
fileModule(); // make sure i18n is initialized properly, needed for pure Qt applications
|
|
KUrl url(KFileDialog::getExistingDirectory(KUrl(dir), parent, caption));
|
|
|
|
if(url.isLocalFile())
|
|
return url.pathOrUrl();
|
|
else
|
|
return QString();
|
|
}
|
|
|
|
static QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir,
|
|
const QString &filter, QString *selectedFilter,
|
|
QFileDialog::Options options)
|
|
{
|
|
if (KFileDialogPrivate::isNative()) {
|
|
if(qt_filedialog_open_filename_hook)
|
|
qt_filedialog_open_filename_hook=0; // do not override
|
|
return QFileDialog::getOpenFileName(parent, caption, dir, filter, selectedFilter, options);
|
|
}
|
|
|
|
fileModule(); // make sure i18n is initialized properly, needed for pure Qt applications
|
|
KFileDialog dlg(KUrl(dir), qt2KdeFilter(filter), parent);
|
|
|
|
dlg.setOperationMode(KFileDialog::Opening);
|
|
dlg.setMode(KFile::File|KFile::LocalOnly);
|
|
dlg.setCaption(caption);
|
|
dlg.exec();
|
|
|
|
QString rv(dlg.selectedFile());
|
|
|
|
if(!rv.isEmpty())
|
|
kde2QtFilter(filter, dlg.currentFilter(), selectedFilter);
|
|
|
|
return rv;
|
|
}
|
|
|
|
static QStringList getOpenFileNames(QWidget *parent, const QString &caption, const QString &dir,
|
|
const QString &filter, QString *selectedFilter,
|
|
QFileDialog::Options options)
|
|
{
|
|
if (KFileDialogPrivate::isNative()) {
|
|
if(qt_filedialog_open_filenames_hook)
|
|
qt_filedialog_open_filenames_hook=0; // do not override
|
|
return QFileDialog::getOpenFileNames(parent, caption, dir, filter, selectedFilter, options);
|
|
}
|
|
|
|
fileModule(); // make sure i18n is initialized properly, needed for pure Qt applications
|
|
KFileDialog dlg(KUrl(dir), qt2KdeFilter(filter), parent);
|
|
|
|
dlg.setOperationMode(KFileDialog::Opening);
|
|
dlg.setMode(KFile::Files|KFile::LocalOnly);
|
|
dlg.setCaption(caption);
|
|
dlg.exec();
|
|
|
|
QStringList rv(dlg.selectedFiles());
|
|
|
|
if(rv.count())
|
|
kde2QtFilter(filter, dlg.currentFilter(), selectedFilter);
|
|
|
|
return rv;
|
|
}
|
|
|
|
static QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir,
|
|
const QString &filter, QString *selectedFilter,
|
|
QFileDialog::Options options)
|
|
{
|
|
if (KFileDialogPrivate::isNative()) {
|
|
if(qt_filedialog_save_filename_hook)
|
|
qt_filedialog_save_filename_hook=0; // do not override
|
|
return QFileDialog::getSaveFileName(parent, caption, dir, filter, selectedFilter, options);
|
|
}
|
|
|
|
fileModule(); // make sure i18n is initialized properly, needed for pure Qt applications
|
|
KFileDialog dlg(KUrl(dir), qt2KdeFilter(filter), parent);
|
|
|
|
dlg.setOperationMode(KFileDialog::Saving);
|
|
dlg.setMode(KFile::File|KFile::LocalOnly);
|
|
dlg.setCaption(caption);
|
|
dlg.setConfirmOverwrite(!(options & QFileDialog::DontConfirmOverwrite));
|
|
dlg.exec();
|
|
|
|
QString rv(dlg.selectedFile());
|
|
|
|
if(!rv.isEmpty())
|
|
kde2QtFilter(filter, dlg.currentFilter(), selectedFilter);
|
|
|
|
return rv;
|
|
}
|
|
|
|
};
|
|
|
|
static KFileDialogQtOverride qtOverride;
|
|
|
|
#include "moc_kfiledialog.cpp"
|