Skip to content

Commit 4d2b15e

Browse files
committed
Prefs: Add per-field CMRT column toggles with constraint enforcement
1 parent bfe6914 commit 4d2b15e

3 files changed

Lines changed: 216 additions & 2 deletions

File tree

src/preferences/dialog/dlgpreffingerprint.cpp

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <QUrl>
44

5+
#include "library/basetracktablemodel.h"
56
#include "library/library_prefs.h"
67
#include "library/trackcollection.h"
78
#include "library/trackcollectionmanager.h"
@@ -65,11 +66,55 @@ DlgPrefFingerprint::DlgPrefFingerprint(
6566
this,
6667
&DlgPrefFingerprint::slotClearAllFingerprints);
6768

69+
// clicked(bool), not toggled(bool) -- toggled() also fires for the
70+
// programmatic setChecked() calls below in slotUpdate()/slotResetToDefaults(),
71+
// and we only want to validate on an actual user click.
72+
for (QCheckBox* pCheckBox : {checkBoxCmrtColumnShowArtist,
73+
checkBoxCmrtColumnShowTitle,
74+
checkBoxCmrtColumnShowGroupId,
75+
checkBoxCmrtColumnShowOffset,
76+
checkBoxCmrtColumnShowMatchScore}) {
77+
connect(pCheckBox,
78+
&QCheckBox::clicked,
79+
this,
80+
&DlgPrefFingerprint::slotCmrtColumnFieldToggled);
81+
}
82+
6883
slotUpdate();
6984
// No connections needed — the checkbox has no side effects on other
7085
// widgets. slotApply() reads its state directly.
7186
}
7287

88+
void DlgPrefFingerprint::slotCmrtColumnFieldToggled() {
89+
const QList<QCheckBox*> fieldCheckBoxes = {
90+
checkBoxCmrtColumnShowArtist,
91+
checkBoxCmrtColumnShowTitle,
92+
checkBoxCmrtColumnShowGroupId,
93+
checkBoxCmrtColumnShowOffset,
94+
checkBoxCmrtColumnShowMatchScore};
95+
96+
// Constraint 1: at least one field must stay checked. If the user's
97+
// click just unchecked the last one, undo it -- QSignalBlocker
98+
// prevents this programmatic setChecked() from re-entering this slot.
99+
const bool anyChecked = std::any_of(fieldCheckBoxes.begin(),
100+
fieldCheckBoxes.end(),
101+
[](QCheckBox* pCheckBox) { return pCheckBox->isChecked(); });
102+
if (!anyChecked) {
103+
// sender() is whichever checkbox the user just clicked -- it's
104+
// the one that needs to be reverted back to checked.
105+
auto* pClicked = qobject_cast<QCheckBox*>(sender());
106+
if (pClicked) {
107+
const QSignalBlocker blocker(pClicked);
108+
pClicked->setChecked(true);
109+
}
110+
}
111+
112+
// Constraint 2: Append/Prepend only matters when a name is shown.
113+
const bool nameShown = checkBoxCmrtColumnShowArtist->isChecked() ||
114+
checkBoxCmrtColumnShowTitle->isChecked();
115+
checkBoxCmrtColumnGroupIdAppend->setEnabled(nameShown);
116+
}
117+
73118
void DlgPrefFingerprint::slotUpdate() {
74119
const bool fingerprintEnabled = m_pConfig->getValue(
75120
kFingerprintAnalysisEnabledConfigKey, false);
@@ -88,6 +133,44 @@ void DlgPrefFingerprint::slotUpdate() {
88133
// Stored as a 0.0-1.0 fraction; the spin box shows it as a percentage.
89134
spinBoxCmrtMatchThreshold->setValue(matchThreshold * 100.0);
90135

136+
const bool showArtist = m_pConfig->getValue(
137+
kCmrtColumnShowArtistConfigKey, BaseTrackTableModel::kCmrtColumnShowArtistDefault);
138+
checkBoxCmrtColumnShowArtist->setChecked(showArtist);
139+
BaseTrackTableModel::setCmrtColumnShowArtist(showArtist);
140+
141+
const bool showTitle = m_pConfig->getValue(
142+
kCmrtColumnShowTitleConfigKey, BaseTrackTableModel::kCmrtColumnShowTitleDefault);
143+
checkBoxCmrtColumnShowTitle->setChecked(showTitle);
144+
BaseTrackTableModel::setCmrtColumnShowTitle(showTitle);
145+
146+
const bool showGroupId = m_pConfig->getValue(
147+
kCmrtColumnShowGroupIdConfigKey, BaseTrackTableModel::kCmrtColumnShowGroupIdDefault);
148+
checkBoxCmrtColumnShowGroupId->setChecked(showGroupId);
149+
BaseTrackTableModel::setCmrtColumnShowGroupId(showGroupId);
150+
151+
const bool showOffset = m_pConfig->getValue(
152+
kCmrtColumnShowOffsetConfigKey, BaseTrackTableModel::kCmrtColumnShowOffsetDefault);
153+
checkBoxCmrtColumnShowOffset->setChecked(showOffset);
154+
BaseTrackTableModel::setCmrtColumnShowOffset(showOffset);
155+
156+
const bool showMatchScore = m_pConfig->getValue(
157+
kCmrtColumnShowMatchScoreConfigKey,
158+
BaseTrackTableModel::kCmrtColumnShowMatchScoreDefault);
159+
checkBoxCmrtColumnShowMatchScore->setChecked(showMatchScore);
160+
BaseTrackTableModel::setCmrtColumnShowMatchScore(showMatchScore);
161+
162+
const bool groupIdAppend = m_pConfig->getValue(
163+
kCmrtColumnGroupIdPositionConfigKey,
164+
BaseTrackTableModel::kCmrtColumnGroupIdAppendDefault);
165+
checkBoxCmrtColumnGroupIdAppend->setChecked(groupIdAppend);
166+
checkBoxCmrtColumnGroupIdAppend->setEnabled(showArtist || showTitle);
167+
BaseTrackTableModel::setCmrtColumnGroupIdAppend(groupIdAppend);
168+
169+
const QString delimiter = m_pConfig->getValue(
170+
kCmrtColumnDelimiterConfigKey, BaseTrackTableModel::kCmrtColumnDelimiterDefault);
171+
lineEditCmrtColumnDelimiter->setText(delimiter);
172+
BaseTrackTableModel::setCmrtColumnDelimiter(delimiter);
173+
91174
setAcoustIdGroupEnabled(fingerprintEnabled);
92175
}
93176

@@ -110,13 +193,60 @@ void DlgPrefFingerprint::slotApply() {
110193
m_pConfig->set(
111194
kCmrtMatchThresholdConfigKey,
112195
ConfigValue{spinBoxCmrtMatchThreshold->value() / 100.0});
196+
197+
const bool showArtist = checkBoxCmrtColumnShowArtist->isChecked();
198+
m_pConfig->set(kCmrtColumnShowArtistConfigKey, ConfigValue{showArtist});
199+
BaseTrackTableModel::setCmrtColumnShowArtist(showArtist);
200+
201+
const bool showTitle = checkBoxCmrtColumnShowTitle->isChecked();
202+
m_pConfig->set(kCmrtColumnShowTitleConfigKey, ConfigValue{showTitle});
203+
BaseTrackTableModel::setCmrtColumnShowTitle(showTitle);
204+
205+
const bool showGroupId = checkBoxCmrtColumnShowGroupId->isChecked();
206+
m_pConfig->set(kCmrtColumnShowGroupIdConfigKey, ConfigValue{showGroupId});
207+
BaseTrackTableModel::setCmrtColumnShowGroupId(showGroupId);
208+
209+
const bool showOffset = checkBoxCmrtColumnShowOffset->isChecked();
210+
m_pConfig->set(kCmrtColumnShowOffsetConfigKey, ConfigValue{showOffset});
211+
BaseTrackTableModel::setCmrtColumnShowOffset(showOffset);
212+
213+
const bool showMatchScore = checkBoxCmrtColumnShowMatchScore->isChecked();
214+
m_pConfig->set(kCmrtColumnShowMatchScoreConfigKey, ConfigValue{showMatchScore});
215+
BaseTrackTableModel::setCmrtColumnShowMatchScore(showMatchScore);
216+
217+
const bool groupIdAppend = checkBoxCmrtColumnGroupIdAppend->isChecked();
218+
m_pConfig->set(kCmrtColumnGroupIdPositionConfigKey, ConfigValue{groupIdAppend});
219+
BaseTrackTableModel::setCmrtColumnGroupIdAppend(groupIdAppend);
220+
221+
const QString delimiter = lineEditCmrtColumnDelimiter->text();
222+
m_pConfig->set(kCmrtColumnDelimiterConfigKey, ConfigValue{delimiter});
223+
BaseTrackTableModel::setCmrtColumnDelimiter(delimiter);
113224
}
114225

115226
void DlgPrefFingerprint::slotResetToDefaults() {
116227
checkBoxFingerprintEnabled->setChecked(false);
117228
lineEditAcoustIdApiKey->clear();
118229
checkBoxAcoustIdAutoSubmit->setChecked(false);
119230
spinBoxCmrtMatchThreshold->setValue(kCmrtMatchThresholdDefault * 100.0);
231+
232+
checkBoxCmrtColumnShowArtist->setChecked(BaseTrackTableModel::kCmrtColumnShowArtistDefault);
233+
checkBoxCmrtColumnShowTitle->setChecked(BaseTrackTableModel::kCmrtColumnShowTitleDefault);
234+
checkBoxCmrtColumnShowGroupId->setChecked(BaseTrackTableModel::kCmrtColumnShowGroupIdDefault);
235+
checkBoxCmrtColumnShowOffset->setChecked(BaseTrackTableModel::kCmrtColumnShowOffsetDefault);
236+
checkBoxCmrtColumnShowMatchScore->setChecked(
237+
BaseTrackTableModel::kCmrtColumnShowMatchScoreDefault);
238+
239+
checkBoxCmrtColumnGroupIdAppend->setChecked(
240+
BaseTrackTableModel::kCmrtColumnGroupIdAppendDefault);
241+
242+
lineEditCmrtColumnDelimiter->setText(BaseTrackTableModel::kCmrtColumnDelimiterDefault);
243+
244+
// Re-run constraint checks once so the UI reflects the correct state
245+
// Defaults are Artist=on, Title=on, so Append/Prepend ends up enabled after a reset.
246+
checkBoxCmrtColumnGroupIdAppend->setEnabled(
247+
checkBoxCmrtColumnShowArtist->isChecked() ||
248+
checkBoxCmrtColumnShowTitle->isChecked());
249+
120250
// Reflect the cleared state immediately in the UI.
121251
setAcoustIdGroupEnabled(false);
122252
}

src/preferences/dialog/dlgpreffingerprint.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class DlgPrefFingerprint : public DlgPreferencePage, public Ui::DlgPrefFingerpri
2525
void slotFingerprintEnabledToggled(bool enabled);
2626
void slotClearAllFingerprints();
2727

28+
void slotCmrtColumnFieldToggled();
29+
2830
private:
2931
// Applies the enabled/disabled state to the AcoustID group and, within it,
3032
// the auto-submit checkbox (which additionally requires a non-empty key).

src/preferences/dialog/dlgpreffingerprint.ui

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<x>0</x>
88
<y>0</y>
99
<width>576</width>
10-
<height>400</height>
10+
<height>550</height>
1111
</rect>
1212
</property>
1313
<property name="windowTitle">
@@ -138,6 +138,88 @@
138138
</item>
139139

140140
<item row="3" column="0" colspan="2">
141+
<widget class="QGroupBox" name="groupBoxCmrtColumn">
142+
<property name="title">
143+
<string>CMRT Library Column</string>
144+
</property>
145+
<property name="toolTip">
146+
<string>At least one field must remain shown.</string>
147+
</property>
148+
<layout class="QVBoxLayout" name="verticalLayoutCmrtColumn">
149+
<item>
150+
<widget class="QCheckBox" name="checkBoxCmrtColumnShowArtist">
151+
<property name="text">
152+
<string>Show artist</string>
153+
</property>
154+
</widget>
155+
</item>
156+
<item>
157+
<widget class="QCheckBox" name="checkBoxCmrtColumnShowTitle">
158+
<property name="text">
159+
<string>Show title</string>
160+
</property>
161+
</widget>
162+
</item>
163+
<item>
164+
<widget class="QCheckBox" name="checkBoxCmrtColumnShowGroupId">
165+
<property name="text">
166+
<string>Show group ID</string>
167+
</property>
168+
</widget>
169+
</item>
170+
<item>
171+
<widget class="QCheckBox" name="checkBoxCmrtColumnShowOffset">
172+
<property name="text">
173+
<string>Show offset (non-canonical tracks)</string>
174+
</property>
175+
</widget>
176+
</item>
177+
<item>
178+
<widget class="QCheckBox" name="checkBoxCmrtColumnShowMatchScore">
179+
<property name="text">
180+
<string>Show match % (non-canonical tracks)</string>
181+
</property>
182+
</widget>
183+
</item>
184+
<item>
185+
<widget class="QCheckBox" name="checkBoxCmrtColumnGroupIdAppend">
186+
<property name="text">
187+
<string>Append group ID after name (uncheck to prepend)</string>
188+
</property>
189+
</widget>
190+
</item>
191+
<item>
192+
<layout class="QHBoxLayout" name="horizontalLayoutCmrtDelimiter">
193+
<item>
194+
<widget class="QLabel" name="labelCmrtColumnDelimiter">
195+
<property name="text">
196+
<string>Delimiter:</string>
197+
</property>
198+
</widget>
199+
</item>
200+
<item>
201+
<widget class="QLineEdit" name="lineEditCmrtColumnDelimiter"/>
202+
</item>
203+
<item>
204+
<spacer name="horizontalSpacerCmrtDelimiter">
205+
<property name="orientation">
206+
<enum>Qt::Horizontal</enum>
207+
</property>
208+
<property name="sizeHint" stdset="0">
209+
<size>
210+
<width>40</width>
211+
<height>20</height>
212+
</size>
213+
</property>
214+
</spacer>
215+
</item>
216+
</layout>
217+
</item>
218+
</layout>
219+
</widget>
220+
</item>
221+
222+
<item row="4" column="0" colspan="2">
141223
<widget class="QGroupBox" name="groupBoxClearFingerprints">
142224
<property name="title">
143225
<string>Library-wide Fingerprint Cleanup</string>
@@ -167,7 +249,7 @@
167249
</widget>
168250
</item>
169251

170-
<item row="4" column="0">
252+
<item row="5" column="0">
171253
<spacer name="verticalSpacer">
172254
<property name="orientation">
173255
<enum>Qt::Vertical</enum>

0 commit comments

Comments
 (0)