diff options
Diffstat (limited to 'src/gui/pieList.vala')
-rw-r--r-- | src/gui/pieList.vala | 1105 |
1 files changed, 151 insertions, 954 deletions
diff --git a/src/gui/pieList.vala b/src/gui/pieList.vala index 46970d5..bfcb832 100644 --- a/src/gui/pieList.vala +++ b/src/gui/pieList.vala @@ -17,1029 +17,226 @@ this program. If not, see <http://www.gnu.org/licenses/>. namespace GnomePie { -// A very complex Widget. This is by far the most ugly file of this project -// but well, this list *is* complex... sorry ;) +///////////////////////////////////////////////////////////////////////// +/// A list, containing one entry for each existing Pie. +///////////////////////////////////////////////////////////////////////// class PieList : Gtk.TreeView { - private Gtk.ListStore groups; - private Gtk.ListStore pies; - private Gtk.ListStore actions; - private Gtk.TreeStore data; + ///////////////////////////////////////////////////////////////////// + /// This signal gets emitted when the user selects a new Pie. + ///////////////////////////////////////////////////////////////////// - private const int small_icon = 24; - private const int large_icon = 36; + public signal void on_select(string id); - // data positions in the data ListStore - private enum DataPos {IS_QUICKACTION, ICON, NAME, TYPE_ID, ACTION_TYPE, - ICON_PIXBUF, FONT_WEIGHT, ICON_NAME_EDITABLE, QUICKACTION_VISIBLE, QUICKACTION_ACTIVATABLE, - TYPE_VISIBLE, GROUP_VISIBLE, APP_VISIBLE, KEY_VISIBLE, PIE_VISIBLE, - URI_VISIBLE, TRIGGER_VISIBLE, DISPLAY_COMMAND_GROUP, DISPLAY_COMMAND_APP, - DISPLAY_COMMAND_KEY, DISPLAY_COMMAND_PIE, DISPLAY_COMMAND_URI, - REAL_COMMAND_GROUP, REAL_COMMAND_PIE, REAL_COMMAND_KEY} + ///////////////////////////////////////////////////////////////////// + /// Stores the data internally. + ///////////////////////////////////////////////////////////////////// - // data positions in the actions ListStore - private enum ActionPos {NAME, TYPE, CAN_QUICKACTION, ICON_NAME_EDITABLE} + private Gtk.ListStore data; + private enum DataPos {ICON, ICON_NAME, NAME, ID} - // data positions in the pies ListStore - private enum PiePos {NAME, ID} + ///////////////////////////////////////////////////////////////////// + /// Stores where a drag startet. + ///////////////////////////////////////////////////////////////////// - // data positions in the groups ListStore - private enum GroupPos {NAME, TYPE, ICON} + private Gtk.TreeIter? drag_start = null; + + ///////////////////////////////////////////////////////////////////// + /// Rembers the time when a last drag move event was reported. Used + /// to avoid frequent changes of selected Pie when a Pie is dragged + /// over this widget. + ///////////////////////////////////////////////////////////////////// + + private uint last_hover = 0; + + ///////////////////////////////////////////////////////////////////// + /// C'tor, constructs the Widget. + ///////////////////////////////////////////////////////////////////// public PieList() { GLib.Object(); - Gtk.TreeIter last; - - // group choices - this.groups = new Gtk.ListStore(3, typeof(string), // group name - typeof(string), // group type - typeof(string)); // group icon - - // add all registered group types - foreach (var type in GroupRegistry.types) { - this.groups.append(out last); - this.groups.set(last, GroupPos.NAME, GroupRegistry.names[type], - GroupPos.TYPE, type.name(), - GroupPos.ICON, GroupRegistry.icons[type]); - } - - // pie choices - this.pies = new Gtk.ListStore(2, typeof(string), // pie name - typeof(string)); // pie id - - // action type choices - this.actions = new Gtk.ListStore(4, typeof(string), // type name - typeof(string), // action type - typeof(bool), // can be quickaction - typeof(bool)); // icon/name editable - - // add all registered action types - foreach (var type in ActionRegistry.types) { - this.actions.append(out last); - this.actions.set(last, ActionPos.NAME, ActionRegistry.names[type], - ActionPos.TYPE, type.name(), - ActionPos.CAN_QUICKACTION, true, - ActionPos.ICON_NAME_EDITABLE, ActionRegistry.icon_name_editables[type]); - } - // and one type for groups - this.actions.append(out last); - this.actions.set(last, ActionPos.NAME, _("Slice group"), - ActionPos.TYPE, typeof(ActionGroup).name(), - ActionPos.CAN_QUICKACTION, false, - ActionPos.ICON_NAME_EDITABLE, false); + this.data = new Gtk.ListStore(4, typeof(Gdk.Pixbuf), + typeof(string), + typeof(string), + typeof(string)); + + this.data.set_sort_column_id(DataPos.NAME, Gtk.SortType.ASCENDING); - // main data model - this.data = new Gtk.TreeStore(25, typeof(bool), // is quickaction - typeof(string), // icon - typeof(string), // name - typeof(string), // slice: type label, pie: "ID: %id" - typeof(string), // typeof(action), typeof(ActionGroup).name() if group action, pie_id if Pie - - typeof(Gdk.Pixbuf), // icon pixbuf - typeof(int), // font weight - - typeof(bool), // icon/name editable - - typeof(bool), // quickaction visible - typeof(bool), // quickaction activatable - typeof(bool), // type visible - typeof(bool), // group renderer visible - typeof(bool), // app renderer visible - typeof(bool), // key renderer visible - typeof(bool), // pie renderer visible - typeof(bool), // uri renderer visible - typeof(bool), // trigger renderer visible - - typeof(string), // display command group - typeof(string), // display command app - typeof(string), // display command key - typeof(string), // display command pie - typeof(string), // display command uri - - typeof(string), // real command group - typeof(string), // real command pie - typeof(string)); // real command key - - this.set_model(this.data); + this.set_headers_visible(false); this.set_grid_lines(Gtk.TreeViewGridLines.NONE); - this.set_enable_tree_lines(false); - this.set_reorderable(false); - this.set_level_indentation(-10); + this.width_request = 170; + this.set_enable_search(false); - // create the gui - // icon column - var icon_column = new Gtk.TreeViewColumn(); - icon_column.title = _("Icon"); - icon_column.expand = false; - - // quickaction checkbox - var check_render = new Gtk.CellRendererToggle(); - check_render.activatable = true; - check_render.radio = true; - check_render.width = 15; - - check_render.toggled.connect((path) => { - Gtk.TreeIter toggled; - this.data.get_iter_from_string(out toggled, path); - - bool current = false; - this.data.get(toggled, DataPos.IS_QUICKACTION, out current); - - // set all others off - Gtk.TreeIter parent; - this.data.iter_parent(out parent, toggled); - string parent_pos = this.data.get_string_from_iter(parent); - int child_count = this.data.iter_n_children(parent); - - for (int i=0; i<child_count; ++i) { - Gtk.TreeIter child; - this.data.get_iter_from_string(out child, "%s:%d".printf(parent_pos, i)); - this.data.set(child, DataPos.IS_QUICKACTION, false); - } - - // toggle selected - this.data.set(toggled, DataPos.IS_QUICKACTION, !current); - - this.update_pie(toggled); - }); - - icon_column.pack_start(check_render, false); - icon_column.add_attribute(check_render, "activatable", DataPos.QUICKACTION_ACTIVATABLE); - icon_column.add_attribute(check_render, "sensitive", DataPos.QUICKACTION_ACTIVATABLE); - icon_column.add_attribute(check_render, "visible", DataPos.QUICKACTION_VISIBLE); - icon_column.add_attribute(check_render, "active", DataPos.IS_QUICKACTION); - + this.set_events(Gdk.EventMask.POINTER_MOTION_MASK); - // icon - var icon_render = new GnomePie.CellRendererIcon(); - icon_render.editable = true; - - icon_render.on_select.connect((path, icon_name) => { - Gtk.TreeIter iter; - this.data.get_iter_from_string(out iter, path); - int icon_size = this.data.iter_depth(iter) == 0 ? this.large_icon : this.small_icon; - - this.data.set(iter, DataPos.ICON, icon_name); - this.data.set(iter, DataPos.ICON_PIXBUF, this.load_icon(icon_name, icon_size)); - - this.update_pie(iter); - this.update_linked(); - }); - - icon_column.pack_start(icon_render, false); - icon_column.add_attribute(icon_render, "icon_name", DataPos.ICON); - icon_column.add_attribute(icon_render, "pixbuf", DataPos.ICON_PIXBUF); - icon_column.add_attribute(icon_render, "editable", DataPos.ICON_NAME_EDITABLE); - icon_column.add_attribute(icon_render, "icon_sensitive", DataPos.ICON_NAME_EDITABLE); - - // command column - var command_column = new Gtk.TreeViewColumn(); - command_column.title = _("Command"); - command_column.resizable = true; - command_column.expand = true; - - // trigger - var command_renderer_trigger = new CellRendererTrigger(); - command_renderer_trigger.editable = true; - command_renderer_trigger.ellipsize = Pango.EllipsizeMode.END; - - command_renderer_trigger.on_select.connect((path, trigger) => { - Gtk.TreeIter data_iter; - this.data.get_iter_from_string(out data_iter, path); - - this.data.set(data_iter, DataPos.DISPLAY_COMMAND_KEY, trigger.label_with_specials); - this.data.set(data_iter, DataPos.REAL_COMMAND_KEY, trigger.name); - - this.update_pie(data_iter); - }); - - command_column.pack_end(command_renderer_trigger, true); - command_column.add_attribute(command_renderer_trigger, "weight", DataPos.FONT_WEIGHT); - command_column.add_attribute(command_renderer_trigger, "markup", DataPos.DISPLAY_COMMAND_KEY); - command_column.add_attribute(command_renderer_trigger, "visible", DataPos.TRIGGER_VISIBLE); - command_column.add_attribute(command_renderer_trigger, "trigger", DataPos.REAL_COMMAND_KEY); - - // slice group - var command_renderer_group = new Gtk.CellRendererCombo(); - command_renderer_group.editable = true; - command_renderer_group.has_entry = false; - command_renderer_group.text_column = 0; - command_renderer_group.ellipsize = Pango.EllipsizeMode.END; - command_renderer_group.model = this.groups; - - command_renderer_group.changed.connect((path, iter) => { - string display_name; - string type; - string icon; - - this.groups.get(iter, GroupPos.NAME, out display_name); - this.groups.get(iter, GroupPos.TYPE, out type); - this.groups.get(iter, GroupPos.ICON, out icon); - - Gtk.TreeIter data_iter; - this.data.get_iter_from_string(out data_iter, path); - - this.data.set(data_iter, DataPos.DISPLAY_COMMAND_GROUP, display_name); - this.data.set(data_iter, DataPos.REAL_COMMAND_GROUP, type); - this.data.set(data_iter, DataPos.NAME, display_name); - this.data.set(data_iter, DataPos.ICON, icon); - - this.update_pie(data_iter); - }); - - command_column.pack_end(command_renderer_group, true); - command_column.add_attribute(command_renderer_group, "weight", DataPos.FONT_WEIGHT); - command_column.add_attribute(command_renderer_group, "text", DataPos.DISPLAY_COMMAND_GROUP); - command_column.add_attribute(command_renderer_group, "visible", DataPos.GROUP_VISIBLE); - - - // app action - var command_renderer_app = new Gtk.CellRendererText(); - command_renderer_app.editable = true; - command_renderer_app.ellipsize = Pango.EllipsizeMode.END; - - command_renderer_app.edited.connect((path, command) => { - Gtk.TreeIter data_iter; - this.data.get_iter_from_string(out data_iter, path); - - this.data.set(data_iter, DataPos.DISPLAY_COMMAND_APP, command); - - this.update_pie(data_iter); - }); - - command_column.pack_end(command_renderer_app, true); - command_column.add_attribute(command_renderer_app, "weight", DataPos.FONT_WEIGHT); - command_column.add_attribute(command_renderer_app, "text", DataPos.DISPLAY_COMMAND_APP); - command_column.add_attribute(command_renderer_app, "visible", DataPos.APP_VISIBLE); - - - // key action - var command_renderer_key = new Gtk.CellRendererAccel(); - command_renderer_key.editable = true; - command_renderer_key.ellipsize = Pango.EllipsizeMode.END; - - command_renderer_key.accel_edited.connect((path, key, mods) => { - Gtk.TreeIter data_iter; - this.data.get_iter_from_string(out data_iter, path); - - string label = Gtk.accelerator_get_label(key, mods); - string accelerator = Gtk.accelerator_name(key, mods); - - this.data.set(data_iter, DataPos.DISPLAY_COMMAND_KEY, label); - this.data.set(data_iter, DataPos.REAL_COMMAND_KEY, accelerator); - - this.update_pie(data_iter); - }); - - command_renderer_key.accel_cleared.connect((path) => { - Gtk.TreeIter data_iter; - this.data.get_iter_from_string(out data_iter, path); - - this.data.set(data_iter, DataPos.DISPLAY_COMMAND_KEY, _("Not bound")); - this.data.set(data_iter, DataPos.REAL_COMMAND_KEY, ""); - - this.update_pie(data_iter); - }); - - command_column.pack_end(command_renderer_key, true); - command_column.add_attribute(command_renderer_key, "weight", DataPos.FONT_WEIGHT); - command_column.add_attribute(command_renderer_key, "text", DataPos.DISPLAY_COMMAND_KEY); - command_column.add_attribute(command_renderer_key, "visible", DataPos.KEY_VISIBLE); - - - // pie action - var command_renderer_pie = new Gtk.CellRendererCombo(); - command_renderer_pie.editable = true; - command_renderer_pie.has_entry = false; - command_renderer_pie.text_column = 0; - command_renderer_pie.ellipsize = Pango.EllipsizeMode.END; - command_renderer_pie.model = this.pies; - - command_renderer_pie.changed.connect((path, iter) => { - string name; - string id; - - this.pies.get(iter, PiePos.NAME, out name); - this.pies.get(iter, PiePos.ID, out id); - - Gtk.TreeIter data_iter; - this.data.get_iter_from_string(out data_iter, path); - - this.data.set(data_iter, DataPos.DISPLAY_COMMAND_PIE, name); - this.data.set(data_iter, DataPos.REAL_COMMAND_PIE, id); - - this.update_pie(data_iter); - this.update_linked(); - }); - - command_column.pack_end(command_renderer_pie, true); - command_column.add_attribute(command_renderer_pie, "weight", DataPos.FONT_WEIGHT); - command_column.add_attribute(command_renderer_pie, "text", DataPos.DISPLAY_COMMAND_PIE); - command_column.add_attribute(command_renderer_pie, "visible", DataPos.PIE_VISIBLE); - - - // uri action - var command_renderer_uri = new Gtk.CellRendererText(); - command_renderer_uri.editable = true; - command_renderer_uri.ellipsize = Pango.EllipsizeMode.END; - - command_renderer_uri.edited.connect((path, uri) => { - Gtk.TreeIter data_iter; - this.data.get_iter_from_string(out data_iter, path); - - this.data.set(data_iter, DataPos.DISPLAY_COMMAND_URI, uri); - - this.update_pie(data_iter); - }); - - command_column.pack_end(command_renderer_uri, true); - command_column.add_attribute(command_renderer_uri, "weight", DataPos.FONT_WEIGHT); - command_column.add_attribute(command_renderer_uri, "text", DataPos.DISPLAY_COMMAND_URI); - command_column.add_attribute(command_renderer_uri, "visible", DataPos.URI_VISIBLE); - - - // type column - var type_column = new Gtk.TreeViewColumn(); - type_column.title = _("Pie-ID / Action type"); - type_column.resizable = true; - type_column.expand = false; - - var type_render = new Gtk.CellRendererCombo(); - type_render.editable = true; - type_render.has_entry = false; - type_render.model = actions; - type_render.text_column = 0; - type_render.ellipsize = Pango.EllipsizeMode.END; - - // change command_render's visibility accordingly - type_render.changed.connect((path, iter) => { - string text = ""; - string type; - bool can_quickaction; - bool icon_name_editable; - - this.actions.get(iter, ActionPos.NAME, out text); - this.actions.get(iter, ActionPos.TYPE, out type); - this.actions.get(iter, ActionPos.CAN_QUICKACTION, out can_quickaction); - this.actions.get(iter, ActionPos.ICON_NAME_EDITABLE, out icon_name_editable); - - Gtk.TreeIter data_iter; - this.data.get_iter_from_string(out data_iter, path); - - this.data.set(data_iter, DataPos.TYPE_ID, text); - this.data.set(data_iter, DataPos.ACTION_TYPE, type); - this.data.set(data_iter, DataPos.QUICKACTION_ACTIVATABLE, can_quickaction); - this.data.set(data_iter, DataPos.ICON_NAME_EDITABLE, icon_name_editable); - - // set all command renderes invisible - this.data.set(data_iter, DataPos.GROUP_VISIBLE, false); - this.data.set(data_iter, DataPos.APP_VISIBLE, false); - this.data.set(data_iter, DataPos.KEY_VISIBLE, false); - this.data.set(data_iter, DataPos.PIE_VISIBLE, false); - this.data.set(data_iter, DataPos.URI_VISIBLE, false); - - // set one visible - int type_id = 0; - if(type == typeof(AppAction).name()) type_id = 1; - else if(type == typeof(KeyAction).name()) type_id = 2; - else if(type == typeof(PieAction).name()) type_id = 3; - else if(type == typeof(UriAction).name()) type_id = 4; - else type_id = 0; - - this.data.set(data_iter, DataPos.GROUP_VISIBLE + type_id, true); - - this.update_linked(); - this.update_pie(data_iter); - - //this.set_cursor(new Gtk.TreePath.from_string(path), command_column, true); - }); - - type_column.pack_start(type_render, true); - type_column.add_attribute(type_render, "sensitive", DataPos.TYPE_VISIBLE); - type_column.add_attribute(type_render, "editable", DataPos.TYPE_VISIBLE); - type_column.add_attribute(type_render, "text", DataPos.TYPE_ID); - - // name column - var name_column = new Gtk.TreeViewColumn(); - name_column.title = _("Name"); - name_column.expand = true; - name_column.resizable = true; + var main_column = new Gtk.TreeViewColumn(); + var icon_render = new Gtk.CellRendererPixbuf(); + icon_render.xpad = 4; + icon_render.ypad = 4; + main_column.pack_start(icon_render, false); var name_render = new Gtk.CellRendererText(); - name_render.editable = true; name_render.ellipsize = Pango.EllipsizeMode.END; - - name_render.edited.connect((path, text) => { - Gtk.TreeIter iter; - this.data.get_iter_from_string(out iter, path); - - this.data.set(iter, DataPos.NAME, text); - - // try to change icon to a fitting one - string icon; - this.data.get(iter, DataPos.ICON, out icon); - if (icon == "application-default-icon" && Gtk.IconTheme.get_default().has_icon(text.down())) { - this.data.set(iter, DataPos.ICON, text.down()); - } - - this.update_pie(iter); - this.update_linked(); - - //this.set_cursor(new Gtk.TreePath.from_string(path), type_column, true); - }); - - name_column.pack_start(name_render, true); - name_column.add_attribute(name_render, "weight", DataPos.FONT_WEIGHT); - name_column.add_attribute(name_render, "text", DataPos.NAME); - name_column.add_attribute(name_render, "sensitive", DataPos.ICON_NAME_EDITABLE); - name_column.add_attribute(name_render, "editable", DataPos.ICON_NAME_EDITABLE); - - this.append_column(icon_column); - this.append_column(name_column); - this.append_column(type_column); - this.append_column(command_column); + name_render.ellipsize_set = true; + main_column.pack_start(name_render, true); - this.realize.connect(this.load); - - // context menu - var menu = new Gtk.Menu(); - - var item = new Gtk.ImageMenuItem.with_label(_("Add new Pie")); - item.set_image(new Gtk.Image.from_stock(Gtk.Stock.ADD, Gtk.IconSize.MENU)); - item.activate.connect(this.add_empty_pie); - menu.append(item); - - item = new Gtk.ImageMenuItem.with_label(_("Add new Slice")); - item.set_image(new Gtk.Image.from_stock(Gtk.Stock.ADD, Gtk.IconSize.MENU)); - item.activate.connect(this.add_empty_slice); - menu.append(item); - - var sepa = new Gtk.SeparatorMenuItem(); - menu.append(sepa); - - item = new Gtk.ImageMenuItem.with_label(_("Delete")); - item.set_image(new Gtk.Image.from_stock(Gtk.Stock.DELETE, Gtk.IconSize.MENU)); - item.activate.connect(this.delete_selection); - menu.append(item); + base.append_column(main_column); - menu.show_all(); - - this.button_press_event.connect((event) => { - if (event.type == Gdk.EventType.BUTTON_PRESS && event.button == 3) { - menu.popup(null, null, null, event.button, event.time); - } - return false; - }); + main_column.add_attribute(icon_render, "pixbuf", DataPos.ICON); + main_column.add_attribute(name_render, "markup", DataPos.NAME); // setup drag'n'drop Gtk.TargetEntry uri_source = {"text/uri-list", 0, 0}; Gtk.TargetEntry[] entries = { uri_source }; - - this.drag_data_received.connect(this.on_dnd_received); - this.drag_data_get.connect(this.on_dnd_source); + this.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, entries, Gdk.DragAction.LINK); this.enable_model_drag_dest(entries, Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK); + this.drag_data_get.connect(this.on_dnd_source); + this.drag_begin.connect_after(this.on_start_drag); + this.drag_motion.connect(this.on_drag_move); + this.drag_leave.connect(() => { + this.last_hover = 0; + }); this.get_selection().changed.connect(() => { - Gtk.TreeIter selected; - if (this.get_selection().get_selected(null, out selected)) { - if (this.data.iter_depth(selected) == 0) { - this.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, entries, Gdk.DragAction.LINK); - } else { - this.unset_rows_drag_source(); - } + Gtk.TreeIter active; + if (this.get_selection().get_selected(null, out active)) { + string id = ""; + this.data.get(active, DataPos.ID, out id); + this.on_select(id); } }); - this.drag_begin.connect(() => { - this.unset_rows_drag_dest(); - }); - - this.drag_end.connect(() => { - this.enable_model_drag_dest(entries, Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK); - }); + reload_all(); } - // moves the selected slice up - public void selection_up() { - Gtk.TreeIter selected; - if (this.get_selection().get_selected(null, out selected)) { - Gtk.TreePath path = this.data.get_path(selected); - Gtk.TreeIter? before = null;; - if (path.prev() && this.data.get_iter(out before, path)) { - this.data.swap(selected, before); - this.get_selection().changed(); - this.update_pie(selected); - } - } - } + ///////////////////////////////////////////////////////////////////// + /// Loads all existing Pies to the list. + ///////////////////////////////////////////////////////////////////// - // moves the selected slice down - public void selection_down() { - Gtk.TreeIter selected; - if (this.get_selection().get_selected(null, out selected)) { - Gtk.TreePath path = this.data.get_path(selected); - Gtk.TreeIter? after = null; - path.next(); - if (this.data.get_iter(out after, path)) { - this.data.swap(selected, after); - this.get_selection().changed(); - this.update_pie(selected); - } - } - } + public void reload_all() { + Gtk.TreeIter active; + string id = ""; + if (this.get_selection().get_selected(null, out active)) + this.data.get(active, DataPos.ID, out id); - // updates the entire list, checking for changed cross-references via PieActions - // updates their names and icons if needed - private void update_linked() { - this.data.foreach((model, path, iter) => { - string action_type; - this.data.get(iter, DataPos.ACTION_TYPE, out action_type); - - if (action_type == typeof(PieAction).name()) { - string command; - this.data.get(iter, DataPos.REAL_COMMAND_PIE, out command); - - var referee = PieManager.all_pies[command]; - - if (referee != null) { - this.data.set(iter, DataPos.ICON, referee.icon); - this.data.set(iter, DataPos.NAME, referee.name); - this.data.set(iter, DataPos.ICON_PIXBUF, this.load_icon(referee.icon, this.small_icon)); - this.data.set(iter, DataPos.DISPLAY_COMMAND_PIE, referee.name); - } else { - // referenced Pie does not exist anymore or no is selected; - // select the first one... - Gtk.TreeIter first_pie; - this.pies.get_iter_first(out first_pie); - - string name; - string id; - - this.pies.get(first_pie, PiePos.NAME, out name); - this.pies.get(first_pie, PiePos.ID, out id); - - this.data.set(iter, DataPos.DISPLAY_COMMAND_PIE, name); - this.data.set(iter, DataPos.REAL_COMMAND_PIE, id); - - update_linked(); - } - } else if (action_type == typeof(ActionGroup).name()) { - string command; - this.data.get(iter, DataPos.REAL_COMMAND_GROUP, out command); - - if (command == "") { - // no group is selected, select the first one... - Gtk.TreeIter first_group; - this.groups.get_iter_first(out first_group); - - string name; - string type; - string icon; - - this.groups.get(first_group, GroupPos.NAME, out name); - this.groups.get(first_group, GroupPos.TYPE, out type); - this.groups.get(first_group, GroupPos.ICON, out icon); - - this.data.set(iter, DataPos.DISPLAY_COMMAND_GROUP, name); - this.data.set(iter, DataPos.NAME, name); - this.data.set(iter, DataPos.REAL_COMMAND_GROUP, type); - this.data.set(iter, DataPos.ICON, icon); - } - } - - return false; - }); + data.clear(); + foreach (var pie in PieManager.all_pies.entries) { + this.load_pie(pie.value); + } + + select(id); } - // adds a new, empty pie to the list - private void add_empty_pie() { - var new_one = PieManager.create_persistent_pie(_("New Pie"), "application-default-icon", null); - - Gtk.TreeIter last; - this.pies.append(out last); this.pies.set(last, 0, new_one.name, 1, new_one.id); + ///////////////////////////////////////////////////////////////////// + /// Selects the first Pie. + ///////////////////////////////////////////////////////////////////// - Gtk.TreeIter parent; - this.data.append(out parent, null); - this.data.set(parent, DataPos.IS_QUICKACTION, false, - DataPos.ICON, new_one.icon, - DataPos.NAME, new_one.name, - DataPos.TYPE_ID, "ID: " + new_one.id, - DataPos.ACTION_TYPE, new_one.id, - DataPos.ICON_PIXBUF, this.load_icon(new_one.icon, this.large_icon), - DataPos.FONT_WEIGHT, 800, - DataPos.ICON_NAME_EDITABLE, true, - DataPos.QUICKACTION_VISIBLE, false, - DataPos.QUICKACTION_ACTIVATABLE, false, - DataPos.TYPE_VISIBLE, false, - DataPos.GROUP_VISIBLE, false, - DataPos.APP_VISIBLE, false, - DataPos.KEY_VISIBLE, false, - DataPos.PIE_VISIBLE, false, - DataPos.URI_VISIBLE, false, - DataPos.TRIGGER_VISIBLE, true, - DataPos.DISPLAY_COMMAND_GROUP, "", - DataPos.DISPLAY_COMMAND_APP, "", - DataPos.DISPLAY_COMMAND_KEY, PieManager.get_accelerator_label_of(new_one.id), - DataPos.DISPLAY_COMMAND_PIE, "", - DataPos.DISPLAY_COMMAND_URI, "", - DataPos.REAL_COMMAND_GROUP, "", - DataPos.REAL_COMMAND_PIE, "", - DataPos.REAL_COMMAND_KEY, PieManager.get_accelerator_of(new_one.id)); - + public void select_first() { + Gtk.TreeIter active; - this.get_selection().select_iter(parent); - this.scroll_to_cell(this.data.get_path(parent), null, true, 0.5f, 0.0f); - } - - // adds a new empty slice to the list - private void add_empty_slice() { - Gtk.TreeIter selected; - if (this.get_selection().get_selected(null, out selected)) { - var path = this.data.get_path(selected); - if (path != null) { - if (path.get_depth() == 2) - this.data.iter_parent(out selected, selected); - - this.load_action(selected, new AppAction(_("New Action"), "application-default-icon", "")); - - Gtk.TreeIter new_one; - this.data.iter_nth_child(out new_one, selected, this.data.iter_n_children(selected)-1); - this.expand_to_path(this.data.get_path(new_one)); - this.get_selection().select_iter(new_one); - this.scroll_to_cell(this.data.get_path(new_one), null, true, 0.5f, 0.0f); - - this.update_pie(selected); - } + if(this.data.get_iter_first(out active) ) { + this.get_selection().select_iter(active); + string id = ""; + this.data.get(active, DataPos.ID, out id); + this.on_select(id); } else { - var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), Gtk.DialogFlags.MODAL, - Gtk.MessageType.INFO, - Gtk.ButtonsType.CLOSE, - _("You have to select a Pie to add a Slice to!")); - dialog.run(); - dialog.destroy(); + this.on_select(""); } } - // writes the contents of action to the position pointed by slice - private void write_action(Action action, Gtk.TreeIter slice) { - this.data.set(slice, DataPos.IS_QUICKACTION, action.is_quick_action, - DataPos.ICON, action.icon, - DataPos.NAME, action.name, - DataPos.TYPE_ID, ActionRegistry.names[action.get_type()], - DataPos.ACTION_TYPE, action.get_type().name(), - DataPos.ICON_PIXBUF, this.load_icon(action.icon, this.small_icon), - DataPos.FONT_WEIGHT, 400, - DataPos.ICON_NAME_EDITABLE, !(action is PieAction), - DataPos.QUICKACTION_VISIBLE, true, - DataPos.QUICKACTION_ACTIVATABLE, true, - DataPos.TYPE_VISIBLE, true, - DataPos.GROUP_VISIBLE, false, - DataPos.TRIGGER_VISIBLE, false, - DataPos.APP_VISIBLE, action is AppAction, - DataPos.KEY_VISIBLE, action is KeyAction, - DataPos.PIE_VISIBLE, action is PieAction, - DataPos.URI_VISIBLE, action is UriAction, - DataPos.DISPLAY_COMMAND_GROUP, "", - DataPos.DISPLAY_COMMAND_APP, (action is AppAction) ? action.display_command : "", - DataPos.DISPLAY_COMMAND_KEY, (action is KeyAction) ? action.display_command : _("Not bound"), - DataPos.DISPLAY_COMMAND_PIE, (action is PieAction) ? action.display_command : "", - DataPos.DISPLAY_COMMAND_URI, (action is UriAction) ? action.display_command : "", - DataPos.REAL_COMMAND_GROUP, "", - DataPos.REAL_COMMAND_PIE, (action is PieAction) ? action.real_command : "", - DataPos.REAL_COMMAND_KEY, (action is KeyAction) ? action.real_command : ""); - } + ///////////////////////////////////////////////////////////////////// + /// Selects the Pie with the given ID. + ///////////////////////////////////////////////////////////////////// - // deletes the currently selected pie or slice - private void delete_selection() { - Gtk.TreeIter selected; - if (this.get_selection().get_selected(null, out selected)) { - var path = this.data.get_path(selected); - if (path != null) { - if (path.get_depth() == 1) - this.delete_pie(selected); - else - this.delete_slice(selected); - } - } else { - var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), Gtk.DialogFlags.MODAL, - Gtk.MessageType.INFO, - Gtk.ButtonsType.CLOSE, - _("You have to select a Pie or a Slice to delete!")); - dialog.run(); - dialog.destroy(); - } - } - - // deletes the given pie - private void delete_pie(Gtk.TreeIter pie) { - var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), Gtk.DialogFlags.MODAL, - Gtk.MessageType.QUESTION, - Gtk.ButtonsType.YES_NO, - _("Do you really want to delete the selected Pie with all contained Slices?")); - - dialog.response.connect((response) => { - if (response == Gtk.ResponseType.YES) { - string id; - this.data.get(pie, DataPos.ACTION_TYPE, out id); - this.data.remove(pie); - PieManager.remove_pie(id); - - this.pies.foreach((model, path, iter) => { - string pies_id; - this.pies.get(iter, PiePos.ID, out pies_id); - - if (id == pies_id) { - this.pies.remove(iter); - return true; - } - - return false; - }); - - this.update_linked(); - } - }); - - dialog.run(); - dialog.destroy(); - } - - // deletes the given slice - private void delete_slice(Gtk.TreeIter slice) { - var dialog = new Gtk.MessageDialog((Gtk.Window)this.get_toplevel(), Gtk.DialogFlags.MODAL, - Gtk.MessageType.QUESTION, - Gtk.ButtonsType.YES_NO, - _("Do you really want to delete the selected Slice?")); - - dialog.response.connect((response) => { - if (response == Gtk.ResponseType.YES) { - Gtk.TreeIter parent; - this.data.iter_parent(out parent, slice); - this.data.remove(slice); - this.update_pie(parent); + public void select(string id) { + this.data.foreach((model, path, iter) => { + string pie_id; + this.data.get(iter, DataPos.ID, out pie_id); + + if (id == pie_id) { + this.get_selection().select_iter(iter); + return true; } + + return false; }); - - dialog.run(); - dialog.destroy(); } - // loads all pies to the list - private void load() { - foreach (var pie in PieManager.all_pies.entries) { - this.load_pie(pie.value); - } - } + ///////////////////////////////////////////////////////////////////// + /// Loads one given pie to the list. + ///////////////////////////////////////////////////////////////////// - // loads one given pie to the list private void load_pie(Pie pie) { if (pie.id.length == 3) { - Gtk.TreeIter last; - this.pies.append(out last); this.pies.set(last, PiePos.NAME, pie.name, - PiePos.ID, pie.id); - - Gtk.TreeIter parent; - this.data.append(out parent, null); - this.data.set(parent, DataPos.IS_QUICKACTION, false, - DataPos.ICON, pie.icon, - DataPos.NAME, pie.name, - DataPos.TYPE_ID, "ID: " + pie.id, - DataPos.ACTION_TYPE, pie.id, - DataPos.ICON_PIXBUF, this.load_icon(pie.icon, this.large_icon), - DataPos.FONT_WEIGHT, 800, - DataPos.ICON_NAME_EDITABLE, true, - DataPos.QUICKACTION_VISIBLE, false, - DataPos.QUICKACTION_ACTIVATABLE, false, - DataPos.TYPE_VISIBLE, false, - DataPos.GROUP_VISIBLE, false, - DataPos.APP_VISIBLE, false, - DataPos.KEY_VISIBLE, false, - DataPos.PIE_VISIBLE, false, - DataPos.URI_VISIBLE, false, - DataPos.TRIGGER_VISIBLE, true, - DataPos.DISPLAY_COMMAND_GROUP, "", - DataPos.DISPLAY_COMMAND_APP, "", - DataPos.DISPLAY_COMMAND_KEY, PieManager.get_accelerator_label_of(pie.id), - DataPos.DISPLAY_COMMAND_PIE, "", - DataPos.DISPLAY_COMMAND_URI, "", - DataPos.REAL_COMMAND_GROUP, "", - DataPos.REAL_COMMAND_PIE, "", - DataPos.REAL_COMMAND_KEY, PieManager.get_accelerator_of(pie.id)); - - foreach (var group in pie.action_groups) { - this.load_group(parent, group); - } + this.data.append(out last); + var icon = new Icon(pie.icon, 24); + this.data.set(last, DataPos.ICON, icon.to_pixbuf(), + DataPos.ICON_NAME, pie.icon, + DataPos.NAME, pie.name, + DataPos.ID, pie.id); } } - // loads a given group - private void load_group(Gtk.TreeIter parent, ActionGroup group) { - if (group.get_type() == typeof(ActionGroup)) { - foreach (var action in group.actions) { - this.load_action(parent, action); - } - } else { - Gtk.TreeIter child; - this.data.append(out child, parent); - this.data.set(child, DataPos.IS_QUICKACTION, false, - DataPos.ICON, GroupRegistry.icons[group.get_type()], - DataPos.NAME, GroupRegistry.names[group.get_type()], - DataPos.TYPE_ID, _("Slice group"), - DataPos.ACTION_TYPE, typeof(ActionGroup).name(), - DataPos.ICON_PIXBUF, this.load_icon(GroupRegistry.icons[group.get_type()], this.small_icon), - DataPos.FONT_WEIGHT, 400, - DataPos.ICON_NAME_EDITABLE, false, - DataPos.QUICKACTION_VISIBLE, true, - DataPos.QUICKACTION_ACTIVATABLE, false, - DataPos.TYPE_VISIBLE, true, - DataPos.GROUP_VISIBLE, true, - DataPos.APP_VISIBLE, false, - DataPos.KEY_VISIBLE, false, - DataPos.PIE_VISIBLE, false, - DataPos.URI_VISIBLE, false, - DataPos.TRIGGER_VISIBLE, false, - DataPos.DISPLAY_COMMAND_GROUP, GroupRegistry.names[group.get_type()], - DataPos.DISPLAY_COMMAND_APP, "", - DataPos.DISPLAY_COMMAND_KEY, _("Not bound"), - DataPos.DISPLAY_COMMAND_PIE, "", - DataPos.DISPLAY_COMMAND_URI, "", - DataPos.REAL_COMMAND_GROUP, group.get_type().name(), - DataPos.REAL_COMMAND_PIE, "", - DataPos.REAL_COMMAND_KEY, ""); + ///////////////////////////////////////////////////////////////////// + /// Called when a drag which started on this Widget was successfull. + ///////////////////////////////////////////////////////////////////// + + private void on_dnd_source(Gdk.DragContext context, Gtk.SelectionData selection_data, uint info, uint time_) { + if (this.drag_start != null) { + string id = ""; + this.data.get(this.drag_start, DataPos.ID, out id); + selection_data.set_uris({"file://" + Paths.launchers + "/" + id + ".desktop"}); } } - // loads a given slice - private void load_action(Gtk.TreeIter parent, Action action) { - Gtk.TreeIter child; - this.data.append(out child, parent); - this.write_action(action, child); - } + ///////////////////////////////////////////////////////////////////// + /// Called when a drag operation is started on this Widget. + ///////////////////////////////////////////////////////////////////// - // applies all changes done to the given pie - private void update_pie(Gtk.TreeIter slice_or_pie) { - // get pie iter - var path = this.data.get_path(slice_or_pie); - if (path != null) { - var pie = slice_or_pie; - if (path.get_depth() == 2) - this.data.iter_parent(out pie, slice_or_pie); + private void on_start_drag(Gdk.DragContext ctx) { + if (this.get_selection().get_selected(null, out this.drag_start)) { + string icon_name = ""; + this.data.get(this.drag_start, DataPos.ICON_NAME, out icon_name); - // get information on pie - string id; - string icon; - string name; - string hotkey; - - this.data.get(pie, DataPos.ICON, out icon); - this.data.get(pie, DataPos.NAME, out name); - this.data.get(pie, DataPos.ACTION_TYPE, out id); - this.data.get(pie, DataPos.REAL_COMMAND_KEY, out hotkey); - - // remove pie - PieManager.remove_pie(id); - - this.pies.foreach((model, path, iter) => { - string pies_id; - this.pies.get(iter, PiePos.ID, out pies_id); - - if (id == pies_id) { - this.pies.set(iter, PiePos.NAME, name); - return true; - } - - return false; - }); - - // create new pie - var new_pie = PieManager.create_persistent_pie(name, icon, new Trigger.from_string(hotkey), id); - - // add actions accordingly - if (this.data.iter_has_child(pie)) { - Gtk.TreeIter child; - this.data.iter_children(out child, pie); - - do { - // get slice information - string slice_type; - string slice_icon; - string slice_name; - bool is_quick_action; - - this.data.get(child, DataPos.ICON, out slice_icon); - this.data.get(child, DataPos.NAME, out slice_name); - this.data.get(child, DataPos.ACTION_TYPE, out slice_type); - this.data.get(child, DataPos.IS_QUICKACTION, out is_quick_action); - - if (slice_type == typeof(AppAction).name()) { - string slice_command; - this.data.get(child, DataPos.DISPLAY_COMMAND_APP, out slice_command); - var group = new ActionGroup(new_pie.id); - group.add_action(new AppAction(slice_name, slice_icon, slice_command, is_quick_action)); - new_pie.add_group(group); - } else if (slice_type == typeof(KeyAction).name()) { - string slice_command; - this.data.get(child, DataPos.REAL_COMMAND_KEY, out slice_command); - var group = new ActionGroup(new_pie.id); - group.add_action(new KeyAction(slice_name, slice_icon, slice_command, is_quick_action)); - new_pie.add_group(group); - } else if (slice_type == typeof(PieAction).name()) { - string slice_command; - this.data.get(child, DataPos.REAL_COMMAND_PIE, out slice_command); - var group = new ActionGroup(new_pie.id); - group.add_action(new PieAction(slice_command, is_quick_action)); - new_pie.add_group(group); - } else if (slice_type == typeof(UriAction).name()) { - string slice_command; - this.data.get(child, DataPos.DISPLAY_COMMAND_URI, out slice_command); - var group = new ActionGroup(new_pie.id); - group.add_action(new UriAction(slice_name, slice_icon, slice_command, is_quick_action)); - new_pie.add_group(group); - } else if (slice_type == typeof(ActionGroup).name()) { - string slice_command; - this.data.get(child, DataPos.REAL_COMMAND_GROUP, out slice_command); - - var group = GLib.Object.new(GLib.Type.from_name(slice_command), "parent_id", new_pie.id); - new_pie.add_group(group as ActionGroup); - } - - } while (this.data.iter_next(ref child)); - } - } + var icon = new Icon(icon_name, 48); + var pixbuf = icon.to_pixbuf(); + Gtk.drag_set_icon_pixbuf(ctx, pixbuf, icon.size()/2, icon.size()/2); + } } - // creates new action when the list receives a drag'n'drop event - private void on_dnd_received(Gdk.DragContext context, int x, int y, Gtk.SelectionData selection_data, uint info, uint time_) { - string[] uris = selection_data.get_uris(); - + ///////////////////////////////////////////////////////////////////// + /// Called when something is dragged over this Widget. + ///////////////////////////////////////////////////////////////////// + + private bool on_drag_move(Gdk.DragContext context, int x, int y, uint time) { + + Gtk.TreeViewDropPosition position; Gtk.TreePath path; - Gtk.TreeViewDropPosition pos; - // check for valid position - if (!this.get_dest_row_at_pos(x, y, out path, out pos) - || (path.to_string() == "0" && pos == Gtk.TreeViewDropPosition.BEFORE)) { - - warning("Failed to insert Slice: Invalid location!"); - return; - } - - // get position to insert (when child: after, when parent: as first child) - Gtk.TreeIter parent; - int insert_pos = 0; - if (path.get_depth() == 1) { - if (pos == Gtk.TreeViewDropPosition.BEFORE) { - path.prev(); - this.data.get_iter(out parent, path); - insert_pos = this.data.iter_n_children(parent); - } else { - this.data.get_iter(out parent, path); - } - } else { - if (pos == Gtk.TreeViewDropPosition.BEFORE) { - insert_pos = path.get_indices()[1]; - } else { - insert_pos = path.get_indices()[1]+1; - } - - path.up(); - this.data.get_iter(out parent, path); - } + if (!this.get_dest_row_at_pos(x, y, out path, out position)) + return false; - foreach (var uri in uris) { - Gtk.TreeIter new_child; - this.data.insert(out new_child, parent, insert_pos); - this.write_action(ActionRegistry.new_for_uri(uri), new_child); - } + if (position == Gtk.TreeViewDropPosition.BEFORE) + this.set_drag_dest_row(path, Gtk.TreeViewDropPosition.INTO_OR_BEFORE); + else if (position == Gtk.TreeViewDropPosition.AFTER) + this.set_drag_dest_row(path, Gtk.TreeViewDropPosition.INTO_OR_AFTER); + + Gdk.drag_status(context, context.get_suggested_action(), time); - this.update_pie(parent); - } - - private void on_dnd_source(Gdk.DragContext context, Gtk.SelectionData selection_data, uint info, uint time_) { - Gtk.TreeIter selected; - if (this.get_selection().get_selected(null, out selected)) { - string id = ""; - this.data.get(selected, DataPos.ACTION_TYPE, out id); - selection_data.set_uris({"file://" + Paths.launchers + "/" + id + ".desktop"}); - } - } - - private Gdk.Pixbuf load_icon(string name, int size) { - Gdk.Pixbuf pixbuf = null; + // avoid too frequent selection... + this.last_hover = time; - try { - if (name.contains("/")) - pixbuf = new Gdk.Pixbuf.from_file_at_size(name, size, size); - else - pixbuf = new Gdk.Pixbuf.from_file_at_size(Icon.get_icon_file(name, size), size, size); - } catch (GLib.Error e) { - warning(e.message); - } + GLib.Timeout.add(150, () => { + if (this.last_hover == time) + this.get_selection().select_path(path); + return false; + }); - return pixbuf; + return true; } } |