transmission/gtk/Actions.cc

317 lines
11 KiB
C++
Raw Normal View History

/*
* This file Copyright (C) 2007-2021 Mnemosyne LLC
*
* It may be used under the GNU GPL versions 2 or 3
* or any future license endorsed by Mnemosyne LLC.
*
*/
#include <string>
#include <string.h>
#include <unordered_map>
#include <glibmm.h>
#include <glibmm/i18n.h>
#include <libtransmission/transmission.h>
#include "Actions.h"
#include "Prefs.h"
#include "PrefsDialog.h"
#include "Session.h"
#include "Utils.h"
namespace
{
Session* myCore = nullptr;
void action_cb(Glib::RefPtr<Gtk::Action> const& a, void* user_data)
{
gtr_actions_handler(a->get_name(), user_data);
}
struct ActionEntryBase
{
char const* name;
char const* stock_id;
char const* label;
char const* accelerator;
char const* tooltip;
};
ActionEntryBase sort_radio_entries[] = {
{ "sort-by-activity", nullptr, N_("Sort by _Activity"), nullptr, nullptr },
{ "sort-by-name", nullptr, N_("Sort by _Name"), nullptr, nullptr },
{ "sort-by-progress", nullptr, N_("Sort by _Progress"), nullptr, nullptr },
{ "sort-by-queue", nullptr, N_("Sort by _Queue"), nullptr, nullptr },
{ "sort-by-ratio", nullptr, N_("Sort by Rati_o"), nullptr, nullptr },
{ "sort-by-state", nullptr, N_("Sort by Stat_e"), nullptr, nullptr },
{ "sort-by-age", nullptr, N_("Sort by A_ge"), nullptr, nullptr },
{ "sort-by-time-left", nullptr, N_("Sort by Time _Left"), nullptr, nullptr },
{ "sort-by-size", nullptr, N_("Sort by Si_ze"), nullptr, nullptr },
};
void sort_changed_cb(Glib::RefPtr<Gtk::RadioAction> const& action, void* /*user_data*/)
{
if (!action->get_active())
{
return;
}
myCore->set_pref(TR_KEY_sort_mode, action->get_name());
}
struct : ActionEntryBase
{
bool is_active;
} show_toggle_entries[] = {
{ "toggle-main-window", nullptr, N_("_Show Transmission"), nullptr, nullptr, true },
{ "toggle-message-log", nullptr, N_("Message _Log"), nullptr, nullptr, false },
};
void toggle_pref_cb(Glib::RefPtr<Gtk::ToggleAction> const& action, void* /*user_data*/)
2007-12-19 18:42:33 +00:00
{
auto const key = action->get_name();
bool const val = action->get_active();
myCore->set_pref(tr_quark_new({ key.c_str(), key.size() }), val);
2007-12-19 18:42:33 +00:00
}
struct : ActionEntryBase
{
bool is_active;
} pref_toggle_entries[] = {
{ "alt-speed-enabled", nullptr, N_("Enable Alternative Speed _Limits"), nullptr, nullptr, false },
{ "compact-view", nullptr, N_("_Compact View"), "<alt>C", nullptr, false },
{ "sort-reversed", nullptr, N_("Re_verse Sort Order"), nullptr, nullptr, false },
{ "show-filterbar", nullptr, N_("_Filterbar"), nullptr, nullptr, false },
{ "show-statusbar", nullptr, N_("_Statusbar"), nullptr, nullptr, false },
{ "show-toolbar", nullptr, N_("_Toolbar"), nullptr, nullptr, false },
};
struct : ActionEntryBase
{
bool is_actionable;
} entries[] = {
{ "file-menu", nullptr, N_("_File"), nullptr, nullptr, false },
{ "torrent-menu", nullptr, N_("_Torrent"), nullptr, nullptr, false },
{ "view-menu", nullptr, N_("_View"), nullptr, nullptr, false },
{ "sort-menu", nullptr, N_("_Sort Torrents By"), nullptr, nullptr, false },
{ "queue-menu", nullptr, N_("_Queue"), nullptr, nullptr, false },
{ "edit-menu", nullptr, N_("_Edit"), nullptr, nullptr, false },
{ "help-menu", nullptr, N_("_Help"), nullptr, nullptr, false },
{ "copy-magnet-link-to-clipboard", "edit-copy", N_("Copy _Magnet Link to Clipboard"), "", nullptr, true },
{ "open-torrent-from-url", "document-open", N_("Open _URL…"), "<control>U", N_("Open URL…"), true },
{ "open-torrent-toolbar", "document-open", N_("_Open"), nullptr, N_("Open a torrent"), true },
{ "open-torrent-menu", "document-open", N_("_Open"), nullptr, N_("Open a torrent"), true },
{ "torrent-start", "media-playback-start", N_("_Start"), "<control>S", N_("Start torrent"), true },
{ "torrent-start-now", "media-playback-start", N_("Start _Now"), "<shift><control>S", N_("Start torrent now"), true },
{ "show-stats", nullptr, N_("_Statistics"), nullptr, nullptr, true },
{ "donate", nullptr, N_("_Donate"), nullptr, nullptr, true },
{ "torrent-verify", nullptr, N_("_Verify Local Data"), "<control>V", nullptr, true },
{ "torrent-stop", "media-playback-pause", N_("_Pause"), "<control>P", N_("Pause torrent"), true },
{ "pause-all-torrents", "media-playback-pause", N_("_Pause All"), nullptr, N_("Pause all torrents"), true },
{ "start-all-torrents", "media-playback-start", N_("_Start All"), nullptr, N_("Start all torrents"), true },
{ "relocate-torrent", nullptr, N_("Set _Location…"), nullptr, nullptr, true },
{ "remove-torrent", "list-remove", N_("Remove torrent"), "Delete", nullptr, true },
{ "delete-torrent", "edit-delete", N_("_Delete Files and Remove"), "<shift>Delete", nullptr, true },
{ "new-torrent", "document-new", N_("_New…"), nullptr, N_("Create a torrent"), true },
{ "quit", "application-exit", N_("_Quit"), nullptr, nullptr, true },
{ "select-all", "edit-select-all", N_("Select _All"), "<control>A", nullptr, true },
{ "deselect-all", nullptr, N_("Dese_lect All"), "<shift><control>A", nullptr, true },
{ "edit-preferences", "preferences-system", N_("_Preferences"), nullptr, nullptr, true },
{ "show-torrent-properties", "document-properties", N_("_Properties"), "<alt>Return", N_("Torrent properties"), true },
{ "open-torrent-folder", "document-open", N_("Open Fold_er"), "<control>E", nullptr, true },
{ "show-about-dialog", "help-about", N_("_About"), nullptr, nullptr, true },
{ "help", "help-browser", N_("_Contents"), "F1", nullptr, true },
{ "torrent-reannounce", "network-workgroup", N_("Ask Tracker for _More Peers"), nullptr, nullptr, true },
{ "queue-move-top", "go-top", N_("Move to _Top"), nullptr, nullptr, true },
{ "queue-move-up", "go-up", N_("Move _Up"), "<control>Up", nullptr, true },
{ "queue-move-down", "go-down", N_("Move _Down"), "<control>Down", nullptr, true },
{ "queue-move-bottom", "go-bottom", N_("Move to _Bottom"), nullptr, nullptr, true },
{ "present-main-window", nullptr, N_("Present Main Window"), nullptr, nullptr, true },
};
struct BuiltinIconInfo
{
char const* filename;
char const* name;
};
BuiltinIconInfo const my_fallback_icons[] = {
{ "logo-48", WINDOW_ICON }, //
{ "logo-24", TRAY_ICON }, //
{ "logo-48", NOTIFICATION_ICON }, //
{ "lock", "transmission-lock" }, //
{ "utilities", "utilities" }, //
{ "turtle-blue", "alt-speed-on" }, //
{ "turtle-grey", "alt-speed-off" }, //
{ "ratio", "ratio" }, //
};
void register_my_icons()
{
auto const theme = Gtk::IconTheme::get_default();
auto const factory = Gtk::IconFactory::create();
factory->add_default();
for (auto const& icon : my_fallback_icons)
{
if (!theme->has_icon(icon.name))
{
auto const p = Gdk::Pixbuf::create_from_resource(gtr_sprintf(TR_RESOURCE_PATH "icons/%s.png", icon.filename));
if (p != nullptr)
{
Gtk::IconTheme::add_builtin_icon(icon.name, p->get_width(), p);
factory->add(Gtk::StockID(icon.name), Gtk::IconSet::create(p));
}
}
}
}
Gtk::UIManager* myUIManager = nullptr;
} // namespace
void gtr_actions_set_core(Glib::RefPtr<Session> const& core)
2007-12-19 18:42:33 +00:00
{
myCore = gtr_get_ptr(core);
2007-12-19 18:42:33 +00:00
}
void gtr_actions_init(Glib::RefPtr<Gtk::UIManager> const& ui_manager, void* callback_user_data)
{
myUIManager = gtr_get_ptr(ui_manager);
register_my_icons();
auto const action_group = Gtk::ActionGroup::create("Actions");
auto const match = gtr_pref_string_get(TR_KEY_sort_mode);
Gtk::RadioAction::Group sort_group;
for (auto const& entry : sort_radio_entries)
{
auto const action = Gtk::RadioAction::create(sort_group, entry.name, _(entry.label));
if (entry.name == match)
{
action->set_active(true);
}
action_group->add(action, [action, callback_user_data]() { sort_changed_cb(action, callback_user_data); });
}
for (auto const& entry : show_toggle_entries)
{
auto const action = Gtk::ToggleAction::create(entry.name, _(entry.label), {}, entry.is_active);
action_group->add(action, [action, callback_user_data]() { action_cb(action, callback_user_data); });
}
for (auto& entry : pref_toggle_entries)
{
entry.is_active = gtr_pref_flag_get(tr_quark_new(entry.name));
}
for (auto const& entry : pref_toggle_entries)
{
auto const action = Gtk::ToggleAction::create(entry.name, _(entry.label), {}, entry.is_active);
action->signal_activate().connect([action, callback_user_data]() { toggle_pref_cb(action, callback_user_data); });
if (entry.accelerator != nullptr)
{
action_group->add(action, Gtk::AccelKey(entry.accelerator));
}
else
{
action_group->add(action);
}
}
for (auto const& entry : entries)
{
auto const action = Gtk::Action::create(
entry.name,
entry.stock_id != nullptr ? Gtk::StockID(entry.stock_id) : Gtk::StockID(),
_(entry.label),
entry.tooltip != nullptr ? _(entry.tooltip) : Glib::ustring());
if (entry.stock_id != nullptr && Gtk::IconTheme::get_default()->has_icon(entry.stock_id))
{
action->set_icon_name(entry.stock_id);
}
if (entry.is_actionable)
{
action->signal_activate().connect([action, callback_user_data]() { action_cb(action, callback_user_data); });
}
if (entry.accelerator != nullptr)
{
action_group->add(action, Gtk::AccelKey(entry.accelerator));
}
else
{
action_group->add(action);
}
}
ui_manager->insert_action_group(action_group, 0);
}
/****
*****
****/
namespace
{
std::unordered_map<Glib::ustring, Glib::RefPtr<Gtk::Action>> key_to_action;
void ensure_action_map_loaded(Gtk::UIManager& uim)
{
if (!key_to_action.empty())
{
return;
}
for (auto const& action_group : uim.get_action_groups())
{
for (auto const& action : action_group->get_actions())
{
key_to_action.emplace(action->get_name(), action);
}
}
}
Glib::RefPtr<Gtk::Action> get_action(Glib::ustring const& name)
{
ensure_action_map_loaded(*myUIManager);
return key_to_action.at(name);
}
} // namespace
void gtr_action_activate(Glib::ustring const& name)
{
get_action(name)->activate();
}
void gtr_action_set_sensitive(Glib::ustring const& name, bool b)
{
get_action(name)->set_sensitive(b);
}
void gtr_action_set_important(Glib::ustring const& name, bool b)
{
get_action(name)->set_is_important(b);
}
void gtr_action_set_toggled(Glib::ustring const& name, bool b)
{
dynamic_cast<Gtk::ToggleAction*>(gtr_get_ptr(get_action(name)))->set_active(b);
}
Gtk::Widget* gtr_action_get_widget(Glib::ustring const& path)
{
return myUIManager->get_widget(path);
}