diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/actionGroups/actionGroup.vala | 23 | ||||
| -rw-r--r-- | src/actionGroups/clipboardGroup.vala | 124 | ||||
| -rw-r--r-- | src/actionGroups/groupRegistry.vala | 31 | ||||
| -rw-r--r-- | src/actionGroups/windowListGroup.vala | 54 | ||||
| -rw-r--r-- | src/actionGroups/workspaceWindowListGroup.vala | 145 | ||||
| -rw-r--r-- | src/deamon.vala | 90 | ||||
| -rw-r--r-- | src/gui/aboutWindow.vala | 1 | ||||
| -rw-r--r-- | src/gui/newSliceWindow.vala | 55 | ||||
| -rw-r--r-- | src/gui/preferencesWindow.vala | 38 | ||||
| -rw-r--r-- | src/gui/themeList.vala | 3 | ||||
| -rw-r--r-- | src/pies/defaultConfig.vala | 4 | ||||
| -rw-r--r-- | src/pies/load.vala | 11 | ||||
| -rw-r--r-- | src/pies/save.vala | 2 | ||||
| -rwxr-xr-x | src/renderers/pieWindow.vala | 1 | ||||
| -rw-r--r-- | src/themes/theme.vala | 46 | ||||
| -rw-r--r-- | src/utilities/config.vala | 2 | ||||
| -rw-r--r-- | src/utilities/paths.vala | 22 | 
17 files changed, 408 insertions, 244 deletions
| diff --git a/src/actionGroups/actionGroup.vala b/src/actionGroups/actionGroup.vala index 8bbcde4..85488ad 100644 --- a/src/actionGroups/actionGroup.vala +++ b/src/actionGroups/actionGroup.vala @@ -56,6 +56,20 @@ public class ActionGroup : GLib.Object {      public virtual void on_remove() {}      ///////////////////////////////////////////////////////////////////// +    /// This one is called, when the ActionGroup is saved. +    ///////////////////////////////////////////////////////////////////// + +    public virtual void on_save(Xml.TextWriter writer) { +        writer.write_attribute("type", GroupRegistry.descriptions[this.get_type().name()].id); +    } + +    ///////////////////////////////////////////////////////////////////// +    /// This one is called, when the ActionGroup is loaded. +    ///////////////////////////////////////////////////////////////////// + +    public virtual void on_load(Xml.Node* data) {} + +    /////////////////////////////////////////////////////////////////////      /// Adds a new Action to the group.      ///////////////////////////////////////////////////////////////////// @@ -76,8 +90,9 @@ public class ActionGroup : GLib.Object {      /////////////////////////////////////////////////////////////////////      public void disable_quickactions() { -        foreach (var action in actions) +        foreach (var action in actions) {              action.is_quickaction = false; +        }      }      ///////////////////////////////////////////////////////////////////// @@ -85,9 +100,11 @@ public class ActionGroup : GLib.Object {      /////////////////////////////////////////////////////////////////////      public bool has_quickaction() { -        foreach (var action in actions) -            if (action.is_quickaction) +        foreach (var action in actions) { +            if (action.is_quickaction) {                  return true; +            } +        }          return false;      } diff --git a/src/actionGroups/clipboardGroup.vala b/src/actionGroups/clipboardGroup.vala index ad18740..58409de 100644 --- a/src/actionGroups/clipboardGroup.vala +++ b/src/actionGroups/clipboardGroup.vala @@ -25,34 +25,78 @@ namespace GnomePie {  public class ClipboardGroup : ActionGroup {      ///////////////////////////////////////////////////////////////////// -    /// -    /////////////////////////////////////////////////////////////////////      private class ClipboardItem : GLib.Object { -        public string name { get; private set; } -        public string icon { get; private set; } +        public string name { get; protected set; } +        public string icon { get; protected set; } + +        protected Gtk.Clipboard clipboard { get; set; } +        protected static Key paste_key = new Key.from_string("<Control>v"); + +        public virtual void paste() {} +    } -        private Gtk.SelectionData contents; +    ///////////////////////////////////////////////////////////////////// -        public ClipboardItem(Gtk.SelectionData contents) { -            this.contents = contents.copy(); -            this.name = this.contents.get_text() ?? ""; -            this.icon = "edit-paste"; +    private class TextClipboardItem : ClipboardItem { + +        public TextClipboardItem(Gtk.Clipboard clipboard) { +            GLib.Object(clipboard : clipboard, +                        name      : clipboard.wait_for_text(), +                        icon      : "edit-paste"); + +            // check whether a file has been copied and search for a cool icon +            var first_line = this.name.substring(0, this.name.index_of("\n")); +            var file = GLib.File.new_for_path(first_line); + +            if (file.query_exists()) { +                try { +                    var info = file.query_info("standard::icon", 0); +                    this.icon = Icon.get_icon_name(info.get_icon()); +                } catch (Error e) { +                    warning("Failed to generate icon for ClipboardGroupItem."); +                } +            }          } -        public void paste() { -            debug(name); +        public override void paste() { +            clipboard.set_text(name, name.length); +            paste_key.press();          }      } -    public ClipboardGroup(string parent_id) { -        GLib.Object(parent_id : parent_id); +    ///////////////////////////////////////////////////////////////////// + +    private class ImageClipboardItem : ClipboardItem { + +        private Gdk.Pixbuf image { get; set; } + +        public ImageClipboardItem(Gtk.Clipboard clipboard) { +            GLib.Object(clipboard : clipboard, +                        name      : _("Image data"), +                        icon      : "image-viewer"); +            this.image = clipboard.wait_for_image(); +        } + +        public override void paste() { +            clipboard.set_image(image); +            paste_key.press(); +        }      }      ///////////////////////////////////////////////////////////////////// +    /// The maximum remembered items of the clipboard. +    ///////////////////////////////////////////////////////////////////// + +    public int max_items {get; set; default=8; } +      ///////////////////////////////////////////////////////////////////// +    public ClipboardGroup(string parent_id) { +        GLib.Object(parent_id : parent_id); +    } +      /////////////////////////////////////////////////////////////////////      /// Used to register this type of ActionGroup. It sets the display      /// name for this ActionGroup, it's icon name and the string used in @@ -74,12 +118,7 @@ public class ClipboardGroup : ActionGroup {      private Gtk.Clipboard clipboard; - -    ///////////////////////////////////////////////////////////////////// -    /// The maximum remembered items of the clipboard. -    ///////////////////////////////////////////////////////////////////// - -    private static const int max_items = 6; +    private bool ignore_next_change = false;      private Gee.ArrayList<ClipboardItem?> items; @@ -89,26 +128,61 @@ public class ClipboardGroup : ActionGroup {          this.clipboard.owner_change.connect(this.on_change);      } +    ///////////////////////////////////////////////////////////////////// +    /// This one is called, when the ActionGroup is saved. +    ///////////////////////////////////////////////////////////////////// + +    public override void on_save(Xml.TextWriter writer) { +        base.on_save(writer); +        writer.write_attribute("max_items", this.max_items.to_string()); +    } + +    ///////////////////////////////////////////////////////////////////// +    /// This one is called, when the ActionGroup is loaded. +    ///////////////////////////////////////////////////////////////////// + +    public override void on_load(Xml.Node* data) { +        for (Xml.Attr* attribute = data->properties; attribute != null; attribute = attribute->next) { +            string attr_name = attribute->name.down(); +            string attr_content = attribute->children->content; + +            if (attr_name == "max_items") { +                this.max_items = int.parse(attr_content); +            } +        } +    } +      private void on_change() { +        if (ignore_next_change) { +            ignore_next_change = false; +            return; +        } +          if (this.clipboard.wait_is_text_available()) { -            this.clipboard.request_contents(Gdk.Atom.intern("text/plain", false), this.add_item); +            if (clipboard.wait_for_text() != null) { +                add_item(new TextClipboardItem(this.clipboard)); +            } +        } else if (this.clipboard.wait_is_image_available()) { +            add_item(new ImageClipboardItem(this.clipboard));          }      } -    private void add_item(Gtk.Clipboard c, Gtk.SelectionData contents) { -        var new_item = new ClipboardItem(contents); +    private void add_item(ClipboardItem item) { -        if (this.items.size == ClipboardGroup.max_items) +        // remove one item if there are too many +        if (this.items.size == this.max_items) {              this.items.remove_at(0); +        } -        this.items.add(new_item); +        this.items.add(item);          // update slices          this.delete_all(); -        for (int i=0; i<this.items.size; ++i) { +        for (int i=this.items.size-1; i>=0; --i) {              var action = new SigAction(items[i].name, items[i].icon, i.to_string());              action.activated.connect(() => { +                ignore_next_change = true;                  this.items[int.parse(action.real_command)].paste();              });              this.add_action(action); diff --git a/src/actionGroups/groupRegistry.vala b/src/actionGroups/groupRegistry.vala index ebf34ba..c97cf95 100644 --- a/src/actionGroups/groupRegistry.vala +++ b/src/actionGroups/groupRegistry.vala @@ -57,6 +57,10 @@ public class GroupRegistry : GLib.Object {          types.add(typeof(BookmarkGroup).name());          descriptions.set(typeof(BookmarkGroup).name(), type_description); +        type_description = ClipboardGroup.register(); +        types.add(typeof(ClipboardGroup).name()); +        descriptions.set(typeof(ClipboardGroup).name(), type_description); +          type_description = DevicesGroup.register();          types.add(typeof(DevicesGroup).name());          descriptions.set(typeof(DevicesGroup).name(), type_description); @@ -72,10 +76,6 @@ public class GroupRegistry : GLib.Object {          type_description = WindowListGroup.register();          types.add(typeof(WindowListGroup).name());          descriptions.set(typeof(WindowListGroup).name(), type_description); - -        type_description = WorkspaceWindowListGroup.register(); -        types.add(typeof(WorkspaceWindowListGroup).name()); -        descriptions.set(typeof(WorkspaceWindowListGroup).name(), type_description);      }      ///////////////////////////////////////////////////////////////////// @@ -84,12 +84,23 @@ public class GroupRegistry : GLib.Object {      public static ActionGroup? create_group(string type_id, string parent_id) {          switch (type_id) { -            case "bookmarks": return new BookmarkGroup(parent_id); -            case "devices": return new DevicesGroup(parent_id); -            case "menu": return new MenuGroup(parent_id); -            case "session": return new SessionGroup(parent_id); -            case "window_list": return new WindowListGroup(parent_id); -            case "workspace_window_list": return new WorkspaceWindowListGroup(parent_id); +            case "bookmarks": +                return new BookmarkGroup(parent_id); +            case "clipboard": +                return new ClipboardGroup(parent_id); +            case "devices": +                return new DevicesGroup(parent_id); +            case "menu": +                return new MenuGroup(parent_id); +            case "session": +                return new SessionGroup(parent_id); +            case "window_list": +                return new WindowListGroup(parent_id); +            // deprecated +            case "workspace_window_list": +                var group = new WindowListGroup(parent_id); +                group.current_workspace_only = true; +                return group;          }          return null; diff --git a/src/actionGroups/windowListGroup.vala b/src/actionGroups/windowListGroup.vala index 1560f5f..69029a7 100644 --- a/src/actionGroups/windowListGroup.vala +++ b/src/actionGroups/windowListGroup.vala @@ -38,6 +38,8 @@ public class WindowListGroup : ActionGroup {          return description;      } +    public bool current_workspace_only { get; set; default=false; } +      /////////////////////////////////////////////////////////////////////      /// Two members needed to avoid useless, frequent changes of the      /// stored Actions. @@ -65,22 +67,50 @@ public class WindowListGroup : ActionGroup {          this.screen.window_opened.connect(reload);          this.screen.window_closed.connect(reload); +        this.screen.active_workspace_changed.connect(reload); -        this.load(); +        this.update(); +    } + +    ///////////////////////////////////////////////////////////////////// +    /// This one is called, when the ActionGroup is saved. +    ///////////////////////////////////////////////////////////////////// + +    public override void on_save(Xml.TextWriter writer) { +        base.on_save(writer); +        writer.write_attribute("current_workspace_only", this.current_workspace_only.to_string()); +    } + +    ///////////////////////////////////////////////////////////////////// +    /// This one is called, when the ActionGroup is loaded. +    ///////////////////////////////////////////////////////////////////// + +    public override void on_load(Xml.Node* data) { +        for (Xml.Attr* attribute = data->properties; attribute != null; attribute = attribute->next) { +            string attr_name = attribute->name.down(); +            string attr_content = attribute->children->content; + +            if (attr_name == "current_workspace_only") { +                this.current_workspace_only = bool.parse(attr_content); +            } +        }      }      /////////////////////////////////////////////////////////////////////      /// Loads all currently opened windows and creates actions for them.      ///////////////////////////////////////////////////////////////////// -    private void load() { +    private void update() {          unowned GLib.List<Wnck.Window?> windows = this.screen.get_windows();          var matcher = Bamf.Matcher.get_default();          foreach (var window in windows) {              if (window.get_window_type() == Wnck.WindowType.NORMAL -                && !window.is_skip_pager() && !window.is_skip_tasklist()) { +                && !window.is_skip_pager() && !window.is_skip_tasklist() +                && (!current_workspace_only || (window.get_workspace() != null +                && window.get_workspace() == this.screen.get_active_workspace()))) { +                  var application = window.get_application();                  var bamf_app = matcher.get_application_for_xid((uint32)window.get_xid()); @@ -102,17 +132,18 @@ public class WindowListGroup : ActionGroup {                      if (win.get_workspace() != null) {                          //select the workspace -                        if (win.get_workspace() != win.get_screen().get_active_workspace()) +                        if (win.get_workspace() != win.get_screen().get_active_workspace()) {                              win.get_workspace().activate(time_stamp); +                        } -                        //select the viewport inside the wprkspace +                        //select the viewport inside the workspace                          if (!win.is_in_viewport(win.get_workspace()) ) {                              int xp, yp, widthp, heightp, scx, scy, nx, ny, wx, wy;                              win.get_geometry (out xp, out yp, out widthp, out heightp); -                            scx= win.get_screen().get_width(); -                            scy= win.get_screen().get_height(); -                            wx= win.get_workspace().get_viewport_x(); -                            wy= win.get_workspace().get_viewport_y(); +                            scx = win.get_screen().get_width(); +                            scy = win.get_screen().get_height(); +                            wx = win.get_workspace().get_viewport_x(); +                            wy = win.get_workspace().get_viewport_y();                              if (scx > 0 && scy > 0) {                                  nx= ((wx+xp) / scx) * scx;                                  ny= ((wy+yp) / scy) * scy; @@ -121,8 +152,9 @@ public class WindowListGroup : ActionGroup {                          }                      } -                    if (win.is_minimized()) +                    if (win.is_minimized()) {                          win.unminimize(time_stamp); +                    }                      win.activate_transient(time_stamp);                  }); @@ -147,7 +179,7 @@ public class WindowListGroup : ActionGroup {                  // reload                  this.delete_all(); -                this.load(); +                this.update();                  this.changing = false;                  return false; diff --git a/src/actionGroups/workspaceWindowListGroup.vala b/src/actionGroups/workspaceWindowListGroup.vala deleted file mode 100644 index 42a4863..0000000 --- a/src/actionGroups/workspaceWindowListGroup.vala +++ /dev/null @@ -1,145 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// Copyright (c) 2011-2015 by Simon Schneegans -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or (at -// your option) any later version. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -///////////////////////////////////////////////////////////////////////// - -namespace GnomePie { - -///////////////////////////////////////////////////////////////////// -/// This group displays a list of all running application windows of -/// the current workspace. -///////////////////////////////////////////////////////////////////// - -public class WorkspaceWindowListGroup : ActionGroup { - -    ///////////////////////////////////////////////////////////////////// -    /// Used to register this type of ActionGroup. It sets the display -    /// name for this ActionGroup, it's icon name and the string used in -    /// the pies.conf file for this kind of ActionGroups. -    ///////////////////////////////////////////////////////////////////// - -    public static GroupRegistry.TypeDescription register() { -        var description = new GroupRegistry.TypeDescription(); -        description.name = _("Group: Window List for current workspace"); -        description.icon = "preferences-system-windows"; -        description.description = _("Shows a Slice for each of your opened windows on the current workspace."); -        description.id = "workspace_window_list"; -        return description; -    } - -    ///////////////////////////////////////////////////////////////////// -    /// Two members needed to avoid useless, frequent changes of the -    /// stored Actions. -    ///////////////////////////////////////////////////////////////////// - -    private bool changing = false; -    private bool changed_again = false; - -    private Wnck.Screen screen; - -    ///////////////////////////////////////////////////////////////////// -    /// C'tor, initializes all members. -    ///////////////////////////////////////////////////////////////////// - -    public WorkspaceWindowListGroup(string parent_id) { -        GLib.Object(parent_id : parent_id); -    } - -    ///////////////////////////////////////////////////////////////////// -    /// Loads all windows. -    ///////////////////////////////////////////////////////////////////// - -    construct { -        this.screen = Wnck.Screen.get_default(); - -        this.screen.window_opened.connect(reload); -        this.screen.window_closed.connect(reload); -        this.screen.active_workspace_changed.connect(reload); - -        this.load(); -    } - -    ///////////////////////////////////////////////////////////////////// -    /// Loads all currently opened windows and creates actions for them. -    ///////////////////////////////////////////////////////////////////// - -    private void load() { -        unowned GLib.List<Wnck.Window?> windows = this.screen.get_windows(); - -        var matcher = Bamf.Matcher.get_default(); - -        foreach (var window in windows) { -            if (window.get_window_type() == Wnck.WindowType.NORMAL -                && !window.is_skip_pager() && !window.is_skip_tasklist() -                && window.get_workspace() != null -                && window.get_workspace() == this.screen.get_active_workspace()) { - -                var application = window.get_application(); -                var bamf_app = matcher.get_application_for_xid((uint32)window.get_xid()); - -                string name = window.get_name(); - -                if (name.length > 30) -                    name = name.substring(0, 30) + "..."; - -                var action = new SigAction( -                    name, -                    (bamf_app == null) ? application.get_icon_name().down() : bamf_app.get_icon(), -                    "%lu".printf(window.get_xid()) -                ); -                action.activated.connect((time_stamp) => { -                    Wnck.Screen.get_default().force_update(); - -                    var xid = (X.Window)uint64.parse(action.real_command); -                    var win = Wnck.Window.get(xid); - -                    if (win.is_minimized()) -                        win.unminimize(time_stamp); - -                    win.activate_transient(time_stamp); -                }); -                this.add_action(action); -            } -        } -    } - -    ///////////////////////////////////////////////////////////////////// -    /// Reloads all running applications. -    ///////////////////////////////////////////////////////////////////// - -    private void reload() { -        // avoid too frequent changes... -        if (!this.changing) { -            this.changing = true; -            Timeout.add(500, () => { -                if (this.changed_again) { -                    this.changed_again = false; -                    return true; -                } - -                // reload -                this.delete_all(); -                this.load(); - -                this.changing = false; -                return false; -            }); -        } else { -            this.changed_again = true; -        } -    } -} - -} diff --git a/src/deamon.vala b/src/deamon.vala index f4e1aeb..5430a09 100644 --- a/src/deamon.vala +++ b/src/deamon.vala @@ -38,12 +38,18 @@ public class Deamon : GLib.Application {      public static bool disable_header_bar     = false;      public static bool disable_stack_switcher = false; + +    ///////////////////////////////////////////////////////////////////// +    /// true if init_pies() has been called already +    ///////////////////////////////////////////////////////////////////// +    private bool initialized = false; +      /////////////////////////////////////////////////////////////////////      /// The beginning of everything.      /////////////////////////////////////////////////////////////////////      public static int main(string[] args) { -        version = "0.6.6"; +        version = "0.6.7";          // disable overlay scrollbar --- hacky workaround for black /          // transparent background @@ -81,15 +87,20 @@ public class Deamon : GLib.Application {      /////////////////////////////////////////////////////////////////////      private const GLib.OptionEntry[] options = { -        { "open", 'o', 0, GLib.OptionArg.STRING, out open_pie, +        { "open", 'o', 0, GLib.OptionArg.STRING, +          out open_pie,            "Open the Pie with the given ID", "ID" }, -        { "reset", 'r', 0, GLib.OptionArg.NONE, out reset, +        { "reset", 'r', 0, GLib.OptionArg.NONE, +          out reset,            "Reset all options to default values" }, -        { "no-header-bar", 'b', 0, GLib.OptionArg.NONE, out disable_header_bar, +        { "no-header-bar", 'b', 0, GLib.OptionArg.NONE, +          out disable_header_bar,            "Disables the usage of GTK.HeaderBar" }, -        { "no-stack-switcher", 's', 0, GLib.OptionArg.NONE, out disable_stack_switcher, +        { "no-stack-switcher", 's', 0, GLib.OptionArg.NONE, +          out disable_stack_switcher,            "Disables the usage of GTK.StackSwitcher" }, -        { "print-ids", 'p', 0, GLib.OptionArg.NONE, out print_ids, +        { "print-ids", 'p', 0, GLib.OptionArg.NONE, +          out print_ids,            "Prints all Pie names with their according IDs" },          { null }      }; @@ -103,31 +114,27 @@ public class Deamon : GLib.Application {          Object(application_id: "org.gnome.gnomepie",                 flags: GLib.ApplicationFlags.HANDLES_COMMAND_LINE); -        message("Welcome to Gnome-Pie " + version + "!"); -          // init locale support          Intl.bindtextdomain("gnomepie", Paths.locales);          Intl.textdomain("gnomepie"); -        // init toolkits and static stuff -        ActionRegistry.init(); -        GroupRegistry.init(); - -        PieManager.init(); - -        // initialize icon cache -        Icon.init(); -          // connect SigHandlers          Posix.signal(Posix.SIGINT, sig_handler);          Posix.signal(Posix.SIGTERM, sig_handler);          this.startup.connect(()=>{ +            message("Welcome to Gnome-Pie " + version + "!"); + +            this.init_pies();              // launch the indicator              this.indicator = new Indicator(); +            if (open_pie != null && open_pie != "") { +                PieManager.open_pie(open_pie); +            } +              // finished loading... so run the prog!              message("Started happily...");              hold(); @@ -138,7 +145,9 @@ public class Deamon : GLib.Application {      /// Call handle_command_line on program launch.      ///////////////////////////////////////////////////////////////////// -    protected override bool local_command_line(ref unowned string[] args, out int exit_status) { +    protected override bool local_command_line( +        ref unowned string[] args, out int exit_status) { +          exit_status = 0;          // copy command line @@ -173,6 +182,26 @@ public class Deamon : GLib.Application {          GLib.Application.get_default().release();      } +    ///////////////////////////////////////////////////////////////////// +    /// Print a nifty message when the prog is killed. +    ///////////////////////////////////////////////////////////////////// + +    private void init_pies() { +        if (!this.initialized) { + +            // init static stuff +            ActionRegistry.init(); +            GroupRegistry.init(); + +            // load all pies +            PieManager.init(); + +            // initialize icon cache +            Icon.init(); + +            this.initialized = true; +        } +    }      /////////////////////////////////////////////////////////////////////      /// Handles command line parameters. @@ -188,7 +217,9 @@ public class Deamon : GLib.Application {              context.parse(ref args);          } catch(GLib.OptionError error) {              warning(error.message); -            message("Run '%s' to launch Gnome-Pie or run '%s --help' to see a full list of available command line options.\n", args[0], args[0]); +            message("Run '%s' to launch Gnome-Pie or run '%s --help' to" + +                    " see a full list of available command line options.\n", +                    args[0], args[0]);          }          if (reset) { @@ -199,22 +230,29 @@ public class Deamon : GLib.Application {                  message("Removed file \"%s\"", Paths.settings);              } +            // do not notify the already running instance (if any)              return true;          } -        if (open_pie != null && open_pie != "") { -            PieManager.open_pie(open_pie); -            open_pie = ""; -        } else if (called_from_remote) { -            this.indicator.show_preferences(); -        } -          if (print_ids) { +            this.init_pies();              PieManager.print_ids();              print_ids = false; + +            // do not notify the already running instance (if any)              return true;          } + +        if (called_from_remote) { +            if (open_pie != null && open_pie != "") { +                PieManager.open_pie(open_pie); +            } else { +                this.indicator.show_preferences(); +            } +        } + +        // notify the already running instance (if any)          return false;      }  } diff --git a/src/gui/aboutWindow.vala b/src/gui/aboutWindow.vala index 896d2ba..fd38c8c 100644 --- a/src/gui/aboutWindow.vala +++ b/src/gui/aboutWindow.vala @@ -47,6 +47,7 @@ public class AboutWindow: Gtk.AboutDialog {              "Moo <hazap@hotmail.com> (LT)",              "Gabriel Dubatti <gdubatti@gmail.com> (ES)",              "Grégoire Bellon-Gervais <greggbg@gmail.com> (FR)", +            "Raphaël Rochet <raphael@rri.fr> (FR)",              "Alex Maxime <cad.maxime@gmail.com> (FR)",              "Eugene Roskin <pams@imail.ru> (RU)",              "Ting Zhou <tzhou@haverford.edu> (ZH-CN)", diff --git a/src/gui/newSliceWindow.vala b/src/gui/newSliceWindow.vala index 6066e57..89294b5 100644 --- a/src/gui/newSliceWindow.vala +++ b/src/gui/newSliceWindow.vala @@ -57,11 +57,15 @@ public class NewSliceWindow : GLib.Object {      private Gtk.Box hotkey_box = null;      private Gtk.Box uri_box = null;      private Gtk.Box quickaction_box = null; +    private Gtk.Box clipboard_box = null; +    private Gtk.Box workspace_only_box = null;      private Gtk.Image icon = null;      private Gtk.Entry name_entry = null;      private Gtk.Entry command_entry = null;      private Gtk.Entry uri_entry = null; -    private Gtk.CheckButton quickaction_checkbutton = null; +    private Gtk.Switch quickaction_checkbutton = null; +    private Gtk.Switch workspace_only_checkbutton = null; +    private Gtk.Scale clipboard_slider = null;      /////////////////////////////////////////////////////////////////////      /// Two custom widgets. For Pie and hotkey selection respectively. @@ -116,16 +120,25 @@ public class NewSliceWindow : GLib.Object {                  this.hotkey_box.hide();                  this.uri_box.hide();                  this.quickaction_box.hide(); +                this.workspace_only_box.hide(); +                this.clipboard_box.hide();                  this.current_type = type;                  switch (type) { -                    case "bookmarks": case "clipboard": case "devices": -                    case "menu": case "session": case "window_list": -                    case "workspace_window_list": +                    case "bookmarks": case "devices": +                    case "menu": case "session":                          this.no_options_box.show();                          this.set_icon(icon);                          break; +                    case "window_list": +                        this.workspace_only_box.show(); +                        this.set_icon(icon); +                        break; +                    case "clipboard": +                        this.clipboard_box.show(); +                        this.set_icon(icon); +                        break;                      case "app":                          this.name_box.show();                          this.command_box.show(); @@ -183,11 +196,18 @@ public class NewSliceWindow : GLib.Object {              this.name_entry = builder.get_object("name-entry") as Gtk.Entry;              this.uri_entry = builder.get_object("uri-entry") as Gtk.Entry;              this.command_entry = builder.get_object("command-entry") as Gtk.Entry; -            this.quickaction_checkbutton = builder.get_object("quick-action-checkbutton") as Gtk.CheckButton; - +            this.quickaction_checkbutton = builder.get_object("quick-action-checkbutton") as Gtk.Switch;              this.quickaction_box = builder.get_object("quickaction-box") as Gtk.Box;              this.icon = builder.get_object("icon") as Gtk.Image; +            this.workspace_only_checkbutton = builder.get_object("workspace-only-checkbutton") as Gtk.Switch; +            this.workspace_only_box = builder.get_object("workspace-only-box") as Gtk.Box; + +            this.clipboard_box = builder.get_object("clipboard-box") as Gtk.Box; +            this.clipboard_slider = (builder.get_object("clipboard-scale") as Gtk.Scale); +                 clipboard_slider.set_range(2, 24); +                 clipboard_slider.set_value(8); +              this.icon_button.clicked.connect(on_icon_button_clicked);              var scroll_area = builder.get_object("slice-scrolledwindow") as Gtk.ScrolledWindow; @@ -273,6 +293,15 @@ public class NewSliceWindow : GLib.Object {          } else {              type = GroupRegistry.descriptions[group.get_type().name()].id; +            switch (type) { +                case "clipboard": +                    this.clipboard_slider.set_value((group as ClipboardGroup).max_items); +                    break; +                case "window_list": +                    this.workspace_only_checkbutton.active = (group as WindowListGroup).current_workspace_only; +                    break; + +            }              this.select_type(type);          }      } @@ -314,13 +343,19 @@ public class NewSliceWindow : GLib.Object {          switch (this.current_type) {              case "bookmarks":   group = new BookmarkGroup(this.current_id);      break; -            case "clipboard":   group = new ClipboardGroup(this.current_id);     break;              case "devices":     group = new DevicesGroup(this.current_id);       break;              case "menu":        group = new MenuGroup(this.current_id);          break;              case "session":     group = new SessionGroup(this.current_id);       break; -            case "window_list": group = new WindowListGroup(this.current_id);    break; -            case "workspace_window_list": group = new WorkspaceWindowListGroup(this.current_id);    break; - +            case "clipboard": +                var g = new ClipboardGroup(this.current_id); +                g.max_items = (int)this.clipboard_slider.get_value(); +                group = g; +                break; +            case "window_list": +                var g = new WindowListGroup(this.current_id); +                g.current_workspace_only = this.workspace_only_checkbutton.active; +                group = g; +                break;              case "app":                  group = new ActionGroup(this.current_id);                  group.add_action(new AppAction(this.name_entry.text, this.current_icon, diff --git a/src/gui/preferencesWindow.vala b/src/gui/preferencesWindow.vala index d671501..09d8a3c 100644 --- a/src/gui/preferencesWindow.vala +++ b/src/gui/preferencesWindow.vala @@ -43,6 +43,7 @@ public class PreferencesWindow : GLib.Object {      private Gtk.EventBox? preview_background = null;      private Gtk.Button? remove_pie_button = null;      private Gtk.Button? edit_pie_button = null; +    private Gtk.Button? theme_delete_button = null;      private ThemeList? theme_list = null;      private Gtk.ToggleButton? indicator = null; @@ -149,6 +150,11 @@ public class PreferencesWindow : GLib.Object {              } else {                  this.captions.sensitive = false;              } +            if (Config.global.theme.is_local()) { +                this.theme_delete_button.sensitive = true; +            } else { +                this.theme_delete_button.sensitive = false; +            }          });          scroll_area = builder.get_object("theme-scrolledwindow") as Gtk.ScrolledWindow; @@ -164,6 +170,8 @@ public class PreferencesWindow : GLib.Object {          (builder.get_object("theme-export-button") as Gtk.Button).clicked.connect(on_export_theme_button_clicked);          (builder.get_object("theme-import-button") as Gtk.Button).clicked.connect(on_import_theme_button_clicked); +        this.theme_delete_button = (builder.get_object("theme-delete-button") as Gtk.Button); +        this.theme_delete_button.clicked.connect(on_delete_theme_button_clicked);          this.autostart = (builder.get_object("autostart-checkbox") as Gtk.ToggleButton);          this.autostart.toggled.connect(on_autostart_toggled); @@ -230,7 +238,7 @@ public class PreferencesWindow : GLib.Object {              _("You can support the development of Gnome-Pie by donating via %s.").printf("<a href='https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=X65SUVC4ZTQSC'>Paypal</a>"),              _("Translating Gnome-Pie to your language is easy. Translations are managed at %s.").printf("<a href='https://translate.zanata.org/zanata/iteration/view/gnome-pie/develop'>Zanata</a>"),              _("It's easy to create new themes for Gnome-Pie. Read the <a href='%s'>Tutorial</a> online.").printf("http://simmesimme.github.io/lessons/2015/04/26/themes-for-gnome-pie/"), -            _("It's usually a good practive to have at most twelve slices per pie."), +            _("It's usually a good practice to have at most twelve slices per pie."),              _("You can export themes you created and share them with the community!"),              _("The source code of Gnome-Pie is available on %s.").printf("<a href='https://github.com/Simmesimme/Gnome-Pie'>Github</a>"),              _("Bugs can be reported at %s!").printf("<a href='https://github.com/Simmesimme/Gnome-Pie/issues'>Github</a>"), @@ -284,6 +292,12 @@ public class PreferencesWindow : GLib.Object {              this.captions.sensitive = false;          } +        if (Config.global.theme.is_local()) { +            this.theme_delete_button.sensitive = true; +        } else { +            this.theme_delete_button.sensitive = false; +        } +          if (!Deamon.disable_stack_switcher) {              this.stack.set_visible_child_full("2", Gtk.StackTransitionType.NONE);          } else { @@ -427,6 +441,28 @@ public class PreferencesWindow : GLib.Object {      }      ///////////////////////////////////////////////////////////////////// +    /// Deleted the slected theme. +    ///////////////////////////////////////////////////////////////////// + +    private void on_delete_theme_button_clicked(Gtk.Button button) { + +        var dialog = new Gtk.MessageDialog((Gtk.Window)this.window.get_toplevel(), Gtk.DialogFlags.MODAL, +                         Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, +                         _("Do you really want to delete the selected theme from %s?").printf(Config.global.theme.directory)); + +        dialog.response.connect((response) => { +            if (response == Gtk.ResponseType.YES) { +                Paths.delete_directory(Config.global.theme.directory); +                Config.global.load_themes(""); +                this.theme_list.reload(); +            } +        }); + +        dialog.run(); +        dialog.destroy(); +    } + +    /////////////////////////////////////////////////////////////////////      /// Shows or hides the indicator.      ///////////////////////////////////////////////////////////////////// diff --git a/src/gui/themeList.vala b/src/gui/themeList.vala index 46ae876..e6ecb3c 100644 --- a/src/gui/themeList.vala +++ b/src/gui/themeList.vala @@ -105,7 +105,8 @@ class ThemeList : Gtk.TreeView {              data.set(current, DataPos.ICON, theme.preview_icon.to_pixbuf());              data.set(current, DataPos.NAME, GLib.Markup.escape_text(theme.name)+"\n"                                              + "<span font-size='x-small'>" + GLib.Markup.escape_text(theme.description) -                                            + "</span>"); +                                            + " - <i>"+GLib.Markup.escape_text(_("by")+" "+theme.author) +                                            + "</i></span>");              if(theme == Config.global.theme) {                  get_selection().select_iter(current);              } diff --git a/src/pies/defaultConfig.vala b/src/pies/defaultConfig.vala index e446c2b..8763a1d 100644 --- a/src/pies/defaultConfig.vala +++ b/src/pies/defaultConfig.vala @@ -62,6 +62,10 @@ namespace Pies {              window.add_action(new KeyAction(_("Maximize"), "view-fullscreen", "<Alt>F10"));              window.add_action(new KeyAction(_("Restore"), "view-restore", "<Alt>F5")); +        // add a pie with window list group +        var alt_tab = PieManager.create_persistent_pie("Alt Tab", "dock", new Trigger.from_string("<Control><Alt>T")); +            alt_tab.add_group(new WindowListGroup(alt_tab.id)); +          // save the configuration to file          Pies.save();      } diff --git a/src/pies/load.vala b/src/pies/load.vala index 7402094..0dfb423 100644 --- a/src/pies/load.vala +++ b/src/pies/load.vala @@ -192,17 +192,14 @@ namespace Pies {              string attr_name = attribute->name.down();              string attr_content = attribute->children->content; -            switch (attr_name) { -                case "type": -                    type = attr_content; -                    break; -                default: -                    warning("Invalid attribute \"" + attr_name + "\" in <group> element in pies.conf!"); -                    break; +            if (attr_name == "type") { +                type = attr_content; +                break;              }          }          ActionGroup group = GroupRegistry.create_group(type, pie.id); +        group.on_load(slice);          if (group != null) pie.add_group(group);      } diff --git a/src/pies/save.vala b/src/pies/save.vala index 9760cce..efb3fb6 100644 --- a/src/pies/save.vala +++ b/src/pies/save.vala @@ -72,7 +72,7 @@ namespace Pies {                          }                      } else {                          writer.start_element("group"); -                            writer.write_attribute("type", GroupRegistry.descriptions[group.get_type().name()].id); +                            group.on_save(writer);                          writer.end_element();                          slice_count += group.actions.size; diff --git a/src/renderers/pieWindow.vala b/src/renderers/pieWindow.vala index c1d70b7..5accb15 100755 --- a/src/renderers/pieWindow.vala +++ b/src/renderers/pieWindow.vala @@ -445,6 +445,7 @@ public class PieWindow : Gtk.Window {          if      (Gdk.keyval_name(key) == "Escape") this.cancel();          else if (Gdk.keyval_name(key) == "Return") this.activate_slice(time_stamp); +        else if (Gdk.keyval_name(key) == "KP_Enter") this.activate_slice(time_stamp);          else if (!PieManager.get_is_turbo(this.renderer.id)) {              if (Gdk.keyval_name(key) == "Up") this.renderer.select_up();              else if (Gdk.keyval_name(key) == "Down") this.renderer.select_down(); diff --git a/src/themes/theme.vala b/src/themes/theme.vala index 98e8994..2e256f9 100644 --- a/src/themes/theme.vala +++ b/src/themes/theme.vala @@ -87,14 +87,44 @@ public class Theme : GLib.Object {          this.active_slice_layers.clear();          this.inactive_slice_layers.clear(); +        if (!GLib.File.new_for_path(this.directory).query_exists()) { +            return false; +        } + +        string config_file = this.directory + "/theme.xml"; + +        if (!GLib.File.new_for_path(config_file).query_exists()) { +            try { +                // detect whether theme is one directory deeper +                string child; +                bool success = false; + +                // load global themes +                var d = Dir.open(this.directory); +                while ((child = d.read_name()) != null && !success) { +                    config_file = this.directory + "/" + child + "/theme.xml"; +                    if (GLib.File.new_for_path(config_file).query_exists()) { +                        this.directory = this.directory + "/" + child; +                        success = true; +                    } +                } + +                if (!success) { +                    return false; +                } +            } catch (Error e) { +                warning (e.message); +                return false; +            } +        } +          this.preview_icon = new Icon(this.directory + "/preview.png", 36);          Xml.Parser.init(); -        string path = this.directory + "/theme.xml"; -        Xml.Doc* themeXML = Xml.Parser.parse_file(path); +        Xml.Doc* themeXML = Xml.Parser.parse_file(config_file);          if (themeXML == null) { -            warning("Failed to add theme: \"" + path + "\" not found!"); +            warning("Failed to add theme: \"" + config_file + "\" not found!");              return false;          } @@ -151,6 +181,7 @@ public class Theme : GLib.Object {          }      } +      /////////////////////////////////////////////////////////////////////      /// Loads all images of the theme.      ///////////////////////////////////////////////////////////////////// @@ -165,6 +196,15 @@ public class Theme : GLib.Object {      }      ///////////////////////////////////////////////////////////////////// +    /// Returns true if the theme is installed to the local themes +    /// directory. +    ///////////////////////////////////////////////////////////////////// + +    public bool is_local() { +        return this.directory.has_prefix(Paths.local_themes); +    } + +    /////////////////////////////////////////////////////////////////////      /// The following methods parse specific parts of the theme file.      /// Nothing special here, just some boring code.      ///////////////////////////////////////////////////////////////////// diff --git a/src/utilities/config.vala b/src/utilities/config.vala index 5dedddb..74bbcbb 100644 --- a/src/utilities/config.vala +++ b/src/utilities/config.vala @@ -57,7 +57,7 @@ public class Config : GLib.Object {      public int  activation_range { get; set; default = 200; }      public int  max_visible_slices { get; set; default = 24; }      public bool show_indicator { get; set; default = true; } -    public bool show_captions { get; set; default = true; } +    public bool show_captions { get; set; default = false; }      public bool search_by_string { get; set; default = true; }      public bool auto_start { get; set; default = false; }      public int showed_news { get; set; default = 0; } diff --git a/src/utilities/paths.vala b/src/utilities/paths.vala index 96bce0a..7bdd642 100644 --- a/src/utilities/paths.vala +++ b/src/utilities/paths.vala @@ -108,6 +108,28 @@ public class Paths : GLib.Object {      public static string executable { get; private set; default=""; }      ///////////////////////////////////////////////////////////////////// +    /// Deletes a directory recursively from disk. Use with care :) +    ///////////////////////////////////////////////////////////////////// + +    public static void delete_directory(string directory) { +        try { +            var d = Dir.open(directory); +            string name; +            while ((name = d.read_name()) != null) { +                string path = Path.build_filename(directory, name); +                if (FileUtils.test(path, FileTest.IS_DIR)) { +                    delete_directory(path); +                } else { +                    FileUtils.remove(path); +                } +            } +            DirUtils.remove(directory); +        } catch (Error e) { +            warning (e.message); +        } +    } + +    /////////////////////////////////////////////////////////////////////      /// Initializes all values above.      ///////////////////////////////////////////////////////////////////// | 
