Skip to content

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.

1. Includes:

#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 the SnigdhaOSBlackbox 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.

2. Constant for Internet Check URL:

const char* INTERNET_CHECK_URL = "https://snigdha-os.github.io/";  
  • Defines the URL used to verify if the system has an active internet connection.

3. Constructor SnigdhaOSBlackbox::SnigdhaOSBlackbox:

SnigdhaOSBlackbox::SnigdhaOSBlackbox(QWidget *parent, QString state)
    : QMainWindow(parent)  
    , ui(new Ui::SnigdhaOSBlackbox)  
{
  • Constructor for the SnigdhaOSBlackbox class, inheriting from QMainWindow.
  • 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.

Window Icon and UI Setup:

    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.

Window Flags:

    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 Modification Date:

    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.

State Update:

    updateState(state);
}
  • Calls updateState to set the initial state of the application based on the provided state parameter.

4. Destructor SnigdhaOSBlackbox::~SnigdhaOSBlackbox:

SnigdhaOSBlackbox::~SnigdhaOSBlackbox()
{
    delete ui;
}
  • Destructor for the SnigdhaOSBlackbox class.
  • Frees the memory allocated for the ui object, ensuring there are no memory leaks.

5. Internet Check Request doInternetUpRequest:

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 a HEAD request to the specified INTERNET_CHECK_URL to check if the system has internet access.

Timer Setup:

    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.

Timeout Handling:

    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.

Network Response Handling:

    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.

6. Update Function doUpdate:

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 the pacman update command (sudo pacman -Syyu).
  • A temporary file is used to track the update process.

Process Handling:

    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 with relaunchSelf("POST_UPDATE").
  • If there’s an issue, it retries by calling relaunchSelf("UPDATE_RETRY").

7. Apply Function doApply:

void SnigdhaOSBlackbox::doApply() {
    QStringList packages;
    QStringList setup_commands;
    QStringList prepare_commands;
  • The doApply function handles applying configurations based on user-selected options.

Checkbox Handling:

    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 associated packages, setup_commands, and prepare_commands for checked items.

File Creation and Command Execution:

    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.

Process Execution:

    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.

Process Completion:

    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.

8. Populate Select Widget:

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.

Summary:

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.