summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/qmlviewer/main.cpp15
-rw-r--r--tools/qmlviewer/qmlviewer.cpp217
-rw-r--r--tools/qmlviewer/qmlviewer.h17
-rw-r--r--tools/qmlviewer/qmlviewer.pro5
-rw-r--r--tools/qmlviewer/recopts.ui338
5 files changed, 562 insertions, 30 deletions
diff --git a/tools/qmlviewer/main.cpp b/tools/qmlviewer/main.cpp
index 8784ae0..e5f5e05 100644
--- a/tools/qmlviewer/main.cpp
+++ b/tools/qmlviewer/main.cpp
@@ -32,7 +32,7 @@ void usage()
qWarning(" - png file for raw frames");
qWarning(" - 'ffmpeg' for other formats");
qWarning(" -recorddither ordered|threshold|floyd .... set GIF dither recording mode");
- qWarning(" -recordperiod <milliseconds> ............. set time between recording frames");
+ qWarning(" -recordrate <fps> ........................ set recording frame rate");
qWarning(" -record arg .............................. add a recording process argument");
qWarning(" -autorecord [from-]<tomilliseconds> ...... set recording to start and stop");
qWarning(" -devicekeys .............................. use numeric keys (see F1)");
@@ -63,7 +63,7 @@ int main(int argc, char ** argv)
bool frameless = false;
QString fileName;
- int period = 0;
+ double fps = 0;
int autorecord_from = 0;
int autorecord_to = 0;
QString dither = "none";
@@ -83,8 +83,8 @@ int main(int argc, char ** argv)
skin = QString(argv[++i]);
} else if (arg == "-netcache") {
cache = QString(argv[++i]).toInt();
- } else if (arg == "-recordperiod") {
- period = QString(argv[++i]).toInt();
+ } else if (arg == "-recordrate") {
+ fps = QString(argv[++i]).toDouble();
} else if (arg == "-recordfile") {
recordfile = QString(argv[++i]);
} else if (arg == "-record") {
@@ -127,8 +127,8 @@ int main(int argc, char ** argv)
viewer.addLibraryPath(lib);
viewer.setNetworkCacheSize(cache);
viewer.setRecordFile(recordfile);
- if (period>0)
- viewer.setRecordPeriod(period);
+ if (fps>0)
+ viewer.setRecordRate(fps);
if (autorecord_to)
viewer.setAutoRecord(autorecord_from,autorecord_to);
if (!skin.isEmpty() && QDir(skin).exists())
@@ -136,7 +136,8 @@ int main(int argc, char ** argv)
if (devkeys)
viewer.setDeviceKeys(true);
viewer.setRecordDither(dither);
- viewer.setRecordArgs(recordargs);
+ if (recordargs.count())
+ viewer.setRecordArgs(recordargs);
if (!fileName.isEmpty()) {
viewer.openQml(fileName);
viewer.show();
diff --git a/tools/qmlviewer/qmlviewer.cpp b/tools/qmlviewer/qmlviewer.cpp
index 95cd24b..643760b 100644
--- a/tools/qmlviewer/qmlviewer.cpp
+++ b/tools/qmlviewer/qmlviewer.cpp
@@ -12,6 +12,7 @@
****************************************************************************/
#include <qfxview.h>
+#include "ui_recopts.h"
#include "qmlviewer.h"
#include <QtDeclarative/qmlcontext.h>
@@ -30,6 +31,7 @@
#include <QWidget>
#include <QApplication>
#include <QDir>
+#include <QTextBrowser>
#include <QFile>
#include <QFileInfo>
#include <QVBoxLayout>
@@ -127,6 +129,79 @@ void PreviewDeviceSkin::slotPopupMenu()
menu->exec(QCursor::pos());
}
+static struct { const char *name, *args; } ffmpegprofiles[] = {
+ {"Maximum Quality", "-sameq"},
+ {"High Quality", "-qcomp 0.75"},
+ {"Medium Quality", "-qcomp 0.5"},
+ {"Low Quality", "-qcomp 0.2"},
+ {"Custom ffmpeg arguments", ""},
+ {0,0}
+};
+
+class RecordingDialog : public QDialog, public Ui::RecordingOptions {
+ Q_OBJECT
+
+public:
+ RecordingDialog(QWidget *parent) : QDialog(parent)
+ {
+ setupUi(this);
+ hz->setValidator(new QDoubleValidator(hz));
+ for (int i=0; ffmpegprofiles[i].name; ++i) {
+ profile->addItem(ffmpegprofiles[i].name);
+ }
+ }
+
+ void setArguments(QString a)
+ {
+ int i;
+ for (i=0; ffmpegprofiles[i].args[0]; ++i) {
+ if (ffmpegprofiles[i].args == a) {
+ profile->setCurrentIndex(i);
+ args->setText(QLatin1String(ffmpegprofiles[i].args));
+ return;
+ }
+ }
+ customargs = a;
+ args->setText(a);
+ profile->setCurrentIndex(i);
+ }
+
+ QString arguments() const
+ {
+ int i = profile->currentIndex();
+ return ffmpegprofiles[i].args[0] ? QLatin1String(ffmpegprofiles[i].args) : customargs;
+ }
+
+private slots:
+ void pickProfile(int i)
+ {
+ if (ffmpegprofiles[i].args[0]) {
+ args->setText(QLatin1String(ffmpegprofiles[i].args));
+ } else {
+ args->setText(customargs);
+ }
+ }
+
+ void storeCustomArgs(QString s)
+ {
+ setArguments(s);
+ }
+
+private:
+ QString customargs;
+};
+
+QString QmlViewer::getVideoFileName()
+{
+ QString title = convertAvailable || ffmpegAvailable ? tr("Save Video File") : tr("Save PNG Frames");
+ QStringList types;
+ if (ffmpegAvailable) types += tr("Common Video files")+QLatin1String(" (*.avi *.mpeg *.mov)");
+ if (convertAvailable) types += tr("GIF Animation")+QLatin1String(" (*.gif)");
+ types += tr("Individual PNG frames")+QLatin1String(" (*.png)");
+ if (ffmpegAvailable) types += tr("All ffmpeg formats (*.*)");
+ return QFileDialog::getSaveFileName(this, title, "", types.join(";; "));
+}
+
QmlViewer::QmlViewer(QWidget *parent, Qt::WindowFlags flags)
: QWidget(parent, flags), frame_stream(0), scaleSkin(true), mb(0)
@@ -137,7 +212,28 @@ QmlViewer::QmlViewer(QWidget *parent, Qt::WindowFlags flags)
palette = 0;
disabledPalette = 0;
record_autotime = 0;
- record_period = 20;
+ record_rate = 50;
+ record_args += QLatin1String("-sameq");
+
+ recdlg = new RecordingDialog(this);
+ connect(recdlg->pickfile, SIGNAL(clicked()), this, SLOT(pickRecordingFile()));
+ senseFfmpeg();
+ senseImageMagick();
+ if (!ffmpegAvailable)
+ recdlg->ffmpegOptions->hide();
+ if (!ffmpegAvailable && !convertAvailable)
+ recdlg->rateOptions->hide();
+ QString warn;
+ if (!ffmpegAvailable) {
+ if (!convertAvailable)
+ warn = tr("ffmpeg and ImageMagick not available - no video output");
+ else
+ warn = tr("ffmpeg not available - GIF and PNG outputs only");
+ recdlg->warning->setText(warn);
+ } else {
+ recdlg->warning->hide();
+ }
+
if (!(flags & Qt::FramelessWindowHint))
createMenu(menuBar(),0);
@@ -205,6 +301,10 @@ void QmlViewer::createMenu(QMenuBar *menu, QMenu *flatmenu)
connect(recordAction, SIGNAL(triggered()), this, SLOT(toggleRecordingWithSelection()));
recordMenu->addAction(recordAction);
+ QAction *recordOptions = new QAction(tr("Recording &Options..."), parent);
+ connect(recordOptions, SIGNAL(triggered()), this, SLOT(chooseRecordingOptions()));
+ recordMenu->addAction(recordOptions);
+
if (flatmenu) flatmenu->addSeparator();
QMenu *skinMenu = flatmenu ? flatmenu->addMenu(tr("&Skin")) : menu->addMenu(tr("&Skin"));
@@ -310,15 +410,57 @@ void QmlViewer::takeSnapShot()
++snapshotcount;
}
+void QmlViewer::pickRecordingFile()
+{
+ QString fileName = getVideoFileName();
+ if (!fileName.isEmpty())
+ recdlg->file->setText(fileName);
+}
+
+void QmlViewer::chooseRecordingOptions()
+{
+ recdlg->file->setText(record_file);
+ if (record_rate == 24)
+ recdlg->hz24->setChecked(true);
+ else if (record_rate == 25)
+ recdlg->hz25->setChecked(true);
+ else if (record_rate == 50)
+ recdlg->hz50->setChecked(true);
+ else if (record_rate == 60)
+ recdlg->hz60->setChecked(true);
+ else {
+ recdlg->hzCustom->setChecked(true);
+ recdlg->hz->setText(QString::number(record_rate));
+ }
+ recdlg->setArguments(record_args.join(" "));
+ if (recdlg->exec()) {
+ record_file = recdlg->file->text();
+ if (recdlg->hz24->isChecked())
+ record_rate = 24;
+ else if (recdlg->hz25->isChecked())
+ record_rate = 25;
+ else if (recdlg->hz50->isChecked())
+ record_rate = 50;
+ else if (recdlg->hz60->isChecked())
+ record_rate = 60;
+ else {
+ record_rate = recdlg->hz->text().toDouble();
+ }
+ record_args = recdlg->arguments().split(" ",QString::SkipEmptyParts);
+ }
+}
+
void QmlViewer::toggleRecordingWithSelection()
{
if (!recordTimer.isRunning()) {
- QString fileName = QFileDialog::getSaveFileName(this, tr("Save Video File"), "", tr("Common Video files (*.avi *.mpeg *.mov);; GIF Animation (*.gif);; Individual PNG frames (*.png);; All ffmpeg formats (*.*)"));
- if (fileName.isEmpty())
- return;
- if (!fileName.contains(QRegExp(".[^\\/]*$")))
- fileName += ".avi";
- setRecordFile(fileName);
+ if (record_file.isEmpty()) {
+ QString fileName = getVideoFileName();
+ if (fileName.isEmpty())
+ return;
+ if (!fileName.contains(QRegExp(".[^\\/]*$")))
+ fileName += ".avi";
+ setRecordFile(fileName);
+ }
}
toggleRecording();
}
@@ -503,9 +645,9 @@ void QmlViewer::setRecordFile(const QString& f)
record_file = f;
}
-void QmlViewer::setRecordPeriod(int ms)
+void QmlViewer::setRecordRate(int fps)
{
- record_period = ms;
+ record_rate = fps;
}
void QmlViewer::sceneResized(QSize size)
@@ -545,32 +687,63 @@ void QmlViewer::keyPressEvent(QKeyEvent *event)
QWidget::keyPressEvent(event);
}
+void QmlViewer::senseImageMagick()
+{
+ QProcess proc;
+ proc.start("convert", QStringList() << "-h");
+ proc.waitForFinished(2000);
+ QString help = proc.readAllStandardOutput();
+ convertAvailable = help.contains("ImageMagick");
+}
+
+void QmlViewer::senseFfmpeg()
+{
+ QProcess proc;
+ proc.start("ffmpeg", QStringList() << "-h");
+ proc.waitForFinished(2000);
+ QString ffmpegHelp = proc.readAllStandardOutput();
+ ffmpegAvailable = ffmpegHelp.contains("-s ");
+ ffmpegHelp = tr("Video recording use ffmpeg:")+"\n\n"+ffmpegHelp;
+
+ QDialog *d = new QDialog(recdlg);
+ QVBoxLayout *l = new QVBoxLayout(d);
+ QTextBrowser *b = new QTextBrowser(d);
+ QFont f = b->font();
+ f.setFamily("courier");
+ b->setFont(f);
+ b->setText(ffmpegHelp);
+ l->addWidget(b);
+ d->setLayout(l);
+ ffmpegHelpWindow = d;
+ connect(recdlg->ffmpegHelp,SIGNAL(clicked()), ffmpegHelpWindow, SLOT(show()));
+}
+
void QmlViewer::setRecording(bool on)
{
if (on == recordTimer.isRunning())
return;
- QUnifiedTimer::instance()->setTimingInterval(on ? record_period:16);
+ int period = int(1000/record_rate+0.5);
+ QUnifiedTimer::instance()->setTimingInterval(on ? period:16);
QUnifiedTimer::instance()->setConsistentTiming(on);
if (on) {
canvas->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
- recordTimer.setInterval(record_period);
+ recordTimer.setInterval(period);
recordTimer.setRunning(true);
- QString fmt = record_file.right(4).toLower();
- if (fmt != ".png" && fmt != ".gif") {
+ frame_fmt = record_file.right(4).toLower();
+ frame = QImage(canvas->width(),canvas->height(),QImage::Format_RGB32);
+ if (frame_fmt != ".png" && (!convertAvailable || frame_fmt != ".gif")) {
// Stream video to ffmpeg
QProcess *proc = new QProcess(this);
connect(proc, SIGNAL(finished(int)), this, SLOT(ffmpegFinished(int)));
frame_stream = proc;
- frame = QImage(canvas->width(),canvas->height(),QImage::Format_RGB32);
QStringList args;
- args << "-sameq"; // ie. high
args << "-y";
- args << "-r" << QString::number(1000/record_period);
+ args << "-r" << QString::number(record_rate);
args << "-f" << "rawvideo";
- args << "-pix_fmt" << "rgb32";
+ args << "-pix_fmt" << (frame_fmt == ".gif" ? "rgb24" : "rgb32");
args << "-s" << QString("%1x%2").arg(canvas->width()).arg(canvas->height());
args << "-i" << "-";
args += record_args;
@@ -635,7 +808,7 @@ void QmlViewer::setRecording(bool on)
// ImageMagick and gifsicle for GIF encoding
progress.setLabelText(tr("Converting frames to GIF file..."));
QStringList args;
- args << "-delay" << QString::number(record_period/10);
+ args << "-delay" << QString::number(period/10);
args << inputs;
args << record_file;
qDebug() << "Converting..." << record_file << "(this may take a while)";
@@ -685,7 +858,13 @@ void QmlViewer::recordFrame()
{
canvas->QWidget::render(&frame);
if (frame_stream) {
- frame_stream->write((char*)frame.bits(),frame.numBytes());
+ if (frame_fmt == ".gif") {
+ // ffmpeg can't do 32bpp with gif
+ QImage rgb24 = frame.convertToFormat(QImage::Format_RGB888);
+ frame_stream->write((char*)rgb24.bits(),rgb24.numBytes());
+ } else {
+ frame_stream->write((char*)frame.bits(),frame.numBytes());
+ }
} else {
frames.append(new QImage(frame));
}
diff --git a/tools/qmlviewer/qmlviewer.h b/tools/qmlviewer/qmlviewer.h
index e7177eb..15acf72 100644
--- a/tools/qmlviewer/qmlviewer.h
+++ b/tools/qmlviewer/qmlviewer.h
@@ -26,6 +26,7 @@ class PreviewDeviceSkin;
class QFxTestEngine;
class QmlPalette;
class QProcess;
+class RecordingDialog;
class QmlViewer : public QWidget
{
@@ -34,10 +35,9 @@ public:
QmlViewer(QWidget *parent=0, Qt::WindowFlags flags=0);
void setRecordDither(const QString& s) { record_dither = s; }
- void setRecordPeriod(int ms);
+ void setRecordRate(int fps);
void setRecordFile(const QString&);
void setRecordArgs(const QStringList&);
- int recordPeriod() const { return record_period; }
void setRecording(bool on);
bool isRecording() const { return recordTimer.isRunning(); }
void setAutoRecord(int from, int to);
@@ -69,10 +69,13 @@ private slots:
void autoStartRecording();
void autoStopRecording();
void recordFrame();
+ void chooseRecordingOptions();
+ void pickRecordingFile();
private:
void setupProxy();
void setupPalettes();
+ QString getVideoFileName();
QString currentFileName;
PreviewDeviceSkin *skin;
@@ -81,6 +84,7 @@ private:
QmlPalette *palette;
QmlPalette *disabledPalette;
QmlTimer recordTimer;
+ QString frame_fmt;
QImage frame;
QList<QImage*> frames;
QProcess* frame_stream;
@@ -89,13 +93,20 @@ private:
QString record_dither;
QString record_file;
QStringList record_args;
- int record_period;
+ int record_rate;
int record_autotime;
bool devicemode;
QAction *recordAction;
QString currentSkin;
bool scaleSkin;
mutable QMenuBar *mb;
+ RecordingDialog *recdlg;
+
+ void senseImageMagick();
+ void senseFfmpeg();
+ QWidget *ffmpegHelpWindow;
+ bool ffmpegAvailable;
+ bool convertAvailable;
};
QT_END_NAMESPACE
diff --git a/tools/qmlviewer/qmlviewer.pro b/tools/qmlviewer/qmlviewer.pro
index 08d2d2b..a8ccd91 100644
--- a/tools/qmlviewer/qmlviewer.pro
+++ b/tools/qmlviewer/qmlviewer.pro
@@ -1,12 +1,15 @@
+TEMPLATE = app
+CONFIG += qt uic
DESTDIR = ../../bin
QT += declarative script network sql
# Input
HEADERS += qmlviewer.h
SOURCES += main.cpp qmlviewer.cpp
+FORMS = recopts.ui
+
include($$QT_SOURCE_TREE/tools/shared/deviceskin/deviceskin.pri)
target.path=$$[QT_INSTALL_BINS]
INSTALLS += target
-CONFIG += console
diff --git a/tools/qmlviewer/recopts.ui b/tools/qmlviewer/recopts.ui
new file mode 100644
index 0000000..041a4c4
--- /dev/null
+++ b/tools/qmlviewer/recopts.ui
@@ -0,0 +1,338 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RecordingOptions</class>
+ <widget class="QDialog" name="RecordingOptions">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>290</width>
+ <height>297</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Recording options</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>File:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" colspan="2">
+ <widget class="QLineEdit" name="file"/>
+ </item>
+ <item row="6" column="2" colspan="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <widget class="QToolButton" name="pickfile">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="4">
+ <widget class="QWidget" name="ffmpegOptions" native="true">
+ <layout class="QGridLayout" name="gridLayout_2">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Profile:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="2">
+ <widget class="QComboBox" name="profile"/>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="args"/>
+ </item>
+ <item row="2" column="2">
+ <widget class="QToolButton" name="ffmpegHelp">
+ <property name="text">
+ <string>Help</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="4">
+ <widget class="QWidget" name="rateOptions" native="true">
+ <layout class="QGridLayout" name="gridLayout_3">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Rate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QRadioButton" name="hz24">
+ <property name="text">
+ <string>24Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QRadioButton" name="hz50">
+ <property name="text">
+ <string>50Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QRadioButton" name="hz25">
+ <property name="text">
+ <string>25Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QRadioButton" name="hz60">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>60Hz</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" colspan="2">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="hzCustom">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="hz">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>60</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="3" column="0" colspan="4">
+ <widget class="QLabel" name="warning">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>hzCustom</sender>
+ <signal>clicked()</signal>
+ <receiver>hz</receiver>
+ <slot>setFocus()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>54</x>
+ <y>104</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>85</x>
+ <y>107</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>hz</sender>
+ <signal>textChanged(QString)</signal>
+ <receiver>hzCustom</receiver>
+ <slot>toggle()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>138</x>
+ <y>102</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>49</x>
+ <y>104</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>hz</sender>
+ <signal>selectionChanged()</signal>
+ <receiver>hzCustom</receiver>
+ <slot>toggle()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>110</x>
+ <y>105</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>51</x>
+ <y>103</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>RecordingOptions</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>280</x>
+ <y>287</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>60</x>
+ <y>219</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>RecordingOptions</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>280</x>
+ <y>287</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>92</x>
+ <y>219</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>profile</sender>
+ <signal>activated(int)</signal>
+ <receiver>RecordingOptions</receiver>
+ <slot>pickProfile(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>72</x>
+ <y>132</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>48</x>
+ <y>194</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>args</sender>
+ <signal>textEdited(QString)</signal>
+ <receiver>RecordingOptions</receiver>
+ <slot>storeCustomArgs(QString)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>108</x>
+ <y>161</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>102</x>
+ <y>189</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+ <slots>
+ <signal>filePicked(QString)</signal>
+ <signal>argumentsPicked(QString)</signal>
+ <slot>pickFile()</slot>
+ <slot>pickProfile(int)</slot>
+ <slot>storeCustomArgs(QString)</slot>
+ </slots>
+</ui>