File indexing completed on 2025-02-23 04:34:19
0001 /** 0002 * \file servertrackimportdialog.cpp 0003 * Generic dialog for track based import from a server. 0004 * 0005 * \b Project: Kid3 0006 * \author Urs Fleisch 0007 * \date 13 Sep 2005 0008 * 0009 * Copyright (C) 2005-2024 Urs Fleisch 0010 * 0011 * This file is part of Kid3. 0012 * 0013 * Kid3 is free software; you can redistribute it and/or modify 0014 * it under the terms of the GNU General Public License as published by 0015 * the Free Software Foundation; either version 2 of the License, or 0016 * (at your option) any later version. 0017 * 0018 * Kid3 is distributed in the hope that it will be useful, 0019 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0021 * GNU General Public License for more details. 0022 * 0023 * You should have received a copy of the GNU General Public License 0024 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0025 */ 0026 0027 #include "servertrackimportdialog.h" 0028 #include <QLayout> 0029 #include <QPushButton> 0030 #include <QLineEdit> 0031 #include <QComboBox> 0032 #include <QCheckBox> 0033 #include <QLabel> 0034 #include <QStatusBar> 0035 #include <QTableView> 0036 #include <QHeaderView> 0037 #include <QVBoxLayout> 0038 #include <QHBoxLayout> 0039 #include <QCoreApplication> 0040 #include "serverimporterconfig.h" 0041 #include "contexthelp.h" 0042 #include "servertrackimporter.h" 0043 #include "comboboxdelegate.h" 0044 #include "trackdatamodel.h" 0045 #include "standardtablemodel.h" 0046 0047 namespace { 0048 0049 class AlbumTableModel : public StandardTableModel { 0050 public: 0051 using StandardTableModel::StandardTableModel; 0052 0053 Qt::ItemFlags flags(const QModelIndex& index) const override { 0054 Qt::ItemFlags itemFlags = 0055 QAbstractItemModel::flags(index) | Qt::ItemIsDropEnabled; 0056 if (index.isValid()) 0057 itemFlags |= Qt::ItemIsDragEnabled; 0058 if (index.column() != 1) 0059 itemFlags |= Qt::ItemIsEditable; 0060 return itemFlags; 0061 } 0062 }; 0063 0064 } 0065 0066 /** 0067 * Constructor. 0068 * 0069 * @param parent parent widget 0070 * @param trackDataModel track data to be filled with imported values, 0071 * is passed with filenames set 0072 */ 0073 ServerTrackImportDialog::ServerTrackImportDialog(QWidget* parent, 0074 TrackDataModel* trackDataModel) 0075 : QDialog(parent), m_statusBar(nullptr), 0076 m_client(nullptr), m_trackDataModel(trackDataModel) 0077 { 0078 setObjectName(QLatin1String("ServerTrackImportDialog")); 0079 setModal(true); 0080 0081 auto vlayout = new QVBoxLayout(this); 0082 auto serverLayout = new QHBoxLayout; 0083 m_serverLabel = new QLabel(tr("&Server:"), this); 0084 m_serverComboBox = new QComboBox(this); 0085 m_serverComboBox->setEditable(true); 0086 m_serverComboBox->setSizePolicy( 0087 QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); 0088 m_serverLabel->setBuddy(m_serverComboBox); 0089 serverLayout->addWidget(m_serverLabel); 0090 serverLayout->addWidget(m_serverComboBox); 0091 vlayout->addLayout(serverLayout); 0092 0093 m_albumTableModel = new AlbumTableModel(this); 0094 m_albumTableModel->setColumnCount(2); 0095 m_albumTableModel->setHorizontalHeaderLabels({ 0096 QLatin1String("08 A Not So Short Title/Medium Sized Artist - And The Album Title [2005]"), 0097 QLatin1String("A Not So Short State") 0098 }); 0099 m_albumTable = new QTableView(this); 0100 m_albumTable->setModel(m_albumTableModel); 0101 m_albumTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); 0102 m_albumTable->setSelectionMode(QAbstractItemView::NoSelection); 0103 m_albumTable->resizeColumnsToContents(); 0104 m_albumTable->setItemDelegateForColumn(0, new ComboBoxDelegate(this)); 0105 m_albumTableModel->setHorizontalHeaderLabels({ 0106 tr("Track Title/Artist - Album"), 0107 tr("State") 0108 }); 0109 initTable(); 0110 vlayout->addWidget(m_albumTable); 0111 0112 auto hlayout = new QHBoxLayout; 0113 auto hspacer = new QSpacerItem(16, 0, QSizePolicy::Expanding, 0114 QSizePolicy::Minimum); 0115 m_helpButton = new QPushButton(tr("&Help"), this); 0116 m_helpButton->setAutoDefault(false); 0117 m_saveButton = new QPushButton(tr("&Save Settings"), this); 0118 m_saveButton->setAutoDefault(false); 0119 auto okButton = new QPushButton(tr("&OK"), this); 0120 auto applyButton = new QPushButton(tr("&Apply"), this); 0121 auto cancelButton = new QPushButton(tr("&Cancel"), this); 0122 hlayout->addWidget(m_helpButton); 0123 hlayout->addWidget(m_saveButton); 0124 hlayout->addItem(hspacer); 0125 hlayout->addWidget(okButton); 0126 hlayout->addWidget(applyButton); 0127 hlayout->addWidget(cancelButton); 0128 // auto default is switched off to use the return key to set the server 0129 // configuration 0130 okButton->setAutoDefault(false); 0131 okButton->setDefault(true); 0132 cancelButton->setAutoDefault(false); 0133 applyButton->setAutoDefault(false); 0134 connect(m_helpButton, &QAbstractButton::clicked, this, &ServerTrackImportDialog::showHelp); 0135 connect(m_saveButton, &QAbstractButton::clicked, this, &ServerTrackImportDialog::saveConfig); 0136 connect(okButton, &QAbstractButton::clicked, this, &ServerTrackImportDialog::accept); 0137 connect(cancelButton, &QAbstractButton::clicked, this, &ServerTrackImportDialog::reject); 0138 connect(applyButton, &QAbstractButton::clicked, this, &ServerTrackImportDialog::apply); 0139 vlayout->addLayout(hlayout); 0140 0141 m_statusBar = new QStatusBar(this); 0142 vlayout->addWidget(m_statusBar); 0143 connect(m_albumTable->selectionModel(), 0144 &QItemSelectionModel::currentRowChanged, 0145 this, &ServerTrackImportDialog::showFilenameInStatusBar); 0146 } 0147 0148 /** 0149 * Destructor. 0150 */ 0151 ServerTrackImportDialog::~ServerTrackImportDialog() 0152 { 0153 stopClient(); 0154 } 0155 0156 /** 0157 * Set importer to be used. 0158 * 0159 * @param source import source to use 0160 */ 0161 void ServerTrackImportDialog::setImportSource(ServerTrackImporter* source) 0162 { 0163 if (m_client) { 0164 disconnect(m_client, &ServerTrackImporter::statusChanged, 0165 this, &ServerTrackImportDialog::setFileStatus); 0166 disconnect(m_client, &ServerTrackImporter::resultsReceived, 0167 this, &ServerTrackImportDialog::setResults); 0168 } 0169 m_client = source; 0170 0171 if (m_client) { 0172 connect(m_client, &ServerTrackImporter::statusChanged, 0173 this, &ServerTrackImportDialog::setFileStatus); 0174 connect(m_client, &ServerTrackImporter::resultsReceived, 0175 this, &ServerTrackImportDialog::setResults); 0176 0177 setWindowTitle(QCoreApplication::translate("@default", m_client->name())); 0178 if (m_client->defaultServer()) { 0179 m_serverLabel->show(); 0180 m_serverComboBox->show(); 0181 if (m_client->serverList()) { 0182 QStringList strList; 0183 for (const char** sl = m_client->serverList(); *sl != nullptr; ++sl) { 0184 strList += QString::fromLatin1(*sl); // clazy:exclude=reserve-candidates 0185 } 0186 m_serverComboBox->clear(); 0187 m_serverComboBox->addItems(strList); 0188 } 0189 } else { 0190 m_serverLabel->hide(); 0191 m_serverComboBox->hide(); 0192 } 0193 if (m_client->helpAnchor()) { 0194 m_helpButton->show(); 0195 } else { 0196 m_helpButton->hide(); 0197 } 0198 if (m_client->config()) { 0199 m_saveButton->show(); 0200 } else { 0201 m_saveButton->hide(); 0202 } 0203 } 0204 } 0205 0206 /** 0207 * Initialize the table model. 0208 * Has to be called before reusing the dialog with new track data. 0209 */ 0210 void ServerTrackImportDialog::initTable() 0211 { 0212 if (m_client && m_client->config()) { 0213 setServer(m_client->config()->server()); 0214 } 0215 0216 int numRows = 0; 0217 const ImportTrackDataVector& trackDataVector(m_trackDataModel->trackData()); 0218 for (auto it = trackDataVector.constBegin(); it != trackDataVector.constEnd(); ++it) { 0219 if (it->isEnabled()) { 0220 ++numRows; 0221 } 0222 } 0223 0224 m_trackResults.resize(numRows); 0225 m_albumTableModel->clear(); 0226 m_albumTableModel->insertRows(0, numRows); 0227 for (int i = 0; i < numRows; ++i) { 0228 QStringList cbItems; 0229 cbItems << tr("No result") << tr("Unknown"); 0230 QModelIndex idx = m_albumTableModel->index(i, 0); 0231 m_albumTableModel->setData(idx, cbItems.first(), Qt::EditRole); 0232 m_albumTableModel->setData(idx, cbItems, Qt::UserRole); 0233 idx = m_albumTableModel->index(i, 1); 0234 m_albumTableModel->setData(idx, tr("Unknown")); 0235 } 0236 showFilenameInStatusBar(m_albumTable->currentIndex()); 0237 } 0238 0239 /** 0240 * Clear all results. 0241 */ 0242 void ServerTrackImportDialog::clearResults() 0243 { 0244 const int numRows = m_trackResults.size(); 0245 for (int i = 0; i < numRows; ++i) { 0246 m_trackResults[i].clear(); 0247 setFileStatus(i, tr("Unknown")); 0248 updateFileTrackData(i); 0249 } 0250 } 0251 0252 /** 0253 * Create and start the track import client. 0254 */ 0255 void ServerTrackImportDialog::startClient() 0256 { 0257 if (m_client) { 0258 clearResults(); 0259 ServerImporterConfig cfg; 0260 cfg.setServer(getServer()); 0261 m_client->setConfig(&cfg); 0262 m_client->start(); 0263 } 0264 } 0265 0266 /** 0267 * Stop and destroy the track import client. 0268 */ 0269 void ServerTrackImportDialog::stopClient() 0270 { 0271 if (m_client) { 0272 m_client->stop(); 0273 } 0274 } 0275 0276 /** 0277 * Hides the dialog and sets the result to QDialog::Accepted. 0278 */ 0279 void ServerTrackImportDialog::accept() 0280 { 0281 apply(); 0282 stopClient(); 0283 QDialog::accept(); 0284 } 0285 0286 /** 0287 * Hides the dialog and sets the result to QDialog::Rejected. 0288 */ 0289 void ServerTrackImportDialog::reject() 0290 { 0291 stopClient(); 0292 QDialog::reject(); 0293 } 0294 0295 /** 0296 * Apply imported data. 0297 */ 0298 void ServerTrackImportDialog::apply() 0299 { 0300 ImportTrackDataVector trackDataVector(m_trackDataModel->getTrackData()); 0301 trackDataVector.setCoverArtUrl(QUrl()); 0302 auto it = trackDataVector.begin(); 0303 bool newTrackData = false; 0304 int numRows = m_albumTableModel->rowCount(); 0305 for (int index = 0; index < numRows; ++index) { 0306 while (it != trackDataVector.end() && !it->isEnabled()) { 0307 ++it; 0308 } 0309 if (it == trackDataVector.end()) { 0310 break; 0311 } 0312 QModelIndex idx(m_albumTableModel->index(index, 0)); 0313 if (idx.isValid()) { 0314 if (int selectedItem = idx.data(Qt::UserRole).toStringList().indexOf( 0315 idx.data(Qt::EditRole).toString()); 0316 selectedItem > 0) { 0317 const ImportTrackData& selectedData = 0318 m_trackResults[index][selectedItem - 1]; 0319 it->setTitle(selectedData.getTitle()); 0320 it->setArtist(selectedData.getArtist()); 0321 it->setAlbum(selectedData.getAlbum()); 0322 it->setTrack(selectedData.getTrack()); 0323 it->setYear(selectedData.getYear()); 0324 it->setImportDuration(selectedData.getImportDuration()); 0325 newTrackData = true; 0326 } 0327 } 0328 ++it; 0329 } 0330 if (newTrackData) { 0331 m_trackDataModel->setTrackData(trackDataVector); 0332 emit trackDataUpdated(); 0333 } 0334 } 0335 0336 /** 0337 * Shows the dialog as a modal dialog. 0338 */ 0339 int ServerTrackImportDialog::exec() 0340 { 0341 startClient(); 0342 return QDialog::exec(); 0343 } 0344 0345 /** 0346 * Set the status of a file. 0347 * 0348 * @param index index of file 0349 * @param status status string 0350 */ 0351 void ServerTrackImportDialog::setFileStatus(int index, const QString& status) 0352 { 0353 m_albumTableModel->setData(m_albumTableModel->index(index, 1), 0354 status); 0355 } 0356 0357 /** 0358 * Update the track data combo box of a file. 0359 * 0360 * @param index index of file 0361 */ 0362 void ServerTrackImportDialog::updateFileTrackData(int index) 0363 { 0364 QStringList stringList; 0365 const ImportTrackDataVector& trackData = m_trackResults.at(index); 0366 const int numResults = trackData.size(); 0367 QString str(numResults == 0 ? 0368 tr("No result") : tr("No result selected")); 0369 stringList.push_back(str); 0370 for (auto it = trackData.constBegin(); it != trackData.constEnd(); ++it) { 0371 str = QString(QLatin1String("%1 ")) 0372 .arg(it->getTrack(), 2, 10, QLatin1Char('0')); 0373 str += it->getTitle(); 0374 str += QLatin1Char('/'); 0375 str += it->getArtist(); 0376 str += QLatin1String(" - "); 0377 str += it->getAlbum(); 0378 if (it->getYear() > 0) { 0379 str += QString(QLatin1String(" [%1]")).arg(it->getYear()); 0380 } 0381 stringList.push_back(str); 0382 } 0383 m_albumTableModel->setData(m_albumTableModel->index(index, 0), 0384 stringList, Qt::UserRole); 0385 m_albumTableModel->setData(m_albumTableModel->index(index, 0), 0386 stringList.at(numResults == 1 ? 1 : 0), 0387 Qt::EditRole); 0388 } 0389 0390 /** 0391 * Set result list for a file. 0392 * 0393 * @param index index of file 0394 * @param trackDataVector result list 0395 */ 0396 void ServerTrackImportDialog::setResults( 0397 int index, const ImportTrackDataVector& trackDataVector) 0398 { 0399 m_trackResults[index] = trackDataVector; 0400 updateFileTrackData(index); 0401 } 0402 0403 /** 0404 * Get string with server and port. 0405 * 0406 * @return "servername:port". 0407 */ 0408 QString ServerTrackImportDialog::getServer() const 0409 { 0410 QString server(m_serverComboBox->currentText()); 0411 if (server.isEmpty() && m_client && m_client->defaultServer()) { 0412 server = QString::fromLatin1(m_client->defaultServer()); 0413 } 0414 return server; 0415 } 0416 0417 /** 0418 * Set string with server and port. 0419 * 0420 * @param srv "servername:port" 0421 */ 0422 void ServerTrackImportDialog::setServer(const QString& srv) 0423 { 0424 if (int idx = m_serverComboBox->findText(srv); idx >= 0) { 0425 m_serverComboBox->setCurrentIndex(idx); 0426 } else { 0427 m_serverComboBox->addItem(srv); 0428 m_serverComboBox->setCurrentIndex(m_serverComboBox->count() - 1); 0429 } 0430 } 0431 0432 /** 0433 * Save the local settings to the configuration. 0434 */ 0435 void ServerTrackImportDialog::saveConfig() 0436 { 0437 if (m_client && m_client->config()) { 0438 m_client->config()->setServer(getServer()); 0439 } 0440 } 0441 0442 /** 0443 * Show help. 0444 */ 0445 void ServerTrackImportDialog::showHelp() 0446 { 0447 if (m_client && m_client->helpAnchor()) { 0448 ContextHelp::displayHelp(QString::fromLatin1(m_client->helpAnchor())); 0449 } 0450 } 0451 0452 /** 0453 * Show the name of the current track in the status bar. 0454 * 0455 * @param index model index 0456 */ 0457 void ServerTrackImportDialog::showFilenameInStatusBar(const QModelIndex& index) 0458 { 0459 if (m_statusBar) { 0460 int row = index.row(); 0461 0462 int rowNr = 0; 0463 const ImportTrackDataVector& trackDataVector(m_trackDataModel->trackData()); 0464 for (auto it = trackDataVector.constBegin(); 0465 it != trackDataVector.constEnd(); 0466 ++it) { 0467 if (it->isEnabled()) { 0468 if (rowNr == row) { 0469 m_statusBar->showMessage(it->getFilename()); 0470 return; 0471 } 0472 ++rowNr; 0473 } 0474 } 0475 m_statusBar->clearMessage(); 0476 } 0477 }