Browse Source

Backported APIs from other projects + major refactoring

master
Sasko Usinov 4 months ago
parent
commit
8581d6e93c
17 changed files with 830 additions and 419 deletions
  1. +8
    -5
      dm4l.pro
  2. +1
    -1
      dm4l.pro.user
  3. +14
    -0
      lib/libsources/api.h
  4. +180
    -0
      lib/libsources/cns.cpp
  5. +98
    -2
      lib/libsources/sys.cpp
  6. +3
    -3
      qt/main_window/main_window.cpp
  7. +5
    -5
      qt/main_window/main_window.h
  8. +0
    -233
      qt/main_window/mw_device_config.cpp
  9. +86
    -0
      qt/main_window/mw_slots_c_file_ops.cpp
  10. +0
    -48
      qt/main_window/mw_slots_q_file_ops.cpp
  11. +156
    -0
      qt/main_window/mw_slots_q_general.cpp
  12. +3
    -119
      qt/main_window/mw_slots_q_popup_builder.cpp
  13. +0
    -0
      qt/main_window/mw_slots_q_script_completed.cpp
  14. +0
    -0
      qt/main_window/mw_slots_q_threads_std.cpp
  15. +0
    -0
      qt/main_window/mw_slots_q_timers.cpp
  16. +271
    -0
      qt/main_window/mw_startup_script_gen.cpp
  17. +5
    -3
      res/css/popup_menu.css

+ 8
- 5
dm4l.pro View File

@@ -43,11 +43,14 @@ SOURCES += \
qt/main_window/mw_load_pci_device_list.cpp \
qt/main_window/mw_load_scsi_device_list.cpp \
qt/main_window/mw_load_usb_device_list.cpp \
qt/main_window/mw_slots_general.cpp \
qt/main_window/mw_slots_script_completed.cpp \
qt/main_window/mw_slots_threads_std.cpp \
qt/main_window/mw_slots_timers.cpp \
qt/main_window/mw_slots_ui.cpp \
qt/main_window/mw_slots_c_file_ops.cpp \
qt/main_window/mw_slots_q_file_ops.cpp \
qt/main_window/mw_slots_q_general.cpp \
qt/main_window/mw_slots_q_popup_builder.cpp \
qt/main_window/mw_slots_q_script_completed.cpp \
qt/main_window/mw_slots_q_threads_std.cpp \
qt/main_window/mw_slots_q_timers.cpp \
qt/main_window/mw_startup_script_gen.cpp \
qt/main_window/mw_threads_std.cpp \
qt/toast_message/tm_events_qt.cpp \
qt/toast_message/tm_slots_qt.cpp \


+ 1
- 1
dm4l.pro.user View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.9.1, 2019-12-26T16:03:58. -->
<!-- Written by QtCreator 4.9.1, 2019-12-29T19:40:30. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>


+ 14
- 0
lib/libsources/api.h View File

@@ -35,6 +35,8 @@
#include <thread>

#define SHELL_PATH std::string("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
#define NAME_TO_STRING(var) (#var)
#define SHOW_VAR_VALUE std::cout << "Var" << #var << " = " << var << std::endl;

//------------------------------------------------------------------------------------------------//
// Backported api - more will be released
@@ -42,8 +44,14 @@
namespace api
{
#define API_ERROR_IDX_NOT_FOUND std::string::npos

#define API_ERROR_FILE_WRITE 1
#define API_ERROR_FILE_OPEN 2
#define API_ERROR_CHMOD_FAILURE 3

#define nullchr '\0'


namespace str
{
std::string get_file_name_from_url (const std::string & path_name, const char & path_del = '/');
@@ -115,6 +123,11 @@
runstruct exec (const std::string & cmd, const std::string & output_dir = "/tmp");
runstruct exec_ext (const std::string & cmd, const std::string & output_dir = "/tmp");
std::string run (const std::string & cmd);

int run_in_pseudo_terminal (const std::string & terminal, const std::string & cmd);
std::string run_in_pseudo_terminal (const std::string & prompt, std::vector<std::string> & cmd_list, bool run_in_background = true);
std::vector<std::string> get_supported_terminals ();
std::string get_preferred_terminal ();
}

namespace sys
@@ -123,6 +136,7 @@
inline bool vm_detected () {return !system("dmesg | grep \"Hypervisor detected\"");}
std::string read_link (const std::string & path);
std::string get_file_icon_name (const std::string & file_path, const std::string & theme_path, const std::string & icon_extenstion);
std::string get_file_icon_name (const std::string & file_path, std::vector<std::string> & icon_theme_paths, const std::string & icon_extenstion);
}

namespace ini


+ 180
- 0
lib/libsources/cns.cpp View File

@@ -46,6 +46,186 @@

#include <array>

//-------------------------------------------------------------------------------//
// Type: namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Returns a list of supported terminals that we can use
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
std::vector<std::string> api::cns::get_supported_terminals()
{
std::vector<std::string> term_list;

term_list.push_back("xterm");
term_list.push_back("xfce4-terminal");
term_list.push_back("gnome-terminal");
term_list.push_back("konsole");
term_list.push_back("terminator");
term_list.push_back("tilix");
term_list.push_back("mate-terminal");

return term_list;
}

//-------------------------------------------------------------------------------//
// Type: namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Returns a terminal that we can use
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
std::string api::cns::get_preferred_terminal()
{
std::string out;

//------------------------------------------------------------------------------------------------
// Warning! Do not add lxterminal - the version I tested did not work properly with "-e"
// when you add quotations etc
//------------------------------------------------------------------------------------------------
std::vector<std::string> term_list = get_supported_terminals();

for (size_t i = 0; i < term_list.size(); i++)
{
std::string t = "which " + term_list[i] + " > /dev/null";

if (!system(t.c_str()))
out = term_list[i];
}

return out;
}

//-------------------------------------------------------------------------------//
// Type: namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Returns a terminal that we can use
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
int api::cns::run_in_pseudo_terminal(const std::string & terminal, const std::string & cmd)
{
std::string script_path {api::fs::generate_unique_filename("/tmp", "run_in_terminal")};
std::vector<std::string> script {};
std::string sys_cmd {terminal + " -e " + script_path + " &"};

script.push_back("#!/bin/bash");
script.push_back(cmd);

if (!api::fs::save_to_file(script_path, api::vct::to_string(script, '\n')))
return API_ERROR_FILE_WRITE;

if (system(("chmod u+x " + script_path).c_str()))
return API_ERROR_CHMOD_FAILURE;

api::writout << "Script path: " << script_path << api::endl;
api::writout << "sys_cmd: " << sys_cmd << api::endl;

return system((sys_cmd).c_str());
}

//-------------------------------------------------------------------------------//
// Type: namespace
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Runs command in a pseudo terminal
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
std::string api::cns::run_in_pseudo_terminal(const std::string & prompt, std::vector<std::string> & cmd_list, bool run_in_background)
{
//------------------------------------------------------------------------------------------------
// Get a terminal that we can use
//------------------------------------------------------------------------------------------------
std::string terminal = get_preferred_terminal();

if (!terminal.size())
{
std::vector<std::string> term_list = get_supported_terminals();

throw std::invalid_argument("Did not find a supported terminal emulator. In order for this to work, you need to have one of the following terminals installed:\n\n" + api::vct::to_string(term_list, '\n') + "\nPlease install one of the aforementioned terminal emulators and try again.");
}

//------------------------------------------------------------------------------------------------
// We are good to go
//------------------------------------------------------------------------------------------------
std::vector<std::string> cmd;
std::string script_content;

for (size_t i = 0; i < cmd_list.size(); i++)
{
if (cmd_list[i][cmd_list[i].size() -1] == '\n')
script_content += cmd_list[i];
else
script_content += cmd_list[i] + "\n";
}

script_content.insert(0, "#!/bin/sh\n");

//------------------------------------------------------------------------------------------------
// Save the script
//------------------------------------------------------------------------------------------------
std::string script_path = api::fs::generate_unique_filename("/tmp", "file_run.sh");

if (!api::fs::save_to_file(script_path, script_content))
{
throw std::invalid_argument("Failed to create " + script_path);
return std::string();
}

//------------------------------------------------------------------------------------------------
// Change permissions
//------------------------------------------------------------------------------------------------
system(std::string("chmod u+x " + script_path).c_str());

//------------------------------------------------------------------------------------------------
// Ask the user to confirm
//------------------------------------------------------------------------------------------------
if (prompt.length())
{
cmd.push_back(terminal + " -e \'sh -c \"(echo " + prompt + ");");

cmd.push_back("echo;");
cmd.push_back("echo;");
}
else
{
cmd.push_back(terminal + " -e \'sh -c \"");
}

cmd.push_back(script_path + ";");

cmd.push_back("echo;");
cmd.push_back("echo Done running the script. This terminal window may now be closed.;");
cmd.push_back("echo;");

cmd.push_back("read input;");

cmd.push_back("\"'");

if (run_in_background)
system(std::string(api::vct::to_string(cmd) + " &").c_str());
else
system(api::vct::to_string(cmd).c_str());

return api::vct::to_string(cmd);
}


//-------------------------------------------------------------------------------//
// Type: namespace


+ 98
- 2
lib/libsources/sys.cpp View File

@@ -152,15 +152,111 @@ std::string api::sys::get_file_icon_name(const std::string & file_path, const st

out = api::str::trim(paths[paths.size() - 1]);

std::cout << __func__ << "(): RETURNING: \"" << out << "\"" << std::endl;
api::writout << __func__ << "(): RETURNING: \"" << out << "\"" << api::endl;

return out;
}

api::writout << __func__ << "(): EXITIng with a failure: \"" << file_icon << "\"" << api::endl;

return file_icon;
return std::string();
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: Requires:
// #include <gio/gio.h>
//
// Compile with:
// -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -fpermissive -lgio-2.0
//
// If using with Qt, put #define QT_NO_KEYWORDS at the top of the file
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
std::string api::sys::get_file_icon_name(const std::string & file_path, std::vector<std::string> & icon_theme_paths, const std::string & icon_extenstion)
{
// typedef std::vector<std::string> string_list;

if (!api::fs::path_exists(file_path))
return std::string();

std::string home_dir {get_env("HOME")};
GError * error;
GFile * file = g_file_new_for_path (file_path.c_str());
GFileInfo * file_info = g_file_query_info (file, "standard::*", GFileQueryInfoFlags::G_FILE_QUERY_INFO_NONE, nullptr, &error);

const char * content_type = g_file_info_get_content_type (file_info);
char * desc = g_content_type_get_description (content_type);
// GAppInfo * app_info = g_app_info_get_default_for_type (content_type, FALSE);

GIcon * icon = g_file_info_get_icon (file_info);
const char * file_icon = g_icon_to_string (icon);

std::vector<std::string> icon_names_list {api::vct::to_vector_string_list(file_icon, 32)};
size_t icon_idx {0};
api::cns::runstruct find_output;
std::string out {};

icon_theme_paths.push_back("/usr/share/icons/gnome");
icon_theme_paths.push_back("/usr/share/icons/Adwaita");
icon_theme_paths.push_back("/usr/share/icons/elementary-xfce");

api::writout << __func__ << "(): g_icon_to_string returned: \"" << file_icon << "\"" << api::endl;
api::writout << __func__ << "(): Content Type is: \"" << content_type << "\"" << api::endl;
api::writout << __func__ << "(): Description is: \"" << desc << "\"" << api::endl;

for (size_t i = 0; i < icon_theme_paths.size(); i++)
{
if (!api::fs::path_exists(icon_theme_paths[i]))
continue;

//-------------------------------------------------------------------------------//
// Try to obtain the path to the correct icon resource in the theme path specified
//-------------------------------------------------------------------------------//
obtain_icon:
{
std::string cmd {"find \"" + icon_theme_paths[i] + "\" -name \"" + std::string(api::str::trim(icon_names_list[icon_idx])) + "." + (icon_extenstion.size() ? icon_extenstion : "png") + "\""};
api::writout << __func__ << "(): RUNNING: " << cmd << api::endl;
find_output = {api::cns::exec(cmd)};
}

//-------------------------------------------------------------------------------//
// If "find" returned nothing
//-------------------------------------------------------------------------------//
if (!api::str::trim(find_output.std_out).size())
{
icon_idx++;

if (icon_idx >= icon_names_list.size())
{
icon_idx = 0;
continue;
}

goto obtain_icon;
}

std::vector<std::string> paths = api::vct::to_vector_string_list(find_output.std_out, 10);

out = api::str::trim(paths[paths.size() - 1]);

api::writout << __func__ << "(): RETURNING: \"" << out << "\"" << api::endl;

return out;
}

api::writout << __func__ << "(): EXITIng with a failure: \"" << file_icon << "\"" << api::endl;

return std::string();
}






+ 3
- 3
qt/main_window/main_window.cpp View File

@@ -145,7 +145,7 @@ void main_window::connect_signals()
connect(get_device_list(), SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(slotq_on_device_list_item_expanded(QTreeWidgetItem *)));

connect(get_system_boot_list(), SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotq_on_boot_list_context_menu(const QPoint &)));
connect(get_corner_button(), SIGNAL(clicked()), this, SLOT(slotq_on_corner_button_clicked()));
connect(get_corner_button(), SIGNAL(clicked()), this, SLOT(slotq_corner_button_clicked()));

connect(this, SIGNAL(sigq_new_script_thread_started(const std::string &)), this, SLOT(slotq_on_new_std_thread_started(const std::string &)));
connect(this, SIGNAL(sigq_pci_script_completed(int)), this, SLOT(slotq_on_pci_script_completed(int)));
@@ -171,8 +171,8 @@ void main_window::connect_signals()
connect(get_timer_start_search(), SIGNAL(timeout()), this, SLOT(slotq_on_timeout_start_search()));
connect(get_timer_clear_file_nodes_buffer(), SIGNAL(timeout()), this, SLOT(slotq_on_timeout_clear_event_buffer()));

connect(new QShortcut(QKeySequence("F7"), this), SIGNAL(activated()), this, SLOT(slotq_copy_pci_ids_to_clipboard()));
connect(new QShortcut(QKeySequence("F8"), this), SIGNAL(activated()), this, SLOT(slotq_copy_usb_ids_to_clipboard()));
connect(new QShortcut(QKeySequence("F7"), this), SIGNAL(activated()), this, SLOT(slotq_copy_pci_ids_to_clipboard_clicked()));
connect(new QShortcut(QKeySequence("F8"), this), SIGNAL(activated()), this, SLOT(slotq_copy_usb_ids_to_clipboard_clicked()));
}

//-------------------------------------------------------------------------------//


+ 5
- 5
qt/main_window/main_window.h View File

@@ -304,9 +304,9 @@ class main_window : public QDialog

inline void slotq_on_read_rc_local_clicked () {read_rc_local(); new toast_message(this, "Done!", 4000, 500);}

void slotq_on_corner_button_clicked ();
void slotq_corner_button_clicked ();

void slotq_on_device_prop_clicked ();
void slotq_device_prop_clicked ();
inline void slotq_on_usb_device_prop_clicked () {show_usb_device_prop();}

inline void slotq_on_about_qt_clicked () {qApp->aboutQt();}
@@ -332,12 +332,12 @@ class main_window : public QDialog
void slotq_on_file_added (const std::string &);
void slotq_on_file_removed (const std::string &);

void slotq_on_about_clicked ();
void slotq_about_clicked ();
void slotq_on_timeout_start_search ();
void slotq_on_timeout_clear_event_buffer ();

void slotq_copy_pci_ids_to_clipboard ();
void slotq_copy_usb_ids_to_clipboard ();
void slotq_copy_pci_ids_to_clipboard_clicked ();
void slotq_copy_usb_ids_to_clipboard_clicked ();

//------------------------------------------------------------------------------------------------//
// ...


+ 0
- 233
qt/main_window/mw_device_config.cpp View File

@@ -88,239 +88,6 @@ void main_window::configure_usb_device()
emit sigq_new_script_thread_started(script_path);
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::generate_usb_startup_script()
{
tree_widget_item * item {dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])};
usb_device_struct * data {static_cast<usb_device_struct *>(item->get_custom_data())};
std::string action {get_usb_config_op() == ACT_DISABLE_DEVICE ? "unbind" : "bind"};
std::string script_path {data->boot_script_path};
std::vector<std::string> script;

script.push_back("#!/bin/bash");
script.push_back("");
script.push_back("# This script was generated automatically by: " + app::about::app_name);
script.push_back("");
script.push_back("# Running this script as su will disable this device.");
script.push_back("");
script.push_back("# Invoke this script from within /etc/rc.local");
script.push_back("");
script.push_back("# Device Name: " + data->hub_info);
script.push_back("");

script.push_back("sysfs_id=$(grep -il '" + data->vid_did_processed + "' /sys/bus/usb/devices/*/uevent | tail -1)");
script.push_back("sysfs_id=$(echo $sysfs_id | cut -f6 -d'/')");
script.push_back("echo $sysfs_id > /sys/bus/usb/drivers/usb/" + action);

if (!api::fs::save_to_file(script_path, api::vct::to_string(script, '\n')))
{
messages::show_message(("An error occured while trying to save: " + script_path).c_str());
return;
}

if (system(("chmod u+x " + script_path).c_str()))
{
messages::show_message(("An error occured changing file permissions of: " + script_path).c_str());
return;
}

int status = add_to_rc_local(script_path, data->hub_info + "_" + data->actual_dev_details);

if (status == OP_FAIL)
{
messages::show_message("Operation failed.");
return;
}

if (status == OP_SUCCESS)
{
new toast_message(this, "Done!", 1200, 500);

get_main_pager()->setCurrentIndex(1);

read_rc_local();
}
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::generate_pci_startup_script()
{
tree_widget_item * item {nullptr};

if (dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])->get_node_type() == NODE_TYPE_PCI_DEVICE_DESC)
item = dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0]);
else
item = dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0]->parent()); // it will alwyas be a NODE_TYPE_DEVICE_PROP when this runs

//-------------------------------------------------------------------------------//
// Check the casting...
//-------------------------------------------------------------------------------//
if (dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])->get_node_type() == NODE_TYPE_PCI_PERIPHERAL_TYPE)
{
messages::show_message(("In " + std::string(__func__) + " - get_node_type() == NODE_TYPE_PERIPHERAL_TYPE. Cannot continue.").c_str());
return;
}

pci_device_struct * dev_info = static_cast<pci_device_struct *>(item->get_custom_data());

//-------------------------------------------------------------------------------//
//
// Check to see if the output of "lspci" returned the kernel module
// of the currently selected device.
//
// This section will only run if we failed to find the "Kernel modules" line
// in the output of lspci
//
//-------------------------------------------------------------------------------//
if (!dev_info->kernel_module.size())
{
messages::show_message("Cannot disable this device because no kernel module was listed by lspci.");
return;
}

std::vector<std::string> script;
script.push_back("#!/bin/bash");
script.push_back("");
script.push_back("# This script was generated automatically by: " + app::about::app_name);
script.push_back("");
script.push_back("# Running this script as su will disable this device.");
script.push_back("");
script.push_back("# Invoke this script from within /etc/rc.local");
script.push_back("");
script.push_back("# Device Name: " + dev_info->device_desc);
script.push_back("");
script.push_back("sysfs_id=$(grep -il '" + dev_info->dev_desc_vid_did + "' /sys/bus/pci/devices/*/uevent | tail -1)");
script.push_back("sysfs_id=$(echo $sysfs_id | cut -f6 -d'/')");

//-------------------------------------------------------------------------------//
// Check to see if we have multiple module entries
//
// When we do so, they are separated by commas like this: "module1, module2"
//-------------------------------------------------------------------------------//
if (dev_info->kernel_module.find(",") != std::string::npos)
{
std::vector<std::string> lst {api::vct::to_vector_string_list(dev_info->kernel_module, std::vector<char>() = {','})};

//-------------------------------------------------------------------------------//
// Build a separate "echo" command for each module entry
//-------------------------------------------------------------------------------//
for (size_t i = 0; i < lst.size(); i++)
{
std::string mdl_name = api::str::trim(api::str::remove_char(',', lst[i]));

if (api::fs::path_exists("/sys/bus/pci/drivers/" + mdl_name + "/unbind"))
script.push_back("echo \"$sysfs_id\" > /sys/bus/pci/drivers/" + mdl_name + "/unbind");
}
}
else
script.push_back("echo \"$sysfs_id\" > /sys/bus/pci/drivers/" + dev_info->kernel_module + "/unbind");

std::string script_path = dev_info->boot_script_path;

if (!api::fs::save_to_file(script_path, api::vct::to_string(script, '\n')))
{
messages::show_message(("An error occured while trying to save: " + script_path).c_str());
return;
}

if (system(("chmod u+x " + script_path).c_str()))
{
messages::show_message(("An error occured changing file permissions of: " + script_path).c_str());
return;
}

int status = add_to_rc_local(script_path, dev_info->device_desc);

if (status == OP_FAIL)
{
messages::show_message("Operation failed.");
return;
}

if (status == OP_SUCCESS)
{
new toast_message(this, "Done!", 1200, 500);

get_main_pager()->setCurrentIndex(1);

read_rc_local();
}
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::generate_scsi_startup_script()
{
std::vector<std::string> script;
std::string shell_file {get_scsi_struct(get_device_list()->selectedItems()[0])->boot_script_path};
std::string dev_file {"/sys/class/scsi_device/" + get_scsi_hba_id(get_device_list()->selectedItems()[0]) + "/device/delete"};

if (!api::fs::path_exists(dev_file))
{
messages::show_message("\"" + dev_file + "\" does not exist. Cannot disable this device.");
return;
}

script.push_back("#!/usr/bin/pkexec /bin/bash");
script.push_back("echo 1 > " + dev_file);

if (!api::fs::save_to_file(shell_file, api::vct::to_string(script, 10)))
{
messages::show_message("Failed to write to: \"" + shell_file + "\". Cannot continue.");
return;
}

if (system(("chmod u+x " + shell_file).c_str()))
{
messages::show_message("Failed to change permissions of: \"" + shell_file + "\". Cannot continue.");
return;
}

int status = add_to_rc_local(shell_file, static_cast<scsi_device_struct *>((dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0]))->get_custom_data())->product_info);

if (status == OP_FAIL)
{
messages::show_message("Operation failed.");
return;
}

if (status == OP_SUCCESS)
{
new toast_message(this, "Done!", 1200, 500);
get_main_pager()->setCurrentIndex(1);

read_rc_local();
}
}

//-------------------------------------------------------------------------------//
// Type: class


+ 86
- 0
qt/main_window/mw_slots_c_file_ops.cpp View File

@@ -0,0 +1,86 @@
//-----------------------------------------------------------------------------------------//
// Distributed under the MIT License - https://opensource.org/licenses/MIT
//-----------------------------------------------------------------------------------------//
//
// Copyright © 2019 Sasko Usinov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRactions[actions.size() - 1], TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//-----------------------------------------------------------------------------------------//
// Distributed under the MIT License - https://opensource.org/licenses/MIT
//-----------------------------------------------------------------------------------------//


#include "main_window.h"
#include "ui_main_window.h"

#include "qt/wrappers/wrappers.h"
#include "qt/toast_message/toast_message.h"

#include <QTreeWidgetItemIterator>
#include <QScrollBar>

#include <unistd.h>

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotc_file_added(const std::string & file_path)
{
emit sigq_file_added(file_path);
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotc_file_removed(const std::string & file_path)
{
emit sigq_file_removed(file_path);
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotc_dev_query_end(const std::string & data)
{
emit sigq_dev_query_end(data);
}

qt/main_window/mw_slots_general.cpp → qt/main_window/mw_slots_q_file_ops.cpp View File

@@ -54,54 +54,6 @@ void main_window::slotq_on_dev_query_end(const std::string &)

}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotc_file_added(const std::string & file_path)
{
emit sigq_file_added(file_path);
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotc_file_removed(const std::string & file_path)
{
emit sigq_file_removed(file_path);
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotc_dev_query_end(const std::string & data)
{
emit sigq_dev_query_end(data);
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//

+ 156
- 0
qt/main_window/mw_slots_q_general.cpp View File

@@ -0,0 +1,156 @@
//-----------------------------------------------------------------------------------------//
// Distributed under the MIT License - https://opensource.org/licenses/MIT
//-----------------------------------------------------------------------------------------//
//
// Copyright © 2019 Sasko Usinov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRactions[actions.size() - 1], TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//-----------------------------------------------------------------------------------------//
// Distributed under the MIT License - https://opensource.org/licenses/MIT
//-----------------------------------------------------------------------------------------//


#include "main_window.h"
#include "ui_main_window.h"

#include "qt/wrappers/wrappers.h"
#include "qt/toast_message/toast_message.h"

#include <QTreeWidgetItemIterator>
#include <QScrollBar>

#include <unistd.h>



//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotq_about_clicked()
{
std::string txt = "<b><font size=\"4\">" + app::about::app_friendly_name + " - " + app::about::app_desc + "</font></b><br><br>";
txt += "Copyright Ⓒ - 2019-2020, " + app::about::app_author + "<br><br>";
txt += "Version: " + app::about::app_version + "<br><br>";
txt += "Build Date: " + app::about::app_build_date + "<br><br>";
txt += "Build Time: " + app::about::app_build_time + "<br><br>";
txt += "<b><font color=\"blue\">" + app::about::app_contact + " / ";
txt += app::about::app_website + "</font></b><br><br>";

messages::show_message(txt.c_str());
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes:
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotq_device_prop_clicked()
{
tree_widget_item * item {dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])};

if (!item) return;

pci_device_struct * dev_info {static_cast<pci_device_struct *>(item->get_custom_data())};

std::vector<std::string> res = app::get_device_prop(dev_info->sysfs_id);

device_prop * prop = new device_prop(this);
prop->get_device_details_box()->setPlainText(api::vct::to_string(res, 10).c_str());
prop->get_device_details_box()->setWordWrapMode(QTextOption::NoWrap);
prop->get_header_label()->setText(dev_info->device_desc.c_str());
prop->get_device_details_box()->setTextInteractionFlags(prop->get_device_details_box()->textInteractionFlags() | Qt::TextSelectableByKeyboard);

prop->exec();

delete prop;
}



//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotq_copy_pci_ids_to_clipboard_clicked()
{
tree_widget_item * item {dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])};

if (item == nullptr)
return;

if (item->get_node_type() != NODE_TYPE_PCI_DEVICE_DESC && item->get_node_type() != NODE_TYPE_PCI_DEVICE_PROP)
return;

pci_device_struct * data {static_cast<pci_device_struct *>(item->get_custom_data())};

qApp->clipboard()->setText(data->dev_desc_vid_did.c_str());

new toast_message(this, "PCI ID copied Clipboard", 1000);
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotq_copy_usb_ids_to_clipboard_clicked()
{
tree_widget_item * item {dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])};

if (item == nullptr)
return;

if (item->get_node_type() != NODE_TYPE_USB_DEVICE_DESC)
return;

usb_device_struct * data {static_cast<usb_device_struct *>(item->get_custom_data())};

qApp->clipboard()->setText(data->vid_did_processed.c_str());

new toast_message(this, "USB ID copied Clipboard", 1000);
}



qt/main_window/mw_slots_ui.cpp → qt/main_window/mw_slots_q_popup_builder.cpp View File

@@ -89,7 +89,7 @@ void main_window::slotq_on_device_list_context_menu(const QPoint & point)
set_pci_config_op(dev_info->device_enabled ? ACT_DISABLE_DEVICE : ACT_ENABLE_DEVICE);

utils::create_action(actions, popup_menu, std::string((dev_info->device_enabled ? "Disable Device" : "Enable Device")).c_str(), this, SLOT(slotq_on_configure_pci_device_clicked()));
utils::create_action(actions, popup_menu, "Device Properties", this, SLOT(slotq_on_device_prop_clicked()));
utils::create_action(actions, popup_menu, "Device Properties", this, SLOT(slotq_device_prop_clicked()));
utils::create_action(actions, popup_menu, "Refresh Device List", this, SLOT(slotq_on_refresh_hardware_list_clicked()));
utils::create_action(actions, popup_menu, "Disable on System Boot", this, SLOT(slotq_on_disable_pci_on_boot_clicked()));

@@ -188,7 +188,7 @@ void main_window::slotq_on_boot_list_context_menu(const QPoint & point)
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotq_on_corner_button_clicked()
void main_window::slotq_corner_button_clicked()
{
std::vector<QAction *> actions {};
QMenu * popup_menu {new QMenu(this)};
@@ -197,7 +197,7 @@ void main_window::slotq_on_corner_button_clicked()
utils::create_action(actions, popup_menu, "Collapse Device List", this, SLOT(slotq_on_collapse_all_clicked()));
utils::create_action(actions, popup_menu, "Install New Module", this, SLOT(slotq_on_install_new_module_clicked()), false);
utils::create_action(actions, popup_menu, std::string("About Qt"), this, SLOT(slotq_on_about_qt_clicked()));
utils::create_action(actions, popup_menu, std::string("About " + app::about::app_friendly_name).c_str(), this, SLOT(slotq_on_about_clicked()));
utils::create_action(actions, popup_menu, std::string("About " + app::about::app_friendly_name).c_str(), this, SLOT(slotq_about_clicked()));

if (popup_menu)
{
@@ -207,119 +207,3 @@ void main_window::slotq_on_corner_button_clicked()
delete popup_menu;
}
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotq_on_about_clicked()
{
std::string txt = "<b><font size=\"4\">" + app::about::app_friendly_name + " - " + app::about::app_desc + "</font></b><br><br>";
txt += "Copyright Ⓒ - 2019-2020, " + app::about::app_author + "<br><br>";
txt += "Version: " + app::about::app_version + "<br><br>";
txt += "Build Date: " + app::about::app_build_date + "<br><br>";
txt += "Build Time: " + app::about::app_build_time + "<br><br>";
txt += "<b><font color=\"blue\">" + app::about::app_contact + " / ";
txt += app::about::app_website + "</font></b><br><br>";

messages::show_message(txt.c_str());
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes:
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotq_on_device_prop_clicked()
{
tree_widget_item * item {dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])};

if (!item) return;

pci_device_struct * dev_info {static_cast<pci_device_struct *>(item->get_custom_data())};

std::vector<std::string> res = app::get_device_prop(dev_info->sysfs_id);

device_prop * prop = new device_prop(this);
prop->get_device_details_box()->setPlainText(api::vct::to_string(res, 10).c_str());
prop->get_device_details_box()->setWordWrapMode(QTextOption::NoWrap);
prop->get_header_label()->setText(dev_info->device_desc.c_str());
prop->get_device_details_box()->setTextInteractionFlags(prop->get_device_details_box()->textInteractionFlags() | Qt::TextSelectableByKeyboard);

prop->exec();

delete prop;
}



//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotq_copy_pci_ids_to_clipboard()
{
tree_widget_item * item {dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])};

if (item == nullptr)
return;

if (item->get_node_type() != NODE_TYPE_PCI_DEVICE_DESC && item->get_node_type() != NODE_TYPE_PCI_DEVICE_PROP)
return;

pci_device_struct * data {static_cast<pci_device_struct *>(item->get_custom_data())};

qApp->clipboard()->setText(data->dev_desc_vid_did.c_str());

new toast_message(this, "PCI ID copied Clipboard", 1000);
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::slotq_copy_usb_ids_to_clipboard()
{
tree_widget_item * item {dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])};

if (item == nullptr)
return;

if (item->get_node_type() != NODE_TYPE_USB_DEVICE_DESC)
return;

usb_device_struct * data {static_cast<usb_device_struct *>(item->get_custom_data())};

qApp->clipboard()->setText(data->vid_did_processed.c_str());

new toast_message(this, "USB ID copied Clipboard", 1000);
}



qt/main_window/mw_slots_script_completed.cpp → qt/main_window/mw_slots_q_script_completed.cpp View File


qt/main_window/mw_slots_threads_std.cpp → qt/main_window/mw_slots_q_threads_std.cpp View File


qt/main_window/mw_slots_timers.cpp → qt/main_window/mw_slots_q_timers.cpp View File


+ 271
- 0
qt/main_window/mw_startup_script_gen.cpp View File

@@ -0,0 +1,271 @@
//-----------------------------------------------------------------------------------------//
// Distributed under the MIT License - https://opensource.org/licenses/MIT
//-----------------------------------------------------------------------------------------//
//
// Copyright © 2019 Sasko Usinov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
// CONTRactions[actions.size() - 1], TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//-----------------------------------------------------------------------------------------//
// Distributed under the MIT License - https://opensource.org/licenses/MIT
//-----------------------------------------------------------------------------------------//

#include "main_window.h"
#include "ui_main_window.h"

#include "qt/wrappers/wrappers.h"
#include "qt/toast_message/toast_message.h"

#include <QTreeWidgetItemIterator>
#include <QScrollBar>

#include <unistd.h>

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::generate_usb_startup_script()
{
tree_widget_item * item {dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])};
usb_device_struct * data {static_cast<usb_device_struct *>(item->get_custom_data())};
std::string action {get_usb_config_op() == ACT_DISABLE_DEVICE ? "unbind" : "bind"};
std::string script_path {data->boot_script_path};
std::vector<std::string> script;

script.push_back("#!/bin/bash");
script.push_back("");
script.push_back("# This script was generated automatically by: " + app::about::app_name);
script.push_back("");
script.push_back("# Running this script as su will disable this device.");
script.push_back("");
script.push_back("# Invoke this script from within /etc/rc.local");
script.push_back("");
script.push_back("# Device Name: " + data->hub_info);
script.push_back("");

script.push_back("sysfs_id=$(grep -il '" + data->vid_did_processed + "' /sys/bus/usb/devices/*/uevent | tail -1)");
script.push_back("sysfs_id=$(echo $sysfs_id | cut -f6 -d'/')");
script.push_back("echo $sysfs_id > /sys/bus/usb/drivers/usb/" + action);

if (!api::fs::save_to_file(script_path, api::vct::to_string(script, '\n')))
{
messages::show_message(("An error occured while trying to save: " + script_path).c_str());
return;
}

if (system(("chmod u+x " + script_path).c_str()))
{
messages::show_message(("An error occured changing file permissions of: " + script_path).c_str());
return;
}

int status = add_to_rc_local(script_path, data->hub_info + "_" + data->actual_dev_details);

if (status == OP_FAIL)
{
messages::show_message("Operation failed.");
return;
}

if (status == OP_SUCCESS)
{
new toast_message(this, "Done!", 1200, 500);

get_main_pager()->setCurrentIndex(1);

read_rc_local();
}
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::generate_pci_startup_script()
{
tree_widget_item * item {nullptr};

if (dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])->get_node_type() == NODE_TYPE_PCI_DEVICE_DESC)
item = dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0]);
else
item = dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0]->parent()); // it will alwyas be a NODE_TYPE_DEVICE_PROP when this runs

//-------------------------------------------------------------------------------//
// Check the casting...
//-------------------------------------------------------------------------------//
if (dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0])->get_node_type() == NODE_TYPE_PCI_PERIPHERAL_TYPE)
{
messages::show_message(("In " + std::string(__func__) + " - get_node_type() == NODE_TYPE_PERIPHERAL_TYPE. Cannot continue.").c_str());
return;
}

pci_device_struct * dev_info = static_cast<pci_device_struct *>(item->get_custom_data());

//-------------------------------------------------------------------------------//
//
// Check to see if the output of "lspci" returned the kernel module
// of the currently selected device.
//
// This section will only run if we failed to find the "Kernel modules" line
// in the output of lspci
//
//-------------------------------------------------------------------------------//
if (!dev_info->kernel_module.size())
{
messages::show_message("Cannot disable this device because no kernel module was listed by lspci.");
return;
}

std::vector<std::string> script;
script.push_back("#!/bin/bash");
script.push_back("");
script.push_back("# This script was generated automatically by: " + app::about::app_name);
script.push_back("");
script.push_back("# Running this script as su will disable this device.");
script.push_back("");
script.push_back("# Invoke this script from within /etc/rc.local");
script.push_back("");
script.push_back("# Device Name: " + dev_info->device_desc);
script.push_back("");
script.push_back("sysfs_id=$(grep -il '" + dev_info->dev_desc_vid_did + "' /sys/bus/pci/devices/*/uevent | tail -1)");
script.push_back("sysfs_id=$(echo $sysfs_id | cut -f6 -d'/')");

//-------------------------------------------------------------------------------//
// Check to see if we have multiple module entries
//
// When we do so, they are separated by commas like this: "module1, module2"
//-------------------------------------------------------------------------------//
if (dev_info->kernel_module.find(",") != std::string::npos)
{
std::vector<std::string> lst {api::vct::to_vector_string_list(dev_info->kernel_module, std::vector<char>() = {','})};

//-------------------------------------------------------------------------------//
// Build a separate "echo" command for each module entry
//-------------------------------------------------------------------------------//
for (size_t i = 0; i < lst.size(); i++)
{
std::string mdl_name = api::str::trim(api::str::remove_char(',', lst[i]));

if (api::fs::path_exists("/sys/bus/pci/drivers/" + mdl_name + "/unbind"))
script.push_back("echo \"$sysfs_id\" > /sys/bus/pci/drivers/" + mdl_name + "/unbind");
}
}
else
script.push_back("echo \"$sysfs_id\" > /sys/bus/pci/drivers/" + dev_info->kernel_module + "/unbind");

std::string script_path = dev_info->boot_script_path;

if (!api::fs::save_to_file(script_path, api::vct::to_string(script, '\n')))
{
messages::show_message(("An error occured while trying to save: " + script_path).c_str());
return;
}

if (system(("chmod u+x " + script_path).c_str()))
{
messages::show_message(("An error occured changing file permissions of: " + script_path).c_str());
return;
}

int status = add_to_rc_local(script_path, dev_info->device_desc);

if (status == OP_FAIL)
{
messages::show_message("Operation failed.");
return;
}

if (status == OP_SUCCESS)
{
new toast_message(this, "Done!", 1200, 500);

get_main_pager()->setCurrentIndex(1);

read_rc_local();
}
}

//-------------------------------------------------------------------------------//
// Type: class
//-------------------------------------------------------------------------------//
//
// ToDo: n/a
//
// Notes: n/a
//
// Returns: n/a
//
//-------------------------------------------------------------------------------//
void main_window::generate_scsi_startup_script()
{
std::vector<std::string> script;
std::string shell_file {get_scsi_struct(get_device_list()->selectedItems()[0])->boot_script_path};
std::string dev_file {"/sys/class/scsi_device/" + get_scsi_hba_id(get_device_list()->selectedItems()[0]) + "/device/delete"};

if (!api::fs::path_exists(dev_file))
{
messages::show_message("\"" + dev_file + "\" does not exist. Cannot disable this device.");
return;
}

script.push_back("#!/usr/bin/pkexec /bin/bash");
script.push_back("echo 1 > " + dev_file);

if (!api::fs::save_to_file(shell_file, api::vct::to_string(script, 10)))
{
messages::show_message("Failed to write to: \"" + shell_file + "\". Cannot continue.");
return;
}

if (system(("chmod u+x " + shell_file).c_str()))
{
messages::show_message("Failed to change permissions of: \"" + shell_file + "\". Cannot continue.");
return;
}

int status = add_to_rc_local(shell_file, static_cast<scsi_device_struct *>((dynamic_cast<tree_widget_item *>(get_device_list()->selectedItems()[0]))->get_custom_data())->product_info);

if (status == OP_FAIL)
{
messages::show_message("Operation failed.");
return;
}

if (status == OP_SUCCESS)
{
new toast_message(this, "Done!", 1200, 500);
get_main_pager()->setCurrentIndex(1);

read_rc_local();
}
}

+ 5
- 3
res/css/popup_menu.css View File

@@ -6,7 +6,7 @@ QMenu

QMenu::item
{
padding: 2px 20px 2px 20px;
padding: 2px 20px 2px 25px;
border: 1px solid transparent; /* reserve space for selection border */
min-height: 27px;
}
@@ -57,12 +57,14 @@ QMenu::indicator:non-exclusive:unchecked:selected

QMenu::indicator:non-exclusive:checked
{
image: url(:/images/checkbox_checked.png);
padding-left: 9px;
image: url(:/icons/png/icon_checked_bk.png);
}

QMenu::indicator:non-exclusive:checked:selected
{
image: url(:/images/checkbox_checked_hover.png);
padding-left: 9px;
image: url(:/icons/png/icon_checked_bk.png);
}

/* exclusive indicator = radio button style indicator (see QActionGroup::setExclusive) */


Loading…
Cancel
Save