diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index ecc1c2a4bc26dcba9e6def2a20d7c8a5e8ec80e3..13081d5ecc764eb311771a26acc443316d63a78e 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 59b5b2e8fe97c9a8348e247dbfaf40d5c442d069..74abe1321e12452d3241ec37c44b16bfdcc8b6e0 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 c0e56ac3a8b97d7b3c2295fbe427fd12b015c467..6b58cc7f8508aebec056907f9cbe65ddaa1665d1 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -77,6 +77,8 @@ #include <QtGui/QSplitter> #include <QtGui/QStackedLayout> +#include <algorithm> + Q_DECLARE_METATYPE(Core::IEditor*) enum { debugEditorManager=0 }; @@ -208,9 +210,6 @@ struct EditorManagerPrivate { QMap<QString, QVariant> 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<IEditor *> 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 1551adc04eecc8475435a774eee40742e6c3dcf8..bb5bf60825ff4568fb616d41458716d08afec40a 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 <utils/qtcassert.h> #include <utils/pathchooser.h> @@ -689,22 +690,45 @@ QList<IFile *> FileManager::saveModifiedFiles(const QList<IFile *> &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 9834bce17e58c13cbcf35df9ab6e5ce16a9fc905..0de993330843849ee26f85d29074418e53e58859 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<IFile *> saveModifiedFilesSilently(const QList<IFile *> &files); QList<IFile *> saveModifiedFiles(const QList<IFile *> &files, diff --git a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp index 60107acf4f3bcd3b1ae5493dbb8e028e8a9a9188..838e0c1191db5c2323d3ab7f0d7d2a66efac51c1 100644 --- a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp +++ b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp @@ -58,7 +58,7 @@ CppCurrentDocumentFilter::CppCurrentDocumentFilter(CppModelManager *manager, Cor this, SLOT(onEditorAboutToClose(Core::IEditor*))); } -QList<Locator::FilterEntry> CppCurrentDocumentFilter::matchesFor(const QString & origEntry) +QList<Locator::FilterEntry> CppCurrentDocumentFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString & origEntry) { QString entry = trimWildcards(origEntry); QList<Locator::FilterEntry> goodEntries; @@ -82,6 +82,9 @@ QList<Locator::FilterEntry> CppCurrentDocumentFilter::matchesFor(const QString & foreach (const ModelItemInfo & info, m_itemsOfCurrentDoc) { + if (future.isCanceled()) + break; + if ((hasWildcard && regexp.exactMatch(info.symbolName)) || (!hasWildcard && matcher.indexIn(info.symbolName) != -1)) { diff --git a/src/plugins/cpptools/cppcurrentdocumentfilter.h b/src/plugins/cpptools/cppcurrentdocumentfilter.h index 0231124eb3a12f19ec9a8216674067562069de61..6f4bbbc5cd4eb5539d7bc740146fa96e54596d70 100644 --- a/src/plugins/cpptools/cppcurrentdocumentfilter.h +++ b/src/plugins/cpptools/cppcurrentdocumentfilter.h @@ -53,7 +53,7 @@ public: QString displayName() const { return tr("Methods in current Document"); } QString id() const { return QLatin1String("Methods in current Document"); } Priority priority() const { return Medium; } - QList<Locator::FilterEntry> matchesFor(const QString &entry); + QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); void accept(Locator::FilterEntry selection) const; void refresh(QFutureInterface<void> &future); diff --git a/src/plugins/cpptools/cpplocatorfilter.cpp b/src/plugins/cpptools/cpplocatorfilter.cpp index 2b10afdce60f1518f0f4bab24cc39b95526f44b1..62162025d252d809396f682ed307ae82aa9027a4 100644 --- a/src/plugins/cpptools/cpplocatorfilter.cpp +++ b/src/plugins/cpptools/cpplocatorfilter.cpp @@ -76,7 +76,7 @@ static bool compareLexigraphically(const Locator::FilterEntry &a, return a.displayName < b.displayName; } -QList<Locator::FilterEntry> CppLocatorFilter::matchesFor(const QString &origEntry) +QList<Locator::FilterEntry> CppLocatorFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &origEntry) { QString entry = trimWildcards(origEntry); QList<Locator::FilterEntry> goodEntries; @@ -90,6 +90,9 @@ QList<Locator::FilterEntry> CppLocatorFilter::matchesFor(const QString &origEntr QHashIterator<QString, QList<ModelItemInfo> > it(m_searchList); while (it.hasNext()) { + if (future.isCanceled()) + break; + it.next(); const QList<ModelItemInfo> items = it.value(); diff --git a/src/plugins/cpptools/cpplocatorfilter.h b/src/plugins/cpptools/cpplocatorfilter.h index 7b13adc6c7fa83b66cf4cd47b4b63910be89678e..c58a9100c1b47d41cd29311bf231f19e34891639 100644 --- a/src/plugins/cpptools/cpplocatorfilter.h +++ b/src/plugins/cpptools/cpplocatorfilter.h @@ -48,7 +48,7 @@ public: QString displayName() const { return tr("Classes and Methods"); } QString id() const { return QLatin1String("Classes and Methods"); } Priority priority() const { return Medium; } - QList<Locator::FilterEntry> matchesFor(const QString &entry); + QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); void accept(Locator::FilterEntry selection) const; void refresh(QFutureInterface<void> &future); diff --git a/src/plugins/help/helpindexfilter.cpp b/src/plugins/help/helpindexfilter.cpp index 10c4fc06f59b1f855054bffba1cf9ba9b83e9f0b..5bb20698ed1eee62b61a480a22308f860bba6551 100644 --- a/src/plugins/help/helpindexfilter.cpp +++ b/src/plugins/help/helpindexfilter.cpp @@ -70,7 +70,7 @@ ILocatorFilter::Priority HelpIndexFilter::priority() const return Medium; } -QList<FilterEntry> HelpIndexFilter::matchesFor(const QString &entry) +QList<FilterEntry> HelpIndexFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry) { QStringList keywords; if (entry.length() < 2) @@ -79,8 +79,11 @@ QList<FilterEntry> HelpIndexFilter::matchesFor(const QString &entry) keywords = Core::HelpManager::instance()->findKeywords(entry); QList<FilterEntry> entries; - foreach (const QString &keyword, keywords) + foreach (const QString &keyword, keywords) { + if (future.isCanceled()) + break; entries.append(FilterEntry(this, keyword, QVariant(), m_icon)); + } return entries; } diff --git a/src/plugins/help/helpindexfilter.h b/src/plugins/help/helpindexfilter.h index dde609b3f549e772a1c339280d37a7b365671b4a..0203890b90ba3e98d4d4e68dd79cf6f21d983379 100644 --- a/src/plugins/help/helpindexfilter.h +++ b/src/plugins/help/helpindexfilter.h @@ -49,7 +49,7 @@ public: QString displayName() const; QString id() const; Priority priority() const; - QList<Locator::FilterEntry> matchesFor(const QString &entry); + QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); void accept(Locator::FilterEntry selection) const; void refresh(QFutureInterface<void> &future); diff --git a/src/plugins/help/remotehelpfilter.cpp b/src/plugins/help/remotehelpfilter.cpp index 8fcbeae3eda29313be429c888274306892a9b307..05a7f462186b9d3554a1f6721c39efe513f22ef6 100644 --- a/src/plugins/help/remotehelpfilter.cpp +++ b/src/plugins/help/remotehelpfilter.cpp @@ -100,10 +100,13 @@ Locator::ILocatorFilter::Priority RemoteHelpFilter::priority() const return Medium; } -QList<Locator::FilterEntry> RemoteHelpFilter::matchesFor(const QString &pattern) +QList<Locator::FilterEntry> RemoteHelpFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &pattern) { QList<Locator::FilterEntry> entries; foreach (const QString &url, m_remoteUrls) { + if (future.isCanceled()) + break; + entries.append(Locator::FilterEntry(this, url.arg(pattern), QVariant(), m_icon)); } diff --git a/src/plugins/help/remotehelpfilter.h b/src/plugins/help/remotehelpfilter.h index e2d32fbb329fb2c2d34539c52a2d6d8791a73bdf..5c858de33cfc9af033f9296d35d64a3f48986fbf 100644 --- a/src/plugins/help/remotehelpfilter.h +++ b/src/plugins/help/remotehelpfilter.h @@ -50,7 +50,7 @@ public: QString displayName() const; QString id() const; Priority priority() const; - QList<Locator::FilterEntry> matchesFor(const QString &entry); + QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); void accept(Locator::FilterEntry selection) const; void refresh(QFutureInterface<void> &future); QByteArray saveState() const; diff --git a/src/plugins/locator/basefilefilter.cpp b/src/plugins/locator/basefilefilter.cpp index 4f35ec7d827ec93f26caecc12845e990170513e1..5ba5437cbc5007c20741de93fdf18901a5b3eb34 100644 --- a/src/plugins/locator/basefilefilter.cpp +++ b/src/plugins/locator/basefilefilter.cpp @@ -42,7 +42,7 @@ BaseFileFilter::BaseFileFilter() { } -QList<FilterEntry> BaseFileFilter::matchesFor(const QString &origEntry) +QList<FilterEntry> BaseFileFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &origEntry) { updateFiles(); QList<FilterEntry> matches; @@ -70,6 +70,9 @@ QList<FilterEntry> BaseFileFilter::matchesFor(const QString &origEntry) QStringListIterator paths(searchListPaths); QStringListIterator names(searchListNames); while (paths.hasNext() && names.hasNext()) { + if (future.isCanceled()) + break; + QString path = paths.next(); QString name = names.next(); if ((hasWildcard && regexp.exactMatch(name)) diff --git a/src/plugins/locator/basefilefilter.h b/src/plugins/locator/basefilefilter.h index ee942694463721230a2c56952e5abd29d0759ddc..707a61dc2617d997e0a029c27b0af959c6efa019 100644 --- a/src/plugins/locator/basefilefilter.h +++ b/src/plugins/locator/basefilefilter.h @@ -43,7 +43,7 @@ class LOCATOR_EXPORT BaseFileFilter : public Locator::ILocatorFilter public: BaseFileFilter(); - QList<Locator::FilterEntry> matchesFor(const QString &entry); + QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); void accept(Locator::FilterEntry selection) const; protected: diff --git a/src/plugins/locator/commandlocator.cpp b/src/plugins/locator/commandlocator.cpp index fa3684f60d6f83798d0621155dcdf08073ffd274..cb1aa287c3bf2a6a491d1d8508c1a1a766b10945 100644 --- a/src/plugins/locator/commandlocator.cpp +++ b/src/plugins/locator/commandlocator.cpp @@ -84,7 +84,7 @@ ILocatorFilter::Priority CommandLocator::priority() const return Medium; } -QList<Locator::FilterEntry> CommandLocator::matchesFor(const QString &entry) +QList<Locator::FilterEntry> CommandLocator::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry) { QList<FilterEntry> filters; // Get active, enabled actions matching text, store in list. @@ -92,6 +92,8 @@ QList<Locator::FilterEntry> CommandLocator::matchesFor(const QString &entry) const QChar ampersand = QLatin1Char('&'); const int count = d->commands.size(); for (int i = 0; i < count; i++) { + if (future.isCanceled()) + break; if (d->commands.at(i)->isActive()) { if (QAction *action = d->commands.at(i)->action()) if (action->isEnabled()) { diff --git a/src/plugins/locator/commandlocator.h b/src/plugins/locator/commandlocator.h index bc18667191ed63577d78f50b00eff92529c5de49..186bf9e916deb93561ce5e21887a60281f064c7c 100644 --- a/src/plugins/locator/commandlocator.h +++ b/src/plugins/locator/commandlocator.h @@ -64,7 +64,7 @@ public: virtual QString displayName() const; virtual QString id() const; virtual Priority priority() const; - virtual QList<FilterEntry> matchesFor(const QString &entry); + virtual QList<FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); virtual void accept(FilterEntry selection) const; virtual void refresh(QFutureInterface<void> &future); diff --git a/src/plugins/locator/filesystemfilter.cpp b/src/plugins/locator/filesystemfilter.cpp index 6ef07bdbaec0cbc784b6fe685dd74ea340dc0425..fe24241dbe34ac489c9406b6c8a6010881b577d8 100644 --- a/src/plugins/locator/filesystemfilter.cpp +++ b/src/plugins/locator/filesystemfilter.cpp @@ -45,7 +45,7 @@ FileSystemFilter::FileSystemFilter(EditorManager *editorManager, LocatorWidget * setIncludedByDefault(false); } -QList<FilterEntry> FileSystemFilter::matchesFor(const QString &entry) +QList<FilterEntry> FileSystemFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry) { QList<FilterEntry> value; QFileInfo entryInfo(entry); @@ -75,6 +75,8 @@ QList<FilterEntry> FileSystemFilter::matchesFor(const QString &entry) QStringList files = dirInfo.entryList(fileFilter, QDir::Name|QDir::IgnoreCase|QDir::LocaleAware); foreach (const QString &dir, dirs) { + if (future.isCanceled()) + break; if (dir != QLatin1String(".") && (name.isEmpty() || dir.startsWith(name, Qt::CaseInsensitive))) { FilterEntry filterEntry(this, dir, dirInfo.filePath(dir)); filterEntry.resolveFileIcon = true; @@ -82,6 +84,8 @@ QList<FilterEntry> FileSystemFilter::matchesFor(const QString &entry) } } foreach (const QString &file, files) { + if (future.isCanceled()) + break; if (name.isEmpty() || file.startsWith(name, Qt::CaseInsensitive)) { const QString fullPath = dirInfo.filePath(file); FilterEntry filterEntry(this, file, fullPath); diff --git a/src/plugins/locator/filesystemfilter.h b/src/plugins/locator/filesystemfilter.h index 07ab3414a520c75e1d51bcbcc259acf58c93c2ce..21b740c6d691619702755a5cfeff0b5b311e6ba4 100644 --- a/src/plugins/locator/filesystemfilter.h +++ b/src/plugins/locator/filesystemfilter.h @@ -56,7 +56,7 @@ public: QString displayName() const { return tr("Files in file system"); } QString id() const { return "Files in file system"; } Locator::ILocatorFilter::Priority priority() const { return Locator::ILocatorFilter::Medium; } - QList<Locator::FilterEntry> matchesFor(const QString &entry); + QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); void accept(Locator::FilterEntry selection) const; QByteArray saveState() const; bool restoreState(const QByteArray &state); diff --git a/src/plugins/locator/ilocatorfilter.h b/src/plugins/locator/ilocatorfilter.h index f3207c208734ce6d347f98513a6e56f2452934ac..7f519d7fe1c14d8c3402034f93fd5d7ba884d733 100644 --- a/src/plugins/locator/ilocatorfilter.h +++ b/src/plugins/locator/ilocatorfilter.h @@ -100,7 +100,7 @@ public: QString shortcutString() const; /* List of matches for the given user entry. */ - virtual QList<FilterEntry> matchesFor(const QString &entry) = 0; + virtual QList<FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry) = 0; /* User has selected the given entry that belongs to this filter. */ virtual void accept(FilterEntry selection) const = 0; diff --git a/src/plugins/locator/locatorfiltersfilter.cpp b/src/plugins/locator/locatorfiltersfilter.cpp index f02e63d4f3741316b566e282860b2c273a3b2c39..a0fe20c46432bc5c5ee6d69cde90b7e6cd9acd52 100644 --- a/src/plugins/locator/locatorfiltersfilter.cpp +++ b/src/plugins/locator/locatorfiltersfilter.cpp @@ -63,11 +63,13 @@ ILocatorFilter::Priority LocatorFiltersFilter::priority() const return High; } -QList<FilterEntry> LocatorFiltersFilter::matchesFor(const QString &entry) +QList<FilterEntry> LocatorFiltersFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry) { QList<FilterEntry> entries; if (entry.isEmpty()) { foreach (ILocatorFilter *filter, m_plugin->filters()) { + if (future.isCanceled()) + break; if (!filter->shortcutString().isEmpty() && !filter->isHidden()) { FilterEntry filterEntry(this, filter->shortcutString(), diff --git a/src/plugins/locator/locatorfiltersfilter.h b/src/plugins/locator/locatorfiltersfilter.h index ea7d5d75aa1bcd6928aec3953a6710be9e855819..2b7d22e12b2956efb1cd63eb589efbdc526ac327 100644 --- a/src/plugins/locator/locatorfiltersfilter.h +++ b/src/plugins/locator/locatorfiltersfilter.h @@ -56,7 +56,7 @@ public: QString displayName() const; QString id() const; Priority priority() const; - QList<FilterEntry> matchesFor(const QString &entry); + QList<FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); void accept(FilterEntry selection) const; void refresh(QFutureInterface<void> &future); bool isConfigurable() const; diff --git a/src/plugins/locator/locatorwidget.cpp b/src/plugins/locator/locatorwidget.cpp index 0ee99048ea07d7ef59c0aba86b14fda438a6fa22..4ea486caddc8460eb610d07ed364815b3156ae11 100644 --- a/src/plugins/locator/locatorwidget.cpp +++ b/src/plugins/locator/locatorwidget.cpp @@ -428,7 +428,7 @@ QList<ILocatorFilter*> LocatorWidget::filtersFor(const QString &text, QString &s return activeFilters; } -static void filter_helper(QFutureInterface<FilterEntry> &entries, QList<ILocatorFilter *> filters, QString searchText) +static void filter_helper(QFutureInterface<Locator::FilterEntry> &entries, QList<ILocatorFilter *> filters, QString searchText) { QSet<FilterEntry> alreadyAdded; const bool checkDuplicates = (filters.size() > 1); @@ -436,7 +436,7 @@ static void filter_helper(QFutureInterface<FilterEntry> &entries, QList<ILocator if (entries.isCanceled()) break; - foreach (const FilterEntry &entry, filter->matchesFor(searchText)) { + foreach (const FilterEntry &entry, filter->matchesFor(entries, searchText)) { if (checkDuplicates && alreadyAdded.contains(entry)) continue; entries.reportResult(entry); @@ -453,6 +453,7 @@ void LocatorWidget::updateCompletionList(const QString &text) // cancel the old future m_entriesWatcher->future().cancel(); + m_entriesWatcher->future().waitForFinished(); QFuture<FilterEntry> future = QtConcurrent::run(filter_helper, filters, searchText); m_entriesWatcher->setFuture(future); diff --git a/src/plugins/locator/opendocumentsfilter.cpp b/src/plugins/locator/opendocumentsfilter.cpp index 535d670e4703a053011e189d255aa7b725c9e098..0c06aff5a13fdd1e2b83baae0c6cca291f013c64 100644 --- a/src/plugins/locator/opendocumentsfilter.cpp +++ b/src/plugins/locator/opendocumentsfilter.cpp @@ -49,7 +49,7 @@ OpenDocumentsFilter::OpenDocumentsFilter(EditorManager *editorManager) : setIncludedByDefault(true); } -QList<FilterEntry> OpenDocumentsFilter::matchesFor(const QString &entry) +QList<FilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry) { QList<FilterEntry> value; const QChar asterisk = QLatin1Char('*'); @@ -60,6 +60,8 @@ QList<FilterEntry> OpenDocumentsFilter::matchesFor(const QString &entry) if (!regexp.isValid()) return value; foreach (const OpenEditorsModel::Entry &editorEntry, m_editors) { + if (future.isCanceled()) + break; QString fileName = editorEntry.fileName(); QString displayName = editorEntry.displayName(); if (regexp.exactMatch(displayName)) { diff --git a/src/plugins/locator/opendocumentsfilter.h b/src/plugins/locator/opendocumentsfilter.h index 3b419b980be3ce3e206b75b769d41bdafdbe4a25..33fe15a0621accae5e1e2979d8e635810eb96a60 100644 --- a/src/plugins/locator/opendocumentsfilter.h +++ b/src/plugins/locator/opendocumentsfilter.h @@ -55,7 +55,7 @@ public: QString displayName() const { return tr("Open documents"); } QString id() const { return "Open documents"; } Locator::ILocatorFilter::Priority priority() const { return Locator::ILocatorFilter::Medium; } - QList<Locator::FilterEntry> matchesFor(const QString &entry); + QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); void accept(Locator::FilterEntry selection) const; void refresh(QFutureInterface<void> &future); diff --git a/src/plugins/projectexplorer/customwizard/customwizard.cpp b/src/plugins/projectexplorer/customwizard/customwizard.cpp index 7f4c5107b6169044a4e6b7d573f83837eba988a4..2943e55dfd3f7327b0677be4a31f20c0c0c40fab 100644 --- a/src/plugins/projectexplorer/customwizard/customwizard.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizard.cpp @@ -182,6 +182,18 @@ template <class WizardPage> return 0; } +// Determine where to run the generator script. The user may specify +// an expression subject to field replacement, default is the target path. +static inline QString scriptWorkingDirectory(const QSharedPointer<Internal::CustomWizardContext> &ctx, + const QSharedPointer<Internal::CustomWizardParameters> &p) +{ + if (p->filesGeneratorScriptWorkingDirectory.isEmpty()) + return ctx->targetPath; + QString path = p->filesGeneratorScriptWorkingDirectory; + Internal::CustomWizardContext::replaceFields(ctx->replacements, &path); + return path; +} + Core::GeneratedFiles CustomWizard::generateFiles(const QWizard *dialog, QString *errorMessage) const { // Look for the Custom field page to find the path @@ -215,17 +227,18 @@ bool CustomWizard::writeFiles(const Core::GeneratedFiles &files, QString *errorM // project wizard that is entirely created by a script, // the target project directory might not exist. const CustomWizardContextPtr ctx = context(); - QDir targetPathDir(ctx->targetPath); - if (!targetPathDir.exists()) { + const QString scriptWorkingDir = scriptWorkingDirectory(ctx, d->m_parameters); + const QDir scriptWorkingDirDir(scriptWorkingDir); + if (!scriptWorkingDirDir.exists()) { if (CustomWizardPrivate::verbose) - qDebug("Creating directory %s", qPrintable(ctx->targetPath)); - if (!targetPathDir.mkpath(ctx->targetPath)) { - *errorMessage = QString::fromLatin1("Unable to create the target directory '%1'").arg(ctx->targetPath); + qDebug("Creating directory %s", qPrintable(scriptWorkingDir)); + if (!scriptWorkingDirDir.mkpath(scriptWorkingDir)) { + *errorMessage = QString::fromLatin1("Unable to create the target directory '%1'").arg(scriptWorkingDir); return false; } } // Run the custom script to actually generate the files. - if (!Internal::runCustomWizardGeneratorScript(ctx->targetPath, + if (!Internal::runCustomWizardGeneratorScript(scriptWorkingDir, d->m_parameters->filesGeneratorScript, d->m_parameters->filesGeneratorScriptArguments, ctx->replacements, errorMessage)) @@ -254,10 +267,11 @@ Core::GeneratedFiles CustomWizard::generateWizardFiles(QString *errorMessage) co // If generator script is non-empty, do a dry run to get it's files. if (!d->m_parameters->filesGeneratorScript.isEmpty()) { - rc += Internal::dryRunCustomWizardGeneratorScript(ctx->targetPath, + rc += Internal::dryRunCustomWizardGeneratorScript(scriptWorkingDirectory(ctx, d->m_parameters), d->m_parameters->filesGeneratorScript, d->m_parameters->filesGeneratorScriptArguments, - ctx->replacements, errorMessage); + ctx->replacements, + errorMessage); if (rc.isEmpty()) return rc; } @@ -276,6 +290,9 @@ CustomWizard::FieldReplacementMap CustomWizard::replacementMap(const QWizard *w) const QString value = w->field(field.name).toString(); fieldReplacementMap.insert(field.name, value); } + // Insert paths for generator scripts. + fieldReplacementMap.insert(QLatin1String("Path"), QDir::toNativeSeparators(context()->path)); + fieldReplacementMap.insert(QLatin1String("TargetPath"), QDir::toNativeSeparators(context()->targetPath)); return fieldReplacementMap; } diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp index 6efcd8d6ec2f21780d9c788727f646054e692bbb..6ccca0449895df5bcf8b07571c94b95abf2cafa4 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp @@ -72,6 +72,7 @@ static const char comboEntryTextElementC[] = "comboentrytext"; static const char generatorScriptElementC[] = "generatorscript"; static const char generatorScriptBinaryAttributeC[] = "binary"; +static const char generatorScriptWorkingDirectoryAttributeC[] = "workingdirectory"; static const char generatorScriptArgumentElementC[] = "argument"; static const char generatorScriptArgumentValueAttributeC[] = "value"; static const char generatorScriptArgumentOmitEmptyAttributeC[] = "omit-empty"; @@ -557,6 +558,7 @@ CustomWizardParameters::ParseResult *errorMessage = QString::fromLatin1("No binary specified for generator script."); return ParseFailed; } + filesGeneratorScriptWorkingDirectory = attributeValue(reader, generatorScriptWorkingDirectoryAttributeC); break; case ParseWithinScriptArguments: { GeneratorScriptArgument argument(attributeValue(reader, generatorScriptArgumentValueAttributeC)); @@ -623,6 +625,8 @@ QString CustomWizardParameters::toString() const str << "Script:"; foreach(const QString &a, filesGeneratorScript) str << " '" << a << '\''; + if (!filesGeneratorScriptWorkingDirectory.isEmpty()) + str << "\nrun in '" << filesGeneratorScriptWorkingDirectory << '\''; str << "\nArguments: "; foreach(const GeneratorScriptArgument &a, filesGeneratorScriptArguments) { str << " '" << a.value << '\''; diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.h b/src/plugins/projectexplorer/customwizard/customwizardparameters.h index 59ee8599cccd0d5bb762cca94ea2b76885978e3b..732098ff35ec3421291f2262d7d7c5d24ba4298c 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardparameters.h +++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.h @@ -104,6 +104,7 @@ public: QString klass; QList<CustomWizardFile> files; QStringList filesGeneratorScript; // Complete binary, such as 'cmd /c myscript.pl'. + QString filesGeneratorScriptWorkingDirectory; QList<GeneratorScriptArgument> filesGeneratorScriptArguments; QString fieldPageTitle; diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp index 5b6c2bef19a92740b90408a3c97abf47d8ae50f4..72f91696429b32ef2fbf0f09ee06e0ca2c3811e5 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp @@ -178,7 +178,12 @@ Core::GeneratedFiles attributes |= Core::GeneratedFile::OpenProjectAttribute; } else { // Token 0 is file name. Wizard wants native names. - const QString fullPath = targetPath + QLatin1Char('/') + token; + // Expand to full path if relative + const QFileInfo fileInfo(token); + const QString fullPath = + fileInfo.isAbsolute() ? + token : + (targetPath + QLatin1Char('/') + token); file.setPath(QDir::toNativeSeparators(fullPath)); } } @@ -186,9 +191,12 @@ Core::GeneratedFiles files.push_back(file); } } - if (CustomWizard::verbose()) + if (CustomWizard::verbose()) { + QDebug nospace = qDebug().nospace(); + nospace << script << " generated:\n"; foreach(const Core::GeneratedFile &f, files) - qDebug() << script << " generated: " << f.path() << f.attributes(); + nospace << ' ' << f.path() << f.attributes() << '\n'; + } return files; } diff --git a/src/plugins/projectexplorer/userfileaccessor.cpp b/src/plugins/projectexplorer/userfileaccessor.cpp index e9feb7e784d42277f8aba5e2ae20a197ed242536..948780e82b63b45c79d125565f7b90bce3e786aa 100644 --- a/src/plugins/projectexplorer/userfileaccessor.cpp +++ b/src/plugins/projectexplorer/userfileaccessor.cpp @@ -1034,7 +1034,7 @@ QVariantMap Version3Handler::update(Project *, const QVariantMap &map) // first iteration: search run configurations, get signing info, remove old signing keys QString customKeyPath; QString customSignaturePath; - int signingMode; + int signingMode = 0; // SelfSign QMapIterator<QString, QVariant> targetIt(originalTarget); while (targetIt.hasNext()) { targetIt.next(); diff --git a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp index 2921ee23e88e1582729124df2c6abd9ecccb1034..a5d7c9ec95df26dcf2ce3917dd35e4edb8fadf2a 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp @@ -140,7 +140,7 @@ QVariantMap S60CreatePackageStep::toMap() const bool S60CreatePackageStep::fromMap(const QVariantMap &map) { - m_signingMode = (SigningMode)map.value(QLatin1String(SIGNMODE_KEY)).toInt(); + m_signingMode = static_cast<SigningMode>(map.value(QLatin1String(SIGNMODE_KEY), static_cast<int>(SignSelf)).toInt()); m_customSignaturePath = map.value(QLatin1String(CERTIFICATE_KEY)).toString(); setCustomKeyPath(map.value(QLatin1String(KEYFILE_KEY)).toString()); m_createSmartInstaller = map.value(QLatin1String(SMART_INSTALLER_KEY), false).toBool(); diff --git a/src/plugins/texteditor/linenumberfilter.cpp b/src/plugins/texteditor/linenumberfilter.cpp index 961c03c9e44793d64fe2b1db497fcf4c6678decd..6cbd99713a088a60bf7faf34a7c4bad2eaca34e5 100644 --- a/src/plugins/texteditor/linenumberfilter.cpp +++ b/src/plugins/texteditor/linenumberfilter.cpp @@ -48,7 +48,7 @@ LineNumberFilter::LineNumberFilter(QObject *parent) setIncludedByDefault(true); } -QList<FilterEntry> LineNumberFilter::matchesFor(const QString &entry) +QList<FilterEntry> LineNumberFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry) { bool ok; QList<FilterEntry> value; diff --git a/src/plugins/texteditor/linenumberfilter.h b/src/plugins/texteditor/linenumberfilter.h index 8a21a220a17ce96ba8e6806dd2301e94e5e4897b..f4d61a66d5ab418ab861c6890ec8217fcac38844 100644 --- a/src/plugins/texteditor/linenumberfilter.h +++ b/src/plugins/texteditor/linenumberfilter.h @@ -52,7 +52,7 @@ public: QString displayName() const { return tr("Line in current document"); } QString id() const { return "Line in current document"; } Locator::ILocatorFilter::Priority priority() const { return Locator::ILocatorFilter::High; } - QList<Locator::FilterEntry> matchesFor(const QString &entry); + QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); void accept(Locator::FilterEntry selection) const; void refresh(QFutureInterface<void> &) {}