Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
537130c
Move track filtering widgets to a separate .h/.cpp
hyperquantum Jan 21, 2026
264f91d
Add foundation for track criterium editor widgets
hyperquantum Feb 2, 2026
62f03c1
Add editor widget for track length comparisons
hyperquantum Feb 3, 2026
5143690
Add "OK" button and read-only view to filter line
hyperquantum Feb 7, 2026
c89b691
Add editor widget for "(not) heard in the last X"
hyperquantum Feb 7, 2026
65d878b
FilterLabelWidget: add click-to-edit
hyperquantum Feb 8, 2026
ea5caae
Improve read-only view of track length comparison
hyperquantum Feb 8, 2026
0d23e0e
Normalize hours/minutes/seconds before displaying
hyperquantum Feb 8, 2026
a4cc3f1
Switch to icons for the "Edit" and "OK" button
hyperquantum Feb 11, 2026
2bc13f4
Rename "_okButton" to "_doneButton"
hyperquantum Feb 11, 2026
873caa7
Bugfix: wrong button visible after click on reset
hyperquantum Feb 11, 2026
cdbf7d0
Add hours to "(not) heard in the last X" filter
hyperquantum Feb 15, 2026
313f31a
Change how an extra filter is added
hyperquantum Mar 8, 2026
76f00b6
Do not add an empty filter line at startup
hyperquantum Mar 18, 2026
64e8d7a
Eliminate the combobox from the filter line UI
hyperquantum Mar 23, 2026
12de476
Use a FilterLineWidget for the highlighting UI
hyperquantum Mar 24, 2026
4dbe0cb
Delete unused class FilterPickerWidget
hyperquantum Mar 24, 2026
e71db78
Delete enum PredefinedTrackCriterium
hyperquantum Mar 24, 2026
c1265c8
Disable the reset highlighting button after reset
hyperquantum Mar 24, 2026
fb1e20e
Add context menu option to add empty filter slot
hyperquantum Mar 27, 2026
53759d7
Filters: add shorter length display without hours
hyperquantum Mar 27, 2026
56b2f89
Improve consistency between view and context menu
hyperquantum Mar 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ set(PMP_DESKTOP_REMOTE_SOURCES
desktop-remote/scrobblingauthenticationdialog.cpp
desktop-remote/searchdata.cpp
desktop-remote/searchdialog.cpp
desktop-remote/trackfilterwidgets.cpp
desktop-remote/trackinfodialog.cpp
desktop-remote/trackjudge.cpp
desktop-remote/trackprogresswidget.cpp
Expand Down Expand Up @@ -267,6 +268,7 @@ set(PMP_DESKTOP_REMOTE_HEADERS
desktop-remote/scrobblingauthenticationdialog.h
desktop-remote/searchdata.h
desktop-remote/searchdialog.h
desktop-remote/trackfilterwidgets.h
desktop-remote/trackinfodialog.h
desktop-remote/trackprogresswidget.h
desktop-remote/useraccountcreationwidget.h
Expand Down
2 changes: 1 addition & 1 deletion src/common/commonmetatypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ namespace PMP
CommonMetatypesInit()
{
qRegisterMetaType<PMP::AudioData>();
qRegisterMetaType<PMP::ComparisonOperator>();
qRegisterMetaType<PMP::FileHash>();
qRegisterMetaType<PMP::PlayerHistoryTrackInfo>();
qRegisterMetaType<PMP::PlayerMode>();
qRegisterMetaType<PMP::PlayerState>();
qRegisterMetaType<PMP::PredefinedTrackCriterium>();
qRegisterMetaType<PMP::QueueEntryType>();
qRegisterMetaType<PMP::QueueIndexType>();
qRegisterMetaType<PMP::ScrobblerStatus>();
Expand Down
184 changes: 4 additions & 180 deletions src/common/trackcriteria.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (C) 2023-2025, Kevin André <hyperquantum@gmail.com>
Copyright (C) 2023-2026, Kevin André <hyperquantum@gmail.com>

This file is part of PMP (Party Music Player).

Expand All @@ -23,193 +23,17 @@

namespace PMP
{
namespace
{
std::unique_ptr<TrackCriterium> createLengthLessThanCriterium(
int lengthMinutesCeiling)
{
return std::make_unique<TrackLengthComparisonCriterium>(
ComparisonOperator::LessThan, lengthMinutesCeiling);
}

std::unique_ptr<TrackCriterium> createLengthAtLeastCriterium(
int minimumLengthMinutes)
{
return std::make_unique<TrackLengthComparisonCriterium>(
ComparisonOperator::GreaterThanOrEqual, minimumLengthMinutes);
}

std::unique_ptr<TrackCriterium> createScoreLessThanCriterium(short scoreCeiling)
{
return std::make_unique<TrackScoreComparisonCriterium>(
ComparisonOperator::LessThan, scoreCeiling);
}

std::unique_ptr<TrackCriterium> createScoreAtLeastCriterium(short minimumScore)
{
return std::make_unique<TrackScoreComparisonCriterium>(
ComparisonOperator::GreaterThanOrEqual, minimumScore);
}

std::unique_ptr<TrackCriterium> createNotRecentlyHeardCriterium(
CompositeDuration duration)
{
return std::make_unique<TrackLastHeardRecentlyCriterium>(
duration, /* isInverted: */ true);
}
}

std::unique_ptr<TrackCriterium> convertToTrackCriterium(
PredefinedTrackCriterium criterium)
{
switch (criterium)
{
case PredefinedTrackCriterium::AllTracks:
return ConstantTrackCriterium::allTracksMatch();

case PredefinedTrackCriterium::NoTracks:
return ConstantTrackCriterium::noTracksMatch();

case PredefinedTrackCriterium::NeverHeard:
return TrackLastHeardPresenceCriterium::lastHeardMustBeAbsent();

case PredefinedTrackCriterium::NotHeardInLast5Years:
return createNotRecentlyHeardCriterium(CompositeDuration { .years = 5 });

case PredefinedTrackCriterium::NotHeardInLast3Years:
return createNotRecentlyHeardCriterium(CompositeDuration { .years = 3 });

case PredefinedTrackCriterium::NotHeardInLast2Years:
return createNotRecentlyHeardCriterium(CompositeDuration { .years = 2 });

case PredefinedTrackCriterium::NotHeardInLastYear:
return createNotRecentlyHeardCriterium(CompositeDuration { .years = 1 });

case PredefinedTrackCriterium::NotHeardInLast180Days:
return createNotRecentlyHeardCriterium(CompositeDuration { .days = 180 });

case PredefinedTrackCriterium::NotHeardInLast90Days:
return createNotRecentlyHeardCriterium(CompositeDuration { .days = 90 });

case PredefinedTrackCriterium::NotHeardInLast30Days:
return createNotRecentlyHeardCriterium(CompositeDuration { .days = 30 });

case PredefinedTrackCriterium::NotHeardInLast10Days:
return createNotRecentlyHeardCriterium(CompositeDuration { .days = 10 });

case PredefinedTrackCriterium::HeardAtLeastOnce:
return TrackLastHeardPresenceCriterium::lastHeardMustBePresent();

case PredefinedTrackCriterium::WithoutScore:
return TrackScorePresenceCriterium::scoreMustBeAbsent();

case PredefinedTrackCriterium::WithScore:
return TrackScorePresenceCriterium::scoreMustBePresent();

case PredefinedTrackCriterium::ScoreLessThan30:
return createScoreLessThanCriterium(30);

case PredefinedTrackCriterium::ScoreLessThan50:
return createScoreLessThanCriterium(50);

case PredefinedTrackCriterium::ScoreAtLeast80:
return createScoreAtLeastCriterium(80);

case PredefinedTrackCriterium::ScoreAtLeast85:
return createScoreAtLeastCriterium(85);

case PredefinedTrackCriterium::ScoreAtLeast90:
return createScoreAtLeastCriterium(90);

case PredefinedTrackCriterium::ScoreAtLeast95:
return createScoreAtLeastCriterium(95);

case PredefinedTrackCriterium::LengthLessThanOneMinute:
return createLengthLessThanCriterium(1);

case PredefinedTrackCriterium::LengthAtLeastOneMinute:
return createLengthAtLeastCriterium(1);

case PredefinedTrackCriterium::LengthLessThanTwoMinutes:
return createLengthLessThanCriterium(2);

case PredefinedTrackCriterium::LengthAtLeastTwoMinutes:
return createLengthAtLeastCriterium(2);

case PredefinedTrackCriterium::LengthLessThanThreeMinutes:
return createLengthLessThanCriterium(3);

case PredefinedTrackCriterium::LengthAtLeastThreeMinutes:
return createLengthAtLeastCriterium(3);

case PredefinedTrackCriterium::LengthLessThanFourMinutes:
return createLengthLessThanCriterium(4);

case PredefinedTrackCriterium::LengthAtLeastFourMinutes:
return createLengthAtLeastCriterium(4);

case PredefinedTrackCriterium::LengthLessThanFiveMinutes:
return createLengthLessThanCriterium(5);

case PredefinedTrackCriterium::LengthAtLeastFiveMinutes:
return createLengthAtLeastCriterium(5);

case PredefinedTrackCriterium::NotInTheQueue:
return TrackQueuePresenceCriterium::mustBeAbsentInQueue();

case PredefinedTrackCriterium::InTheQueue:
return TrackQueuePresenceCriterium::mustBePresentInQueue();

case PredefinedTrackCriterium::WithoutTitle:
return TrackMetaDataPresenceCriterium::mustBeAbsent(TrackMetaDataKind::Title);

case PredefinedTrackCriterium::WithoutArtist:
return TrackMetaDataPresenceCriterium::mustBeAbsent(
TrackMetaDataKind::Artist);

case PredefinedTrackCriterium::WithoutAlbum:
return TrackMetaDataPresenceCriterium::mustBeAbsent(TrackMetaDataKind::Album);

case PredefinedTrackCriterium::NoLongerAvailable:
return TrackAvailabilityCriterium::mustBeUnavailable();
}

/* should be unreachable because we handled all enum values */
Q_UNREACHABLE();
}

std::unique_ptr<TrackCriterium> convertToTrackCriterium(
const QList<PredefinedTrackCriterium>& criteria)
{
if (criteria.isEmpty())
return ConstantTrackCriterium::allTracksMatch();

if (criteria.size() == 1)
return convertToTrackCriterium(criteria.front());

auto composite = std::make_unique<CompositeTrackCriterium>();

for (PredefinedTrackCriterium c : criteria)
{
composite->add(convertToTrackCriterium(c));
}

return composite;
}

/* ============================================================================ */

TrackLengthComparisonCriterium::TrackLengthComparisonCriterium()
: _operator(ComparisonOperator::GreaterThanOrEqual),
_minutes(0)
_hours(0), _minutes(0), _seconds(0)
{
//
}

TrackLengthComparisonCriterium::TrackLengthComparisonCriterium(
ComparisonOperator comparisonOperator, int minutes)
ComparisonOperator comparisonOperator, int hours, int minutes, int seconds)
: _operator(comparisonOperator),
_minutes(minutes)
_hours(hours), _minutes(minutes), _seconds(seconds)
{
//
}
Expand Down
Loading
Loading