%PDF- %PDF-
| Direktori : /usr/share/gnome-shell/extensions/ding@rastersoft.com/app/ |
| Current File : //usr/share/gnome-shell/extensions/ding@rastersoft.com/app/thumbnails.js |
/* DING: Desktop Icons New Generation for GNOME Shell
*
* Copyright (C) 2021 Sergio Costas (rastersoft@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
'use strict';
imports.gi.versions.GnomeDesktop = '3.0';
const GnomeDesktop = imports.gi.GnomeDesktop;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
var ThumbnailLoader = class {
constructor(codePath) {
this._timeoutValue = 5000;
this._codePath = codePath;
this._thumbList = [];
this._thumbnailScriptWatch = null;
this._running = false;
this._thumbnailFactoryNormal = GnomeDesktop.DesktopThumbnailFactory.new(GnomeDesktop.DesktopThumbnailSize.NORMAL);
this._thumbnailFactoryLarge = GnomeDesktop.DesktopThumbnailFactory.new(GnomeDesktop.DesktopThumbnailSize.LARGE);
if (this._thumbnailFactoryLarge.generate_thumbnail_async) {
this._useAsyncAPI = true;
print('Detected async api for thumbnails');
} else {
this._useAsyncAPI = false;
print('Failed to detected async api for thumbnails');
}
}
_generateThumbnail(file, callback) {
this._thumbList.push([file, callback]);
if (!this._running) {
this._launchNewBuild();
}
}
_launchNewBuild() {
let file, callback;
do {
if (this._thumbList.length == 0) {
this._running = false;
return;
}
// if the file disappeared while waiting in the queue, don't refresh the thumbnail
[file, callback] = this._thumbList.shift();
if (file.file.query_exists(null)) {
if (this._thumbnailFactoryLarge.has_valid_failed_thumbnail(file.uri, file.modifiedTime)) {
if (callback) {
callback();
}
continue;
} else {
break;
}
}
} while (true);
this._running = true;
if (this._useAsyncAPI) {
this._createThumbnailAsync(file, callback);
} else {
this._createThumbnailSubprocess(file, callback);
}
}
_createThumbnailAsync(file, callback) {
let fileInfo = file.file.query_info('standard::content-type,time::modified', Gio.FileQueryInfoFlags.NONE, null);
this._doCancel = new Gio.Cancellable();
let modifiedTime = fileInfo.get_attribute_uint64('time::modified');
this._thumbnailFactoryLarge.generate_thumbnail_async(file.uri, fileInfo.get_content_type(), this._doCancel, (obj, res) => {
this._removeTimeout();
try {
let thumbnailPixbuf = obj.generate_thumbnail_finish(res);
this._thumbnailFactoryLarge.save_thumbnail_async(thumbnailPixbuf, file.uri, modifiedTime, this._doCancel, (obj, res) => {
obj.save_thumbnail_finish(res);
if (callback) {
callback();
}
this._launchNewBuild();
});
} catch (e) {
print(`Error while creating thumbnail: ${e.message}\n${e.stack}`);
this._createFailedThumbnailAsync(file, modifiedTime, callback);
}
});
this._timeoutID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, this._timeoutValue, () => {
print(`Timeout while generating thumbnail for ${file.displayName}`);
this._timeoutID = 0;
this._doCancel.cancel();
this._createFailedThumbnailAsync(file, modifiedTime, callback);
return false;
});
}
_createFailedThumbnailAsync(file, modifiedTime, callback) {
this._doCancel = new Gio.Cancellable();
this._thumbnailFactoryLarge.create_failed_thumbnail_async(file.uri, modifiedTime, this._doCancel, (obj, res) => {
try {
obj.create_failed_thumbnail_finish(res);
} catch (e) {
print(`Error while creating failed thumbnail: ${e.message}\n${e.stack}`);
}
if (callback) {
callback();
}
this._launchNewBuild();
});
}
_createThumbnailSubprocess(file, callback) {
let args = [];
args.push(GLib.build_filenamev([this._codePath, 'createThumbnail.js']));
args.push(file.path);
this._proc = new Gio.Subprocess({argv: args});
this._proc.init(null);
this._proc.wait_check_async(null, (source, result) => {
this._removeTimeout();
try {
let result2 = source.wait_check_finish(result);
if (result2) {
let status = source.get_status();
if (status == 0) {
if (callback) {
callback();
}
}
} else {
print(`Failed to generate thumbnail for ${file.displayName}`);
}
} catch (error) {
print(`Exception when generating thumbnail for ${file.displayName}: ${error}`);
}
this._launchNewBuild();
});
this._timeoutID = GLib.timeout_add(GLib.PRIORITY_DEFAULT, this._timeoutValue, () => {
print(`Timeout while generating thumbnail for ${file.displayName}`);
this._timeoutID = 0;
this._proc.force_exit();
this._thumbnailFactoryLarge.create_failed_thumbnail(file.uri, file.modifiedTime);
return false;
});
}
_removeTimeout() {
if (this._timeoutID != 0) {
GLib.source_remove(this._timeoutID);
this._timeoutID = 0;
}
}
getThumbnail(file, callback) {
try {
let thumbnail = this._thumbnailFactoryLarge.lookup(file.uri, file.modifiedTime);
if (thumbnail == null) {
thumbnail = this._thumbnailFactoryNormal.lookup(file.uri, file.modifiedTime);
if ((thumbnail == null) &&
!this._thumbnailFactoryLarge.has_valid_failed_thumbnail(file.uri, file.modifiedTime) &&
this._thumbnailFactoryLarge.can_thumbnail(file.uri, file.attributeContentType, file.modifiedTime)) {
this._generateThumbnail(file, callback);
}
}
return thumbnail;
} catch (error) {
print(`Error when asking for a thumbnail for ${file.displayName}: ${error.message}\n${error.stack}`);
}
return null;
}
};