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
0 commit comments