diff --git a/src/data/db/tables/Tags.vala b/src/data/db/tables/Tags.vala index 68ab2e0d..dfcad4a0 100644 --- a/src/data/db/tables/Tags.vala +++ b/src/data/db/tables/Tags.vala @@ -163,6 +163,39 @@ namespace GameHub.Data.DB.Tables return true; } + public static bool remove(Tag tag) + { + unowned Sqlite.Database? db = Database.instance.db; + if(db == null) return false; + + Statement s; + int res = db.prepare_v2("DELETE FROM `tags` WHERE `id` = ?", -1, out s); + + if(res != Sqlite.OK) + { + warning("[Database.Tags.remove] Can't prepare DELETE query (%d): %s", db.errcode(), db.errmsg()); + return false; + } + + res = s.bind_text(1, tag.id); + + res = s.step(); + + if(res != Sqlite.DONE) + { + warning("[Database.Tags.remove] Error (%d): %s", db.errcode(), db.errmsg()); + return false; + } + + if(TAGS.contains(tag)) + { + TAGS.remove(tag); + instance.tags_updated(); + } + + return true; + } + public class Tag: Object { public const string BUILTIN_PREFIX = "builtin:"; @@ -210,11 +243,12 @@ namespace GameHub.Data.DB.Tables } } - public string? id { get; construct set; } - public string? name { get; construct set; } - public string icon { get; construct set; } - public bool selected { get; construct set; default = true; } - public bool enabled { get; construct set; default = true; } + public string? id { get; construct set; } + public string? name { get; construct set; } + public string icon { get; construct set; } + public bool selected { get; construct set; default = true; } + public bool enabled { get; construct set; default = true; } + public bool removable { get { return id != null && id.has_prefix(USER_PREFIX); } } public Tag(string? id, string? name, string icon="gh-tag-symbolic", bool selected=true) { @@ -233,6 +267,11 @@ namespace GameHub.Data.DB.Tables this(USER_PREFIX + Utils.md5(name), name); } + public bool remove() + { + return Tags.remove(this); + } + public static bool is_equal(Tag first, Tag second) { return first == second || first.id == second.id; diff --git a/src/ui/widgets/GameTagsList.vala b/src/ui/widgets/GameTagsList.vala index 9162f1c8..479c6c83 100644 --- a/src/ui/widgets/GameTagsList.vala +++ b/src/ui/widgets/GameTagsList.vala @@ -51,6 +51,7 @@ namespace GameHub.UI.Widgets { _games.add(game); } + update(); } construct @@ -118,7 +119,6 @@ namespace GameHub.UI.Widgets add(new_entry); Tables.Tags.instance.tags_updated.connect(update); - update(); show_all(); } diff --git a/src/ui/widgets/TagRow.vala b/src/ui/widgets/TagRow.vala index 07fb20e4..0359d601 100644 --- a/src/ui/widgets/TagRow.vala +++ b/src/ui/widgets/TagRow.vala @@ -80,11 +80,17 @@ namespace GameHub.UI.Widgets box.add(name); box.add(icon); - ebox.add_events(EventMask.BUTTON_RELEASE_MASK); - ebox.button_release_event.connect(e => { - if(e.button == 1) + ebox.add_events(EventMask.BUTTON_PRESS_MASK); + ebox.button_press_event.connect(e => { + switch(e.button) { - toggle(); + case 1: + toggle(); + break; + + case 3: + show_context_menu(e, true); + break; } return true; }); @@ -132,5 +138,31 @@ namespace GameHub.UI.Widgets tag.selected = check.active; } } + + private void show_context_menu(Event e, bool at_pointer=true) + { + var menu = new Gtk.Menu(); + + var remove = new Gtk.MenuItem.with_label(_("Remove")); + remove.sensitive = tag.removable; + remove.activate.connect(() => tag.remove()); + + menu.add(remove); + + menu.show_all(); + + #if GTK_3_22 + if(at_pointer) + { + menu.popup_at_pointer(e); + } + else + { + menu.popup_at_widget(this, Gravity.SOUTH, Gravity.NORTH, e); + } + #else + menu.popup(null, null, null, 0, ((EventButton) e).time); + #endif + } } }