summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEran Mizrahi <erasmux@gmail.com>2017-12-13 16:18:54 +0200
committerEran Mizrahi <erasmux@gmail.com>2017-12-13 22:27:11 +0200
commita5bb70f53bc20f36f695ac5cd9f8b91163f694eb (patch)
tree0d6f2c1e2bce7497c59785dd6de645d741620193
parent0586b2856b0b8973e5781b9b0a1b5e5acac20532 (diff)
Wait for injected processes on MO close
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/ilockedwaitingforprocess.h2
-rw-r--r--src/lockeddialog.cpp37
-rw-r--r--src/lockeddialog.h33
-rw-r--r--src/lockeddialogbase.cpp73
-rw-r--r--src/lockeddialogbase.h62
-rw-r--r--src/mainwindow.cpp20
-rw-r--r--src/mainwindow.h6
-rw-r--r--src/organizercore.cpp45
-rw-r--r--src/organizercore.h1
-rw-r--r--src/waitingonclosedialog.cpp71
-rw-r--r--src/waitingonclosedialog.h56
-rw-r--r--src/waitingonclosedialog.ui119
13 files changed, 443 insertions, 87 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 39aabb91..914bdd12 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -42,7 +42,9 @@ SET(organizer_SRCS
main.cpp
loghighlighter.cpp
logbuffer.cpp
+ lockeddialogbase.cpp
lockeddialog.cpp
+ waitingonclosedialog.cpp
loadmechanism.cpp
installationmanager.cpp
helper.cpp
@@ -128,7 +130,9 @@ SET(organizer_HDRS
mainwindow.h
loghighlighter.h
logbuffer.h
+ lockeddialogbase.h
lockeddialog.h
+ waitingonclosedialog.h
loadmechanism.h
installationmanager.h
helper.h
@@ -200,6 +204,7 @@ SET(organizer_UIS
messagedialog.ui
mainwindow.ui
lockeddialog.ui
+ waitingonclosedialog.ui
installdialog.ui
finddialog.ui
editexecutablesdialog.ui
diff --git a/src/ilockedwaitingforprocess.h b/src/ilockedwaitingforprocess.h
index 5bf1f1ca..9475ddb9 100644
--- a/src/ilockedwaitingforprocess.h
+++ b/src/ilockedwaitingforprocess.h
@@ -6,7 +6,7 @@ class QString;
class ILockedWaitingForProcess
{
public:
- virtual bool unlockForced() = 0;
+ virtual bool unlockForced() const = 0;
virtual void setProcessName(QString const &) = 0;
};
diff --git a/src/lockeddialog.cpp b/src/lockeddialog.cpp
index 09538a0f..143d5838 100644
--- a/src/lockeddialog.cpp
+++ b/src/lockeddialog.cpp
@@ -26,10 +26,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <Qt> // for Qt::FramelessWindowHint, etc
LockedDialog::LockedDialog(QWidget *parent, bool unlockByButton)
- : QDialog(parent)
+ : LockedDialogBase(parent, !unlockByButton)
, ui(new Ui::LockedDialog)
- , m_Unlocked(false)
- , m_allowClose(!unlockByButton)
{
ui->setupUi(this);
@@ -38,7 +36,7 @@ LockedDialog::LockedDialog(QWidget *parent, bool unlockByButton)
// seem to work. We will ignore pressing the close button if unlockByButton == true
Qt::WindowFlags flags =
this->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint;
- if (!unlockByButton)
+ if (m_allowClose)
flags |= Qt::WindowCloseButtonHint;
this->setWindowFlags(flags);
@@ -48,13 +46,6 @@ LockedDialog::LockedDialog(QWidget *parent, bool unlockByButton)
ui->verticalLayout->addItem(
new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
}
-
- if (parent != nullptr) {
- QPoint position = parent->mapToGlobal(QPoint(parent->width() / 2, parent->height() / 2));
- position.rx() -= this->width() / 2;
- position.ry() -= this->height() / 2;
- move(position);
- }
}
LockedDialog::~LockedDialog()
@@ -68,35 +59,13 @@ void LockedDialog::setProcessName(const QString &name)
ui->processLabel->setText(name);
}
-
-void LockedDialog::resizeEvent(QResizeEvent *event)
-{
- QWidget *par = parentWidget();
- if (par != nullptr) {
- QPoint position = par->mapToGlobal(QPoint(par->width() / 2, par->height() / 2));
- position.rx() -= event->size().width() / 2;
- position.ry() -= event->size().height() / 2;
- move(position);
- }
-}
-
void LockedDialog::on_unlockButton_clicked()
{
unlock();
}
-void LockedDialog::reject()
-{
- if (m_allowClose)
- unlock();
-}
-
-bool LockedDialog::unlockForced() {
- return m_Unlocked;
-}
-
void LockedDialog::unlock() {
- m_Unlocked = true;
+ LockedDialogBase::unlock();
ui->label->setText("unlocking may take a few seconds");
ui->unlockButton->setEnabled(false);
}
diff --git a/src/lockeddialog.h b/src/lockeddialog.h
index 82a15a93..36c16429 100644
--- a/src/lockeddialog.h
+++ b/src/lockeddialog.h
@@ -17,16 +17,9 @@ You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef LOCKEDDIALOG_H
-#define LOCKEDDIALOG_H
+#pragma once
-#include "ilockedwaitingforprocess.h"
-#include <QDialog> // for QDialog
-#include <QObject> // for Q_OBJECT, slots
-#include <QString> // for QString
-
-class QResizeEvent;
-class QWidget;
+#include "lockeddialogbase.h"
namespace Ui {
class LockedDialog;
@@ -40,7 +33,7 @@ namespace Ui {
* data on which Mod Organizer works. After the UI is unlocked (manually or after the
* external application closed) MO will refresh all of its data sources
**/
-class LockedDialog : public QDialog, public ILockedWaitingForProcess
+class LockedDialog : public LockedDialogBase
{
Q_OBJECT
@@ -48,35 +41,17 @@ public:
explicit LockedDialog(QWidget *parent = 0, bool unlockByButton = false);
~LockedDialog();
- /**
- * @brief see if the user clicked the unlock-button
- *
- * @return true if the user clicked the unlock button
- **/
- bool unlockForced() override;
-
- /**
- * @brief set the name of the process being run
- * @param name of process
- */
void setProcessName(const QString &name) override;
protected:
- virtual void resizeEvent(QResizeEvent *event);
-
- virtual void reject();
+ void unlock() override;
private slots:
void on_unlockButton_clicked();
private:
- void unlock();
Ui::LockedDialog *ui;
- bool m_Unlocked;
- bool m_allowClose;
};
-
-#endif // LOCKEDDIALOG_H
diff --git a/src/lockeddialogbase.cpp b/src/lockeddialogbase.cpp
new file mode 100644
index 00000000..b18f7429
--- /dev/null
+++ b/src/lockeddialogbase.cpp
@@ -0,0 +1,73 @@
+/*
+Copyright (C) 2012 Sebastian Herbord. All rights reserved.
+
+This file is part of Mod Organizer.
+
+Mod Organizer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Mod Organizer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "lockeddialogbase.h"
+
+#include <QPoint>
+#include <QResizeEvent>
+#include <QWidget>
+#include <Qt> // for Qt::FramelessWindowHint, etc
+
+LockedDialogBase::LockedDialogBase(QWidget *parent, bool allowClose)
+ : QDialog(parent)
+ , m_Unlocked(false)
+ , m_Canceled(false)
+ , m_allowClose(allowClose)
+{
+ if (parent != nullptr) {
+ QPoint position = parent->mapToGlobal(QPoint(parent->width() / 2, parent->height() / 2));
+ position.rx() -= this->width() / 2;
+ position.ry() -= this->height() / 2;
+ move(position);
+ }
+}
+
+void LockedDialogBase::resizeEvent(QResizeEvent *event)
+{
+ QWidget *par = parentWidget();
+ if (par != nullptr) {
+ QPoint position = par->mapToGlobal(QPoint(par->width() / 2, par->height() / 2));
+ position.rx() -= event->size().width() / 2;
+ position.ry() -= event->size().height() / 2;
+ move(position);
+ }
+}
+
+void LockedDialogBase::reject()
+{
+ if (m_allowClose)
+ unlock();
+}
+
+bool LockedDialogBase::unlockForced() const {
+ return m_Unlocked;
+}
+
+bool LockedDialogBase::canceled() const {
+ return m_Canceled;
+}
+
+void LockedDialogBase::unlock() {
+ m_Unlocked = true;
+}
+
+void LockedDialogBase::cancel() {
+ m_Canceled = true;
+}
+
diff --git a/src/lockeddialogbase.h b/src/lockeddialogbase.h
new file mode 100644
index 00000000..3c974a38
--- /dev/null
+++ b/src/lockeddialogbase.h
@@ -0,0 +1,62 @@
+/*
+Copyright (C) 2012 Sebastian Herbord. All rights reserved.
+
+This file is part of Mod Organizer.
+
+Mod Organizer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Mod Organizer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "ilockedwaitingforprocess.h"
+#include <QDialog> // for QDialog
+#include <QObject> // for Q_OBJECT, slots
+#include <QString> // for QString
+
+class QResizeEvent;
+class QWidget;
+
+/**
+ * a small borderless dialog displayed while the Mod Organizer UI is locked
+ * The dialog contains only a label and a button to force the UI to be unlocked
+ *
+ * The UI gets locked while running external applications since they may modify the
+ * data on which Mod Organizer works. After the UI is unlocked (manually or after the
+ * external application closed) MO will refresh all of its data sources
+ **/
+class LockedDialogBase : public QDialog, public ILockedWaitingForProcess
+{
+ Q_OBJECT
+
+public:
+ explicit LockedDialogBase(QWidget *parent, bool allowClose);
+
+ bool unlockForced() const override;
+
+ virtual bool canceled() const;
+
+protected:
+
+ virtual void resizeEvent(QResizeEvent *event);
+
+ virtual void reject();
+
+ virtual void unlock();
+
+ virtual void cancel();
+
+ bool m_Unlocked;
+ bool m_Canceled;
+ bool m_allowClose;
+};
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 1e1a4558..85808e8d 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -59,6 +59,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "messagedialog.h"
#include "installationmanager.h"
#include "lockeddialog.h"
+#include "waitingonclosedialog.h"
#include "logbuffer.h"
#include "downloadlistsortproxy.h"
#include "motddialog.h"
@@ -855,6 +856,8 @@ void MainWindow::showEvent(QShowEvent *event)
void MainWindow::closeEvent(QCloseEvent* event)
{
+ m_closing = true;
+
if (m_OrganizerCore.downloadManager()->downloadsInProgress()) {
if (QMessageBox::question(this, tr("Downloads in progress"),
tr("There are still downloads in progress, do you really want to quit?"),
@@ -866,6 +869,16 @@ void MainWindow::closeEvent(QCloseEvent* event)
}
}
+ HANDLE injected_process_still_running = m_OrganizerCore.findAndOpenAUSVFSProcess();
+ if (injected_process_still_running != INVALID_HANDLE_VALUE)
+ {
+ m_OrganizerCore.waitForApplication(injected_process_still_running);
+ if (!m_closing) { // if operation cancelled
+ event->ignore();
+ return;
+ }
+ }
+
setCursor(Qt::WaitCursor);
}
@@ -1471,7 +1484,10 @@ ILockedWaitingForProcess* MainWindow::lock()
++m_LockCount;
return m_LockDialog;
}
- m_LockDialog = new LockedDialog(this, true);
+ if (m_closing)
+ m_LockDialog = new WaitingOnCloseDialog(this);
+ else
+ m_LockDialog = new LockedDialog(this, true);
m_LockDialog->setModal(true);
m_LockDialog->show();
setEnabled(false);
@@ -1489,6 +1505,8 @@ void MainWindow::unlock()
}
--m_LockCount;
if (m_LockCount == 0) {
+ if (m_closing && m_LockDialog->canceled())
+ m_closing = false;
m_LockDialog->hide();
m_LockDialog->deleteLater();
m_LockDialog = nullptr;
diff --git a/src/mainwindow.h b/src/mainwindow.h
index f6f11157..575bf020 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -35,7 +35,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
//when I get round to cleaning up main.cpp
struct Executable;
class CategoryFactory;
-class LockedDialog;
+class LockedDialogBase;
class OrganizerCore;
#include "plugincontainer.h" //class PluginContainer;
class PluginListSortProxy;
@@ -348,9 +348,11 @@ private:
bool m_DidUpdateMasterList;
- LockedDialog *m_LockDialog { nullptr };
+ LockedDialogBase *m_LockDialog { nullptr };
uint64_t m_LockCount { 0 };
+ bool m_closing{ false };
+
std::vector<std::pair<QString, QHeaderView*>> m_PersistedGeometry;
enum class ShortcutType {
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index 1f42bf95..c4bcaf3d 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -1367,26 +1367,8 @@ bool OrganizerCore::waitForProcessCompletion(HANDLE handle, LPDWORD exitCode, IL
QThread::msleep(500);
// search if there is another usvfs process active and if so wait for it
- // in theory a querySize of 1 is probably enough since the MO process doesn't seem to be returned by GetVFSProcessList
- constexpr size_t querySize = 2; // just to be on the safe side
- DWORD pids[querySize];
- size_t found = querySize;
- if (!::GetVFSProcessList(&found, pids)) {
- qWarning() << "Failed waiting for process completion : GetVFSProcessList failed?!";
- break;
- }
-
- for (size_t i = 0; i < found; ++i) {
- if (pids[i] == GetCurrentProcessId())
- continue; // obviously don't wait for MO process
- handle = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION|SYNCHRONIZE, FALSE, pids[i]);
- if (handle == INVALID_HANDLE_VALUE) {
- qWarning() << "Failed waiting for process completion : OpenProcess failed" << GetLastError();
- continue;
- }
- newHandle = true;
- break;
- }
+ handle = findAndOpenAUSVFSProcess();
+ newHandle = handle != INVALID_HANDLE_VALUE;
}
}
@@ -1403,6 +1385,29 @@ bool OrganizerCore::waitForProcessCompletion(HANDLE handle, LPDWORD exitCode, IL
return res == WAIT_OBJECT_0;
}
+HANDLE OrganizerCore::findAndOpenAUSVFSProcess() {
+ // in theory a querySize of 1 is probably enough since the MO process doesn't seem to be returned by GetVFSProcessList
+ constexpr size_t querySize = 2; // just to be on the safe side
+ DWORD pids[querySize];
+ size_t found = querySize;
+ if (!::GetVFSProcessList(&found, pids)) {
+ qWarning() << "Failed seeking USVFS processes : GetVFSProcessList failed?!";
+ return INVALID_HANDLE_VALUE;
+ }
+
+ for (size_t i = 0; i < found; ++i) {
+ if (pids[i] == GetCurrentProcessId())
+ continue; // obviously don't wait for MO process
+ HANDLE handle = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE, FALSE, pids[i]);
+ if (handle != INVALID_HANDLE_VALUE)
+ return handle;
+ else
+ qWarning() << "Failed openning USVFS process " << pids[i] << " : OpenProcess failed" << GetLastError();
+ }
+
+ return INVALID_HANDLE_VALUE;
+}
+
bool OrganizerCore::onAboutToRun(
const std::function<bool(const QString &)> &func)
{
diff --git a/src/organizercore.h b/src/organizercore.h
index f8806289..cf030e0a 100644
--- a/src/organizercore.h
+++ b/src/organizercore.h
@@ -206,6 +206,7 @@ public:
HANDLE runShortcut(const QString &title);
HANDLE startApplication(const QString &executable, const QStringList &args, const QString &cwd, const QString &profile);
bool waitForApplication(HANDLE processHandle, LPDWORD exitCode = nullptr);
+ HANDLE findAndOpenAUSVFSProcess();
bool onModInstalled(const std::function<void (const QString &)> &func);
bool onAboutToRun(const std::function<bool (const QString &)> &func);
bool onFinishedRun(const std::function<void (const QString &, unsigned int)> &func);
diff --git a/src/waitingonclosedialog.cpp b/src/waitingonclosedialog.cpp
new file mode 100644
index 00000000..565d0a36
--- /dev/null
+++ b/src/waitingonclosedialog.cpp
@@ -0,0 +1,71 @@
+/*
+Copyright (C) 2012 Sebastian Herbord. All rights reserved.
+
+This file is part of Mod Organizer.
+
+Mod Organizer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Mod Organizer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "waitingonclosedialog.h"
+#include "ui_waitingonclosedialog.h"
+
+#include <QPoint>
+#include <QResizeEvent>
+#include <QWidget>
+#include <Qt> // for Qt::FramelessWindowHint, etc
+
+WaitingOnCloseDialog::WaitingOnCloseDialog(QWidget *parent)
+ : LockedDialogBase(parent,true)
+ , ui(new Ui::WaitingOnCloseDialog)
+{
+ ui->setupUi(this);
+
+ // Supposedly the Qt::CustomizeWindowHint should use a customized window
+ // allowing us to select if there is a close button. In practice this doesn't
+ // seem to work. We will ignore pressing the close button if unlockByButton == true
+ Qt::WindowFlags flags =
+ this->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint;
+ if (m_allowClose)
+ flags |= Qt::WindowCloseButtonHint;
+ this->setWindowFlags(flags);
+}
+
+WaitingOnCloseDialog::~WaitingOnCloseDialog()
+{
+ delete ui;
+}
+
+
+void WaitingOnCloseDialog::setProcessName(const QString &name)
+{
+ ui->processLabel->setText(name);
+}
+
+void WaitingOnCloseDialog::on_closeButton_clicked()
+{
+ unlock();
+}
+
+void WaitingOnCloseDialog::on_cancelButton_clicked()
+{
+ cancel();
+ unlock();
+}
+
+void WaitingOnCloseDialog::unlock() {
+ LockedDialogBase::unlock();
+ ui->label->setText("unlocking may take a few seconds");
+ ui->closeButton->setEnabled(false);
+ ui->cancelButton->setEnabled(false);
+}
diff --git a/src/waitingonclosedialog.h b/src/waitingonclosedialog.h
new file mode 100644
index 00000000..6650c390
--- /dev/null
+++ b/src/waitingonclosedialog.h
@@ -0,0 +1,56 @@
+/*
+Copyright (C) 2012 Sebastian Herbord. All rights reserved.
+
+This file is part of Mod Organizer.
+
+Mod Organizer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Mod Organizer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "lockeddialogbase.h"
+
+namespace Ui {
+ class WaitingOnCloseDialog;
+}
+
+/**
+ * Similar to the LockedDialog but used for waiting on running process during
+ * a process close request which requries a slightly different dialog.
+ **/
+class WaitingOnCloseDialog : public LockedDialogBase
+{
+ Q_OBJECT
+
+public:
+ explicit WaitingOnCloseDialog(QWidget *parent = 0);
+ ~WaitingOnCloseDialog();
+
+ bool canceled() const { return m_Canceled; }
+
+ void setProcessName(const QString &name) override;
+
+protected:
+
+ void unlock() override;
+
+private slots:
+
+ void on_closeButton_clicked();
+ void on_cancelButton_clicked();
+
+private:
+
+ Ui::WaitingOnCloseDialog *ui;
+};
diff --git a/src/waitingonclosedialog.ui b/src/waitingonclosedialog.ui
new file mode 100644
index 00000000..9c7818e0
--- /dev/null
+++ b/src/waitingonclosedialog.ui
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WaitingOnCloseDialog</class>
+ <widget class="QDialog" name="WaitingOnCloseDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>317</width>
+ <height>151</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Waiting for virtualized processes</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="1,0,0">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="toolTip">
+ <string>This dialog should disappear automatically if the application/game is done.</string>
+ </property>
+ <property name="text">
+ <string>Virtualized processes are still running, it is prefered to keep MO running until they are finished.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer1">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="processLabel">
+ <property name="font">
+ <font>
+ <italic>true</italic>
+ </font>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">color: grey;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,0">
+ <item>
+ <widget class="QPushButton" name="closeButton">
+ <property name="text">
+ <string>Close Now</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <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="cancelButton">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>