summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actionGroups/actionGroup.vala23
-rw-r--r--src/actionGroups/clipboardGroup.vala124
-rw-r--r--src/actionGroups/groupRegistry.vala31
-rw-r--r--src/actionGroups/windowListGroup.vala54
-rw-r--r--src/actionGroups/workspaceWindowListGroup.vala145
-rw-r--r--src/deamon.vala90
-rw-r--r--src/gui/aboutWindow.vala1
-rw-r--r--src/gui/newSliceWindow.vala55
-rw-r--r--src/gui/preferencesWindow.vala38
-rw-r--r--src/gui/themeList.vala3
-rw-r--r--src/pies/defaultConfig.vala4
-rw-r--r--src/pies/load.vala11
-rw-r--r--src/pies/save.vala2
-rwxr-xr-xsrc/renderers/pieWindow.vala1
-rw-r--r--src/themes/theme.vala46
-rw-r--r--src/utilities/config.vala2
-rw-r--r--src/utilities/paths.vala22
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&amp;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.
/////////////////////////////////////////////////////////////////////