/* 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 "downloadlistwidget.h" #include "ui_downloadlistwidget.h" #include #include #include #include #include DownloadListWidget::DownloadListWidget(QWidget *parent) : QWidget(parent), ui(new Ui::DownloadListWidget) { ui->setupUi(this); } DownloadListWidget::~DownloadListWidget() { delete ui; } DownloadListWidgetDelegate::DownloadListWidgetDelegate(DownloadManager *manager, bool metaDisplay, QTreeView *view, QObject *parent) : QItemDelegate(parent) , m_Manager(manager) , m_MetaDisplay(metaDisplay) , m_ItemWidget(new DownloadListWidget) , m_ContextRow(0) , m_View(view) { m_NameLabel = m_ItemWidget->findChild("nameLabel"); m_SizeLabel = m_ItemWidget->findChild("sizeLabel"); m_Progress = m_ItemWidget->findChild("downloadProgress"); m_InstallLabel = m_ItemWidget->findChild("installLabel"); m_InstallLabel->setVisible(false); connect(manager, SIGNAL(stateChanged(int,DownloadManager::DownloadState)), this, SLOT(stateChanged(int,DownloadManager::DownloadState))); connect(manager, SIGNAL(downloadRemoved(int)), this, SLOT(resetCache(int))); } DownloadListWidgetDelegate::~DownloadListWidgetDelegate() { delete m_ItemWidget; } void DownloadListWidgetDelegate::stateChanged(int row,DownloadManager::DownloadState) { m_Cache.remove(row); } void DownloadListWidgetDelegate::resetCache(int) { m_Cache.clear(); } void DownloadListWidgetDelegate::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 DownloadListWidgetDelegate::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)); m_SizeLabel->setText("???"); m_InstallLabel->setVisible(true); m_InstallLabel->setText(tr("Pending")); m_Progress->setVisible(false); } void DownloadListWidgetDelegate::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); m_SizeLabel->setText(QString::number(m_Manager->getFileSize(downloadIndex) / 1024)); DownloadManager::DownloadState state = m_Manager->getState(downloadIndex); if ((state == DownloadManager::STATE_PAUSED) || (state == DownloadManager::STATE_ERROR)) { QPalette labelPalette; m_InstallLabel->setVisible(true); m_Progress->setVisible(false); #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) m_InstallLabel->setText(QApplication::translate("DownloadListWidget", "Paused - Double Click to resume", 0)); #else m_InstallLabel->setText(QApplication::translate("DownloadListWidget", "Paused - Double Click to resume", 0, QApplication::UnicodeUTF8)); #endif labelPalette.setColor(QPalette::WindowText, Qt::darkRed); m_InstallLabel->setPalette(labelPalette); } else if (state == DownloadManager::STATE_FETCHINGMODINFO) { m_InstallLabel->setText(tr("Fetching Info 1")); m_Progress->setVisible(false); } else if (state == DownloadManager::STATE_FETCHINGFILEINFO) { m_InstallLabel->setText(tr("Fetching Info 2")); m_Progress->setVisible(false); } else if (state >= DownloadManager::STATE_READY) { QPalette labelPalette; m_InstallLabel->setVisible(true); m_Progress->setVisible(false); if (state == DownloadManager::STATE_INSTALLED) { // the tr-macro doesn't work here, maybe because the translation is actually associated with DownloadListWidget instead // of DownloadListWidgetDelegate? #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) m_InstallLabel->setText(QApplication::translate("DownloadListWidget", "Installed - Double Click to re-install", 0)); #else m_InstallLabel->setText(QApplication::translate("DownloadListWidget", "Installed - Double Click to re-install", 0, QApplication::UnicodeUTF8)); #endif labelPalette.setColor(QPalette::WindowText, Qt::darkGray); } else if (state == DownloadManager::STATE_UNINSTALLED) { #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) m_InstallLabel->setText(QApplication::translate("DownloadListWidget", "Uninstalled - Double Click to re-install", 0)); #else m_InstallLabel->setText(QApplication::translate("DownloadListWidget", "Uninstalled - Double Click to re-install", 0, QApplication::UnicodeUTF8)); #endif labelPalette.setColor(QPalette::WindowText, Qt::lightGray); } else { #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) m_InstallLabel->setText(QApplication::translate("DownloadListWidget", "Done - Double Click to install", 0)); #else m_InstallLabel->setText(QApplication::translate("DownloadListWidget", "Done - Double Click to install", 0, QApplication::UnicodeUTF8)); #endif labelPalette.setColor(QPalette::WindowText, Qt::darkGreen); } m_InstallLabel->setPalette(labelPalette); if (m_Manager->isInfoIncomplete(downloadIndex)) { m_NameLabel->setText(" " + m_NameLabel->text()); } } else { m_InstallLabel->setVisible(false); m_Progress->setVisible(true); m_Progress->setValue(m_Manager->getProgress(downloadIndex)); } } void DownloadListWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { 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())); 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 (state >= DownloadManager::STATE_READY) { if (false) { #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: %s", e.what()); } } QSize DownloadListWidgetDelegate::sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const { const int width = m_ItemWidget->minimumWidth(); const int height = m_ItemWidget->height(); return QSize(width, height); } void DownloadListWidgetDelegate::issueInstall() { emit installDownload(m_ContextRow); } void DownloadListWidgetDelegate::issueQueryInfo() { emit queryInfo(m_ContextRow); } void DownloadListWidgetDelegate::issueDelete() { emit removeDownload(m_ContextRow, true); } void DownloadListWidgetDelegate::issueRemoveFromView() { emit removeDownload(m_ContextRow, false); } void DownloadListWidgetDelegate::issueRestoreToView() { emit restoreDownload(m_ContextRow); } void DownloadListWidgetDelegate::issueCancel() { emit cancelDownload(m_ContextRow); } void DownloadListWidgetDelegate::issuePause() { emit pauseDownload(m_ContextRow); } void DownloadListWidgetDelegate::issueResume() { emit resumeDownload(m_ContextRow); } void DownloadListWidgetDelegate::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 DownloadListWidgetDelegate::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 DownloadListWidgetDelegate::issueRemoveFromViewAll() { if (QMessageBox::question(nullptr, tr("Are you sure?"), tr("This will remove all finished downloads from this list (but NOT from disk)."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { emit removeDownload(-1, false); } } void DownloadListWidgetDelegate::issueRemoveFromViewCompleted() { if (QMessageBox::question(nullptr, tr("Are you sure?"), tr("This will remove all installed downloads from this list (but NOT from disk)."), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { emit removeDownload(-2, false); } } bool DownloadListWidgetDelegate::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(m_View); bool hidden = false; m_ContextRow = qobject_cast(model)->mapToSource(index).row(); if (m_ContextRow < m_Manager->numTotalDownloads()) { DownloadManager::DownloadState state = m_Manager->getState(m_ContextRow); hidden = m_Manager->isHidden(m_ContextRow); if (state >= DownloadManager::STATE_READY) { menu.addAction(tr("Install"), this, SLOT(issueInstall())); if (m_Manager->isInfoIncomplete(m_ContextRow)) { 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 true; } } } catch (const std::exception &e) { qCritical("failed to handle editor event: %s", e.what()); } return QItemDelegate::editorEvent(event, model, option, index); }