diff --git a/src/Application.vala b/src/Application.vala index 468ab18..393f10c 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -51,7 +51,7 @@ namespace Webpin { }); } - public Gtk.Window mainwindow; + public Gtk.Window mainwindow { get; private set; default = null; } protected override void activate () { if (mainwindow != null) { @@ -66,14 +66,14 @@ namespace Webpin { start_webapp (files [0].get_uri ()); } - public void start_webapp (string url) { + private void start_webapp (string url) { if (mainwindow != null ) { mainwindow.present (); return; } var app_info = Services.DesktopFilesManager.get_app_by_url (url); var desktop_file = new Webpin.DesktopFile.from_desktopappinfo (app_info); - mainwindow = new WebWindow (desktop_file); + mainwindow = new Windows.WebApp (desktop_file); mainwindow.set_application (this); } } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 26b049c..b26fde2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,14 +1,14 @@ vala_precompile(VALA_C ${CMAKE_PROJECT_NAME} - Widgets/ApplicationIcon.vala - Widgets/ApplicationsView.vala - Widgets/Assistant.vala - Widgets/WebApp.vala + Widgets/WebItem.vala + Widgets/Views/WebItemsView.vala + Widgets/Views/Editor.vala + Widgets/Browser.vala + Windows/WebApp.vala Objects/DesktopFile.vala Dialogs/Preferences.vala Services/DesktopFilesManager.vala Settings.vala MainWindow.vala - WebWindow.vala Application.vala PACKAGES gtk+-3.0 diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 89368a1..2f36c7a 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -36,8 +36,8 @@ namespace Webpin { Gtk.Button add_button; Gtk.MenuButton app_menu; - Assistant assistant; - ApplicationsView apps_view; + Widgets.Views.Editor editor; + Widgets.Views.WebItemsView web_items_view; construct { settings = Settings.get_default (); @@ -106,44 +106,44 @@ namespace Webpin { } }); - apps_view = new ApplicationsView(); - assistant = new Assistant(); + web_items_view = new Widgets.Views.WebItemsView (); + editor = new Widgets.Views.Editor (); stack = new Gtk.Stack (); stack.set_transition_duration (500); stack.add_named (welcome, "welcome"); - stack.add_named (apps_view, "apps_view"); - stack.add_named (assistant, "assistant"); + stack.add_named (web_items_view, "apps_view"); + stack.add_named (editor, "editor"); add (stack); - apps_view.add_request.connect (() => { + web_items_view.add_request.connect (() => { show_assistant (); }); - apps_view.edit_request.connect ((desktop_file) => { + web_items_view.edit_request.connect ((desktop_file) => { show_assistant (desktop_file); }); - apps_view.app_deleted.connect (() => { - if (!apps_view.has_items) { + web_items_view.app_deleted.connect (() => { + if (!web_items_view.has_items) { show_welcome_view (Gtk.StackTransitionType.NONE); } }); - assistant.application_created.connect ((new_file) => { - apps_view.add_button (new_file); - apps_view.select_last_item (); + editor.application_created.connect ((new_file) => { + web_items_view.add_web_item (new_file); + web_items_view.select_last_item (); show_apps_view (); }); - assistant.application_edited.connect ((edited_file) => { - apps_view.update_button (edited_file); + editor.application_edited.connect ((edited_file) => { + web_items_view.update_button (edited_file); show_apps_view (); }); back_button.clicked.connect (() => { - if (apps_view.has_items) { + if (web_items_view.has_items) { show_apps_view (); } else { show_welcome_view (); @@ -162,7 +162,7 @@ namespace Webpin { this.restore_settings (); show_all (); - if (apps_view.has_items) { + if (web_items_view.has_items) { show_apps_view (Gtk.StackTransitionType.NONE); } else { show_welcome_view (Gtk.StackTransitionType.NONE); @@ -173,10 +173,10 @@ namespace Webpin { private void show_assistant (DesktopFile? desktop_file = null) { stack.set_transition_type (Gtk.StackTransitionType.SLIDE_LEFT); - stack.set_visible_child_name("assistant"); + stack.set_visible_child_name("editor"); back_button.show_all (); add_button.hide (); - assistant.edit_desktop_file (desktop_file); + editor.edit_desktop_file (desktop_file); } private void show_apps_view (Gtk.StackTransitionType slide = Gtk.StackTransitionType.SLIDE_RIGHT) { @@ -184,7 +184,7 @@ namespace Webpin { stack.set_visible_child_name ("apps_view"); back_button.hide (); add_button.show_all (); - assistant.reset_fields (); + editor.reset_fields (); } private void show_welcome_view (Gtk.StackTransitionType slide = Gtk.StackTransitionType.SLIDE_RIGHT) { @@ -192,7 +192,7 @@ namespace Webpin { stack.set_visible_child_name ("welcome"); back_button.hide (); add_button.hide (); - assistant.reset_fields (); + editor.reset_fields (); } private void restore_settings () { diff --git a/src/Services/DesktopFilesManager.vala b/src/Services/DesktopFilesManager.vala index 8d4b4ee..eda853f 100644 --- a/src/Services/DesktopFilesManager.vala +++ b/src/Services/DesktopFilesManager.vala @@ -50,17 +50,54 @@ namespace Webpin.Services { } public static Gee.HashMap get_webpin_applications () { - var list = new Gee.HashMap(); + var list = new Gee.HashMap (); - foreach (GLib.AppInfo app in GLib.AppInfo.get_all()) { - var desktop_app = new GLib.DesktopAppInfo(app.get_id ()); + foreach (GLib.AppInfo app in GLib.AppInfo.get_all ()) { + var desktop_app = new GLib.DesktopAppInfo (app.get_id ()); string keywords = desktop_app.get_string ("Keywords"); if (keywords != null && keywords.contains ("webpin")) { - list.set(desktop_app.get_name(), desktop_app); + list.set (desktop_app.get_name (), desktop_app); } } return list; } + + public static Gdk.Pixbuf? align_and_scale_pixbuf (Gdk.Pixbuf p, int size) { + Gdk.Pixbuf? pixbuf = p; + if (pixbuf.width != pixbuf.height) { + if (pixbuf.width > pixbuf.height) { + int dif = (pixbuf.width - pixbuf.height) / 2; + pixbuf = new Gdk.Pixbuf.subpixbuf (pixbuf, dif, 0, pixbuf.height, pixbuf.height); + } else { + int dif = (pixbuf.height - pixbuf.width) / 2; + pixbuf = new Gdk.Pixbuf.subpixbuf (pixbuf, 0, dif, pixbuf.width, pixbuf.width); + } + } + pixbuf = pixbuf.scale_simple (size, size, Gdk.InterpType.BILINEAR); + return pixbuf; + } + + public static string? choose_new_icon () { + string? return_value = null; + var dialog = new Gtk.FileChooserDialog ( + _("Choose an imageā€¦"), WebpinApp.instance.mainwindow, + Gtk.FileChooserAction.OPEN, + _("_Cancel"), Gtk.ResponseType.CANCEL, + _("_Open"), Gtk.ResponseType.ACCEPT); + + var filter = new Gtk.FileFilter (); + filter.set_filter_name (_("Images")); + filter.add_mime_type ("image/*"); + + dialog.add_filter (filter); + + if (dialog.run () == Gtk.ResponseType.ACCEPT) { + return_value = dialog.get_filename (); + } + + dialog.destroy(); + return return_value; + } } } diff --git a/src/Widgets/WebApp.vala b/src/Widgets/Browser.vala similarity index 98% rename from src/Widgets/WebApp.vala rename to src/Widgets/Browser.vala index 2e19619..6489345 100644 --- a/src/Widgets/WebApp.vala +++ b/src/Widgets/Browser.vala @@ -26,8 +26,8 @@ * Authored by: Artem Anufrij */ -namespace Webpin { - public class WebApp : Gtk.Stack { +namespace Webpin.Widgets { + public class Browser : Gtk.Stack { public WebKit.WebView app_view { get; private set; } public DesktopFile desktop_file { get; private set; } @@ -43,7 +43,7 @@ namespace Webpin { public signal void found_website_color (Gdk.RGBA color); - public WebApp (DesktopFile desktop_file) { + public Browser (DesktopFile desktop_file) { this.desktop_file = desktop_file; this.transition_duration = 350; this.transition_type = Gtk.StackTransitionType.SLIDE_UP; diff --git a/src/Widgets/Assistant.vala b/src/Widgets/Views/Editor.vala similarity index 99% rename from src/Widgets/Assistant.vala rename to src/Widgets/Views/Editor.vala index 6e6e1f6..ae71906 100644 --- a/src/Widgets/Assistant.vala +++ b/src/Widgets/Views/Editor.vala @@ -26,8 +26,8 @@ * Authored by: Artem Anufrij */ -namespace Webpin { - public class Assistant : Gtk.Box { +namespace Webpin.Widgets.Views { + public class Editor : Gtk.Box { public enum assistant_mode { new_app, edit_app } @@ -63,7 +63,7 @@ namespace Webpin { default_color = { 222, 222, 222, 255 }; } - public Assistant () { + public Editor () { GLib.Object (orientation: Gtk.Orientation.VERTICAL); apps = Services.DesktopFilesManager.get_applications (); diff --git a/src/Widgets/ApplicationsView.vala b/src/Widgets/Views/WebItemsView.vala similarity index 61% rename from src/Widgets/ApplicationsView.vala rename to src/Widgets/Views/WebItemsView.vala index 75edeae..517ffb3 100644 --- a/src/Widgets/ApplicationsView.vala +++ b/src/Widgets/Views/WebItemsView.vala @@ -26,33 +26,33 @@ * Authored by: Artem Anufrij */ -namespace Webpin { - public class ApplicationsView : Gtk.Box { +namespace Webpin.Widgets.Views { + public class WebItemsView : Gtk.Box { - public signal void add_request(); - public signal void edit_request(DesktopFile desktop_file); + public signal void add_request (); + public signal void edit_request (DesktopFile desktop_file); public signal void app_deleted (); - Gtk.FlowBox icon_view; + Gtk.FlowBox web_items; - public bool has_items { get { return icon_view.get_children ().length () > 0; } } + public bool has_items { get { return web_items.get_children ().length () > 0; } } - public ApplicationsView () { + public WebItemsView () { GLib.Object (orientation: Gtk.Orientation.VERTICAL); var scrolled = new Gtk.ScrolledWindow (null, null); scrolled.hscrollbar_policy = Gtk.PolicyType.NEVER; - icon_view = new Gtk.FlowBox(); - icon_view.valign = Gtk.Align.START; - icon_view.vexpand = false; - icon_view.homogeneous = true; - icon_view.column_spacing = 24; - icon_view.row_spacing = 24; - icon_view.margin = 24; - icon_view.child_activated.connect ((child) => { - if ((child as Gtk.FlowBoxChild).get_child () is ApplicationIcon) { - var app_icon = (child as Gtk.FlowBoxChild).get_child () as ApplicationIcon; + web_items = new Gtk.FlowBox(); + web_items.valign = Gtk.Align.START; + web_items.vexpand = false; + web_items.homogeneous = true; + web_items.column_spacing = 12; + web_items.row_spacing = 12; + web_items.margin = 24; + web_items.child_activated.connect ((child) => { + if (child is WebItem) { + var app_icon = child as WebItem; try { Process.spawn_command_line_async ("com.github.artemanufrij.webpin " + app_icon.desktop_file.url.replace("%%", "%")); } catch (SpawnError err) { @@ -62,7 +62,7 @@ namespace Webpin { }); load_applications (); - scrolled.add (icon_view); + scrolled.add (web_items); this.pack_start (scrolled, true, true, 0); } @@ -70,40 +70,39 @@ namespace Webpin { var applications = Services.DesktopFilesManager.get_webpin_applications (); foreach (GLib.DesktopAppInfo app in applications.values) { - this.add_button (app); + this.add_web_item (app); } } - public void add_button (GLib.DesktopAppInfo app) { - var image = new ApplicationIcon (app); - image.edit_request.connect ((desktop_file) => { + public void add_web_item (GLib.DesktopAppInfo app) { + var web_item = new WebItem (app); + web_item.edit_request.connect ((desktop_file) => { edit_request (desktop_file); - icon_view.unselect_all (); + web_items.unselect_all (); }); - image.deleted.connect ((parent) => { - this.icon_view.remove (parent); + web_item.deleted.connect (() => { app_deleted (); }); - icon_view.add (image); - icon_view.show_all (); + web_items.add (web_item); + web_items.show_all (); } public void select_last_item () { - icon_view.select_child (icon_view.get_child_at_index ((int)icon_view.get_children ().length () - 1)); + web_items.select_child (web_items.get_child_at_index ((int)web_items.get_children ().length () - 1)); } public void select_first_item () { - icon_view.select_child (icon_view.get_child_at_index (0)); + web_items.select_child (web_items.get_child_at_index (0)); } public void update_button (GLib.DesktopAppInfo app) { - foreach (var item in icon_view.get_children ()) { - if ((item as Gtk.FlowBoxChild).get_child () is ApplicationIcon) { - var app_icon = (item as Gtk.FlowBoxChild).get_child () as ApplicationIcon; + foreach (var item in web_items.get_children ()) { + if (item is WebItem) { + var app_icon = item as WebItem; if (app_icon.desktop_file.name == app.get_display_name ()) { app_icon.set_new_desktopfile (new DesktopFile.from_desktopappinfo (app)); - icon_view.select_child (item as Gtk.FlowBoxChild); + web_items.select_child (item as Gtk.FlowBoxChild); break; } } diff --git a/src/Widgets/ApplicationIcon.vala b/src/Widgets/WebItem.vala similarity index 63% rename from src/Widgets/ApplicationIcon.vala rename to src/Widgets/WebItem.vala index acbd2a8..7fde4cc 100644 --- a/src/Widgets/ApplicationIcon.vala +++ b/src/Widgets/WebItem.vala @@ -26,51 +26,48 @@ * Authored by: Artem Anufrij */ -namespace Webpin { - public class ApplicationIcon : Gtk.Overlay { +namespace Webpin.Widgets { + public class WebItem : Gtk.FlowBoxChild { Gtk.Image image; Gtk.Label label; - Gtk.Box box; internal DesktopFile desktop_file { get; private set; } - public signal void deleted (Gtk.Container? parent); + public signal void deleted (); public signal void edit_request (DesktopFile desktop_file); - public ApplicationIcon (GLib.DesktopAppInfo app) { + public WebItem (GLib.DesktopAppInfo app) { this.desktop_file = new DesktopFile.from_desktopappinfo (app); + build_ui (); + } - hexpand = false; - vexpand = false; + private void build_ui () { + var content = new Gtk.Grid (); + content.margin = 12; + content.halign = Gtk.Align.CENTER; + content.row_spacing = 6; + image = new Gtk.Image (); label = new Gtk.Label (this.desktop_file.name); set_icon (this.desktop_file.icon); - this.margin = 6; - this.margin_start = 20; - this.margin_end = 20; - var menu = new ActionMenu (); menu.halign = Gtk.Align.CENTER; menu.delete_clicked.connect (() => { remove_application (); }); menu.edit_clicked.connect (() => { edit_request (desktop_file); }); - box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); - box.pack_start (image, false, false, 0); - box.pack_start (label, false, false, 0); - box.pack_start (menu, false, false, 0); - - box.hexpand = false; - box.vexpand = false; + content.attach (image, 0, 0); + content.attach (label, 0, 1); + content.attach (menu, 0, 2); var event_box = new Gtk.EventBox (); - event_box.add (box); + event_box.add (content); event_box.events |= Gdk.EventMask.ENTER_NOTIFY_MASK|Gdk.EventMask.LEAVE_NOTIFY_MASK; event_box.enter_notify_event.connect ((event) => { - menu.set_reveal_child (true); + menu.opacity = 0.5; return false; }); @@ -78,7 +75,7 @@ namespace Webpin { if (event.detail == Gdk.NotifyType.INFERIOR) { return false; } - menu.set_reveal_child (false); + menu.opacity = 0; return false; }); @@ -98,30 +95,9 @@ namespace Webpin { } catch (Error e) { warning (e.message); } - int new_height = 64; - int new_width = 64; - int margin_vertical = 0; - int margin_horizontal = 0; - - if (pix.height > pix.width) { - new_width = new_width * pix.width / pix.height; - margin_horizontal = (new_height - new_width) / 2; - } else if (pix.height < pix.width) { - new_height = new_height * pix.height / pix.width; - margin_vertical = (new_width - new_height) / 2; - } - if (image == null) { - image = new Gtk.Image.from_pixbuf (pix.scale_simple (new_width, new_height, Gdk.InterpType.BILINEAR)); - } else { - image.set_from_pixbuf (pix.scale_simple (new_width, new_height, Gdk.InterpType.BILINEAR)); - } - - image.margin_top = margin_vertical; - image.margin_bottom = margin_vertical; - image.margin_right = margin_horizontal; - image.margin_left = margin_horizontal; + pix = Services.DesktopFilesManager.align_and_scale_pixbuf (pix, 64); + image.set_from_pixbuf (pix); } else { - image = new Gtk.Image (); image.icon_name = icon; image.pixel_size = 64; } @@ -129,12 +105,12 @@ namespace Webpin { private void remove_application () { desktop_file.delete_file (); - deleted (this.get_parent()); + deleted (); this.destroy (); } } - public class ActionMenu : Gtk.Revealer { + public class ActionMenu : Gtk.Grid { public signal void delete_clicked (); public signal void edit_clicked (); @@ -150,14 +126,9 @@ namespace Webpin { edit_button.relief = Gtk.ReliefStyle.NONE; edit_button.clicked.connect (() => { edit_clicked (); }); - var buttons = new Gtk.Grid (); - buttons.orientation = Gtk.Orientation.HORIZONTAL; - buttons.add (edit_button); - buttons.add (delete_button); - buttons.opacity = 0.5; - - this.transition_type = Gtk.RevealerTransitionType.CROSSFADE; - this.add (buttons); + this.add (edit_button); + this.add (delete_button); + this.opacity = 0; } } } diff --git a/src/WebWindow.vala b/src/Windows/WebApp.vala similarity index 87% rename from src/WebWindow.vala rename to src/Windows/WebApp.vala index 3470b00..4db5791 100644 --- a/src/WebWindow.vala +++ b/src/Windows/WebApp.vala @@ -26,17 +26,17 @@ * Authored by: Artem Anufrij */ -namespace Webpin { - public class WebWindow : Gtk.Window { +namespace Webpin.Windows { + public class WebApp : Gtk.Window { Gdk.WindowState current_state; - WebApp web_app; + Widgets.Browser browser; Gtk.Spinner spinner; public DesktopFile desktop_file { get; private set; } - public WebWindow (DesktopFile desktop_file) { + public WebApp (DesktopFile desktop_file) { this.desktop_file = desktop_file; this.set_wmclass (desktop_file.url, desktop_file.url); this.events |= Gdk.EventMask.STRUCTURE_MASK; @@ -45,7 +45,7 @@ namespace Webpin { if (color != null) { set_color (color); } - web_app = new WebApp (desktop_file); + browser = new Widgets.Browser (desktop_file); var headerbar = new Gtk.HeaderBar (); headerbar.title = desktop_file.name; @@ -54,7 +54,7 @@ namespace Webpin { var copy_url = new Gtk.Button.from_icon_name ("insert-link-symbolic", Gtk.IconSize.MENU); copy_url.tooltip_text = _("Copy URL into clipboard"); copy_url.clicked.connect (() => { - Gtk.Clipboard.get_default (Gdk.Display.get_default ()).set_text (web_app.app_view.uri, -1); + Gtk.Clipboard.get_default (Gdk.Display.get_default ()).set_text (browser.app_view.uri, -1); }); headerbar.pack_end (copy_url); @@ -87,7 +87,7 @@ namespace Webpin { return false; }); - web_app.external_request.connect ((action) => { + browser.external_request.connect ((action) => { debug ("Web app external request: %s", action.get_request ().uri); try { Process.spawn_command_line_async ("xdg-open " + action.get_request ().uri); @@ -96,7 +96,7 @@ namespace Webpin { } }); - web_app.desktop_notification.connect ((title, body, icon) => { + browser.desktop_notification.connect ((title, body, icon) => { var desktop_notification = new Notification (title); desktop_notification.set_body (body); desktop_notification.set_icon (icon); @@ -104,15 +104,15 @@ namespace Webpin { WebpinApp.instance.send_notification (null, desktop_notification); }); - web_app.request_begin.connect (() => { + browser.request_begin.connect (() => { spinner.active = true; }); - web_app.request_finished.connect (() => { + browser.request_finished.connect (() => { spinner.active = false; }); - web_app.found_website_color.connect ((color) => { + browser.found_website_color.connect ((color) => { int gray_val = (int)(desktop_file.color.red * 255); if (desktop_file.color == null || (gray_val == 222 && desktop_file.color.red == desktop_file.color.green && desktop_file.color.red == desktop_file.color.blue)) { set_color (color); @@ -120,7 +120,7 @@ namespace Webpin { } }); - this.add (web_app); + this.add (browser); load_settings (); @@ -161,7 +161,7 @@ namespace Webpin { } if (zoom != null) { - web_app.app_view.zoom_level = double.parse (zoom); + browser.app_view.zoom_level = double.parse (zoom); } } @@ -186,43 +186,43 @@ namespace Webpin { case Gdk.Key.KP_Add: case Gdk.Key.plus: if (Gdk.ModifierType.CONTROL_MASK in event.state) { - web_app.app_view.zoom_level += 0.1; - desktop_file.edit_property ("X-Webpin-WindowZoom", web_app.app_view.zoom_level.to_string ()); + browser.app_view.zoom_level += 0.1; + desktop_file.edit_property ("X-Webpin-WindowZoom", browser.app_view.zoom_level.to_string ()); return true; } break; case Gdk.Key.KP_Subtract: case Gdk.Key.minus: if (Gdk.ModifierType.CONTROL_MASK in event.state) { - web_app.app_view.zoom_level -= 0.1; - desktop_file.edit_property ("X-Webpin-WindowZoom", web_app.app_view.zoom_level.to_string ()); + browser.app_view.zoom_level -= 0.1; + desktop_file.edit_property ("X-Webpin-WindowZoom", browser.app_view.zoom_level.to_string ()); return true; } break; case Gdk.Key.KP_0: case Gdk.Key.@0: if (Gdk.ModifierType.CONTROL_MASK in event.state) { - web_app.app_view.zoom_level = 1; - desktop_file.edit_property ("X-Webpin-WindowZoom", web_app.app_view.zoom_level.to_string ()); + browser.app_view.zoom_level = 1; + desktop_file.edit_property ("X-Webpin-WindowZoom", browser.app_view.zoom_level.to_string ()); return true; } break; case Gdk.Key.F5: if (Gdk.ModifierType.CONTROL_MASK in event.state) { - web_app.app_view.reload (); + browser.app_view.reload (); } else { - web_app.app_view.reload_bypass_cache (); + browser.app_view.reload_bypass_cache (); } return true; case Gdk.Key.Left: if (Gdk.ModifierType.MOD1_MASK in event.state) { - web_app.app_view.go_back (); + browser.app_view.go_back (); return true; } break; case Gdk.Key.Right: if (Gdk.ModifierType.MOD1_MASK in event.state) { - web_app.app_view.go_forward (); + browser.app_view.go_forward (); return true; } break;