-
-
Notifications
You must be signed in to change notification settings - Fork 54
/
carousel.js
298 lines (252 loc) · 11.2 KB
/
carousel.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
// Bing Wallpaper GNOME extension
// Copyright (C) 2017-2023 Michael Carroll
// This extension is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// See the GNU General Public License, version 3 or later for details.
// Based on GNOME shell extension NASA APOD by Elia Argentieri https://github.com/Elinvention/gnome-shell-extension-nasa-apod
const { Gtk, Gdk, GdkPixbuf, Gio, GLib } = imports.gi;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const Utils = Me.imports.utils;
const Gettext = imports.gettext.domain('BingWallpaper');
const _ = Gettext.gettext;
const default_dimensions = [30, 30, 1650, 800]; // TODO: pull from and save dimensions to settings, but perhaps verify that dimensions are ok
const GALLERY_THUMB_WIDTH = 320;
const GALLERY_THUMB_HEIGHT = 180;
var Carousel = class Carousel {
constructor(settings, button = null, callbackfunc = null, prefs_flowbox = null) {
//create_gallery(widget, settings);
this.settings = settings;
this.button = button;
this.callbackfunc = callbackfunc;
this.flowBox = null;
this.window = null;
this.imageList = Utils.imageListSortByDate(Utils.getImageList(this.settings)).reverse(); // get images and reverse order
this.searchEntry = null;
this.log('create carousel...');
if (!prefs_flowbox) {
[this.window, this.flowBox] = this._create_gallery_window(_('Bing Wallpaper Gallery'), default_dimensions);
if (Gtk.get_major_version() < 4)
this.window.show_all();
else
this.window.show();
//this.window.connect('destroy', this._enable_button);
}
else {
this.flowBox = prefs_flowbox;
}
if (Gtk.get_major_version() < 4) {
this._create_gallery();
}
else {
this.flowBox.insert(this._create_placeholder_item(), -1);
}
}
_enable_button() {
if (this.button) {
this.button.set_sensitive(state);
}
}
_create_gallery_window(title, dimensions) {
let buildable = new Gtk.Builder();
let win = new Gtk.Window();
let flowBox;
win.set_default_size(dimensions[2], dimensions[3]);
win.set_title(title);
if (Gtk.get_major_version() < 4) {
buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel.ui', ['carouselScrollable']);
flowBox = buildable.get_object('carouselFlowBox');
win.add(buildable.get_object('carouselScrollable'));
}
else {
buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel4.ui', ['carouselViewPort']);
flowBox = buildable.get_object('carouselFlowBox');
win.set_child(buildable.get_object('carouselScrollable'));
}
return [win, flowBox];
}
_create_gallery() {
Utils.randomIntervals.forEach((seconds, i) => {
let item = this._create_random_item(seconds, Utils.randomIntervalsTitle[i]);
if (Gtk.get_major_version() < 4)
this.flowBox.add(item);
else
this.flowBox.insert(item, -1);
});
this.imageList.forEach((image) => {
let item = this._create_gallery_item(image);
if (Gtk.get_major_version() < 4)
this.flowBox.add(item);
else
this.flowBox.insert(item, -1);
});
}
_create_gallery_item(image) {
let buildable = new Gtk.Builder();
// grab appropriate object from UI file
if (Gtk.get_major_version() < 4)
buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel.ui', ["flowBoxChild"]);
else
buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel4.ui', ["flowBoxChild"]);
// assign variables to the UI objects we've just loaded
let galleryImage = buildable.get_object('galleryImage');
let filename = Utils.imageToFilename(this.settings, image);
let viewButton = buildable.get_object('viewButton');
let applyButton = buildable.get_object('applyButton');
let infoButton = buildable.get_object('infoButton');
let deleteButton = buildable.get_object('deleteButton');
let favButton = buildable.get_object('favButton');
let unfavButton = buildable.get_object('unfavButton');
if (Utils.isFavourite(image)) {
favButton.set_visible(false);
this.log('image is favourited');
}
else {
unfavButton.set_visible(false);
}
try {
this._load_image(galleryImage, filename);
}
catch (e) {
if (Gtk.get_major_version() < 4) {
galleryImage.set_from_icon_name('image-missing', '64x64');
}
else {
galleryImage.set_from_icon_name('image-missing');
}
galleryImage.set_icon_size = 2; // Gtk.GTK_ICON_SIZE_LARGE;
this.log('create_gallery_image: '+e);
}
galleryImage.set_tooltip_text(image.copyright);
// set up actions for when a image button is clicked
viewButton.connect('clicked', () => {
Utils.openInSystemViewer(filename);
});
applyButton.connect('clicked', () => {
this.settings.set_string('selected-image', Utils.getImageUrlBase(image));
this.log('gallery selected '+Utils.getImageUrlBase(image));
});
infoButton.connect('clicked', () => {
Utils.openInSystemViewer(image.copyrightlink, false);
this.log('info page link opened '+image.copyrightlink);
});
deleteButton.connect('clicked', (widget) => {
this.log('Delete requested for '+filename);
Utils.deleteImage(filename);
Utils.cleanupImageList(this.settings);
widget.get_parent().get_parent().set_visible(false); // bit of a hack
if (this.callbackfunc)
this.callbackfunc();
});
// button is unchecked, so we want to make the checked one visible
favButton.connect('clicked', (widget) => {
this.log('favourited '+Utils.getImageUrlBase(image));
widget.set_visible(false);
unfavButton.set_visible(true);
Utils.setImageFavouriteStatus(this.settings, image.urlbase, true);
});
// button is checked, so we want to make the unchecked one visible
unfavButton.connect('clicked', (widget) => {
this.log('unfavourited '+Utils.getImageUrlBase(image));
widget.set_visible(false);
favButton.set_visible(true);
Utils.setImageFavouriteStatus(this.settings, image.urlbase, false);
});
let item = buildable.get_object('flowBoxChild');
return item;
}
_create_random_item(seconds, title) {
let buildable = new Gtk.Builder();
// grab appropriate object from UI file
if (Gtk.get_major_version() < 4) {
buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel.ui', ["flowBoxRandom"]);
}
else {
buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel4.ui', ["flowBoxRandom"]);
}
let randomLabel = buildable.get_object('randomLabel');
randomLabel.set_text(title);
let filename = 'random';
let applyButton = buildable.get_object('randomButton');
applyButton.connect('clicked', (widget) => {
this.settings.set_string('selected-image', filename);
this.settings.set_int('random-interval', seconds);
this.log('gallery selected random with interval '+seconds);
});
let item = buildable.get_object('flowBoxRandom');
return item;
}
_create_placeholder_item() {
let buildable = new Gtk.Builder();
this.flowBox.set_max_children_per_line(1);
// grab appropriate object from UI file
if (Gtk.get_major_version() >= 4) {
buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel4.ui', ["flowBoxPlaceholder"]);
}
else {
return null;
}
let loadButton = buildable.get_object('loadButton');
loadButton.connect('clicked', (widget) => {
this.flowBox.remove(widget.get_parent());
this.flowBox.set_max_children_per_line(2);
this._create_gallery();
});
let item = buildable.get_object('flowBoxPlaceholder');
return item;
}
_load_image(galleryImage, filename) {
let thumb_path = Utils.getWallpaperDir(this.settings)+'.thumbs/';
let thumb_dir = Gio.file_new_for_path(thumb_path);
let save_thumbs = !this.settings.get_boolean('delete-previous') && this.settings.get_boolean('create-thumbs'); // create thumbs only if not deleting previous and thumbs are enabled
if (!thumb_dir.query_exists(null)) {
thumb_dir.make_directory_with_parents(null);
}
let image_file = Gio.file_new_for_path(filename);
// load gallery image or create new thumbnail if it doesn't
if (!image_file.query_exists(null)){
this._set_blank_image(galleryImage);
}
else {
let image_thumb_path = thumb_path + image_file.get_basename();
let image_thumb = Gio.file_new_for_path(image_thumb_path);
try {
let pixbuf;
// use thumbnail if available
if (image_thumb.query_exists(null)) {
pixbuf = GdkPixbuf.Pixbuf.new_from_file(image_thumb_path);
}
else { // save changed thumbnail significantly speeds up gallery loading, but costs some addtional disk space
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(filename, GALLERY_THUMB_WIDTH, GALLERY_THUMB_HEIGHT);
if (save_thumbs)
pixbuf.savev(image_thumb_path,'jpeg',['quality'], ['90']);
}
if (Gtk.get_major_version() < 4) {
galleryImage.set_from_pixbuf(pixbuf);
}
else {
galleryImage.set_pixbuf(pixbuf);
}
}
catch (e) {
this._set_blank_image(galleryImage);
this.log('create_gallery_image: '+e);
}
}
}
_set_blank_image(galleryImage) {
if (Gtk.get_major_version() < 4) {
galleryImage.set_from_icon_name('image-missing', '64x64');
galleryImage.set_icon_size = 3; // Gtk.GTK_ICON_SIZE_LARGE;
}
else {
//galleryImage.set_from_icon_name('image-missing');
//galleryImage.set_icon_size = 2; // Gtk.GTK_ICON_SIZE_LARGE;
}
}
log(msg) {
if (this.settings.get_boolean('debug-logging'))
print("BingWallpaper extension: " + msg); // disable to keep the noise down in journal
}
};