From 8b14ddb5e83ebb381072601656ef1000c05aebc5 Mon Sep 17 00:00:00 2001 From: casey Date: Thu, 2 Jun 2016 18:45:16 -0700 Subject: [PATCH] A couple small but important fixes: - Don't adjust scroll position in TrackListView after a requery if the query contents haven't actually changed - Ensure resizing doesn't lose the selected item in ListWindow - Added the concept of query hashes and generalized TrackListQueryBase so different types of queries can be supplied to a TrackListView. --- src/core/audio/Stream.h | 1 - src/musikbox/app/layout/LibraryLayout.cpp | 2 +- src/musikbox/app/query/TrackListQueryBase.h | 24 +++++++++++++++++++ src/musikbox/app/query/TrackListViewQuery.cpp | 18 ++++++++++++-- src/musikbox/app/query/TrackListViewQuery.h | 23 +++++++++--------- src/musikbox/app/window/CommandWindow.cpp | 19 ++++++++------- src/musikbox/app/window/TrackListView.cpp | 11 ++++++++- src/musikbox/app/window/TrackListView.h | 2 ++ src/musikbox/cursespp/ListWindow.cpp | 9 +++++++ src/musikbox/cursespp/ListWindow.h | 1 + src/musikbox/cursespp/ScrollableWindow.cpp | 8 ++++++- src/musikbox/musikbox.vcxproj | 1 + src/musikbox/musikbox.vcxproj.filters | 3 +++ 13 files changed, 95 insertions(+), 27 deletions(-) create mode 100755 src/musikbox/app/query/TrackListQueryBase.h diff --git a/src/core/audio/Stream.h b/src/core/audio/Stream.h index be4ee800d..991609e50 100644 --- a/src/core/audio/Stream.h +++ b/src/core/audio/Stream.h @@ -75,7 +75,6 @@ namespace musik { namespace core { namespace audio { BufferPtr GetEmptyBuffer(); void LoadDecoderPlugins(); - private: typedef std::list BufferList; typedef std::shared_ptr DecoderFactoryPtr; typedef std::vector DecoderFactoryList; diff --git a/src/musikbox/app/layout/LibraryLayout.cpp b/src/musikbox/app/layout/LibraryLayout.cpp index a3f52fd99..47d3c4b7b 100755 --- a/src/musikbox/app/layout/LibraryLayout.cpp +++ b/src/musikbox/app/layout/LibraryLayout.cpp @@ -17,7 +17,7 @@ using namespace musik::core::library::constants; #define TRANSPORT_HEIGHT 2 #endif -#define DEFAULT_CATEGORY constants::Track::ALBUM_ID +#define DEFAULT_CATEGORY constants::Track::ARTIST_ID using namespace musik::core; using namespace musik::core::audio; diff --git a/src/musikbox/app/query/TrackListQueryBase.h b/src/musikbox/app/query/TrackListQueryBase.h new file mode 100755 index 000000000..f59d3017c --- /dev/null +++ b/src/musikbox/app/query/TrackListQueryBase.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include +#include "CategoryListViewQuery.h" + +namespace musik { + namespace box { + class TrackListQueryBase : public musik::core::query::QueryBase { + public: + typedef std::shared_ptr< + std::vector > Result; + + typedef std::shared_ptr > Headers; + + virtual ~TrackListQueryBase() { }; + virtual std::string Name() = 0; + virtual Result GetResult() = 0; + virtual Headers GetHeaders() = 0; + virtual size_t GetQueryHash() = 0; + }; + } +} diff --git a/src/musikbox/app/query/TrackListViewQuery.cpp b/src/musikbox/app/query/TrackListViewQuery.cpp index 067e4767a..1437dd15d 100755 --- a/src/musikbox/app/query/TrackListViewQuery.cpp +++ b/src/musikbox/app/query/TrackListViewQuery.cpp @@ -21,6 +21,9 @@ TrackListViewQuery::TrackListViewQuery(LibraryPtr library, const std::string& co this->id = id; this->result.reset(new std::vector()); this->headers.reset(new std::set()); + this->hash = 0; + + this->GetQueryHash(); } TrackListViewQuery::~TrackListViewQuery() { @@ -35,13 +38,24 @@ TrackListViewQuery::Headers TrackListViewQuery::GetHeaders() { return this->headers; } +size_t TrackListViewQuery::GetQueryHash() { + if (this->hash == 0) { + std::string parts = boost::str( + boost::format("%s-%s") % this->column % this->id); + + this->hash = std::hash()(parts); + } + + return this->hash; +} + bool TrackListViewQuery::OnRun(Connection& db) { if (result) { result.reset(new std::vector()); headers.reset(new std::set()); } - std::string query = boost::str(boost::format( + this->query = boost::str(boost::format( "SELECT DISTINCT t.id, t.track, t.bpm, t.duration, t.filesize, t.year, t.title, t.filename, t.thumbnail_id, al.name AS album, gn.name AS genre, ar.name AS artist, t.filetime " \ "FROM tracks t, paths p, albums al, artists ar, genres gn " \ "WHERE t.%s=? AND t.album_id=al.id AND t.visual_genre_id=gn.id AND t.visual_artist_id=ar.id " @@ -50,7 +64,7 @@ bool TrackListViewQuery::OnRun(Connection& db) { std::string lastAlbum; size_t index = 0; - Statement trackQuery(query.c_str(), db); + Statement trackQuery(this->query.c_str(), db); trackQuery.BindInt(0, this->id); while (trackQuery.Step() == Row) { diff --git a/src/musikbox/app/query/TrackListViewQuery.h b/src/musikbox/app/query/TrackListViewQuery.h index ed18cae3d..ec4a25ce2 100755 --- a/src/musikbox/app/query/TrackListViewQuery.h +++ b/src/musikbox/app/query/TrackListViewQuery.h @@ -3,38 +3,37 @@ #include #include #include -#include "CategoryListViewQuery.h" + +#include "TrackListQueryBase.h" namespace musik { namespace box { - class TrackListViewQuery : public musik::core::query::QueryBase { + class TrackListViewQuery : public TrackListQueryBase { public: - typedef std::shared_ptr< - std::vector > Result; - - typedef std::shared_ptr > Headers; - TrackListViewQuery( musik::core::LibraryPtr library, - const std::string& column, DBID id); + const std::string& column, + DBID id); virtual ~TrackListViewQuery(); - std::string Name() { return "TrackListViewQuery"; } + virtual std::string Name() { return "TrackListViewQuery"; } virtual Result GetResult(); virtual Headers GetHeaders(); + virtual size_t GetQueryHash(); protected: virtual bool OnRun(musik::core::db::Connection &db); - Result result; - Headers headers; - private: musik::core::LibraryPtr library; + Result result; + Headers headers; std::string column; DBID id; + std::string query; + size_t hash; }; } } diff --git a/src/musikbox/app/window/CommandWindow.cpp b/src/musikbox/app/window/CommandWindow.cpp index 0bf316862..5ea7bd8ed 100755 --- a/src/musikbox/app/window/CommandWindow.cpp +++ b/src/musikbox/app/window/CommandWindow.cpp @@ -140,16 +140,18 @@ void CommandWindow::Help() { this->output->WriteLine(" console view", s); this->output->WriteLine(" library view", s); this->output->WriteLine("\n", s); - this->output->WriteLine(" play : play audio at location", s); + this->output->WriteLine(" addir : add a music directory", s); + this->output->WriteLine(" rmdir : remove a music directory", s); + this->output->WriteLine(" lsdirs: list scanned directories", s); + this->output->WriteLine(" rescan: rescan paths for new metadata", s); + this->output->WriteLine("\n", s); + this->output->WriteLine(" play : play audio at ", s); this->output->WriteLine(" pause: pause/resume", s); - this->output->WriteLine(" stop: stop all playback", s); + this->output->WriteLine(" stop: stop and clean up everything", s); this->output->WriteLine(" volume: <0 - 100>: set % volume", s); this->output->WriteLine(" clear: clear the log window", s); this->output->WriteLine(" seek : seek to into track", s); - this->output->WriteLine(" addir : add a directory to be indexed", s); - this->output->WriteLine(" rmdir : remove indexed directory path", s); - this->output->WriteLine(" lsdirs: list scanned directories", s); - this->output->WriteLine(" rescan: rescan paths for new metadata", s); + this->output->WriteLine("\n", s); this->output->WriteLine(" plugins: list loaded plugins", s); this->output->WriteLine("\n : quit\n", s); } @@ -254,10 +256,9 @@ void CommandWindow::ListPlugins() const { PluginList::iterator it = plugins.begin(); for (; it != plugins.end(); it++) { std::string format = - "plugin:\n" - " name: " + std::string((*it)->Name()) + " " + " " + std::string((*it)->Name()) + " " "v" + std::string((*it)->Version()) + "\n" - " author: " + std::string((*it)->Author()) + "\n"; + " by " + std::string((*it)->Author()) + "\n"; this->output->WriteLine(format, BOX_COLOR_RED_ON_BLUE); } diff --git a/src/musikbox/app/window/TrackListView.cpp b/src/musikbox/app/window/TrackListView.cpp index 5d67bab12..7a9abafde 100755 --- a/src/musikbox/app/window/TrackListView.cpp +++ b/src/musikbox/app/window/TrackListView.cpp @@ -37,6 +37,7 @@ TrackListView::TrackListView(PlaybackService& playback, LibraryPtr library) this->library->QueryCompleted.connect(this, &TrackListView::OnQueryCompleted); this->playback.TrackChanged.connect(this, &TrackListView::OnTrackChanged); this->adapter = new Adapter(*this); + this->lastQueryHash = 0; } TrackListView::~TrackListView() { @@ -71,8 +72,16 @@ void TrackListView::ProcessMessage(IMessage &message) { if (this->query && this->query->GetStatus() == IQuery::Finished) { this->metadata = this->query->GetResult(); this->headers = this->query->GetHeaders(); + + /* if the query was functionally the same as the last query, don't + mess with the selected index */ + if (this->lastQueryHash != query->GetQueryHash()) { + this->SetSelectedIndex(0); + } + + this->lastQueryHash = this->query->GetQueryHash(); this->query.reset(); - this->SetSelectedIndex(0); + this->OnAdapterChanged(); } } diff --git a/src/musikbox/app/window/TrackListView.h b/src/musikbox/app/window/TrackListView.h index 02e6e5a31..81cf551df 100755 --- a/src/musikbox/app/window/TrackListView.h +++ b/src/musikbox/app/window/TrackListView.h @@ -58,6 +58,8 @@ namespace musik { PlaybackService& playback; musik::core::TrackPtr playing; musik::core::LibraryPtr library; + + size_t lastQueryHash; }; } } diff --git a/src/musikbox/cursespp/ListWindow.cpp b/src/musikbox/cursespp/ListWindow.cpp index d72d526c1..e2919a2b1 100755 --- a/src/musikbox/cursespp/ListWindow.cpp +++ b/src/musikbox/cursespp/ListWindow.cpp @@ -152,6 +152,15 @@ void ListWindow::OnAdapterChanged() { this->Repaint(); } +void ListWindow::OnSizeChanged() { + ScrollableWindow::OnSizeChanged(); + + this->GetScrollAdapter().DrawPage( + this->GetContent(), + this->selectedIndex, + &this->GetScrollPosition()); +} + IScrollAdapter::ScrollPosition& ListWindow::GetScrollPosition() { return this->scrollPosition; } diff --git a/src/musikbox/cursespp/ListWindow.h b/src/musikbox/cursespp/ListWindow.h index 6a41cbd9c..1e874f98c 100755 --- a/src/musikbox/cursespp/ListWindow.h +++ b/src/musikbox/cursespp/ListWindow.h @@ -30,6 +30,7 @@ namespace cursespp { virtual void OnAdapterChanged(); virtual void OnSelectionChanged(size_t newIndex, size_t oldIndex); virtual void OnInvalidated(); + virtual void OnSizeChanged(); virtual IScrollAdapter::ScrollPosition& GetScrollPosition(); diff --git a/src/musikbox/cursespp/ScrollableWindow.cpp b/src/musikbox/cursespp/ScrollableWindow.cpp index cb7fd9d7f..65e346305 100755 --- a/src/musikbox/cursespp/ScrollableWindow.cpp +++ b/src/musikbox/cursespp/ScrollableWindow.cpp @@ -29,7 +29,13 @@ ScrollableWindow::~ScrollableWindow() { void ScrollableWindow::OnSizeChanged() { Window::OnSizeChanged(); - GetScrollAdapter().SetDisplaySize(GetContentWidth(), GetContentHeight()); + + IScrollAdapter& adapter = this->GetScrollAdapter(); + ScrollPos& pos = this->GetScrollPosition(); + + adapter.SetDisplaySize( + this->GetContentWidth(), + this->GetContentHeight()); } ScrollPos& ScrollableWindow::GetScrollPosition() { diff --git a/src/musikbox/musikbox.vcxproj b/src/musikbox/musikbox.vcxproj index 9d8f8b50d..cd01db48a 100755 --- a/src/musikbox/musikbox.vcxproj +++ b/src/musikbox/musikbox.vcxproj @@ -156,6 +156,7 @@ + diff --git a/src/musikbox/musikbox.vcxproj.filters b/src/musikbox/musikbox.vcxproj.filters index e537b1190..da947c46b 100755 --- a/src/musikbox/musikbox.vcxproj.filters +++ b/src/musikbox/musikbox.vcxproj.filters @@ -231,6 +231,9 @@ app\window + + app\query +