/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Mod Organizer is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see .
*/
#include "downloadlistwidgetcompact.h"
#include "ui_downloadlistwidgetcompact.h"
#include
#include
#include
#include
#include
DownloadListWidgetCompact::DownloadListWidgetCompact(QWidget* parent)
: QWidget(parent), ui(new Ui::DownloadListWidgetCompact) {
ui->setupUi(this);
}
DownloadListWidgetCompact::~DownloadListWidgetCompact() { delete ui; }
DownloadListWidgetCompactDelegate::DownloadListWidgetCompactDelegate(DownloadManager* manager, bool metaDisplay,
QTreeView* view, QObject* parent)
: QItemDelegate(parent), m_Manager(manager), m_MetaDisplay(metaDisplay),
m_ItemWidget(new DownloadListWidgetCompact), m_View(view) {
m_NameLabel = m_ItemWidget->findChild("nameLabel");
m_SizeLabel = m_ItemWidget->findChild("sizeLabel");
m_Progress = m_ItemWidget->findChild("downloadProgress");
m_DoneLabel = m_ItemWidget->findChild("doneLabel");
m_DoneLabel->setVisible(false);
connect(manager, SIGNAL(stateChanged(int, DownloadManager::DownloadState)), this,
SLOT(stateChanged(int, DownloadManager::DownloadState)));
connect(manager, SIGNAL(downloadRemoved(int)), this, SLOT(resetCache(int)));
}
DownloadListWidgetCompactDelegate::~DownloadListWidgetCompactDelegate() { delete m_ItemWidget; }
void DownloadListWidgetCompactDelegate::stateChanged(int row, DownloadManager::DownloadState) { m_Cache.remove(row); }
void DownloadListWidgetCompactDelegate::resetCache(int) { m_Cache.clear(); }
void DownloadListWidgetCompactDelegate::drawCache(QPainter* painter, const QStyleOptionViewItem& option,
const QPixmap& cache) const {
QRect rect = option.rect;
rect.setLeft(0);
rect.setWidth(m_View->columnWidth(0) + m_View->columnWidth(1) + m_View->columnWidth(2));
painter->drawPixmap(rect, cache);
}
void DownloadListWidgetCompactDelegate::paintPendingDownload(int downloadIndex) const {
std::pair nexusids = m_Manager->getPendingDownload(downloadIndex);
m_NameLabel->setText(tr("< mod %1 file %2 >").arg(nexusids.first).arg(nexusids.second));
if (m_SizeLabel != nullptr) {
m_SizeLabel->setText("???");
}
m_DoneLabel->setVisible(true);
m_DoneLabel->setText(tr("Pending"));
m_Progress->setVisible(false);
}
void DownloadListWidgetCompactDelegate::paintRegularDownload(int downloadIndex) const {
QString name = m_MetaDisplay ? m_Manager->getDisplayName(downloadIndex) : m_Manager->getFileName(downloadIndex);
if (name.length() > 53) {
name.truncate(50);
name.append("...");
}
m_NameLabel->setText(name);
DownloadManager::DownloadState state = m_Manager->getState(downloadIndex);
if ((m_SizeLabel != nullptr) && (state >= DownloadManager::STATE_READY)) {
m_SizeLabel->setText(QString::number(m_Manager->getFileSize(downloadIndex) / 1048576));
}
if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR)) {
m_DoneLabel->setVisible(true);
m_Progress->setVisible(false);
m_DoneLabel->setText(QString("%1
").arg(tr("Paused")));
} else if (state == DownloadManager::STATE_FETCHINGMODINFO) {
m_DoneLabel->setText(QString("%1").arg(tr("Fetching Info 1")));
} else if (state == DownloadManager::STATE_FETCHINGFILEINFO) {
m_DoneLabel->setText(QString("%1").arg(tr("Fetching Info 2")));
} else if (state >= DownloadManager::STATE_READY) {
m_DoneLabel->setVisible(true);
m_Progress->setVisible(false);
if (state == DownloadManager::STATE_INSTALLED) {
m_DoneLabel->setText(QString("%1
").arg(tr("Installed")));
} else if (state == DownloadManager::STATE_UNINSTALLED) {
m_DoneLabel->setText(QString("%1
").arg(tr("Uninstalled")));
} else {
m_DoneLabel->setText(QString("%1
").arg(tr("Done")));
}
if (m_Manager->isInfoIncomplete(downloadIndex)) {
m_NameLabel->setText("
" + m_NameLabel->text());
}
} else {
m_DoneLabel->setVisible(false);
m_Progress->setVisible(true);
m_Progress->setValue(m_Manager->getProgress(downloadIndex));
}
}
void DownloadListWidgetCompactDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const {
#pragma message("This is quite costy - room for optimization?")
try {
auto iter = m_Cache.find(index.row());
if (iter != m_Cache.end()) {
drawCache(painter, option, *iter);
return;
}
m_ItemWidget->resize(
QSize(m_View->columnWidth(0) + m_View->columnWidth(1) + m_View->columnWidth(2), option.rect.height()));
if (index.row() % 2 == 1) {
m_ItemWidget->setBackgroundRole(QPalette::AlternateBase);
} else {
m_ItemWidget->setBackgroundRole(QPalette::Base);
}
int downloadIndex = index.data().toInt();
if (downloadIndex >= m_Manager->numTotalDownloads()) {
paintPendingDownload(downloadIndex - m_Manager->numTotalDownloads());
} else {
paintRegularDownload(downloadIndex);
}
#pragma message("caching disabled because changes in the list (including resorting) doesn't work correctly")
if (false) {
// if (state >= DownloadManager::STATE_READY) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
QPixmap cache = m_ItemWidget->grab();
#else
QPixmap cache = QPixmap::grabWidget(m_ItemWidget);
#endif
m_Cache[index.row()] = cache;
drawCache(painter, option, cache);
} else {
painter->save();
painter->translate(QPoint(0, option.rect.topLeft().y()));
m_ItemWidget->render(painter);
painter->restore();
}
} catch (const std::exception& e) {
qCritical("failed to paint download list item %d: %s", index.row(), e.what());
}
}
QSize DownloadListWidgetCompactDelegate::sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const {
const int width = m_ItemWidget->minimumWidth();
const int height = m_ItemWidget->height();
return QSize(width, height);
}
void DownloadListWidgetCompactDelegate::issueInstall() { emit installDownload(m_ContextIndex.row()); }
void DownloadListWidgetCompactDelegate::issueQueryInfo() { emit queryInfo(m_ContextIndex.row()); }
void DownloadListWidgetCompactDelegate::issueDelete() { emit removeDownload(m_ContextIndex.row(), true); }
void DownloadListWidgetCompactDelegate::issueRemoveFromView() { emit removeDownload(m_ContextIndex.row(), false); }
void DownloadListWidgetCompactDelegate::issueRestoreToView() { emit restoreDownload(m_ContextIndex.row()); }
void DownloadListWidgetCompactDelegate::issueCancel() { emit cancelDownload(m_ContextIndex.row()); }
void DownloadListWidgetCompactDelegate::issuePause() { emit pauseDownload(m_ContextIndex.row()); }
void DownloadListWidgetCompactDelegate::issueResume() { emit resumeDownload(m_ContextIndex.row()); }
void DownloadListWidgetCompactDelegate::issueDeleteAll() {
if (QMessageBox::question(nullptr, tr("Are you sure?"),
tr("This will remove all finished downloads from this list and from disk."),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
emit removeDownload(-1, true);
}
}
void DownloadListWidgetCompactDelegate::issueDeleteCompleted() {
if (QMessageBox::question(nullptr, tr("Are you sure?"),
tr("This will remove all installed downloads from this list and from disk."),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
emit removeDownload(-2, true);
}
}
void DownloadListWidgetCompactDelegate::issueRemoveFromViewAll() {
if (QMessageBox::question(
nullptr, tr("Are you sure?"),
tr("This will permanently remove all finished downloads from this list (but NOT from disk)."),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
emit removeDownload(-1, false);
}
}
void DownloadListWidgetCompactDelegate::issueRemoveFromViewCompleted() {
if (QMessageBox::question(
nullptr, tr("Are you sure?"),
tr("This will permanently remove all installed downloads from this list (but NOT from disk)."),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
emit removeDownload(-2, false);
}
}
bool DownloadListWidgetCompactDelegate::editorEvent(QEvent* event, QAbstractItemModel* model,
const QStyleOptionViewItem& option, const QModelIndex& index) {
try {
if (event->type() == QEvent::MouseButtonDblClick) {
QModelIndex sourceIndex = qobject_cast(model)->mapToSource(index);
if (m_Manager->getState(sourceIndex.row()) >= DownloadManager::STATE_READY) {
emit installDownload(sourceIndex.row());
} else if (m_Manager->getState(sourceIndex.row()) >= DownloadManager::STATE_PAUSED) {
emit resumeDownload(sourceIndex.row());
}
return true;
} else if (event->type() == QEvent::MouseButtonRelease) {
QMouseEvent* mouseEvent = static_cast(event);
if (mouseEvent->button() == Qt::RightButton) {
QMenu menu;
bool hidden = false;
m_ContextIndex = qobject_cast(model)->mapToSource(index);
if (m_ContextIndex.row() < m_Manager->numTotalDownloads()) {
DownloadManager::DownloadState state = m_Manager->getState(m_ContextIndex.row());
hidden = m_Manager->isHidden(m_ContextIndex.row());
if (state >= DownloadManager::STATE_READY) {
menu.addAction(tr("Install"), this, SLOT(issueInstall()));
if (m_Manager->isInfoIncomplete(m_ContextIndex.row())) {
menu.addAction(tr("Query Info"), this, SLOT(issueQueryInfo()));
}
menu.addAction(tr("Delete"), this, SLOT(issueDelete()));
if (hidden) {
menu.addAction(tr("Un-Hide"), this, SLOT(issueRestoreToView()));
} else {
menu.addAction(tr("Hide"), this, SLOT(issueRemoveFromView()));
}
} else if (state == DownloadManager::STATE_DOWNLOADING) {
menu.addAction(tr("Cancel"), this, SLOT(issueCancel()));
menu.addAction(tr("Pause"), this, SLOT(issuePause()));
} else if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR)) {
menu.addAction(tr("Remove"), this, SLOT(issueDelete()));
menu.addAction(tr("Resume"), this, SLOT(issueResume()));
}
menu.addSeparator();
}
menu.addAction(tr("Delete Installed..."), this, SLOT(issueDeleteCompleted()));
menu.addAction(tr("Delete All..."), this, SLOT(issueDeleteAll()));
if (!hidden) {
menu.addSeparator();
menu.addAction(tr("Hide Installed..."), this, SLOT(issueRemoveFromViewCompleted()));
menu.addAction(tr("Hide All..."), this, SLOT(issueRemoveFromViewAll()));
}
menu.exec(mouseEvent->globalPos());
event->accept();
return false;
}
}
} catch (const std::exception& e) {
qCritical("failed to handle editor event: %s", e.what());
}
return QItemDelegate::editorEvent(event, model, option, index);
}