17#include <glibmm/i18n.h>
18#include <glibmm/markup.h>
19#include <gtkmm/cellrenderertext.h>
20#include <gtkmm/droptarget.h>
21#include <gtkmm/eventcontrollerkey.h>
22#include <gtkmm/messagedialog.h>
23#include <gtkmm/treestore.h>
25#include <sigc++/functors/mem_fun.h>
38 treeview = Gtk::make_managed<Gtk::TreeView>();
51 cell_text = Gtk::make_managed<Gtk::CellRendererText>();
65 treeview->set_headers_visible (
false);
66 treeview->enable_model_drag_dest (Gdk::DragAction::MOVE);
73 scroll.set_policy (Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
74 scroll.set_overlay_scrolling(
false);
77 frame.set_hexpand (
true);
78 frame.set_vexpand (
true);
82 set_name(
"FontCollection");
84 set_column_spacing(1);
87 attach (
frame, 0, 0, 1, 2);
97 cell_text->signal_edited().connect([
this](
const Glib::ustring ¤t_path,
const Glib::ustring &new_text) {
99 std::set<Glib::ustring> expanded_collections;
101 store->foreach ([&](Gtk::TreeModel::Path
const &path, Gtk::TreeModel::const_iterator
const &it) {
104 expanded_collections.insert(collection);
109 bool current_collection_expanded =
false;
110 if (
auto iter =
store->get_iter(current_path)) {
111 auto path =
store->get_path(iter);
113 current_collection_expanded =
true;
118 Gtk::TreeModel::Path updated_path;
119 if (updated && current_collection_expanded) {
120 expanded_collections.insert(new_text);
123 if (
auto iter =
store->get_iter(current_path)) {
129 store->foreach ([&](Gtk::TreeModel::Path
const &path, Gtk::TreeModel::const_iterator
const &it) {
132 if (expanded_collections.contains(collection)) {
136 if (updated && (collection == new_text)) {
143 auto tree_sel =
treeview->get_selection();
144 if (updated && updated_path) {
146 tree_sel->select(updated_path);
162 auto const key = Gtk::EventControllerKey::create();
167 auto const drop = Gtk::DropTarget::create(G_TYPE_STRING, Gdk::DragAction::COPY);
178 Gtk::TreeModel::const_iterator
const &iter)
181 bool const is_collection = !iter->parent();
182 cell_text->property_editable() = is_collection ? true :
false;
187 Gtk::TreeModel::const_iterator
const &iter)
190 bool const is_collection = !iter->parent();
193 Glib::ustring
const markup =
"<span alpha='50%'>" + std::to_string((*iter)[
FontCollection.font_count]) +
"</span>";
194 renderer->set_property(
"markup", markup);
199 Gtk::TreeModel::const_iterator
const &iter)
202 if (
auto const parent = iter->parent()) {
217 Gtk::TreeModel::const_iterator
const &iter)
219 renderer->set_visible(
false);
235 Gtk::TreeModel::const_iterator
const &iter)
254 store->freeze_notify();
255 Gtk::TreeModel::iterator iter;
257 for(
const auto &col: collections) {
258 iter =
store->append();
267 store->thaw_notify();
274 std::set <Glib::ustring> fonts = font_collections->
get_fonts(collection_name);
279 store->freeze_notify();
283 path.push_back(
index);
284 Gtk::TreeModel::iterator iter =
store->get_iter(path);
287 store->thaw_notify();
295 auto size = iter->children().size();
299 Gtk::TreeModel::iterator
child = iter->children().begin();
303 for(
auto const &font: fonts) {
304 Gtk::TreeModel::iterator
child =
store->append((*iter).children());
309 store->thaw_notify();
315 auto iter =
store->get_iter(path);
316 if (
auto const parent = iter->parent()) {
335 if (response == Gtk::ResponseType::YES) {
336 auto collections = Inkscape::FontCollections::get();
337 collections->remove_collection((*iter)[FontCollection.name]);
344void FontCollectionSelector::on_create_collection()
347 Gtk::TreeModel::iterator iter =
store->append();
351 Gtk::TreeModel::Path path = (Gtk::TreeModel::Path)iter;
352 treeview->set_cursor(path, text_column,
true);
356bool FontCollectionSelector::on_rename_collection(
const Glib::ustring &path,
const Glib::ustring &new_text)
367 if (new_text ==
"" || is_system || is_user) {
371 Gtk::TreeModel::iterator iter =
store->get_iter(path);
387 populate_collections();
392void FontCollectionSelector::on_delete_button_pressed()
395 Glib::RefPtr<Gtk::TreeSelection> selection = treeview->get_selection();
396 Gtk::TreeModel::iterator iter = selection->get_selected();
397 Gtk::TreeModel::Row row = *iter;
398 auto const parent = iter->parent();
411 deletion_warning_message_dialog((*iter)[
FontCollection.
name], [
this, iter] (
int response) {
412 if (response == Gtk::ResponseType::YES) {
413 auto collections = Inkscape::FontCollections::get();
414 collections->remove_collection((*iter)[FontCollection.name]);
433void FontCollectionSelector::on_edit_button_pressed()
435 Glib::RefPtr<Gtk::TreeSelection> selection = treeview->get_selection();
438 Gtk::TreeModel::iterator iter = selection->get_selected();
443 auto const parent = iter->parent();
446 if (!
parent && !is_system) {
448 treeview->set_cursor(Gtk::TreePath(iter), text_column,
true);
453void FontCollectionSelector::deletion_warning_message_dialog(Glib::ustring
const &collection_name, sigc::slot<
void(
int)> onresponse)
455 auto message = Glib::ustring::compose(_(
"Are you sure want to delete the \"%1\" font collection?\n"), collection_name);
456 auto dialog = std::make_unique<Gtk::MessageDialog>(message,
false, Gtk::MessageType::WARNING, Gtk::ButtonsType::YES_NO,
true);
457 dialog->signal_response().connect(onresponse);
461bool FontCollectionSelector::on_key_pressed(Gtk::EventControllerKey
const &controller,
462 unsigned keyval,
unsigned keycode, Gdk::ModifierType state)
466 on_delete_button_pressed();
473Gdk::DragAction FontCollectionSelector::on_drop_motion(
double x,
double y)
475 Gtk::TreeModel::Path path;
476 Gtk::TreeView::DropPosition pos;
477 treeview->get_dest_row_at_pos(x, y, path, pos);
478 treeview->unset_state_flags(Gtk::StateFlags::DROP_ACTIVE);
480 auto tree_sel = treeview->get_selection();
482 if (
auto iter =
store->get_iter(path)) {
483 if (
auto parent = iter->parent()) {
486 tree_sel->select(iter);
488 return Gdk::DragAction::COPY;
492 tree_sel->unselect_all();
496void FontCollectionSelector::on_drop_leave()
498 treeview->get_selection()->unselect_all();
501bool FontCollectionSelector::on_drop_drop(Glib::ValueBase
const &,
double x,
double y)
506 treeview->convert_widget_to_bin_window_coords(x, y, bx, by);
507 if (!treeview->get_path_at_pos(bx, by, path)) {
510 Gtk::TreeModel::iterator iter =
store->get_iter(path);
518 bool is_expanded =
false;
519 if (
auto const parent = iter->parent()) {
523 is_expanded = treeview->row_expanded(path);
528 bool const is_system = collections->find_collection(collection_name,
true);
539 collections->add_font(collection_name, font_name);
542 populate_fonts(collection_name);
546 treeview->expand_to_path(path);
552void FontCollectionSelector::on_selection_changed()
554 Glib::RefPtr <Gtk::TreeSelection> selection = treeview->get_selection();
555 if (!selection)
return;
558 Gtk::TreeModel::iterator iter = selection->get_selected();
561 auto parent = iter->parent();
580 state = (is_system) ? SYSTEM_COLLECTION: USER_COLLECTION_FONT;
584 state = (is_system) ? SYSTEM_COLLECTION: USER_COLLECTION;
587 signal_changed.emit(state);
static FontCollections * get()
int get_user_collection_location(const Glib::ustring &collection_name)
void rename_font(const Glib::ustring &collection_name, const Glib::ustring &old_name, const Glib::ustring &new_name)
std::set< Glib::ustring > const & get_fonts(Glib::ustring const &name, bool is_system=false) const
void rename_collection(const Glib::ustring &old_name, const Glib::ustring &new_name)
bool find_collection(Glib::ustring const &collection_name, bool is_system=false) const
std::vector< Glib::ustring > get_collections(bool is_system=false) const
Glib::ustring const & get_dragging_family() const
static Inkscape::FontLister * get_instance()
Utilities to more easily use Gtk::EventController & subclasses like Gesture.
static char const *const parent
This file contains the definition of the FontCollectionSelector class.
void dialog_show_modal_and_selfdestruct(std::unique_ptr< Gtk::Dialog > dialog, Gtk::Root *root)
Show a dialog modally, destroying it when the user dismisses it.
static cairo_user_data_key_t key