[UI] Added some stats on the track view
This commit is contained in:
@@ -113,6 +113,20 @@ Track::getUIQuery(Wt::Dbo::Session& session, SearchFilter filter)
|
||||
return query;
|
||||
}
|
||||
|
||||
Track::StatsQueryResult
|
||||
Track::getStats(Wt::Dbo::Session& session, SearchFilter filter)
|
||||
{
|
||||
SqlQuery sqlQuery = generatePartialQuery(filter);
|
||||
|
||||
Wt::Dbo::Query<StatsQueryResult> query = session.query<StatsQueryResult>( "SELECT COUNT(DISTINCT t.id), SUM(t.duration) FROM track t INNER JOIN artist a ON t.artist_id = a.id INNER JOIN genre g ON g.id = t_g.genre_id INNER JOIN track_genre t_g ON t_g.track_id = t.id INNER JOIN release r ON r.id = t.release_id " + sqlQuery.where().get());
|
||||
|
||||
for (const std::string& bindArg : sqlQuery.where().getBindArgs())
|
||||
query.bind(bindArg);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Track::pointer>
|
||||
Track::getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset, int size)
|
||||
{
|
||||
|
||||
@@ -105,10 +105,8 @@ class Track
|
||||
static pointer getByPath(Wt::Dbo::Session& session, const boost::filesystem::path& p);
|
||||
static pointer getById(Wt::Dbo::Session& session, id_type id);
|
||||
static pointer getByMBID(Wt::Dbo::Session& session, const std::string& MBID);
|
||||
static Wt::Dbo::collection< pointer > getAll(Wt::Dbo::Session& session);
|
||||
|
||||
// Used for remote
|
||||
static std::vector<pointer> getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset = -1, int size = -1);
|
||||
static Wt::Dbo::collection< pointer > getAll(Wt::Dbo::Session& session);
|
||||
|
||||
// Utility fonctions
|
||||
// MVC models for the user interface
|
||||
@@ -127,6 +125,13 @@ class Track
|
||||
static Wt::Dbo::Query< UIQueryResult > getUIQuery(Wt::Dbo::Session& session, SearchFilter filter);
|
||||
static void updateUIQueryModel(Wt::Dbo::Session& session, Wt::Dbo::QueryModel< UIQueryResult >& model, SearchFilter filter, const std::vector<Wt::WString>& columnNames = std::vector<Wt::WString>());
|
||||
|
||||
// Stats for a given search filter
|
||||
typedef boost::tuple<
|
||||
int, // Total tracks
|
||||
boost::posix_time::time_duration // Total duration
|
||||
> StatsQueryResult;
|
||||
static StatsQueryResult getStats(Wt::Dbo::Session& session, SearchFilter filter);
|
||||
|
||||
// Create utility
|
||||
static pointer create(Wt::Dbo::Session& session, const boost::filesystem::path& p);
|
||||
|
||||
|
||||
@@ -102,8 +102,13 @@ _playQueue(nullptr)
|
||||
Wt::WPushButton* addBtn = new Wt::WPushButton("Add");
|
||||
addBtn->setStyleClass("btn-sm");
|
||||
trackControls->addWidget(addBtn);
|
||||
trackControls->addWidget(new Wt::WText("Total duration: "), 1);
|
||||
|
||||
Wt::WText *statsText = new Wt::WText();
|
||||
statsText->setStyleClass("vertical-align");
|
||||
trackControls->addWidget(statsText, 1);
|
||||
_trackView->statsUpdated().connect(std::bind([=] (Wt::WString stats) {
|
||||
statsText->setText(stats);
|
||||
}, std::placeholders::_1));
|
||||
|
||||
trackLayout->addLayout(trackControls);
|
||||
|
||||
@@ -111,6 +116,7 @@ _playQueue(nullptr)
|
||||
|
||||
_filterChain.addFilter(_trackView);
|
||||
|
||||
|
||||
_playQueue = new PlayQueue();
|
||||
|
||||
// Playlist/PlayQueue
|
||||
@@ -216,6 +222,9 @@ _playQueue(nullptr)
|
||||
|
||||
|
||||
playlistRefreshMenus();
|
||||
|
||||
// Initially, search for everything
|
||||
_filterChain.searchKeyword("");
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -30,14 +30,6 @@ namespace Desktop {
|
||||
class Filter
|
||||
{
|
||||
public:
|
||||
|
||||
struct Constraint {
|
||||
std::vector<std::string> search;
|
||||
|
||||
typedef std::map<std::string, std::vector<std::string> > ColumnValues;
|
||||
ColumnValues columnValues;
|
||||
};
|
||||
|
||||
Filter() {}
|
||||
virtual ~Filter() {}
|
||||
|
||||
|
||||
@@ -501,7 +501,7 @@ PlayQueue::delSelected(void)
|
||||
int minId = _model->rowCount();
|
||||
Wt::WModelIndexSet indexSet = this->selectedIndexes();
|
||||
|
||||
BOOST_REVERSE_FOREACH(Wt::WModelIndex index, indexSet)
|
||||
for (Wt::WModelIndex index : indexSet)
|
||||
{
|
||||
_model->removeRow(index.row());
|
||||
if (index.row() < minId)
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <Wt/WItemDelegate>
|
||||
|
||||
#include "database/Types.hpp"
|
||||
@@ -163,8 +161,8 @@ TableFilterArtist::getConstraint(SearchFilter& filter)
|
||||
{
|
||||
Wt::WModelIndexSet indexSet = this->selectedIndexes();
|
||||
|
||||
BOOST_FOREACH(Wt::WModelIndex index, indexSet) {
|
||||
|
||||
for (Wt::WModelIndex index : indexSet)
|
||||
{
|
||||
if (!index.isValid())
|
||||
continue;
|
||||
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <Wt/WItemDelegate>
|
||||
#include <Wt/WBreak>
|
||||
|
||||
@@ -31,6 +28,8 @@
|
||||
namespace UserInterface {
|
||||
namespace Desktop {
|
||||
|
||||
using namespace Database;
|
||||
|
||||
TrackView::TrackView(Wt::WContainerWidget* parent)
|
||||
: Wt::WTableView( parent )
|
||||
{
|
||||
@@ -48,9 +47,9 @@ TrackView::TrackView(Wt::WContainerWidget* parent)
|
||||
"Genres",
|
||||
};
|
||||
|
||||
Database::SearchFilter filter;
|
||||
SearchFilter filter;
|
||||
|
||||
Database::Track::updateUIQueryModel(DboSession(), _queryModel, filter, columnNames);
|
||||
Track::updateUIQueryModel(DboSession(), _queryModel, filter, columnNames);
|
||||
|
||||
_queryModel.setBatchSize(300);
|
||||
|
||||
@@ -107,15 +106,47 @@ TrackView::TrackView(Wt::WContainerWidget* parent)
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
TrackView::emitStats(const SearchFilter& filter)
|
||||
{
|
||||
Wt::Dbo::Transaction transaction (DboSession());
|
||||
|
||||
// Update stats on the view
|
||||
Track::StatsQueryResult stats = Track::getStats(DboSession(), filter);
|
||||
|
||||
transaction.commit();
|
||||
|
||||
int nbTracks = stats.get<0>();
|
||||
boost::posix_time::time_duration totalDuration = stats.get<1>();
|
||||
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << nbTracks << " track" << (nbTracks > 1 ? "s" : "") << ", ";
|
||||
|
||||
if (totalDuration.hours() >= 24)
|
||||
{
|
||||
auto days = totalDuration.hours() / 24;
|
||||
oss << days << " day" << (days > 1 ? "s " : " ");
|
||||
}
|
||||
|
||||
oss << std::setw(2) << std::setfill('0') << totalDuration.hours() % 24
|
||||
<< ":" << std::setw(2) << std::setfill('0') << totalDuration.minutes()
|
||||
<< ":" << std::setw(2) << std::setfill('0') << totalDuration.seconds();
|
||||
|
||||
_sigStatsUpdated.emit(Wt::WString(oss.str()));
|
||||
}
|
||||
|
||||
// Set constraints created by parent filters
|
||||
void
|
||||
TrackView::refresh(Database::SearchFilter& filter)
|
||||
TrackView::refresh(SearchFilter& filter)
|
||||
{
|
||||
Database::Track::updateUIQueryModel(DboSession(), _queryModel, filter);
|
||||
Track::updateUIQueryModel(DboSession(), _queryModel, filter);
|
||||
|
||||
emitStats(filter);
|
||||
}
|
||||
|
||||
void
|
||||
TrackView::getSelectedTracks(std::vector<Database::Track::id_type>& track_ids)
|
||||
TrackView::getSelectedTracks(std::vector<Track::id_type>& track_ids)
|
||||
{
|
||||
LMS_LOG(MOD_UI, SEV_DEBUG) << "Getting selected tracks...";
|
||||
|
||||
@@ -126,7 +157,7 @@ TrackView::getSelectedTracks(std::vector<Database::Track::id_type>& track_ids)
|
||||
if (!index.isValid())
|
||||
continue;
|
||||
|
||||
Database::Track::id_type id = _queryModel.resultRow( index.row() ).get<0>();
|
||||
Track::id_type id = _queryModel.resultRow( index.row() ).get<0>();
|
||||
|
||||
track_ids.push_back(id);
|
||||
}
|
||||
@@ -157,16 +188,16 @@ TrackView::getFirstSelectedTrackPosition(void)
|
||||
}
|
||||
|
||||
void
|
||||
TrackView::getTracks(std::vector<Database::Track::id_type>& trackIds)
|
||||
TrackView::getTracks(std::vector<Track::id_type>& trackIds)
|
||||
{
|
||||
LMS_LOG(MOD_UI, SEV_DEBUG) << "Getting all tracks...";
|
||||
|
||||
Wt::Dbo::Transaction transaction(DboSession());
|
||||
Wt::Dbo::collection<Database::Track::UIQueryResult> results = _queryModel.query();
|
||||
Wt::Dbo::collection<Track::UIQueryResult> results = _queryModel.query();
|
||||
|
||||
for (auto it = results.begin(); it != results.end(); ++it)
|
||||
{
|
||||
Database::Track::id_type id = it->get<0>();
|
||||
Track::id_type id = it->get<0>();
|
||||
trackIds.push_back(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,12 +55,17 @@ class TrackView : public Wt::WTableView, public Filter
|
||||
void getTracks(std::vector<Database::Track::id_type>& track_ids);
|
||||
|
||||
typedef Wt::Signal<void> SigTrackDoubleClicked;
|
||||
typedef Wt::Signal<Wt::WString> SigStatsUpdated;
|
||||
|
||||
SigTrackDoubleClicked& trackDoubleClicked() { return _sigTrackDoubleClicked; }
|
||||
SigStatsUpdated& statsUpdated() { return _sigStatsUpdated; }
|
||||
|
||||
private:
|
||||
|
||||
SigTrackDoubleClicked _sigTrackDoubleClicked;
|
||||
SigStatsUpdated _sigStatsUpdated;
|
||||
|
||||
void emitStats(const Database::SearchFilter& filter);
|
||||
|
||||
typedef Database::Track::UIQueryResult ResultType;
|
||||
Wt::Dbo::QueryModel< ResultType > _queryModel;
|
||||
|
||||
Reference in New Issue
Block a user