mirror of
https://github.com/transmission/transmission
synced 2025-02-19 04:41:11 +00:00
* Add compat operator* for RefPtr * Rename `*_tree_view_*` button handling helpers to `*_item_view_*` * Move torrent item colors to CSS * Switch to list view for torrents list (GTK 4) * Bump Fedora image to 39 (current rawhide) for GTK 4.11 Enable deprecations as there're lots of them in 4.11 and I'm not keen on fixing them all right now. Disable warnings as errors due to -Warray-bounds issue somewhere in libfmt.
639 lines
21 KiB
C++
639 lines
21 KiB
C++
// This file Copyright © 2007-2023 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 "TorrentCellRenderer.h"
|
|
|
|
#include "HigWorkarea.h" // GUI_PAD, GUI_PAD_SMALL
|
|
#include "Percents.h"
|
|
#include "Torrent.h"
|
|
|
|
#include <libtransmission/transmission.h>
|
|
#include <libtransmission/utils.h> /* tr_truncd() */
|
|
|
|
#include <cairomm/context.h>
|
|
#include <cairomm/refptr.h>
|
|
#include <cairomm/surface.h>
|
|
#include <gdkmm/rectangle.h>
|
|
#include <gdkmm/rgba.h>
|
|
#include <giomm/icon.h>
|
|
#include <glibmm.h>
|
|
#include <glibmm/i18n.h>
|
|
#include <glibmm/property.h>
|
|
#include <gtkmm/cellrendererpixbuf.h>
|
|
#include <gtkmm/cellrendererprogress.h>
|
|
#include <gtkmm/cellrenderertext.h>
|
|
#include <gtkmm/requisition.h>
|
|
|
|
#if GTKMM_CHECK_VERSION(4, 0, 0)
|
|
#include <gtkmm/snapshot.h>
|
|
#endif
|
|
|
|
#include <fmt/core.h>
|
|
|
|
#include <algorithm> // std::max()
|
|
#include <cstring> // strchr()
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
/* #define TEST_RTL */
|
|
|
|
using namespace std::string_literals;
|
|
|
|
/***
|
|
****
|
|
***/
|
|
|
|
namespace
|
|
{
|
|
|
|
auto const DefaultBarHeight = 12;
|
|
auto const CompactBarWidth = 50;
|
|
auto const SmallScale = 0.9;
|
|
auto const CompactIconSize = Gtk::ICON_SIZE_MENU;
|
|
auto const FullIconSize = Gtk::ICON_SIZE_DND;
|
|
|
|
} // namespace
|
|
|
|
/***
|
|
****
|
|
***/
|
|
|
|
class TorrentCellRenderer::Impl
|
|
{
|
|
public:
|
|
explicit Impl(TorrentCellRenderer& renderer);
|
|
~Impl();
|
|
|
|
TR_DISABLE_COPY_MOVE(Impl)
|
|
|
|
Gtk::Requisition get_size_compact(Gtk::Widget& widget) const;
|
|
Gtk::Requisition get_size_full(Gtk::Widget& widget) const;
|
|
|
|
void render_compact(
|
|
Cairo::RefPtr<Cairo::Context> const& context,
|
|
Gtk::Widget& widget,
|
|
Gdk::Rectangle const& background_area,
|
|
Gtk::CellRendererState flags);
|
|
void render_full(
|
|
Cairo::RefPtr<Cairo::Context> const& context,
|
|
Gtk::Widget& widget,
|
|
Gdk::Rectangle const& background_area,
|
|
Gtk::CellRendererState flags);
|
|
|
|
auto& property_torrent()
|
|
{
|
|
return property_torrent_;
|
|
}
|
|
|
|
auto& property_bar_height()
|
|
{
|
|
return property_bar_height_;
|
|
}
|
|
|
|
auto& property_compact()
|
|
{
|
|
return property_compact_;
|
|
}
|
|
|
|
private:
|
|
void render_progress_bar(
|
|
Cairo::RefPtr<Cairo::Context> const& context,
|
|
Gtk::Widget& widget,
|
|
Gdk::Rectangle const& area,
|
|
Gtk::CellRendererState flags,
|
|
std::optional<Gdk::RGBA> const& color);
|
|
|
|
static void adjust_progress_bar_hue(
|
|
Cairo::RefPtr<Cairo::Context> const& context,
|
|
Gdk::RGBA const& color,
|
|
Gdk::Rectangle const& area);
|
|
|
|
private:
|
|
TorrentCellRenderer& renderer_;
|
|
|
|
Glib::Property<Torrent*> property_torrent_;
|
|
Glib::Property<int> property_bar_height_;
|
|
Glib::Property<bool> property_compact_;
|
|
|
|
Gtk::CellRendererText* text_renderer_ = nullptr;
|
|
Gtk::CellRendererProgress* progress_renderer_ = nullptr;
|
|
Gtk::CellRendererPixbuf* icon_renderer_ = nullptr;
|
|
};
|
|
|
|
/***
|
|
****
|
|
***/
|
|
|
|
Gtk::Requisition TorrentCellRenderer::Impl::get_size_compact(Gtk::Widget& widget) const
|
|
{
|
|
int xpad = 0;
|
|
int ypad = 0;
|
|
Gtk::Requisition min_size;
|
|
Gtk::Requisition icon_size;
|
|
Gtk::Requisition name_size;
|
|
Gtk::Requisition stat_size;
|
|
|
|
auto const& torrent = *property_torrent_.get_value();
|
|
|
|
auto const icon = torrent.get_icon();
|
|
auto const name = torrent.get_name();
|
|
auto const gstr_stat = torrent.get_short_status_text();
|
|
renderer_.get_padding(xpad, ypad);
|
|
|
|
/* get the idealized cell dimensions */
|
|
icon_renderer_->property_gicon() = icon;
|
|
icon_renderer_->property_stock_size() = CompactIconSize;
|
|
icon_renderer_->get_preferred_size(widget, min_size, icon_size);
|
|
text_renderer_->property_text() = name;
|
|
text_renderer_->property_ellipsize() = TR_PANGO_ELLIPSIZE_MODE(NONE);
|
|
text_renderer_->property_scale() = 1.0;
|
|
text_renderer_->get_preferred_size(widget, min_size, name_size);
|
|
text_renderer_->property_text() = gstr_stat;
|
|
text_renderer_->property_scale() = SmallScale;
|
|
text_renderer_->get_preferred_size(widget, min_size, stat_size);
|
|
|
|
/**
|
|
*** LAYOUT
|
|
**/
|
|
|
|
return { xpad * 2 + icon_size.width + GUI_PAD + CompactBarWidth + GUI_PAD + stat_size.width,
|
|
ypad * 2 + std::max(name_size.height, property_bar_height_.get_value()) };
|
|
}
|
|
|
|
Gtk::Requisition TorrentCellRenderer::Impl::get_size_full(Gtk::Widget& widget) const
|
|
{
|
|
int xpad = 0;
|
|
int ypad = 0;
|
|
Gtk::Requisition min_size;
|
|
Gtk::Requisition icon_size;
|
|
Gtk::Requisition name_size;
|
|
Gtk::Requisition stat_size;
|
|
Gtk::Requisition prog_size;
|
|
|
|
auto const& torrent = *property_torrent_.get_value();
|
|
|
|
auto const icon = torrent.get_icon();
|
|
auto const name = torrent.get_name();
|
|
auto const gstr_stat = torrent.get_long_status_text();
|
|
auto const gstr_prog = torrent.get_long_progress_text();
|
|
renderer_.get_padding(xpad, ypad);
|
|
|
|
/* get the idealized cell dimensions */
|
|
icon_renderer_->property_gicon() = icon;
|
|
icon_renderer_->property_stock_size() = FullIconSize;
|
|
icon_renderer_->get_preferred_size(widget, min_size, icon_size);
|
|
text_renderer_->property_text() = name;
|
|
text_renderer_->property_weight() = TR_PANGO_WEIGHT(BOLD);
|
|
text_renderer_->property_scale() = 1.0;
|
|
text_renderer_->property_ellipsize() = TR_PANGO_ELLIPSIZE_MODE(NONE);
|
|
text_renderer_->get_preferred_size(widget, min_size, name_size);
|
|
text_renderer_->property_text() = gstr_prog;
|
|
text_renderer_->property_weight() = TR_PANGO_WEIGHT(NORMAL);
|
|
text_renderer_->property_scale() = SmallScale;
|
|
text_renderer_->get_preferred_size(widget, min_size, prog_size);
|
|
text_renderer_->property_text() = gstr_stat;
|
|
text_renderer_->get_preferred_size(widget, min_size, stat_size);
|
|
|
|
/**
|
|
*** LAYOUT
|
|
**/
|
|
|
|
return { xpad * 2 + icon_size.width + GUI_PAD + std::max(prog_size.width, stat_size.width),
|
|
ypad * 2 + name_size.height + prog_size.height + GUI_PAD_SMALL + property_bar_height_.get_value() + GUI_PAD_SMALL +
|
|
stat_size.height };
|
|
}
|
|
|
|
void TorrentCellRenderer::get_preferred_width_vfunc(Gtk::Widget& widget, int& minimum_width, int& natural_width) const
|
|
{
|
|
if (impl_->property_torrent().get_value() != nullptr)
|
|
{
|
|
auto const size = impl_->property_compact().get_value() ? impl_->get_size_compact(widget) :
|
|
impl_->get_size_full(widget);
|
|
|
|
minimum_width = size.width;
|
|
natural_width = minimum_width;
|
|
}
|
|
}
|
|
|
|
void TorrentCellRenderer::get_preferred_height_vfunc(Gtk::Widget& widget, int& minimum_height, int& natural_height) const
|
|
{
|
|
if (impl_->property_torrent().get_value() != nullptr)
|
|
{
|
|
auto const size = impl_->property_compact().get_value() ? impl_->get_size_compact(widget) :
|
|
impl_->get_size_full(widget);
|
|
|
|
minimum_height = size.height;
|
|
natural_height = minimum_height;
|
|
}
|
|
}
|
|
|
|
namespace
|
|
{
|
|
|
|
void set_error_color(
|
|
Gtk::CellRendererText& text_renderer,
|
|
Torrent const& torrent,
|
|
Gtk::Widget& widget,
|
|
Gtk::CellRendererState flags)
|
|
{
|
|
static auto const error_color_name = Glib::ustring("tr_error_color"s);
|
|
|
|
auto color = Gdk::RGBA();
|
|
if (torrent.get_error_code() != 0 && (flags & TR_GTK_CELL_RENDERER_STATE(SELECTED)) == Gtk::CellRendererState{} &&
|
|
widget.get_style_context()->lookup_color(error_color_name, color))
|
|
{
|
|
text_renderer.property_foreground_rgba() = color;
|
|
}
|
|
else
|
|
{
|
|
text_renderer.property_foreground_set() = false;
|
|
}
|
|
}
|
|
|
|
std::optional<Gdk::RGBA> get_progress_bar_color(Torrent const& torrent, Gtk::Widget const& widget)
|
|
{
|
|
static auto const down_color_name = Glib::ustring("tr_transfer_down_color"s);
|
|
static auto const up_color_name = Glib::ustring("tr_transfer_up_color"s);
|
|
static auto const idle_color_name = Glib::ustring("tr_transfer_idle_color"s);
|
|
|
|
auto const* color_name = &idle_color_name;
|
|
switch (torrent.get_activity())
|
|
{
|
|
case TR_STATUS_DOWNLOAD:
|
|
color_name = &down_color_name;
|
|
break;
|
|
|
|
case TR_STATUS_SEED:
|
|
color_name = &up_color_name;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
auto color = Gdk::RGBA();
|
|
return widget.get_style_context()->lookup_color(*color_name, color) ? std::make_optional(color) : std::nullopt;
|
|
}
|
|
|
|
Cairo::RefPtr<Cairo::Surface> get_mask_surface(Cairo::RefPtr<Cairo::Surface> const& surface, Gdk::Rectangle const& area)
|
|
{
|
|
auto const mask_surface = Cairo::Surface::create(surface, Cairo::CONTENT_ALPHA, area.get_width(), area.get_height());
|
|
auto const mask_context = Cairo::Context::create(mask_surface);
|
|
|
|
mask_context->set_source_rgb(0, 0, 0);
|
|
mask_context->rectangle(area.get_x(), area.get_y(), area.get_width(), area.get_height());
|
|
mask_context->fill();
|
|
|
|
mask_context->set_operator(TR_CAIRO_CONTEXT_OPERATOR(CLEAR));
|
|
mask_context->mask(surface, area.get_x(), area.get_y());
|
|
mask_context->fill();
|
|
|
|
return mask_surface;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void TorrentCellRenderer::Impl::adjust_progress_bar_hue(
|
|
Cairo::RefPtr<Cairo::Context> const& context,
|
|
Gdk::RGBA const& color,
|
|
Gdk::Rectangle const& area)
|
|
{
|
|
auto const mask_surface = get_mask_surface(context->get_target(), area);
|
|
|
|
// Adjust surface color
|
|
context->set_source_rgb(color.get_red(), color.get_green(), color.get_blue());
|
|
context->set_operator(static_cast<Cairo::Operator>(CAIRO_OPERATOR_HSL_COLOR));
|
|
context->rectangle(area.get_x(), area.get_y(), area.get_width(), area.get_height());
|
|
context->fill();
|
|
|
|
// Clear out masked (fully transparent) areas
|
|
context->set_operator(TR_CAIRO_CONTEXT_OPERATOR(CLEAR));
|
|
context->mask(mask_surface, area.get_x(), area.get_y());
|
|
context->fill();
|
|
}
|
|
|
|
void TorrentCellRenderer::Impl::render_progress_bar(
|
|
Cairo::RefPtr<Cairo::Context> const& context,
|
|
Gtk::Widget& widget,
|
|
Gdk::Rectangle const& area,
|
|
Gtk::CellRendererState flags,
|
|
std::optional<Gdk::RGBA> const& color)
|
|
{
|
|
if (!color.has_value())
|
|
{
|
|
progress_renderer_->render(context, widget, area, area, flags);
|
|
return;
|
|
}
|
|
|
|
auto const temp_area = Gdk::Rectangle(0, 0, area.get_width(), area.get_height());
|
|
auto const temp_surface = Cairo::Surface::create(
|
|
context->get_target(),
|
|
Cairo::CONTENT_COLOR_ALPHA,
|
|
area.get_width(),
|
|
area.get_height());
|
|
auto const temp_context = Cairo::Context::create(temp_surface);
|
|
|
|
progress_renderer_->render(temp_context, widget, temp_area, temp_area, flags);
|
|
|
|
adjust_progress_bar_hue(temp_context, color.value(), temp_area);
|
|
|
|
context->set_source(temp_context->get_target(), area.get_x(), area.get_y());
|
|
context->rectangle(area.get_x(), area.get_y(), area.get_width(), area.get_height());
|
|
context->fill();
|
|
}
|
|
|
|
void TorrentCellRenderer::Impl::render_compact(
|
|
Cairo::RefPtr<Cairo::Context> const& context,
|
|
Gtk::Widget& widget,
|
|
Gdk::Rectangle const& background_area,
|
|
Gtk::CellRendererState flags)
|
|
{
|
|
int xpad = 0;
|
|
int ypad = 0;
|
|
int min_width = 0;
|
|
int width = 0;
|
|
|
|
auto const& torrent = *property_torrent_.get_value();
|
|
auto const percent_done = torrent.get_percent_done().to_int();
|
|
bool const sensitive = torrent.get_sensitive();
|
|
|
|
set_error_color(*text_renderer_, torrent, widget, flags);
|
|
|
|
auto const icon = torrent.get_icon();
|
|
auto const name = torrent.get_name();
|
|
auto const progress_color = get_progress_bar_color(torrent, widget);
|
|
auto const gstr_stat = torrent.get_short_status_text();
|
|
renderer_.get_padding(xpad, ypad);
|
|
|
|
auto fill_area = background_area;
|
|
fill_area.set_x(fill_area.get_x() + xpad);
|
|
fill_area.set_y(fill_area.get_y() + ypad);
|
|
fill_area.set_width(fill_area.get_width() - xpad * 2);
|
|
fill_area.set_height(fill_area.get_height() - ypad * 2);
|
|
|
|
auto icon_area = fill_area;
|
|
icon_renderer_->property_gicon() = icon;
|
|
icon_renderer_->property_stock_size() = CompactIconSize;
|
|
icon_renderer_->get_preferred_width(widget, min_width, width);
|
|
icon_area.set_width(width);
|
|
|
|
auto prog_area = fill_area;
|
|
prog_area.set_width(CompactBarWidth);
|
|
|
|
auto stat_area = fill_area;
|
|
text_renderer_->property_text() = gstr_stat;
|
|
text_renderer_->property_ellipsize() = TR_PANGO_ELLIPSIZE_MODE(NONE);
|
|
text_renderer_->property_scale() = SmallScale;
|
|
text_renderer_->get_preferred_width(widget, min_width, width);
|
|
stat_area.set_width(width);
|
|
|
|
auto name_area = fill_area;
|
|
name_area.set_width(
|
|
fill_area.get_width() - icon_area.get_width() - stat_area.get_width() - prog_area.get_width() - GUI_PAD * 3);
|
|
|
|
if ((renderer_.get_state(widget, flags) & TR_GTK_STATE_FLAGS(DIR_RTL)) == Gtk::StateFlags{})
|
|
{
|
|
icon_area.set_x(fill_area.get_x());
|
|
prog_area.set_x(fill_area.get_x() + fill_area.get_width() - prog_area.get_width());
|
|
stat_area.set_x(prog_area.get_x() - stat_area.get_width() - GUI_PAD);
|
|
name_area.set_x(icon_area.get_x() + icon_area.get_width() + GUI_PAD);
|
|
}
|
|
else
|
|
{
|
|
icon_area.set_x(fill_area.get_x() + fill_area.get_width() - icon_area.get_width());
|
|
prog_area.set_x(fill_area.get_x());
|
|
stat_area.set_x(prog_area.get_x() + prog_area.get_width() + GUI_PAD);
|
|
name_area.set_x(stat_area.get_x() + stat_area.get_width() + GUI_PAD);
|
|
}
|
|
|
|
/**
|
|
*** RENDER
|
|
**/
|
|
|
|
icon_renderer_->property_gicon() = icon;
|
|
icon_renderer_->property_stock_size() = CompactIconSize;
|
|
icon_renderer_->property_sensitive() = sensitive;
|
|
icon_renderer_->render(context, widget, icon_area, icon_area, flags);
|
|
|
|
progress_renderer_->property_value() = percent_done;
|
|
progress_renderer_->property_text() = fmt::format(FMT_STRING("{:d}%"), percent_done);
|
|
progress_renderer_->property_sensitive() = sensitive;
|
|
render_progress_bar(context, widget, prog_area, flags, progress_color);
|
|
|
|
text_renderer_->property_text() = gstr_stat;
|
|
text_renderer_->property_scale() = SmallScale;
|
|
text_renderer_->property_ellipsize() = TR_PANGO_ELLIPSIZE_MODE(END);
|
|
text_renderer_->property_sensitive() = sensitive;
|
|
text_renderer_->render(context, widget, stat_area, stat_area, flags);
|
|
|
|
text_renderer_->property_text() = name;
|
|
text_renderer_->property_scale() = 1.0;
|
|
text_renderer_->render(context, widget, name_area, name_area, flags);
|
|
}
|
|
|
|
void TorrentCellRenderer::Impl::render_full(
|
|
Cairo::RefPtr<Cairo::Context> const& context,
|
|
Gtk::Widget& widget,
|
|
Gdk::Rectangle const& background_area,
|
|
Gtk::CellRendererState flags)
|
|
{
|
|
int xpad = 0;
|
|
int ypad = 0;
|
|
Gtk::Requisition min_size;
|
|
Gtk::Requisition size;
|
|
|
|
auto const& torrent = *property_torrent_.get_value();
|
|
auto const percent_done = torrent.get_percent_done().to_int();
|
|
bool const sensitive = torrent.get_sensitive();
|
|
|
|
set_error_color(*text_renderer_, torrent, widget, flags);
|
|
|
|
auto const icon = torrent.get_icon();
|
|
auto const name = torrent.get_name();
|
|
auto const progress_color = get_progress_bar_color(torrent, widget);
|
|
auto const gstr_prog = torrent.get_long_progress_text();
|
|
auto const gstr_stat = torrent.get_long_status_text();
|
|
renderer_.get_padding(xpad, ypad);
|
|
|
|
/* get the idealized cell dimensions */
|
|
Gdk::Rectangle icon_area;
|
|
icon_renderer_->property_gicon() = icon;
|
|
icon_renderer_->property_stock_size() = FullIconSize;
|
|
icon_renderer_->get_preferred_size(widget, min_size, size);
|
|
icon_area.set_width(size.width);
|
|
icon_area.set_height(size.height);
|
|
|
|
Gdk::Rectangle name_area;
|
|
text_renderer_->property_text() = name;
|
|
text_renderer_->property_weight() = TR_PANGO_WEIGHT(BOLD);
|
|
text_renderer_->property_ellipsize() = TR_PANGO_ELLIPSIZE_MODE(NONE);
|
|
text_renderer_->property_scale() = 1.0;
|
|
text_renderer_->get_preferred_size(widget, min_size, size);
|
|
name_area.set_height(size.height);
|
|
|
|
Gdk::Rectangle prog_area;
|
|
text_renderer_->property_text() = gstr_prog;
|
|
text_renderer_->property_weight() = TR_PANGO_WEIGHT(NORMAL);
|
|
text_renderer_->property_scale() = SmallScale;
|
|
text_renderer_->get_preferred_size(widget, min_size, size);
|
|
prog_area.set_height(size.height);
|
|
|
|
Gdk::Rectangle stat_area;
|
|
text_renderer_->property_text() = gstr_stat;
|
|
text_renderer_->get_preferred_size(widget, min_size, size);
|
|
stat_area.set_height(size.height);
|
|
|
|
Gdk::Rectangle prct_area;
|
|
|
|
/**
|
|
*** LAYOUT
|
|
**/
|
|
|
|
auto fill_area = background_area;
|
|
fill_area.set_x(fill_area.get_x() + xpad);
|
|
fill_area.set_y(fill_area.get_y() + ypad);
|
|
fill_area.set_width(fill_area.get_width() - xpad * 2);
|
|
fill_area.set_height(fill_area.get_height() - ypad * 2);
|
|
|
|
/* icon */
|
|
icon_area.set_y(fill_area.get_y() + (fill_area.get_height() - icon_area.get_height()) / 2);
|
|
|
|
/* name */
|
|
name_area.set_y(fill_area.get_y());
|
|
name_area.set_width(fill_area.get_width() - GUI_PAD - icon_area.get_width());
|
|
|
|
if ((renderer_.get_state(widget, flags) & TR_GTK_STATE_FLAGS(DIR_RTL)) == Gtk::StateFlags{})
|
|
{
|
|
icon_area.set_x(fill_area.get_x());
|
|
name_area.set_x(fill_area.get_x() + fill_area.get_width() - name_area.get_width());
|
|
}
|
|
else
|
|
{
|
|
icon_area.set_x(fill_area.get_x() + fill_area.get_width() - icon_area.get_width());
|
|
name_area.set_x(fill_area.get_x());
|
|
}
|
|
|
|
/* prog */
|
|
prog_area.set_x(name_area.get_x());
|
|
prog_area.set_y(name_area.get_y() + name_area.get_height());
|
|
prog_area.set_width(name_area.get_width());
|
|
|
|
/* progressbar */
|
|
prct_area.set_x(prog_area.get_x());
|
|
prct_area.set_y(prog_area.get_y() + prog_area.get_height() + GUI_PAD_SMALL);
|
|
prct_area.set_width(prog_area.get_width());
|
|
prct_area.set_height(property_bar_height_.get_value());
|
|
|
|
/* status */
|
|
stat_area.set_x(prct_area.get_x());
|
|
stat_area.set_y(prct_area.get_y() + prct_area.get_height() + GUI_PAD_SMALL);
|
|
stat_area.set_width(prct_area.get_width());
|
|
|
|
/**
|
|
*** RENDER
|
|
**/
|
|
|
|
icon_renderer_->property_gicon() = icon;
|
|
icon_renderer_->property_stock_size() = FullIconSize;
|
|
icon_renderer_->property_sensitive() = sensitive;
|
|
icon_renderer_->render(context, widget, icon_area, icon_area, flags);
|
|
|
|
text_renderer_->property_text() = name;
|
|
text_renderer_->property_scale() = 1.0;
|
|
text_renderer_->property_ellipsize() = TR_PANGO_ELLIPSIZE_MODE(END);
|
|
text_renderer_->property_weight() = TR_PANGO_WEIGHT(BOLD);
|
|
text_renderer_->property_sensitive() = sensitive;
|
|
text_renderer_->render(context, widget, name_area, name_area, flags);
|
|
|
|
text_renderer_->property_text() = gstr_prog;
|
|
text_renderer_->property_scale() = SmallScale;
|
|
text_renderer_->property_weight() = TR_PANGO_WEIGHT(NORMAL);
|
|
text_renderer_->render(context, widget, prog_area, prog_area, flags);
|
|
|
|
progress_renderer_->property_value() = percent_done;
|
|
progress_renderer_->property_text() = Glib::ustring();
|
|
progress_renderer_->property_sensitive() = sensitive;
|
|
render_progress_bar(context, widget, prct_area, flags, progress_color);
|
|
|
|
text_renderer_->property_text() = gstr_stat;
|
|
text_renderer_->render(context, widget, stat_area, stat_area, flags);
|
|
}
|
|
|
|
void TorrentCellRenderer::render_vfunc(
|
|
Cairo::RefPtr<Cairo::Context> const& context,
|
|
Gtk::Widget& widget,
|
|
Gdk::Rectangle const& background_area,
|
|
Gdk::Rectangle const& /*cell_area*/,
|
|
Gtk::CellRendererState flags)
|
|
{
|
|
#ifdef TEST_RTL
|
|
auto const real_dir = widget.get_direction();
|
|
widget.set_direction(Gtk::TEXT_DIR_RTL);
|
|
#endif
|
|
|
|
if (impl_->property_torrent().get_value() != nullptr)
|
|
{
|
|
if (impl_->property_compact().get_value())
|
|
{
|
|
impl_->render_compact(context, widget, background_area, flags);
|
|
}
|
|
else
|
|
{
|
|
impl_->render_full(context, widget, background_area, flags);
|
|
}
|
|
}
|
|
|
|
#ifdef TEST_RTL
|
|
widget.set_direction(real_dir);
|
|
#endif
|
|
}
|
|
|
|
TorrentCellRenderer::Impl::~Impl()
|
|
{
|
|
text_renderer_->unreference();
|
|
progress_renderer_->unreference();
|
|
icon_renderer_->unreference();
|
|
}
|
|
|
|
TorrentCellRenderer::TorrentCellRenderer()
|
|
: Glib::ObjectBase(typeid(TorrentCellRenderer))
|
|
, impl_(std::make_unique<Impl>(*this))
|
|
{
|
|
}
|
|
|
|
TorrentCellRenderer::~TorrentCellRenderer() = default;
|
|
|
|
TorrentCellRenderer::Impl::Impl(TorrentCellRenderer& renderer)
|
|
: renderer_(renderer)
|
|
, property_torrent_(renderer, "torrent", nullptr)
|
|
, property_bar_height_(renderer, "bar-height", DefaultBarHeight)
|
|
, property_compact_(renderer, "compact", false)
|
|
, text_renderer_(Gtk::make_managed<Gtk::CellRendererText>())
|
|
, progress_renderer_(Gtk::make_managed<Gtk::CellRendererProgress>())
|
|
, icon_renderer_(Gtk::make_managed<Gtk::CellRendererPixbuf>())
|
|
{
|
|
renderer_.property_xpad() = GUI_PAD_SMALL;
|
|
renderer_.property_ypad() = GUI_PAD_SMALL;
|
|
|
|
text_renderer_->property_xpad() = 0;
|
|
text_renderer_->property_ypad() = 0;
|
|
}
|
|
|
|
Glib::PropertyProxy<Torrent*> TorrentCellRenderer::property_torrent()
|
|
{
|
|
return impl_->property_torrent().get_proxy();
|
|
}
|
|
|
|
Glib::PropertyProxy<int> TorrentCellRenderer::property_bar_height()
|
|
{
|
|
return impl_->property_bar_height().get_proxy();
|
|
}
|
|
|
|
Glib::PropertyProxy<bool> TorrentCellRenderer::property_compact()
|
|
{
|
|
return impl_->property_compact().get_proxy();
|
|
}
|