[calligra/calligra/2.8] libs/widgets: Fix: no file formats shown in save dialogs
Cyrille Berger
cberger at cberger.net
Mon Jun 30 08:56:41 BST 2014
Git commit cf804b42cb313d53729a4535622bda66951e6e42 by Cyrille Berger.
Committed on 30/06/2014 at 07:54.
Pushed by berger into branch 'calligra/2.8'.
Fix: no file formats shown in save dialogs
Backports KoFileDialog from master.
Tested on several applications, seem to work, but if someone else could test and confirm ?
CCMAIL: calligra-devel at kde.org
M +261 -208 libs/widgets/KoFileDialog.cpp
M +62 -19 libs/widgets/KoFileDialog.h
http://commits.kde.org/calligra/cf804b42cb313d53729a4535622bda66951e6e42
diff --git a/libs/widgets/KoFileDialog.cpp b/libs/widgets/KoFileDialog.cpp
index 534ab9e..eb02a00 100644
--- a/libs/widgets/KoFileDialog.cpp
+++ b/libs/widgets/KoFileDialog.cpp
@@ -21,12 +21,12 @@
#include <QDebug>
#include <QFileDialog>
#include <QApplication>
+#include <QImageReader>
#include <kconfiggroup.h>
#include <kmimetype.h>
#include <klocale.h>
-
class KoFileDialog::Private
{
public:
@@ -34,34 +34,61 @@ public:
KoFileDialog::DialogType dialogType_,
const QString caption_,
const QString defaultDir_,
- const QString uniqueName_)
+ const QString dialogName_)
: parent(parent_)
, type(dialogType_)
- , uniqueName(uniqueName_)
+ , dialogName(dialogName_)
, caption(caption_)
- , directory(defaultDir_)
- , filterType(KoFileDialog::NameFilter)
+ , defaultDirectory(defaultDir_)
, filterList(QStringList())
, defaultFilter(QString())
, fileDialog(0)
+ , mimeType(0)
+ , useStaticForNative(false)
+ , hideDetails(false)
{
+ // Force the native file dialogs on Windows. Except for KDE, the native file dialogs are only possible
+ // using the static methods. The Qt documentation is wrong here, if it means what it says " By default,
+ // the native file dialog is used unless you use a subclass of QFileDialog that contains the Q_OBJECT
+ // macro."
+#ifdef Q_OS_WIN
+ useStaticForNative = true;
+#endif
+ // Non-static KDE file is broken when called with QFileDialog::AcceptSave:
+ // then the directory above defaultdir is opened, and defaultdir is given as the default file name...
+ //
+ // So: in X11, use static methods inside KDE, which give working native dialogs, but non-static outside
+ // KDE, which gives working Qt dialogs.
+ //
+ // Only show the GTK dialog in Gnome, where people deserve it
+#ifdef Q_WS_X11
+ if (qgetenv("KDE_FULL_SESSION").size() > 0) {
+ useStaticForNative = true;
+ }
+ if (qgetenv("XDG_CURRENT_DESKTOP") == "GNOME") {
+ useStaticForNative = true;
+ }
+
+#endif
}
QWidget *parent;
KoFileDialog::DialogType type;
- QString uniqueName;
+ QString dialogName;
QString caption;
- QString directory;
- KoFileDialog::FilterType filterType;
+ QString defaultDirectory;
QStringList filterList;
QString defaultFilter;
QFileDialog *fileDialog;
+ KMimeType::Ptr mimeType;
+ bool useStaticForNative;
+ bool hideDetails;
};
KoFileDialog::KoFileDialog(QWidget *parent,
KoFileDialog::DialogType type,
- const QString uniqueName)
- : d(new Private(parent, type, "", getUsedDir(uniqueName), uniqueName))
+ const QString dialogName)
+ : d(new Private(parent, type, "", getUsedDir(dialogName), dialogName))
{
}
@@ -78,40 +105,99 @@ void KoFileDialog::setCaption(const QString &caption)
void KoFileDialog::setDefaultDir(const QString &defaultDir)
{
- if (d->directory.isEmpty() || d->directory.isNull())
- d->directory = defaultDir;
+ if (d->defaultDirectory.isEmpty() || !QDir(d->defaultDirectory).exists()) {
+ d->defaultDirectory = defaultDir;
+ }
+}
+
+void KoFileDialog::setOverrideDir(const QString &overrideDir)
+{
+ d->defaultDirectory = overrideDir;
+}
+
+void KoFileDialog::setImageFilters()
+{
+ QStringList imageFilters;
+ // add filters for all formats supported by QImage
+ foreach(const QByteArray &format, QImageReader::supportedImageFormats()) {
+ imageFilters << "image/" + format;
+ }
+ setMimeTypeFilters(imageFilters);
}
void KoFileDialog::setNameFilter(const QString &filter)
{
- d->filterType = KoFileDialog::NameFilter;
d->filterList.clear();
- d->filterList << filter;
- d->defaultFilter.clear();
+ if (d->type == KoFileDialog::SaveFile) {
+ d->filterList << splitNameFilter(filter);
+ d->defaultFilter = d->filterList.first();
+ }
+ else {
+ d->filterList << filter;
+ }
}
void KoFileDialog::setNameFilters(const QStringList &filterList,
- const QString &defaultFilter)
+ QString defaultFilter)
{
- d->filterType = KoFileDialog::NameFilter;
- d->filterList = filterList;
+ d->filterList.clear();
+
+ if (d->type == KoFileDialog::SaveFile) {
+ foreach(const QString &filter, filterList) {
+ d->filterList << splitNameFilter(filter);
+ }
+
+ if (!defaultFilter.isEmpty()) {
+ QStringList defaultFilters = splitNameFilter(defaultFilter);
+ if (defaultFilters.size() > 0) {
+ defaultFilter = defaultFilters.first();
+ }
+ }
+ }
+ else {
+ d->filterList = filterList;
+ }
d->defaultFilter = defaultFilter;
+
}
void KoFileDialog::setMimeTypeFilters(const QStringList &filterList,
- const QString &defaultFilter)
+ QString defaultFilter)
{
- d->filterType = KoFileDialog::MimeFilter;
- d->filterList = filterList;
+ d->filterList = getFilterStringListFromMime(filterList, true);
+
+ if (!defaultFilter.isEmpty()) {
+ QStringList defaultFilters = getFilterStringListFromMime(QStringList() << defaultFilter, false);
+ if (defaultFilters.size() > 0) {
+ defaultFilter = defaultFilters.first();
+ }
+ }
d->defaultFilter = defaultFilter;
}
void KoFileDialog::setHideNameFilterDetailsOption()
{
- if (!d->fileDialog) {
- createFileDialog();
+ d->hideDetails = true;
+}
+
+QString KoFileDialog::selectedNameFilter() const
+{
+ if (!d->useStaticForNative) {
+ return d->fileDialog->selectedNameFilter();
+ }
+ else {
+ return d->defaultFilter;
+ }
+}
+
+QString KoFileDialog::selectedMimeType() const
+{
+ if (d->mimeType) {
+ return d->mimeType->name();
+ }
+ else {
+ return "";
}
- d->fileDialog->setOption(QFileDialog::HideNameFilterDetails);
}
void KoFileDialog::createFileDialog()
@@ -120,198 +206,209 @@ void KoFileDialog::createFileDialog()
delete d->fileDialog;
}
- d->fileDialog = new QFileDialog(d->parent, d->caption, d->directory);
+ d->fileDialog = new QFileDialog(d->parent, d->caption, d->defaultDirectory);
- if (d->type == SaveFile || d->type == SaveFiles) {
+ if (d->type == SaveFile) {
d->fileDialog->setAcceptMode(QFileDialog::AcceptSave);
d->fileDialog->setFileMode(QFileDialog::AnyFile);
- } else { // open / import
+ }
+ else { // open / import
+
d->fileDialog->setAcceptMode(QFileDialog::AcceptOpen);
- if (d->type == ImportDirectory || d->type == ImportDirectories ||
- d->type == OpenDirectory || d->type == OpenDirectories) {
+
+ if (d->type == ImportDirectory
+ || d->type == OpenDirectory)
+ {
d->fileDialog->setFileMode(QFileDialog::Directory);
d->fileDialog->setOption(QFileDialog::ShowDirsOnly, true);
- } else { // open / import file(s)
- if (d->type == OpenFile || d->type == ImportFile) {
+ }
+ else { // open / import file(s)
+ if (d->type == OpenFile
+ || d->type == ImportFile)
+ {
d->fileDialog->setFileMode(QFileDialog::ExistingFile);
- } else { // files
+ }
+ else { // files
d->fileDialog->setFileMode(QFileDialog::ExistingFiles);
}
}
}
- // add "All Supported Formats" filter
- if (d->type == OpenFile || d->type == OpenFiles ||
- d->type == ImportFile || d->type == ImportFiles) {
- if (d->filterType == MimeFilter) {
- d->filterType = NameFilter;
- d->filterList = getFilterStringList(d->filterList, true);
- d->defaultFilter = getFilterString(d->defaultFilter);
- }
- }
-
- if (d->filterType = MimeFilter) {
-#if QT_VERSION >= 0x050200
- d->fileDialog->setMimeTypeFilters(d->filterList);
- if (!d->defaultFilter.isEmpty())
- d->fileDialog->selectMimeTypeFilter(d->defaultFilter);
-#else
- d->fileDialog->setNameFilters(getFilterStringList(d->filterList));
- if (!d->defaultFilter.isEmpty())
- d->fileDialog->selectNameFilter(getFilterString(d->defaultFilter));
-#endif
- } else {
- d->fileDialog->setNameFilters(d->filterList);
- if (!d->defaultFilter.isEmpty())
- d->fileDialog->selectNameFilter(d->defaultFilter);
+ d->fileDialog->setNameFilters(d->filterList);
+ if (!d->defaultFilter.isEmpty()) {
+ d->fileDialog->selectNameFilter(d->defaultFilter);
}
- if (d->type == ImportDirectory || d->type == ImportDirectories ||
+ if (d->type == ImportDirectory ||
d->type == ImportFile || d->type == ImportFiles ||
- d->type == SaveFile || d->type == SaveFiles) {
+ d->type == SaveFile) {
d->fileDialog->setWindowModality(Qt::WindowModal);
}
-#ifdef Q_WS_X11
- if (qgetenv("KDE_FULL_SESSION").size() == 0) {
- d->fileDialog->setOption(QFileDialog::DontUseNativeDialog);
+ if (d->hideDetails) {
+ d->fileDialog->setOption(QFileDialog::HideNameFilterDetails);
}
-#endif
connect(d->fileDialog, SIGNAL(filterSelected(QString)), this, SLOT(filterSelected(QString)));
}
QString KoFileDialog::url()
{
-#ifndef Q_OS_WIN
- if (!d->fileDialog) {
- createFileDialog();
- }
QString url;
- if (d->fileDialog->exec() == QDialog::Accepted) {
- url = d->fileDialog->selectedFiles().first();
- saveUsedDir(url, d->uniqueName);
- }
- return url;
-#else
- QString url;
- switch (d->type) {
- case OpenFile:
- {
- url = QFileDialog::getOpenFileName(d->parent,
- d->caption,
- d->directory,
- getFilterString(d->filterList),
- &d->defaultFilter);
- break;
- }
- case OpenDirectory:
- {
- url = QFileDialog::getExistingDirectory(d->parent,
- d->caption,
- "",
- QFileDialog::ShowDirsOnly);
- break;
- }
- case ImportFile:
- {
- url = QFileDialog::getOpenFileName(d->parent,
- d->caption,
- d->directory,
- getFilterString(d->filterList),
- &d->defaultFilter);
- break;
- }
- case ImportDirectory:
- {
- url = QFileDialog::getExistingDirectory(d->parent,
- d->caption,
- d->directory,
- QFileDialog::ShowDirsOnly);
- break;
- }
- case SaveFile:
- {
- url = QFileDialog::getSaveFileName(d->parent,
- d->caption,
- d->directory,
- getFilterString(d->filterList),
- &d->defaultFilter);
- break;
+ if (!d->useStaticForNative) {
+
+ if (!d->fileDialog) {
+ createFileDialog();
+ }
+
+ if (d->fileDialog->exec() == QDialog::Accepted) {
+ url = d->fileDialog->selectedFiles().first();
+ }
}
- default:
- ;
+ else {
+ switch (d->type) {
+ case OpenFile:
+ {
+ url = QFileDialog::getOpenFileName(d->parent,
+ d->caption,
+ d->defaultDirectory,
+ d->filterList.join(";;"),
+ &d->defaultFilter);
+ break;
+ }
+ case OpenDirectory:
+ {
+ url = QFileDialog::getExistingDirectory(d->parent,
+ d->caption,
+ d->defaultDirectory,
+ QFileDialog::ShowDirsOnly);
+ break;
+ }
+ case ImportFile:
+ {
+ url = QFileDialog::getOpenFileName(d->parent,
+ d->caption,
+ d->defaultDirectory,
+ d->filterList.join(";;"),
+ &d->defaultFilter);
+ break;
+ }
+ case ImportDirectory:
+ {
+ url = QFileDialog::getExistingDirectory(d->parent,
+ d->caption,
+ d->defaultDirectory,
+ QFileDialog::ShowDirsOnly);
+ break;
+ }
+ case SaveFile:
+ {
+ url = QFileDialog::getSaveFileName(d->parent,
+ d->caption,
+ d->defaultDirectory,
+ d->filterList.join(";;"),
+ &d->defaultFilter);
+ break;
+ }
+ default:
+ ;
+ }
}
- qDebug() << url << "," << d->defaultFilter;
- if (d->type == SaveFile && QFileInfo(url).suffix().isEmpty()) {
- int start = d->defaultFilter.lastIndexOf("*.") + 2;
- int end = d->defaultFilter.lastIndexOf(" )");
- int n = end - start;
- QString extension = d->defaultFilter.mid(start, n);
- url.append(extension);
+
+ if (!url.isEmpty()) {
+
+ if (d->type == SaveFile && QFileInfo(url).suffix().isEmpty()) {
+ int start = d->defaultFilter.lastIndexOf("*.") + 1;
+ int end = d->defaultFilter.lastIndexOf(" )");
+ int n = end - start;
+ QString extension = d->defaultFilter.mid(start, n);
+ url.append(extension);
+ }
+
+ d->mimeType = KMimeType::findByUrl(KUrl(url), 0, true, true);
+ saveUsedDir(url, d->dialogName);
+
}
return url;
-#endif
}
QStringList KoFileDialog::urls()
{
-#ifndef Q_OS_WIN
- if (!d->fileDialog) {
- createFileDialog();
- }
QStringList urls;
- if (d->fileDialog->exec() == QDialog::Accepted) {
- urls = d->fileDialog->selectedFiles();
- saveUsedDir(urls.first(), d->uniqueName);
- }
- return urls;
-#else
- switch (d->type) {
- case OpenFiles:
- case ImportFiles:
- {
- return QFileDialog::getOpenFileNames(d->parent,
- d->caption,
- d->directory,
- getFilterString(d->filterList),
- &d->defaultFilter);
- }
- case OpenDirectories:
- case ImportDirectories:
- case SaveFiles:
- {
- // These don't exist as a static method. They aren't used in Calligra either, afaict
+
+ if (!d->useStaticForNative) {
if (!d->fileDialog) {
createFileDialog();
}
- QStringList urls;
if (d->fileDialog->exec() == QDialog::Accepted) {
urls = d->fileDialog->selectedFiles();
- saveUsedDir(urls.first(), d->uniqueName);
}
- return urls;
-
}
- default:
- return QStringList();
+ else {
+ switch (d->type) {
+ case OpenFiles:
+ case ImportFiles:
+ {
+ urls = QFileDialog::getOpenFileNames(d->parent,
+ d->caption,
+ d->defaultDirectory,
+ d->filterList.join(";;"),
+ &d->defaultFilter);
+ break;
+ }
+ default:
+ ;
+ }
}
-#endif
+ if (urls.size() > 0) {
+ saveUsedDir(urls.first(), d->dialogName);
+ }
+ return urls;
}
void KoFileDialog::filterSelected(const QString &filter)
{
- "Windows BMP image ( *.bmp )";
+ // "Windows BMP image ( *.bmp )";
int start = filter.lastIndexOf("*.") + 2;
int end = filter.lastIndexOf(" )");
int n = end - start;
QString extension = filter.mid(start, n);
-
+ d->defaultFilter = filter;
d->fileDialog->setDefaultSuffix(extension);
}
-const QStringList KoFileDialog::getFilterStringList(const QStringList &mimeList,
- bool withAllSupportedEntry)
+QStringList KoFileDialog::splitNameFilter(const QString &nameFilter)
+{
+ QStringList filters;
+ QString description;
+
+ if (nameFilter.contains("(")) {
+ description = nameFilter.left(nameFilter.indexOf("(") -1).trimmed();
+ }
+
+
+ QStringList entries = nameFilter.mid(nameFilter.indexOf("(") + 1).split(" ",QString::SkipEmptyParts );
+
+
+ foreach(QString entry, entries) {
+
+ entry = entry.remove("*");
+ entry = entry.remove(")");
+
+ KMimeType::Ptr mime = KMimeType::findByUrl(KUrl("bla" + entry), 0, true, true);
+ if (mime->name() != "application/octet-stream") {
+ filters.append(mime->comment() + "( *" + entry + " )");
+ }
+ else {
+ filters.append(entry.remove(".").toUpper() + " " + description + " ( " + entry + " )");
+ }
+ }
+
+ return filters;
+}
+
+const QStringList KoFileDialog::getFilterStringListFromMime(const QStringList &mimeList,
+ bool withAllSupportedEntry)
{
QStringList ret;
if (withAllSupportedEntry) {
@@ -339,37 +436,23 @@ const QStringList KoFileDialog::getFilterStringList(const QStringList &mimeList,
if (withAllSupportedEntry) {
ret[0].append(")");
}
-
return ret;
}
-const QString KoFileDialog::getFilterString(const QString &defaultMime)
-{
- QString filter;
- KMimeType::Ptr type = KMimeType::mimeType(defaultMime);
- if(type) {
- filter.append(type->comment() + " (");
- QStringList patterns = type->patterns();
- QStringList::ConstIterator jt;
- for (jt = patterns.begin(); jt != patterns.end(); ++jt)
- filter.append(*jt + " ");
- filter.append(")");
- }
- return filter;
-}
-
const QString KoFileDialog::getUsedDir(const QString &dialogName)
{
if (dialogName.isEmpty()) return "";
KConfigGroup group = KGlobal::config()->group("File Dialogs");
QString dir = group.readEntry(dialogName);
+
return dir;
}
void KoFileDialog::saveUsedDir(const QString &fileName,
const QString &dialogName)
{
+
if (dialogName.isEmpty()) return;
QFileInfo fileInfo(fileName);
@@ -378,33 +461,3 @@ void KoFileDialog::saveUsedDir(const QString &fileName,
}
-const QString KoFileDialog::getFilterString(const QStringList &mimeList,
- bool withAllSupported)
-{
- QString allSupportedFilter;
- if (withAllSupported) {
- allSupportedFilter = QString(i18n("All supported formats") + " ( ");
- }
- QString restFilters;
- for (QStringList::ConstIterator it = mimeList.begin(); it != mimeList.end(); ++it) {
- KMimeType::Ptr type = KMimeType::mimeType( *it );
- if(!type)
- continue;
- restFilters.append(";;" + type->comment() + " ( ");
- QStringList patterns = type->patterns();
- QStringList::ConstIterator jt;
- for (jt = patterns.begin(); jt != patterns.end(); ++jt) {
- restFilters.append(*jt + " ");
- if (withAllSupported) {
- allSupportedFilter.append(*jt + " ");
- }
- }
- restFilters.append(")");
- }
-
- if (withAllSupported) {
- return allSupportedFilter + ")" + restFilters;
- } else {
- return restFilters.remove(0, 2);
- }
-}
diff --git a/libs/widgets/KoFileDialog.h b/libs/widgets/KoFileDialog.h
index 87d6457..e446c52 100644
--- a/libs/widgets/KoFileDialog.h
+++ b/libs/widgets/KoFileDialog.h
@@ -42,65 +42,108 @@ public:
OpenFile,
OpenFiles,
OpenDirectory,
- OpenDirectories,
ImportFile,
ImportFiles,
ImportDirectory,
- ImportDirectories,
- SaveFile,
- SaveFiles
+ SaveFile
};
/**
* @brief constructor
* @param parent The parent of the file dialog
* @param dialogType usage of the file dialog
- * @param uniqueName the name for the file dialog. This will be used to open
+ * @param dialogName the name for the file dialog. This will be used to open
* the filedialog in the last open location, instead the specified directory.
*
* @return The name of the entry user selected in the file dialog
*
*/
- KoFileDialog(QWidget *parent = 0,
- KoFileDialog::DialogType type = OpenFile,
- const QString uniqueName = QString());
+ KoFileDialog(QWidget *parent,
+ KoFileDialog::DialogType type,
+ const QString dialogName = QString());
~KoFileDialog();
void setCaption(const QString &caption);
+
+ /**
+ * @brief setDefaultDir set the default directory to defaultDir
+ *
+ * @param defaultDir a path to a file or directory
+ */
void setDefaultDir(const QString &defaultDir);
+
+ /**
+ * @brief setOverrideDir override both the default dir and the saved dir found by dialogName
+ * @param overrideDir a path to a file or directory
+ */
+ void setOverrideDir(const QString &overrideDir);
+
+ /**
+ * @brief setImageFilters sets the name filters for the file dialog to all
+ * image formats Qt's QImageReader supports.
+ */
+ void setImageFilters();
+
void setNameFilter(const QString &filter);
+
+ /**
+ * @brief setNameFilters set a list of description/extension pairs.
+ *
+ * These are not registered mimetypes. In contrast with Qt's filedialog namefilters,
+ * you can only have _one_ pair per line. I.e.
+ *
+ * Gif Image (*gif)
+ * Tiff Image (*tif)
+ *
+ * And NOT Images (*gif *tif)
+ *
+ * @param filterList
+ * @param defaultFilter
+ */
void setNameFilters(const QStringList &filterList,
- const QString &defaultFilter = QString());
+ QString defaultFilter = QString());
void setMimeTypeFilters(const QStringList &filterList,
- const QString &defaultFilter = QString());
+ QString defaultFilter = QString());
void setHideNameFilterDetailsOption();
QStringList urls();
QString url();
+ /**
+ * @brief selectedNameFilter returns the name filter the user selected, either
+ * directory or by clicking on it.
+ * @return
+ */
+ QString selectedNameFilter() const;
+
+ QString selectedMimeType() const;
+
private slots:
void filterSelected(const QString &filter);
private:
- enum FilterType {
- MimeFilter,
- NameFilter
- };
+ /**
+ * @brief splitNameFilter take a single line of a QDialog name filter and split it
+ * into several lines. This is needed because a single line name filter can contain
+ * more than one mimetype, making it impossible to figure out the correct extension.
+ *
+ * The methods takes care of some duplicated extensions, like jpeg and jpg.
+ * @param nameFilter the namefilter to be split
+ * @return a stringlist of all name filters.
+ */
+ QStringList splitNameFilter(const QString &nameFilter);
void createFileDialog();
const QString getUsedDir(const QString &dialogName);
void saveUsedDir(const QString &fileName, const QString &dialogName);
- const QStringList getFilterStringList(const QStringList &mimeList,
- bool withAllSupportedEntry = false);
+ const QStringList getFilterStringListFromMime(const QStringList &mimeList,
+ bool withAllSupportedEntry = false);
- const QString getFilterString(const QStringList &mimeList,
- bool withAllSupportedEntry = false);
- const QString getFilterString(const QString &defaultMime);
class Private;
Private * const d;
More information about the calligra-devel
mailing list