diff --git a/gui/LICENSE b/gui/LICENSE new file mode 100644 index 0000000000..755068f255 --- /dev/null +++ b/gui/LICENSE @@ -0,0 +1,27 @@ +Copyright (C) 2016 The Qt Company Ltd. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/gui/README.md b/gui/README.md new file mode 100644 index 0000000000..2f5ff99457 --- /dev/null +++ b/gui/README.md @@ -0,0 +1,24 @@ +# System Tray Icon + +## Running + +Open in [Qt Creator](https://doc.qt.io/qtcreator/) GUI: + +```shell +qtcreator systray.pro +``` + +Or on the command line: + +```console +$ qmake +$ make +... +$ ./systray +``` + +---- + +See + +minikube logo from the project. diff --git a/gui/images/minikube.png b/gui/images/minikube.png new file mode 100644 index 0000000000..9607014b3a Binary files /dev/null and b/gui/images/minikube.png differ diff --git a/gui/instance.cpp b/gui/instance.cpp new file mode 100644 index 0000000000..580470a769 --- /dev/null +++ b/gui/instance.cpp @@ -0,0 +1,92 @@ +#include "instance.h" + +#include + +void InstanceModel::setInstances(const InstanceList &instances) +{ + beginResetModel(); + instanceList = instances; + endResetModel(); +} + +int InstanceModel::rowCount(const QModelIndex &) const +{ + return instanceList.count(); +} + +int InstanceModel::columnCount(const QModelIndex &) const +{ + return 6; +} + +static QStringList binaryAbbrs = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" }; + +QVariant InstanceModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (index.row() >= instanceList.size()) + return QVariant(); + if (index.column() >= 6) + return QVariant(); + + if (role == Qt::TextAlignmentRole) { + switch (index.column()) { + case 0: + return QVariant(Qt::AlignLeft | Qt::AlignVCenter); + case 1: + return QVariant(Qt::AlignRight | Qt::AlignVCenter); + case 2: + // fall-through + case 3: + // fall-through + case 4: + // fall-through + case 5: + return QVariant(Qt::AlignHCenter | Qt::AlignVCenter); + } + } + if (role == Qt::DisplayRole) { + Instance instance = instanceList.at(index.row()); + switch (index.column()) { + case 0: + return instance.name(); + case 1: + return instance.status(); + case 2: + return instance.driver(); + case 3: + return instance.containerRuntime(); + case 4: + return QString::number(instance.cpus()); + case 5: + return QString::number(instance.memory()); + } + } + return QVariant(); +} + +QVariant InstanceModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) { + switch (section) { + case 0: + return tr("Name"); + case 1: + return tr("Status"); + case 2: + return tr("Driver"); + case 3: + return tr("Container Runtime"); + case 4: + return tr("CPUs"); + case 5: + return tr("Memory (MB)"); + } + } + return QVariant(); // QStringLiteral("Row %1").arg(section); +} diff --git a/gui/instance.h b/gui/instance.h new file mode 100644 index 0000000000..500e9ed0bf --- /dev/null +++ b/gui/instance.h @@ -0,0 +1,67 @@ +#ifndef INSTANCE_H +#define INSTANCE_H + +#include +#include +#include +#include + +//! [0] +class Instance +{ +public: + Instance() : Instance("") { } + Instance(const QString &name) + : m_name(name), m_status(""), m_driver(""), m_container_runtime(""), m_cpus(0), m_memory(0) + { + } + + QString name() const { return m_name; } + QString status() const { return m_status; } + void setStatus(QString status) { m_status = status; } + QString driver() const { return m_driver; } + void setDriver(QString driver) { m_driver = driver; } + QString containerRuntime() const { return m_container_runtime; } + void setContainerRuntime(QString containerRuntime) { m_container_runtime = containerRuntime; } + int cpus() const { return m_cpus; } + void setCpus(int cpus) { m_cpus = cpus; } + int memory() const { return m_memory; } + void setMemory(int memory) { m_memory = memory; } + +private: + QString m_name; + QString m_status; + QString m_driver; + QString m_container_runtime; + int m_cpus; + int m_memory; +}; +//! [0] + +typedef QList InstanceList; +typedef QHash InstanceHash; + +//! [1] +class InstanceModel : public QAbstractListModel +{ + Q_OBJECT + +public: + InstanceModel(const InstanceList &instances, QObject *parent = nullptr) + : QAbstractListModel(parent), instanceList(instances) + { + } + + void setInstances(const InstanceList &instances); + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const override; + +private: + InstanceList instanceList; +}; +//! [1] + +#endif // INSTANCE_H diff --git a/gui/main.cpp b/gui/main.cpp new file mode 100644 index 0000000000..d981415b44 --- /dev/null +++ b/gui/main.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#ifndef QT_NO_SYSTEMTRAYICON + +#include +#include "window.h" + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(systray); + + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + + QApplication app(argc, argv); + + if (!QSystemTrayIcon::isSystemTrayAvailable()) { + QMessageBox::critical(0, QObject::tr("Systray"), + QObject::tr("I couldn't detect any system tray " + "on this system.")); + return 1; + } + QApplication::setQuitOnLastWindowClosed(false); + + Window window; + window.show(); + return app.exec(); +} + +#else + +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + QString text("QSystemTrayIcon is not supported on this platform"); + + QLabel *label = new QLabel(text); + label->setWordWrap(true); + + label->show(); + qDebug() << text; + + app.exec(); +} + +#endif diff --git a/gui/systray.pro b/gui/systray.pro new file mode 100644 index 0000000000..f379d4f882 --- /dev/null +++ b/gui/systray.pro @@ -0,0 +1,9 @@ +HEADERS = window.h \ + instance.h +SOURCES = main.cpp \ + instance.cpp \ + window.cpp +RESOURCES = systray.qrc + +QT += widgets +requires(qtConfig(combobox)) diff --git a/gui/systray.qrc b/gui/systray.qrc new file mode 100644 index 0000000000..6e9fe37397 --- /dev/null +++ b/gui/systray.qrc @@ -0,0 +1,5 @@ + + + images/minikube.png + + diff --git a/gui/window.cpp b/gui/window.cpp new file mode 100644 index 0000000000..2c6bc12c5b --- /dev/null +++ b/gui/window.cpp @@ -0,0 +1,472 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "window.h" + +#ifndef QT_NO_SYSTEMTRAYICON + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//! [0] +Window::Window() +{ + createInstanceGroupBox(); + + createActions(); + createTrayIcon(); + + connect(startButton, &QAbstractButton::clicked, this, &Window::startMinikube); + connect(stopButton, &QAbstractButton::clicked, this, &Window::stopMinikube); + connect(deleteButton, &QAbstractButton::clicked, this, &Window::deleteMinikube); + connect(refreshButton, &QAbstractButton::clicked, this, &Window::updateInstances); + connect(createButton, &QAbstractButton::clicked, this, &Window::initMachine); + connect(trayIcon, &QSystemTrayIcon::messageClicked, this, &Window::messageClicked); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(instanceGroupBox); + setLayout(mainLayout); + + trayIcon->show(); + + setWindowTitle(tr("minikube")); + setWindowIcon(*trayIconIcon); + resize(600, 400); +} +//! [0] + +//! [1] +void Window::setVisible(bool visible) +{ + minimizeAction->setEnabled(visible); + restoreAction->setEnabled(!visible); + QDialog::setVisible(visible); +} +//! [1] + +//! [2] +void Window::closeEvent(QCloseEvent *event) +{ +#ifdef Q_OS_OSX + if (!event->spontaneous() || !isVisible()) { + return; + } +#endif + if (trayIcon->isVisible()) { + QMessageBox::information(this, tr("Systray"), + tr("The program will keep running in the " + "system tray. To terminate the program, " + "choose Quit in the context menu " + "of the system tray entry.")); + hide(); + event->ignore(); + } +} +//! [2] + +//! [6] +void Window::messageClicked() +{ + QMessageBox::information(0, tr("Systray"), + tr("Sorry, I already gave what help I could.\n" + "Maybe you should try asking a human?")); +} +//! [6] + +void Window::createActions() +{ + minimizeAction = new QAction(tr("Mi&nimize"), this); + connect(minimizeAction, &QAction::triggered, this, &QWidget::hide); + + restoreAction = new QAction(tr("&Restore"), this); + connect(restoreAction, &QAction::triggered, this, &QWidget::showNormal); + + quitAction = new QAction(tr("&Quit"), this); + connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit); +} + +void Window::createTrayIcon() +{ + trayIconMenu = new QMenu(this); + trayIconMenu->addAction(minimizeAction); + trayIconMenu->addAction(restoreAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(quitAction); + + trayIconIcon = new QIcon(":/images/minikube.png"); + + trayIcon = new QSystemTrayIcon(this); + trayIcon->setContextMenu(trayIconMenu); + trayIcon->setIcon(*trayIconIcon); +} + +void Window::startMinikube() +{ + QStringList args = {"start", "-p", selectedInstance()}; + sendMinikubeCommand(args); + updateInstances(); +} + +void Window::stopMinikube() +{ + QStringList args = {"stop", "-p", selectedInstance()}; + sendMinikubeCommand(args); + updateInstances(); +} + +void Window::deleteMinikube() +{ + QStringList args = {"delete", "-p", selectedInstance()}; + sendMinikubeCommand(args); + updateInstances(); +} + +void Window::updateInstances() +{ + QString instance = selectedInstance(); + instanceModel->setInstances(getInstances()); + setSelectedInstance(instance); + updateButtons(); +} + +InstanceList Window::getInstances() +{ + InstanceList instances; + QStringList args = {"profile", "list", "-o", "json"}; + QString text; + bool success = sendMinikubeCommand(args, text); + QStringList lines; + if (success) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + lines = text.split("\n", Qt::SkipEmptyParts); +#else + lines = text.split("\n", QString::SkipEmptyParts); +#endif + } + for (int i = 0; i < lines.size(); i++) { + QString line = lines.at(i); + QJsonParseError error; + QJsonDocument json = QJsonDocument::fromJson(line.toUtf8(), &error); + if (json.isNull()) { + qDebug() << error.errorString(); + continue; + } + if (json.isObject()) { + QJsonObject par = json.object(); + QJsonArray a = par["valid"].toArray(); + for (int j = 0; j < a.size(); j++) { + QJsonObject obj = a[j].toObject(); + QString name; + if (obj.contains("Name")) { + name = obj["Name"].toString(); + } + if (name.isEmpty()) { + continue; + } + Instance instance(name); + if (obj.contains("Status")) { + QString status = obj["Status"].toString(); + instance.setStatus(status); + } + if (!obj.contains("Config")) { + instances << instance; + continue; + } + QJsonObject config = obj["Config"].toObject(); + if (config.contains("CPUs")) { + int cpus = config["CPUs"].toInt(); + instance.setCpus(cpus); + } + if (config.contains("Memory")) { + int memory = config["Memory"].toInt(); + instance.setMemory(memory); + } + if (config.contains("Driver")) { + QString driver = config["Driver"].toString(); + instance.setDriver(driver); + } + if (!config.contains("KubernetesConfig")) { + instances << instance; + continue; + } + QJsonObject k8sConfig = config["KubernetesConfig"].toObject(); + if (k8sConfig.contains("ContainerRuntime")) { + QString containerRuntime = k8sConfig["ContainerRuntime"].toString(); + instance.setContainerRuntime(containerRuntime); + } + instances << instance; + } + } + } + return instances; +} + +QString Window::selectedInstance() +{ + QModelIndex index = instanceListView->currentIndex(); + QVariant variant = index.data(Qt::DisplayRole); + if (variant.isNull()) { + return QString(); + } + return variant.toString(); +} + +void Window::setSelectedInstance(QString instance) +{ + QAbstractItemModel *model = instanceListView->model(); + QModelIndex start = model->index(0, 0); + QModelIndexList index = model->match(start, Qt::DisplayRole, instance); + if (index.size() == 0) { + return; + } + instanceListView->setCurrentIndex(index[0]); +} + +void Window::createInstanceGroupBox() +{ + instanceGroupBox = new QGroupBox(tr("Instances")); + + InstanceList instances = getInstances(); + instanceModel = new InstanceModel(instances); + + instanceListView = new QTableView(); + instanceListView->setModel(instanceModel); + instanceListView->setSelectionMode(QAbstractItemView::SingleSelection); + instanceListView->setSelectionBehavior(QAbstractItemView::SelectRows); + instanceListView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); + instanceListView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents); + instanceListView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeToContents); + instanceListView->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents); + instanceListView->horizontalHeader()->setSectionResizeMode(4, QHeaderView::ResizeToContents); + instanceListView->horizontalHeader()->setSectionResizeMode(5, QHeaderView::ResizeToContents); + setSelectedInstance("default"); + + connect(instanceListView, SIGNAL(clicked(QModelIndex)), this, SLOT(updateButtons())); + + startButton = new QPushButton(tr("Start")); + stopButton = new QPushButton(tr("Stop")); + deleteButton = new QPushButton(tr("Delete")); + refreshButton = new QPushButton(tr("Refresh")); + createButton = new QPushButton(tr("Create")); + + updateButtons(); + + QHBoxLayout *instanceButtonLayout = new QHBoxLayout; + instanceButtonLayout->addWidget(startButton); + instanceButtonLayout->addWidget(stopButton); + instanceButtonLayout->addWidget(deleteButton); + instanceButtonLayout->addWidget(refreshButton); + instanceButtonLayout->addWidget(createButton); + + QVBoxLayout *instanceLayout = new QVBoxLayout; + instanceLayout->addWidget(instanceListView); + instanceLayout->addLayout(instanceButtonLayout); + instanceGroupBox->setLayout(instanceLayout); +} + +void Window::updateButtons() +{ + QString inst = selectedInstance(); + if (inst.isEmpty()) { + startButton->setEnabled(false); + stopButton->setEnabled(false); + deleteButton->setEnabled(false); + return; + } + deleteButton->setEnabled(true); + Instance instance = getInstanceHash()[inst]; + if (instance.status() == "Running") { + startButton->setEnabled(false); + stopButton->setEnabled(true); + } else { + startButton->setEnabled(true); + stopButton->setEnabled(false); + } +} + +InstanceHash Window::getInstanceHash() +{ + InstanceList instances = getInstances(); + InstanceHash instanceHash; + for (int i = 0; i < instances.size(); i++) { + Instance instance = instances.at(i); + instanceHash[instance.name()] = instance; + } + return instanceHash; +} + +bool Window::sendMinikubeCommand(QStringList cmds) +{ + QString text; + return sendMinikubeCommand(cmds, text); +} + +bool Window::sendMinikubeCommand(QStringList cmds, QString &text) +{ + QString program = "minikube"; + QStringList arguments; + arguments << cmds; + bool success; + + QProcess *process = new QProcess(this); + process->start(program, arguments); + this->setCursor(Qt::WaitCursor); + success = process->waitForFinished(300 * 1000); + this->unsetCursor(); + + if (success) { + text = process->readAllStandardOutput(); + } else { + qDebug() << process->readAllStandardOutput(); + qDebug() << process->readAllStandardError(); + } + delete process; + return success; +} + +static QString profile = "minikube"; +static int cpus = 2; +static int memory = 2400; +static QString driver = ""; +static QString containerRuntime = ""; + +void Window::askName() +{ + QDialog dialog; + dialog.setWindowTitle(tr("Create minikube Instance")); + dialog.setModal(true); + + QFormLayout form(&dialog); + QDialogButtonBox buttonBox(Qt::Horizontal, &dialog); + QLineEdit profileField(profile, &dialog); + form.addRow(new QLabel(tr("Profile")), &profileField); + buttonBox.addButton(QString(tr("Use Default Values")), QDialogButtonBox::AcceptRole); + connect(&buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + buttonBox.addButton(QString(tr("Set Custom Values")), QDialogButtonBox::RejectRole); + connect(&buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + form.addRow(&buttonBox); + + int code = dialog.exec(); + if (code == QDialog::Accepted) { + QStringList arg = {"start", "-p", profile}; + sendMinikubeCommand(arg); + } else if (code == QDialog::Rejected) { + askCustom(); + } +} + +void Window::askCustom() +{ + QDialog dialog; + dialog.setWindowTitle(tr("Create minikube Instance")); + dialog.setModal(true); + + QFormLayout form(&dialog); + driverComboBox = new QComboBox; + driverComboBox->addItem("docker"); + driverComboBox->addItem("hyperv"); + driverComboBox->addItem("hyperkit"); + form.addRow(new QLabel(tr("Driver")), driverComboBox); + containerRuntimeComboBox = new QComboBox; + containerRuntimeComboBox->addItem("docker"); + containerRuntimeComboBox->addItem("containerd"); + containerRuntimeComboBox->addItem("crio"); + form.addRow(new QLabel(tr("Container Runtime")), containerRuntimeComboBox); + QLineEdit cpuField(QString::number(cpus), &dialog); + form.addRow(new QLabel(tr("CPUs")), &cpuField); + QLineEdit memoryField(QString::number(memory), &dialog); + form.addRow(new QLabel(tr("Memory")), &memoryField); + + QDialogButtonBox buttonBox(Qt::Horizontal, &dialog); + buttonBox.addButton(QString(tr("Create")), QDialogButtonBox::AcceptRole); + connect(&buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + buttonBox.addButton(QString(tr("Cancel")), QDialogButtonBox::RejectRole); + connect(&buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + form.addRow(&buttonBox); + + int code = dialog.exec(); + if (code == QDialog::Accepted) { + driver = driverComboBox->itemText(driverComboBox->currentIndex()); + containerRuntime = containerRuntimeComboBox->itemText(containerRuntimeComboBox->currentIndex()); + cpus = cpuField.text().toInt(); + memory = memoryField.text().toInt(); + QStringList args = {"start", "-p", profile, "--driver", driver, "--container-runtime", containerRuntime, "--cpus", QString::number(cpus), "--memory", QString::number(memory)}; + sendMinikubeCommand(args); + } +} + +void Window::initMachine() +{ + askName(); + updateInstances(); +} + +#endif diff --git a/gui/window.h b/gui/window.h new file mode 100644 index 0000000000..22a95ecbe1 --- /dev/null +++ b/gui/window.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WINDOW_H +#define WINDOW_H + +#include + +#ifndef QT_NO_SYSTEMTRAYICON + +#include + +QT_BEGIN_NAMESPACE +class QAction; +class QCheckBox; +class QComboBox; +class QGroupBox; +class QIcon; +class QLabel; +class QLineEdit; +class QMenu; +class QPushButton; +class QSpinBox; +class QTextEdit; +class QTableView; +QT_END_NAMESPACE + +#include "instance.h" + +//! [0] +class Window : public QDialog +{ + Q_OBJECT + +public: + Window(); + + void setVisible(bool visible) override; + +protected: + void closeEvent(QCloseEvent *event) override; + +private slots: + void messageClicked(); + void updateButtons(); + +private: + void createActionGroupBox(); + void createActions(); + void createTrayIcon(); + void startMinikube(); + void stopMinikube(); + void deleteMinikube(); + InstanceList getInstances(); + QString selectedInstance(); + void setSelectedInstance(QString instance); + QTableView *instanceListView; + void createInstanceGroupBox(); + QGroupBox *instanceGroupBox; + InstanceModel *instanceModel; + InstanceHash getInstanceHash(); + bool sendMinikubeCommand(QStringList cmds); + bool sendMinikubeCommand(QStringList cmds, QString &text); + void updateInstances(); + void askCustom(); + void askName(); + QComboBox *driverComboBox; + QComboBox *containerRuntimeComboBox; + void initMachine(); + + QPushButton *startButton; + QPushButton *stopButton; + QPushButton *deleteButton; + QPushButton *refreshButton; + QPushButton *createButton; + + QAction *minimizeAction; + QAction *restoreAction; + QAction *quitAction; + + QSystemTrayIcon *trayIcon; + QMenu *trayIconMenu; + QIcon *trayIconIcon; +}; +//! [0] + +#endif // QT_NO_SYSTEMTRAYICON + +#endif