Don't use deprecated GTK APIs (#2129)

* Don't use deprecated Glib::Thread

* Don't use deprecated stock ID APIs

* Don't use deprecated operator const void* in IconInfo

* Don't use deprecated Gtk::TreeView::set_rules_hint()

* Don't use deprecated Gtk::Widget::set_margin_left()

* Don't use deprecated Gtk::UIManager

* Don't use deprecated sigc::mem_ptr accepting object pointer

* Enable {GDK,GIO,GLIB,GTK,PANGO,SIGCXX}MM deprecation guards

* Enable GTK deprecation guard

Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
Mike Gelfand 2021-11-12 12:12:50 +03:00 committed by GitHub
parent 319e1fc6bb
commit 82b3da0a54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 864 additions and 501 deletions

View File

@ -6,8 +6,9 @@
*
*/
#include <array>
#include <string>
#include <string.h>
#include <string_view>
#include <unordered_map>
#include <glibmm.h>
@ -21,158 +22,89 @@
#include "Session.h"
#include "Utils.h"
using namespace std::string_view_literals;
namespace
{
Session* myCore = nullptr;
void action_cb(Glib::RefPtr<Gtk::Action> const& a, void* user_data)
void action_cb(Gio::SimpleAction& action, void* user_data)
{
gtr_actions_handler(a->get_name(), user_data);
gtr_actions_handler(action.get_name(), user_data);
}
struct ActionEntryBase
void sort_changed_cb(Gio::SimpleAction& action, Glib::VariantBase const& value, void* /*user_data*/)
{
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());
action.set_state(value);
myCore->set_pref(TR_KEY_sort_mode, Glib::VariantBase::cast_dynamic<Glib::Variant<Glib::ustring>>(value).get());
}
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 },
std::array<std::string_view, 2> const show_toggle_entries = {
"toggle-main-window"sv,
"toggle-message-log"sv,
};
void toggle_pref_cb(Glib::RefPtr<Gtk::ToggleAction> const& action, void* /*user_data*/)
void toggle_pref_cb(Gio::SimpleAction& action, void* /*user_data*/)
{
auto const key = action->get_name();
bool const val = action->get_active();
auto const key = action.get_name();
bool val = false;
action.get_state(val);
myCore->set_pref(tr_quark_new({ key.c_str(), key.size() }), val);
action.set_state(Glib::Variant<bool>::create(!val));
myCore->set_pref(tr_quark_new({ key.c_str(), key.size() }), !val);
}
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 },
std::array<std::string_view, 6> const pref_toggle_entries = {
"alt-speed-enabled"sv, //
"compact-view"sv, //
"sort-reversed"sv, //
"show-filterbar"sv, //
"show-statusbar"sv, //
"show-toolbar"sv, //
};
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" }, //
std::array<std::string_view, 29> const entries = {
"copy-magnet-link-to-clipboard"sv,
"open-torrent-from-url"sv,
"open-torrent"sv,
"torrent-start"sv,
"torrent-start-now"sv,
"show-stats"sv,
"donate"sv,
"torrent-verify"sv,
"torrent-stop"sv,
"pause-all-torrents"sv,
"start-all-torrents"sv,
"relocate-torrent"sv,
"remove-torrent"sv,
"delete-torrent"sv,
"new-torrent"sv,
"quit"sv,
"select-all"sv,
"deselect-all"sv,
"edit-preferences"sv,
"show-torrent-properties"sv,
"open-torrent-folder"sv,
"show-about-dialog"sv,
"help"sv,
"torrent-reannounce"sv,
"queue-move-top"sv,
"queue-move-up"sv,
"queue-move-down"sv,
"queue-move-bottom"sv,
"present-main-window"sv,
};
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::IconTheme::get_default()->add_resource_path(TR_RESOURCE_PATH "icons");
}
Gtk::UIManager* myUIManager = nullptr;
Gtk::Builder* myBuilder = nullptr;
std::unordered_map<Glib::ustring, Glib::RefPtr<Gio::SimpleAction>> key_to_action;
} // namespace
@ -181,80 +113,56 @@ void gtr_actions_set_core(Glib::RefPtr<Session> const& core)
myCore = gtr_get_ptr(core);
}
void gtr_actions_init(Glib::RefPtr<Gtk::UIManager> const& ui_manager, void* callback_user_data)
Glib::RefPtr<Gio::SimpleActionGroup> gtr_actions_init(Glib::RefPtr<Gtk::Builder> const& builder, void* callback_user_data)
{
myUIManager = gtr_get_ptr(ui_manager);
myBuilder = gtr_get_ptr(builder);
register_my_icons();
auto const action_group = Gtk::ActionGroup::create("Actions");
auto const action_group = Gio::SimpleActionGroup::create();
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); });
auto const action_name = Glib::ustring("sort-torrents");
auto const action = Gio::SimpleAction::create_radio_string(action_name, match);
action->signal_activate().connect([a = gtr_get_ptr(action), callback_user_data](auto const& value)
{ sort_changed_cb(*a, value, callback_user_data); });
action_group->add_action(action);
key_to_action.emplace(action_name, action);
}
for (auto const& entry : show_toggle_entries)
for (auto const& action_name_view : 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); });
auto const action_name = Glib::ustring(std::string(action_name_view));
auto const action = Gio::SimpleAction::create_bool(action_name);
action->signal_activate().connect([a = gtr_get_ptr(action), callback_user_data](auto const& /*value*/)
{ action_cb(*a, callback_user_data); });
action_group->add_action(action);
key_to_action.emplace(action_name, action);
}
for (auto& entry : pref_toggle_entries)
for (auto const& action_name_view : pref_toggle_entries)
{
entry.is_active = gtr_pref_flag_get(tr_quark_new(entry.name));
auto const action_name = Glib::ustring(std::string(action_name_view));
auto const action = Gio::SimpleAction::create_bool(action_name, gtr_pref_flag_get(tr_quark_new(action_name_view)));
action->signal_activate().connect([a = gtr_get_ptr(action), callback_user_data](auto const& /*value*/)
{ toggle_pref_cb(*a, callback_user_data); });
action_group->add_action(action);
key_to_action.emplace(action_name, action);
}
for (auto const& entry : pref_toggle_entries)
for (auto const& action_name_view : 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);
}
auto const action_name = Glib::ustring(std::string(action_name_view));
auto const action = Gio::SimpleAction::create(action_name);
action->signal_activate().connect([a = gtr_get_ptr(action), callback_user_data](auto const& /*value*/)
{ action_cb(*a, callback_user_data); });
action_group->add_action(action);
key_to_action.emplace(action_name, 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);
return action_group;
}
/****
@ -264,27 +172,8 @@ void gtr_actions_init(Glib::RefPtr<Gtk::UIManager> const& ui_manager, void* call
namespace
{
std::unordered_map<Glib::ustring, Glib::RefPtr<Gtk::Action>> key_to_action;
void ensure_action_map_loaded(Gtk::UIManager& uim)
Glib::RefPtr<Gio::SimpleAction> get_action(Glib::ustring const& name)
{
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);
}
@ -297,20 +186,22 @@ void gtr_action_activate(Glib::ustring const& name)
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);
get_action(name)->set_enabled(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);
get_action(name)->set_state(Glib::Variant<bool>::create(b));
}
Gtk::Widget* gtr_action_get_widget(Glib::ustring const& path)
Gtk::Widget* gtr_action_get_widget(Glib::ustring const& name)
{
return myUIManager->get_widget(path);
Gtk::Widget* widget;
myBuilder->get_widget(name, widget);
return widget;
}
Glib::RefPtr<Glib::Object> gtr_action_get_object(Glib::ustring const& name)
{
return myBuilder->get_object(name);
}

View File

@ -10,24 +10,32 @@
#include <gtkmm.h>
#include "Utils.h"
class Session;
#define WINDOW_ICON "transmission-main-window-icon"
#define TRAY_ICON "transmission-tray-icon"
#define NOTIFICATION_ICON "transmission-notification-icon"
void gtr_actions_init(Glib::RefPtr<Gtk::UIManager> const& ui_manager, void* callback_user_data);
Glib::RefPtr<Gio::SimpleActionGroup> gtr_actions_init(Glib::RefPtr<Gtk::Builder> const& builder, void* callback_user_data);
void gtr_actions_set_core(Glib::RefPtr<Session> const& core);
void gtr_actions_handler(Glib::ustring const& action_name, void* user_data);
void gtr_action_activate(Glib::ustring const& action_name);
void gtr_action_set_sensitive(Glib::ustring const& action_name, bool is_sensitive);
void gtr_action_set_toggled(Glib::ustring const& action_name, bool is_toggled);
void gtr_action_set_important(Glib::ustring const& action_name, bool is_important);
Gtk::Widget* gtr_action_get_widget(Glib::ustring const& path);
Gtk::Widget* gtr_action_get_widget(Glib::ustring const& name);
Glib::RefPtr<Glib::Object> gtr_action_get_object(Glib::ustring const& name);
template<typename T>
inline T* gtr_action_get_widget(Glib::ustring const& path)
inline T* gtr_action_get_widget(Glib::ustring const& name)
{
return static_cast<T*>(gtr_action_get_widget(path));
return static_cast<T*>(gtr_action_get_widget(name));
}
template<typename T>
inline Glib::RefPtr<T> gtr_action_get_object(Glib::ustring const& name)
{
return gtr_ptr_static_cast<T>(gtr_action_get_object(name));
}

View File

@ -28,6 +28,7 @@
#include <stdio.h>
#include <stdlib.h> /* exit() */
#include <string.h>
#include <thread>
#include <time.h>
#include <vector>
#include <string_view>
@ -171,7 +172,7 @@ private:
bool is_iconified_ = false;
bool is_closing_ = false;
Glib::RefPtr<Gtk::UIManager> ui_manager_;
Glib::RefPtr<Gtk::Builder> ui_builder_;
unsigned int activation_count_ = 0;
sigc::connection timer_;
@ -328,7 +329,7 @@ void Application::Impl::refresh_actions_soon()
{
if (!is_closing_ && !refresh_actions_tag_.connected())
{
refresh_actions_tag_ = Glib::signal_idle().connect(sigc::mem_fun(this, &Impl::refresh_actions));
refresh_actions_tag_ = Glib::signal_idle().connect(sigc::mem_fun(*this, &Impl::refresh_actions));
}
}
@ -560,14 +561,14 @@ void Application::Impl::on_startup()
core_ = Session::create(session);
/* init the ui manager */
ui_manager_ = Gtk::UIManager::create();
gtr_actions_init(ui_manager_, this);
ui_manager_->add_ui_from_resource(TR_RESOURCE_PATH "transmission-ui.xml");
ui_manager_->ensure_update();
ui_builder_ = Gtk::Builder::create_from_resource(TR_RESOURCE_PATH "transmission-ui.xml");
auto const actions = gtr_actions_init(ui_builder_, this);
app_.set_menubar(gtr_action_get_object<Gio::Menu>("main-window-menu"));
/* create main window now to be a parent to any error dialogs */
wind_ = MainWindow::create(app_, ui_manager_, core_);
wind_->signal_size_allocate().connect(sigc::mem_fun(this, &Impl::on_main_window_size_allocated));
wind_ = MainWindow::create(app_, actions, core_);
wind_->signal_size_allocate().connect(sigc::mem_fun(*this, &Impl::on_main_window_size_allocated));
app_.hold();
app_setup();
tr_sessionSetRPCCallback(session, &Impl::on_rpc_changed, this);
@ -674,10 +675,10 @@ void Application::Impl::app_setup()
gtr_actions_set_core(core_);
/* set up core handlers */
core_->signal_busy().connect(sigc::mem_fun(this, &Impl::on_core_busy));
core_->signal_add_error().connect(sigc::mem_fun(this, &Impl::on_core_error));
core_->signal_add_prompt().connect(sigc::mem_fun(this, &Impl::on_add_torrent));
core_->signal_prefs_changed().connect(sigc::mem_fun(this, &Impl::on_prefs_changed));
core_->signal_busy().connect(sigc::mem_fun(*this, &Impl::on_core_busy));
core_->signal_add_error().connect(sigc::mem_fun(*this, &Impl::on_core_error));
core_->signal_add_prompt().connect(sigc::mem_fun(*this, &Impl::on_add_torrent));
core_->signal_prefs_changed().connect(sigc::mem_fun(*this, &Impl::on_prefs_changed));
/* add torrents from command-line and saved state */
core_->load(start_paused_);
@ -691,7 +692,7 @@ void Application::Impl::app_setup()
/* start model update timer */
timer_ = Glib::signal_timeout().connect_seconds(
sigc::mem_fun(this, &Impl::update_model_loop),
sigc::mem_fun(*this, &Impl::update_model_loop),
MAIN_WINDOW_REFRESH_INTERVAL_SECONDS);
update_model_once();
@ -699,6 +700,7 @@ void Application::Impl::app_setup()
if (!is_iconified_)
{
wind_->show();
gtr_action_set_toggled("toggle-main-window", true);
}
else
{
@ -742,6 +744,8 @@ void Application::Impl::placeWindowFromPrefs()
void Application::Impl::presentMainWindow()
{
gtr_action_set_toggled("toggle-main-window", true);
if (is_iconified_)
{
is_iconified_ = false;
@ -761,6 +765,8 @@ void Application::Impl::presentMainWindow()
void Application::Impl::hideMainWindow()
{
gtr_action_set_toggled("toggle-main-window", false);
wind_->set_skip_taskbar_hint(true);
gtr_widget_set_visible(*wind_, false);
is_iconified_ = true;
@ -825,17 +831,17 @@ void Application::Impl::main_window_setup()
// cbdata->wind = wind;
sel_ = wind_->get_selection();
sel_->signal_changed().connect(sigc::mem_fun(this, &Impl::refresh_actions_soon));
sel_->signal_changed().connect(sigc::mem_fun(*this, &Impl::refresh_actions_soon));
refresh_actions_soon();
auto const model = core_->get_model();
model->signal_row_changed().connect(sigc::mem_fun(this, &Impl::rowChangedCB));
wind_->signal_delete_event().connect(sigc::mem_fun(this, &Impl::winclose));
model->signal_row_changed().connect(sigc::mem_fun(*this, &Impl::rowChangedCB));
wind_->signal_delete_event().connect(sigc::mem_fun(*this, &Impl::winclose));
refresh_actions();
/* register to handle URIs that get dragged onto our main window */
wind_->drag_dest_set(Gtk::DEST_DEFAULT_ALL, Gdk::ACTION_COPY);
wind_->drag_dest_add_uri_targets();
wind_->signal_drag_data_received().connect(sigc::mem_fun(this, &Impl::on_drag_data_received));
wind_->signal_drag_data_received().connect(sigc::mem_fun(*this, &Impl::on_drag_data_received));
}
bool Application::Impl::on_session_closed()
@ -916,12 +922,13 @@ void Application::Impl::on_app_exit()
/* since tr_sessionClose () is a blocking function,
* delegate its call to another thread here... when it's done,
* punt the GUI teardown back to the GTK+ thread */
Glib::Thread::create(
std::thread(
[this, session = core_->close()]()
{
tr_sessionClose(session);
Glib::signal_idle().connect(sigc::mem_fun(this, &Impl::on_session_closed));
});
Glib::signal_idle().connect(sigc::mem_fun(*this, &Impl::on_session_closed));
})
.detach();
}
void Application::Impl::show_torrent_errors(Glib::ustring const& primary, std::vector<std::string>& files)
@ -996,7 +1003,7 @@ void Application::Impl::on_add_torrent(tr_ctor* ctor)
OptionsDialog::create(*wind_, core_, std::unique_ptr<tr_ctor, decltype(&tr_ctorFree)>(ctor, &tr_ctorFree)));
w->signal_hide().connect([w]() mutable { w.reset(); });
w->signal_focus_in_event().connect(sigc::mem_fun(this, &Impl::on_main_window_focus_in));
w->signal_focus_in_event().connect(sigc::mem_fun(*this, &Impl::on_main_window_focus_in));
if (wind_ != nullptr)
{
@ -1042,7 +1049,7 @@ void Application::Impl::on_prefs_changed(tr_quark const key)
if (show && icon_ == nullptr)
{
icon_ = std::make_unique<SystemTrayIcon>(core_);
icon_ = std::make_unique<SystemTrayIcon>(*wind_, core_);
}
else if (!show && icon_ != nullptr)
{
@ -1237,7 +1244,7 @@ void Application::Impl::update_model_soon()
{
if (!update_model_soon_tag_.connected())
{
update_model_soon_tag_ = Glib::signal_idle().connect(sigc::mem_fun(this, &Impl::update_model_once));
update_model_soon_tag_ = Glib::signal_idle().connect(sigc::mem_fun(*this, &Impl::update_model_once));
}
}
@ -1405,7 +1412,7 @@ void Application::Impl::actions_handler(Glib::ustring const& action_name)
w->signal_hide().connect([w]() mutable { w.reset(); });
w->show();
}
else if (action_name == "open-torrent-menu" || action_name == "open-torrent-toolbar")
else if (action_name == "open-torrent")
{
auto w = std::shared_ptr<TorrentFileChooserDialog>(TorrentFileChooserDialog::create(*wind_, core_));
w->signal_hide().connect([w]() mutable { w.reset(); });
@ -1505,8 +1512,9 @@ void Application::Impl::actions_handler(Glib::ustring const& action_name)
{
if (msgwin_ == nullptr)
{
gtr_action_set_toggled("toggle-message-log", true);
msgwin_ = MessageLogWindow::create(*wind_, core_);
msgwin_->signal_hide().connect(sigc::mem_fun(this, &Impl::on_message_window_closed));
msgwin_->signal_hide().connect(sigc::mem_fun(*this, &Impl::on_message_window_closed));
}
else
{

View File

@ -144,12 +144,17 @@ add_definitions(
-DG_DISABLE_DEPRECATED
-DGDK_PIXBUF_DISABLE_DEPRECATED
-DGDK_DISABLE_DEPRECATED
# FIXME: migrate from GtkUIManager to GtkBuilder in 2.90
# -DGTK_DISABLE_DEPRECATED
-DGTK_DISABLE_DEPRECATED
-DPANGO_DISABLE_DEPRECATED
# FIXME: these break libnotify's headers
# -DG_DISABLE_SINGLE_INCLUDES
# -DGTK_DISABLE_SINGLE_INCLUDES
-DGDKMM_DISABLE_DEPRECATED
-DGIOMM_DISABLE_DEPRECATED
-DGLIBMM_DISABLE_DEPRECATED
-DGTKMM_DISABLE_DEPRECATED
-DPANGOMM_DISABLE_DEPRECATED
-DSIGCXX_DISABLE_DEPRECATED
${GTK_CFLAGS_OTHER}
)

View File

@ -1238,7 +1238,7 @@ void initPeerRow(Gtk::TreeIter const& iter, std::string const& key, std::string
(*iter)[peer_cols.address] = peer->addr;
(*iter)[peer_cols.address_collated] = collated_name;
(*iter)[peer_cols.client] = client;
(*iter)[peer_cols.encryption_stock_id] = peer->isEncrypted ? "transmission-lock" : "";
(*iter)[peer_cols.encryption_stock_id] = peer->isEncrypted ? "lock" : "";
(*iter)[peer_cols.key] = key;
(*iter)[peer_cols.torrent_name] = torrentName;
}
@ -1653,7 +1653,7 @@ void setPeerViewColumns(Gtk::TreeView* peer_view)
r->property_xalign() = 0.0F;
r->property_yalign() = 0.5F;
c = Gtk::make_managed<Gtk::TreeViewColumn>(Glib::ustring(), *r);
c->add_attribute(r->property_stock_id(), *col);
c->add_attribute(r->property_icon_name(), *col);
c->set_sizing(Gtk::TREE_VIEW_COLUMN_FIXED);
c->set_fixed_width(20);
}
@ -1794,10 +1794,9 @@ Gtk::Widget* DetailsDialog::Impl::peer_page_new()
auto m = Gtk::TreeModelSort::create(peer_store_);
m->set_sort_column(peer_cols.progress, Gtk::SORT_DESCENDING);
peer_view_ = Gtk::make_managed<Gtk::TreeView>(m);
peer_view_->set_rules_hint(true);
peer_view_->set_has_tooltip(true);
peer_view_->signal_query_tooltip().connect(sigc::mem_fun(this, &Impl::onPeerViewQueryTooltip));
peer_view_->signal_query_tooltip().connect(sigc::mem_fun(*this, &Impl::onPeerViewQueryTooltip));
peer_view_->signal_button_release_event().connect([this](GdkEventButton* event)
{ return on_tree_view_button_released(peer_view_, event); });
@ -1818,7 +1817,7 @@ Gtk::Widget* DetailsDialog::Impl::peer_page_new()
more_peer_details_check_ = Gtk::make_managed<Gtk::CheckButton>(_("Show _more details"), true);
more_peer_details_check_->set_active(gtr_pref_flag_get(TR_KEY_show_extra_peer_details));
more_peer_details_check_->signal_toggled().connect(sigc::mem_fun(this, &Impl::onMorePeerInfoToggled));
more_peer_details_check_->signal_toggled().connect(sigc::mem_fun(*this, &Impl::onMorePeerInfoToggled));
vbox->pack_start(*more_peer_details_check_, false, false);
return vbox;
@ -2461,7 +2460,7 @@ Gtk::Widget* DetailsDialog::Impl::tracker_page_new()
tracker_store_ = Gtk::ListStore::create(tracker_cols);
trackers_filtered_ = Gtk::TreeModelFilter::create(tracker_store_);
trackers_filtered_->set_visible_func(sigc::mem_fun(this, &Impl::trackerVisibleFunc));
trackers_filtered_->set_visible_func(sigc::mem_fun(*this, &Impl::trackerVisibleFunc));
auto* hbox = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_HORIZONTAL, GUI_PAD_BIG);
@ -2473,7 +2472,7 @@ Gtk::Widget* DetailsDialog::Impl::tracker_page_new()
{ return on_tree_view_button_released(tracker_view_, event); });
auto sel = tracker_view_->get_selection();
sel->signal_changed().connect(sigc::mem_fun(this, &Impl::on_tracker_list_selection_changed));
sel->signal_changed().connect(sigc::mem_fun(*this, &Impl::on_tracker_list_selection_changed));
auto* c = Gtk::make_managed<Gtk::TreeViewColumn>();
c->set_title(_("Trackers"));
@ -2510,15 +2509,15 @@ Gtk::Widget* DetailsDialog::Impl::tracker_page_new()
auto* v = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_VERTICAL, GUI_PAD);
add_tracker_button_ = Gtk::make_managed<Gtk::Button>(_("_Add"), true);
add_tracker_button_->signal_clicked().connect(sigc::mem_fun(this, &Impl::on_tracker_list_add_button_clicked));
add_tracker_button_->signal_clicked().connect(sigc::mem_fun(*this, &Impl::on_tracker_list_add_button_clicked));
v->pack_start(*add_tracker_button_, false, false);
edit_trackers_button_ = Gtk::make_managed<Gtk::Button>(_("_Edit"), true);
edit_trackers_button_->signal_clicked().connect(sigc::mem_fun(this, &Impl::on_edit_trackers));
edit_trackers_button_->signal_clicked().connect(sigc::mem_fun(*this, &Impl::on_edit_trackers));
v->pack_start(*edit_trackers_button_, false, false);
remove_tracker_button_ = Gtk::make_managed<Gtk::Button>(_("_Remove"), true);
remove_tracker_button_->signal_clicked().connect(sigc::mem_fun(this, &Impl::on_tracker_list_remove_button_clicked));
remove_tracker_button_->signal_clicked().connect(sigc::mem_fun(*this, &Impl::on_tracker_list_remove_button_clicked));
v->pack_start(*remove_tracker_button_, false, false);
hbox->pack_start(*v, false, false);
@ -2527,12 +2526,12 @@ Gtk::Widget* DetailsDialog::Impl::tracker_page_new()
scrape_check_ = Gtk::make_managed<Gtk::CheckButton>(_("Show _more details"), true);
scrape_check_->set_active(gtr_pref_flag_get(TR_KEY_show_tracker_scrapes));
scrape_check_->signal_toggled().connect(sigc::mem_fun(this, &Impl::onScrapeToggled));
scrape_check_->signal_toggled().connect(sigc::mem_fun(*this, &Impl::onScrapeToggled));
vbox->pack_start(*scrape_check_, false, false);
all_check_ = Gtk::make_managed<Gtk::CheckButton>(_("Show _backup trackers"), true);
all_check_->set_active(gtr_pref_flag_get(TR_KEY_show_backup_trackers));
all_check_->signal_toggled().connect(sigc::mem_fun(this, &Impl::onBackupToggled));
all_check_->signal_toggled().connect(sigc::mem_fun(*this, &Impl::onBackupToggled));
vbox->pack_start(*all_check_, false, false);
return vbox;
@ -2594,7 +2593,7 @@ DetailsDialog::Impl::Impl(DetailsDialog& dialog, Glib::RefPtr<Session> const& co
/* return saved window size */
dialog_.resize((int)gtr_pref_int_get(TR_KEY_details_window_width), (int)gtr_pref_int_get(TR_KEY_details_window_height));
dialog_.signal_size_allocate().connect(sigc::mem_fun(this, &Impl::on_details_window_size_allocated));
dialog_.signal_size_allocate().connect(sigc::mem_fun(*this, &Impl::on_details_window_size_allocated));
dialog_.signal_response().connect(sigc::hide<0>(sigc::mem_fun(dialog_, &DetailsDialog::hide)));
dialog_.set_border_width(GUI_PAD);

View File

@ -828,8 +828,8 @@ FileList::Impl::Impl(FileList& widget, Glib::RefPtr<Session> const& core, int to
/* create the view */
view_ = Gtk::make_managed<Gtk::TreeView>();
view_->set_border_width(GUI_PAD_BIG);
view_->signal_button_press_event().connect(sigc::mem_fun(this, &Impl::onViewButtonPressed), false);
view_->signal_row_activated().connect(sigc::mem_fun(this, &Impl::onRowActivated));
view_->signal_button_press_event().connect(sigc::mem_fun(*this, &Impl::onViewButtonPressed), false);
view_->signal_row_activated().connect(sigc::mem_fun(*this, &Impl::onRowActivated));
view_->signal_button_release_event().connect([this](GdkEventButton* event)
{ return on_tree_view_button_released(view_, event); });
@ -856,7 +856,7 @@ FileList::Impl::Impl(FileList& widget, Glib::RefPtr<Session> const& core, int to
text_rend->property_editable() = true;
text_rend->property_ellipsize() = Pango::ELLIPSIZE_END;
text_rend->property_font_desc() = pango_font_description;
text_rend->signal_edited().connect(sigc::mem_fun(this, &Impl::cell_edited_callback));
text_rend->signal_edited().connect(sigc::mem_fun(*this, &Impl::cell_edited_callback));
col->pack_start(*text_rend, true);
col->add_attribute(text_rend->property_text(), file_cols.label);
col->set_sort_column(file_cols.label);

View File

@ -737,7 +737,7 @@ void FilterBar::Impl::update_count_label_idle()
if (!pending)
{
show_lb_->set_data(DIRTY_KEY, GINT_TO_POINTER(1));
Glib::signal_idle().connect(sigc::mem_fun(this, &Impl::update_count_label));
Glib::signal_idle().connect(sigc::mem_fun(*this, &Impl::update_count_label));
}
}
@ -765,10 +765,10 @@ FilterBar::Impl::Impl(FilterBar& widget, tr_session* session, Glib::RefPtr<Gtk::
tracker_->property_width_request() = 170;
static_cast<Gtk::TreeStore*>(gtr_get_ptr(tracker_->get_model()))->set_data(SESSION_KEY, session);
filter_model_->set_visible_func(sigc::mem_fun(this, &Impl::is_row_visible));
filter_model_->set_visible_func(sigc::mem_fun(*this, &Impl::is_row_visible));
tracker_->signal_changed().connect(sigc::mem_fun(this, &Impl::selection_changed_cb));
activity_->signal_changed().connect(sigc::mem_fun(this, &Impl::selection_changed_cb));
tracker_->signal_changed().connect(sigc::mem_fun(*this, &Impl::selection_changed_cb));
activity_->signal_changed().connect(sigc::mem_fun(*this, &Impl::selection_changed_cb));
/* add the activity combobox */
show_lb_->set_mnemonic_widget(*activity_);
@ -786,7 +786,7 @@ FilterBar::Impl::Impl(FilterBar& widget, tr_session* session, Glib::RefPtr<Gtk::
entry_->signal_icon_release().connect([this](auto /*icon_position*/, auto const* /*event*/) { entry_->set_text({}); });
widget_.pack_start(*entry_, true, true, 0);
entry_->signal_changed().connect(sigc::mem_fun(this, &Impl::filter_entry_changed));
entry_->signal_changed().connect(sigc::mem_fun(*this, &Impl::filter_entry_changed));
selection_changed_cb();
update_count_label();

View File

@ -64,7 +64,7 @@ FreeSpaceLabel::Impl::Impl(FreeSpaceLabel& label, Glib::RefPtr<Session> const& c
, core_(core)
, dir_(dir)
{
timer_id_ = Glib::signal_timeout().connect_seconds(sigc::mem_fun(this, &Impl::on_freespace_timer), 3);
timer_id_ = Glib::signal_timeout().connect_seconds(sigc::mem_fun(*this, &Impl::on_freespace_timer), 3);
on_freespace_timer();
}

View File

@ -80,7 +80,7 @@ Glib::RefPtr<Gdk::Pixbuf> get_themed_icon_pixbuf(Gio::ThemedIcon& icon, int size
auto icon_info = icon_theme.choose_icon(icon_names, size);
if (icon_info == nullptr)
if (!bool{ icon_info })
{
icon_info = icon_theme.lookup_icon("text-x-generic", size, Gtk::ICON_LOOKUP_USE_BUILTIN);
}

View File

@ -40,7 +40,7 @@
class MainWindow::Impl
{
public:
Impl(MainWindow& window, Glib::RefPtr<Gtk::UIManager> const& ui_mgr, Glib::RefPtr<Session> const& core);
Impl(MainWindow& window, Glib::RefPtr<Gio::ActionGroup> const& actions, Glib::RefPtr<Session> const& core);
~Impl();
Glib::RefPtr<Gtk::TreeSelection> get_selection() const;
@ -56,6 +56,8 @@ private:
Gtk::Menu* createSpeedMenu(tr_direction dir);
Gtk::Menu* createRatioMenu();
void on_popup_menu(GdkEventButton* event);
void onSpeedToggled(Gtk::CheckMenuItem* check, tr_direction dir, bool enabled);
void onSpeedSet(tr_direction dir, int KBps);
@ -67,7 +69,6 @@ private:
void syncAltSpeedButton();
bool onAskTrackerQueryTooltip(int x, int y, bool keyboard_tip, Glib::RefPtr<Gtk::Tooltip> tooltip);
void status_menu_toggled_cb(Gtk::CheckMenuItem* menu_item, std::string const& val);
void onOptionsClicked(Gtk::Button* button);
void onYinYangClicked(Gtk::Button* button);
@ -75,6 +76,8 @@ private:
void onAltSpeedToggledIdle();
private:
MainWindow& window_;
Gtk::RadioMenuItem* speedlimit_on_item_[2] = { nullptr, nullptr };
Gtk::RadioMenuItem* speedlimit_off_item_[2] = { nullptr, nullptr };
Gtk::RadioMenuItem* ratio_on_item_ = nullptr;
@ -96,21 +99,27 @@ private:
Gtk::TreeViewColumn* column_ = nullptr;
Glib::RefPtr<Session> const core_;
sigc::connection pref_handler_id_;
Gtk::Menu* popup_menu_;
};
/***
****
***/
void MainWindow::Impl::on_popup_menu(GdkEventButton* event)
{
if (popup_menu_ == nullptr)
{
popup_menu_ = Gtk::make_managed<Gtk::Menu>(gtr_action_get_object<Gio::Menu>("main-window-popup"));
popup_menu_->attach_to_widget(window_);
}
popup_menu_->popup_at_pointer(reinterpret_cast<GdkEvent*>(event));
}
namespace
{
void on_popup_menu(GdkEventButton* event)
{
auto* menu = gtr_action_get_widget<Gtk::Menu>("/main-window-popup");
menu->popup_at_pointer(reinterpret_cast<GdkEvent*>(event));
}
bool tree_view_search_equal_func(
Glib::RefPtr<Gtk::TreeModel> const& /*model*/,
int /*column*/,
@ -150,9 +159,10 @@ Gtk::TreeView* MainWindow::Impl::makeview(Glib::RefPtr<Gtk::TreeModel> const& mo
selection_->set_mode(Gtk::SELECTION_MULTIPLE);
view->signal_popup_menu().connect_notify([]() { on_popup_menu(nullptr); });
view->signal_popup_menu().connect_notify([this]() { on_popup_menu(nullptr); });
view->signal_button_press_event().connect(
[view](GdkEventButton* event) { return on_tree_view_button_pressed(view, event, &on_popup_menu); },
[this, view](GdkEventButton* event)
{ return on_tree_view_button_pressed(view, event, sigc::mem_fun(*this, &Impl::on_popup_menu)); },
false);
view->signal_button_release_event().connect([view](GdkEventButton* event)
{ return on_tree_view_button_released(view, event); });
@ -235,7 +245,7 @@ void MainWindow::Impl::syncAltSpeedButton()
gtr_sprintf(_("Click to enable Alternative Speed Limits\n (%1$s down, %2$s up)"), d, u);
alt_speed_button_->set_active(b);
alt_speed_image_->set(Gtk::StockID(stock), Gtk::IconSize(-1));
alt_speed_image_->set_from_icon_name(stock, Gtk::BuiltinIconSize::ICON_SIZE_MENU);
alt_speed_button_->set_halign(Gtk::ALIGN_CENTER);
alt_speed_button_->set_valign(Gtk::ALIGN_CENTER);
alt_speed_button_->set_tooltip_text(str);
@ -250,35 +260,6 @@ void MainWindow::Impl::alt_speed_toggled_cb()
**** FILTER
***/
bool MainWindow::Impl::onAskTrackerQueryTooltip(int /*x*/, int /*y*/, bool /*keyboard_tip*/, Glib::RefPtr<Gtk::Tooltip> tooltip)
{
bool handled;
time_t maxTime = 0;
time_t const now = time(nullptr);
selection_->selected_foreach(
[&maxTime](auto const& /*path*/, auto const& iter)
{
auto* tor = static_cast<tr_torrent*>(iter->get_value(torrent_cols.torrent));
auto const* torStat = tr_torrentStatCached(tor);
maxTime = std::max(maxTime, torStat->manualAnnounceTime);
});
if (maxTime <= now)
{
handled = false;
}
else
{
time_t const seconds = maxTime - now;
tooltip->set_text(gtr_sprintf(_("Tracker will allow requests in %s"), tr_strltime(seconds)));
handled = true;
}
return handled;
}
void MainWindow::Impl::onAltSpeedToggledIdle()
{
core_->set_pref(TR_KEY_alt_speed_enabled, tr_sessionUsesAltSpeed(core_->get_session()));
@ -435,23 +416,24 @@ void MainWindow::Impl::onOptionsClicked(Gtk::Button* button)
std::unique_ptr<MainWindow> MainWindow::create(
Gtk::Application& app,
Glib::RefPtr<Gtk::UIManager> const& uim,
Glib::RefPtr<Gio::ActionGroup> const& actions,
Glib::RefPtr<Session> const& core)
{
return std::unique_ptr<MainWindow>(new MainWindow(app, uim, core));
return std::unique_ptr<MainWindow>(new MainWindow(app, actions, core));
}
MainWindow::MainWindow(Gtk::Application& app, Glib::RefPtr<Gtk::UIManager> const& ui_mgr, Glib::RefPtr<Session> const& core)
MainWindow::MainWindow(Gtk::Application& app, Glib::RefPtr<Gio::ActionGroup> const& actions, Glib::RefPtr<Session> const& core)
: Gtk::ApplicationWindow()
, impl_(std::make_unique<Impl>(*this, ui_mgr, core))
, impl_(std::make_unique<Impl>(*this, actions, core))
{
app.add_window(*this);
}
MainWindow::~MainWindow() = default;
MainWindow::Impl::Impl(MainWindow& window, Glib::RefPtr<Gtk::UIManager> const& ui_mgr, Glib::RefPtr<Session> const& core)
: core_(core)
MainWindow::Impl::Impl(MainWindow& window, Glib::RefPtr<Gio::ActionGroup> const& actions, Glib::RefPtr<Session> const& core)
: window_(window)
, core_(core)
{
static struct
{
@ -475,7 +457,7 @@ MainWindow::Impl::Impl(MainWindow& window, Glib::RefPtr<Gtk::UIManager> const& u
window.maximize();
}
window.add_accel_group(ui_mgr->get_accel_group());
window.insert_action_group("win", actions);
/* Add style provider to the window. */
/* Please move it to separate .css file if youre adding more styles here. */
auto const* style = ".tr-workarea.frame {border-left-width: 0; border-right-width: 0; border-radius: 0;}";
@ -490,17 +472,9 @@ MainWindow::Impl::Impl(MainWindow& window, Glib::RefPtr<Gtk::UIManager> const& u
auto* vbox = Gtk::make_managed<Gtk::Box>(Gtk::ORIENTATION_VERTICAL, 0);
window.add(*vbox);
/* main menu */
auto* mainmenu = gtr_action_get_widget<Gtk::MenuBar>("/main-window-menu");
gtr_action_get_widget<Gtk::MenuItem>("/main-window-menu/torrent-menu/torrent-reannounce")
->signal_query_tooltip()
.connect(sigc::mem_fun(this, &Impl::onAskTrackerQueryTooltip));
/* toolbar */
toolbar_ = gtr_action_get_widget<Gtk::Toolbar>("/main-window-toolbar");
toolbar_ = gtr_action_get_widget<Gtk::Toolbar>("main-window-toolbar");
toolbar_->get_style_context()->add_class(GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
gtr_action_set_important("open-torrent-toolbar", true);
gtr_action_set_important("show-torrent-properties", true);
/* filter */
filter_ = Gtk::make_managed<FilterBar>(core_->get_session(), core_->get_model());
@ -542,7 +516,7 @@ MainWindow::Impl::Impl(MainWindow& window, Glib::RefPtr<Gtk::UIManager> const& u
alt_speed_button_ = Gtk::make_managed<Gtk::ToggleButton>();
alt_speed_button_->set_image(*alt_speed_image_);
alt_speed_button_->set_relief(Gtk::RELIEF_NONE);
alt_speed_button_->signal_toggled().connect(sigc::mem_fun(this, &Impl::alt_speed_toggled_cb));
alt_speed_button_->signal_toggled().connect(sigc::mem_fun(*this, &Impl::alt_speed_toggled_cb));
status_->add(*alt_speed_button_);
/* spacer */
@ -557,13 +531,13 @@ MainWindow::Impl::Impl(MainWindow& window, Glib::RefPtr<Gtk::UIManager> const& u
/* upload */
ul_lb_ = Gtk::make_managed<Gtk::Label>();
ul_lb_->set_margin_left(GUI_PAD);
ul_lb_->set_margin_start(GUI_PAD);
ul_lb_->set_single_line_mode(true);
status_->add(*ul_lb_);
/* ratio */
stats_lb_ = Gtk::make_managed<Gtk::Label>();
stats_lb_->set_margin_left(GUI_PAD_BIG);
stats_lb_->set_margin_start(GUI_PAD_BIG);
stats_lb_->set_single_line_mode(true);
status_->add(*stats_lb_);
@ -587,7 +561,6 @@ MainWindow::Impl::Impl(MainWindow& window, Glib::RefPtr<Gtk::UIManager> const& u
scroll_->add(*view_);
/* lay out the widgets */
vbox->pack_start(*mainmenu, false, false);
vbox->pack_start(*toolbar_, false, false);
vbox->pack_start(*filter_, false, false);
vbox->pack_start(*scroll_, true, true);
@ -617,7 +590,7 @@ MainWindow::Impl::Impl(MainWindow& window, Glib::RefPtr<Gtk::UIManager> const& u
prefsChanged(TR_KEY_statusbar_stats);
prefsChanged(TR_KEY_show_toolbar);
prefsChanged(TR_KEY_alt_speed_enabled);
pref_handler_id_ = core_->signal_prefs_changed().connect(sigc::mem_fun(this, &Impl::prefsChanged));
pref_handler_id_ = core_->signal_prefs_changed().connect(sigc::mem_fun(*this, &Impl::prefsChanged));
tr_sessionSetAltSpeedFunc(
core_->get_session(),

View File

@ -36,7 +36,7 @@ public:
static std::unique_ptr<MainWindow> create(
Gtk::Application& app,
Glib::RefPtr<Gtk::UIManager> const& uim,
Glib::RefPtr<Gio::ActionGroup> const& actions,
Glib::RefPtr<Session> const& core);
Glib::RefPtr<Gtk::TreeSelection> get_selection() const;
@ -45,7 +45,7 @@ public:
void refresh();
protected:
MainWindow(Gtk::Application& app, Glib::RefPtr<Gtk::UIManager> const& uim, Glib::RefPtr<Session> const& core);
MainWindow(Gtk::Application& app, Glib::RefPtr<Gio::ActionGroup> const& actions, Glib::RefPtr<Session> const& core);
private:
class Impl;

View File

@ -204,7 +204,7 @@ MakeProgressDialog::MakeProgressDialog(
add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
add_button(_("_Close"), Gtk::RESPONSE_CLOSE);
add_button(_("_Add"), Gtk::RESPONSE_ACCEPT);
signal_response().connect(sigc::mem_fun(this, &MakeProgressDialog::onProgressDialogResponse));
signal_response().connect(sigc::mem_fun(*this, &MakeProgressDialog::onProgressDialogResponse));
auto* fr = Gtk::make_managed<Gtk::Frame>();
fr->set_border_width(GUI_PAD_BIG);
@ -222,7 +222,7 @@ MakeProgressDialog::MakeProgressDialog(
v->pack_start(*progress_bar_, false, false, 0);
progress_tag_ = Glib::signal_timeout().connect_seconds(
sigc::mem_fun(this, &MakeProgressDialog::onProgressDialogRefresh),
sigc::mem_fun(*this, &MakeProgressDialog::onProgressDialogRefresh),
SECONDARY_WINDOW_REFRESH_INTERVAL_SECONDS);
onProgressDialogRefresh();
@ -436,7 +436,7 @@ MakeDialog::Impl::Impl(MakeDialog& dialog, Glib::RefPtr<Session> const& core)
dialog_.add_button(_("_Close"), Gtk::RESPONSE_CLOSE);
dialog_.add_button(_("_New"), Gtk::RESPONSE_ACCEPT);
dialog_.signal_response().connect(sigc::mem_fun(this, &Impl::onResponse));
dialog_.signal_response().connect(sigc::mem_fun(*this, &Impl::onResponse));
auto* t = Gtk::make_managed<HigWorkarea>();
@ -513,5 +513,5 @@ MakeDialog::Impl::Impl(MakeDialog& dialog, Glib::RefPtr<Session> const& core)
dialog_.drag_dest_set(Gtk::DEST_DEFAULT_ALL, Gdk::ACTION_COPY);
dialog_.drag_dest_add_uri_targets();
dialog_.signal_drag_data_received().connect(sigc::mem_fun(this, &Impl::on_drag_data_received));
dialog_.signal_drag_data_received().connect(sigc::mem_fun(*this, &Impl::on_drag_data_received));
}

View File

@ -461,27 +461,33 @@ MessageLogWindow::Impl::Impl(MessageLogWindow& window, Glib::RefPtr<Session> con
toolbar->get_style_context()->add_class(GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
{
auto* item = Gtk::make_managed<Gtk::ToolButton>(Gtk::StockID("document-save-as"));
auto* icon = Gtk::make_managed<Gtk::Image>();
icon->set_from_icon_name("document-save-as", Gtk::BuiltinIconSize::ICON_SIZE_SMALL_TOOLBAR);
auto* item = Gtk::make_managed<Gtk::ToolButton>(*icon);
item->set_is_important(true);
item->set_label(_("Save _As"));
item->set_use_underline(true);
item->signal_clicked().connect(sigc::mem_fun(this, &Impl::onSaveRequest));
item->signal_clicked().connect(sigc::mem_fun(*this, &Impl::onSaveRequest));
toolbar->insert(*item, -1);
}
{
auto* item = Gtk::make_managed<Gtk::ToolButton>(Gtk::StockID("edit-clear"));
auto* icon = Gtk::make_managed<Gtk::Image>();
icon->set_from_icon_name("edit-clear", Gtk::BuiltinIconSize::ICON_SIZE_SMALL_TOOLBAR);
auto* item = Gtk::make_managed<Gtk::ToolButton>(*icon);
item->set_is_important(true);
item->set_label(_("Clear"));
item->set_use_underline(true);
item->signal_clicked().connect(sigc::mem_fun(this, &Impl::onClearRequest));
item->signal_clicked().connect(sigc::mem_fun(*this, &Impl::onClearRequest));
toolbar->insert(*item, -1);
}
toolbar->insert(*Gtk::make_managed<Gtk::SeparatorToolItem>(), -1);
{
auto* item = Gtk::make_managed<Gtk::ToggleToolButton>(Gtk::StockID("media-playback-pause"));
auto* icon = Gtk::make_managed<Gtk::Image>();
icon->set_from_icon_name("media-playback-pause", Gtk::BuiltinIconSize::ICON_SIZE_SMALL_TOOLBAR);
auto* item = Gtk::make_managed<Gtk::ToggleToolButton>(*icon);
item->set_is_important(true);
item->set_label(_("P_ause"));
item->set_use_underline(true);
@ -522,7 +528,7 @@ MessageLogWindow::Impl::Impl(MessageLogWindow& window, Glib::RefPtr<Session> con
sort_ = Gtk::TreeModelSort::create(filter_);
sort_->set_sort_column(message_log_cols.sequence, Gtk::SORT_ASCENDING);
maxLevel_ = static_cast<tr_log_level>(gtr_pref_int_get(TR_KEY_message_level));
filter_->set_visible_func(sigc::mem_fun(this, &Impl::isRowVisible));
filter_->set_visible_func(sigc::mem_fun(*this, &Impl::isRowVisible));
view_ = Gtk::make_managed<Gtk::TreeView>(sort_);
view_->signal_button_release_event().connect([this](GdkEventButton* event)
@ -538,7 +544,7 @@ MessageLogWindow::Impl::Impl(MessageLogWindow& window, Glib::RefPtr<Session> con
window_.add(*vbox);
refresh_tag_ = Glib::signal_timeout().connect_seconds(
sigc::mem_fun(this, &Impl::onRefresh),
sigc::mem_fun(*this, &Impl::onRefresh),
SECONDARY_WINDOW_REFRESH_INTERVAL_SECONDS);
scroll_to_bottom();

View File

@ -303,7 +303,7 @@ OptionsDialog::Impl::Impl(
priority_combo_ = gtr_priority_combo_new();
gtr_priority_combo_set_value(*priority_combo_, TR_PRI_NORMAL);
dialog.signal_response().connect(sigc::mem_fun(this, &Impl::addResponseCB));
dialog.signal_response().connect(sigc::mem_fun(*this, &Impl::addResponseCB));
auto* grid = Gtk::make_managed<Gtk::Grid>();
grid->set_border_width(GUI_PAD_BIG);

View File

@ -1094,7 +1094,7 @@ PrefsDialog::Impl::Impl(PrefsDialog& dialog, Glib::RefPtr<Session> const& core)
{
static tr_quark const prefs_quarks[] = { TR_KEY_peer_port, TR_KEY_download_dir };
core_prefs_tag_ = core_->signal_prefs_changed().connect(sigc::mem_fun(this, &Impl::on_core_prefs_changed));
core_prefs_tag_ = core_->signal_prefs_changed().connect(sigc::mem_fun(*this, &Impl::on_core_prefs_changed));
dialog_.add_button(_("_Help"), Gtk::RESPONSE_HELP);
dialog_.add_button(_("_Close"), Gtk::RESPONSE_CLOSE);
@ -1118,6 +1118,6 @@ PrefsDialog::Impl::Impl(PrefsDialog& dialog, Glib::RefPtr<Session> const& core)
on_core_prefs_changed(key);
}
dialog_.signal_response().connect(sigc::mem_fun(this, &Impl::response_cb));
dialog_.signal_response().connect(sigc::mem_fun(*this, &Impl::response_cb));
gtr_dialog_set_content(dialog_, *n);
}

View File

@ -124,7 +124,7 @@ void RelocateDialog::Impl::onResponse(int response)
/* start the move and periodically check its status */
done_ = TR_LOC_DONE;
timer_ = Glib::signal_timeout().connect_seconds(sigc::mem_fun(this, &Impl::onTimer), 1);
timer_ = Glib::signal_timeout().connect_seconds(sigc::mem_fun(*this, &Impl::onTimer), 1);
onTimer();
}
else
@ -159,7 +159,7 @@ RelocateDialog::Impl::Impl(RelocateDialog& dialog, Glib::RefPtr<Session> const&
dialog_.add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
dialog_.add_button(_("_Apply"), Gtk::RESPONSE_APPLY);
dialog_.set_default_response(Gtk::RESPONSE_CANCEL);
dialog_.signal_response().connect(sigc::mem_fun(this, &Impl::onResponse));
dialog_.signal_response().connect(sigc::mem_fun(*this, &Impl::onResponse));
row = 0;
auto* t = Gtk::make_managed<HigWorkarea>();

View File

@ -713,7 +713,7 @@ void Session::Impl::watchdir_monitor_file(Glib::RefPtr<Gio::File> const& file)
if (!monitor_idle_tag_.connected())
{
monitor_idle_tag_ = Glib::signal_timeout().connect_seconds(sigc::mem_fun(this, &Impl::watchdir_idle), 1);
monitor_idle_tag_ = Glib::signal_timeout().connect_seconds(sigc::mem_fun(*this, &Impl::watchdir_idle), 1);
}
}
}
@ -769,7 +769,7 @@ void Session::Impl::watchdir_update()
monitor_ = m;
monitor_dir_ = dir;
monitor_tag_ = m->signal_changed().connect(sigc::mem_fun(this, &Impl::on_file_changed_in_watchdir));
monitor_tag_ = m->signal_changed().connect(sigc::mem_fun(*this, &Impl::on_file_changed_in_watchdir));
}
}

View File

@ -181,8 +181,8 @@ StatsDialog::Impl::Impl(StatsDialog& dialog, Glib::RefPtr<Session> const& core)
gtr_dialog_set_content(dialog_, *t);
updateStats();
dialog_.signal_response().connect(sigc::mem_fun(this, &Impl::dialogResponse));
dialog_.signal_response().connect(sigc::mem_fun(*this, &Impl::dialogResponse));
update_stats_tag_ = Glib::signal_timeout().connect_seconds(
sigc::mem_fun(this, &Impl::updateStats),
sigc::mem_fun(*this, &Impl::updateStats),
SECONDARY_WINDOW_REFRESH_INTERVAL_SECONDS);
}

View File

@ -1,14 +1,18 @@
/*
* This file Copyright (C) 2007-2014 Mnemosyne LLC
* 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.
*
*/
// _AppIndicatorClass::{fallback,unfallback} use deprecated GtkStatusIcon
#undef GTK_DISABLE_DEPRECATED
// We're using deprecated Gtk::StatusItem ourselves as well
#undef GTKMM_DISABLE_DEPRECATED
#include <glibmm.h>
#include <glibmm/i18n.h>
#include <gtkmm.h>
#ifdef HAVE_LIBAPPINDICATOR
#include <libappindicator/app-indicator.h>
@ -27,7 +31,7 @@
class SystemTrayIcon::Impl
{
public:
Impl(Glib::RefPtr<Session> const& core);
Impl(Gtk::Window& main_window, Glib::RefPtr<Session> const& core);
~Impl();
void refresh();
@ -163,8 +167,8 @@ std::string getIconName()
} // namespace
SystemTrayIcon::SystemTrayIcon(Glib::RefPtr<Session> const& core)
: impl_(std::make_unique<Impl>(core))
SystemTrayIcon::SystemTrayIcon(Gtk::Window& main_window, Glib::RefPtr<Session> const& core)
: impl_(std::make_unique<Impl>(main_window, core))
{
}
@ -175,11 +179,12 @@ void SystemTrayIcon::refresh()
impl_->refresh();
}
SystemTrayIcon::Impl::Impl(Glib::RefPtr<Session> const& core)
SystemTrayIcon::Impl::Impl(Gtk::Window& main_window, Glib::RefPtr<Session> const& core)
: core_(core)
{
auto const icon_name = getIconName();
menu_ = gtr_action_get_widget<Gtk::Menu>("/icon-popup");
menu_ = Gtk::make_managed<Gtk::Menu>(gtr_action_get_object<Gio::Menu>("icon-popup"));
menu_->attach_to_widget(main_window);
#ifdef HAVE_LIBAPPINDICATOR
@ -191,8 +196,8 @@ SystemTrayIcon::Impl::Impl(Glib::RefPtr<Session> const& core)
#else
icon_ = Gtk::StatusIcon::create(icon_name);
icon_->signal_activate().connect(sigc::mem_fun(this, &Impl::activated));
icon_->signal_popup_menu().connect(sigc::mem_fun(this, &Impl::popup));
icon_->signal_activate().connect(sigc::mem_fun(*this, &Impl::activated));
icon_->signal_popup_menu().connect(sigc::mem_fun(*this, &Impl::popup));
#endif
}

View File

@ -1,5 +1,5 @@
/*
* This file Copyright (C) 2007-2014 Mnemosyne LLC
* 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.
@ -10,12 +10,14 @@
#include <memory>
#include <gtkmm.h>
class Session;
class SystemTrayIcon
{
public:
SystemTrayIcon(Glib::RefPtr<Session> const& core);
SystemTrayIcon(Gtk::Window& main_window, Glib::RefPtr<Session> const& core);
~SystemTrayIcon();
void refresh();

View File

@ -198,6 +198,16 @@ inline T* gtr_get_ptr(Glib::RefPtr<T> const& ptr)
#endif
}
template<typename T, typename U>
inline Glib::RefPtr<T> gtr_ptr_static_cast(Glib::RefPtr<U> const& ptr)
{
#if G_ENCODE_VERSION(GLIBMM_MAJOR_VERSION, GLIBMM_MINOR_VERSION) < G_ENCODE_VERSION(2, 68)
return Glib::RefPtr<T>::cast_static(ptr);
#else
return std::static_pointer_cast<T>(ptr);
#endif
}
template<>
struct std::hash<Glib::ustring>
{

View File

@ -1,130 +1,585 @@
<ui>
<menubar name='main-window-menu'>
<menu action='file-menu'>
<menuitem action='open-torrent-menu'/>
<menuitem action='open-torrent-from-url'/>
<menuitem action='new-torrent'/>
<separator/>
<menuitem action='start-all-torrents'/>
<menuitem action='pause-all-torrents'/>
<separator/>
<menuitem action='quit'/>
</menu>
<menu action='edit-menu'>
<menuitem action='select-all'/>
<menuitem action='deselect-all'/>
<separator/>
<menuitem action='edit-preferences'/>
</menu>
<menu action='torrent-menu'>
<menuitem action='show-torrent-properties'/>
<menuitem action='open-torrent-folder'/>
<separator/>
<menuitem action='torrent-start'/>
<menuitem action='torrent-start-now'/>
<menuitem action='torrent-reannounce'/>
<menu action='queue-menu'>
<menuitem action='queue-move-top'/>
<menuitem action='queue-move-up'/>
<menuitem action='queue-move-down'/>
<menuitem action='queue-move-bottom'/>
</menu>
<menuitem action='torrent-stop'/>
<separator/>
<menuitem action='relocate-torrent'/>
<menuitem action='torrent-verify'/>
<menuitem action='copy-magnet-link-to-clipboard'/>
<separator/>
<menuitem action='remove-torrent'/>
<menuitem action='delete-torrent'/>
</menu>
<menu action='view-menu'>
<menuitem action='compact-view'/>
<separator/>
<menuitem action='show-toolbar'/>
<menuitem action='show-filterbar'/>
<menuitem action='show-statusbar'/>
<separator/>
<menuitem action='sort-by-activity'/>
<menuitem action='sort-by-age'/>
<menuitem action='sort-by-name'/>
<menuitem action='sort-by-progress'/>
<menuitem action='sort-by-queue'/>
<menuitem action='sort-by-ratio'/>
<menuitem action='sort-by-size'/>
<menuitem action='sort-by-state'/>
<menuitem action='sort-by-time-left'/>
<separator/>
<menuitem action='sort-reversed'/>
</menu>
<menu action='help-menu'>
<menuitem action='toggle-message-log'/>
<menuitem action='show-stats'/>
<separator/>
<menuitem action='donate'/>
<separator/>
<menuitem action='help'/>
<menuitem action='show-about-dialog'/>
</menu>
</menubar>
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.24"/>
<toolbar name='main-window-toolbar'>
<toolitem action='open-torrent-toolbar'/>
<toolitem action='torrent-start'/>
<toolitem action='torrent-stop'/>
<toolitem action='remove-torrent'/>
<separator/>
<toolitem action='show-torrent-properties'/>
</toolbar>
<menu id="main-window-menu">
<submenu>
<attribute name="label" translatable="true">_File</attribute>
<section>
<item>
<attribute name="action">win.open-torrent</attribute>
<attribute name="icon">document-open</attribute>
<attribute name="label" translatable="yes">_Open</attribute>
<attribute name="tooltip" translatable="yes">Open a torrent</attribute>
</item>
<item>
<attribute name="action">win.open-torrent-from-url</attribute>
<attribute name="icon">document-open</attribute>
<attribute name="label" translatable="yes">Open _URL…</attribute>
<attribute name="accel">&lt;control&gt;U</attribute>
<attribute name="tooltip" translatable="yes">Open URL…</attribute>
</item>
<item>
<attribute name="action">win.new-torrent</attribute>
<attribute name="icon">document-new</attribute>
<attribute name="label" translatable="yes">_New…</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.start-all-torrents</attribute>
<attribute name="icon">media-playback-start</attribute>
<attribute name="label" translatable="yes">_Start All</attribute>
<attribute name="tooltip" translatable="yes">Start all torrents</attribute>
</item>
<item>
<attribute name="action">win.pause-all-torrents</attribute>
<attribute name="icon">media-playback-pause</attribute>
<attribute name="label" translatable="yes">_Pause All</attribute>
<attribute name="tooltip" translatable="yes">Pause all torrents</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.quit</attribute>
<attribute name="icon">application-exit</attribute>
<attribute name="label" translatable="yes">_Quit</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="true">_Edit</attribute>
<section>
<item>
<attribute name="action">win.select-all</attribute>
<attribute name="icon">edit-select-all</attribute>
<attribute name="label" translatable="yes">Select _All</attribute>
<attribute name="accel">&lt;control&gt;A</attribute>
</item>
<item>
<attribute name="action">win.deselect-all</attribute>
<attribute name="label" translatable="yes">Dese_lect All</attribute>
<attribute name="accel">&lt;shift&gt;&lt;control&gt;A</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.edit-preferences</attribute>
<attribute name="icon">preferences-system</attribute>
<attribute name="label" translatable="yes">_Preferences</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="true">_Torrent</attribute>
<section>
<item>
<attribute name="action">win.show-torrent-properties</attribute>
<attribute name="icon">document-properties</attribute>
<attribute name="label" translatable="yes">_Properties</attribute>
<attribute name="accel">&lt;alt&gt;Return</attribute>
<attribute name="tooltip" translatable="yes">Torrent properties</attribute>
</item>
<item>
<attribute name="action">win.open-torrent-folder</attribute>
<attribute name="icon">document-open</attribute>
<attribute name="label" translatable="yes">Open Fold_er</attribute>
<attribute name="accel">&lt;control&gt;E</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.torrent-start</attribute>
<attribute name="icon">media-playback-start</attribute>
<attribute name="label" translatable="yes">_Start</attribute>
<attribute name="accel">&lt;control&gt;S</attribute>
<attribute name="tooltop" translatable="yes">Start torrent</attribute>
</item>
<item>
<attribute name="action">win.torrent-start-now</attribute>
<attribute name="icon">media-playback-start</attribute>
<attribute name="label" translatable="yes">Start _Now</attribute>
<attribute name="accel">&lt;shift&gt;&lt;control&gt;S</attribute>
<attribute name="tooltop" translatable="yes">Start torrent now</attribute>
</item>
<item>
<attribute name="action">win.torrent-reannounce</attribute>
<attribute name="icon">network-workgroup</attribute>
<attribute name="label" translatable="yes">Ask Tracker for _More Peers</attribute>
</item>
<submenu>
<attribute name="label" translatable="true">_Queue</attribute>
<section>
<item>
<attribute name="action">win.queue-move-top</attribute>
<attribute name="icon">go-top</attribute>
<attribute name="label" translatable="yes">Move to _Top</attribute>
</item>
<item>
<attribute name="action">win.queue-move-up</attribute>
<attribute name="icon">go-up</attribute>
<attribute name="label" translatable="yes">Move _Up</attribute>
</item>
<item>
<attribute name="action">win.queue-move-down</attribute>
<attribute name="icon">go-down</attribute>
<attribute name="label" translatable="yes">Move _Down</attribute>
</item>
<item>
<attribute name="action">win.queue-move-bottom</attribute>
<attribute name="icon">go-bottom</attribute>
<attribute name="label" translatable="yes">Move to _Bottom</attribute>
</item>
</section>
</submenu>
<item>
<attribute name="action">win.torrent-stop</attribute>
<attribute name="icon">media-playback-pause</attribute>
<attribute name="label" translatable="yes">_Pause</attribute>
<attribute name="accel">&lt;control&gt;P</attribute>
<attribute name="tooltip" translatable="yes">Pause torrent</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.relocate-torrent</attribute>
<attribute name="label" translatable="yes">Set _Location…</attribute>
</item>
<item>
<attribute name="action">win.torrent-verify</attribute>
<attribute name="label" translatable="yes">_Verify Local Data</attribute>
<attribute name="accel">&lt;control&gt;V</attribute>
</item>
<item>
<attribute name="action">win.copy-magnet-link-to-clipboard</attribute>
<attribute name="icon">edit-copy</attribute>
<attribute name="label" translatable="yes">Copy _Magnet Link to Clipboard</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.remove-torrent</attribute>
<attribute name="icon">list-remove</attribute>
<attribute name="label" translatable="yes">Remove torrent</attribute>
<attribute name="accel">Delete</attribute>
</item>
<item>
<attribute name="action">win.delete-torrent</attribute>
<attribute name="icon">edit-delete</attribute>
<attribute name="label" translatable="yes">_Delete Files and Remove</attribute>
<attribute name="accel">&lt;shift&gt;Delete</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="true">_View</attribute>
<section>
<item>
<attribute name="action">win.compact-view</attribute>
<attribute name="label" translatable="yes">_Compact View</attribute>
<attribute name="accel">&lt;alt&gt;C</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.show-toolbar</attribute>
<attribute name="label" translatable="yes">_Toolbar</attribute>
</item>
<item>
<attribute name="action">win.show-filterbar</attribute>
<attribute name="label" translatable="yes">_Filterbar</attribute>
</item>
<item>
<attribute name="action">win.show-statusbar</attribute>
<attribute name="label" translatable="yes">_Statusbar</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by _Activity</attribute>
<attribute name="target">sort-by-activity</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by A_ge</attribute>
<attribute name="target">sort-by-age</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by _Name</attribute>
<attribute name="target">sort-by-name</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by _Progress</attribute>
<attribute name="target">sort-by-progress</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by _Queue</attribute>
<attribute name="target">sort-by-queue</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by Rati_o</attribute>
<attribute name="target">sort-by-ratio</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by Si_ze</attribute>
<attribute name="target">sort-by-size</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by Stat_e</attribute>
<attribute name="target">sort-by-state</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by Time _Left</attribute>
<attribute name="target">sort-by-time-left</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.sort-reversed</attribute>
<attribute name="label" translatable="yes">Re_verse Sort Order</attribute>
</item>
</section>
</submenu>
<submenu>
<attribute name="label" translatable="true">_Help</attribute>
<section>
<item>
<attribute name="action">win.toggle-message-log</attribute>
<attribute name="label" translatable="yes">Message _Log</attribute>
</item>
<item>
<attribute name="action">win.show-stats</attribute>
<attribute name="label" translatable="yes">_Statistics</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.donate</attribute>
<attribute name="label" translatable="yes">_Donate</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.help</attribute>
<attribute name="icon">help-browser</attribute>
<attribute name="label" translatable="yes">_Contents</attribute>
<attribute name="accel">F1</attribute>
</item>
<item>
<attribute name="action">win.show-about-dialog</attribute>
<attribute name="icon">help-about</attribute>
<attribute name="label" translatable="yes">_About</attribute>
</item>
</section>
</submenu>
</menu>
<popup name='main-window-popup'>
<menuitem action='show-torrent-properties'/>
<menuitem action='open-torrent-folder'/>
<separator/>
<menu action='sort-menu'>
<menuitem action='sort-by-activity'/>
<menuitem action='sort-by-age'/>
<menuitem action='sort-by-name'/>
<menuitem action='sort-by-progress'/>
<menuitem action='sort-by-queue'/>
<menuitem action='sort-by-ratio'/>
<menuitem action='sort-by-size'/>
<menuitem action='sort-by-state'/>
<menuitem action='sort-by-time-left'/>
<separator/>
<menuitem action='sort-reversed'/>
</menu>
<separator/>
<menuitem action='torrent-start'/>
<menuitem action='torrent-start-now'/>
<menuitem action='torrent-reannounce'/>
<menu action='queue-menu'>
<menuitem action='queue-move-top'/>
<menuitem action='queue-move-up'/>
<menuitem action='queue-move-down'/>
<menuitem action='queue-move-bottom'/>
</menu>
<menuitem action='torrent-stop'/>
<separator/>
<menuitem action='relocate-torrent'/>
<menuitem action='torrent-verify'/>
<menuitem action='copy-magnet-link-to-clipboard'/>
<separator/>
<menuitem action='remove-torrent'/>
<menuitem action='delete-torrent'/>
</popup>
<object class="GtkToolbar" id="main-window-toolbar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkToolButton">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Open a torrent</property>
<property name="is-important">True</property>
<property name="action-name">win.open-torrent</property>
<property name="label" translatable="yes">_Open</property>
<property name="use-underline">True</property>
<property name="icon-name">document-open</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
<child>
<object class="GtkToolButton">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Start torrent</property>
<property name="action-name">win.torrent-start</property>
<property name="label" translatable="yes">_Start</property>
<property name="use-underline">True</property>
<property name="icon-name">media-playback-start</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
<child>
<object class="GtkToolButton">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Pause torrent</property>
<property name="action-name">win.torrent-stop</property>
<property name="label" translatable="yes">_Pause</property>
<property name="use-underline">True</property>
<property name="icon-name">media-playback-pause</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
<child>
<object class="GtkToolButton">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="action-name">win.remove-torrent</property>
<property name="label" translatable="yes">Remove torrent</property>
<property name="use-underline">True</property>
<property name="icon-name">list-remove</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
<child>
<object class="GtkSeparatorToolItem">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">True</property>
</packing>
</child>
<child>
<object class="GtkToolButton">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Torrent properties</property>
<property name="is-important">True</property>
<property name="action-name">win.show-torrent-properties</property>
<property name="label" translatable="yes">_Properties</property>
<property name="use-underline">True</property>
<property name="icon-name">document-properties</property>
</object>
<packing>
<property name="expand">False</property>
<property name="homogeneous">False</property>
</packing>
</child>
</object>
<popup name='icon-popup'>
<menuitem action='toggle-main-window'/>
<separator/>
<menuitem action='open-torrent-menu'/>
<menuitem action='open-torrent-from-url'/>
<separator/>
<menuitem action='pause-all-torrents'/>
<menuitem action='start-all-torrents'/>
<separator/>
<menuitem action='alt-speed-enabled'/>
<separator/>
<menuitem action='quit'/>
</popup>
</ui>
<menu id="main-window-popup">
<section>
<item>
<attribute name="action">win.show-torrent-properties</attribute>
<attribute name="icon">document-properties</attribute>
<attribute name="label" translatable="yes">_Properties</attribute>
<attribute name="accel">&lt;alt&gt;Return</attribute>
<attribute name="tooltip" translatable="yes">Torrent properties</attribute>
</item>
<item>
<attribute name="action">win.open-torrent-folder</attribute>
<attribute name="icon">document-open</attribute>
<attribute name="label" translatable="yes">Open Fold_er</attribute>
<attribute name="accel">&lt;control&gt;E</attribute>
</item>
</section>
<section>
<submenu>
<attribute name="label" translatable="true">_Sort Torrents By</attribute>
<section>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by _Activity</attribute>
<attribute name="target">sort-by-activity</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by A_ge</attribute>
<attribute name="target">sort-by-age</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by _Name</attribute>
<attribute name="target">sort-by-name</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by _Progress</attribute>
<attribute name="target">sort-by-progress</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by _Queue</attribute>
<attribute name="target">sort-by-queue</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by Rati_o</attribute>
<attribute name="target">sort-by-ratio</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by Si_ze</attribute>
<attribute name="target">sort-by-size</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by Stat_e</attribute>
<attribute name="target">sort-by-state</attribute>
</item>
<item>
<attribute name="action">win.sort-torrents</attribute>
<attribute name="label" translatable="yes">Sort by Time _Left</attribute>
<attribute name="target">sort-by-time-left</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.sort-reversed</attribute>
<attribute name="label" translatable="yes">Re_verse Sort Order</attribute>
</item>
</section>
</submenu>
</section>
<section>
<item>
<attribute name="action">win.torrent-start</attribute>
<attribute name="icon">media-playback-start</attribute>
<attribute name="label" translatable="yes">_Start</attribute>
<attribute name="accel">&lt;control&gt;S</attribute>
<attribute name="tooltop" translatable="yes">Start torrent</attribute>
</item>
<item>
<attribute name="action">win.torrent-start-now</attribute>
<attribute name="icon">media-playback-start</attribute>
<attribute name="label" translatable="yes">Start _Now</attribute>
<attribute name="accel">&lt;shift&gt;&lt;control&gt;S</attribute>
<attribute name="tooltop" translatable="yes">Start torrent now</attribute>
</item>
<item>
<attribute name="action">win.torrent-reannounce</attribute>
<attribute name="icon">network-workgroup</attribute>
<attribute name="label" translatable="yes">Ask Tracker for _More Peers</attribute>
</item>
<submenu>
<attribute name="label" translatable="true">_Queue</attribute>
<section>
<item>
<attribute name="action">win.queue-move-top</attribute>
<attribute name="icon">go-top</attribute>
<attribute name="label" translatable="yes">Move to _Top</attribute>
</item>
<item>
<attribute name="action">win.queue-move-up</attribute>
<attribute name="icon">go-up</attribute>
<attribute name="label" translatable="yes">Move _Up</attribute>
</item>
<item>
<attribute name="action">win.queue-move-down</attribute>
<attribute name="icon">go-down</attribute>
<attribute name="label" translatable="yes">Move _Down</attribute>
</item>
<item>
<attribute name="action">win.queue-move-bottom</attribute>
<attribute name="icon">go-bottom</attribute>
<attribute name="label" translatable="yes">Move to _Bottom</attribute>
</item>
</section>
</submenu>
<item>
<attribute name="action">win.torrent-stop</attribute>
<attribute name="icon">media-playback-pause</attribute>
<attribute name="label" translatable="yes">_Pause</attribute>
<attribute name="accel">&lt;control&gt;P</attribute>
<attribute name="tooltip" translatable="yes">Pause torrent</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.relocate-torrent</attribute>
<attribute name="label" translatable="yes">Set _Location…</attribute>
</item>
<item>
<attribute name="action">win.torrent-verify</attribute>
<attribute name="label" translatable="yes">_Verify Local Data</attribute>
<attribute name="accel">&lt;control&gt;V</attribute>
</item>
<item>
<attribute name="action">win.copy-magnet-link-to-clipboard</attribute>
<attribute name="icon">edit-copy</attribute>
<attribute name="label" translatable="yes">Copy _Magnet Link to Clipboard</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.remove-torrent</attribute>
<attribute name="icon">list-remove</attribute>
<attribute name="label" translatable="yes">Remove torrent</attribute>
<attribute name="accel">Delete</attribute>
</item>
<item>
<attribute name="action">win.delete-torrent</attribute>
<attribute name="icon">edit-delete</attribute>
<attribute name="label" translatable="yes">_Delete Files and Remove</attribute>
<attribute name="accel">&lt;shift&gt;Delete</attribute>
</item>
</section>
</menu>
<menu id="icon-popup">
<section>
<item>
<attribute name="action">win.toggle-main-window</attribute>
<attribute name="label" translatable="yes">_Show Transmission</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.open-torrent</attribute>
<attribute name="icon">document-open</attribute>
<attribute name="label" translatable="yes">_Open</attribute>
<attribute name="tooltip" translatable="yes">Open a torrent</attribute>
</item>
<item>
<attribute name="action">win.open-torrent-from-url</attribute>
<attribute name="icon">document-open</attribute>
<attribute name="label" translatable="yes">Open _URL…</attribute>
<attribute name="accel"></attribute>
<attribute name="tooltip" translatable="yes">Open URL…</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.pause-all-torrents</attribute>
<attribute name="icon">media-playback-pause</attribute>
<attribute name="label" translatable="yes">_Pause All</attribute>
<attribute name="tooltip" translatable="yes">Pause all torrents</attribute>
</item>
<item>
<attribute name="action">win.start-all-torrents</attribute>
<attribute name="icon">media-playback-start</attribute>
<attribute name="label" translatable="yes">_Start All</attribute>
<attribute name="tooltip" translatable="yes">Start all torrents</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.alt-speed-enabled</attribute>
<attribute name="label" translatable="yes">Enable Alternative Speed _Limits</attribute>
</item>
</section>
<section>
<item>
<attribute name="action">win.quit</attribute>
<attribute name="icon">application-exit</attribute>
<attribute name="label" translatable="yes">_Quit</attribute>
</item>
</section>
</menu>
</interface>

View File

@ -1,13 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/com/transmissionbt/transmission">
<file alias="icons/logo-24.png">icons/hicolor_apps_scalable_transmission.svg</file>
<file alias="icons/logo-48.png">icons/hicolor_apps_scalable_transmission.svg</file>
<file>icons/lock.png</file>
<file>icons/ratio.png</file>
<file>icons/turtle-blue.png</file>
<file>icons/turtle-grey.png</file>
<file>icons/utilities.png</file>
<file>transmission-ui.xml</file>
</gresource>
</gresources>
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/com/transmissionbt/transmission">
<file alias="icons/scalable/panel/transmission-main-window-icon.svg" compressed="true" preprocess="xml-stripblanks">icons/hicolor_apps_scalable_transmission.svg</file>
<file alias="icons/scalable/panel/transmission-notification-icon.svg" compressed="true" preprocess="xml-stripblanks">icons/hicolor_apps_scalable_transmission.svg</file>
<file alias="icons/scalable/panel/transmission-tray-icon.svg" compressed="true" preprocess="xml-stripblanks">icons/hicolor_apps_scalable_transmission.svg</file>
<file alias="icons/16x16/actions/lock.png">icons/lock.png</file>
<file alias="icons/16x16/status/ratio.png">icons/ratio.png</file>
<file alias="icons/16x16/status/alt-speed-on.png">icons/turtle-blue.png</file>
<file alias="icons/16x16/status/alt-speed-off.png">icons/turtle-grey.png</file>
<file alias="icons/16x16/status/utilities.png">icons/utilities.png</file>
<file compressed="true" preprocess="xml-stripblanks">transmission-ui.xml</file>
</gresource>
</gresources>