X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Frenderwidget.cpp;h=385203ad6829fc54139cf66bd0db0e7dc17443b8;hb=5f2ae774dfd6cc7870cb8de75fb38259a4f96dd1;hp=e4b6b9eaa4e086d3f8909c413aa6846b9947ed01;hpb=c6f581eb95db46086221714f84f7fd56a3e8153b;p=kdenlive diff --git a/src/renderwidget.cpp b/src/renderwidget.cpp index e4b6b9ea..385203ad 100644 --- a/src/renderwidget.cpp +++ b/src/renderwidget.cpp @@ -46,7 +46,12 @@ #include #include #include +#include +#include "locale.h" + + +// Render profiles roles const int GroupRole = Qt::UserRole; const int ExtensionRole = GroupRole + 1; const int StandardRole = GroupRole + 2; @@ -57,20 +62,98 @@ const int MetaGroupRole = GroupRole + 6; const int ExtraRole = GroupRole + 7; const int BitratesRole = GroupRole + 8; 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 ProgressRole = Qt::UserRole + 3; +const int ExtraInfoRole = Qt::UserRole + 5; + +const int DirectRenderType = QTreeWidgetItem::Type; +const int ScriptRenderType = 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() * 3)); + 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(1, ProgressRole, 100); + break; + case FAILEDJOB: + setData(1, Qt::UserRole, i18n("Rendering crashed")); + setIcon(0, KIcon("dialog-close")); + setData(1, ProgressRole, 100); + break; + case ABORTEDJOB: + setData(1, Qt::UserRole, i18n("Rendering aborted")); + setIcon(0, KIcon("dialog-cancel")); + setData(1, ProgressRole, 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, QWidget * parent) : +RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, const MltVideoProfile &profile, QWidget * parent) : QDialog(parent), m_projectFolder(projectfolder), + m_profile(profile), m_blockProcessing(false) { m_view.setupUi(this); + int size = style()->pixelMetric(QStyle::PM_SmallIconSize); + QSize iconSize(size, size); + setWindowTitle(i18n("Rendering")); + m_view.buttonDelete->setIconSize(iconSize); + m_view.buttonEdit->setIconSize(iconSize); + m_view.buttonSave->setIconSize(iconSize); + m_view.buttonInfo->setIconSize(iconSize); + m_view.buttonFavorite->setIconSize(iconSize); + m_view.buttonDelete->setIcon(KIcon("trash-empty")); m_view.buttonDelete->setToolTip(i18n("Delete profile")); m_view.buttonDelete->setEnabled(false); @@ -88,14 +171,44 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, QWidg m_view.buttonFavorite->setIcon(KIcon("favorites")); m_view.buttonFavorite->setToolTip(i18n("Copy profile to favorites")); + m_view.show_all_profiles->setToolTip(i18n("Show profiles with different framerate")); + m_view.advanced_params->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 5); - + + m_view.buttonRender->setEnabled(false); + m_view.buttonGenerateScript->setEnabled(false); + setRescaleEnabled(false); + m_view.guides_box->setVisible(false); + m_view.open_dvd->setVisible(false); + m_view.create_chapter->setVisible(false); + m_view.open_browser->setVisible(false); + m_view.error_box->setVisible(false); + m_view.tc_type->setEnabled(false); + m_view.checkTwoPass->setEnabled(false); + if (KdenliveSettings::showrenderparams()) { m_view.buttonInfo->setDown(true); - } else m_view.advanced_params->hide(); + } else { + m_view.advanced_params->hide(); + } m_view.proxy_render->setHidden(!enableProxy); + KColorScheme scheme(palette().currentColorGroup(), KColorScheme::Window, KSharedConfig::openConfig(KdenliveSettings::colortheme())); + QColor bg = scheme.background(KColorScheme::NegativeBackground).color(); + m_view.errorBox->setStyleSheet(QString("QGroupBox { background-color: rgb(%1, %2, %3); border-radius: 5px;}; ").arg(bg.red()).arg(bg.green()).arg(bg.blue())); + int height = QFontInfo(font()).pixelSize(); + m_view.errorIcon->setPixmap(KIcon("dialog-warning").pixmap(height, height)); + m_view.errorBox->setHidden(true); + +#if KDE_IS_VERSION(4,7,0) + m_infoMessage = new KMessageWidget; + QGridLayout *s = static_cast (m_view.tab->layout()); + s->addWidget(m_infoMessage, 16, 0, 1, -1); + m_infoMessage->setCloseButtonVisible(false); + m_infoMessage->hide(); +#endif + m_view.encoder_threads->setMaximum(QThread::idealThreadCount()); m_view.encoder_threads->setValue(KdenliveSettings::encodethreads()); connect(m_view.encoder_threads, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateEncodeThreads(int))); @@ -117,13 +230,6 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, QWidg m_view.format_list->setAlternatingRowColors(true); m_view.size_list->setAlternatingRowColors(true); - KColorScheme scheme(palette().currentColorGroup(), KColorScheme::Window, KSharedConfig::openConfig(KdenliveSettings::colortheme())); - QColor bg = scheme.background(KColorScheme::NegativeBackground).color(); - m_view.errorBox->setStyleSheet(QString("QGroupBox { background-color: rgb(%1, %2, %3); border-radius: 5px;}; ").arg(bg.red()).arg(bg.green()).arg(bg.blue())); - int height = QFontInfo(font()).pixelSize(); - m_view.errorIcon->setPixmap(KIcon("dialog-warning").pixmap(height, height)); - m_view.errorBox->setHidden(true); - connect(m_view.export_audio, SIGNAL(stateChanged(int)), this, SLOT(slotUpdateAudioLabel(int))); m_view.export_audio->setCheckState(Qt::PartiallyChecked); @@ -135,7 +241,7 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, QWidg connect(m_view.delete_script, SIGNAL(clicked()), this, SLOT(slotDeleteScript())); connect(m_view.scripts_list, SIGNAL(itemSelectionChanged()), this, SLOT(slotCheckScript())); connect(m_view.running_jobs, SIGNAL(itemSelectionChanged()), this, SLOT(slotCheckJob())); - connect(m_view.running_jobs, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(slotPlayRendering(QTreeWidgetItem *, int))); + connect(m_view.running_jobs, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotPlayRendering(QTreeWidgetItem*,int))); connect(m_view.buttonInfo, SIGNAL(clicked()), this, SLOT(showInfoPanel())); @@ -152,14 +258,15 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, QWidg connect(m_view.buttonClose, SIGNAL(clicked()), this, SLOT(hide())); connect(m_view.buttonClose2, SIGNAL(clicked()), this, SLOT(hide())); connect(m_view.buttonClose3, SIGNAL(clicked()), this, SLOT(hide())); - connect(m_view.rescale, SIGNAL(toggled(bool)), m_view.rescale_box, SLOT(setEnabled(bool))); + connect(m_view.rescale, SIGNAL(toggled(bool)), this, SLOT(setRescaleEnabled(bool))); connect(m_view.destination_list, SIGNAL(activated(int)), this, SLOT(refreshCategory())); - connect(m_view.out_file, SIGNAL(textChanged(const QString &)), this, SLOT(slotUpdateButtons())); - connect(m_view.out_file, SIGNAL(urlSelected(const KUrl &)), this, SLOT(slotUpdateButtons(const KUrl &))); + connect(m_view.out_file, SIGNAL(textChanged(QString)), this, SLOT(slotUpdateButtons())); + connect(m_view.out_file, SIGNAL(urlSelected(KUrl)), this, SLOT(slotUpdateButtons(KUrl))); connect(m_view.format_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshView())); connect(m_view.size_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshParams())); + connect(m_view.show_all_profiles, SIGNAL(stateChanged(int)), this, SLOT(refreshView())); - connect(m_view.size_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(slotEditItem(QListWidgetItem *))); + connect(m_view.size_list, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(slotEditItem(QListWidgetItem*))); connect(m_view.render_guide, SIGNAL(clicked(bool)), this, SLOT(slotUpdateGuideBox())); connect(m_view.render_zone, SIGNAL(clicked(bool)), this, SLOT(slotUpdateGuideBox())); @@ -170,23 +277,13 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, QWidg connect(m_view.tc_overlay, SIGNAL(toggled(bool)), m_view.tc_type, SLOT(setEnabled(bool))); - m_view.buttonRender->setEnabled(false); - m_view.buttonGenerateScript->setEnabled(false); - m_view.rescale_box->setEnabled(false); - m_view.guides_box->setVisible(false); - m_view.open_dvd->setVisible(false); - m_view.create_chapter->setVisible(false); - m_view.open_browser->setVisible(false); - m_view.error_box->setVisible(false); - m_view.tc_type->setEnabled(false); - m_view.checkTwoPass->setEnabled(false); - m_view.splitter->setStretchFactor(1, 5); m_view.splitter->setStretchFactor(0, 2); m_view.out_file->setMode(KFile::File); + m_view.out_file->setFocusPolicy(Qt::ClickFocus); - m_view.running_jobs->setHeaderLabels(QStringList() << QString() << i18n("File") << i18n("Progress")); + m_view.running_jobs->setHeaderLabels(QStringList() << QString() << i18n("File")); m_jobsDelegate = new RenderViewDelegate(this); m_view.running_jobs->setItemDelegate(m_jobsDelegate); @@ -194,11 +291,6 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, QWidg header->setResizeMode(0, QHeaderView::Fixed); header->resizeSection(0, 30); header->setResizeMode(1, QHeaderView::Interactive); - header->setResizeMode(2, QHeaderView::Fixed); - header->resizeSection(1, width() * 2 / 3 - 15); - header->setResizeMode(2, QHeaderView::Interactive); - //header->setResizeMode(1, QHeaderView::Fixed); - m_view.scripts_list->setHeaderLabels(QStringList() << QString() << i18n("Script Files")); m_scriptsDelegate = new RenderViewDelegate(this); @@ -211,8 +303,10 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, QWidg m_renderer = QCoreApplication::applicationDirPath() + QString("/kdenlive_render"); if (!QFile::exists(m_renderer)) { m_renderer = KStandardDirs::findExe("kdenlive_render"); - if (m_renderer.isEmpty()) m_renderer = KStandardDirs::locate("exe", "kdenlive_render"); - if (m_renderer.isEmpty()) m_renderer = "kdenlive_render"; + if (m_renderer.isEmpty()) + m_renderer = KStandardDirs::locate("exe", "kdenlive_render"); + if (m_renderer.isEmpty()) + m_renderer = "kdenlive_render"; } QDBusConnectionInterface* interface = QDBusConnection::sessionBus().interface(); @@ -220,6 +314,13 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, QWidg m_view.shutdown->setEnabled(false); focusFirstVisibleItem(); + adjustSize(); +} + +QSize RenderWidget::sizeHint() const +{ + // Make sure the widget has minimum size on opening + return QSize(200, 200); } RenderWidget::~RenderWidget() @@ -230,12 +331,16 @@ RenderWidget::~RenderWidget() m_view.scripts_list->clear(); delete m_jobsDelegate; delete m_scriptsDelegate; +#if KDE_IS_VERSION(4,7,0) + delete m_infoMessage; +#endif } void RenderWidget::slotEditItem(QListWidgetItem *item) { - QString edit = item->data(EditableRole).toString(); - if (edit.isEmpty() || !edit.endsWith("customprofiles.xml")) slotSaveProfile(); + const QString edit = item->data(EditableRole).toString(); + if (edit.isEmpty() || !edit.endsWith(QLatin1String("customprofiles.xml"))) + slotSaveProfile(); else slotEditProfile(); } @@ -252,7 +357,7 @@ void RenderWidget::showInfoPanel() } } -void RenderWidget::setDocumentPath(const QString path) +void RenderWidget::setDocumentPath(const QString &path) { if (m_view.out_file->url().directory() == KUrl(m_projectFolder).directory()) { const QString fileName = m_view.out_file->url().fileName(); @@ -285,7 +390,7 @@ void RenderWidget::setGuides(QDomElement guidesxml, double duration) m_view.guide_start->clear(); m_view.guide_end->clear(); QDomNodeList nodes = guidesxml.elementsByTagName("guide"); - if (nodes.count() > 0) { + if (!nodes.isEmpty()) { m_view.guide_start->addItem(i18n("Beginning"), "0"); m_view.render_guide->setEnabled(true); m_view.create_chapter->setEnabled(true); @@ -294,7 +399,7 @@ void RenderWidget::setGuides(QDomElement guidesxml, double duration) m_view.create_chapter->setEnabled(false); } double fps = (double) m_profile.frame_rate_num / m_profile.frame_rate_den; - for (int i = 0; i < nodes.count(); i++) { + for (int i = 0; i < nodes.count(); ++i) { QDomElement e = nodes.item(i).toElement(); if (!e.isNull()) { GenTime pos = GenTime(e.attribute("time").toDouble()); @@ -303,7 +408,7 @@ void RenderWidget::setGuides(QDomElement guidesxml, double duration) m_view.guide_end->addItem(e.attribute("comment") + '/' + guidePos, e.attribute("time").toDouble()); } } - if (nodes.count() > 0) + if (!nodes.isEmpty()) m_view.guide_end->addItem(i18n("End"), QString::number(duration)); } @@ -311,7 +416,7 @@ void RenderWidget::setGuides(QDomElement guidesxml, double duration) * Will be called when the user selects an output file via the file dialog. * File extension will be added automatically. */ -void RenderWidget::slotUpdateButtons(KUrl url) +void RenderWidget::slotUpdateButtons(const KUrl &url) { if (m_view.out_file->url().isEmpty()) { m_view.buttonGenerateScript->setEnabled(false); @@ -326,9 +431,8 @@ void RenderWidget::slotUpdateButtons(KUrl url) m_view.buttonGenerateScript->setEnabled(false); return; } - QString extension = item->data(ExtensionRole).toString(); - url = filenameWithExtension(url, extension); - m_view.out_file->setUrl(url); + const QString extension = item->data(ExtensionRole).toString(); + m_view.out_file->setUrl(filenameWithExtension(url, extension)); } } @@ -353,7 +457,7 @@ void RenderWidget::slotSaveProfile() QDialog *d = new QDialog(this); ui.setupUi(d); - for (int i = 0; i < m_view.destination_list->count(); i++) + for (int i = 0; i < m_view.destination_list->count(); ++i) ui.destination_list->addItem(m_view.destination_list->itemIcon(i), m_view.destination_list->itemText(i), m_view.destination_list->itemData(i, Qt::UserRole)); ui.destination_list->setCurrentIndex(m_view.destination_list->currentIndex()); @@ -363,9 +467,29 @@ void RenderWidget::slotSaveProfile() if (customGroup.isEmpty()) customGroup = i18nc("Group Name", "Custom"); ui.group_name->setText(customGroup); - ui.parameters->setText(m_view.advanced_params->toPlainText()); + QStringList arguments = m_view.advanced_params->toPlainText().split(' ', QString::SkipEmptyParts); + ui.parameters->setText(arguments.join(" ")); ui.extension->setText(m_view.size_list->currentItem()->data(ExtensionRole).toString()); ui.profile_name->setFocus(); + QListWidgetItem *item = m_view.size_list->currentItem(); + if (ui.parameters->toPlainText().contains("%bitrate")) { + if ( item && item->data(BitratesRole).canConvert(QVariant::StringList) && item->data(BitratesRole).toStringList().count()) { + QStringList bitrates = item->data(BitratesRole).toStringList(); + ui.vbitrates_list->setText(bitrates.join(",")); + if (item->data(DefaultBitrateRole).canConvert(QVariant::String)) + ui.default_vbitrate->setValue(item->data(DefaultBitrateRole).toInt()); + } + } + else ui.vbitrates->setHidden(true); + if (ui.parameters->toPlainText().contains("%audiobitrate")) { + if ( item && item->data(AudioBitratesRole).canConvert(QVariant::StringList) && item->data(AudioBitratesRole).toStringList().count()) { + QStringList bitrates = item->data(AudioBitratesRole).toStringList(); + ui.abitrates_list->setText(bitrates.join(",")); + if (item->data(DefaultAudioBitrateRole).canConvert(QVariant::String)) + ui.default_abitrate->setValue(item->data(DefaultAudioBitrateRole).toInt()); + } + } + else ui.abitrates->setHidden(true); if (d->exec() == QDialog::Accepted && !ui.profile_name->text().simplified().isEmpty()) { QString newProfileName = ui.profile_name->text().simplified(); @@ -379,7 +503,18 @@ void RenderWidget::slotSaveProfile() profileElement.setAttribute("category", newGroupName); profileElement.setAttribute("destinationid", newMetaGroupId); profileElement.setAttribute("extension", ui.extension->text().simplified()); - profileElement.setAttribute("args", ui.parameters->toPlainText().simplified()); + QString args = ui.parameters->toPlainText().simplified(); + profileElement.setAttribute("args", args); + if (args.contains("%bitrate")) { + // profile has a variable bitrate + profileElement.setAttribute("defaultbitrate", QString::number(ui.default_vbitrate->value())); + profileElement.setAttribute("bitrates", ui.vbitrates_list->text()); + } + if (args.contains("%audiobitrate")) { + // profile has a variable bitrate + profileElement.setAttribute("defaultaudiobitrate", QString::number(ui.default_abitrate->value())); + profileElement.setAttribute("audiobitrates", ui.abitrates_list->text()); + } doc.appendChild(profileElement); saveProfile(doc.documentElement()); @@ -389,7 +524,7 @@ void RenderWidget::slotSaveProfile() } -void RenderWidget::saveProfile(QDomElement newprofile) +void RenderWidget::saveProfile(const QDomElement &newprofile) { QString exportFile = KStandardDirs::locateLocal("appdata", "export/customprofiles.xml"); QDomDocument doc; @@ -430,7 +565,7 @@ void RenderWidget::saveProfile(QDomElement newprofile) break; } } - i++; + ++i; } profiles.appendChild(newprofile); @@ -454,7 +589,8 @@ void RenderWidget::saveProfile(QDomElement newprofile) void RenderWidget::slotCopyToFavorites() { QListWidgetItem *item = m_view.size_list->currentItem(); - if (!item) return; + if (!item) + return; QString currentGroup = m_view.format_list->currentItem()->text(); QString params = item->data(ParamsRole).toString(); @@ -467,6 +603,10 @@ void RenderWidget::slotCopyToFavorites() profileElement.setAttribute("destinationid", "favorites"); profileElement.setAttribute("extension", extension); profileElement.setAttribute("args", params); + profileElement.setAttribute("bitrates", item->data(BitratesRole).toStringList().join(",")); + profileElement.setAttribute("defaultbitrate", item->data(DefaultBitrateRole).toString()); + profileElement.setAttribute("audiobitrates", item->data(AudioBitratesRole).toStringList().join(",")); + profileElement.setAttribute("defaultaudiobitrate", item->data(DefaultAudioBitrateRole).toString()); doc.appendChild(profileElement); saveProfile(doc.documentElement()); parseProfiles(m_view.destination_list->itemData(m_view.destination_list->currentIndex(), Qt::UserRole).toString(), currentGroup, currentProfile); @@ -486,7 +626,7 @@ void RenderWidget::slotEditProfile() QDialog *d = new QDialog(this); ui.setupUi(d); - for (int i = 0; i < m_view.destination_list->count(); i++) + for (int i = 0; i < m_view.destination_list->count(); ++i) ui.destination_list->addItem(m_view.destination_list->itemIcon(i), m_view.destination_list->itemText(i), m_view.destination_list->itemData(i, Qt::UserRole)); ui.destination_list->setCurrentIndex(m_view.destination_list->currentIndex()); @@ -500,6 +640,27 @@ void RenderWidget::slotEditProfile() ui.extension->setText(extension); ui.parameters->setText(params); ui.profile_name->setFocus(); + if (ui.parameters->toPlainText().contains("%bitrate")) { + if ( item->data(BitratesRole).canConvert(QVariant::StringList) && item->data(BitratesRole).toStringList().count()) { + QStringList bitrates = item->data(BitratesRole).toStringList(); + ui.vbitrates_list->setText(bitrates.join(",")); + if (item->data(DefaultBitrateRole).canConvert(QVariant::String)) + ui.default_vbitrate->setValue(item->data(DefaultBitrateRole).toInt()); + } + } else { + ui.vbitrates->setHidden(true); + } + + if (ui.parameters->toPlainText().contains("%audiobitrate")) { + if ( item->data(AudioBitratesRole).canConvert(QVariant::StringList) && item->data(AudioBitratesRole).toStringList().count()) { + QStringList bitrates = item->data(AudioBitratesRole).toStringList(); + ui.abitrates_list->setText(bitrates.join(",")); + if (item->data(DefaultAudioBitrateRole).canConvert(QVariant::String)) + ui.default_abitrate->setValue(item->data(DefaultAudioBitrateRole).toInt()); + } + } + else ui.abitrates->setHidden(true); + d->setWindowTitle(i18n("Edit Profile")); if (d->exec() == QDialog::Accepted) { slotDeleteProfile(false); @@ -547,7 +708,7 @@ void RenderWidget::slotEditProfile() break; } } - i++; + ++i; } QDomElement profileElement = doc.createElement("profile"); @@ -555,7 +716,19 @@ void RenderWidget::slotEditProfile() profileElement.setAttribute("category", newGroupName); profileElement.setAttribute("destinationid", newMetaGroupId); profileElement.setAttribute("extension", ui.extension->text().simplified()); - profileElement.setAttribute("args", ui.parameters->toPlainText().simplified()); + QString args = ui.parameters->toPlainText().simplified(); + profileElement.setAttribute("args", args); + if (args.contains("%bitrate")) { + // profile has a variable bitrate + profileElement.setAttribute("defaultbitrate", QString::number(ui.default_vbitrate->value())); + profileElement.setAttribute("bitrates", ui.vbitrates_list->text()); + } + if (args.contains("%audiobitrate")) { + // profile has a variable bitrate + profileElement.setAttribute("defaultaudiobitrate", QString::number(ui.default_abitrate->value())); + profileElement.setAttribute("audiobitrates", ui.abitrates_list->text()); + } + profiles.appendChild(profileElement); //QCString save = doc.toString().utf8(); @@ -617,7 +790,7 @@ void RenderWidget::slotDeleteProfile(bool refresh) doc.documentElement().removeChild(profiles.item(i)); break; } - i++; + ++i; } if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { @@ -662,8 +835,13 @@ void RenderWidget::updateButtons() } -void RenderWidget::focusFirstVisibleItem() +void RenderWidget::focusFirstVisibleItem(const QString &profile) { + if (!profile.isEmpty()) { + QList child = m_view.size_list->findItems(profile, Qt::MatchExactly); + if (!child.isEmpty()) + m_view.size_list->setCurrentItem(child.at(0)); + } if (m_view.size_list->currentItem()) { updateButtons(); return; @@ -694,20 +872,22 @@ void RenderWidget::slotPrepareExport(bool scriptExport) } -void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const QString &playlistPath, const QString &scriptPath, bool exportAudio) +void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const QMap &metadata, const QString &playlistPath, const QString &scriptPath, bool exportAudio) { QListWidgetItem *item = m_view.size_list->currentItem(); - if (!item) return; + if (!item) + return; - QString dest = m_view.out_file->url().path(); - if (dest.isEmpty()) return; + QString dest = m_view.out_file->url().path().trimmed(); + if (dest.isEmpty()) + return; // Check whether target file has an extension. // If not, ask whether extension should be added or not. QString extension = item->data(ExtensionRole).toString(); if (!dest.endsWith(extension, Qt::CaseInsensitive)) { if (KMessageBox::questionYesNo(this, i18n("File has no extension. Add extension (%1)?", extension)) == KMessageBox::Yes) { - dest.append("." + extension); + dest.append('.' + extension); } } @@ -730,6 +910,15 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const if (!scriptExport) render_process_args << "-erase"; if (KdenliveSettings::usekuiserver()) render_process_args << "-kuiserver"; + // get process id + render_process_args << QString("-pid:%1").arg(QCoreApplication::applicationPid()); + + // Set locale for render process if required + if (QLocale().decimalPoint() != QLocale::system().decimalPoint()) { + const QString currentLocale = setlocale(LC_NUMERIC, NULL); + render_process_args << QString("-locale:%1").arg(currentLocale); + } + double guideStart = 0; double guideEnd = 0; @@ -743,11 +932,24 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const if (!overlayargs.isEmpty()) render_process_args << "preargs=" + overlayargs.join(" "); - render_process_args << KdenliveSettings::rendererpath() << m_profile.path << item->data(RenderRole).toString(); + if (scriptExport) + render_process_args << "$MELT"; + else + render_process_args << KdenliveSettings::rendererpath(); + render_process_args << m_profile.path << item->data(RenderRole).toString(); if (m_view.play_after->isChecked()) render_process_args << KdenliveSettings::KdenliveSettings::defaultplayerapp(); else render_process_args << "-"; QString renderArgs = m_view.advanced_params->toPlainText().simplified(); + + // Project metadata + if (m_view.export_meta->isChecked()) { + QMap::const_iterator i = metadata.constBegin(); + while (i != metadata.constEnd()) { + renderArgs.append(QString(" %1=%2").arg(i.key()).arg(QString(QUrl::toPercentEncoding(i.value())))); + ++i; + } + } // Adjust frame scale int width; @@ -771,7 +973,9 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const if (!exportAudio) renderArgs.append(" an=1 "); // Set the thread counts - renderArgs.append(QString(" threads=%1").arg(KdenliveSettings::encodethreads())); + if (!renderArgs.contains("threads=")) { + renderArgs.append(QString(" threads=%1").arg(KdenliveSettings::encodethreads())); + } renderArgs.append(QString(" real_time=-%1").arg(KdenliveSettings::mltthreads())); // Check if the rendering profile is different from project profile, @@ -792,10 +996,11 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const renderArgs.append(subsize); } bool resizeProfile = (subsize != currentSize); - QStringList paramsList = renderArgs.split(" ", QString::SkipEmptyParts); + QStringList paramsList = renderArgs.split(' ', QString::SkipEmptyParts); QScriptEngine sEngine; - sEngine.globalObject().setProperty("bitrate", m_view.comboBitrates->currentText()); + sEngine.globalObject().setProperty("bitrate", m_view.comboBitrates->currentText().toInt()); + sEngine.globalObject().setProperty("audiobitrate", m_view.comboAudioBitrates->currentText().toInt()); sEngine.globalObject().setProperty("dar", '@' + QString::number(m_profile.display_aspect_num) + '/' + QString::number(m_profile.display_aspect_den)); sEngine.globalObject().setProperty("passes", static_cast(m_view.checkTwoPass->isChecked()) + 1); @@ -818,12 +1023,13 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const render_process_args << "consumer:" + (scriptExport ? "$SOURCE" : playlistPath); else render_process_args << (scriptExport ? "$SOURCE" : playlistPath); + render_process_args << (scriptExport ? "$TARGET" : KUrl(dest).url()); render_process_args << paramsList; QString group = m_view.size_list->currentItem()->data(MetaGroupRole).toString(); - QString scriptName; + //QString scriptName; if (scriptExport) { // Generate script file QFile file(scriptPath); @@ -833,12 +1039,12 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const } QTextStream outStream(&file); outStream << "#! /bin/sh" << "\n" << "\n"; - outStream << "SOURCE=" << "\"" + playlistPath + "\"" << "\n"; - outStream << "TARGET=" << "\"" + KUrl(dest).url() + "\"" << "\n"; + outStream << "SOURCE=" << "\"" + QUrl(playlistPath).toEncoded() + "\"" << "\n"; + outStream << "TARGET=" << "\"" + QUrl(dest).toEncoded() + "\"" << "\n"; outStream << "RENDERER=" << "\"" + m_renderer + "\"" << "\n"; - outStream << "MELT=" << "\"" + render_process_args.takeFirst() + "\"" << "\n"; + outStream << "MELT=" << "\"" + KdenliveSettings::rendererpath() + "\"" << "\n"; outStream << "PARAMETERS=" << "\"" + render_process_args.join(" ") + "\"" << "\n"; - outStream << "$RENDERER $MELT $PARAMETERS" << "\n" << "\n"; + outStream << "$RENDERER $PARAMETERS" << "\n" << "\n"; if (file.error() != QFile::NoError) { KMessageBox::error(this, i18n("Cannot write to file %1", scriptPath)); file.close(); @@ -865,8 +1071,10 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const renderProps.insert("renderendguide", QString::number(m_view.guide_end->currentIndex())); renderProps.insert("renderscanning", QString::number(m_view.scanning_list->currentIndex())); int export_audio = 0; - if (m_view.export_audio->checkState() == Qt::Checked) export_audio = 2; - else if (m_view.export_audio->checkState() == Qt::Unchecked) export_audio = 1; + if (m_view.export_audio->checkState() == Qt::Checked) + export_audio = 2; + else if (m_view.export_audio->checkState() == Qt::Unchecked) + export_audio = 1; renderProps.insert("renderexportaudio", QString::number(export_audio)); renderProps.insert("renderrescale", QString::number(m_view.rescale->isChecked())); renderProps.insert("renderrescalewidth", QString::number(m_view.rescale_width->value())); @@ -880,34 +1088,40 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const emit selectedRenderProfile(renderProps); // insert item in running jobs list - QTreeWidgetItem *renderItem; + RenderJobItem *renderItem = NULL; 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 || renderItem->status() == WAITINGJOB) { 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()); - } else { - renderItem = new QTreeWidgetItem(m_view.running_jobs, QStringList() << QString() << dest << QString()); + if (renderItem->type() != DirectRenderType) { + delete renderItem; + renderItem = NULL; + } + else { + renderItem->setData(1, ProgressRole, 0); + renderItem->setStatus(WAITINGJOB); + renderItem->setIcon(0, KIcon("media-playback-pause")); + renderItem->setData(1, Qt::UserRole, i18n("Waiting...")); + renderItem->setData(1, ParametersRole, dest); + } } - 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()); + if (!renderItem) renderItem = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << dest); + 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 { @@ -915,12 +1129,15 @@ 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); - if (exportAudio == false) renderItem->setData(1, Qt::UserRole + 5, i18n("Video without audio track")); - else renderItem->setData(1, Qt::UserRole + 5, QString()); + + renderItem->setData(1, ParametersRole, render_process_args); + if (exportAudio == false) + renderItem->setData(1, ExtraInfoRole, i18n("Video without audio track")); + else + renderItem->setData(1, ExtraInfoRole, QString()); m_view.running_jobs->setCurrentItem(renderItem); m_view.tabWidget->setCurrentIndex(1); checkRenderStatus(); @@ -930,60 +1147,62 @@ 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)); + + // Make sure no other rendering is running 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; + + // Find first waiting job 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() == DirectRenderType) { // 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); - } else KNotification::event("RenderStarted", i18n("Rendering %1 started", item->text(1)), QPixmap(), this); - } else { + kDebug()<<"// Normal process"; + 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 if (item->type() == ScriptRenderType){ // 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); + kDebug()<<"// SCRIPT process: "<data(1, ParametersRole).toString(); + 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; } -void RenderWidget::setProfile(MltVideoProfile profile) +void RenderWidget::setProfile(const MltVideoProfile &profile) { - m_profile = profile; m_view.scanning_list->setCurrentIndex(0); m_view.rescale_width->setValue(KdenliveSettings::defaultrescalewidth()); if (!m_view.rescale_keep->isChecked()) { @@ -991,20 +1210,24 @@ void RenderWidget::setProfile(MltVideoProfile profile) m_view.rescale_height->setValue(KdenliveSettings::defaultrescaleheight()); m_view.rescale_height->blockSignals(false); } - refreshView(); + if (m_profile != profile) { + m_profile = profile; + refreshView(); + } } -void RenderWidget::refreshCategory() + + +void RenderWidget::refreshCategory(const QString &group, const QString &profile) { m_view.format_list->blockSignals(true); m_view.format_list->clear(); QListWidgetItem *sizeItem; - + QString destination; if (m_view.destination_list->currentIndex() > 0) destination = m_view.destination_list->itemData(m_view.destination_list->currentIndex()).toString(); - if (destination == "dvd") { m_view.open_dvd->setVisible(true); m_view.create_chapter->setVisible(true); @@ -1019,7 +1242,7 @@ void RenderWidget::refreshCategory() m_view.open_browser->setVisible(false); // hide groups that are not in the correct destination - for (int i = 0; i < m_renderCategory.count(); i++) { + for (int i = 0; i < m_renderCategory.count(); ++i) { sizeItem = m_renderCategory.at(i); if (sizeItem->data(MetaGroupRole).toString() == destination) { m_view.format_list->addItem(sizeItem->clone()); @@ -1027,15 +1250,20 @@ void RenderWidget::refreshCategory() } } - // activate first visible item + // activate requested item or first visible + QList child; + if (!group.isEmpty()) child = m_view.format_list->findItems(group, Qt::MatchExactly); + if (!child.isEmpty()) { + m_view.format_list->setCurrentItem(child.at(0)); + child.clear(); + } else m_view.format_list->setCurrentRow(0); QListWidgetItem * item = m_view.format_list->currentItem(); - if (!item) { - m_view.format_list->setCurrentRow(0); - item = m_view.format_list->currentItem(); - } + m_view.format_list->blockSignals(false); if (!item) { m_view.format_list->setEnabled(false); + m_view.format_list->clear(); m_view.size_list->setEnabled(false); + m_view.size_list->clear(); m_view.size_list->blockSignals(false); m_view.format_list->blockSignals(false); return; @@ -1048,10 +1276,11 @@ void RenderWidget::refreshCategory() m_view.format_list->setVisible(true); else m_view.format_list->setVisible(false); - refreshView(); + + refreshView(profile); } -void RenderWidget::refreshView() +void RenderWidget::refreshView(const QString &profile) { if (!m_view.format_list->currentItem()) return; m_view.size_list->blockSignals(true); @@ -1065,21 +1294,26 @@ void RenderWidget::refreshView() KIcon brokenIcon("dialog-close"); KIcon warningIcon("dialog-warning"); - const QStringList formatsList = KdenliveSettings::supportedformats(); - const QStringList vcodecsList = KdenliveSettings::videocodecs(); - const QStringList acodecsList = KdenliveSettings::audiocodecs(); + QStringList formatsList; + QStringList vcodecsList; + QStringList acodecsList; + if (!KdenliveSettings::bypasscodeccheck()) { + formatsList= KdenliveSettings::supportedformats(); + vcodecsList = KdenliveSettings::videocodecs(); + acodecsList = KdenliveSettings::audiocodecs(); + } KColorScheme scheme(palette().currentColorGroup(), KColorScheme::Window); const QColor disabled = scheme.foreground(KColorScheme::InactiveText).color(); const QColor disabledbg = scheme.background(KColorScheme::NegativeBackground).color(); double project_framerate = (double) m_profile.frame_rate_num / m_profile.frame_rate_den; - for (int i = 0; i < m_renderItems.count(); i++) { + for (int i = 0; i < m_renderItems.count(); ++i) { sizeItem = m_renderItems.at(i); QListWidgetItem *dupItem = NULL; if ((sizeItem->data(GroupRole).toString() == group || sizeItem->data(GroupRole).toString().isEmpty()) && sizeItem->data(MetaGroupRole).toString() == destination) { std = sizeItem->data(StandardRole).toString(); - if (!std.isEmpty()) { + if (!m_view.show_all_profiles->isChecked() && !std.isEmpty()) { if ((std.contains("PAL", Qt::CaseInsensitive) && m_profile.frame_rate_num == 25 && m_profile.frame_rate_den == 1) || (std.contains("NTSC", Qt::CaseInsensitive) && m_profile.frame_rate_num == 30000 && m_profile.frame_rate_den == 1001)) dupItem = sizeItem->clone(); @@ -1091,7 +1325,7 @@ void RenderWidget::refreshView() m_view.size_list->addItem(dupItem); std = dupItem->data(ParamsRole).toString(); // Make sure the selected profile uses the same frame rate as project profile - if (std.contains("mlt_profile=")) { + if (!m_view.show_all_profiles->isChecked() && std.contains("mlt_profile=")) { QString profile = std.section("mlt_profile=", 1, 1).section(' ', 0, 0); MltVideoProfile p = ProfilesDialog::getVideoProfile(profile); if (p.frame_rate_den > 0) { @@ -1163,17 +1397,19 @@ void RenderWidget::refreshView() } } } - // m_view.size_list->sortItems(); - focusFirstVisibleItem(); + focusFirstVisibleItem(profile); m_view.size_list->blockSignals(false); - m_view.format_list->blockSignals(false); - if (m_view.size_list->count() > 0) + if (m_view.size_list->count() > 0) { refreshParams(); - else + } + else { + // No matching profile + errorMessage(i18n("No matching profile")); m_view.advanced_params->clear(); + } } -KUrl RenderWidget::filenameWithExtension(KUrl url, QString extension) +KUrl RenderWidget::filenameWithExtension(KUrl url, const QString &extension) { if (url.isEmpty()) url = KUrl(m_projectFolder); QString directory = url.directory(KUrl::AppendTrailingSlash | KUrl::ObeyTrailingSlash); @@ -1200,13 +1436,15 @@ void RenderWidget::refreshParams() { // Format not available (e.g. codec not installed); Disable start button QListWidgetItem *item = m_view.size_list->currentItem(); - errorMessage(item->toolTip()); if (!item || item->isHidden()) { + if (!item) + errorMessage(i18n("No matching profile")); m_view.advanced_params->clear(); m_view.buttonRender->setEnabled(false); m_view.buttonGenerateScript->setEnabled(false); return; } + errorMessage(item->toolTip()); QString params = item->data(ParamsRole).toString(); QString extension = item->data(ExtensionRole).toString(); m_view.advanced_params->setPlainText(params); @@ -1214,10 +1452,10 @@ void RenderWidget::refreshParams() if (params.contains(" s=") || params.startsWith("s=") || destination == "audioonly") { // profile has a fixed size, do not allow resize m_view.rescale->setEnabled(false); - m_view.rescale_box->setEnabled(false); + setRescaleEnabled(false); } else { m_view.rescale->setEnabled(true); - m_view.rescale_box->setEnabled(m_view.rescale->isChecked()); + setRescaleEnabled(m_view.rescale->isChecked()); } KUrl url = filenameWithExtension(m_view.out_file->url(), extension); m_view.out_file->setUrl(url); @@ -1244,19 +1482,40 @@ void RenderWidget::refreshParams() m_view.comboBitrates->clear(); if (params.contains("bitrate")) { m_view.comboBitrates->setEnabled(true); + m_view.bitrateLabel->setEnabled(true); if ( item->data(BitratesRole).canConvert(QVariant::StringList) && item->data(BitratesRole).toStringList().count()) { QStringList bitrates = item->data(BitratesRole).toStringList(); - foreach (QString bitrate, bitrates) + foreach (const QString &bitrate, bitrates) m_view.comboBitrates->addItem(bitrate); if (item->data(DefaultBitrateRole).canConvert(QVariant::String)) m_view.comboBitrates->setCurrentIndex(bitrates.indexOf(item->data(DefaultBitrateRole).toString())); } } else { m_view.comboBitrates->setEnabled(false); + m_view.bitrateLabel->setEnabled(false); + } + + // setup comboBox with audiobitrates + m_view.comboAudioBitrates->clear(); + if (params.contains("audiobitrate")) { + m_view.comboAudioBitrates->setEnabled(true); + m_view.audiobitrateLabel->setEnabled(true); + if ( item->data(AudioBitratesRole).canConvert(QVariant::StringList) && item->data(AudioBitratesRole).toStringList().count()) { + QStringList audiobitrates = item->data(AudioBitratesRole).toStringList(); + foreach (const QString &bitrate, audiobitrates) + m_view.comboAudioBitrates->addItem(bitrate); + if (item->data(DefaultAudioBitrateRole).canConvert(QVariant::String)) + m_view.comboAudioBitrates->setCurrentIndex(audiobitrates.indexOf(item->data(DefaultAudioBitrateRole).toString())); + } + } else { + m_view.comboAudioBitrates->setEnabled(false); + m_view.audiobitrateLabel->setEnabled(false); } - + m_view.checkTwoPass->setEnabled(params.contains("passes")); + m_view.encoder_threads->setEnabled(!params.contains("threads=")); + m_view.buttonRender->setEnabled(m_view.size_list->currentItem()->toolTip().isEmpty()); m_view.buttonGenerateScript->setEnabled(m_view.size_list->currentItem()->toolTip().isEmpty()); } @@ -1266,12 +1525,9 @@ void RenderWidget::reloadProfiles() parseProfiles(); } -void RenderWidget::parseProfiles(QString meta, QString group, QString profile) +void RenderWidget::parseProfiles(const QString &meta, const QString &group, const QString &profile) { - m_view.size_list->blockSignals(true); - m_view.format_list->blockSignals(true); - m_view.size_list->clear(); - m_view.format_list->clear(); + m_view.destination_list->blockSignals(true); m_view.destination_list->clear(); qDeleteAll(m_renderItems); qDeleteAll(m_renderCategory); @@ -1302,30 +1558,14 @@ void RenderWidget::parseProfiles(QString meta, QString group, QString profile) parseFile(exportFolder + filename, true); if (QFile::exists(exportFolder + "customprofiles.xml")) parseFile(exportFolder + "customprofiles.xml", true); - if (!meta.isEmpty()) { - m_view.destination_list->blockSignals(true); - m_view.destination_list->setCurrentIndex(m_view.destination_list->findData(meta)); - m_view.destination_list->blockSignals(false); - } - refreshCategory(); - QList child; - if (!group.isEmpty()) child = m_view.format_list->findItems(group, Qt::MatchExactly); - if (!child.isEmpty()) { - for (int i = 0; i < child.count(); i++) { - if (child.at(i)->data(MetaGroupRole).toString() == meta) { - m_view.format_list->setCurrentItem(child.at(i)); - break; - } - } - } - child.clear(); - m_view.size_list->blockSignals(false); - m_view.format_list->blockSignals(false); - if (!profile.isEmpty()) child = m_view.size_list->findItems(profile, Qt::MatchExactly); - if (!child.isEmpty()) m_view.size_list->setCurrentItem(child.at(0)); + int categoryIndex = m_view.destination_list->findData(meta); + if (categoryIndex == -1) categoryIndex = 0; + m_view.destination_list->setCurrentIndex(categoryIndex); + m_view.destination_list->blockSignals(false); + refreshCategory(group, profile); } -void RenderWidget::parseFile(QString exportFile, bool editable) +void RenderWidget::parseFile(const QString &exportFile, bool editable) { kDebug() << "// Parsing file: " << exportFile; kDebug() << "------------------------------"; @@ -1344,7 +1584,6 @@ void RenderWidget::parseFile(QString exportFile, bool editable) bool replaceLibfaacCodec = false; if (!acodecsList.contains("aac") && acodecsList.contains("libfaac")) replaceLibfaacCodec = true; - if (editable || groups.count() == 0) { QDomElement profiles = doc.documentElement(); if (editable && profiles.attribute("version", 0).toInt() < 1) { @@ -1355,7 +1594,7 @@ void RenderWidget::parseFile(QString exportFile, bool editable) newprofiles.setAttribute("version", 1); newdoc.appendChild(newprofiles); QDomNodeList profilelist = doc.elementsByTagName("profile"); - for (int i = 0; i < profilelist.count(); i++) { + for (int i = 0; i < profilelist.count(); ++i) { QString category = i18nc("Category Name", "Custom"); QString extension; QDomNode parent = profilelist.at(i).parentNode(); @@ -1406,7 +1645,7 @@ void RenderWidget::parseFile(QString exportFile, bool editable) QString prof_extension = profile.attribute("extension"); if (!prof_extension.isEmpty()) extension = prof_extension; bool exists = false; - for (int j = 0; j < m_renderCategory.count(); j++) { + for (int j = 0; j < m_renderCategory.count(); ++j) { if (m_renderCategory.at(j)->text() == category && m_renderCategory.at(j)->data(MetaGroupRole) == dest) { exists = true; break; @@ -1423,7 +1662,7 @@ void RenderWidget::parseFile(QString exportFile, bool editable) // allowing to override default profiles - for (int j = 0; j < m_renderItems.count(); j++) { + for (int j = 0; j < m_renderItems.count(); ++j) { if (m_renderItems.at(j)->text() == profileName && m_renderItems.at(j)->data(MetaGroupRole) == dest) { QListWidgetItem *duplicate = m_renderItems.takeAt(j); delete duplicate; @@ -1439,6 +1678,10 @@ void RenderWidget::parseFile(QString exportFile, bool editable) item->setData(RenderRole, "avformat"); item->setData(StandardRole, standard); item->setData(ParamsRole, params); + item->setData(BitratesRole, profile.attribute("bitrates").split(',', QString::SkipEmptyParts)); + item->setData(DefaultBitrateRole, profile.attribute("defaultbitrate")); + item->setData(AudioBitratesRole, profile.attribute("audiobitrates").split(',', QString::SkipEmptyParts)); + item->setData(DefaultAudioBitrateRole, profile.attribute("defaultaudiobitrate")); if (profile.hasAttribute("url")) item->setData(ExtraRole, profile.attribute("url")); if (editable) { item->setData(EditableRole, exportFile); @@ -1460,7 +1703,7 @@ void RenderWidget::parseFile(QString exportFile, bool editable) QString renderer; QString params; QString standard; - QString bitrates, defaultBitrate; + QString bitrates, defaultBitrate, audioBitrates, defaultAudioBitrate; KIcon icon; while (!groups.item(i).isNull()) { @@ -1486,7 +1729,7 @@ void RenderWidget::parseFile(QString exportFile, bool editable) extension = documentElement.attribute("extension", QString()); renderer = documentElement.attribute("renderer", QString()); bool exists = false; - for (int j = 0; j < m_renderCategory.count(); j++) { + for (int j = 0; j < m_renderCategory.count(); ++j) { if (m_renderCategory.at(j)->text() == groupName && m_renderCategory.at(j)->data(MetaGroupRole) == metagroupId) { exists = true; break; @@ -1509,6 +1752,8 @@ void RenderWidget::parseFile(QString exportFile, bool editable) standard = profileElement.attribute("standard"); bitrates = profileElement.attribute("bitrates"); defaultBitrate = profileElement.attribute("defaultbitrate"); + audioBitrates = profileElement.attribute("audiobitrates"); + defaultAudioBitrate = profileElement.attribute("defaultaudiobitrate"); params = profileElement.attribute("args"); if (replaceVorbisCodec && params.contains("acodec=vorbis")) { @@ -1531,39 +1776,40 @@ void RenderWidget::parseFile(QString exportFile, bool editable) item->setData(ParamsRole, params); item->setData(BitratesRole, bitrates.split(',', QString::SkipEmptyParts)); item->setData(DefaultBitrateRole, defaultBitrate); + item->setData(AudioBitratesRole, audioBitrates.split(',', QString::SkipEmptyParts)); + item->setData(DefaultAudioBitrateRole, defaultAudioBitrate); if (profileElement.hasAttribute("url")) item->setData(ExtraRole, profileElement.attribute("url")); - if (editable) item->setData(EditableRole, exportFile); + //if (editable) item->setData(EditableRole, exportFile); m_renderItems.append(item); n = n.nextSibling(); } - i++; + ++i; } } + + 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); - 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)); + if (!existing.isEmpty()) { + item = static_cast (existing.at(0)); + } else { + item = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << dest); 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->setData(1, ProgressRole, progress); + 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); @@ -1572,44 +1818,37 @@ 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->setSizeHint(1, QSize(m_view.running_jobs->columnWidth(1), fontMetrics().height() * 2)); + item = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << dest); } - 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)); } 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(); @@ -1617,9 +1856,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; @@ -1631,8 +1870,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); } @@ -1640,35 +1879,36 @@ 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()) { + /* + for (int i = 0; i < m_view.running_jobs->topLevelItemCount(); ++i) { + 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)); - } + }*/ } 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(); } @@ -1688,24 +1928,27 @@ void RenderWidget::parseScriptFiles() QString renderer; QString melt; QFile file(scriptpath.path()); + kDebug()<<"------------------\n"<setIcon(0, KIcon("dialog-cancel")); @@ -1717,27 +1960,24 @@ void RenderWidget::parseScriptFiles() item->setData(0, Qt::UserRole, '1'); } else item->setIcon(0, KIcon("application-x-executable-script")); item->setSizeHint(0, QSize(m_view.scripts_list->columnWidth(0), fontMetrics().height() * 2)); - item->setData(1, Qt::UserRole, KUrl(target).path()); + item->setData(1, Qt::UserRole, KUrl(QUrl::fromEncoded(target.toUtf8())).pathOrUrl()); item->setData(1, Qt::UserRole + 1, scriptpath.path()); } -// bool activate = false; QTreeWidgetItem *script = m_view.scripts_list->topLevelItem(0); if (script) { m_view.scripts_list->setCurrentItem(script); script->setSelected(true); -// activate = true; } -// m_view.start_script->setEnabled(activate); -// m_view.delete_script->setEnabled(activate); } void RenderWidget::slotCheckScript() { QTreeWidgetItem *current = m_view.scripts_list->currentItem(); - if (current == NULL) return; + if (current == NULL) + return; m_view.start_script->setEnabled(current->data(0, Qt::UserRole).toString().isEmpty()); m_view.delete_script->setEnabled(true); - for (int i = 0; i < m_view.scripts_list->topLevelItemCount(); i++) { + for (int i = 0; i < m_view.scripts_list->topLevelItemCount(); ++i) { current = m_view.scripts_list->topLevelItem(i); if (current == m_view.scripts_list->currentItem()) { current->setSizeHint(1, QSize(m_view.scripts_list->columnWidth(1), fontMetrics().height() * 3)); @@ -1747,30 +1987,33 @@ void RenderWidget::slotCheckScript() void RenderWidget::slotStartScript() { - QTreeWidgetItem *item = m_view.scripts_list->currentItem(); + RenderJobItem* item = static_cast (m_view.scripts_list->currentItem()); if (item) { + kDebug() << "// STARTING SCRIPT: "<text(1); 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 = NULL; 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 || renderItem->status() == WAITINGJOB) { 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"; - renderItem->setData(2, Qt::UserRole, 0); - renderItem->setData(1, Qt::UserRole + 2, WAITINGJOB); + else if (renderItem->type() != ScriptRenderType) { + delete renderItem; + renderItem = NULL; + } + } + if (!renderItem) renderItem = new RenderJobItem(m_view.running_jobs, QStringList() << QString() << destination, ScriptRenderType); + renderItem->setData(1, ProgressRole, 0); + 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); } @@ -1797,10 +2040,8 @@ void RenderWidget::slotHideLog() m_view.error_box->setVisible(false); } -void RenderWidget::setRenderProfile(QMap props) +void RenderWidget::setRenderProfile(const QMap &props) { - m_view.destination_list->blockSignals(true); - m_view.format_list->blockSignals(true); m_view.scanning_list->setCurrentIndex(props.value("renderscanning").toInt()); int exportAudio = props.value("renderexportaudio").toInt(); switch (exportAudio) { @@ -1831,44 +2072,24 @@ void RenderWidget::setRenderProfile(QMap props) slotUpdateGuideBox(); QString url = props.value("renderurl"); - if (!url.isEmpty()) m_view.out_file->setUrl(KUrl(url)); + if (!url.isEmpty()) + m_view.out_file->setUrl(KUrl(url)); // set destination - for (int i = 0; i < m_view.destination_list->count(); i++) { - if (m_view.destination_list->itemData(i, Qt::UserRole) == props.value("renderdestination")) { - m_view.destination_list->setCurrentIndex(i); - break; - } - } - refreshCategory(); - - // set category - QString group = props.value("rendercategory"); - if (!group.isEmpty()) { - QList childs = m_view.format_list->findItems(group, Qt::MatchExactly); - if (!childs.isEmpty()) { - m_view.format_list->setCurrentItem(childs.at(0)); - m_view.format_list->scrollToItem(childs.at(0)); - } - refreshView(); - } - - // set profile - QList childs = m_view.size_list->findItems(props.value("renderprofile"), Qt::MatchExactly); - if (!childs.isEmpty()) { - m_view.size_list->setCurrentItem(childs.at(0)); - m_view.size_list->scrollToItem(childs.at(0)); - } - //refreshView(); + int categoryIndex = m_view.destination_list->findData(props.value("renderdestination")); + if (categoryIndex == -1) categoryIndex = 0; + m_view.destination_list->blockSignals(true); + m_view.destination_list->setCurrentIndex(categoryIndex); m_view.destination_list->blockSignals(false); - m_view.format_list->blockSignals(false); - + + // Clear previous error messages + refreshCategory(props.value("rendercategory"), props.value("renderprofile")); } bool RenderWidget::startWaitingRenderJobs() { m_blockProcessing = true; - QString autoscriptFile = getFreeScriptName("auto"); + QString autoscriptFile = getFreeScriptName(KUrl(), "auto"); QFile file(autoscriptFile); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { kWarning() << "////// ERROR writing to file: " << autoscriptFile; @@ -1878,19 +2099,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() == DirectRenderType) { // 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() == ScriptRenderType){ // 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"; @@ -1906,22 +2127,26 @@ bool RenderWidget::startWaitingRenderJobs() return true; } -QString RenderWidget::getFreeScriptName(const QString &prefix) +QString RenderWidget::getFreeScriptName(const KUrl &projectName, const QString &prefix) { int ix = 0; QString scriptsFolder = m_projectFolder + "scripts/"; KStandardDirs::makeDir(scriptsFolder); QString path; + QString fileName; + if (projectName.isEmpty()) fileName = i18n("script"); + else fileName = projectName.fileName().section('.', 0, -2) + "_"; while (path.isEmpty() || QFile::exists(path)) { - ix++; - path = scriptsFolder + prefix + i18n("script") + QString::number(ix).rightJustified(3, '0', false) + ".sh"; + ++ix; + path = scriptsFolder + prefix + fileName + QString::number(ix).rightJustified(3, '0', false) + ".sh"; } return path; } 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); @@ -1938,12 +2163,37 @@ void RenderWidget::missingClips(bool hasMissing) void RenderWidget::errorMessage(const QString &message) { if (!message.isEmpty()) { +#if KDE_IS_VERSION(4,7,0) + m_infoMessage->setMessageType(KMessageWidget::Warning); + m_infoMessage->setText(message); +#if KDE_IS_VERSION(4,10,0) + m_infoMessage->animatedShow(); +#else + // Workaround KDE bug in KMessageWidget + QTimer::singleShot(0, m_infoMessage, SLOT(animatedShow())); +#endif +#else m_view.errorLabel->setText(message); m_view.errorBox->setHidden(false); +#endif } else { - m_view.errorBox->setHidden(true); - m_view.errorLabel->setText(QString()); +#if KDE_IS_VERSION(4,7,0) + if (m_view.tabWidget->currentIndex() == 0 && m_infoMessage->isVisible()) { +#if KDE_IS_VERSION(4,10,0) + m_infoMessage->animatedHide(); +#else + QTimer::singleShot(0, m_infoMessage, SLOT(animatedHide())); +#endif + } else { + // Seems like animated hide does not work when page is not visible + m_infoMessage->hide(); + } +#else + m_view.errorBox->setHidden(true); + m_view.errorLabel->setText(QString()); +#endif + } } @@ -2006,3 +2256,31 @@ bool RenderWidget::proxyRendering() { return m_view.proxy_render->isChecked(); } + +void RenderWidget::setRescaleEnabled(bool enable) +{ + for (int i = 0; i < m_view.rescale_box->layout()->count(); ++i) { + if (m_view.rescale_box->itemAt(i)->widget()) + m_view.rescale_box->itemAt(i)->widget()->setEnabled(enable); + } +} + +void RenderWidget::keyPressEvent(QKeyEvent *e) { + if(e->key()==Qt::Key_Return || e->key()==Qt::Key_Enter) { + switch (m_view.tabWidget->currentIndex()) { + case 1: + if (m_view.start_job->isEnabled()) slotStartCurrentJob(); + break; + case 2: + if (m_view.start_script->isEnabled()) slotStartScript(); + break; + default: + if (m_view.buttonRender->isEnabled()) slotPrepareExport(); + break; + } + } + else QDialog::keyPressEvent(e); +} + + +#include "renderwidget.moc"