From e99aa082ad8b93a793dde509a0f914a86cd3ace0 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Sun, 26 Oct 2025 22:24:09 +0100 Subject: [PATCH 1/3] Track comment: show only first line in WTrackPropertyEditor --- src/widget/wtrackproperty.cpp | 48 ++++++++++++++++++++++++++++++----- src/widget/wtrackproperty.h | 1 + 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/widget/wtrackproperty.cpp b/src/widget/wtrackproperty.cpp index ca1f0d03ec3f..c3fcf4d08f74 100644 --- a/src/widget/wtrackproperty.cpp +++ b/src/widget/wtrackproperty.cpp @@ -29,6 +29,7 @@ WTrackProperty::WTrackProperty( m_pConfig(pConfig), m_pLibrary(pLibrary), m_isMainDeck(isMainDeck), + m_isComment(false), m_propertyIsWritable(false), m_pSelectedClickTimer(nullptr), m_bSelected(false), @@ -65,6 +66,9 @@ void WTrackProperty::setup(const QDomNode& node, const SkinContext& context) { return; } m_editProperty = m_displayProperty; + if (m_editProperty == QStringLiteral("comment")) { + m_isComment = true; + } } m_propertyIsWritable = true; } @@ -97,6 +101,10 @@ void WTrackProperty::slotLoadingTrack(TrackPointer pNewTrack, TrackPointer pOldT void WTrackProperty::slotTrackChanged(TrackId trackId) { Q_UNUSED(trackId); updateLabel(); + if (m_pEditor && m_pEditor->isVisible()) { + // Close and discard new text + m_pEditor->hide(); + } } void WTrackProperty::updateLabel() { @@ -165,6 +173,14 @@ void WTrackProperty::mousePressEvent(QMouseEvent* pEvent) { QString editText = getPropertyStringFromTrack(m_editProperty); if (m_displayProperty == "titleInfo" && editText.isEmpty()) { editText = tr("title"); + } else if (m_isComment) { + // For comments we only load the first line, + // ie. truncate track text at first linebreak. + // On commit we replace the first line with the edited text. + int firstLB = editText.indexOf('\n'); + if (firstLB >= 0) { + editText.truncate(firstLB); + } } m_pEditor->setText(editText); m_pEditor->selectAll(); @@ -309,14 +325,34 @@ void WTrackProperty::slotShowTrackMenuChangeRequest(bool show) { } void WTrackProperty::slotCommitEditorData(const QString& text) { + if (!m_pCurrentTrack) { + return; + } + // use real track data instead of text() to be independent from display text - if (m_pCurrentTrack && text != getPropertyStringFromTrack(m_editProperty)) { - const QVariant var(QVariant::fromValue(text)); - m_pCurrentTrack->setProperty( - m_editProperty.toUtf8().constData(), - var); - // Track::changed() will update label + const QString trackText = getPropertyStringFromTrack(m_editProperty); + QString editorText = text; + if (m_isComment) { + // For multi-line comments, the editor received only the first line. + // In order to keep the other lines, we need to replace + // the first line of the original text with the editor text. + // (which may add new linebreaks) + // Note: assumes the comment didn't change while we were editing it. + int firstLB = trackText.indexOf('\n'); + if (firstLB >= 0) { // has linebreak + QString trackTSliced = trackText; + trackTSliced = trackTSliced.sliced(firstLB); + editorText.append(trackTSliced); + } + } + if (editorText == trackText) { + return; } + const QVariant var(QVariant::fromValue(editorText)); + m_pCurrentTrack->setProperty( + m_editProperty.toUtf8().constData(), + var); + // Track::changed() will update label } void WTrackProperty::resetSelectedState() { diff --git a/src/widget/wtrackproperty.h b/src/widget/wtrackproperty.h index 0e97f5efe98b..7e85e8c14b4f 100644 --- a/src/widget/wtrackproperty.h +++ b/src/widget/wtrackproperty.h @@ -93,6 +93,7 @@ class WTrackProperty : public WLabel, public TrackDropTarget { const UserSettingsPointer m_pConfig; Library* m_pLibrary; const bool m_isMainDeck; + bool m_isComment; TrackPointer m_pCurrentTrack; QString m_displayProperty; From 7af755874ea40758c58eba82bb49366843b38ab6 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Sun, 26 Oct 2025 22:25:38 +0100 Subject: [PATCH 2/3] Track comment: add linebreak with \n in WTrackPropertyEditor --- src/widget/wtrackproperty.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/widget/wtrackproperty.cpp b/src/widget/wtrackproperty.cpp index c3fcf4d08f74..c3c3c36fd51c 100644 --- a/src/widget/wtrackproperty.cpp +++ b/src/widget/wtrackproperty.cpp @@ -333,6 +333,11 @@ void WTrackProperty::slotCommitEditorData(const QString& text) { const QString trackText = getPropertyStringFromTrack(m_editProperty); QString editorText = text; if (m_isComment) { + // Transform ALL occurrences of \n into linebreaks. + // Existing linebreaks are not affected. + QString cr(QChar::CarriageReturn); + cr.append(QChar::LineFeed); + editorText.replace("\\n", cr); // For multi-line comments, the editor received only the first line. // In order to keep the other lines, we need to replace // the first line of the original text with the editor text. From fbf55e0f509b687a1846be454eb289c4054bb6d1 Mon Sep 17 00:00:00 2001 From: ronso0 Date: Sun, 26 Oct 2025 23:03:53 +0100 Subject: [PATCH 3/3] Track comment: add shortcut to edit deck label, Alt + deckNum --- src/skin/legacy/legacyskinparser.cpp | 6 +- src/widget/wtrackproperty.cpp | 88 ++++++++++++++++++---------- src/widget/wtrackproperty.h | 7 ++- 3 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/skin/legacy/legacyskinparser.cpp b/src/skin/legacy/legacyskinparser.cpp index 8ac490ecdb3a..85acbb087387 100644 --- a/src/skin/legacy/legacyskinparser.cpp +++ b/src/skin/legacy/legacyskinparser.cpp @@ -1176,13 +1176,15 @@ QWidget* LegacySkinParser::parseTrackProperty(const QDomElement& node) { return nullptr; } - bool isMainDeck = PlayerManager::isDeckGroup(group); + int mainDeckNum = 0; + bool isMainDeck = PlayerManager::isDeckGroup(group, &mainDeckNum); WTrackProperty* pTrackProperty = new WTrackProperty( m_pParent, m_pConfig, m_pLibrary, group, - isMainDeck); + isMainDeck, + mainDeckNum); setupLabelWidget(node, pTrackProperty); // Ensure 'show_track_menu' control is created for each main deck and diff --git a/src/widget/wtrackproperty.cpp b/src/widget/wtrackproperty.cpp index c3c3c36fd51c..d517b9eb0943 100644 --- a/src/widget/wtrackproperty.cpp +++ b/src/widget/wtrackproperty.cpp @@ -23,13 +23,15 @@ WTrackProperty::WTrackProperty( UserSettingsPointer pConfig, Library* pLibrary, const QString& group, - bool isMainDeck) + bool isMainDeck, + int deckNum) : WLabel(pParent), m_group(group), m_pConfig(pConfig), m_pLibrary(pLibrary), m_isMainDeck(isMainDeck), m_isComment(false), + m_mainDeckNum(deckNum), m_propertyIsWritable(false), m_pSelectedClickTimer(nullptr), m_bSelected(false), @@ -70,6 +72,31 @@ void WTrackProperty::setup(const QDomNode& node, const SkinContext& context) { m_isComment = true; } } + + // Create a QAction with a hotkey which allows us to open the editor without + // having to use the mouse + if (m_isComment && m_isMainDeck && m_mainDeckNum > 0) { + parented_ptr pEditCommentAction = make_parented("edit comment", this); + pEditCommentAction->setShortcut(QKeySequence(tr("Alt+%1").arg(m_mainDeckNum))); + connect(pEditCommentAction.get(), + &QAction::triggered, + this, + [this]() { + // Assumes only one comment label is visible. + // If there are more, Qt _should_ trigger the first QAction + // in the internal list and throw a warning for the others + // "QAction::event: Ambiguous shortcut overload: [shortcut]" + // Anyways, as soon as one editor is opened (gets focus), + // others will receive a focusOut event and close. + if (isVisible() && + (!m_pEditor || (m_pEditor && !m_pEditor->isVisible()))) { + // Note: if the editor is already visible, this would + // reload/reset the comment from the track + openEditor(); + } + }); + addAction(pEditCommentAction); + } m_propertyIsWritable = true; } @@ -157,36 +184,7 @@ void WTrackProperty::mousePressEvent(QMouseEvent* pEvent) { this, &WTrackProperty::resetSelectedState); } else if (m_pSelectedClickTimer->isActive()) { resetSelectedState(); - // create the persistent editor, populate & connect - if (!m_pEditor) { - m_pEditor = make_parented(this); - connect(m_pEditor, - // use custom signal. editingFinished() doesn't suit since it's - // also emitted weh pressing Esc (which should cancel editing) - &WTrackPropertyEditor::commitEditorData, - this, - &WTrackProperty::slotCommitEditorData); - } - // Don't let the editor expand beyond its initial size - m_pEditor->setFixedSize(size()); - - QString editText = getPropertyStringFromTrack(m_editProperty); - if (m_displayProperty == "titleInfo" && editText.isEmpty()) { - editText = tr("title"); - } else if (m_isComment) { - // For comments we only load the first line, - // ie. truncate track text at first linebreak. - // On commit we replace the first line with the edited text. - int firstLB = editText.indexOf('\n'); - if (firstLB >= 0) { - editText.truncate(firstLB); - } - } - m_pEditor->setText(editText); - m_pEditor->selectAll(); - m_pEditor->show(); - m_pEditor->setFocus(); - return; + openEditor(); } // start timer m_pSelectedClickTimer->start(); @@ -324,6 +322,34 @@ void WTrackProperty::slotShowTrackMenuChangeRequest(bool show) { contextMenuEvent(pEvent); } +void WTrackProperty::openEditor() { + resetSelectedState(); + if (!m_pCurrentTrack) { + return; + } + // create the persistent editor, populate & connect + if (!m_pEditor) { + m_pEditor = make_parented(this); + connect(m_pEditor, + // use custom signal. editingFinished() doesn't suit since it's + // also emitted weh pressing Esc (which should cancel editing) + &WTrackPropertyEditor::commitEditorData, + this, + &WTrackProperty::slotCommitEditorData); + } + // Don't let the editor expand beyond its initial size + m_pEditor->setFixedSize(size()); + + QString editText = getPropertyStringFromTrack(m_editProperty); + if (m_displayProperty == "titleInfo" && editText.isEmpty()) { + editText = tr("title"); + } + m_pEditor->setText(editText); + m_pEditor->selectAll(); + m_pEditor->show(); + m_pEditor->setFocus(); +} + void WTrackProperty::slotCommitEditorData(const QString& text) { if (!m_pCurrentTrack) { return; diff --git a/src/widget/wtrackproperty.h b/src/widget/wtrackproperty.h index 7e85e8c14b4f..9fce54a37427 100644 --- a/src/widget/wtrackproperty.h +++ b/src/widget/wtrackproperty.h @@ -42,7 +42,8 @@ class WTrackProperty : public WLabel, public TrackDropTarget { UserSettingsPointer pConfig, Library* pLibrary, const QString& group, - bool isMainDeck); + bool isMainDeck, + int mainDeckNum); ~WTrackProperty() override; // Custom property to allow skins to style the 'selected' state when the // widget awaits a second click to open the editor. It's reset automatically @@ -89,11 +90,15 @@ class WTrackProperty : public WLabel, public TrackDropTarget { void restyleAndRepaint(); void ensureTrackMenuIsCreated(); + void openEditor(); + const QString m_group; const UserSettingsPointer m_pConfig; Library* m_pLibrary; const bool m_isMainDeck; bool m_isComment; + int m_mainDeckNum; + TrackPointer m_pCurrentTrack; QString m_displayProperty;