add interface HasColumns and its appropriate implementations

This commit is contained in:
Andrzej Rybczak
2012-09-13 18:24:57 +02:00
parent 31b06470d1
commit cfe738b2f7
10 changed files with 230 additions and 242 deletions

View File

@@ -668,46 +668,24 @@ void PressSpace::Run()
bool PreviousColumn::canBeRun() const bool PreviousColumn::canBeRun() const
{ {
return (myScreen == myLibrary && myLibrary->isPrevColumnAvailable()) auto hc = hasColumns(myScreen);
|| (myScreen == myPlaylistEditor && myPlaylistEditor->isPrevColumnAvailable()) return hc && hc->previousColumnAvailable();
# ifdef HAVE_TAGLIB_H
|| (myScreen == myTagEditor && myTagEditor->isPrevColumnAvailable())
# endif // HAVE_TAGLIB_H
;
} }
void PreviousColumn::Run() void PreviousColumn::Run()
{ {
if (myScreen == myLibrary) hasColumns(myScreen)->previousColumn();
myLibrary->PrevColumn();
else if (myScreen == myPlaylistEditor)
myPlaylistEditor->PrevColumn();
# ifdef HAVE_TAGLIB_H
else if (myScreen == myTagEditor)
myTagEditor->PrevColumn();
# endif // HAVE_TAGLIB_H
} }
bool NextColumn::canBeRun() const bool NextColumn::canBeRun() const
{ {
return (myScreen == myLibrary && myLibrary->isNextColumnAvailable()) auto hc = hasColumns(myScreen);
|| (myScreen == myPlaylistEditor && myPlaylistEditor->isNextColumnAvailable()) return hc && hc->nextColumnAvailable();
# ifdef HAVE_TAGLIB_H
|| (myScreen == myTagEditor && myTagEditor->isNextColumnAvailable())
# endif // HAVE_TAGLIB_H
;
} }
void NextColumn::Run() void NextColumn::Run()
{ {
if (myScreen == myLibrary) hasColumns(myScreen)->nextColumn();
myLibrary->NextColumn();
else if (myScreen == myPlaylistEditor)
myPlaylistEditor->NextColumn();
# ifdef HAVE_TAGLIB_H
else if (myScreen == myTagEditor)
myTagEditor->NextColumn();
# endif // HAVE_TAGLIB_H
} }
bool MasterScreen::canBeRun() const bool MasterScreen::canBeRun() const

View File

@@ -28,6 +28,11 @@
#include "status.h" #include "status.h"
#include "utility/wide_string.h" #include "utility/wide_string.h"
inline HasColumns *hasColumns(BasicScreen *screen)
{
return dynamic_cast<HasColumns *>(screen);
}
inline HasSongs *hasSongs(BasicScreen *screen) inline HasSongs *hasSongs(BasicScreen *screen)
{ {
return dynamic_cast<HasSongs *>(screen); return dynamic_cast<HasSongs *>(screen);

View File

@@ -50,4 +50,13 @@ struct HasSongs
virtual MPD::SongList getSelectedSongs() = 0; virtual MPD::SongList getSelectedSongs() = 0;
}; };
struct HasColumns
{
virtual bool previousColumnAvailable() = 0;
virtual void previousColumn() = 0;
virtual bool nextColumnAvailable() = 0;
virtual void nextColumn() = 0;
};
#endif // _INTERFACES_H #endif // _INTERFACES_H

View File

@@ -414,8 +414,8 @@ void MediaLibrary::MouseButtonPressed(MEVENT me)
bool result = true; bool result = true;
if (w != Songs) if (w != Songs)
{ {
if (isNextColumnAvailable()) if (nextColumnAvailable())
NextColumn(); nextColumn();
else else
result = false; result = false;
} }
@@ -425,8 +425,8 @@ void MediaLibrary::MouseButtonPressed(MEVENT me)
bool result = true; bool result = true;
if (w != Tags) if (w != Tags)
{ {
if (isPrevColumnAvailable()) if (previousColumnAvailable())
PrevColumn(); previousColumn();
else else
result = false; result = false;
} }
@@ -683,15 +683,41 @@ MPD::SongList MediaLibrary::getSelectedSongs()
/***********************************************************************/ /***********************************************************************/
int MediaLibrary::Columns() bool MediaLibrary::previousColumnAvailable()
{ {
if (hasTwoColumns) assert(!hasTwoColumns || w != Tags);
return 2; if (w == Songs)
else {
return 3; if (!Albums->reallyEmpty() && (hasTwoColumns || !Tags->reallyEmpty()))
return true;
}
else if (w == Albums)
{
if (!hasTwoColumns && !Tags->reallyEmpty())
return true;
}
return false;
} }
bool MediaLibrary::isNextColumnAvailable() void MediaLibrary::previousColumn()
{
if (w == Songs)
{
Songs->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = Albums;
Albums->setHighlightColor(Config.active_column_color);
}
else if (w == Albums && !hasTwoColumns)
{
Albums->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = Tags;
Tags->setHighlightColor(Config.active_column_color);
}
}
bool MediaLibrary::nextColumnAvailable()
{ {
assert(!hasTwoColumns || w != Tags); assert(!hasTwoColumns || w != Tags);
if (w == Tags) if (w == Tags)
@@ -707,7 +733,7 @@ bool MediaLibrary::isNextColumnAvailable()
return false; return false;
} }
void MediaLibrary::NextColumn() void MediaLibrary::nextColumn()
{ {
if (w == Tags) if (w == Tags)
{ {
@@ -725,38 +751,14 @@ void MediaLibrary::NextColumn()
} }
} }
bool MediaLibrary::isPrevColumnAvailable() /***********************************************************************/
{
assert(!hasTwoColumns || w != Tags);
if (w == Songs)
{
if (!Albums->reallyEmpty() && (hasTwoColumns || !Tags->reallyEmpty()))
return true;
}
else if (w == Albums)
{
if (!hasTwoColumns && !Tags->reallyEmpty())
return true;
}
return false;
}
void MediaLibrary::PrevColumn() int MediaLibrary::Columns()
{ {
if (w == Songs) if (hasTwoColumns)
{ return 2;
Songs->setHighlightColor(Config.main_highlight_color); else
w->refresh(); return 3;
w = Albums;
Albums->setHighlightColor(Config.active_column_color);
}
else if (w == Albums && !hasTwoColumns)
{
Albums->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = Tags;
Tags->setHighlightColor(Config.active_column_color);
}
} }
std::shared_ptr<ProxySongList> MediaLibrary::songsProxyList() std::shared_ptr<ProxySongList> MediaLibrary::songsProxyList()

View File

@@ -24,7 +24,7 @@
#include "interfaces.h" #include "interfaces.h"
#include "screen.h" #include "screen.h"
class MediaLibrary : public Screen<NC::Window>, public Filterable, public HasSongs, public Searchable class MediaLibrary : public Screen<NC::Window>, public Filterable, public HasColumns, public HasSongs, public Searchable
{ {
public: public:
virtual void SwitchTo() OVERRIDE; virtual void SwitchTo() OVERRIDE;
@@ -42,33 +42,34 @@ class MediaLibrary : public Screen<NC::Window>, public Filterable, public HasSon
virtual bool isTabbable() OVERRIDE { return true; } virtual bool isTabbable() OVERRIDE { return true; }
virtual bool isMergable() OVERRIDE { return true; } virtual bool isMergable() OVERRIDE { return true; }
/// Filterable implementation // Filterable implementation
virtual bool allowsFiltering() OVERRIDE; virtual bool allowsFiltering() OVERRIDE;
virtual std::string currentFilter() OVERRIDE; virtual std::string currentFilter() OVERRIDE;
virtual void applyFilter(const std::string &filter) OVERRIDE; virtual void applyFilter(const std::string &filter) OVERRIDE;
/// Searchable implementation // Searchable implementation
virtual bool allowsSearching() OVERRIDE; virtual bool allowsSearching() OVERRIDE;
virtual bool search(const std::string &constraint) OVERRIDE; virtual bool search(const std::string &constraint) OVERRIDE;
virtual void nextFound(bool wrap) OVERRIDE; virtual void nextFound(bool wrap) OVERRIDE;
virtual void prevFound(bool wrap) OVERRIDE; virtual void prevFound(bool wrap) OVERRIDE;
/// HasSongs implementation // HasSongs implementation
virtual std::shared_ptr<ProxySongList> getProxySongList() OVERRIDE; virtual std::shared_ptr<ProxySongList> getProxySongList() OVERRIDE;
virtual bool allowsSelection() OVERRIDE; virtual bool allowsSelection() OVERRIDE;
virtual void reverseSelection() OVERRIDE; virtual void reverseSelection() OVERRIDE;
virtual MPD::SongList getSelectedSongs() OVERRIDE; virtual MPD::SongList getSelectedSongs() OVERRIDE;
// HasColumns implementation
virtual bool previousColumnAvailable() OVERRIDE;
virtual void previousColumn() OVERRIDE;
virtual bool nextColumnAvailable() OVERRIDE;
virtual void nextColumn() OVERRIDE;
// private members // private members
int Columns(); int Columns();
bool isNextColumnAvailable();
void NextColumn();
bool isPrevColumnAvailable();
void PrevColumn();
void LocateSong(const MPD::Song &); void LocateSong(const MPD::Song &);
std::shared_ptr<ProxySongList> songsProxyList(); std::shared_ptr<ProxySongList> songsProxyList();
struct SearchConstraints struct SearchConstraints

View File

@@ -93,7 +93,7 @@ class Playlist : public Screen<NC::Window>, public Filterable, public HasSongs,
void registerHash(size_t hash); void registerHash(size_t hash);
void unregisterHash(size_t hash); void unregisterHash(size_t hash);
NC::Menu< MPD::Song > *Items; NC::Menu<MPD::Song> *Items;
static bool ReloadTotalLength; static bool ReloadTotalLength;
static bool ReloadRemaining; static bool ReloadRemaining;

View File

@@ -219,52 +219,6 @@ bool PlaylistEditor::isContentFiltered()
return false; return false;
} }
bool PlaylistEditor::isNextColumnAvailable()
{
if (w == Playlists)
{
if (!Content->reallyEmpty())
return true;
}
return false;
}
bool PlaylistEditor::NextColumn()
{
if (w == Playlists)
{
Playlists->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = Content;
Content->setHighlightColor(Config.active_column_color);
return true;
}
return false;
}
bool PlaylistEditor::isPrevColumnAvailable()
{
if (w == Content)
{
if (!Playlists->reallyEmpty())
return true;
}
return false;
}
bool PlaylistEditor::PrevColumn()
{
if (w == Content)
{
Content->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = Playlists;
Playlists->setHighlightColor(Config.active_column_color);
return true;
}
return false;
}
std::shared_ptr<ProxySongList> PlaylistEditor::contentProxyList() std::shared_ptr<ProxySongList> PlaylistEditor::contentProxyList()
{ {
return mkProxySongList(*Content, [](NC::Menu<MPD::Song>::Item &item) { return mkProxySongList(*Content, [](NC::Menu<MPD::Song>::Item &item) {
@@ -328,8 +282,8 @@ void PlaylistEditor::MouseButtonPressed(MEVENT me)
{ {
if (w != Playlists) if (w != Playlists)
{ {
if (isPrevColumnAvailable()) if (previousColumnAvailable())
PrevColumn(); previousColumn();
else else
return; return;
} }
@@ -352,8 +306,8 @@ void PlaylistEditor::MouseButtonPressed(MEVENT me)
{ {
if (w != Content) if (w != Content)
{ {
if (isNextColumnAvailable()) if (nextColumnAvailable())
NextColumn(); nextColumn();
else else
return; return;
} }
@@ -508,6 +462,51 @@ MPD::SongList PlaylistEditor::getSelectedSongs()
/***********************************************************************/ /***********************************************************************/
bool PlaylistEditor::previousColumnAvailable()
{
if (w == Content)
{
if (!Playlists->reallyEmpty())
return true;
}
return false;
}
void PlaylistEditor::previousColumn()
{
if (w == Content)
{
Content->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = Playlists;
Playlists->setHighlightColor(Config.active_column_color);
}
}
bool PlaylistEditor::nextColumnAvailable()
{
if (w == Playlists)
{
if (!Content->reallyEmpty())
return true;
}
return false;
}
void PlaylistEditor::nextColumn()
{
if (w == Playlists)
{
Playlists->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = Content;
Content->setHighlightColor(Config.active_column_color);
}
}
/***********************************************************************/
void PlaylistEditor::Locate(const std::string &name) void PlaylistEditor::Locate(const std::string &name)
{ {
if (!isInitialized) if (!isInitialized)

View File

@@ -24,7 +24,7 @@
#include "interfaces.h" #include "interfaces.h"
#include "screen.h" #include "screen.h"
class PlaylistEditor : public Screen<NC::Window>, public Filterable, public HasSongs, public Searchable class PlaylistEditor : public Screen<NC::Window>, public Filterable, public HasColumns, public HasSongs, public Searchable
{ {
public: public:
virtual void SwitchTo() OVERRIDE; virtual void SwitchTo() OVERRIDE;
@@ -42,36 +42,37 @@ class PlaylistEditor : public Screen<NC::Window>, public Filterable, public HasS
virtual bool isTabbable() OVERRIDE { return true; } virtual bool isTabbable() OVERRIDE { return true; }
virtual bool isMergable() OVERRIDE { return true; } virtual bool isMergable() OVERRIDE { return true; }
/// Filterable implementation // Filterable implementation
virtual bool allowsFiltering() OVERRIDE; virtual bool allowsFiltering() OVERRIDE;
virtual std::string currentFilter() OVERRIDE; virtual std::string currentFilter() OVERRIDE;
virtual void applyFilter(const std::string &filter) OVERRIDE; virtual void applyFilter(const std::string &filter) OVERRIDE;
/// Searchable implementation // Searchable implementation
virtual bool allowsSearching() OVERRIDE; virtual bool allowsSearching() OVERRIDE;
virtual bool search(const std::string &constraint) OVERRIDE; virtual bool search(const std::string &constraint) OVERRIDE;
virtual void nextFound(bool wrap) OVERRIDE; virtual void nextFound(bool wrap) OVERRIDE;
virtual void prevFound(bool wrap) OVERRIDE; virtual void prevFound(bool wrap) OVERRIDE;
/// HasSongs implementation // HasSongs implementation
virtual std::shared_ptr<ProxySongList> getProxySongList() OVERRIDE; virtual std::shared_ptr<ProxySongList> getProxySongList() OVERRIDE;
virtual bool allowsSelection() OVERRIDE; virtual bool allowsSelection() OVERRIDE;
virtual void reverseSelection() OVERRIDE; virtual void reverseSelection() OVERRIDE;
virtual MPD::SongList getSelectedSongs() OVERRIDE; virtual MPD::SongList getSelectedSongs() OVERRIDE;
// private members // HasColumns implementation
virtual void Locate(const std::string &); virtual bool previousColumnAvailable() OVERRIDE;
virtual void previousColumn() OVERRIDE;
virtual bool nextColumnAvailable() OVERRIDE;
virtual void nextColumn() OVERRIDE;
// private members
void requestPlaylistsUpdate() { playlistsUpdateRequested = true; } void requestPlaylistsUpdate() { playlistsUpdateRequested = true; }
void requestContentsUpdate() { contentUpdateRequested = true; } void requestContentsUpdate() { contentUpdateRequested = true; }
virtual void Locate(const std::string &);
bool isContentFiltered(); bool isContentFiltered();
bool isNextColumnAvailable();
bool NextColumn();
bool isPrevColumnAvailable();
bool PrevColumn();
std::shared_ptr<ProxySongList> contentProxyList(); std::shared_ptr<ProxySongList> contentProxyList();
NC::Menu<std::string> *Playlists; NC::Menu<std::string> *Playlists;

View File

@@ -646,8 +646,8 @@ void TagEditor::MouseButtonPressed(MEVENT me)
bool result = true; bool result = true;
if (w != Dirs) if (w != Dirs)
{ {
if (isPrevColumnAvailable()) if (previousColumnAvailable())
PrevColumn(); previousColumn();
else else
result = false; result = false;
} }
@@ -657,8 +657,8 @@ void TagEditor::MouseButtonPressed(MEVENT me)
bool result = true; bool result = true;
if (w != Tags) if (w != Tags)
{ {
if (isNextColumnAvailable()) if (nextColumnAvailable())
NextColumn(); nextColumn();
else else
result = false; result = false;
} }
@@ -684,8 +684,8 @@ void TagEditor::MouseButtonPressed(MEVENT me)
{ {
if (w != FParser) if (w != FParser)
{ {
if (isPrevColumnAvailable()) if (previousColumnAvailable())
PrevColumn(); previousColumn();
else else
return; return;
} }
@@ -702,8 +702,8 @@ void TagEditor::MouseButtonPressed(MEVENT me)
{ {
if (w != FParserHelper) if (w != FParserHelper)
{ {
if (isNextColumnAvailable()) if (nextColumnAvailable())
NextColumn(); nextColumn();
else else
return; return;
} }
@@ -880,63 +880,7 @@ MPD::SongList TagEditor::getSelectedSongs()
/***********************************************************************/ /***********************************************************************/
bool TagEditor::ifAnyModifiedAskForDiscarding() bool TagEditor::previousColumnAvailable()
{
bool result = true;
if (isAnyModified(*Tags))
result = Action::AskYesNoQuestion("There are pending changes, are you sure?", Status::trace);
return result;
}
bool TagEditor::isNextColumnAvailable()
{
bool result = false;
if (w == Dirs)
{
if (!TagTypes->reallyEmpty() && !Tags->reallyEmpty())
result = true;
}
else if (w == TagTypes)
{
if (!Tags->reallyEmpty())
result = true;
}
else if (w == FParser)
result = true;
return result;
}
bool TagEditor::NextColumn()
{
if (w == Dirs)
{
Dirs->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = TagTypes;
TagTypes->setHighlightColor(Config.active_column_color);
return true;
}
else if (w == TagTypes && TagTypes->choice() < 13 && !Tags->reallyEmpty())
{
TagTypes->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = Tags;
Tags->setHighlightColor(Config.active_column_color);
return true;
}
else if (w == FParser)
{
FParser->setBorder(Config.window_border);
FParser->display();
w = FParserHelper;
FParserHelper->setBorder(Config.active_window_border);
FParserHelper->display();
return true;
}
return false;
}
bool TagEditor::isPrevColumnAvailable()
{ {
bool result = false; bool result = false;
if (w == Tags) if (w == Tags)
@@ -954,7 +898,7 @@ bool TagEditor::isPrevColumnAvailable()
return result; return result;
} }
bool TagEditor::PrevColumn() void TagEditor::previousColumn()
{ {
if (w == Tags) if (w == Tags)
{ {
@@ -962,7 +906,6 @@ bool TagEditor::PrevColumn()
w->refresh(); w->refresh();
w = TagTypes; w = TagTypes;
TagTypes->setHighlightColor(Config.active_column_color); TagTypes->setHighlightColor(Config.active_column_color);
return true;
} }
else if (w == TagTypes) else if (w == TagTypes)
{ {
@@ -970,7 +913,6 @@ bool TagEditor::PrevColumn()
w->refresh(); w->refresh();
w = Dirs; w = Dirs;
Dirs->setHighlightColor(Config.active_column_color); Dirs->setHighlightColor(Config.active_column_color);
return true;
} }
else if (w == FParserHelper) else if (w == FParserHelper)
{ {
@@ -979,9 +921,61 @@ bool TagEditor::PrevColumn()
w = FParser; w = FParser;
FParser->setBorder(Config.active_window_border); FParser->setBorder(Config.active_window_border);
FParser->display(); FParser->display();
return true;
} }
return false; }
bool TagEditor::nextColumnAvailable()
{
bool result = false;
if (w == Dirs)
{
if (!TagTypes->reallyEmpty() && !Tags->reallyEmpty())
result = true;
}
else if (w == TagTypes)
{
if (!Tags->reallyEmpty())
result = true;
}
else if (w == FParser)
result = true;
return result;
}
void TagEditor::nextColumn()
{
if (w == Dirs)
{
Dirs->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = TagTypes;
TagTypes->setHighlightColor(Config.active_column_color);
}
else if (w == TagTypes && TagTypes->choice() < 13 && !Tags->reallyEmpty())
{
TagTypes->setHighlightColor(Config.main_highlight_color);
w->refresh();
w = Tags;
Tags->setHighlightColor(Config.active_column_color);
}
else if (w == FParser)
{
FParser->setBorder(Config.window_border);
FParser->display();
w = FParserHelper;
FParserHelper->setBorder(Config.active_window_border);
FParserHelper->display();
}
}
/***********************************************************************/
bool TagEditor::ifAnyModifiedAskForDiscarding()
{
bool result = true;
if (isAnyModified(*Tags))
result = Action::AskYesNoQuestion("There are pending changes, are you sure?", Status::trace);
return result;
} }
void TagEditor::LocateSong(const MPD::Song &s) void TagEditor::LocateSong(const MPD::Song &s)

View File

@@ -33,61 +33,60 @@
#include "regex_filter.h" #include "regex_filter.h"
#include "screen.h" #include "screen.h"
class TagEditor : public Screen<NC::Window>, public Filterable, public HasSongs, public Searchable class TagEditor : public Screen<NC::Window>, public Filterable, public HasColumns, public HasSongs, public Searchable
{ {
public: public:
TagEditor() : FParser(0), FParserHelper(0), FParserLegend(0), FParserPreview(0), itsBrowsedDir("/") { } TagEditor() : FParser(0), FParserHelper(0), FParserLegend(0), FParserPreview(0), itsBrowsedDir("/") { }
virtual void Resize(); virtual void Resize() OVERRIDE;
virtual void SwitchTo(); virtual void SwitchTo() OVERRIDE;
virtual std::wstring Title(); virtual std::wstring Title() OVERRIDE;
virtual void Refresh(); virtual void Refresh() OVERRIDE;
virtual void Update(); virtual void Update() OVERRIDE;
virtual void EnterPressed(); virtual void EnterPressed() OVERRIDE;
virtual void SpacePressed(); virtual void SpacePressed() OVERRIDE;
virtual void MouseButtonPressed(MEVENT); virtual void MouseButtonPressed(MEVENT) OVERRIDE;
virtual bool isTabbable() { return true; }
virtual bool isTabbable() OVERRIDE { return true; }
virtual bool isMergable() OVERRIDE { return true; }
// Filterable implementation // Filterable implementation
virtual bool allowsFiltering(); virtual bool allowsFiltering() OVERRIDE;
virtual std::string currentFilter(); virtual std::string currentFilter() OVERRIDE;
virtual void applyFilter(const std::string &filter); virtual void applyFilter(const std::string &filter) OVERRIDE;
// Searchable implementation // Searchable implementation
virtual bool allowsSearching(); virtual bool allowsSearching() OVERRIDE;
virtual bool search(const std::string &constraint); virtual bool search(const std::string &constraint) OVERRIDE;
virtual void nextFound(bool wrap); virtual void nextFound(bool wrap) OVERRIDE;
virtual void prevFound(bool wrap); virtual void prevFound(bool wrap) OVERRIDE;
// HasSongs implementation // HasSongs implementation
virtual std::shared_ptr<ProxySongList> getProxySongList(); virtual std::shared_ptr<ProxySongList> getProxySongList() OVERRIDE;
virtual bool allowsSelection(); virtual bool allowsSelection() OVERRIDE;
virtual void reverseSelection(); virtual void reverseSelection() OVERRIDE;
virtual MPD::SongList getSelectedSongs(); virtual MPD::SongList getSelectedSongs() OVERRIDE;
virtual bool isMergable() { return true; } // HasColumns implementation
virtual bool previousColumnAvailable() OVERRIDE;
virtual void previousColumn() OVERRIDE;
virtual bool nextColumnAvailable() OVERRIDE;
virtual void nextColumn() OVERRIDE;
// private members // private members
bool ifAnyModifiedAskForDiscarding(); bool ifAnyModifiedAskForDiscarding();
bool isNextColumnAvailable();
bool NextColumn();
bool isPrevColumnAvailable();
bool PrevColumn();
void LocateSong(const MPD::Song &s); void LocateSong(const MPD::Song &s);
const std::string &CurrentDir() { return itsBrowsedDir; }
NC::Menu< std::pair<std::string, std::string> > *Dirs; NC::Menu< std::pair<std::string, std::string> > *Dirs;
NC::Menu<std::string> *TagTypes; NC::Menu<std::string> *TagTypes;
NC::Menu<MPD::MutableSong> *Tags; NC::Menu<MPD::MutableSong> *Tags;
/// NOTICE: this string is always in utf8, no need to convert it
const std::string &CurrentDir() { return itsBrowsedDir; }
static void ReadTags(MPD::MutableSong &); static void ReadTags(MPD::MutableSong &);
static bool WriteTags(MPD::MutableSong &); static bool WriteTags(MPD::MutableSong &);