Commit 7c6f1c89 by Belákovics Ádám

First

parents
#-------------------------------------------------
#
# Project created by QtCreator 2017-04-24T16:19:49
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = QCircleClient
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += main.cpp\
mainwindow.cpp \
computewidget.cpp \
controller.cpp \
vmchooserdialog.cpp \
sshdialog.cpp
HEADERS += mainwindow.h \
computewidget.h \
controller.h \
vmchooserdialog.h \
computedata.h \
sshdialog.h
FORMS += mainwindow.ui \
computewidget.ui \
vmchooserdialog.ui \
sshdialog.ui
RESOURCES += \
resource.qrc
CONFIG += c++11
INCLUDEPATH += $$PWD/libocci/restclient-cpp/include
INCLUDEPATH += $$PWD/libocci
DEPENDPATH += $$PWD/libocci
LIBS += -L$$PWD/libocci/ -locci -lrestclient-cpp -lcurl -lgobject-2.0 -llasso -lgq
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../../usr/lib/x86_64-linux-gnu/release/ -lqtermwidget5
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../../usr/lib/x86_64-linux-gnu/debug/ -lqtermwidget5
else:unix: LIBS += -L$$PWD/../../../usr/lib/x86_64-linux-gnu/ -lqtermwidget5
INCLUDEPATH += $$PWD/../../../usr/lib/x86_64-linux-gnu
DEPENDPATH += $$PWD/../../../usr/lib/x86_64-linux-gnu
compute.png

498 Bytes

#ifndef COMPUTEDATA
#define COMPUTEDATA
struct ComputeData{
double memory;
int cpu;
int cores;
std::string hostname;
int port;
std::string username;
std::string password;
std::string connString;
};
#endif // COMPUTEDATA
#include "computewidget.h"
#include "ui_computewidget.h"
ComputeWidget::ComputeWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::ComputeWidget)
{
ui->setupUi(this);
ui->lComputeIcon->setPixmap(QPixmap(":/new/icons/compute.png").scaled(80, 55, Qt::KeepAspectRatio));
ui->bRenew->setStyleSheet("background-color:blue");
}
void ComputeWidget::setID(std::string _id){
id = _id;
}
void ComputeWidget::setName(std::string _name){
name = _name;
ui->lHostName->setText(_name.c_str());
}
ComputeWidget::~ComputeWidget()
{
delete ui;
}
void ComputeWidget::on_bRenew_clicked()
{
emit renew(id);
}
void ComputeWidget::on_bStartShutdown_clicked()
{
emit startshutdown(id);
}
void ComputeWidget::on_bWakeUpSleep_clicked()
{
emit wakeupsleep(id);
}
/*!
* \brief Implements a state machine for showing the appropriate buttons for each state
* \param newState
* \param _id
*/
void ComputeWidget::stateChangedHandler(std::string newState, std::string _id){
if(id == _id){ //check if we changed or not
if(newState == "inactive"){
ui->bStartShutdown->setVisible(true);
ui->bStartShutdown->setEnabled(true);
ui->bStartShutdown->setText("Start");
ui->bStartShutdown->setStyleSheet("background-color:green");
ui->bWakeUpSleep->setVisible(false);
ui->bWakeUpSleep->setEnabled(false);
ui->lStatusIcon->setPixmap(QPixmap(":/new/icons/stopped.png").scaled(80, 55, Qt::KeepAspectRatio));
}
else if(newState == "suspended"){
ui->bStartShutdown->setVisible(false);
ui->bStartShutdown->setEnabled(false);
ui->bWakeUpSleep->setVisible(true);
ui->bWakeUpSleep->setEnabled(true);
ui->bWakeUpSleep->setText("Wake up");
ui->bWakeUpSleep->setStyleSheet("background-color:green");
ui->lStatusIcon->setPixmap(QPixmap(":/new/icons/suspended.png").scaled(80, 55, Qt::KeepAspectRatio));
}
else if(newState == "active"){
ui->bStartShutdown->setVisible(true);
ui->bStartShutdown->setEnabled(true);
ui->bStartShutdown->setText("Shut down");
ui->bStartShutdown->setStyleSheet("background-color:red");
ui->bWakeUpSleep->setVisible(true);
ui->bWakeUpSleep->setEnabled(true);
ui->bWakeUpSleep->setText("Sleep");
ui->bWakeUpSleep->setStyleSheet("background-color:yellow");
ui->lStatusIcon->setPixmap(QPixmap(":/new/icons/running.png").scaled(80, 55, Qt::KeepAspectRatio));
}
else
throw std::runtime_error("undefined VM state!");
}
}
#ifndef COMPUTEWIDGET_H
#define COMPUTEWIDGET_H
#include <QWidget>
#include <QPixmap>
namespace Ui {
class ComputeWidget;
}
class ComputeWidget : public QWidget
{
Q_OBJECT
public:
std::string id;
std::string name;
explicit ComputeWidget(QWidget *parent = 0);
void setID(std::string id);
void setName(std::string name);
~ComputeWidget();
signals:
void startshutdown(std::string id);
void wakeupsleep(std::string id);
void renew(std::string id);
public slots:
void stateChangedHandler(std::string newState, std::string id);
private slots:
void on_bRenew_clicked();
void on_bWakeUpSleep_clicked();
void on_bStartShutdown_clicked();
private:
Ui::ComputeWidget *ui;
};
#endif // COMPUTEWIDGET_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ComputeWidget</class>
<widget class="QWidget" name="ComputeWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>672</width>
<height>196</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="6" column="2" rowspan="2">
<widget class="QPushButton" name="bRenew">
<property name="text">
<string>Renew</string>
</property>
</widget>
</item>
<item row="4" column="2" rowspan="2">
<widget class="QPushButton" name="bWakeUpSleep">
<property name="text">
<string>Wake up</string>
</property>
</widget>
</item>
<item row="2" column="2" rowspan="2">
<widget class="QPushButton" name="bStartShutdown">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="2" column="0" rowspan="5">
<widget class="QLabel" name="lComputeIcon">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="lHostName">
<property name="text">
<string>Virtual Machine</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1" rowspan="6">
<widget class="QLabel" name="lStatusIcon">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
#include "controller.h"
///Implementation for class Controller
/*!
* \brief Connects to the cloud server specified by the url
* \param url
* \return
*/
bool Controller::connect(std::string url){
session = new OcciClient::OcciSession(url.c_str(), true, true);
return true; //TODO validation
}
/*!
* \brief Logs in to a connected server, loads all data into the Controller
* \param username
* \param password
* \return
*/
bool Controller::login(std::string username, std::string password){
session->circleOcciLogin(username, password);
if(username == "admin" && password == "admin"){ //TODO TODO lib should handle this
refresh(); //initialize data
return true;
}
return false;
}
/*!
* \brief Refreshes all data (Computes, Templates), communicates with the server
*/
void Controller::refresh(){
allCompute.clear();
for(auto c : OcciClient::Compute::getComputeInstances(session))
allCompute.push_back(c);
allTemplate.clear();
for (auto t : OcciClient::getTemplates(session))
allTemplate.push_back(t);
}
///Data Access
/// ----------------------------------------------------------------------------------
/*!
* \brief Returns with an std::vector of the VM ids
* \return
*/
std::vector<std::string> Controller::getVMs(){
std::vector<std::string> VMs;
for(auto c : allCompute){
VMs.push_back(c->getHostname());
}
return VMs;
}
/*!
* \brief Returns with an std::vector of the Template ids
* \return
*/
std::vector<std::string> Controller::getTemplates(){
std::vector<std::string> templates;
for(auto t : allTemplate){
templates.push_back(t);
}
return templates;
}
/*!
* \brief Returns the state of the VM specified by the id
* \param id
* \return
*/
std::string Controller::getState(std::string id){
return allCompute.at(std::stoi(id))->getState();
}
/*!
* \brief Returns with a ComputeData objects which contains all information about the specified VM
* \param id
* \return
*/
ComputeData Controller::getDataByID(std::string id){
ComputeData data;
data.memory = allCompute.at(std::stoi(id))->getMemory();
data.cpu = allCompute.at(std::stoi(id))->getCpuShare();
data.cores = allCompute.at(std::stoi(id))->getCores();
data.hostname = allCompute.at(std::stoi(id))->getCredentialHost();
data.port = allCompute.at(std::stoi(id))->getCredentialPort();
data.username = allCompute.at(std::stoi(id))->getCredentialUsername();
data.password = allCompute.at(std::stoi(id))->getCredentialPassword();
data.connString = allCompute.at(std::stoi(id))->getCredentialCommand();
return data;
}
///Actions
/// ----------------------------------------------------------------------------------
/*!
* \brief Renew action
* \param id
*/
void Controller::renewByID(std::string id){
allCompute.at(std::stoi(id))->renew();
refresh();
}
/*!
* \brief Start action
* \param id
*/
void Controller::startByID(std::string id){
allCompute.at(std::stoi(id))->start();
refresh();
}
/*!
* \brief Shutdown action
* \param id
*/
void Controller::shutdownByID(std::string id){
allCompute.at(std::stoi(id))->shutoff(); //TODO modositani shutdownra tesztelesnel csak a shutoff mukodik
refresh();
}
/*!
* \brief Wakeup action
* \param id
*/
void Controller::wakeupByID(std::string id){
allCompute.at(std::stoi(id))->wakeup();
refresh();
}
/*!
* \brief Sleep action
* \param id
*/
void Controller::sleepByID(std::string id){
allCompute.at(std::stoi(id))->sleep();
refresh();
}
/*!
* \brief Creates a new Compute by the Template
* \param id
*/
void Controller::newCompute(Template t){
OcciClient::Compute::createComputeInstance(session, t);
refresh();
}
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <QObject>
#include <vector>
#include <memory>
#include "occilib.h"
#include "computedata.h"
class Controller
{
public:
OcciClient::OcciSession* session;
std::vector<std::shared_ptr<OcciClient::Compute> > allCompute;
std::vector<Template> allTemplate;
bool connect(std::string url);
bool login(std::string username, std::string password);
void refresh();
void renewByID(std::string id);
void startByID(std::string id);
void shutdownByID(std::string id);
void wakeupByID(std::string id);
void sleepByID(std::string id);
void newCompute(Template);
ComputeData getDataByID(std::string id);
std::string getState(std::string id);
std::vector<std::string> getVMs();
std::vector<std::string> getTemplates();
};
#endif // CONTROLLER_H
libocci @ e5ef02d9
Subproject commit e5ef02d9e0cab1cbeac1b9ff929d8e2161a46a01
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.showMaximized();
return a.exec();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "sshdialog.h"
///Implementation for class MainWindow
///
///---------------------------------------------------------------------------------------------------
/// Basic Methods
/*!
* \brief Constructor, sets up ui, disable tabs other than login
* \param parent
*/
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->tabWidget->setTabEnabled(1, false);
ui->tabWidget->setTabEnabled(2, false);
}
/*!
* \brief Destructor
*/
MainWindow::~MainWindow()
{
delete ui;
}
///---------------------------------------------------------------------------------------------------
/// Methods for loading data to the UI
/*!
* \brief Adds a VM to the listWidget, sets its id, connects all Quick Action buttons
* \param id
* \param name
*/
void MainWindow::addVM(std::string id, std::string name){
QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
ComputeWidget* cw = new ComputeWidget();
cw->setID(id);
cw->setName(name);
connect(this, SIGNAL(stateChanged(std::string, std::string)), cw, SLOT(stateChangedHandler(std::string, std::string)));
emit stateChanged(myController.getState(id), id);
connect(cw, SIGNAL(renew(std::string)), this, SLOT(renewClicked(std::string)));
connect(cw, SIGNAL(startshutdown(std::string)), this, SLOT(startshutdownClicked(std::string)));
connect(cw, SIGNAL(wakeupsleep(std::string)), this, SLOT(wakeupsleepClicked(std::string)));
item->setSizeHint(cw->minimumSize());
ui->listWidget->addItem(item);
ui->listWidget->setItemWidget(item, cw);
}
/*!
* \brief loads all data to the UI, which are stored in Controller, DOES NOT COMMUNICATE WITH THE CLOUD SERVER!!
*/
void MainWindow::loadAllData(){
VM_names = myController.getVMs();
ui->listWidget->clear();
for(size_t i = 0; i < VM_names.size(); i++)
addVM(std::to_string(i), VM_names.at(i));
ui->lwTemplates->clear();
for(auto t : myController.getTemplates())
ui->lwTemplates->addItem(t.c_str());
}
/*!
* \brief Loads all data for a VM specified by the id, does NOT communicate with the cloud server!!
* \param id
*/
void MainWindow::loadVMData(std::string id){
ui->lStatus->setText(myController.getState(id).c_str());
ComputeData data = myController.getDataByID(id.c_str());
currentSelectedVM = data;
ui->lCPU->setText(std::to_string(data.cpu).c_str());
ui->lMemory->setText(std::to_string(data.memory).c_str());
ui->lCores->setText(std::to_string(data.cores).c_str());
ui->lHostname->setText((data.hostname + ":" + std::to_string(data.port)).c_str());
ui->lUsernameVM->setText(data.username.c_str());
ui->lPasswordVM->setText(data.password.c_str());
}
///---------------------------------------------------------------------------------------------------
/// Button handlers
///Tab 0 - Login Screen
/*!
* \brief Login Button handler, connects to server, if authentication is succesful enables all tabs, and loads all data
*/
void MainWindow::on_bLogin_clicked()
{
std::string serverUrl = ui->iCloudServer->text().toStdString();
myController.connect(serverUrl);
std::string username = ui->iUsername->text().toStdString();
std::string password = ui->iPassword->text().toStdString();
if(!myController.login(username, password)){
ui->lInfo->setText("Invalid username or password...");
return;
}
ui->tabWidget->setTabEnabled(1, true);
ui->tabWidget->setTabEnabled(2, true);
loadAllData();
ui->tabWidget->setCurrentIndex(1);
}
/// Tab 1 - Virtual Machines
/*!
* \brief handles Renew button, all static data is refreshed
* \param id
*/
void MainWindow::renewClicked(std::string id){
myController.renewByID(id);
loadVMData(id);
ui->listWidget->item(std::stoi(id))->setSelected(true);
}
/*!
* \brief handles Start/Shutdown button (fetches data from server)
* \param id
*/
void MainWindow::startshutdownClicked(std::string id){
std::string state = myController.getState(id);
if(state == "inactive"){
myController.startByID(id);
}
else {
myController.shutdownByID(id);
}
emit stateChanged(myController.getState(id), id);
loadVMData(id);
ui->listWidget->item(std::stoi(id))->setSelected(true);
}
/*!
* \brief Handles the Wakeup/Sleep toggle button (fetches data from server)
* \param id
*/
void MainWindow::wakeupsleepClicked(std::string id){
std::string state = myController.getState(id);
if(state == "active"){ //sleep
myController.sleepByID(id);
}
else if(state == "suspended" || state == "inactive"){ //wake up
myController.wakeupByID(id);
}
else{
throw std::runtime_error("undefined VM STATE!!!");
}
emit stateChanged(myController.getState(id), id);
loadVMData(id);
ui->listWidget->item(std::stoi(id))->setSelected(true);
}
/*!
* \brief handles Renew button (fetches data from server)
* \param id
*/
void MainWindow::on_listWidget_clicked(const QModelIndex &index)
{
loadVMData(std::to_string(index.row()));
}
/*!
* \brief handles Refresh button, refreshes Controller's data and loads to the UI (fetches data from server)
*/
void MainWindow::on_bRefresh_clicked()
{
myController.refresh();
loadAllData();
}
/*!
* \brief handles new VM button, Opens a dialog for choosing from templates
*/
void MainWindow::on_bNewVM_clicked()
{
VMChooserDialog* v = new VMChooserDialog(this);
v->set_templates(getTemplates(myController.session));
connect(v, SIGNAL(send_chosen_template(Template)), this, SLOT(receive_chosen_template(Template)));
v->exec();
}
/*!
* \brief Slot for dialog, creates new VM by the chosen template
* \param t
*/
void MainWindow::receive_chosen_template(Template t){
myController.newCompute(t);
loadAllData();
}
/*!
* \brief handler, shows/hides VM password
*/
void MainWindow::on_bShowPassword_clicked()
{
if(ui->lPasswordVM->echoMode() == QLineEdit::Password){
ui->lPasswordVM->setEchoMode(QLineEdit::Normal);
ui->bShowPassword->setText("Hide");
}
else if(ui->lPasswordVM->echoMode() == QLineEdit::Normal){
ui->lPasswordVM->setEchoMode(QLineEdit::Password);
ui->bShowPassword->setText("Show");
}
else
ui->lPasswordVM->setEchoMode(QLineEdit::Password);
}
void MainWindow::on_bConnect_clicked()
{
QTermWidget* console = new QTermWidget(0);
console->setShellProgram("/usr/bin/sshpass");
//QString connString = currentSelectedVM.connString; //use outside of devenv
QString connString = "-p WdqxhS7BmK ssh -o StrictHostKeyChecking=no cloud@vm.ik.bme.hu -p 3309"; //test stub
QStringList args = connString.split(" ");
console->setArgs(args);
console->startShellProgram();
SSHDialog* sshdialog = new SSHDialog();
sshdialog->setWindowTitle((currentSelectedVM.hostname + " " + std::to_string(currentSelectedVM.port)).c_str());
sshdialog->setSSHConsole(console);
sshdialog->show();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QPushButton>
#include <QListWidget>
#include <computewidget.h>
#include "libocci/occilib.h"
#include "controller.h"
#include "vmchooserdialog.h"
#include <qtermwidget5/qtermwidget.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void addVM(std::string id, std::string name);
void loadAllData();
void loadVMData(std::string id);
signals:
void stateChanged(std::string state, std::string id);
private slots:
void on_bLogin_clicked();
void renewClicked(std::string);
void startshutdownClicked(std::string);
void wakeupsleepClicked(std::string);
void receive_chosen_template(Template);
void on_listWidget_clicked(const QModelIndex &index);
void on_bRefresh_clicked();
void on_bNewVM_clicked();
void on_bShowPassword_clicked();
void on_bConnect_clicked();
private:
Ui::MainWindow *ui;
Controller myController;
std::vector<std::string> VM_names;
ComputeData currentSelectedVM;
};
#endif // MAINWINDOW_H
This diff is collapsed. Click to expand it.
<RCC>
<qresource prefix="/new/icons">
<file>compute.png</file>
<file>cloud icon.png</file>
<file>running.png</file>
<file>suspended.png</file>
<file>stopped.png</file>
</qresource>
<qresource prefix="/">
<file>running.png</file>
</qresource>
</RCC>
running.png

1.29 KB

#include "sshdialog.h"
#include "ui_sshdialog.h"
SSHDialog::SSHDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SSHDialog)
{
ui->setupUi(this);
}
void SSHDialog::setSSHConsole(QWidget* ssh){
ui->gridLayout_2->addWidget(ssh);
}
SSHDialog::~SSHDialog()
{
delete ui;
}
#ifndef SSHDIALOG_H
#define SSHDIALOG_H
#include <QDialog>
#include <QtWidgets>
namespace Ui {
class SSHDialog;
}
class SSHDialog : public QDialog
{
Q_OBJECT
public:
explicit SSHDialog(QWidget *parent = 0);
~SSHDialog();
void setSSHConsole(QWidget* ssh);
private:
Ui::SSHDialog *ui;
};
#endif // SSHDIALOG_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SSHDialog</class>
<widget class="QDialog" name="SSHDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>653</width>
<height>378</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout_2"/>
</widget>
<resources/>
<connections/>
</ui>
stopped.png

196 Bytes

suspended.png

205 Bytes

#include "vmchooserdialog.h"
#include "ui_vmchooserdialog.h"
VMChooserDialog::VMChooserDialog(QWidget *parent):QDialog(parent), ui(new Ui::VMChooserDialog)
{
ui->setupUi(this);
}
VMChooserDialog::~VMChooserDialog(){
delete ui;
}
void VMChooserDialog::on_buttonBox_accepted()
{
emit send_chosen_template(templates.at(ui->lwTemplates->currentIndex().row()));
this->done(1);
}
void VMChooserDialog::on_buttonBox_rejected()
{
this->done(-1);
}
void VMChooserDialog::set_templates(std::vector<Template> _templates){
templates = _templates;
for(auto t : templates){
ui->lwTemplates->addItem(QString::fromUtf8(t.c_str()));
}
}
#ifndef VMCHOOSERDIALOG_H
#define VMCHOOSERDIALOG_H
#include <QDialog>
#include "occilib.h"
namespace Ui{
class VMChooserDialog;
}
class VMChooserDialog : public QDialog
{
Q_OBJECT
public:
explicit VMChooserDialog(QWidget *parent = 0);
void set_templates(std::vector<Template> templates);
~VMChooserDialog();
signals:
void send_chosen_template(Template);
private slots:
void on_buttonBox_accepted();
void on_buttonBox_rejected();
private:
Ui::VMChooserDialog* ui;
std::vector<Template> templates;
};
#endif // VMCHOOSERDIALOG_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VMChooserDialog</class>
<widget class="VMChooserDialog" name="VMChooserDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>458</width>
<height>355</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<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 row="1" column="1">
<widget class="QListWidget" name="lwTemplates"/>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer_3">
<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="1">
<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="1">
<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="1" column="2">
<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>
<customwidgets>
<customwidget>
<class>VMChooserDialog</class>
<extends>QWidget</extends>
<header>vmchooserdialog.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment