mirror of
https://github.com/Hopiu/RandomWallpaperGnome3.git
synced 2026-04-14 11:50:59 +00:00
commit
608f45c63b
21 changed files with 1380 additions and 512 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,4 +1,7 @@
|
|||
.idea
|
||||
|
||||
# ready to deploy to gnome extensions
|
||||
random-wallpaper-gnome3.zip
|
||||
|
||||
# Temporary ui files
|
||||
**/*~
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 ifl0w
|
||||
Copyright (c) 2014 Wolfgang Rumpler
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
13
build.sh
Executable file
13
build.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
BASEDIR='randomwallpaper@iflow.space'
|
||||
ZIPNAME='random-wallpaper-gnome3.zip'
|
||||
|
||||
rm $ZIPNAME
|
||||
rm $BASEDIR/schemas/gschemas.compiled
|
||||
rm $BASEDIR/wallpapers/*
|
||||
glib-compile-schemas $BASEDIR/schemas/
|
||||
|
||||
cd $BASEDIR
|
||||
zip -r $ZIPNAME .
|
||||
mv $ZIPNAME ..
|
||||
BIN
icon.png
BIN
icon.png
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 1.3 KiB |
83
icon.svg
Normal file
83
icon.svg
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:version="0.92.1 r">
|
||||
<metadata
|
||||
id="metadata10">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs8">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4545">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4541" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4543" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4545"
|
||||
id="linearGradient4547"
|
||||
x1="0"
|
||||
y1="12"
|
||||
x2="24"
|
||||
y2="12"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1145"
|
||||
id="namedview6"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4.9166667"
|
||||
inkscape:cx="41.499897"
|
||||
inkscape:cy="40.854617"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<path
|
||||
style="fill:#33334b;fill-opacity:1;stroke:none;stroke-width:13.66373348;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
d="M 5.515625,0 C 2.4604779,0 0,2.460478 0,5.515625 v 88.96875 C 0,97.539522 2.4604779,100 5.515625,100 h 88.970703 c 3.055148,0 5.513671,-2.460478 5.513671,-5.515625 V 5.515625 C 99.999999,2.460478 97.541476,0 94.486328,0 Z M 16.150391,14.357422 H 83.84961 c 0.981656,0.0014 1.791596,0.811308 1.792968,1.792969 v 53.591796 c -0.0014,0.981653 -0.805639,1.799405 -1.792968,1.800782 H 16.150391 c -0.987332,-0.0014 -1.791593,-0.819133 -1.792969,-1.800782 V 16.150391 c 0.0014,-0.981657 0.811312,-1.791594 1.792969,-1.792969 z m 7.857422,8.041016 c -0.988906,2.75e-4 -1.775116,0.786485 -1.775391,1.77539 v 37.542969 c 2.75e-4,0.988909 0.786484,1.777067 1.775391,1.777344 h 51.984375 c 0.988901,-2.77e-4 1.775114,-0.788439 1.77539,-1.777344 V 24.173828 c -2.76e-4,-0.988906 -0.786489,-1.775115 -1.77539,-1.77539 z m 3.439453,2.470703 h 45.107422 c 0.567933,-4.7e-5 1.12966,0.230279 1.53125,0.623047 0.401589,0.392767 0.636766,0.942589 0.636719,1.498046 v 31.863282 c 4.7e-5,0.555457 -0.23513,1.105279 -0.636719,1.498046 -0.40159,0.392768 -0.963317,0.621141 -1.53125,0.621094 H 27.447266 c -0.567934,4.7e-5 -1.131613,-0.228326 -1.533203,-0.621094 -0.40159,-0.392767 -0.636767,-0.942589 -0.636719,-1.498046 V 26.990234 c -4.8e-5,-0.555457 0.235129,-1.105279 0.636719,-1.498046 0.40159,-0.392768 0.965269,-0.623094 1.533203,-0.623047 z M 40.40625,73.59375 h 19.1875 c 0.521531,0.0013 1.013887,0.230804 1.351563,0.621094 l 7.335937,8.464843 c 0.483066,0.562457 0.543936,1.329127 0.275391,1.917969 -0.26855,0.588843 -0.885438,1.041378 -1.626953,1.044922 H 33.070313 c -0.741487,-0.0036 -1.358401,-0.456092 -1.626953,-1.044922 -0.268553,-0.58883 -0.207669,-1.35552 0.27539,-1.917969 l 7.335938,-8.464843 c 0.337681,-0.390282 0.830068,-0.619807 1.351562,-0.621094 z"
|
||||
id="rect4614"
|
||||
inkscape:connector-curvature="0" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
|
|
@ -1,260 +0,0 @@
|
|||
const Lang = imports.lang;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const St = imports.gi.St;
|
||||
const Slider = imports.ui.slider;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const Self = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const Timer = Self.imports.timer;
|
||||
|
||||
const HistoryElement = new Lang.Class({
|
||||
Name: 'HistoryElement',
|
||||
Extends: PopupMenu.PopupBaseMenuItem,
|
||||
historyId: null,
|
||||
|
||||
_init: function(historyId, index, params) {
|
||||
index = String(index)+'.' || '0.';
|
||||
|
||||
this.parent(params);
|
||||
|
||||
let timestamp = parseInt(historyId.slice(0, historyId.lastIndexOf('.')));
|
||||
let date = new Date(timestamp);
|
||||
|
||||
let timeString = date.toLocaleTimeString();
|
||||
let dateString = date.toLocaleDateString();
|
||||
|
||||
this.label = new St.Label({
|
||||
text: index,
|
||||
style_class: 'rwg-history-index'
|
||||
});
|
||||
|
||||
this.actor.add_child(this.label);
|
||||
|
||||
this._container = new St.BoxLayout({
|
||||
vertical: true
|
||||
});
|
||||
|
||||
this.dateLabel = new St.Label({
|
||||
text: dateString,
|
||||
style_class: 'rwg-history-date'
|
||||
});
|
||||
this._container.add_child(this.dateLabel);
|
||||
|
||||
this.timeLabel = new St.Label({
|
||||
text: timeString,
|
||||
style_class: 'rwg-history-time'
|
||||
});
|
||||
this._container.add_child(this.timeLabel);
|
||||
|
||||
this.historyId = historyId;
|
||||
this.actor.historyId = historyId; // extend the actor with the historyId
|
||||
|
||||
this.actor.add_child(this._container);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Element for the New Wallpaper button and the remaining time for the auto fetch
|
||||
* feature.
|
||||
* The remaining time will only be displayed if the af-feature is activated.
|
||||
*
|
||||
* @type {Lang.Class}
|
||||
*/
|
||||
const NewWallpaperElement = new Lang.Class({
|
||||
Name: 'NewWallpaperElement',
|
||||
Extends: PopupMenu.PopupBaseMenuItem,
|
||||
|
||||
_init: function(params) {
|
||||
this.parent(params);
|
||||
|
||||
this._timer = new Timer.AFTimer();
|
||||
|
||||
this._container = new St.BoxLayout({
|
||||
vertical: true
|
||||
});
|
||||
|
||||
this._newWPLabel = new St.Label({
|
||||
text: 'New Wallpaper',
|
||||
style_class: 'rwg-new-lable'
|
||||
});
|
||||
this._container.add_child(this._newWPLabel);
|
||||
|
||||
this._remainingLabel = new St.Label({
|
||||
text: '1 minute remaining'
|
||||
});
|
||||
this._container.add_child(this._remainingLabel);
|
||||
|
||||
this.actor.add_child(this._container);
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if (this._timer.isActive()) {
|
||||
let remainingMinutes = this._timer.remainingMinutes();
|
||||
let minutes = remainingMinutes % 60;
|
||||
let hours = Math.floor(remainingMinutes / 60);
|
||||
|
||||
let hoursText = hours.toString();
|
||||
hoursText += (hours == 1) ? ' hour' : ' hours';
|
||||
let minText = minutes.toString();
|
||||
minText += (minutes == 1) ? ' minute' : ' minutes';
|
||||
|
||||
if (hours >= 1) {
|
||||
this._remainingLabel.text = '... ' + hoursText + ' and ' + minText + ' remaining.'
|
||||
} else {
|
||||
this._remainingLabel.text = '... ' + minText + ' remaining.'
|
||||
}
|
||||
|
||||
this._remainingLabel.show();
|
||||
} else {
|
||||
this._remainingLabel.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const StatusElement = new Lang.Class({
|
||||
Name: 'StatusElement',
|
||||
Extends: St.Icon,
|
||||
|
||||
_init: function() {
|
||||
|
||||
this.parent({
|
||||
icon_name: 'preferences-desktop-wallpaper-symbolic',
|
||||
style_class: 'system-status-icon'
|
||||
});
|
||||
|
||||
let _this = this;
|
||||
|
||||
this.loadingTweenIn = {
|
||||
opacity:20,
|
||||
time:1,
|
||||
transition:'easeInOutSine',
|
||||
onComplete: function() {
|
||||
Tweener.addTween(_this, _this.loadingTweenOut);
|
||||
}
|
||||
}
|
||||
|
||||
this.loadingTweenOut = {
|
||||
opacity:255,
|
||||
time:1,
|
||||
transition:'easeInOutSine',
|
||||
onComplete: function() {
|
||||
if (_this.isLoading) {
|
||||
Tweener.addTween(_this, _this.loadingTweenIn);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
startLoading: function() {
|
||||
this.isLoading = true;
|
||||
Tweener.addTween(this, this.loadingTweenOut);
|
||||
},
|
||||
|
||||
stopLoading: function() {
|
||||
this.isLoading = false;
|
||||
Tweener.removeTweens(this);
|
||||
this.opacity = 255;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
// borrowed from: https://github.com/eonpatapon/gnome-shell-extensions-mediaplayer
|
||||
const SliderItem = new Lang.Class({
|
||||
Name: 'SliderItem',
|
||||
Extends: PopupMenu.PopupBaseMenuItem,
|
||||
|
||||
_init: function(value) {
|
||||
this.parent();
|
||||
|
||||
this._box = new St.Table({style_class: 'slider-item'});
|
||||
|
||||
this._slider = new Slider.Slider(value);
|
||||
|
||||
this._box.add(this._slider.actor, {row: 0, col: 2, x_expand: true});
|
||||
this.actor.add(this._box, {span: -1, expand: true});
|
||||
},
|
||||
|
||||
setValue: function(value) {
|
||||
this._slider.setValue(value);
|
||||
},
|
||||
|
||||
getValue: function() {
|
||||
return this._slider._getCurrentValue();
|
||||
},
|
||||
|
||||
setIcon: function(icon) {
|
||||
this._icon.icon_name = icon + '-symbolic';
|
||||
},
|
||||
|
||||
connect: function(signal, callback) {
|
||||
this._slider.connect(signal, callback);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Widget for setting the delay for the next Wallpaper-change.
|
||||
* @type {Lang.Class}
|
||||
*/
|
||||
const DelaySlider = new Lang.Class({
|
||||
Name: 'DelaySlider',
|
||||
Extends: SliderItem,
|
||||
|
||||
_MINUTES_MAX: 59,
|
||||
_MINUTES_MIN: 5,
|
||||
_HOURS_MAX: 48,
|
||||
_HOURS_MIN: 1,
|
||||
|
||||
/**
|
||||
* Construct a new Widget.
|
||||
* @private
|
||||
*/
|
||||
_init: function(minutes){
|
||||
this.parent(0, ''); // value MUST be specified!
|
||||
this.setMinutes(minutes); // Set the real value.
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the value of the slider to x minutes.
|
||||
* @param minutes the value in minutes between _MINUTES_MAX and _MINUTES_MIN
|
||||
*/
|
||||
setMinutes: function(minutes){
|
||||
// Validate:
|
||||
if (isNaN(minutes) || minutes < this._MINUTES_MIN || minutes > this._HOURS_MAX*60){
|
||||
throw TypeError("'minutes' should be an integer between "
|
||||
+this._MINUTES_MIN+" and "+this._HOURS_MAX*60);
|
||||
}
|
||||
|
||||
let value = 0;
|
||||
if (minutes <= this._MINUTES_MAX){
|
||||
value = (minutes - this._MINUTES_MIN) / (this._MINUTES_MAX - this._MINUTES_MIN) / 2;
|
||||
} else {
|
||||
value = (((minutes / 60) - this._HOURS_MIN) / (this._HOURS_MAX - this._HOURS_MIN) / 2) + 0.5;
|
||||
}
|
||||
|
||||
this.setValue(value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the value in minutes from the slider.
|
||||
* @return int the value in minutes.
|
||||
*/
|
||||
getMinutes: function(){
|
||||
let minutes = 0;
|
||||
if (this.getValue() < 0.5) {
|
||||
minutes = this._MINUTES_MIN + (this.getValue() * 2) * (this._MINUTES_MAX - this._MINUTES_MIN);
|
||||
} else {
|
||||
minutes = (this._HOURS_MIN + (this.getValue() - 0.5) * 2 * (this._HOURS_MAX - this._HOURS_MIN)) * 60;
|
||||
}
|
||||
|
||||
return (minutes < this._MINUTES_MIN) ? this._MINUTES_MIN : Math.floor(minutes);
|
||||
}
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
213
randomwallpaper@iflow.space/elements.js
Normal file
213
randomwallpaper@iflow.space/elements.js
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
const Lang = imports.lang;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const St = imports.gi.St;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Self = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const Timer = Self.imports.timer;
|
||||
|
||||
const HistoryElement = new Lang.Class({
|
||||
Name: 'HistoryElement',
|
||||
Extends: PopupMenu.PopupSubMenuMenuItem,
|
||||
historyEntry: null,
|
||||
|
||||
_init: function (historyEntry, index) {
|
||||
this.parent("", false);
|
||||
|
||||
let timestamp = historyEntry.timestamp;
|
||||
let date = new Date(timestamp);
|
||||
|
||||
let timeString = date.toLocaleTimeString();
|
||||
let dateString = date.toLocaleDateString();
|
||||
|
||||
let prefixText;
|
||||
if (index === 0) {
|
||||
prefixtext = "Current Background";
|
||||
} else {
|
||||
prefixtext = String(index) + '.';
|
||||
}
|
||||
this.prefixLabel = new St.Label({
|
||||
text: prefixtext,
|
||||
style_class: 'rwg-history-index'
|
||||
});
|
||||
|
||||
this.actor.insert_child_above(this.prefixLabel, this.label);
|
||||
this.label.destroy();
|
||||
|
||||
this._container = new St.BoxLayout({
|
||||
vertical: true
|
||||
});
|
||||
|
||||
this.dateLabel = new St.Label({
|
||||
text: dateString,
|
||||
style_class: 'rwg-history-date'
|
||||
});
|
||||
this._container.add_child(this.dateLabel);
|
||||
|
||||
this.timeLabel = new St.Label({
|
||||
text: timeString,
|
||||
style_class: 'rwg-history-time'
|
||||
});
|
||||
this._container.add_child(this.timeLabel);
|
||||
|
||||
this.historyEntry = historyEntry;
|
||||
this.actor.historyId = historyEntry.id; // extend the actor with the historyId
|
||||
|
||||
if (index !== 0) {
|
||||
this.actor.insert_child_above(this._container, this.prefixLabel);
|
||||
}
|
||||
|
||||
if (this.historyEntry.source && this.historyEntry.source !== null) {
|
||||
|
||||
if (this.historyEntry.source.author !== null
|
||||
&& this.historyEntry.source.authorUrl !== null) {
|
||||
this.authorItem = new PopupMenu.PopupMenuItem('Image By: ' + this.historyEntry.source.author);
|
||||
this.authorItem.connect('activate', () => {
|
||||
Util.spawn(['xdg-open', this.historyEntry.source.authorUrl]);
|
||||
});
|
||||
|
||||
this.menu.addMenuItem(this.authorItem);
|
||||
}
|
||||
|
||||
if (this.historyEntry.source.source !== null
|
||||
&& this.historyEntry.source.sourceUrl !== null) {
|
||||
this.sourceItem = new PopupMenu.PopupMenuItem('Image From: ' + this.historyEntry.source.source);
|
||||
this.sourceItem.connect('activate', () => {
|
||||
Util.spawn(['xdg-open', this.historyEntry.source.sourceUrl]);
|
||||
});
|
||||
|
||||
this.menu.addMenuItem(this.sourceItem);
|
||||
}
|
||||
|
||||
this.imageUrlItem = new PopupMenu.PopupMenuItem('Open Image In Browser');
|
||||
this.imageUrlItem.connect('activate', () => {
|
||||
Util.spawn(['xdg-open', this.historyEntry.source.imageUrl]);
|
||||
});
|
||||
|
||||
this.menu.addMenuItem(this.imageUrlItem);
|
||||
|
||||
} else {
|
||||
this.menu.addMenuItem(new PopupMenu.PopupMenuItem('Unknown source.'));
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
const CurrentImageElement = new Lang.Class({
|
||||
Name: 'CurrentImageElement',
|
||||
Extends: HistoryElement,
|
||||
|
||||
_init: function(historyElement) {
|
||||
this.parent(historyElement, 0);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Element for the New Wallpaper button and the remaining time for the auto fetch
|
||||
* feature.
|
||||
* The remaining time will only be displayed if the af-feature is activated.
|
||||
*
|
||||
* @type {Lang.Class}
|
||||
*/
|
||||
const NewWallpaperElement = new Lang.Class({
|
||||
Name: 'NewWallpaperElement',
|
||||
Extends: PopupMenu.PopupBaseMenuItem,
|
||||
|
||||
_init: function (params) {
|
||||
this.parent(params);
|
||||
|
||||
this._timer = new Timer.AFTimer();
|
||||
|
||||
this._container = new St.BoxLayout({
|
||||
vertical: true
|
||||
});
|
||||
|
||||
this._newWPLabel = new St.Label({
|
||||
text: 'New Wallpaper',
|
||||
style_class: 'rwg-new-lable'
|
||||
});
|
||||
this._container.add_child(this._newWPLabel);
|
||||
|
||||
this._remainingLabel = new St.Label({
|
||||
text: '1 minute remaining'
|
||||
});
|
||||
this._container.add_child(this._remainingLabel);
|
||||
|
||||
this.actor.add_child(this._container);
|
||||
},
|
||||
|
||||
show: function () {
|
||||
if (this._timer.isActive()) {
|
||||
let remainingMinutes = this._timer.remainingMinutes();
|
||||
let minutes = remainingMinutes % 60;
|
||||
let hours = Math.floor(remainingMinutes / 60);
|
||||
|
||||
let hoursText = hours.toString();
|
||||
hoursText += (hours == 1) ? ' hour' : ' hours';
|
||||
let minText = minutes.toString();
|
||||
minText += (minutes == 1) ? ' minute' : ' minutes';
|
||||
|
||||
if (hours >= 1) {
|
||||
this._remainingLabel.text = '... ' + hoursText + ' and ' + minText + ' remaining.'
|
||||
} else {
|
||||
this._remainingLabel.text = '... ' + minText + ' remaining.'
|
||||
}
|
||||
|
||||
this._remainingLabel.show();
|
||||
} else {
|
||||
this._remainingLabel.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const StatusElement = new Lang.Class({
|
||||
Name: 'StatusElement',
|
||||
Extends: St.Icon,
|
||||
|
||||
_init: function () {
|
||||
|
||||
this.parent({
|
||||
icon_name: 'preferences-desktop-wallpaper-symbolic',
|
||||
style_class: 'system-status-icon'
|
||||
});
|
||||
|
||||
let _this = this;
|
||||
|
||||
this.loadingTweenIn = {
|
||||
opacity: 20,
|
||||
time: 1,
|
||||
transition: 'easeInOutSine',
|
||||
onComplete: function () {
|
||||
Tweener.addTween(_this, _this.loadingTweenOut);
|
||||
}
|
||||
};
|
||||
|
||||
this.loadingTweenOut = {
|
||||
opacity: 255,
|
||||
time: 1,
|
||||
transition: 'easeInOutSine',
|
||||
onComplete: function () {
|
||||
if (_this.isLoading) {
|
||||
Tweener.addTween(_this, _this.loadingTweenIn);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
startLoading: function () {
|
||||
this.isLoading = true;
|
||||
Tweener.addTween(this, this.loadingTweenOut);
|
||||
},
|
||||
|
||||
stopLoading: function () {
|
||||
this.isLoading = false;
|
||||
Tweener.removeTweens(this);
|
||||
this.opacity = 255;
|
||||
}
|
||||
|
||||
});
|
||||
|
|
@ -6,12 +6,14 @@ const Shell = imports.gi.Shell;
|
|||
const Self = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const WallpaperController = Self.imports.wallpaperController;
|
||||
|
||||
const LoggerModule = Self.imports.logger;
|
||||
|
||||
// UI Imports
|
||||
const Main = imports.ui.main;
|
||||
const St = imports.gi.St;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const CustomElements = Self.imports.Elements;
|
||||
const CustomElements = Self.imports.elements;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
// Filesystem
|
||||
|
|
@ -33,9 +35,11 @@ let panelEntry;
|
|||
let RandomWallpaperEntry = new Lang.Class({
|
||||
Extends: PanelMenu.Button,
|
||||
Name: "RandomWallpaperEntry",
|
||||
logger: null,
|
||||
|
||||
_init: function(menuAlignment, nameText) {
|
||||
this.parent(menuAlignment, nameText);
|
||||
this.logger = new LoggerModule.Logger('RWG3', 'RandomWallpaperEntry');
|
||||
|
||||
// Panelmenu Icon
|
||||
this.statusIcon = new CustomElements.StatusElement();
|
||||
|
|
@ -48,6 +52,11 @@ let RandomWallpaperEntry = new Lang.Class({
|
|||
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
// current background section
|
||||
this.currentBackgroundSection = new PopupMenu.PopupMenuSection();
|
||||
this.menu.addMenuItem(this.currentBackgroundSection);
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
// history section
|
||||
this.historySection = new PopupMenu.PopupMenuSection();
|
||||
this.menu.addMenuItem(this.historySection);
|
||||
|
|
@ -64,7 +73,10 @@ let RandomWallpaperEntry = new Lang.Class({
|
|||
this.openFolder = new PopupMenu.PopupMenuItem('Open Wallpaper Folder');
|
||||
this.menu.addMenuItem(this.openFolder);
|
||||
|
||||
//this.menu.addMenuItem(new CustomElements.DelaySlider(60));
|
||||
// settings button
|
||||
this.openSettings = new PopupMenu.PopupMenuItem('Settings');
|
||||
this.menu.addMenuItem(this.openSettings);
|
||||
|
||||
/*
|
||||
add eventlistener
|
||||
*/
|
||||
|
|
@ -89,6 +101,17 @@ let RandomWallpaperEntry = new Lang.Class({
|
|||
Gio.AppInfo.launch_default_for_uri(uri, global.create_app_launch_context(0, -1))
|
||||
});
|
||||
|
||||
this.openSettings.connect("activate", function(){
|
||||
// call gnome settings tool for this extension
|
||||
let app = Shell.AppSystem.get_default().lookup_app("gnome-shell-extension-prefs.desktop");
|
||||
if( app!=null ) {
|
||||
// only works in Gnome >= 3.12
|
||||
let info = app.get_app_info();
|
||||
let timestamp = global.display.get_current_time_roundtrip();
|
||||
info.launch_uris([Self.uuid], global.create_app_launch_context(timestamp, -1));
|
||||
}
|
||||
});
|
||||
|
||||
this.menu.actor.connect('show', function() {
|
||||
this.newWallpaperItem.show();
|
||||
wallpaperController.menuShowHook();
|
||||
|
|
@ -107,19 +130,34 @@ let RandomWallpaperEntry = new Lang.Class({
|
|||
|
||||
},
|
||||
|
||||
setCurrentBackgroundElement: function () {
|
||||
this.currentBackgroundSection.removeAll();
|
||||
|
||||
let historyController = wallpaperController.getHistoryController();
|
||||
let history = historyController.history;
|
||||
|
||||
if (history.length > 0) {
|
||||
let currentImage = new CustomElements.CurrentImageElement(history[0]);
|
||||
this.currentBackgroundSection.addMenuItem(currentImage);
|
||||
}
|
||||
},
|
||||
|
||||
setHistoryList: function() {
|
||||
this.setCurrentBackgroundElement();
|
||||
|
||||
this.historySection.removeAll();
|
||||
|
||||
let history = this.history = wallpaperController.getHistory();
|
||||
let historyController = wallpaperController.getHistoryController();
|
||||
let history = historyController.history;
|
||||
|
||||
if (history.length <= 1) {
|
||||
this.clearHistoryList();
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
for (var i = 1; i < history.length; i++) {
|
||||
let historyid = history[i];
|
||||
let tmp = new CustomElements.HistoryElement(historyid, i);
|
||||
for (let i = 1; i < history.length; i++) {
|
||||
let historyid = history[i].id;
|
||||
let tmp = new CustomElements.HistoryElement(history[i], i);
|
||||
|
||||
tmp.actor.connect('key-focus-in', onEnter);
|
||||
tmp.actor.connect('key-focus-out', onLeave);
|
||||
|
|
@ -128,7 +166,7 @@ let RandomWallpaperEntry = new Lang.Class({
|
|||
tmp.connect('activate', onSelect);
|
||||
|
||||
this.historySection.addMenuItem(tmp);
|
||||
};
|
||||
}
|
||||
|
||||
function onLeave(actor) {
|
||||
wallpaperController.resetWallpaper();
|
||||
|
|
|
|||
159
randomwallpaper@iflow.space/history.js
Normal file
159
randomwallpaper@iflow.space/history.js
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
const Lang = imports.lang;
|
||||
const Mainloop = imports.gi.GLib;
|
||||
|
||||
// Filesystem
|
||||
const Gio = imports.gi.Gio;
|
||||
|
||||
const Self = imports.misc.extensionUtils.getCurrentExtension();
|
||||
const Prefs = Self.imports.settings;
|
||||
|
||||
const LoggerModule = Self.imports.logger;
|
||||
|
||||
let HistoryEntry = new Lang.Class({
|
||||
Name: "HistoryEntry",
|
||||
timestamp: null,
|
||||
id: null,
|
||||
path: null,
|
||||
source: null,
|
||||
|
||||
_init: function(author, source, url) {
|
||||
this.timestamp = new Date().getTime();
|
||||
|
||||
this.source = {
|
||||
author: author,
|
||||
authorUrl: null,
|
||||
source: source,
|
||||
sourceUrl: null,
|
||||
imageUrl: url
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
let HistoryController = new Lang.Class({
|
||||
Name: "HistoryController",
|
||||
_settings: null,
|
||||
_wallpaperlocation: null,
|
||||
|
||||
logger: null,
|
||||
size: 10,
|
||||
history: [],
|
||||
|
||||
_init: function(wallpaperlocation) {
|
||||
this.logger = new LoggerModule.Logger('RWG3', 'HistoryController');
|
||||
|
||||
this._settings = new Prefs.Settings();
|
||||
this._wallpaperlocation = wallpaperlocation;
|
||||
|
||||
this.load();
|
||||
},
|
||||
|
||||
insert: function(historyElement) {
|
||||
this.history.unshift(historyElement);
|
||||
this._deleteOldPictures();
|
||||
this.save();
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the given id to to the first history element (the current one)
|
||||
* @param id
|
||||
* @returns {boolean}
|
||||
*/
|
||||
promoteToActive: function(id) {
|
||||
let element = this.get(id);
|
||||
if (element === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
element.timestamp = new Date().getTime();
|
||||
this.history = this.history.sort((elem1, elem2) => { return elem1.timestamp < elem2.timestamp });
|
||||
this.save();
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the corresponding HistoryEntry or null
|
||||
* @param id
|
||||
* @returns {*}
|
||||
*/
|
||||
get: function(id) {
|
||||
for (let elem of this.history) {
|
||||
if (elem.id == id) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the history from the gschema
|
||||
*/
|
||||
load: function() {
|
||||
this.size = this._settings.get('history-length', 'int');
|
||||
let stringHistory = this._settings.get('history', 'strv');
|
||||
this.history = stringHistory.map(elem => {
|
||||
return JSON.parse(elem)
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Save the history to the gschema
|
||||
*/
|
||||
save: function() {
|
||||
let stringHistory = this.history.map(elem => { return JSON.stringify(elem) });
|
||||
this._settings.set('history', 'strv', stringHistory);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the history and delete all photos except the current one.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
clear() {
|
||||
let firstHistoryElement = this.history[0];
|
||||
|
||||
if (firstHistoryElement)
|
||||
this.history = [firstHistoryElement];
|
||||
|
||||
let directory = Gio.file_new_for_path(this._wallpaperlocation);
|
||||
let enumerator = directory.enumerate_children('', Gio.FileQueryInfoFlags.NONE, null);
|
||||
|
||||
let fileinfo;
|
||||
let deleteFile;
|
||||
|
||||
do {
|
||||
|
||||
fileinfo = enumerator.next_file(null);
|
||||
|
||||
if (!fileinfo) {
|
||||
break;
|
||||
}
|
||||
|
||||
let id = fileinfo.get_name();
|
||||
|
||||
// ignore hidden files and first element
|
||||
if (id[0] != '.' && id != firstHistoryElement.id) {
|
||||
deleteFile = Gio.file_new_for_path(this._wallpaperlocation + id);
|
||||
deleteFile.delete(null);
|
||||
}
|
||||
|
||||
} while(fileinfo);
|
||||
|
||||
this.save();
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete all pictures that have no slot in the history.
|
||||
* @private
|
||||
*/
|
||||
_deleteOldPictures: function() {
|
||||
this.size = this._settings.get('history-length', 'int');
|
||||
let deleteFile;
|
||||
while(this.history.length > this.size) {
|
||||
deleteFile = Gio.file_new_for_path(this.history.pop().path);
|
||||
deleteFile.delete(null);
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.6 KiB |
|
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- License Agreement at http://iconmonstr.com/license/ -->
|
||||
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
|
||||
<path id="shuffle-icon" fill="#FFFFFF" d="M102.319,187.959H50v-40h52.319c38.263,0,75.373,15.736,102.147,44.485
|
||||
c-1.163,1.716-22.359,35.536-22.359,35.536C163.371,202.782,134.117,187.959,102.319,187.959z M462,342.987l-88.489-55.225v36.195
|
||||
h-28.664c-31.797,0-61.052-14.823-79.788-40.021c0,0-21.196,33.82-22.358,35.536c26.8,28.776,63.928,44.484,102.146,44.484h28.768
|
||||
l0.086,33.082L462,342.987z M462,169.013l-88.3-54.053l-0.086,33.082h-28.768c-47.448,0-92.504,24.248-118.344,65.592l-39.76,63.616
|
||||
c-18.312,29.299-49.872,46.791-84.424,46.791H50v40h52.319c47.448,0,92.504-24.248,118.344-65.592l39.76-63.616
|
||||
c18.312-29.299,49.872-46.791,84.424-46.791h28.664l-0.095,36.195L462,169.013z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB |
|
|
@ -22,7 +22,7 @@ let Logger = new Lang.Class({
|
|||
this._log("INFO", message);
|
||||
},
|
||||
|
||||
warning: function (message) {
|
||||
warn: function (message) {
|
||||
this._log("WARNING", message);
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
"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",
|
||||
"version": 1.1
|
||||
"description": "Fetches a random wallpaper from an online source and sets it as desktop background. \nThe desktop background can be updated periodically or manually.",
|
||||
"version": 2.0,
|
||||
"url": "https://github.com/ifl0w/RandomWallpaperGnome3"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ const Gettext = imports.gettext.domain('space.iflow.randomwallpaper');
|
|||
//const _ = Gettext.gettext;
|
||||
|
||||
const RWG_SETTINGS_SCHEMA = 'org.gnome.shell.extensions.space.iflow.randomwallpaper';
|
||||
const RWG_SETTINGS_SCHEMA_DESKTOPPER = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.desktopper';
|
||||
const RWG_SETTINGS_SCHEMA_UNSPLASH = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.unsplash';
|
||||
const RWG_SETTINGS_SCHEMA_WALLHEAVEN = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.wallheaven';
|
||||
|
||||
const LoggerModule = Self.imports.logger;
|
||||
|
||||
function init() {
|
||||
//Convenience.initTranslations();
|
||||
|
|
@ -28,6 +33,14 @@ function buildPrefsWidget() {
|
|||
/* UI Setup */
|
||||
const RandomWallpaperSettings = new Lang.Class({
|
||||
Name: 'RandomWallpaper.Settings',
|
||||
logger: null,
|
||||
|
||||
currentSourceSettingsWidget: null,
|
||||
|
||||
noSettings: null,
|
||||
desktopperSettings: null,
|
||||
unsplashSettings: null,
|
||||
wallheavenSettings: null,
|
||||
|
||||
_init: function () {
|
||||
this._settings = Convenience.getSettings(RWG_SETTINGS_SCHEMA);
|
||||
|
|
@ -35,6 +48,25 @@ const RandomWallpaperSettings = new Lang.Class({
|
|||
//this._builder.set_translation_domain(Self.metadata['gettext-domain']);
|
||||
this._builder.add_from_file(Self.path + '/settings.ui');
|
||||
|
||||
this.logger = new LoggerModule.Logger('RWG3', 'RandomWallpaper.Settings');
|
||||
|
||||
this.noSettings = this._builder.get_object('no-settings');
|
||||
|
||||
// Desktopper Settings
|
||||
this._desktopper_settings = Convenience.getSettings(RWG_SETTINGS_SCHEMA_DESKTOPPER);
|
||||
this.desktopperSettings = this._builder.get_object('desktopper-settings');
|
||||
this.bindDesktopper();
|
||||
|
||||
// Unsplash Settings
|
||||
this._unsplash_settings = Convenience.getSettings(RWG_SETTINGS_SCHEMA_UNSPLASH);
|
||||
this.unsplashSettings = this._builder.get_object('unsplash-settings');
|
||||
this.bindUnsplash();
|
||||
|
||||
// Wallheaven Settings
|
||||
this._wallheaven_settings = Convenience.getSettings(RWG_SETTINGS_SCHEMA_WALLHEAVEN);
|
||||
this.wallheavenSettings = this._builder.get_object('wallheaven-settings');
|
||||
this.bindWallheaven();
|
||||
|
||||
this._toggleAfSliders();
|
||||
|
||||
this.widget = this._builder.get_object('main-widget');
|
||||
|
|
@ -43,6 +75,31 @@ const RandomWallpaperSettings = new Lang.Class({
|
|||
this._toggleAfSliders();
|
||||
}.bind(this));
|
||||
|
||||
this._builder.get_object('source-combo').connect('changed', (sourceCombo) => {
|
||||
let container = this._builder.get_object('source-settings-frame');
|
||||
if (this.currentSourceSettingsWidget !== null) {
|
||||
container.remove(this.currentSourceSettingsWidget);
|
||||
}
|
||||
|
||||
switch (sourceCombo.active) {
|
||||
case 0: // desktopper
|
||||
this.currentSourceSettingsWidget = this.desktopperSettings;
|
||||
break;
|
||||
case 1: // unsplash
|
||||
this.currentSourceSettingsWidget = this.unsplashSettings;
|
||||
break;
|
||||
case 2: // wallheaven
|
||||
this.currentSourceSettingsWidget = this.wallheavenSettings;
|
||||
break;
|
||||
default:
|
||||
this.currentSourceSettingsWidget = this.noSettings;
|
||||
break;
|
||||
}
|
||||
|
||||
container.add(this.currentSourceSettingsWidget);
|
||||
|
||||
});
|
||||
|
||||
this._settings.bind('history-length',
|
||||
this._builder.get_object('history-length'),
|
||||
'value',
|
||||
|
|
@ -73,6 +130,66 @@ const RandomWallpaperSettings = new Lang.Class({
|
|||
this._builder.get_object('duration-slider-hours').set_sensitive(false);
|
||||
this._builder.get_object('duration-slider-minutes').set_sensitive(false);
|
||||
}
|
||||
},
|
||||
|
||||
bindDesktopper: function () {
|
||||
this._desktopper_settings.bind('allow-unsafe',
|
||||
this._builder.get_object('desktopper-allow-unsafe'),
|
||||
'active',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
},
|
||||
|
||||
bindUnsplash: function () {
|
||||
this._unsplash_settings.bind('unsplash-keyword',
|
||||
this._builder.get_object('unsplash-keyword'),
|
||||
'text',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
this._unsplash_settings.bind('username',
|
||||
this._builder.get_object('unsplash-username'),
|
||||
'text',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
|
||||
this._unsplash_settings.bind('image-width',
|
||||
this._builder.get_object('unsplash-image-width'),
|
||||
'value',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
this._unsplash_settings.bind('image-height',
|
||||
this._builder.get_object('unsplash-image-height'),
|
||||
'value',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
},
|
||||
|
||||
bindWallheaven: function () {
|
||||
this._wallheaven_settings.bind('wallheaven-keyword',
|
||||
this._builder.get_object('wallheaven-keyword'),
|
||||
'text',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
this._wallheaven_settings.bind('resolutions',
|
||||
this._builder.get_object('wallheaven-resolutions'),
|
||||
'text',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
|
||||
this._wallheaven_settings.bind('category-general',
|
||||
this._builder.get_object('wallheaven-category-general'),
|
||||
'active',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
this._wallheaven_settings.bind('category-anime',
|
||||
this._builder.get_object('wallheaven-category-anime'),
|
||||
'active',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
this._wallheaven_settings.bind('category-people',
|
||||
this._builder.get_object('wallheaven-category-people'),
|
||||
'active',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
|
||||
this._wallheaven_settings.bind('allow-sfw',
|
||||
this._builder.get_object('wallheaven-allow-sfw'),
|
||||
'active',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
this._wallheaven_settings.bind('allow-sketchy',
|
||||
this._builder.get_object('wallheaven-allow-sketchy'),
|
||||
'active',
|
||||
Gio.SettingsBindFlags.DEFAULT);
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -2,13 +2,13 @@
|
|||
<schemalist gettext-domain='gnome-shell-extensions'>
|
||||
|
||||
<enum id='org.gnome.shell.extensions.space.iflow.randomwallpaper.sources'>
|
||||
<value value='0' nick='desktoppr'/>
|
||||
<value value='1' nick='unsplash'/>
|
||||
<value value='2' nick='wallheaven'/>
|
||||
<value value='0' nick='desktoppr'/>
|
||||
<value value='1' nick='unsplash'/>
|
||||
<value value='2' nick='wallheaven'/>
|
||||
</enum>
|
||||
|
||||
<schema path="/org/gnome/shell/extensions/space-iflow-randomwallpaper-sources/"
|
||||
id='org.gnome.shell.extensions.space.iflow.randomwallpaper'>
|
||||
id='org.gnome.shell.extensions.space.iflow.randomwallpaper'>
|
||||
|
||||
<key type='i' name='history-length'>
|
||||
<default>10</default>
|
||||
|
|
@ -38,9 +38,9 @@
|
|||
</key>
|
||||
|
||||
<key name='source' enum='org.gnome.shell.extensions.space.iflow.randomwallpaper.sources'>
|
||||
<default>'desktoppr'</default>
|
||||
<summary>Wallpaper Source</summary>
|
||||
<description>Describs the adapter that will be used.</description>
|
||||
<default>'desktoppr'</default>
|
||||
<summary>Wallpaper Source</summary>
|
||||
<description>Describs the adapter that will be used.</description>
|
||||
</key>
|
||||
|
||||
<key type='as' name='history'>
|
||||
|
|
@ -56,4 +56,77 @@
|
|||
</key>
|
||||
|
||||
</schema>
|
||||
|
||||
<schema path="/org/gnome/shell/extensions/space-iflow-randomwallpaper-sources/"
|
||||
id='org.gnome.shell.extensions.space.iflow.randomwallpaper.desktopper'>
|
||||
<key type='b' name='allow-unsafe'>
|
||||
<default>false</default>
|
||||
<summary>Allow Unsafe</summary>
|
||||
<description>Weather the extension should fetch images that are rated as unsafe.</description>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<schema path="/org/gnome/shell/extensions/space-iflow-randomwallpaper-sources/"
|
||||
id='org.gnome.shell.extensions.space.iflow.randomwallpaper.unsplash'>
|
||||
<key type='s' name='unsplash-keyword'>
|
||||
<default>""</default>
|
||||
<summary>Keyword</summary>
|
||||
<description>The keyword will be used to search images.</description>
|
||||
</key>
|
||||
<key type='s' name='username'>
|
||||
<default>""</default>
|
||||
<summary>Username</summary>
|
||||
<description>Only fetch random images of a given user.</description>
|
||||
</key>
|
||||
<key type='i' name='image-width'>
|
||||
<default>1920</default>
|
||||
<summary>Image Width</summary>
|
||||
<description>The width of the image.</description>
|
||||
</key>
|
||||
<key type='i' name='image-height'>
|
||||
<default>1080</default>
|
||||
<summary>Image Width</summary>
|
||||
<description>The height of the image.</description>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<schema path="/org/gnome/shell/extensions/space-iflow-randomwallpaper-sources/"
|
||||
id='org.gnome.shell.extensions.space.iflow.randomwallpaper.wallheaven'>
|
||||
<key type='s' name='wallheaven-keyword'>
|
||||
<default>""</default>
|
||||
<summary>Keyword</summary>
|
||||
<description>The keyword will be used to search images.</description>
|
||||
</key>
|
||||
<key type='s' name='resolutions'>
|
||||
<default>"1920x1200, 1920x1080, 2560x1440, 2560x1600, 3840x1080"</default>
|
||||
<summary>Resolutions</summary>
|
||||
<description>The acceptable resolutions.</description>
|
||||
</key>
|
||||
<key type='b' name='allow-sfw'>
|
||||
<default>true</default>
|
||||
<summary>SFW</summary>
|
||||
<description>Weather safe images are allowed.</description>
|
||||
</key>
|
||||
<key type='b' name='allow-sketchy'>
|
||||
<default>false</default>
|
||||
<summary>Sketchy</summary>
|
||||
<description>Weather sketchy images are allowed.</description>
|
||||
</key>
|
||||
|
||||
<key type='b' name='category-general'>
|
||||
<default>true</default>
|
||||
<summary>Category General</summary>
|
||||
<description>Weather the general category should be searched.</description>
|
||||
</key>
|
||||
<key type='b' name='category-anime'>
|
||||
<default>true</default>
|
||||
<summary>Category Anime</summary>
|
||||
<description>Weather the anime category should be searched.</description>
|
||||
</key>
|
||||
<key type='b' name='category-people'>
|
||||
<default>true</default>
|
||||
<summary>Category People</summary>
|
||||
<description>Weather the people category should be searched.</description>
|
||||
</key>
|
||||
</schema>
|
||||
</schemalist>
|
||||
|
|
|
|||
|
|
@ -6,31 +6,37 @@ const Self = imports.misc.extensionUtils.getCurrentExtension();
|
|||
const Convenience = Self.imports.convenience;
|
||||
|
||||
let Settings = new Lang.Class({
|
||||
Name: "Settings",
|
||||
Name: "Settings",
|
||||
_settings: null,
|
||||
|
||||
_init: function() {
|
||||
this._settings = Convenience.getSettings();
|
||||
},
|
||||
/**
|
||||
* Settings object.
|
||||
*
|
||||
* @param [schema]
|
||||
* @private
|
||||
*/
|
||||
_init: function (schema) {
|
||||
this._settings = Convenience.getSettings(schema);
|
||||
},
|
||||
|
||||
observe: function(key, callback) {
|
||||
this._settings.connect('changed::'+key, callback);
|
||||
},
|
||||
observe: function (key, callback) {
|
||||
this._settings.connect('changed::' + key, callback);
|
||||
},
|
||||
|
||||
set: function(key, type, value) {
|
||||
if (this._settings['set_'+type](key, value)){
|
||||
Gio.Settings.sync(); // wait for write
|
||||
} else {
|
||||
throw "Could not set " + key + " (type: " + type + ") with the value " + value;
|
||||
}
|
||||
},
|
||||
set: function (key, type, value) {
|
||||
if (this._settings['set_' + type](key, value)) {
|
||||
Gio.Settings.sync(); // wait for write
|
||||
} else {
|
||||
throw "Could not set " + key + " (type: " + type + ") with the value " + value;
|
||||
}
|
||||
},
|
||||
|
||||
get: function(key, type) {
|
||||
return this._settings['get_'+type](key);
|
||||
},
|
||||
get: function (key, type) {
|
||||
return this._settings['get_' + type](key);
|
||||
},
|
||||
|
||||
getSourceAdapter: function() {
|
||||
getSourceAdapter: function () {
|
||||
global.log(this._settings.get_enum('source'));
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,6 +2,29 @@
|
|||
<!-- Generated with glade 3.20.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkBox" id="desktopper-settings">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="desktopper-allow-unsafe">
|
||||
<property name="label" translatable="yes">Allow unsafe images (also fetch images that are marked as unsafe)</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="duration-hours">
|
||||
<property name="upper">23</property>
|
||||
<property name="value">1</property>
|
||||
|
|
@ -115,7 +138,7 @@
|
|||
<property name="active_id">0</property>
|
||||
<items>
|
||||
<item id="desktoppr">desktoppr.co</item>
|
||||
<item id="unsplash">unsplash.com (not implemented, defaults to desktopper)</item>
|
||||
<item id="unsplash">unsplash.com (experimental)</item>
|
||||
<item id="wallheaven">alpha.wallheaven.cc (experimental)</item>
|
||||
</items>
|
||||
</object>
|
||||
|
|
@ -131,34 +154,22 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<object class="GtkFrame" id="source-settings-frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="label_xalign">0</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkAlignment">
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child type="label">
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="left_padding">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="label" translatable="yes">No Settings Available</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<property name="label" translatable="yes">Source Settings</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label_item">
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
|
|
@ -466,4 +477,362 @@
|
|||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkLabel" id="no-settings">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="label" translatable="yes">No Settings Available</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="unsplash-image-height">
|
||||
<property name="lower">1</property>
|
||||
<property name="upper">1000000</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="unsplash-image-width">
|
||||
<property name="lower">1</property>
|
||||
<property name="upper">1000000</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_increment">10</property>
|
||||
</object>
|
||||
<object class="GtkBox" id="unsplash-settings">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Username</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="unsplash-username">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="placeholder_text" translatable="yes">@username</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Keyword</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="unsplash-keyword">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="placeholder_text" translatable="yes">Enter a keyword ...</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_right">5</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Image Width</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="input_purpose">number</property>
|
||||
<property name="adjustment">unsplash-image-width</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">5</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Image Height</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="input_purpose">number</property>
|
||||
<property name="adjustment">unsplash-image-height</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkBox" id="wallheaven-settings">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="margin_top">10</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Keyword</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="wallheaven-keyword">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="placeholder_text" translatable="yes">Enter a keyword ...</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Allowed Content Ratings</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="layout_style">start</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="wallheaven-allow-sfw">
|
||||
<property name="label" translatable="yes">SFW (Safe for work)</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="wallheaven-allow-sketchy">
|
||||
<property name="label" translatable="yes">Sketchy</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Categories</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_bottom">10</property>
|
||||
<property name="layout_style">start</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="wallheaven-category-general">
|
||||
<property name="label" translatable="yes">General</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="wallheaven-category-anime">
|
||||
<property name="label" translatable="yes">Anime</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="wallheaven-category-people">
|
||||
<property name="label" translatable="yes">People</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Resolutions</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="wallheaven-resolutions">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="placeholder_text" translatable="yes">1920x1080, 1920x1200</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
|
|
|||
|
|
@ -1,78 +1,198 @@
|
|||
const Lang = imports.lang;
|
||||
const Self = imports.misc.extensionUtils.getCurrentExtension();
|
||||
|
||||
// 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
|
||||
const RWG_SETTINGS_SCHEMA_DESKTOPPER = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.desktopper';
|
||||
const RWG_SETTINGS_SCHEMA_UNSPLASH = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.unsplash';
|
||||
const RWG_SETTINGS_SCHEMA_WALLHEAVEN = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.wallheaven';
|
||||
|
||||
const SettingsModule = Self.imports.settings;
|
||||
const HistoryModule = Self.imports.history;
|
||||
|
||||
const LoggerModule = Self.imports.logger;
|
||||
|
||||
let BaseAdapter = new Lang.Class({
|
||||
Name: "BaseAdapter",
|
||||
logger: null,
|
||||
|
||||
_init: function () {
|
||||
this.logger = new LoggerModule.Logger('RWG3', 'BaseAdapter');
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves a new url for an image and calls the given callback with an HistoryEntry as parameter.
|
||||
* @param callback
|
||||
*/
|
||||
requestRandomImage: function (callback) {
|
||||
this.logger.error("requestRandomImage not implemented");
|
||||
|
||||
callback(null);
|
||||
},
|
||||
|
||||
fileName: function (uri) {
|
||||
let base = new String(uri).substring(uri.lastIndexOf('/') + 1);
|
||||
return base;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
let DesktopperAdapter = new Lang.Class({
|
||||
Name: "DesktopperAdapter",
|
||||
Extends: BaseAdapter,
|
||||
|
||||
_settings: null,
|
||||
|
||||
_init: function () {
|
||||
this.parent();
|
||||
|
||||
this._settings = new SettingsModule.Settings(RWG_SETTINGS_SCHEMA_DESKTOPPER);
|
||||
},
|
||||
|
||||
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();
|
||||
let url = 'https://api.desktoppr.co/1/wallpapers/random';
|
||||
let allowUnsafe = this._settings.get('allow-unsafe', 'boolean');
|
||||
if (allowUnsafe) {
|
||||
url += '?safe_filter=all';
|
||||
} else {
|
||||
url += '?safe_filter=safe';
|
||||
}
|
||||
url = encodeURI(url);
|
||||
this.logger.debug("Base URL: " + url);
|
||||
|
||||
var _this = this;
|
||||
let message = Soup.Message.new('GET', url);
|
||||
|
||||
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');
|
||||
session.queue_message(message, (session, message) => {
|
||||
let data = JSON.parse(message.response_body.data);
|
||||
let response = data.response;
|
||||
let imageUrl = encodeURI(response.image.url);
|
||||
|
||||
if (callback) {
|
||||
callback(imageUrl);
|
||||
let historyEntry = new HistoryModule.HistoryEntry(null, 'desktopper.co', imageUrl);
|
||||
historyEntry.source.sourceUrl = 'https://www.desktoppr.co/';
|
||||
callback(historyEntry);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let UnsplashAdapter = new Lang.Class({
|
||||
Name: "UnsplashAdapter",
|
||||
Extends: BaseAdapter,
|
||||
|
||||
sourceName: 'Unsplash',
|
||||
sourceUrl: 'https://unsplash.com/',
|
||||
|
||||
_settings: null,
|
||||
|
||||
// query options
|
||||
options: {
|
||||
'username': '',
|
||||
'query': '',
|
||||
'w': 1920,
|
||||
'h': 1080,
|
||||
},
|
||||
|
||||
_init: function () {
|
||||
this.parent();
|
||||
|
||||
this._settings = new SettingsModule.Settings(RWG_SETTINGS_SCHEMA_UNSPLASH);
|
||||
},
|
||||
|
||||
requestRandomImage: function (callback) {
|
||||
let session = new Soup.SessionAsync();
|
||||
|
||||
this._readOptionsFromSettings();
|
||||
let optionsString = this._generateOptionsString();
|
||||
let url = 'https://api.unsplash.com/photos/random?' + optionsString;
|
||||
url += 'client_id=64daf439e9b579dd566620c0b07022706522d87b255d06dd01d5470b7f193b8d';
|
||||
url = encodeURI(url);
|
||||
this.logger.debug("Base URL: " + url);
|
||||
|
||||
let message = Soup.Message.new('GET', url);
|
||||
|
||||
let utmParameters = '?utm_source=RandomWallpaperGnome3&utm_medium=referral&utm_campaign=api-credit';
|
||||
|
||||
session.queue_message(message, (session, message) => {
|
||||
let data = JSON.parse(message.response_body.data);
|
||||
|
||||
let imageUrl = encodeURI(data.links.download + utmParameters);
|
||||
let authorName = data.user.name;
|
||||
let authorUrl = encodeURI(data.user.links.html);
|
||||
|
||||
if (callback) {
|
||||
let historyEntry = new HistoryModule.HistoryEntry(authorName, this.sourceName, encodeURI(imageUrl));
|
||||
historyEntry.source.sourceUrl = encodeURI(this.sourceUrl + utmParameters);
|
||||
historyEntry.source.authorUrl = encodeURI(authorUrl + utmParameters);
|
||||
callback(historyEntry);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_generateOptionsString: function () {
|
||||
let options = this.options;
|
||||
let optionsString = "";
|
||||
|
||||
for (let key in options) {
|
||||
if (options.hasOwnProperty(key)) {
|
||||
if (options[key]) {
|
||||
optionsString += key + "=" + options[key] + "&";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return optionsString;
|
||||
},
|
||||
|
||||
_readOptionsFromSettings: function () {
|
||||
this.options.query = this._settings.get('unsplash-keyword', 'string');
|
||||
|
||||
this.options.username = this._settings.get('username', 'string');
|
||||
if (this.options.username[0] === '@') {
|
||||
this.options.username = this.options.username.substring(1); // remove @ prefix
|
||||
}
|
||||
|
||||
this.options.w = this._settings.get('image-width', 'int');
|
||||
this.options.h = this._settings.get('image-height', 'int');
|
||||
}
|
||||
});
|
||||
|
||||
let WallheavenAdapter = new Lang.Class({
|
||||
Name: "WallheavenAdapter",
|
||||
Extends: BaseAdapter,
|
||||
_settings: null,
|
||||
|
||||
// query options
|
||||
options: {
|
||||
'q': '',
|
||||
'purity': '110', // SFW, sketchy
|
||||
'sorting': 'random',
|
||||
'category': '111', // General, Anime, People
|
||||
'categories': '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
|
||||
*/
|
||||
_init: function () {
|
||||
this.parent();
|
||||
|
||||
this._settings = new SettingsModule.Settings(RWG_SETTINGS_SCHEMA_WALLHEAVEN);
|
||||
},
|
||||
|
||||
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);
|
||||
|
||||
this._readOptionsFromSettings();
|
||||
let optionsString = this._generateOptionsString();
|
||||
let url = 'http://alpha.wallhaven.cc/search?' + optionsString;
|
||||
url = encodeURI(url);
|
||||
this.logger.debug("Base URL: " + url);
|
||||
|
||||
let message = Soup.Message.new('GET', url);
|
||||
|
||||
var _this = this;
|
||||
|
||||
session.queue_message(message, function (session, message) {
|
||||
session.queue_message(message, (session, message) => {
|
||||
let body = message.response_body.data;
|
||||
let urlArray = body.match(new RegExp(/http[s]*:\/\/alpha.wallhaven.cc\/wallpaper\/[0-9]+/g));
|
||||
|
||||
|
|
@ -82,22 +202,65 @@ let WallheavenAdapter = new Lang.Class({
|
|||
});
|
||||
|
||||
// get a random entry from the array
|
||||
var url = uniqueUrlArray[Math.floor(Math.random() * uniqueUrlArray.length)];
|
||||
let url = uniqueUrlArray[Math.floor(Math.random() * uniqueUrlArray.length)];
|
||||
|
||||
message = Soup.Message.new('GET', url);
|
||||
|
||||
session.queue_message(message, function () {
|
||||
session.queue_message(message, () => {
|
||||
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;
|
||||
imageUrl = encodeURI(imageUrl);
|
||||
|
||||
if (callback) {
|
||||
callback(imageUrl);
|
||||
let historyEntry = new HistoryModule.HistoryEntry(null, 'wallhaven.cc', imageUrl);
|
||||
historyEntry.source.sourceUrl = 'https://alpha.wallhaven.cc/';
|
||||
callback(historyEntry);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
_generateOptionsString: function () {
|
||||
let options = this.options;
|
||||
let optionsString = "";
|
||||
|
||||
for (let key in options) {
|
||||
if (options.hasOwnProperty(key)) {
|
||||
if (Array.isArray(options[key])) {
|
||||
optionsString += key + "=" + options[key].join() + "&";
|
||||
} else {
|
||||
if (options[key]) {
|
||||
optionsString += key + "=" + options[key] + "&";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return optionsString;
|
||||
},
|
||||
|
||||
_readOptionsFromSettings: function () {
|
||||
this.options.q = this._settings.get('wallheaven-keyword', 'string');
|
||||
|
||||
this.options.resolutions = this._settings.get('resolutions', 'string').split(',');
|
||||
this.options.resolutions = this.options.resolutions.map((elem) => {
|
||||
return elem.trim();
|
||||
});
|
||||
|
||||
let categories = [];
|
||||
categories.push(+this._settings.get('category-general', 'boolean')); // + is implicit conversion to int
|
||||
categories.push(+this._settings.get('category-anime', 'boolean'));
|
||||
categories.push(+this._settings.get('category-people', 'boolean'));
|
||||
this.options.categories = categories.join('');
|
||||
|
||||
let purity = [];
|
||||
purity.push(+this._settings.get('allow-sfw', 'boolean'));
|
||||
purity.push(+this._settings.get('allow-sketchy', 'boolean'));
|
||||
purity.push(0); // required by wallheaven
|
||||
this.options.purity = purity.join('');
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
|
||||
.rwg_system_status_icon {
|
||||
/*icon-size: 1.09em;*/
|
||||
icon-size: 1em;
|
||||
/*padding: 0 5px;*/
|
||||
padding: 0 0;
|
||||
padding: 0 0;
|
||||
position: absolute;
|
||||
-webkit-animation:spin 4s linear infinite;
|
||||
-moz-animation:spin 4s linear infinite;
|
||||
|
|
@ -26,25 +24,23 @@
|
|||
|
||||
.rwg-recent-lable {
|
||||
width: 100%;
|
||||
/*font-weight: bold;*/
|
||||
font-size: 90%;
|
||||
text-align: left;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.rwg-history-index {
|
||||
text-align: left;
|
||||
padding-top: .35em;
|
||||
font-size: 130%;
|
||||
font-weight: lighter;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.rwg-history-date {
|
||||
/*padding-top: .35em;*/
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.rwg-history-time {
|
||||
/*padding-top: .35em;*/
|
||||
font-size: 100%;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ const SourceAdapter = Self.imports.sourceAdapter;
|
|||
const Convenience = Self.imports.convenience;
|
||||
const Prefs = Self.imports.settings;
|
||||
const Timer = Self.imports.timer;
|
||||
const HistoryModule = Self.imports.history;
|
||||
|
||||
const LoggerModule = Self.imports.logger;
|
||||
|
||||
|
|
@ -24,9 +25,8 @@ let WallpaperController = new Lang.Class({
|
|||
|
||||
wallpaperlocation: '',
|
||||
currentWallpaper: '',
|
||||
historySize: 10,
|
||||
history: [],
|
||||
imageSourceAdapter: undefined,
|
||||
_historyController: null,
|
||||
imageSourceAdapter: null,
|
||||
|
||||
_timer: null,
|
||||
_autoFetch : {
|
||||
|
|
@ -44,6 +44,7 @@ let WallpaperController = new Lang.Class({
|
|||
this.wallpaperlocation = this.extensionMeta.path + '/wallpapers/';
|
||||
|
||||
this._timer = new Timer.AFTimer();
|
||||
this._historyController = new HistoryModule.HistoryController(this.wallpaperlocation);
|
||||
|
||||
this._settings = new Prefs.Settings();
|
||||
this._settings.observe('history-length', this._updateHistory.bind(this));
|
||||
|
|
@ -54,17 +55,17 @@ let WallpaperController = new Lang.Class({
|
|||
this._updateHistory();
|
||||
this._updateAutoFetching();
|
||||
|
||||
this.history = this._loadHistory();
|
||||
this.currentWallpaper = this._getCurrentWallpaper();
|
||||
|
||||
this._desktopperAdapter = new SourceAdapter.DesktopperAdapter();
|
||||
this._unsplashAdapter = new SourceAdapter.UnsplashAdapter();
|
||||
this._wallheavenAdapter = new SourceAdapter.WallheavenAdapter();
|
||||
|
||||
this.logger = new LoggerModule.Logger('RWG3', 'WallpaperController');
|
||||
},
|
||||
|
||||
_updateHistory: function() {
|
||||
this.historySize = this._settings.get('history-length', 'int');
|
||||
this._historyController.load();
|
||||
},
|
||||
|
||||
_updateAutoFetching: function() {
|
||||
|
|
@ -91,6 +92,9 @@ let WallpaperController = new Lang.Class({
|
|||
case 0:
|
||||
this.imageSourceAdapter = this._desktopperAdapter;
|
||||
break;
|
||||
case 1:
|
||||
this.imageSourceAdapter = this._unsplashAdapter;
|
||||
break;
|
||||
case 2:
|
||||
this.imageSourceAdapter = this._wallheavenAdapter;
|
||||
break;
|
||||
|
|
@ -108,21 +112,17 @@ let WallpaperController = new Lang.Class({
|
|||
the written file as parameter.
|
||||
*/
|
||||
_fetchFile: function(uri, callback){
|
||||
//extract the name from the url and
|
||||
let date = new Date();
|
||||
let inputbuffer;
|
||||
|
||||
//extract the name from the desktopper url and add timestamp prefix
|
||||
let name = date.getTime() + uri.substr(uri.lastIndexOf('.'));
|
||||
let name = date.getTime()+'_'+this.imageSourceAdapter.fileName(uri); // timestamp ensures uniqueness
|
||||
|
||||
let output_file = Gio.file_new_for_path(this.wallpaperlocation + String(name));
|
||||
let output_stream = output_file.create(0, null);
|
||||
|
||||
let input_file = Gio.file_new_for_uri(uri);
|
||||
|
||||
let _this = this;
|
||||
|
||||
input_file.load_contents_async(null, function(file, result){
|
||||
let contents = file.load_contents_finish(result)[1];
|
||||
input_file.load_contents_async(null, (file, result) => {
|
||||
let contents = file.load_contents_finish(result)[1]; // TODO: error handling. This failes due to: "An unexpected TLS packet was received."
|
||||
output_stream.write(contents, null);
|
||||
|
||||
// call callback with the name and the full filepath of the written file as parameter
|
||||
|
|
@ -132,38 +132,8 @@ let WallpaperController = new Lang.Class({
|
|||
});
|
||||
},
|
||||
|
||||
/*
|
||||
Set a new timestamp as name for the given file
|
||||
and adapt the history
|
||||
*/
|
||||
_setNewFileName: function(historyid) {
|
||||
let date = new Date();
|
||||
let file = Gio.file_new_for_path(this.wallpaperlocation + historyid);
|
||||
let name = date.getTime() + historyid.substr(historyid.lastIndexOf('.'));
|
||||
let newFile = Gio.file_new_for_path(this.wallpaperlocation + name);
|
||||
|
||||
for (var i = 0; i < this.history.length; i++) {
|
||||
if(this.history[i] == historyid) {
|
||||
file.move(newFile, Gio.FileCopyFlags.NONE, null, function(){
|
||||
});
|
||||
|
||||
// TODO: error handling, what if move fails?
|
||||
|
||||
this.history[i] = name;
|
||||
|
||||
this.history.sort();
|
||||
this.history.reverse();
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_setBackground: function(path, callback){
|
||||
let background_setting = new Gio.Settings({schema: "org.gnome.desktop.background"});
|
||||
this.deleteOldPictures();
|
||||
|
||||
/*
|
||||
inspired from:
|
||||
|
|
@ -192,69 +162,37 @@ let WallpaperController = new Lang.Class({
|
|||
return background_setting.get_string("picture-uri").replace(/^(file:\/\/)/, "");
|
||||
},
|
||||
|
||||
_loadHistory: function () {
|
||||
let directory = Gio.file_new_for_path(this.wallpaperlocation);
|
||||
let enumerator = directory.enumerate_children('', Gio.FileQueryInfoFlags.NONE, null);
|
||||
setWallpaper: function(historyId) {
|
||||
let historyElement = this._historyController.get(historyId);
|
||||
|
||||
let fileinfo;
|
||||
let history = [];
|
||||
|
||||
do {
|
||||
fileinfo = enumerator.next_file(null);
|
||||
|
||||
if (!fileinfo) {
|
||||
break;
|
||||
}
|
||||
|
||||
let name = fileinfo.get_name();
|
||||
|
||||
// ignore hidden files
|
||||
if (name[0] != '.') {
|
||||
history.push(fileinfo.get_name());
|
||||
}
|
||||
|
||||
} while(fileinfo);
|
||||
|
||||
history.sort();
|
||||
history.reverse();
|
||||
|
||||
return history;
|
||||
},
|
||||
|
||||
deleteOldPictures: function() {
|
||||
this.historySize = this._settings.get('history-length', 'int');
|
||||
let deleteFile;
|
||||
while(this.history.length > this.historySize) {
|
||||
deleteFile = Gio.file_new_for_path(this.wallpaperlocation + this.history.pop());
|
||||
deleteFile.delete(null);
|
||||
if(this._historyController.promoteToActive(historyElement.id)) {
|
||||
this._setBackground(historyElement.path);
|
||||
this.currentWallpaper = this._getCurrentWallpaper();
|
||||
} else {
|
||||
this.logger.warn("The history id ("+historyElement.id+") could not be found.")
|
||||
// TODO: Error handling history id not found.
|
||||
}
|
||||
},
|
||||
|
||||
setWallpaper: function(historyEntry, keepName) {
|
||||
if (!keepName) {
|
||||
historyEntry = this._setNewFileName(historyEntry);
|
||||
}
|
||||
this._setBackground(this.wallpaperlocation + historyEntry);
|
||||
this.currentWallpaper = this._getCurrentWallpaper();
|
||||
},
|
||||
|
||||
fetchNewWallpaper: function(callback) {
|
||||
this._startLoadingHooks.forEach((element) => {
|
||||
element();
|
||||
});
|
||||
this._timer.begin(); // reset timer
|
||||
|
||||
let _this = this;
|
||||
this._requestRandomImageFromAdapter((imageUrl) => {
|
||||
this.logger.debug("Requesting image: "+imageUrl);
|
||||
this._requestRandomImageFromAdapter((historyElement) => {
|
||||
this.logger.info("Requesting image: "+historyElement.source.imageUrl);
|
||||
|
||||
_this._fetchFile(imageUrl, (historyid, path) => {
|
||||
// insert file into history
|
||||
_this.history.unshift(historyid);
|
||||
this._fetchFile(historyElement.source.imageUrl, (historyId, path) => {
|
||||
historyElement.path = path;
|
||||
historyElement.id = historyId;
|
||||
|
||||
this._setBackground(path, () => {
|
||||
// insert file into history
|
||||
this._historyController.insert(historyElement);
|
||||
|
||||
_this._setBackground(_this.wallpaperlocation + historyid, function(){
|
||||
// call callback if given
|
||||
_this._stopLoadingHooks.forEach((element) => {
|
||||
this._stopLoadingHooks.forEach((element) => {
|
||||
element(null);
|
||||
});
|
||||
if (callback) {
|
||||
|
|
@ -270,16 +208,15 @@ let WallpaperController = new Lang.Class({
|
|||
return;
|
||||
}
|
||||
|
||||
let _this = this;
|
||||
delay = delay || 200;
|
||||
|
||||
this.timeout = Mainloop.timeout_add(Mainloop.PRIORITY_DEFAULT, delay, function(){
|
||||
_this.timeout = null;
|
||||
if (_this._resetWallpaper) {
|
||||
_this._setBackground(_this.currentWallpaper);
|
||||
_this._resetWallpaper = false;
|
||||
this.timeout = Mainloop.timeout_add(Mainloop.PRIORITY_DEFAULT, delay, () => {
|
||||
this.timeout = null;
|
||||
if (this._resetWallpaper) {
|
||||
this._setBackground(this.currentWallpaper);
|
||||
this._resetWallpaper = false;
|
||||
} else {
|
||||
_this._setBackground(_this.wallpaperlocation + _this.previewId);
|
||||
this._setBackground(this.wallpaperlocation + this.previewId);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
|
@ -297,41 +234,12 @@ let WallpaperController = new Lang.Class({
|
|||
this._backgroundTimout();
|
||||
},
|
||||
|
||||
getHistory: function() {
|
||||
return this.history;
|
||||
getHistoryController: function() {
|
||||
return this._historyController;
|
||||
},
|
||||
|
||||
deleteHistory: function() {
|
||||
let firstHistoryElement = this.history[0];
|
||||
|
||||
if (firstHistoryElement)
|
||||
this.history = [firstHistoryElement];
|
||||
|
||||
let directory = Gio.file_new_for_path(this.wallpaperlocation);
|
||||
let enumerator = directory.enumerate_children('', Gio.FileQueryInfoFlags.NONE, null);
|
||||
|
||||
let fileinfo;
|
||||
let deleteFile;
|
||||
|
||||
do {
|
||||
|
||||
fileinfo = enumerator.next_file(null);
|
||||
|
||||
if (!fileinfo) {
|
||||
break;
|
||||
};
|
||||
|
||||
let name = fileinfo.get_name();
|
||||
|
||||
// ignore hidden files and first element
|
||||
if (name[0] != '.' && name != firstHistoryElement) {
|
||||
deleteFile = Gio.file_new_for_path(this.wallpaperlocation + name);
|
||||
deleteFile.delete(null);
|
||||
};
|
||||
|
||||
} while(fileinfo);
|
||||
|
||||
return true;
|
||||
this._historyController.clear();
|
||||
},
|
||||
|
||||
menuShowHook: function() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue