commit e18f3c2ac6beae12cd026fcfbcafdeacbaa2da25
parent dcc8840e030f2b862f2ac2b4f31239314ba02492
Author: Alexandre BIQUE <bique.alexandre@gmail.com>
Date: Sat, 28 Aug 2021 22:42:49 +0200
Initial work on custom knobs and re-usable qml components
Diffstat:
9 files changed, 98 insertions(+), 13 deletions(-)
diff --git a/examples/gui/application.cc b/examples/gui/application.cc
@@ -19,9 +19,11 @@ Application::Application(int &argc, char **argv)
QCommandLineOption skinOpt("skin", tr("path to the skin directory"), tr("path"));
QCommandLineOption socketOpt("socket", tr("path to the QML skin"), tr("path"));
+ QCommandLineOption qmlLibOpt("qml-import", tr("QML import path"), tr("path"));
parser.addOption(skinOpt);
parser.addOption(socketOpt);
+ parser.addOption(qmlLibOpt);
parser.addHelpOption();
parser.process(*this);
@@ -29,6 +31,8 @@ Application::Application(int &argc, char **argv)
pluginProxy_ = new PluginProxy(this);
auto qmlContext = quickView_->engine()->rootContext();
+ for (const auto &str : parser.values(qmlLibOpt))
+ quickView_->engine()->addImportPath(str);
qmlContext->setContextProperty("plugin", pluginProxy_);
quickView_->setSource(parser.value(skinOpt) + "/main.qml");
diff --git a/examples/gui/parameter-proxy.cc b/examples/gui/parameter-proxy.cc
@@ -39,6 +39,10 @@ void ParameterProxy::setIsAdjusting(bool isAdjusting) {
}
void ParameterProxy::setValueFromUI(double value) {
+ value = std::max(minValue_, std::min(maxValue_, value));
+ if (value == value_)
+ return;
+
value_ = value;
clap::messages::AdjustRequest rq{id_, value_, 0};
diff --git a/examples/gui/parameter-proxy.hh b/examples/gui/parameter-proxy.hh
@@ -53,14 +53,12 @@ public:
double normalize(double value) const {
double delta = maxValue_ - minValue_;
- return delta != 0 ? (value - minValue_) / delta : 0;
+ return delta != 0 ? std::min(1., std::max(0., (value - minValue_) / delta)) : 0;
}
double denormalize(double value) const {
- Q_ASSERT(value >= 0);
- Q_ASSERT(value <= 1);
double delta = maxValue_ - minValue_;
- return minValue_ + value * delta;
+ return minValue_ + std::min(1., std::max(0., value)) * delta;
}
signals:
diff --git a/examples/plugins/dc-offset/skin/main.qml b/examples/plugins/dc-offset/skin/main.qml
@@ -1,20 +1,15 @@
import QtQuick 2.1
import QtQuick.Controls 2.1
+import clap 1.0
Rectangle {
width: 300
height: 200
color: "#224477"
- Dial {
+ Knob {
id: dc_offset_knob
- property QtObject param: plugin.param(0)
- from: param.minValue
- to: param.maxValue
- value: param.value
- inputMode: Dial.Vertical
- onMoved: {
- param.value = value;
- }
+ param: plugin.param(0)
+ size: 80
}
}
\ No newline at end of file
diff --git a/examples/plugins/path-provider.cc b/examples/plugins/path-provider.cc
@@ -24,6 +24,8 @@ namespace clap {
std::string getSkinDirectory() const override { return prefix_ / "lib/clap/" / pluginName_ / "skin"; }
+ std::string getQmlLibDirectory() const override { return prefix_ / "lib/clap" / pluginName_ / "qml"; }
+
bool isValid() const noexcept override { return !prefix_.empty(); }
private:
@@ -59,6 +61,8 @@ namespace clap {
std::string getSkinDirectory() const override { return srcRoot_ / "examples/plugins/" / pluginName_ / "skin"; }
+ std::string getQmlLibDirectory() const override { return srcRoot_ / "examples/plugins/qml"; }
+
bool isValid() const noexcept override { return !srcRoot_.empty() && !buildRoot_.empty(); }
private:
diff --git a/examples/plugins/path-provider.hh b/examples/plugins/path-provider.hh
@@ -12,6 +12,7 @@ namespace clap {
virtual std::string getGuiExecutable() const = 0;
virtual std::string getSkinDirectory() const = 0;
+ virtual std::string getQmlLibDirectory() const = 0;
virtual bool isValid() const = 0;
};
diff --git a/examples/plugins/qml/clap/Knob.qml b/examples/plugins/qml/clap/Knob.qml
@@ -0,0 +1,72 @@
+import QtQuick 2.1
+import QtQuick.Controls 2.1
+
+Item {
+ property QtObject param
+ property int size: 20
+ id: knob
+ width: size
+ height: size
+
+ Rectangle {
+ width: knob.size
+ height: knob.size
+ radius: knob.size / 2
+ color: "#332277"
+
+ MouseArea {
+ anchors.fill: parent
+ drag.axis: Drag.YAxis
+ property real lastY: 0
+ onPressed: (mouse) => {
+ if (mouse.button === Qt.LeftButton) {
+ lastY = mouse.y;
+ knob.param.isAdjusting = true
+ }
+ }
+ onReleased: (mouse) => {
+ if (mouse.button === Qt.LeftButton) {
+ knob.param.isAdjusting = false
+ }
+ }
+ onPositionChanged: (mouse) => {
+ if (!(mouse.buttons & Qt.LeftButton))
+ return;
+ knob.param.normalizedValue += ((mouse.modifiers & Qt.ShiftModifier) ? 0.001 : 0.01) * (mouse.y - lastY);
+ lastY = mouse.y;
+ }
+ }
+ }
+
+ Item {
+ Rectangle {
+ x: knob.size / 2 - knob.size / 40
+ y: knob.size / 20
+ height: knob.size / 10
+ width: knob.size / 20
+ radius: knob.size / 40
+ color: "#2282ff"
+ }
+
+ transform: Rotation {
+ angle: knob.param.normalizedModulation * 270 - 135
+ origin.x: knob.size / 2
+ origin.y: knob.size / 2
+ }
+ }
+
+ Rectangle {
+ x: knob.size / 2 - knob.size / 20
+ y: knob.size / 20
+ height: knob.size / 10
+ width: knob.size / 10
+ radius: knob.size / 40
+ color: "#dd82ff"
+ }
+
+ transform: Rotation {
+ angle: knob.param.normalizedValue * 270 - 135
+ origin.x: knob.size / 2
+ origin.y: knob.size / 2
+ }
+}
diff --git a/examples/plugins/qml/clap/qmldir b/examples/plugins/qml/clap/qmldir
@@ -0,0 +1,3 @@
+module clap
+
+Knob 1.0 Knob.qml
+\ No newline at end of file
diff --git a/examples/plugins/remote-gui.cc b/examples/plugins/remote-gui.cc
@@ -49,12 +49,15 @@ namespace clap {
::snprintf(socketStr, sizeof(socketStr), "%d", sockets[1]);
auto path = pathProvider.getGuiExecutable();
auto skin = pathProvider.getSkinDirectory();
+ auto qmlLib = pathProvider.getQmlLibDirectory();
::execl(path.c_str(),
path.c_str(),
"--socket",
socketStr,
"--skin",
skin.c_str(),
+ "--qml-import",
+ qmlLib.c_str(),
(const char *)nullptr);
printf("Failed to start child process: %m\n");
std::terminate();