From 15d8b6ba811d3dc5b483baa8bf763b29c3750b34 Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Thu, 9 Apr 2015 14:10:35 +0200 Subject: [PATCH] EditorManager: If opening a editor fails, offer other editors factories Change-Id: Ia8cf298c1a62e01d6df6f9f871a8d3eafde5821d Task-number: QTCREATORBUG-14064 Reviewed-by: Eike Ziller --- src/libs/utils/overridecursor.cpp | 64 +++++++++++++ src/libs/utils/overridecursor.h | 54 +++++++++++ src/libs/utils/utils-lib.pri | 6 +- src/libs/utils/utils.qbs | 2 + .../editormanager/editormanager.cpp | 94 +++++++++++++++---- .../editormanager/editormanager_p.h | 3 +- 6 files changed, 200 insertions(+), 23 deletions(-) create mode 100644 src/libs/utils/overridecursor.cpp create mode 100644 src/libs/utils/overridecursor.h diff --git a/src/libs/utils/overridecursor.cpp b/src/libs/utils/overridecursor.cpp new file mode 100644 index 00000000000..cf510080e50 --- /dev/null +++ b/src/libs/utils/overridecursor.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "overridecursor.h" + +#include + +using namespace Utils; + +OverrideCursor::OverrideCursor(const QCursor &cursor) + : m_set(true), m_cursor(cursor) +{ + QApplication::setOverrideCursor(cursor); +} + +OverrideCursor::~OverrideCursor() +{ + if (m_set) + QApplication::restoreOverrideCursor(); +} + +void OverrideCursor::set() +{ + if (!m_set) { + QApplication::setOverrideCursor(m_cursor); + m_set = true; + } +} + +void OverrideCursor::reset() +{ + if (m_set) { + QApplication::restoreOverrideCursor(); + m_set = false; + } +} + diff --git a/src/libs/utils/overridecursor.h b/src/libs/utils/overridecursor.h new file mode 100644 index 00000000000..1cf6efba32a --- /dev/null +++ b/src/libs/utils/overridecursor.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef OVERRIDECURSOR_H +#define OVERRIDECURSOR_H + +#include "utils_global.h" + +#include + +namespace Utils { + +class QTCREATOR_UTILS_EXPORT OverrideCursor +{ +public: + OverrideCursor(const QCursor &cursor); + ~OverrideCursor(); + void set(); + void reset(); +private: + bool m_set; + QCursor m_cursor; +}; + +} + +#endif // OVERRIDECURSOR_H diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index 800920a46dd..4016eca551d 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -89,7 +89,8 @@ SOURCES += $$PWD/environment.cpp \ $$PWD/macroexpander.cpp \ $$PWD/theme/theme.cpp \ $$PWD/progressindicator.cpp \ - $$PWD/fadingindicator.cpp + $$PWD/fadingindicator.cpp \ + $$PWD/overridecursor.cpp win32:SOURCES += $$PWD/consoleprocess_win.cpp else:SOURCES += $$PWD/consoleprocess_unix.cpp @@ -190,7 +191,8 @@ HEADERS += \ $$PWD/theme/theme_p.h \ $$PWD/progressindicator.h \ $$PWD/fadingindicator.h \ - $$PWD/executeondestruction.h + $$PWD/executeondestruction.h \ + $$PWD/overridecursor.h FORMS += $$PWD/filewizardpage.ui \ $$PWD/projectintropage.ui \ diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index a3855fff540..d4de660ae31 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -123,6 +123,8 @@ QtcLibrary { "outputformat.h", "outputformatter.cpp", "outputformatter.h", + "overridecursor.cpp", + "overridecursor.h", "parameteraction.cpp", "parameteraction.h", "pathchooser.cpp", diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index eac873ea348..e4bbb6bd1e7 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include #include @@ -91,6 +92,8 @@ #include #include +#include + using namespace Utils; enum { debugEditorManager=0 }; @@ -579,22 +582,64 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const QString &fileN realFn = fn; } - IEditor *editor = createEditor(editorId, fn); - // If we could not open the file in the requested editor, fall - // back to the default editor: - if (!editor) - editor = createEditor(Id(), fn); - QTC_ASSERT(editor, return 0); - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - QString errorString; - if (!editor->open(&errorString, fn, realFn)) { - QApplication::restoreOverrideCursor(); + EditorManager::EditorFactoryList factories = EditorManagerPrivate::findFactories(Id(), fn); + if (editorId.isValid()) + std::stable_partition(factories.begin(), factories.end(), Utils::equal(&IEditorFactory::id, editorId)); + + IEditor *editor = 0; + auto overrideCursor = Utils::OverrideCursor(QCursor(Qt::WaitCursor)); + + IEditorFactory *factory = factories.takeFirst(); + while (factory) { + editor = createEditor(factory, fn); + if (!editor) { + factory = factories.takeFirst(); + continue; + } + + QString errorString; + if (editor->open(&errorString, fn, realFn)) + break; + + overrideCursor.reset(); + delete editor; + if (errorString.isEmpty()) errorString = tr("Could not open \"%1\": Unknown error.").arg(realFn); - QMessageBox::critical(ICore::mainWindow(), EditorManager::tr("File Error"), errorString); - delete editor; - return 0; + + QMessageBox msgbox(QMessageBox::Critical, EditorManager::tr("File Error"), errorString, QMessageBox::Open | QMessageBox::Cancel, ICore::mainWindow()); + + IEditorFactory *selectedFactory = 0; + if (!factories.isEmpty()) { + QPushButton *button = qobject_cast(msgbox.button(QMessageBox::Open)); + QTC_ASSERT(button, return 0); + QMenu *menu = new QMenu(button); + foreach (IEditorFactory *factory, factories) { + QAction *action = menu->addAction(factory->displayName()); + connect(action, &QAction::triggered, [&selectedFactory, factory, &msgbox]() { + selectedFactory = factory; + msgbox.done(QMessageBox::Open); + }); + } + + button->setMenu(menu); + } else { + msgbox.setStandardButtons(QMessageBox::Ok); + } + + int ret = msgbox.exec(); + if (ret == QMessageBox::Cancel || ret == QMessageBox::Ok) + return 0; + + overrideCursor.set(); + + factories.removeOne(selectedFactory); + factory = selectedFactory; } + + if (!editor) + return 0; + if (realFn != fn) editor->document()->setRestoredFrom(realFn); addEditor(editor); @@ -609,7 +654,6 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const QString &fileN if (flags & EditorManager::CanContainLineAndColumnNumber) editor->gotoLine(lineNumber, columnNumber); - QApplication::restoreOverrideCursor(); return result; } @@ -905,7 +949,7 @@ int EditorManagerPrivate::autoSaveInterval() return d->m_autoSaveInterval; } -IEditor *EditorManagerPrivate::createEditor(Id editorId, const QString &fileName) +EditorManager::EditorFactoryList EditorManagerPrivate::findFactories(Id editorId, const QString &fileName) { if (debugEditorManager) qDebug() << Q_FUNC_INFO << editorId.name() << fileName; @@ -926,7 +970,7 @@ IEditor *EditorManagerPrivate::createEditor(Id editorId, const QString &fileName && mimeType.name().startsWith(QLatin1String("text"))) { mimeType = mdb.mimeTypeForName(QLatin1String("application/octet-stream")); } - factories = EditorManager::editorFactories(mimeType, true); + factories = EditorManager::editorFactories(mimeType, false); } else { // Find by editor id if (IEditorFactory *factory = findById(editorId)) @@ -935,10 +979,17 @@ IEditor *EditorManagerPrivate::createEditor(Id editorId, const QString &fileName if (factories.empty()) { qWarning("%s: unable to find an editor factory for the file '%s', editor Id '%s'.", Q_FUNC_INFO, fileName.toUtf8().constData(), editorId.name().constData()); - return 0; } - IEditor *editor = factories.front()->createEditor(); + return factories; +} + +IEditor *EditorManagerPrivate::createEditor(IEditorFactory *factory, const QString &fileName) +{ + if (!factory) + return 0; + + IEditor *editor = factory->createEditor(); if (editor) { QTC_CHECK(editor->document()->id().isValid()); // sanity check that the editor has an id set connect(editor->document(), SIGNAL(changed()), d, SLOT(handleDocumentStateChange())); @@ -2420,10 +2471,13 @@ IEditor *EditorManager::openEditorWithContents(Id editorId, } } - edt = EditorManagerPrivate::createEditor(editorId, title); - if (!edt) + EditorFactoryList factories = EditorManagerPrivate::findFactories(editorId, title); + if (factories.isEmpty()) return 0; + edt = EditorManagerPrivate::createEditor(factories.first(), title); + if (!edt) + return 0; if (!edt->document()->setContents(contents)) { delete edt; edt = 0; diff --git a/src/plugins/coreplugin/editormanager/editormanager_p.h b/src/plugins/coreplugin/editormanager/editormanager_p.h index a6411645320..28872f3a022 100644 --- a/src/plugins/coreplugin/editormanager/editormanager_p.h +++ b/src/plugins/coreplugin/editormanager/editormanager_p.h @@ -174,7 +174,8 @@ private: static OpenEditorsWindow *windowPopup(); static void showPopupOrSelectDocument(); - static IEditor *createEditor(Id editorId = Id(), const QString &fileName = QString()); + static EditorManager::EditorFactoryList findFactories(Id editorId, const QString &fileName); + static IEditor *createEditor(IEditorFactory *factory, const QString &fileName); static void addEditor(IEditor *editor); static void removeEditor(IEditor *editor); static IEditor *placeEditor(EditorView *view, IEditor *editor);