From: Jean-Baptiste Mardelle Date: Fri, 16 Jan 2009 17:43:39 +0000 (+0000) Subject: Updated the rendering dialog: X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=8bf1b4441dfc6e518764ce687f149aa6677ee715;p=kdenlive Updated the rendering dialog: * add option to disable audio * Re-organise categories * Improved info in the "Running jobs" widget, including crash log svn path=/branches/KDE4/; revision=2927 --- diff --git a/export/profiles.xml b/export/profiles.xml index c13492d9..594fe5ab 100644 --- a/export/profiles.xml +++ b/export/profiles.xml @@ -42,9 +42,10 @@ +DVD - - + + @@ -160,6 +161,7 @@ + Media players @@ -169,6 +171,7 @@ + Web sites @@ -181,13 +184,15 @@ - - - - + Audio only + + + + + Lossless / HQ diff --git a/renderer/renderjob.cpp b/renderer/renderjob.cpp index 7c2448b6..72339e1b 100644 --- a/renderer/renderjob.cpp +++ b/renderer/renderjob.cpp @@ -90,7 +90,8 @@ void RenderJob::slotAbort() { if (m_kdenliveinterface) { m_dbusargs[1] = -3; - m_kdenliveinterface->callWithArgumentList(QDBus::NoBlock, "setRenderingProgress", m_dbusargs); + m_dbusargs.append(QString()); + m_kdenliveinterface->callWithArgumentList(QDBus::NoBlock, "setRenderingFinished", m_dbusargs); } if (m_jobUiserver) m_jobUiserver->call("terminate", QString()); if (m_erase) { @@ -107,6 +108,7 @@ void RenderJob::slotAbort() { void RenderJob::receivedStderr() { QString result = QString(m_renderProcess->readAllStandardError()).simplified(); + if (!result.startsWith("Current Frame")) m_errorMessage.append(result + "
"); m_logstream << "ReceivedStderr from inigo: " << result << endl; result = result.section(" ", -1); int pro = result.toInt(); @@ -203,8 +205,9 @@ void RenderJob::slotIsOver(int exitcode, QProcess::ExitStatus status) { if (status == QProcess::CrashExit) { // rendering crashed if (m_kdenliveinterface) { - m_dbusargs[1] = -2; - m_kdenliveinterface->callWithArgumentList(QDBus::NoBlock, "setRenderingProgress", m_dbusargs); + m_dbusargs[1] = (int) - 2; + m_dbusargs.append(m_errorMessage); + m_kdenliveinterface->callWithArgumentList(QDBus::NoBlock, "setRenderingFinished", m_dbusargs); } QStringList args; args << "--error" << tr("Rendering of %1 aborted, resulting video will probably be corrupted.").arg(m_dest); @@ -213,8 +216,9 @@ void RenderJob::slotIsOver(int exitcode, QProcess::ExitStatus status) { QProcess::startDetached("kdialog", args); } else { if (m_kdenliveinterface) { - m_dbusargs[1] = -1; - m_kdenliveinterface->callWithArgumentList(QDBus::NoBlock, "setRenderingProgress", m_dbusargs); + m_dbusargs[1] = (int) - 1; + m_dbusargs.append(QString()); + m_kdenliveinterface->callWithArgumentList(QDBus::NoBlock, "setRenderingFinished", m_dbusargs); } QDBusConnectionInterface* interface = QDBusConnection::sessionBus().interface(); if (interface && interface->isServiceRegistered("org.kde.knotify")) { diff --git a/renderer/renderjob.h b/renderer/renderjob.h index 3683a961..5a3887ec 100644 --- a/renderer/renderjob.h +++ b/renderer/renderjob.h @@ -47,6 +47,7 @@ private: QString m_dest; int m_progress; QProcess *m_renderProcess; + QString m_errorMessage; QString m_prog; QString m_player; QStringList m_args; diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg index 6237aa20..8685e4d7 100644 --- a/src/kdenlivesettings.kcfg +++ b/src/kdenlivesettings.kcfg @@ -417,11 +417,6 @@ false - - - false - - diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2e66714e..2985814e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1443,6 +1443,7 @@ void MainWindow::slotDoRender(const QString &dest, const QString &render, const } if (!QFile::exists(KdenliveSettings::rendererpath())) { KMessageBox::sorry(this, i18n("Cannot find the inigo program required for rendering (part of Mlt)")); + setRenderingProgress(dest, -3); return; } args << KdenliveSettings::rendererpath() << m_activeDocument->profilePath() << render << videoPlayer; @@ -1471,6 +1472,10 @@ void MainWindow::setRenderingProgress(const QString &url, int progress) { if (m_renderWidget) m_renderWidget->setRenderJob(url, progress); } +void MainWindow::setRenderingFinished(const QString &url, int status, const QString &error) { + if (m_renderWidget) m_renderWidget->setRenderStatus(url, status, error); +} + void MainWindow::slotUpdateMousePosition(int pos) { if (m_activeDocument) switch (m_timecodeFormat->currentIndex()) { diff --git a/src/mainwindow.h b/src/mainwindow.h index 57d87fe6..de974fd8 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -197,6 +197,7 @@ public slots: void openFile(const KUrl &url); void slotGotProgressInfo(const QString &message, int progress); Q_SCRIPTABLE void setRenderingProgress(const QString &url, int progress); + Q_SCRIPTABLE void setRenderingFinished(const QString &url, int status, const QString &error); private slots: void newFile(bool showProjectSettings = true); diff --git a/src/org.kdenlive.MainWindow.xml b/src/org.kdenlive.MainWindow.xml index e7cdc107..36f00658 100644 --- a/src/org.kdenlive.MainWindow.xml +++ b/src/org.kdenlive.MainWindow.xml @@ -8,5 +8,10 @@ + + + + + diff --git a/src/renderwidget.cpp b/src/renderwidget.cpp index 0a9a5c88..50d21b91 100644 --- a/src/renderwidget.cpp +++ b/src/renderwidget.cpp @@ -38,6 +38,7 @@ const int StandardRole = GroupRole + 2; const int RenderRole = GroupRole + 3; const int ParamsRole = GroupRole + 4; const int EditableRole = GroupRole + 5; +const int MetaGroupRole = GroupRole + 6; RenderWidget::RenderWidget(QWidget * parent): QDialog(parent) { m_view.setupUi(this); @@ -59,9 +60,7 @@ RenderWidget::RenderWidget(QWidget * parent): QDialog(parent) { m_view.buttonInfo->setDown(true); } else m_view.advanced_params->hide(); - m_view.experimentalrender->setChecked(KdenliveSettings::experimentalrender()); - - m_view.experimentalrender->setToolTip(i18n("Changing the size of video when rendering\nis not fully supported, you may have problems\nwith some effects or title clips, so the export\nprofiles that resize your video are marked as\nexperimental")); + parseProfiles(); connect(m_view.buttonInfo, SIGNAL(clicked()), this, SLOT(showInfoPanel())); @@ -72,6 +71,8 @@ RenderWidget::RenderWidget(QWidget * parent): QDialog(parent) { connect(m_view.abort_job, SIGNAL(clicked()), this, SLOT(slotAbortCurrentJob())); connect(m_view.buttonClose, SIGNAL(clicked()), this, SLOT(hide())); connect(m_view.buttonClose2, SIGNAL(clicked()), this, SLOT(hide())); + connect(m_view.rescale, SIGNAL(toggled(bool)), m_view.rescale_size, SLOT(setEnabled(bool))); + connect(m_view.destination_list, SIGNAL(activated(int)), this, SLOT(refreshView())); connect(m_view.out_file, SIGNAL(textChanged(const QString &)), this, SLOT(slotUpdateButtons())); connect(m_view.format_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshView())); connect(m_view.size_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshParams())); @@ -84,11 +85,14 @@ RenderWidget::RenderWidget(QWidget * parent): QDialog(parent) { connect(m_view.guide_start, SIGNAL(activated(int)), this, SLOT(slotCheckEndGuidePosition())); connect(m_view.format_selection, SIGNAL(activated(int)), this, SLOT(refreshView())); - connect(m_view.experimentalrender, SIGNAL(stateChanged(int)), this, SLOT(slotUpdateExperimentalRendering())); m_view.buttonStart->setEnabled(false); + m_view.rescale_size->setEnabled(false); m_view.guides_box->setVisible(false); - parseProfiles(); + m_view.open_dvd->setVisible(false); + m_view.open_browser->setVisible(false); + m_view.error_box->setVisible(false); + m_view.splitter->setStretchFactor(1, 5); m_view.splitter->setStretchFactor(0, 2); @@ -108,12 +112,6 @@ RenderWidget::RenderWidget(QWidget * parent): QDialog(parent) { focusFirstVisibleItem(); } -void RenderWidget::slotUpdateExperimentalRendering() { - KdenliveSettings::setExperimentalrender(m_view.experimentalrender->isChecked()); - refreshView(); -} - - void RenderWidget::showInfoPanel() { if (m_view.advanced_params->isVisible()) { m_view.advanced_params->setVisible(false); @@ -396,7 +394,9 @@ void RenderWidget::focusFirstVisibleItem() { void RenderWidget::slotExport() { QListWidgetItem *item = m_view.size_list->currentItem(); if (!item) return; - QFile f(m_view.out_file->url().path()); + const QString dest = m_view.out_file->url().path(); + if (dest.isEmpty()) return; + QFile f(dest); if (f.exists()) { if (KMessageBox::warningYesNo(this, i18n("File already exists. Do you want to overwrite it ?")) != KMessageBox::Yes) return; @@ -415,27 +415,50 @@ void RenderWidget::slotExport() { endPos = m_view.guide_end->itemData(m_view.guide_end->currentIndex()).toDouble(); } QString renderArgs = m_view.advanced_params->toPlainText(); - renderArgs.replace("%width", QString::number(m_profile.width)); - renderArgs.replace("%height", QString::number(m_profile.height)); + + // Adjust frame scale + int width; + int height; + if (m_view.rescale->isChecked() && m_view.rescale->isEnabled()) { + width = m_view.rescale_size->text().section('x', 0, 0).toInt(); + height = m_view.rescale_size->text().section('x', 1, 1).toInt(); + } else { + width = m_profile.width; + height = m_profile.height; + } + renderArgs.replace("%width", QString::number(width)); + renderArgs.replace("%height", QString::number(height)); renderArgs.replace("%dar", "@" + QString::number(m_profile.display_aspect_num) + "/" + QString::number(m_profile.display_aspect_den)); - if (m_view.force_progressive->checkState() == Qt::Checked) renderArgs.append(" progressive=1"); - else if (m_view.force_progressive->checkState() == Qt::Unchecked) renderArgs.append(" progressive=0"); + + // Adjust scanning + if (m_view.scanning_list->currentIndex() == 1) renderArgs.append(" progressive=1"); + else if (m_view.scanning_list->currentIndex() == 2) renderArgs.append(" progressive=0"); + + // disable audio if requested + if (!m_view.export_audio->isChecked()) + renderArgs.append(" an=1 "); // Check if the rendering profile is different from project profile, // in which case we need to use the producer_comsumer from MLT bool resizeProfile = false; - QString std = item->data(ParamsRole).toString(); + QString std = renderArgs; if (resizeProfile == false && std.contains(" s=")) { QString subsize = std.section(" s=", 1, 1); subsize = subsize.section(' ', 0, 0).toLower(); - if (subsize != "%widthx%height") { - const QString currentSize = QString::number(m_profile.width) + 'x' + QString::number(m_profile.height); - if (subsize != currentSize) resizeProfile = true; - } + const QString currentSize = QString::number(m_profile.width) + 'x' + QString::number(m_profile.height); + if (subsize != currentSize) resizeProfile = true; } - emit doRender(m_view.out_file->url().path(), item->data(RenderRole).toString(), overlayargs, renderArgs.simplified().split(' '), m_view.render_zone->isChecked(), m_view.play_after->isChecked(), startPos, endPos, resizeProfile); + // insert item in running jobs list + QTreeWidgetItem *renderItem; + QList existing = m_view.running_jobs->findItems(dest, Qt::MatchExactly); + if (!existing.isEmpty()) renderItem = existing.at(0); + else renderItem = new QTreeWidgetItem(m_view.running_jobs, QStringList() << dest << QString()); + // Set rendering type + renderItem->setData(0, Qt::UserRole, m_view.size_list->currentItem()->data(MetaGroupRole).toString()); + + emit doRender(dest, item->data(RenderRole).toString(), overlayargs, renderArgs.simplified().split(' '), m_view.render_zone->isChecked(), m_view.play_after->isChecked(), startPos, endPos, resizeProfile); m_view.tabWidget->setCurrentIndex(1); } @@ -444,25 +467,58 @@ void RenderWidget::setProfile(MltVideoProfile profile) { //WARNING: this way to tell the video standard is a bit hackish... if (m_profile.description.contains("pal", Qt::CaseInsensitive) || m_profile.description.contains("25", Qt::CaseInsensitive) || m_profile.description.contains("50", Qt::CaseInsensitive)) m_view.format_selection->setCurrentIndex(0); else m_view.format_selection->setCurrentIndex(1); - m_view.force_progressive->setCheckState(Qt::PartiallyChecked); + m_view.scanning_list->setCurrentIndex(0); refreshView(); } void RenderWidget::refreshView() { m_view.size_list->blockSignals(true); - QListWidgetItem *item = m_view.format_list->currentItem(); - if (!item) { - m_view.format_list->setCurrentRow(0); + 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); + else m_view.open_dvd->setVisible(false); + if (destination == "websites") m_view.open_browser->setVisible(true); + else m_view.open_browser->setVisible(false); + if (!destination.isEmpty() && QString("dvd websites audioonly").contains(destination)) + m_view.rescale->setEnabled(false); + else m_view.rescale->setEnabled(true); + // hide groups that are not in the correct destination + for (int i = 0; i < m_view.format_list->count(); i++) { + sizeItem = m_view.format_list->item(i); + if (sizeItem->data(MetaGroupRole).toString() == destination) + sizeItem->setHidden(false); + else sizeItem->setHidden(true); + } + + // activate first visible item + QListWidgetItem * item = m_view.format_list->currentItem(); + if (!item || item->isHidden()) { + for (int i = 0; i < m_view.format_list->count(); i++) { + if (!m_view.format_list->item(i)->isHidden()) { + m_view.format_list->setCurrentRow(i); + break; + } + } item = m_view.format_list->currentItem(); } if (!item) return; + int count = 0; + for (int i = 0; i < m_view.format_list->count() && count < 2; i++) { + if (!m_view.format_list->isRowHidden(i)) count++; + } + if (count > 1) m_view.format_list->setVisible(true); + else m_view.format_list->setVisible(false); QString std; QString group = item->text(); - QListWidgetItem *sizeItem; bool firstSelected = false; const QStringList formatsList = KdenliveSettings::supportedformats(); const QStringList vcodecsList = KdenliveSettings::videocodecs(); const QStringList acodecsList = KdenliveSettings::audiocodecs(); + for (int i = 0; i < m_view.size_list->count(); i++) { sizeItem = m_view.size_list->item(i); if (sizeItem->data(GroupRole) == group) { @@ -475,18 +531,7 @@ void RenderWidget::refreshView() { if (!firstSelected) m_view.size_list->setCurrentItem(sizeItem); firstSelected = true; } - if (!KdenliveSettings::experimentalrender() && !sizeItem->isHidden()) { - // hide experimental codecs (which do resize the video) - std = sizeItem->data(ParamsRole).toString(); - if (std.contains(" s=")) { - QString subsize = std.section(" s=", 1, 1); - subsize = subsize.section(' ', 0, 0).toLower(); - if (subsize != "%widthx%height") { - const QString currentSize = QString::number(m_profile.width) + 'x' + QString::number(m_profile.height); - if (subsize != currentSize) sizeItem->setHidden(true); - } - } - } + if (!sizeItem->isHidden()) { // Make sure the selected profile uses an installed avformat codec / format std = sizeItem->data(ParamsRole).toString(); @@ -571,6 +616,8 @@ void RenderWidget::refreshParams() { void RenderWidget::parseProfiles(QString group, QString profile) { m_view.size_list->clear(); m_view.format_list->clear(); + m_view.destination_list->clear(); + m_view.destination_list->addItem(KIcon("video-x-generic"), i18n("File rendering")); QString exportFile = KStandardDirs::locate("appdata", "export/profiles.xml"); parseFile(exportFile, false); exportFile = KStandardDirs::locateLocal("appdata", "export/customprofiles.xml"); @@ -605,17 +652,39 @@ void RenderWidget::parseFile(QString exportFile, bool editable) { QString renderer; QString params; QString standard; + KIcon icon; QListWidgetItem *item; while (!groups.item(i).isNull()) { documentElement = groups.item(i).toElement(); + QDomNode gname = documentElement.elementsByTagName("groupname").at(0); + QString metagroupName; + QString metagroupId; + if (!gname.isNull()) { + metagroupName = gname.firstChild().nodeValue(); + metagroupId = gname.toElement().attribute("id"); + if (!metagroupName.isEmpty() && !m_view.destination_list->contains(metagroupName)) { + if (metagroupId == "dvd") icon = KIcon("media-optical"); + else if (metagroupId == "audioonly") icon = KIcon("audio-x-generic"); + else if (metagroupId == "websites") icon = KIcon("applications-internet"); + else if (metagroupId == "mediaplayers") icon = KIcon("applications-multimedia"); + else if (metagroupId == "lossless") icon = KIcon("drive-harddisk"); + m_view.destination_list->addItem(icon, i18n(metagroupName.toUtf8().data()), metagroupId); + } + } groupName = documentElement.attribute("name", QString::null); extension = documentElement.attribute("extension", QString::null); renderer = documentElement.attribute("renderer", QString::null); - if (m_view.format_list->findItems(groupName, Qt::MatchExactly).isEmpty()) - new QListWidgetItem(groupName, m_view.format_list); + if (m_view.format_list->findItems(groupName, Qt::MatchExactly).isEmpty()) { + item = new QListWidgetItem(groupName, m_view.format_list); + item->setData(MetaGroupRole, metagroupId); + } QDomNode n = groups.item(i).firstChild(); while (!n.isNull()) { + if (n.toElement().tagName() != "profile") { + n = n.nextSibling(); + continue; + } profileElement = n.toElement(); profileName = profileElement.attribute("name"); standard = profileElement.attribute("standard"); @@ -624,6 +693,7 @@ void RenderWidget::parseFile(QString exportFile, bool editable) { if (!prof_extension.isEmpty()) extension = prof_extension; item = new QListWidgetItem(profileName, m_view.size_list); item->setData(GroupRole, groupName); + item->setData(MetaGroupRole, metagroupId); item->setData(ExtensionRole, extension); item->setData(RenderRole, renderer); item->setData(StandardRole, standard); @@ -637,38 +707,37 @@ void RenderWidget::parseFile(QString exportFile, bool editable) { } void RenderWidget::setRenderJob(const QString &dest, int progress) { + QTreeWidgetItem *item; QList existing = m_view.running_jobs->findItems(dest, Qt::MatchExactly); - if (!existing.isEmpty()) { - if (progress == -1) { - // Job finished successfully - existing.at(0)->setIcon(0, KIcon("dialog-ok")); - existing.at(0)->setData(1, Qt::UserRole, 100); - } else if (progress == -2) { - // Rendering crashed - existing.at(0)->setIcon(0, KIcon("dialog-close")); - existing.at(0)->setData(1, Qt::UserRole, 0); - } else if (progress == -3) { - // User aborted job - existing.at(0)->setIcon(0, KIcon("dialog-close")); - existing.at(0)->setData(1, Qt::UserRole, 100); - } else existing.at(0)->setData(1, Qt::UserRole, progress); - return; - } - QTreeWidgetItem *item = new QTreeWidgetItem(m_view.running_jobs, QStringList() << dest << QString()); - if (progress == -1) { + if (!existing.isEmpty()) item = existing.at(0); + else item = new QTreeWidgetItem(m_view.running_jobs, QStringList() << dest << QString()); + item->setData(1, Qt::UserRole, progress); + if (progress == 0) item->setIcon(0, KIcon("system-run")); +} + +void RenderWidget::setRenderStatus(const QString &dest, int status, const QString &error) { + QTreeWidgetItem *item; + QList existing = m_view.running_jobs->findItems(dest, Qt::MatchExactly); + if (!existing.isEmpty()) item = existing.at(0); + else item = new QTreeWidgetItem(m_view.running_jobs, QStringList() << dest << QString()); + if (status == -1) { // Job finished successfully item->setIcon(0, KIcon("dialog-ok")); item->setData(1, Qt::UserRole, 100); - } else if (progress == -2) { + } else if (status == -2) { // Rendering crashed item->setIcon(0, KIcon("dialog-close")); item->setData(1, Qt::UserRole, 0); - } else if (progress == -3) { + 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->setIcon(0, KIcon("dialog-close")); + item->setIcon(0, KIcon("dialog-cancel")); item->setData(1, Qt::UserRole, 100); - } else item->setData(1, Qt::UserRole, progress); - + item->setData(1, Qt::UserRole + 1, i18n("Aborted by user")); + } } void RenderWidget::slotAbortCurrentJob() { diff --git a/src/renderwidget.h b/src/renderwidget.h index 24e82aa1..1a0015a0 100644 --- a/src/renderwidget.h +++ b/src/renderwidget.h @@ -73,6 +73,7 @@ public: void focusFirstVisibleItem(); void setProfile(MltVideoProfile profile); void setRenderJob(const QString &dest, int progress = 0); + void setRenderStatus(const QString &dest, int status, const QString &error); private slots: void slotUpdateButtons(); @@ -86,7 +87,6 @@ private slots: void slotCheckStartGuidePosition(); void slotCheckEndGuidePosition(); void showInfoPanel(); - void slotUpdateExperimentalRendering(); void slotAbortCurrentJob(); private: diff --git a/src/widgets/renderwidget_ui.ui b/src/widgets/renderwidget_ui.ui index e9841e9a..87f9e02f 100644 --- a/src/widgets/renderwidget_ui.ui +++ b/src/widgets/renderwidget_ui.ui @@ -5,14 +5,14 @@ 0 0 - 444 - 407 + 415 + 512 Dialog - + 0 @@ -25,142 +25,210 @@ Render Project - - + + + + + Destination + + + + + + + Output file - + - - - + + + + I + + + + + + + Format + + + + + + + Qt::Horizontal + + + + 124 + 23 + + + + + + + + + PAL + + + + + NTSC + + + + + + + + E + + + + + + + S + + + + + + + D + + + + + + + Qt::Vertical + + + + Qt::Horizontal + + + + + 0 + 0 + + + + + + + 0 + 0 + + + + + + + true + + + false + + + + + + + + Scanning + + + + + + + + Auto + + + + + Force Progressive + + + + + Force Interlaced + + + + + + + + Export audio + + + true + + + + + + + Rescale + + + + + + + 0099\x0099; + + + 320x240 + + - - - - - Format - - - - - - - Qt::Horizontal - - - - 165 - 24 - - - - - - - - - PAL - - - - - NTSC - - - - - - - - E - - - - - - - I - - - - - - - S - - - - - - - D - - - - - - - Qt::Vertical - - - - Qt::Horizontal - - - - - 0 - 0 - - - - - - - 0 - 0 - - - - - - - true - - - false - - - - - - - - Show experimental formats - - - - - - - Progressive - - - true - - - - - + + + + Timecode overlay + + + + + + + Open Dvd wizard after rendering + + + + + + + Open browser window after export + + + + + + + Play after render + + + + @@ -188,7 +256,7 @@ - + @@ -231,32 +299,14 @@ - - - - - - Play after render - - - - - - - Timecode overlay - - - - - - + Start Rendering - + Qt::Horizontal @@ -269,7 +319,7 @@ - + Close @@ -282,31 +332,69 @@ Current jobs - + - - - false - - - true - - - false - - - 2 + + + Qt::Vertical - - - File + + + + 0 + 0 + - - - - Progress + + false + + + true + + + false + + + 2 + + + + File + + + + + Progress + + + + + + + 0 + 0 + + + + - + + + + + Error Log + + + + + + + true + + + + + @@ -337,6 +425,11 @@ + running_jobs + abort_job + buttonClose2 + error_box + splitter_2 @@ -358,6 +451,11 @@ QPushButton
kpushbutton.h
+ + KRestrictedLine + KLineEdit +
krestrictedline.h
+
KTextEdit QTextEdit