/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * renderdialog.cc * * Thu Sep 20 17:32:11 CEST 2018 * Copyright 2018 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of DrumGizmo. * * DrumGizmo 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 2 of the License, or * (at your option) any later version. * * DrumGizmo 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 DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "renderdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include "project.h" class ProgressDelegate : public QStyledItemDelegate { // Q_OBJECT public: ProgressDelegate(Project& project, QObject *parent) : QStyledItemDelegate(parent) , project(project) { } void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const override { if(/*index.row() == current_row &&*/ index.column() == 2 && index.parent() == QModelIndex()) { QStyleOptionProgressBar progressBarOption; progressBarOption.state = QStyle::State_Enabled; progressBarOption.direction = QApplication::layoutDirection(); progressBarOption.rect = option.rect; progressBarOption.fontMetrics = QApplication::fontMetrics(); progressBarOption.minimum = 0; progressBarOption.textAlignment = Qt::AlignCenter; progressBarOption.textVisible = true; if(index.row() == current_row) { // Current task progressBarOption.maximum = progress_max; progressBarOption.progress = progress; } else if(index.row() < current_row) { // Finished task progressBarOption.maximum = 100; progressBarOption.progress = 100; } else { // Waiting task progressBarOption.maximum = 100; progressBarOption.progress = 0; } QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); } else { QStyledItemDelegate::paint(painter, option, index); } } void setActiveTask(int current_instrument_id) { auto instrument_ids = project.getInstrumentList(); current_row = 0; for(auto instrument_id : instrument_ids) { if(current_instrument_id == instrument_id) { return; } current_row++; } // current_row will be one above the row count here } void setProgressMaximum(int progress_max) { this->progress_max = progress_max; } void setProgress(int progress) { this->progress = progress; } private: Project& project; int progress{0}; int progress_max{100}; int current_row{-1}; }; class RenderDataModel : public QAbstractItemModel { public: RenderDataModel(Project& project) : project(project) { } QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override { if(!hasIndex(row, column, parent)) { return QModelIndex(); } if(!parent.isValid()) { auto instrument_ids = project.getInstrumentList(); if(row < instrument_ids.size()) { return createIndex(row, column, (void*)42); } else { return QModelIndex(); // row is out of bounds. } } return QModelIndex(); } QModelIndex parent(const QModelIndex &index) const override { return QModelIndex(); // no parent } int rowCount(const QModelIndex &parent = QModelIndex()) const override { if(parent.column() > 0) // only return row count on first column { return 0; } if(!parent.isValid()) { auto instrument_ids = project.getInstrumentList(); return instrument_ids.size(); } return 0; // no children } int columnCount(const QModelIndex &parent = QModelIndex()) const override { return 3; // icon, text, progressbar } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { if(!index.isValid()) { return QVariant(); } if(role == Qt::DecorationRole) { if(index.column() == 0) { if(index.row() < current_row) { return QPixmap(":/icons/task_done.png"); } else if(index.row() == current_row) { if(error) { return QPixmap(":/icons/task_error.png"); } else { return QPixmap(":/icons/task_running.png"); } } else { return QPixmap(":/icons/task_waiting.png"); } } } if(role == Qt::DisplayRole) { auto instrument_ids = project.getInstrumentList(); auto instrument_id = instrument_ids.begin() + index.row(); const auto& instrument = project.getInstrument(*instrument_id); switch(index.column()) { case 1: return instrument.getInstrumentName(); default: return QVariant(); } } return QVariant(); } void setError() { error = true; } QVariant headerData(int section, Qt::Orientation orientation, int role) const override { return QVariant(); } void refresh() { beginResetModel(); endResetModel(); } void setActiveTask(int current_instrument_id) { auto instrument_ids = project.getInstrumentList(); current_row = 0; for(auto instrument_id : instrument_ids) { if(current_instrument_id == instrument_id) { return; } current_row++; } // current_row will be one above the row count here } private: Project& project; int current_row{-1}; bool error{false}; }; RenderDialog::RenderDialog(QWidget* parent, Project& project) : QDialog(parent) , project(project) , renderer(project) { setWindowTitle(tr("Export drumkit")); model = new RenderDataModel(project); auto vl = new QVBoxLayout(); setLayout(vl); layout()->addWidget(new QLabel(tr("Export path:"))); { auto hl = new QHBoxLayout(); export_path = new QLineEdit(this); export_path->setText(project.getExportPath()); connect(export_path, SIGNAL(textEdited(const QString&)), this, SLOT(exportPathChanged(const QString&))); auto btn = new QPushButton(tr("...")); btn->setMaximumWidth(32); connect(btn, SIGNAL(clicked()), this, SLOT(chooseExportPath())); hl->addWidget(export_path); hl->addWidget(btn); vl->addLayout(hl); } export_btn = new QPushButton(this); export_btn->setText(tr("Export")); connect(export_btn, SIGNAL(clicked()), this, SLOT(render())); layout()->addWidget(export_btn); bar = new QProgressBar(this); connect(&renderer, SIGNAL(progressStart(int)), bar, SLOT(setMaximum(int))); layout()->addWidget(bar); connect(&renderer, SIGNAL(progressRenderStart(int)), this, SLOT(progressRenderStart(int))); connect(&renderer, SIGNAL(progressRenderTask(int)), this, SLOT(progressRenderTask(int))); tasks = new QTreeView(this); tasks->setModel(model); tasks->setHeaderHidden(true); tasks->setRootIsDecorated(false); tasks->header()->resizeSection(0, 24); delegate = new ProgressDelegate(project, this); tasks->setItemDelegate(delegate); connect(&renderer, SIGNAL(progressStart(int)), this, SLOT(progressStart(int))); connect(&renderer, SIGNAL(progressFinished(int)), this, SLOT(progressFinished(int))); layout()->addWidget(tasks); connect(&renderer, SIGNAL(progressTask(QString)), this, SLOT(progressTask(QString))); connect(&renderer, SIGNAL(progressRenderFinished(int)), this, SLOT(progressRenderFinished(int))); } void RenderDialog::render() { bar->setValue(1); renderer.render(); } void RenderDialog::progressStart(int total) { export_btn->setEnabled(false); } void RenderDialog::progressTask(QString text) { //tasks->addItem(text); } void RenderDialog::progressRenderStart(int tasktotal) { auto task = bar->value(); auto instrument_ids = project.getInstrumentList(); auto instrument_id = instrument_ids.begin() + (task - 1); delegate->setActiveTask(*instrument_id); model->setActiveTask(*instrument_id); delegate->setProgressMaximum(tasktotal); model->refresh(); } void RenderDialog::progressRenderTask(int subtask) { delegate->setProgress(subtask); model->refresh(); } void RenderDialog::progressRenderFinished(int success) { auto task = bar->value(); // Search past the last instriment id to mark all tasks as finished auto instrument_ids = project.getInstrumentList(); auto instrument_id = instrument_ids.begin() + task; delegate->setActiveTask(*instrument_id); // note this id is invalid model->setActiveTask(*instrument_id); // note this id is invalid bar->setValue(task + 1); if(success != 0) { model->setError(); } model->refresh(); } void RenderDialog::progressFinished(int success) { if(success != 0) { model->setError(); } model->refresh(); export_btn->setEnabled(true); } void RenderDialog::chooseExportPath() { QString path = QFileDialog::getExistingDirectory( this, tr("Choose export directory."), project.getExportPath(), QFileDialog::ShowDirsOnly); if(path != "") { export_path->setText(path); project.setExportPath(path); } } void RenderDialog::exportPathChanged(const QString& path) { project.setExportPath(path); }