diff --git a/framework/extensions/internal/legacy/extpluginrunner.cpp b/framework/extensions/internal/legacy/extpluginrunner.cpp index 4a67b7b374..e18b02cf5f 100644 --- a/framework/extensions/internal/legacy/extpluginrunner.cpp +++ b/framework/extensions/internal/legacy/extpluginrunner.cpp @@ -26,6 +26,8 @@ #include "../../api/v1/ipluginapiv1.h" #include "../../extensionserrors.h" +#include "translation.h" + #include "log.h" using namespace muse; @@ -33,6 +35,7 @@ using namespace muse::extensions; using namespace muse::extensions::legacy; using namespace muse::extensions::apiv1; +//! Loads and runs the legacy plug-in described by `action`. Ret ExtPluginRunner::run(const Action& action) { io::path_t qmlPath = action.path; @@ -41,20 +44,26 @@ Ret ExtPluginRunner::run(const Action& action) //! making it easier to maintain backward compatibility and stability. QQmlComponent component = QQmlComponent(engine()->qmlEngineApiV1(), qmlPath.toQString()); if (!component.isReady()) { + const QString errorMessage = component.errorString().trimmed(); LOGE() << "Failed to load QML file: " << qmlPath; - LOGE() << component.errorString(); + LOGE() << errorMessage; + showError(errorMessage); return make_ret(Err::ExtLoadError); } QObject* obj = component.create(); if (!obj) { - LOGE() << "Failed to create QML Object: " << qmlPath; + const QString errorMessage = component.errorString().trimmed(); + LOGE() << "Failed to create QML Object: " << qmlPath << ", error: " << errorMessage; + showError(errorMessage); return make_ret(Err::ExtLoadError); } IPluginApiV1* plugin = dynamic_cast(obj); if (!plugin) { - LOGE() << "Qml Object not MuseScore plugin: " << qmlPath; + const QString errorMessage = muse::qtrc("extensions", "QML object is not a MuseScore plug-in: %1").arg(qmlPath.toQString()); + LOGE() << errorMessage; + showError(errorMessage); return make_ret(Err::ExtBadFormat); } @@ -62,3 +71,13 @@ Ret ExtPluginRunner::run(const Action& action) return muse::make_ok(); } + +//! Displays `errorMessage` in a copyable error dialog. +void ExtPluginRunner::showError(const QString& errorMessage) +{ + IInteractive::Text text( + muse::qtrc("extensions", "An error occurred in the plug-in: %1. Please contact the developer.").arg(errorMessage).toStdString(), + IInteractive::TextFormat::PlainText); + text.detailedText = errorMessage.toStdString(); + interactive()->error(muse::trc("extensions", "Plug-in error"), text); +} diff --git a/framework/extensions/internal/legacy/extpluginrunner.h b/framework/extensions/internal/legacy/extpluginrunner.h index 73bf6a3a1e..afa3269d61 100644 --- a/framework/extensions/internal/legacy/extpluginrunner.h +++ b/framework/extensions/internal/legacy/extpluginrunner.h @@ -23,6 +23,7 @@ #define MUSE_EXTENSIONS_EXTPLUGINRUNNER_H #include "global/types/ret.h" +#include "interactive/iinteractive.h" #include "../../extensionstypes.h" @@ -35,12 +36,19 @@ namespace muse::extensions::legacy { class ExtPluginRunner : public Contextable { ContextInject engine = { this }; + ContextInject interactive = { this }; public: + //! Creates a runner in the given dependency-injection context. ExtPluginRunner(const modularity::ContextPtr& iocCtx) : Contextable(iocCtx) {} + //! Loads and runs the legacy plug-in described by `action`. Ret run(const Action& action); + +private: + //! Displays `errorMessage` in a copyable error dialog. + void showError(const QString& errorMessage); }; } diff --git a/framework/interactive/qml/Muse/Interactive/ErrorDetailsView.qml b/framework/interactive/qml/Muse/Interactive/ErrorDetailsView.qml index 6cbeffcbe4..a2cf185d3d 100644 --- a/framework/interactive/qml/Muse/Interactive/ErrorDetailsView.qml +++ b/framework/interactive/qml/Muse/Interactive/ErrorDetailsView.qml @@ -60,8 +60,8 @@ Column { anchors.fill: parent anchors.margins: 1 - contentWidth: contentItem.childrenRect.width - flickableDirection: Flickable.AutoFlickDirection + contentWidth: width + flickableDirection: Flickable.VerticalFlick spacing: 0 @@ -91,8 +91,8 @@ Column { background.color: model.index % 2 === 0 ? ui.theme.backgroundSecondaryColor : "transparent" mouseArea.enabled: false - implicitWidth: label.implicitWidth + 2 * 30 - width: Math.max(ListView.view.width, implicitWidth) + implicitHeight: Math.max(30, label.implicitHeight + 12) + width: ListView.view.width StyledTextLabel { id: label @@ -104,6 +104,7 @@ Column { horizontalAlignment: Text.AlignLeft width: parent.width + wrapMode: Text.WrapAnywhere textFormat: Qt.RichText text: model.errorText