Skip to content

Commit 2140537

Browse files
committed
feat(library): Add custom date format with live preview
- Replaced DateFormat enum with QString to support custom formats. - Leveraged QLocale for 'Native' (System Default) date formatting. - Updated Library Preferences with an editable combobox and live Preview label. - Added presets for ISO 8601 and Regional formats. - Added unit tests for date formatting logic.
1 parent 811257a commit 2140537

7 files changed

Lines changed: 105 additions & 69 deletions

File tree

src/library/basetracktablemodel.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,10 @@ void BaseTrackTableModel::setApplyPlayedTrackColor(bool apply) {
115115
s_bApplyPlayedTrackColor = apply;
116116
}
117117

118-
mixxx::DateFormat BaseTrackTableModel::s_dateFormat =
119-
BaseTrackTableModel::kDateFormatDefault;
118+
const QString BaseTrackTableModel::kDateFormatDefault = QString();
119+
QString BaseTrackTableModel::s_dateFormat = BaseTrackTableModel::kDateFormatDefault;
120120

121-
void BaseTrackTableModel::setDateFormat(mixxx::DateFormat format) {
121+
void BaseTrackTableModel::setDateFormat(const QString& format) {
122122
s_dateFormat = format;
123123
}
124124

src/library/basetracktablemodel.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ class BaseTrackTableModel : public QAbstractTableModel, public TrackModel {
133133
static constexpr bool kApplyPlayedTrackColorDefault = true;
134134
static void setApplyPlayedTrackColor(bool apply);
135135

136-
static constexpr mixxx::DateFormat kDateFormatDefault = mixxx::DateFormat::Native;
137-
static void setDateFormat(mixxx::DateFormat format);
136+
static const QString kDateFormatDefault;
137+
static void setDateFormat(const QString& format);
138138

139139
protected:
140140
// Build a map from the column names to their indices
@@ -311,5 +311,5 @@ class BaseTrackTableModel : public QAbstractTableModel, public TrackModel {
311311
static std::optional<ColorPalette> s_keyColorPalette;
312312

313313
static bool s_bApplyPlayedTrackColor;
314-
static mixxx::DateFormat s_dateFormat;
314+
static QString s_dateFormat;
315315
};

src/preferences/dialog/dlgpreflibrary.cpp

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,19 @@ DlgPrefLibrary::DlgPrefLibrary(
111111

112112
updateSearchLineEditHistoryOptions();
113113

114-
comboBox_dateFormat->addItem(tr("Native (System Default)"),
115-
static_cast<int>(mixxx::DateFormat::Native));
116-
comboBox_dateFormat->addItem(tr("YYYY-MM-DD"),
117-
static_cast<int>(mixxx::DateFormat::ISO8601));
118-
comboBox_dateFormat->addItem(tr("DD/MM/YYYY"),
119-
static_cast<int>(mixxx::DateFormat::DayMonthYear));
120-
comboBox_dateFormat->addItem(tr("MM/DD/YYYY"),
121-
static_cast<int>(mixxx::DateFormat::MonthDayYear));
122-
comboBox_dateFormat->addItem(tr("YYYY/MM/DD"),
123-
static_cast<int>(mixxx::DateFormat::YearMonthDay));
114+
comboBox_dateFormat->setEditable(true);
115+
// Use empty string data for Native to invoke QLocale default
116+
comboBox_dateFormat->addItem(tr("Native (System Default)"), QString());
117+
comboBox_dateFormat->addItem(tr("ISO 8601 (yyyy-MM-dd)"), QStringLiteral("yyyy-MM-dd"));
118+
comboBox_dateFormat->addItem(tr("Regional Short (d/M/yy)"), QStringLiteral("d/M/yy"));
119+
comboBox_dateFormat->addItem(tr("Regional Long (dd.MM.yyyy)"), QStringLiteral("dd.MM.yyyy"));
120+
// Custom option is handled by the edit behavior
121+
122+
// Update preview initially
123+
slotDateFormatChanged(comboBox_dateFormat->currentText());
124+
124125
connect(comboBox_dateFormat,
125-
QOverload<int>::of(&QComboBox::currentIndexChanged),
126+
&QComboBox::currentTextChanged,
126127
this,
127128
&DlgPrefLibrary::slotDateFormatChanged);
128129

@@ -283,10 +284,13 @@ void DlgPrefLibrary::slotResetToDefaults() {
283284
comboBox_search_bpm_fuzzy_range->setCurrentIndex(
284285
comboBox_search_bpm_fuzzy_range->findData(kDefaultFuzzyRateRangePercent));
285286

286-
int defaultDateFormat = static_cast<int>(BaseTrackTableModel::kDateFormatDefault);
287-
int dateIndex = comboBox_dateFormat->findData(defaultDateFormat);
287+
int dateIndex = comboBox_dateFormat->findData(BaseTrackTableModel::kDateFormatDefault);
288288
if (dateIndex != -1) {
289289
comboBox_dateFormat->setCurrentIndex(dateIndex);
290+
} else {
291+
// Fallback or custom default? Default is usually Native (empty string)
292+
// which should be found.
293+
comboBox_dateFormat->setCurrentIndex(0);
290294
}
291295

292296
checkBox_show_rhythmbox->setChecked(true);
@@ -331,15 +335,18 @@ void DlgPrefLibrary::slotUpdate() {
331335
checkBox_show_serato->setChecked(m_pConfig->getValue(
332336
ConfigKey("[Library]", "ShowSeratoLibrary"), true));
333337

334-
int dateFormat = m_pConfig->getValue(
338+
QString dateFormat = m_pConfig->getValue(
335339
kDateFormatConfigKey,
336-
static_cast<int>(BaseTrackTableModel::kDateFormatDefault));
340+
BaseTrackTableModel::kDateFormatDefault);
337341
int dateIndex = comboBox_dateFormat->findData(dateFormat);
338342
if (dateIndex != -1) {
339343
comboBox_dateFormat->setCurrentIndex(dateIndex);
344+
} else {
345+
// Custom format string
346+
comboBox_dateFormat->setCurrentText(dateFormat);
340347
}
341348
// Ensure the static member is updated on startup/load
342-
BaseTrackTableModel::setDateFormat(static_cast<mixxx::DateFormat>(dateFormat));
349+
BaseTrackTableModel::setDateFormat(dateFormat);
343350

344351
switch (m_pConfig->getValue<int>(
345352
kTrackDoubleClickActionConfigKey,
@@ -747,9 +754,25 @@ void DlgPrefLibrary::setSeratoMetadataEnabled(bool shouldSyncTrackMetadata) {
747754
}
748755
}
749756

750-
void DlgPrefLibrary::slotDateFormatChanged(int index) {
751-
int formatInt = comboBox_dateFormat->itemData(index).toInt();
752-
mixxx::DateFormat format = static_cast<mixxx::DateFormat>(formatInt);
753-
m_pConfig->setValue(kDateFormatConfigKey, formatInt);
757+
void DlgPrefLibrary::slotDateFormatChanged(const QString& text) {
758+
QString format = text;
759+
// Check if the text matches a predefined item (like "Native (...)")
760+
int index = comboBox_dateFormat->findText(text);
761+
if (index != -1) {
762+
// Use the underlying data (e.g. empty string for Native, or "yyyy-MM-dd" for ISO)
763+
format = comboBox_dateFormat->itemData(index).toString();
764+
}
765+
766+
// Update Preview
767+
QDate exampleDate = QDate::currentDate();
768+
QString previewStr;
769+
if (format.isEmpty()) {
770+
previewStr = QLocale().toString(exampleDate, QLocale::ShortFormat);
771+
} else {
772+
previewStr = exampleDate.toString(format);
773+
}
774+
label_dateFormatPreview->setText(previewStr);
775+
776+
m_pConfig->setValue(kDateFormatConfigKey, format);
754777
BaseTrackTableModel::setDateFormat(format);
755778
}

src/preferences/dialog/dlgpreflibrary.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class DlgPrefLibrary : public DlgPreferencePage, public Ui::DlgPrefLibraryDlg {
6767
void slotBpmRangeSelected(int index);
6868
void slotBpmColumnPrecisionChanged(int bpmPrecision);
6969
void slotSeratoMetadataExportClicked(bool);
70-
void slotDateFormatChanged(int index);
70+
void slotDateFormatChanged(const QString& text);
7171

7272
private:
7373
void populateDirList();

src/preferences/dialog/dlgpreflibrarydlg.ui

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,9 +308,16 @@
308308
</property>
309309
</widget>
310310
</item>
311-
<item row="11" column="1" colspan="2">
311+
<item row="11" column="1">
312312
<widget class="QComboBox" name="comboBox_dateFormat"/>
313313
</item>
314+
<item row="11" column="2">
315+
<widget class="QLabel" name="label_dateFormatPreview">
316+
<property name="text">
317+
<string>Preview</string>
318+
</property>
319+
</widget>
320+
</item>
314321

315322
</layout>
316323
</widget>

src/test/datetime_test.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "util/datetime.h"
2+
3+
#include <gtest/gtest.h>
4+
5+
#include <QDate>
6+
#include <QLocale>
7+
8+
namespace mixxx {
9+
10+
TEST(DateTimeTest, FormatDate) {
11+
QDate date(2023, 10, 25);
12+
13+
// Test ISO
14+
EXPECT_EQ(formatDate(date, "yyyy-MM-dd"), "2023-10-25");
15+
16+
// Test Custom
17+
EXPECT_EQ(formatDate(date, "dd.MM.yy"), "25.10.23");
18+
19+
// Test Native (empty string)
20+
// Should fallback to QLocale::ShortFormat
21+
QString native = QLocale().toString(date, QLocale::ShortFormat);
22+
EXPECT_EQ(formatDate(date, ""), native);
23+
}
24+
25+
TEST(DateTimeTest, FormatDateTime) {
26+
QDateTime dt(QDate(2023, 10, 25), QTime(14, 30, 0));
27+
28+
// Test Custom
29+
EXPECT_EQ(formatDateTime(dt, "yyyy-MM-dd HH:mm"), "2023-10-25 14:30");
30+
31+
// Test Native (empty string)
32+
QString native = QLocale().toString(dt, QLocale::ShortFormat);
33+
EXPECT_EQ(formatDateTime(dt, ""), native);
34+
}
35+
36+
} // namespace mixxx

src/util/datetime.h

Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,6 @@
88

99
namespace mixxx {
1010

11-
/// Date format options for library display
12-
enum class DateFormat {
13-
Native = 0, ///< System locale default (e.g. 5/20/1998)
14-
ISO8601 = 1, ///< YYYY-MM-DD
15-
DayMonthYear = 2, ///< DD/MM/YYYY
16-
MonthDayYear = 3, ///< MM/DD/YYYY
17-
YearMonthDay = 4, ///< YYYY/MM/DD
18-
};
19-
2011
/// Common utility functions for safely converting and consistently
2112
/// displaying date time values.
2213

@@ -37,59 +28,38 @@ inline QDateTime convertVariantToDateTime(
3728
return data.toDateTime();
3829
}
3930

40-
/// Helper to format a QDate according to DateFormat
31+
/// Helper to format a QDate according to a format string.
32+
/// If format is empty, uses the system's default locale short format.
4133
inline QString formatDate(
4234
const QDate& date,
43-
DateFormat format) {
35+
const QString& format = QString()) {
4436
if (!date.isValid()) {
4537
return QString();
4638
}
47-
switch (format) {
48-
case DateFormat::ISO8601:
49-
return date.toString(Qt::ISODate);
50-
case DateFormat::DayMonthYear:
51-
return date.toString(QStringLiteral("dd/MM/yyyy"));
52-
case DateFormat::MonthDayYear:
53-
// Use standard US format MM/DD/YYYY
54-
return date.toString(QStringLiteral("MM/dd/yyyy"));
55-
case DateFormat::YearMonthDay:
56-
return date.toString(QStringLiteral("yyyy/MM/dd"));
57-
case DateFormat::Native:
58-
default:
39+
if (format.isEmpty()) {
5940
return QLocale().toString(date, QLocale::ShortFormat);
6041
}
42+
return date.toString(format);
6143
}
6244

63-
/// Helper to format a QDateTime according to DateFormat
45+
/// Helper to format a QDateTime according to a format string.
46+
/// If format is empty, uses the system's default locale short format.
6447
inline QString formatDateTime(
6548
const QDateTime& dt,
66-
DateFormat format) {
49+
const QString& format = QString()) {
6750
if (!dt.isValid()) {
6851
return QString();
6952
}
70-
switch (format) {
71-
case DateFormat::ISO8601:
72-
// Qt::ISODate includes 'T' and can include time zone, but usually we
73-
// just want YYYY-MM-DD HH:mm:ss for display. Let's start with a
74-
// comprehensive custom format closest to ISO 8601 style preference.
75-
return dt.toString(QStringLiteral("yyyy-MM-dd hh:mm"));
76-
case DateFormat::DayMonthYear:
77-
return dt.toString(QStringLiteral("dd/MM/yyyy hh:mm"));
78-
case DateFormat::MonthDayYear:
79-
return dt.toString(QStringLiteral("MM/dd/yyyy hh:mm"));
80-
case DateFormat::YearMonthDay:
81-
return dt.toString(QStringLiteral("yyyy/MM/dd hh:mm"));
82-
case DateFormat::Native:
83-
default:
84-
// Uses QLocale::ShortFormat for both Date and Time
53+
if (format.isEmpty()) {
8554
return QLocale().toString(dt, QLocale::ShortFormat);
8655
}
56+
return dt.toString(format);
8757
}
8858

8959
/// Format a QDateTime for display to the user using the
9060
/// application's locale settings or specified preference.
9161
inline QString displayLocalDateTime(
92-
const QDateTime& dt, DateFormat format = DateFormat::Native) {
62+
const QDateTime& dt, const QString& format = QString()) {
9363
return formatDateTime(dt, format);
9464
}
9565

0 commit comments

Comments
 (0)