Add support for fetching tags for multiple songs at once. Fixes issue #1399
This commit is contained in:
parent
34f8c124f5
commit
4a020c0c04
@ -40,8 +40,6 @@
|
||||
#include <QtDebug>
|
||||
|
||||
const char* EditTagDialog::kHintText = QT_TR_NOOP("(different across multiple songs)");
|
||||
const char* EditTagDialog::kTagFetchText = QT_TR_NOOP("Complete tags automatically");
|
||||
const char* EditTagDialog::kTagFetchOnLoadText = QT_TR_NOOP("Generating audio fingerprint and fetching results...");
|
||||
|
||||
EditTagDialog::EditTagDialog(QWidget* parent)
|
||||
: QDialog(parent),
|
||||
@ -51,7 +49,7 @@ EditTagDialog::EditTagDialog(QWidget* parent)
|
||||
loading_(false),
|
||||
ignore_edits_(false),
|
||||
#ifdef HAVE_LIBTUNEPIMP
|
||||
tag_fetcher_(new TagFetcher()),
|
||||
tag_fetcher_(new TagFetcher(this)),
|
||||
#endif
|
||||
cover_loader_(new BackgroundThreadImplementation<AlbumCoverLoader, AlbumCoverLoader>(this)),
|
||||
cover_art_id_(0),
|
||||
@ -64,17 +62,16 @@ EditTagDialog::EditTagDialog(QWidget* parent)
|
||||
SLOT(ArtLoaded(quint64,QImage,QImage)));
|
||||
#ifdef HAVE_LIBTUNEPIMP
|
||||
connect(tag_fetcher_, SIGNAL(FetchFinished(QString, SongList)),
|
||||
this, SLOT(FetchTagFinished(QString, SongList)), Qt::QueuedConnection);
|
||||
connect(results_dialog_, SIGNAL(SongChoosen(QString, Song)), SLOT(FetchTagSongChoosen(QString, Song)));
|
||||
results_dialog_, SLOT(FetchTagFinished(QString, SongList)),
|
||||
Qt::QueuedConnection);
|
||||
connect(results_dialog_, SIGNAL(SongChosen(QString, Song)),
|
||||
SLOT(FetchTagSongChosen(QString, Song)));
|
||||
#endif
|
||||
|
||||
ui_->setupUi(this);
|
||||
ui_->splitter->setSizes(QList<int>() << 200 << width() - 200);
|
||||
ui_->loading_container->hide();
|
||||
#ifdef HAVE_LIBTUNEPIMP
|
||||
ui_->fetch_tag->setText(tr(kTagFetchText));
|
||||
#else
|
||||
ui_->fetch_tag->setDisabled(true);
|
||||
#ifndef HAVE_LIBTUNEPIMP
|
||||
ui_->fetch_tag->setVisible(false);
|
||||
#endif
|
||||
|
||||
@ -128,7 +125,6 @@ EditTagDialog::EditTagDialog(QWidget* parent)
|
||||
connect(ui_->playcount_reset, SIGNAL(clicked()), SLOT(ResetPlayCounts()));
|
||||
#ifdef HAVE_LIBTUNEPIMP
|
||||
connect(ui_->fetch_tag, SIGNAL(clicked()), SLOT(FetchTag()));
|
||||
ui_->fetch_tag->setText(tr(kTagFetchText));
|
||||
#endif
|
||||
|
||||
// Set up the album cover menu
|
||||
@ -172,9 +168,6 @@ EditTagDialog::EditTagDialog(QWidget* parent)
|
||||
}
|
||||
|
||||
EditTagDialog::~EditTagDialog() {
|
||||
#ifdef HAVE_LIBTUNEPIMP
|
||||
delete tag_fetcher_;
|
||||
# endif
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
@ -245,6 +238,7 @@ void EditTagDialog::SetSongsFinished() {
|
||||
}
|
||||
|
||||
// Select all
|
||||
ui_->song_list->setCurrentRow(0);
|
||||
ui_->song_list->selectAll();
|
||||
|
||||
// Hide the list if there's only one song in it
|
||||
@ -253,9 +247,6 @@ void EditTagDialog::SetSongsFinished() {
|
||||
previous_button_->setEnabled(multiple);
|
||||
next_button_->setEnabled(multiple);
|
||||
|
||||
// Display tag fetcher if there's only one song
|
||||
ui_->fetch_tag->setVisible(!multiple);
|
||||
|
||||
ui_->tab_widget->setCurrentWidget(multiple ? ui_->tags_tab : ui_->summary_tab);
|
||||
}
|
||||
|
||||
@ -696,69 +687,50 @@ void EditTagDialog::ResetPlayCounts() {
|
||||
void EditTagDialog::FetchTag() {
|
||||
#ifdef HAVE_LIBTUNEPIMP
|
||||
const QModelIndexList sel = ui_->song_list->selectionModel()->selectedIndexes();
|
||||
if (sel.isEmpty())
|
||||
return;
|
||||
Song* song = &data_[sel.first().row()].original_;
|
||||
if (!song->is_valid())
|
||||
return;
|
||||
tag_fetcher_->FetchFromFile(song->filename());
|
||||
ui_->fetch_tag->setDisabled(true); // disable button, will be re-enabled later
|
||||
ui_->fetch_tag->setText(tr(kTagFetchOnLoadText));
|
||||
QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
|
||||
#endif
|
||||
}
|
||||
|
||||
void EditTagDialog::FetchTagFinished(const QString& filename, const SongList& songs_guessed) {
|
||||
#ifdef HAVE_LIBTUNEPIMP
|
||||
// Restore cursor
|
||||
QApplication::restoreOverrideCursor();
|
||||
SongList songs;
|
||||
|
||||
// Get current song
|
||||
const QModelIndexList sel = ui_->song_list->selectionModel()->selectedIndexes();
|
||||
if (sel.isEmpty())
|
||||
return;
|
||||
Song* current_song = &data_[sel.first().row()].original_;
|
||||
|
||||
// Check if the user has closed edit tag dialog or if it has reopened a new one.
|
||||
// If so, ignore this signal; else open a dialog for selecting best result
|
||||
if(isVisible() && current_song->filename() == filename) {
|
||||
// Restore some components as "no working"
|
||||
ui_->fetch_tag->setDisabled(false);
|
||||
ui_->fetch_tag->setText(tr(kTagFetchText));
|
||||
|
||||
// If no songs have been guessed, just display a message
|
||||
if(songs_guessed.empty()) {
|
||||
QMessageBox::information(this, tr("Sorry"), tr("Clementine was unable to find results for this file"));
|
||||
} else { // Else, display song's tags selection dialog only if edittagdialog is still opened
|
||||
results_dialog_->Init(filename, songs_guessed);
|
||||
results_dialog_->show();
|
||||
foreach (const QModelIndex& index, sel) {
|
||||
Song song = data_[index.row()].original_;
|
||||
if (!song.is_valid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
songs << song;
|
||||
tag_fetcher_->FetchFromFile(song.filename());
|
||||
}
|
||||
|
||||
if (songs.isEmpty())
|
||||
return;
|
||||
|
||||
results_dialog_->Init(songs);
|
||||
results_dialog_->show();
|
||||
#endif
|
||||
}
|
||||
|
||||
void EditTagDialog::FetchTagSongChoosen(const QString& filename, const Song& song_choosen) {
|
||||
// Get current song
|
||||
const QModelIndexList sel = ui_->song_list->selectionModel()->selectedIndexes();
|
||||
if (sel.isEmpty())
|
||||
return;
|
||||
Song* current_song = &data_[sel.first().row()].original_;
|
||||
if (!current_song->is_valid())
|
||||
return;
|
||||
// Check it's still the same song, using filename
|
||||
if(filename != current_song->filename()) {
|
||||
// different song: we shouldn't erase tags with wrong metadata
|
||||
return;
|
||||
}
|
||||
void EditTagDialog::FetchTagSongChosen(const QString& filename, const Song& new_metadata) {
|
||||
|
||||
// Fill tags' fields
|
||||
if(!song_choosen.title().isEmpty())
|
||||
ui_->title->set_text(song_choosen.title());
|
||||
if(!song_choosen.album().isEmpty())
|
||||
ui_->album->set_text(song_choosen.album());
|
||||
if(!song_choosen.album().isEmpty())
|
||||
ui_->artist->set_text(song_choosen.artist());
|
||||
if(song_choosen.track() > 0)
|
||||
ui_->track->set_text(QString::number(song_choosen.track()));
|
||||
// Find the song with this filename
|
||||
for (int i=0 ; i<data_.count() ; ++i) {
|
||||
Data* data = &data_[i];
|
||||
if (data->original_.filename() != filename)
|
||||
continue;
|
||||
|
||||
// Is it currently being displayed in the UI?
|
||||
if (ui_->song_list->currentRow() == i) {
|
||||
// Yes! We can just set the fields in the UI
|
||||
ui_->title->set_text(new_metadata.title());
|
||||
ui_->artist->set_text(new_metadata.artist());
|
||||
ui_->album->set_text(new_metadata.album());
|
||||
ui_->track->setValue(new_metadata.track());
|
||||
} else {
|
||||
data->current_.set_title(new_metadata.title());
|
||||
data->current_.set_artist(new_metadata.artist());
|
||||
data->current_.set_album(new_metadata.album());
|
||||
data->current_.set_track(new_metadata.track());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,8 +49,6 @@ public:
|
||||
~EditTagDialog();
|
||||
|
||||
static const char* kHintText;
|
||||
static const char* kTagFetchText;
|
||||
static const char* kTagFetchOnLoadText;
|
||||
|
||||
void SetSongs(const SongList& songs, const PlaylistItemList& items = PlaylistItemList());
|
||||
void SetTagCompleter(LibraryBackend* backend);
|
||||
@ -77,8 +75,7 @@ private slots:
|
||||
void SongRated(float rating);
|
||||
void ResetPlayCounts();
|
||||
void FetchTag();
|
||||
void FetchTagFinished(const QString& filename, const SongList& songs_guessed);
|
||||
void FetchTagSongChoosen(const QString& filename, const Song& song);
|
||||
void FetchTagSongChosen(const QString& filename, const Song& new_metadata);
|
||||
|
||||
void ArtLoaded(quint64 id, const QImage& scaled, const QImage& original);
|
||||
|
||||
@ -167,7 +164,7 @@ private:
|
||||
QPushButton* previous_button_;
|
||||
QPushButton* next_button_;
|
||||
|
||||
TrackSelectionDialog *results_dialog_;
|
||||
TrackSelectionDialog* results_dialog_;
|
||||
};
|
||||
|
||||
#endif // EDITTAGDIALOG_H
|
||||
|
@ -819,7 +819,11 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QPushButton" name="fetch_tag"/>
|
||||
<widget class="QPushButton" name="fetch_tag">
|
||||
<property name="text">
|
||||
<string>Complete tags automatically</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -15,8 +15,12 @@
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "iconloader.h"
|
||||
#include "trackselectiondialog.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QPushButton>
|
||||
#include <QShortcut>
|
||||
#include <QtDebug>
|
||||
|
||||
TrackSelectionDialog::TrackSelectionDialog(QWidget *parent)
|
||||
@ -25,57 +29,183 @@ TrackSelectionDialog::TrackSelectionDialog(QWidget *parent)
|
||||
{
|
||||
// Setup dialog window
|
||||
ui_->setupUi(this);
|
||||
setModal(true);
|
||||
connect(ui_->resultsTreeWidget, SIGNAL(itemDoubleClicked (QTreeWidgetItem*, int)), this, SLOT(accept()));
|
||||
|
||||
connect(ui_->song_list, SIGNAL(currentRowChanged(int)), SLOT(UpdateStack()));
|
||||
connect(ui_->results, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
|
||||
SLOT(ResultSelected()));
|
||||
|
||||
ui_->splitter->setSizes(QList<int>() << 200 << width() - 200);
|
||||
|
||||
// Add the next/previous buttons
|
||||
previous_button_ = new QPushButton(IconLoader::Load("go-previous"), tr("Previous"), this);
|
||||
next_button_ = new QPushButton(IconLoader::Load("go-next"), tr("Next"), this);
|
||||
ui_->button_box->addButton(previous_button_, QDialogButtonBox::ResetRole);
|
||||
ui_->button_box->addButton(next_button_, QDialogButtonBox::ResetRole);
|
||||
|
||||
connect(previous_button_, SIGNAL(clicked()), SLOT(PreviousSong()));
|
||||
connect(next_button_, SIGNAL(clicked()), SLOT(NextSong()));
|
||||
|
||||
// Set some shortcuts for the buttons
|
||||
new QShortcut(QKeySequence::Back, previous_button_, SLOT(click()));
|
||||
new QShortcut(QKeySequence::Forward, next_button_, SLOT(click()));
|
||||
new QShortcut(QKeySequence::MoveToPreviousPage, previous_button_, SLOT(click()));
|
||||
new QShortcut(QKeySequence::MoveToNextPage, next_button_, SLOT(click()));
|
||||
|
||||
// Resize columns
|
||||
ui_->results->setColumnWidth(0, 50); // Track column
|
||||
ui_->results->setColumnWidth(1, 175); // Title column
|
||||
ui_->results->setColumnWidth(2, 175); // Artist column
|
||||
ui_->results->setColumnWidth(3, 175); // Album column
|
||||
}
|
||||
|
||||
TrackSelectionDialog::~TrackSelectionDialog() {
|
||||
ui_->resultsTreeWidget->clear();
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void TrackSelectionDialog::Init(const QString& filename, const SongList& songs) {
|
||||
current_filename_ = filename;
|
||||
current_songs_ = songs;
|
||||
void TrackSelectionDialog::Init(const SongList& songs) {
|
||||
ui_->song_list->clear();
|
||||
ui_->stack->setCurrentWidget(ui_->loading_page);
|
||||
data_.clear();
|
||||
|
||||
// Set filename
|
||||
ui_->filenameLineEdit->setText(current_filename_); //TODO: use basefilename, it's nicer
|
||||
foreach (const Song& song, songs) {
|
||||
Data data;
|
||||
data.original_song_ = song;
|
||||
data_ << data;
|
||||
|
||||
// Clear tree widget
|
||||
ui_->resultsTreeWidget->clear();
|
||||
|
||||
// Fill tree view with songs
|
||||
int song_index = 0;
|
||||
foreach(const Song& song, songs) {
|
||||
QStringList valuesStringList;
|
||||
if (song.track() > 0) {
|
||||
valuesStringList << QString::number(song.track());
|
||||
}
|
||||
valuesStringList << song.title() << song.artist() << song.album();
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(
|
||||
ui_->resultsTreeWidget, valuesStringList);
|
||||
if(song_index==0) { // if it's the first item, set focus on it
|
||||
ui_->resultsTreeWidget->setCurrentItem(item);
|
||||
}
|
||||
item->setData(0, Qt::UserRole, song_index++); // To remember this widget corresponds to the ith song of our list
|
||||
QListWidgetItem* item = new QListWidgetItem(ui_->song_list);
|
||||
item->setText(QFileInfo(song.filename()).fileName());
|
||||
item->setForeground(palette().color(QPalette::Disabled, QPalette::Text));
|
||||
}
|
||||
|
||||
// Resize columns
|
||||
ui_->resultsTreeWidget->setColumnWidth(0, 50); // Track column
|
||||
ui_->resultsTreeWidget->setColumnWidth(1, 175); // Title column
|
||||
ui_->resultsTreeWidget->setColumnWidth(2, 175); // Artist column
|
||||
ui_->resultsTreeWidget->setColumnWidth(3, 175); // Album column
|
||||
const bool multiple = songs.count() > 1;
|
||||
ui_->song_list->setVisible(multiple);
|
||||
next_button_->setEnabled(multiple);
|
||||
previous_button_->setEnabled(multiple);
|
||||
|
||||
ui_->song_list->setCurrentRow(0);
|
||||
}
|
||||
|
||||
void TrackSelectionDialog::FetchTagFinished(const QString& filename,
|
||||
const SongList& songs_guessed) {
|
||||
// Find the item with this filename
|
||||
int row = -1;
|
||||
for (int i=0 ; i<data_.count() ; ++i) {
|
||||
if (data_[i].original_song_.filename() == filename) {
|
||||
row = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (row == -1)
|
||||
return;
|
||||
|
||||
// Set the color back to black
|
||||
ui_->song_list->item(row)->setForeground(palette().text());
|
||||
|
||||
// Add the results to the list
|
||||
data_[row].pending_ = false;
|
||||
data_[row].results_ = songs_guessed;
|
||||
|
||||
// If it's the current item, update the display
|
||||
if (ui_->song_list->currentIndex().row() == row) {
|
||||
UpdateStack();
|
||||
}
|
||||
}
|
||||
|
||||
void TrackSelectionDialog::UpdateStack() {
|
||||
const int row = ui_->song_list->currentRow();
|
||||
if (row < 0 || row >= data_.count())
|
||||
return;
|
||||
|
||||
const Data& data = data_[row];
|
||||
|
||||
if (data.pending_) {
|
||||
ui_->stack->setCurrentWidget(ui_->loading_page);
|
||||
return;
|
||||
} else if (data.results_.isEmpty()) {
|
||||
ui_->stack->setCurrentWidget(ui_->error_page);
|
||||
return;
|
||||
}
|
||||
ui_->stack->setCurrentWidget(ui_->results_page);
|
||||
|
||||
// Clear tree widget
|
||||
ui_->results->clear();
|
||||
|
||||
// Put the original tags at the top
|
||||
AddDivider(tr("Original tags"), ui_->results);
|
||||
AddSong(data.original_song_, -1, ui_->results);
|
||||
|
||||
// Fill tree view with songs
|
||||
AddDivider(tr("Suggested tags"), ui_->results);
|
||||
|
||||
int song_index = 0;
|
||||
foreach (const Song& song, data.results_) {
|
||||
AddSong(song, song_index++, ui_->results);
|
||||
}
|
||||
|
||||
// Find the item that was selected last time
|
||||
for (int i=0 ; i<ui_->results->model()->rowCount() ; ++i) {
|
||||
const QModelIndex index = ui_->results->model()->index(i, 0);
|
||||
const QVariant id = index.data(Qt::UserRole);
|
||||
if (!id.isNull() && id.toInt() == data.selected_result_) {
|
||||
ui_->results->setCurrentIndex(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TrackSelectionDialog::AddDivider(const QString& text, QTreeWidget* parent) const {
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(parent);
|
||||
item->setFirstColumnSpanned(true);
|
||||
item->setText(0, text);
|
||||
item->setFlags(Qt::NoItemFlags);
|
||||
item->setForeground(0, palette().color(QPalette::Disabled, QPalette::Text));
|
||||
|
||||
QFont bold_font(font());
|
||||
bold_font.setBold(true);
|
||||
item->setFont(0, bold_font);
|
||||
}
|
||||
|
||||
void TrackSelectionDialog::AddSong(const Song& song, int result_index, QTreeWidget* parent) const {
|
||||
QStringList values;
|
||||
values << ((song.track() > 0) ? QString::number(song.track()) : QString());
|
||||
values << song.title() << song.artist() << song.album();
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(parent, values);
|
||||
item->setData(0, Qt::UserRole, result_index);
|
||||
item->setData(0, Qt::TextAlignmentRole, Qt::AlignRight);
|
||||
}
|
||||
|
||||
void TrackSelectionDialog::ResultSelected() {
|
||||
if (!ui_->results->currentItem())
|
||||
return;
|
||||
|
||||
const int song_row = ui_->song_list->currentRow();
|
||||
if (song_row == -1)
|
||||
return;
|
||||
|
||||
const int result_index = ui_->results->currentItem()->data(0, Qt::UserRole).toInt();
|
||||
data_[song_row].selected_result_ = result_index;
|
||||
}
|
||||
|
||||
void TrackSelectionDialog::accept() {
|
||||
QDialog::accept();
|
||||
QTreeWidgetItem *item =ui_->resultsTreeWidget->currentItem();
|
||||
if(!item) { // no item selected
|
||||
return;
|
||||
}
|
||||
int selected_song_index = item->data(0, Qt::UserRole).toInt();
|
||||
if(selected_song_index >= 0 && selected_song_index < current_songs_.size()) {
|
||||
emit SongChoosen(current_filename_, current_songs_[selected_song_index]);
|
||||
|
||||
foreach (const Data& data, data_) {
|
||||
if (data.pending_ || data.results_.isEmpty() || data.selected_result_ == -1)
|
||||
continue;
|
||||
|
||||
emit SongChosen(data.original_song_.filename(), data.results_[data.selected_result_]);
|
||||
}
|
||||
}
|
||||
|
||||
void TrackSelectionDialog::NextSong() {
|
||||
int row = (ui_->song_list->currentRow() + 1) % ui_->song_list->count();
|
||||
ui_->song_list->setCurrentRow(row);
|
||||
}
|
||||
|
||||
void TrackSelectionDialog::PreviousSong() {
|
||||
int row = (ui_->song_list->currentRow() - 1 + ui_->song_list->count()) % ui_->song_list->count();
|
||||
ui_->song_list->setCurrentRow(row);
|
||||
}
|
||||
|
||||
|
@ -32,18 +32,45 @@ public:
|
||||
TrackSelectionDialog(QWidget *parent = 0);
|
||||
~TrackSelectionDialog();
|
||||
|
||||
void Init(const QString& filename, const SongList& songs);
|
||||
void Init(const SongList& songs);
|
||||
|
||||
public slots:
|
||||
void FetchTagFinished(const QString& filename, const SongList& songs_guessed);
|
||||
|
||||
// QDialog
|
||||
void accept();
|
||||
|
||||
signals:
|
||||
void SongChoosen(const QString& filename, const Song& song);
|
||||
void SongChosen(const QString& filename, const Song& song);
|
||||
|
||||
private slots:
|
||||
void UpdateStack();
|
||||
|
||||
void NextSong();
|
||||
void PreviousSong();
|
||||
|
||||
void ResultSelected();
|
||||
|
||||
private:
|
||||
Ui_TrackSelectionDialog *ui_;
|
||||
void AddDivider(const QString& text, QTreeWidget* parent) const;
|
||||
void AddSong(const Song& song, int result_index, QTreeWidget* parent) const;
|
||||
|
||||
QString current_filename_;
|
||||
SongList current_songs_;
|
||||
private:
|
||||
Ui_TrackSelectionDialog* ui_;
|
||||
|
||||
struct Data {
|
||||
Data() : pending_(true), selected_result_(0) {}
|
||||
|
||||
Song original_song_;
|
||||
bool pending_;
|
||||
SongList results_;
|
||||
int selected_result_;
|
||||
};
|
||||
|
||||
QList<Data> data_;
|
||||
|
||||
QPushButton* previous_button_;
|
||||
QPushButton* next_button_;
|
||||
};
|
||||
|
||||
#endif // TRACKSELECTIONDIALOG_H
|
||||
|
@ -6,178 +6,222 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>613</width>
|
||||
<height>366</height>
|
||||
<width>773</width>
|
||||
<height>375</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Results fetched</string>
|
||||
<string>Tag fetcher</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../data/data.qrc">
|
||||
<normaloff>:/icon.png</normaloff>:/icon.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="fileNameGroupBox">
|
||||
<property name="title">
|
||||
<string>File name</string>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="filenameLineEdit">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="0">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="0">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="0">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="0">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="0">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="0">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="0">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="0">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="0">
|
||||
<red>0</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QListWidget" name="song_list">
|
||||
<property name="uniformItemSizes">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStackedWidget" name="stack">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="loading_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>133</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<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="BusyIndicator" name="label_2"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Identifying song...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>133</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="error_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>124</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { font-weight: bold; }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sorry</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Clementine was unable to find results for this file</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>124</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="results_page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel { font-weight: bold; }</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select best possible match</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="results">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>150</number>
|
||||
</attribute>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>50</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Track</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Artist</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Album</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="resultsGroupBox">
|
||||
<property name="title">
|
||||
<string>Select best possible match</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="resultsTreeWidget">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>150</number>
|
||||
</attribute>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>50</number>
|
||||
</attribute>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>150</number>
|
||||
</attribute>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>50</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Track</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Artist</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Album</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<widget class="QDialogButtonBox" name="button_box">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@ -194,12 +238,19 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BusyIndicator</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>widgets/busyindicator.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../data/data.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<sender>button_box</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>TrackSelectionDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
@ -215,7 +266,7 @@
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<sender>button_box</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>TrackSelectionDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
|
Loading…
x
Reference in New Issue
Block a user