forked from qt-creator/qt-creator
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
This commit is contained in:
@@ -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_TR_CATEGORY_CORE = QT_TRANSLATE_NOOP("Core", "Environment");
|
||||||
const char * const SETTINGS_ID_ENVIRONMENT = "A.General";
|
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;
|
const int TARGET_ICON_SIZE = 32;
|
||||||
|
|
||||||
} // namespace Constants
|
} // namespace Constants
|
||||||
|
|||||||
@@ -264,8 +264,7 @@ void ShortcutSettings::exportAction()
|
|||||||
QString fileName = ICore::instance()->fileManager()->getSaveFileNameWithExtension(
|
QString fileName = ICore::instance()->fileManager()->getSaveFileNameWithExtension(
|
||||||
tr("Export Keyboard Mapping Scheme"),
|
tr("Export Keyboard Mapping Scheme"),
|
||||||
ICore::instance()->resourcePath() + "/schemes/",
|
ICore::instance()->resourcePath() + "/schemes/",
|
||||||
tr("Keyboard Mapping Scheme (*.kms)"),
|
tr("Keyboard Mapping Scheme (*.kms)"));
|
||||||
".kms");
|
|
||||||
if (!fileName.isEmpty()) {
|
if (!fileName.isEmpty()) {
|
||||||
CommandsFile cf(fileName);
|
CommandsFile cf(fileName);
|
||||||
cf.exportCommands(m_scitems);
|
cf.exportCommands(m_scitems);
|
||||||
|
|||||||
@@ -77,6 +77,8 @@
|
|||||||
#include <QtGui/QSplitter>
|
#include <QtGui/QSplitter>
|
||||||
#include <QtGui/QStackedLayout>
|
#include <QtGui/QStackedLayout>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(Core::IEditor*)
|
Q_DECLARE_METATYPE(Core::IEditor*)
|
||||||
|
|
||||||
enum { debugEditorManager=0 };
|
enum { debugEditorManager=0 };
|
||||||
@@ -208,9 +210,6 @@ struct EditorManagerPrivate {
|
|||||||
QMap<QString, QVariant> m_editorStates;
|
QMap<QString, QVariant> m_editorStates;
|
||||||
Internal::OpenEditorsViewFactory *m_openEditorsFactory;
|
Internal::OpenEditorsViewFactory *m_openEditorsFactory;
|
||||||
|
|
||||||
QString fileFilters;
|
|
||||||
QString selectedFilter;
|
|
||||||
|
|
||||||
OpenEditorsModel *m_editorModel;
|
OpenEditorsModel *m_editorModel;
|
||||||
QString m_externalEditor;
|
QString m_externalEditor;
|
||||||
|
|
||||||
@@ -1152,33 +1151,28 @@ QString EditorManager::getOpenWithEditorId(const QString &fileName,
|
|||||||
return selectedId;
|
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();
|
QStringList filters = core->mimeDatabase()->filterStrings();
|
||||||
filters.sort();
|
|
||||||
selectedFilter->clear();
|
|
||||||
if (filters.empty())
|
if (filters.empty())
|
||||||
return rc;
|
return QString();
|
||||||
|
filters.sort();
|
||||||
|
filters.erase(std::unique(filters.begin(), filters.end()), filters.end());
|
||||||
|
|
||||||
const QString filterSeparator = QLatin1String(";;");
|
static const QString allFilesFilter =
|
||||||
foreach (const QString &filterString, filters) {
|
QCoreApplication::translate("Core", Constants::ALL_FILES_FILTER);
|
||||||
if (!rc.isEmpty())
|
if (selectedFilter)
|
||||||
rc += filterSeparator;
|
*selectedFilter = allFilesFilter;
|
||||||
rc += filterString;
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepend all files filter
|
// Prepend all files filter (instead of appending to work around a bug in Qt/Mac).
|
||||||
// prepending instead of appending to work around a bug in Qt/Mac
|
filters.prepend(allFilesFilter);
|
||||||
QString allFilesFilter = EditorManager::tr("All Files (*)");
|
|
||||||
if (!rc.isEmpty())
|
|
||||||
allFilesFilter += filterSeparator;
|
|
||||||
rc.prepend(allFilesFilter);
|
|
||||||
*selectedFilter = allFilesFilter;
|
|
||||||
|
|
||||||
return rc;
|
return filters.join(QLatin1String(";;"));
|
||||||
}
|
}
|
||||||
|
|
||||||
IEditor *EditorManager::openEditor(const QString &fileName, const QString &editorId,
|
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
|
QStringList EditorManager::getOpenFileNames() const
|
||||||
{
|
{
|
||||||
if (m_d->fileFilters.isEmpty())
|
QString selectedFilter;
|
||||||
m_d->fileFilters = formatFileFilters(m_d->m_core, &m_d->selectedFilter);
|
const QString &fileFilters = formatFileFilters(m_d->m_core, &selectedFilter);
|
||||||
return ICore::instance()->fileManager()->getOpenFileNames(m_d->fileFilters,
|
return ICore::instance()->fileManager()->getOpenFileNames(fileFilters,
|
||||||
QString(), &m_d->selectedFilter);
|
QString(), &selectedFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1475,23 +1469,35 @@ bool EditorManager::saveFileAs(IEditor *editor)
|
|||||||
if (!editor)
|
if (!editor)
|
||||||
return false;
|
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())
|
if (absoluteFilePath.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
if (absoluteFilePath != editor->file()->fileName()) {
|
if (absoluteFilePath != file->fileName()) {
|
||||||
const QList<IEditor *> existList = editorsForFileName(absoluteFilePath);
|
const QList<IEditor *> existList = editorsForFileName(absoluteFilePath);
|
||||||
if (!existList.isEmpty()) {
|
if (!existList.isEmpty()) {
|
||||||
closeEditors(existList, false);
|
closeEditors(existList, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_d->m_core->fileManager()->blockFileChange(editor->file());
|
m_d->m_core->fileManager()->blockFileChange(file);
|
||||||
const bool success = editor->file()->save(absoluteFilePath);
|
const bool success = file->save(absoluteFilePath);
|
||||||
m_d->m_core->fileManager()->unblockFileChange(editor->file());
|
m_d->m_core->fileManager()->unblockFileChange(file);
|
||||||
editor->file()->checkPermissions();
|
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())
|
if (success && !editor->isTemporary())
|
||||||
m_d->m_core->fileManager()->addToRecentFiles(editor->file()->fileName());
|
m_d->m_core->fileManager()->addToRecentFiles(file->fileName());
|
||||||
|
|
||||||
updateActions();
|
updateActions();
|
||||||
return success;
|
return success;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "mimedatabase.h"
|
#include "mimedatabase.h"
|
||||||
#include "saveitemsdialog.h"
|
#include "saveitemsdialog.h"
|
||||||
#include "vcsmanager.h"
|
#include "vcsmanager.h"
|
||||||
|
#include "coreconstants.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/pathchooser.h>
|
#include <utils/pathchooser.h>
|
||||||
@@ -689,22 +690,45 @@ QList<IFile *> FileManager::saveModifiedFiles(const QList<IFile *> &files,
|
|||||||
return notSaved;
|
return notSaved;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FileManager::getSaveFileNameWithExtension(const QString &title, const QString &pathIn,
|
QString FileManager::getSaveFileName(const QString &title, const QString &pathIn,
|
||||||
const QString &fileFilter, const QString &extension)
|
const QString &filter, QString *selectedFilter)
|
||||||
{
|
{
|
||||||
|
const QString &path = pathIn.isEmpty() ? fileDialogInitialDirectory() : pathIn;
|
||||||
QString fileName;
|
QString fileName;
|
||||||
bool repeat;
|
bool repeat;
|
||||||
do {
|
do {
|
||||||
repeat = false;
|
repeat = false;
|
||||||
const QString path = pathIn.isEmpty() ? fileDialogInitialDirectory() : pathIn;
|
fileName = QFileDialog::getSaveFileName(
|
||||||
fileName = QFileDialog::getSaveFileName(d->m_mainWindow, title, path, fileFilter);
|
d->m_mainWindow, title, path, filter, selectedFilter, QFileDialog::DontConfirmOverwrite);
|
||||||
if (!fileName.isEmpty() && !extension.isEmpty() && !fileName.endsWith(extension)) {
|
if (!fileName.isEmpty()) {
|
||||||
fileName.append(extension);
|
// 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 (QFile::exists(fileName)) {
|
||||||
if (QMessageBox::warning(d->m_mainWindow, tr("Overwrite?"),
|
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),
|
tr("An item named '%1' already exists at this location. "
|
||||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
"Do you want to overwrite it?").arg(fileName),
|
||||||
|
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
|
||||||
repeat = true;
|
repeat = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (repeat);
|
} while (repeat);
|
||||||
@@ -713,12 +737,19 @@ QString FileManager::getSaveFileNameWithExtension(const QString &title, const QS
|
|||||||
return fileName;
|
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)
|
\fn QString FileManager::getSaveAsFileName(IFile *file)
|
||||||
|
|
||||||
Asks the user for a new file name (Save File As) for /arg 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)
|
if (!file)
|
||||||
return QLatin1String("");
|
return QLatin1String("");
|
||||||
@@ -732,17 +763,20 @@ QString FileManager::getSaveAsFileName(IFile *file)
|
|||||||
if (!defaultPath.isEmpty())
|
if (!defaultPath.isEmpty())
|
||||||
path = defaultPath;
|
path = defaultPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString filterString;
|
QString filterString;
|
||||||
QString preferredSuffix;
|
if (filter.isEmpty()) {
|
||||||
if (const MimeType mt = Core::ICore::instance()->mimeDatabase()->findByFile(fi)) {
|
if (const MimeType &mt = Core::ICore::instance()->mimeDatabase()->findByFile(fi))
|
||||||
filterString = mt.filterString();
|
filterString = mt.filterString();
|
||||||
preferredSuffix = mt.preferredSuffix();
|
selectedFilter = &filterString;
|
||||||
|
} else {
|
||||||
|
filterString = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
absoluteFilePath = getSaveFileNameWithExtension(tr("Save File As"),
|
absoluteFilePath = getSaveFileName(tr("Save File As"),
|
||||||
path + QDir::separator() + fileName,
|
path + QDir::separator() + fileName,
|
||||||
filterString,
|
filterString,
|
||||||
preferredSuffix);
|
selectedFilter);
|
||||||
return absoluteFilePath;
|
return absoluteFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,10 +87,12 @@ public:
|
|||||||
QStringList getOpenFileNames(const QString &filters,
|
QStringList getOpenFileNames(const QString &filters,
|
||||||
const QString path = QString(),
|
const QString path = QString(),
|
||||||
QString *selectedFilter = 0);
|
QString *selectedFilter = 0);
|
||||||
|
QString getSaveFileName(const QString &title, const QString &pathIn,
|
||||||
QString getSaveFileNameWithExtension(const QString &title, const QString &path,
|
const QString &filter = QString(), QString *selectedFilter = 0);
|
||||||
const QString &fileFilter, const QString &extension);
|
QString getSaveFileNameWithExtension(const QString &title, const QString &pathIn,
|
||||||
QString getSaveAsFileName(IFile *file);
|
const QString &filter);
|
||||||
|
QString getSaveAsFileName(IFile *file, const QString &filter = QString(),
|
||||||
|
QString *selectedFilter = 0);
|
||||||
|
|
||||||
QList<IFile *> saveModifiedFilesSilently(const QList<IFile *> &files);
|
QList<IFile *> saveModifiedFilesSilently(const QList<IFile *> &files);
|
||||||
QList<IFile *> saveModifiedFiles(const QList<IFile *> &files,
|
QList<IFile *> saveModifiedFiles(const QList<IFile *> &files,
|
||||||
|
|||||||
Reference in New Issue
Block a user