This commit is contained in:
Matthieu Gautier 2021-10-19 11:01:45 +02:00 committed by GitHub
commit 30d6ffde2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 473 additions and 299 deletions

View File

@ -44,7 +44,7 @@ SOURCES += \
src/blobbuffer.cpp \
src/library.cpp \
src/settingsmanager.cpp \
src/settingsmanagerview.cpp \
src/settingsview.cpp \
src/topwidget.cpp \
src/urlschemehandler.cpp \
src/webview.cpp \
@ -76,7 +76,7 @@ HEADERS += \
src/blobbuffer.h \
src/library.h \
src/settingsmanager.h \
src/settingsmanagerview.h \
src/settingsview.h \
src/topwidget.h \
src/kconstants.h \
src/urlschemehandler.h \
@ -105,7 +105,8 @@ FORMS += \
ui/about.ui \
src/contentmanagerside.ui \
src/readinglistbar.ui \
ui/localkiwixserver.ui
ui/localkiwixserver.ui \
ui/settings.ui
include(subprojects/QtSingleApplication/src/qtsingleapplication.pri)
CODECFORSRC = UTF-8

View File

@ -1,88 +1,40 @@
html, body {
padding: 0;
margin: auto;
height: 100%;
position: relative;
width: 80%;
overflow: hidden;
QWidget#widget {
max-width: 500;
}
#settings {
height: 100%;
position: relative;
QLabel,
QPushButton,
QSpinBox {
font-size: 16px;
line-height: 24px;
padding: 8px;
}
#header {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
QFrame[frameShape="4"] {
/*frameShape 4 is HLine */
border: 1px solid #eaecf0;
min-height: 0pt;
max-height: 1pt;
}
.row {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
align-items: center;
border-top: 1px solid grey;
height: 40px;
}
input {
margin: 5px;
}
#download_dir {
flex: 1;
margin: 5px;
overflow: hidden;
direction: rtl;
}
#download_dir > span {
display: block;
float: right;
direction: ltr;
min-width: 100%;
font-size: 0.9em;
}
input[type=number] {
width: 80px;
}
input[type=button] {
color: blue;
QLabel#settingsLabel {
font-size: 32px;
line-height: 44px;
font-weight: bold;
font-size: 14px;
border: 0;
background: transparent;
border-radius: 2px;
}
QSpinBox,
QLabel#downloadDirPath {
font: bold 12pt "Cantarell";
}
QPushButton {
background-color: white;
color: #3366cc;
padding: 4px;
font: bold;
border-radius: 4px;
}
input[type=button]:hover {
QPushButton:hover {
background-color: #3366cc;
color: white;
background: blue;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
opacity: 1;
}
div.percentage-symbol {
position: relative;
}
div.percentage-symbol:before {
position: absolute;
content: "%";
top: 0.4em;
right: 1.5em;
}
div.percentage-symbol input {
text-align: left;
}

View File

@ -1,61 +0,0 @@
function onDownloadDirChanged (downloadDir) {
app.downloadDir = downloadDir;
}
function validPort (port) {
return /^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/.test(port);
}
function setTranslations(translations) {
app.translations = createDict(TRANSLATION_KEYS, translations);
}
const TRANSLATION_KEYS = ["settings",
"port-for-local-kiwix-server-setting",
"zoom-level-setting",
"download-directory-setting",
"reset",
"browse",
"invalid-port"];
function init() {
new QWebChannel(qt.webChannelTransport, function(channel) {
settingsManager = channel.objects.settingsManager;
app = new Vue({
el: "#settings",
data: {
settingsManager: settingsManager,
kiwixServerPort: settingsManager.kiwixServerPort,
zoomFactor: Math.floor(settingsManager.zoomFactor * 100),
downloadDir: settingsManager.downloadDir,
translations:{}
},
methods: {
gt : function(key) {
return this.translations[key];
},
setPort : function() {
if (!validPort(this.kiwixServerPort)) {
alert(this.gt("invalid-port"));
this.kiwixServerPort = settingsManager.kiwixServerPort;
return;
}
settingsManager.setKiwixServerPort(this.kiwixServerPort);
},
setZoomFactor : function() {
this.zoomFactor = (this.zoomFactor < 30) ? 30 : this.zoomFactor;
this.zoomFactor = (this.zoomFactor > 500) ? 500 : this.zoomFactor;
settingsManager.setZoomFactor(this.zoomFactor / 100);
},
resetDownloadDir : function() {
settingsManager.resetDownloadDir();
},
browseDownloadDir : function() {
settingsManager.browseDownloadDir();
}
}
});
settingsManager.downloadDirChanged.connect(onDownloadDirChanged)
settingsManager.getTranslations(TRANSLATION_KEYS, setTranslations);
});
}

View File

@ -1,7 +1,5 @@
<RCC>
<qresource prefix="/">
<file>texts/_settingsManager.html</file>
<file>css/_settingsManager.css</file>
<file>js/_settingsManager.js</file>
</qresource>
</RCC>

View File

@ -1,33 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
<head>
<script src="qrc:///js/vue.js"></script>
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script src="qrc:///js/_settingsManager.js"></script>
<script src="qrc:///js/tools.js"></script>
<link rel="stylesheet" type="text/css" href="qrc:///css/_settingsManager.css"/>
</head>
<body onload="init()">
<div id="settings">
<div id="header">
<h1>{{ gt("settings") }}</h1>
</div>
<div class="row">
<label>{{ gt("port-for-local-kiwix-server-setting") }}</label>
<input type="number" min="1" max="65535" v-on:change="setPort()" v-model="kiwixServerPort">
</div>
<div class="row">
<label>{{ gt("zoom-level-setting") }}</label>
<div class="percentage-symbol">
<input type="number" step="10" min="30" max="500" v-on:change="setZoomFactor()" v-model="zoomFactor" >
</div>
</div>
<div class="row">
<label>{{ gt("download-directory-setting") }}</label>
<span id="download_dir"><span>{{ downloadDir }}</span></span>
<input type="button" :value="gt('reset')" v-on:click="resetDownloadDir()">
<input type="button" :value="gt('browse')" v-on:click="browseDownloadDir()">
</div>
</div>
</body></html>

View File

@ -17,7 +17,6 @@
KiwixApp::KiwixApp(int& argc, char *argv[])
: QtSingleApplication("kiwix-desktop", argc, argv),
m_settingsManager(),
m_profile(),
m_libraryDirectory(findLibraryDirectory()),
m_library(m_libraryDirectory),

View File

@ -4,23 +4,23 @@
#include <QFileDialog>
#include <QMessageBox>
#include <kiwix/tools.h>
SettingsManager::SettingsManager(QObject *parent)
: QObject(parent),
m_settings("Kiwix", "Kiwix-desktop"),
m_settingsViewDisplayed(false)
m_view(nullptr)
{
initSettings();
}
SettingsManagerView* SettingsManager::getView()
SettingsView* SettingsManager::getView()
{
auto view = new SettingsManagerView();
view->registerObject("settingsManager", this);
view->setHtml();
connect(view, &QObject::destroyed, this, [=]() { m_settingsViewDisplayed = false; });
m_settingsViewDisplayed = true;
return view;
if (m_view == nullptr) {
auto view = new SettingsView();
view->init(m_kiwixServerPort, m_zoomFactor * 100, m_downloadDir);
connect(view, &QObject::destroyed, this, [=]() { m_view = nullptr; });
m_view = view;
}
return m_view;
}
void SettingsManager::setSettings(const QString &key, const QVariant &value)
@ -64,69 +64,17 @@ void SettingsManager::setZoomFactor(qreal zoomFactor)
{
m_zoomFactor = zoomFactor;
m_settings.setValue("view/zoomFactor", zoomFactor);
emit(zoomChanged(zoomFactor));
}
bool SettingsManager::setDownloadDir(QString downloadDir)
{
m_downloadDir = downloadDir;
m_settings.setValue("download/dir", downloadDir);
emit(downloadDirChanged(downloadDir));
return true;
}
bool SettingsManager::confirmDialogDownloadDir(const QString& dir)
{
auto text = gt("download-dir-dialog-msg");
text = text.replace("{{DIRECTORY}}", dir);
QMessageBox msgBox(
QMessageBox::Question, //Icon
gt("download-dir-dialog-title"), //Title
text, //Text
QMessageBox::Ok | QMessageBox::Cancel //Buttons
);
msgBox.setDefaultButton(QMessageBox::Ok);
int ret = msgBox.exec();
return (ret == QMessageBox::Ok);
}
void SettingsManager::resetDownloadDir()
{
auto dir = QString::fromStdString(kiwix::getDataDirectory());
if (dir == m_downloadDir) {
return;
}
if (confirmDialogDownloadDir(dir)) {
setDownloadDir(dir);
emit(downloadDirChanged(dir));
}
}
void SettingsManager::browseDownloadDir()
{
QString dir = QFileDialog::getExistingDirectory(KiwixApp::instance()->getMainWindow(),
gt("browse-directory"),
m_downloadDir,
QFileDialog::ShowDirsOnly);
if (dir == m_downloadDir || dir.isEmpty()) {
return;
}
if (confirmDialogDownloadDir(dir)) {
setDownloadDir(dir);
emit(downloadDirChanged(dir));
}
}
QStringList SettingsManager::getTranslations(const QStringList &keys)
{
QStringList translations;
for(auto& key: keys) {
translations.append(KiwixApp::instance()->getText(key));
}
return translations;
}
void SettingsManager::initSettings()
{
m_kiwixServerPort = m_settings.value("localKiwixServer/port", 8181).toInt();

View File

@ -3,21 +3,20 @@
#include <QObject>
#include <QSettings>
#include "settingsmanagerview.h"
#include "settingsview.h"
class SettingsManager : public QObject
{
Q_OBJECT
Q_PROPERTY(int kiwixServerPort READ getKiwixServerPort NOTIFY portChanged)
Q_PROPERTY(qreal zoomFactor READ getZoomFactor NOTIFY zoomChanged)
Q_PROPERTY(QString downloadDir READ getDownloadDir NOTIFY downloadDirChanged)
Q_PROPERTY(qreal zoomFactor MEMBER m_zoomFactor WRITE setZoomFactor NOTIFY zoomChanged)
Q_PROPERTY(QString downloadDir MEMBER m_downloadDir WRITE setDownloadDir NOTIFY downloadDirChanged)
public:
explicit SettingsManager(QObject *parent = nullptr);
virtual ~SettingsManager() {};
SettingsManagerView* getView();
bool isSettingsViewdisplayed() { return m_settingsViewDisplayed; };
SettingsView* getView();
void setSettings(const QString &key, const QVariant &value);
void deleteSettings(const QString &key);
bool settingsExists(const QString &key);
@ -25,19 +24,14 @@ public:
qreal getZoomFactorByZimId(const QString &id);
public slots:
QStringList getTranslations(const QStringList &keys);
void setKiwixServerPort(int port);
int getKiwixServerPort() { return m_kiwixServerPort; };
void setZoomFactor(qreal zoomFactor);
qreal getZoomFactor() { return m_zoomFactor; };
bool setDownloadDir(QString downloadDir);
QString getDownloadDir() { return m_downloadDir; }
void resetDownloadDir();
void browseDownloadDir();
private:
void initSettings();
bool confirmDialogDownloadDir(const QString& dir);
signals:
void portChanged(int port);
@ -46,7 +40,7 @@ signals:
private:
QSettings m_settings;
bool m_settingsViewDisplayed;
SettingsView *m_view;
int m_kiwixServerPort;
qreal m_zoomFactor;
QString m_downloadDir;

View File

@ -1,23 +0,0 @@
#include "settingsmanagerview.h"
#include "kiwixapp.h"
#include <QFile>
SettingsManagerView::SettingsManagerView(QWidget *parent) : QWebEngineView(parent)
{
page()->setWebChannel(&m_webChannel);
setContextMenuPolicy( Qt::NoContextMenu );
}
void SettingsManagerView::registerObject(const QString& id, QObject* object)
{
m_webChannel.registerObject(id, object);
}
void SettingsManagerView::setHtml()
{
QFile contentFile(":texts/_settingsManager.html");
contentFile.open(QIODevice::ReadOnly);
auto byteContent = contentFile.readAll();
contentFile.close();
QWebEngineView::setHtml(byteContent);
}

View File

@ -1,19 +0,0 @@
#ifndef SETTINGSMANAGERVIEW_H
#define SETTINGSMANAGERVIEW_H
#include <QWebEngineView>
#include <QWebChannel>
class SettingsManagerView : public QWebEngineView
{
Q_OBJECT
public:
SettingsManagerView(QWidget *parent = nullptr);
void registerObject(const QString &id, QObject *object);
void setHtml();
private:
QWebChannel m_webChannel;
};
#endif // SETTINGSMANAGERVIEW_H

105
src/settingsview.cpp Normal file
View File

@ -0,0 +1,105 @@
#include "settingsview.h"
#include "ui_settings.h"
#include "kiwixapp.h"
#include <kiwix/tools.h>
#include <QMessageBox>
#include <QFileDialog>
SettingsView::SettingsView(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Settings)
{
ui->setupUi(this);
QFile file(QString::fromUtf8(":/css/_settingsManager.css"));
file.open(QFile::ReadOnly);
QString styleSheet = QString(file.readAll());
ui->widget->setStyleSheet(styleSheet);
connect(ui->serverPortSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &SettingsView::setKiwixServerPort);
connect(ui->zoomPercentSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &SettingsView::setZoom);
connect(ui->browseButton, &QPushButton::clicked, this, &SettingsView::browseDownloadDir);
connect(ui->resetButton, &QPushButton::clicked, this, &SettingsView::resetDownloadDir);
connect(KiwixApp::instance()->getSettingsManager(), &SettingsManager::downloadDirChanged, this, &SettingsView::onDownloadDirChanged);
connect(KiwixApp::instance()->getSettingsManager(), &SettingsManager::zoomChanged, this, &SettingsView::onZoomChanged);
connect(KiwixApp::instance()->getSettingsManager(), &SettingsManager::portChanged, this, &SettingsView::onServerPortChanged);
ui->settingsLabel->setText(gt("settings"));
ui->serverPortLabel->setText(gt("port-for-local-kiwix-server-setting"));
ui->zoomPercentLabel->setText(gt("zoom-level-setting"));
ui->downloadDirLabel->setText(gt("download-directory-setting"));
ui->resetButton->setText(gt("reset"));
ui->browseButton->setText(gt("browse"));
}
void SettingsView::init(int port, int zoomPercent, const QString &dir)
{
ui->serverPortSpinBox->setValue(port);
ui->zoomPercentSpinBox->setValue(zoomPercent);
ui->downloadDirPath->setText(dir);
}
bool SettingsView::confirmDialogDownloadDir(const QString& dir)
{
auto text = gt("download-dir-dialog-msg");
text = text.replace("{{DIRECTORY}}", dir);
QMessageBox msgBox(
QMessageBox::Question, //Icon
gt("download-dir-dialog-title"), //Title
text, //Text
QMessageBox::Ok | QMessageBox::Cancel //Buttons
);
msgBox.setDefaultButton(QMessageBox::Ok);
int ret = msgBox.exec();
return (ret == QMessageBox::Ok);
}
void SettingsView::resetDownloadDir()
{
auto dir = QString::fromStdString(kiwix::getDataDirectory());
const auto &downloadDir = KiwixApp::instance()->getSettingsManager()->getDownloadDir();
if (dir == downloadDir) {
return;
}
if (confirmDialogDownloadDir(dir)) {
KiwixApp::instance()->getSettingsManager()->setDownloadDir(dir);
}
}
void SettingsView::browseDownloadDir()
{
const auto &downloadDir = KiwixApp::instance()->getSettingsManager()->getDownloadDir();
QString dir = QFileDialog::getExistingDirectory(KiwixApp::instance()->getMainWindow(),
gt("browse-directory"),
downloadDir,
QFileDialog::ShowDirsOnly);
if (dir == downloadDir || dir.isEmpty()) {
return;
}
if (confirmDialogDownloadDir(dir)) {
KiwixApp::instance()->getSettingsManager()->setDownloadDir(dir);
}
}
void SettingsView::setZoom(int zoomPercent)
{
qreal zoomFactor = (qreal) zoomPercent/100;
KiwixApp::instance()->getSettingsManager()->setZoomFactor(zoomFactor);
}
void SettingsView::setKiwixServerPort(int port)
{
KiwixApp::instance()->getSettingsManager()->setKiwixServerPort(port);
}
void SettingsView::onDownloadDirChanged(const QString &dir)
{
ui->downloadDirPath->setText(dir);
}
void SettingsView::onZoomChanged(qreal zoomFactor)
{
qreal zoomPercent = zoomFactor * 100;
ui->zoomPercentSpinBox->setValue(zoomPercent);
}
void SettingsView::onServerPortChanged(int port)
{
ui->serverPortSpinBox->setValue(port);
}

29
src/settingsview.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef SETTINGSVIEW_H
#define SETTINGSVIEW_H
#include <QWidget>
namespace Ui {
class Settings;
}
class SettingsView : public QWidget
{
Q_OBJECT
public:
SettingsView(QWidget *parent = nullptr);
~SettingsView(){};
void init(int port, int zoomPercent, const QString &dir);
public Q_SLOTS:
void resetDownloadDir();
void browseDownloadDir();
void setZoom(int zoomPercent);
void onDownloadDirChanged(const QString &dir);
void onZoomChanged(qreal zoomFactor);
void onServerPortChanged(int port);
void setKiwixServerPort(int port);
private:
bool confirmDialogDownloadDir(const QString& dir);
Ui::Settings *ui;
};
#endif // SETTINGSVIEW_H

View File

@ -8,7 +8,6 @@
#include <QToolTip>
#include <QCursor>
#include <QPainter>
#define QUITIFNULL(VIEW) if (nullptr==(VIEW)) { return; }
#define CURRENTIFNULL(VIEW) if(nullptr==VIEW) { VIEW = currentZimView();}
@ -55,16 +54,17 @@ TabBar::TabBar(QWidget *parent) :
});
connect(app->getAction(KiwixApp::SettingAction), &QAction::triggered,
this, [=]() {
for (int i = 0 ; i < (mp_stackedWidget->count() - 1) ; i++) {
if (qobject_cast<SettingsManagerView*>(mp_stackedWidget->widget(i))) {
SettingsView* view = KiwixApp::instance()->getSettingsManager()->getView();
for (int i = 0 ; i < mp_stackedWidget->count(); i++) {
if (mp_stackedWidget->widget(i) == view) {
setCurrentIndex(i);
return;
}
}
int index = currentIndex() + 1;
SettingsManagerView* view = KiwixApp::instance()->getSettingsManager()->getView();
mp_stackedWidget->insertWidget(index, view);
insertTab(index,QIcon(":/icons/settings.svg"), gt("settings"));
KiwixApp::instance()->setSideBar(KiwixApp::SideBarType::NONE);
QToolButton *tb = new QToolButton(this);
tb->setDefaultAction(KiwixApp::instance()->getAction(KiwixApp::CloseTabAction));
setTabButton(index, QTabBar::RightSide, tb);
@ -294,7 +294,7 @@ void TabBar::onCurrentChanged(int index)
QWidget *w = mp_stackedWidget->widget(index);
if (qobject_cast<SettingsManagerView*>(w)) {
if (qobject_cast<SettingsView*>(w)) {
emit webActionEnabledChanged(QWebEnginePage::Back, false);
emit webActionEnabledChanged(QWebEnginePage::Forward, false);
emit libraryPageDisplayed(false);

View File

@ -79,7 +79,11 @@
</widget>
</item>
<item>
<widget class="QStackedWidget" name="mainView"/>
<widget class="QStackedWidget" name="mainView">
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 255, 255);</string>
</property>
</widget>
</item>
</layout>
</item>

280
ui/settings.ui Normal file
View File

@ -0,0 +1,280 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Settings</class>
<widget class="QWidget" name="Settings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1029</width>
<height>580</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>600</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QWidget" name="widget" native="true">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="mainLayout">
<item>
<widget class="QLabel" name="settingsLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Settings</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="serverPortLabel">
<property name="text">
<string>Port for local kiwix server:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSpinBox" name="serverPortSpinBox">
<property name="frame">
<bool>false</bool>
</property>
<property name="suffix">
<string/>
</property>
<property name="prefix">
<string/>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="zoomPercentLabel">
<property name="text">
<string>Zoom level:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QSpinBox" name="zoomPercentSpinBox">
<property name="frame">
<bool>false</bool>
</property>
<property name="suffix">
<string>%</string>
</property>
<property name="minimum">
<number>30</number>
</property>
<property name="maximum">
<number>500</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="downloadDirLabel">
<property name="text">
<string>Download directory:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="downloadDirPath">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<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>
<item>
<widget class="QPushButton" name="resetButton">
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>Reset</string>
</property>
<property name="autoDefault">
<bool>true</bool>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="browseButton">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>Browse</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<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>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>