From bcb3bb0fbab247cfb48dc4621359b539308670a6 Mon Sep 17 00:00:00 2001 From: Leandro Melo Date: Tue, 7 Sep 2010 11:55:52 +0200 Subject: Allow the user to save as files with different extensions. There is still an open issue in this fix since the new extension might be of a different mime type (and our editors are attached to it currently). More details documented in the code. Task-number: QTCREATORBUG-2094 Reviewed-by: Thorbjorn Lindeijer --- src/plugins/coreplugin/coreconstants.h | 2 + .../coreplugin/dialogs/shortcutsettings.cpp | 3 +- .../coreplugin/editormanager/editormanager.cpp | 74 ++++++++++++---------- src/plugins/coreplugin/filemanager.cpp | 64 ++++++++++++++----- src/plugins/coreplugin/filemanager.h | 10 +-- 5 files changed, 98 insertions(+), 55 deletions(-) diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index ecc1c2a4bc..13081d5ecc 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -246,6 +246,8 @@ const char * const SETTINGS_CATEGORY_CORE_ICON = ":/core/images/category_core.pn const char * const SETTINGS_TR_CATEGORY_CORE = QT_TRANSLATE_NOOP("Core", "Environment"); const char * const SETTINGS_ID_ENVIRONMENT = "A.General"; +const char * const ALL_FILES_FILTER = QT_TRANSLATE_NOOP("Core", "All Files (*)"); + const int TARGET_ICON_SIZE = 32; } // namespace Constants diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp index 59b5b2e8fe..74abe1321e 100644 --- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp +++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp @@ -264,8 +264,7 @@ void ShortcutSettings::exportAction() QString fileName = ICore::instance()->fileManager()->getSaveFileNameWithExtension( tr("Export Keyboard Mapping Scheme"), ICore::instance()->resourcePath() + "/schemes/", - tr("Keyboard Mapping Scheme (*.kms)"), - ".kms"); + tr("Keyboard Mapping Scheme (*.kms)")); if (!fileName.isEmpty()) { CommandsFile cf(fileName); cf.exportCommands(m_scitems); diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index c0e56ac3a8..6b58cc7f85 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -77,6 +77,8 @@ #include #include +#include + Q_DECLARE_METATYPE(Core::IEditor*) enum { debugEditorManager=0 }; @@ -208,9 +210,6 @@ struct EditorManagerPrivate { QMap m_editorStates; Internal::OpenEditorsViewFactory *m_openEditorsFactory; - QString fileFilters; - QString selectedFilter; - OpenEditorsModel *m_editorModel; QString m_externalEditor; @@ -1152,33 +1151,28 @@ QString EditorManager::getOpenWithEditorId(const QString &fileName, return selectedId; } -static QString formatFileFilters(const Core::ICore *core, QString *selectedFilter) +static QString formatFileFilters(const Core::ICore *core, QString *selectedFilter = 0) { - QString rc; + if (selectedFilter) + selectedFilter->clear(); - // Compile list of filter strings + // Compile list of filter strings, sort, and remove duplicates (different mime types might + // generate the same filter). QStringList filters = core->mimeDatabase()->filterStrings(); - filters.sort(); - selectedFilter->clear(); if (filters.empty()) - return rc; + return QString(); + filters.sort(); + filters.erase(std::unique(filters.begin(), filters.end()), filters.end()); - const QString filterSeparator = QLatin1String(";;"); - foreach (const QString &filterString, filters) { - if (!rc.isEmpty()) - rc += filterSeparator; - rc += filterString; - } + static const QString allFilesFilter = + QCoreApplication::translate("Core", Constants::ALL_FILES_FILTER); + if (selectedFilter) + *selectedFilter = allFilesFilter; - // prepend all files filter - // prepending instead of appending to work around a bug in Qt/Mac - QString allFilesFilter = EditorManager::tr("All Files (*)"); - if (!rc.isEmpty()) - allFilesFilter += filterSeparator; - rc.prepend(allFilesFilter); - *selectedFilter = allFilesFilter; + // Prepend all files filter (instead of appending to work around a bug in Qt/Mac). + filters.prepend(allFilesFilter); - return rc; + return filters.join(QLatin1String(";;")); } IEditor *EditorManager::openEditor(const QString &fileName, const QString &editorId, @@ -1244,10 +1238,10 @@ bool EditorManager::openExternalEditor(const QString &fileName, const QString &e QStringList EditorManager::getOpenFileNames() const { - if (m_d->fileFilters.isEmpty()) - m_d->fileFilters = formatFileFilters(m_d->m_core, &m_d->selectedFilter); - return ICore::instance()->fileManager()->getOpenFileNames(m_d->fileFilters, - QString(), &m_d->selectedFilter); + QString selectedFilter; + const QString &fileFilters = formatFileFilters(m_d->m_core, &selectedFilter); + return ICore::instance()->fileManager()->getOpenFileNames(fileFilters, + QString(), &selectedFilter); } @@ -1475,23 +1469,35 @@ bool EditorManager::saveFileAs(IEditor *editor) if (!editor) return false; - QString absoluteFilePath = m_d->m_core->fileManager()->getSaveAsFileName(editor->file()); + IFile *file = editor->file(); + const QString &filter = formatFileFilters(m_d->m_core); + QString selectedFilter = + m_d->m_core->mimeDatabase()->findByFile(QFileInfo(file->fileName())).filterString(); + const QString &absoluteFilePath = + m_d->m_core->fileManager()->getSaveAsFileName(file, filter, &selectedFilter); + if (absoluteFilePath.isEmpty()) return false; - if (absoluteFilePath != editor->file()->fileName()) { + if (absoluteFilePath != file->fileName()) { const QList existList = editorsForFileName(absoluteFilePath); if (!existList.isEmpty()) { closeEditors(existList, false); } } - m_d->m_core->fileManager()->blockFileChange(editor->file()); - const bool success = editor->file()->save(absoluteFilePath); - m_d->m_core->fileManager()->unblockFileChange(editor->file()); - editor->file()->checkPermissions(); + m_d->m_core->fileManager()->blockFileChange(file); + const bool success = file->save(absoluteFilePath); + m_d->m_core->fileManager()->unblockFileChange(file); + file->checkPermissions(); + + // @todo: There is an issue to be treated here. The new file might be of a different mime + // type than the original and thus require a different editor. An alternative strategy + // would be to close the current editor and open a new appropriate one, but this is not + // a good way out either (also the undo stack would be lost). Perhaps the best is to + // re-think part of the editors design. if (success && !editor->isTemporary()) - m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName()); + m_d->m_core->fileManager()->addToRecentFiles(file->fileName()); updateActions(); return success; diff --git a/src/plugins/coreplugin/filemanager.cpp b/src/plugins/coreplugin/filemanager.cpp index 1551adc04e..bb5bf60825 100644 --- a/src/plugins/coreplugin/filemanager.cpp +++ b/src/plugins/coreplugin/filemanager.cpp @@ -37,6 +37,7 @@ #include "mimedatabase.h" #include "saveitemsdialog.h" #include "vcsmanager.h" +#include "coreconstants.h" #include #include @@ -689,22 +690,45 @@ QList FileManager::saveModifiedFiles(const QList &files, return notSaved; } -QString FileManager::getSaveFileNameWithExtension(const QString &title, const QString &pathIn, - const QString &fileFilter, const QString &extension) +QString FileManager::getSaveFileName(const QString &title, const QString &pathIn, + const QString &filter, QString *selectedFilter) { + const QString &path = pathIn.isEmpty() ? fileDialogInitialDirectory() : pathIn; QString fileName; bool repeat; do { repeat = false; - const QString path = pathIn.isEmpty() ? fileDialogInitialDirectory() : pathIn; - fileName = QFileDialog::getSaveFileName(d->m_mainWindow, title, path, fileFilter); - if (!fileName.isEmpty() && !extension.isEmpty() && !fileName.endsWith(extension)) { - fileName.append(extension); + fileName = QFileDialog::getSaveFileName( + d->m_mainWindow, title, path, filter, selectedFilter, QFileDialog::DontConfirmOverwrite); + if (!fileName.isEmpty()) { + // If the selected filter is All Files (*) we leave the name exactly as the user + // specified. Otherwise the suffix must be one available in the selected filter. If + // the name already ends with such suffix nothing needs to be done. But if not, the + // first one from the filter is appended. + if (selectedFilter && *selectedFilter != QCoreApplication::translate( + "Core", Constants::ALL_FILES_FILTER)) { + // Mime database creates filter strings like this: Anything here (*.foo *.bar) + QRegExp regExp(".*\\s+\\((.*)\\)$"); + const int index = regExp.lastIndexIn(*selectedFilter); + bool suffixOk = false; + if (index != -1) { + const QStringList &suffixes = regExp.cap(1).remove('*').split(' '); + foreach (const QString &suffix, suffixes) + if (fileName.endsWith(suffix)) { + suffixOk = true; + break; + } + if (!suffixOk && !suffixes.isEmpty()) + fileName.append(suffixes.at(0)); + } + } if (QFile::exists(fileName)) { if (QMessageBox::warning(d->m_mainWindow, tr("Overwrite?"), - tr("An item named '%1' already exists at this location. Do you want to overwrite it?").arg(fileName), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) + tr("An item named '%1' already exists at this location. " + "Do you want to overwrite it?").arg(fileName), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) { repeat = true; + } } } } while (repeat); @@ -713,12 +737,19 @@ QString FileManager::getSaveFileNameWithExtension(const QString &title, const QS return fileName; } +QString FileManager::getSaveFileNameWithExtension(const QString &title, const QString &pathIn, + const QString &filter) +{ + QString selected = filter; + return getSaveFileName(title, pathIn, filter, &selected); +} + /*! \fn QString FileManager::getSaveAsFileName(IFile *file) Asks the user for a new file name (Save File As) for /arg file. */ -QString FileManager::getSaveAsFileName(IFile *file) +QString FileManager::getSaveAsFileName(IFile *file, const QString &filter, QString *selectedFilter) { if (!file) return QLatin1String(""); @@ -732,17 +763,20 @@ QString FileManager::getSaveAsFileName(IFile *file) if (!defaultPath.isEmpty()) path = defaultPath; } + QString filterString; - QString preferredSuffix; - if (const MimeType mt = Core::ICore::instance()->mimeDatabase()->findByFile(fi)) { - filterString = mt.filterString(); - preferredSuffix = mt.preferredSuffix(); + if (filter.isEmpty()) { + if (const MimeType &mt = Core::ICore::instance()->mimeDatabase()->findByFile(fi)) + filterString = mt.filterString(); + selectedFilter = &filterString; + } else { + filterString = filter; } - absoluteFilePath = getSaveFileNameWithExtension(tr("Save File As"), + absoluteFilePath = getSaveFileName(tr("Save File As"), path + QDir::separator() + fileName, filterString, - preferredSuffix); + selectedFilter); return absoluteFilePath; } diff --git a/src/plugins/coreplugin/filemanager.h b/src/plugins/coreplugin/filemanager.h index 9834bce17e..0de9933308 100644 --- a/src/plugins/coreplugin/filemanager.h +++ b/src/plugins/coreplugin/filemanager.h @@ -87,10 +87,12 @@ public: QStringList getOpenFileNames(const QString &filters, const QString path = QString(), QString *selectedFilter = 0); - - QString getSaveFileNameWithExtension(const QString &title, const QString &path, - const QString &fileFilter, const QString &extension); - QString getSaveAsFileName(IFile *file); + QString getSaveFileName(const QString &title, const QString &pathIn, + const QString &filter = QString(), QString *selectedFilter = 0); + QString getSaveFileNameWithExtension(const QString &title, const QString &pathIn, + const QString &filter); + QString getSaveAsFileName(IFile *file, const QString &filter = QString(), + QString *selectedFilter = 0); QList saveModifiedFilesSilently(const QList &files); QList saveModifiedFiles(const QList &files, -- cgit v1.2.1