mirror of
https://github.com/Quill-OS/quill.git
synced 2024-12-26 23:57:22 -08:00
Merge branch 'userapps' into 'master'
This commit is contained in:
commit
0dfcc20409
17 changed files with 1486 additions and 274 deletions
230
apps.cpp
230
apps.cpp
|
@ -1,8 +1,14 @@
|
||||||
#include "apps.h"
|
#include "apps.h"
|
||||||
#include "ui_apps.h"
|
#include "ui_apps.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "userapps.h"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QJsonParseError>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
apps::apps(QWidget *parent) :
|
apps::apps(QWidget *parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
|
@ -29,6 +35,8 @@ apps::apps(QWidget *parent) :
|
||||||
ui->reversiLaunchBtn->setStyleSheet("background: lightGrey; font-size: 9pt; padding: 8px");
|
ui->reversiLaunchBtn->setStyleSheet("background: lightGrey; font-size: 9pt; padding: 8px");
|
||||||
ui->g2048LaunchBtn->setStyleSheet("background: lightGrey; font-size: 9pt; padding: 8px");
|
ui->g2048LaunchBtn->setStyleSheet("background: lightGrey; font-size: 9pt; padding: 8px");
|
||||||
|
|
||||||
|
ui->noUserAppsAvailableLabel->hide();
|
||||||
|
|
||||||
// Hiding KoBox apps button and label if X11 isn't enabled/wasn't started
|
// Hiding KoBox apps button and label if X11 isn't enabled/wasn't started
|
||||||
if(checkconfig("/external_root/boot/flags/X11_START") == false or checkconfig("/external_root/boot/flags/X11_STARTED") == false) {
|
if(checkconfig("/external_root/boot/flags/X11_START") == false or checkconfig("/external_root/boot/flags/X11_STARTED") == false) {
|
||||||
ui->label_5->hide();
|
ui->label_5->hide();
|
||||||
|
@ -61,6 +69,15 @@ apps::apps(QWidget *parent) :
|
||||||
ui->lightmapsLaunchBtn->deleteLater();
|
ui->lightmapsLaunchBtn->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ui->editUserAppsBtn->setProperty("type", "borderless");
|
||||||
|
ui->editUserAppsBtn->setIcon(QIcon(":/resources/edit.png"));
|
||||||
|
|
||||||
|
// Refresh because Qt shows the scrollbar for one second then hides it, leaving a mark on the eInk screen
|
||||||
|
QTimer::singleShot(1750, this, SLOT(refreshScreenNative()));
|
||||||
|
|
||||||
|
jsonParseSuccess = parseJson();
|
||||||
|
showUserApps(false);
|
||||||
|
|
||||||
QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss");
|
QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss");
|
||||||
stylesheetFile.open(QFile::ReadOnly);
|
stylesheetFile.open(QFile::ReadOnly);
|
||||||
this->setStyleSheet(stylesheetFile.readAll());
|
this->setStyleSheet(stylesheetFile.readAll());
|
||||||
|
@ -160,3 +177,216 @@ void apps::on_g2048LaunchBtn_clicked()
|
||||||
void apps::showToastNative(QString messageToDisplay) {
|
void apps::showToastNative(QString messageToDisplay) {
|
||||||
emit showToast(messageToDisplay);
|
emit showToast(messageToDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function opens and reads the main GUI user applications' JSON file, parses and verifies its content to avoid issues in the future.
|
||||||
|
*/
|
||||||
|
bool apps::parseJson() {
|
||||||
|
// If the path changes, it is also used statically in showUserApps()
|
||||||
|
jsonFile.setFileName("/mnt/onboard/onboard/.apps/apps.json");
|
||||||
|
bool jsonCheckSuccess = true;
|
||||||
|
|
||||||
|
if(jsonFile.exists() == false) {
|
||||||
|
log("GUI user applications' main JSON file is missing", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jsonFile.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||||
|
QString fileRead = jsonFile.readAll();
|
||||||
|
jsonFile.close();
|
||||||
|
|
||||||
|
jsonDocument = QJsonDocument::fromJson(fileRead.toUtf8());
|
||||||
|
if(jsonDocument.isNull() == true) {
|
||||||
|
log("GUI user applications' main JSON file is invalid", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QJsonObject jsonObject = jsonDocument.object();
|
||||||
|
if(jsonObject["list"].isArray() == true) {
|
||||||
|
QJsonArray jsonArray = jsonObject["list"].toArray();
|
||||||
|
for(QJsonValueRef refJsonObject: jsonArray) {
|
||||||
|
if(refJsonObject.isObject()) {
|
||||||
|
QJsonObject jsonMainObject = refJsonObject.toObject();
|
||||||
|
if(jsonMainObject.size() == 9) {
|
||||||
|
if(!jsonMainObject["Name"].isString()) {
|
||||||
|
QString function = __func__; log(function + ": Invalid 'Name' type inside object", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(!jsonMainObject["Author"].isString()) {
|
||||||
|
QString function = __func__; log(function + ": Invalid 'Author' type inside object", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(!jsonMainObject["AuthorContact"].isString()) {
|
||||||
|
QString function = __func__; log(function + ": Invalid 'AuthorContact' type inside object", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(!jsonMainObject["Version"].isString()) {
|
||||||
|
QString function = __func__; log(function + ": Invalid 'Version' type inside object", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(!jsonMainObject["IconPath"].isString()) {
|
||||||
|
log("JSON: Invalid IconPath type inside object", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(!jsonMainObject["ExecPath"].isString()) {
|
||||||
|
QString function = __func__; log(function + ": Invalid 'ExecPath' type inside object", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(jsonMainObject["ExecPath"].toString().contains("..")) {
|
||||||
|
// Possible security risk
|
||||||
|
showToastNative("ERROR: 'ExecPath' has invalid path");
|
||||||
|
QString function = __func__; log(function + ": 'ExecPath' contains \"..\"", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!jsonMainObject["Enabled"].isBool()) {
|
||||||
|
QString function = __func__; log(function + ": Invalid 'Enabled' type inside object", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(!jsonMainObject["SupportedDevices"].isArray()) {
|
||||||
|
QString function = __func__; log(function + ": Invalid 'SupportedDevices' type inside object", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QJsonArray jsonArray = jsonMainObject["SupportedDevices"].toArray();
|
||||||
|
for(QJsonValueRef refJsonObject: jsonArray) {
|
||||||
|
// https://doc.qt.io/qt-5/qjsonvalue.html#toInt
|
||||||
|
if(!refJsonObject.isString()) {
|
||||||
|
QString function = __func__; log(function + ": Array from 'RequiredFeatures' contains a wrong type", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!jsonMainObject["RequiredFeatures"].isArray()) {
|
||||||
|
QString function = __func__; log(function + ": Invalid 'RequiredFeatures' type inside object", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QJsonArray jsonArray = jsonMainObject["RequiredFeatures"].toArray();
|
||||||
|
for(QJsonValueRef refJsonObject: jsonArray) {
|
||||||
|
// https://doc.qt.io/qt-5/qjsonvalue.html#toInt
|
||||||
|
if(!refJsonObject.isDouble()) {
|
||||||
|
QString function = __func__; log(function + ": Array from 'RequiredFeatures' contains a wrong type", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QString function = __func__; QString message = function + ": An object inside list array has too many items (or not enough): ";
|
||||||
|
message.append(QString::number(jsonMainObject.size()));
|
||||||
|
log(message, className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QString function = __func__; log(function + ": List array has an item of other type than object", className);
|
||||||
|
jsonCheckSuccess = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jsonCheckSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
void apps::on_editUserAppsBtn_clicked()
|
||||||
|
{
|
||||||
|
if(userAppsSecondPage == false) {
|
||||||
|
userAppsSecondPage = true;
|
||||||
|
|
||||||
|
// Settings page
|
||||||
|
ui->editUserAppsBtn->setIcon(QIcon(":/resources/save.png"));
|
||||||
|
showUserApps(userAppsSecondPage);
|
||||||
|
emit showUserAppsEdit(userAppsSecondPage);
|
||||||
|
|
||||||
|
QTimer::singleShot(500, this, SLOT(refreshScreenNative()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
userAppsSecondPage = false;
|
||||||
|
userAppsAvailable = false;
|
||||||
|
|
||||||
|
// Launch page
|
||||||
|
ui->editUserAppsBtn->setIcon(QIcon(":/resources/edit.png"));
|
||||||
|
// It changed via updateJsonFileSlot, and now it writes it only once
|
||||||
|
jsonFile.open(QFile::WriteOnly | QFile::Text | QFile::Truncate);
|
||||||
|
jsonFile.write(jsonDocument.toJson());
|
||||||
|
jsonFile.flush();
|
||||||
|
jsonFile.close();
|
||||||
|
|
||||||
|
showUserApps(userAppsSecondPage);
|
||||||
|
emit showUserAppsEdit(userAppsSecondPage);
|
||||||
|
|
||||||
|
QTimer::singleShot(500, this, SLOT(refreshScreenNative()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void apps::showUserApps(bool showDisabledJson)
|
||||||
|
{
|
||||||
|
emit clearAppsLayout();
|
||||||
|
|
||||||
|
if(jsonParseSuccess == true) {
|
||||||
|
QString function = __func__; log(function + ": Main user applications' JSON is valid", className);
|
||||||
|
QJsonArray jsonListArray = jsonDocument.object()["list"].toArray();
|
||||||
|
for(QJsonValueRef refJsonObject: jsonListArray) {
|
||||||
|
QJsonObject appInfo = refJsonObject.toObject();
|
||||||
|
if(appInfo["Enabled"].toBool() == true or showDisabledJson == true) {
|
||||||
|
userAppsAvailable = true;
|
||||||
|
userapps * newUserApp = new userapps;
|
||||||
|
newUserApp->provideInfo(appInfo);
|
||||||
|
connect(this, SIGNAL(clearAppsLayout()), newUserApp, SLOT(deleteLater()));
|
||||||
|
connect(this, SIGNAL(showUserAppsEdit(bool)), newUserApp, SLOT(changePageEnabling(bool)));
|
||||||
|
connect(this, SIGNAL(updateJsonFileSignal(QJsonDocument)), newUserApp, SLOT(updateJsonFileSlotUA(QJsonDocument)));
|
||||||
|
connect(newUserApp, SIGNAL(updateJsonFileSignalUA(QJsonDocument)), this, SLOT(updateJsonFileSlot(QJsonDocument)));
|
||||||
|
newUserApp->jsonDocument = jsonDocument;
|
||||||
|
newUserApp->jsonFilePath = jsonFile.fileName();
|
||||||
|
ui->verticalLayout_4->addWidget(newUserApp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(userAppsAvailable == false) {
|
||||||
|
ui->noUserAppsAvailableLabel->show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui->noUserAppsAvailableLabel->hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(QFile::exists("/mnt/onboard/onboard/.apps/apps.json")) {
|
||||||
|
QString function = __func__; log(function + ": Main user applications' JSON file is invalid", className);
|
||||||
|
QTimer::singleShot(500, this, SLOT(showFailedToParseMainUserAppsJsonFile()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QString function = __func__; log(function + ": Main user applications' JSON file doesn't exist; assuming that no user applications are currently installed", className);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->editUserAppsBtn->hide();
|
||||||
|
ui->label_6->hide();
|
||||||
|
ui->line_2->hide();
|
||||||
|
ui->line_3->hide();
|
||||||
|
ui->editUserAppsBtn->hide();
|
||||||
|
ui->label_6->deleteLater();
|
||||||
|
ui->horizontalLayout->deleteLater();
|
||||||
|
ui->line_2->deleteLater();
|
||||||
|
ui->line_3->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void apps::updateJsonFileSlot(QJsonDocument jsonDocumentFunc)
|
||||||
|
{
|
||||||
|
jsonDocument = jsonDocumentFunc;
|
||||||
|
emit updateJsonFileSignal(jsonDocument);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apps::showFailedToParseMainUserAppsJsonFile() {
|
||||||
|
emit showToast("Failed to parse 'apps.json'");
|
||||||
|
}
|
||||||
|
|
16
apps.h
16
apps.h
|
@ -7,6 +7,8 @@
|
||||||
#include <koboxappsdialog.h>
|
#include <koboxappsdialog.h>
|
||||||
#include <generaldialog.h>
|
#include <generaldialog.h>
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class apps;
|
class apps;
|
||||||
}
|
}
|
||||||
|
@ -30,9 +32,14 @@ private slots:
|
||||||
void on_koboxAppsOpenButton_clicked();
|
void on_koboxAppsOpenButton_clicked();
|
||||||
void on_vncLaunchBtn_clicked();
|
void on_vncLaunchBtn_clicked();
|
||||||
void on_reversiLaunchBtn_clicked();
|
void on_reversiLaunchBtn_clicked();
|
||||||
|
void on_editUserAppsBtn_clicked();
|
||||||
void refreshScreenNative();
|
void refreshScreenNative();
|
||||||
void on_g2048LaunchBtn_clicked();
|
void on_g2048LaunchBtn_clicked();
|
||||||
void showToastNative(QString messageToDisplay);
|
void showToastNative(QString messageToDisplay);
|
||||||
|
bool parseJson();
|
||||||
|
void showUserApps(bool showDisabledJson);
|
||||||
|
void updateJsonFileSlot(QJsonDocument jsonDocument);
|
||||||
|
void showFailedToParseMainUserAppsJsonFile();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::apps *ui;
|
Ui::apps *ui;
|
||||||
|
@ -41,9 +48,18 @@ private:
|
||||||
koboxAppsDialog *koboxAppsDialogWindow;
|
koboxAppsDialog *koboxAppsDialogWindow;
|
||||||
generalDialog *generalDialogWindow;
|
generalDialog *generalDialogWindow;
|
||||||
|
|
||||||
|
QFile jsonFile;
|
||||||
|
QJsonDocument jsonDocument;
|
||||||
|
bool jsonParseSuccess = false;
|
||||||
|
bool userAppsSecondPage = false;
|
||||||
|
bool userAppsAvailable = false;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void refreshScreen();
|
void refreshScreen();
|
||||||
void showToast(QString messageToDisplay);
|
void showToast(QString messageToDisplay);
|
||||||
|
void updateJsonFileSignal(QJsonDocument jsonDocument);
|
||||||
|
void clearAppsLayout();
|
||||||
|
void showUserAppsEdit(bool show);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APPS_H
|
#endif // APPS_H
|
||||||
|
|
734
apps.ui
734
apps.ui
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>400</width>
|
<width>430</width>
|
||||||
<height>321</height>
|
<height>544</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -28,12 +28,469 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="4" column="0">
|
<property name="topMargin">
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<number>0</number>
|
||||||
<property name="bottomMargin">
|
</property>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
</layout>
|
<property name="horizontalScrollBarPolicy">
|
||||||
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
|
</property>
|
||||||
|
<property name="widgetResizable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>-30</y>
|
||||||
|
<width>407</width>
|
||||||
|
<height>541</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>15</number>
|
||||||
|
</property>
|
||||||
|
<property name="verticalSpacing">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>KoBox apps</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="12" column="0">
|
||||||
|
<widget class="QLabel" name="vncViewerLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>VNC viewer</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QPushButton" name="scribbleLaunchBtn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Inter</family>
|
||||||
|
<weight>75</weight>
|
||||||
|
<italic>false</italic>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Saved words</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="scribbleLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Scribble</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Calculator</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QPushButton" name="calendarLaunchBtn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Inter</family>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QPushButton" name="koboxAppsOpenButton">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Inter</family>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Open</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Light Maps</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="reversiLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Reversi</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QPushButton" name="reversiLaunchBtn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QPushButton" name="savedWordsLaunchBtn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Inter</family>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="1">
|
||||||
|
<widget class="QPushButton" name="calculatorLaunchBtn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Inter</family>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="g2048Label">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>2048</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QPushButton" name="g2048LaunchBtn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="12" column="1">
|
||||||
|
<widget class="QPushButton" name="vncLaunchBtn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Inter</family>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="11" column="1">
|
||||||
|
<widget class="QPushButton" name="lightmapsLaunchBtn">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Inter</family>
|
||||||
|
<weight>75</weight>
|
||||||
|
<italic>false</italic>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="calendarLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Calendar</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_3">
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<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>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>User apps</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>10</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="editUserAppsBtn">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<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>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_2">
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="noUserAppsAvailableLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Chivo</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>
|
||||||
|
No user apps currently available</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
|
@ -44,276 +501,13 @@
|
||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Apps</string>
|
<string>Built-in apps</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item row="7" column="1">
|
|
||||||
<widget class="QPushButton" name="calculatorLaunchBtn">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Inter</family>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QPushButton" name="calendarLaunchBtn">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Inter</family>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Light Maps</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="scribbleLabel">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Scribble</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QPushButton" name="savedWordsLaunchBtn">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Inter</family>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="reversiLabel">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Reversi</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Saved words</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>KoBox apps</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="calendarLabel">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Calendar</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<widget class="QPushButton" name="lightmapsLaunchBtn">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Inter</family>
|
|
||||||
<weight>75</weight>
|
|
||||||
<italic>false</italic>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QPushButton" name="reversiLaunchBtn">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="1">
|
|
||||||
<widget class="QPushButton" name="vncLaunchBtn">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Inter</family>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QPushButton" name="koboxAppsOpenButton">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Inter</family>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Open</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Calculator</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="9" column="0">
|
|
||||||
<widget class="QLabel" name="vncViewerLabel">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>VNC viewer</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QPushButton" name="scribbleLaunchBtn">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Inter</family>
|
|
||||||
<weight>75</weight>
|
|
||||||
<italic>false</italic>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QPushButton" name="g2048LaunchBtn">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Launch</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="g2048Label">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>2048</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<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="0">
|
<item row="1" column="0">
|
||||||
<widget class="Line" name="line">
|
<widget class="Line" name="line">
|
||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
|
|
2
eink.qrc
2
eink.qrc
|
@ -74,5 +74,7 @@
|
||||||
<file>resources/clock.png</file>
|
<file>resources/clock.png</file>
|
||||||
<file>resources/eink-square-encfs.qss</file>
|
<file>resources/eink-square-encfs.qss</file>
|
||||||
<file>resources/tzlist</file>
|
<file>resources/tzlist</file>
|
||||||
|
<file>resources/edit.png</file>
|
||||||
|
<file>resources/save.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
97
functions.h
97
functions.h
|
@ -13,6 +13,12 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonParseError>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
@ -122,6 +128,13 @@ namespace global {
|
||||||
namespace logger {
|
namespace logger {
|
||||||
inline bool status;
|
inline bool status;
|
||||||
}
|
}
|
||||||
|
namespace userApps {
|
||||||
|
inline bool appCompatibilityDialog;
|
||||||
|
inline QString appCompatibilityText;
|
||||||
|
inline bool appCompatibilityLastContinueStatus = true; // This is for RequiredFeatures to show only one dialog if 'Cancel' is clicked.
|
||||||
|
inline bool appInfoDialog;
|
||||||
|
inline bool launchApp;
|
||||||
|
}
|
||||||
inline QString systemInfoText;
|
inline QString systemInfoText;
|
||||||
inline bool forbidOpenSearchDialog;
|
inline bool forbidOpenSearchDialog;
|
||||||
inline bool isN705 = false;
|
inline bool isN705 = false;
|
||||||
|
@ -846,6 +859,90 @@ namespace {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void updateUserAppsMainJsonFile() {
|
||||||
|
QDirIterator appsDir("/mnt/onboard/onboard/.apps", QDirIterator::NoIteratorFlags);
|
||||||
|
QFile newJsonFile = QFile{"/mnt/onboard/onboard/.apps/apps.json"};
|
||||||
|
QJsonDocument newJsonDocument;
|
||||||
|
QJsonArray array;
|
||||||
|
|
||||||
|
while (appsDir.hasNext())
|
||||||
|
{
|
||||||
|
QDir dir(appsDir.next());
|
||||||
|
if(dir.exists() == true) {
|
||||||
|
if(dir.path().split("/").last().contains(".") == false) {
|
||||||
|
QFile jsonSmall = QFile{dir.path() + "/app.json"};
|
||||||
|
if(jsonSmall.exists() == true) {
|
||||||
|
jsonSmall.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||||
|
QString jsonString = jsonSmall.readAll();
|
||||||
|
jsonSmall.close();
|
||||||
|
|
||||||
|
QJsonDocument jsonSmallDoc = QJsonDocument::fromJson(jsonString.toUtf8());
|
||||||
|
if(jsonSmallDoc["app"].isObject() == true) {
|
||||||
|
QJsonObject jsonSmallMainObj = jsonSmallDoc["app"].toObject();
|
||||||
|
array.append(jsonSmallMainObj);
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log("Error: User application '" + appsDir.path() + "''s JSON file descriptor is missing main object 'app'", "main");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QString message = "User application '" + appsDir.path() + "' does not contain any 'app.json' file: ";
|
||||||
|
message.append(jsonSmall.fileName());
|
||||||
|
log(message, "main");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// https://forum.qt.io/topic/104791/how-i-can-create-json-format-in-qt/5
|
||||||
|
QJsonObject root;
|
||||||
|
root["list"] = array;
|
||||||
|
newJsonDocument.setObject(root);
|
||||||
|
|
||||||
|
newJsonFile.open(QFile::WriteOnly | QFile::Text | QFile::Truncate);
|
||||||
|
newJsonFile.write(newJsonDocument.toJson());
|
||||||
|
newJsonFile.flush();
|
||||||
|
newJsonFile.close();
|
||||||
|
}
|
||||||
|
void updateUserAppsSmallJsonFiles() {
|
||||||
|
QFile jsonFile = QFile{"/mnt/onboard/onboard/.apps/apps.json"};
|
||||||
|
|
||||||
|
jsonFile.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||||
|
QString fileRead = jsonFile.readAll();
|
||||||
|
jsonFile.close();
|
||||||
|
QJsonDocument jsonDocument = QJsonDocument::fromJson(fileRead.toUtf8());
|
||||||
|
|
||||||
|
if(jsonDocument["list"].isArray() == true) {
|
||||||
|
QJsonArray jsonArray = jsonDocument["list"].toArray();
|
||||||
|
for(QJsonValueRef refJsonObject: jsonArray) {
|
||||||
|
QJsonObject jsonMainObject = refJsonObject.toObject();
|
||||||
|
QString appName = jsonMainObject["Name"].toString();
|
||||||
|
|
||||||
|
// This needs to be here and not at the beggining of this function because it is an iterator
|
||||||
|
QDirIterator appsDir("/mnt/onboard/onboard/.apps", QDirIterator::NoIteratorFlags);
|
||||||
|
while (appsDir.hasNext()) {
|
||||||
|
QDir dir(appsDir.next());
|
||||||
|
if(dir.exists() == true) {
|
||||||
|
if(dir.path().split("/").last().toLower().contains(appName.toLower()) == true) {
|
||||||
|
QJsonObject root;
|
||||||
|
root["app"] = refJsonObject.toObject();;
|
||||||
|
QJsonDocument newJsonDocument;
|
||||||
|
newJsonDocument.setObject(root);
|
||||||
|
|
||||||
|
QFile newSmallJson = QFile{dir.path() + "/" + "app.json"};
|
||||||
|
|
||||||
|
newSmallJson.open(QIODevice::ReadWrite);
|
||||||
|
QTextStream stream(&newSmallJson);
|
||||||
|
stream << newJsonDocument.toJson() << Qt::endl;
|
||||||
|
newSmallJson.flush();
|
||||||
|
newSmallJson.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // FUNCTIONS_H
|
#endif // FUNCTIONS_H
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
#include <QListView>
|
#include <QListView>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QTextEdit>
|
||||||
|
|
||||||
generalDialog::generalDialog(QWidget *parent) :
|
generalDialog::generalDialog(QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
|
@ -131,6 +132,7 @@ generalDialog::generalDialog(QWidget *parent) :
|
||||||
}
|
}
|
||||||
else if(global::usbms::usbmsDialog == true) {
|
else if(global::usbms::usbmsDialog == true) {
|
||||||
usbmsDialog = true;
|
usbmsDialog = true;
|
||||||
|
ui->stackedWidget->setCurrentIndex(0);
|
||||||
ui->okBtn->setText("Connect");
|
ui->okBtn->setText("Connect");
|
||||||
ui->cancelBtn->setText("Not now");
|
ui->cancelBtn->setText("Not now");
|
||||||
ui->bodyLabel->setText("<font face='u001'>Do you want to connect your device to a computer to manage books</font><font face='Inter'>?</font>");
|
ui->bodyLabel->setText("<font face='u001'>Do you want to connect your device to a computer to manage books</font><font face='Inter'>?</font>");
|
||||||
|
@ -187,9 +189,29 @@ generalDialog::generalDialog(QWidget *parent) :
|
||||||
ui->bodyLabel->setText("<font face='u001'>New files have been found in 'encfs-dropbox'. Would you want to repack your encrypted storage</font><font face='Inter'>?</font>");
|
ui->bodyLabel->setText("<font face='u001'>New files have been found in 'encfs-dropbox'. Would you want to repack your encrypted storage</font><font face='Inter'>?</font>");
|
||||||
QTimer::singleShot(50, this, SLOT(adjust_size()));
|
QTimer::singleShot(50, this, SLOT(adjust_size()));
|
||||||
}
|
}
|
||||||
|
else if(global::userApps::appCompatibilityDialog == true) {
|
||||||
|
appCompatibilityDialog = true;
|
||||||
|
global::userApps::appCompatibilityLastContinueStatus = true;
|
||||||
|
ui->okBtn->setText("Continue");
|
||||||
|
ui->cancelBtn->setText("Cancel");
|
||||||
|
ui->bodyLabel->setText(global::userApps::appCompatibilityText);
|
||||||
|
ui->headerLabel->setText("Compatibility warning");
|
||||||
|
QTimer::singleShot(50, this, SLOT(adjust_size()));
|
||||||
|
}
|
||||||
|
else if(global::userApps::appInfoDialog == true) {
|
||||||
|
appInfoDialog = true;
|
||||||
|
textwidgetWindow = new textwidget();
|
||||||
|
|
||||||
|
ui->headerLabel->setText("App info");
|
||||||
|
ui->stackedWidget->setCurrentIndex(1);
|
||||||
|
ui->mainStackedWidget->insertWidget(1, textwidgetWindow);
|
||||||
|
ui->mainStackedWidget->setCurrentIndex(1);
|
||||||
|
yIncrease = 1.8;
|
||||||
|
QTimer::singleShot(50, this, SLOT(increaseSize()));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// We shouldn't be there ;)
|
// We shouldn't be there ;)
|
||||||
;
|
log("Launched without settings", className);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Centering dialog
|
// Centering dialog
|
||||||
|
@ -248,6 +270,12 @@ void generalDialog::on_cancelBtn_clicked()
|
||||||
else if(global::encfs::repackDialog == true) {
|
else if(global::encfs::repackDialog == true) {
|
||||||
global::encfs::repackDialog = false;
|
global::encfs::repackDialog = false;
|
||||||
}
|
}
|
||||||
|
else if(global::userApps::appCompatibilityDialog == true) {
|
||||||
|
global::userApps::launchApp = false;
|
||||||
|
global::userApps::appCompatibilityLastContinueStatus = false;
|
||||||
|
global::userApps::appCompatibilityText = "";
|
||||||
|
global::userApps::appCompatibilityDialog = false;
|
||||||
|
}
|
||||||
generalDialog::close();
|
generalDialog::close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,6 +535,13 @@ void generalDialog::on_okBtn_clicked()
|
||||||
string_writeconfig("/external_root/run/encfs_repack", "true");
|
string_writeconfig("/external_root/run/encfs_repack", "true");
|
||||||
quit_restart();
|
quit_restart();
|
||||||
}
|
}
|
||||||
|
else if(global::userApps::appCompatibilityDialog == true) {
|
||||||
|
global::userApps::launchApp = true;
|
||||||
|
global::userApps::appCompatibilityText = "";
|
||||||
|
global::userApps::appCompatibilityLastContinueStatus = true; // Not really necceserry, only if something fails horibly
|
||||||
|
global::userApps::appCompatibilityDialog = false;
|
||||||
|
generalDialog::close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void generalDialog::on_acceptBtn_clicked()
|
void generalDialog::on_acceptBtn_clicked()
|
||||||
{
|
{
|
||||||
|
@ -533,6 +568,11 @@ void generalDialog::on_acceptBtn_clicked()
|
||||||
global::text::textBrowserDialog = false;
|
global::text::textBrowserDialog = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(appInfoDialog == true) {
|
||||||
|
global::text::textBrowserContents = "";
|
||||||
|
global::userApps::appInfoDialog = false;
|
||||||
|
}
|
||||||
|
|
||||||
// We don't have any other option ;p
|
// We don't have any other option ;p
|
||||||
generalDialog::close();
|
generalDialog::close();
|
||||||
}
|
}
|
||||||
|
@ -552,6 +592,7 @@ void generalDialog::restartSearchDialog() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void generalDialog::setupKeyboardDialog() {
|
void generalDialog::setupKeyboardDialog() {
|
||||||
|
ui->stackedWidget->setCurrentIndex(0);
|
||||||
keyboardDialog = true;
|
keyboardDialog = true;
|
||||||
ui->stackedWidget->setVisible(true);
|
ui->stackedWidget->setVisible(true);
|
||||||
if(global::keyboard::searchDialog == true) {
|
if(global::keyboard::searchDialog == true) {
|
||||||
|
@ -732,3 +773,25 @@ void generalDialog::waitForGutenbergSearchDone() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generalDialog::increaseSize()
|
||||||
|
{
|
||||||
|
log("Resizing generalDialog", className);
|
||||||
|
|
||||||
|
ui->topStackedWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||||
|
ui->mainStackedWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
|
||||||
|
ui->stackedWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
|
||||||
|
|
||||||
|
QRect screenGeometry = QGuiApplication::screens()[0]->geometry();
|
||||||
|
int wx = screenGeometry.width();
|
||||||
|
|
||||||
|
int x = wx - 25;
|
||||||
|
int y = this->height() * yIncrease;
|
||||||
|
this->setFixedWidth(x);
|
||||||
|
this->setFixedHeight(y);
|
||||||
|
|
||||||
|
ui->bodyLabel->sizePolicy().setVerticalPolicy(QSizePolicy::Expanding);
|
||||||
|
ui->bodyLabel->sizePolicy().setHorizontalPolicy(QSizePolicy::Expanding);
|
||||||
|
|
||||||
|
adjust_size();
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ public:
|
||||||
bool lowBatteryDialog = false;
|
bool lowBatteryDialog = false;
|
||||||
bool usbmsDialog = false;
|
bool usbmsDialog = false;
|
||||||
bool textBrowserDialog = false;
|
bool textBrowserDialog = false;
|
||||||
|
bool appCompatibilityDialog = false;
|
||||||
|
bool appInfoDialog = false;
|
||||||
bool resetKoboxDialog = false;
|
bool resetKoboxDialog = false;
|
||||||
bool keyboardDialog = false;
|
bool keyboardDialog = false;
|
||||||
bool keypadDialog = false;
|
bool keypadDialog = false;
|
||||||
|
@ -49,6 +51,10 @@ public:
|
||||||
QString wifiPassphrase;
|
QString wifiPassphrase;
|
||||||
void setupKeyboardDialog();
|
void setupKeyboardDialog();
|
||||||
void startVNC(QString server, QString password, QString port);
|
void startVNC(QString server, QString password, QString port);
|
||||||
|
float yIncrease;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void increaseSize();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_cancelBtn_clicked();
|
void on_cancelBtn_clicked();
|
||||||
|
|
|
@ -48,6 +48,7 @@ SOURCES += \
|
||||||
textwidget.cpp \
|
textwidget.cpp \
|
||||||
toast.cpp \
|
toast.cpp \
|
||||||
usbms_splash.cpp \
|
usbms_splash.cpp \
|
||||||
|
userapps.cpp \
|
||||||
virtualkeyboard.cpp \
|
virtualkeyboard.cpp \
|
||||||
virtualkeypad.cpp \
|
virtualkeypad.cpp \
|
||||||
wifidialog.cpp
|
wifidialog.cpp
|
||||||
|
@ -77,6 +78,7 @@ HEADERS += \
|
||||||
textwidget.h \
|
textwidget.h \
|
||||||
toast.h \
|
toast.h \
|
||||||
usbms_splash.h \
|
usbms_splash.h \
|
||||||
|
userapps.h \
|
||||||
virtualkeyboard.h \
|
virtualkeyboard.h \
|
||||||
virtualkeypad.h \
|
virtualkeypad.h \
|
||||||
wifidialog.h
|
wifidialog.h
|
||||||
|
@ -105,6 +107,7 @@ FORMS += \
|
||||||
textwidget.ui \
|
textwidget.ui \
|
||||||
toast.ui \
|
toast.ui \
|
||||||
usbms_splash.ui \
|
usbms_splash.ui \
|
||||||
|
userapps.ui \
|
||||||
virtualkeyboard.ui \
|
virtualkeyboard.ui \
|
||||||
virtualkeypad.ui \
|
virtualkeypad.ui \
|
||||||
wifidialog.ui
|
wifidialog.ui
|
||||||
|
|
31
main.cpp
31
main.cpp
|
@ -38,6 +38,9 @@ int main(int argc, char *argv[])
|
||||||
global::deviceID = readFile("/opt/inkbox_device");
|
global::deviceID = readFile("/opt/inkbox_device");
|
||||||
log("Running on device " + global::deviceID, "main", true);
|
log("Running on device " + global::deviceID, "main", true);
|
||||||
|
|
||||||
|
// Tell the OS that we're currently running
|
||||||
|
string_writeconfig("/tmp/inkbox_running", "true");
|
||||||
|
|
||||||
setDefaultWorkDir();
|
setDefaultWorkDir();
|
||||||
if(checkconfig("/run/wifi_able") == true) {
|
if(checkconfig("/run/wifi_able") == true) {
|
||||||
log("Device has Wi-Fi capabilities", "main");
|
log("Device has Wi-Fi capabilities", "main");
|
||||||
|
@ -47,6 +50,31 @@ int main(int argc, char *argv[])
|
||||||
log("Device does not have Wi-Fi capabilities", "main");
|
log("Device does not have Wi-Fi capabilities", "main");
|
||||||
global::device::isWifiAble = false;
|
global::device::isWifiAble = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(QFile::exists("/tmp/rescan_userapps")) {
|
||||||
|
QFile::remove("/tmp/rescan_userapps");
|
||||||
|
log("Re-scanning user applications from explicit request", "main");
|
||||||
|
string_writeconfig("/opt/ibxd", "gui_apps_stop\n");
|
||||||
|
QThread::msleep(1000);
|
||||||
|
string_writeconfig("/opt/ibxd", "gui_apps_start\n");
|
||||||
|
while(true) {
|
||||||
|
if(QFile::exists("/tmp/gui_apps_started")) {
|
||||||
|
if(checkconfig("/tmp/gui_apps_started") == true) {
|
||||||
|
log("GUI apps service started successfully", "main");
|
||||||
|
QFile::remove("/tmp/gui_apps_started");
|
||||||
|
updateUserAppsMainJsonFile();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log("GUI apps service failed to start", "main");
|
||||||
|
QFile::remove("/tmp/gui_apps_started");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateUserAppsMainJsonFile();
|
||||||
|
}
|
||||||
|
|
||||||
if(checkconfig(".config/18-encrypted_storage/status") == true and checkconfig("/external_root/run/encfs_mounted") == false) {
|
if(checkconfig(".config/18-encrypted_storage/status") == true and checkconfig("/external_root/run/encfs_mounted") == false) {
|
||||||
// Open Encryption Manager to unlock encrypted storage
|
// Open Encryption Manager to unlock encrypted storage
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
|
@ -66,9 +94,6 @@ int main(int argc, char *argv[])
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Tell scripts that we're currently running
|
|
||||||
string_writeconfig("/tmp/inkbox_running", "true");
|
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
global::reader::startBatteryWatchdog = false;
|
global::reader::startBatteryWatchdog = false;
|
||||||
global::reader::startUsbmsPrompt = false;
|
global::reader::startUsbmsPrompt = false;
|
||||||
|
|
6
quit.cpp
6
quit.cpp
|
@ -51,6 +51,9 @@ void quit::on_pushButton_clicked()
|
||||||
global::battery::showCriticalBatteryAlert = false;
|
global::battery::showCriticalBatteryAlert = false;
|
||||||
global::battery::showLowBatteryDialog = false;
|
global::battery::showLowBatteryDialog = false;
|
||||||
|
|
||||||
|
// GUI apps
|
||||||
|
updateUserAppsMainJsonFile();
|
||||||
|
|
||||||
poweroff(true);
|
poweroff(true);
|
||||||
qApp->quit();
|
qApp->quit();
|
||||||
}
|
}
|
||||||
|
@ -60,6 +63,9 @@ void quit::on_pushButton_2_clicked()
|
||||||
global::battery::showCriticalBatteryAlert = false;
|
global::battery::showCriticalBatteryAlert = false;
|
||||||
global::battery::showLowBatteryDialog = false;
|
global::battery::showLowBatteryDialog = false;
|
||||||
|
|
||||||
|
// GUI apps
|
||||||
|
updateUserAppsMainJsonFile();
|
||||||
|
|
||||||
reboot(true);
|
reboot(true);
|
||||||
qApp->quit();
|
qApp->quit();
|
||||||
}
|
}
|
||||||
|
|
BIN
resources/edit.png
Normal file
BIN
resources/edit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
resources/save.png
Normal file
BIN
resources/save.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -822,6 +822,10 @@ void settings::on_showSystemInfoBtn_clicked()
|
||||||
// Show a system info dialog
|
// Show a system info dialog
|
||||||
log("Showing system info dialog", className);
|
log("Showing system info dialog", className);
|
||||||
generalDialogWindow = new generalDialog();
|
generalDialogWindow = new generalDialog();
|
||||||
|
if(global::deviceID == "n306\n") {
|
||||||
|
generalDialogWindow->yIncrease = 2.6;
|
||||||
|
}
|
||||||
|
generalDialogWindow->increaseSize();
|
||||||
generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose);
|
generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,9 @@ void usbms_splash::usbms_launch()
|
||||||
string_writeconfig("/opt/ibxd", "usbnet_stop\n");
|
string_writeconfig("/opt/ibxd", "usbnet_stop\n");
|
||||||
QThread::msleep(1000);
|
QThread::msleep(1000);
|
||||||
|
|
||||||
|
string_writeconfig("/opt/ibxd", "gui_apps_stop\n");
|
||||||
|
QThread::msleep(1000);
|
||||||
|
|
||||||
if(global::deviceID == "n306\n" or global::deviceID == "n873\n") {
|
if(global::deviceID == "n306\n" or global::deviceID == "n873\n") {
|
||||||
QProcess::execute("insmod", QStringList() << "/external_root/lib/modules/fs/configfs/configfs.ko");
|
QProcess::execute("insmod", QStringList() << "/external_root/lib/modules/fs/configfs/configfs.ko");
|
||||||
QProcess::execute("insmod", QStringList() << "/external_root/lib/modules/drivers/usb/gadget/libcomposite.ko");
|
QProcess::execute("insmod", QStringList() << "/external_root/lib/modules/drivers/usb/gadget/libcomposite.ko");
|
||||||
|
@ -197,6 +200,22 @@ void usbms_splash::restartServices() {
|
||||||
string_writeconfig("/opt/ibxd", "update_inkbox_restart\n");
|
string_writeconfig("/opt/ibxd", "update_inkbox_restart\n");
|
||||||
QThread::msleep(2500);
|
QThread::msleep(2500);
|
||||||
string_writeconfig("/tmp/in_usbms", "false");
|
string_writeconfig("/tmp/in_usbms", "false");
|
||||||
|
// GUI apps: update main JSON file
|
||||||
|
string_writeconfig("/opt/ibxd", "gui_apps_start\n");
|
||||||
|
while(true) {
|
||||||
|
if(QFile::exists("/tmp/gui_apps_started")) {
|
||||||
|
if(checkconfig("/tmp/gui_apps_started") == true) {
|
||||||
|
QFile::remove("/tmp/gui_apps_started");
|
||||||
|
updateUserAppsMainJsonFile();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log("GUI apps service failed to start", className);
|
||||||
|
QFile::remove("/tmp/gui_apps_started");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
quit_restart();
|
quit_restart();
|
||||||
}
|
}
|
||||||
|
|
274
userapps.cpp
Normal file
274
userapps.cpp
Normal file
|
@ -0,0 +1,274 @@
|
||||||
|
#include "userapps.h"
|
||||||
|
#include "ui_userapps.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "generaldialog.h"
|
||||||
|
|
||||||
|
userapps::userapps(QWidget *parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
ui(new Ui::userapps)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->launchBtn->setProperty("type", "borderless");
|
||||||
|
ui->launchBtn->setStyleSheet("background: lightGrey; font-size: 9pt; padding: 8px");
|
||||||
|
|
||||||
|
ui->launchBtn->setProperty("type", "borderless");
|
||||||
|
|
||||||
|
ui->iconBtn->setProperty("type", "borderless");
|
||||||
|
ui->iconBtn->setStyleSheet("QPushButton[type='borderless']:pressed { background: white; color: white; border: none; }");
|
||||||
|
|
||||||
|
ui->infoBtn->setProperty("type", "borderless");
|
||||||
|
ui->statusBtn->setProperty("type", "borderless");
|
||||||
|
ui->statusBtn->setStyleSheet("background: lightGrey; font-size: 9pt; padding: 8px");
|
||||||
|
}
|
||||||
|
|
||||||
|
userapps::~userapps()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void userapps::provideInfo(QJsonObject jsonInfo)
|
||||||
|
{
|
||||||
|
QString name = jsonInfo["Name"].toString();
|
||||||
|
appName = name; // It is for searching for json entry while disabling / enabling
|
||||||
|
jsonObject = jsonInfo;
|
||||||
|
// Limit name size to avoid breaking the GUI
|
||||||
|
if(name.size() > 20) {
|
||||||
|
// If someone wants to break the GUI, they will do it ¯\^-^/¯
|
||||||
|
name.remove(16, 100);
|
||||||
|
}
|
||||||
|
ui->appNameLabel->setText(name);
|
||||||
|
|
||||||
|
appDir.setPath("/mnt/onboard/onboard/.apps/" + name + "/" + name);
|
||||||
|
|
||||||
|
QFile iconPath = QFile{appDir.path() + "/" + jsonInfo["IconPath"].toString()};
|
||||||
|
if(iconPath.exists() == true) {
|
||||||
|
QIcon appIcon = QIcon(iconPath.fileName());
|
||||||
|
ui->iconBtn->setIconSize(QSize(40, 40));
|
||||||
|
ui->iconBtn->setIcon(appIcon);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QString function = __func__;
|
||||||
|
QString message = ": Warning: Icon not found: ";
|
||||||
|
message.append(iconPath.fileName());
|
||||||
|
log(function + message, className);
|
||||||
|
ui->iconBtn->deleteLater();
|
||||||
|
ui->gridLayout->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
execPath.setFileName(jsonInfo["ExecPath"].toString());
|
||||||
|
|
||||||
|
userAppEnabled = jsonInfo["Enabled"].toBool();
|
||||||
|
if(userAppEnabled == true) {
|
||||||
|
ui->statusBtn->setText("Disable");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui->statusBtn->setText("Enable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is needed when we dont want to repaint all widgets, but only change the the page (when no changes to the main JSON file were applied)
|
||||||
|
void userapps::changePageEnabling(bool SecondPage)
|
||||||
|
{
|
||||||
|
if(SecondPage == true){
|
||||||
|
ui->stackedWidget->setCurrentIndex(1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui->stackedWidget->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void userapps::on_infoBtn_clicked()
|
||||||
|
{
|
||||||
|
log("Launching user application information dialog", className);
|
||||||
|
// https://stackoverflow.com/questions/28181627/how-to-convert-a-qjsonobject-to-qstring
|
||||||
|
QString jsonStringParsed = parseJsonShow(jsonObject);
|
||||||
|
global::text::textBrowserContents = jsonStringParsed;
|
||||||
|
|
||||||
|
global::userApps::appInfoDialog = true;
|
||||||
|
generalDialogWindow = new generalDialog();
|
||||||
|
generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
generalDialogWindow->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void userapps::on_statusBtn_clicked()
|
||||||
|
{
|
||||||
|
ui->statusBtn->setEnabled(false);
|
||||||
|
|
||||||
|
// Here the text on this button is used as a boolean; no need to create a new one
|
||||||
|
// Disable and Enable
|
||||||
|
if(userAppEnabled == false) {
|
||||||
|
userAppEnabled = true;
|
||||||
|
ui->statusBtn->setText("Disable");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
userAppEnabled = false;
|
||||||
|
ui->statusBtn->setText("Enable");
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject jsonRootObject = jsonDocument.object();
|
||||||
|
QJsonArray jsonArrayList = jsonRootObject["list"].toArray();
|
||||||
|
|
||||||
|
int arraySize = jsonArrayList.size();
|
||||||
|
|
||||||
|
for(int i = 0; i < arraySize; i++) {
|
||||||
|
QJsonObject jsonObject = jsonArrayList.at(i).toObject();
|
||||||
|
QString entryName = jsonObject["Name"].toString();
|
||||||
|
|
||||||
|
if(entryName == appName) {
|
||||||
|
jsonObject.insert("Enabled", QJsonValue(userAppEnabled));
|
||||||
|
|
||||||
|
QJsonArray sonArrayListNew = jsonDocument.object()["list"].toArray();
|
||||||
|
sonArrayListNew.replace(i, jsonObject);
|
||||||
|
|
||||||
|
jsonRootObject["list"] = sonArrayListNew;
|
||||||
|
|
||||||
|
jsonDocument.setObject(jsonRootObject);
|
||||||
|
emit updateJsonFileSignalUA(jsonDocument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui->statusBtn->setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void userapps::updateJsonFileSlotUA(QJsonDocument jsonDocumentProvided)
|
||||||
|
{
|
||||||
|
jsonDocument = jsonDocumentProvided;
|
||||||
|
}
|
||||||
|
|
||||||
|
void userapps::on_launchBtn_clicked()
|
||||||
|
{
|
||||||
|
// Some command to execute script or binary at "ExecPath"
|
||||||
|
QJsonArray supportedDevices = jsonObject["SupportedDevices"].toArray();
|
||||||
|
|
||||||
|
// This will work even if we are looking for 'n306' and there is a device named 'n306b' because QJsonArray::contains() works that way
|
||||||
|
if(supportedDevices.contains("all") == false and supportedDevices.contains(global::deviceID.trimmed()) == false) {
|
||||||
|
log("Warning: User application '" + appName + "' does not support this device", className);
|
||||||
|
global::userApps::appCompatibilityDialog = true;
|
||||||
|
global::userApps::appCompatibilityText = "<font face='u001'>Your device is not compatible with this app.<br>Continue anyway</font><font face='Inter'>?</font>";
|
||||||
|
generalDialogWindow = new generalDialog();
|
||||||
|
generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
|
generalDialogWindow->exec();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
global::userApps::launchApp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(manageRequiredFeatures() == true) {
|
||||||
|
if(global::userApps::launchApp == true) {
|
||||||
|
global::userApps::launchApp = false;
|
||||||
|
QString message = "Launching user application at: ";
|
||||||
|
message.append("[" + appDir.path() + "]" + execPath.fileName());
|
||||||
|
log(message, className);
|
||||||
|
// Tell the OS that we're not running anymore
|
||||||
|
string_writeconfig("/tmp/inkbox_running", "false");
|
||||||
|
|
||||||
|
QProcess process;
|
||||||
|
QStringList args;
|
||||||
|
args << appDir.path() << execPath.fileName();
|
||||||
|
process.startDetached("launch_user_application.sh", args);
|
||||||
|
qApp->quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool userapps::manageRequiredFeatures()
|
||||||
|
{
|
||||||
|
// This should be already set to 'true', but just in case
|
||||||
|
global::userApps::appCompatibilityLastContinueStatus = true;
|
||||||
|
QJsonArray jsonArray = jsonObject["RequiredFeatures"].toArray();
|
||||||
|
for(QJsonValueRef refJsonObject: jsonArray) {
|
||||||
|
bool launchDialog = false;
|
||||||
|
int featureId = refJsonObject.toInt();
|
||||||
|
// Wi-Fi connection required
|
||||||
|
if(featureId == 0) {
|
||||||
|
// Double 'if' conditions to avoid launching unnecesery testPing() in emu
|
||||||
|
if(global::deviceID != "emu\n") {
|
||||||
|
if(testPing(true) != 0) {
|
||||||
|
global::userApps::appCompatibilityText = "<font face='u001'>This app needs a Wi-Fi connection, continue anyway</font><font face='Inter'>?</font>";
|
||||||
|
launchDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Rooted kernel required
|
||||||
|
if(featureId == 1) {
|
||||||
|
if(checkconfig("/external_root/opt/root/rooted") == true) {
|
||||||
|
global::userApps::appCompatibilityText = "<font face='u001'>This app needs a rooted kernel, continue anyway</font><font face='Inter'>?</font>";
|
||||||
|
launchDialog = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Pseudoterminal support (ID: 2) is managed by the 'gui_apps' service (https://github.com/Kobo-InkBox/rootfs/blob/master/etc/init.d/gui_apps)
|
||||||
|
|
||||||
|
if(launchDialog == true) {
|
||||||
|
global::userApps::appCompatibilityDialog = true;
|
||||||
|
generalDialogWindow = new generalDialog();
|
||||||
|
generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
generalDialogWindow->exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(global::userApps::appCompatibilityLastContinueStatus == false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString userapps::parseJsonShow(QJsonObject json)
|
||||||
|
{
|
||||||
|
QString mainString;
|
||||||
|
foreach(const QString& key, json.keys()) {
|
||||||
|
QJsonValue value = json.value(key);
|
||||||
|
|
||||||
|
QString appendString;
|
||||||
|
|
||||||
|
appendString.append("<b>");
|
||||||
|
appendString.append(key);
|
||||||
|
appendString.append("</b>: ");
|
||||||
|
|
||||||
|
if(value.isString()) {
|
||||||
|
appendString.append(value.toString());
|
||||||
|
}
|
||||||
|
else if(value.isBool()) {
|
||||||
|
appendString.append(QVariant(value.toBool()).toString());
|
||||||
|
}
|
||||||
|
else if(value.isArray()) {
|
||||||
|
QJsonArray array = value.toArray();
|
||||||
|
if(key == "RequiredFeatures") {
|
||||||
|
bool foundRequiredFeature = false;
|
||||||
|
appendString.append("None");
|
||||||
|
|
||||||
|
for(QJsonValueRef ref: array) {
|
||||||
|
foundRequiredFeature = true;
|
||||||
|
appendString.remove(appendString.size() - 4, 4);
|
||||||
|
int id = ref.toInt();
|
||||||
|
if(id == 0) {
|
||||||
|
appendString.append("Wi-Fi connection");
|
||||||
|
}
|
||||||
|
else if(id == 1) {
|
||||||
|
appendString.append("Rooted kernel");
|
||||||
|
}
|
||||||
|
else if(id == 2) {
|
||||||
|
appendString.append("Pseudoterminal support");
|
||||||
|
}
|
||||||
|
appendString.append(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(foundRequiredFeature == true) {
|
||||||
|
appendString.remove(appendString.size() - 2, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(key == "SupportedDevices") {
|
||||||
|
for(QJsonValueRef ref: array) {
|
||||||
|
QString name = ref.toString();
|
||||||
|
appendString.append(name);
|
||||||
|
appendString.append(", ");
|
||||||
|
}
|
||||||
|
appendString.remove(appendString.size() - 2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
appendString.append("<br>");
|
||||||
|
mainString.append(appendString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mainString;
|
||||||
|
}
|
58
userapps.h
Normal file
58
userapps.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#ifndef USERAPPS_H
|
||||||
|
#define USERAPPS_H
|
||||||
|
|
||||||
|
#include "generaldialog.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonParseError>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class userapps;
|
||||||
|
}
|
||||||
|
|
||||||
|
class userapps : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QString className = this->metaObject()->className();
|
||||||
|
explicit userapps(QWidget * parent = nullptr);
|
||||||
|
~userapps();
|
||||||
|
QJsonDocument jsonDocument; // TODO: Optimize for RAM usage
|
||||||
|
QJsonObject jsonObject; // Needed for 'App info' button
|
||||||
|
QString jsonFilePath;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
// This is needed, because user application have their own JSON file. If the user changes it too fast it won't read it and overwrite previous changes
|
||||||
|
void updateJsonFileSignalUA(QJsonDocument jsonDocument);
|
||||||
|
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void provideInfo(QJsonObject jsonObject);
|
||||||
|
void changePageEnabling(bool goThere);
|
||||||
|
void updateJsonFileSlotUA(QJsonDocument jsonDocument);
|
||||||
|
bool manageRequiredFeatures();
|
||||||
|
QString parseJsonShow(QJsonObject json);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_infoBtn_clicked();
|
||||||
|
void on_statusBtn_clicked();
|
||||||
|
void on_launchBtn_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::userapps * ui;
|
||||||
|
generalDialog * generalDialogWindow;
|
||||||
|
|
||||||
|
QDir appDir;
|
||||||
|
QFile execPath;
|
||||||
|
bool userAppEnabled;
|
||||||
|
QString appName;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // USERAPPS_H
|
215
userapps.ui
Normal file
215
userapps.ui
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>userapps</class>
|
||||||
|
<widget class="QWidget" name="userapps">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>461</width>
|
||||||
|
<height>79</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QStackedWidget" name="stackedWidget">
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="pageLaunch">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="launchBtn">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Launch</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_2Edit">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="infoBtn">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="eink.qrc">
|
||||||
|
<normaloff>:/resources/info.png</normaloff>:/resources/info.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>34</width>
|
||||||
|
<height>34</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="statusBtn">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Disable</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QPushButton" name="iconBtn">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="appNameLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>AppName</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Expanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>13</width>
|
||||||
|
<height>13</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="eink.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
Reference in a new issue