2016-03-03 22:21:15 +01:00
|
|
|
#include "./dbquerywidget.h"
|
|
|
|
#include "./tagedit.h"
|
2018-03-07 01:18:01 +01:00
|
|
|
#include "./tageditorwidget.h"
|
2016-03-03 22:21:15 +01:00
|
|
|
|
|
|
|
#include "../application/knownfieldmodel.h"
|
|
|
|
#include "../application/settings.h"
|
|
|
|
#include "../dbquery/dbquery.h"
|
|
|
|
#include "../misc/utility.h"
|
|
|
|
|
|
|
|
#include "ui_dbquerywidget.h"
|
|
|
|
|
|
|
|
#include <tagparser/tag.h>
|
|
|
|
|
|
|
|
#include <qtutilities/misc/dialogutils.h>
|
|
|
|
|
|
|
|
#include <c++utilities/conversion/conversionexception.h>
|
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
#include <QDesktopServices>
|
2016-03-06 17:52:33 +01:00
|
|
|
#include <QDialog>
|
|
|
|
#include <QGraphicsItem>
|
2018-03-07 01:18:01 +01:00
|
|
|
#include <QGraphicsView>
|
|
|
|
#include <QKeyEvent>
|
|
|
|
#include <QMenu>
|
2018-06-05 22:45:43 +02:00
|
|
|
#include <QStyle>
|
2016-10-09 22:41:34 +02:00
|
|
|
#include <QTextBrowser>
|
2019-02-13 18:15:49 +01:00
|
|
|
#ifndef QT_NO_CLIPBOARD
|
|
|
|
#include <QClipboard>
|
|
|
|
#endif
|
2016-03-03 22:21:15 +01:00
|
|
|
|
2016-10-24 20:15:10 +02:00
|
|
|
#include <functional>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace std::placeholders;
|
2019-06-10 22:49:46 +02:00
|
|
|
using namespace CppUtilities;
|
|
|
|
using namespace QtUtilities;
|
2016-03-03 22:21:15 +01:00
|
|
|
using namespace Settings;
|
|
|
|
using namespace Utility;
|
2018-03-06 23:10:13 +01:00
|
|
|
using namespace TagParser;
|
2016-03-03 22:21:15 +01:00
|
|
|
|
|
|
|
namespace QtGui {
|
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
DbQueryWidget::DbQueryWidget(TagEditorWidget *tagEditorWidget, QWidget *parent)
|
|
|
|
: QWidget(parent)
|
|
|
|
, m_ui(new Ui::DbQueryWidget)
|
|
|
|
, m_tagEditorWidget(tagEditorWidget)
|
|
|
|
, m_model(nullptr)
|
|
|
|
, m_coverIndex(-1)
|
|
|
|
, m_lyricsIndex(-1)
|
|
|
|
, m_menu(new QMenu(parent))
|
2016-03-03 22:21:15 +01:00
|
|
|
{
|
|
|
|
m_ui->setupUi(this);
|
2023-03-26 22:19:27 +02:00
|
|
|
updateStyleSheet();
|
2016-03-03 22:21:15 +01:00
|
|
|
|
2016-10-09 19:44:06 +02:00
|
|
|
m_ui->notificationLabel->setText(tr("Search hasn't been started"));
|
2017-07-30 20:57:55 +02:00
|
|
|
m_ui->notificationLabel->setContext(tr("MusicBrainz/LyricsWikia notifications"));
|
2017-08-08 18:45:23 +02:00
|
|
|
m_ui->notificationLabel->setMaxLineCount(5);
|
2016-03-03 22:21:15 +01:00
|
|
|
m_ui->searchGroupBox->installEventFilter(this);
|
|
|
|
|
|
|
|
// initialize buttons
|
|
|
|
m_ui->abortPushButton->setIcon(style()->standardIcon(QStyle::SP_DialogCancelButton, nullptr, m_ui->abortPushButton));
|
|
|
|
m_ui->abortPushButton->setVisible(false);
|
|
|
|
m_ui->applyPushButton->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton, nullptr, m_ui->applyPushButton));
|
|
|
|
|
|
|
|
// initialize fields model
|
2016-10-24 20:15:10 +02:00
|
|
|
m_ui->fieldsListView->setModel(&values().dbQuery.fields);
|
2016-03-03 22:21:15 +01:00
|
|
|
|
|
|
|
// initialize search terms form
|
|
|
|
insertSearchTermsFromTagEdit(m_tagEditorWidget->activeTagEdit());
|
|
|
|
|
|
|
|
// restore settings
|
2016-10-24 20:15:10 +02:00
|
|
|
m_ui->overrideCheckBox->setChecked(values().dbQuery.override);
|
2016-03-03 22:21:15 +01:00
|
|
|
|
2016-06-02 22:41:01 +02:00
|
|
|
// setup menu
|
2019-09-02 20:37:31 +02:00
|
|
|
const auto searchIcon = QIcon::fromTheme(QStringLiteral("search"));
|
2019-09-02 22:12:03 +02:00
|
|
|
m_menu->setTitle(tr("New search"));
|
|
|
|
m_menu->setIcon(searchIcon);
|
2019-09-02 20:37:31 +02:00
|
|
|
m_searchMusicBrainzAction = m_lastSearchAction = m_menu->addAction(tr("Query MusicBrainz"));
|
|
|
|
m_searchMusicBrainzAction->setIcon(searchIcon);
|
2021-04-07 20:53:32 +02:00
|
|
|
m_searchMusicBrainzAction->setShortcut(QKeySequence(Qt::CTRL, Qt::Key_M));
|
2019-09-02 20:37:31 +02:00
|
|
|
connect(m_searchMusicBrainzAction, &QAction::triggered, this, &DbQueryWidget::searchMusicBrainz);
|
|
|
|
m_searchLyricsWikiaAction = m_menu->addAction(tr("Query LyricsWikia"));
|
|
|
|
m_searchLyricsWikiaAction->setIcon(searchIcon);
|
2021-04-07 20:53:32 +02:00
|
|
|
m_searchLyricsWikiaAction->setShortcut(QKeySequence(Qt::CTRL, Qt::Key_L));
|
2019-09-02 20:37:31 +02:00
|
|
|
connect(m_searchLyricsWikiaAction, &QAction::triggered, this, &DbQueryWidget::searchLyricsWikia);
|
2019-09-02 21:47:11 +02:00
|
|
|
m_searchMakeItPersonalAction = m_menu->addAction(tr("Query makeitpersonal"));
|
|
|
|
m_searchMakeItPersonalAction->setIcon(searchIcon);
|
2021-04-07 20:53:32 +02:00
|
|
|
m_searchMakeItPersonalAction->setShortcut(QKeySequence(Qt::CTRL, Qt::Key_K));
|
2019-09-02 21:47:11 +02:00
|
|
|
connect(m_searchMakeItPersonalAction, &QAction::triggered, this, &DbQueryWidget::searchMakeItPersonal);
|
2019-09-02 20:37:31 +02:00
|
|
|
m_menu->addSeparator();
|
|
|
|
m_insertPresentDataAction = m_menu->addAction(tr("Use present data as search criteria"));
|
2016-06-02 22:41:01 +02:00
|
|
|
m_insertPresentDataAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy")));
|
|
|
|
m_insertPresentDataAction->setEnabled(m_tagEditorWidget->activeTagEdit());
|
|
|
|
connect(m_insertPresentDataAction, &QAction::triggered, this, &DbQueryWidget::insertSearchTermsFromActiveTagEdit);
|
2019-09-03 22:04:43 +02:00
|
|
|
m_refreshAutomaticallyAction = m_menu->addAction(tr("Start new query automatically when inserting search criteria"));
|
|
|
|
m_refreshAutomaticallyAction->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
|
|
|
|
m_refreshAutomaticallyAction->setCheckable(true);
|
2019-09-02 20:37:31 +02:00
|
|
|
auto *const clearSearchCriteria = m_menu->addAction(tr("Clear search criteria"));
|
2016-06-02 22:41:01 +02:00
|
|
|
clearSearchCriteria->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear")));
|
|
|
|
connect(clearSearchCriteria, &QAction::triggered, this, &DbQueryWidget::clearSearchCriteria);
|
2019-09-02 20:37:31 +02:00
|
|
|
m_ui->searchPushButton->setMenu(m_menu);
|
2016-06-02 22:41:01 +02:00
|
|
|
|
2017-08-15 23:13:43 +02:00
|
|
|
// ensure fieldsGroupBox takes only minimal space (initially)
|
2019-09-02 20:37:31 +02:00
|
|
|
m_ui->splitter->setSizes({ 1, 1000 });
|
2017-08-15 23:13:43 +02:00
|
|
|
|
2016-03-03 22:21:15 +01:00
|
|
|
// connect signals and slots
|
|
|
|
connect(m_ui->abortPushButton, &QPushButton::clicked, this, &DbQueryWidget::abortSearch);
|
2019-08-12 20:27:51 +02:00
|
|
|
connect(m_ui->resultsTreeView, &QTreeView::doubleClicked, this, &DbQueryWidget::applySpecifiedResults);
|
|
|
|
connect(m_ui->applyPushButton, &QPushButton::clicked, this, &DbQueryWidget::applySelectedResults);
|
2016-08-07 19:59:33 +02:00
|
|
|
connect(m_tagEditorWidget, &TagEditorWidget::fileStatusChanged, this, &DbQueryWidget::fileStatusChanged);
|
2016-03-06 17:52:33 +01:00
|
|
|
connect(m_ui->resultsTreeView, &QTreeView::customContextMenuRequested, this, &DbQueryWidget::showResultsContextMenu);
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DbQueryWidget::~DbQueryWidget()
|
|
|
|
{
|
2016-10-24 20:15:10 +02:00
|
|
|
values().dbQuery.override = m_ui->overrideCheckBox->isChecked();
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
|
2019-05-30 14:25:45 +02:00
|
|
|
void DbQueryWidget::insertSearchTermsFromTagEdit(TagEdit *tagEdit, bool songSpecific)
|
2016-03-03 22:21:15 +01:00
|
|
|
{
|
2018-08-19 15:11:46 +02:00
|
|
|
if (!tagEdit) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-09-03 22:04:43 +02:00
|
|
|
bool somethingChanged = false;
|
|
|
|
|
|
|
|
// be always song-specific when querying makeitpersonal
|
|
|
|
songSpecific = m_lastSearchAction == m_searchMakeItPersonalAction;
|
|
|
|
|
2019-05-30 14:25:45 +02:00
|
|
|
// set album and artist
|
2019-09-03 22:04:43 +02:00
|
|
|
if (m_lastSearchAction != m_searchMakeItPersonalAction) {
|
|
|
|
const auto newAlbum = tagValueToQString(tagEdit->value(KnownField::Album));
|
|
|
|
if (m_ui->albumLineEdit->text() != newAlbum) {
|
|
|
|
m_ui->albumLineEdit->setText(newAlbum);
|
|
|
|
somethingChanged = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const auto newArtist = tagValueToQString(tagEdit->value(KnownField::Artist));
|
|
|
|
if (m_ui->artistLineEdit->text() != newArtist) {
|
|
|
|
m_ui->artistLineEdit->setText(newArtist);
|
|
|
|
somethingChanged = true;
|
2019-09-02 21:47:11 +02:00
|
|
|
}
|
2018-08-19 15:11:46 +02:00
|
|
|
|
2019-05-30 14:25:45 +02:00
|
|
|
if (!songSpecific) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-30 14:45:26 +02:00
|
|
|
// set title and track number
|
2019-09-03 22:04:43 +02:00
|
|
|
const auto newTitle = tagValueToQString(tagEdit->value(KnownField::Title));
|
|
|
|
if (m_ui->titleLineEdit->text() != newTitle) {
|
|
|
|
m_ui->titleLineEdit->setText(newTitle);
|
|
|
|
somethingChanged = true;
|
|
|
|
}
|
|
|
|
if (m_lastSearchAction != m_searchMakeItPersonalAction) {
|
|
|
|
const auto newTrackNumber = tagEdit->trackNumber();
|
|
|
|
if (m_ui->trackSpinBox->value() != newTrackNumber) {
|
|
|
|
m_ui->trackSpinBox->setValue(newTrackNumber);
|
|
|
|
somethingChanged = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// refresh automatically if enabled and something has changed
|
|
|
|
if (somethingChanged && m_refreshAutomaticallyAction->isChecked()) {
|
|
|
|
m_lastSearchAction->trigger();
|
|
|
|
}
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
|
2016-10-09 22:41:34 +02:00
|
|
|
SongDescription DbQueryWidget::currentSongDescription() const
|
|
|
|
{
|
|
|
|
SongDescription desc;
|
|
|
|
desc.title = m_ui->titleLineEdit->text();
|
|
|
|
desc.album = m_ui->albumLineEdit->text();
|
|
|
|
desc.artist = m_ui->artistLineEdit->text();
|
2017-08-08 19:16:11 +02:00
|
|
|
desc.track = m_ui->trackSpinBox->value();
|
2016-10-09 22:41:34 +02:00
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
2016-10-09 19:44:06 +02:00
|
|
|
void DbQueryWidget::searchMusicBrainz()
|
2016-03-03 22:21:15 +01:00
|
|
|
{
|
2019-09-02 20:37:31 +02:00
|
|
|
m_lastSearchAction = m_searchMusicBrainzAction;
|
|
|
|
|
2016-10-09 19:44:06 +02:00
|
|
|
// check whether enough search terms are supplied
|
2018-03-07 01:18:01 +01:00
|
|
|
if (m_ui->titleLineEdit->text().isEmpty() && m_ui->albumLineEdit->text().isEmpty() && m_ui->artistLineEdit->text().isEmpty()) {
|
2016-03-03 22:21:15 +01:00
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Critical);
|
2016-10-09 22:41:34 +02:00
|
|
|
m_ui->notificationLabel->setText(tr("Insufficient search criteria supplied - at least title, album or artist must be specified"));
|
2016-03-03 22:21:15 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// delete current model
|
|
|
|
m_ui->resultsTreeView->setModel(nullptr);
|
|
|
|
delete m_model;
|
|
|
|
|
|
|
|
// show status
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Progress);
|
2016-10-09 22:41:34 +02:00
|
|
|
m_ui->notificationLabel->setText(tr("Retrieving meta data from MusicBrainz ..."));
|
2016-03-03 22:21:15 +01:00
|
|
|
setStatus(false);
|
|
|
|
|
|
|
|
// do actual query
|
2017-08-08 19:16:11 +02:00
|
|
|
useQueryResults(queryMusicBrainz(currentSongDescription()));
|
2016-10-09 19:44:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void DbQueryWidget::searchLyricsWikia()
|
|
|
|
{
|
2019-09-02 20:37:31 +02:00
|
|
|
m_lastSearchAction = m_searchLyricsWikiaAction;
|
|
|
|
|
2016-10-09 19:44:06 +02:00
|
|
|
// check whether enough search terms are supplied
|
2018-03-07 01:18:01 +01:00
|
|
|
if (m_ui->artistLineEdit->text().isEmpty()) {
|
2016-10-09 19:44:06 +02:00
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Critical);
|
2016-10-09 22:41:34 +02:00
|
|
|
m_ui->notificationLabel->setText(tr("Insufficient search criteria supplied - artist is mandatory"));
|
2016-10-09 19:44:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// delete current model
|
|
|
|
m_ui->resultsTreeView->setModel(nullptr);
|
|
|
|
delete m_model;
|
|
|
|
|
|
|
|
// show status
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Progress);
|
2016-10-09 22:41:34 +02:00
|
|
|
m_ui->notificationLabel->setText(tr("Retrieving meta data from LyricsWikia ..."));
|
2016-10-09 19:44:06 +02:00
|
|
|
setStatus(false);
|
|
|
|
|
|
|
|
// do actual query
|
2017-08-08 19:16:11 +02:00
|
|
|
useQueryResults(queryLyricsWikia(currentSongDescription()));
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
|
2019-09-02 21:47:11 +02:00
|
|
|
void DbQueryWidget::searchMakeItPersonal()
|
|
|
|
{
|
|
|
|
m_lastSearchAction = m_searchMakeItPersonalAction;
|
|
|
|
|
|
|
|
// check whether enough search terms are supplied
|
|
|
|
if (m_ui->artistLineEdit->text().isEmpty() || m_ui->titleLineEdit->text().isEmpty()) {
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Critical);
|
|
|
|
m_ui->notificationLabel->setText(tr("Insufficient search criteria supplied - artist and title are mandatory"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// delete current model
|
|
|
|
m_ui->resultsTreeView->setModel(nullptr);
|
|
|
|
delete m_model;
|
|
|
|
|
|
|
|
// show status
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Progress);
|
|
|
|
m_ui->notificationLabel->setText(tr("Retrieving lyrics from makeitpersonal ..."));
|
|
|
|
setStatus(false);
|
|
|
|
|
|
|
|
// do actual query
|
|
|
|
useQueryResults(queryMakeItPersonal(currentSongDescription()));
|
|
|
|
}
|
|
|
|
|
2016-03-03 22:21:15 +01:00
|
|
|
void DbQueryWidget::abortSearch()
|
|
|
|
{
|
2018-08-19 15:11:46 +02:00
|
|
|
if (!m_model) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m_model->isFetchingCover()) {
|
|
|
|
// call abort to abort fetching cover
|
|
|
|
m_model->abort();
|
|
|
|
} else if (!m_model->areResultsAvailable()) {
|
|
|
|
// delete model to abort search
|
|
|
|
m_ui->resultsTreeView->setModel(nullptr);
|
|
|
|
delete m_model;
|
|
|
|
m_model = nullptr;
|
|
|
|
|
|
|
|
// update status
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Information);
|
|
|
|
m_ui->notificationLabel->setText(tr("Aborted"));
|
|
|
|
setStatus(true);
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DbQueryWidget::showResults()
|
|
|
|
{
|
2018-08-19 15:11:46 +02:00
|
|
|
if (!m_model) {
|
|
|
|
return;
|
|
|
|
}
|
2019-06-01 12:51:11 +02:00
|
|
|
|
|
|
|
// update notification label
|
2018-08-19 15:11:46 +02:00
|
|
|
if (m_model->errorList().isEmpty()) {
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::TaskComplete);
|
2018-03-07 01:18:01 +01:00
|
|
|
if (m_model->results().isEmpty()) {
|
2018-08-19 15:11:46 +02:00
|
|
|
m_ui->notificationLabel->setText(tr("No results available"));
|
2016-03-03 22:21:15 +01:00
|
|
|
} else {
|
2023-07-25 23:34:39 +02:00
|
|
|
m_ui->notificationLabel->setText(
|
|
|
|
tr("%1 result(s) available", nullptr, Utility::containerSizeToInt(m_model->results().size())).arg(m_model->results().size()));
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
2018-08-19 15:11:46 +02:00
|
|
|
} else {
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Critical);
|
|
|
|
m_ui->notificationLabel->clearText();
|
|
|
|
for (const QString &error : m_model->errorList()) {
|
|
|
|
m_ui->notificationLabel->appendLine(error);
|
|
|
|
}
|
|
|
|
}
|
2019-06-01 12:51:11 +02:00
|
|
|
|
|
|
|
// update push buttons
|
2018-08-19 15:11:46 +02:00
|
|
|
if (m_model->results().isEmpty()) {
|
|
|
|
m_ui->applyPushButton->setEnabled(false);
|
|
|
|
} else {
|
2018-08-20 21:41:17 +02:00
|
|
|
auto *const selectionModel(m_ui->resultsTreeView->selectionModel());
|
|
|
|
if (selectionModel->selection().isEmpty()) {
|
|
|
|
selectionModel->setCurrentIndex(m_model->index(0, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
|
|
|
}
|
2018-08-19 15:11:46 +02:00
|
|
|
m_ui->applyPushButton->setEnabled(m_tagEditorWidget->activeTagEdit());
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
2019-06-01 12:51:11 +02:00
|
|
|
|
|
|
|
// hide empty columns
|
|
|
|
for (int columnIndex = 0, columnCount = m_model->columnCount(), rowCount = m_model->rowCount(); columnIndex != columnCount; ++columnIndex) {
|
|
|
|
bool columnHasValues = false;
|
|
|
|
for (int rowIndex = 0; rowIndex != rowCount; ++rowIndex) {
|
|
|
|
const auto value = m_model->data(m_model->index(rowIndex, columnIndex));
|
|
|
|
if (value.isNull()) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-12-14 21:20:14 +01:00
|
|
|
if (
|
|
|
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
|
|
|
value.metaType() == QMetaType::fromType<QString>()
|
|
|
|
#else
|
|
|
|
value.type() == QVariant::String
|
|
|
|
#endif
|
|
|
|
&& value.toString().isEmpty()) {
|
2019-06-01 12:51:11 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
columnHasValues = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
m_ui->resultsTreeView->setColumnHidden(columnIndex, !columnHasValues);
|
|
|
|
}
|
|
|
|
|
2018-08-19 15:11:46 +02:00
|
|
|
setStatus(true);
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DbQueryWidget::setStatus(bool aborted)
|
|
|
|
{
|
|
|
|
m_ui->abortPushButton->setVisible(!aborted);
|
2019-09-02 20:37:31 +02:00
|
|
|
m_searchMusicBrainzAction->setEnabled(aborted);
|
|
|
|
m_searchLyricsWikiaAction->setEnabled(aborted);
|
2016-03-03 22:21:15 +01:00
|
|
|
m_ui->applyPushButton->setVisible(aborted);
|
|
|
|
}
|
|
|
|
|
2016-03-06 17:52:33 +01:00
|
|
|
void DbQueryWidget::fileStatusChanged(bool, bool hasTags)
|
2016-03-03 22:21:15 +01:00
|
|
|
{
|
|
|
|
m_ui->applyPushButton->setEnabled(hasTags && m_ui->resultsTreeView->selectionModel() && m_ui->resultsTreeView->selectionModel()->hasSelection());
|
2016-06-02 22:41:01 +02:00
|
|
|
insertSearchTermsFromActiveTagEdit();
|
|
|
|
m_insertPresentDataAction->setEnabled(hasTags);
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
|
2016-10-24 20:15:10 +02:00
|
|
|
/*!
|
|
|
|
* \brief Applies the selected results for the selected fields to the active tag edit.
|
|
|
|
* \sa applyResults()
|
|
|
|
*/
|
|
|
|
void DbQueryWidget::applySelectedResults()
|
2016-03-03 22:21:15 +01:00
|
|
|
{
|
2019-08-12 20:27:51 +02:00
|
|
|
const auto *const selectionModel = m_ui->resultsTreeView->selectionModel();
|
|
|
|
if (!selectionModel) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const auto selection = selectionModel->selection().indexes();
|
|
|
|
if (!selection.isEmpty()) {
|
|
|
|
applySpecifiedResults(selection.front());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Applies the results for the specified \a modelIndex.
|
|
|
|
*/
|
|
|
|
void DbQueryWidget::applySpecifiedResults(const QModelIndex &modelIndex)
|
|
|
|
{
|
|
|
|
auto *const tagEdit = m_tagEditorWidget->activeTagEdit();
|
|
|
|
if (!tagEdit) {
|
|
|
|
return;
|
2016-10-24 20:15:10 +02:00
|
|
|
}
|
2019-08-12 20:27:51 +02:00
|
|
|
applyResults(tagEdit, modelIndex);
|
2016-10-24 20:15:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Completes all present tag edits with the best matching result row.
|
|
|
|
* \remarks
|
|
|
|
* - Does nothing if no result row matches.
|
|
|
|
* - Only the selected fields are applied.
|
|
|
|
* \sa applyResults()
|
|
|
|
*/
|
|
|
|
void DbQueryWidget::applyMatchingResults()
|
|
|
|
{
|
2018-03-07 01:18:01 +01:00
|
|
|
m_tagEditorWidget->foreachTagEdit(bind(static_cast<void (DbQueryWidget::*)(TagEdit *)>(&DbQueryWidget::applyMatchingResults), this, _1));
|
2016-10-24 20:15:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Completes the specified \a tagEdit with the best matching result row.
|
|
|
|
* \remarks
|
|
|
|
* - Does nothing if no result row matches.
|
|
|
|
* - Only the selected fields are applied.
|
|
|
|
* \sa applyResults()
|
|
|
|
*/
|
|
|
|
void DbQueryWidget::applyMatchingResults(TagEdit *tagEdit)
|
|
|
|
{
|
2018-03-07 01:18:01 +01:00
|
|
|
if (!m_model) {
|
2016-12-01 22:23:01 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-10-24 20:15:10 +02:00
|
|
|
// determine already present title, album and artist
|
2018-08-19 15:11:46 +02:00
|
|
|
const auto givenTitle = tagEdit->value(KnownField::Title);
|
|
|
|
const auto givenAlbum = tagEdit->value(KnownField::Album);
|
|
|
|
const auto givenArtist = tagEdit->value(KnownField::Artist);
|
2019-05-30 14:45:26 +02:00
|
|
|
const auto givenTrack = tagEdit->trackNumber();
|
2019-06-01 12:50:09 +02:00
|
|
|
const auto givenDisk = tagEdit->diskNumber();
|
2016-10-24 20:15:10 +02:00
|
|
|
|
2019-05-31 13:55:36 +02:00
|
|
|
if (givenTitle.isEmpty() && !givenTrack) {
|
2016-12-01 22:23:01 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-10-24 20:15:10 +02:00
|
|
|
// find row matching already present data
|
2018-03-07 01:18:01 +01:00
|
|
|
for (int row = 0, rowCount = m_model->rowCount(); row != rowCount; ++row) {
|
2019-06-01 12:50:09 +02:00
|
|
|
// skip row if title, track, album or artist do not match
|
|
|
|
// -> ignore fields which aren't specified, though
|
|
|
|
// -> ignore track and disk mismatch if the title matches (likely the track/disk number has been taken over incorrectly)
|
2019-08-12 20:27:16 +02:00
|
|
|
constexpr auto options = TagValueComparisionFlags::IgnoreMetaData | TagValueComparisionFlags::CaseInsensitive;
|
2019-06-01 12:50:09 +02:00
|
|
|
const auto rowTitle = m_model->fieldValue(row, KnownField::Title);
|
|
|
|
const auto rowAlbum = m_model->fieldValue(row, KnownField::Album);
|
|
|
|
const auto rowArtist = m_model->fieldValue(row, KnownField::Artist);
|
|
|
|
const auto rowTrack = m_model->fieldValue(row, KnownField::PartNumber).toInteger();
|
|
|
|
const auto rowDisk = m_model->fieldValue(row, KnownField::DiskPosition).toInteger();
|
2019-08-12 20:27:16 +02:00
|
|
|
const auto titleMismatch = !givenTitle.compareTo(rowTitle, options);
|
|
|
|
if ((!givenTitle.isEmpty() && titleMismatch) || (!givenAlbum.isEmpty() && !givenAlbum.compareTo(rowAlbum, options))
|
|
|
|
|| (!givenArtist.isEmpty() && !givenArtist.compareTo(rowArtist, options))
|
2019-06-01 12:50:09 +02:00
|
|
|
|| (givenTrack && (givenTitle.isEmpty() || titleMismatch) && givenTrack != rowTrack)
|
|
|
|
|| (givenDisk && rowDisk && (givenTitle.isEmpty() || titleMismatch) && givenDisk != rowDisk)) {
|
2016-10-24 20:15:10 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// apply results for matching row
|
2019-06-01 12:54:22 +02:00
|
|
|
const auto rowIndex = m_model->index(row, 0);
|
|
|
|
applyResults(tagEdit, rowIndex);
|
|
|
|
|
|
|
|
// select the row which has just been applied
|
|
|
|
if (auto *const selectionModel = m_ui->resultsTreeView->selectionModel()) {
|
|
|
|
selectionModel->select(rowIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_tagEditorWidget->addParsingNotificationLine(
|
|
|
|
tr("Inserted search result row %1 (with title \"%2\", album \"%3\" and artist \"%4\").")
|
|
|
|
.arg(row + 1)
|
|
|
|
.arg(tagValueToQString(rowTitle), tagValueToQString(rowAlbum), tagValueToQString(rowArtist)));
|
2016-10-24 20:15:10 +02:00
|
|
|
|
|
|
|
// just take the first matching row for now
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-01 22:23:01 +01:00
|
|
|
/*!
|
|
|
|
* \brief The same as applyMatchingResults() but checks whether auto-insert is enabled before (and does nothing if not).
|
|
|
|
*/
|
|
|
|
void DbQueryWidget::autoInsertMatchingResults()
|
|
|
|
{
|
2018-03-07 01:18:01 +01:00
|
|
|
if (m_ui->autoInsertCheckBox->isChecked()) {
|
2016-12-01 22:23:01 +01:00
|
|
|
applyMatchingResults();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-24 20:15:10 +02:00
|
|
|
/*!
|
|
|
|
* \brief Applies the results at the specified \a resultIndex for the selected fields to the specified \a tagEdit.
|
|
|
|
* \remarks
|
|
|
|
* - Returns instantly. If cover/lyrics need to be retrieved, this is done asynchronously.
|
|
|
|
* - Does nothing if no results are available.
|
|
|
|
*/
|
|
|
|
void DbQueryWidget::applyResults(TagEdit *tagEdit, const QModelIndex &resultIndex)
|
|
|
|
{
|
2018-08-19 15:11:46 +02:00
|
|
|
if (!m_model) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// determine previous value handling
|
|
|
|
const auto previousValueHandling = m_ui->overrideCheckBox->isChecked() ? PreviousValueHandling::Update : PreviousValueHandling::Keep;
|
|
|
|
|
|
|
|
// loop through all fields
|
|
|
|
for (const ChecklistItem &item : values().dbQuery.fields.items()) {
|
|
|
|
if (!item.isChecked()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// determine the field to be used and its value
|
|
|
|
const auto field = static_cast<KnownField>(item.id().toInt());
|
|
|
|
const auto row = resultIndex.row();
|
|
|
|
const auto value = m_model->fieldValue(row, field);
|
|
|
|
|
|
|
|
// set the value if available
|
|
|
|
if (!value.isEmpty()) {
|
|
|
|
tagEdit->setValue(field, value, previousValueHandling);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// cover and lyrics might be fetched asynchronously
|
|
|
|
switch (field) {
|
|
|
|
case KnownField::Cover:
|
|
|
|
if (m_model->fetchCover(resultIndex)) {
|
|
|
|
// cover is available now
|
|
|
|
tagEdit->setValue(KnownField::Cover, m_model->fieldValue(row, KnownField::Cover), previousValueHandling);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// cover is fetched asynchronously
|
|
|
|
// -> show status
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Progress);
|
|
|
|
m_ui->notificationLabel->appendLine(tr("Retrieving cover art to be applied ..."));
|
|
|
|
setStatus(false);
|
|
|
|
// -> apply cover when available
|
|
|
|
connect(m_model, &QueryResultsModel::coverAvailable, [this, row, previousValueHandling](const QModelIndex &index) {
|
|
|
|
if (row != index.row()) {
|
|
|
|
return;
|
|
|
|
}
|
2021-03-20 21:59:49 +01:00
|
|
|
if (auto *const activeTagEdit = m_tagEditorWidget->activeTagEdit()) {
|
|
|
|
activeTagEdit->setValue(KnownField::Cover, m_model->fieldValue(row, KnownField::Cover), previousValueHandling);
|
2016-03-06 17:52:33 +01:00
|
|
|
}
|
2018-08-19 15:11:46 +02:00
|
|
|
});
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KnownField::Lyrics:
|
|
|
|
if (m_model->fetchLyrics(resultIndex)) {
|
|
|
|
// lyrics are available now
|
|
|
|
tagEdit->setValue(KnownField::Lyrics, m_model->fieldValue(row, KnownField::Lyrics), previousValueHandling);
|
|
|
|
continue;
|
2016-03-06 17:52:33 +01:00
|
|
|
}
|
2018-08-19 15:11:46 +02:00
|
|
|
|
|
|
|
// lyrics are fetched asynchronously
|
|
|
|
// -> show status
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Progress);
|
|
|
|
m_ui->notificationLabel->appendLine(tr("Retrieving lyrics to be applied ..."));
|
|
|
|
setStatus(false);
|
|
|
|
// -> apply cover when available
|
|
|
|
connect(m_model, &QueryResultsModel::lyricsAvailable, [this, row, previousValueHandling](const QModelIndex &index) {
|
|
|
|
if (row != index.row()) {
|
|
|
|
return;
|
|
|
|
}
|
2021-03-20 21:59:49 +01:00
|
|
|
if (auto *const activeTagEdit = m_tagEditorWidget->activeTagEdit()) {
|
|
|
|
activeTagEdit->setValue(KnownField::Lyrics, m_model->fieldValue(row, KnownField::Lyrics), previousValueHandling);
|
2018-08-19 15:11:46 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:;
|
2016-03-06 17:52:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-02 22:41:01 +02:00
|
|
|
void DbQueryWidget::insertSearchTermsFromActiveTagEdit()
|
|
|
|
{
|
|
|
|
insertSearchTermsFromTagEdit(m_tagEditorWidget->activeTagEdit());
|
|
|
|
}
|
|
|
|
|
2019-07-20 18:42:32 +02:00
|
|
|
void DbQueryWidget::showResultsContextMenu(const QPoint &pos)
|
2016-03-06 17:52:33 +01:00
|
|
|
{
|
2018-08-19 15:11:46 +02:00
|
|
|
const auto *const selectionModel = m_ui->resultsTreeView->selectionModel();
|
2019-09-02 22:12:03 +02:00
|
|
|
const auto hasSelection = selectionModel && !selectionModel->selection().isEmpty();
|
|
|
|
|
2018-08-19 15:11:46 +02:00
|
|
|
QMenu contextMenu;
|
2019-09-02 22:12:03 +02:00
|
|
|
if (hasSelection && m_ui->applyPushButton->isEnabled()) {
|
2018-08-19 15:11:46 +02:00
|
|
|
contextMenu.addAction(m_ui->applyPushButton->icon(), tr("Use selected row"), this,
|
|
|
|
static_cast<void (DbQueryWidget::*)(void)>(&DbQueryWidget::applySelectedResults));
|
|
|
|
}
|
2019-02-13 18:15:49 +01:00
|
|
|
#ifndef QT_NO_CLIPBOARD
|
2019-09-02 22:12:03 +02:00
|
|
|
if (hasSelection) {
|
2019-02-13 18:15:49 +01:00
|
|
|
contextMenu.addAction(QIcon::fromTheme(QStringLiteral("edit-copy")), tr("Copy value"), this, &DbQueryWidget::copySelectedResult);
|
2019-09-02 22:12:03 +02:00
|
|
|
}
|
2019-02-13 18:15:49 +01:00
|
|
|
#endif
|
2019-09-02 22:12:03 +02:00
|
|
|
contextMenu.addAction(QIcon::fromTheme(QStringLiteral("view-refresh")), tr("Refresh results"), m_lastSearchAction, &QAction::trigger);
|
|
|
|
if (hasSelection) {
|
|
|
|
contextMenu.addSeparator();
|
2018-08-19 15:11:46 +02:00
|
|
|
contextMenu.addAction(
|
|
|
|
QIcon::fromTheme(QStringLiteral("view-preview")), tr("Show cover"), this, &DbQueryWidget::fetchAndShowCoverForSelection);
|
|
|
|
contextMenu.addAction(
|
|
|
|
QIcon::fromTheme(QStringLiteral("view-media-lyrics")), tr("Show lyrics"), this, &DbQueryWidget::fetchAndShowLyricsForSelection);
|
|
|
|
contextMenu.addAction(
|
|
|
|
QIcon::fromTheme(QStringLiteral("internet-web-browser")), tr("Show in browser"), this, &DbQueryWidget::openSelectionInBrowser);
|
2016-03-06 17:52:33 +01:00
|
|
|
}
|
2019-09-02 22:12:03 +02:00
|
|
|
if (!contextMenu.isEmpty()) {
|
|
|
|
contextMenu.addSeparator();
|
|
|
|
}
|
|
|
|
contextMenu.addMenu(m_menu);
|
2019-07-20 18:42:32 +02:00
|
|
|
m_contextMenuPos = m_ui->resultsTreeView->viewport()->mapToGlobal(pos);
|
2019-02-13 18:15:49 +01:00
|
|
|
contextMenu.exec(m_contextMenuPos);
|
2016-03-06 17:52:33 +01:00
|
|
|
}
|
|
|
|
|
2019-02-13 18:15:49 +01:00
|
|
|
#ifndef QT_NO_CLIPBOARD
|
|
|
|
void DbQueryWidget::copySelectedResult()
|
|
|
|
{
|
|
|
|
auto *const clipboard = QGuiApplication::clipboard();
|
|
|
|
if (!clipboard) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const auto selectedIndex = this->selectedIndex();
|
|
|
|
if (!selectedIndex.isValid()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const auto clickedColumnIndex = m_ui->resultsTreeView->indexAt(m_ui->resultsTreeView->mapFromGlobal(m_contextMenuPos));
|
|
|
|
if (!clickedColumnIndex.isValid()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const auto value = m_model->data(m_model->index(selectedIndex.row(), clickedColumnIndex.column()));
|
|
|
|
if (value.isValid()) {
|
|
|
|
clipboard->setText(value.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-03-06 17:52:33 +01:00
|
|
|
void DbQueryWidget::fetchAndShowCoverForSelection()
|
|
|
|
{
|
2018-08-19 15:11:46 +02:00
|
|
|
const auto selectedIndex = this->selectedIndex();
|
2018-03-07 01:18:01 +01:00
|
|
|
if (!selectedIndex.isValid()) {
|
2017-08-08 20:04:17 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-19 15:11:46 +02:00
|
|
|
if (m_model->fetchCover(selectedIndex)) {
|
2019-09-25 18:18:06 +02:00
|
|
|
if (const auto *const cover = m_model->cover(selectedIndex)) {
|
2018-08-19 15:11:46 +02:00
|
|
|
showCover(*cover);
|
2017-08-08 20:04:17 +02:00
|
|
|
} else {
|
2018-08-19 15:11:46 +02:00
|
|
|
// cover couldn't be fetched, error tracked via resultsAvailable() signal so nothing to do
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
2018-08-19 15:11:46 +02:00
|
|
|
} else {
|
|
|
|
// cover is fetched asynchronously
|
|
|
|
// -> memorize index to be shown
|
|
|
|
m_coverIndex = selectedIndex.row();
|
|
|
|
// -> show status
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Progress);
|
|
|
|
m_ui->notificationLabel->setText(tr("Retrieving cover art ..."));
|
|
|
|
setStatus(false);
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-09 22:41:34 +02:00
|
|
|
void DbQueryWidget::fetchAndShowLyricsForSelection()
|
|
|
|
{
|
2018-08-19 15:11:46 +02:00
|
|
|
const auto selectedIndex = this->selectedIndex();
|
2018-03-07 01:18:01 +01:00
|
|
|
if (!selectedIndex.isValid()) {
|
2017-08-08 20:04:17 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-19 15:11:46 +02:00
|
|
|
if (m_model->fetchLyrics(selectedIndex)) {
|
2019-09-25 18:18:06 +02:00
|
|
|
if (const auto *const lyrics = m_model->lyrics(selectedIndex)) {
|
|
|
|
showLyrics(*lyrics);
|
2017-08-08 20:04:17 +02:00
|
|
|
} else {
|
2018-08-19 15:11:46 +02:00
|
|
|
// lyrics couldn't be fetched, error tracked via resultsAvailable() signal so nothing to do
|
2016-10-09 22:41:34 +02:00
|
|
|
}
|
2018-08-19 15:11:46 +02:00
|
|
|
} else {
|
|
|
|
// lyrics are fetched asynchronously
|
|
|
|
// -> memorize index to be shown
|
|
|
|
m_lyricsIndex = selectedIndex.row();
|
|
|
|
// -> show status
|
|
|
|
m_ui->notificationLabel->setNotificationType(NotificationType::Progress);
|
|
|
|
m_ui->notificationLabel->setText(tr("Retrieving lyrics ..."));
|
|
|
|
setStatus(false);
|
2016-10-09 22:41:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-08 20:22:37 +02:00
|
|
|
void DbQueryWidget::openSelectionInBrowser()
|
|
|
|
{
|
2018-08-19 15:11:46 +02:00
|
|
|
const auto selectedIndex = this->selectedIndex();
|
2018-03-07 01:18:01 +01:00
|
|
|
if (!selectedIndex.isValid()) {
|
2017-08-08 20:22:37 +02:00
|
|
|
return;
|
|
|
|
}
|
2018-08-19 15:11:46 +02:00
|
|
|
const auto url = m_model->webUrl(selectedIndex);
|
2018-03-07 01:18:01 +01:00
|
|
|
if (url.isEmpty()) {
|
2019-09-02 22:12:03 +02:00
|
|
|
m_ui->notificationLabel->appendLine(tr("No web URL available"));
|
2017-08-08 20:22:37 +02:00
|
|
|
return;
|
|
|
|
}
|
2018-03-07 01:18:01 +01:00
|
|
|
if (!QDesktopServices::openUrl(url)) {
|
2017-08-08 20:22:37 +02:00
|
|
|
m_ui->notificationLabel->appendLine(tr("Unable to open URL: ") + url.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-06 17:52:33 +01:00
|
|
|
void DbQueryWidget::showCover(const QByteArray &data)
|
|
|
|
{
|
|
|
|
QDialog dlg;
|
|
|
|
dlg.setWindowFlags(Qt::Tool);
|
|
|
|
dlg.setWindowTitle(tr("Cover - %1").arg(QApplication::applicationName()));
|
|
|
|
QBoxLayout layout(QBoxLayout::Up);
|
2019-06-25 14:00:09 +02:00
|
|
|
layout.setContentsMargins(0, 0, 0, 0);
|
2016-03-06 17:52:33 +01:00
|
|
|
QGraphicsView view(&dlg);
|
|
|
|
QGraphicsScene scene;
|
|
|
|
layout.addWidget(&view);
|
|
|
|
scene.addItem(new QGraphicsPixmapItem(QPixmap::fromImage(QImage::fromData(data))));
|
|
|
|
view.setScene(&scene);
|
|
|
|
view.show();
|
|
|
|
dlg.setLayout(&layout);
|
|
|
|
dlg.exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DbQueryWidget::showCoverFromIndex(const QModelIndex &index)
|
|
|
|
{
|
2018-03-07 01:18:01 +01:00
|
|
|
if (m_coverIndex == index.row()) {
|
2016-03-06 17:52:33 +01:00
|
|
|
m_coverIndex = -1;
|
|
|
|
showCover(*m_model->cover(index));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-09 22:41:34 +02:00
|
|
|
void DbQueryWidget::showLyrics(const QString &data)
|
|
|
|
{
|
|
|
|
QDialog dlg;
|
|
|
|
dlg.setWindowFlags(Qt::Tool);
|
|
|
|
dlg.setWindowTitle(tr("Lyrics - %1").arg(QApplication::applicationName()));
|
|
|
|
QBoxLayout layout(QBoxLayout::Up);
|
2019-06-25 14:00:09 +02:00
|
|
|
layout.setContentsMargins(0, 0, 0, 0);
|
2016-10-09 22:41:34 +02:00
|
|
|
QTextBrowser textBrowser;
|
|
|
|
layout.addWidget(&textBrowser);
|
|
|
|
textBrowser.setText(data);
|
|
|
|
dlg.setLayout(&layout);
|
|
|
|
dlg.resize(400, 400);
|
|
|
|
dlg.exec();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DbQueryWidget::showLyricsFromIndex(const QModelIndex &index)
|
|
|
|
{
|
2018-03-07 01:18:01 +01:00
|
|
|
if (m_lyricsIndex == index.row()) {
|
2016-10-09 22:41:34 +02:00
|
|
|
m_lyricsIndex = -1;
|
|
|
|
showLyrics(*m_model->lyrics(index));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-26 22:19:27 +02:00
|
|
|
bool DbQueryWidget::event(QEvent *event)
|
|
|
|
{
|
|
|
|
const auto res = QWidget::event(event);
|
|
|
|
switch (event->type()) {
|
|
|
|
case QEvent::PaletteChange:
|
|
|
|
updateStyleSheet();
|
|
|
|
break;
|
|
|
|
default:;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2016-06-02 22:41:01 +02:00
|
|
|
void DbQueryWidget::clearSearchCriteria()
|
|
|
|
{
|
|
|
|
m_ui->titleLineEdit->clear();
|
|
|
|
m_ui->albumLineEdit->clear();
|
|
|
|
m_ui->artistLineEdit->clear();
|
|
|
|
m_ui->trackSpinBox->setValue(0);
|
|
|
|
}
|
|
|
|
|
2023-03-26 22:19:27 +02:00
|
|
|
void DbQueryWidget::updateStyleSheet()
|
|
|
|
{
|
|
|
|
#ifdef Q_OS_WINDOWS
|
|
|
|
setStyleSheet(dialogStyleForPalette(palette()));
|
|
|
|
#else
|
|
|
|
setStyleSheet(QStringLiteral("QGroupBox { color: palette(text); background-color: palette(base); }"));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-03-03 22:21:15 +01:00
|
|
|
bool DbQueryWidget::eventFilter(QObject *obj, QEvent *event)
|
|
|
|
{
|
2018-03-07 01:18:01 +01:00
|
|
|
if (obj == m_ui->searchGroupBox) {
|
|
|
|
switch (event->type()) {
|
2016-03-28 20:28:59 +02:00
|
|
|
case QEvent::KeyRelease:
|
2018-03-07 01:18:01 +01:00
|
|
|
switch (static_cast<QKeyEvent *>(event)->key()) {
|
2016-03-03 22:21:15 +01:00
|
|
|
case Qt::Key_Return:
|
2019-09-02 20:37:31 +02:00
|
|
|
m_lastSearchAction->trigger();
|
2016-03-03 22:21:15 +01:00
|
|
|
break;
|
2018-03-07 01:18:01 +01:00
|
|
|
default:;
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
break;
|
2018-03-07 01:18:01 +01:00
|
|
|
default:;
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
}
|
2016-03-28 20:28:59 +02:00
|
|
|
return QWidget::eventFilter(obj, event);
|
2016-03-03 22:21:15 +01:00
|
|
|
}
|
|
|
|
|
2017-08-08 19:16:11 +02:00
|
|
|
void DbQueryWidget::useQueryResults(QueryResultsModel *queryResults)
|
|
|
|
{
|
|
|
|
m_ui->resultsTreeView->setModel(m_model = queryResults);
|
|
|
|
connect(queryResults, &QueryResultsModel::resultsAvailable, this, &DbQueryWidget::showResults);
|
|
|
|
connect(queryResults, &QueryResultsModel::lyricsAvailable, this, &DbQueryWidget::showLyricsFromIndex);
|
|
|
|
connect(queryResults, &QueryResultsModel::coverAvailable, this, &DbQueryWidget::showCoverFromIndex);
|
2019-09-03 22:04:43 +02:00
|
|
|
connect(queryResults, &QAbstractItemModel::modelReset, this, &DbQueryWidget::autoInsertMatchingResults);
|
2017-08-08 19:16:11 +02:00
|
|
|
}
|
|
|
|
|
2017-08-08 20:04:17 +02:00
|
|
|
QModelIndex DbQueryWidget::selectedIndex() const
|
|
|
|
{
|
2018-03-07 01:18:01 +01:00
|
|
|
if (!m_model) {
|
2017-08-08 20:04:17 +02:00
|
|
|
return QModelIndex();
|
|
|
|
}
|
2018-08-19 15:11:46 +02:00
|
|
|
const auto *const selectionModel = m_ui->resultsTreeView->selectionModel();
|
2018-03-07 01:18:01 +01:00
|
|
|
if (!selectionModel) {
|
2017-08-08 20:04:17 +02:00
|
|
|
return QModelIndex();
|
|
|
|
}
|
2018-08-19 15:11:46 +02:00
|
|
|
const auto selection = selectionModel->selectedRows();
|
2018-03-07 01:18:01 +01:00
|
|
|
if (selection.size() != 1) {
|
2017-08-08 20:04:17 +02:00
|
|
|
return QModelIndex();
|
|
|
|
}
|
|
|
|
return selection.at(0);
|
|
|
|
}
|
|
|
|
|
2018-03-07 01:18:01 +01:00
|
|
|
} // namespace QtGui
|