diff --git a/src/lib/core/view/Window.cpp b/src/lib/core/view/Window.cpp
index 5bcc1fd66a..845f5aed7a 100644
--- a/src/lib/core/view/Window.cpp
+++ b/src/lib/core/view/Window.cpp
@@ -468,6 +468,7 @@ void View::resizeEvent(QResizeEvent* e)
QMainWindow::resizeEvent(e);
sizeChanged(e->size());
}
+
bool score::View::event(QEvent* event)
{
if (event->type() == QEvent::StatusTip)
@@ -484,7 +485,7 @@ bool score::View::event(QEvent* event)
tip.push_front("");
tip.push_back("");
}
- tip.replace(QChar('\n'), "");
+ tip.replace(QChar('\n'), "
");
m_status->setText(tip);
}
else if (event->type() == QEvent::ToolTip)
diff --git a/src/lib/score/graphics/GraphicsItem.hpp b/src/lib/score/graphics/GraphicsItem.hpp
index 0c30a0b9c7..aa0371bfec 100644
--- a/src/lib/score/graphics/GraphicsItem.hpp
+++ b/src/lib/score/graphics/GraphicsItem.hpp
@@ -31,15 +31,16 @@ QGraphicsView* getView(const QPainter& painter);
SCORE_LIB_BASE_EXPORT
QImage newImage(double logical_w, double logical_h);
+
template
struct graphics_item_ptr
{
T* impl{};
graphics_item_ptr() = default;
graphics_item_ptr(const graphics_item_ptr&) = default;
- graphics_item_ptr(graphics_item_ptr&&) = default;
+ graphics_item_ptr(graphics_item_ptr&&) noexcept = default;
graphics_item_ptr& operator=(const graphics_item_ptr&) = default;
- graphics_item_ptr& operator=(graphics_item_ptr&&) = default;
+ graphics_item_ptr& operator=(graphics_item_ptr&&) noexcept = default;
graphics_item_ptr(T* p)
: impl{p}
diff --git a/src/plugins/score-lib-process/Effect/EffectLayout.hpp b/src/plugins/score-lib-process/Effect/EffectLayout.hpp
index 8ab76bd1c0..7ab659364d 100644
--- a/src/plugins/score-lib-process/Effect/EffectLayout.hpp
+++ b/src/plugins/score-lib-process/Effect/EffectLayout.hpp
@@ -142,6 +142,7 @@ auto createControl(
QPointF pos = Process::currentWigetPos(i, setup.getControlSize);
item->setPos(pos);
item->setRect(itemRect);
+ item->setToolTip(QString("%1\n%2").arg(port.name(), port.description()));
return Controls{item, portItem, widg, lab, itemRect};
}
@@ -153,6 +154,7 @@ auto createControl(
lab->setPos(20., 2);
item->setPos(pos);
item->setRect(itemRect);
+ item->setToolTip(QString("%1\n%2").arg(port.name(), port.description()));
return Controls{item, portItem, nullptr, lab, itemRect};
}
diff --git a/src/plugins/score-lib-process/Process/Dataflow/CableItem.cpp b/src/plugins/score-lib-process/Process/Dataflow/CableItem.cpp
index 5bb6dae7d6..60afb6bcba 100644
--- a/src/plugins/score-lib-process/Process/Dataflow/CableItem.cpp
+++ b/src/plugins/score-lib-process/Process/Dataflow/CableItem.cpp
@@ -41,6 +41,7 @@ CableItem::CableItem(
auto& plug = ctx.dataflow;
this->setCursor(Qt::CrossCursor);
this->setFlag(QGraphicsItem::ItemClipsToShape);
+ this->setToolTip(tr("Cable\n"));
SCORE_ASSERT(canCreateCable(c, plug));
diff --git a/src/plugins/score-lib-process/Process/Dataflow/NodeItem.cpp b/src/plugins/score-lib-process/Process/Dataflow/NodeItem.cpp
index 70d03a540c..3467c50269 100644
--- a/src/plugins/score-lib-process/Process/Dataflow/NodeItem.cpp
+++ b/src/plugins/score-lib-process/Process/Dataflow/NodeItem.cpp
@@ -319,6 +319,17 @@ void NodeItem::createContentItem()
m_contentSize = m_fx->boundingRect().size();
}
+ if(m_fx->toolTip().isEmpty())
+ {
+ auto& p = this->m_context.app.interfaces();
+ const auto& desc = p.get(m_model.concreteKey())->descriptor({});
+ this->setToolTip(QString("%1\n%2").arg(desc.prettyName, desc.description));
+ }
+ else
+ {
+ this->setToolTip(m_fx->toolTip());
+ }
+
// Positions / size
m_fx->setPos({0, 0});
diff --git a/src/plugins/score-plugin-curve/Curve/Segment/CurveSegmentView.cpp b/src/plugins/score-plugin-curve/Curve/Segment/CurveSegmentView.cpp
index 4a4259c8bd..830a2cce08 100644
--- a/src/plugins/score-plugin-curve/Curve/Segment/CurveSegmentView.cpp
+++ b/src/plugins/score-plugin-curve/Curve/Segment/CurveSegmentView.cpp
@@ -32,6 +32,8 @@ SegmentView::SegmentView(
: QGraphicsItem{parent}
, m_style{style}
{
+ this->setToolTip(QObject::tr("Curve segment\nRight-click to change options. If the type is power, shift can be used to change its curvature."));
+
this->setCacheMode(QGraphicsItem::NoCache);
this->setZValue(1);
this->setFlag(ItemIsFocusable, false);
diff --git a/src/plugins/score-plugin-midi/Midi/MidiNoteView.cpp b/src/plugins/score-plugin-midi/Midi/MidiNoteView.cpp
index 73ddb3949a..34396cce7e 100644
--- a/src/plugins/score-plugin-midi/Midi/MidiNoteView.cpp
+++ b/src/plugins/score-plugin-midi/Midi/MidiNoteView.cpp
@@ -19,6 +19,7 @@ NoteView::NoteView(const Note& n, Presenter& p, View* parent)
, m_presenter{p}
, m_action{None}
{
+ this->setToolTip(QObject::tr("A MIDI note."));
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
this->setFlag(QGraphicsItem::ItemIsMovable, true);
this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/CommentBlock/CommentBlockView.cpp b/src/plugins/score-plugin-scenario/Scenario/Document/CommentBlock/CommentBlockView.cpp
index 47cd763f7e..04a6dbd860 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/CommentBlock/CommentBlockView.cpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/CommentBlock/CommentBlockView.cpp
@@ -25,6 +25,7 @@ CommentBlockView::CommentBlockView(
this->setParentItem(parent);
this->setZValue(ZPos::Comment);
this->setAcceptHoverEvents(true);
+ this->setToolTip(tr("Comment box\nPut the text you want in here by double-clicking !"));
m_textItem = new score::TextItem{"", this};
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/Event/ConditionView.cpp b/src/plugins/score-plugin-scenario/Scenario/Document/Event/ConditionView.cpp
index 751ef50c80..9fced64fdf 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/Event/ConditionView.cpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/Event/ConditionView.cpp
@@ -37,6 +37,7 @@ ConditionView::ConditionView(const EventModel& model, QGraphicsItem* parent)
, m_model{model}
{
this->setCacheMode(QGraphicsItem::NoCache);
+ this->setToolTip(tr("Condition\nSet whether the following intervals will execute."));
setFlag(ItemStacksBehindParent, true);
setCursor(Qt::CursorShape::CrossCursor);
setHeight(0.);
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/FullView/AddressBarItem.cpp b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/FullView/AddressBarItem.cpp
index d953f351dd..7fc88c80df 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/FullView/AddressBarItem.cpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/FullView/AddressBarItem.cpp
@@ -26,6 +26,7 @@ AddressBarItem::AddressBarItem(
: QGraphicsItem{parent}
, m_ctx{ctx}
{
+ this->setToolTip(tr("Address bar\nClick here to travel to the specific hierarchy level"));
this->setFlag(QGraphicsItem::ItemHasNoContents, true);
}
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/FullView/TimeSignatureItem.hpp b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/FullView/TimeSignatureItem.hpp
index 80f9a6cd47..42fcaf705b 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/FullView/TimeSignatureItem.hpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/FullView/TimeSignatureItem.hpp
@@ -110,6 +110,7 @@ class TimeSignatureHandle
TimeSignatureHandle(const IntervalModel& itv, QGraphicsItem* parent)
: QGraphicsItem{parent}
{
+ this->setToolTip(QObject::tr("Time signature handle\nDrag to displace, double-click to change the signature."));
setFlag(ItemIsSelectable, true);
}
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/IntervalView.cpp b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/IntervalView.cpp
index 31c190853a..53a7ece06f 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/IntervalView.cpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/IntervalView.cpp
@@ -37,6 +37,7 @@ IntervalView::IntervalView(IntervalPresenter& presenter, QGraphicsItem* parent)
, m_dropTarget{false}
, m_state{}
{
+ this->setToolTip(QObject::tr("Interval\nA span of time which can contain processes."));
setAcceptHoverEvents(true);
setAcceptDrops(true);
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/LayerData.cpp b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/LayerData.cpp
index 6dddc314d2..a87068fc0c 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/LayerData.cpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/LayerData.cpp
@@ -44,6 +44,12 @@ void LayerData::addView(
container->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
container->setY(m_slotY);
auto view = factory.makeLayerView(*m_model, context, container);
+ if(view->toolTip().isEmpty())
+ {
+ auto& p = context.app.interfaces();
+ const auto& desc = p.get(m_model->concreteKey())->descriptor({});
+ view->setToolTip(QString("%1\n%2").arg(desc.prettyName, desc.description));
+ }
double startX = m_model->flags() & Process::ProcessFlags::HandlesLooping
? 0.
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/SlotHeader.cpp b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/SlotHeader.cpp
index 5469377507..c579ab6be9 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/SlotHeader.cpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/SlotHeader.cpp
@@ -34,6 +34,7 @@ SlotHeader::SlotHeader(
, m_width{slotView.view()->boundingRect().width()}
, m_slotIndex{slotIndex}
{
+ this->setToolTip(QObject::tr("Slot header\nDrag the \u2630 symbol to move the slot elsewhere."));
this->setCacheMode(QGraphicsItem::NoCache);
this->setAcceptHoverEvents(true);
this->setFlag(ItemClipsToShape);
@@ -312,6 +313,7 @@ AmovibleSlotFooter::AmovibleSlotFooter(
, m_fullView{
bool(qobject_cast(&m_presenter))}
{
+ this->setToolTip(QObject::tr("Drag me to resize this slot."));
auto& skin = score::Skin::instance();
this->setCursor(skin.CursorScaleV);
}
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/Temporal/Braces/LeftBrace.hpp b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/Temporal/Braces/LeftBrace.hpp
index e0b1d6b03e..790cd11a94 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/Interval/Temporal/Braces/LeftBrace.hpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/Interval/Temporal/Braces/LeftBrace.hpp
@@ -14,6 +14,7 @@ class SCORE_PLUGIN_SCENARIO_EXPORT LeftBraceView final : public IntervalBrace
LeftBraceView(const IntervalView& parentCstr, QGraphicsItem* parent)
: IntervalBrace{parentCstr, parent}
{
+ this->setToolTip(QObject::tr("Interval left brace\nDrag to change the minimal duration of an interval."));
}
~LeftBraceView() override;
@@ -28,6 +29,7 @@ class SCORE_PLUGIN_SCENARIO_EXPORT RightBraceView final : public IntervalBrace
: IntervalBrace{parentCstr, parent}
{
this->setRotation(180);
+ this->setToolTip(QObject::tr("Interval right brace\nDrag to change the maximal duration of an interval."));
}
~RightBraceView() override;
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioDocumentView.cpp b/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioDocumentView.cpp
index 26fad1dd20..c6cf7e24b4 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioDocumentView.cpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioDocumentView.cpp
@@ -424,6 +424,55 @@ void ProcessGraphicsView::dropEvent(QDropEvent* event)
}
}
+bool ProcessGraphicsView::event(QEvent* event)
+{
+ switch (event->type())
+ {
+ case QEvent::HoverEnter:
+ hoverEnterEvent(static_cast(event));
+ return true;
+ case QEvent::HoverLeave:
+ hoverLeaveEvent(static_cast(event));
+ return true;
+ case QEvent::HoverMove:
+ hoverMoveEvent(static_cast(event));
+ return true;
+ default:
+ return QGraphicsView::event(event);
+ }
+}
+
+void ProcessGraphicsView::hoverEnterEvent(QHoverEvent* event)
+{
+
+}
+
+void ProcessGraphicsView::hoverMoveEvent(QHoverEvent* event)
+{
+ const auto scenePos = this->mapToScene(event->pos());
+ auto items = this->scene()->items(scenePos);
+ auto set_tip = [&] (const QString& t) {
+ QStatusTipEvent ev{t};
+ auto obj = reinterpret_cast(this->m_app.mainWindow);
+ obj->event(&ev);
+ };
+ for (int i = 0; i < items.size(); ++i)
+ {
+ if(const auto& tooltip = items.at(i)->toolTip(); !tooltip.isEmpty())
+ {
+ set_tip(tooltip);
+ return;
+ }
+ }
+
+ set_tip(QString{});
+}
+
+void ProcessGraphicsView::hoverLeaveEvent(QHoverEvent* event)
+{
+
+}
+
ScenarioDocumentView::ScenarioDocumentView(
const score::DocumentContext& ctx,
QObject* parent)
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioDocumentView.hpp b/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioDocumentView.hpp
index 1cd92a4353..aea5c40620 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioDocumentView.hpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioDocumentView.hpp
@@ -98,6 +98,12 @@ class SCORE_PLUGIN_SCENARIO_EXPORT ProcessGraphicsView final
void dragMoveEvent(QDragMoveEvent* event) override;
void dragLeaveEvent(QDragLeaveEvent* event) override;
void dropEvent(QDropEvent* event) override;
+ bool event(QEvent*) override;
+
+ void hoverEnterEvent(QHoverEvent* event);
+ void hoverMoveEvent(QHoverEvent* event);
+ void hoverLeaveEvent(QHoverEvent* event);
+
void checkAndRemoveCurrentDialog(QPoint pos);
// void drawBackground(QPainter* painter, const QRectF& rect) override;
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioScene.cpp b/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioScene.cpp
index 9c9f350759..1c0072586a 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioScene.cpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioScene.cpp
@@ -11,4 +11,8 @@ ScenarioScene::ScenarioScene(QObject* parent)
{
setItemIndexMethod(QGraphicsScene::NoIndex);
}
+
+void ScenarioScene::helpEvent(QGraphicsSceneHelpEvent* event)
+{
+}
}
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioScene.hpp b/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioScene.hpp
index 4bcf37cf4b..98a94ef347 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioScene.hpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/ScenarioDocument/ScenarioScene.hpp
@@ -10,5 +10,7 @@ class ScenarioScene final : public QGraphicsScene
W_OBJECT(ScenarioScene)
public:
ScenarioScene(QObject* parent);
+
+ void helpEvent(QGraphicsSceneHelpEvent* event) override;
};
}
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/State/StateMenuOverlay.hpp b/src/plugins/score-plugin-scenario/Scenario/Document/State/StateMenuOverlay.hpp
index cbfcd88409..554105df1d 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/State/StateMenuOverlay.hpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/State/StateMenuOverlay.hpp
@@ -15,7 +15,7 @@ namespace Scenario
class CrossOverlay : public QGraphicsItem
{
public:
- CrossOverlay(StateView* parent)
+ explicit CrossOverlay(StateView* parent)
: QGraphicsItem{parent}
{
this->setFlag(ItemStacksBehindParent, true);
@@ -111,7 +111,11 @@ class CrossOverlay : public QGraphicsItem
class StatePlusOverlay final : public CrossOverlay
{
public:
- using CrossOverlay::CrossOverlay;
+ explicit StatePlusOverlay(StateView* parent)
+ : CrossOverlay{parent}
+ {
+ this->setToolTip(QObject::tr("Create an interval.\nDrag the plus to create an interval"));
+ }
private:
const score::Brush& brush() const noexcept override
@@ -140,7 +144,11 @@ class StatePlusOverlay final : public CrossOverlay
class StateGraphPlusOverlay final : public CrossOverlay
{
public:
- using CrossOverlay::CrossOverlay;
+ explicit StateGraphPlusOverlay(StateView* parent)
+ : CrossOverlay{parent}
+ {
+ this->setToolTip(QObject::tr("Create a graph link.\nDrag the plus to create a graph link"));
+ }
private:
const score::Brush& brush() const noexcept override
@@ -169,7 +177,11 @@ class StateGraphPlusOverlay final : public CrossOverlay
class StateSequencePlusOverlay final : public CrossOverlay
{
public:
- using CrossOverlay::CrossOverlay;
+ explicit StateSequencePlusOverlay(StateView* parent)
+ : CrossOverlay{parent}
+ {
+ this->setToolTip(QObject::tr("Create a sequence.\nDrag the plus to create a sequence."));
+ }
private:
const score::Brush& brush() const noexcept override
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/State/StateView.cpp b/src/plugins/score-plugin-scenario/Scenario/Document/State/StateView.cpp
index 6c3325ef38..235d8f27c0 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/State/StateView.cpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/State/StateView.cpp
@@ -70,6 +70,7 @@ StateView::StateView(StatePresenter& pres, QGraphicsItem* parent)
if (!is_hidpi())
this->setCacheMode(QGraphicsItem::CacheMode::ItemCoordinateCache);
this->setParentItem(parent);
+ this->setToolTip(QStringLiteral("State view"));
auto& skin = score::Skin::instance();
this->setCursor(skin.CursorMove);
diff --git a/src/plugins/score-plugin-scenario/Scenario/Document/TimeSync/TriggerView.cpp b/src/plugins/score-plugin-scenario/Scenario/Document/TimeSync/TriggerView.cpp
index 8affdf9f93..5571c23b77 100644
--- a/src/plugins/score-plugin-scenario/Scenario/Document/TimeSync/TriggerView.cpp
+++ b/src/plugins/score-plugin-scenario/Scenario/Document/TimeSync/TriggerView.cpp
@@ -57,6 +57,7 @@ TriggerView::TriggerView(QGraphicsItem* parent)
, m_waiting{false}
{
auto& skin = score::Skin::instance();
+ this->setToolTip(QObject::tr("Trigger\nUsed to introduce temporal interactions."));
this->setCursor(skin.CursorPointingHand);
this->setCacheMode(QGraphicsItem::NoCache);
this->setAcceptHoverEvents(true);