quill/src/functions.h

1170 lines
44 KiB
C
Raw Normal View History

#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#include <QFile>
#include <QString>
#include <QTextStream>
#include <fstream>
#include <QDir>
#include <QProcess>
#include <regex>
#include <QThread>
#include <QTimer>
#include <QDebug>
#include <QRandomGenerator>
#include <QDateTime>
2022-06-18 06:26:52 -07:00
#include <QDirIterator>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
2022-06-28 23:15:13 -07:00
#include <QCryptographicHash>
2021-06-25 19:09:42 -07:00
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
2021-06-25 19:09:42 -07:00
2021-04-22 07:10:47 -07:00
// WoW, global variables and namespaces are awesome
namespace global {
namespace battery {
2021-04-22 07:10:47 -07:00
inline bool showLowBatteryDialog;
inline bool showCriticalBatteryAlert;
inline bool batteryAlertLock;
}
namespace reader {
inline QString bookFile;
2021-04-22 07:10:47 -07:00
inline int pageNumber;
inline int bookNumber;
inline bool skipOpenDialog;
inline bool startBatteryWatchdog;
2021-06-29 09:26:30 -07:00
inline bool startUsbmsPrompt;
2021-06-17 05:34:00 -07:00
inline bool bookIsEpub;
2021-08-19 09:55:12 -07:00
inline bool globalReadingSettings;
inline int pdfOrientation;
2022-08-08 16:57:45 -07:00
inline bool highlightAlreadyDone;
inline int textAlignment;
inline int lineSpacing;
inline QString font;
static inline int initialFontSize = 6;
inline int fontSize;
inline int margins;
2021-04-22 07:10:47 -07:00
}
namespace kobox {
inline bool showKoboxSplash;
2021-05-01 12:53:52 -07:00
inline bool koboxSettingsRebootDialog;
inline bool resetKoboxUserDataBool;
inline bool resetKoboxDialog;
}
2021-04-22 07:10:47 -07:00
namespace mainwindow {
namespace tabSwitcher {
inline bool repaint;
2022-06-28 23:15:13 -07:00
inline bool homePageWidgetCreated;
inline bool appsWidgetCreated;
inline bool appsWidgetSelected;
inline bool settingsChooserWidgetCreated;
inline bool settingsChooserWidgetSelected;
inline bool libraryWidgetCreated;
inline bool libraryWidgetSelected;
2022-06-27 15:14:20 -07:00
inline bool localLibraryWidgetCreated;
inline bool localLibraryWidgetSelected;
}
2021-04-22 07:10:47 -07:00
inline bool updateDialog;
inline bool lowBatteryDialog;
}
namespace usbms {
2021-05-07 22:03:25 -07:00
inline bool usbmsDialog;
inline bool showUsbmsDialog;
inline bool launchUsbms;
2021-05-13 18:40:05 -07:00
inline bool koboxExportExtensions;
}
2021-05-01 12:53:52 -07:00
namespace settings {
inline bool settingsRebootDialog;
}
namespace text {
inline bool textBrowserDialog;
inline QString textBrowserContents;
}
namespace keyboard {
inline bool keyboardDialog;
inline bool keypadDialog;
inline bool searchDialog;
2021-10-08 20:37:32 -07:00
inline bool encfsDialog;
2021-07-05 21:13:11 -07:00
inline bool vncDialog;
inline bool wifiPassphraseDialog;
inline QString keyboardText;
inline QString keypadText;
2022-09-13 05:20:37 -07:00
inline bool embed = true;
}
namespace toast {
inline QString message;
inline bool modalToast;
inline bool indefiniteToast;
inline int delay;
}
namespace device {
inline bool isWifiAble;
}
namespace otaUpdate {
inline bool isUpdateOta;
inline bool downloadOta;
}
2021-10-08 20:37:32 -07:00
namespace encfs {
inline QString passphrase;
inline QString unlockTime;
2022-04-04 22:37:04 -07:00
inline QString lockdownMessage;
inline bool cancelSetup;
inline bool cancelUnlock;
inline bool lockdown;
2021-10-18 05:46:27 -07:00
inline bool enableStorageEncryptionDialog;
2021-10-17 19:31:44 -07:00
inline bool disableStorageEncryptionDialog;
2021-11-14 18:22:58 -08:00
inline bool errorNoBooksInDropboxDialog;
inline bool repackDialog;
2021-10-08 20:37:32 -07:00
}
2021-12-27 12:04:39 -08:00
namespace library {
inline unsigned long bookId;
inline bool isLatestBook;
inline int latestBookNumber;
inline QString bookTitle;
inline bool librarySearchDialog;
inline bool libraryResults;
2021-12-27 12:04:39 -08:00
}
2022-07-12 09:34:36 -07:00
namespace bookInfoDialog {
inline bool localInfoDialog;
}
2022-06-27 15:14:20 -07:00
namespace localLibrary {
static inline QString rawDatabasePath = "/inkbox/LocalLibrary.db.raw";
static inline QString databaseDirectoryPath = "/mnt/onboard/onboard/.database/";
static inline QString databasePath = databaseDirectoryPath + "LocalLibrary.db";
static inline QString recentBooksDatabasePath = databaseDirectoryPath + "RecentBooks.db";
static inline QString pinnedBooksDatabasePath = databaseDirectoryPath + "PinnedBooks.db";
2022-08-08 16:57:45 -07:00
static inline QString highlightsDatabasePath = databaseDirectoryPath + "Highlights.db";
2022-09-13 05:20:37 -07:00
static inline QString todoDatabasePath = databaseDirectoryPath + "ToDo.db";
2022-09-18 20:59:46 -07:00
// Maximum signed integer value for 32-bit systems
static inline int folderID = 2147483647;
inline bool headless;
namespace bookOptionsDialog {
inline int bookID;
2022-07-17 23:40:32 -07:00
inline bool deleteOption = true;
inline bool bookDeleted;
2022-07-17 23:40:32 -07:00
inline bool bookPinAction;
2022-09-18 20:59:46 -07:00
inline QString folderPath;
inline bool isFolder = false;
}
2022-06-27 15:14:20 -07:00
}
namespace localStorage {
inline QStringList searchResultsPaths;
}
namespace logger {
inline bool status;
}
namespace userApps {
2022-06-28 23:15:13 -07:00
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;
}
namespace homePageWidget {
static inline int recentBooksNumber = 8;
static inline int recentBooksNumberPerRow = 4;
static inline int recentBooksRowNumber = global::homePageWidget::recentBooksNumber / global::homePageWidget::recentBooksNumberPerRow;
2022-07-17 23:40:32 -07:00
static inline int pinnedBooksNumber = 4;
static inline int pinnedBooksNumberPerRow = 4;
static inline int pinnedBooksRowNumber = global::homePageWidget::pinnedBooksNumber / global::homePageWidget::pinnedBooksNumberPerRow;
}
2022-08-09 19:31:29 -07:00
namespace highlightsListDialog {
inline QString bookPath;
}
2022-08-15 12:10:32 -07:00
namespace wifi {
2022-08-22 13:09:18 -07:00
enum class wifiState {
2022-08-22 06:42:39 -07:00
configured,
enabled,
disabled,
unknown, // To not confuse lastWifiState
2022-08-15 12:10:32 -07:00
};
inline bool isConnected;
2022-08-16 06:25:01 -07:00
class wifiNetworkData {
public:
QString mac;
QString name;
bool encryption;
int signal;
};
2022-08-15 12:10:32 -07:00
}
inline QString systemInfoText;
inline bool forbidOpenSearchDialog;
2022-05-22 12:38:02 -07:00
inline bool isN705 = false;
inline bool isN905C = false;
inline bool isN613 = false;
inline bool isN873 = false;
inline bool isN236 = false;
inline bool isN437 = false;
inline bool isN306 = false;
inline bool isKT = false;
inline bool runningInstanceIsReaderOnly;
inline QString deviceID;
}
// https://stackoverflow.com/questions/6080853/c-multiple-definition-error-for-global-functions-in-the-header-file/20679534#20679534
namespace {
QString checkconfig_str_val;
2021-05-26 05:33:40 -07:00
QString deviceUID;
2021-06-25 19:09:42 -07:00
QString device;
QString batt_level;
QString kernelVersion;
int batt_level_int;
int defaultEpubPageWidth;
int defaultEpubPageHeight;
2021-08-29 12:05:07 -07:00
int defaultPdfPageWidth;
int defaultPdfPageHeight;
bool checked_box = false;
2022-04-16 20:20:24 -07:00
QFile logFile("/external_root/var/log/inkbox-gui.log");
2022-07-12 09:34:36 -07:00
void log(QString message, QString className = "undefined", bool applicationStart = false) {
if(global::logger::status == true) {
2022-04-16 20:20:24 -07:00
QString initialTime;
if(applicationStart == true) {
initialTime = QDateTime::currentDateTime().toString("dd/MM/yyyy @ hh:mm:ss");
}
QDebug logger = qDebug();
logger.noquote();
2022-04-16 20:20:24 -07:00
QStringList logStringList;
logStringList << QDateTime::currentDateTime().toString("dd/MM/yyyy @ hh:mm:ss") << "|" << className + ":" << message.trimmed();
QString logString = logStringList.join(" ");
logger << logString;
if(!logFile.isOpen()) {
logFile.open(QIODevice::Append|QIODevice::Text);
}
QTextStream logFileOut(&logFile);
if(applicationStart == true) {
logFileOut << "========== InkBox binary start at " << initialTime << " ==========" << Qt::endl;
}
logFileOut << logString << Qt::endl;
logFile.close();
}
}
2022-07-26 18:08:25 -07:00
void logEnabled(QString configOption, QString className) {
log("Enabling " + configOption + " setting", className);
}
void logDisabled(QString configOption, QString className) {
log("Disabling " + configOption + " setting", className);
}
bool checkconfig(QString file) {
2021-09-05 06:49:37 -07:00
if(QFile::exists(file)) {
QFile config(file);
config.open(QIODevice::ReadOnly);
QTextStream in (&config);
const QString content = in.readAll();
std::string contentstr = content.toStdString();
if(contentstr.find("true") != std::string::npos) {
return true;
}
else {
return false;
}
config.close();
}
else {
return false;
}
return 0;
};
bool checkconfig_rw(QString file) {
2021-09-05 06:49:37 -07:00
if(QFile::exists(file)) {
QFile config(file);
config.open(QIODevice::ReadWrite);
QTextStream in (&config);
const QString content = in.readAll();
std::string contentstr = content.toStdString();
if(contentstr.find("true") != std::string::npos) {
return true;
}
else {
return false;
}
config.close();
}
else {
return false;
}
return 0;
};
2021-06-26 16:29:51 -07:00
void setDefaultWorkDir() {
QDir::setCurrent("/mnt/onboard/.adds/inkbox");
}
int brightness_checkconfig(QString file) {
2021-09-05 06:49:37 -07:00
if(QFile::exists(file)) {
QFile config(file);
config.open(QIODevice::ReadWrite);
QTextStream in (&config);
const QString content = in.readAll();
int content_int = content.toInt();
return content_int;
config.close();
}
else {
return EXIT_FAILURE;
}
return 0;
}
void set_brightness(int value) {
if(QFile::exists("/var/run/brightness")) {
std::ofstream fhandler;
fhandler.open("/var/run/brightness");
fhandler << value;
fhandler.close();
}
}
2021-06-25 19:09:42 -07:00
void set_brightness_ntxio(int value) {
// Thanks to Kevin Short for this (GloLight)
int light;
if((light = open("/dev/ntx_io", O_RDWR)) == -1) {
fprintf(stderr, "Error opening ntx_io device\n");
2021-06-25 19:09:42 -07:00
}
ioctl(light, 241, value);
close(light);
2021-06-25 19:09:42 -07:00
}
int int_checkconfig(QString file) {
2021-09-05 06:49:37 -07:00
if(QFile::exists(file)) {
QFile int_config(file);
int_config.open(QIODevice::ReadOnly);
QString valuestr = int_config.readAll();
int value = valuestr.toInt();
int_config.close();
return value;
}
else {
return EXIT_FAILURE;
}
return 0;
}
int display_quote() {
int quoteNumber = QRandomGenerator::global()->bounded(1, 6);
return quoteNumber;
return 0;
}
bool writeFile(QString filename, QString content) {
QFile file(filename);
if(file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)) {
QTextStream stream(&file);
stream << content;
return true;
}
else {
QString function = __func__; log(function + ": Failed to write string '" + content + "' to file '" + filename + "'", "functions");
return false;
}
}
void string_writeconfig(std::string file, std::string config_option) {
std::ofstream fhandler;
fhandler.open(file);
fhandler << config_option;
fhandler.close();
}
void string_checkconfig(QString file) {
2021-09-05 06:49:37 -07:00
if(QFile::exists(file)) {
checkconfig_str_val = "";
QFile config(file);
config.open(QIODevice::ReadWrite);
QTextStream in (&config);
checkconfig_str_val = in.readAll();
config.close();
}
else {
checkconfig_str_val = "";
}
}
void string_checkconfig_ro(QString file) {
2021-09-05 06:49:37 -07:00
if(QFile::exists(file)) {
checkconfig_str_val = "";
QFile config(file);
config.open(QIODevice::ReadOnly);
QTextStream in (&config);
checkconfig_str_val = in.readAll();
config.close();
}
else {
checkconfig_str_val = "";
}
}
2021-12-26 16:08:21 -08:00
QString readFile(QString file) {
if(QFile::exists(file)) {
QFile fileToRead(file);
fileToRead.open(QIODevice::ReadOnly);
QTextStream in (&fileToRead);
QString content = in.readAll();
return content;
}
else {
return NULL;
}
}
void brightness_writeconfig(int value) {
std::ofstream fhandler;
fhandler.open(".config/03-brightness/config");
fhandler << value;
fhandler.close();
}
void warmth_writeconfig(int value) {
std::ofstream fhandler;
fhandler.open(".config/03-brightness/config-warmth");
fhandler << value;
fhandler.close();
}
int get_brightness() {
if(global::deviceID == "n613\n") {
string_checkconfig_ro(".config/03-brightness/config");
int brightness;
if(checkconfig_str_val == "") {
brightness = 0;
}
else {
brightness = checkconfig_str_val.toInt();
}
return brightness;
}
else {
if(QFile::exists("/var/run/brightness")) {
QFile brightness("/var/run/brightness");
brightness.open(QIODevice::ReadOnly);
QString valuestr = brightness.readAll();
int value = valuestr.toInt();
brightness.close();
return value;
}
else {
return 0;
}
}
return 0;
}
void get_battery_level() {
2022-05-23 12:24:21 -07:00
QString batteryLevelFileQstr;
if(global::deviceID == "kt\n") {
QFile batt_level_file("/sys/devices/system/yoshi_battery/yoshi_battery0/battery_capacity");
if(batt_level_file.exists()) {
batt_level_file.open(QIODevice::ReadOnly);
batt_level = batt_level_file.readAll();
batt_level = batt_level.trimmed();
batt_level_int = batt_level.toInt();
batt_level = batt_level.append("%");
batt_level_file.close();
}
2021-12-25 07:36:38 -08:00
}
else {
2022-05-23 12:24:21 -07:00
QFile batt_level_file("/sys/devices/platform/pmic_battery.1/power_supply/mc13892_bat/capacity");
if(batt_level_file.exists()) {
batt_level_file.open(QIODevice::ReadOnly);
batt_level = batt_level_file.readAll();
batt_level = batt_level.trimmed();
batt_level_int = batt_level.toInt();
batt_level = batt_level.append("%");
batt_level_file.close();
}
else {
batt_level_int = 100;
batt_level = "100%";
}
2021-12-25 07:36:38 -08:00
}
}
void writeconfig(std::string file, std::string config) {
2021-09-05 06:49:37 -07:00
std::ofstream fhandler;
fhandler.open(file);
fhandler << config << std::boolalpha << checked_box << std::endl;
fhandler.close();
}
bool checkconfig_match(QString file, std::string pattern) {
QFile config(file);
config.open(QIODevice::ReadWrite);
QTextStream in (&config);
const QString content = in.readAll();
std::string contentstr = content.toStdString();
// Thanks to https://stackoverflow.com/questions/22516463/how-do-i-find-a-complete-word-not-part-of-it-in-a-string-in-c
std::regex r("\\b" + pattern + "\\b");
std::smatch m;
if(std::regex_search(contentstr, m, r)) {
return true;
}
else {
return false;
}
config.close();
return 0;
};
bool isBatteryLow() {
// Checks if battery level is under 15% of total capacity.
get_battery_level();
if(batt_level_int <= 15) {
return true;
}
else {
return false;
}
return 0;
}
bool isBatteryCritical() {
// Checks if the battery level is critical (i.e. <= 5%)
get_battery_level();
if(batt_level_int <= 5) {
QString function = __func__; log(function + ": Battery is at a critical charge level!", "functions");
return true;
}
else {
return false;
}
return 0;
}
void zeroBrightness() {
if(global::deviceID != "n613\n") {
set_brightness(0);
}
else {
set_brightness_ntxio(0);
}
}
void poweroff(bool splash) {
log("Powering off", "functions");
if(splash == true) {
2021-05-28 05:36:24 -07:00
QString prog ("/sbin/poweroff");
QStringList args;
QProcess *proc = new QProcess();
proc->start(prog, args);
2021-08-29 12:05:07 -07:00
proc->waitForFinished();
proc->deleteLater();
}
else {
2021-05-28 05:36:24 -07:00
QString prog ("/sbin/poweroff");
QStringList args;
2021-05-28 05:36:24 -07:00
args << "no_splash";
QProcess *proc = new QProcess();
proc->start(prog, args);
2021-08-29 12:05:07 -07:00
proc->waitForFinished();
proc->deleteLater();
}
}
void reboot(bool splash) {
log("Rebooting", "functions");
if(splash == true) {
QString prog ("/sbin/reboot");
QStringList args;
if(global::kobox::resetKoboxUserDataBool == true) {
args << "splash" << "reset_kobox";
}
QProcess *proc = new QProcess();
proc->start(prog, args);
2021-08-29 12:05:07 -07:00
proc->waitForFinished();
proc->deleteLater();
}
else {
QString prog ("/sbin/reboot");
QStringList args;
if(global::kobox::resetKoboxUserDataBool == true) {
args << "no_splash" << "reset_kobox";
}
else {
args << "no_splash";
}
QProcess *proc = new QProcess();
proc->start(prog, args);
2021-08-29 12:05:07 -07:00
proc->waitForFinished();
proc->deleteLater();
}
}
2021-05-26 05:33:40 -07:00
void getUID() {
QString prog ("dd");
QStringList args;
args << "if=/dev/mmcblk0" << "bs=512" << "skip=1" << "count=1" << "status=none";
QProcess *proc = new QProcess();
proc->start(prog, args);
proc->waitForFinished();
2021-05-26 05:33:40 -07:00
deviceUID = proc->readAllStandardOutput();
deviceUID = deviceUID.left(256);
2021-08-29 12:05:07 -07:00
proc->deleteLater();
}
void getKernelVersion() {
QString prog ("uname");
QStringList args;
args << "-r";
QProcess *proc = new QProcess();
proc->start(prog, args);
proc->waitForFinished();
kernelVersion = proc->readAllStandardOutput();
kernelVersion = kernelVersion.trimmed();
2021-06-26 16:29:51 -07:00
2022-02-15 19:47:10 -08:00
proc->deleteLater();
2021-06-26 16:29:51 -07:00
setDefaultWorkDir();
2022-02-20 17:03:40 -08:00
string_writeconfig("/external_root/run/initrd-fifo", "get_kernel_build_id\n");
QThread::msleep(100);
string_writeconfig("/external_root/run/initrd-fifo", "get_kernel_commit\n");
QThread::msleep(100);
2021-06-26 16:29:51 -07:00
2022-02-20 17:03:40 -08:00
string_checkconfig_ro("/external_root/run/kernel_build_id");
QString kernelBuildID = checkconfig_str_val.trimmed();
kernelVersion.append(", build ");
kernelVersion.append(kernelBuildID);
2022-02-20 17:03:40 -08:00
string_checkconfig_ro("/external_root/run/kernel_commit");
QString kernelCommit = checkconfig_str_val.trimmed();
kernelVersion.append(", commit ");
kernelVersion.append(kernelCommit);
}
QString getConnectionInformation() {
QString getIpProg ("sh");
QStringList getIpArgs;
if(global::deviceID != "n437\n") {
2022-02-18 08:06:09 -08:00
getIpArgs << "-c" << "/sbin/ifconfig eth0 | grep 'inet addr' | cut -d: -f2 | awk '{print $1}'";
}
else {
getIpArgs << "-c" << "/sbin/ifconfig wlan0 | grep 'inet addr' | cut -d: -f2 | awk '{print $1}'";
}
QProcess *getIpProc = new QProcess();
getIpProc->start(getIpProg, getIpArgs);
getIpProc->waitForFinished();
QString ipAddress = getIpProc->readAllStandardOutput();
if(ipAddress == "") {
ipAddress = "Not available";
}
2021-08-29 12:05:07 -07:00
getIpProc->deleteLater();
return ipAddress;
}
void getSystemInfo() {
getUID();
getKernelVersion();
global::systemInfoText = "<b>InkBox OS version ";
string_checkconfig_ro("/external_root/opt/isa/version");
global::systemInfoText.append(checkconfig_str_val);
2022-07-17 23:40:32 -07:00
global::systemInfoText.append("</b><br>Copyright <font face='Inter'>©</font> 2021-2022 Nicolas Mailloux and contributors");
global::systemInfoText.append("<br><b>Git:</b> ");
global::systemInfoText.append(GIT_VERSION);
global::systemInfoText.append("<br><b>Device UID:</b> ");
global::systemInfoText.append(deviceUID);
global::systemInfoText.append("<br><b>Kernel version:</b> ");
global::systemInfoText.append(kernelVersion);
global::systemInfoText.append("<br><b>Device:</b> ");
QString device = global::deviceID.trimmed();
global::systemInfoText.append(device);
QString ipAddress = getConnectionInformation();
global::systemInfoText.append("<br><b>IP address: </b>");
global::systemInfoText.append(ipAddress);
}
void resetKoboxUserData() {
log("Resetting KoBox user data", "functions");
global::kobox::resetKoboxUserDataBool = true;
reboot(true);
}
QString findEpubMetadata(QString book_file, QString metadata) {
log("Finding ePUB metadata, query: " + metadata, "functions");
setDefaultWorkDir();
QString prog ("sh");
QStringList args;
args << "find_epub_metadata.sh" << book_file << metadata;
QProcess *proc = new QProcess();
proc->start(prog, args);
proc->waitForFinished();
QString returnedMetadata = proc->readAllStandardOutput();
QString function = __func__; log(function + ": ePUB metadata is: " + returnedMetadata, "functions");
return returnedMetadata;
}
2021-08-29 12:05:07 -07:00
void defineDefaultPageSize(int fileType) {
/* fileType can be:
* 0: ePUB
* 1: PDF
*/
if(fileType == 0) {
if(global::deviceID == "n705\n") {
2021-08-29 12:05:07 -07:00
defaultEpubPageHeight = 365;
defaultEpubPageWidth = 365;
}
2022-05-22 12:38:02 -07:00
else if(global::deviceID == "n905\n" or global::deviceID == "kt\n") {
2021-08-29 12:05:07 -07:00
defaultEpubPageHeight = 425;
defaultEpubPageWidth = 425;
}
else if(global::deviceID == "n613\n" or global::deviceID == "n236\n" or global::deviceID == "n437\n" or global::deviceID == "n306\n" or global::deviceID == "emu\n") {
2021-08-29 12:05:07 -07:00
defaultEpubPageHeight = 450;
defaultEpubPageWidth = 450;
}
else if(global::deviceID == "n873\n") {
2021-08-29 12:05:07 -07:00
defaultEpubPageHeight = 525;
defaultEpubPageWidth = 525;
}
QString function = __func__;
log(function + ": Defined default ePUB page height to " + QString::number(defaultEpubPageHeight), "functions");
log(function + ": Defined default ePUB page width to " + QString::number(defaultEpubPageWidth), "functions");
}
2021-08-29 12:05:07 -07:00
else if(fileType == 1) {
2022-05-22 12:38:02 -07:00
if(global::deviceID == "n705\n" or global::deviceID == "n905\n" or global::deviceID == "kt\n") {
if(global::reader::pdfOrientation == 0) {
defaultPdfPageHeight = 750;
defaultPdfPageWidth = 550;
}
else {
defaultPdfPageHeight = 550;
defaultPdfPageWidth = 750;
}
2021-08-29 12:05:07 -07:00
}
else if(global::deviceID == "n613\n" or global::deviceID == "n236\n" or global::deviceID == "n306\n" or global::deviceID == "emu\n") {
if(global::reader::pdfOrientation == 0) {
defaultPdfPageHeight = 974;
defaultPdfPageWidth = 708;
}
else {
defaultPdfPageHeight = 708;
defaultPdfPageWidth = 974;
}
2021-08-29 12:05:07 -07:00
}
else if(global::deviceID == "n437\n") {
if(global::reader::pdfOrientation == 0) {
defaultPdfPageHeight = 1398;
defaultPdfPageWidth = 1022;
}
else {
defaultPdfPageHeight = 1022;
defaultPdfPageWidth = 1398;
}
2022-02-06 19:49:06 -08:00
}
else if(global::deviceID == "n873\n") {
if(global::reader::pdfOrientation == 0) {
defaultPdfPageHeight = 1630;
defaultPdfPageWidth = 1214;
}
else {
defaultPdfPageHeight = 1214;
defaultPdfPageWidth = 1630;
}
2021-08-29 12:05:07 -07:00
}
QString function = __func__;
log(function + "Defined default PDF page height to " + QString::number(defaultPdfPageHeight), "functions");
log(function + "Defined default PDF page width to " + QString::number(defaultPdfPageWidth), "functions");
}
}
void pre_set_brightness(int brightnessValue) {
2022-05-22 12:38:02 -07:00
if(global::deviceID == "n705\n" or global::deviceID == "n905\n" or global::deviceID == "n873\n" or global::deviceID == "n236\n" or global::deviceID == "n437\n" or global::deviceID == "n306\n" or global::deviceID == "kt\n") {
set_brightness(brightnessValue);
}
else if(global::deviceID == "n613\n") {
set_brightness_ntxio(brightnessValue);
}
else {
set_brightness(brightnessValue);
}
}
void cinematicBrightness(int value, int mode) {
/* mode can be 0, 1, or 2, respectively:
* 0: Bring UP brightness
* 1: Bring DOWN brightness
* 2: Auto; smooth brightness transition between two brightness levels
*/
2022-05-22 12:38:02 -07:00
if(global::deviceID != "n705\n" && global::deviceID != "n905\n" && global::deviceID != "kt\n") {
QString function = __func__; log(function + ": Setting brightness to " + QString::number(value), "functions");
}
if(mode == 0) {
int brightness = 0;
while(brightness != value) {
brightness = brightness + 1;
pre_set_brightness(brightness);
QThread::msleep(30);
}
}
else if(mode == 1) {
int brightness = get_brightness();
while(brightness != 0) {
brightness = brightness - 1;
pre_set_brightness(brightness);
QThread::msleep(30);
}
}
else if(mode == 2) {
int brightness = get_brightness();
if(brightness <= value) {
while(brightness != value) {
brightness = brightness + 1;
pre_set_brightness(brightness);
QThread::msleep(30);
}
}
else if(brightness >= value) {
while(brightness != value) {
brightness = brightness - 1;
pre_set_brightness(brightness);
QThread::msleep(30);
}
}
}
}
int get_warmth() {
QString sysfsWarmthPath;
if(global::deviceID == "n873\n") {
sysfsWarmthPath = "/sys/class/backlight/lm3630a_led/color";
}
string_checkconfig_ro(sysfsWarmthPath);
int warmthValue = checkconfig_str_val.toInt();
warmthValue = 10 - warmthValue;
return warmthValue;
}
void set_warmth(int warmthValue) {
// Value 0 gives a warmer lighting than value 10
warmthValue = 10 - warmthValue;
std::string warmthValueStr = std::to_string(warmthValue);
std::string sysfsWarmthPath;
if(global::deviceID == "n873\n") {
sysfsWarmthPath = "/sys/class/backlight/lm3630a_led/color";
}
string_writeconfig(sysfsWarmthPath, warmthValueStr);
}
void installUpdate() {
2022-04-15 17:27:58 -07:00
log("Installing update package", "functions");
string_writeconfig("/mnt/onboard/onboard/.inkbox/can_really_update", "true");
string_writeconfig("/external_root/opt/update/will_update", "true");
string_writeconfig("/external_root/boot/flags/WILL_UPDATE", "true");
reboot(true);
}
2021-11-14 18:22:58 -08:00
bool getEncFSStatus() {
2021-11-14 19:23:09 -08:00
return checkconfig("/external_root/run/encfs_mounted");
2021-11-14 18:22:58 -08:00
}
bool isUsbPluggedIn() {
2022-05-23 12:24:21 -07:00
if(global::deviceID == "kt\n") {
if(readFile("/sys/devices/system/yoshi_battery/yoshi_battery0/battery_status") == "1\n") {
return 1;
}
else {
return 0;
}
}
else {
2022-05-22 12:38:02 -07:00
// Thanks to https://github.com/koreader/KoboUSBMS/blob/2efdf9d920c68752b2933f21c664dc1afb28fc2e/usbms.c#L148-L158
int ntxfd;
if((ntxfd = open("/dev/ntx_io", O_RDWR)) == -1) {
fprintf(stderr, "Error opening ntx_io device\n");
}
unsigned long ptr = 0U;
ioctl(ntxfd, 108, &ptr);
close(ntxfd);
return !!ptr;
}
}
2022-06-18 06:26:52 -07:00
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();
}
}
}
}
}
}
QString fileChecksum(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm) {
2022-06-28 23:15:13 -07:00
QFile f(fileName);
if (f.open(QFile::ReadOnly)) {
QCryptographicHash hash(hashAlgorithm);
if (hash.addData(&f)) {
return hash.result().toHex();
2022-06-28 23:15:13 -07:00
}
}
}
QJsonObject getBookMetadata(int bookID) {
// Read library database from file
QFile database(global::localLibrary::databasePath);
QByteArray data;
if(database.open(QIODevice::ReadOnly)) {
data = database.readAll();
database.close();
}
else {
QString function = __func__; log(function + ": Failed to open local library database file for reading at '" + database.fileName() + "'", "functions");
}
// Parse JSON data
QJsonObject jsonObject = QJsonDocument::fromJson(qUncompress(QByteArray::fromBase64(data))).object();
QJsonArray jsonArrayList = jsonObject["database"].toArray();
return jsonArrayList.at(bookID - 1).toObject();
}
2022-08-08 16:57:45 -07:00
QJsonObject readHighlightsDatabase() {
// Read highlights database from file
QFile database(global::localLibrary::highlightsDatabasePath);
QByteArray data;
if(database.open(QIODevice::ReadOnly)) {
data = database.readAll();
database.close();
}
else {
QString function = __func__; log(function + ": Failed to open highlights database file for reading at '" + database.fileName() + "'", "functions");
}
// Parse JSON data
return QJsonDocument::fromJson(qUncompress(QByteArray::fromBase64(data))).object();
}
void writeHighlightsDatabase(QJsonObject jsonObject) {
QFile::remove(global::localLibrary::highlightsDatabasePath);
writeFile(global::localLibrary::highlightsDatabasePath, qCompress(QJsonDocument(jsonObject).toJson()).toBase64());
}
2022-09-13 05:20:37 -07:00
QJsonDocument readTodoDatabase() {
// Read To-Do database from file
QFile database(global::localLibrary::todoDatabasePath);
QByteArray data;
if(database.open(QIODevice::ReadOnly)) {
data = database.readAll();
database.close();
}
else {
QString function = __func__; log(function + ": Failed to open To-Do database file for reading at '" + database.fileName() + "'", "functions");
}
// Parse JSON data
return QJsonDocument::fromJson(data);
}
void writeTodoDatabase(QJsonDocument jsonDocument) {
QFile::remove(global::localLibrary::todoDatabasePath);
writeFile(global::localLibrary::todoDatabasePath, jsonDocument.toJson());
}
2022-08-08 16:57:45 -07:00
void highlightBookText(QString text, QString bookPath, bool remove) {
if(remove == false) {
if(!QFile::exists(global::localLibrary::highlightsDatabasePath)) {
QJsonObject mainJsonObject;
QJsonObject firstJsonObject;
firstJsonObject.insert("BookPath", QJsonValue(bookPath));
2022-08-09 12:41:50 -07:00
firstJsonObject.insert("T-" + QUuid::createUuid().toString(QUuid::WithoutBraces), QJsonValue(text));
2022-08-08 16:57:45 -07:00
mainJsonObject["Book1"] = firstJsonObject;
writeHighlightsDatabase(mainJsonObject);
}
else {
QJsonObject jsonObject = readHighlightsDatabase();
bool highlightWrote = false;
int length = jsonObject.length();
for(int i = 1; i <= length; i++) {
if(jsonObject["Book" + QString::number(i)].toObject().value("BookPath").toString() == bookPath) {
2022-08-09 12:41:50 -07:00
log("highlightBookText: Found existing book in database with path '" + bookPath + "'", "functions");
2022-08-08 16:57:45 -07:00
// Insert highlight
QJsonObject highlightJsonObject = jsonObject["Book" + QString::number(i)].toObject();
// Finding available slot for highlight in case the one we are looking for is already occupied
2022-08-09 12:41:50 -07:00
QString uuid = "T-"+ QUuid::createUuid().toString(QUuid::WithoutBraces);
if(highlightJsonObject.contains(uuid)) {
2022-08-08 16:57:45 -07:00
while(true) {
2022-08-09 12:41:50 -07:00
if(highlightJsonObject.contains(uuid)) {
uuid = "T-" + QUuid::createUuid().toString(QUuid::WithoutBraces);
2022-08-08 16:57:45 -07:00
}
else {
break;
}
}
}
2022-08-09 12:41:50 -07:00
highlightJsonObject.insert(uuid, text);
2022-08-08 16:57:45 -07:00
jsonObject["Book" + QString::number(i)] = highlightJsonObject;
writeHighlightsDatabase(jsonObject);
highlightWrote = true;
}
}
if(highlightWrote == false) {
2022-08-09 12:41:50 -07:00
// This block of code is called when the book is referenced in the database, but no highlights are currently indexed
2022-08-08 16:57:45 -07:00
QJsonObject bookJsonObject;
bookJsonObject.insert("BookPath", QJsonValue(bookPath));
2022-08-09 12:41:50 -07:00
bookJsonObject.insert("T-" + QUuid::createUuid().toString(QUuid::WithoutBraces), QJsonValue(text));
2022-08-08 16:57:45 -07:00
jsonObject["Book" + QString::number(length + 1)] = bookJsonObject;
writeHighlightsDatabase(jsonObject);
highlightWrote = true;
}
}
}
else {
QJsonObject jsonObject = readHighlightsDatabase();
int length = jsonObject.length();
for(int i = 1; i <= length; i++) {
if(jsonObject["Book" + QString::number(i)].toObject().value("BookPath").toString() == bookPath) {
QJsonObject bookJsonObject = jsonObject["Book" + QString::number(i)].toObject();
foreach(const QString& key, bookJsonObject.keys()) {
if(bookJsonObject.value(key).toString() == text) {
log("Found matching highlight to remove with text '" + text + "'", "functions.h");
bookJsonObject.remove(key);
}
}
jsonObject["Book" + QString::number(i)] = bookJsonObject;
writeHighlightsDatabase(jsonObject);
}
}
}
}
QJsonObject getHighlightsForBook(QString bookPath) {
QJsonObject jsonObject = readHighlightsDatabase();
int length = jsonObject.length();
for(int i = 1; i <= length; i++) {
if(jsonObject["Book" + QString::number(i)].toObject().value("BookPath").toString() == bookPath) {
return jsonObject["Book" + QString::number(i)].toObject();
break;
}
}
return QJsonObject();
}
2022-07-12 09:34:36 -07:00
float determineYIncrease() {
if(global::deviceID == "n705\n" or global::deviceID == "n905\n") {
return 2;
}
else if(global::deviceID == "n613\n" or global::deviceID == "n236\n" or global::deviceID == "n306\n" or global::deviceID == "emu\n") {
2022-07-12 09:34:36 -07:00
return 2.6;
}
else if(global::deviceID == "n437\n" or global::deviceID == "n873\n") {
return 3;
}
else {
return 2;
}
}
2022-08-22 06:42:39 -07:00
global::wifi::wifiState checkWifiState() {
2022-08-15 12:10:32 -07:00
QProcess *wifiStateProcess = new QProcess();
QString path = "/external_root/usr/local/bin/wifi/wifi_status.sh";
QStringList args;
wifiStateProcess->start(path, args);
wifiStateProcess->waitForFinished();
wifiStateProcess->deleteLater();
2022-08-22 06:42:39 -07:00
2022-08-15 12:10:32 -07:00
QString currentWifiState;
if(QFile("/run/wifi_status").exists() == true) {
currentWifiState = readFile("/run/wifi_status");
} else {
2022-08-22 06:42:39 -07:00
log("/run/wifi_status doesn't exist", "functions");
2022-08-15 12:10:32 -07:00
}
if (currentWifiState.contains("configured") == true) {
global::wifi::isConnected = true;
2022-08-22 06:42:39 -07:00
return global::wifi::wifiState::configured;
2022-08-15 12:10:32 -07:00
}
else if (currentWifiState.contains("enabled") == true) {
global::wifi::isConnected = false;
2022-08-22 06:42:39 -07:00
return global::wifi::wifiState::enabled;
2022-08-15 12:10:32 -07:00
}
else if (currentWifiState.contains("disabled") == true) {
global::wifi::isConnected = false;
2022-08-22 06:42:39 -07:00
return global::wifi::wifiState::disabled;
2022-08-15 12:10:32 -07:00
} else {
global::wifi::isConnected = false;
2022-08-22 06:42:39 -07:00
QString function = __func__; log(function + ": Critical error", "functions");
return global::wifi::wifiState::unknown;
2022-08-15 12:10:32 -07:00
}
}
int testPing() {
// For some reason, implementing a non-blocking version of this functions triggers a "terminate called without an active exception" error with a platform plugin compiled with a newer GCC 11 toolchain. The problem has been solved by transplanting this function into the related area which uses it.
QProcess *pingProcess = new QProcess();
QString pingProg = "ping";
QStringList pingArgs;
pingArgs << "-c" << "1" << "1.1.1.1";
pingProcess->start(pingProg, pingArgs);
pingProcess->waitForFinished();
int exitCode = pingProcess->exitCode();
pingProcess->deleteLater();
if(exitCode == 0) {
global::wifi::isConnected = true;
}
else {
global::wifi::isConnected = false;
}
return exitCode;
}
2022-08-18 12:47:08 -07:00
bool checkProcessName(QString name) {
QDirIterator appsDir("/proc", QDirIterator::NoIteratorFlags);
while (appsDir.hasNext()) {
QDir dir(appsDir.next());
QFile process = QFile(dir.path() + "/cmdline");
if(process.exists() == true) {
process.open(QIODevice::ReadOnly);
QTextStream stream(&process);
if(stream.readLine().contains(name) == true) {
process.close();
return true;
}
process.close();
}
}
return false;
}
}
#endif // FUNCTIONS_H