- fixed os selection row for one item

- implemented new executeCommand() function
- further implemented backend functionality
This commit is contained in:
Dorian Zedler 2020-11-20 15:09:36 +01:00
parent b73d45d955
commit ba722f1634
Signed by: dorian
GPG key ID: D3B255CB8BC7CD37
9 changed files with 305 additions and 188 deletions

View file

@ -40,6 +40,7 @@ using namespace std;
class LinboBackend : public QObject
{
Q_OBJECT
Q_PROPERTY(LinboState state READ getState NOTIFY stateChanged)
public:
explicit LinboBackend(QObject *parent = nullptr);
@ -49,9 +50,10 @@ public:
Partitioning,
Starting,
Syncing,
Installing
Reinstalling
};
LinboState getState();
LinboConfig* getConfig();
QList<LinboOs*> getOperatingSystems();
@ -64,25 +66,40 @@ protected:
LinboDiskPartition* read_partition(ifstream* input);
void read_globals( ifstream* input, LinboConfig* config );
void saveappend( QStringList& command, const QString& item );
QStringList mksyncstartcommand(LinboConfig& config, LinboOs& os);
QStringList mksynccommand(LinboConfig& config, LinboOs& os);
QStringList mksyncrcommand(LinboConfig& config, LinboOs& os);
QStringList mkpartitioncommand(vector <LinboDiskPartition> &p);
QStringList mkpartitioncommand_noformat(vector <LinboDiskPartition> &p);
QStringList mkcacheinitcommand(LinboConfig& config, vector<LinboOs> &os, const QString& type);
QStringList mklinboupdatecommand(LinboConfig& config);
void setState(LinboState state);
private:
LinboState state;
LinboConfig* config;
QStringList linboCommandCache;
QList<LinboOs*> operatingSystems;
QList<LinboDiskPartition*> diskPartitions;
QProcess* process;
QString executeCommand(bool waitForFinished);
template<typename ... Strings>
QString executeCommand(bool waitForFinished, QString argument, const Strings&... arguments) {
// this appends a quoted space in case item is empty and resolves
// problems with linbo_cmd's weird "shift"-usage
if (argument.isEmpty())
this->linboCommandCache.append("");
else
this->linboCommandCache.append(argument);
return executeCommand(waitForFinished, arguments...);
}
void readFromStdout();
void readFromStderr();
void executeCommand(QStringList commandArgs, bool waitForFinished = true);
QString executeCommand(bool wait, QString command, QStringList commandArgs);
public slots:
void executeAutostart();
@ -90,10 +107,11 @@ public slots:
void reboot();
bool startOs(LinboOs* os);
//bool syncStartOs();
//bool reinstallStartOs();
bool syncOs(LinboOs* os);
bool reinstallOs(LinboOs* os);
signals:
void stateChanged();
};

View file

@ -20,6 +20,7 @@
#define LINBOOS_H
#include <QObject>
#include <QtDebug>
#include "linboimage.h"
@ -29,6 +30,13 @@ class LinboOs : public QObject
public:
friend class LinboBackend;
enum LinboOsStartAction {
UnknownAction = -1,
StartOs,
SyncOs,
ReinstallOs
};
const QString& getName() const {return this->name;}
const QString& getDescription() const {return this->description;}
const QString& getVersion() const {return this->version;}
@ -45,9 +53,29 @@ public:
const bool& getNewbutton() const {return this->newButton;}
const bool& getAutostart() const {return this->autostart;}
const int& getAutostartTimeout() const {return this->autostartTimeout;}
const QString& getDefaultAction() const {return this->defaultAction;}
const LinboOsStartAction& getDefaultAction() const {return this->defaultAction;}
const bool& getHidden() const {return this->hidden;}
bool getActionEnabled(LinboOsStartAction action) {
switch (action) {
case StartOs: return this->getStartbutton();
case SyncOs: return this->getSyncbutton();
case ReinstallOs: return this->getNewbutton();
case UnknownAction: return false;
}
}
LinboOsStartAction startActionFromString(const QString& name) const {
qDebug() << "default action name is: " << name;
if(name == "start")
return StartOs;
else if(name == "sync")
return SyncOs;
else if(name == "new")
return ReinstallOs;
return UnknownAction;
}
protected:
explicit LinboOs(QObject *parent = nullptr);
@ -67,27 +95,27 @@ protected:
void setNewButton ( const bool& newButton ) {this->newButton = newButton;}
void setAutostart ( const bool& autostart ) {this->autostart = autostart;}
void setAutostartTimeout ( const int& autostartTimeout ) {this->autostartTimeout = autostartTimeout;}
void setDefaultAction ( const QString& defaultAction ) {this->defaultAction = defaultAction;}
void setDefaultAction ( const LinboOsStartAction& defaultAction ) {this->defaultAction = defaultAction;}
void setHidden ( const bool& hidden ) {this->hidden = hidden;}
private:
QString name, // OS Name
version,
description,
iconName, // Thumbnail for Image
rootPartition, // Root partition
bootPartition, // Root partition
image,
kernel,
initrd,
kernelOptions,
defaultAction;
int autostartTimeout;
bool syncButton, startButton, newButton, autostart,
hidden; // show OS tab or not
QString name, // OS Name
version,
description,
iconName, // Thumbnail for Image
rootPartition, // Root partition
bootPartition, // Root partition
image,
kernel,
initrd,
kernelOptions;
int autostartTimeout;
bool syncButton, startButton, newButton, autostart,
hidden; // show OS tab or not
LinboOsStartAction defaultAction;
LinboImage* baseImage;
LinboImage* differentialImage;
LinboImage* baseImage;
LinboImage* differentialImage;
};

View file

@ -5,6 +5,7 @@
#include <QWidget>
#include <QHBoxLayout>
#include <QStackedWidget>
#include <QList>
#include "linbobackend.h"
#include "linboosselectionrow.h"
@ -28,9 +29,10 @@ private:
QModernStackedWidget* stackView;
QWidget* buttonWidget;
QModernPushButton* defaultActionButton;
QModernPushButton* secondActionButton;
QModernPushButton* thirdActionButton;
QModernPushButton* startOsButton;
QModernPushButton* syncOsButton;
QModernPushButton* reinstallOsButton;
QList<QModernPushButton*> actionButtons;
QWidget* progressBarWidget;
QModernProgressBar* progressBar;
@ -38,9 +40,12 @@ private:
void resizeAndPositionAllItems();
private slots:
void startOs();
void executeStartAction();
void executeSyncAction();
void executeReinstallAction();
signals:
void selectedOsChanged();
};

View file

@ -18,7 +18,7 @@
#include "linbobackend.h"
#define LINBO_CMD(arg) QStringList("linbo_cmd") << (arg);
#define LINBO_CMD(arg) QStringList("linbo_cmd") << (arg)
using namespace std;
@ -88,65 +88,33 @@ LinboBackend::LinboBackend(QObject *parent) : QObject(parent)
*/
// client ip
command = LINBO_CMD("ip");
// myprocess->setArguments( command );
process->start( command.join(" ") );
while( !process->waitForFinished(10000) ) {}
this->config->setIpAddress(process->readAllStandardOutput());
this->config->setIpAddress(this->executeCommand(true, "ip"));
// mac address
command.clear();
command = LINBO_CMD("mac");
process->start( command.join(" ") );
while( !process->waitForFinished(10000) ) {}
this->config->setMacAddress(process->readAllStandardOutput());
this->config->setMacAddress(this->executeCommand(true, "mac"));
// Version
command = LINBO_CMD("version");
// myprocess->setArguments( command );
process->start( command.join(" ") );
while( !process->waitForFinished(10000) ) {}
this->config->setVersion(process->readAllStandardOutput().stripWhiteSpace());
this->config->setVersion(this->executeCommand(true, "version").stripWhiteSpace());
// hostname
command = LINBO_CMD("hostname");
// myprocess->setArguments( command );
process->start( command.join(" ") );
while( !process->waitForFinished(10000) ) {}
this->config->setHostname(process->readAllStandardOutput());
this->config->setHostname(this->executeCommand(true, "hostname"));
// CPU
command = LINBO_CMD("cpu");
// myprocess->setArguments( command );
process->start( command.join(" ") );
while( !process->waitForFinished(10000) ) {}
this->config->setCpu(process->readAllStandardOutput());
this->config->setCpu(this->executeCommand(true, "cpu"));
// Memory
command = LINBO_CMD("memory");
process->start( command.join(" ") );
while( !process->waitForFinished(10000) ) {}
this->config->setRamSize(process->readAllStandardOutput());
this->config->setRamSize(this->executeCommand(true, "memory"));
// Cache Size
command = LINBO_CMD("size");
saveappend( command, this->config->getCache() );
process->start( command.join(" ") );
while( !process->waitForFinished(10000) ) {}
this->config->setCacheSize(process->readAllStandardOutput());
this->config->setCacheSize(this->executeCommand(true, "size"));
// Harddisk Size
QRegExp *removePartition = new QRegExp("[0-9]{1,2}");
QString hd = this->config->getCache();
// e.g. turn /dev/sda1 into /dev/sda
hd.remove( *removePartition );
command = LINBO_CMD("size");
saveappend( command, hd );
process->start( command.join(" ") );
while( !process->waitForFinished(10000) ) {}
this->config->setHddSize(process->readAllStandardOutput());
this->config->setHddSize(this->executeCommand(true, "size", hd));
}
// --------------------
@ -158,36 +126,76 @@ void LinboBackend::executeAutostart() {
}
void LinboBackend::shutdown() {
QStringList command;
command.clear();
command = QStringList("busybox");
command.append("poweroff");
// TODO logConsole->writeStdOut( QString("shutdown entered") );
process->start( command.join(" ") );
this->executeCommand(false, "busybox", QStringList("poweroff"));
}
void LinboBackend::reboot() {
QStringList command;
command.clear();
command = QStringList("busybox");
command.append("reboot");
// TODO logConsole->writeStdOut( QString("reboot entered") );
process->start( command.join(" ") );
this->executeCommand(false, "busybox", QStringList("reboot"));
}
bool LinboBackend::startOs(LinboOs* os) {
if(os == nullptr)
if(os == nullptr || this->state != Idle)
return false;
QStringList command = LINBO_CMD("start");
saveappend( command, os->getBootPartition() );
saveappend( command, os->getRootPartition() );
saveappend( command, os->getKernel() );
saveappend( command, os->getInitrd() );
saveappend( command, os->getKernelOptions() );
saveappend( command, this->config->getCache() );
this->setState(Starting);
this->executeCommand(command, false);
this->executeCommand(
false,
"start",
os->getBootPartition(),
os->getRootPartition(),
os->getKernel(),
os->getInitrd(),
os->getKernelOptions(),
this->config->getCache()
);
return true;
}
bool LinboBackend::syncOs(LinboOs* os) {
if(os == nullptr || this->state != Idle)
return false;
this->setState(Syncing);
this->executeCommand(
false,
"syncstart",
this->config->getServer(),
this->config->getCache(),
os->getBaseImage()->getName(),
os->getDifferentialImage()->getName(),
os->getBootPartition(),
os->getRootPartition(),
os->getKernel(),
os->getInitrd(),
os->getKernelOptions()
);
return true;
}
bool LinboBackend::reinstallOs(LinboOs* os) {
if(os == nullptr || this->state != Idle)
return false;
this->setState(Reinstalling);
this->executeCommand(
false,
"syncr",
this->config->getServer(),
this->config->getCache(),
os->getBaseImage()->getName(),
os->getDifferentialImage()->getName(),
os->getBootPartition(),
os->getRootPartition(),
os->getKernel(),
os->getInitrd(),
os->getKernelOptions(),
QString("force")
);
return true;
}
@ -205,19 +213,42 @@ QList<LinboOs*> LinboBackend::getOperatingSystems() {
// - Helpers -
// -----------
void LinboBackend::executeCommand(QStringList commandArgs, bool waitForFinished) {
QString LinboBackend::executeCommand(bool waitForFinished) {
QStringList tmpList = this->linboCommandCache;
this->linboCommandCache.clear();
QString command = commandArgs.takeFirst();
return this->executeCommand(waitForFinished, "linbo_cmd", tmpList);
}
QString LinboBackend::executeCommand(bool waitForFinished, QString command, QStringList commandArgs) {
if(waitForFinished)
// clear old output
this->process->readAll();
qDebug() << "Executing: " << command << " " << commandArgs.join(" ");
return;
process->start(command, commandArgs);
process->waitForStarted();
if(waitForFinished)
if(waitForFinished) {
while( !process->waitForFinished(10000) ) {}
return this->process->readAllStandardOutput();
}
return "";
}
LinboBackend::LinboState LinboBackend::getState() {
return this->state;
}
void LinboBackend::setState(LinboState state) {
if(this->state == state)
return;
this->state = state;
emit this->stateChanged();
}
void LinboBackend::read_qstring( ifstream* input, QString& tmp ) {
@ -258,6 +289,7 @@ LinboOs* LinboBackend::read_os(ifstream* input) {
LinboOs* os = new LinboOs(this);
QString key, value;
while(!input->eof() && read_pair(input, key, value)) {
qDebug() << key << "=" << value;
if(key.compare("name") == 0) os->setName(value);
else if(key.compare("description") == 0) os->setDescription(value);
else if(key.compare("version") == 0) os->setVersion(value);
@ -272,7 +304,7 @@ LinboOs* LinboBackend::read_os(ifstream* input) {
else if(key.compare("syncenabled") == 0) os->setSyncButton(toBool(value));
else if(key.compare("startenabled") == 0) os->setStartButton(toBool(value));
else if((key.compare("remotesyncenabled") == 0) || (key.compare("newenabled") == 0)) os->setNewButton(toBool(value));
else if(key.compare("defaultaction") == 0) os->setDefaultAction(value);
else if(key.compare("defaultaction") == 0) os->setDefaultAction(os->startActionFromString(value));
else if(key.compare("autostart") == 0) os->setAutostart(toBool(value));
else if(key.compare("autostarttimeout") == 0) os->setAutostartTimeout(value.toInt());
else if(key.compare("hidden") == 0) os->setHidden(toBool(value));
@ -316,61 +348,6 @@ void LinboBackend::read_globals( ifstream* input, LinboConfig* config ) {
}
}
// this appends a quoted space in case item is empty and resolves
// problems with linbo_cmd's weird "shift"-usage
void LinboBackend::saveappend( QStringList& command, const QString& item ) {
if ( item.isEmpty() )
command.append("");
else
command.append( item );
}
// Sync+start image
QStringList LinboBackend::mksyncstartcommand(LinboConfig& config, LinboOs& os) {
QStringList command = LINBO_CMD("syncstart");
saveappend( command, config.getServer() );
saveappend( command, config.getCache() );
saveappend( command, os.getBaseImage()->getName() );
saveappend( command, os.getDifferentialImage()->getName() );
saveappend( command, os.getBootPartition() ); // boot is same as root
saveappend( command, os.getRootPartition() );
saveappend( command, os.getKernel() );
saveappend( command, os.getInitrd() );
saveappend( command, os.getKernelOptions() );
return command;
}
// Sync image from cache
QStringList LinboBackend::mksynccommand(LinboConfig& config, LinboOs& os) {
QStringList command = LINBO_CMD("sync");
saveappend( command, config.getCache() );
saveappend( command, os.getBaseImage()->getName() );
saveappend( command, os.getDifferentialImage()->getName() );
saveappend( command, os.getBootPartition() );
saveappend( command, os.getRootPartition() );
saveappend( command, os.getKernel() );
saveappend( command, os.getInitrd() );
saveappend( command, os.getKernelOptions() );
return command;
}
// Sync image from server
QStringList LinboBackend::mksyncrcommand(LinboConfig& config, LinboOs& os) {
QStringList command = LINBO_CMD("syncr");
saveappend( command, config.getServer() );
saveappend( command, config.getCache() );
saveappend( command, os.getBaseImage()->getName() );
saveappend( command, os.getDifferentialImage()->getName() );
saveappend( command, os.getBootPartition() );
saveappend( command, os.getRootPartition() );
saveappend( command, os.getKernel() );
saveappend( command, os.getInitrd() );
saveappend( command, os.getKernelOptions() );
saveappend( command, QString("force") );
return command;
}
QStringList LinboBackend::mkpartitioncommand(vector <LinboDiskPartition> &p) {
QStringList command = LINBO_CMD("partition");
for(unsigned int i=0; i<p.size(); i++) {

View file

@ -23,7 +23,7 @@ LinboOs::LinboOs(QObject *parent) : QObject(parent)
autostart = false;
autostartTimeout = 0;
hidden = false;
defaultAction = QString("sync");
defaultAction = SyncOs;
// TODO ?? image_history.clear();
iconName = QString("defaultIcon.svg");
}

View file

@ -1,4 +1,4 @@
//#define NEVERDEF
#define NEVERDEF
#ifdef NEVERDEF
/* class building the LINBO GUI

View file

@ -21,23 +21,22 @@ LinboOsSelectionRow::LinboOsSelectionRow(LinboBackend* backend, QWidget *parent)
void LinboOsSelectionRow::resizeAndPositionAllButtons() {
qDebug() << "Resizing all Buttons";
if(this->showOnlySelectedButton) {
int buttonWidth = this->width() / this->osButtonGroup->buttons().length();
for(int i = 0; i < this->osButtons.length(); i++) {
if(!this->osButtons[i]->button->isChecked())
this->osButtons[i]->hide();
else {
QPropertyAnimation* moveAnimation = new QPropertyAnimation(this->osButtons[i], "geometry");
moveAnimation->setEasingCurve(QEasingCurve::InOutQuad);
moveAnimation->setDuration(400);
moveAnimation->setStartValue(this->osButtons[i]->geometry());
moveAnimation->setEndValue(QRect(buttonWidth / 2, 0, buttonWidth, this->height()));
moveAnimation->start();
if(this->showOnlySelectedButton) {
for(int i = 0; i < this->osButtons.length(); i++) {
if(!this->osButtons[i]->button->isChecked())
this->osButtons[i]->hide();
else {
QPropertyAnimation* moveAnimation = new QPropertyAnimation(this->osButtons[i], "geometry");
moveAnimation->setEasingCurve(QEasingCurve::InOutQuad);
moveAnimation->setDuration(400);
moveAnimation->setStartValue(this->osButtons[i]->geometry());
moveAnimation->setEndValue(QRect((this->width() - buttonWidth) / 2, 0, buttonWidth, this->height()));
moveAnimation->start();
}
}
}
}
else {
int buttonWidth = this->width() / this->osButtonGroup->buttons().length();
for(int i = 0; i < this->osButtons.length(); i++) {
this->osButtons[i]->setGeometry(buttonWidth * i, 0, buttonWidth, this->height());
}

View file

@ -9,12 +9,16 @@ LinboStartActions::LinboStartActions(LinboBackend* backend, LinboOsSelectionRow*
// Action Buttons
this->buttonWidget = new QWidget();
defaultActionButton = new QModernPushButton(":/svgIcons/startAction.svg", this->buttonWidget);
connect(defaultActionButton, SIGNAL(clicked()), this, SLOT(startOs()));
secondActionButton = new QModernPushButton(":/svgIcons/syncAction.svg", this->buttonWidget);
thirdActionButton = new QModernPushButton(":/svgIcons/resetAction.svg", this->buttonWidget);
startOsButton = new QModernPushButton(":/svgIcons/startAction.svg", this->buttonWidget);
connect(startOsButton, SIGNAL(clicked()), this, SLOT(executeStartAction()));
syncOsButton = new QModernPushButton(":/svgIcons/syncAction.svg", this->buttonWidget);
reinstallOsButton = new QModernPushButton(":/svgIcons/resetAction.svg", this->buttonWidget);
this->stackView->addWidget(this->buttonWidget);
actionButtons.append(startOsButton);
actionButtons.append(syncOsButton);
actionButtons.append(reinstallOsButton);
// Progress bar
this->progressBarWidget = new QWidget();
progressBar = new QModernProgressBar(this->progressBarWidget);
@ -30,24 +34,96 @@ void LinboStartActions::resizeAndPositionAllItems() {
this->stackView->setFixedSize(this->size());
// Action buttons
// bring buttons in correct order:
LinboOs* selectedOs = this->osSelectionRow->getSelectedOs();
LinboOs::LinboOsStartAction defaultAction = selectedOs->getDefaultAction();
int startOsPosition = 0;
int syncOsPosition = 1;
int reinstallOsPosition = 2;
qDebug() << "Default action is: " << defaultAction;
switch (defaultAction) {
case LinboOs::StartOs:
break;
case LinboOs::SyncOs:
syncOsPosition = 0;
startOsPosition = 1;
reinstallOsPosition = 2;
break;
case LinboOs::ReinstallOs:
reinstallOsPosition = 0;
syncOsPosition = 1;
startOsPosition = 2;
break;
default:
break;
}
//this->actionButtons.move(this->actionButtons.indexOf(this->startOsButton), startOsPosition);
//this->actionButtons.move(this->actionButtons.indexOf(this->syncOsButton), syncOsPosition);
//this->actionButtons.move(this->actionButtons.indexOf(this->reinstallOsButton), reinstallOsPosition);
while (this->actionButtons.length() < 3) {
this->actionButtons.append(nullptr);
}
this->actionButtons[startOsPosition] = this->startOsButton;
this->actionButtons[syncOsPosition] = this->syncOsButton;
this->actionButtons[reinstallOsPosition] = this->reinstallOsButton;
// check for disabled actions
QList<bool> positionsEnabled;
positionsEnabled.append(true);
positionsEnabled.append(true);
positionsEnabled.append(true);
positionsEnabled[startOsPosition] = selectedOs->getStartbutton();
positionsEnabled[syncOsPosition] = selectedOs->getSyncbutton();
positionsEnabled[reinstallOsPosition] = selectedOs->getNewbutton();
// move buttons into place
this->buttonWidget->setFixedSize(this->size());
int buttonSpacing = this->height() * 0.1;
int defaultButtonHeight = this->height() * 0.6;
defaultActionButton->setGeometry((this->width() - defaultButtonHeight) / 2, 0,defaultButtonHeight, defaultButtonHeight);
int secondaryButtonHeight = this->height() * 0.3;
secondActionButton->setGeometry(
this->width() / 2 - secondaryButtonHeight - buttonSpacing / 2,
defaultButtonHeight + buttonSpacing,
secondaryButtonHeight,
secondaryButtonHeight
);
this->actionButtons[0]->setGeometry((this->width() - defaultButtonHeight) / 2, 0,defaultButtonHeight, defaultButtonHeight);
thirdActionButton->setGeometry(
this->width() / 2 + buttonSpacing / 2,
defaultButtonHeight + buttonSpacing,
secondaryButtonHeight,
secondaryButtonHeight
);
int secondaryButtonHeight = this->height() * 0.3;
if(positionsEnabled[1] && positionsEnabled[2]) {
this->actionButtons[1]->setGeometry(
this->width() / 2 - secondaryButtonHeight - buttonSpacing / 2,
defaultButtonHeight + buttonSpacing,
secondaryButtonHeight,
secondaryButtonHeight
);
this->actionButtons[2]->setGeometry(
this->width() / 2 + buttonSpacing / 2,
defaultButtonHeight + buttonSpacing,
secondaryButtonHeight,
secondaryButtonHeight
);
}
else if(!positionsEnabled[1]) {
this->actionButtons[1]->hide();
this->actionButtons[2]->setGeometry(
this->width() / 2 - secondaryButtonHeight / 2,
defaultButtonHeight + buttonSpacing,
secondaryButtonHeight,
secondaryButtonHeight
);
}
else if(!positionsEnabled[2]) {
this->actionButtons[1]->setGeometry(
this->width() / 2 - secondaryButtonHeight / 2,
defaultButtonHeight + buttonSpacing,
secondaryButtonHeight,
secondaryButtonHeight
);
this->actionButtons[2]->hide();
}
// Progress bar
this->progressBarWidget->setFixedSize(this->size());
@ -61,7 +137,21 @@ void LinboStartActions::resizeEvent(QResizeEvent *event) {
QWidget::resizeEvent(event);
}
void LinboStartActions::startOs() {
void LinboStartActions::executeStartAction() {
this->stackView->setCurrentWidgetAnimated(this->progressBarWidget);
this->osSelectionRow->setShowOnlySelectedButton(true);
this->backend->startOs(this->osSelectionRow->getSelectedOs());
//this->progressBar->show();
}
void LinboStartActions::executeSyncAction() {
this->stackView->setCurrentWidgetAnimated(this->progressBarWidget);
this->osSelectionRow->setShowOnlySelectedButton(true);
this->backend->startOs(this->osSelectionRow->getSelectedOs());
//this->progressBar->show();
}
void LinboStartActions::executeReinstallAction() {
this->stackView->setCurrentWidgetAnimated(this->progressBarWidget);
this->osSelectionRow->setShowOnlySelectedButton(true);
this->backend->startOs(this->osSelectionRow->getSelectedOs());

View file

@ -47,7 +47,7 @@ LinboStartPage::LinboStartPage(LinboBackend* backend, QWidget *parent) : QWidget
QWidget* mainLayoutWidget = new QWidget(this);
mainLayoutWidget->setGeometry(this->geometry());
QVBoxLayout* mainLayout = new QVBoxLayout(mainLayoutWidget);
mainLayout->setSpacing(0);
mainLayout->setSpacing(this->height()*0.025);
mainLayout->setContentsMargins(0,0,0,0);
mainLayout->addItem(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::Expanding));
mainLayout->addWidget(osSelectionRow);