diff --git a/randomwallpaper@iflow.space/convenience.js b/randomwallpaper@iflow.space/convenience.js new file mode 100644 index 0000000..58d9e1a --- /dev/null +++ b/randomwallpaper@iflow.space/convenience.js @@ -0,0 +1,92 @@ +/* + Copyright (c) 2011-2012, Giovanni Campagna + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the GNOME nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +const Gettext = imports.gettext; +const Gio = imports.gi.Gio; + +const Config = imports.misc.config; +const ExtensionUtils = imports.misc.extensionUtils; + +/** + * initTranslations: + * @domain: (optional): the gettext domain to use + * + * Initialize Gettext to load translations from extensionsdir/locale. + * If @domain is not provided, it will be taken from metadata['gettext-domain'] + */ +function initTranslations(domain) { + let extension = ExtensionUtils.getCurrentExtension(); + + domain = domain || extension.metadata['gettext-domain']; + + // check if this extension was built with "make zip-file", and thus + // has the locale files in a subfolder + // otherwise assume that extension has been installed in the + // same prefix as gnome-shell + let localeDir = extension.dir.get_child('locale'); + if (localeDir.query_exists(null)) + Gettext.bindtextdomain(domain, localeDir.get_path()); + else + Gettext.bindtextdomain(domain, Config.LOCALEDIR); +} + +/** + * getSettings: + * @schema: (optional): the GSettings schema id + * + * Builds and return a GSettings schema for @schema, using schema files + * in extensionsdir/schemas. If @schema is not provided, it is taken from + * metadata['settings-schema']. + */ +function getSettings(schema) { + let extension = ExtensionUtils.getCurrentExtension(); + + schema = schema || extension.metadata['settings-schema']; + + const GioSSS = Gio.SettingsSchemaSource; + + // check if this extension was built with "make zip-file", and thus + // has the schema files in a subfolder + // otherwise assume that extension has been installed in the + // same prefix as gnome-shell (and therefore schemas are available + // in the standard folders) + let schemaDir = extension.dir.get_child('schemas'); + let schemaSource; + if (schemaDir.query_exists(null)) + schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), + GioSSS.get_default(), + false); + else + schemaSource = GioSSS.get_default(); + + let schemaObj = schemaSource.lookup(schema, true); + if (!schemaObj) + throw new Error('Schema ' + schema + ' could not be found for extension ' + + extension.metadata.uuid + '. Please check your installation.'); + + return new Gio.Settings({ settings_schema: schemaObj }); +} + diff --git a/randomwallpaper@iflow.space/extension.js b/randomwallpaper@iflow.space/extension.js index 31506c6..3fea861 100644 --- a/randomwallpaper@iflow.space/extension.js +++ b/randomwallpaper@iflow.space/extension.js @@ -17,6 +17,9 @@ const Tweener = imports.ui.tweener; // Filesystem const Gio = imports.gi.Gio; +// Settings +const Convenience = Self.imports.convenience; + let wallpaperController; let extensionMeta; @@ -156,7 +159,8 @@ let RandomWallpaperEntry = new Lang.Class({ function enable() { // Extension enabled - + this.settings = Convenience.getSettings(); + // UI panelEntry = new RandomWallpaperEntry(0, "Random wallpaper"); diff --git a/randomwallpaper@iflow.space/metadata.json b/randomwallpaper@iflow.space/metadata.json index 01fc2a6..2dd17c6 100644 --- a/randomwallpaper@iflow.space/metadata.json +++ b/randomwallpaper@iflow.space/metadata.json @@ -6,6 +6,7 @@ "3.18" ], "uuid": "randomwallpaper@iflow.space", + "settings-schema": "org.gnome.shell.extensions.space.iflow.randomwallpaper", "name": "Random Wallpaper", "description": "Fetches a random wallpaper from desktopper.co and sets it as desktop background" } diff --git a/randomwallpaper@iflow.space/prefs.js b/randomwallpaper@iflow.space/prefs.js new file mode 100644 index 0000000..65e4917 --- /dev/null +++ b/randomwallpaper@iflow.space/prefs.js @@ -0,0 +1,121 @@ +const GLib = imports.gi.GLib; +const Gtk = imports.gi.Gtk; +const Gdk = imports.gi.Gdk; +const Lang = imports.lang; + +const Self = imports.misc.extensionUtils.getCurrentExtension(); +//const Convenience = Self.imports.convenience; + +//const Gettext = imports.gettext.domain('space.iflow.randomwallpaper'); +//const _ = Gettext.gettext; + +/* Settings Keys */ +const SETTINGS_HIDE_CORNERS = 'hide-corners'; +const SETTINGS_TRANSITION_SPEED = 'transition-speed'; +const SETTINGS_FORCE_ANIMATION = 'force-animation'; +const SETTINGS_UNMAXIMIZED_OPACITY = 'unmaximized-opacity'; +const SETTINGS_MAXIMIZED_OPACITY = 'maximized-opacity'; +const SETTINGS_PANEL_COLOR = 'panel-color'; + +/* Color Scaling Factor (Byte to Decimal) */ +const SCALE_FACTOR = 255.9999999; + +function init() { + // Convenience.initTranslations(); +} + +function buildPrefsWidget() { + let widget = new RandomWallpaperSettingsWidget(); + widget.show_all(); + + return widget; +} + +/* UI Setup */ +const RandomWallpaperSettingsWidget = new Lang.Class({ + Name: 'RandomWallpaper.Prefs.SettingsUI', + GTypeName: 'RandomWallpaperSettingsWidget', + Extends: Gtk.Grid, + + _init: function(params) { + this.parent(params); + + this.margin = this.row_spacing = this.column_spacing = 20; + + //this._settings = Convenience.getSettings(); + + let i = 0; + + this.attach(new Gtk.Label({ label: 'Poll Sensors Every (sec)', halign : Gtk.Align.END}), 0, i++, 1, 1); + let updateTime = Gtk.SpinButton.new_with_range (1, 60, 1); + this.attach(updateTime, 1, i++, 1, 1); + // this._settings.bind('update-time', updateTime, 'value', Gio.SettingsBindFlags.DEFAULT); + + let adjustment = new Gtk.Adjustment({ + lower: 10, + upper: 60, + step_increment: 1 + }); + let scale = new Gtk.HScale({ + digits:2, + adjustment: adjustment, + value_pos: Gtk.PositionType.RIGHT + }); + + this.add(scale); + + this._addSwitch({key : 'group-voltage', y : i++, x : 2, + label : 'Group Voltage Items', + help : "Works if you have more than three voltage sensors"}); + + /* + this._addComboBox({ + items : { + 'none' : 'None', + 'nvidia-settings' : 'NVIDIA', + 'aticonfig' : 'Catalyst', + 'bumblebee-nvidia-smi': 'Bumblebee + NVIDIA' }, + key: 'gpu-utility', y : i, x : 2, + label: 'Video Card Temperature Utility' + }); */ + + }, + + _addSwitch : function(params){ + let lbl = new Gtk.Label({label: params.label,halign : Gtk.Align.END}); + this.attach(lbl, params.x, params.y, 1, 1); + let sw = new Gtk.Switch({halign : Gtk.Align.END, valign : Gtk.Align.CENTER}); + this.attach(sw, params.x + 1, params.y, 1, 1); + if(params.help){ + lbl.set_tooltip_text(params.help); + sw.set_tooltip_text(params.help); + } + //this._settings.bind(params.key, sw, 'active', Gio.SettingsBindFlags.DEFAULT); + }, + + _addComboBox : function(params){ + let model = new Gtk.ListStore(); + model.set_column_types([GObject.TYPE_STRING, GObject.TYPE_STRING]); + + let combobox = new Gtk.ComboBox({model: model}); + let renderer = new Gtk.CellRendererText(); + combobox.pack_start(renderer, true); + combobox.add_attribute(renderer, 'text', 1); + + for(let k in params.items){ + model.set(model.append(), [0, 1], [k, params.items[k]]); + } + + //combobox.set_active(Object.keys(params.items).indexOf(this._settings.get_string(params.key))); + + combobox.connect('changed', Lang.bind(this, function(entry) { + let [success, iter] = combobox.get_active_iter(); + if (!success) + return; + //this._settings.set_string(params.key, model.get_value(iter, 0)) + })); + + this.attach(new Gtk.Label({ label: params.label, halign : Gtk.Align.END}), params.x, params.y, 1, 1); + this.attach(combobox, params.x + 1, params.y, 1, 1); + } +}); \ No newline at end of file diff --git a/randomwallpaper@iflow.space/schemas/gschemas.compiled b/randomwallpaper@iflow.space/schemas/gschemas.compiled new file mode 100644 index 0000000..5af116b Binary files /dev/null and b/randomwallpaper@iflow.space/schemas/gschemas.compiled differ diff --git a/randomwallpaper@iflow.space/schemas/org.gnome.shell.extensions.space.iflow.randomwallpaper.gschema.xml b/randomwallpaper@iflow.space/schemas/org.gnome.shell.extensions.space.iflow.randomwallpaper.gschema.xml new file mode 100644 index 0000000..423fd6c --- /dev/null +++ b/randomwallpaper@iflow.space/schemas/org.gnome.shell.extensions.space.iflow.randomwallpaper.gschema.xml @@ -0,0 +1,13 @@ + + + + + 15 + Time to wait before first check (seconds) + A first check is made this number of seconds after startup + + + + + diff --git a/randomwallpaper@iflow.space/sourceAdapter.js b/randomwallpaper@iflow.space/sourceAdapter.js new file mode 100644 index 0000000..961f3b3 --- /dev/null +++ b/randomwallpaper@iflow.space/sourceAdapter.js @@ -0,0 +1,103 @@ +const Lang = imports.lang; + +// network requests +const Soup = imports.gi.Soup; +const Json = imports.gi.Json; + +let DesktopperAdapter = new Lang.Class({ + Name: "DesktopperAdapter", + /* + fetch a random image url from desktopper.cc + and call callback function with the URL of the image + */ + requestRandomImage: function(callback){ + let session = new Soup.SessionAsync(); + let message = Soup.Message.new('GET', 'https://api.desktoppr.co/1/wallpapers/random') + + let parser = new Json.Parser(); + + var _this = this; + + session.queue_message(message, function(session, message) { + parser.load_from_data(message.response_body.data, -1); + + let data = parser.get_root().get_object() + let response = data.get_object_member('response'); + let imageUrl = response.get_object_member('image').get_string_member('url'); + + if (callback) { + callback(imageUrl); + }; + }); + } +}) + +let WallheavenAdapter = new Lang.Class({ + Name: "WallheavenAdapter", + + // query options + options: { + 'q': '', + 'purity': '110', // SFW, sketchy + 'sorting': 'random', + 'category': '111', // General, Anime, People + 'resolutions': ['1920x1200','2560x1440'], + }, + + /* + fetch a random image url from wallheaven.cc with the given options + and call callback function with the URL of the image + */ + requestRandomImage: function(callback){ + let session = new Soup.SessionAsync(); + + let options = this.options; + let optionsString="" + + for (var key in options) { + if (options.hasOwnProperty(key)) { + if (Array.isArray(options[key])) { + optionsString += key + "=" + options[key].join() + "&"; + } else { + optionsString += key + "=" + options[key] + "&"; + } + } + } + // remove last '&' + optionsString = optionsString.slice(0,-1); + + let url = 'http://alpha.wallhaven.cc/search?'+optionsString; + + let message = Soup.Message.new('GET', url); + + var _this = this; + + session.queue_message(message, function(session, message) { + let body = message.response_body.data; + let urlArray = body.match(new RegExp(/http:\/\/alpha.wallhaven.cc\/wallpaper\/[0-9]+/g)); + + // remove dublicates from array + let uniqueUrlArray = urlArray.filter(function(item, pos) { + return urlArray.indexOf(item) == pos; + }); + + // get a random entry from the array + var url = uniqueUrlArray[Math.floor(Math.random()*uniqueUrlArray.length)]; + + message = Soup.Message.new('GET', url); + + session.queue_message(message, function(){ + let body = message.response_body.data; + let imageUrl = body.match(new RegExp(/\/\/wallpapers.wallhaven.cc\/wallpapers\/full\/.*?"/))[0]; + imageUrl = imageUrl.slice(0,-1); + imageUrl = 'http:' + imageUrl; + + if (callback) { + callback(imageUrl); + }; + }) + + + }); + } +}) \ No newline at end of file diff --git a/randomwallpaper@iflow.space/wallpaperController.js b/randomwallpaper@iflow.space/wallpaperController.js index f5b0f8f..1b0baa3 100644 --- a/randomwallpaper@iflow.space/wallpaperController.js +++ b/randomwallpaper@iflow.space/wallpaperController.js @@ -8,6 +8,10 @@ const Json = imports.gi.Json; // Filesystem const Gio = imports.gi.Gio; +//self +const Self = imports.misc.extensionUtils.getCurrentExtension(); +const SourceAdapter = Self.imports.sourceAdapter; + let WallpaperController = new Lang.Class({ Name: "WallpaperController", extensionMeta: null, @@ -16,38 +20,22 @@ let WallpaperController = new Lang.Class({ currentWallpaper: '', historySize: 10, history: [], + imageSourceAdapter: undefined, _init: function(extensionMeta){ this.extensionMeta = extensionMeta; this.wallpaperlocation = this.extensionMeta.path + '/wallpapers/'; this.history = this._loadHistory(); this.currentWallpaper = this._getCurrentWallpaper(); + this.imageSourceAdapter = new SourceAdapter.DesktopperAdapter(); + this.imageSourceAdapter = new SourceAdapter.WallheavenAdapter(); }, - /* - fetch a random image url from desktopper.cc - and call callback function with the URL of the image + forwards the request to the adapter */ - _requestRandomImageDesktopper: function(callback){ - let session = new Soup.SessionAsync(); - let message = Soup.Message.new('GET', 'https://api.desktoppr.co/1/wallpapers/random') - - let parser = new Json.Parser(); - - var _this = this; - - session.queue_message(message, function(session, message) { - parser.load_from_data(message.response_body.data, -1); - - let data = parser.get_root().get_object() - let response = data.get_object_member('response'); - let imageUrl = response.get_object_member('image').get_string_member('url'); - - if (callback) { - callback(imageUrl); - }; - }); + _requestRandomImageFromAdapter: function(callback){ + this.imageSourceAdapter.requestRandomImage(callback); }, /* @@ -184,7 +172,7 @@ let WallpaperController = new Lang.Class({ fetchNewWallpaper: function(callback) { let _this = this; - this._requestRandomImageDesktopper(function(imageUrl){ + this._requestRandomImageFromAdapter(function(imageUrl){ _this._fetchFile(imageUrl, function(historyid, path) { // insert file into history _this.history.unshift(historyid);