[gnome-documents] collections: create special icons for collection items
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents] collections: create special icons for collection items
- Date: Wed, 16 Nov 2011 02:46:52 +0000 (UTC)
commit 899aa0a9fbf9c56f9d82343d90329e632b087fff
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Thu Nov 10 01:07:27 2011 -0500
collections: create special icons for collection items
We need to build an array of icons/thumbnails for documents in a
category:
- query for the first 4 documents matching nie:isPartOf for the category
- if the documents obtained are in the model already, just use those
pixbufs
- otherwise, load a cursor for the child document, and use the newly
created document's icon
src/documents.js | 311 ++++++++++++++++++++++++++++++----------------------
src/lib/gd-utils.c | 2 +-
src/query.js | 46 +++++++--
src/utils.js | 3 +
4 files changed, 224 insertions(+), 138 deletions(-)
---
diff --git a/src/documents.js b/src/documents.js
index 0038043..c489ebf 100644
--- a/src/documents.js
+++ b/src/documents.js
@@ -95,19 +95,26 @@ SingleItemJob.prototype = {
}
};
-function CollectionIconJob(collection) {
+function CollectionIconWatcher(collection) {
this._init(collection);
}
-CollectionIconJob.prototype = {
+CollectionIconWatcher.prototype = {
_init: function(collection) {
this._collection = collection;
- this._urns = [];
this._pixbuf = null;
+
+ this._start();
},
- run: function(callback) {
- this._callback = callback;
+ _clear: function() {
+ this._docConnections = {};
+ this._urns = [];
+ this._docs = [];
+ },
+
+ _start: function() {
+ this._clear();
let query = Global.queryBuilder.buildCollectionIconQuery(this._collection.id);
Global.connectionQueue.add(query.sparql, null, Lang.bind(this,
@@ -117,8 +124,6 @@ CollectionIconJob.prototype = {
cursor = object.query_finish(res);
} catch (e) {
log('Unable to query collection items ' + e.toString());
- this._emitCallback();
-
return;
}
@@ -134,8 +139,6 @@ CollectionIconJob.prototype = {
} catch (e) {
log('Unable to query collection items ' + e.toString());
cursor.close();
- this._emitCallback();
-
return;
}
@@ -153,12 +156,10 @@ CollectionIconJob.prototype = {
},
_onCollectionIconFinished: function() {
- if (!this._urns.length) {
- this._emitCallback();
+ if (!this._urns.length)
return;
- }
- this._docs = [];
+ // now this._urns has all the URNs of items contained in the collection
let toQuery = [];
this._urns.forEach(Lang.bind(this,
@@ -172,7 +173,7 @@ CollectionIconJob.prototype = {
this._toQueryRemaining = toQuery.length;
if (!this._toQueryRemaining) {
- this._createCollectionIcon();
+ this._allDocsReady();
return;
}
@@ -193,29 +194,53 @@ CollectionIconJob.prototype = {
_toQueryCollector: function() {
this._toQueryRemaining--;
+
if (!this._toQueryRemaining)
- this._createCollectionIcon();
+ this._allDocsReady();
+ },
+
+ _allDocsReady: function() {
+ this._docs.forEach(Lang.bind(this,
+ function(doc) {
+ let updateId = doc.connect('info-updated',
+ Lang.bind(this, this._createCollectionIcon));
+ this._docConnections[updateId] = doc;
+ }));
+
+ this._createCollectionIcon();
},
_createCollectionIcon: function() {
+ // now this._docs has an array of Document objects from which we will create the
+ // collection icon
let pixbufs = [];
this._docs.forEach(
function(doc) {
pixbufs.push(doc.pixbuf);
-
- if (!Global.documentManager.getItemById(doc.id))
- doc.destroy();
});
this._pixbuf = Gd.create_collection_icon(Utils.getIconSize(), pixbufs);
- this._emitCallback();
+ this._emitRefresh();
},
- _emitCallback: function() {
- this._callback(this._pixbuf);
+ _emitRefresh: function() {
+ this.emit('icon-updated', this._pixbuf);
+ },
+
+ destroy: function() {
+ for (id in this._docConnections) {
+ let doc = this._docConnections[id];
+ doc.disconnect(id);
+ }
+ },
+
+ refresh: function() {
+ this.destroy();
+ this._start();
}
};
+Signals.addSignalMethods(CollectionIconWatcher.prototype);
function DocCommon(cursor) {
this._init(cursor);
@@ -240,9 +265,12 @@ DocCommon.prototype = {
this.favorite = false;
this.shared = false;
+
this.collection = false;
+ this._collectionIconWatcher = null;
this.thumbnailed = false;
+ this._thumbPath = null;
this.populateFromCursor(cursor);
@@ -325,8 +353,127 @@ DocCommon.prototype = {
this.checkEffectsAndUpdateInfo();
},
+ _refreshCollectionIcon: function() {
+ if (!this._collectionIconWatcher) {
+ this._collectionIconWatcher = new CollectionIconWatcher(this);
+
+ this._collectionIconWatcher.connect('icon-updated', Lang.bind(this,
+ function(watcher, pixbuf) {
+ if (!pixbuf)
+ return;
+
+ this.pixbuf = pixbuf;
+ this.checkEffectsAndUpdateInfo();
+ }));
+ } else {
+ this._collectionIconWatcher.refresh();
+ }
+ },
+
refreshIcon: function() {
+ if (this._thumbPath) {
+ this._refreshThumbPath();
+ return;
+ }
+
this.updateIconFromType();
+
+ if (this.collection) {
+ this._refreshCollectionIcon();
+ return;
+ }
+
+ if (this._failedThumbnailing)
+ return;
+
+ if (!this._triedThumbnailing)
+ this._triedThumbnailing = true;
+
+ this._file = Gio.file_new_for_uri(this.uri);
+ this._file.query_info_async(Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH,
+ 0, 0, null,
+ Lang.bind(this, this._onFileQueryInfo));
+ },
+
+ _onFileQueryInfo: function(object, res) {
+ let info = null;
+ let haveNewIcon = false;
+
+ try {
+ info = object.query_info_finish(res);
+ } catch (e) {
+ log('Unable to query info for file at ' + this.uri + ': ' + e.toString());
+ this._failedThumbnailing = true;
+ return;
+ }
+
+ this._thumbPath = info.get_attribute_byte_string(Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH);
+ if (this._thumbPath) {
+ this._refreshThumbPath();
+ } else {
+ this.thumbnailed = false;
+
+ // try to create the thumbnail
+ Gd.queue_thumbnail_job_for_file_async(this._file,
+ Lang.bind(this, this._onQueueThumbnailJob));
+ }
+ },
+
+ _onQueueThumbnailJob: function(object, res) {
+ let thumbnailed = Gd.queue_thumbnail_job_for_file_finish(res);
+
+ if (!thumbnailed) {
+ this._failedThumbnailing = true;
+ return;
+ }
+
+ // get the new thumbnail path
+ this._file.query_info_async(Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH,
+ 0, 0, null,
+ Lang.bind(this, this._onThumbnailPathInfo));
+ },
+
+ _onThumbnailPathInfo: function(object, res) {
+ let info = null;
+
+ try {
+ info = object.query_info_finish(res);
+ } catch (e) {
+ log('Unable to query info for file at ' + this.uri + ': ' + e.toString());
+ this._failedThumbnailing = true;
+ return;
+ }
+
+ this._thumbPath = info.get_attribute_byte_string(Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH);
+ if (this._thumbPath)
+ this._refreshThumbPath();
+ else
+ this._failedThumbnailing = true;
+ },
+
+ _refreshThumbPath: function() {
+ let thumbFile = Gio.file_new_for_path(this._thumbPath);
+
+ thumbFile.read_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this,
+ function(object, res) {
+ try {
+ let stream = object.read_finish(res);
+ GdkPixbuf.Pixbuf.new_from_stream_at_scale_async(stream,
+ Utils.getIconSize(), Utils.getIconSize(),
+ true, null, Lang.bind(this,
+ function(object, res) {
+ try {
+ this.pixbuf = GdkPixbuf.Pixbuf.new_from_stream_finish(res);
+ this.thumbnailed = true;
+ this.checkEffectsAndUpdateInfo();
+ } catch (e) {
+ this._failedThumbnailing = true;
+ }
+ }));
+ } catch (e) {
+ this._failedThumbnailing = true;
+ }
+ }));
},
_updateInfoFromType: function() {
@@ -396,6 +543,11 @@ DocCommon.prototype = {
},
destroy: function() {
+ if (this._collectionIconWatcher) {
+ this._collectionIconWatcher.destroy();
+ this._collectionIconWatcher = null;
+ }
+
Global.settings.disconnect(this._refreshIconId);
Global.searchCategoryManager.disconnect(this._filterId);
},
@@ -419,8 +571,6 @@ DocCommon.prototype = {
};
Signals.addSignalMethods(DocCommon.prototype);
-const _FILE_ATTRIBUTES = 'thumbnail::path';
-
function LocalDocument(cursor) {
this._init(cursor);
}
@@ -429,7 +579,6 @@ LocalDocument.prototype = {
__proto__: DocCommon.prototype,
_init: function(cursor) {
- this._thumbPath = null;
this._failedThumbnailing = false;
this._triedThumbnailing = false;
@@ -450,110 +599,6 @@ LocalDocument.prototype = {
this.typeDescription = Gio.content_type_get_description(this.mimeType);
},
- _refreshThumbPath: function() {
- let thumbFile = Gio.file_new_for_path(this._thumbPath);
-
- thumbFile.read_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this,
- function(object, res) {
- try {
- let stream = object.read_finish(res);
- GdkPixbuf.Pixbuf.new_from_stream_at_scale_async(stream,
- Utils.getIconSize(), Utils.getIconSize(),
- true, null, Lang.bind(this,
- function(object, res) {
- try {
- this.pixbuf = GdkPixbuf.Pixbuf.new_from_stream_finish(res);
- this.thumbnailed = true;
- this.checkEffectsAndUpdateInfo();
- } catch (e) {
- this._failedThumbnailing = true;
- }
- }));
- } catch (e) {
- this._failedThumbnailing = true;
- }
- }));
- },
-
- refreshIcon: function() {
- if (this._thumbPath) {
- this._refreshThumbPath();
- return;
- }
-
- if (this._failedThumbnailing) {
- this.updateIconFromType();
- return;
- }
-
- if (!this._triedThumbnailing) {
- this.updateIconFromType();
- this._triedThumbnailing = true;
- }
-
- this._triedThumbnailing = true;
- this._file = Gio.file_new_for_uri(this.uri);
- this._file.query_info_async(_FILE_ATTRIBUTES,
- 0, 0, null,
- Lang.bind(this, this._onFileQueryInfo));
- },
-
- _onFileQueryInfo: function(object, res) {
- let info = null;
- let haveNewIcon = false;
-
- try {
- info = object.query_info_finish(res);
- } catch (e) {
- log('Unable to query info for file at ' + this.uri + ': ' + e.toString());
- this._failedThumbnailing = true;
- return;
- }
-
- this._thumbPath = info.get_attribute_byte_string(Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH);
- if (this._thumbPath) {
- this._refreshThumbPath();
- } else {
- this.thumbnailed = false;
-
- // try to create the thumbnail
- Gd.queue_thumbnail_job_for_file_async(this._file,
- Lang.bind(this, this._onQueueThumbnailJob));
- }
- },
-
- _onQueueThumbnailJob: function(object, res) {
- let thumbnailed = Gd.queue_thumbnail_job_for_file_finish(res);
-
- if (!thumbnailed) {
- this._failedThumbnailing = true;
- return;
- }
-
- // get the new thumbnail path
- this._file.query_info_async(Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH,
- 0, 0, null,
- Lang.bind(this, this._onThumbnailPathInfo));
- },
-
- _onThumbnailPathInfo: function(object, res) {
- let info = null;
-
- try {
- info = object.query_info_finish(res);
- } catch (e) {
- log('Unable to query info for file at ' + this.uri + ': ' + e.toString());
- this._failedThumbnailing = true;
- return;
- }
-
- this._thumbPath = info.get_attribute_byte_string(Gio.FILE_ATTRIBUTE_THUMBNAIL_PATH);
- if (this._thumbPath)
- this._refreshThumbPath();
- else
- this._failedThumbnailing = true;
- },
-
loadPreview: function(cancellable, callback) {
Gd.pdf_loader_load_uri_async(this.uri, cancellable, Lang.bind(this,
function(source, res) {
@@ -578,6 +623,9 @@ GoogleDocument.prototype = {
__proto__: DocCommon.prototype,
_init: function(cursor) {
+ this._triedThumbnailing = true;
+ this._failedThumbnailing = true;
+
DocCommon.prototype._init.call(this, cursor);
// overridden
@@ -775,7 +823,7 @@ DocumentManager.prototype = {
return this._pixbufFrame;
},
- addDocumentFromCursor: function(cursor) {
+ createDocumentFromCursor: function(cursor) {
let identifier = cursor.get_string(Query.QueryColumns.IDENTIFIER)[0];
let doc;
@@ -784,6 +832,11 @@ DocumentManager.prototype = {
else
doc = new LocalDocument(cursor);
+ return doc;
+ },
+
+ addDocumentFromCursor: function(cursor) {
+ let doc = this.createDocumentFromCursor(cursor);
this.addItem(doc);
this._model.documentAdded(doc);
diff --git a/src/lib/gd-utils.c b/src/lib/gd-utils.c
index 35c4fec..34af37e 100644
--- a/src/lib/gd-utils.c
+++ b/src/lib/gd-utils.c
@@ -520,7 +520,7 @@ gd_create_collection_icon (gint base_size,
{
pix = l->data;
pix_width = gdk_pixbuf_get_width (pix);
- pix_height = gdk_pixbuf_get_width (pix);
+ pix_height = gdk_pixbuf_get_height (pix);
scale_size = MIN (pix_width, pix_height);
diff --git a/src/query.js b/src/query.js
index 224c3f5..fcf0e4c 100644
--- a/src/query.js
+++ b/src/query.js
@@ -39,6 +39,11 @@ const QueryColumns = {
SHARED: 11
};
+const QueryFlags = {
+ NONE: 0,
+ UNFILTERED: 1 << 0
+};
+
function Query(sparql) {
this._init(sparql);
}
@@ -129,22 +134,28 @@ QueryBuilder.prototype = {
return sparql;
},
- _buildQueryInternal: function(global) {
+ _buildQueryInternal: function(global, flags) {
let globalSparql =
'WHERE { ?urn a rdfs:Resource ' +
this._buildOptional();
if (global) {
+ if ((flags & QueryFlags.UNFILTERED) == 0)
+ globalSparql +=
+ Global.searchCategoryManager.getWhere() +
+ Global.collectionManager.getWhere() +
+ this._buildFilterString();
+
globalSparql +=
- Global.searchCategoryManager.getWhere() +
- Global.collectionManager.getWhere() +
- this._buildFilterString() +
' } ' +
'ORDER BY DESC (?mtime)' +
('LIMIT %d OFFSET %d').format(Global.offsetController.getOffsetStep(),
Global.offsetController.getOffset());
} else {
- globalSparql += this._buildFilterString() + ' }';
+ if ((flags & QueryFlags.UNFILTERED) == 0)
+ globalSparql += this._buildFilterString();
+
+ globalSparql += ' }';
}
let sparql =
@@ -165,15 +176,21 @@ QueryBuilder.prototype = {
return sparql;
},
- buildSingleQuery: function(resource) {
- let sparql = this._buildQueryInternal(false);
+ buildSingleQuery: function() {
+ let resource = arguments[0];
+ let flags = QueryFlags.NONE;
+
+ if (arguments.length == 2)
+ flags = arguments[1];
+
+ let sparql = this._buildQueryInternal(false, flags);
sparql = sparql.replace('?urn', '<' + resource + '>', 'g');
return new Query(sparql);
},
buildGlobalQuery: function() {
- return new Query(this._buildQueryInternal(true));
+ return new Query(this._buildQueryInternal(true, QueryFlags.NONE));
},
buildCountQuery: function() {
@@ -184,5 +201,18 @@ QueryBuilder.prototype = {
'}';
return new Query(sparql);
+ },
+
+ // queries for all the items which are part of the given collection
+ buildCollectionIconQuery: function(resource) {
+ let sparql =
+ ('SELECT ' +
+ '?urn ' +
+ 'tracker:coalesce(nfo:fileLastModified(?urn), nie:contentLastModified(?urn)) AS ?mtime ' +
+ 'WHERE { ?urn nie:isPartOf ?collUrn } ' +
+ 'ORDER BY DESC (?mtime)' +
+ 'LIMIT 4').replace('?collUrn', '<' + resource + '>');
+
+ return new Query(sparql);
}
};
diff --git a/src/utils.js b/src/utils.js
index cd7f946..3fda1a3 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -19,6 +19,7 @@
*
*/
+const Gd = imports.gi.Gd;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
@@ -46,6 +47,8 @@ function iconFromRdfType(type) {
iconName = 'x-office-spreadsheet';
else if (type.indexOf('nfo#Presentation') != -1)
iconName = 'x-office-presentation';
+ else if (type.indexOf('nfo#DataContainer') != -1)
+ return Gd.create_collection_icon(getIconSize(), []);
else
iconName = 'x-office-document';
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]