1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-17 17:25:32 +00:00
transmission/gtk/PathButton.cc
Mike Gelfand 67c4e4081c
Add ENABLE_WERROR option for use on CI (#4381)
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.
2022-12-16 22:38:30 +00:00

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