Loading...
Searching...
No Matches
ScriptEditor.hpp
1#pragma once
2
3#include <score/command/Dispatchers/CommandDispatcher.hpp>
4#include <score/command/PropertyCommand.hpp>
5#include <score/document/DocumentContext.hpp>
6#include <score/tools/Bind.hpp>
7
8#include <QCloseEvent>
9#include <QDialog>
10
11#include <score_lib_process_export.h>
12
13#include <string_view>
14
15class QPlainTextEdit;
16class QTextEdit;
17class QTabWidget;
18namespace Process
19{
20class ProcessModel;
21class SCORE_LIB_PROCESS_EXPORT ScriptDialog : public QDialog
22{
23public:
25 const std::string_view lang, const score::DocumentContext& ctx, QWidget* parent);
27
28 QSize sizeHint() const override { return {800, 300}; }
29 QString text() const noexcept;
30
31 void setText(const QString& str);
32 void setError(int line, const QString& str);
33 void openInExternalEditor(const QString& editorPath);
34 void stopWatchingFile();
35
36protected:
37 virtual void on_accepted() = 0;
38
39 void hideEvent(QHideEvent* event) override;
40 void keyPressEvent(QKeyEvent* event) override;
41
42 const score::DocumentContext& m_context;
43 QObject* m_compileFilter{};
44 QTextEdit* m_textedit{};
45 QPlainTextEdit* m_error{};
46
47private:
48 QString m_watchedFile;
49 std::shared_ptr<std::function<void()>> m_fileHandle;
50};
51
52template <typename Process_T, typename Property_T, typename Spec_T>
54{
55public:
57 const Process_T& process, const score::DocumentContext& ctx, QWidget* parent)
58 : ScriptDialog{Spec_T::language, ctx, parent}
59 , m_process{process}
60 {
61 setText((m_process.*Property_T::get)());
62 con(m_process, &Process_T::errorMessage, this, &ProcessScriptEditDialog::setError);
63 // The process goes first when its document closes: the dialog can still
64 // get closed after that (with the document's view) and must not look at
65 // it any more.
67 [this] {
68 m_processGone = true;
69 deleteLater();
70 });
71 con(m_process, Property_T::notify, this, &ProcessScriptEditDialog::setText);
72 }
73
74 void on_accepted() override
75 {
76 this->setError(0, QString{});
77 if(this->text() != (m_process.*Property_T::get)())
78 {
79 // TODO try to see if we can make this a bit more efficient,
80 // by passing the validated / transformed data to the command maybe ?
81 if(m_process.validate(this->text()))
82 {
83 CommandDispatcher<>{m_context.commandStack}.submit(
85 m_process, this->text(), m_context});
86 }
87 }
88 }
89
90protected:
91 const Process_T& m_process;
92 bool m_processGone{};
93
94 // The editor may be a window or be docked in the main window: in both
95 // cases, going away means closing (which deletes it with WA_DeleteOnClose),
96 // not merely hiding like QDialog::reject() would do on Escape.
97 void reject() override { close(); }
98
99 void closeEvent(QCloseEvent* event) override
100 {
101 if(!m_processGone && m_process.scriptUI == this)
102 {
103 const_cast<QWidget*&>(m_process.scriptUI) = nullptr;
104 m_process.scriptUIVisible(false);
105 }
106 event->accept();
107 }
108};
109
110}
The CommandDispatcher class.
Definition CommandDispatcher.hpp:13
void identified_object_destroying(IdentifiedObjectAbstract *o)
To be called by subclasses.
Definition ScriptEditor.hpp:54
Definition ScriptEditor.hpp:22
Base classes and tools to implement processes and layers.
Definition JSONVisitor.hpp:1115
Definition DocumentContext.hpp:18
Definition PropertyCommand.hpp:112