grab icon, save position
This commit is contained in:
parent
5f45d85e04
commit
5bd378c9ff
8 changed files with 1804 additions and 203 deletions
16
.vscode/tasks.json
vendored
Normal file
16
.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "make",
|
||||
"type": "shell",
|
||||
"command": "cd ${workspaceFolder}/build && make",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -32,6 +32,19 @@
|
|||
</screenshot>
|
||||
</screenshots>
|
||||
<releases>
|
||||
<release version="0.2.6" date="2018-02-07">
|
||||
<description>
|
||||
<p>New:</p>
|
||||
<ul>
|
||||
<li>Save and restore window position</li>
|
||||
<li>Grab favorite icon</li>
|
||||
</ul>
|
||||
<p>Fix:</p>
|
||||
<ul>
|
||||
<li>Grab website color</li>
|
||||
</ul>
|
||||
</description>
|
||||
</release>
|
||||
<release version="0.2.5" date="2017-12-17">
|
||||
<description>
|
||||
<p>Translation:</p>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
namespace Webpin {
|
||||
public class WebpinApp : Gtk.Application {
|
||||
public string CACHE_FOLDER { get; private set; }
|
||||
|
||||
static WebpinApp _instance = null;
|
||||
|
||||
|
@ -49,10 +50,24 @@ namespace Webpin {
|
|||
start_webapp (parameter.get_string ());
|
||||
}
|
||||
});
|
||||
|
||||
create_cache_folders ();
|
||||
}
|
||||
|
||||
public Gtk.Window mainwindow { get; private set; default = null; }
|
||||
|
||||
public void create_cache_folders () {
|
||||
CACHE_FOLDER = GLib.Path.build_filename (GLib.Environment.get_user_cache_dir (), "com.github.artemanufrij.webpin");
|
||||
try {
|
||||
File file = File.new_for_path (CACHE_FOLDER);
|
||||
if (!file.query_exists ()) {
|
||||
file.make_directory ();
|
||||
}
|
||||
} catch (Error e) {
|
||||
warning (e.message);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void activate () {
|
||||
if (mainwindow != null) {
|
||||
mainwindow.present ();
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace Webpin {
|
|||
Categories=Network;
|
||||
X-GNOME-FullName=webpin
|
||||
StartupWMClass=Webpin
|
||||
X-Webpin-PrimaryColor=none""";
|
||||
X-Webpin-PrimaryColor=rgba (222,222,222,1)""";
|
||||
|
||||
GLib.KeyFile file;
|
||||
|
||||
|
|
|
@ -120,23 +120,6 @@ namespace Webpin.Widgets {
|
|||
app_notification.reveal_child = false;
|
||||
}
|
||||
request_finished ();
|
||||
var source = web_view.get_main_resource ();
|
||||
source.get_data.begin (null, (obj, res) => {
|
||||
try {
|
||||
var body = (string)source.get_data.end (res);
|
||||
var regex = new Regex ("(?<=<meta name=\"theme-color\" content=\")#[0-9a-fA-F]{6}");
|
||||
MatchInfo match_info;
|
||||
if (regex.match (body, 0, out match_info)) {
|
||||
var result = match_info.fetch (0);
|
||||
Gdk.RGBA return_value = {0, 0, 0, 1};
|
||||
if (return_value.parse (result)) {
|
||||
found_website_color (return_value);
|
||||
}
|
||||
}
|
||||
} catch (Error err) {
|
||||
warning (err.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 2015 Erasmo Marín <erasmo.marin@gmail.com>
|
||||
* Copyright (c) 2017-2017 Artem Anufrij <artem.anufrij@live.de>
|
||||
* Copyright (c) 2017-2018 Artem Anufrij <artem.anufrij@live.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
|
@ -28,7 +28,6 @@
|
|||
|
||||
namespace Webpin.Widgets.Views {
|
||||
public class Editor : Gtk.Box {
|
||||
|
||||
public enum assistant_mode { new_app, edit_app }
|
||||
|
||||
public signal void application_created (GLib.DesktopAppInfo ? new_file);
|
||||
|
@ -59,19 +58,23 @@ namespace Webpin.Widgets.Views {
|
|||
|
||||
Gdk.RGBA default_color;
|
||||
|
||||
string tmp_icon_file;
|
||||
string tmp_icon_ext;
|
||||
uint grab_timer = 0;
|
||||
|
||||
construct {
|
||||
default_color = { 222, 222, 222, 255 };
|
||||
default_color = { 0, 0, 0, 1 };
|
||||
default_color.parse ("rgba (222, 222, 222, 1)");
|
||||
}
|
||||
|
||||
public Editor () {
|
||||
|
||||
GLib.Object (orientation : Gtk.Orientation.VERTICAL);
|
||||
apps = Services.DesktopFilesManager.get_applications ();
|
||||
|
||||
this.margin = 15;
|
||||
|
||||
try {
|
||||
this.protocol_regex = new Regex ("""https?\:\/\/[\w+\d+]((\:\d+)?\/\S*)?""");
|
||||
this.protocol_regex = new Regex ("https?://[\\w+\\d+]((:\\d+)?/\\S*)?");
|
||||
} catch (RegexError e) {
|
||||
critical ("%s", e.message);
|
||||
}
|
||||
|
@ -115,7 +118,8 @@ namespace Webpin.Widgets.Views {
|
|||
|
||||
primary_color_button = new Gtk.ColorButton.with_rgba (default_color);
|
||||
primary_color_button.use_alpha = false;
|
||||
primary_color_button.color_activated.connect ((color) => {
|
||||
primary_color_button.color_activated.connect (
|
||||
(color) => {
|
||||
stdout.printf ("COLOR %s\n", color.to_string ());
|
||||
});
|
||||
|
||||
|
@ -161,30 +165,37 @@ namespace Webpin.Widgets.Views {
|
|||
pack_end (accept_button, false, false, 0);
|
||||
|
||||
//signals and handlers
|
||||
icon_button.clicked.connect(() => {
|
||||
icon_button.clicked.connect (
|
||||
() => {
|
||||
icon_selector_popover.show_all ();
|
||||
});
|
||||
|
||||
app_url_entry.changed.connect (() => {
|
||||
app_url_entry.changed.connect (
|
||||
() => {
|
||||
if (!this.protocol_regex.match (app_url_entry.get_text ())) {
|
||||
reset_grab_color_and_icon ();
|
||||
app_url_entry.get_style_context ().add_class ("error");
|
||||
app_url_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "dialog-information");
|
||||
app_url_entry.set_icon_tooltip_text (Gtk.EntryIconPosition.SECONDARY, _ ("url must start with http:// or https://"));
|
||||
app_url_valid = false;
|
||||
} else {
|
||||
grab_color_and_icon ();
|
||||
app_url_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, null);
|
||||
app_url_entry.get_style_context ().remove_class ("error");
|
||||
app_url_valid = true;
|
||||
}
|
||||
validate ();
|
||||
});
|
||||
|
||||
app_name_entry.changed.connect (() => {
|
||||
app_name_entry.changed.connect (
|
||||
() => {
|
||||
if (mode == assistant_mode.new_app && Services.DesktopFilesManager.get_applications ().has_key (app_name_entry.get_text ())) {
|
||||
app_name_entry.get_style_context ().add_class ("error");
|
||||
app_name_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "dialog-information");
|
||||
app_name_entry.set_icon_tooltip_text (Gtk.EntryIconPosition.SECONDARY, _ ("App already exist"));
|
||||
app_name_valid = false;
|
||||
} else {
|
||||
app_name_entry.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, null);
|
||||
app_name_entry.get_style_context ().remove_class ("error");
|
||||
app_name_valid = true;
|
||||
}
|
||||
|
@ -197,6 +208,108 @@ namespace Webpin.Widgets.Views {
|
|||
icon_name_entry.changed.connect (update_app_icon);
|
||||
}
|
||||
|
||||
private void grab_color_and_icon () {
|
||||
reset_grab_color_and_icon ();
|
||||
grab_timer = Timeout.add (
|
||||
500,
|
||||
() => {
|
||||
var url = app_url_entry.text;
|
||||
var session = new Soup.Session.with_options ("user_agent", "WebPin/0.1.0 (https://github.com/artemanufrij/webpin)");
|
||||
session.timeout = 2;
|
||||
var msg = new Soup.Message ("GET", url);
|
||||
session.send_message (msg);
|
||||
|
||||
if (msg.status_code == 200) {
|
||||
var body = (string)msg.response_body.data;
|
||||
|
||||
stdout.printf ("%s\n", body);
|
||||
|
||||
var regex = new Regex ("(?<=<meta name=\"theme-color\" content=\")#[0-9a-fA-F]{6}");
|
||||
MatchInfo match_info;
|
||||
if (regex.match (body, 0, out match_info)) {
|
||||
var result = match_info.fetch (0);
|
||||
Gdk.RGBA return_value = {0, 0, 0, 1};
|
||||
if (return_value.parse (result)) {
|
||||
primary_color_button.set_rgba (return_value);
|
||||
}
|
||||
}
|
||||
|
||||
regex = new Regex ("(?<=\"apple-touch-icon\" href=\")[/\\w\\.]*");
|
||||
if (regex.match (body, 0, out match_info)) {
|
||||
var result = match_info.fetch (0);
|
||||
|
||||
var icon_path = result;
|
||||
if (!result.has_prefix ("http")) {
|
||||
result = Path.build_filename (url, result);
|
||||
}
|
||||
download_icon (icon_path);
|
||||
icon_name_entry.set_text (tmp_icon_file);
|
||||
}
|
||||
|
||||
if (tmp_icon_file == "") {
|
||||
regex = new Regex ("(?<=\"fluid-icon\" href=\")[/\\w\\.:\\-]*");
|
||||
if (regex.match (body, 0, out match_info)) {
|
||||
var result = match_info.fetch (0);
|
||||
|
||||
var icon_path = result;
|
||||
if (!result.has_prefix ("http")) {
|
||||
result = Path.build_filename (url, result);
|
||||
}
|
||||
download_icon (icon_path);
|
||||
icon_name_entry.set_text (tmp_icon_file);
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_icon_file == "") {
|
||||
regex = new Regex ("(?<=\"mask-icon\" href=\")[/\\w\\.:\\-]*");
|
||||
if (regex.match (body, 0, out match_info)) {
|
||||
var result = match_info.fetch (0);
|
||||
|
||||
var icon_path = result;
|
||||
if (!result.has_prefix ("http")) {
|
||||
result = Path.build_filename (url, result);
|
||||
}
|
||||
download_icon (icon_path);
|
||||
icon_name_entry.set_text (tmp_icon_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
msg.dispose ();
|
||||
session.dispose ();
|
||||
|
||||
reset_grab_color_and_icon ();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private void reset_grab_color_and_icon () {
|
||||
if (grab_timer != 0) {
|
||||
Source.remove (grab_timer);
|
||||
grab_timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool download_icon (string url) {
|
||||
var session = new Soup.Session.with_options ("user_agent", "WebPin/0.1.0 (https://github.com/artemanufrij/webpin)");
|
||||
var msg = new Soup.Message ("GET", url);
|
||||
session.send_message (msg);
|
||||
if (msg.status_code == 200) {
|
||||
tmp_icon_ext = ".png";
|
||||
|
||||
if (url.has_suffix (".svg")) {
|
||||
tmp_icon_ext = ".svg";
|
||||
}
|
||||
|
||||
tmp_icon_file = GLib.Path.build_filename (WebpinApp.instance.CACHE_FOLDER, Random.next_int ().to_string () + tmp_icon_ext);
|
||||
var fs = FileStream.open (tmp_icon_file, "w");
|
||||
fs.write (msg.response_body.data, (size_t)msg.response_body.length);
|
||||
}
|
||||
msg.dispose ();
|
||||
session.dispose ();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void update_app_icon () {
|
||||
string icon = icon_name_entry.get_text ();
|
||||
|
@ -237,7 +350,7 @@ namespace Webpin.Widgets.Views {
|
|||
filter.set_filter_name (_ ("Images"));
|
||||
filter.add_mime_type ("image/*");
|
||||
|
||||
file_chooser = new Gtk.FileChooserDialog ("", null,
|
||||
file_chooser = new Gtk.FileChooserDialog ("", WebpinApp.instance.mainwindow,
|
||||
Gtk.FileChooserAction.OPEN,
|
||||
_ ("Cancel"), Gtk.ResponseType.CANCEL,
|
||||
_ ("Open"), Gtk.ResponseType.ACCEPT);
|
||||
|
@ -247,7 +360,8 @@ namespace Webpin.Widgets.Views {
|
|||
var preview = new Gtk.Image ();
|
||||
preview.valign = Gtk.Align.START;
|
||||
|
||||
file_chooser.update_preview.connect (()=> {
|
||||
file_chooser.update_preview.connect (
|
||||
()=> {
|
||||
string filename = file_chooser.get_preview_filename ();
|
||||
Gdk.Pixbuf pix = null;
|
||||
|
||||
|
@ -269,14 +383,12 @@ namespace Webpin.Widgets.Views {
|
|||
});
|
||||
|
||||
if (file_chooser.run () == Gtk.ResponseType.ACCEPT) {
|
||||
|
||||
icon_name_entry.set_text (file_chooser.get_filename ());
|
||||
file_chooser.destroy ();
|
||||
}
|
||||
file_chooser.destroy ();
|
||||
}
|
||||
|
||||
|
||||
private void validate () {
|
||||
if (app_icon_valid && app_name_valid && app_url_valid) {
|
||||
accept_button.set_sensitive (true);
|
||||
|
@ -285,8 +397,8 @@ namespace Webpin.Widgets.Views {
|
|||
accept_button.set_sensitive (false);
|
||||
}
|
||||
|
||||
|
||||
public void reset_fields () {
|
||||
tmp_icon_file = "";
|
||||
icon_name_entry.set_text ("");
|
||||
app_name_entry.set_text ("");
|
||||
app_name_entry.set_sensitive (true);
|
||||
|
@ -299,6 +411,12 @@ namespace Webpin.Widgets.Views {
|
|||
|
||||
private void on_accept () {
|
||||
string icon = icon_name_entry.get_text ();
|
||||
if (tmp_icon_file != "") {
|
||||
var new_icon = GLib.Path.build_filename (WebpinApp.instance.CACHE_FOLDER, app_name_entry.get_text () + tmp_icon_ext);
|
||||
FileUtils.rename (tmp_icon_file, new_icon);
|
||||
FileUtils.remove (tmp_icon_file);
|
||||
icon = new_icon;
|
||||
}
|
||||
string name = app_name_entry.get_text ();
|
||||
string url = app_url_entry.get_text ().replace ("%", "%%");
|
||||
bool stay_open = stay_open_when_closed.active;
|
||||
|
@ -337,6 +455,7 @@ namespace Webpin.Widgets.Views {
|
|||
} else {
|
||||
primary_color_button.set_rgba (default_color);
|
||||
}
|
||||
reset_grab_color_and_icon ();
|
||||
update_app_icon ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*-
|
||||
* Copyright (c) 2015 Erasmo Marín <erasmo.marin@gmail.com>
|
||||
* Copyright (c) 2017-2017 Artem Anufrij <artem.anufrij@live.de>
|
||||
* Copyright (c) 2017-2018 Artem Anufrij <artem.anufrij@live.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
|
@ -28,7 +28,6 @@
|
|||
|
||||
namespace Webpin.Windows {
|
||||
public class WebApp : Gtk.Window {
|
||||
|
||||
Gdk.WindowState current_state;
|
||||
|
||||
Widgets.Browser browser;
|
||||
|
@ -53,7 +52,8 @@ namespace Webpin.Windows {
|
|||
|
||||
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 (() => {
|
||||
copy_url.clicked.connect (
|
||||
() => {
|
||||
Gtk.Clipboard.get_default (Gdk.Display.get_default ()).set_text (browser.web_view.uri, -1);
|
||||
});
|
||||
headerbar.pack_end (copy_url);
|
||||
|
@ -66,7 +66,8 @@ namespace Webpin.Windows {
|
|||
stay_open.active = desktop_file.hide_on_close;
|
||||
stay_open.tooltip_text = _ ("Run in background if closed");
|
||||
stay_open.image = new Gtk.Image.from_icon_name ("view-pin-symbolic", Gtk.IconSize.MENU);
|
||||
stay_open.toggled.connect (() => {
|
||||
stay_open.toggled.connect (
|
||||
() => {
|
||||
desktop_file.edit_property ("X-Webpin-StayOpen", stay_open.active.to_string ());
|
||||
desktop_file.save_to_file ();
|
||||
});
|
||||
|
@ -74,7 +75,8 @@ namespace Webpin.Windows {
|
|||
|
||||
this.set_titlebar (headerbar);
|
||||
|
||||
this.delete_event.connect (() => {
|
||||
this.delete_event.connect (
|
||||
() => {
|
||||
save_settings ();
|
||||
if (desktop_file.hide_on_close) {
|
||||
this.hide_on_delete ();
|
||||
|
@ -82,12 +84,14 @@ namespace Webpin.Windows {
|
|||
return desktop_file.hide_on_close;
|
||||
});
|
||||
|
||||
this.window_state_event.connect ((event) => {
|
||||
this.window_state_event.connect (
|
||||
(event) => {
|
||||
current_state = event.new_window_state;
|
||||
return false;
|
||||
});
|
||||
|
||||
browser.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 +100,8 @@ namespace Webpin.Windows {
|
|||
}
|
||||
});
|
||||
|
||||
browser.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 +109,19 @@ namespace Webpin.Windows {
|
|||
WebpinApp.instance.send_notification (null, desktop_notification);
|
||||
});
|
||||
|
||||
browser.request_begin.connect (() => {
|
||||
browser.request_begin.connect (
|
||||
() => {
|
||||
spinner.active = true;
|
||||
});
|
||||
|
||||
browser.request_finished.connect (() => {
|
||||
browser.request_finished.connect (
|
||||
() => {
|
||||
spinner.active = false;
|
||||
});
|
||||
|
||||
browser.found_website_color.connect ((color) => {
|
||||
browser.found_website_color.connect (
|
||||
(color) => {
|
||||
stdout.printf ("%s\n", color.to_string ());
|
||||
int gray_val = (int)(desktop_file.color.red * 255);
|
||||
if (desktop_file.color == null || ((gray_val == 222 || gray_val == 255) && desktop_file.color.red == desktop_file.color.green && desktop_file.color.red == desktop_file.color.blue)) {
|
||||
set_color (color);
|
||||
|
@ -147,6 +156,8 @@ namespace Webpin.Windows {
|
|||
private void load_settings () {
|
||||
var width = desktop_file.info.get_string ("X-Webpin-WindowWidth");
|
||||
var height = desktop_file.info.get_string ("X-Webpin-WindowHeight");
|
||||
var x = desktop_file.info.get_string ("X-Webpin-WindowX");
|
||||
var y = desktop_file.info.get_string ("X-Webpin-WindowY");
|
||||
var state = desktop_file.info.get_string ("X-Webpin-WindowMaximized");
|
||||
var zoom = desktop_file.info.get_string ("X-Webpin-WindowZoom");
|
||||
|
||||
|
@ -156,6 +167,12 @@ namespace Webpin.Windows {
|
|||
set_default_size (1000, 600);
|
||||
}
|
||||
|
||||
if (x != null && y != null) {
|
||||
this.move (int.parse (x), int.parse (y));
|
||||
} else {
|
||||
this.window_position = Gtk.WindowPosition.CENTER;
|
||||
}
|
||||
|
||||
if (state != null && state == "max") {
|
||||
this.maximize ();
|
||||
}
|
||||
|
@ -169,6 +186,10 @@ namespace Webpin.Windows {
|
|||
if (this.is_maximized) {
|
||||
desktop_file.edit_property ("X-Webpin-WindowMaximized", "max");
|
||||
} else {
|
||||
int x, y;
|
||||
this.get_position (out x, out y);
|
||||
desktop_file.edit_property ("X-Webpin-WindowX", x.to_string ());
|
||||
desktop_file.edit_property ("X-Webpin-WindowY", y.to_string ());
|
||||
desktop_file.edit_property ("X-Webpin-WindowWidth", this.get_allocated_width ().to_string ());
|
||||
desktop_file.edit_property ("X-Webpin-WindowHeight", this.get_allocated_height ().to_string ());
|
||||
desktop_file.edit_property ("X-Webpin-WindowMaximized", "norm");
|
||||
|
|
1434
uncrustify.cfg
Normal file
1434
uncrustify.cfg
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue