Skip to content

Commit d75a08d

Browse files
committed
Update arrangement panel
1 parent 10e984a commit d75a08d

11 files changed

+408
-7
lines changed

src/plugins/visualeditor/core/ArrangementPanelInterface.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <coreplugin/ProjectWindowInterface.h>
1717
#include <coreplugin/ProjectTimeline.h>
1818

19+
#include <visualeditor/PositionAlignmentManipulator.h>
1920
#include <visualeditor/ProjectViewModelContext.h>
2021
#include <visualeditor/internal/EditorPreference.h>
2122

@@ -35,6 +36,7 @@ namespace VisualEditor {
3536
void ArrangementPanelInterfacePrivate::bindTimeLayoutViewModel() const {
3637
}
3738
void ArrangementPanelInterfacePrivate::bindTimelineInteractionController() const {
39+
3840
}
3941

4042
static Qt::KeyboardModifier getModifier(Internal::EditorPreference::ScrollModifier modifier) {
@@ -49,7 +51,16 @@ namespace VisualEditor {
4951
Q_UNREACHABLE();
5052
}
5153

54+
static sflow::ScrollBehaviorViewModel::ScrollTypes getScrollTypes(ArrangementPanelInterface::Tool tool) {
55+
if (tool == ArrangementPanelInterface::HandTool) {
56+
return sflow::ScrollBehaviorViewModel::Wheel | sflow::ScrollBehaviorViewModel::Pinch | sflow::ScrollBehaviorViewModel::MiddleButton | sflow::ScrollBehaviorViewModel::LeftButton;
57+
} else {
58+
return sflow::ScrollBehaviorViewModel::Wheel | sflow::ScrollBehaviorViewModel::Pinch | sflow::ScrollBehaviorViewModel::MiddleButton;
59+
}
60+
}
61+
5262
void ArrangementPanelInterfacePrivate::bindScrollBehaviorViewModel() const {
63+
Q_Q(const ArrangementPanelInterface);
5364
scrollBehaviorViewModel->setAlternateAxisModifier(getModifier(Internal::EditorPreference::alternateAxisModifier()));
5465
scrollBehaviorViewModel->setZoomModifier(getModifier(Internal::EditorPreference::zoomModifier()));
5566
scrollBehaviorViewModel->setPageModifier(getModifier(Internal::EditorPreference::pageModifier()));
@@ -70,6 +81,11 @@ namespace VisualEditor {
7081
QObject::connect(Internal::EditorPreference::instance(), &Internal::EditorPreference::middleButtonAutoScrollChanged, scrollBehaviorViewModel, [=, this] {
7182
scrollBehaviorViewModel->setAutoScroll(Internal::EditorPreference::middleButtonAutoScroll());
7283
});
84+
85+
scrollBehaviorViewModel->setScrollTypes(getScrollTypes(tool));
86+
QObject::connect(q, &ArrangementPanelInterface::toolChanged, scrollBehaviorViewModel, [=, this] {
87+
scrollBehaviorViewModel->setScrollTypes(getScrollTypes(tool));
88+
});
7389
}
7490

7591
ArrangementPanelInterface::ArrangementPanelInterface(Core::ProjectWindowInterface *windowHandle) : QObject(windowHandle), d_ptr(new ArrangementPanelInterfacePrivate) {
@@ -84,6 +100,9 @@ namespace VisualEditor {
84100
d->timelineInteractionController = new sflow::TimelineInteractionController(this);
85101
d->scrollBehaviorViewModel = new sflow::ScrollBehaviorViewModel(this);
86102

103+
d->positionAlignmentManipulator = new PositionAlignmentManipulator(this);
104+
d->positionAlignmentManipulator->setTimeLayoutViewModel(d->timeLayoutViewModel);
105+
87106
QQmlComponent component(Core::RuntimeInterface::qmlEngine(), "DiffScope.VisualEditor", "ArrangementView");
88107
if (component.isError()) {
89108
qFatal() << component.errorString();
@@ -133,6 +152,11 @@ namespace VisualEditor {
133152
return d->timelineInteractionController;
134153
}
135154

155+
PositionAlignmentManipulator *ArrangementPanelInterface::positionAlignmentManipulator() const {
156+
Q_D(const ArrangementPanelInterface);
157+
return d->positionAlignmentManipulator;
158+
}
159+
136160
QQuickItem *ArrangementPanelInterface::arrangementView() const {
137161
Q_D(const ArrangementPanelInterface);
138162
return d->arrangementView;

src/plugins/visualeditor/core/ArrangementPanelInterface.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ namespace VisualEditor {
2525
class ArrangementAddOn;
2626
}
2727

28+
class PositionAlignmentManipulator;
29+
2830
class ArrangementPanelInterfacePrivate;
2931

3032
class VISUAL_EDITOR_EXPORT ArrangementPanelInterface : public QObject {
@@ -37,6 +39,7 @@ namespace VisualEditor {
3739
Q_PROPERTY(sflow::TimeLayoutViewModel *timeLayoutViewModel READ timeLayoutViewModel CONSTANT)
3840
Q_PROPERTY(sflow::ScrollBehaviorViewModel *scrollBehaviorViewModel READ scrollBehaviorViewModel CONSTANT)
3941
Q_PROPERTY(sflow::TimelineInteractionController *timelineInteractionController READ timelineInteractionController CONSTANT)
42+
Q_PROPERTY(PositionAlignmentManipulator *positionAlignmentManipulator READ positionAlignmentManipulator CONSTANT)
4043
Q_PROPERTY(QQuickItem *arrangementView READ arrangementView CONSTANT)
4144
Q_PROPERTY(Tool tool READ tool WRITE setTool NOTIFY toolChanged)
4245

@@ -52,6 +55,8 @@ namespace VisualEditor {
5255
sflow::ScrollBehaviorViewModel *scrollBehaviorViewModel() const;
5356
sflow::TimelineInteractionController *timelineInteractionController() const;
5457

58+
PositionAlignmentManipulator *positionAlignmentManipulator() const;
59+
5560
QQuickItem *arrangementView() const;
5661

5762
enum Tool {

src/plugins/visualeditor/core/ArrangementPanelInterface_p.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ namespace VisualEditor {
1616
sflow::TimelineInteractionController *timelineInteractionController;
1717
sflow::ScrollBehaviorViewModel *scrollBehaviorViewModel;
1818

19+
PositionAlignmentManipulator *positionAlignmentManipulator;
20+
1921
QQuickItem *arrangementView;
2022

2123
ArrangementPanelInterface::Tool tool{ArrangementPanelInterface::PointerTool};
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#include "PositionAlignmentManipulator.h"
2+
#include "PositionAlignmentManipulator_p.h"
3+
4+
#include <ScopicFlowCore/TimeLayoutViewModel.h>
5+
6+
namespace VisualEditor {
7+
8+
// Static helper function to find the appropriate note duration for auto mode
9+
static PositionAlignmentManipulator::Duration findNoteDurationInRange(double minValue, double maxValue) {
10+
// Define all note durations in descending order (longest to shortest)
11+
static const QList<PositionAlignmentManipulator::Duration> noteDurations = {
12+
PositionAlignmentManipulator::Note1st,
13+
PositionAlignmentManipulator::Note2nd,
14+
PositionAlignmentManipulator::Note4th,
15+
PositionAlignmentManipulator::Note8th,
16+
PositionAlignmentManipulator::Note16th,
17+
PositionAlignmentManipulator::Note32nd,
18+
PositionAlignmentManipulator::Note64th,
19+
PositionAlignmentManipulator::Note128th
20+
};
21+
22+
// Find the first note duration that falls within the range [minValue, maxValue)
23+
for (auto noteDuration : noteDurations) {
24+
double noteValue = static_cast<double>(noteDuration);
25+
if (noteValue >= minValue && noteValue < maxValue) {
26+
return noteDuration;
27+
}
28+
}
29+
30+
// If no note duration is in range, return the boundary values
31+
if (maxValue <= static_cast<double>(PositionAlignmentManipulator::Note128th)) {
32+
return PositionAlignmentManipulator::Note128th; // shortest
33+
} else {
34+
return PositionAlignmentManipulator::Note1st; // longest
35+
}
36+
}
37+
38+
PositionAlignmentManipulator::PositionAlignmentManipulator(QObject *parent)
39+
: QObject(parent), d_ptr(new PositionAlignmentManipulatorPrivate) {
40+
Q_D(PositionAlignmentManipulator);
41+
d->q_ptr = this;
42+
d->timeLayoutViewModel = nullptr;
43+
d->duration = Note8th;
44+
d->tuplet = None;
45+
d->autoDurationPositionAlignment = 48;
46+
d->helper = new PositionAlignmentManipulatorHelper(d, this);
47+
}
48+
49+
PositionAlignmentManipulator::~PositionAlignmentManipulator() = default;
50+
51+
sflow::TimeLayoutViewModel *PositionAlignmentManipulator::timeLayoutViewModel() const {
52+
Q_D(const PositionAlignmentManipulator);
53+
return d->timeLayoutViewModel;
54+
}
55+
56+
void PositionAlignmentManipulator::setTimeLayoutViewModel(sflow::TimeLayoutViewModel *timeLayoutViewModel) {
57+
Q_D(PositionAlignmentManipulator);
58+
if (d->timeLayoutViewModel == timeLayoutViewModel)
59+
return;
60+
61+
// Disconnect old connections
62+
d->disconnectTimeLayoutViewModel();
63+
64+
d->timeLayoutViewModel = timeLayoutViewModel;
65+
66+
// Connect new connections
67+
d->connectTimeLayoutViewModel();
68+
69+
// Update position alignment with new view model
70+
d->updatePositionAlignment();
71+
72+
Q_EMIT timeLayoutViewModelChanged();
73+
}
74+
75+
PositionAlignmentManipulator::Duration PositionAlignmentManipulator::duration() const {
76+
Q_D(const PositionAlignmentManipulator);
77+
return d->duration;
78+
}
79+
80+
void PositionAlignmentManipulator::setDuration(Duration duration) {
81+
Q_D(PositionAlignmentManipulator);
82+
if (d->duration == duration)
83+
return;
84+
85+
d->duration = duration;
86+
d->updatePositionAlignment();
87+
Q_EMIT durationChanged();
88+
}
89+
90+
PositionAlignmentManipulator::Tuplet PositionAlignmentManipulator::tuplet() const {
91+
Q_D(const PositionAlignmentManipulator);
92+
return d->tuplet;
93+
}
94+
95+
void PositionAlignmentManipulator::setTuplet(Tuplet tuplet) {
96+
Q_D(PositionAlignmentManipulator);
97+
if (d->tuplet == tuplet)
98+
return;
99+
100+
d->tuplet = tuplet;
101+
d->updatePositionAlignment();
102+
Q_EMIT tupletChanged();
103+
}
104+
105+
int PositionAlignmentManipulator::autoDurationPositionAlignment() const {
106+
Q_D(const PositionAlignmentManipulator);
107+
return d->autoDurationPositionAlignment;
108+
}
109+
110+
void PositionAlignmentManipulator::setAutoDurationPositionAlignment(int autoDurationPositionAlignment) {
111+
Q_D(PositionAlignmentManipulator);
112+
if (d->autoDurationPositionAlignment == autoDurationPositionAlignment)
113+
return;
114+
115+
d->autoDurationPositionAlignment = autoDurationPositionAlignment;
116+
d->updatePositionAlignment();
117+
Q_EMIT autoDurationPositionAlignmentChanged();
118+
}
119+
120+
void PositionAlignmentManipulatorPrivate::updatePositionAlignment() {
121+
Q_Q(PositionAlignmentManipulator);
122+
123+
if (!timeLayoutViewModel)
124+
return;
125+
126+
int newAlignment = 1; // Default value
127+
128+
if (duration == PositionAlignmentManipulator::Unset) {
129+
newAlignment = 1;
130+
} else if (duration != PositionAlignmentManipulator::Auto) {
131+
// Calculate: duration * 2 / tuplet
132+
newAlignment = static_cast<int>(duration) * 2 / static_cast<int>(tuplet);
133+
} else {
134+
// Auto mode: find appropriate note duration based on pixel density
135+
double pixelDensity = timeLayoutViewModel->pixelDensity();
136+
if (pixelDensity > 0) {
137+
double minValue = autoDurationPositionAlignment / pixelDensity;
138+
double maxValue = 2.0 * autoDurationPositionAlignment / pixelDensity;
139+
140+
auto foundDuration = findNoteDurationInRange(minValue, maxValue);
141+
newAlignment = static_cast<int>(foundDuration) * 2 / static_cast<int>(tuplet);
142+
}
143+
}
144+
145+
timeLayoutViewModel->setPositionAlignment(newAlignment);
146+
}
147+
148+
void PositionAlignmentManipulatorPrivate::connectTimeLayoutViewModel() const {
149+
if (!timeLayoutViewModel)
150+
return;
151+
152+
// Connect to pixelDensity changes to recalculate auto mode alignment
153+
QObject::connect(timeLayoutViewModel, SIGNAL(pixelDensityChanged()), helper, SLOT(onPixelDensityChanged()));
154+
}
155+
156+
void PositionAlignmentManipulatorPrivate::disconnectTimeLayoutViewModel() const {
157+
if (!timeLayoutViewModel)
158+
return;
159+
160+
// Disconnect all connections from the old timeLayoutViewModel
161+
QObject::disconnect(timeLayoutViewModel, nullptr, helper, nullptr);
162+
}
163+
164+
PositionAlignmentManipulatorHelper::PositionAlignmentManipulatorHelper(PositionAlignmentManipulatorPrivate *d, QObject *parent)
165+
: QObject(parent), d(d) {
166+
}
167+
168+
void PositionAlignmentManipulatorHelper::onPixelDensityChanged() const {
169+
if (d->duration == PositionAlignmentManipulator::Auto) {
170+
d->updatePositionAlignment();
171+
}
172+
}
173+
174+
}
175+
176+
#include "moc_PositionAlignmentManipulator.cpp"
177+
#include "moc_PositionAlignmentManipulator_p.cpp"
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#ifndef DIFFSCOPE_VISUALEDITOR_POSITIONALIGNMENTMANIPULATOR_H
2+
#define DIFFSCOPE_VISUALEDITOR_POSITIONALIGNMENTMANIPULATOR_H
3+
4+
#include <QObject>
5+
#include <qqmlintegration.h>
6+
7+
#include <visualeditor/visualeditorglobal.h>
8+
9+
namespace sflow {
10+
class TimeLayoutViewModel;
11+
}
12+
13+
namespace VisualEditor {
14+
15+
class PositionAlignmentManipulatorPrivate;
16+
17+
class VISUAL_EDITOR_EXPORT PositionAlignmentManipulator : public QObject {
18+
Q_OBJECT
19+
QML_ELEMENT
20+
Q_DECLARE_PRIVATE(PositionAlignmentManipulator)
21+
Q_PROPERTY(sflow::TimeLayoutViewModel *timeLayoutViewModel READ timeLayoutViewModel WRITE setTimeLayoutViewModel NOTIFY timeLayoutViewModelChanged)
22+
Q_PROPERTY(Duration duration READ duration WRITE setDuration NOTIFY durationChanged)
23+
Q_PROPERTY(Tuplet tuplet READ tuplet WRITE setTuplet NOTIFY tupletChanged)
24+
Q_PROPERTY(int autoDurationPositionAlignment READ autoDurationPositionAlignment WRITE setAutoDurationPositionAlignment NOTIFY autoDurationPositionAlignmentChanged)
25+
26+
public:
27+
explicit PositionAlignmentManipulator(QObject *parent = nullptr);
28+
~PositionAlignmentManipulator() override;
29+
30+
sflow::TimeLayoutViewModel *timeLayoutViewModel() const;
31+
void setTimeLayoutViewModel(sflow::TimeLayoutViewModel *timeLayoutViewModel);
32+
33+
enum Duration {
34+
Auto = 0,
35+
Unset = 1,
36+
Note1st = 1920,
37+
Note2nd = 960,
38+
Note4th = 480,
39+
Note8th = 240,
40+
Note16th = 120,
41+
Note32nd = 60,
42+
Note64th = 30,
43+
Note128th = 15
44+
};
45+
Q_ENUM(Duration)
46+
Duration duration() const;
47+
void setDuration(Duration duration);
48+
49+
enum Tuplet {
50+
None = 2,
51+
Triplet = 3,
52+
Quintuplet = 5
53+
};
54+
Q_ENUM(Tuplet)
55+
Tuplet tuplet() const;
56+
void setTuplet(Tuplet tuplet);
57+
58+
int autoDurationPositionAlignment() const;
59+
void setAutoDurationPositionAlignment(int autoDurationPositionAlignment);
60+
61+
Q_SIGNALS:
62+
void timeLayoutViewModelChanged();
63+
void durationChanged();
64+
void tupletChanged();
65+
void autoDurationPositionAlignmentChanged();
66+
67+
private:
68+
QScopedPointer<PositionAlignmentManipulatorPrivate> d_ptr;
69+
};
70+
71+
}
72+
73+
#endif //DIFFSCOPE_VISUALEDITOR_POSITIONALIGNMENTMANIPULATOR_H

0 commit comments

Comments
 (0)