Wired up some basic UX to support toggling between substring and regex

matching.
This commit is contained in:
casey langen 2020-11-07 21:24:53 -08:00
parent d4a1fba4b6
commit b5c2795928
10 changed files with 108 additions and 16 deletions

View File

@ -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());

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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" },

View File

@ -115,6 +115,9 @@ namespace musik {
TrackListPreviousGroup,
TrackListPlayFromTop,
/* search input */
SearchInputToggleMatchType,
/* lyrics */
LyricsRetry,

View File

@ -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);
}
}

View File

@ -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;
};

View File

@ -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",