Skip to content

Commit 760e5d7

Browse files
committed
Refactor + fixes
1 parent 1e5ca51 commit 760e5d7

File tree

8 files changed

+161
-65
lines changed

8 files changed

+161
-65
lines changed

include/FloatModelEditorBase.h

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class LMMS_EXPORT FloatModelEditorBase : public QWidget, public FloatModelView
4444
void initUi(const QString & name); //!< to be called by ctors
4545

4646
public:
47-
enum class DirectionOfManipulation
47+
enum class DirectionOfManipulation : bool
4848
{
4949
Vertical,
5050
Horizontal
@@ -60,25 +60,34 @@ class LMMS_EXPORT FloatModelEditorBase : public QWidget, public FloatModelView
6060
setUnit(txt_after);
6161
}
6262

63-
//! In this mode, floating text is obtained by calling `pullFloatingText`.
64-
void setFloatingTextPullMode()
63+
//! Push model or pull model for floating text updates
64+
enum class FloatingTextMode : bool
6565
{
66-
m_floatingTextPushMode = false;
67-
m_floatingTextRefreshRate = 0;
68-
}
66+
//! Floating text is updated by this widget calling `pullFloatingText` as needed
67+
Pull,
68+
69+
/**
70+
* Floating text is updated by an external component calling `pushFloatingText` when needed.
71+
*
72+
* This mode may optionally function in a hybrid fashion where this widget periodically emits
73+
* the `floatingTextUpdateRequested` signal for an external component to respond to by pushing
74+
* an update to `pushFloatingText`.
75+
*/
76+
Push
77+
};
78+
79+
//! In this mode, floating text is updated by this widget calling `pullFloatingText` as needed
80+
void setFloatingTextPullMode();
6981

7082
/**
71-
* In this mode, floating text must be set manually by calling `pushFloatingText`.
83+
* In this mode, floating text must be updated by an external component calling `pushFloatingText`.
7284
*
7385
* @param refreshRate How many times per second `floatingTextUpdateRequested` will be emitted
86+
* while the text float is visible
7487
*/
75-
void setFloatingTextPushMode(std::uint8_t refreshRate = 0)
76-
{
77-
m_floatingTextPushMode = true;
78-
m_floatingTextRefreshRate = refreshRate;
79-
}
88+
void setFloatingTextPushMode(std::uint8_t refreshRate = 0);
8089

81-
//! Manually updates the text float's text
90+
//! When using the push mode, external components must call this to update the text float's text
8291
void pushFloatingText(const QString& text);
8392

8493
signals:
@@ -87,8 +96,8 @@ class LMMS_EXPORT FloatModelEditorBase : public QWidget, public FloatModelView
8796
void sliderMoved(float value);
8897

8998
/**
90-
* May be emitted periodically when the text float is visible.
91-
* Upon receiving this signal, call `pushFloatingText()` to update the
99+
* In push mode, may be emitted periodically when the text float is visible.
100+
* Upon receiving this signal, call `pushFloatingText` to update the
92101
* text float's text.
93102
*/
94103
void floatingTextUpdateRequested();
@@ -114,10 +123,11 @@ class LMMS_EXPORT FloatModelEditorBase : public QWidget, public FloatModelView
114123

115124
virtual float getValue(const QPoint & p);
116125

117-
//! Retreives floating text in a "pull" fashion
126+
//! When using the pull mode, this method is periodically called to obtain the text float's text
118127
virtual QString pullFloatingText() const;
119128

120-
void updateFloatingText();
129+
//! Call before showing the text float
130+
void takeControlOfTextFloat();
121131

122132
void doConnections() override;
123133

@@ -137,13 +147,19 @@ class LMMS_EXPORT FloatModelEditorBase : public QWidget, public FloatModelView
137147

138148
DirectionOfManipulation m_directionOfManipulation;
139149

140-
bool m_floatingTextPushMode = false;
150+
FloatingTextMode m_floatingTextMode = FloatingTextMode::Pull;
141151
std::uint8_t m_floatingTextRefreshRate = 0; //! times per second
152+
int m_textFloatRefreshTimerId = 0;
153+
154+
private:
155+
void timerEvent(QTimerEvent* event) override;
142156

143157
private slots:
144158
virtual void enterValue();
145159
void friendlyUpdate();
146160
void toggleScale();
161+
162+
void textFloatVisibilityChanged(bool visible);
147163
};
148164

149165
} // namespace lmms::gui

include/SimpleTextFloat.h

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
#ifndef LMMS_GUI_SIMPLE_TEXT_FLOAT_H
2727
#define LMMS_GUI_SIMPLE_TEXT_FLOAT_H
2828

29-
#include <QTimer>
29+
3030
#include <QWidget>
31+
#include <atomic>
32+
#include <mutex>
3133

3234
#include "lmms_export.h"
3335

@@ -60,25 +62,28 @@ class LMMS_EXPORT SimpleTextFloat : public QWidget
6062
void show();
6163
void hide();
6264

63-
void setRefreshRate(int timesPerSecond);
65+
//! Stores which object is currently controlling the text float and disconnects the old source (if any)
66+
void setSource(QObject* source);
6467

65-
template<class T>
66-
void setRefreshConnection(T* receiver, void(T::* slot)(), Qt::ConnectionType type = Qt::AutoConnection)
67-
{
68-
if (auto connection = m_refreshTimer->callOnTimeout(receiver, slot,
69-
static_cast<Qt::ConnectionType>(type | Qt::UniqueConnection)))
70-
{
71-
m_textUpdateConnection = connection;
72-
}
73-
}
68+
//! Stores which object is currently controlling the text float and disconnects the old source (if any)
69+
void setSource(QObject* source, QMetaObject::Connection connection);
70+
71+
//! @returns which object is currently controlling the text float
72+
auto source() const -> QObject* { return m_source; }
73+
74+
signals:
75+
void visibilityChanged(bool visible);
7476

7577
private:
7678
QLabel * m_textLabel;
7779
QTimer * m_showTimer;
7880
QTimer * m_hideTimer;
79-
QTimer* m_refreshTimer;
8081

81-
QMetaObject::Connection m_textUpdateConnection;
82+
std::atomic<QObject*> m_source = nullptr;
83+
QMetaObject::Connection m_connection;
84+
85+
// TODO: See if the mutex usage can be removed or reduced
86+
std::recursive_mutex m_mutex;
8287
};
8388

8489
} // namespace lmms::gui

plugins/Vestige/Vestige.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ ManageVestigeInstrumentView::ManageVestigeInstrumentView( Instrument * _instrume
982982

983983
auto knob = new Knob(KnobType::Bright26, description.left(15), SMALL_FONT_SIZE, this, description);
984984
knob->setDescription(description + ":");
985-
knob->setFloatingTextPushMode(10);
985+
knob->setFloatingTextPushMode(15);
986986
connect(knob, &Knob::floatingTextUpdateRequested, this, [i, this]() {
987987
updateParameterText(i);
988988
}, Qt::DirectConnection);

plugins/VstEffect/VstEffectControls.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ ManageVSTEffectView::ManageVSTEffectView( VstEffect * _eff, VstEffectControls *
386386

387387
auto knob = new Knob(KnobType::Bright26, description.left(15), SMALL_FONT_SIZE, widget, description);
388388
knob->setDescription(description + ":");
389-
knob->setFloatingTextPushMode(10);
389+
knob->setFloatingTextPushMode(15);
390390
connect(knob, &Knob::floatingTextUpdateRequested, this, [i, this]() {
391391
updateParameterText(i);
392392
}, Qt::DirectConnection);

src/common/RemotePluginBase.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ RemotePluginBase::message RemotePluginBase::waitForMessage(
172172
#ifndef BUILD_REMOTE_PLUGIN_CLIENT
173173
if (_busy_waiting && !messagesLeft())
174174
{
175+
// FIXME: Can hang sometimes (due to too many messages?)
175176
QCoreApplication::processEvents(
176177
QEventLoop::ExcludeUserInputEvents, 50);
177178
continue;

src/gui/widgets/Draggable.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,9 @@ void Draggable::mouseMoveEvent(QMouseEvent* me)
107107

108108
emit sliderMoved(model()->value());
109109
m_lastMousePos = pPos;
110-
updateFloatingText();
111-
s_textFloat->moveGlobal(this, QPoint(width() + 2, 0));
110+
111+
takeControlOfTextFloat();
112+
s_textFloat->show();
112113
}
113114
}
114115

src/gui/widgets/FloatModelEditorBase.cpp

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <QApplication>
2929
#include <QInputDialog>
3030
#include <QPainter>
31+
#include <QTimerEvent>
3132

3233
#include "lmms_math.h"
3334
#include "DeprecationHelper.h"
@@ -72,18 +73,37 @@ void FloatModelEditorBase::initUi(const QString & name)
7273
}
7374

7475

76+
void FloatModelEditorBase::setFloatingTextPullMode()
77+
{
78+
m_floatingTextMode = FloatingTextMode::Pull;
79+
m_floatingTextRefreshRate = 0;
80+
81+
killTimer(m_textFloatRefreshTimerId);
82+
m_textFloatRefreshTimerId = 0;
83+
84+
disconnect(s_textFloat, &SimpleTextFloat::visibilityChanged,
85+
this, &FloatModelEditorBase::textFloatVisibilityChanged);
86+
}
87+
88+
89+
void FloatModelEditorBase::setFloatingTextPushMode(std::uint8_t refreshRate)
90+
{
91+
m_floatingTextMode = FloatingTextMode::Push;
92+
m_floatingTextRefreshRate = refreshRate;
93+
}
94+
95+
7596
void FloatModelEditorBase::pushFloatingText(const QString& text)
7697
{
77-
if (!m_floatingTextPushMode) { return; }
98+
if (m_floatingTextMode == FloatingTextMode::Pull || s_textFloat->source() != this) { return; }
99+
78100
s_textFloat->setText(m_description.trimmed() + ' ' + text);
79101
}
80102

81103

82104
void FloatModelEditorBase::showTextFloat(int msecBeforeDisplay, int msecDisplayTime)
83105
{
84-
updateFloatingText();
85-
s_textFloat->moveGlobal(this, QPoint(width() + 2, 0));
86-
s_textFloat->setRefreshRate(m_floatingTextRefreshRate);
106+
takeControlOfTextFloat();
87107
s_textFloat->showWithDelay(msecBeforeDisplay, msecDisplayTime);
88108
}
89109

@@ -207,7 +227,7 @@ void FloatModelEditorBase::mouseMoveEvent(QMouseEvent * me)
207227
m_lastMousePos = pos;
208228
}
209229

210-
updateFloatingText();
230+
takeControlOfTextFloat();
211231
s_textFloat->show();
212232
}
213233

@@ -342,6 +362,7 @@ void FloatModelEditorBase::wheelEvent(QWheelEvent * we)
342362
const int inc = direction * stepMult;
343363
model()->incValue(inc);
344364

365+
// NOTE: Calling timerEvent(nullptr) here can cause RemotePlugin to hang
345366
showTextFloat(0, 1000);
346367

347368
emit sliderMoved(model()->value());
@@ -419,17 +440,52 @@ QString FloatModelEditorBase::pullFloatingText() const
419440
}
420441

421442

422-
void FloatModelEditorBase::updateFloatingText()
443+
void FloatModelEditorBase::takeControlOfTextFloat()
423444
{
424-
if (!m_floatingTextPushMode)
445+
if (m_floatingTextMode == FloatingTextMode::Pull)
425446
{
447+
s_textFloat->setSource(this);
426448
s_textFloat->setText(m_description.trimmed() + ' ' + pullFloatingText());
427449
}
428-
else if (!s_textFloat->isVisible())
450+
else if (m_floatingTextRefreshRate > 0)
429451
{
430-
s_textFloat->setText("");
431-
s_textFloat->setRefreshConnection(this, &FloatModelEditorBase::floatingTextUpdateRequested);
452+
const auto connection = connect(s_textFloat, &SimpleTextFloat::visibilityChanged,
453+
this, &FloatModelEditorBase::textFloatVisibilityChanged,
454+
static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection));
455+
456+
s_textFloat->setSource(this, connection);
432457
}
458+
459+
s_textFloat->moveGlobal(this, QPoint(width() + 2, 0));
460+
}
461+
462+
void FloatModelEditorBase::timerEvent(QTimerEvent* event)
463+
{
464+
if (event && event->timerId() != m_textFloatRefreshTimerId) { return; }
465+
466+
// TODO: Thread check?
467+
468+
emit floatingTextUpdateRequested();
469+
}
470+
471+
void FloatModelEditorBase::textFloatVisibilityChanged(bool visible)
472+
{
473+
killTimer(m_textFloatRefreshTimerId);
474+
if (visible)
475+
{
476+
if (m_floatingTextRefreshRate > 0)
477+
{
478+
// Emit timeout signal once at the very start so that the text is ready
479+
// to be displayed when the text float becomes visible
480+
timerEvent(nullptr);
481+
482+
// Now start timer normally
483+
m_textFloatRefreshTimerId = startTimer(1000 / m_floatingTextRefreshRate);
484+
return;
485+
}
486+
}
487+
488+
m_textFloatRefreshTimerId = 0;
433489
}
434490

435491

0 commit comments

Comments
 (0)