-
Notifications
You must be signed in to change notification settings - Fork 4
03 snigdhaosblackbox.cpp
Eshan Roy edited this page Dec 20, 2024
·
1 revision
It is a detailed implementation of a Qt-based application (SnigdhaOSBlackbox) that interacts with the system for tasks like updating, applying configurations, and managing internet connectivity. I will explain the code line by line in detail, using comments and descriptions to clarify each part.
#include "snigdhaosblackbox.h"
#include "./ui_snigdhaosblackbox.h"
#include <QCheckBox>
#include <QDebug>
#include <QFileInfo>
#include <QProcess>
#include <QScrollArea>
#include <QTemporaryFile>
#include <QTimer>
#include <QtNetwork/QNetworkReply>
#include <unistd.h>
These lines include necessary header files:
-
"snigdhaosblackbox.h"
is the header for theSnigdhaOSBlackbox
class. -
"ui_snigdhaosblackbox.h"
is the auto-generated header for the UI components designed in Qt Designer. - Qt libraries are included for UI elements (
QCheckBox
,QScrollArea
), system utilities (QProcess
,QTemporaryFile
), network requests (QNetworkReply
), debugging (QDebug
), etc.
const char* INTERNET_CHECK_URL = "https://snigdha-os.github.io/";
- Defines the URL used to verify if the system has an active internet connection.
SnigdhaOSBlackbox::SnigdhaOSBlackbox(QWidget *parent, QString state)
: QMainWindow(parent)
, ui(new Ui::SnigdhaOSBlackbox)
{
- Constructor for the
SnigdhaOSBlackbox
class, inheriting fromQMainWindow
. - Initializes the
ui
pointer to manage the UI components. -
parent
is passed to the base class constructor, allowing the window to be embedded in another widget if needed.
this->setWindowIcon(QIcon("/usr/share/pixmaps/snigdhaos-blackbox.svg"));
ui->setupUi(this);
- Sets the window icon to the specified SVG file.
- Initializes the UI using the
setupUi
function generated by Qt Designer.
this->setWindowFlags(this->windowFlags() & -Qt::WindowCloseButtonHint);
- Disables the close button on the window, preventing the application from being closed directly through the window controls.
executable_modify_date = QFileInfo(QCoreApplication::applicationFilePath()).lastModified();
- Retrieves the last modification date of the application executable, which can be useful to check if the executable has been updated.
updateState(state);
}
- Calls
updateState
to set the initial state of the application based on the providedstate
parameter.
SnigdhaOSBlackbox::~SnigdhaOSBlackbox()
{
delete ui;
}
- Destructor for the
SnigdhaOSBlackbox
class. - Frees the memory allocated for the
ui
object, ensuring there are no memory leaks.
void SnigdhaOSBlackbox::doInternetUpRequest() {
QNetworkAccessManager* network_manager = new QNetworkAccessManager(this);
QNetworkReply* network_reply = network_manager->head(QNetworkRequest(QString(INTERNET_CHECK_URL)));
- Creates a
QNetworkAccessManager
and sends aHEAD
request to the specifiedINTERNET_CHECK_URL
to check if the system has internet access.
QTimer* timer = new QTimer(this);
timer->setSingleShot(true);
timer->start(5000); //5 sec
- Sets up a
QTimer
to allow the network request to timeout after 5 seconds if no response is received.
connect(timer, &QTimer::timeout, this, [this, timer, network_reply, network_manager]() {
timer->deleteLater();
network_reply->abort();
network_reply->deleteLater();
network_manager->deleteLater();
doInternetUpRequest();
});
- If the timer times out, the network request is aborted, and the resources are cleaned up.
- It then re-invokes
doInternetUpRequest
to attempt the request again.
connect(network_reply, &QNetworkReply::finished, this, [this, timer, network_reply, network_manager]() {
timer->stop();
timer->deleteLater();
network_reply->deleteLater();
network_manager->deleteLater();
if (network_reply->error() == network_reply->NoError){
updateState(State::UPDATE);
}
else {
doInternetUpRequest();
}
});
}
- When the network request finishes, the
finished
signal is emitted, and it checks if the request was successful (NoError
). - If successful, it moves to the
UPDATE
state. - If failed, it retries the internet check by calling
doInternetUpRequest()
again.
void SnigdhaOSBlackbox::doUpdate() {
if (qEnvironmentVariableIsSet("SNIGDHAOS_BLACKBOX_SELFUPDATE")) {
updateState(State::SELECT);
return;
}
auto process = new QProcess(this);
QTemporaryFile* file = new QTemporaryFile(this);
file->open();
file->setAutoRemove(true);
process->start("/usr/lib/snigdhaos/launch-terminal", QStringList() << QString("sudo pacman -Syyu 2>&1 && rm \"" + file->fileName() + "\"; read -p 'Press Enter↵ to Exit"));
- This function checks for the
SNIGDHAOS_BLACKBOX_SELFUPDATE
environment variable and proceeds with the update if not set. - It creates a
QProcess
to run thepacman
update command (sudo pacman -Syyu
). - A temporary file is used to track the update process.
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this, process, file](int exitcode, QProcess::ExitStatus status) {
process->deleteLater();
file->deleteLater();
if (exitcode == 0 && !file->exists()) {
relaunchSelf("POST_UPDATE");
}
else {
relaunchSelf("UPDATE_RETRY");
}
});
}
- After the update process finishes, the exit code is checked.
- If successful (
exitcode == 0
), it proceeds withrelaunchSelf("POST_UPDATE")
. - If there’s an issue, it retries by calling
relaunchSelf("UPDATE_RETRY")
.
void SnigdhaOSBlackbox::doApply() {
QStringList packages;
QStringList setup_commands;
QStringList prepare_commands;
- The
doApply
function handles applying configurations based on user-selected options.
auto checkBoxList = ui->selectWidget_tabs->findChildren<QCheckBox*>();
for (auto checkbox : checkBoxList) {
if (checkbox->isChecked()) {
packages += checkbox->property("packages").toStringList();
setup_commands += checkbox->property("setup_commands").toStringList();
prepare_commands += checkbox->property("prepare_commands").toStringList();
}
}
- Iterates through the checkboxes in the
selectWidget_tabs
and collects the associatedpackages
,setup_commands
, andprepare_commands
for checked items.
QTemporaryFile* prepareFile = new QTemporaryFile(this);
prepareFile->setAutoRemove(true);
prepareFile->open();
QTextStream prepareStream(prepareFile);
prepareStream << prepare_commands.join('\n');
prepareFile->close();
- Creates temporary files to store commands and settings that need to be applied.
- Writes the list of
prepare_commands
to a temporary file.
auto process = new QProcess(this);
process->start("/usr/lib/snigdhaos/launch-terminal", QStringList() << QString("/usr/lib/snigdhaos-blackbox/apply.sh \"") + prepareFile->fileName() + "\" \"" + packagesFile->fileName() + "\" \"" + setupFile->fileName() + "\"");
- Starts the
apply.sh
script, passing the files containing the prepared commands and packages.
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this, process, prepareFile, packagesFile, setupFile](int exitcode, QProcess::ExitStatus status) {
process->deleteLater();
prepareFile->deleteLater();
packagesFile->deleteLater();
setupFile->deleteLater();
if (exitcode == 0 && !packagesFile->exists()) {
updateState(State::SELECT);
}
else {
updateState(State::APPLY_RETRY);
}
});
}
- After the process finishes, temporary files are deleted.
- If the process succeeds, the state is updated to
SELECT
. - If it fails, it retries with
APPLY_RETRY
.
void SnigdhaOSBlackbox::populateSelectWidget() {
if (ui->selectWidget_tabs->count() >
0)
return;
// Add setup items dynamically
for (const auto& item : CONFIG_ITEMS) {
auto checkbox = new QCheckBox(item["label"]);
checkbox->setProperty("packages", item["packages"]);
checkbox->setProperty("setup_commands", item["setup_commands"]);
checkbox->setProperty("prepare_commands", item["prepare_commands"]);
checkbox->setChecked(true);
ui->selectWidget_tabs->addTab(checkbox, item["label"]);
}
}
- This function dynamically populates the selection widget (
selectWidget_tabs
) with checkboxes based on a configuration list (CONFIG_ITEMS
), each containing a label, packages, and commands.
This code manages the update and application process for the SnigdhaOS system, allowing the user to verify internet connectivity, apply system updates, and configure software packages through checkboxes. Each step involves executing commands, handling processes, and updating the UI based on success or failure.