Skip to content

Commit bb603a0

Browse files
committed
Update tempo editing
1 parent e450d61 commit bb603a0

File tree

4 files changed

+101
-9
lines changed

4 files changed

+101
-9
lines changed

src/libs/application/dspxmodel/src/selectionmodel/GenericGlobalItemSelectionModelData_p.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace dspx {
2727
bool selectionUpdatedFlag = false;
2828
bool currentItemUpdatedFlag = false;
2929

30-
if (!static_cast<PrivateClass *>(this)->isAddedToModel(item)) {
30+
if (item && !static_cast<PrivateClass *>(this)->isAddedToModel(item)) {
3131
return;
3232
}
3333

@@ -130,6 +130,7 @@ namespace dspx {
130130
selectedItems.insert(item);
131131
static_cast<PrivateClass *>(this)->updateSuperItem(getSuperItem(item));
132132
static_cast<PrivateClass *>(this)->updateAssociation(item);
133+
Q_EMIT q->itemSelected(item, true);
133134
}
134135
void removeFromSelection(Item *item) {
135136
auto q = q_ptr;
@@ -138,13 +139,15 @@ namespace dspx {
138139
}
139140
selectedItems.remove(item);
140141
static_cast<PrivateClass *>(this)->removeAssociation(item);
142+
Q_EMIT q->itemSelected(item, false);
141143
}
142144
void clearSelection() {
143145
auto q = q_ptr;
144146
for (auto item : selectedItems) {
145147
if (currentItem != item) {
146148
QObject::disconnect(item, nullptr, q, nullptr);
147149
}
150+
Q_EMIT q->itemSelected(item, false);
148151
}
149152
selectedItems.clear();
150153
static_cast<PrivateClass *>(this)->clearAssociation();

src/plugins/visualeditor/core/TempoViewModelContextData.cpp

Lines changed: 95 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <QLocale>
77
#include <QLoggingCategory>
88
#include <QStateMachine>
9+
#include <QSignalTransition>
910

1011
#include <ScopicFlowCore/LabelViewModel.h>
1112
#include <ScopicFlowCore/PointSequenceViewModel.h>
@@ -61,16 +62,16 @@ namespace VisualEditor {
6162
void TempoSelectionController::select(QObject *item, SelectionCommand command) {
6263
qCDebug(lcTempoViewModelContextData) << "Tempo view item selected" << item << command;
6364
dspx::SelectionModel::SelectionCommand documentSelectionCommand = {};
64-
if (command | Select) {
65+
if (command & Select) {
6566
documentSelectionCommand |= dspx::SelectionModel::Select;
6667
}
67-
if (command | Deselect) {
68+
if (command & Deselect) {
6869
documentSelectionCommand |= dspx::SelectionModel::Deselect;
6970
}
70-
if (command | ClearPreviousSelection) {
71+
if (command & ClearPreviousSelection) {
7172
documentSelectionCommand |= dspx::SelectionModel::ClearPreviousSelection;
7273
}
73-
if (command | SetCurrentItem) {
74+
if (command & SetCurrentItem) {
7475
documentSelectionCommand |= dspx::SelectionModel::SetCurrentItem;
7576
}
7677
auto documentItem = q->getTempoDocumentItemFromViewItem(qobject_cast<sflow::LabelViewModel *>(item));
@@ -84,6 +85,7 @@ namespace VisualEditor {
8485
void TempoViewModelContextData::init() {
8586
Q_Q(ProjectViewModelContext);
8687
tempoSequence = q->windowHandle()->projectDocumentContext()->document()->model()->timeline()->tempos();
88+
tempoSelectionModel = q->windowHandle()->projectDocumentContext()->document()->selectionModel()->tempoSelectionModel();
8789

8890
tempoSequenceViewModel = new sflow::PointSequenceViewModel(q);
8991

@@ -97,6 +99,27 @@ namespace VisualEditor {
9799
stateMachine->addState(movingState);
98100
stateMachine->addState(rubberBandDraggingState);
99101
stateMachine->setInitialState(idleState);
102+
stateMachine->start();
103+
104+
QObject::connect(movingState, &QState::exited, q, [=, this] {
105+
QSet<dspx::Tempo *> updatedItems;
106+
for (auto viewItem : transactionalUpdatedTempos) {
107+
auto item = tempoDocumentItemMap.value(viewItem);
108+
Q_ASSERT(item);
109+
item->setPos(viewItem->position());
110+
updatedItems.insert(item);
111+
}
112+
transactionalUpdatedTempos.clear();
113+
for (auto item : updatedItems) {
114+
auto overlappingItems = tempoSequence->slice(item->pos(), item->pos() + 1);
115+
for (auto overlappingItem : overlappingItems) {
116+
if (updatedItems.contains(overlappingItem))
117+
continue;
118+
tempoSequence->removeItem(overlappingItem);
119+
q->windowHandle()->projectDocumentContext()->document()->model()->destroyItem(overlappingItem);
120+
}
121+
}
122+
});
100123
}
101124

102125
void TempoViewModelContextData::bindTempoSequenceViewModel() {
@@ -111,6 +134,12 @@ namespace VisualEditor {
111134
for (auto item : tempoSequence->asRange()) {
112135
bindTempoDocumentItem(item);
113136
}
137+
QObject::connect(tempoSelectionModel, &dspx::TempoSelectionModel::itemSelected, q, [=, this](dspx::Tempo *item, bool selected) {
138+
qCDebug(lcTempoViewModelContextData) << "Tempo item selected" << item << selected;
139+
auto viewItem = tempoViewItemMap.value(item);
140+
Q_ASSERT(viewItem);
141+
viewItem->setSelected(selected);
142+
});
114143
}
115144

116145
void TempoViewModelContextData::bindTempoDocumentItem(dspx::Tempo *item) {
@@ -138,6 +167,10 @@ namespace VisualEditor {
138167
QObject::connect(viewItem, &sflow::LabelViewModel::positionChanged, item, [=] {
139168
if (viewItem->position() == item->pos())
140169
return;
170+
if (item->pos() == 0) {
171+
viewItem->setPosition(0);
172+
return;
173+
}
141174
qCDebug(lcTempoViewModelContextData) << "Tempo view item pos updated" << viewItem << viewItem->position();
142175
if (!stateMachine->configuration().contains(movingState)) {
143176
qCWarning(lcTempoViewModelContextData) << "Suspicious tempo view updating: moving state not entered";
@@ -167,11 +200,66 @@ namespace VisualEditor {
167200
viewItem->deleteLater();
168201
}
169202

203+
class InteractionSignalTransition : public QSignalTransition {
204+
public:
205+
template <typename PointerToMemberFunction>
206+
explicit InteractionSignalTransition(sflow::LabelSequenceInteractionController *controller, sflow::LabelSequenceInteractionController::InteractionFlag flag, PointerToMemberFunction signal)
207+
: QSignalTransition(controller, signal), m_flag(flag) {
208+
}
209+
210+
protected:
211+
bool eventTest(QEvent *event) override {
212+
if (!QSignalTransition::eventTest(event))
213+
return false;
214+
auto se = static_cast<QStateMachine::SignalEvent*>(event);
215+
return se->arguments().at(1).toInt() == m_flag;
216+
}
217+
218+
private:
219+
sflow::LabelSequenceInteractionController::InteractionFlag m_flag;
220+
};
221+
222+
class ItemInteractionSignalTransition : public QSignalTransition {
223+
public:
224+
template <typename PointerToMemberFunction>
225+
explicit ItemInteractionSignalTransition(sflow::LabelSequenceInteractionController *controller, sflow::LabelSequenceInteractionController::ItemInteractionFlag flag, PointerToMemberFunction signal)
226+
: QSignalTransition(controller, signal), m_flag(flag) {
227+
}
228+
229+
protected:
230+
bool eventTest(QEvent *event) override {
231+
if (!QSignalTransition::eventTest(event))
232+
return false;
233+
auto se = static_cast<QStateMachine::SignalEvent*>(event);
234+
return se->arguments().at(2).toInt() == m_flag;
235+
}
236+
237+
private:
238+
sflow::LabelSequenceInteractionController::ItemInteractionFlag m_flag;
239+
};
240+
170241
sflow::LabelSequenceInteractionController *TempoViewModelContextData::createController(QObject *parent) {
171-
// TODO
172242
auto controller = new sflow::LabelSequenceInteractionController(parent);
173-
controller->setInteraction({});
174-
controller->setItemInteraction({});
243+
controller->setInteraction(sflow::LabelSequenceInteractionController::SelectByRubberBand);
244+
controller->setItemInteraction(sflow::LabelSequenceInteractionController::Move | sflow::LabelSequenceInteractionController::Select);
245+
auto moveStartTransition = new ItemInteractionSignalTransition(controller, sflow::LabelSequenceInteractionController::Move, &sflow::LabelSequenceInteractionController::itemInteractionOperationStarted);
246+
moveStartTransition->setTargetState(movingState);
247+
idleState->addTransition(moveStartTransition);
248+
auto moveFinishTransition = new ItemInteractionSignalTransition(controller, sflow::LabelSequenceInteractionController::Move, &sflow::LabelSequenceInteractionController::itemInteractionOperationFinished);
249+
moveFinishTransition->setTargetState(idleState);
250+
movingState->addTransition(moveFinishTransition);
251+
auto rubberBandDragStartTransition = new InteractionSignalTransition(controller, sflow::LabelSequenceInteractionController::SelectByRubberBand, &sflow::LabelSequenceInteractionController::interactionOperationStarted);
252+
rubberBandDragStartTransition->setTargetState(rubberBandDraggingState);
253+
idleState->addTransition(rubberBandDragStartTransition);
254+
auto rubberBandDragFinishTransition = new InteractionSignalTransition(controller, sflow::LabelSequenceInteractionController::SelectByRubberBand, &sflow::LabelSequenceInteractionController::interactionOperationFinished);
255+
rubberBandDragFinishTransition->setTargetState(idleState);
256+
rubberBandDraggingState->addTransition(rubberBandDragFinishTransition);
257+
QObject::connect(controller, &QObject::destroyed, [=] {
258+
idleState->removeTransition(moveStartTransition);
259+
idleState->removeTransition(rubberBandDragStartTransition);
260+
movingState->removeTransition(moveFinishTransition);
261+
rubberBandDraggingState->removeTransition(rubberBandDragFinishTransition);
262+
});
175263
return controller;
176264
}
177265

src/plugins/visualeditor/core/TempoViewModelContextData_p.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ namespace VisualEditor {
5151
TempoSelectionController *tempoSelectionController;
5252

5353
dspx::TempoSequence *tempoSequence;
54+
dspx::TempoSelectionModel *tempoSelectionModel;
5455

5556
QStateMachine *stateMachine;
5657
QState *idleState;

0 commit comments

Comments
 (0)