videodownloader/gui/addmultipledownloadsdialog.cpp

439 lines
16 KiB
C++

#include "addmultipledownloadsdialog.h"
#include "ui_addmultipledownloadsdialog.h"
#include "download/finder/youtubeplaylist.h"
#include "download/finder/groovesharksearcher.h"
#include <QInputDialog>
#include <QMessageBox>
#include <QStandardItem>
#include <QScrollBar>
#define checkForExistingQuery if(m_finder) { return; }
using namespace ChronoUtilities;
const int AddMultipleDownloadsDialog::m_maxInfoRequests = 3;
const int AddMultipleDownloadsDialog::m_titleCol = 0;
const int AddMultipleDownloadsDialog::m_uploaderCol = 1;
const int AddMultipleDownloadsDialog::m_nrCol = 2;
const int AddMultipleDownloadsDialog::m_collectionCol = 3;
const int AddMultipleDownloadsDialog::m_durationCol = 4;
const int AddMultipleDownloadsDialog::m_idCol = 5;
const QString &emptyField()
{
static const QString value = QStringLiteral("-");
return value;
}
const QString &retrievingField()
{
static const QString value = QApplication::translate("AddMultipleDownloadsDialog", "retrieving ...");
return value;
}
AddMultipleDownloadsDialog::AddMultipleDownloadsDialog(QWidget *parent, const QNetworkProxy &proxy) :
QDialog(parent),
m_ui(new Ui::AddMultipleDownloadsDialog),
m_selectedSource(SelectedSource::YoutubePlaylist),
m_proxy(proxy)
{
// setup ui
m_ui->setupUi(this);
#ifdef Q_OS_WIN32
setStyleSheet(QStringLiteral("* { font: 9pt \"Segoe UI\"; } #mainWidget { color: black; background-color: white; border: none; } #bottomWidget { background-color: #F0F0F0; border-top: 1px solid #DFDFDF; } QMessageBox QLabel, QInputDialog QLabel, QCommandLinkButton { font-size: 12pt; color: #003399; } #buttonsTabWidget, #resultsTabWidget { background-color: white; } #tabWidget:pane { border: none; }"));
#else
setStyleSheet(QStringLiteral("#tabWidget:pane { border: none; }"));
#endif
m_ui->tabWidget->tabBar()->setHidden(true);
m_ui->tabWidget->setCurrentIndex(0);
m_ui->progressBar->setHidden(true);
m_ui->selectAllPushButton->setHidden(true);
m_ui->addPushButton->setHidden(true);
m_ui->searchPushButton->setHidden(true);
m_ui->moreDownloadsAvailableLabel->setHidden(true);
// setup tree view
m_model = new QStandardItemModel(this);
m_model->setHorizontalHeaderLabels(QStringList() << "Title" << "Uploader or Artist" << "Nr." << "Collection name" << "Duration" << "Id");
m_ui->downloadsTreeView->setModel(m_model);
if(QScrollBar *sb = m_ui->downloadsTreeView->verticalScrollBar())
connect(sb, &QScrollBar::valueChanged, this, &AddMultipleDownloadsDialog::scrollBarValueChanged);
// connect signals and slots
connect(m_ui->backPushButton, &QPushButton::clicked, this, &AddMultipleDownloadsDialog::back);
connect(m_ui->addPushButton, &QPushButton::clicked, this, &AddMultipleDownloadsDialog::addResultsClicked);
connect(m_ui->addPushButton, &QPushButton::clicked, this, &AddMultipleDownloadsDialog::accept);
connect(m_ui->searchPushButton, &QPushButton::clicked, this, &AddMultipleDownloadsDialog::startSearch);
connect(m_ui->termLineEdit, &QLineEdit::returnPressed, this, &AddMultipleDownloadsDialog::startSearch);
connect(m_ui->youtubePlaylistCommandLinkButton, &QCommandLinkButton::clicked, this, &AddMultipleDownloadsDialog::youtubePlaylistSelected);
connect(m_ui->groovesharkAlbumCommandLinkButton, &QCommandLinkButton::clicked, this, &AddMultipleDownloadsDialog::groovesharkAlbumSelected);
connect(m_ui->groovesharkPlaylistCommandLinkButton, &QCommandLinkButton::clicked, this, &AddMultipleDownloadsDialog::groovesharkPlaylistSelected);
connect(m_ui->selectAllPushButton, &QPushButton::clicked, this, &AddMultipleDownloadsDialog::selectAll);
connect(m_ui->downloadsTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &AddMultipleDownloadsDialog::updateControls);
// set fields
m_currentInfoRequests = 0;
}
AddMultipleDownloadsDialog::~AddMultipleDownloadsDialog()
{ }
QList<Download *> AddMultipleDownloadsDialog::results()
{
QList<Download *> res;
Download *download;
int rowCount = m_model->rowCount();
QModelIndexList selectedIndexes = m_ui->downloadsTreeView->selectionModel()->selectedRows();
QModelIndex index;
QStandardItem *item;
for(int i = 0; i < rowCount; ++i) {
index = m_model->index(i, 0);
if(selectedIndexes.contains(index)) {
item = m_model->item(i, 0);
download = item->data(Qt::UserRole + 1).value<Download *>();
if(download->status() != DownloadStatus::Failed)
res.append(download);
}
}
return res;
}
void AddMultipleDownloadsDialog::downloadChangedStatus(Download *download)
{
switch(download->status()) {
case DownloadStatus::Failed:
showDownloadError(download);
--m_currentInfoRequests;
break;
case DownloadStatus::Ready:
addDownloadInformation(download);
--m_currentInfoRequests;
break;
default:
;
}
while(m_currentInfoRequests < m_maxInfoRequests
&& !m_pendingDownloads.isEmpty()) {
Download *download = m_pendingDownloads.takeFirst();
if(!download->isInitiated() && download->isInitiatingInstantlyRecommendable()) {
++m_currentInfoRequests;
download->init();
}
}
}
void AddMultipleDownloadsDialog::addFinder(DownloadFinder *finder)
{
m_finder.reset(finder);
m_finder->setContinueAutomatically(false);
connect(finder, &DownloadFinder::newResultsAvailable, this, &AddMultipleDownloadsDialog::addResults);
connect(finder, &DownloadFinder::finished, this, &AddMultipleDownloadsDialog::retrievingFinished);
m_ui->tabWidget->setCurrentIndex(2);
m_ui->progressBar->setHidden(false);
m_ui->addPushButton->setHidden(false);
m_ui->selectAllPushButton->setHidden(false);
m_ui->searchPushButton->setHidden(true);
m_pendingDownloads.clear();
m_currentInfoRequests = 0;
m_ui->titleLabel->setText(tr("Retrieving downloads ..."));
finder->start();
}
void AddMultipleDownloadsDialog::addDownloadInformation(Download *download)
{
QStandardItem *item;
for(int row = 0; row < m_model->rowCount(); ++row) {
item = m_model->item(row, 0);
if(item->data(Qt::UserRole + 1).value<Download *>() == download) {
const QString &title = download->title();
const QString &id = download->id();
const QString &uploader = download->uploader();
const QString &collectionName = download->collectionName();
int nr = download->positionInCollection();
TimeSpan duration = download->duration();
m_model->item(row, m_titleCol)->setText(title.isEmpty() ? emptyField() : title);
m_model->item(row, m_uploaderCol)->setText(uploader.isEmpty() ? emptyField() : uploader);
m_model->item(row, m_nrCol)->setText(nr == 0 ? emptyField() : QStringLiteral("%1").arg(nr));
m_model->item(row, m_collectionCol)->setText(collectionName.isEmpty() ? emptyField() : collectionName);
m_model->item(row, m_durationCol)->setText(duration.isNull() ? emptyField() : QString::fromStdString(duration.toString(TimeSpanOutputFormat::WithMeasures)));
m_model->item(row, m_idCol)->setText(id.isEmpty() ? emptyField() : id);
break;
}
}
}
void AddMultipleDownloadsDialog::showDownloadError(Download *download)
{
QStandardItem *item;
for(int row = 0; row < m_model->rowCount(); ++row) {
item = m_model->item(row, 0);
if(item->data(Qt::UserRole +1).value<Download *>() == download) {
for(int i = m_titleCol; i <= m_idCol; i++) {
item = m_model->item(row, i);
if(i != m_titleCol)
item->setText(QStringLiteral("not found"));
item->setSelectable(false);
}
break;
}
}
}
void AddMultipleDownloadsDialog::youtubePlaylistSelected()
{
checkForExistingQuery;
m_ui->enterTermLabel->setText(tr("Enter the url of the playlist or the id:"));
m_ui->termLineEdit->setInputMethodHints(Qt::ImhUrlCharactersOnly);
m_ui->termLineEdit->setText(m_ui->byIdCheckBox->isChecked() ? QString() : QStringLiteral("http://www.youtube.com/playlist?list="));
m_ui->termLineEdit->selectAll();
m_ui->byIdCheckBox->setHidden(false);
m_ui->verifiedCheckBox->setHidden(true);
m_ui->addPushButton->setHidden(true);
m_ui->searchPushButton->setHidden(false);
m_selectedSource = SelectedSource::YoutubePlaylist;
m_ui->tabWidget->setCurrentIndex(1);
}
void AddMultipleDownloadsDialog::groovesharkAlbumSelected()
{
checkForExistingQuery;
m_ui->enterTermLabel->setText(tr("Enter a search term or the album id:"));
m_ui->termLineEdit->setInputMethodHints(Qt::ImhNone);
m_ui->termLineEdit->clear();
m_ui->byIdCheckBox->setHidden(false);
m_ui->verifiedCheckBox->setHidden(false);
m_ui->addPushButton->setHidden(true);
m_ui->searchPushButton->setHidden(false);
m_selectedSource = SelectedSource::GroovesharkAlbum;
m_ui->tabWidget->setCurrentIndex(1);
// "124486"
}
void AddMultipleDownloadsDialog::groovesharkPlaylistSelected()
{
checkForExistingQuery;
m_ui->enterTermLabel->setText(tr("Enter a search term or the playlist id:"));
m_ui->termLineEdit->setInputMethodHints(Qt::ImhNone);
m_ui->termLineEdit->clear();
m_ui->byIdCheckBox->setHidden(false);
m_ui->verifiedCheckBox->setHidden(false);
m_ui->addPushButton->setHidden(true);
m_ui->searchPushButton->setHidden(false);
m_selectedSource = SelectedSource::GroovesharkPlaylist;
m_ui->tabWidget->setCurrentIndex(1);
}
void AddMultipleDownloadsDialog::startSearch()
{
if(m_ui->tabWidget->currentIndex() != 1)
return;
if(m_ui->termLineEdit->text().isEmpty())
return;
m_ui->searchPushButton->setHidden(false);
switch(m_selectedSource) {
case SelectedSource::YoutubePlaylist:
addFinder(new YoutubePlaylist(
m_ui->byIdCheckBox->isChecked() ?
QUrl(QStringLiteral("http://www.youtube.com/playlist?list=%1").arg(m_ui->termLineEdit->text())) :
m_ui->termLineEdit->text(),
parent()));
break;
case SelectedSource::GroovesharkAlbum:
addFinder(new GroovesharkSearcher(
m_ui->termLineEdit->text(),
m_ui->byIdCheckBox->isChecked() ? GroovesharkSearchTermRole::AlbumId : GroovesharkSearchTermRole::AlbumName,
m_ui->verifiedCheckBox->isChecked(),
parent()));
break;
case SelectedSource::GroovesharkPlaylist:
addFinder(new GroovesharkSearcher(
m_ui->termLineEdit->text(),
m_ui->byIdCheckBox->isChecked() ? GroovesharkSearchTermRole::PlaylistId : GroovesharkSearchTermRole::PlaylistName,
m_ui->verifiedCheckBox->isChecked(),
parent()));
break;
}
}
void AddMultipleDownloadsDialog::addResults(const QList<Download *> &results)
{
if(m_ui->tabWidget->currentIndex() != 2)
return;
foreach(Download *download, results) {
QList<QStandardItem *> items;
QStandardItem *item;
item = new QStandardItem(download->title());
item->setEditable(false);
item->setData(QVariant::fromValue(download), Qt::UserRole + 1);
items << item;
item = new QStandardItem(download->uploader().isEmpty() ? retrievingField() : download->uploader());
item->setEditable(false);
items << item;
item = new QStandardItem(download->positionInCollection() == 0 ? retrievingField() : QString("%1").arg(download->positionInCollection()));
item->setEditable(false);
items << item;
item = new QStandardItem(download->collectionName().isEmpty() ? retrievingField() : download->collectionName());
item->setEditable(false);
items << item;
item = new QStandardItem(download->duration().isNull() ? retrievingField() : QString::fromStdString(download->duration().toString()));
item->setEditable(false);
items << item;
item = new QStandardItem(download->id().isEmpty() ? retrievingField() : download->id());
item->setEditable(false);
items << item;
m_model->appendRow(items);
connect(download, &Download::statusChanged, this, &AddMultipleDownloadsDialog::downloadChangedStatus);
if(download->isInitiated() || (!download->isInitiatingInstantlyRecommendable()))
addDownloadInformation(download);
else {
if(m_currentInfoRequests < m_maxInfoRequests) {
++m_currentInfoRequests;
download->setProxy(m_proxy);
download->init();
} else {
m_pendingDownloads.append(download);
}
}
}
m_ui->selectAllPushButton->setText(tr("Select all"));
if(m_finder) {
if(!m_finder->collectionTitle().isEmpty()) {
m_ui->titleLabel->setText(m_listName + m_finder->collectionTitle());
}
if(!m_finder->hasFinished() && !m_finder->isDownloading()) {
QScrollBar *sb = m_ui->downloadsTreeView->verticalScrollBar();
if(!sb || ((sb->maximum() + sb->minimum()) == 0)) {
m_ui->progressBar->setHidden(false);
m_finder->start();
} else {
m_ui->progressBar->setHidden(true);
}
}
}
}
void AddMultipleDownloadsDialog::scrollBarValueChanged()
{
if(m_finder && !m_finder->hasFinished() && !m_finder->isDownloading()) {
QScrollBar *sb = m_ui->downloadsTreeView->verticalScrollBar();
if(!sb || (sb->value() == sb->maximum()) || ((sb->maximum() + sb->minimum()) == 0)) {
m_ui->progressBar->setHidden(false);
m_finder->start();
} else {
m_ui->progressBar->setHidden(true);
}
} else {
m_ui->progressBar->setHidden(true);
}
}
void AddMultipleDownloadsDialog::retrievingFinished(bool sucess, const QString &reasonForFail)
{
if(m_finder) {
m_ui->progressBar->setHidden(true);
m_ui->selectAllPushButton->setHidden(false);
m_ui->addPushButton->setHidden(false);
m_ui->titleLabel->setText(sucess
? (m_listName + m_finder->collectionTitle())
: tr("Failed to retrieve downloads: %1").arg(reasonForFail));
m_finder.release()->deleteLater();
}
}
void AddMultipleDownloadsDialog::updateControls(const QItemSelection &, const QItemSelection &)
{
int count = m_ui->downloadsTreeView->selectionModel()->selectedRows().count();
if(count > 0) {
m_ui->addPushButton->setText(tr("Add selected downloads (%1)").arg(count));
m_ui->addPushButton->setEnabled(true);
} else {
m_ui->addPushButton->setText(tr("Add selected downloads"));
m_ui->addPushButton->setEnabled(false);
}
if(count >= m_model->rowCount())
m_ui->selectAllPushButton->setText(tr("Repeal selection"));
else
m_ui->selectAllPushButton->setText(tr("Select all"));
}
void AddMultipleDownloadsDialog::selectAll()
{
QItemSelectionModel *selectionModel = m_ui->downloadsTreeView->selectionModel();
if(selectionModel->selectedRows().length() >= m_model->rowCount())
selectionModel->clearSelection();
else
m_ui->downloadsTreeView->selectAll();
}
void AddMultipleDownloadsDialog::back()
{
m_finder.reset();
switch(m_ui->tabWidget->currentIndex()) {
case 0:
close();
break;
case 1:
reset();
break;
case 2:
abortSearch();
break;
}
}
void AddMultipleDownloadsDialog::reset()
{
m_finder.reset();
m_ui->progressBar->setHidden(true);
m_ui->selectAllPushButton->setHidden(true);
m_ui->addPushButton->setHidden(true);
m_ui->searchPushButton->setHidden(true);
m_ui->tabWidget->setCurrentIndex(0);
m_model->removeRows(0, m_model->rowCount());
m_pendingDownloads.clear();
m_currentInfoRequests = 0;
}
void AddMultipleDownloadsDialog::abortSearch()
{
m_finder.reset();
m_ui->tabWidget->setCurrentIndex(1);
m_ui->progressBar->setHidden(true);
m_ui->selectAllPushButton->setHidden(true);
m_ui->addPushButton->setHidden(true);
m_ui->searchPushButton->setHidden(false);
m_model->removeRows(0, m_model->rowCount());
m_pendingDownloads.clear();
m_currentInfoRequests = 0;
m_ui->titleLabel->setText(tr("Aborted"));
}