From 2e624b94dc62f4e0a21f9d66b70e3ca9850872da Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Sat, 5 Dec 2020 07:28:38 +0000 Subject: [PATCH] kemu: move from kde-playground Signed-off-by: Ivailo Monev --- CMakeLists.txt | 1 + kemu/CMakeLists.txt | 20 ++ kemu/kemu.desktop | 9 + kemu/kemu.ui | 327 ++++++++++++++++++++++++++++++++ kemu/kemumainwindow.cpp | 411 ++++++++++++++++++++++++++++++++++++++++ kemu/kemumainwindow.h | 62 ++++++ kemu/kemuui.rc | 13 ++ kemu/main.cpp | 43 +++++ 8 files changed, 886 insertions(+) create mode 100644 kemu/CMakeLists.txt create mode 100644 kemu/kemu.desktop create mode 100644 kemu/kemu.ui create mode 100644 kemu/kemumainwindow.cpp create mode 100644 kemu/kemumainwindow.h create mode 100644 kemu/kemuui.rc create mode 100644 kemu/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b88da0b9..9e28bcc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ macro_optional_add_subdirectory(kdeplasma-addons) macro_optional_add_subdirectory(lokalize) macro_optional_add_subdirectory(libksane) macro_optional_add_subdirectory(kcolorchooser) +macro_optional_add_subdirectory(kemu) macro_optional_add_subdirectory(kfloppy) macro_optional_add_subdirectory(kgpg) macro_optional_add_subdirectory(kmix) diff --git a/kemu/CMakeLists.txt b/kemu/CMakeLists.txt new file mode 100644 index 00000000..9f94de86 --- /dev/null +++ b/kemu/CMakeLists.txt @@ -0,0 +1,20 @@ +project(kemu) + +if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + find_package(KDE4 4.19.0 REQUIRED) + include(KDE4Defaults) + include_directories(${KDE4_INCLUDES}) + add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) +endif() + +set(kemu_sources + main.cpp + kemumainwindow.cpp +) + +add_executable(kemu ${kemu_sources}) +target_link_libraries(kemu ${KDE4_KDEUI_LIBS} ${KDE4_KFILE_LIBS}) + +install(TARGETS kemu DESTINATION ${KDE4_BIN_INSTALL_DIR}) +install(FILES kemuui.rc DESTINATION ${KDE4_DATA_INSTALL_DIR}/kemu) +install(PROGRAMS kemu.desktop DESTINATION ${KDE4_XDG_APPS_INSTALL_DIR}) diff --git a/kemu/kemu.desktop b/kemu/kemu.desktop new file mode 100644 index 00000000..008c89af --- /dev/null +++ b/kemu/kemu.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Icon=applications-engineering +Name=KEmu +GenericName=KEmu +Comment=Simple QEMU frontend for KDE +Exec=kemu --icon '%i' --caption '%c' %U +Terminal=false +Type=Application +Categories=Qt;KDE; diff --git a/kemu/kemu.ui b/kemu/kemu.ui new file mode 100644 index 00000000..3aaa8c2a --- /dev/null +++ b/kemu/kemu.ui @@ -0,0 +1,327 @@ + + + KEmuWindow + + + + 0 + 0 + 800 + 600 + + + + KEmu + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 40 + 20 + + + + + + + + false + + + Start + + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 40 + 20 + + + + + + + + + 300 + 16777215 + + + + + + + + + + + + + + CD-ROM image + + + + + + + + + + Hard Disk image + + + + + + + + + + System type + + + + + + + + + + Video output + + + + + + + + cirrus + + + + + vmware + + + + + qxl + + + + + xenfb + + + + + tcx + + + + + cg3 + + + + + virtio + + + + + + + + Random Access Memory + + + + + + + 32 + + + + + + + Qt::Vertical + + + + 471 + 373 + + + + + + + + Kernel-based Virtual Machine + + + true + + + + + + + + + + 1 + + + + + + + Extra arguments + + + + + + + CPU cores + + + + + + + Advanced Configuration and Power Interface + + + + + + + + sb16 + + + + + es1370 + + + + + ac97 + + + + + adlib + + + + + gus + + + + + cs4231a + + + + + hda + + + + + pcspk + + + + + all + + + + + + + + Audio output + + + + + + + + + + + + 0 + 0 + 800 + 21 + + + + + + + + KEditListWidget + QWidget +
keditlistwidget.h
+
+ + KLineEdit + QLineEdit +
klineedit.h
+
+ + KUrlRequester + QFrame +
kurlrequester.h
+
+ + KIntNumInput + QWidget +
knuminput.h
+
+
+ + +
diff --git a/kemu/kemumainwindow.cpp b/kemu/kemumainwindow.cpp new file mode 100644 index 00000000..ffef0ec3 --- /dev/null +++ b/kemu/kemumainwindow.cpp @@ -0,0 +1,411 @@ +/* This file is part of the KDE libraries + Copyright (C) 2016 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kemumainwindow.h" +#include "ui_kemu.h" + +KEmuMainWindow::KEmuMainWindow(QWidget *parent, Qt::WindowFlags flags) + : KXmlGuiWindow(parent, flags), m_loading(false), m_installed(false), m_kemuui(new Ui_KEmuWindow) +{ + m_kemuui->setupUi(this); + + KAction *a = actionCollection()->addAction("harddisk_create", this, SLOT(createHardDisk())); + a->setText(i18n("Create Hard Disk image")); + a->setIcon(KIcon("drive-harddisk")); + a->setShortcut(KStandardShortcut::openNew()); + a->setWhatsThis(i18n("Create a new Hard Disk image for later use.")); + + KAction *b = actionCollection()->addAction("file_quit", this, SLOT(quit())); + b->setText(i18n("Quit")); + b->setIcon(KIcon("application-exit")); + b->setShortcut(KStandardShortcut::quit()); + b->setWhatsThis(i18n("Close the application.")); + + setupGUI(); + setAutoSaveSettings(); + + setWindowIcon(KIcon("applications-engineering")); + m_kemuui->groupBox->setEnabled(false); + m_kemuui->startStopButton->setText(i18n("Start")); + m_kemuui->startStopButton->setIcon(KIcon("system-run")); + m_kemuui->CPUInput->setMaximum(QThread::idealThreadCount()); + statusBar()->showMessage(i18n("No machines running")); + connect(m_kemuui->machinesList->listView()->selectionModel(), + SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(machineChanged(QItemSelection,QItemSelection))); + connect(m_kemuui->machinesList, SIGNAL(added(QString)), this, SLOT(addMachine(QString))); + connect(m_kemuui->startStopButton, SIGNAL(clicked()), this, SLOT(startStopMachine())); + connect(m_kemuui->machinesList, SIGNAL(removed(QString)), this, SLOT(removeMachine(QString))); + + static const QStringList qemuBins = QStringList() << "qemu-system-aarch64" + << "qemu-system-alpha" + << "qemu-system-arm" + << "qemu-system-cris" + << "qemu-system-i386" + << "qemu-system-lm32" + << "qemu-system-m68k" + << "qemu-system-microblaze" + << "qemu-system-microblazeel" + << "qemu-system-mips" + << "qemu-system-mips64" + << "qemu-system-mips64el" + << "qemu-system-mipsel" + << "qemu-system-moxie" + << "qemu-system-or32" + << "qemu-system-ppc" + << "qemu-system-ppc64" + << "qemu-system-ppcemb" + << "qemu-system-s390x" + << "qemu-system-sh4" + << "qemu-system-sh4eb" + << "qemu-system-sparc" + << "qemu-system-sparc64" + << "qemu-system-tricore" + << "qemu-system-unicore32" + << "qemu-system-x86_64" + << "qemu-system-xtensa" + << "qemu-system-xtensaeb"; + foreach (const QString bin, qemuBins) { + if(!KStandardDirs::findExe(bin).isEmpty()) { + m_installed = true; + m_kemuui->systemComboBox->addItem(bin); + } + } + + m_settings = new KSettings("kemu", KSettings::SimpleConfig); +#ifndef QT_KATIE + foreach(const QString machine, m_settings->childGroups()) { +#else + QStringList addedmachines; + foreach(const QString key, m_settings->keys()) { + const int sepindex = key.indexOf("/"); + if (sepindex < 1) { + continue; + } + QString machine = key.left(sepindex); + if (addedmachines.contains(machine)) { + continue; + } + addedmachines.append(machine); +#endif + if (m_settings->value(machine + "/enable").toBool() == true) { + m_kemuui->machinesList->insertItem(machine); + machineLoad(machine); + } else { + kDebug() << "garbage machine" << machine; + } + } + const QString lastSelected = m_settings->value("lastselected").toString(); + if (!lastSelected.isEmpty()) { + m_kemuui->machinesList->listView()->keyboardSearch(lastSelected); + } + + if(!m_installed) { + m_kemuui->startStopButton->setEnabled(false); + QMessageBox::critical(this, i18n("QEMU not available"), i18n("QEMU not available")); + return; + } + + QFileInfo kvmdev("/dev/kvm"); + if (!kvmdev.exists()) { + const QString modprobeBin = KStandardDirs::findExe("modprobe"); + if (!modprobeBin.isEmpty()) { + QProcess modprobe(this); + modprobe.start(modprobeBin, QStringList() << "-b" << "kvm"); + modprobe.waitForFinished(); + if (!kvmdev.exists()) { + QMessageBox::warning(this, i18n("KVM not available"), i18n("KVM not available")); + } + } else { + kDebug() << "modprobe not found"; + } + } + + connect(m_kemuui->CDROMInput, SIGNAL(textChanged(QString)), this, SLOT(machineSave(QString))); + connect(m_kemuui->HardDiskInput, SIGNAL(textChanged(QString)), this, SLOT(machineSave(QString))); + connect(m_kemuui->systemComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(machineSave(QString))); + connect(m_kemuui->videoComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(machineSave(QString))); + connect(m_kemuui->audioComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(machineSave(QString))); + connect(m_kemuui->RAMInput, SIGNAL(valueChanged(int)), this, SLOT(machineSave(int))); + connect(m_kemuui->CPUInput, SIGNAL(valueChanged(int)), this, SLOT(machineSave(int))); + connect(m_kemuui->KVMCheckBox, SIGNAL(stateChanged(int)), this, SLOT(machineSave(int))); + connect(m_kemuui->ACPICheckBox, SIGNAL(stateChanged(int)), this, SLOT(machineSave(int))); + connect(m_kemuui->argumentsLineEdit, SIGNAL(textChanged(QString)), this, SLOT(machineSave(QString))); +} + +KEmuMainWindow::~KEmuMainWindow() +{ + saveAutoSaveSettings(); + const QString lastSelected = m_kemuui->machinesList->currentText(); + if (!lastSelected.isEmpty()) { + m_settings->setValue("lastselected", lastSelected); + } + m_settings->sync(); + m_settings->deleteLater(); + foreach(QProcess* machineProcess, m_machines) { + const QString machine = m_machines.key(machineProcess); + kDebug() << "stopping machine" << machine; + machineProcess->terminate(); + machineProcess->deleteLater(); + m_machines.remove(machine); + } + delete m_kemuui; +} + +void KEmuMainWindow::createHardDisk() +{ + const QString qemuImg = KStandardDirs::findExe("qemu-img"); + if (qemuImg.isEmpty()) { + QMessageBox::warning(this, i18n("Requirements not met"), + i18n("qemu-img not found")); + return; + } + const QString diskPath = KFileDialog::getSaveFileName(KUrl(), QString(), this, i18n("Hard Disk path")); + if (!diskPath.isEmpty()) { + bool ok = false; + const int diskSize = KInputDialog::getInteger(i18n("Hard Disk size"), + i18n("Hard Disk size in MegaBytes"), 10, 10, INT_MAX, 1, 10, &ok, this); + if (ok) { + QProcess imageProcess(this); + imageProcess.setProcessChannelMode(QProcess::MergedChannels); + imageProcess.start(qemuImg, QStringList() << "create" << "-f" << "raw" + << diskPath << QByteArray(QByteArray::number(diskSize) + QByteArray("M"))); + imageProcess.waitForFinished(); + if (imageProcess.exitCode() == 0) { + QMessageBox::information(this, i18n("Success"), + i18n("Image successfully created")); + } else { + QMessageBox::warning(this, i18n("QEMU error"), + i18n("An error occured:\n%1", QString(imageProcess.readAll()))); + } + } + } +} + +void KEmuMainWindow::quit() +{ + qApp->quit(); +} + +void KEmuMainWindow::updateStatus() +{ + if (m_machines.size() == 0) { + statusBar()->showMessage(i18n("No machines running")); + } else { + QString machineNames; + bool firstmachine = true; + foreach (const QString name, m_machines.keys()) { + if (firstmachine) { + machineNames += name; + firstmachine = false; + } else { + machineNames += ", " + name; + } + } + const QString statusText = i18n("Machines running: %1 (%2)", machineNames, m_machines.size()); + statusBar()->showMessage(statusText); + } +} + +void KEmuMainWindow::machineSave(const QString ignored) +{ + Q_UNUSED(ignored); + if (m_loading) { + return; + } + const QString machine = m_kemuui->machinesList->currentText(); + kDebug() << "saving machine" << machine; + m_settings->setValue(machine + "/cdrom", m_kemuui->CDROMInput->url().prettyUrl()); + m_settings->setValue(machine + "/harddisk", m_kemuui->HardDiskInput->url().prettyUrl()); + m_settings->setValue(machine + "/system", m_kemuui->systemComboBox->currentText()); + m_settings->setValue(machine + "/video", m_kemuui->videoComboBox->currentText()); + m_settings->setValue(machine + "/audio", m_kemuui->audioComboBox->currentText()); + m_settings->setValue(machine + "/ram", m_kemuui->RAMInput->value()); + m_settings->setValue(machine + "/cpu", m_kemuui->CPUInput->value()); + m_settings->setValue(machine + "/kvm", m_kemuui->KVMCheckBox->isChecked()); + m_settings->setValue(machine + "/acpi", m_kemuui->ACPICheckBox->isChecked()); + m_settings->setValue(machine + "/args", m_kemuui->argumentsLineEdit->text()); + m_settings->sync(); +} + +void KEmuMainWindow::machineSave(int ignored) +{ + Q_UNUSED(ignored); + machineSave(QString()); +} + + +void KEmuMainWindow::machineLoad(const QString machine) +{ + m_loading = true; + kDebug() << "loading machine" << machine; + m_kemuui->CDROMInput->setUrl(m_settings->value(machine + "/cdrom").toUrl()); + m_kemuui->HardDiskInput->setUrl(m_settings->value(machine + "/harddisk").toUrl()); + const QString system = m_settings->value(machine + "/system").toString(); + const int systemIndex = m_kemuui->systemComboBox->findText(system); + m_kemuui->systemComboBox->setCurrentIndex(systemIndex); + const QString video = m_settings->value(machine + "/video", "virtio").toString(); + const int videoIndex = m_kemuui->videoComboBox->findText(video); + m_kemuui->videoComboBox->setCurrentIndex(videoIndex); + const QString audio = m_settings->value(machine + "/audio", "ac97").toString(); + const int audioIndex = m_kemuui->audioComboBox->findText(audio); + m_kemuui->audioComboBox->setCurrentIndex(audioIndex); + m_kemuui->RAMInput->setValue(m_settings->value(machine + "/ram", 32).toInt()); + m_kemuui->CPUInput->setValue(m_settings->value(machine + "/cpu", 1).toInt()); + m_kemuui->KVMCheckBox->setChecked(m_settings->value(machine + "/kvm", false).toBool()); + m_kemuui->ACPICheckBox->setChecked(m_settings->value(machine + "/acpi", false).toBool()); + m_kemuui->argumentsLineEdit->setText(m_settings->value(machine + "/args").toString()); + m_loading = false; +} + +void KEmuMainWindow::machineChanged(QItemSelection ignored, QItemSelection ignored2) +{ + Q_UNUSED(ignored); + Q_UNUSED(ignored2); + const QString machine = m_kemuui->machinesList->currentText(); + if (!machine.isEmpty()) { + QFileInfo kvmdev("/dev/kvm"); + m_kemuui->KVMCheckBox->setEnabled(kvmdev.exists()); + + m_kemuui->startStopButton->setEnabled(m_installed); + m_kemuui->groupBox->setEnabled(true); + if (m_machines.contains(machine)) { + kDebug() << "machine is running" << machine; + m_kemuui->startStopButton->setText(i18n("Stop")); + m_kemuui->startStopButton->setIcon(KIcon("system-shutdown")); + } else { + kDebug() << "machine is stopped" << machine; + m_kemuui->startStopButton->setText(i18n("Start")); + m_kemuui->startStopButton->setIcon(KIcon("system-run")); + } + machineLoad(machine); + } else { + m_kemuui->startStopButton->setEnabled(false); + m_kemuui->groupBox->setEnabled(false); + } +} + +void KEmuMainWindow::machineFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + QProcess *machineProcess = qobject_cast(sender()); + disconnect(machineProcess, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(machineFinished(int,QProcess::ExitStatus))); + if (exitCode != 0) { + QMessageBox::warning(this, i18n("QEMU error"), + i18n("An error occured:\n%1", QString(machineProcess->readAll()))); + } + m_kemuui->startStopButton->setText(i18n("Start")); + m_kemuui->startStopButton->setIcon(KIcon("system-run")); + const QString machine = m_machines.key(machineProcess); + m_machines.remove(machine); + machineProcess->deleteLater(); + + updateStatus(); +} + +void KEmuMainWindow::addMachine(const QString machine) +{ + m_settings->setValue(machine + "/enable", true); + // TODO: set defaults? + m_settings->sync(); +} + +void KEmuMainWindow::startStopMachine() +{ + const QString machine = m_kemuui->machinesList->currentText(); + if (!machine.isEmpty()) { + if (m_machines.contains(machine)) { + kDebug() << "stopping machine" << machine; + QProcess* machineProcess = m_machines.take(machine); + machineProcess->terminate(); + machineProcess->deleteLater(); + m_kemuui->startStopButton->setText(i18n("Start")); + m_kemuui->startStopButton->setIcon(KIcon("system-run")); + } else { + kDebug() << "starting machine" << machine; + QStringList machineArgs; + machineArgs << "-name" << machine; + const QString CDRom = m_kemuui->CDROMInput->url().prettyUrl(); + if (!CDRom.isEmpty()) { + machineArgs << "-cdrom" << CDRom; + } + const QString HardDisk = m_kemuui->HardDiskInput->url().prettyUrl(); + if (!HardDisk.isEmpty()) { + machineArgs << "-hda" << HardDisk; + } + if (CDRom.isEmpty() && HardDisk.isEmpty()) { + QMessageBox::warning(this, i18n("Requirements not met"), + i18n("Either CD-ROM or Hard Disk image must be set")); + return; + } + machineArgs << "-vga" << m_kemuui->videoComboBox->currentText(); + machineArgs << "-soundhw" << m_kemuui->audioComboBox->currentText(); + machineArgs << "-m" << QByteArray::number(m_kemuui->RAMInput->value()); + machineArgs << "-smp" << QByteArray::number(m_kemuui->CPUInput->value()); + if (m_kemuui->KVMCheckBox->isEnabled() && m_kemuui->KVMCheckBox->isChecked()) { + machineArgs << "-enable-kvm"; + } + if (!m_kemuui->ACPICheckBox->isChecked()) { + machineArgs << "-no-acpi"; + } + const QString extraArgs = m_kemuui->argumentsLineEdit->text(); + if (!extraArgs.isEmpty()) { + foreach (const QString argument, extraArgs.split(" ")) { + machineArgs << argument; + } + } + QProcess* machineProcess = new QProcess(this); + machineProcess->setProcessChannelMode(QProcess::MergedChannels); + m_kemuui->startStopButton->setText(i18n("Stop")); + m_kemuui->startStopButton->setIcon(KIcon("system-shutdown")); + m_machines.insert(machine, machineProcess); + connect(machineProcess, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(machineFinished(int,QProcess::ExitStatus))); + machineProcess->start(m_kemuui->systemComboBox->currentText(), machineArgs); + } + + updateStatus(); + } +} + +void KEmuMainWindow::removeMachine(const QString machine) +{ + if (m_machines.contains(machine)) { + kDebug() << "stopping machine" << machine; + QProcess* machineProcess = m_machines.take(machine); + machineProcess->terminate(); + machineProcess->deleteLater(); + } + kDebug() << "removing machine" << machine; + m_settings->setValue(machine + "/enable", false); + m_settings->sync(); +} diff --git a/kemu/kemumainwindow.h b/kemu/kemumainwindow.h new file mode 100644 index 00000000..c66c595c --- /dev/null +++ b/kemu/kemumainwindow.h @@ -0,0 +1,62 @@ +/* This file is part of the KDE libraries + Copyright (C) 2016 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KEMUMAINWINDOW_H +#define KEMUMAINWINDOW_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class Ui_KEmuWindow; +QT_END_NAMESPACE + +class KEmuMainWindow: public KXmlGuiWindow +{ + Q_OBJECT +public: + KEmuMainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0); + ~KEmuMainWindow(); + +public slots: + void createHardDisk(); + void quit(); + +private slots: + void machineLoad(const QString machine); + void machineSave(const QString ignored); + void machineSave(int ignored); + void machineChanged(QItemSelection ignored, QItemSelection ignored2); + void machineFinished(int exitCode, QProcess::ExitStatus exitStatus); + void addMachine(const QString machine); + void startStopMachine(); + void removeMachine(const QString machine); + +private: + void updateStatus(); + + bool m_loading; + bool m_installed; + Ui_KEmuWindow *m_kemuui; + QSettings *m_settings; + QHash m_machines; +}; + +#endif // KEMUMAINWINDOW_H \ No newline at end of file diff --git a/kemu/kemuui.rc b/kemu/kemuui.rc new file mode 100644 index 00000000..20986a22 --- /dev/null +++ b/kemu/kemuui.rc @@ -0,0 +1,13 @@ + + + + &File + + + + + + + Main Toolbar + + diff --git a/kemu/main.cpp b/kemu/main.cpp new file mode 100644 index 00000000..f0cb32ac --- /dev/null +++ b/kemu/main.cpp @@ -0,0 +1,43 @@ +/* This file is part of the KDE libraries + Copyright (C) 2016 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include +#include +#include +#include "kemumainwindow.h" + +int main(int argc, char** argv) +{ + KAboutData aboutData("kemu", 0, ki18n("KEmu"), + "1.0.0", ki18n("Simple QEMU frontend for KDE."), + KAboutData::License_GPL_V2, + ki18n("(c) 2016 Ivailo Monev"), + KLocalizedString(), + "http://github.com/fluxer/katana" + ); + + aboutData.addAuthor(ki18n("Ivailo Monev"), + ki18n("Maintainer"), + "xakepa10@gmail.com"); + aboutData.setProgramIconName(QLatin1String("applications-engineering")); + KCmdLineArgs::init(argc, argv, &aboutData); + KApplication *kemuapp = new KApplication(); + KEmuMainWindow *kemuwindow = new KEmuMainWindow(); + kemuwindow->show(); + return kemuapp->exec(); +}