mirror of
https://github.com/clangen/musikcube.git
synced 2025-01-30 06:32:36 +00:00
Wired up some basic UX to support toggling between substring and regex
matching.
This commit is contained in:
parent
d4a1fba4b6
commit
b5c2795928
@ -88,7 +88,7 @@ CategoryListQuery::CategoryListQuery(
|
||||
const std::string& trackField,
|
||||
const category::PredicateList predicates,
|
||||
const std::string& filter)
|
||||
: matchType(MatchType::Regex)
|
||||
: matchType(matchType)
|
||||
, trackField(trackField)
|
||||
, filter(filter) {
|
||||
result.reset(new SdkValueList());
|
||||
|
@ -106,7 +106,9 @@ void CategorySearchLayout::OnLayout() {
|
||||
size_t inputWidth = cx / 2;
|
||||
size_t inputX = x + ((cx - inputWidth) / 2);
|
||||
this->input->MoveAndResize(inputX, 0, cx / 2, SEARCH_HEIGHT);
|
||||
this->input->SetHint(_TSTR("search_filter_hint"));
|
||||
|
||||
bool inputIsRegex = this->matchType == MatchType::Regex;
|
||||
this->input->SetHint(_TSTR(inputIsRegex ? "search_regex_hint" : "search_filter_hint"));
|
||||
|
||||
size_t labelY = SEARCH_HEIGHT;
|
||||
size_t categoryWidth = cx / 3;
|
||||
@ -134,9 +136,9 @@ void CategorySearchLayout::InitializeWindows(musik::core::audio::PlaybackService
|
||||
|
||||
void CategorySearchLayout::Requery() {
|
||||
const std::string& value = this->input->GetText();
|
||||
this->albums->Requery(value);
|
||||
this->artists->Requery(value);
|
||||
this->genres->Requery(value);
|
||||
this->albums->Requery(this->matchType, value);
|
||||
this->artists->Requery(this->matchType, value);
|
||||
this->genres->Requery(this->matchType, value);
|
||||
}
|
||||
|
||||
void CategorySearchLayout::FocusInput() {
|
||||
@ -198,6 +200,10 @@ bool CategorySearchLayout::KeyPress(const std::string& key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (Hotkeys::Is(Hotkeys::SearchInputToggleMatchType, key)) {
|
||||
this->ToggleMatchType();
|
||||
return true;
|
||||
}
|
||||
|
||||
return LayoutBase::KeyPress(key);
|
||||
}
|
||||
@ -211,3 +217,16 @@ void CategorySearchLayout::ProcessMessage(IMessage &message) {
|
||||
}
|
||||
}
|
||||
|
||||
void CategorySearchLayout::ToggleMatchType() {
|
||||
const bool isRegex = this->matchType == MatchType::Regex;
|
||||
this->SetMatchType(isRegex ? MatchType::Substring : MatchType::Regex);
|
||||
}
|
||||
|
||||
void CategorySearchLayout::SetMatchType(MatchType matchType) {
|
||||
if (matchType != this->matchType) {
|
||||
this->matchType = matchType;
|
||||
this->Layout();
|
||||
this->Requery();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,8 @@ namespace musik {
|
||||
virtual void ProcessMessage(musik::core::runtime::IMessage &message);
|
||||
|
||||
private:
|
||||
using MatchType = musik::core::library::query::QueryBase::MatchType;
|
||||
|
||||
void InitializeWindows(musik::core::audio::PlaybackService& playback);
|
||||
void OnCategoryEntryActivated(cursespp::ListWindow* sender, size_t index);
|
||||
void Requery();
|
||||
@ -85,7 +87,11 @@ namespace musik {
|
||||
cursespp::TextInput* sender,
|
||||
std::string value);
|
||||
|
||||
void ToggleMatchType();
|
||||
void SetMatchType(MatchType matchType);
|
||||
|
||||
musik::core::ILibraryPtr library;
|
||||
MatchType matchType{ MatchType::Substring };
|
||||
std::shared_ptr<musik::core::Preferences> prefs;
|
||||
std::shared_ptr<CategoryListView> albums;
|
||||
std::shared_ptr<CategoryListView> artists;
|
||||
|
@ -104,7 +104,9 @@ void TrackSearchLayout::OnLayout() {
|
||||
size_t inputWidth = cx / 2;
|
||||
size_t inputX = x + ((cx - inputWidth) / 2);
|
||||
this->input->MoveAndResize(inputX, y, cx / 2, SEARCH_HEIGHT);
|
||||
this->input->SetHint(_TSTR("search_filter_hint"));
|
||||
|
||||
bool inputIsRegex = this->matchType == MatchType::Regex;
|
||||
this->input->SetHint(_TSTR(inputIsRegex ? "search_regex_hint" : "search_filter_hint"));
|
||||
|
||||
this->trackList->MoveAndResize(
|
||||
x,
|
||||
@ -150,10 +152,7 @@ void TrackSearchLayout::Requery() {
|
||||
const TrackSortType sortOrder = getDefaultTrackSort(this->prefs);
|
||||
this->trackList->Requery(std::shared_ptr<TrackListQueryBase>(
|
||||
new SearchTrackListQuery(
|
||||
this->library,
|
||||
SearchTrackListQuery::MatchType::Substring,
|
||||
filter,
|
||||
sortOrder)));
|
||||
this->library, this->matchType, filter, sortOrder)));
|
||||
}
|
||||
|
||||
void TrackSearchLayout::PlayFromTop() {
|
||||
@ -191,6 +190,19 @@ void TrackSearchLayout::OnEnterPressed(cursespp::TextInput* sender) {
|
||||
}
|
||||
}
|
||||
|
||||
void TrackSearchLayout::ToggleMatchType() {
|
||||
const bool isRegex = this->matchType == MatchType::Regex;
|
||||
this->SetMatchType(isRegex ? MatchType::Substring : MatchType::Regex);
|
||||
}
|
||||
|
||||
void TrackSearchLayout::SetMatchType(MatchType matchType) {
|
||||
if (matchType != this->matchType) {
|
||||
this->matchType = matchType;
|
||||
this->Layout();
|
||||
this->Requery();
|
||||
}
|
||||
}
|
||||
|
||||
bool TrackSearchLayout::KeyPress(const std::string& key) {
|
||||
if (Hotkeys::Is(Hotkeys::Down, key)) {
|
||||
if (this->GetFocus() == this->input) {
|
||||
@ -214,5 +226,9 @@ bool TrackSearchLayout::KeyPress(const std::string& key) {
|
||||
});
|
||||
return true;
|
||||
}
|
||||
else if (Hotkeys::Is(Hotkeys::SearchInputToggleMatchType, key)) {
|
||||
this->ToggleMatchType();
|
||||
return true;
|
||||
}
|
||||
return LayoutBase::KeyPress(key);
|
||||
}
|
||||
|
@ -70,6 +70,8 @@ namespace musik {
|
||||
virtual void OnLayout();
|
||||
|
||||
private:
|
||||
using MatchType = musik::core::library::query::QueryBase::MatchType;
|
||||
|
||||
void SaveSession();
|
||||
void InitializeWindows();
|
||||
void Requery();
|
||||
@ -82,8 +84,12 @@ namespace musik {
|
||||
|
||||
void OnEnterPressed(cursespp::TextInput* sender);
|
||||
|
||||
void ToggleMatchType();
|
||||
void SetMatchType(MatchType matchType);
|
||||
|
||||
musik::core::audio::PlaybackService& playback;
|
||||
musik::core::ILibraryPtr library;
|
||||
MatchType matchType{ MatchType::Substring };
|
||||
std::shared_ptr<musik::core::Preferences> prefs;
|
||||
std::shared_ptr<TrackListView> trackList;
|
||||
std::shared_ptr<cursespp::TextInput> input;
|
||||
|
@ -104,6 +104,8 @@ static std::unordered_map<std::string, Id> NAME_TO_ID = {
|
||||
{ "track_list_previous_group", Id::TrackListPreviousGroup },
|
||||
{ "track_list_play_from_top", Id::TrackListPlayFromTop },
|
||||
|
||||
{ "search_input_toggle_match_type", Id::SearchInputToggleMatchType },
|
||||
|
||||
{ "lyrics_retry", Id::LyricsRetry },
|
||||
|
||||
{ "playback_toggle_mute", Id::ToggleMute },
|
||||
@ -196,6 +198,8 @@ static std::unordered_map<Id, std::string, EnumHasher> ID_TO_DEFAULT = {
|
||||
{ Id::TrackListPreviousGroup, "[" },
|
||||
{ Id::TrackListPlayFromTop, "M-P" },
|
||||
|
||||
{ Id::SearchInputToggleMatchType, "M-m" },
|
||||
|
||||
{ Id::LyricsRetry, "r" },
|
||||
|
||||
{ Id::ToggleMute, "m" },
|
||||
|
@ -115,6 +115,9 @@ namespace musik {
|
||||
TrackListPreviousGroup,
|
||||
TrackListPlayFromTop,
|
||||
|
||||
/* search input */
|
||||
SearchInputToggleMatchType,
|
||||
|
||||
/* lyrics */
|
||||
LyricsRetry,
|
||||
|
||||
|
@ -97,6 +97,7 @@ void CategoryListView::OnVisibilityChanged(bool visible) {
|
||||
}
|
||||
|
||||
void CategoryListView::RequeryWithField(
|
||||
MatchType matchType,
|
||||
const std::string& fieldName,
|
||||
const std::string& filter,
|
||||
const int64_t selectAfterQuery)
|
||||
@ -105,25 +106,45 @@ void CategoryListView::RequeryWithField(
|
||||
this->activeQuery->Cancel();
|
||||
}
|
||||
|
||||
this->matchType = matchType;
|
||||
this->fieldName = fieldName;
|
||||
this->fieldIdColumn = getFieldIdColumn(fieldName);
|
||||
this->selectAfterQuery = selectAfterQuery;
|
||||
this->filter = filter;
|
||||
this->activeQuery.reset(new CategoryListQuery(
|
||||
CategoryListQuery::MatchType::Substring, fieldName, filter));
|
||||
this->activeQuery = std::make_shared<CategoryListQuery>(matchType, fieldName, filter);
|
||||
this->library->Enqueue(activeQuery);
|
||||
}
|
||||
|
||||
void CategoryListView::RequeryWithField(
|
||||
const std::string& fieldName,
|
||||
const std::string& filter,
|
||||
const int64_t selectAfterQuery)
|
||||
{
|
||||
this->RequeryWithField(this->matchType, fieldName, filter, selectAfterQuery);
|
||||
}
|
||||
|
||||
void CategoryListView::Requery(
|
||||
MatchType matchType,
|
||||
const std::string& filter,
|
||||
const int64_t selectAfterQuery)
|
||||
{
|
||||
this->RequeryWithField(matchType, this->fieldName, filter, selectAfterQuery);
|
||||
}
|
||||
|
||||
void CategoryListView::Requery(const std::string& filter, const int64_t selectAfterQuery) {
|
||||
this->RequeryWithField(this->fieldName, filter, selectAfterQuery);
|
||||
this->RequeryWithField(this->matchType, this->fieldName, filter, selectAfterQuery);
|
||||
}
|
||||
|
||||
void CategoryListView::Requery(const int64_t selectAfterQuery) {
|
||||
this->RequeryWithField(this->fieldName, this->filter, selectAfterQuery);
|
||||
this->RequeryWithField(this->matchType, this->fieldName, this->filter, selectAfterQuery);
|
||||
}
|
||||
|
||||
void CategoryListView::Requery() {
|
||||
this->RequeryWithField(this->matchType, this->fieldName, "", -1LL);
|
||||
}
|
||||
|
||||
void CategoryListView::Reset() {
|
||||
this->metadata.reset(new SdkValueList()); /* ugh */
|
||||
this->metadata = std::make_shared<SdkValueList>(); /* ugh */
|
||||
this->OnAdapterChanged();
|
||||
}
|
||||
|
||||
@ -167,7 +188,7 @@ void CategoryListView::SetFieldName(const std::string& fieldName) {
|
||||
this->metadata.reset();
|
||||
}
|
||||
|
||||
this->Requery();
|
||||
this->Requery(this->matchType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,8 @@ namespace musik {
|
||||
public sigslot::has_slots<>
|
||||
{
|
||||
public:
|
||||
using MatchType = musik::core::library::query::QueryBase::MatchType;
|
||||
|
||||
CategoryListView(
|
||||
musik::core::audio::PlaybackService& playback,
|
||||
musik::core::ILibraryPtr library,
|
||||
@ -62,17 +64,30 @@ namespace musik {
|
||||
|
||||
virtual ~CategoryListView();
|
||||
|
||||
void RequeryWithField(
|
||||
MatchType matchType,
|
||||
const std::string& fieldName,
|
||||
const std::string& filter = "",
|
||||
const int64_t selectAfterQuery = -1LL);
|
||||
|
||||
void RequeryWithField(
|
||||
const std::string& fieldName,
|
||||
const std::string& filter = "",
|
||||
const int64_t selectAfterQuery = -1LL);
|
||||
|
||||
void Requery(
|
||||
MatchType matchType,
|
||||
const std::string& filter = "",
|
||||
const int64_t selectAfterQuery = -1LL);
|
||||
|
||||
void Requery(
|
||||
const std::string& filter,
|
||||
const int64_t selectAfterQuery);
|
||||
|
||||
void Requery(const int64_t selectAfterQuery);
|
||||
|
||||
void Requery();
|
||||
|
||||
void Reset();
|
||||
|
||||
int64_t GetSelectedId();
|
||||
@ -121,6 +136,7 @@ namespace musik {
|
||||
|
||||
std::string fieldName, fieldIdColumn;
|
||||
std::string filter;
|
||||
MatchType matchType{ MatchType::Substring };
|
||||
int64_t selectAfterQuery;
|
||||
musik::core::library::query::CategoryListQuery::Result metadata;
|
||||
};
|
||||
|
@ -37,6 +37,7 @@
|
||||
"browse_no_subdirectories_toast": "there are no more sub-directories.\n\npress '%s' to play the selection.",
|
||||
|
||||
"search_filter_hint": "search",
|
||||
"search_regex_hint": "regex",
|
||||
|
||||
"console_list_title": "debug logs",
|
||||
"console_version": "musikcube version %s",
|
||||
|
Loading…
x
Reference in New Issue
Block a user