implemented basic history

- preview on hover
	- load from history by click
	- history size is 10
This commit is contained in:
Wolfgang R 2014-10-21 23:13:21 +02:00
parent 092650e3ad
commit 77d3f08981
4 changed files with 301 additions and 153 deletions

View file

@ -3,12 +3,33 @@ const PopupMenu = imports.ui.popupMenu;
const St = imports.gi.St;
const Slider = imports.ui.slider;
const Controls = new Lang.Class({
Name: 'Controls',
const HistoryElement = new Lang.Class({
Name: 'HistoryElement',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function() {
this.parent();
historyId: null,
_init: function(historyId, params) {
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._container = new St.BoxLayout({
vertical: true
});
this.label = new St.Label({ text: dateString });
this._container.add_child(this.label);
this.label = new St.Label({ text: timeString });
this._container.add_child(this.label);
this.historyId = historyId;
this.actor.add_child(this._container);
}
});
@ -16,35 +37,35 @@ const Controls = new Lang.Class({
// borrowed from: https://github.com/eonpatapon/gnome-shell-extensions-mediaplayer
const SliderItem = new Lang.Class({
Name: 'SliderItem',
Extends: PopupMenu.PopupBaseMenuItem,
Name: 'SliderItem',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function(value) {
this.parent();
_init: function(value) {
this.parent();
this._box = new St.Table({style_class: 'slider-item'});
this._box = new St.Table({style_class: 'slider-item'});
this._slider = new Slider.Slider(value);
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});
},
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);
},
setValue: function(value) {
this._slider.setValue(value);
},
getValue: function() {
return this._slider._getCurrentValue();
},
getValue: function() {
return this._slider._getCurrentValue();
},
setIcon: function(icon) {
this._icon.icon_name = icon + '-symbolic';
},
setIcon: function(icon) {
this._icon.icon_name = icon + '-symbolic';
},
connect: function(signal, callback) {
this._slider.connect(signal, callback);
}
connect: function(signal, callback) {
this._slider.connect(signal, callback);
}
});
@ -53,58 +74,58 @@ const SliderItem = new Lang.Class({
* @type {Lang.Class}
*/
const DelaySlider = new Lang.Class({
Name: 'DelaySlider',
Extends: SliderItem,
Name: 'DelaySlider',
Extends: SliderItem,
_MINUTES_MAX: 59,
_MINUTES_MIN: 5,
_HOURS_MAX: 48,
_HOURS_MIN: 1,
_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.
},
/**
* 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);
}
/**
* 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;
}
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);
},
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;
}
/**
* 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);
}
return (minutes < this._MINUTES_MIN) ? this._MINUTES_MIN : Math.floor(minutes);
}
});
// -------------------------------------------------------------------------------

View file

@ -18,85 +18,117 @@ let wallpaperController;
let extensionMeta;
function init(metaData) {
extensionMeta = metaData;
wallpaperController = new WallpaperController.WallpaperController(metaData);
global.log("INIT");
extensionMeta = metaData;
wallpaperController = new WallpaperController.WallpaperController(metaData);
global.log("INIT");
}
let panelEntry;
let RandomWallpaperEntry = new Lang.Class({
Extends: PanelMenu.Button,
Name: "RandomWallpaperEntry",
Extends: PanelMenu.Button,
Name: "RandomWallpaperEntry",
_history: [],
_init: function(menuAlignment, nameText) {
this.parent(menuAlignment, nameText);
_init: function(menuAlignment, nameText){
this.parent(menuAlignment, nameText);
//let gicon = Gio.Icon.new_for_string(extensionMeta.path + "/images/shuffle-icon.svg");
//let gicon = Gio.Icon.new_for_string(extensionMeta.path + "/images/shuffle-icon.svg");
/*let icon = new St.Icon({
gicon: gicon,
style_class: 'rwg_status_icon'
});*/
/*let icon = new St.Icon({
gicon: gicon,
style_class: 'rwg_status_icon'
});*/
let icon = new St.Icon({
icon_name: 'preferences-desktop-wallpaper-symbolic',
style_class: 'rwg_system_status_icon'
});
let icon = new St.Icon({
icon_name: 'preferences-desktop-wallpaper-symbolic',
style_class: 'rwg_system_status_icon'
});
this.actor.add_child(icon);
this.actor.add_child(icon);
let menu_item = new PopupMenu.PopupMenuItem('New Wallpaper');
let menu_item = new PopupMenu.PopupMenuItem('Change Background');
let lable = new PopupMenu.PopupMenuItem('Change Background', { reactive: false, activate: false, hover: false, style_class: 'rwg-lable', can_focus: false });
this.menu.addMenuItem(menu_item, 1);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addMenuItem(lable, 0);
this.menu.addMenuItem(menu_item, 1);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.historySection = new PopupMenu.PopupMenuSection();
this.menu.addMenuItem(this.historySection);
this.historySection = new PopupMenu.PopupMenuSection();
this.menu.addMenuItem(this.historySection);
this.setHistoryList();
this.clearHistory();
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
//this.menu.addMenuItem(new CustomElements.DelaySlider(60));
this.menu.addMenuItem(new CustomElements.DelaySlider(60));
// add eventlistener
let _this = this;
menu_item.actor.connect('button-press-event', function() {
wallpaperController.fetchNewWallpaper(function() {
_this.setHistoryList();
});
});
// add eventlistener
menu_item.actor.connect('button-press-event', function() {
wallpaperController._requestRandomImage();
});
},
// when the popupmenu disapears, check if the wallpaper is the original and
// reset it if needed
this.menu.actor.connect('hide', function() {
wallpaperController.setWallpaper(_this.history[0]);
});
},
setHistoryList: function() {
this.historySection.addMenuItem(new PopupMenu.PopupMenuItem('Test Item 0'));
this.historySection.addMenuItem(new PopupMenu.PopupMenuItem('Test Item 1'));
this.historySection.addMenuItem(new PopupMenu.PopupMenuItem('Test Item 2'));
setHistoryList: function() {
this.historySection.removeAll();
},
let history = this.history = wallpaperController.getHistory();
clearHistory: function() {
this.historySection.removeAll();
let empty = new PopupMenu.PopupMenuItem('No recent wallpaper ...', { reactive: false, activate: false, hover: false, style_class: 'rwg-lable', can_focus: false });
this.historySection.addMenuItem(empty);
},
if (!history.length) {
this.clearHistory();
};
for (var i = 0; i < history.length; i++) {
let historyid = history[i];
let tmp = new CustomElements.HistoryElement(historyid);
tmp.actor.connect('key-focus-in', function(actor) {
wallpaperController.previewWallpaper(historyid);
});
tmp.actor.connect('button-press-event', function(actor) {
wallpaperController.setWallpaper(historyid);
_this.setHistoryList();
});
this.historySection.addMenuItem(tmp);
};
},
clearHistory: function() {
this.historySection.removeAll();
let empty = new PopupMenu.PopupMenuItem('No recent wallpaper ...', {
reactive: false,
activate: false,
hover: false,
style_class: 'rwg-recent-lable',
can_focus: false
});
this.historySection.addMenuItem(empty);
},
});
function enable() {
global.log("ENABLE");
global.log("ENABLE");
// UI
panelEntry = new RandomWallpaperEntry(0, "Random wallpaper");
// UI
panelEntry = new RandomWallpaperEntry(0, "Random wallpaper");
// add to panel
Main.panel.addToStatusArea("random-wallpaper-menu", panelEntry);
// add to panel
Main.panel.addToStatusArea("random-wallpaper-menu", panelEntry);
}
function disable() {
global.log("DISABLE");
panelEntry.destroy();
global.log("DISABLE");
panelEntry.destroy();
}

View file

@ -1,11 +1,11 @@
.helloworld-label {
font-size: 36px;
font-weight: bold;
color: #ffffff;
background-color: rgba(10,10,10,0.7);
border-radius: 5px;
padding: .5em;
font-size: 36px;
font-weight: bold;
color: #ffffff;
background-color: rgba(10,10,10,0.7);
border-radius: 5px;
padding: .5em;
}
.rwg_system_status_icon {
@ -21,4 +21,12 @@
/*font-size: 110%;*/
text-align: left;
border: 0;
}
.rwg-recent-lable {
width: 100%;
/*font-weight: bold;*/
font-size: 90%;
text-align: left;
border: 0;
}

View file

@ -1,4 +1,5 @@
const Lang = imports.lang;
const Mainloop = imports.gi.GLib;
// network requests
const Soup = imports.gi.Soup;
@ -12,16 +13,23 @@ let WallpaperController = new Lang.Class({
extensionMeta: null,
wallpaperlocation: '',
historySize: 5,
currentWallpaper: '',
historySize: 10,
history: [],
_init: function(extensionMeta){
this.extensionMeta = extensionMeta;
this.wallpaperlocation = this.extensionMeta.path + '/wallpapers/';
this.history = this._loadHistory();
this.currentWallpaper = this._getCurrentWallpaper();
},
// fetch a random image url from desktopper.cc
_requestRandomImage: function(){
/*
fetch a random image url from desktopper.cc
and call callback function with the URL of the image
*/
_requestRandomImageDesktopper: function(callback){
let session = new Soup.SessionAsync();
let message = Soup.Message.new('GET', 'https://api.desktoppr.co/1/wallpapers/random')
@ -36,20 +44,23 @@ let WallpaperController = new Lang.Class({
let response = data.get_object_member('response');
let imageUrl = response.get_object_member('image').get_string_member('url');
_this._writeToFile(imageUrl);
if (callback) {
callback(imageUrl);
};
});
},
// copy file from uri to local direcotry
_writeToFile: function(uri){
/*
copy file from uri to local wallpaper direcotry and calls
the given callback with the name and the full filepath of
the written file as parameter.
*/
_fetchFile: function(uri, callback){
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('.'));
global.log(uri);
global.log(this.wallpaperlocation + String(name));
let output_file = Gio.file_new_for_path(this.wallpaperlocation + String(name));
let output_stream = output_file.create(0, null);
@ -61,25 +72,52 @@ let WallpaperController = new Lang.Class({
input_file.load_contents_async(null, function(file, result){
let contents = file.load_contents_finish(result)[1];
output_stream.write(contents, null);
_this._setBackground(output_file.get_path());
});
/*let fstream = input_file.copy(output_file, Gio.FileCopyFlags.OVERWRITE, null, function(){
}, function(){
}); */
// call callback with the name and the full filepath of the written file as parameter
if (callback) {
callback(name, output_file.get_path());
};
});
},
/*
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(){
});
this.history[i] = name;
this.history.sort();
this.history.reverse();
return name;
}
};
return false;
},
_setBackground: function(path){
let background_setting = new Gio.Settings({schema: "org.gnome.desktop.background"});
global.log("Current Background-Image: "+ background_setting.get_string("picture-uri"));
/*
inspired from:
https://bitbucket.org/LukasKnuth/backslide/src/7e36a49fc5e1439fa9ed21e39b09b61eca8df41a/backslide@codeisland.org/settings.js?at=master
*/
// Set:
if (background_setting.is_writable("picture-uri")){
// Set a new Background-Image (should show up immediately):
if (background_setting.set_string("picture-uri", "file://"+path) ){
//background_setting.apply();
Gio.Settings.sync(); // Necessary: http://stackoverflow.com/questions/9985140
} else {
global.log("FAAILLEEDD");
@ -91,9 +129,15 @@ let WallpaperController = new Lang.Class({
this.deleteOldPictures();
},
getHistory: function () {
_getCurrentWallpaper: function() {
let background_setting = new Gio.Settings({schema: "org.gnome.desktop.background"});
return background_setting.get_string("picture-uri");
},
_loadHistory: function () {
let directory = Gio.file_new_for_path(this.wallpaperlocation);
let enumerator = directory.enumerate_children('', Gio.FileQueryInfoFlags.NONE, null);
let fileinfo;
let history = [];
@ -101,7 +145,6 @@ let WallpaperController = new Lang.Class({
fileinfo = enumerator.next_file(null);
if (!fileinfo) {
global.log("SHOUT!!!");
break;
};
@ -115,18 +158,62 @@ let WallpaperController = new Lang.Class({
} while(fileinfo);
history.sort();
history.reverse();
global.log(history);
return history;
},
deleteOldPictures: function() {
let history = this.getHistory();
let deleteFile;
while(history.length > this.historySize) {
deleteFile = Gio.file_new_for_path(this.wallpaperlocation + history.shift());
while(this.history.length > this.historySize) {
deleteFile = Gio.file_new_for_path(this.wallpaperlocation + this.history.pop());
deleteFile.delete(null);
}
},
setWallpaper: function(historyEntry) {
historyEntry = this._setNewFileName(historyEntry);
this._setBackground(this.wallpaperlocation + historyEntry);
},
fetchNewWallpaper: function(callback) {
let _this = this;
this._requestRandomImageDesktopper(function(imageUrl){
_this._fetchFile(imageUrl, function(historyid, path) {
// insert file into history
_this.history.unshift(historyid);
_this._setBackground(_this.wallpaperlocation + historyid);
// call callback if given
if (callback) {
callback();
};
});
});
},
previewWallpaper: function(historyid) {
this.previewId = historyid;
let _this = this;
if (_this.timeout) {
return;
};
this.timeout = Mainloop.timeout_add(Mainloop.PRIORITY_DEFAULT, 250, function(){
_this.timeout = null;
_this._setBackground(_this.wallpaperlocation + _this.previewId);
return false;
});
},
resetWallpaper: function() {
},
getHistory: function() {
return this.history;
}
});