Somewhat-working smart playlist preview widget for the wizard. Still needs a lot of polish.
This commit is contained in:
parent
fb224608ae
commit
2a480f7b1c
|
@ -133,6 +133,8 @@ set(SOURCES
|
|||
smartplaylists/playlistgeneratorinserter.cpp
|
||||
smartplaylists/smartplaylistcontainer.cpp
|
||||
smartplaylists/smartplaylistmodel.cpp
|
||||
smartplaylists/smartplaylistsearch.cpp
|
||||
smartplaylists/smartplaylistsearchpreview.cpp
|
||||
smartplaylists/smartplaylistsearchterm.cpp
|
||||
smartplaylists/smartplaylistsearchtermwidget.cpp
|
||||
smartplaylists/smartplaylistview.cpp
|
||||
|
@ -293,6 +295,7 @@ set(HEADERS
|
|||
smartplaylists/playlistgeneratorinserter.h
|
||||
smartplaylists/smartplaylistcontainer.h
|
||||
smartplaylists/smartplaylistmodel.h
|
||||
smartplaylists/smartplaylistsearchpreview.h
|
||||
smartplaylists/smartplaylistsearchtermwidget.h
|
||||
smartplaylists/smartplaylistview.h
|
||||
smartplaylists/smartplaylistwizard.h
|
||||
|
@ -378,6 +381,7 @@ set(UI
|
|||
radio/radioviewcontainer.ui
|
||||
|
||||
smartplaylists/smartplaylistcontainer.ui
|
||||
smartplaylists/smartplaylistsearchpreview.ui
|
||||
smartplaylists/smartplaylistsearchtermwidget.ui
|
||||
smartplaylists/smartplaylistwizard.ui
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "sqlrow.h"
|
||||
#include "core/database.h"
|
||||
#include "core/scopedtransaction.h"
|
||||
#include "smartplaylists/smartplaylistsearch.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QVariant>
|
||||
|
@ -808,16 +809,13 @@ bool LibraryBackend::ExecQuery(LibraryQuery *q) {
|
|||
return !db_->CheckErrors(q->Exec(db_->Connect(), songs_table_, fts_table_));
|
||||
}
|
||||
|
||||
SongList LibraryBackend::FindSongs(const QString& where_sql,
|
||||
const QString& order_sql, int limit) {
|
||||
SongList LibraryBackend::FindSongs(const SmartPlaylistSearch& search) {
|
||||
QMutexLocker l(db_->Mutex());
|
||||
QSqlDatabase db(db_->Connect());
|
||||
|
||||
// Build the query
|
||||
QString sql = "SELECT ROWID, " + Song::kColumnSpec + " FROM " + songs_table_;
|
||||
if (!where_sql.isEmpty()) sql += " WHERE " + where_sql;
|
||||
if (!order_sql.isEmpty()) sql += " ORDER BY " + order_sql;
|
||||
if (limit) sql += " LIMIT " + QString::number(limit);
|
||||
QString sql = search.ToSql(songs_table());
|
||||
qDebug() << sql;
|
||||
|
||||
// Run the query
|
||||
SongList ret;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
class Database;
|
||||
class SmartPlaylistSearch;
|
||||
|
||||
class LibraryBackendInterface : public QObject {
|
||||
public:
|
||||
|
@ -131,7 +132,7 @@ class LibraryBackend : public LibraryBackendInterface {
|
|||
void RemoveDirectory(const Directory& dir);
|
||||
|
||||
bool ExecQuery(LibraryQuery* q);
|
||||
SongList FindSongs(const QString& where_sql, const QString& order_sql, int limit);
|
||||
SongList FindSongs(const SmartPlaylistSearch& search);
|
||||
|
||||
void IncrementPlayCountAsync(int id);
|
||||
void IncrementSkipCountAsync(int id);
|
||||
|
|
|
@ -19,19 +19,14 @@
|
|||
|
||||
#include <QSettings>
|
||||
|
||||
const int PlaylistGenerator::kDefaultLimit = 15;
|
||||
const int PlaylistGenerator::kDefaultLimit = 20;
|
||||
|
||||
PlaylistGenerator::PlaylistGenerator()
|
||||
: QObject(NULL),
|
||||
backend_(NULL),
|
||||
limit_(kDefaultLimit)
|
||||
backend_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void PlaylistGenerator::Load(const QSettings& s) {
|
||||
limit_ = s.value("limit", kDefaultLimit).toInt();
|
||||
}
|
||||
|
||||
PlaylistGeneratorPtr PlaylistGenerator::Create(const QString& type) {
|
||||
if (type == "Query")
|
||||
return PlaylistGeneratorPtr(new QueryPlaylistGenerator);
|
||||
|
|
|
@ -38,10 +38,9 @@ public:
|
|||
|
||||
void set_library(LibraryBackend* backend) { backend_ = backend; }
|
||||
|
||||
int limit() const { return limit_; }
|
||||
QString name() const { return name_; }
|
||||
|
||||
virtual void Load(const QSettings& s);
|
||||
virtual void Load(const QSettings& s) {}
|
||||
virtual PlaylistItemList Generate() = 0;
|
||||
|
||||
signals:
|
||||
|
@ -50,7 +49,6 @@ signals:
|
|||
protected:
|
||||
LibraryBackend* backend_;
|
||||
|
||||
int limit_;
|
||||
QString name_;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,15 +25,19 @@ QueryPlaylistGenerator::QueryPlaylistGenerator()
|
|||
{
|
||||
}
|
||||
|
||||
void QueryPlaylistGenerator::Load(const SmartPlaylistSearch& search) {
|
||||
search_ = search;
|
||||
}
|
||||
|
||||
void QueryPlaylistGenerator::Load(const QSettings& s) {
|
||||
PlaylistGenerator::Load(s);
|
||||
name_ = s.value("name").toString();
|
||||
where_ = s.value("where").toString();
|
||||
order_ = s.value("order").toString();
|
||||
|
||||
QDataStream stream(s.value("search").toByteArray());
|
||||
stream >> search_;
|
||||
}
|
||||
|
||||
PlaylistItemList QueryPlaylistGenerator::Generate() {
|
||||
SongList songs = backend_->FindSongs(where_, order_, limit_);
|
||||
SongList songs = backend_->FindSongs(search_);
|
||||
|
||||
PlaylistItemList items;
|
||||
foreach (const Song& song, songs) {
|
||||
|
|
|
@ -18,17 +18,18 @@
|
|||
#define QUERYPLAYLISTGENERATOR_H
|
||||
|
||||
#include "playlistgenerator.h"
|
||||
#include "smartplaylistsearch.h"
|
||||
|
||||
class QueryPlaylistGenerator : public PlaylistGenerator {
|
||||
public:
|
||||
QueryPlaylistGenerator();
|
||||
|
||||
void Load(const SmartPlaylistSearch& search);
|
||||
void Load(const QSettings& s);
|
||||
PlaylistItemList Generate();
|
||||
|
||||
private:
|
||||
QString where_;
|
||||
QString order_;
|
||||
SmartPlaylistSearch search_;
|
||||
};
|
||||
|
||||
#endif // QUERYPLAYLISTGENERATOR_H
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/* This file is part of Clementine.
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "smartplaylistsearch.h"
|
||||
#include "core/song.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
SmartPlaylistSearch::SmartPlaylistSearch() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
void SmartPlaylistSearch::Reset() {
|
||||
terms_.clear();
|
||||
sort_type_ = Sort_Random;
|
||||
sort_field_ = SmartPlaylistSearchTerm::Field_Title;
|
||||
limit_ = -1;
|
||||
}
|
||||
|
||||
QString SmartPlaylistSearch::ToSql(const QString& songs_table) const {
|
||||
QString sql = "SELECT ROWID," + Song::kColumnSpec + " FROM " + songs_table;
|
||||
|
||||
// Add search terms
|
||||
QStringList term_sql;
|
||||
foreach (const SmartPlaylistSearchTerm& term, terms_) {
|
||||
term_sql += term.ToSql();
|
||||
}
|
||||
if (!terms_.isEmpty()) {
|
||||
sql += " WHERE " + term_sql.join(" AND ");
|
||||
}
|
||||
|
||||
// Add sort by
|
||||
if (sort_type_ == Sort_Random) {
|
||||
sql += " ORDER BY random()";
|
||||
} else {
|
||||
sql += " ORDER BY " + SmartPlaylistSearchTerm::FieldColumnName(sort_field_)
|
||||
+ (sort_type_ == Sort_FieldAsc ? " ASC" : " DESC");
|
||||
}
|
||||
|
||||
// Add limit
|
||||
if (limit_ != -1) {
|
||||
sql += " LIMIT " + QString::number(limit_);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
QDataStream& operator <<(QDataStream& s, const SmartPlaylistSearch& search) {
|
||||
s << search.terms_;
|
||||
s << quint8(search.sort_type_);
|
||||
s << quint8(search.sort_field_);
|
||||
s << qint32(search.limit_);
|
||||
return s;
|
||||
}
|
||||
|
||||
QDataStream& operator >>(QDataStream& s, SmartPlaylistSearch& search) {
|
||||
quint8 sort_type, sort_field;
|
||||
qint32 limit;
|
||||
|
||||
s >> search.terms_ >> sort_type >> sort_field >> limit;
|
||||
search.sort_type_ = SmartPlaylistSearch::SortType(sort_type);
|
||||
search.sort_field_ = SmartPlaylistSearchTerm::Field(sort_field);
|
||||
search.limit_ = limit;
|
||||
|
||||
return s;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* This file is part of Clementine.
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SMARTPLAYLISTSEARCH_H
|
||||
#define SMARTPLAYLISTSEARCH_H
|
||||
|
||||
#include "smartplaylistsearchterm.h"
|
||||
|
||||
class SmartPlaylistSearch {
|
||||
public:
|
||||
SmartPlaylistSearch();
|
||||
|
||||
// These values are persisted, so add to the end of the enum only
|
||||
enum SortType {
|
||||
Sort_Random = 0,
|
||||
Sort_FieldAsc,
|
||||
Sort_FieldDesc,
|
||||
};
|
||||
|
||||
bool is_valid() const { return !terms_.isEmpty(); }
|
||||
|
||||
QList<SmartPlaylistSearchTerm> terms_;
|
||||
SortType sort_type_;
|
||||
SmartPlaylistSearchTerm::Field sort_field_;
|
||||
int limit_;
|
||||
|
||||
void Reset();
|
||||
QString ToSql(const QString& songs_table) const;
|
||||
};
|
||||
|
||||
QDataStream& operator <<(QDataStream& s, const SmartPlaylistSearch& search);
|
||||
QDataStream& operator >>(QDataStream& s, SmartPlaylistSearch& search);
|
||||
|
||||
#endif // SMARTPLAYLISTSEARCH_H
|
|
@ -0,0 +1,125 @@
|
|||
/* This file is part of Clementine.
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "queryplaylistgenerator.h"
|
||||
#include "smartplaylistsearchpreview.h"
|
||||
#include "ui_smartplaylistsearchpreview.h"
|
||||
#include "playlist/playlistdelegates.h"
|
||||
|
||||
#include <QFutureWatcher>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
typedef QFuture<PlaylistItemList> Future;
|
||||
typedef QFutureWatcher<PlaylistItemList> FutureWatcher;
|
||||
|
||||
SmartPlaylistSearchPreview::SmartPlaylistSearchPreview(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
ui_(new Ui_SmartPlaylistSearchPreview)
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
|
||||
QFont bold_font;
|
||||
bold_font.setBold(true);
|
||||
ui_->preview_label->setFont(bold_font);
|
||||
ui_->busy_container->hide();
|
||||
|
||||
fields_ << SmartPlaylistSearchTerm::Field_Artist;
|
||||
fields_ << SmartPlaylistSearchTerm::Field_Album;
|
||||
fields_ << SmartPlaylistSearchTerm::Field_Title;
|
||||
fields_ << SmartPlaylistSearchTerm::Field_Length;
|
||||
fields_ << SmartPlaylistSearchTerm::Field_PlayCount;
|
||||
fields_ << SmartPlaylistSearchTerm::Field_SkipCount;
|
||||
fields_ << SmartPlaylistSearchTerm::Field_Rating;
|
||||
|
||||
QStringList column_names;
|
||||
foreach (SmartPlaylistSearchTerm::Field field, fields_) {
|
||||
column_names << SmartPlaylistSearchTerm::FieldName(field);
|
||||
}
|
||||
ui_->tree->setHeaderLabels(column_names);
|
||||
|
||||
ui_->tree->setItemDelegateForColumn(0, new TextItemDelegate(this));
|
||||
ui_->tree->setItemDelegateForColumn(1, new TextItemDelegate(this));
|
||||
ui_->tree->setItemDelegateForColumn(2, new TextItemDelegate(this));
|
||||
ui_->tree->setItemDelegateForColumn(3, new LengthItemDelegate(this));
|
||||
ui_->tree->setItemDelegateForColumn(6, new RatingItemDelegate(this));
|
||||
}
|
||||
|
||||
SmartPlaylistSearchPreview::~SmartPlaylistSearchPreview() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void SmartPlaylistSearchPreview::set_library(LibraryBackend* backend) {
|
||||
backend_ = backend;
|
||||
}
|
||||
|
||||
void SmartPlaylistSearchPreview::Update(const SmartPlaylistSearch& search) {
|
||||
if (generator_) {
|
||||
// It's busy generating something already
|
||||
pending_search_ = search;
|
||||
return;
|
||||
}
|
||||
|
||||
RunSearch(search);
|
||||
}
|
||||
|
||||
void SmartPlaylistSearchPreview::RunSearch(const SmartPlaylistSearch& search) {
|
||||
generator_.reset(new QueryPlaylistGenerator);
|
||||
generator_->set_library(backend_);
|
||||
generator_->Load(search);
|
||||
|
||||
ui_->busy_container->show();
|
||||
ui_->count_label->hide();
|
||||
Future future = QtConcurrent::run(generator_.get(), &QueryPlaylistGenerator::Generate);
|
||||
|
||||
FutureWatcher* watcher = new FutureWatcher(this);
|
||||
watcher->setFuture(future);
|
||||
connect(watcher, SIGNAL(finished()), SLOT(SearchFinished()));
|
||||
}
|
||||
|
||||
void SmartPlaylistSearchPreview::SearchFinished() {
|
||||
FutureWatcher* watcher = static_cast<FutureWatcher*>(sender());
|
||||
watcher->deleteLater();
|
||||
generator_.reset();
|
||||
|
||||
PlaylistItemList items = watcher->result();
|
||||
int count = 0;
|
||||
|
||||
ui_->tree->clear();
|
||||
foreach (PlaylistItemPtr item, items) {
|
||||
if (count >= PlaylistGenerator::kDefaultLimit)
|
||||
break;
|
||||
count ++;
|
||||
|
||||
QTreeWidgetItem* tree_item = new QTreeWidgetItem;
|
||||
tree_item->setData(0, Qt::DisplayRole, item->Metadata().album());
|
||||
tree_item->setData(1, Qt::DisplayRole, item->Metadata().artist());
|
||||
tree_item->setData(2, Qt::DisplayRole, item->Metadata().title());
|
||||
tree_item->setData(3, Qt::DisplayRole, item->Metadata().length());
|
||||
tree_item->setData(4, Qt::DisplayRole, item->Metadata().playcount());
|
||||
tree_item->setData(5, Qt::DisplayRole, item->Metadata().skipcount());
|
||||
tree_item->setData(6, Qt::DisplayRole, item->Metadata().rating());
|
||||
ui_->tree->addTopLevelItem(tree_item);
|
||||
}
|
||||
|
||||
if (items.count() > count) {
|
||||
ui_->count_label->setText(tr("%1 songs found (showing %2)").arg(items.count()).arg(count));
|
||||
} else {
|
||||
ui_->count_label->setText(tr("%1 songs found").arg(items.count()));
|
||||
}
|
||||
|
||||
ui_->busy_container->hide();
|
||||
ui_->count_label->show();
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* This file is part of Clementine.
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SMARTPLAYLISTSEARCHPREVIEW_H
|
||||
#define SMARTPLAYLISTSEARCHPREVIEW_H
|
||||
|
||||
#include "smartplaylistsearch.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
class LibraryBackend;
|
||||
class QueryPlaylistGenerator;
|
||||
class Ui_SmartPlaylistSearchPreview;
|
||||
|
||||
class SmartPlaylistSearchPreview : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SmartPlaylistSearchPreview(QWidget *parent = 0);
|
||||
~SmartPlaylistSearchPreview();
|
||||
|
||||
void set_library(LibraryBackend* backend);
|
||||
|
||||
void Update(const SmartPlaylistSearch& search);
|
||||
|
||||
private:
|
||||
void RunSearch(const SmartPlaylistSearch& search);
|
||||
|
||||
private slots:
|
||||
void SearchFinished();
|
||||
|
||||
private:
|
||||
Ui_SmartPlaylistSearchPreview* ui_;
|
||||
QList<SmartPlaylistSearchTerm::Field> fields_;
|
||||
|
||||
LibraryBackend* backend_;
|
||||
|
||||
SmartPlaylistSearch pending_search_;
|
||||
boost::scoped_ptr<QueryPlaylistGenerator> generator_;
|
||||
};
|
||||
|
||||
#endif // SMARTPLAYLISTSEARCHPREVIEW_H
|
|
@ -0,0 +1,96 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SmartPlaylistSearchPreview</class>
|
||||
<widget class="QWidget" name="SmartPlaylistSearchPreview">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>651</width>
|
||||
<height>377</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="preview_label">
|
||||
<property name="text">
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="count_label"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="busy_container" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="BusyIndicator" name="widget" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Loading...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="tree">
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BusyIndicator</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/busyindicator.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -46,6 +46,17 @@ QString SmartPlaylistSearchTerm::ToSql() const {
|
|||
return QString();
|
||||
}
|
||||
|
||||
bool SmartPlaylistSearchTerm::is_valid() const {
|
||||
switch (TypeOf(field_)) {
|
||||
case Type_Text: return !value_.toString().isEmpty();
|
||||
case Type_Date: return value_.toInt() != 0;
|
||||
case Type_Number: return value_.toInt() >= 0;
|
||||
case Type_Rating: return value_.toFloat() >= 0.0;
|
||||
case Type_Time: return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SmartPlaylistSearchTerm::Type SmartPlaylistSearchTerm::TypeOf(Field field) {
|
||||
switch (field) {
|
||||
case Field_Length:
|
||||
|
|
|
@ -80,6 +80,7 @@ public:
|
|||
QVariant value_;
|
||||
|
||||
QString ToSql() const;
|
||||
bool is_valid() const;
|
||||
|
||||
static Type TypeOf(Field field);
|
||||
static QList<Operator> OperatorsForType(Type type);
|
||||
|
|
|
@ -70,6 +70,13 @@ SmartPlaylistSearchTermWidget::SmartPlaylistSearchTermWidget(LibraryBackend* lib
|
|||
connect(ui_->field, SIGNAL(currentIndexChanged(int)), SLOT(FieldChanged(int)));
|
||||
connect(ui_->remove, SIGNAL(clicked()), SIGNAL(RemoveClicked()));
|
||||
|
||||
connect(ui_->field, SIGNAL(currentIndexChanged(int)), SIGNAL(Changed()));
|
||||
connect(ui_->value_date, SIGNAL(dateChanged(QDate)), SIGNAL(Changed()));
|
||||
connect(ui_->value_number, SIGNAL(valueChanged(int)), SIGNAL(Changed()));
|
||||
connect(ui_->value_rating, SIGNAL(RatingChanged(float)), SIGNAL(Changed()));
|
||||
connect(ui_->value_text, SIGNAL(textChanged(QString)), SIGNAL(Changed()));
|
||||
connect(ui_->value_time, SIGNAL(timeChanged(QTime)), SIGNAL(Changed()));
|
||||
|
||||
// Populate the combo boxes
|
||||
for (int i=0 ; i<SmartPlaylistSearchTerm::FieldCount ; ++i) {
|
||||
ui_->field->addItem(SmartPlaylistSearchTerm::FieldName(SmartPlaylistSearchTerm::Field(i)));
|
||||
|
|
|
@ -48,6 +48,8 @@ signals:
|
|||
void Clicked();
|
||||
void RemoveClicked();
|
||||
|
||||
void Changed();
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent*);
|
||||
void enterEvent(QEvent*);
|
||||
|
|
|
@ -14,10 +14,24 @@
|
|||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "smartplaylistsearchpreview.h"
|
||||
#include "smartplaylistsearchtermwidget.h"
|
||||
#include "smartplaylistwizard.h"
|
||||
#include "ui_smartplaylistwizard.h"
|
||||
|
||||
SmartPlaylistWizard::SearchPage::SearchPage(QWidget* parent)
|
||||
: QWizardPage(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool SmartPlaylistWizard::SearchPage::isComplete() const {
|
||||
foreach (SmartPlaylistSearchTermWidget* widget, terms_) {
|
||||
if (!widget->Term().is_valid())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SmartPlaylistWizard::SmartPlaylistWizard(LibraryBackend* library, QWidget* parent)
|
||||
: QWizard(parent),
|
||||
ui_(new Ui_SmartPlaylistWizard),
|
||||
|
@ -25,14 +39,21 @@ SmartPlaylistWizard::SmartPlaylistWizard(LibraryBackend* library, QWidget* paren
|
|||
{
|
||||
ui_->setupUi(this);
|
||||
|
||||
new_search_term_ = new SmartPlaylistSearchTermWidget(library_, this);
|
||||
new_search_term_->SetActive(false);
|
||||
connect(new_search_term_, SIGNAL(Clicked()), SLOT(AddSearchTerm()));
|
||||
// Create the new search term widget
|
||||
ui_->page_query_search->new_term_ = new SmartPlaylistSearchTermWidget(library_, this);
|
||||
ui_->page_query_search->new_term_->SetActive(false);
|
||||
connect(ui_->page_query_search->new_term_, SIGNAL(Clicked()), SLOT(AddSearchTerm()));
|
||||
|
||||
search_term_layout_ = new QVBoxLayout(ui_->page_query_search);
|
||||
search_term_layout_->addWidget(new_search_term_);
|
||||
search_term_layout_->addStretch();
|
||||
// Add an empty initial term
|
||||
ui_->page_query_search->layout_ = new QVBoxLayout(ui_->page_query_search);
|
||||
ui_->page_query_search->layout_->addWidget(ui_->page_query_search->new_term_);
|
||||
ui_->page_query_search->layout_->addStretch();
|
||||
AddSearchTerm();
|
||||
|
||||
// Add the preview widget at the bottom
|
||||
ui_->page_query_search->preview_ = new SmartPlaylistSearchPreview(this);
|
||||
ui_->page_query_search->preview_->set_library(library_);
|
||||
ui_->page_query_search->layout_->addWidget(ui_->page_query_search->preview_);
|
||||
}
|
||||
|
||||
SmartPlaylistWizard::~SmartPlaylistWizard() {
|
||||
|
@ -43,9 +64,13 @@ void SmartPlaylistWizard::AddSearchTerm() {
|
|||
SmartPlaylistSearchTermWidget* widget =
|
||||
new SmartPlaylistSearchTermWidget(library_, this);
|
||||
connect(widget, SIGNAL(RemoveClicked()), SLOT(RemoveSearchTerm()));
|
||||
connect(widget, SIGNAL(Changed()), SLOT(UpdateTermPreview()));
|
||||
|
||||
search_term_layout_->insertWidget(search_terms_.count(), widget);
|
||||
search_terms_ << widget;
|
||||
ui_->page_query_search->layout_->insertWidget(
|
||||
ui_->page_query_search->terms_.count(), widget);
|
||||
ui_->page_query_search->terms_ << widget;
|
||||
|
||||
UpdateTermPreview();
|
||||
}
|
||||
|
||||
void SmartPlaylistWizard::RemoveSearchTerm() {
|
||||
|
@ -54,10 +79,33 @@ void SmartPlaylistWizard::RemoveSearchTerm() {
|
|||
if (!widget)
|
||||
return;
|
||||
|
||||
const int index = search_terms_.indexOf(widget);
|
||||
const int index = ui_->page_query_search->terms_.indexOf(widget);
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
delete search_terms_.takeAt(index);
|
||||
delete ui_->page_query_search->terms_.takeAt(index);
|
||||
UpdateTermPreview();
|
||||
}
|
||||
|
||||
void SmartPlaylistWizard::UpdateTermPreview() {
|
||||
SmartPlaylistSearch search = MakeSearch();
|
||||
emit ui_->page_query_search->completeChanged();
|
||||
if (!search.is_valid())
|
||||
return;
|
||||
|
||||
ui_->page_query_search->preview_->Update(search);
|
||||
}
|
||||
|
||||
SmartPlaylistSearch SmartPlaylistWizard::MakeSearch() const {
|
||||
SmartPlaylistSearch ret;
|
||||
|
||||
foreach (SmartPlaylistSearchTermWidget* widget, ui_->page_query_search->terms_) {
|
||||
SmartPlaylistSearchTerm term = widget->Term();
|
||||
if (!term.is_valid())
|
||||
return SmartPlaylistSearch();
|
||||
|
||||
ret.terms_ << term;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -17,9 +17,12 @@
|
|||
#ifndef SMARTPLAYLISTWIZARD_H
|
||||
#define SMARTPLAYLISTWIZARD_H
|
||||
|
||||
#include "smartplaylistsearch.h"
|
||||
|
||||
#include <QWizard>
|
||||
|
||||
class LibraryBackend;
|
||||
class SmartPlaylistSearchPreview;
|
||||
class SmartPlaylistSearchTermWidget;
|
||||
class Ui_SmartPlaylistWizard;
|
||||
|
||||
|
@ -32,17 +35,31 @@ public:
|
|||
SmartPlaylistWizard(LibraryBackend* library, QWidget* parent);
|
||||
~SmartPlaylistWizard();
|
||||
|
||||
class SearchPage : public QWizardPage {
|
||||
friend class SmartPlaylistWizard;
|
||||
public:
|
||||
SearchPage(QWidget* parent = 0);
|
||||
bool isComplete() const;
|
||||
|
||||
QVBoxLayout* layout_;
|
||||
QList<SmartPlaylistSearchTermWidget*> terms_;
|
||||
SmartPlaylistSearchTermWidget* new_term_;
|
||||
|
||||
SmartPlaylistSearchPreview* preview_;
|
||||
};
|
||||
|
||||
private slots:
|
||||
void AddSearchTerm();
|
||||
void RemoveSearchTerm();
|
||||
|
||||
void UpdateTermPreview();
|
||||
|
||||
private:
|
||||
SmartPlaylistSearch MakeSearch() const;
|
||||
|
||||
private:
|
||||
Ui_SmartPlaylistWizard* ui_;
|
||||
LibraryBackend* library_;
|
||||
|
||||
QVBoxLayout* search_term_layout_;
|
||||
QList<SmartPlaylistSearchTermWidget*> search_terms_;
|
||||
SmartPlaylistSearchTermWidget* new_search_term_;
|
||||
};
|
||||
|
||||
#endif // SMARTPLAYLISTWIZARD_H
|
||||
|
|
|
@ -81,7 +81,7 @@ QLabel {
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWizardPage" name="page_query_search">
|
||||
<widget class="SmartPlaylistWizard::SearchPage" name="page_query_search">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">#termframe {
|
||||
border: 1px solid grey;
|
||||
|
@ -206,9 +206,33 @@ margin-left: 9px;
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SmartPlaylistSearchPreview" name="widget" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SmartPlaylistSearchPreview</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>smartplaylists/smartplaylistsearchpreview.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SmartPlaylistWizard::SearchPage</class>
|
||||
<extends>QWizardPage</extends>
|
||||
<header>smartplaylistwizard.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
|
|
@ -61,6 +61,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr "%1 cancó"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 cançons"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -63,6 +63,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -63,6 +63,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -63,6 +63,14 @@ msgstr "%1 Titel"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 Titel"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -64,6 +64,14 @@ msgstr "%1 τραγούδι"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 τραγούδια"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -61,6 +61,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -61,6 +61,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -63,6 +63,14 @@ msgstr "%1 canción"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 canciones"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -63,6 +63,14 @@ msgstr "%1 chanson"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 chansons"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr "%1 canción"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 cancións"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr "%1 szám"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 szám"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -63,6 +63,14 @@ msgstr "%1 brano"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 brani"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -61,6 +61,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr "%1 lied"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 liedjes"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -61,6 +61,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -63,6 +63,14 @@ msgstr "%1 utwór"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 utwory"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -64,6 +64,14 @@ msgstr "%1 música"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 músicas"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr "%1 música"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 músicas"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -61,6 +61,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -61,6 +61,14 @@ msgstr "%1 композиция"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 композиций"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -63,6 +63,14 @@ msgstr "%1 pieseň"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 piesní"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr "%1 skladba"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 skladb"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr "%1 şarkı"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 şarkı"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -52,6 +52,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr "%1 пісня"
|
|||
msgid "%1 songs"
|
||||
msgstr "%1 пісень"
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -61,6 +61,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -62,6 +62,14 @@ msgstr ""
|
|||
msgid "%1 songs"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 songs found (showing %2)"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "%1 total plays"
|
||||
msgstr ""
|
||||
|
|
|
@ -128,6 +128,7 @@ void RatingWidget::paintEvent(QPaintEvent* e) {
|
|||
|
||||
void RatingWidget::mousePressEvent(QMouseEvent* e) {
|
||||
rating_ = RatingPainter::RatingForPos(e->pos(), rect());
|
||||
emit RatingChanged(rating_);
|
||||
}
|
||||
|
||||
void RatingWidget::mouseMoveEvent(QMouseEvent* e) {
|
||||
|
|
|
@ -47,6 +47,9 @@ public:
|
|||
float rating() const { return rating_; }
|
||||
void set_rating(float rating);
|
||||
|
||||
signals:
|
||||
void RatingChanged(float rating);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent*);
|
||||
void mousePressEvent(QMouseEvent* e);
|
||||
|
|
Loading…
Reference in New Issue