From 3689ca2874624a10dc00efbbf143bfeff811c579 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Fri, 16 Dec 2011 22:05:51 +0100 Subject: [PATCH] Make renderjobs code a bit easier to read, fix detection of broken render scripts --- src/renderwidget.cpp | 245 ++++++++++++++++++++++++++----------------- src/renderwidget.h | 18 +++- 2 files changed, 165 insertions(+), 98 deletions(-) diff --git a/src/renderwidget.cpp b/src/renderwidget.cpp index 5c2d624a..9a9f1aa2 100644 --- a/src/renderwidget.cpp +++ b/src/renderwidget.cpp @@ -47,6 +47,8 @@ #include #include + +// Render profiles roles const int GroupRole = Qt::UserRole; const int ExtensionRole = GroupRole + 1; const int StandardRole = GroupRole + 2; @@ -60,10 +62,71 @@ const int DefaultBitrateRole = GroupRole + 9; const int AudioBitratesRole = GroupRole + 10; const int DefaultAudioBitrateRole = GroupRole + 11; +// Render job roles +const int ParametersRole = Qt::UserRole + 1; +const int TimeRole = Qt::UserRole + 2; + +const int ScriptType = QTreeWidgetItem::UserType; + + // Running job status const int WAITINGJOB = 0; const int RUNNINGJOB = 1; const int FINISHEDJOB = 2; +const int FAILEDJOB = 3; +const int ABORTEDJOB = 4; + + +RenderJobItem::RenderJobItem(QTreeWidget * parent, const QStringList & strings, int type) : QTreeWidgetItem(parent, strings, type), + m_status(-1) +{ + setSizeHint(1, QSize(parent->columnWidth(1), parent->fontMetrics().height() * 2)); + setStatus(WAITINGJOB); +} + +void RenderJobItem::setStatus(int status) +{ + if (m_status == status) return; + m_status = status; + switch (status) { + case WAITINGJOB: + setIcon(0, KIcon("media-playback-pause")); + setData(1, Qt::UserRole, i18n("Waiting...")); + break; + case FINISHEDJOB: + setData(1, Qt::UserRole, i18n("Rendering finished")); + setIcon(0, KIcon("dialog-ok")); + setData(2, Qt::UserRole, 100); + break; + case FAILEDJOB: + setData(1, Qt::UserRole, i18n("Rendering crashed")); + setIcon(0, KIcon("dialog-close")); + setData(2, Qt::UserRole, 100); + break; + case ABORTEDJOB: + setData(1, Qt::UserRole, i18n("Rendering aborted")); + setIcon(0, KIcon("dialog-cancel")); + setData(2, Qt::UserRole, 100); + + default: + break; + } +} + +int RenderJobItem::status() const +{ + return m_status; +} + +void RenderJobItem::setMetadata(const QString &data) +{ + m_data = data; +} + +const QString RenderJobItem::metadata() const +{ + return m_data; +} RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, MltVideoProfile profile, QWidget * parent) : @@ -965,34 +1028,32 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const emit selectedRenderProfile(renderProps); // insert item in running jobs list - QTreeWidgetItem *renderItem; + RenderJobItem *renderItem; QList existing = m_view.running_jobs->findItems(dest, Qt::MatchExactly, 1); if (!existing.isEmpty()) { - renderItem = existing.at(0); - if (renderItem->data(1, Qt::UserRole + 2).toInt() == RUNNINGJOB) { + renderItem = static_cast (existing.at(0)); + if (renderItem->status() == RUNNINGJOB) { KMessageBox::information(this, i18n("There is already a job writing file:
%1
Abort the job if you want to overwrite it...", dest), i18n("Already running")); return; } - renderItem->setData(1, Qt::UserRole + 4, QString()); + renderItem->setData(2, Qt::UserRole, 0); + renderItem->setStatus(WAITINGJOB); } else { - renderItem = new QTreeWidgetItem(m_view.running_jobs, QStringList() << QString() << dest << QString()); - } - renderItem->setData(1, Qt::UserRole + 2, WAITINGJOB); - renderItem->setIcon(0, KIcon("media-playback-pause")); - renderItem->setData(1, Qt::UserRole, i18n("Waiting...")); - renderItem->setSizeHint(1, QSize(m_view.running_jobs->columnWidth(1), fontMetrics().height() * 2)); - renderItem->setData(1, Qt::UserRole + 1, QTime::currentTime()); + renderItem = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << dest << QString()); + } + renderItem->setData(1, TimeRole, QTime::currentTime()); // Set rendering type if (group == "dvd") { if (m_view.open_dvd->isChecked()) { renderItem->setData(0, Qt::UserRole, group); if (renderArgs.contains("mlt_profile=")) { + //TODO: probably not valid anymore (no more MLT profiles in args) // rendering profile contains an MLT profile, so pass it to the running jog item, useful for dvd QString prof = renderArgs.section("mlt_profile=", 1, 1); prof = prof.section(' ', 0, 0); kDebug() << "// render profile: " << prof; - renderItem->setData(0, Qt::UserRole + 1, prof); + renderItem->setMetadata(prof); } } } else { @@ -1000,10 +1061,10 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const renderItem->setData(0, Qt::UserRole, group); // pass the url QString url = m_view.size_list->currentItem()->data(ExtraRole).toString(); - renderItem->setData(0, Qt::UserRole + 1, url); + renderItem->setMetadata(url); } } - renderItem->setData(1, Qt::UserRole + 3, render_process_args); + renderItem->setData(1, ParametersRole, render_process_args); if (exportAudio == false) renderItem->setData(1, Qt::UserRole + 5, i18n("Video without audio track")); else renderItem->setData(1, Qt::UserRole + 5, QString()); m_view.running_jobs->setCurrentItem(renderItem); @@ -1015,55 +1076,50 @@ void RenderWidget::checkRenderStatus() { // check if we have a job waiting to render if (m_blockProcessing) return; - QTreeWidgetItem *item = m_view.running_jobs->topLevelItem(0); + RenderJobItem* item = static_cast (m_view.running_jobs->topLevelItem(0)); while (item) { - if (item->data(1, Qt::UserRole + 2).toInt() == RUNNINGJOB) return; - item = m_view.running_jobs->itemBelow(item); + if (item->status() == RUNNINGJOB) return; + item = static_cast (m_view.running_jobs->itemBelow(item)); } - item = m_view.running_jobs->topLevelItem(0); + item = static_cast (m_view.running_jobs->topLevelItem(0)); bool waitingJob = false; while (item) { - if (item->data(1, Qt::UserRole + 2).toInt() == WAITINGJOB) { - item->setData(1, Qt::UserRole + 1, QTime::currentTime()); + if (item->status() == WAITINGJOB) { + item->setData(1, TimeRole, QTime::currentTime()); waitingJob = true; startRendering(item); break; } - item = m_view.running_jobs->itemBelow(item); + item = static_cast (m_view.running_jobs->itemBelow(item)); } if (waitingJob == false && m_view.shutdown->isChecked()) emit shutdown(); } -void RenderWidget::startRendering(QTreeWidgetItem *item) +void RenderWidget::startRendering(RenderJobItem *item) { - if (item->data(1, Qt::UserRole + 4).isNull()) { + if (item->type() == QTreeWidgetItem::Type) { // Normal render process - if (QProcess::startDetached(m_renderer, item->data(1, Qt::UserRole + 3).toStringList()) == false) { - item->setData(1, Qt::UserRole + 2, FINISHEDJOB); - item->setData(1, Qt::UserRole, i18n("Rendering crashed")); - item->setIcon(0, KIcon("dialog-close")); - item->setData(2, Qt::UserRole, 100); + if (QProcess::startDetached(m_renderer, item->data(1, ParametersRole).toStringList()) == false) { + item->setStatus(FAILEDJOB); } else { KNotification::event("RenderStarted", i18n("Rendering %1 started", item->text(1)), QPixmap(), this); } - } else { + } else if (item->type() == ScriptType){ // Script item - if (QProcess::startDetached(item->data(1, Qt::UserRole + 3).toString()) == false) { - item->setData(1, Qt::UserRole + 2, FINISHEDJOB); - item->setData(1, Qt::UserRole, i18n("Rendering crashed")); - item->setIcon(0, KIcon("dialog-close")); - item->setData(2, Qt::UserRole, 100); + if (QProcess::startDetached(item->data(1, ParametersRole).toString()) == false) { + item->setStatus(FAILEDJOB); } } } + int RenderWidget::waitingJobsCount() const { int count = 0; - QTreeWidgetItem *item = m_view.running_jobs->topLevelItem(0); + RenderJobItem* item = static_cast (m_view.running_jobs->topLevelItem(0)); while (item) { - if (item->data(1, Qt::UserRole + 2).toInt() == WAITINGJOB) count++; - item = m_view.running_jobs->itemBelow(item); + if (item->status() == WAITINGJOB) count++; + item = static_cast(m_view.running_jobs->itemBelow(item)); } return count; } @@ -1667,29 +1723,27 @@ void RenderWidget::parseFile(QString exportFile, bool editable) } } + + void RenderWidget::setRenderJob(const QString &dest, int progress) { - QTreeWidgetItem *item; + RenderJobItem *item; QList existing = m_view.running_jobs->findItems(dest, Qt::MatchExactly, 1); - if (!existing.isEmpty()) item = existing.at(0); + if (!existing.isEmpty()) item = static_cast (existing.at(0)); else { - item = new QTreeWidgetItem(m_view.running_jobs, QStringList() << QString() << dest << QString()); - item->setSizeHint(1, QSize(m_view.running_jobs->columnWidth(1), fontMetrics().height() * 2)); + item = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << dest << QString()); if (progress == 0) { - item->setData(1, Qt::UserRole + 2, WAITINGJOB); - item->setIcon(0, KIcon("media-playback-pause")); - item->setData(1, Qt::UserRole, i18n("Waiting...")); + item->setStatus(WAITINGJOB); } } item->setData(2, Qt::UserRole, progress); - item->setData(1, Qt::UserRole + 2, RUNNINGJOB); + item->setStatus(RUNNINGJOB); if (progress == 0) { item->setIcon(0, KIcon("system-run")); - item->setSizeHint(1, QSize(m_view.running_jobs->columnWidth(1), fontMetrics().height() * 2)); - item->setData(1, Qt::UserRole + 1, QTime::currentTime()); + item->setData(1, TimeRole, QTime::currentTime()); slotCheckJob(); } else { - QTime startTime = item->data(1, Qt::UserRole + 1).toTime(); + QTime startTime = item->data(1, TimeRole).toTime(); int seconds = startTime.secsTo(QTime::currentTime());; const QString t = i18n("Estimated time %1", QTime().addSecs(seconds * (100 - progress) / progress).toString("hh:mm:ss")); item->setData(1, Qt::UserRole, t); @@ -1698,44 +1752,38 @@ void RenderWidget::setRenderJob(const QString &dest, int progress) void RenderWidget::setRenderStatus(const QString &dest, int status, const QString &error) { - QTreeWidgetItem *item; + RenderJobItem *item; QList existing = m_view.running_jobs->findItems(dest, Qt::MatchExactly, 1); - if (!existing.isEmpty()) item = existing.at(0); + if (!existing.isEmpty()) item = static_cast (existing.at(0)); else { - item = new QTreeWidgetItem(m_view.running_jobs, QStringList() << QString() << dest << QString()); + item = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << dest << QString()); item->setSizeHint(1, QSize(m_view.running_jobs->columnWidth(1), fontMetrics().height() * 2)); } - item->setData(1, Qt::UserRole + 2, FINISHEDJOB); if (status == -1) { // Job finished successfully - item->setIcon(0, KIcon("dialog-ok")); - item->setData(2, Qt::UserRole, 100); - QTime startTime = item->data(1, Qt::UserRole + 1).toTime(); + item->setStatus(FINISHEDJOB); + QTime startTime = item->data(1, TimeRole).toTime(); int seconds = startTime.secsTo(QTime::currentTime()); const QTime tm = QTime().addSecs(seconds); const QString t = i18n("Rendering finished in %1", tm.toString("hh:mm:ss")); item->setData(1, Qt::UserRole, t); QString itemGroup = item->data(0, Qt::UserRole).toString(); if (itemGroup == "dvd") { - emit openDvdWizard(item->text(1), item->data(0, Qt::UserRole + 1).toString()); + emit openDvdWizard(item->text(1), item->metadata()); } else if (itemGroup == "websites") { - QString url = item->data(0, Qt::UserRole + 1).toString(); + QString url = item->metadata(); if (!url.isEmpty()) new KRun(url, this); } } else if (status == -2) { // Rendering crashed - item->setData(1, Qt::UserRole, i18n("Rendering crashed")); - item->setIcon(0, KIcon("dialog-close")); - item->setData(2, Qt::UserRole, 100); + item->setStatus(FAILEDJOB); m_view.error_log->append(i18n("Rendering of %1 crashed
", dest)); m_view.error_log->append(error); m_view.error_log->append("
"); m_view.error_box->setVisible(true); } else if (status == -3) { // User aborted job - item->setData(1, Qt::UserRole, i18n("Rendering aborted")); - item->setIcon(0, KIcon("dialog-cancel")); - item->setData(2, Qt::UserRole, 100); + item->setStatus(ABORTEDJOB); } slotCheckJob(); checkRenderStatus(); @@ -1743,9 +1791,9 @@ void RenderWidget::setRenderStatus(const QString &dest, int status, const QStrin void RenderWidget::slotAbortCurrentJob() { - QTreeWidgetItem *current = m_view.running_jobs->currentItem(); + RenderJobItem *current = static_cast (m_view.running_jobs->currentItem()); if (current) { - if (current->data(1, Qt::UserRole + 2).toInt() == RUNNINGJOB) + if (current->status() == RUNNINGJOB) emit abortProcess(current->text(1)); else { delete current; @@ -1757,8 +1805,8 @@ void RenderWidget::slotAbortCurrentJob() void RenderWidget::slotStartCurrentJob() { - QTreeWidgetItem *current = m_view.running_jobs->currentItem(); - if (current && current->data(1, Qt::UserRole + 2).toInt() == WAITINGJOB) + RenderJobItem *current = static_cast (m_view.running_jobs->currentItem()); + if (current && current->status() == WAITINGJOB) startRendering(current); m_view.start_job->setEnabled(false); } @@ -1766,21 +1814,21 @@ void RenderWidget::slotStartCurrentJob() void RenderWidget::slotCheckJob() { bool activate = false; - QTreeWidgetItem *current = m_view.running_jobs->currentItem(); + RenderJobItem *current = static_cast (m_view.running_jobs->currentItem()); if (current) { - if (current->data(1, Qt::UserRole + 2).toInt() == RUNNINGJOB) { + if (current->status() == RUNNINGJOB) { m_view.abort_job->setText(i18n("Abort Job")); m_view.start_job->setEnabled(false); } else { m_view.abort_job->setText(i18n("Remove Job")); - m_view.start_job->setEnabled(current->data(1, Qt::UserRole + 2).toInt() == WAITINGJOB); + m_view.start_job->setEnabled(current->status() == WAITINGJOB); } activate = true; } m_view.abort_job->setEnabled(activate); for (int i = 0; i < m_view.running_jobs->topLevelItemCount(); i++) { - current = m_view.running_jobs->topLevelItem(i); - if (current == m_view.running_jobs->currentItem()) { + current = static_cast(m_view.running_jobs->topLevelItem(i)); + if (current == static_cast (m_view.running_jobs->currentItem())) { current->setSizeHint(1, QSize(m_view.running_jobs->columnWidth(1), fontMetrics().height() * 3)); } else current->setSizeHint(1, QSize(m_view.running_jobs->columnWidth(1), fontMetrics().height() * 2)); } @@ -1789,12 +1837,12 @@ void RenderWidget::slotCheckJob() void RenderWidget::slotCLeanUpJobs() { int ix = 0; - QTreeWidgetItem *current = m_view.running_jobs->topLevelItem(ix); + RenderJobItem *current = static_cast (m_view.running_jobs->topLevelItem(ix)); while (current) { - if (current->data(1, Qt::UserRole + 2).toInt() == FINISHEDJOB) + if (current->status() == FINISHEDJOB) delete current; else ix++; - current = m_view.running_jobs->topLevelItem(ix); + current = static_cast(m_view.running_jobs->topLevelItem(ix)); } slotCheckJob(); } @@ -1814,24 +1862,27 @@ void RenderWidget::parseScriptFiles() QString renderer; QString melt; QFile file(scriptpath.path()); + kDebug()<<"------------------\n"<setIcon(0, KIcon("dialog-cancel")); @@ -1873,30 +1924,28 @@ void RenderWidget::slotCheckScript() void RenderWidget::slotStartScript() { - QTreeWidgetItem *item = m_view.scripts_list->currentItem(); + RenderJobItem* item = static_cast (m_view.scripts_list->currentItem()); if (item) { QString destination = item->data(1, Qt::UserRole).toString(); QString path = item->data(1, Qt::UserRole + 1).toString(); // Insert new job in queue - QTreeWidgetItem *renderItem; + RenderJobItem *renderItem; QList existing = m_view.running_jobs->findItems(destination, Qt::MatchExactly, 1); kDebug() << "------ START SCRIPT"; if (!existing.isEmpty()) { - renderItem = existing.at(0); - if (renderItem->data(1, Qt::UserRole + 2).toInt() == RUNNINGJOB) { + renderItem = static_cast (existing.at(0)); + if (renderItem->status() == RUNNINGJOB) { KMessageBox::information(this, i18n("There is already a job writing file:
%1
Abort the job if you want to overwrite it...", destination), i18n("Already running")); return; } - } else renderItem = new QTreeWidgetItem(m_view.running_jobs, QStringList() << QString() << destination << QString()); - kDebug() << "------ START SCRIPT 2"; + } else renderItem = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << destination << QString(), ScriptType); renderItem->setData(2, Qt::UserRole, 0); - renderItem->setData(1, Qt::UserRole + 2, WAITINGJOB); + renderItem->setStatus(WAITINGJOB); renderItem->setIcon(0, KIcon("media-playback-pause")); renderItem->setData(1, Qt::UserRole, i18n("Waiting...")); renderItem->setSizeHint(1, QSize(m_view.running_jobs->columnWidth(1), fontMetrics().height() * 2)); - renderItem->setData(1, Qt::UserRole + 1, QTime::currentTime()); - renderItem->setData(1, Qt::UserRole + 3, path); - renderItem->setData(1, Qt::UserRole + 4, '1'); + renderItem->setData(1, TimeRole, QTime::currentTime()); + renderItem->setData(1, ParametersRole, path); checkRenderStatus(); m_view.tabWidget->setCurrentIndex(1); } @@ -2004,19 +2053,19 @@ bool RenderWidget::startWaitingRenderJobs() QTextStream outStream(&file); outStream << "#! /bin/sh" << "\n" << "\n"; - QTreeWidgetItem *item = m_view.running_jobs->topLevelItem(0); + RenderJobItem *item = static_cast (m_view.running_jobs->topLevelItem(0)); while (item) { - if (item->data(1, Qt::UserRole + 2).toInt() == WAITINGJOB) { - if (item->data(1, Qt::UserRole + 4).isNull()) { + if (item->status() == WAITINGJOB) { + if (item->type() == QTreeWidgetItem::Type) { // Add render process for item - const QString params = item->data(1, Qt::UserRole + 3).toStringList().join(" "); + const QString params = item->data(1, ParametersRole).toStringList().join(" "); outStream << m_renderer << " " << params << "\n"; - } else { + } else if (item->type() == ScriptType){ // Script item - outStream << item->data(1, Qt::UserRole + 3).toString() << "\n"; + outStream << item->data(1, ParametersRole).toString() << "\n"; } } - item = m_view.running_jobs->itemBelow(item); + item = static_cast(m_view.running_jobs->itemBelow(item)); } // erase itself when rendering is finished outStream << "rm " << autoscriptFile << "\n" << "\n"; @@ -2047,7 +2096,8 @@ QString RenderWidget::getFreeScriptName(const QString &prefix) void RenderWidget::slotPlayRendering(QTreeWidgetItem *item, int) { - if (KdenliveSettings::defaultplayerapp().isEmpty() || item->data(1, Qt::UserRole + 2).toInt() != FINISHEDJOB) return; + RenderJobItem *renderItem = static_cast (item); + if (KdenliveSettings::defaultplayerapp().isEmpty() || renderItem->status() != FINISHEDJOB) return; KUrl::List urls; urls.append(KUrl(item->text(1))); KRun::run(KdenliveSettings::defaultplayerapp(), urls, this); @@ -2150,3 +2200,4 @@ void RenderWidget::setRescaleEnabled(bool enable) if (m_view.rescale_box->itemAt(i)->widget()) m_view.rescale_box->itemAt(i)->widget()->setEnabled(enable); } } + diff --git a/src/renderwidget.h b/src/renderwidget.h index 559d9ed3..5cadb060 100644 --- a/src/renderwidget.h +++ b/src/renderwidget.h @@ -109,6 +109,21 @@ public: }; +class RenderJobItem: public QTreeWidgetItem +{ +public: + explicit RenderJobItem(QTreeWidget * parent, const QStringList & strings, int type = QTreeWidgetItem::Type); + void setStatus(int status); + int status() const; + void setMetadata(const QString &data); + const QString metadata() const; + void render(); + +private: + int m_status; + QString m_data; +}; + class RenderWidget : public QDialog { Q_OBJECT @@ -198,8 +213,9 @@ private: void parseFile(QString exportFile, bool editable); void updateButtons(); KUrl filenameWithExtension(KUrl url, QString extension); + /** @brief Check if a job needs to be started. */ void checkRenderStatus(); - void startRendering(QTreeWidgetItem *item); + void startRendering(RenderJobItem *item); void saveProfile(QDomElement newprofile); QList m_renderItems; QList m_renderCategory; -- 2.39.2