mirror of
https://github.com/transmission/transmission
synced 2025-03-17 17:25:32 +00:00
Defaults to `OFF`. Downstream packagers are advised against enabling it as we can't guarantee it working on every possible configuration. Added the actual compile flag in the GTK client subdirectory and not the top-level CMakeLists.txt file due to other subprojects not being ready. Fixed the only GTK client warning reported by Clang on Mac.
267 lines
6.4 KiB
C++
267 lines
6.4 KiB
C++
// This file Copyright © 2022 Mnemosyne LLC.
|
|
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
|
// or any future license endorsed by Mnemosyne LLC.
|
|
// License text can be found in the licenses/ folder.
|
|
|
|
#include <vector>
|
|
|
|
#include <glibmm.h>
|
|
#include <glibmm/i18n.h>
|
|
|
|
#include "PathButton.h"
|
|
|
|
class PathButton::Impl
|
|
{
|
|
public:
|
|
explicit Impl(PathButton& widget);
|
|
~Impl() = default;
|
|
|
|
TR_DISABLE_COPY_MOVE(Impl)
|
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
std::string const& get_filename() const;
|
|
void set_filename(std::string const& value);
|
|
|
|
void set_shortcut_folders(std::list<std::string> const& value);
|
|
|
|
void add_filter(Glib::RefPtr<Gtk::FileFilter> const& value);
|
|
|
|
Glib::Property<Gtk::FileChooser::Action>& property_action();
|
|
Glib::Property<Glib::ustring>& property_title();
|
|
|
|
sigc::signal<void()>& signal_selection_changed();
|
|
#endif
|
|
|
|
private:
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
void show_dialog();
|
|
|
|
void update();
|
|
void update_mode();
|
|
#endif
|
|
|
|
private:
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
PathButton& widget_;
|
|
|
|
Glib::Property<Gtk::FileChooser::Action> action_;
|
|
Glib::Property<Glib::ustring> title_;
|
|
|
|
sigc::signal<void()> selection_changed_;
|
|
|
|
Gtk::Image* const image_ = nullptr;
|
|
Gtk::Label* const label_ = nullptr;
|
|
Gtk::Image* const mode_ = nullptr;
|
|
|
|
std::string current_file_;
|
|
std::list<std::string> shortcut_folders_;
|
|
std::vector<Glib::RefPtr<Gtk::FileFilter>> filters_;
|
|
#endif
|
|
};
|
|
|
|
PathButton::Impl::Impl([[maybe_unused]] PathButton& widget)
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
: widget_(widget)
|
|
, action_(widget, "action", Gtk::FileChooser::Action::OPEN)
|
|
, title_(widget, "title", {})
|
|
, image_(Gtk::make_managed<Gtk::Image>())
|
|
, label_(Gtk::make_managed<Gtk::Label>())
|
|
, mode_(Gtk::make_managed<Gtk::Image>())
|
|
#endif
|
|
{
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
action_.get_proxy().signal_changed().connect([this]() { update_mode(); });
|
|
|
|
label_->set_ellipsize(Pango::EllipsizeMode::END);
|
|
label_->set_hexpand(true);
|
|
label_->set_halign(Gtk::Align::START);
|
|
|
|
auto* const layout = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 5);
|
|
layout->append(*image_);
|
|
layout->append(*label_);
|
|
layout->append(*Gtk::make_managed<Gtk::Separator>(Gtk::Orientation::VERTICAL));
|
|
layout->append(*mode_);
|
|
widget_.set_child(*layout);
|
|
|
|
widget_.signal_clicked().connect(sigc::mem_fun(*this, &Impl::show_dialog));
|
|
|
|
update();
|
|
update_mode();
|
|
#endif
|
|
}
|
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
|
|
std::string const& PathButton::Impl::get_filename() const
|
|
{
|
|
return current_file_;
|
|
}
|
|
|
|
void PathButton::Impl::set_filename(std::string const& value)
|
|
{
|
|
current_file_ = value;
|
|
update();
|
|
selection_changed_.emit();
|
|
}
|
|
|
|
void PathButton::Impl::set_shortcut_folders(std::list<std::string> const& value)
|
|
{
|
|
shortcut_folders_ = value;
|
|
}
|
|
|
|
void PathButton::Impl::add_filter(Glib::RefPtr<Gtk::FileFilter> const& value)
|
|
{
|
|
filters_.push_back(value);
|
|
}
|
|
|
|
Glib::Property<Gtk::FileChooser::Action>& PathButton::Impl::property_action()
|
|
{
|
|
return action_;
|
|
}
|
|
|
|
Glib::Property<Glib::ustring>& PathButton::Impl::property_title()
|
|
{
|
|
return title_;
|
|
}
|
|
|
|
sigc::signal<void()>& PathButton::Impl::signal_selection_changed()
|
|
{
|
|
return selection_changed_;
|
|
}
|
|
|
|
void PathButton::Impl::show_dialog()
|
|
{
|
|
auto const title = title_.get_value();
|
|
|
|
auto dialog = std::make_shared<Gtk::FileChooserDialog>(!title.empty() ? title : _("Select a File"), action_.get_value());
|
|
dialog->set_transient_for(gtr_widget_get_window(widget_));
|
|
dialog->add_button(_("_Cancel"), Gtk::ResponseType::CANCEL);
|
|
dialog->add_button(_("_Open"), Gtk::ResponseType::ACCEPT);
|
|
dialog->set_modal(true);
|
|
|
|
if (!current_file_.empty())
|
|
{
|
|
dialog->set_file(Gio::File::create_for_path(current_file_));
|
|
}
|
|
|
|
for (auto const& folder : shortcut_folders_)
|
|
{
|
|
dialog->remove_shortcut_folder(Gio::File::create_for_path(folder));
|
|
dialog->add_shortcut_folder(Gio::File::create_for_path(folder));
|
|
}
|
|
|
|
for (auto const& filter : filters_)
|
|
{
|
|
dialog->add_filter(filter);
|
|
}
|
|
|
|
dialog->signal_response().connect(
|
|
[this, dialog](int response) mutable
|
|
{
|
|
if (response == Gtk::ResponseType::ACCEPT)
|
|
{
|
|
set_filename(dialog->get_file()->get_path());
|
|
selection_changed_.emit();
|
|
}
|
|
|
|
dialog.reset();
|
|
});
|
|
|
|
dialog->show();
|
|
}
|
|
|
|
void PathButton::Impl::update()
|
|
{
|
|
if (!current_file_.empty())
|
|
{
|
|
auto const file = Gio::File::create_for_path(current_file_);
|
|
|
|
try
|
|
{
|
|
image_->set(file->query_info()->get_icon());
|
|
}
|
|
catch (Glib::Error const&)
|
|
{
|
|
image_->set_from_icon_name("image-missing");
|
|
}
|
|
|
|
label_->set_text(file->get_basename());
|
|
}
|
|
else
|
|
{
|
|
image_->set_from_icon_name("image-missing");
|
|
label_->set_text(_("(None)"));
|
|
}
|
|
|
|
widget_.set_tooltip_text(current_file_);
|
|
}
|
|
|
|
void PathButton::Impl::update_mode()
|
|
{
|
|
mode_->set_from_icon_name(
|
|
action_.get_value() == Gtk::FileChooser::Action::SELECT_FOLDER ? "folder-open-symbolic" : "document-open-symbolic");
|
|
}
|
|
|
|
#endif
|
|
|
|
PathButton::PathButton()
|
|
: Glib::ObjectBase(typeid(PathButton))
|
|
, impl_(std::make_unique<Impl>(*this))
|
|
{
|
|
}
|
|
|
|
PathButton::PathButton(BaseObjectType* cast_item, Glib::RefPtr<Gtk::Builder> const& /*builder*/)
|
|
: Glib::ObjectBase(typeid(PathButton))
|
|
, BaseWidgetType(cast_item)
|
|
, impl_(std::make_unique<Impl>(*this))
|
|
{
|
|
}
|
|
|
|
PathButton::~PathButton() = default;
|
|
|
|
void PathButton::set_shortcut_folders(std::list<std::string> const& value)
|
|
{
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
impl_->set_shortcut_folders(value);
|
|
#else
|
|
for (auto const& folder : value)
|
|
{
|
|
remove_shortcut_folder(folder);
|
|
add_shortcut_folder(folder);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
|
|
std::string PathButton::get_filename() const
|
|
{
|
|
return impl_->get_filename();
|
|
}
|
|
|
|
void PathButton::set_filename(std::string const& value)
|
|
{
|
|
impl_->set_filename(value);
|
|
}
|
|
|
|
void PathButton::add_filter(Glib::RefPtr<Gtk::FileFilter> const& value)
|
|
{
|
|
impl_->add_filter(value);
|
|
}
|
|
|
|
Glib::PropertyProxy<Gtk::FileChooser::Action> PathButton::property_action()
|
|
{
|
|
return impl_->property_action().get_proxy();
|
|
}
|
|
|
|
Glib::PropertyProxy<Glib::ustring> PathButton::property_title()
|
|
{
|
|
return impl_->property_title().get_proxy();
|
|
}
|
|
|
|
sigc::signal<void()>& PathButton::signal_selection_changed()
|
|
{
|
|
return impl_->signal_selection_changed();
|
|
}
|
|
|
|
#endif
|