move searching to Menu class, also remember last constraint
this improvement also make that list of found items is not cleared if one switches to another screen. it's remebered until the content of screen changes (e.g. item is deleted from playlist)
This commit is contained in:
@@ -74,7 +74,6 @@ void Browser::SwitchTo()
|
|||||||
if (hasToBeResized)
|
if (hasToBeResized)
|
||||||
Resize();
|
Resize();
|
||||||
|
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
w->Empty() ? myBrowser->GetDirectory(itsBrowsedDir) : myBrowser->UpdateItemList();
|
w->Empty() ? myBrowser->GetDirectory(itsBrowsedDir) : myBrowser->UpdateItemList();
|
||||||
myScreen = this;
|
myScreen = this;
|
||||||
redraw_header = 1;
|
redraw_header = 1;
|
||||||
@@ -97,7 +96,6 @@ void Browser::EnterPressed()
|
|||||||
{
|
{
|
||||||
case itDirectory:
|
case itDirectory:
|
||||||
{
|
{
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
GetDirectory(item.name, itsBrowsedDir);
|
GetDirectory(item.name, itsBrowsedDir);
|
||||||
redraw_header = 1;
|
redraw_header = 1;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ void Clock::SwitchTo()
|
|||||||
if (hasToBeResized)
|
if (hasToBeResized)
|
||||||
Resize();
|
Resize();
|
||||||
|
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
myScreen = this;
|
myScreen = this;
|
||||||
myPlaylist->Main()->Hide();
|
myPlaylist->Main()->Hide();
|
||||||
redraw_header = 1;
|
redraw_header = 1;
|
||||||
|
|||||||
@@ -53,9 +53,6 @@ namespace Global
|
|||||||
extern bool redraw_header;
|
extern bool redraw_header;
|
||||||
|
|
||||||
extern std::string volume_state;
|
extern std::string volume_state;
|
||||||
|
|
||||||
extern std::vector<int> vFoundPositions;
|
|
||||||
extern int found_pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ void MediaLibrary::SwitchTo()
|
|||||||
if (hasToBeResized)
|
if (hasToBeResized)
|
||||||
Resize();
|
Resize();
|
||||||
|
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
myScreen = this;
|
myScreen = this;
|
||||||
redraw_header = 1;
|
redraw_header = 1;
|
||||||
Refresh();
|
Refresh();
|
||||||
@@ -128,7 +127,6 @@ void MediaLibrary::Update()
|
|||||||
{
|
{
|
||||||
if (Artists->Empty())
|
if (Artists->Empty())
|
||||||
{
|
{
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
TagList list;
|
TagList list;
|
||||||
Albums->Clear(0);
|
Albums->Clear(0);
|
||||||
Songs->Clear(0);
|
Songs->Clear(0);
|
||||||
@@ -284,7 +282,6 @@ void MediaLibrary::GetSelectedSongs(MPD::SongList &v)
|
|||||||
|
|
||||||
void MediaLibrary::NextColumn()
|
void MediaLibrary::NextColumn()
|
||||||
{
|
{
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
if (w == Artists)
|
if (w == Artists)
|
||||||
{
|
{
|
||||||
if (Songs->Empty())
|
if (Songs->Empty())
|
||||||
@@ -307,7 +304,6 @@ void MediaLibrary::NextColumn()
|
|||||||
|
|
||||||
void MediaLibrary::PrevColumn()
|
void MediaLibrary::PrevColumn()
|
||||||
{
|
{
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
if (w == Songs)
|
if (w == Songs)
|
||||||
{
|
{
|
||||||
Songs->HighlightColor(Config.main_highlight_color);
|
Songs->HighlightColor(Config.main_highlight_color);
|
||||||
|
|||||||
61
src/menu.h
61
src/menu.h
@@ -21,6 +21,8 @@
|
|||||||
#ifndef _MENU_H
|
#ifndef _MENU_H
|
||||||
#define _MENU_H
|
#define _MENU_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "strbuffer.h"
|
#include "strbuffer.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
@@ -52,6 +54,11 @@ namespace NCurses
|
|||||||
void ReverseSelection(size_t = 0);
|
void ReverseSelection(size_t = 0);
|
||||||
bool Deselect();
|
bool Deselect();
|
||||||
|
|
||||||
|
virtual bool Search(const std::string &, size_t = 0, bool = 0) = 0;
|
||||||
|
virtual const std::string &GetSearchConstraint() = 0;
|
||||||
|
virtual void NextFound(bool) = 0;
|
||||||
|
virtual void PrevFound(bool) = 0;
|
||||||
|
|
||||||
virtual void ApplyFilter(const std::string &, size_t = 0, bool = 0) = 0;
|
virtual void ApplyFilter(const std::string &, size_t = 0, bool = 0) = 0;
|
||||||
virtual const std::string &GetFilter() = 0;
|
virtual const std::string &GetFilter() = 0;
|
||||||
virtual std::string GetOption(size_t) = 0;
|
virtual std::string GetOption(size_t) = 0;
|
||||||
@@ -119,6 +126,11 @@ namespace NCurses
|
|||||||
virtual size_t Choice() const;
|
virtual size_t Choice() const;
|
||||||
virtual size_t RealChoice() const;
|
virtual size_t RealChoice() const;
|
||||||
|
|
||||||
|
virtual bool Search(const std::string &constraint, size_t beginning = 0, bool case_sensitive = 0);
|
||||||
|
virtual const std::string &GetSearchConstraint() { return itsSearchConstraint; }
|
||||||
|
virtual void NextFound(bool wrap);
|
||||||
|
virtual void PrevFound(bool wrap);
|
||||||
|
|
||||||
virtual void ApplyFilter(const std::string &filter, size_t beginning = 0, bool case_sensitive = 0);
|
virtual void ApplyFilter(const std::string &filter, size_t beginning = 0, bool case_sensitive = 0);
|
||||||
virtual const std::string &GetFilter();
|
virtual const std::string &GetFilter();
|
||||||
virtual std::string GetOption(size_t pos);
|
virtual std::string GetOption(size_t pos);
|
||||||
@@ -170,11 +182,13 @@ namespace NCurses
|
|||||||
void *itsGetStringFunctionUserData;
|
void *itsGetStringFunctionUserData;
|
||||||
|
|
||||||
std::string itsFilter;
|
std::string itsFilter;
|
||||||
|
std::string itsSearchConstraint;
|
||||||
|
|
||||||
std::vector<Option *> *itsOptionsPtr;
|
std::vector<Option *> *itsOptionsPtr;
|
||||||
std::vector<Option *> itsOptions;
|
std::vector<Option *> itsOptions;
|
||||||
std::vector<Option *> itsFilteredOptions;
|
std::vector<Option *> itsFilteredOptions;
|
||||||
std::vector<size_t> itsFilteredRealPositions;
|
std::vector<size_t> itsFilteredRealPositions;
|
||||||
|
std::set<size_t> itsFound;
|
||||||
|
|
||||||
int itsBeginning;
|
int itsBeginning;
|
||||||
int itsHighlight;
|
int itsHighlight;
|
||||||
@@ -279,6 +293,7 @@ template <class T> void NCurses::Menu<T>::DeleteOption(size_t pos)
|
|||||||
delete itsOptions.at(pos);
|
delete itsOptions.at(pos);
|
||||||
itsOptions.erase(itsOptions.begin()+pos);
|
itsOptions.erase(itsOptions.begin()+pos);
|
||||||
}
|
}
|
||||||
|
itsFound.clear();
|
||||||
if (itsOptionsPtr->empty())
|
if (itsOptionsPtr->empty())
|
||||||
Window::Clear();
|
Window::Clear();
|
||||||
}
|
}
|
||||||
@@ -490,6 +505,7 @@ template <class T> void NCurses::Menu<T>::Clear(bool clrscr)
|
|||||||
for (option_iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
|
for (option_iterator it = itsOptions.begin(); it != itsOptions.end(); it++)
|
||||||
delete *it;
|
delete *it;
|
||||||
itsOptions.clear();
|
itsOptions.clear();
|
||||||
|
itsFound.clear();
|
||||||
ClearFiltered();
|
ClearFiltered();
|
||||||
itsOptionsPtr = &itsOptions;
|
itsOptionsPtr = &itsOptions;
|
||||||
if (clrscr)
|
if (clrscr)
|
||||||
@@ -574,10 +590,55 @@ template <class T> size_t NCurses::Menu<T>::RealChoice() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T> bool NCurses::Menu<T>::Search(const std::string &constraint, size_t beginning, bool case_sensitive)
|
||||||
|
{
|
||||||
|
itsFound.clear();
|
||||||
|
if (constraint.empty())
|
||||||
|
return false;
|
||||||
|
itsSearchConstraint = constraint;
|
||||||
|
std::string option;
|
||||||
|
for (size_t i = beginning; i < itsOptionsPtr->size(); i++)
|
||||||
|
{
|
||||||
|
option = GetOption(i);
|
||||||
|
if (!case_sensitive)
|
||||||
|
ToLower(option);
|
||||||
|
if (option.find(itsSearchConstraint) != std::string::npos)
|
||||||
|
itsFound.insert(i);
|
||||||
|
}
|
||||||
|
return !itsFound.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> void NCurses::Menu<T>::NextFound(bool wrap)
|
||||||
|
{
|
||||||
|
if (itsFound.empty())
|
||||||
|
return;
|
||||||
|
std::set<size_t>::iterator next = itsFound.upper_bound(itsHighlight);
|
||||||
|
if (next != itsFound.end())
|
||||||
|
Highlight(*next);
|
||||||
|
else if (wrap)
|
||||||
|
Highlight(*itsFound.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> void NCurses::Menu<T>::PrevFound(bool wrap)
|
||||||
|
{
|
||||||
|
if (itsFound.empty())
|
||||||
|
return;
|
||||||
|
std::set<size_t>::iterator prev = itsFound.lower_bound(itsHighlight);
|
||||||
|
if (prev != itsFound.begin())
|
||||||
|
{
|
||||||
|
if (*prev == size_t(itsHighlight))
|
||||||
|
prev--;
|
||||||
|
Highlight(*prev);
|
||||||
|
}
|
||||||
|
else if (wrap)
|
||||||
|
Highlight(*itsFound.rbegin());
|
||||||
|
}
|
||||||
|
|
||||||
template <class T> void NCurses::Menu<T>::ApplyFilter(const std::string &filter, size_t beginning, bool case_sensitive)
|
template <class T> void NCurses::Menu<T>::ApplyFilter(const std::string &filter, size_t beginning, bool case_sensitive)
|
||||||
{
|
{
|
||||||
if (filter == itsFilter)
|
if (filter == itsFilter)
|
||||||
return;
|
return;
|
||||||
|
itsFound.clear();
|
||||||
ClearFiltered();
|
ClearFiltered();
|
||||||
itsFilter = filter;
|
itsFilter = filter;
|
||||||
if (!case_sensitive)
|
if (!case_sensitive)
|
||||||
|
|||||||
@@ -79,9 +79,6 @@ bool Global::block_item_list_update = 0;
|
|||||||
bool Global::messages_allowed = 0;
|
bool Global::messages_allowed = 0;
|
||||||
bool Global::redraw_header = 1;
|
bool Global::redraw_header = 1;
|
||||||
|
|
||||||
vector<int> Global::vFoundPositions;
|
|
||||||
int Global::found_pos = 0;
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
CreateConfigDir();
|
CreateConfigDir();
|
||||||
@@ -1462,8 +1459,6 @@ int main(int argc, char *argv[])
|
|||||||
if (!mList)
|
if (!mList)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
|
|
||||||
LockStatusbar();
|
LockStatusbar();
|
||||||
Statusbar() << fmtBold << "Apply filter: " << fmtBoldEnd;
|
Statusbar() << fmtBold << "Apply filter: " << fmtBoldEnd;
|
||||||
wFooter->SetGetStringHelper(StatusbarApplyFilterImmediately);
|
wFooter->SetGetStringHelper(StatusbarApplyFilterImmediately);
|
||||||
@@ -1491,83 +1486,36 @@ int main(int argc, char *argv[])
|
|||||||
if (!mList)
|
if (!mList)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
string how = Keypressed(input, Key.FindForward) ? "forward" : "backward";
|
|
||||||
LockStatusbar();
|
LockStatusbar();
|
||||||
Statusbar() << "Find " << how << ": ";
|
Statusbar() << "Find " << (Keypressed(input, Key.FindForward) ? "forward" : "backward") << ": ";
|
||||||
string findme = wFooter->GetString();
|
string findme = wFooter->GetString(mList->GetSearchConstraint());
|
||||||
UnlockStatusbar();
|
UnlockStatusbar();
|
||||||
time(&timer);
|
time(&timer);
|
||||||
if (findme.empty())
|
if (findme.empty())
|
||||||
continue;
|
continue;
|
||||||
ToLower(findme);
|
|
||||||
|
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
|
|
||||||
ShowMessage("Searching...");
|
ShowMessage("Searching...");
|
||||||
for (size_t i = (myScreen == mySearcher ? SearchEngine::StaticOptions : 0); i < mList->Size(); i++)
|
if (mList->Search(findme, myScreen == mySearcher ? SearchEngine::StaticOptions : 0))
|
||||||
{
|
|
||||||
string name = mList->GetOption(i);
|
|
||||||
ToLower(name);
|
|
||||||
if (name.find(findme) != string::npos && !mList->isStatic(i))
|
|
||||||
{
|
|
||||||
vFoundPositions.push_back(i);
|
|
||||||
if (Keypressed(input, Key.FindForward)) // forward
|
|
||||||
{
|
|
||||||
if (found_pos < 0 && i >= mList->Choice())
|
|
||||||
found_pos = vFoundPositions.size()-1;
|
|
||||||
}
|
|
||||||
else // backward
|
|
||||||
{
|
|
||||||
if (i <= mList->Choice())
|
|
||||||
found_pos = vFoundPositions.size()-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ShowMessage("Searching finished!");
|
ShowMessage("Searching finished!");
|
||||||
|
|
||||||
if (Config.wrapped_search ? vFoundPositions.empty() : found_pos < 0)
|
|
||||||
ShowMessage("Unable to find \"%s\"", findme.c_str());
|
|
||||||
else
|
else
|
||||||
{
|
ShowMessage("Unable to find \"%s\"", findme.c_str());
|
||||||
mList->Highlight(vFoundPositions[found_pos < 0 ? 0 : found_pos]);
|
|
||||||
if (myScreen == myPlaylist)
|
if (Keypressed(input, Key.FindForward))
|
||||||
{
|
mList->NextFound(Config.wrapped_search);
|
||||||
time(&timer);
|
else
|
||||||
myPlaylist->Main()->Highlighting(1);
|
mList->PrevFound(Config.wrapped_search);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (Keypressed(input, Key.NextFoundPosition) || Keypressed(input, Key.PrevFoundPosition))
|
else if (Keypressed(input, Key.NextFoundPosition) || Keypressed(input, Key.PrevFoundPosition))
|
||||||
{
|
{
|
||||||
List *mList = myScreen->GetList();
|
List *mList = myScreen->GetList();
|
||||||
|
|
||||||
if (!mList || vFoundPositions.empty())
|
if (!mList)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool next = Keypressed(input, Key.NextFoundPosition);
|
if (Keypressed(input, Key.NextFoundPosition))
|
||||||
|
mList->NextFound(Config.wrapped_search);
|
||||||
try
|
|
||||||
{
|
|
||||||
mList->Highlight(vFoundPositions.at(next ? ++found_pos : --found_pos));
|
|
||||||
}
|
|
||||||
catch (std::out_of_range)
|
|
||||||
{
|
|
||||||
if (Config.wrapped_search)
|
|
||||||
{
|
|
||||||
if (next)
|
|
||||||
{
|
|
||||||
mList->Highlight(vFoundPositions.front());
|
|
||||||
found_pos = 0;
|
|
||||||
}
|
|
||||||
else // prev
|
|
||||||
{
|
|
||||||
mList->Highlight(vFoundPositions.back());
|
|
||||||
found_pos = vFoundPositions.size()-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
found_pos = next ? vFoundPositions.size()-1 : 0;
|
mList->PrevFound(Config.wrapped_search);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (Keypressed(input, Key.ToggleFindMode))
|
else if (Keypressed(input, Key.ToggleFindMode))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,12 +27,6 @@
|
|||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "scrollpad.h"
|
#include "scrollpad.h"
|
||||||
|
|
||||||
#define CLEAR_FIND_HISTORY \
|
|
||||||
do { \
|
|
||||||
found_pos = -1; \
|
|
||||||
vFoundPositions.clear(); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
using namespace NCurses;
|
using namespace NCurses;
|
||||||
|
|
||||||
typedef std::pair<std::string, std::string> string_pair;
|
typedef std::pair<std::string, std::string> string_pair;
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ void Playlist::SwitchTo()
|
|||||||
if (hasToBeResized)
|
if (hasToBeResized)
|
||||||
Resize();
|
Resize();
|
||||||
|
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
myScreen = this;
|
myScreen = this;
|
||||||
w->Window::Clear();
|
w->Window::Clear();
|
||||||
redraw_header = 1;
|
redraw_header = 1;
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ void PlaylistEditor::SwitchTo()
|
|||||||
if (hasToBeResized)
|
if (hasToBeResized)
|
||||||
Resize();
|
Resize();
|
||||||
|
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
myScreen = this;
|
myScreen = this;
|
||||||
redraw_header = 1;
|
redraw_header = 1;
|
||||||
Refresh();
|
Refresh();
|
||||||
@@ -168,7 +167,6 @@ void PlaylistEditor::NextColumn()
|
|||||||
{
|
{
|
||||||
if (w == Playlists)
|
if (w == Playlists)
|
||||||
{
|
{
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
Playlists->HighlightColor(Config.main_highlight_color);
|
Playlists->HighlightColor(Config.main_highlight_color);
|
||||||
w->Refresh();
|
w->Refresh();
|
||||||
w = Content;
|
w = Content;
|
||||||
@@ -180,7 +178,6 @@ void PlaylistEditor::PrevColumn()
|
|||||||
{
|
{
|
||||||
if (w == Content)
|
if (w == Content)
|
||||||
{
|
{
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
Content->HighlightColor(Config.main_highlight_color);
|
Content->HighlightColor(Config.main_highlight_color);
|
||||||
w->Refresh();
|
w->Refresh();
|
||||||
w = Playlists;
|
w = Playlists;
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ void SearchEngine::SwitchTo()
|
|||||||
if (hasToBeResized)
|
if (hasToBeResized)
|
||||||
Resize();
|
Resize();
|
||||||
|
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
if (w->Empty())
|
if (w->Empty())
|
||||||
Prepare();
|
Prepare();
|
||||||
myScreen = this;
|
myScreen = this;
|
||||||
@@ -214,7 +213,6 @@ void SearchEngine::EnterPressed()
|
|||||||
}
|
}
|
||||||
case 16:
|
case 16:
|
||||||
{
|
{
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
itsPattern.Clear();
|
itsPattern.Clear();
|
||||||
w->Reset();
|
w->Reset();
|
||||||
Prepare();
|
Prepare();
|
||||||
|
|||||||
@@ -366,8 +366,6 @@ void TagEditor::SwitchTo()
|
|||||||
if (hasToBeResized)
|
if (hasToBeResized)
|
||||||
Resize();
|
Resize();
|
||||||
|
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
|
|
||||||
myScreen = this;
|
myScreen = this;
|
||||||
redraw_header = 1;
|
redraw_header = 1;
|
||||||
Refresh();
|
Refresh();
|
||||||
@@ -410,7 +408,6 @@ void TagEditor::Update()
|
|||||||
{
|
{
|
||||||
if (LeftColumn->Empty())
|
if (LeftColumn->Empty())
|
||||||
{
|
{
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
LeftColumn->Window::Clear();
|
LeftColumn->Window::Clear();
|
||||||
Tags->Clear();
|
Tags->Clear();
|
||||||
TagList list;
|
TagList list;
|
||||||
@@ -763,7 +760,6 @@ List *TagEditor::GetList()
|
|||||||
|
|
||||||
void TagEditor::NextColumn()
|
void TagEditor::NextColumn()
|
||||||
{
|
{
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
if (w == LeftColumn)
|
if (w == LeftColumn)
|
||||||
{
|
{
|
||||||
LeftColumn->HighlightColor(Config.main_highlight_color);
|
LeftColumn->HighlightColor(Config.main_highlight_color);
|
||||||
@@ -782,7 +778,6 @@ void TagEditor::NextColumn()
|
|||||||
|
|
||||||
void TagEditor::PrevColumn()
|
void TagEditor::PrevColumn()
|
||||||
{
|
{
|
||||||
CLEAR_FIND_HISTORY;
|
|
||||||
if (w == Tags)
|
if (w == Tags)
|
||||||
{
|
{
|
||||||
Tags->HighlightColor(Config.main_highlight_color);
|
Tags->HighlightColor(Config.main_highlight_color);
|
||||||
|
|||||||
Reference in New Issue
Block a user