2023-11-01 21:11:11 +00:00
|
|
|
// This file Copyright © Mnemosyne LLC.
|
2022-08-08 18:05:39 +00:00
|
|
|
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
2022-01-20 18:27:56 +00:00
|
|
|
// or any future license endorsed by Mnemosyne LLC.
|
|
|
|
// License text can be found in the licenses/ folder.
|
2009-07-22 15:55:48 +00:00
|
|
|
|
2016-03-29 16:37:21 +00:00
|
|
|
#pragma once
|
2006-07-16 19:39:23 +00:00
|
|
|
|
2022-12-29 02:42:20 +00:00
|
|
|
#include "GtkCompat.h"
|
|
|
|
|
2022-12-26 21:13:21 +00:00
|
|
|
#include <libtransmission/transmission.h>
|
|
|
|
#include <libtransmission/tr-macros.h>
|
2023-11-16 04:15:40 +00:00
|
|
|
#include <libtransmission/values.h>
|
2022-12-26 21:13:21 +00:00
|
|
|
|
2022-12-27 01:43:20 +00:00
|
|
|
#include <glibmm/objectbase.h>
|
|
|
|
#include <glibmm/refptr.h>
|
|
|
|
#include <glibmm/signalproxy.h>
|
|
|
|
#include <glibmm/ustring.h>
|
|
|
|
#include <gtkmm/builder.h>
|
|
|
|
#include <gtkmm/combobox.h>
|
|
|
|
#include <gtkmm/entry.h>
|
|
|
|
#include <gtkmm/label.h>
|
|
|
|
#include <gtkmm/treeview.h>
|
|
|
|
#include <gtkmm/widget.h>
|
|
|
|
#include <gtkmm/window.h>
|
2022-12-26 21:13:21 +00:00
|
|
|
|
2023-08-06 03:26:29 +00:00
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
|
|
#include <gtkmm/listview.h>
|
|
|
|
#endif
|
|
|
|
|
2022-12-26 21:13:21 +00:00
|
|
|
#include <fmt/core.h>
|
|
|
|
|
2022-04-25 01:49:52 +00:00
|
|
|
#include <cstddef>
|
2024-01-08 14:32:58 +00:00
|
|
|
#include <cstdint>
|
2022-01-13 02:13:58 +00:00
|
|
|
#include <ctime>
|
2021-10-18 20:22:31 +00:00
|
|
|
#include <functional>
|
2022-08-22 02:26:13 +00:00
|
|
|
#include <list>
|
2021-12-14 08:43:27 +00:00
|
|
|
#include <string>
|
2022-10-08 22:50:03 +00:00
|
|
|
#include <type_traits>
|
2022-08-17 16:08:36 +00:00
|
|
|
#include <utility>
|
2022-04-08 01:50:26 +00:00
|
|
|
#include <vector>
|
2021-12-14 08:43:27 +00:00
|
|
|
|
2006-07-16 19:39:23 +00:00
|
|
|
#include <sys/types.h>
|
2021-11-01 00:11:23 +00:00
|
|
|
|
2022-09-10 13:19:54 +00:00
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2022-11-13 17:36:16 +00:00
|
|
|
void gtr_message(std::string const& message);
|
|
|
|
void gtr_warning(std::string const& message);
|
|
|
|
void gtr_error(std::string const& message);
|
|
|
|
|
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2024-01-08 14:32:58 +00:00
|
|
|
enum class GtrUnicode : uint8_t
|
2010-03-20 14:53:08 +00:00
|
|
|
{
|
2022-02-09 02:25:19 +00:00
|
|
|
Up,
|
|
|
|
Down,
|
|
|
|
Inf,
|
|
|
|
Bullet
|
2010-03-20 14:53:08 +00:00
|
|
|
};
|
2017-04-19 12:04:45 +00:00
|
|
|
|
2023-01-21 12:06:20 +00:00
|
|
|
Glib::ustring gtr_get_unicode_string(GtrUnicode uni);
|
2010-03-20 14:53:08 +00:00
|
|
|
|
2007-12-19 02:46:30 +00:00
|
|
|
/* return a human-readable string for the size given in bytes. */
|
2022-11-09 16:58:36 +00:00
|
|
|
Glib::ustring tr_strlsize(guint64 size_in_bytes);
|
2023-11-16 04:15:40 +00:00
|
|
|
Glib::ustring tr_strlsize(libtransmission::Values::Storage const& storage);
|
2007-06-06 00:30:13 +00:00
|
|
|
|
2008-01-04 18:52:39 +00:00
|
|
|
/* return a human-readable string for the given ratio. */
|
2021-10-18 20:22:31 +00:00
|
|
|
Glib::ustring tr_strlratio(double ratio);
|
2008-01-04 18:52:39 +00:00
|
|
|
|
2022-11-09 16:58:36 +00:00
|
|
|
std::string tr_format_time_relative(time_t timestamp, time_t origin);
|
|
|
|
std::string tr_format_time_left(time_t timestamp);
|
|
|
|
std::string tr_format_time(time_t timestamp);
|
2006-07-16 19:39:23 +00:00
|
|
|
|
2009-07-22 15:55:48 +00:00
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
2006-07-16 19:39:23 +00:00
|
|
|
|
2022-12-21 21:26:25 +00:00
|
|
|
using TrObjectSignalNotifyCallback = void(Glib::RefPtr<Glib::ObjectBase const> const&);
|
|
|
|
|
|
|
|
Glib::SignalProxy<TrObjectSignalNotifyCallback> gtr_object_signal_notify(Glib::ObjectBase& object);
|
|
|
|
void gtr_object_notify_emit(Glib::ObjectBase& object);
|
|
|
|
|
2023-08-06 03:26:29 +00:00
|
|
|
template<typename T>
|
|
|
|
inline GParamSpec* gtr_get_param_spec(char const* name, char const* nick, char const* blurb)
|
|
|
|
{
|
|
|
|
auto dummy_value = Glib::Value<T>();
|
|
|
|
dummy_value.init(decltype(dummy_value)::value_type());
|
|
|
|
|
|
|
|
return dummy_value.create_param_spec(name, nick, blurb, TR_GLIB_PARAM_FLAGS(READABLE));
|
|
|
|
}
|
|
|
|
|
2021-10-18 20:22:31 +00:00
|
|
|
void gtr_open_uri(Glib::ustring const& uri);
|
2010-09-22 16:44:38 +00:00
|
|
|
|
2021-10-18 20:22:31 +00:00
|
|
|
void gtr_open_file(std::string const& path);
|
2008-04-11 02:21:33 +00:00
|
|
|
|
2021-10-18 20:22:31 +00:00
|
|
|
Glib::ustring gtr_get_help_uri();
|
2008-05-18 16:44:30 +00:00
|
|
|
|
2009-07-22 15:55:48 +00:00
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2017-04-21 07:40:57 +00:00
|
|
|
/* backwards-compatible wrapper around gtk_widget_set_visible() */
|
2022-11-14 16:22:38 +00:00
|
|
|
void gtr_widget_set_visible(Gtk::Widget& widget, bool is_visible);
|
2010-07-24 03:07:04 +00:00
|
|
|
|
2022-11-13 17:36:16 +00:00
|
|
|
Gtk::Window& gtr_widget_get_window(Gtk::Widget& widget);
|
|
|
|
|
2022-10-08 22:50:03 +00:00
|
|
|
void gtr_window_set_skip_taskbar_hint(Gtk::Window& window, bool value);
|
|
|
|
void gtr_window_set_urgency_hint(Gtk::Window& window, bool value);
|
|
|
|
void gtr_window_raise(Gtk::Window& window);
|
2010-12-22 03:12:47 +00:00
|
|
|
|
2010-02-02 07:51:45 +00:00
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2022-09-07 22:25:04 +00:00
|
|
|
void gtr_priority_combo_init(Gtk::ComboBox& combo);
|
2010-07-23 06:54:49 +00:00
|
|
|
|
2022-09-07 22:25:04 +00:00
|
|
|
void gtr_combo_box_set_enum(Gtk::ComboBox& combo, std::vector<std::pair<Glib::ustring, int>> const& items);
|
2023-01-21 12:06:20 +00:00
|
|
|
int gtr_combo_box_get_active_enum(Gtk::ComboBox const& combo);
|
|
|
|
void gtr_combo_box_set_active_enum(Gtk::ComboBox& combo, int value);
|
2010-02-02 07:51:45 +00:00
|
|
|
|
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2021-10-18 20:22:31 +00:00
|
|
|
void gtr_unrecognized_url_dialog(Gtk::Widget& parent, Glib::ustring const& url);
|
2010-02-05 13:59:44 +00:00
|
|
|
|
2021-12-24 22:05:17 +00:00
|
|
|
void gtr_add_torrent_error_dialog(Gtk::Widget& window_or_child, tr_torrent* duplicate_torrent, std::string const& filename);
|
2006-07-16 19:39:23 +00:00
|
|
|
|
2007-06-18 03:40:41 +00:00
|
|
|
/* pop up the context menu if a user right-clicks.
|
|
|
|
if the row they right-click on isn't selected, select it. */
|
2023-08-06 03:26:29 +00:00
|
|
|
bool on_item_view_button_pressed(
|
2022-10-08 22:50:03 +00:00
|
|
|
Gtk::TreeView& view,
|
2022-11-14 18:27:15 +00:00
|
|
|
double event_x,
|
|
|
|
double event_y,
|
2022-10-08 22:50:03 +00:00
|
|
|
bool context_menu_requested,
|
|
|
|
std::function<void(double, double)> const& callback = {});
|
2023-08-06 03:26:29 +00:00
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
|
|
bool on_item_view_button_pressed(
|
|
|
|
Gtk::ListView& view,
|
|
|
|
double event_x,
|
|
|
|
double event_y,
|
|
|
|
bool context_menu_requested,
|
|
|
|
std::function<void(double, double)> const& callback = {});
|
|
|
|
#endif
|
2007-06-18 03:40:41 +00:00
|
|
|
|
2008-09-27 18:01:31 +00:00
|
|
|
/* if the click didn't specify a row, clear the selection */
|
2023-08-06 03:26:29 +00:00
|
|
|
bool on_item_view_button_released(Gtk::TreeView& view, double event_x, double event_y);
|
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
|
|
bool on_item_view_button_released(Gtk::ListView& view, double event_x, double event_y);
|
|
|
|
#endif
|
2022-10-08 22:50:03 +00:00
|
|
|
|
|
|
|
using TrGdkModifierType = IF_GTKMM4(Gdk::ModifierType, guint);
|
|
|
|
|
2023-08-06 03:26:29 +00:00
|
|
|
void setup_item_view_button_event_handling(
|
2022-10-08 22:50:03 +00:00
|
|
|
Gtk::TreeView& view,
|
|
|
|
std::function<bool(guint, TrGdkModifierType, double, double, bool)> const& press_callback,
|
|
|
|
std::function<bool(double, double)> const& release_callback);
|
2023-08-06 03:26:29 +00:00
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
|
|
void setup_item_view_button_event_handling(
|
|
|
|
Gtk::ListView& view,
|
|
|
|
std::function<bool(guint, TrGdkModifierType, double, double, bool)> const& press_callback,
|
|
|
|
std::function<bool(double, double)> const& release_callback);
|
|
|
|
#endif
|
2008-01-15 17:55:09 +00:00
|
|
|
|
2009-07-22 15:55:48 +00:00
|
|
|
/* move a file to the trashcan if GIO is available; otherwise, delete it */
|
2023-11-04 16:39:41 +00:00
|
|
|
bool gtr_file_trash_or_remove(std::string const& filename, tr_error* error = nullptr);
|
2008-03-09 15:27:08 +00:00
|
|
|
|
2021-10-18 20:22:31 +00:00
|
|
|
void gtr_paste_clipboard_url_into_entry(Gtk::Entry& entry);
|
2011-01-14 21:57:20 +00:00
|
|
|
|
2017-04-21 07:40:57 +00:00
|
|
|
/* Only call gtk_label_set_text() if the new text differs from the old.
|
2011-01-21 16:32:27 +00:00
|
|
|
* This prevents the label from having to recalculate its size
|
|
|
|
* and prevents selected text in the label from being deselected */
|
2021-10-18 20:22:31 +00:00
|
|
|
void gtr_label_set_text(Gtk::Label& lb, Glib::ustring const& text);
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline T gtr_str_strip(T const& text)
|
|
|
|
{
|
|
|
|
auto const new_begin = text.find_first_not_of("\t\n\v\f\r ");
|
|
|
|
auto const new_end = text.find_last_not_of("\t\n\v\f\r ");
|
2021-10-28 20:52:25 +00:00
|
|
|
return new_begin == T::npos ? T() : text.substr(new_begin, new_end == T::npos ? new_end : new_end - new_begin + 1);
|
2021-10-18 20:22:31 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 08:43:27 +00:00
|
|
|
std::string gtr_get_full_resource_path(std::string const& rel_path);
|
|
|
|
|
2022-08-22 02:26:13 +00:00
|
|
|
/***
|
|
|
|
****
|
|
|
|
***/
|
|
|
|
|
2022-12-21 21:26:25 +00:00
|
|
|
class Session;
|
|
|
|
|
2022-08-22 02:26:13 +00:00
|
|
|
extern size_t const max_recent_dirs;
|
|
|
|
std::list<std::string> gtr_get_recent_dirs(std::string const& pref);
|
|
|
|
void gtr_save_recent_dir(std::string const& pref, Glib::RefPtr<Session> const& core, std::string const& dir);
|
|
|
|
|
2021-11-12 09:12:50 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
inline Glib::RefPtr<T> gtr_ptr_static_cast(Glib::RefPtr<U> const& ptr)
|
|
|
|
{
|
2022-12-29 02:42:20 +00:00
|
|
|
#if GLIBMM_CHECK_VERSION(2, 68, 0)
|
2021-11-12 09:12:50 +00:00
|
|
|
return std::static_pointer_cast<T>(ptr);
|
2022-12-29 02:42:20 +00:00
|
|
|
#else
|
|
|
|
return Glib::RefPtr<T>::cast_static(ptr);
|
2021-11-12 09:12:50 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-10-08 22:50:03 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
inline Glib::RefPtr<T> gtr_ptr_dynamic_cast(Glib::RefPtr<U> const& ptr)
|
|
|
|
{
|
2022-12-29 02:42:20 +00:00
|
|
|
#if GLIBMM_CHECK_VERSION(2, 68, 0)
|
2022-10-08 22:50:03 +00:00
|
|
|
return std::dynamic_pointer_cast<T>(ptr);
|
2022-12-29 02:42:20 +00:00
|
|
|
#else
|
|
|
|
return Glib::RefPtr<T>::cast_dynamic(ptr);
|
2022-10-08 22:50:03 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-10-18 20:22:31 +00:00
|
|
|
template<>
|
|
|
|
struct std::hash<Glib::ustring>
|
|
|
|
{
|
|
|
|
std::size_t operator()(Glib::ustring const& s) const
|
|
|
|
{
|
|
|
|
return std::hash<std::string>()(s.raw());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-03-21 14:15:48 +00:00
|
|
|
template<>
|
|
|
|
struct fmt::formatter<Glib::ustring> : formatter<std::string>
|
|
|
|
{
|
|
|
|
template<typename FormatContext>
|
|
|
|
auto format(Glib::ustring const& ustr, FormatContext& ctx) const
|
|
|
|
{
|
|
|
|
return formatter<std::string>::format(ustr.raw(), ctx);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-10-08 22:50:03 +00:00
|
|
|
template<typename T>
|
|
|
|
T* gtr_get_widget(Glib::RefPtr<Gtk::Builder> const& builder, Glib::ustring const& name)
|
2022-09-07 22:25:04 +00:00
|
|
|
{
|
2022-10-08 22:50:03 +00:00
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
|
|
return builder->get_widget<T>(name);
|
|
|
|
#else
|
2022-09-07 22:25:04 +00:00
|
|
|
T* widget = nullptr;
|
2022-10-08 22:50:03 +00:00
|
|
|
builder->get_widget(name, widget);
|
2022-09-07 22:25:04 +00:00
|
|
|
return widget;
|
2022-10-08 22:50:03 +00:00
|
|
|
#endif
|
2022-09-07 22:25:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename... ArgTs>
|
|
|
|
T* gtr_get_widget_derived(Glib::RefPtr<Gtk::Builder> const& builder, Glib::ustring const& name, ArgTs&&... args)
|
|
|
|
{
|
2022-10-08 22:50:03 +00:00
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
|
|
return Gtk::Builder::get_widget_derived<T>(builder, name, std::forward<ArgTs>(args)...);
|
|
|
|
#else
|
2022-09-07 22:25:04 +00:00
|
|
|
T* widget = nullptr;
|
|
|
|
builder->get_widget_derived(name, widget, std::forward<ArgTs>(args)...);
|
|
|
|
return widget;
|
2022-10-08 22:50:03 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename F>
|
|
|
|
void gtr_window_on_close(Gtk::Window& widget, F&& callback)
|
|
|
|
{
|
2023-08-22 02:59:47 +00:00
|
|
|
auto bool_callback = [callback = std::move(callback)]() mutable -> bool
|
2022-10-08 22:50:03 +00:00
|
|
|
{
|
|
|
|
if constexpr (std::is_same_v<void, std::invoke_result_t<decltype(callback)>>)
|
|
|
|
{
|
|
|
|
callback();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return callback();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
|
|
widget.signal_close_request().connect(bool_callback, false);
|
|
|
|
#else
|
|
|
|
widget.signal_delete_event().connect(sigc::hide<0>(bool_callback), false);
|
|
|
|
#endif
|
2022-09-07 22:25:04 +00:00
|
|
|
}
|