From 00d2d3c149a5d6359e12bbe6edccf85a2f7ccc33 Mon Sep 17 00:00:00 2001 From: samamou Date: Fri, 27 Dec 2024 15:39:08 -0500 Subject: [PATCH 1/9] Add external editor button option --- src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp index 1de5d989a4..4496dc9937 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp @@ -28,6 +28,7 @@ class SCORE_LIB_PROCESS_EXPORT ScriptDialog : public QDialog void setText(const QString& str); void setError(int line, const QString& str); + void openInExternalEditor(); protected: virtual void on_accepted() = 0; From 13487a2968dd23e457b70232c22f669622be3fdd Mon Sep 17 00:00:00 2001 From: samamou Date: Fri, 27 Dec 2024 15:40:12 -0500 Subject: [PATCH 2/9] Add missing file to previous commit --- .../score-lib-process/Process/Script/ScriptEditor.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp index 5e49d6227b..425ee0c34b 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp @@ -7,7 +7,9 @@ #include #include #include +#include #include +#include #include #include @@ -50,6 +52,10 @@ ScriptDialog::ScriptDialog( connect( bbox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &QDialog::close); + + auto openExternalBtn = new QPushButton{tr("Open in external editor.."), this}; + connect(openExternalBtn, &QPushButton::clicked, this, [this] {}); + lay->addWidget(openExternalBtn); } QString ScriptDialog::text() const noexcept @@ -150,4 +156,4 @@ void MultiScriptDialog::clearError() m_error->clear(); } -} +void ScriptDialog::openInExternalEditor() { } From 34af3bf7e9cde06894a1dcedb761fa4ccf2a19c2 Mon Sep 17 00:00:00 2001 From: samamou Date: Fri, 27 Dec 2024 17:16:42 -0500 Subject: [PATCH 3/9] Test with hardcoded editor path --- .../Process/Script/ScriptEditor.cpp | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp index 425ee0c34b..b7f926e128 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -54,7 +55,8 @@ ScriptDialog::ScriptDialog( &QDialog::close); auto openExternalBtn = new QPushButton{tr("Open in external editor.."), this}; - connect(openExternalBtn, &QPushButton::clicked, this, [this] {}); + connect( + openExternalBtn, &QPushButton::clicked, this, [this] { openInExternalEditor(); }); lay->addWidget(openExternalBtn); } @@ -156,4 +158,30 @@ void MultiScriptDialog::clearError() m_error->clear(); } -void ScriptDialog::openInExternalEditor() { } +void ScriptDialog::openInExternalEditor() +{ + QString editorPath + = "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"; + + if(editorPath.isEmpty()) + { + QMessageBox::warning( + this, tr("Error"), tr("no 'Default editor' configured in score settings")); + return; + } + + QString tempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation); + QString tempFile = tempDir + "/ossia_script_temp.js"; + + QFile file(tempFile); + + QTextStream stream(&file); + stream << "Temporary file content for testing."; + file.close(); + + if(!QProcess::startDetached(editorPath, QStringList() << tempFile)) + { + QMessageBox::warning(this, tr("Error"), tr("Failed to launch external editor")); + } +} +} From c5f6fd25c6cf097e228752272b7b0674f570c618 Mon Sep 17 00:00:00 2001 From: samamou Date: Fri, 27 Dec 2024 17:39:12 -0500 Subject: [PATCH 4/9] =?UTF-8?q?get=20editor=20path=20from=20settings=20?= =?UTF-8?q?=F0=9F=92=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp index b7f926e128..0d0920e873 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -160,8 +161,7 @@ void MultiScriptDialog::clearError() void ScriptDialog::openInExternalEditor() { - QString editorPath - = "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"; + QString editorPath = QSettings{}.value("Skin/DefaultEditor").toString(); if(editorPath.isEmpty()) { From 705f297789861d0194d7b00ed124621c26e1f734 Mon Sep 17 00:00:00 2001 From: samamou Date: Mon, 30 Dec 2024 13:47:09 -0500 Subject: [PATCH 5/9] better error checking and retrieve script content --- .../Process/Script/ScriptEditor.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp index 0d0920e873..f36c01b992 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp @@ -170,13 +170,26 @@ void ScriptDialog::openInExternalEditor() return; } + if(!QFile::exists(editorPath)) + { + QMessageBox::warning( + this, tr("Error"), tr("the configured external editor does not exist.")); + return; + } + QString tempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation); QString tempFile = tempDir + "/ossia_script_temp.js"; QFile file(tempFile); + if(!file.open(QIODevice::WriteOnly)) + { + QMessageBox::warning(this, tr("Error"), tr("failed to create temporary file.")); + return; + } QTextStream stream(&file); - stream << "Temporary file content for testing."; + QString scriptContent = this->text(); + stream << scriptContent; file.close(); if(!QProcess::startDetached(editorPath, QStringList() << tempFile)) From 6ec16745135d17acccb4a905839f759558983ab2 Mon Sep 17 00:00:00 2001 From: samamou Date: Tue, 31 Dec 2024 16:06:18 -0500 Subject: [PATCH 6/9] Add function for opening multiple scripts --- .../Process/Script/MultiScriptEditor.hpp | 1 + .../Process/Script/ScriptEditor.cpp | 64 ++++++++++++++++++- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/plugins/score-lib-process/Process/Script/MultiScriptEditor.hpp b/src/plugins/score-lib-process/Process/Script/MultiScriptEditor.hpp index 52aac03382..9523d02f49 100644 --- a/src/plugins/score-lib-process/Process/Script/MultiScriptEditor.hpp +++ b/src/plugins/score-lib-process/Process/Script/MultiScriptEditor.hpp @@ -27,6 +27,7 @@ class SCORE_LIB_PROCESS_EXPORT MultiScriptDialog : public QDialog void setText(int idx, const QString& str); void setError(const QString& str); void clearError(); + void openInExternalEditor(); protected: virtual void on_accepted() = 0; diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp index f36c01b992..c05a75f091 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -114,6 +115,11 @@ MultiScriptDialog::MultiScriptDialog(const score::DocumentContext& ctx, QWidget* connect( bbox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &QDialog::close); + + auto openExternalBtn = new QPushButton{tr("Open in external editor.."), this}; + connect( + openExternalBtn, &QPushButton::clicked, this, [this] { openInExternalEditor(); }); + lay->addWidget(openExternalBtn); } void MultiScriptDialog::addTab( @@ -187,9 +193,7 @@ void ScriptDialog::openInExternalEditor() return; } - QTextStream stream(&file); - QString scriptContent = this->text(); - stream << scriptContent; + file.write(this->text().toUtf8()); file.close(); if(!QProcess::startDetached(editorPath, QStringList() << tempFile)) @@ -197,4 +201,58 @@ void ScriptDialog::openInExternalEditor() QMessageBox::warning(this, tr("Error"), tr("Failed to launch external editor")); } } + +void MultiScriptDialog::openInExternalEditor() +{ + QString editorPath = QSettings{}.value("Skin/DefaultEditor").toString(); + + if(editorPath.isEmpty()) + { + QMessageBox::warning( + this, tr("Error"), tr("no 'Default editor' configured in score settings")); + return; + } + + if(!QFile::exists(editorPath)) + { + QMessageBox::warning( + this, tr("Error"), tr("the configured external editor does not exist.")); + return; + } + + QString tempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation); + QDir dir(tempDir); + QStringList openedFiles; + + for(int i = 0; i < m_tabs->count(); ++i) + { + QString tabName = m_tabs->tabText(i); + QString tempFile = tempDir + "/" + tabName + ".js"; + + QFile file(tempFile); + if(!file.open(QIODevice::WriteOnly)) + { + QMessageBox::warning(this, tr("Error"), tr("failed to create temporary files.")); + return; + } + + QWidget* widget = m_tabs->widget(i); + QTextEdit* textedit = qobject_cast(widget); + + if(textedit) + { + QString content = textedit->document()->toPlainText(); + file.write(content.toUtf8()); + } + file.close(); + + openedFiles.append(tempFile); + } + + if(!openedFiles.isEmpty() && !QProcess::startDetached(editorPath, openedFiles)) + { + QMessageBox::warning(this, tr("Error"), tr("Failed to launch external editor")); + } +} + } From ffa0ab1b5e9f6371e15bb7d2bd2bd2e9d266f4b1 Mon Sep 17 00:00:00 2001 From: samamou Date: Mon, 6 Jan 2025 15:56:46 -0500 Subject: [PATCH 7/9] Implement file watching in ScriptEditor --- .../Process/Script/ScriptEditor.cpp | 44 ++++++++++++++----- .../Process/Script/ScriptEditor.hpp | 4 ++ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp index c05a75f091..3671586b11 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp @@ -2,8 +2,10 @@ #include "MultiScriptEditor.hpp" #include "ScriptWidget.hpp" +#include "score/tools/FileWatch.hpp" #include +#include #include #include #include @@ -176,16 +178,8 @@ void ScriptDialog::openInExternalEditor() return; } - if(!QFile::exists(editorPath)) - { - QMessageBox::warning( - this, tr("Error"), tr("the configured external editor does not exist.")); - return; - } - - QString tempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation); - QString tempFile = tempDir + "/ossia_script_temp.js"; - + QString tempFile = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + + "/ossia_script_temp.js"; QFile file(tempFile); if(!file.open(QIODevice::WriteOnly)) { @@ -196,12 +190,40 @@ void ScriptDialog::openInExternalEditor() file.write(this->text().toUtf8()); file.close(); + auto& w = score::FileWatch::instance(); + m_fileHandle = std::make_shared>([this, tempFile]() { + QFile file(tempFile); + if(file.open(QIODevice::ReadOnly)) + { + QString updatedContent = QString::fromUtf8(file.readAll()); + file.close(); + + QMetaObject::invokeMethod(m_textedit, [this, updatedContent]() { + if(m_textedit) + { + m_textedit->setPlainText(updatedContent); + } + }); + } + }); + w.add(tempFile, m_fileHandle); + if(!QProcess::startDetached(editorPath, QStringList() << tempFile)) { - QMessageBox::warning(this, tr("Error"), tr("Failed to launch external editor")); + QMessageBox::warning(this, tr("Error"), tr("failed to launch external editor")); } } +void ScriptDialog::stopWatchingFile(const QString& tempFile) +{ + if(tempFile.isEmpty()) + { + return; + } + + auto& w = score::FileWatch::instance(); + w.remove(tempFile, m_fileHandle); +} void MultiScriptDialog::openInExternalEditor() { QString editorPath = QSettings{}.value("Skin/DefaultEditor").toString(); diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp index 4496dc9937..493cfb5220 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp @@ -29,6 +29,7 @@ class SCORE_LIB_PROCESS_EXPORT ScriptDialog : public QDialog void setText(const QString& str); void setError(int line, const QString& str); void openInExternalEditor(); + void stopWatchingFile(const QString& tempFile); protected: virtual void on_accepted() = 0; @@ -36,6 +37,9 @@ class SCORE_LIB_PROCESS_EXPORT ScriptDialog : public QDialog const score::DocumentContext& m_context; QTextEdit* m_textedit{}; QPlainTextEdit* m_error{}; + +private: + std::shared_ptr> m_fileHandle; }; template From d4a13e31f558f48c1cfbfb04fee1d808fc609867 Mon Sep 17 00:00:00 2001 From: samamou Date: Tue, 7 Jan 2025 19:31:52 -0500 Subject: [PATCH 8/9] Show button only if default editor is set in settings + small fixes --- .../Process/Script/MultiScriptEditor.hpp | 2 +- .../Process/Script/ScriptEditor.cpp | 42 ++++++++++--------- .../Process/Script/ScriptEditor.hpp | 2 +- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/plugins/score-lib-process/Process/Script/MultiScriptEditor.hpp b/src/plugins/score-lib-process/Process/Script/MultiScriptEditor.hpp index 9523d02f49..5c053aa91e 100644 --- a/src/plugins/score-lib-process/Process/Script/MultiScriptEditor.hpp +++ b/src/plugins/score-lib-process/Process/Script/MultiScriptEditor.hpp @@ -27,7 +27,7 @@ class SCORE_LIB_PROCESS_EXPORT MultiScriptDialog : public QDialog void setText(int idx, const QString& str); void setError(const QString& str); void clearError(); - void openInExternalEditor(); + void openInExternalEditor(const QString& editorPath); protected: virtual void on_accepted() = 0; diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp index 3671586b11..0bba2c2039 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp @@ -58,10 +58,15 @@ ScriptDialog::ScriptDialog( bbox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &QDialog::close); - auto openExternalBtn = new QPushButton{tr("Open in external editor.."), this}; - connect( - openExternalBtn, &QPushButton::clicked, this, [this] { openInExternalEditor(); }); - lay->addWidget(openExternalBtn); + if(auto editorPath = QSettings{}.value("Skin/DefaultEditor").toString(); + !editorPath.isEmpty()) + { + auto openExternalBtn = new QPushButton{tr("Edit in default editor"), this}; + connect(openExternalBtn, &QPushButton::clicked, this, [this, editorPath] { + openInExternalEditor(editorPath); + }); + lay->addWidget(openExternalBtn); + } } QString ScriptDialog::text() const noexcept @@ -118,10 +123,15 @@ MultiScriptDialog::MultiScriptDialog(const score::DocumentContext& ctx, QWidget* bbox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &QDialog::close); - auto openExternalBtn = new QPushButton{tr("Open in external editor.."), this}; - connect( - openExternalBtn, &QPushButton::clicked, this, [this] { openInExternalEditor(); }); - lay->addWidget(openExternalBtn); + if(auto editorPath = QSettings{}.value("Skin/DefaultEditor").toString(); + !editorPath.isEmpty()) + { + auto openExternalBtn = new QPushButton{tr("Edit in default editor"), this}; + connect(openExternalBtn, &QPushButton::clicked, this, [this, editorPath] { + openInExternalEditor(editorPath); + }); + lay->addWidget(openExternalBtn); + } } void MultiScriptDialog::addTab( @@ -167,9 +177,8 @@ void MultiScriptDialog::clearError() m_error->clear(); } -void ScriptDialog::openInExternalEditor() +void ScriptDialog::openInExternalEditor(const QString& editorPath) { - QString editorPath = QSettings{}.value("Skin/DefaultEditor").toString(); if(editorPath.isEmpty()) { @@ -178,8 +187,8 @@ void ScriptDialog::openInExternalEditor() return; } - QString tempFile = QStandardPaths::writableLocation(QStandardPaths::TempLocation) - + "/ossia_script_temp.js"; + const QString tempFile = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + + "/ossia_script_temp.js"; QFile file(tempFile); if(!file.open(QIODevice::WriteOnly)) { @@ -188,7 +197,6 @@ void ScriptDialog::openInExternalEditor() } file.write(this->text().toUtf8()); - file.close(); auto& w = score::FileWatch::instance(); m_fileHandle = std::make_shared>([this, tempFile]() { @@ -196,7 +204,6 @@ void ScriptDialog::openInExternalEditor() if(file.open(QIODevice::ReadOnly)) { QString updatedContent = QString::fromUtf8(file.readAll()); - file.close(); QMetaObject::invokeMethod(m_textedit, [this, updatedContent]() { if(m_textedit) @@ -208,7 +215,7 @@ void ScriptDialog::openInExternalEditor() }); w.add(tempFile, m_fileHandle); - if(!QProcess::startDetached(editorPath, QStringList() << tempFile)) + if(!QProcess::startDetached(editorPath, QStringList{tempFile})) { QMessageBox::warning(this, tr("Error"), tr("failed to launch external editor")); } @@ -224,10 +231,8 @@ void ScriptDialog::stopWatchingFile(const QString& tempFile) auto& w = score::FileWatch::instance(); w.remove(tempFile, m_fileHandle); } -void MultiScriptDialog::openInExternalEditor() +void MultiScriptDialog::openInExternalEditor(const QString& editorPath) { - QString editorPath = QSettings{}.value("Skin/DefaultEditor").toString(); - if(editorPath.isEmpty()) { QMessageBox::warning( @@ -266,7 +271,6 @@ void MultiScriptDialog::openInExternalEditor() QString content = textedit->document()->toPlainText(); file.write(content.toUtf8()); } - file.close(); openedFiles.append(tempFile); } diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp index 493cfb5220..cd36db7092 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.hpp @@ -28,7 +28,7 @@ class SCORE_LIB_PROCESS_EXPORT ScriptDialog : public QDialog void setText(const QString& str); void setError(int line, const QString& str); - void openInExternalEditor(); + void openInExternalEditor(const QString& editorPath); void stopWatchingFile(const QString& tempFile); protected: From a5e6586cfc829bfd1972b18e125ae862b78e196d Mon Sep 17 00:00:00 2001 From: samamou Date: Tue, 7 Jan 2025 19:40:29 -0500 Subject: [PATCH 9/9] other smoll fixes from code review --- src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp index 0bba2c2039..76bd9af94e 100644 --- a/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp +++ b/src/plugins/score-lib-process/Process/Script/ScriptEditor.cpp @@ -2,7 +2,8 @@ #include "MultiScriptEditor.hpp" #include "ScriptWidget.hpp" -#include "score/tools/FileWatch.hpp" + +#include #include #include @@ -230,6 +231,7 @@ void ScriptDialog::stopWatchingFile(const QString& tempFile) auto& w = score::FileWatch::instance(); w.remove(tempFile, m_fileHandle); + m_fileHandle.reset(); } void MultiScriptDialog::openInExternalEditor(const QString& editorPath) {