Nicolas Winkler 5 lat temu
rodzic
commit
9e7c788bce
12 zmienionych plików z 873 dodań i 35 usunięć
  1. 75 2
      Almond.cpp
  2. 15 1
      Almond.h
  3. 10 2
      Almond.pro
  4. 30 30
      Almond.ui
  5. 150 0
      AlmondMenuWidget.cpp
  6. 41 0
      AlmondMenuWidget.h
  7. 71 0
      ExportImageMenu.cpp
  8. 30 0
      ExportImageMenu.h
  9. 87 0
      ExportImageMenu.ui
  10. 112 0
      ExportVideoMenu.cpp
  11. 28 0
      ExportVideoMenu.h
  12. 224 0
      ExportVideoMenu.ui

+ 75 - 2
Almond.cpp

@@ -27,7 +27,6 @@ Almond::Almond(QWidget* parent) :
     on_maxIterations_editingFinished();
     mw->setSmoothColoring(ui.smooth->isChecked());
 
-
     currentView = MANDELBROT;
     mandelGenerator = &mandelContext.getDefaultGenerator();
     mandelViewSave = mw->getViewport();
@@ -39,6 +38,26 @@ Almond::Almond(QWidget* parent) :
     ui.backgroundProgress->setEnabled(false);
     ui.cancelProgress->setEnabled(false);
 
+    amw = new AlmondMenuWidget(this);
+    amw->setMainMenu(ui.dockWidgetContents_2);
+    eim = new ExportImageMenu();
+    evm = new ExportVideoMenu();
+    amw->addSubMenu(eim);
+    amw->addSubMenu(evm);
+    ui.dockWidget_2->setWidget(amw);
+
+    connect(amw, &AlmondMenuWidget::submenuCancel, [this] (int) {amw->showMainMenu();});
+    connect(amw, &AlmondMenuWidget::submenuOK, [this] (int smIndex) {
+        switch(smIndex) {
+        case 0:
+            emit imageExportOk();
+            break;
+        case 1:
+            emit videoExportOk();
+            break;
+        }
+        amw->showMainMenu();
+    });
 
     /*QStatusBar* bar = new QStatusBar(this);
     bar->addWidget(new QLabel("ayay"));
@@ -110,6 +129,54 @@ bool Almond::eventFilter(QObject *target, QEvent *event)
 }
 
 
+void Almond::imageExportOk(void)
+{
+    mnd::MandelInfo mi;
+    mi.maxIter = eim->getMaxIterations();
+    mi.view = mw->getViewport();
+    mi.bWidth = eim->getWidth();
+    mi.bHeight = eim->getHeight();
+    mi.view.adjustAspectRatio(mi.bWidth, mi.bHeight);
+    mi.smooth = mw->getSmoothColoring();
+    if (currentView == JULIA) {
+        mi.julia = mw->getMandelInfo().julia;
+        mi.juliaX = mw->getJuliaX();
+        mi.juliaY = mw->getJuliaY();
+    }
+
+    mnd::MandelGenerator* currentGenerator = mw->getGenerator();
+    mnd::MandelGenerator& g = currentGenerator ? *currentGenerator : mandelContext.getDefaultGenerator();
+
+    alm::ImageExportInfo iei;
+    iei.drawInfo = mi;
+    iei.generator = &g;
+    iei.gradient = mw->getGradient();
+    iei.path = eim->getPath().toStdString();
+    iei.options.jpegQuality = 95;
+    submitBackgroundTask(new ImageExportTask(iei, [this] () { return stoppingBackgroundTasks; }));
+}
+
+
+void Almond::videoExportOk(void)
+{
+    ExportVideoInfo evi = evm->getInfo();
+    evi.start = mnd::MandelViewport::standardView();
+    evi.end = mw->getViewport();
+    evi.gradient = mw->getGradient();
+    evi.mi = mw->getMandelInfo();
+    if (evi.path == "") {
+        QMessageBox* errMsg = new QMessageBox(QMessageBox::Icon::Critical, "Error", "No path specified.");
+        errMsg->setParent(this);
+        emit errMsg->exec();
+    }
+    else {
+        MandelVideoGenerator mvg(evi);
+        mnd::MandelGenerator& g = *mw->getGenerator();
+        submitBackgroundTask(new VideoExportTask(std::move(mvg), g));
+    }
+}
+
+
 void Almond::toggleFullscreen(void)
 {
     if (fullscreenMode) {
@@ -141,7 +208,7 @@ void Almond::backgroundTaskFinished(bool succ, QString message)
         emit info.exec();
     }
 
-    ui.backgroundProgress->setFormat("");
+    ui.backgroundProgress->setFormat(tr("Export Progress"));
     ui.backgroundProgress->setEnabled(false);
     ui.cancelProgress->setEnabled(false);
     stoppingBackgroundTasks = false;
@@ -197,6 +264,9 @@ void Almond::on_chooseGradient_clicked()
 
 void Almond::on_exportVideo_clicked()
 {
+    evm->setEndViewport(mw->getViewport());
+    this->amw->showSubMenu(1);
+    return;
     ExportVideoInfo evi;
     evi.start = mnd::MandelViewport::standardView();
     evi.end = mw->getViewport();
@@ -237,6 +307,9 @@ void Almond::on_smooth_stateChanged(int checked)
 
 void Almond::on_exportImage_clicked()
 {
+    this->amw->showSubMenu(0);
+    return;
+
     ExportImageDialog dialog(this);
     dialog.setMaxIterations(mw->getMaxIterations());
     //dialog.show();

+ 15 - 1
Almond.h

@@ -1,4 +1,6 @@
 #pragma once
+#ifndef ALMOND_H
+#define ALMOND_H
 
 #include <QtWidgets/QMainWindow>
 #include "ui_Almond.h"
@@ -10,7 +12,11 @@
 #include "gradientchoosedialog.h"
 #include "choosegenerators.h"
 #include "customgenerator.h"
-//#include "benchmarkdialog.h"
+
+#include "AlmondMenuWidget.h"
+#include "ExportImageMenu.h"
+#include "ExportVideoMenu.h"
+
 
 #include <memory>
 
@@ -37,6 +43,9 @@ private:
     QThreadPool backgroundTasks;
     bool stoppingBackgroundTasks = false;
 
+    AlmondMenuWidget* amw;
+    ExportImageMenu* eim;
+    ExportVideoMenu* evm;
 
     bool fullscreenMode = false;
     QWidget* cw;
@@ -66,6 +75,9 @@ public:
     void stopBackgroundTask();
 
     bool eventFilter(QObject *target, QEvent *event);
+
+    void imageExportOk(void);
+    void videoExportOk(void);
 public slots:
     void toggleFullscreen(void);
 private slots:
@@ -102,3 +114,5 @@ private:
     Ui::AlmondClass ui;
 };
 
+
+#endif // ALMOND_H

+ 10 - 2
Almond.pro

@@ -27,9 +27,12 @@ CONFIG += c++17
 
 SOURCES += \
         Almond.cpp \
+        AlmondMenuWidget.cpp \
         BackgroundTask.cpp \
         Color.cpp \
         CubicSpline.cpp \
+        ExportImageMenu.cpp \
+        ExportVideoMenu.cpp \
         Gradient.cpp \
         GradientWidget.cpp \
         MandelWidget.cpp \
@@ -42,9 +45,12 @@ SOURCES += \
 
 HEADERS += \
         Almond.h \
+        AlmondMenuWidget.h \
         BackgroundTask.h \
         Color.h \
         CubicSpline.h \
+        ExportImageMenu.h \
+        ExportVideoMenu.h \
         Gradient.h \
         GradientWidget.h \
         MandelWidget.h \
@@ -56,6 +62,8 @@ HEADERS += \
 
 FORMS += \
         Almond.ui \
+        ExportImageMenu.ui \
+        ExportVideoMenu.ui \
         choosegenerators.ui \
         customgenerator.ui \
         exportimagedialog.ui \
@@ -128,9 +136,9 @@ unix|win32: LIBS += -L$FFMPEGPATH -lswscale
 RESOURCES += Almond.qrc \
     splash.qrc
 
-win32:LIBS += -llibpng16_static -lzlibstatic
+win32:LIBS += -llibpng16_static -lzlibstatic -ljpeg
 unix|win32: LIBS += -L$$PWD/libmandel/ -L$$PWD/libalmond/ -lmandel -lqd -lasmjit -lalmond
-unix: LIBS += -lrt -lpng -lavcodec -lavdevice -lavformat -lavutil -lswscale -lavfilter
+unix: LIBS += -lrt -lpng -ljpeg -lavcodec -lavdevice -lavformat -lavutil -lswscale -lavfilter
 
 INCLUDEPATH += $$PWD/libmandel/include $$PWD/libmandel/qd-2.3.22/include $$PWD/libalmond/include
 DEPENDPATH += $$PWD/libmandel/include $$PWD/libmandel/qd-2.3.22/include $$PWD/libalmond/include

+ 30 - 30
Almond.ui

@@ -95,6 +95,19 @@
          <layout class="QVBoxLayout" name="verticalLayout_3">
           <item>
            <layout class="QFormLayout" name="formLayout">
+            <item row="0" column="0" colspan="2">
+             <widget class="QPushButton" name="chooseGradient">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>Choose Gradient</string>
+              </property>
+             </widget>
+            </item>
             <item row="1" column="0">
              <widget class="QLabel" name="label">
               <property name="text">
@@ -102,6 +115,22 @@
               </property>
              </widget>
             </item>
+            <item row="1" column="1">
+             <widget class="QLineEdit" name="maxIterations">
+              <property name="minimumSize">
+               <size>
+                <width>70</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>500</string>
+              </property>
+              <property name="maxLength">
+               <number>32</number>
+              </property>
+             </widget>
+            </item>
             <item row="2" column="0" colspan="2">
              <widget class="QCheckBox" name="smooth">
               <property name="sizePolicy">
@@ -138,35 +167,6 @@
               </property>
              </widget>
             </item>
-            <item row="1" column="1">
-             <widget class="QLineEdit" name="maxIterations">
-              <property name="minimumSize">
-               <size>
-                <width>70</width>
-                <height>0</height>
-               </size>
-              </property>
-              <property name="text">
-               <string>500</string>
-              </property>
-              <property name="maxLength">
-               <number>32</number>
-              </property>
-             </widget>
-            </item>
-            <item row="0" column="0" colspan="2">
-             <widget class="QPushButton" name="chooseGradient">
-              <property name="sizePolicy">
-               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
-                <horstretch>0</horstretch>
-                <verstretch>0</verstretch>
-               </sizepolicy>
-              </property>
-              <property name="text">
-               <string>Choose Gradient</string>
-              </property>
-             </widget>
-            </item>
            </layout>
           </item>
          </layout>
@@ -269,7 +269,7 @@
              <set>Qt::AlignCenter</set>
             </property>
             <property name="format">
-             <string>Background Tasks</string>
+             <string>Export Progress</string>
             </property>
            </widget>
           </item>

+ 150 - 0
AlmondMenuWidget.cpp

@@ -0,0 +1,150 @@
+#include "AlmondMenuWidget.h"
+#include <QVBoxLayout>
+#include <QPropertyAnimation>
+#include <QParallelAnimationGroup>
+
+AlmondMenuWidget::AlmondMenuWidget(QWidget* parent) :
+    QWidget{ parent },
+    mainMenu{ nullptr }
+{
+    QVBoxLayout* layout = new QVBoxLayout(this);
+    layout->setMargin(0);
+
+    rightWidget = new QWidget(this);
+    subMenuContainer = new QStackedWidget(this);
+    rightOK = new QPushButton("OK", this);
+    rightCancel = new QPushButton("Cancel", this);
+    subMenuContainer->setContentsMargins(0, 0, 0, 0);
+
+    QVBoxLayout* smlayout = new QVBoxLayout(rightWidget);
+    smlayout->addWidget(subMenuContainer, 1);
+    smlayout->addWidget(rightOK);
+    smlayout->addWidget(rightCancel);
+
+    connect(rightOK, &QPushButton::clicked,
+            this, &AlmondMenuWidget::clickedRightOK);
+    connect(rightCancel, &QPushButton::clicked,
+            this, &AlmondMenuWidget::clickedRightCancel);
+
+    layout->addWidget(rightWidget);
+    rightWidget->hide();
+}
+
+
+void AlmondMenuWidget::setMainMenu(QWidget* mainMenu)
+{
+    //mainMenu->setParent(this);
+    this->mainMenu = mainMenu;
+    this->layout()->addWidget(mainMenu);
+}
+
+
+void AlmondMenuWidget::addSubMenu(QWidget* subMenu)
+{
+    subMenuContainer->addWidget(subMenu);
+    this->subMenus.append(subMenu);
+}
+
+
+QSize AlmondMenuWidget::sizeHint(void) const
+{
+    QSize hint{ 0, 0 };
+    if (mainMenu)
+        hint = mainMenu->sizeHint();
+    for (auto& widget : subMenus) {
+        QSize widgetHint = widget->sizeHint();
+        if (hint.width() < widgetHint.width())
+            hint.setWidth(widgetHint.width());
+        if (hint.height() < widgetHint.height())
+            hint.setHeight(widgetHint.height());
+    }
+    return hint;
+}
+
+
+QSize AlmondMenuWidget::minimumSizeHint(void) const
+{
+    QSize hint{ 0, 0 };
+    if (mainMenu)
+        hint = mainMenu->minimumSizeHint();
+    for (auto& widget : subMenus) {
+        QSize widgetHint = widget->minimumSizeHint();
+        if (hint.width() < widgetHint.width())
+            hint.setWidth(widgetHint.width());
+        if (hint.height() < widgetHint.height())
+            hint.setHeight(widgetHint.height());
+    }
+    return hint;
+}
+
+
+void AlmondMenuWidget::clickedRightOK(void)
+{
+    emit submenuOK(subMenuContainer->currentIndex());
+}
+
+
+void AlmondMenuWidget::clickedRightCancel(void)
+{
+    emit submenuCancel(subMenuContainer->currentIndex());
+}
+
+
+void AlmondMenuWidget::showMainMenu(void)
+{
+    if (!mainMenu)
+        return;
+    QParallelAnimationGroup* ag = new QParallelAnimationGroup(this);
+    QPropertyAnimation* mm = new QPropertyAnimation(mainMenu, "geometry", this);
+    QPropertyAnimation* rw = new QPropertyAnimation(rightWidget, "geometry", this);
+
+    mm->setStartValue(rightWidget->geometry().adjusted(-width(), 0, -width(), 0));
+    mm->setEndValue(rightWidget->geometry());
+
+    rw->setEndValue(rightWidget->geometry().adjusted(width(), 0, width(), 0));
+    rw->setStartValue(rightWidget->geometry());
+
+    mm->setEasingCurve(QEasingCurve::InOutSine);
+    rw->setEasingCurve(QEasingCurve::InOutSine);
+    mm->setDuration(200);
+    rw->setDuration(200);
+
+    ag->addAnimation(mm);
+    ag->addAnimation(rw);
+
+    connect(ag, &QParallelAnimationGroup::finished, [this] () { rightWidget->hide(); });
+    mainMenu->show();
+
+    emit ag->start();
+}
+
+
+void AlmondMenuWidget::showSubMenu(int index)
+{
+    if (!mainMenu)
+        return;
+    QParallelAnimationGroup* ag = new QParallelAnimationGroup(this);
+    QPropertyAnimation* mm = new QPropertyAnimation(mainMenu, "geometry", this);
+    QPropertyAnimation* rw = new QPropertyAnimation(rightWidget, "geometry", this);
+
+    mm->setStartValue(mainMenu->geometry());
+    mm->setEndValue(mainMenu->geometry().adjusted(-width(), 0, -width(), 0));
+
+    rw->setStartValue(mainMenu->geometry().adjusted(width(), 0, width(), 0));
+    rw->setEndValue(mainMenu->geometry());
+
+    mm->setEasingCurve(QEasingCurve::InOutSine);
+    rw->setEasingCurve(QEasingCurve::InOutSine);
+    mm->setDuration(200);
+    rw->setDuration(200);
+
+    ag->addAnimation(mm);
+    ag->addAnimation(rw);
+
+    connect(ag, &QParallelAnimationGroup::finished, [this] () { mainMenu->hide(); });
+
+    subMenuContainer->setCurrentIndex(index);
+    rightWidget->show();
+
+    emit ag->start();
+}

+ 41 - 0
AlmondMenuWidget.h

@@ -0,0 +1,41 @@
+#ifndef ALMONDMENUWIDGET_H
+#define ALMONDMENUWIDGET_H
+
+#include <QWidget>
+#include <QList>
+#include <QStackedWidget>
+#include <QPushButton>
+
+class AlmondMenuWidget : public QWidget
+{
+    Q_OBJECT
+
+    QWidget* mainMenu;
+    QWidget* rightWidget;
+    QPushButton* rightOK;
+    QPushButton* rightCancel;
+    QStackedWidget* subMenuContainer;
+    QList<QWidget*> subMenus;
+public:
+    AlmondMenuWidget(QWidget* parent = nullptr);
+
+    void setMainMenu(QWidget* mainMenu);
+    void addSubMenu(QWidget* subMenu);
+
+    virtual QSize sizeHint(void) const override;
+    virtual QSize minimumSizeHint(void) const override;
+
+protected slots:
+    void clickedRightOK(void);
+    void clickedRightCancel(void);
+
+public slots:
+    void showMainMenu(void);
+    void showSubMenu(int index);
+
+signals:
+    void submenuOK(int index);
+    void submenuCancel(int index);
+};
+
+#endif // ALMONDMENUWIDGET_H

+ 71 - 0
ExportImageMenu.cpp

@@ -0,0 +1,71 @@
+#include "ExportImageMenu.h"
+#include "ui_ExportImageMenu.h"
+
+#include "ImageExport.h"
+
+#include <QIntValidator>
+#include <QFileDialog>
+
+ExportImageMenu::ExportImageMenu(QWidget *parent) :
+    QWidget(parent),
+    ui(new Ui::ExportImageMenu)
+{
+    ui->setupUi(this);
+    ui->maxIterTxt->setValidator(new QIntValidator(1, 1000000000, this));
+    ui->widthTxt->setValidator(new QIntValidator(1, 10000000, this));
+    ui->heightTxt->setValidator(new QIntValidator(1, 10000000, this));
+}
+
+
+ExportImageMenu::~ExportImageMenu()
+{
+    delete ui;
+}
+
+
+int ExportImageMenu::getMaxIterations(void) const
+{
+    return ui->maxIterTxt->text().toInt();
+}
+
+
+int ExportImageMenu::getWidth(void) const
+{
+    return ui->widthTxt->text().toInt();
+}
+
+
+int ExportImageMenu::getHeight(void) const
+{
+    return ui->heightTxt->text().toInt();
+}
+
+
+QString ExportImageMenu::getPath(void) const
+{
+    return ui->pathTxt->text();
+}
+
+
+void ExportImageMenu::on_pathBtn_clicked()
+{
+    std::string formatString = "";
+    if (alm::supportsImageFormat(alm::ImageFormat::PNG)) {
+        formatString += "PNG image (*.png);;";
+    }
+    if (alm::supportsImageFormat(alm::ImageFormat::JPEG)) {
+        formatString += "JPEG image (*.jpg *.jpeg);;";
+    }
+    if (alm::supportsImageFormat(alm::ImageFormat::BMP)) {
+        formatString += "BMP image (*.bmp *.dib);;";
+    }
+    if (!formatString.empty()) {
+        formatString.erase(formatString.end() - 2, formatString.end());
+    }
+
+    QString saveAs = QFileDialog::getSaveFileName(this,
+            tr("Save exported image"), "",
+            tr(formatString.c_str()));
+    if(!saveAs.isEmpty() && !saveAs.isNull())
+        ui->pathTxt->setText(saveAs);
+}

+ 30 - 0
ExportImageMenu.h

@@ -0,0 +1,30 @@
+#ifndef EXPORTIMAGEMENU_H
+#define EXPORTIMAGEMENU_H
+
+#include <QWidget>
+
+namespace Ui {
+class ExportImageMenu;
+}
+
+class ExportImageMenu : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit ExportImageMenu(QWidget *parent = nullptr);
+    ~ExportImageMenu();
+
+    int getMaxIterations(void) const;
+    int getWidth(void) const;
+    int getHeight(void) const;
+    QString getPath(void) const;
+
+private slots:
+    void on_pathBtn_clicked();
+
+private:
+    Ui::ExportImageMenu *ui;
+};
+
+#endif // EXPORTIMAGEMENU_H

+ 87 - 0
ExportImageMenu.ui

@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ExportImageMenu</class>
+ <widget class="QWidget" name="ExportImageMenu">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>253</width>
+    <height>330</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QFormLayout" name="formLayout">
+   <item row="0" column="0" colspan="2">
+    <widget class="QLabel" name="titleLbl">
+     <property name="font">
+      <font>
+       <pointsize>14</pointsize>
+       <weight>75</weight>
+       <bold>true</bold>
+      </font>
+     </property>
+     <property name="text">
+      <string>Export Image</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="maxIterLbl">
+     <property name="text">
+      <string>Max. Iterations</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLineEdit" name="maxIterTxt">
+     <property name="text">
+      <string>5000</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="widthLbl">
+     <property name="text">
+      <string>Width</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QLineEdit" name="widthTxt">
+     <property name="text">
+      <string>1920</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0">
+    <widget class="QLabel" name="heightLbl">
+     <property name="text">
+      <string>Height</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="QLineEdit" name="heightTxt">
+     <property name="text">
+      <string>1080</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="0">
+    <widget class="QPushButton" name="pathBtn">
+     <property name="text">
+      <string>Save As:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="1">
+    <widget class="QLineEdit" name="pathTxt"/>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 112 - 0
ExportVideoMenu.cpp

@@ -0,0 +1,112 @@
+#include "ExportVideoMenu.h"
+#include "ui_ExportVideoMenu.h"
+#include <QIntValidator>
+#include <QDoubleValidator>
+
+ExportVideoMenu::ExportVideoMenu(QWidget *parent) :
+    QWidget{ parent },
+    ui{ new Ui::ExportVideoMenu }
+{
+    ui->setupUi(this);
+    this->adjustSize();
+    ui->maxIterTxt->setValidator(new QIntValidator(1, 1000000000, this));
+    ui->widthTxt->setValidator(new QIntValidator(1, 10000000, this));
+    ui->heightTxt->setValidator(new QIntValidator(1, 10000000, this));
+    ui->bitrate->setValidator(new QIntValidator(1, 10000000, this));
+    ui->fps->setValidator(new QIntValidator(1, 8000, this));
+    ui->zoomSpeed->setValidator(new QDoubleValidator(0.0, 100.0, -1, this));
+
+
+    /*
+    evd.startX->setText(QString::fromStdString(evi.start.x.str()));
+    evd.startY->setText(QString::fromStdString(evi.start.y.str()));
+    evd.startW->setText(QString::fromStdString(evi.start.width.str()));
+    evd.startH->setText(QString::fromStdString(evi.start.height.str()));
+
+    evd.endX->setText(QString::fromStdString(evi.end.x.str()));
+    evd.endY->setText(QString::fromStdString(evi.end.y.str()));
+    evd.endW->setText(QString::fromStdString(evi.end.width.str()));
+    evd.endH->setText(QString::fromStdString(evi.end.height.str()));
+    */
+
+
+    const auto presets = {
+        "ultrafast",
+        "superfast",
+        "veryfast",
+        "faster",
+        "fast",
+        "medium",
+        "slow",
+        "slower",
+        "veryslow",
+    };
+    for (auto& preset : presets) {
+        ui->encodingPresetBox->addItem(preset);
+    }
+    ui->encodingPresetBox->setCurrentText("medium");
+    setStartViewport(mnd::MandelViewport::standardView());
+}
+
+
+ExportVideoMenu::~ExportVideoMenu()
+{
+    delete ui;
+}
+
+
+ExportVideoInfo ExportVideoMenu::getInfo(void) const
+{
+    ExportVideoInfo evi;
+    /*if (ui->pathTxt->text() == "") {
+        QMessageBox* msgBox = new QMessageBox;
+        msgBox->setText("Please specify a path.");
+        msgBox->exec();
+        emit reject();
+    }*/
+
+    evi.path = ui->pathTxt->text().toStdString();
+
+    evi.mi.bWidth = ui->widthTxt->text().toInt();
+    evi.mi.bHeight = ui->heightTxt->text().toInt();
+    evi.mi.maxIter = ui->maxIterTxt->text().toInt();
+
+    evi.bitrate = ui->bitrate->text().toInt();
+    evi.preset = ui->encodingPresetBox->currentText().toStdString();
+    evi.fps = ui->fps->text().toInt();
+    evi.zoomSpeed = QLocale::system().toDouble(ui->zoomSpeed->text());
+    evi.start = mnd::MandelViewport {
+        mnd::Real(ui->startX->text().toStdString().c_str()),
+        mnd::Real(ui->startY->text().toStdString().c_str()),
+        mnd::Real(ui->startW->text().toStdString().c_str()),
+        mnd::Real(ui->startH->text().toStdString().c_str())
+    };
+    evi.end = mnd::MandelViewport {
+        mnd::Real(ui->endX->text().toStdString().c_str()),
+        mnd::Real(ui->endY->text().toStdString().c_str()),
+        mnd::Real(ui->endW->text().toStdString().c_str()),
+        mnd::Real(ui->endH->text().toStdString().c_str())
+    };
+
+    evi.start.adjustAspectRatio(evi.mi.bWidth, evi.mi.bHeight);
+    evi.end.adjustAspectRatio(evi.mi.bWidth, evi.mi.bHeight);
+}
+
+
+void ExportVideoMenu::setStartViewport(const mnd::MandelViewport& mv)
+{
+    ui->startX->setText(QString::fromStdString(mnd::toString(mv.x)));
+    ui->startY->setText(QString::fromStdString(mnd::toString(mv.y)));
+    ui->startW->setText(QString::fromStdString(mnd::toString(mv.width)));
+    ui->startH->setText(QString::fromStdString(mnd::toString(mv.height)));
+}
+
+
+void ExportVideoMenu::setEndViewport(const mnd::MandelViewport& mv)
+{
+    ui->endX->setText(QString::fromStdString(mnd::toString(mv.x)));
+    ui->endY->setText(QString::fromStdString(mnd::toString(mv.y)));
+    ui->endW->setText(QString::fromStdString(mnd::toString(mv.width)));
+    ui->endH->setText(QString::fromStdString(mnd::toString(mv.height)));
+}
+

+ 28 - 0
ExportVideoMenu.h

@@ -0,0 +1,28 @@
+#ifndef EXPORTVIDEOMENU_H
+#define EXPORTVIDEOMENU_H
+
+#include <QWidget>
+
+#include "MandelVideoGenerator.h"
+
+namespace Ui
+{
+    class ExportVideoMenu;
+}
+
+class ExportVideoMenu : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit ExportVideoMenu(QWidget *parent = nullptr);
+    ~ExportVideoMenu();
+
+    ExportVideoInfo getInfo(void) const;
+    void setStartViewport(const mnd::MandelViewport& mv);
+    void setEndViewport(const mnd::MandelViewport& mv);
+private:
+    Ui::ExportVideoMenu *ui;
+};
+
+#endif // EXPORTVIDEOMENU_H

+ 224 - 0
ExportVideoMenu.ui

@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ExportVideoMenu</class>
+ <widget class="QWidget" name="ExportVideoMenu">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>253</width>
+    <height>543</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Frame</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="titleLbl">
+     <property name="font">
+      <font>
+       <pointsize>14</pointsize>
+       <weight>75</weight>
+       <bold>true</bold>
+      </font>
+     </property>
+     <property name="text">
+      <string>Export Video</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QToolBox" name="toolBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <widget class="QWidget" name="toolBoxPage1">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <attribute name="label">
+       <string>General</string>
+      </attribute>
+      <layout class="QFormLayout" name="formLayout_2">
+       <item row="0" column="0">
+        <widget class="QLabel" name="maxIterLbl">
+         <property name="text">
+          <string>Max. Iterations</string>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="0">
+        <widget class="QLabel" name="widthLbl">
+         <property name="text">
+          <string>Video Width</string>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="0">
+        <widget class="QLabel" name="heightLbl">
+         <property name="text">
+          <string>Video Height</string>
+         </property>
+        </widget>
+       </item>
+       <item row="4" column="0" colspan="2">
+        <widget class="QGroupBox" name="groupBox_2">
+         <property name="title">
+          <string>End View</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout">
+          <item row="0" column="0">
+           <widget class="QLineEdit" name="endX"/>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLineEdit" name="endW"/>
+          </item>
+          <item row="1" column="1">
+           <widget class="QLineEdit" name="endH"/>
+          </item>
+          <item row="0" column="1">
+           <widget class="QLineEdit" name="endY"/>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="5" column="0">
+        <widget class="QPushButton" name="pathBtn">
+         <property name="text">
+          <string>Save As</string>
+         </property>
+        </widget>
+       </item>
+       <item row="5" column="1">
+        <widget class="QLineEdit" name="pathTxt"/>
+       </item>
+       <item row="3" column="0" colspan="2">
+        <widget class="QGroupBox" name="groupBox">
+         <property name="title">
+          <string>Start View</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_2">
+          <item row="1" column="0">
+           <widget class="QLineEdit" name="startX"/>
+          </item>
+          <item row="0" column="0">
+           <widget class="QLineEdit" name="startW"/>
+          </item>
+          <item row="1" column="1">
+           <widget class="QLineEdit" name="startY"/>
+          </item>
+          <item row="0" column="1">
+           <widget class="QLineEdit" name="startH"/>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item row="2" column="1">
+        <widget class="QLineEdit" name="heightTxt">
+         <property name="text">
+          <string>1080</string>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="1">
+        <widget class="QLineEdit" name="widthTxt">
+         <property name="text">
+          <string>1920</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="1">
+        <widget class="QLineEdit" name="maxIterTxt">
+         <property name="text">
+          <string>5000</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="toolBoxPage2">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+        <horstretch>0</horstretch>
+        <verstretch>0</verstretch>
+       </sizepolicy>
+      </property>
+      <attribute name="label">
+       <string>Encoding</string>
+      </attribute>
+      <layout class="QFormLayout" name="formLayout_4">
+       <item row="0" column="0">
+        <widget class="QLabel" name="label_6">
+         <property name="text">
+          <string>Bitrate [kbps]</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="1">
+        <widget class="QLineEdit" name="bitrate">
+         <property name="text">
+          <string>5000</string>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="0">
+        <widget class="QLabel" name="label_7">
+         <property name="text">
+          <string>Encoding preset</string>
+         </property>
+        </widget>
+       </item>
+       <item row="1" column="1">
+        <widget class="QComboBox" name="encodingPresetBox">
+         <property name="editable">
+          <bool>false</bool>
+         </property>
+         <property name="currentText">
+          <string/>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="0">
+        <widget class="QLabel" name="label_8">
+         <property name="text">
+          <string>Fps</string>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="1">
+        <widget class="QLineEdit" name="fps">
+         <property name="text">
+          <string>60</string>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="0">
+        <widget class="QLabel" name="label_9">
+         <property name="text">
+          <string>Zoom Speed</string>
+         </property>
+        </widget>
+       </item>
+       <item row="3" column="1">
+        <widget class="QLineEdit" name="zoomSpeed">
+         <property name="text">
+          <string>1</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>