Compare commits

...
10 changed files with 442 additions and 321 deletions
+11 -6
View File
@@ -1,7 +1,7 @@
###############################################################################
# License: BSD Zero Clause License file
# Copyright:
# (C) 2021 Alexander Shaduri <ashaduri@gmail.com>
# (C) 2021 - 2022 Alexander Shaduri <ashaduri@gmail.com>
###############################################################################
# Disable all warnings
@@ -18,7 +18,7 @@ find_package(PkgConfig REQUIRED) # pkg_check_modules()
# Gtkmm.
# Don't make it REQUIRED, we may want to build only the parsers
# Don't make it REQUIRED, we may want to build only the parsers.
pkg_check_modules(Gtkmm IMPORTED_TARGET GLOBAL "gtkmm-3.0>=3.0")
add_library(app_gtkmm_interface INTERFACE)
target_link_libraries(app_gtkmm_interface
@@ -30,11 +30,16 @@ target_compile_definitions(app_gtkmm_interface
ENABLE_GLIB=1
ENABLE_GLIBMM=1
# For porting to GTK4
# GTK_DISABLE_DEPRECATED=1
# GDK_DISABLE_DEPRECATED=1
# GTKMM_DISABLE_DEPRECATED=1
# GDKMM_DISABLE_DEPRECATED=1
GTK_DISABLE_DEPRECATED=1
GDK_DISABLE_DEPRECATED=1
GTKMM_DISABLE_DEPRECATED=1
GDKMM_DISABLE_DEPRECATED=1
GLIBMM_DISABLE_DEPRECATED=1
GIOMM_DISABLE_DEPRECATED=1
)
# Don't forget to set the following environment variable to catch deprecated properties and signals at runtime:
#G_ENABLE_DIAGNOSTIC=1
# Support pre-C++17 glibmm with throw(...) exception specifications
pkg_check_modules(Glibmm "glibmm-2.4")
+14 -14
View File
@@ -152,9 +152,9 @@ bool CommandExecutorGui::execute_tick_func(TickStatus status)
// If quit() was called during one of the manual iterations, and execute()
// is called in a loop, we need to prevent any real execution past that point.
if (Gtk::Main::iteration(false) && Gtk::Main::level() > 0) {
return false; // try to abort execution
}
// if (Gtk::Main::iteration(false) && Gtk::Main::level() > 0) {
// return false; // try to abort execution
// }
execution_running_ = true;
should_abort_ = false;
@@ -181,14 +181,14 @@ bool CommandExecutorGui::execute_tick_func(TickStatus status)
if (status == TickStatus::running) {
while (Gtk::Main::events_pending()) {
// Gtk::Main::iteration() returns true if Gtk::Main::quit() has been called, or if there's no Main yet.
// debug_out_dump("app", Gtk::Main::level() << "\n");
if (Gtk::Main::iteration() && Gtk::Main::level() > 0) {
set_running_dialog_abort_mode(true);
return false; // try to abort execution
}
}
// while (Gtk::Main::events_pending()) {
// // Gtk::Main::iteration() returns true if Gtk::Main::quit() has been called, or if there's no Main yet.
// // debug_out_dump("app", Gtk::Main::level() << "\n");
// if (Gtk::Main::iteration() && Gtk::Main::level() > 0) {
// set_running_dialog_abort_mode(true);
// return false; // try to abort execution
// }
// }
if (should_abort_) {
should_abort_ = false;
@@ -205,9 +205,9 @@ bool CommandExecutorGui::execute_tick_func(TickStatus status)
if (status == TickStatus::stopping) {
if (Gtk::Main::iteration(false) && Gtk::Main::level() > 0) {
return false; // we're exiting from the main loop, so return early
}
// if (Gtk::Main::iteration(false) && Gtk::Main::level() > 0) {
// return false; // we're exiting from the main loop, so return early
// }
// show a dialog with "Aborting..."
this->update_dialog_show_timer();
@@ -25,7 +25,8 @@ int main(int argc, char** argv)
{
return hz::main_exception_wrapper([&argc, &argv]()
{
Gtk::Main m(argc, argv);
// Required by executor
auto app = Gtk::Application::create("org.gsmartcontrol.examples.smartctl_executor");
// NOTE: Don't use long options (e.g. --info). Use short ones (e.g. -i),
// because long options may be unsupported on some platforms.
+8 -8
View File
@@ -112,7 +112,7 @@ bool gui_show_text_entry_dialog(const std::string& title, const std::string& mes
+ (sec_message.empty() ? "\n" : "") + "</b></big>");
main_label.set_line_wrap(true);
main_label.set_selectable(true);
main_label.set_alignment(Gtk::ALIGN_START);
main_label.set_halign(Gtk::ALIGN_START);
Gtk::Label sec_label;
if (sec_msg_markup) {
@@ -122,7 +122,7 @@ bool gui_show_text_entry_dialog(const std::string& title, const std::string& mes
}
sec_label.set_line_wrap(true);
sec_label.set_selectable(true);
sec_label.set_alignment(Gtk::ALIGN_START);
sec_label.set_halign(Gtk::ALIGN_START);
Gtk::Entry input_entry;
input_entry.set_activates_default(true);
@@ -135,16 +135,16 @@ bool gui_show_text_entry_dialog(const std::string& title, const std::string& mes
vbox.pack_start(input_entry, true, true, 0);
vbox.show_all();
dialog.get_action_area()->set_border_width(5);
dialog.get_action_area()->set_spacing(6);
dialog.get_content_area()->set_border_width(5);
// dialog.get_action_area()->set_spacing(6);
dialog.get_vbox()->set_spacing(14); // as in MessageDialog
dialog.get_vbox()->pack_start(vbox, false, false, 0);
dialog.get_content_area()->set_spacing(14); // as in MessageDialog
dialog.get_content_area()->pack_start(vbox, false, false, 0);
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
dialog.add_button("gtk-cancel", Gtk::RESPONSE_CANCEL);
Gtk::Button ok_button(Gtk::Stock::OK);
Gtk::Button ok_button("gtk-ok");
ok_button.set_can_default(true);
ok_button.show_all();
dialog.add_action_widget(ok_button, Gtk::RESPONSE_OK);
+3 -3
View File
@@ -86,7 +86,7 @@ namespace {
Gtk::Label* label = Gtk::manage(new Gtk::Label());
label->set_markup(label_text);
label->set_padding(6, 0);
label->set_alignment(Gtk::ALIGN_START);
label->set_halign(Gtk::ALIGN_START);
// label->set_ellipsize(Pango::ELLIPSIZE_END);
label->set_selectable(true);
label->set_can_focus(false);
@@ -917,7 +917,7 @@ void GscInfoWindow::fill_ui_general(const std::vector<AtaStorageProperty>& props
Gtk::Label* name = Gtk::manage(new Gtk::Label());
// name->set_ellipsize(Pango::ELLIPSIZE_END);
name->set_alignment(Gtk::ALIGN_END); // right-align
name->set_halign(Gtk::ALIGN_END); // right-align
name->set_selectable(true);
name->set_can_focus(false);
name->set_markup("<b>" + Glib::Markup::escape_text(p.displayable_name) + "</b>");
@@ -927,7 +927,7 @@ void GscInfoWindow::fill_ui_general(const std::vector<AtaStorageProperty>& props
// then it stops being right-aligned.
Gtk::Label* value = Gtk::manage(new Gtk::Label());
// value->set_ellipsize(Pango::ELLIPSIZE_END);
value->set_alignment(Gtk::ALIGN_START); // left-align
value->set_halign(Gtk::ALIGN_START); // left-align
value->set_selectable(true);
value->set_can_focus(false);
value->set_markup(Glib::Markup::escape_text(p.format_value()));
+20 -15
View File
@@ -323,13 +323,16 @@ bool app_init_and_loop(int& argc, char**& argv)
// Note that changing GTK locale after it's inited isn't really supported by GTK,
// but we have no other choice - glib needs system locale when parsing the
// arguments, and gtk is inited while the parsing is performed.
#if GTK_CHECK_VERSION(4, 0, 0)
Glib::set_init_to_users_preferred_locale(args.arg_locale == TRUE);
#else
if (args.arg_locale == FALSE) {
hz::locale_c_set("C");
} else {
// change the C++ locale to match the C one.
hz::locale_cpp_set(""); // this may fail on some systems
}
#endif
if (args.arg_version == TRUE) {
// show version information and exit
@@ -410,23 +413,25 @@ bool app_init_and_loop(int& argc, char**& argv)
| G_LOG_FLAG_RECURSION), glib_message_handler, nullptr);
}
#if !GTK_CHECK_VERSION(4, 0, 0)
// Save the locale
std::locale final_loc_cpp = hz::locale_cpp_get<std::locale>();
#endif
// Initialize GTK+ (it's already initialized by command-line parser,
// so this doesn't do much).
// Initialize GTK+.
// GTKMM 3 Notes (no longer valid as of gtkmm4):
// Newer gtkmm will try to set the C++ locale here.
// Note: passing false (as use_locale) as the third parameter here
// will generate a gtk_disable_setlocale() warning (due to gtk being
// already initialized), so manually save / restore the C++ locale
// (C locale won't be touched).
// Nothing is affected in gtkmm itself by C++ locale, so it's ok to do it.
Gtk::Main m(argc, argv);
auto app = Gtk::Application::create("org.gsmartcontrol.base");
#if !GTK_CHECK_VERSION(4, 0, 0)
// Restore the locale
hz::locale_cpp_set(final_loc_cpp);
#endif
debug_out_info("app", "Current C locale: " << hz::locale_c_get() << "\n");
debug_out_info("app", "Current C++ locale: " << hz::locale_cpp_get<std::string>() << "\n");
@@ -487,14 +492,14 @@ bool app_init_and_loop(int& argc, char**& argv)
if (gtk_settings) {
Glib::ustring theme_name = gtk_settings->property_gtk_theme_name().get_value();
debug_out_dump("app", "Current GTK theme: " << theme_name << "\n");
#ifdef _WIN32
if (IsWindowsServer() || !IsWindows8OrGreater()) {
if (theme_name == "win32") {
debug_out_dump("app", "Windows with Classic theme support detected, switching to Adwaita theme.\n");
gtk_settings->property_gtk_theme_name().set_value("Adwaita");
}
bool windows_is_using_classic_theme = false;
#ifdef _WIN32
is_win8_or_newer = IsWindowsServer() || !IsWindows8OrGreater();
#endif
if (windows_is_using_classic_theme && theme_name == "win32") {
debug_out_dump("app", "Windows with Classic theme support detected, switching to Adwaita theme.\n");
gtk_settings->property_gtk_theme_name().set_value("Adwaita");
}
#endif
}
}
@@ -553,7 +558,7 @@ bool app_init_and_loop(int& argc, char**& argv)
// The Main Loop
debug_out_info("app", "Entering main loop.\n");
Gtk::Main::run();
app->run(argc, argv);
debug_out_info("app", "Main loop exited.\n");
}
@@ -578,7 +583,7 @@ void app_quit()
// exit the main loop
debug_out_info("app", "Trying to exit the main loop...\n");
Gtk::Main::quit();
Gtk::Application::get_default()->quit();
// don't destroy main window here - we may be in one of its callbacks
}
+357 -241
View File
@@ -48,7 +48,7 @@ using namespace std::literals;
GscMainWindow::GscMainWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builder> ui)
: AppBuilderWidget<GscMainWindow, false>(gtkcobj, std::move(ui))
: AppBuilderWidget<GscMainWindow, false, Gtk::ApplicationWindow>(gtkcobj, std::move(ui))
{
// iconview, gtkuimanager stuff (menus), custom labels
create_widgets();
@@ -224,175 +224,287 @@ bool GscMainWindow::create_widgets()
iconview_->set_main_window(this);
// --------------------------------- Action widgets
static Glib::ustring ui_info =
"<menubar name='main_menubar'>"
// --------------------------------- Actions
" <menu action='file_menu'>"
" <menuitem action='" APP_ACTION_NAME(action_quit) "' />"
" </menu>"
actiongroup_main_ = Gio::SimpleActionGroup::create();
actiongroup_device_ = Gio::SimpleActionGroup::create();
" <menu action='device_menu'>"
" <menuitem action='" APP_ACTION_NAME(action_view_details) "' />"
" <separator />"
" <menuitem action='" APP_ACTION_NAME(action_enable_smart) "' />"
" <menuitem action='" APP_ACTION_NAME(action_enable_aodc) "' />"
" <separator />"
" <menuitem action='" APP_ACTION_NAME(action_reread_device_data) "' />"
" <menuitem action='" APP_ACTION_NAME(action_perform_tests) "' />"
" <menuitem action='" APP_ACTION_NAME(action_remove_device) "' />"
" <menuitem action='" APP_ACTION_NAME(action_remove_virtual_device) "' />"
// Create actions:
" <separator />"
" <menuitem action='" APP_ACTION_NAME(action_add_device) "' />"
" <menuitem action='" APP_ACTION_NAME(action_load_virtual) "' />"
" <menuitem action='" APP_ACTION_NAME(action_rescan_devices) "' />"
" </menu>"
actiongroup_main_->add_action("quit",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_quit));
" <menu action='options_menu'>"
" <menuitem action='" APP_ACTION_NAME(action_executor_log) "' />"
" <menuitem action='" APP_ACTION_NAME(action_update_drivedb) "' />"
" <menuitem action='" APP_ACTION_NAME(action_preferences) "' />"
" </menu>"
// FIXME tooltips
" <menu action='help_menu'>"
" <menuitem action='" APP_ACTION_NAME(action_online_documentation) "' />"
" <menuitem action='" APP_ACTION_NAME(action_support) "' />"
" <menuitem action='" APP_ACTION_NAME(action_about) "' />"
" </menu>"
// _("View detailed information")
actiongroup_device_->add_action("view_details",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_view_details));
"</menubar>"
// _("Toggle SMART status. The status will be preserved at least until reboot (unless you toggle it again).")
toggle_enable_smart_action_ = actiongroup_device_->add_action_bool("enable_smart",
sigc::mem_fun(*this, &GscMainWindow::on_action_enable_smart_toggled));
// FIXME
// lookup_widget<Gtk::CheckButton*>("status_smart_enabled_check")->set_related_action(action);
"<popup name='device_popup'>"
" <menuitem action='" APP_ACTION_NAME(action_view_details) "' />"
" <separator />"
" <menuitem action='" APP_ACTION_NAME(action_enable_smart) "' />"
" <menuitem action='" APP_ACTION_NAME(action_enable_aodc) "' />"
" <separator />"
" <menuitem action='" APP_ACTION_NAME(action_reread_device_data) "' />"
" <menuitem action='" APP_ACTION_NAME(action_perform_tests) "' />"
" <menuitem action='" APP_ACTION_NAME(action_remove_device) "' />"
" <menuitem action='" APP_ACTION_NAME(action_remove_virtual_device) "' />"
"</popup>"
// _("Toggle Automatic Offline Data Collection which will update \"offline\" SMART attributes every four hours")
toggle_enable_aodc_action_ = actiongroup_device_->add_action_bool("enable_aodc",
sigc::mem_fun(*this, &GscMainWindow::on_action_enable_aodc_toggled));
// FIXME
// lookup_widget<Gtk::CheckButton*>("status_aodc_enabled_check")->set_related_action(action);
"<popup name='empty_area_popup'>"
" <menuitem action='" APP_ACTION_NAME(action_add_device) "' />"
" <menuitem action='" APP_ACTION_NAME(action_load_virtual) "' />"
" <menuitem action='" APP_ACTION_NAME(action_rescan_devices) "' />"
"</popup>";
// _("Re-read basic SMART data")
actiongroup_device_->add_action("reread_device_data",
sigc::mem_fun(*this, &GscMainWindow::on_action_reread_device_data));
// _("Perform various self-tests on the drive")
actiongroup_device_->add_action("perform_tests",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_perform_tests));
// _("Remove previously added device")
actiongroup_device_->add_action("remove_device",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_remove_device));
// _("Remove previously loaded virtual device")
actiongroup_device_->add_action("remove_virtual_device",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_remove_virtual_device));
// Action groups
actiongroup_main_ = Gtk::ActionGroup::create("main_actions");
actiongroup_device_ = Gtk::ActionGroup::create("device_actions");
// _("Manually add device to device list")
actiongroup_main_->add_action("add_device",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_add_device));
Glib::RefPtr<Gtk::Action> action;
// _("Load smartctl output from a text file as a read-only virtual device")
actiongroup_main_->add_action("load_virtual",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_load_virtual));
// _("Re-scan device list")
actiongroup_main_->add_action("rescan_devices",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_rescan_devices));
// Add actions
actiongroup_main_->add(Gtk::Action::create("file_menu", _("_File")));
actiongroup_main_->add_action("executor_log",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_executor_log));
action = Gtk::Action::create(APP_ACTION_NAME(action_quit), Gtk::Stock::QUIT);
actiongroup_main_->add((action_map_[action_quit] = action), Gtk::AccelKey("<control>Q"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_quit));
actiongroup_main_->add_action("update_drivedb",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_update_drivedb));
actiongroup_main_->add(Gtk::Action::create("device_menu", _("_Device")));
action = Gtk::Action::create(APP_ACTION_NAME(action_view_details), Gtk::Stock::INFO, _("_View details"),
_("View detailed information"));
actiongroup_device_->add((action_map_[action_view_details] = action), Gtk::AccelKey("<control>V"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_view_details));
action = Gtk::ToggleAction::create(APP_ACTION_NAME(action_enable_smart), _("Enable SMART"),
_("Toggle SMART status. The status will be preserved at least until reboot (unless you toggle it again)."));
lookup_widget<Gtk::CheckButton*>("status_smart_enabled_check")->set_related_action(action);
actiongroup_device_->add((action_map_[action_enable_smart] = action), Gtk::AccelKey("<control>M"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_enable_smart));
action = Gtk::ToggleAction::create(APP_ACTION_NAME(action_enable_aodc), _("Enable Auto Offline Data Collection"),
_("Toggle Automatic Offline Data Collection which will update \"offline\" SMART attributes every four hours"));
lookup_widget<Gtk::CheckButton*>("status_aodc_enabled_check")->set_related_action(action);
actiongroup_device_->add((action_map_[action_enable_aodc] = action), Gtk::AccelKey("<control>F"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_enable_aodc));
action = Gtk::Action::create(APP_ACTION_NAME(action_reread_device_data), Gtk::Stock::REFRESH, _("Re-read Data"),
_("Re-read basic SMART data"));
actiongroup_device_->add((action_map_[action_reread_device_data] = action), Gtk::AccelKey("<control>E"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_reread_device_data));
action = Gtk::Action::create(APP_ACTION_NAME(action_perform_tests), _("Perform _Tests..."),
_("Perform various self-tests on the drive"));
actiongroup_device_->add((action_map_[action_perform_tests] = action), Gtk::AccelKey("<control>T"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_perform_tests));
action = Gtk::Action::create(APP_ACTION_NAME(action_remove_device), Gtk::Stock::REMOVE, _("Re_move Added Device"),
_("Remove previously added device"));
actiongroup_device_->add((action_map_[action_remove_device] = action), Gtk::AccelKey("<control>W"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_remove_device));
action = Gtk::Action::create(APP_ACTION_NAME(action_remove_virtual_device), Gtk::Stock::REMOVE, _("Re_move Virtual Device"),
_("Remove previously loaded virtual device"));
actiongroup_device_->add((action_map_[action_remove_virtual_device] = action), Gtk::AccelKey("Delete"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_remove_virtual_device));
// ---
action = Gtk::Action::create(APP_ACTION_NAME(action_add_device), Gtk::Stock::OPEN, _("_Add Device..."),
_("Manually add device to device list"));
actiongroup_main_->add((action_map_[action_add_device] = action), Gtk::AccelKey("<control>D"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_add_device));
action = Gtk::Action::create(APP_ACTION_NAME(action_load_virtual), Gtk::Stock::OPEN, _("_Load Smartctl Output as Virtual Device..."),
_("Load smartctl output from a text file as a read-only virtual device"));
actiongroup_main_->add((action_map_[action_load_virtual] = action), Gtk::AccelKey("<control>O"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_load_virtual));
action = Gtk::Action::create(APP_ACTION_NAME(action_rescan_devices), Gtk::Stock::REFRESH, _("_Re-scan Device List"),
_("Re-scan device list"));
actiongroup_main_->add((action_map_[action_rescan_devices] = action), Gtk::AccelKey("<control>R"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_rescan_devices));
actiongroup_main_->add(Gtk::Action::create("options_menu", _("_Options")));
action = Gtk::Action::create(APP_ACTION_NAME(action_executor_log), _("View Execution Log"));
actiongroup_main_->add((action_map_[action_executor_log] = action),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_executor_log));
action = Gtk::Action::create(APP_ACTION_NAME(action_update_drivedb), _("Update Drive Database"));
actiongroup_main_->add((action_map_[action_update_drivedb] = action),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_update_drivedb));
action = Gtk::Action::create(APP_ACTION_NAME(action_preferences), Gtk::Stock::PREFERENCES);
actiongroup_main_->add((action_map_[action_preferences] = action), Gtk::AccelKey("<alt>P"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_preferences));
actiongroup_main_->add(Gtk::Action::create("help_menu", _("_Help")));
action = Gtk::Action::create(APP_ACTION_NAME(action_online_documentation), Gtk::Stock::HELP);
actiongroup_main_->add((action_map_[action_online_documentation] = action), Gtk::AccelKey("F1"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_online_documentation));
action = Gtk::Action::create(APP_ACTION_NAME(action_support), _("Support"));
actiongroup_main_->add((action_map_[action_support] = action),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_support));
action = Gtk::Action::create(APP_ACTION_NAME(action_about), Gtk::Stock::ABOUT);
actiongroup_main_->add((action_map_[action_about] = action),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_about));
actiongroup_main_->add_action("preferences",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_preferences));
actiongroup_main_->add_action("online_documentation",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_online_documentation));
// create uimanager
ui_manager_ = Gtk::UIManager::create();
ui_manager_->insert_action_group(actiongroup_main_);
ui_manager_->insert_action_group(actiongroup_device_);
actiongroup_main_->add_action("support",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_support));
actiongroup_main_->add_action("about",
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_about));
insert_action_group("main", actiongroup_main_);
insert_action_group("device", actiongroup_device_);
// Lay out the actions in a menubar and context menu
Glib::ustring ui_info =
R"(<interface>
<menu id='main_menubar'>
<submenu>
<attribute name='label' translatable='yes'>_File</attribute>
<section>
<item>
<attribute name='label' translatable='yes'>_Quit</attribute>
<attribute name='action'>main.quit</attribute>
<attribute name='accel'>&lt;Primary&gt;n</attribute>
<attribute name="icon">application-exit</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name='label' translatable='yes'>_Device</attribute>
<section>
<item>
<attribute name='label' translatable='yes'>_View details</attribute>
<attribute name='action'>device.view_details</attribute>
<attribute name='accel'>&lt;Primary&gt;v</attribute>
<attribute name="icon">dialog-information</attribute>
</item>
</section>
<section>
<item>
<attribute name='label' translatable='yes'>Enable SMART</attribute>
<attribute name='action'>device.enable_smart</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Enable Auto Offline Data Collection</attribute>
<attribute name='action'>device.enable_aodc</attribute>
</item>
</section>
<section>
<item>
<attribute name='label' translatable='yes'>Re-read Data</attribute>
<attribute name='action'>device.reread_device_data</attribute>
<attribute name='accel'>&lt;Primary&gt;e</attribute>
<attribute name="icon">view-refresh</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Perform _Tests...</attribute>
<attribute name='action'>device.perform_tests</attribute>
<attribute name='accel'>&lt;Primary&gt;t</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Re_move Added Device</attribute>
<attribute name='action'>device.remove_device</attribute>
<attribute name='accel'>&lt;Primary&gt;w</attribute>
<attribute name="icon">list-remove</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Re_move Virtual Device</attribute>
<attribute name='action'>device.remove_virtual_device</attribute>
<attribute name='accel'>Delete</attribute>
<attribute name="icon">list-remove</attribute>
</item>
</section>
<section>
<item>
<attribute name='label' translatable='yes'>_Add Device...</attribute>
<attribute name='action'>main.add_device</attribute>
<attribute name='accel'>&lt;Primary&gt;d</attribute>
<attribute name="icon">document-open</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>_Load Smartctl Output as Virtual Device...</attribute>
<attribute name='action'>main.load_virtual</attribute>
<attribute name='accel'>&lt;Primary&gt;o</attribute>
<attribute name="icon">document-open</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>_Re-scan Device List</attribute>
<attribute name='action'>main.rescan_devices</attribute>
<attribute name='accel'>&lt;Primary&gt;r</attribute>
<attribute name="icon">view-refresh</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name='label' translatable='yes'>_Options</attribute>
<section>
<item>
<attribute name='label' translatable='yes'>View Execution Log</attribute>
<attribute name='action'>main.executor_log</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Update Drive Database</attribute>
<attribute name='action'>main.update_drivedb</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Preferences</attribute>
<attribute name='action'>main.preferences</attribute>
<attribute name='accel'>&lt;Alt&gt;p</attribute>
<attribute name="icon">preferences-system</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name='label' translatable='yes'>_Help</attribute>
<section>
<item>
<attribute name='label' translatable='yes'>Help</attribute>
<attribute name='action'>main.online_documentation</attribute>
<attribute name='accel'>F1</attribute>
<attribute name="icon">help-browser</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Support</attribute>
<attribute name='action'>main.support</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>About GSmartControl...</attribute>
<attribute name='action'>main.about</attribute>
<attribute name="icon">help-about</attribute>
</item>
</section>
</submenu>
</menu>
<menu id='device_popup'>
<section>
<item>
<attribute name='label' translatable='yes'>_View details</attribute>
<attribute name='action'>device.view_details</attribute>
<attribute name='accel'>&lt;Primary&gt;v</attribute>
<attribute name="icon">dialog-information</attribute>
</item>
</section>
<section>
<item>
<attribute name='label' translatable='yes'>Enable SMART</attribute>
<attribute name='action'>device.enable_smart</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Enable Auto Offline Data Collection</attribute>
<attribute name='action'>device.enable_aodc</attribute>
</item>
</section>
<section>
<item>
<attribute name='label' translatable='yes'>Re-read Data</attribute>
<attribute name='action'>device.reread_device_data</attribute>
<attribute name='accel'>&lt;Primary&gt;e</attribute>
<attribute name="icon">view-refresh</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Perform _Tests...</attribute>
<attribute name='action'>device.perform_tests</attribute>
<attribute name='accel'>&lt;Primary&gt;t</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Re_move Added Device</attribute>
<attribute name='action'>device.remove_device</attribute>
<attribute name='accel'>&lt;Primary&gt;w</attribute>
<attribute name="icon">list-remove</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>Re_move Virtual Device</attribute>
<attribute name='action'>device.remove_virtual_device</attribute>
<attribute name='accel'>Delete</attribute>
<attribute name="icon">list-remove</attribute>
</item>
</section>
<section>
<item>
<attribute name='label' translatable='yes'>_Add Device...</attribute>
<attribute name='action'>main.add_device</attribute>
<attribute name='accel'>&lt;Primary&gt;d</attribute>
<attribute name="icon">document-open</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>_Load Smartctl Output as Virtual Device...</attribute>
<attribute name='action'>main.load_virtual</attribute>
<attribute name='accel'>&lt;Primary&gt;o</attribute>
<attribute name="icon">document-open</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>_Re-scan Device List</attribute>
<attribute name='action'>main.rescan_devices</attribute>
<attribute name='accel'>&lt;Primary&gt;r</attribute>
<attribute name="icon">view-refresh</attribute>
</item>
</section>
</menu>
</interface>
)";
ui_builder_ = Gtk::Builder::create();
// add accelerator group to our window so that they work
add_accel_group(ui_manager_->get_accel_group());
// FIXME
// add_accel_group(ui_builder_->get_accel_group());
try {
ui_manager_->add_ui_from_string(ui_info);
ui_builder_->add_from_string(ui_info);
}
catch(Glib::Error& ex)
{
@@ -401,36 +513,39 @@ bool GscMainWindow::create_widgets()
}
// FIXME
// add some more accelerators (in addition to existing ones)
Gtk::Widget* rescan_item = ui_manager_->get_widget("/main_menubar/device_menu/" APP_ACTION_NAME(action_rescan_devices));
if (rescan_item)
rescan_item->add_accelerator("activate", get_accel_group(), GDK_KEY_F5, Gdk::ModifierType(0), Gtk::AccelFlags(0));
// Gtk::Widget* rescan_item = ui_builder_->get_widget("/main_menubar/device_menu/" APP_ACTION_NAME(action_rescan_devices));
// if (rescan_item)
// rescan_item->add_accelerator("activate", get_accel_group(), GDK_KEY_F5, Gdk::ModifierType(0), Gtk::AccelFlags(0));
// look after the created widgets
auto* menubar_vbox = lookup_widget<Gtk::Box*>("menubar_vbox");
Gtk::Widget* menubar = ui_manager_->get_widget("/main_menubar");
if (menubar_vbox && menubar) {
menubar_vbox->pack_start(*menubar, Gtk::PACK_EXPAND_WIDGET);
menubar->set_hexpand(true);
// FIXME
// auto* menubar_vbox = lookup_widget<Gtk::Box*>("menubar_vbox");
// Gtk::Widget* menubar = ui_builder_->get_widget("/main_menubar");
// if (menubar_vbox && menubar) {
// menubar_vbox->pack_start(*menubar, Gtk::PACK_EXPAND_WIDGET);
// menubar->set_hexpand(true);
// menubar->set_halign(Gtk::ALIGN_START);
}
// }
// Set tooltips on menu items - gtk does that only on toolbar items.
Glib::ustring tooltip_text;
std::vector<Glib::RefPtr<Gtk::ActionGroup> > groups = ui_manager_->get_action_groups();
for (auto& group : groups) {
std::vector<Glib::RefPtr<Gtk::Action> > actions = group->get_actions();
for (auto& group_action : actions) {
std::vector<Gtk::Widget*> widgets = group_action->get_proxies();
if (!(tooltip_text = group_action->property_tooltip()).empty()) {
for (auto& widget : widgets) {
app_gtkmm_set_widget_tooltip(*widget, tooltip_text, true);
}
}
}
}
// FIXME
// Glib::ustring tooltip_text;
// std::vector<Glib::RefPtr<Gtk::ActionGroup> > groups = ui_builder_->get_action_groups();
// for (auto& group : groups) {
// std::vector<Glib::RefPtr<Gtk::Action> > actions = group->get_actions();
// for (auto& group_action : actions) {
// std::vector<Gtk::Widget*> widgets = group_action->get_proxies();
// if (!(tooltip_text = group_action->property_tooltip()).empty()) {
// for (auto& widget : widgets) {
// app_gtkmm_set_widget_tooltip(*widget, tooltip_text, true);
// }
// }
// }
// }
// ----------------------------------------- Labels
@@ -497,7 +612,7 @@ void GscMainWindow::on_action_activated(GscMainWindow::action_t action_type)
return;
}
Glib::RefPtr<Gtk::Action> action = action_map_[action_type];
Glib::RefPtr<Gio::Action> action = action_map_[action_type];
if (!action) {
debug_out_error("app", DBG_FUNC_MSG << "Action is NULL for action type " << static_cast<int>(action_type) << ".\n");
return;
@@ -520,16 +635,6 @@ void GscMainWindow::on_action_activated(GscMainWindow::action_t action_type)
this->show_device_info_window(iconview_->get_selected_drive());
break;
case action_enable_smart: // this may be invoked on menu manipulation
on_action_enable_smart_toggled(dynamic_cast<Gtk::ToggleAction*>(
actiongroup_device_->get_action(APP_ACTION_NAME(action_enable_smart)).operator->()));
break;
case action_enable_aodc: // this may be invoked on menu manipulation
on_action_enable_aodc_toggled(dynamic_cast<Gtk::ToggleAction*>(
actiongroup_device_->get_action(APP_ACTION_NAME(action_enable_aodc)).operator->()));
break;
case action_reread_device_data:
on_action_reread_device_data();
break;
@@ -598,13 +703,13 @@ void GscMainWindow::on_action_activated(GscMainWindow::action_t action_type)
case action_online_documentation:
{
hz::launch_url(gobj(), "https://gsmartcontrol.sourceforge.io/documentation.html");
hz::launch_url(Gtk::Window::gobj(), "https://gsmartcontrol.sourceforge.io/documentation.html");
break;
}
case action_support:
{
hz::launch_url(gobj(), "https://gsmartcontrol.sourceforge.io/support.html");
hz::launch_url(Gtk::Window::gobj(), "https://gsmartcontrol.sourceforge.io/support.html");
break;
}
@@ -624,11 +729,9 @@ void GscMainWindow::on_action_activated(GscMainWindow::action_t action_type)
void GscMainWindow::on_action_enable_smart_toggled(Gtk::ToggleAction* action)
void GscMainWindow::on_action_enable_smart_toggled()
{
if (!action || !iconview_)
return;
if (!action->get_sensitive()) // it's insensitive, nothing to do (this shouldn't happen).
if (!iconview_)
return;
StorageDevicePtr drive = iconview_->get_selected_drive();
@@ -641,7 +744,8 @@ void GscMainWindow::on_action_enable_smart_toggled(Gtk::ToggleAction* action)
if (status == StorageDevice::Status::unsupported) // this shouldn't happen
return;
bool toggle_active = action->get_active();
bool toggle_active = false;
toggle_enable_smart_action_->get_state(toggle_active);
if ( (toggle_active && status == StorageDevice::Status::disabled)
|| (!toggle_active && status == StorageDevice::Status::enabled) ) {
@@ -662,11 +766,9 @@ void GscMainWindow::on_action_enable_smart_toggled(Gtk::ToggleAction* action)
void GscMainWindow::on_action_enable_aodc_toggled(Gtk::ToggleAction* action)
void GscMainWindow::on_action_enable_aodc_toggled()
{
if (!action || !iconview_)
return;
if (!action->get_sensitive()) // it's insensitive, nothing to do (this shouldn't happen).
if (!iconview_)
return;
StorageDevicePtr drive = iconview_->get_selected_drive();
@@ -689,17 +791,20 @@ void GscMainWindow::on_action_enable_aodc_toggled(Gtk::ToggleAction* action)
true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE, true); // markup, modal
Gtk::Button dismiss_button(_("Dis_miss"), true);
dismiss_button.set_image(*Gtk::manage(new Gtk::Image(Gtk::Stock::CANCEL, Gtk::ICON_SIZE_BUTTON)));
// FIXME
// dismiss_button.set_image(*Gtk::manage(new Gtk::Image("gtk-cancel", Gtk::ICON_SIZE_BUTTON)));
dismiss_button.show_all();
dialog.add_action_widget(dismiss_button, Gtk::RESPONSE_CANCEL);
Gtk::Button disable_button(_("_Disable"), true);
disable_button.set_image(*Gtk::manage(new Gtk::Image(Gtk::Stock::NO, Gtk::ICON_SIZE_BUTTON)));
// FIXME
// disable_button.set_image(*Gtk::manage(new Gtk::Image("gtk-no", Gtk::ICON_SIZE_BUTTON)));
disable_button.show_all();
dialog.add_action_widget(disable_button, Gtk::RESPONSE_NO);
Gtk::Button enable_button(_("_Enable"), true);
enable_button.set_image(*Gtk::manage(new Gtk::Image(Gtk::Stock::YES, Gtk::ICON_SIZE_BUTTON)));
// FIXME
// enable_button.set_image(*Gtk::manage(new Gtk::Image("gtk-yes", Gtk::ICON_SIZE_BUTTON)));
enable_button.set_can_default(true);
enable_button.show_all();
dialog.add_action_widget(enable_button, Gtk::RESPONSE_YES);
@@ -746,7 +851,8 @@ void GscMainWindow::on_action_enable_aodc_toggled(Gtk::ToggleAction* action)
}
bool toggle_active = action->get_active();
bool toggle_active = false;
toggle_enable_aodc_action_->get_state(toggle_active);
if ( (toggle_active && status == StorageDevice::Status::disabled)
|| (!toggle_active && status == StorageDevice::Status::enabled) ) {
@@ -791,14 +897,19 @@ void GscMainWindow::on_action_reread_device_data()
Gtk::Menu* GscMainWindow::get_popup_menu(const StorageDevicePtr& drive)
std::unique_ptr<Gtk::Menu> GscMainWindow::get_popup_menu(const StorageDevicePtr& drive)
{
if (!ui_manager_)
if (!ui_builder_)
return nullptr;
Gtk::Menu* menu = nullptr;
if (drive) {
return dynamic_cast<Gtk::Menu*>(ui_manager_->get_widget("/device_popup"));
ui_builder_->get_widget("/device_popup", menu);
} else {
ui_builder_->get_widget("/empty_area_popup", menu);
}
return dynamic_cast<Gtk::Menu*>(ui_manager_->get_widget("/empty_area_popup"));
std::unique_ptr<Gtk::Menu> umenu(menu);
return umenu;
}
@@ -813,12 +924,20 @@ void GscMainWindow::set_drive_menu_status(const StorageDevicePtr& drive)
// if no drive is selected or if a test is being run on selected drive, disallow.
if (!drive || drive->get_test_is_active()) {
actiongroup_device_->set_sensitive(false);
for (const auto& action_name : actiongroup_device_->list_actions()) {
if (auto action = Glib::RefPtr<Gio::SimpleAction>::cast_dynamic(actiongroup_device_->lookup_action(action_name))) {
action->set_enabled(false);
}
}
break; // nothing else to do here
}
// make everything sensitive, then disable one by one
actiongroup_device_->set_sensitive(true);
for (const auto& action_name : actiongroup_device_->list_actions()) {
if (auto action = Glib::RefPtr<Gio::SimpleAction>::cast_dynamic(actiongroup_device_->lookup_action(action_name))) {
action->set_enabled(true);
}
}
bool is_virtual = (drive && drive->get_is_virtual());
@@ -834,59 +953,54 @@ void GscMainWindow::set_drive_menu_status(const StorageDevicePtr& drive)
// Sensitivity and visibility manipulation.
// Do this first, then do the enable / disable stuff.
{
Glib::RefPtr<Gtk::Action> action;
if (auto action = Glib::RefPtr<Gio::SimpleAction>::cast_dynamic(actiongroup_device_->lookup_action("perform_tests"))) {
action->set_enabled(smart_status == StorageDevice::Status::enabled);
}
// TODO
// if ((action = actiongroup_device_->get_action(APP_ACTION_NAME(action_reread_device_data))))
// action->set_visible(drive && !is_virtual);
// if ((action = actiongroup_device_->get_action(APP_ACTION_NAME(action_remove_device)))) {
// action->set_visible(drive && drive->get_is_manually_added());
// if ((action = actiongroup_device_->get_action(APP_ACTION_NAME(action_remove_virtual_device))))
// action->set_visible(drive && is_virtual);
if ((action = actiongroup_device_->get_action(APP_ACTION_NAME(action_perform_tests))))
action->set_sensitive(smart_status == StorageDevice::Status::enabled);
if ((action = actiongroup_device_->get_action(APP_ACTION_NAME(action_reread_device_data))))
action->set_visible(drive && !is_virtual);
if ((action = actiongroup_device_->get_action(APP_ACTION_NAME(action_remove_device)))) {
action->set_visible(drive && drive->get_is_manually_added());
// action->set_sensitive(drive && drive->get_is_manually_added());
if (auto action = Glib::RefPtr<Gio::SimpleAction>::cast_dynamic(actiongroup_device_->lookup_action("enable_smart"))) {
action->set_enabled(smart_status != StorageDevice::Status::unsupported);
}
if ((action = actiongroup_device_->get_action(APP_ACTION_NAME(action_remove_virtual_device))))
action->set_visible(drive && is_virtual);
if ((action = actiongroup_device_->get_action(APP_ACTION_NAME(action_enable_smart)))) {
action->set_sensitive(smart_status != StorageDevice::Status::unsupported);
if (auto action = Glib::RefPtr<Gio::SimpleAction>::cast_dynamic(actiongroup_device_->lookup_action("enable_aodc"))) {
action->set_enabled(aodc_status != StorageDevice::Status::unsupported);
}
if ((action = actiongroup_device_->get_action(APP_ACTION_NAME(action_enable_aodc))))
action->set_sensitive(aodc_status != StorageDevice::Status::unsupported);
}
// smart toggle status
{
Gtk::ToggleAction* action = dynamic_cast<Gtk::ToggleAction*>(
actiongroup_device_->get_action(APP_ACTION_NAME(action_enable_smart)).operator->());
if (action) {
action->set_active(smart_status == StorageDevice::Status::enabled);
}
if (auto action = Glib::RefPtr<Gio::SimpleAction>::cast_dynamic(actiongroup_device_->lookup_action("enable_smart"))) {
action->change_state(smart_status == StorageDevice::Status::enabled);
}
// aodc toggle status
{
Gtk::ToggleAction* action = dynamic_cast<Gtk::ToggleAction*>(
actiongroup_device_->get_action(APP_ACTION_NAME(action_enable_aodc)).operator->());
if (auto action = Glib::RefPtr<Gio::SimpleAction>::cast_dynamic(actiongroup_device_->lookup_action("enable_smart"))) {
action->change_state(smart_status == StorageDevice::Status::enabled);
if (action) {
Gtk::CheckMenuItem* dev_odc_item = dynamic_cast<Gtk::CheckMenuItem*>(ui_manager_->get_widget(
"/main_menubar/device_menu/" APP_ACTION_NAME(action_enable_aodc)));
Gtk::CheckMenuItem* popup_odc_item = dynamic_cast<Gtk::CheckMenuItem*>(ui_manager_->get_widget(
"/device_popup/" APP_ACTION_NAME(action_enable_aodc)));
auto* status_aodc_check = lookup_widget<Gtk::CheckButton*>("status_aodc_enabled_check");
Gtk::CheckMenuItem* dev_odc_item = nullptr;
ui_builder_->get_widget("/main_menubar/device_menu/" APP_ACTION_NAME(action_enable_aodc), dev_odc_item);
// true if supported, but unknown whether it's enabled or not.
if (dev_odc_item)
dev_odc_item->set_inconsistent(aodc_status == StorageDevice::Status::unknown);
if (popup_odc_item)
popup_odc_item->set_inconsistent(aodc_status == StorageDevice::Status::unknown);
if (status_aodc_check)
status_aodc_check->set_inconsistent(aodc_status == StorageDevice::Status::unknown);
Gtk::CheckMenuItem* popup_odc_item = nullptr;
ui_builder_->get_widget("/device_popup/" APP_ACTION_NAME(action_enable_aodc), dev_odc_item);
// for unknown it doesn't really matter what state it's in.
action->set_active(aodc_status == StorageDevice::Status::enabled);
}
auto* status_aodc_check = lookup_widget<Gtk::CheckButton*>("status_aodc_enabled_check");
// true if supported, but unknown whether it's enabled or not.
if (dev_odc_item)
dev_odc_item->set_inconsistent(aodc_status == StorageDevice::Status::unknown);
if (popup_odc_item)
popup_odc_item->set_inconsistent(aodc_status == StorageDevice::Status::unknown);
if (status_aodc_check)
status_aodc_check->set_inconsistent(aodc_status == StorageDevice::Status::unknown);
// for unknown it doesn't really matter what state it's in.
action->change_state(aodc_status == StorageDevice::Status::enabled);
}
} while (false);
@@ -1303,8 +1417,10 @@ void GscMainWindow::show_load_virtual_file_chooser()
all_filter->add_pattern("*");
#if GTK_CHECK_VERSION(3, 20, 0)
std::unique_ptr<GtkFileChooserNative, decltype(&g_object_unref)> dialog(gtk_file_chooser_native_new(
_("Load Data From..."), this->gobj(), GTK_FILE_CHOOSER_ACTION_OPEN, nullptr, nullptr),
std::unique_ptr<GtkFileChooserNative, decltype(&g_object_unref)> dialog(
gtk_file_chooser_native_new(
_("Load Data From..."), Gtk::Window::gobj(),
GTK_FILE_CHOOSER_ACTION_OPEN, nullptr, nullptr),
&g_object_unref);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog.get()), specific_filter->gobj());
+12 -8
View File
@@ -13,6 +13,7 @@ Copyright:
#define GSC_MAIN_WINDOW_H
#include <map>
#include <memory>
#include <gtkmm.h>
#include "applib/app_builder_widget.h"
@@ -28,7 +29,7 @@ class GscInfoWindow; // declared in gsc_info_window.h
/// The main window.
/// Use create() / destroy() with this class instead of new / delete!
class GscMainWindow : public AppBuilderWidget<GscMainWindow, false> {
class GscMainWindow : public AppBuilderWidget<GscMainWindow, false, Gtk::ApplicationWindow> {
public:
friend class GscMainWindowIconView; // It needs our privates
@@ -102,7 +103,7 @@ class GscMainWindow : public AppBuilderWidget<GscMainWindow, false> {
void set_drive_menu_status(const StorageDevicePtr& drive);
/// Get popup menu for a drive
Gtk::Menu* get_popup_menu(const StorageDevicePtr& drive);
std::unique_ptr<Gtk::Menu> get_popup_menu(const StorageDevicePtr& drive);
/// Update status widgets (status area, etc...)
void update_status_widgets();
@@ -144,10 +145,10 @@ class GscMainWindow : public AppBuilderWidget<GscMainWindow, false> {
void on_action_activated(action_t action_type);
/// Action callback
void on_action_enable_smart_toggled(Gtk::ToggleAction* action);
void on_action_enable_smart_toggled();
/// Action callback
void on_action_enable_aodc_toggled(Gtk::ToggleAction* action);
void on_action_enable_aodc_toggled();
/// Action callback
void on_action_reread_device_data();
@@ -158,11 +159,14 @@ class GscMainWindow : public AppBuilderWidget<GscMainWindow, false> {
GscMainWindowIconView* iconview_ = nullptr; ///< The main icon view
std::vector<StorageDevicePtr> drives_; ///< Scanned drives
Glib::RefPtr<Gtk::UIManager> ui_manager_; ///< UI manager
Glib::RefPtr<Gtk::ActionGroup> actiongroup_main_; ///< Action group
Glib::RefPtr<Gtk::ActionGroup> actiongroup_device_; ///< Action group
Glib::RefPtr<Gtk::Builder> ui_builder_; ///< UI builder
Glib::RefPtr<Gio::SimpleActionGroup> actiongroup_main_; ///< Action group
Glib::RefPtr<Gio::SimpleActionGroup> actiongroup_device_; ///< Action group
bool action_handling_enabled_ = true; ///< Whether action handling is enabled or not
std::map<action_t, Glib::RefPtr<Gtk::Action> > action_map_; ///< Used by on_action_activated().
std::map<action_t, Glib::RefPtr<Gio::Action> > action_map_; ///< Used by on_action_activated().
Glib::RefPtr<Gio::SimpleAction> toggle_enable_smart_action_;
Glib::RefPtr<Gio::SimpleAction> toggle_enable_aodc_action_;
Gtk::Label* name_label_ = nullptr; ///< A UI label
Gtk::Label* health_label_ = nullptr; ///< A UI label
+8 -4
View File
@@ -18,6 +18,7 @@ Copyright:
#include <cmath> // std::floor
#include <unordered_map>
#include <cairomm/cairomm.h>
#include <memory>
#include "hz/string_algo.h" // string_join
#include "hz/debug.h"
@@ -429,7 +430,8 @@ class GscMainWindowIconView : public Gtk::IconView {
Gdk::Rectangle rect = this->get_allocation();
Glib::RefPtr<Gdk::Window> win = this->get_window();
win->invalidate_rect(rect, true); // force expose event
win->process_updates(false); // update immediately
// FIXME
// win->process_updates(false); // update immediately
}
}
@@ -543,9 +545,9 @@ class GscMainWindowIconView : public Gtk::IconView {
this->unselect_all(); // unselect on empty area right-click
}
Gtk::Menu* menu = main_window->get_popup_menu(drive);
if (menu)
menu->popup(event_button->button, event_button->time);
current_popup_ = main_window->get_popup_menu(drive);
if (current_popup_)
current_popup_->popup_at_pointer(reinterpret_cast<const GdkEvent *>(event_button));
return true; // stop handling
}
@@ -584,6 +586,8 @@ class GscMainWindowIconView : public Gtk::IconView {
Glib::RefPtr<Gdk::Pixbuf> hd_icon; ///< Icon pixbuf
Glib::RefPtr<Gdk::Pixbuf> cddvd_icon; ///< Icon pixbuf
std::unique_ptr<Gtk::Menu> current_popup_; ///< Currently popped up menu
GscMainWindow* main_window = nullptr; ///< The main window, our parent
Message empty_view_message = Message::none; ///< Message type to display when not showing any icons
+7 -21
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1
Copyright (C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
Copyright (C) 2008 - 2022 Alexander Shaduri <ashaduri@gmail.com>
This file is part of GSmartControl.
@@ -23,13 +23,13 @@ along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
<requires lib="gtk+" version="3.20"/>
<!-- interface-license-type gplv3 -->
<!-- interface-name GSmartControl -->
<!-- interface-copyright 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com> -->
<object class="GtkWindow" id="gsc_main_window">
<!-- interface-copyright 2008 - 2022 Alexander Shaduri <ashaduri@gmail.com> -->
<object class="GtkApplicationWindow" id="gsc_main_window">
<property name="can_focus">False</property>
<property name="title" translatable="yes">GSmartControl</property>
<property name="default_width">560</property>
<property name="default_height">450</property>
<child>
<child type="titlebar">
<placeholder/>
</child>
<child>
@@ -37,20 +37,6 @@ along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox" id="menubar_vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
@@ -150,7 +136,7 @@ along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">0</property>
</packing>
</child>
<child>
@@ -177,7 +163,7 @@ along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">1</property>
</packing>
</child>
<child>
@@ -222,7 +208,7 @@ along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
<property name="position">2</property>
</packing>
</child>
</object>