[sushi] fallbackRenderer: load file information from JS
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sushi] fallbackRenderer: load file information from JS
- Date: Tue, 18 Jun 2019 07:04:36 +0000 (UTC)
commit 68103b79fa43f6e9063a2661e43784b5e4c7d42a
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Mon Jun 17 23:59:41 2019 -0700
fallbackRenderer: load file information from JS
Instead of requiring a GObject class for this.
src/libsushi/meson.build | 2 -
src/libsushi/sushi-file-loader.c | 698 ---------------------------------------
src/libsushi/sushi-file-loader.h | 74 -----
src/ui/fallbackRenderer.js | 231 +++++++++++--
4 files changed, 196 insertions(+), 809 deletions(-)
---
diff --git a/src/libsushi/meson.build b/src/libsushi/meson.build
index 1bd7e65..b9d9d97 100644
--- a/src/libsushi/meson.build
+++ b/src/libsushi/meson.build
@@ -1,6 +1,5 @@
libsushi_c = [
'sushi-cover-art.c',
- 'sushi-file-loader.c',
'sushi-font-loader.c',
'sushi-font-widget.c',
'sushi-media-bin.c',
@@ -10,7 +9,6 @@ libsushi_c = [
libsushi_headers = [
'sushi-cover-art.h',
- 'sushi-file-loader.h',
'sushi-font-loader.h',
'sushi-font-widget.h',
'sushi-media-bin.h',
diff --git a/src/ui/fallbackRenderer.js b/src/ui/fallbackRenderer.js
index 3c342d2..bedca5d 100644
--- a/src/ui/fallbackRenderer.js
+++ b/src/ui/fallbackRenderer.js
@@ -23,10 +23,167 @@
*
*/
-const {Gio, GObject, Gtk, Pango, Sushi} = imports.gi;
+const {Gio, GLib, GObject, Gtk, Pango} = imports.gi;
+const Gettext = imports.gettext;
const Renderer = imports.ui.renderer;
+function _getDeepCountAttrs() {
+ return [
+ Gio.FILE_ATTRIBUTE_STANDARD_SIZE,
+ Gio.FILE_ATTRIBUTE_STANDARD_TYPE,
+ Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ Gio.FILE_ATTRIBUTE_STANDARD_NAME,
+ Gio.FILE_ATTRIBUTE_UNIX_INODE
+ ].join(',');
+}
+
+function _getLoaderAttrs() {
+ return [
+ Gio.FILE_ATTRIBUTE_STANDARD_ICON,
+ Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+ Gio.FILE_ATTRIBUTE_STANDARD_SIZE,
+ Gio.FILE_ATTRIBUTE_STANDARD_TYPE,
+ Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+ Gio.FILE_ATTRIBUTE_TIME_MODIFIED
+ ].join(',');
+}
+
+const loadFile = function(_fileToLoad, _cancellable, _updateCallback) {
+ let _seenInodes = new Set();
+ let _subDirectories = [];
+ let _enumerator = null;
+ let _file = null;
+
+ let _state = { fileInfo: null,
+ directoryItems: 0,
+ fileItems: 0,
+ loading: true,
+ totalItems: 0,
+ totalSize: 0,
+ unreadableItems: 0 }
+ let _timeoutId = 0;
+
+ function _cleanup() {
+ if (_enumerator && !_enumerator.is_closed())
+ _enumerator.close_async(0, null, null);
+ }
+
+ function _deepCountLoad() {
+ _file.enumerate_children_async(
+ _getDeepCountAttrs(), Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
+ GLib.PRIORITY_LOW, _cancellable,
+ (f, res) => {
+ try {
+ _enumerator = _file.enumerate_children_finish(res);
+ } catch(e) {
+ _state.unreadableItems++;
+ _deepCountNext();
+ return;
+ }
+
+ _enumerator.next_files_async(
+ 100, GLib.PRIORITY_LOW, _cancellable,
+ _deepCountMoreFiles);
+ });
+ }
+
+ function _deepCountMoreFiles(en, res) {
+ let files = [];
+ try {
+ files = _enumerator.next_files_finish(res);
+ } catch (e) {
+ if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
+ return;
+ }
+
+ files.forEach(_deepCountOne);
+
+ if (files.length) {
+ _enumerator.next_files_async(
+ 100, GLib.PRIORITY_LOW, _cancellable,
+ _deepCountMoreFiles);
+ } else {
+ _cleanup();
+ _deepCountNext();
+ }
+ }
+
+ function _deepCountNext() {
+ _file = _subDirectories.shift();
+ if (_file) {
+ _deepCountLoad();
+ } else {
+ _cleanup();
+ _state.loading = false;
+ }
+
+ _queueUpdate();
+ }
+
+ function _deepCountOne(info) {
+ let inode = info.get_attribute_uint64(Gio.FILE_ATTRIBUTE_UNIX_INODE);
+ let isSeen = false;
+ if (inode) {
+ isSeen = _seenInodes.has(inode);
+ if (!isSeen)
+ _seenInodes.add(inode);
+ }
+
+ let fileType = info.get_file_type();
+ if (fileType == Gio.FileType.DIRECTORY) {
+ _state.directoryItems++;
+ _subDirectories.unshift(_file.get_child(info.get_name()));
+ } else {
+ _state.fileItems++;
+ }
+
+ if (!isSeen && info.has_attribute(Gio.FILE_ATTRIBUTE_STANDARD_SIZE))
+ _state.totalSize += info.get_size();
+ }
+
+ function _queueUpdate() {
+ if (_timeoutId != 0)
+ return;
+
+ _timeoutId = GLib.timeout_add(0, 300, () => {
+ _timeoutId = 0;
+ _sendUpdate();
+ return false;
+ });
+ }
+
+ function _unqueueUpdate() {
+ if (_timeoutId != 0)
+ GLib.source_remove(_timeoutId);
+ }
+
+ function _sendUpdate() {
+ _updateCallback(_state);
+ }
+
+ _cancellable.connect(_unqueueUpdate);
+
+ _file = _fileToLoad;
+ _file.query_info_async(_getLoaderAttrs(), 0, 0, _cancellable, (f, res) => {
+ try {
+ _state.fileInfo = _file.query_info_finish(res);
+ } catch (e) {
+ if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
+ logError(e, `Unable to query info for file ${_file.get_uri()}`);
+ return;
+ }
+
+ let fileType = _state.fileInfo.get_file_type();
+ if (fileType == Gio.FileType.DIRECTORY)
+ _deepCountLoad();
+ else
+ _state.loading = false;
+
+ _sendUpdate();
+ });
+};
+
var FallbackRenderer = GObject.registerClass({
Implements: [Renderer.Renderer],
Properties: {
@@ -42,9 +199,8 @@ var FallbackRenderer = GObject.registerClass({
super._init({ orientation: Gtk.Orientation.HORIZONTAL,
spacing: 6 });
- this._fileLoader = new Sushi.FileLoader();
- this._fileLoader.file = file;
- this._fileLoaderId = this._fileLoader.connect('notify', this._onFileInfoChanged.bind(this));
+ this._cancellable = new Gio.Cancellable();
+ loadFile(file, this._cancellable, this._onFileInfoUpdated.bind(this));
this._image = new Gtk.Image();
this.pack_start(this._image, false, false, 0);
@@ -69,6 +225,7 @@ var FallbackRenderer = GObject.registerClass({
this._spinner = new Gtk.Spinner();
hbox.pack_start(this._spinner, false, false, 0);
this._spinner.start();
+ this._spinner.show();
this._typeLabel = new Gtk.Label();
this._typeLabel.set_halign(Gtk.Align.START);
@@ -82,42 +239,54 @@ var FallbackRenderer = GObject.registerClass({
this._dateLabel.set_halign(Gtk.Align.START);
vbox.pack_start(this._dateLabel, false, false, 0);
- this._applyLabels();
-
this.connect('destroy', this._onDestroy.bind(this));
this.isReady();
}
- _applyLabels() {
- let titleStr =
- '<b><big>' +
- ((this._fileLoader.name) ? (this._fileLoader.name) : (this._fileLoader.file.get_basename()))
- + '</big></b>';
+ _applyLabels(state) {
+ let titleStr = `<b><big>${state.fileInfo.get_display_name()}</big></b>`;
this._titleLabel.set_markup(titleStr);
- if (this._fileLoader.get_file_type() != Gio.FileType.DIRECTORY) {
- let typeStr =
- '<small><b>' + _("Type") + ' </b>' +
- ((this._fileLoader.contentType) ? (this._fileLoader.contentType) : (_("Loading…")))
- + '</small>';
+ if (state.fileInfo.get_file_type() != Gio.FileType.DIRECTORY) {
+ let contentType = state.fileInfo.get_content_type();
+ let typeDescr = Gio.content_type_get_description(contentType);
+ let typeStr = '<small><b>' + _("Type") + ' </b>' +
+ `${typeDescr}</small>`;
this._typeLabel.set_markup(typeStr);
} else {
this._typeLabel.hide();
}
- let sizeStr =
- '<small><b>' + _("Size") + ' </b>' +
- ((this._fileLoader.size) ? (this._fileLoader.size) : (_("Loading…")))
- + '</small>';
+ let sizeFormatted;
+ if (state.fileInfo.get_file_type() != Gio.FileType.DIRECTORY) {
+ sizeFormatted = GLib.format_size(state.fileInfo.get_size());
+ } else if (state.totalSize > 0) {
+ let itemsStr = Gettext.ngettext(
+ "%d item", "%d items",
+ state.fileItems + state.directoryItems).
+ format(state.fileItems + state.directoryItems);
+ sizeFormatted = `${GLib.format_size(state.totalSize)}, ${itemsStr}`;
+ } else {
+ sizeFormatted = _("Empty Folder");
+ }
+
+ let sizeStr = '<small><b>' + _("Size") + ' </b>' +
+ `${sizeFormatted}</small>`;
this._sizeLabel.set_markup(sizeStr);
+ let date = GLib.DateTime.new_from_timeval_local(state.fileInfo.get_modification_time());
+ let dateFormatted = date.format('%x %X');
let dateStr =
'<small><b>' + _("Modified") + ' </b>' +
- ((this._fileLoader.time) ? (this._fileLoader.time) : (_("Loading…")))
- + '</small>';
+ `${dateFormatted}</small>`;
this._dateLabel.set_markup(dateStr);
}
+ _applyIcon(state) {
+ let icon = state.fileInfo.get_icon();
+ this._updateIcon(icon);
+ }
+
_updateIcon(icon) {
let iconTheme = Gtk.IconTheme.get_default();
let iconInfo = iconTheme.lookup_by_gicon_for_scale(icon, 256,
@@ -133,26 +302,18 @@ var FallbackRenderer = GObject.registerClass({
}
}
- _onFileInfoChanged() {
- if (!this._fileLoader.get_loading()) {
+ _onFileInfoUpdated(state) {
+ if (!state.loading) {
this._spinner.stop();
this._spinner.hide();
}
- if (this._fileLoader.icon)
- this._updateIcon(this._fileLoader.icon);
-
- this._applyLabels();
+ this._applyIcon(state);
+ this._applyLabels(state);
}
_onDestroy() {
- if (this._fileLoader) {
- this._fileLoader.disconnect(this._fileLoaderId);
- this._fileLoaderId = 0;
-
- this._fileLoader.stop();
- this._fileLoader = null;
- }
+ this._cancellable.cancel();
}
get resizable() {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]