diff --git a/.gitignore b/.gitignore index 6fdfd04..0ffbf47 100644 --- a/.gitignore +++ b/.gitignore @@ -30,13 +30,17 @@ po/Makefile.in.in src/.libs src/*.c src/*.stamp +examples/*.c +examples/*.stamp +examples/*.deps +examples/*.libs src/zeitgeist src/bluebird test/direct/where-clause-test data/ontology/*.py query-operators-test -src/ontology.vala -src/ontology-uris.vala +ontology.vala +ontology-uris.vala data/org.gnome.zeitgeist.service extensions/.deps extensions/.libs @@ -59,7 +63,6 @@ extensions/fts++/zeitgeist-fts test/direct/marshalling test/dbus/__pycache__ test/direct/table-lookup-test -src/zeitgeist-engine.vapi src/zeitgeist-engine.h py-compile python/_ontology.py @@ -69,9 +72,24 @@ mimetype-test marshalling-test test/direct/datamodel-test libzeitgeist/*.c +examples/get-events-with-id +examples/monitor-events +examples/most-recent-events +examples/data-source-stuff +libzeitgeist/libzeitgeist-2.0.pc +libzeitgeist/zeitgeist-2.0.pc +gtk-doc.make +doc/libzeitgeist/zeitgeist-2.0-*.txt +doc/libzeitgeist/zeitgeist-2.0.types +doc/libzeitgeist/zeitgeist-2.0-scan.c +doc/libzeitgeist/devhelp +doc/libzeitgeist/valadoc +doc/libzeitgeist/gtkdoc *.o *.la *.stamp *.lo *.pyc *.swp +*.h +*.vapi diff --git a/Makefile.am b/Makefile.am index 824aa91..7b5731a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,11 +1,13 @@ NULL = SUBDIRS = \ + libzeitgeist \ src \ extensions \ data \ python \ test \ + examples \ po \ doc \ $(NULL) @@ -16,7 +18,9 @@ zeitgeistdoc_DATA = \ NEWS \ $(NULL) -DISTCHECK_CONFIGURE_FLAGS = --with-session-bus-services-dir="\$(datadir)"/dbus-1/services +DISTCHECK_CONFIGURE_FLAGS = \ + --with-session-bus-services-dir="\$(datadir)"/dbus-1/services \ + --enable-gtk-doc EXTRA_DIST = \ $(zeitgeistdoc_DATA) \ diff --git a/configure.ac b/configure.ac index bc065ce..607d57d 100644 --- a/configure.ac +++ b/configure.ac @@ -29,6 +29,7 @@ AC_SUBST(LDFLAGS) GLIB_REQUIRED=2.26.0 SQLITE_REQUIRED=3.7 +VALADOC_REQUIRED=0.2 ZEITGEIST_REQUIRED="glib-2.0 >= $GLIB_REQUIRED gobject-2.0 >= $GLIB_REQUIRED @@ -43,6 +44,8 @@ AC_SUBST(ZEITGEIST_LIBS) AC_CONFIG_FILES([ Makefile src/Makefile + libzeitgeist/Makefile + libzeitgeist/zeitgeist-2.0.pc extensions/Makefile extensions/fts++/Makefile extensions/fts++/test/Makefile @@ -52,7 +55,9 @@ AC_CONFIG_FILES([ test/Makefile test/dbus/Makefile test/direct/Makefile + examples/Makefile doc/Makefile + doc/libzeitgeist/Makefile po/Makefile.in ]) @@ -136,12 +141,46 @@ fi LIBZEITGEIST_VERSION_MAJOR="2" LIBZEITGEIST_VERSION_MINOR="0" LIBZEITGEIST_VERSION_PATCH="0" -LIBZEITGEIST_VERSION="$(LIBZEITGEIST_VERSION_MAJOR).$(LIBZEITGEIST_VERSION_MINOR).$(LIBZEITGEIST_VERSION_PATCH)" +LIBZEITGEIST_VERSION="$LIBZEITGEIST_VERSION_MAJOR.$LIBZEITGEIST_VERSION_MINOR.$LIBZEITGEIST_VERSION_PATCH" AC_SUBST(LIBZEITGEIST_VERSION_MAJOR) AC_SUBST(LIBZEITGEIST_VERSION_MINOR) AC_SUBST(LIBZEITGEIST_VERSION_PATCH) AC_SUBST(LIBZEITGEIST_VERSION) +# Before making a release, the ZEITGEIST_LT_VERSION string should be updated. +# The string is of the form C:R:A. +# - If interfaces have been changed or added, but binary compatibility has +# been preserved, change to C+1:0:A+1 +# - If binary compatibility has been broken (eg removed or changed interfaces) +# change to C+1:0:0 +# - If the interface is the same as the previous version, change to C:R+1:A +LIBZEITGEIST_LT_CURRENT=1 +LIBZEITGEIST_LT_REV=0 +LIBZEITGEIST_LG_AGE=0 +LIBZEITGEIST_LT_VERSION="$LIBZEITGEIST_LT_CURRENT:$LIBZEITGEIST_LT_REV:$LIBZEITGEIST_LT_AGE" +AC_SUBST(LIBZEITGEIST_LT_VERSION) + +################################################# +# Docs +################################################# + +AC_ARG_ENABLE([docs], + AS_HELP_STRING([--enable-docs], [Enable documentation generation]), + [enable_docs=$enableval], [enable_docs="yes"]) # FIXME: change to no + +found_valadoc=no +AS_IF([test "x$enable_docs" != "xno"], [ + AC_PATH_PROG(VALADOC, valadoc, :) + AS_IF([test -x "$VALADOC"], [ + found_valadoc=yes + AC_SUBST(VALADOC) + ], [ + AS_IF([test "x$enable_docs" == "xyes"], AC_MSG_ERROR([Unable to find valadoc])) + ]) +]) + +AM_CONDITIONAL(ENABLE_DOCS, test "x$found_valadoc" = "xyes") + ################################################# # Ontology parsing dependencies ################################################# @@ -180,5 +219,6 @@ ${PACKAGE}-${VERSION} Other build options: SQL debugging: ${explain_queries} + libzeitgeist docs: ${enable_docs} EOF diff --git a/data/ontology2code b/data/ontology2code index 3375e04..a5a230e 100755 --- a/data/ontology2code +++ b/data/ontology2code @@ -301,7 +301,7 @@ class ValaSerializer(GenericSerializer): # Convert docstring to gtk-doc style C comment doc = doc.replace('\n', '\n *') - doc = '/**\n * %s:\n *\n * %s%s\n * \n * %s\n */' % ( + doc = '/**\n * %s:\n *\n * %s%s\n *\n * %s\n */' % ( symbol.name, doc_prefix, uri_link, doc) return doc @@ -364,9 +364,9 @@ class OntologyCodeGenerator: self._python_serializer.dump() def generate_vala(self): - self._write_file('src/ontology-uris.vala.in', 'src/ontology-uris.vala', + self._write_file('libzeitgeist/ontology-uris.vala.in', 'libzeitgeist/ontology-uris.vala', self._vala_serializer.dump_uris, 'vala') - self._write_file('src/ontology.vala.in', 'src/ontology.vala', + self._write_file('libzeitgeist/ontology.vala.in', 'libzeitgeist/ontology.vala', self._vala_serializer.dump_symbols, 'vala') def _write_file(self, tplfilename, outfilename, content_generator, _type): diff --git a/doc/Makefile.am b/doc/Makefile.am index a1f6940..74b2aa7 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,3 +1,9 @@ +NULL = + +SUBDIRS = \ + libzeitgeist \ + $(NULL) + man_MANS = \ zeitgeist-daemon.1 diff --git a/doc/libzeitgeist/Makefile.am b/doc/libzeitgeist/Makefile.am new file mode 100644 index 0000000..1e73b99 --- /dev/null +++ b/doc/libzeitgeist/Makefile.am @@ -0,0 +1,45 @@ +NULL = + +if ENABLE_DOCS + +# valadoc in Ubuntu doesn't find it vala-0.16/vapi +VALADOC_FLAGS = \ + --force \ + --vapidir $(top_srcdir)/libzeitgeist \ + --vapidir /usr/share/vala-0.16/vapi/ \ + --pkg gio-2.0 \ + --pkg sqlite3 \ + --basedir $(top_srcdir)/libzeitgeist \ + --package-name libzeitgeist2 \ + --package-version $(PACKAGE_VERSION) \ + $(wildcard $(top_srcdir)/libzeitgeist/*.vala) \ + $(NULL) + +valadoc: + $(VALADOC) \ + -o valadoc \ + $(VALADOC_FLAGS) \ + $(NULL) + +devhelp: + $(VALADOC) \ + -o devhelp \ + --doclet devhelp \ + $(VALADOC_FLAGS) \ + $(NULL) + +gtkdoc: + $(VALADOC) \ + -X $(top_srcdir)/libzeitgeist/zeitgeist.h \ + -X -l -X $(top_srcdir)/libzeitgeist/.libs/libzeitgeist-2.0.so \ + -o gtkdoc \ + --doclet gtkdoc \ + $(VALADOC_FLAGS) \ + $(NULL) + +clean-local: + rm -rf valadoc devhelp gtkdoc + +all: valadoc devhelp gtkdoc + +endif diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..9f32c6f --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,41 @@ +NULL = + +AM_CPPFLAGS = \ + $(ZEITGEIST_CFLAGS) \ + -include $(CONFIG_HEADER) \ + -I $(top_srcdir)/libzeitgeist/ \ + -w \ + $(NULL) + +AM_VALAFLAGS = \ + --target-glib=2.26 \ + --pkg gio-2.0 \ + $(top_srcdir)/libzeitgeist/zeitgeist.vapi \ + $(top_srcdir)/config.vapi \ + $(NULL) + +zeitgeist_libs = \ + $(top_builddir)/libzeitgeist/libzeitgeist-2.0.la \ + $(ZEITGEIST_LIBS) + +noinst_PROGRAMS = \ + data-source-stuff \ + get-events-with-id \ + monitor-events \ + most-recent-events \ + $(NULL) + +data_source_stuff_SOURCES = data-source-stuff.vala +data_source_stuff_LDADD = $(zeitgeist_libs) + +get_events_with_id_SOURCES = get-events-with-id.vala +get_events_with_id_LDADD = $(zeitgeist_libs) + +monitor_events_SOURCES = monitor-events.vala +monitor_events_LDADD = $(zeitgeist_libs) + +most_recent_events_SOURCES = most-recent-events.vala +most_recent_events_LDADD = $(zeitgeist_libs) + +distclean-local: + rm -f *.c *.o *.~[0-9]~ diff --git a/examples/build.txt b/examples/build.txt new file mode 100644 index 0000000..87acc7c --- /dev/null +++ b/examples/build.txt @@ -0,0 +1,12 @@ +valac --target-glib=2.26 most-recent-events.vala ../libzeitgeist/*.vala --pkg gio-2.0 && ./most-recent-events + +valac --target-glib=2.26 get-events-with-id.vala ../libzeitgeist/*.vala --pkg gio-2.0 && ./get-events-with-id + +valac --target-glib=2.26 monitor-events.vala ../libzeitgeist/*.vala --pkg gio-2.0 && ./monitor-events + +valac --target-glib=2.26 datamodel-example.vala ../libzeitgeist/ontology-uris.vala && ./datamodel-example + +gcc --target-glib=2.26 datamodel-example.c `pkg-config --cflags gtk+-2.0` -I../../libzeitgeist/ + +$ gcc get-events.c -lzeitgeist -L../../libzeitgeist/.libs/ `pkg-config --cflags --libs glib-2.0 gobject-2.0 gio-2.0 gio-unix-2.0` -I../../libzeitgeist/ +$ LD_LIBRARY_PATH=../../libzeitgeist/.libs/ ./a.out diff --git a/examples/data-source-stuff.vala b/examples/data-source-stuff.vala new file mode 100644 index 0000000..6e74428 --- /dev/null +++ b/examples/data-source-stuff.vala @@ -0,0 +1,79 @@ +using Zeitgeist; + +MainLoop loop; + +async void do_stuff () throws Error +{ + var registry = new Zeitgeist.DataSourceRegistry (); + + registry.source_registered.connect (on_source_registered); + registry.source_enabled.connect (on_source_enabled); + + DataSource my_data_source = new DataSource.full ( + "com.example.test/my-ds", "Example Data-Source", + "An example data-source for testing libzeitgeist2", + new GenericArray()); + + stdout.printf ("Registering with data-source registry...\n"); + bool enabled = yield registry.register_data_source (my_data_source); + stdout.printf ("Done. The data-source is %s.\n\n", + (enabled) ? "enabled" : "disabled"); + + stdout.printf ("Disabling the data-source...\n"); + yield registry.set_data_source_enabled (my_data_source.unique_id, false); + + yield print_data_sources (registry); + + stdout.printf ("\nEnabling it again...\n"); + yield registry.set_data_source_enabled (my_data_source.unique_id, true); + + yield print_data_sources (registry); + + loop.quit (); +} + +void on_source_registered (DataSource source) +{ + stdout.printf("%s registered!\n", source.name); +} + +async void on_source_enabled (string unique_id, bool enabled) +{ + var registry = new Zeitgeist.DataSourceRegistry (); + DataSource source; + try + { + source = yield registry.get_data_source_from_id (unique_id); + stdout.printf("%s has been %s!\n", source.name, + (enabled) ? "enabled" : "disabled"); + } + catch (Error e) + { + critical ("Error retrieving data-source information: %s", e.message); + } +} + +async void print_data_sources (DataSourceRegistry registry) throws Error +{ + GenericArray datasources = null; + datasources = yield registry.get_data_sources (); + + stdout.printf ("\nThe following data-sources are registered:\n"); + for (int i = 0; i < datasources.length; ++i) + { + DataSource datasource = datasources[i]; + stdout.printf (" - %s [%s]\n", datasource.name, + (datasource.enabled) ? "enabled" : "disabled"); + } +} + +int main () +{ + loop = new MainLoop(); + + do_stuff(); + + loop.run (); + + return 0; +} diff --git a/examples/get-events-with-id.vala b/examples/get-events-with-id.vala new file mode 100644 index 0000000..d9c63a7 --- /dev/null +++ b/examples/get-events-with-id.vala @@ -0,0 +1,21 @@ +int main () +{ + uint32[] ids = { 31575, 31569 }; + + var loop = new MainLoop(); + + Zeitgeist.Log zg = new Zeitgeist.Log (); + zg.get_events (ids, null, (obj, res) => { + Zeitgeist.ResultSet events = zg.get_events.end (res); + while (events.has_next ()) + { + Zeitgeist.Event event = events.next (); + stdout.printf ("Subject: %s\n", event.subjects[0].uri); + } + loop.quit(); + }); + + loop.run (); + + return 0; +} diff --git a/examples/monitor-events.vala b/examples/monitor-events.vala new file mode 100644 index 0000000..63f0e44 --- /dev/null +++ b/examples/monitor-events.vala @@ -0,0 +1,33 @@ +void on_events_inserted (Zeitgeist.TimeRange tr, Zeitgeist.ResultSet events) +{ + message ("%u events inserted", events.size ()); + + while (events.has_next ()) + { + Zeitgeist.Event event = events.next (); + for (int i = 0; i < event.num_subjects (); ++i ) + { + Zeitgeist.Subject subject = event.subjects[i]; + message (" * %s", subject.uri); + } + } +} + +int main () +{ + var loop = new MainLoop(); + + var time_range = new Zeitgeist.TimeRange.anytime (); + var template = new GenericArray (); + + var monitor = new Zeitgeist.Monitor(time_range, template); + Zeitgeist.Log log = new Zeitgeist.Log (); + + monitor.events_inserted.connect (on_events_inserted); + //monitor.events_deleted.connect (on_events_deleted); + + log.install_monitor (monitor); + + loop.run (); + return 0; +} diff --git a/examples/most-recent-events.vala b/examples/most-recent-events.vala new file mode 100644 index 0000000..1d6b0bb --- /dev/null +++ b/examples/most-recent-events.vala @@ -0,0 +1,29 @@ +using Zeitgeist; + +int main () +{ + var loop = new MainLoop(); + var log = new Zeitgeist.Log (); + + var time_range = new TimeRange.anytime (); + var templates = new GenericArray (); + int num_events = 20; + + log.find_events (time_range, templates, StorageState.ANY, num_events, + ResultType.MOST_RECENT_SUBJECTS, null, (obj, res) => + { + ResultSet events = log.find_events.end (res); + stdout.printf ("%u most recent subjects:", events.size ()); + while (events.has_next ()) + { + Event event = events.next (); + stdout.printf (" - %s\n", event.subjects[0].uri); + } + loop.quit(); + } + ); + + loop.run (); + + return 0; +} diff --git a/extensions/Makefile.am b/extensions/Makefile.am index f939ccf..b0a47e0 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -4,12 +4,17 @@ endif NULL = +zeitgeist_libs = \ + $(top_builddir)/libzeitgeist/libzeitgeist-2.0.la \ + $(ZEITGEIST_LIBS) + #extensionsdir = $(libdir)/zeitgeist/extensions noinst_LTLIBRARIES = ds-registry.la blacklist.la storage-monitor.la fts.la benchmark.la histogram.la AM_CPPFLAGS = \ $(ZEITGEIST_CFLAGS) \ -include $(CONFIG_HEADER) \ + -I $(top_srcdir)/libzeitgeist \ -I $(top_srcdir)/src \ -w \ $(NULL) @@ -19,6 +24,7 @@ VALAFLAGS = \ --pkg gio-2.0 \ --pkg sqlite3 \ --pkg gmodule-2.0 \ + $(top_srcdir)/libzeitgeist/zeitgeist-private.vapi \ $(top_srcdir)/src/zeitgeist-engine.vapi \ $(NULL) diff --git a/extensions/benchmark.vala b/extensions/benchmark.vala index e6826cc..76bfd37 100644 --- a/extensions/benchmark.vala +++ b/extensions/benchmark.vala @@ -107,7 +107,7 @@ namespace Zeitgeist warning ("%s", err.message); } - debug ("%s, this.ref_count = %u", Log.METHOD, this.ref_count); + debug ("%s, this.ref_count = %u", GLib.Log.METHOD, this.ref_count); } } diff --git a/extensions/blacklist.vala b/extensions/blacklist.vala index ec69969..fa81e25 100644 --- a/extensions/blacklist.vala +++ b/extensions/blacklist.vala @@ -47,7 +47,7 @@ namespace Zeitgeist private const string SIG_BLACKLIST = "a{s("+Utils.SIG_EVENT+")}"; private static HashTable from_variant ( - Variant templates_variant) throws EngineError + Variant templates_variant) throws DataModelError { var blacklist = new HashTable (str_hash, str_equal); @@ -105,7 +105,7 @@ namespace Zeitgeist { blacklist = BlacklistTemplates.from_variant (templates); } - catch (EngineError e) + catch (DataModelError e) { warning ("Could not load blacklist from variant: %s", e.message); blacklist = new HashTable (str_hash, str_equal); @@ -145,7 +145,7 @@ namespace Zeitgeist warning ("%s", err.message); } - debug ("%s, this.ref_count = %u", Log.METHOD, this.ref_count); + debug ("%s, this.ref_count = %u", GLib.Log.METHOD, this.ref_count); } private void flush () @@ -172,7 +172,7 @@ namespace Zeitgeist } public void add_template (string template_id, Variant event_template) - throws EngineError + throws DataModelError { Event template = new Event.from_variant (event_template); blacklist.insert (template_id, template); diff --git a/extensions/ds-registry.vala b/extensions/ds-registry.vala index 46beb37..6555762 100644 --- a/extensions/ds-registry.vala +++ b/extensions/ds-registry.vala @@ -23,117 +23,21 @@ * */ +using Zeitgeist; + namespace Zeitgeist { - [DBus (name = "org.gnome.zeitgeist.DataSourceRegistry")] - public interface RemoteRegistry: Object - { - [DBus (signature = "a(sssa(asaasay)bxb)")] - public abstract Variant get_data_sources () throws Error; - public abstract bool register_data_source (string unique_id, - string name, string description, - [DBus (signature = "a(asaasay)")] Variant event_templates, BusName? sender) - throws Error; - public abstract void set_data_source_enabled (string unique_id, - bool enabled) throws Error; - [DBus (signature = "(sssa(asaasay)bxb)")] - public abstract Variant get_data_source_from_id (string id) throws Error; - - public signal void data_source_disconnected ( - [DBus (signature = "(sssa(asaasay)bxb)")] Variant data_source); - public signal void data_source_enabled (string unique_id, - bool enabled); - public signal void data_source_registered ( - [DBus (signature = "(sssa(asaasay)bxb)")] Variant data_source); - } - - class DataSource: Object - { - public string unique_id { get; set; } - public string name { get; set; } - public string description { get; set; } - - public GenericArray? event_templates { get; set; } - - public bool enabled { get; set; } - public bool running { get; set; } - public int64 timestamp { get; set; } - - public DataSource () - { - Object (); - } - - public DataSource.full (string unique_id, string name, - string description, GenericArray templates) - { - Object (unique_id: unique_id, name: name, description: description, - event_templates: templates); - } - - public DataSource.from_variant (Variant variant, - bool reset_running=false) throws EngineError - { - warn_if_fail ( - variant.get_type_string () == "(sssa("+Utils.SIG_EVENT+")bxb)" - || variant.get_type_string () == "sssa("+Utils.SIG_EVENT+")"); - var iter = variant.iterator (); - - assert (iter.n_children () >= 4); - unique_id = iter.next_value ().get_string (); - name = iter.next_value ().get_string (); - description = iter.next_value ().get_string (); - event_templates = Events.from_variant (iter.next_value ()); - - if (iter.n_children () > 4) - { - running = iter.next_value ().get_boolean (); - if (reset_running) - running = false; - timestamp = iter.next_value ().get_int64 (); - enabled = iter.next_value ().get_boolean (); - } - } - - public Variant to_variant () - { - var vb = new VariantBuilder (new VariantType ( - "(sssa("+Utils.SIG_EVENT+")bxb)")); - - vb.add ("s", unique_id); - vb.add ("s", name); - vb.add ("s", description); - if (event_templates != null && event_templates.length > 0) - { - vb.add_value (Events.to_variant (event_templates)); - } - else - { - vb.open (new VariantType ("a("+Utils.SIG_EVENT+")")); - vb.close (); - } - - vb.add ("b", running); - vb.add ("x", timestamp); - vb.add ("b", enabled); - - return vb.end (); - } - } namespace DataSources { - private const string SIG_DATASOURCES = - "a(sssa("+Utils.SIG_EVENT+")bxb)"; - - private static HashTable from_variant ( - Variant sources_variant, bool reset_running=false) throws EngineError + private static HashTable registry_from_variant ( + Variant sources_variant, bool reset_running=false) throws DataModelError { var registry = new HashTable ( str_hash, str_equal); warn_if_fail ( - sources_variant.get_type_string() == SIG_DATASOURCES); + sources_variant.get_type_string() == DataSources.SIG_DATASOURCES); foreach (Variant ds_variant in sources_variant) { DataSource ds = new DataSource.from_variant (ds_variant, @@ -143,28 +47,9 @@ namespace Zeitgeist return registry; } - - private static Variant to_variant ( - HashTable sources) - { - var vb = new VariantBuilder (new VariantType (SIG_DATASOURCES)); - - List data_sources = sources.get_values (); - data_sources.sort ((a, b) => - { - return strcmp (a.unique_id, b.unique_id); - }); - - foreach (unowned DataSource ds in data_sources) - { - vb.add_value (ds.to_variant ()); - } - - return vb.end (); - } } - class DataSourceRegistry: Extension, RemoteRegistry + class DataSourceRegistryExtension: Extension, RemoteRegistry { private const string MULTIPLE_MARKER = ""; private HashTable sources; @@ -175,7 +60,7 @@ namespace Zeitgeist private static const uint DISK_WRITE_TIMEOUT = 5 * 60; // 5 minutes - DataSourceRegistry () + DataSourceRegistryExtension () { Object (); } @@ -192,9 +77,9 @@ namespace Zeitgeist { try { - sources = DataSources.from_variant (registry, true); + sources = DataSources.registry_from_variant (registry, true); } - catch (EngineError e) + catch (DataModelError e) { warning ("Error while loading datasource registry: %s", e.message); sources = new HashTable ( @@ -245,10 +130,10 @@ namespace Zeitgeist } flush (); - debug ("%s, this.ref_count = %u", Log.METHOD, this.ref_count); + debug ("%s, this.ref_count = %u", GLib.Log.METHOD, this.ref_count); } - public Variant get_data_sources () + public async Variant get_data_sources (Cancellable? cancellable=null) { return DataSources.to_variant (sources); } @@ -264,13 +149,16 @@ namespace Zeitgeist return false; } - public bool register_data_source (string unique_id, string name, - string description, Variant event_templates, BusName? sender) throws EngineError + public async bool register_data_source (string unique_id, + string name, string description, Variant event_templates, + Cancellable? cancellable=null, BusName? sender) + throws DataModelError { - debug ("%s: %s, %s, %s", Log.METHOD, unique_id, name, description); + debug ("%s: %s, %s, %s", GLib.Log.METHOD, unique_id, + name, description); if (sender == null) { - warning ("%s: sender == null, ignoring request", Log.METHOD); + warning ("%s: sender == null, ignoring request", GLib.Log.METHOD); return false; } @@ -297,10 +185,11 @@ namespace Zeitgeist bus_name_2_ds.insert (sender, MULTIPLE_MARKER); } + GenericArray templates; // Vala: block scopes in async buggy unowned DataSource? ds = sources.lookup (unique_id); if (ds != null) { - var templates = Events.from_variant (event_templates); + templates = Events.from_variant (event_templates); ds.name = name; ds.description = description; ds.event_templates = templates; @@ -314,7 +203,7 @@ namespace Zeitgeist } else { - var templates = Events.from_variant (event_templates); + templates = Events.from_variant (event_templates); DataSource new_ds = new DataSource.full (unique_id, name, description, templates); new_ds.enabled = true; @@ -330,9 +219,10 @@ namespace Zeitgeist } - public void set_data_source_enabled (string unique_id, bool enabled) + public async void set_data_source_enabled (string unique_id, bool enabled, + Cancellable? cancellable=null) { - debug ("%s: %s, %d", Log.METHOD, unique_id, (int) enabled); + debug ("%s: %s, %d", GLib.Log.METHOD, unique_id, (int) enabled); unowned DataSource? ds = sources.lookup (unique_id); if (ds != null) { @@ -349,7 +239,8 @@ namespace Zeitgeist } } - public Variant get_data_source_from_id (string unique_id) throws Error + public async Variant get_data_source_from_id (string unique_id, + Cancellable? cancellable=null) throws Error { unowned DataSource? ds = sources.lookup (unique_id); if (ds != null) @@ -458,13 +349,13 @@ namespace Zeitgeist [ModuleInit] #if BUILTIN_EXTENSIONS - public static Type data_source_registry_init (TypeModule module) + public static Type data_source_registry_extension_init (TypeModule module) { #else public static Type extension_register (TypeModule module) { #endif - return typeof (DataSourceRegistry); + return typeof (DataSourceRegistryExtension); } } diff --git a/extensions/fts++/Makefile.am b/extensions/fts++/Makefile.am index 6580f13..1eb8181 100644 --- a/extensions/fts++/Makefile.am +++ b/extensions/fts++/Makefile.am @@ -15,6 +15,7 @@ AM_CPPFLAGS = \ $(ZEITGEIST_CFLAGS) \ $(XAPIAN_CXXFLAGS) \ -include $(CONFIG_HEADER) \ + -I $(top_srcdir)/libzeitgeist \ -w \ $(NULL) @@ -28,19 +29,13 @@ AM_VALAFLAGS = \ $(NULL) libzeitgeist_internal_la_VALASOURCES = \ - datamodel.vala \ db-reader.vala \ engine.vala \ sql.vala \ - remote.vala \ - utils.vala \ errors.vala \ table-lookup.vala \ sql-schema.vala \ where-clause.vala \ - ontology.vala \ - ontology-uris.vala \ - mimetype.vala \ ext-dummies.vala \ $(NULL) @@ -74,6 +69,7 @@ zeitgeist_fts_SOURCES = \ zeitgeist_fts_LDADD = \ $(builddir)/libzeitgeist-internal.la \ + $(top_builddir)/libzeitgeist/libzeitgeist-2.0.la \ $(XAPIAN_LIBS) \ $(NULL) diff --git a/extensions/fts++/datamodel.vala b/extensions/fts++/datamodel.vala deleted file mode 120000 index 02172aa..0000000 --- a/extensions/fts++/datamodel.vala +++ /dev/null @@ -1 +0,0 @@ -../../src/datamodel.vala \ No newline at end of file diff --git a/extensions/fts++/ontology-uris.vala b/extensions/fts++/ontology-uris.vala deleted file mode 120000 index c0b93ab..0000000 --- a/extensions/fts++/ontology-uris.vala +++ /dev/null @@ -1 +0,0 @@ -../../src/ontology-uris.vala \ No newline at end of file diff --git a/extensions/fts++/ontology.vala b/extensions/fts++/ontology.vala deleted file mode 120000 index 5daa021..0000000 --- a/extensions/fts++/ontology.vala +++ /dev/null @@ -1 +0,0 @@ -../../src/ontology.vala \ No newline at end of file diff --git a/extensions/fts++/test/Makefile.am b/extensions/fts++/test/Makefile.am index 915dd4f..359d828 100644 --- a/extensions/fts++/test/Makefile.am +++ b/extensions/fts++/test/Makefile.am @@ -22,6 +22,7 @@ test_fts_SOURCES = \ test_fts_LDADD = \ $(builddir)/../libzeitgeist-internal.la \ + $(top_builddir)/libzeitgeist/libzeitgeist-2.0.la \ -lxapian \ $(NULL) diff --git a/extensions/fts++/utils.vala b/extensions/fts++/utils.vala deleted file mode 120000 index 6da71ce..0000000 --- a/extensions/fts++/utils.vala +++ /dev/null @@ -1 +0,0 @@ -../../src/utils.vala \ No newline at end of file diff --git a/extensions/fts++/zeitgeist-fts.vala b/extensions/fts++/zeitgeist-fts.vala index 29ea1f4..a760ee3 100644 --- a/extensions/fts++/zeitgeist-fts.vala +++ b/extensions/fts++/zeitgeist-fts.vala @@ -100,7 +100,7 @@ namespace Zeitgeist } public async void notify_insert (Variant time_range, Variant events) - throws IOError, EngineError + throws Error { debug ("got insertion notification"); var events_arr = Events.from_variant (events); @@ -117,7 +117,8 @@ namespace Zeitgeist public async void search (string query_string, Variant time_range, Variant filter_templates, uint offset, uint count, uint result_type, - out Variant events, out uint matches) + out Variant events, out uint matches, + Cancellable? cancellable=null) throws Error { var tr = new TimeRange.from_variant (time_range); @@ -139,7 +140,8 @@ namespace Zeitgeist uint storage_state, uint offset, uint count, uint result_type, out Variant events, out double[] relevancies, - out uint matches) + out uint matches, + Cancellable? cancellable=null) throws Error { var tr = new TimeRange.from_variant (time_range); diff --git a/extensions/fts.vala b/extensions/fts.vala index 5331203..698e313 100644 --- a/extensions/fts.vala +++ b/extensions/fts.vala @@ -41,22 +41,6 @@ namespace Zeitgeist out uint matches) throws Error; } - /* Because of a Vala bug we have to define the proxy interface outside of - * [ModuleInit] source */ - /* - [DBus (name = "org.gnome.zeitgeist.SimpleIndexer")] - public interface RemoteSimpleIndexer : Object - { - public abstract async void search ( - string query_string, - [DBus (signature = "(xx)")] Variant time_range, - [DBus (signature = "a(asaasay)")] Variant filter_templates, - uint offset, uint count, uint result_type, - [DBus (signature = "a(asaasay)")] out Variant events, - out uint matches) throws Error; - } - */ - class SearchEngine: Extension, RemoteSearchEngine { @@ -105,7 +89,7 @@ namespace Zeitgeist warning ("%s", err.message); } } - + private void proxy_not_present() { notifier.remove_monitor (new BusName (INDEXER_NAME),"/org/gnome/zeitgeist/monitor/special"); @@ -153,7 +137,7 @@ namespace Zeitgeist "Not connected to SimpleIndexer"); } } - + public override void unload () { try @@ -170,7 +154,7 @@ namespace Zeitgeist warning ("%s", err.message); } - debug ("%s, this.ref_count = %u", Log.METHOD, this.ref_count); + debug ("%s, this.ref_count = %u", GLib.Log.METHOD, this.ref_count); } public async void search (string query_string, Variant time_range, diff --git a/extensions/histogram.vala b/extensions/histogram.vala index d5aa28a..11ce45a 100644 --- a/extensions/histogram.vala +++ b/extensions/histogram.vala @@ -66,7 +66,7 @@ namespace Zeitgeist warning ("%s", err.message); } - debug ("%s, this.ref_count = %u", Log.METHOD, this.ref_count); + debug ("%s, this.ref_count = %u", GLib.Log.METHOD, this.ref_count); } public Variant get_histogram_data () throws Error diff --git a/extensions/storage-monitor.vala b/extensions/storage-monitor.vala index a0010e4..f1c1eee 100644 --- a/extensions/storage-monitor.vala +++ b/extensions/storage-monitor.vala @@ -217,7 +217,7 @@ namespace Zeitgeist warning ("%s", err.message); } - debug ("%s, this.ref_count = %u", Log.METHOD, this.ref_count); + debug ("%s, this.ref_count = %u", GLib.Log.METHOD, this.ref_count); } private void prepare_queries () throws EngineError diff --git a/libzeitgeist/.gitignore b/libzeitgeist/.gitignore new file mode 100644 index 0000000..c8b0843 --- /dev/null +++ b/libzeitgeist/.gitignore @@ -0,0 +1,2 @@ +.deps +.libs diff --git a/libzeitgeist/API_CHANGES b/libzeitgeist/API_CHANGES new file mode 100644 index 0000000..c1a3917 --- /dev/null +++ b/libzeitgeist/API_CHANGES @@ -0,0 +1,33 @@ +API CHANGES FROM LIBZEITGEIST1: + + - removed reference stealing + - "connected" property renamed to "is-connected" + - DataSource.is_enabled renamed to get_enabled (?) + - introduced ZeitgeistRelevantResultType + - event_new_full now has an actor parameter + - subject_new_full now has a current_uri parameter + - introduced result_type_is_sort_order_asc (or hide it?) + - removed event_new_full_valist and events_from_valist + - introduced get_data_source_from_id + - introduced zeitgeist_{event,subject}_matches_template + - some functions involving variants now have a GError parameter + - introduced zeitgeist_event_take_subject + - introduced zeitgeist_time_range_intersect + - removed time_range_get_{start,end}_iso8601 + +Vala: + - stuff is more valaish (eg. properties vs set/get) + + +------------------------------------------------- + +LIBZEITGEIST2 TODO: + - gtkdoc: document enum values + - gtkdoc: make index.html nice + - gtkdoc: add object hierarchy page + - gtkdoc: split stuff (eg. datamodel.html) into 1 page for class + - gtkdoc: fix api index so that eveyrthing isn't under Z + - gtkdoc: show properties & signals!! + - lots of documentation missing + - make zeitgeist_events_to_variant_with_limit internal? + - make utils.* internal? diff --git a/libzeitgeist/Makefile.am b/libzeitgeist/Makefile.am new file mode 100644 index 0000000..02fc63e --- /dev/null +++ b/libzeitgeist/Makefile.am @@ -0,0 +1,76 @@ +NULL = + +lib_LTLIBRARIES = libzeitgeist-2.0.la + +AM_CPPFLAGS = \ + $(ZEITGEIST_CFLAGS) \ + -include $(CONFIG_HEADER) \ + -w \ + $(NULL) + +AM_VALAFLAGS = \ + --target-glib=2.26 \ + --pkg gio-2.0 \ + --pkg sqlite3 \ + $(top_srcdir)/config.vapi \ + --vapi zeitgeist.vapi \ + -H zeitgeist.h \ + --internal-vapi zeitgeist-private.vapi \ + -h zeitgeist-private.h \ + --library=zeitgeist \ + $(NULL) + +libzeitgeist_2_0_la_SOURCES = \ + data-source.vala \ + data-source-registry.vala \ + mimetype.vala \ + datamodel.vala \ + index.vala \ + log.vala \ + timestamp.vala \ + monitor.vala \ + ontology-uris.vala \ + ontology.vala \ + queued-proxy-wrapper.vala \ + remote.vala \ + result-set.vala \ + simple-result-set.vala \ + utils.vala \ + $(NULL) + +libzeitgeist_2_0_la_LDFLAGS = -version-info $(LIBZEITGEIST_LT_VERSION) + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = zeitgeist-2.0.pc + +libzeitgeist_includedir=$(includedir)/zeitgeist-2.0/ +libzeitgeist_include_HEADERS = \ + zeitgeist.h \ + $(NULL) + +libzeitgeist_vapidir = $(datadir)/vala/vapi/ +libzeitgeist_vapi_DATA = \ + zeitgeist.vapi + $(NULL) + +EXTRA_DIST = \ + ontology.vala.in \ + ontology-uris.vala.in \ + $(NULL) + +DISTCLEANFILES = \ + ontology.vala \ + ontology-uris.vala \ + zeitgeist.vapi \ + zeitgeist-private.vapi \ + $(NULL) + +# FIXME: can we make this depend on $(ontology_trig_DATA)? +ontology_vala.stamp: ontology.vala.in ontology-uris.vala.in + $(AM_V_GEN)$(top_srcdir)/data/ontology2code --vala + @touch "$@" + +ontology.vala ontology-uris.vala: ontology_vala.stamp + +distclean-local: + rm -f *.c *.o *.stamp *.~[0-9]~ diff --git a/libzeitgeist/data-source-registry.vala b/libzeitgeist/data-source-registry.vala new file mode 100644 index 0000000..1171c5f --- /dev/null +++ b/libzeitgeist/data-source-registry.vala @@ -0,0 +1,144 @@ +/* data-source-registry.vala + * + * Copyright © 2012 Collabora Ltd. + * By Siegfried-Angel Gevatter Pujals + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + + [DBus (name = "org.gnome.zeitgeist.DataSourceRegistry")] + internal interface RemoteRegistry: Object + { + [DBus (signature = "a(sssa(asaasay)bxb)")] + public abstract async Variant get_data_sources ( + Cancellable? cancellable=null) throws Error; + public abstract async bool register_data_source (string unique_id, + string name, string description, + [DBus (signature = "a(asaasay)")] Variant event_templates, + Cancellable? cancellable=null, BusName? sender=null) throws Error; + public abstract async void set_data_source_enabled (string unique_id, + bool enabled, Cancellable? cancellable=null) throws Error; + [DBus (signature = "(sssa(asaasay)bxb)")] + public abstract async Variant get_data_source_from_id ( + string unique_id, Cancellable? cancellable=null) throws Error; + + public signal void data_source_disconnected ( + [DBus (signature = "(sssa(asaasay)bxb)")] Variant data_source); + public signal void data_source_enabled (string unique_id, + bool enabled); + public signal void data_source_registered ( + [DBus (signature = "(sssa(asaasay)bxb)")] Variant data_source); + } + + public class DataSourceRegistry : QueuedProxyWrapper + { + + private RemoteRegistry proxy; + + public signal void source_disconnected (DataSource data_source); + public signal void source_enabled (string unique_id, bool enabled); + public signal void source_registered (DataSource data_source); + + public DataSourceRegistry () + { + Bus.get_proxy (BusType.SESSION, + Utils.ENGINE_DBUS_NAME, + "/org/gnome/zeitgeist/data_source_registry", 0, null, + (obj, res) => + { + try + { + proxy = Bus.get_proxy.end (res); + proxy_acquired (proxy); + + // FIXME: here or each time in _connection_established? + proxy.data_source_disconnected.connect ((data_source) => { + var source = new DataSource.from_variant (data_source); + source_disconnected (source); + }); + proxy.data_source_enabled.connect ((unique_id, enabled) => { + // FIXME: why don't we return DataSource here too? :( + source_enabled (unique_id, enabled); + }); + proxy.data_source_registered.connect ((data_source) => { + var source = new DataSource.from_variant (data_source); + source_registered (source); + }); + } + catch (IOError err) + { + critical ( + "Unable to connect to Zeitgeist's " + + "DataSourceRegistry: %s", err.message); + proxy_unavailable(); + } + }); + } + + protected override void on_connection_established () + { + } + + protected override void on_connection_lost () + { + } + + public async GenericArray get_data_sources ( + Cancellable? cancellable=null) throws Error + { + yield wait_for_proxy (get_data_sources.callback); + var result = yield proxy.get_data_sources (cancellable); + return DataSources.from_variant (result); + } + + public async DataSource get_data_source_from_id ( + string unique_id, Cancellable? cancellable=null) throws Error + { + yield wait_for_proxy (get_data_source_from_id.callback); + var result = yield proxy.get_data_source_from_id (unique_id, + cancellable); + + return new DataSource.from_variant (result); + } + + public async bool register_data_source ( + DataSource data_source, Cancellable? cancellable=null) throws Error + { + yield wait_for_proxy (register_data_source.callback); + return yield proxy.register_data_source ( + data_source.unique_id, data_source.name, + data_source.description, + Events.to_variant(data_source.event_templates), + cancellable); + } + + // FIXME: return bool with false if error? (+ rethrow error) + public async void set_data_source_enabled ( + string unique_id, bool enabled, Cancellable? cancellable=null) + throws Error + { + yield wait_for_proxy (set_data_source_enabled.callback); + yield proxy.set_data_source_enabled (unique_id, enabled, + cancellable); + } + + } + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/data-source.vala b/libzeitgeist/data-source.vala new file mode 100644 index 0000000..5d8c620 --- /dev/null +++ b/libzeitgeist/data-source.vala @@ -0,0 +1,140 @@ +/* data-source.vala + * + * Copyright © 2011 Michal Hruby + * Copyright © 2011, 2012 Collabora Ltd. + * By Siegfried-Angel Gevatter Pujals + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + public class DataSource: Object + { + public string unique_id { get; set; } + public string name { get; set; } + public string description { get; set; } + + public GenericArray? event_templates { get; set; } + + public bool enabled { get; set; } + public bool running { get; set; } + public int64 timestamp { get; set; } + + public DataSource () + { + Object (); + } + + public DataSource.full (string unique_id, string name, + string description, GenericArray templates) + { + Object (unique_id: unique_id, name: name, description: description, + event_templates: templates); + } + + public DataSource.from_variant (Variant variant, + bool reset_running=false) throws DataModelError + { + warn_if_fail ( + variant.get_type_string () == "(sssa("+Utils.SIG_EVENT+")bxb)" + || variant.get_type_string () == "sssa("+Utils.SIG_EVENT+")"); + var iter = variant.iterator (); + + assert (iter.n_children () >= 4); + unique_id = iter.next_value ().get_string (); + name = iter.next_value ().get_string (); + description = iter.next_value ().get_string (); + event_templates = Events.from_variant (iter.next_value ()); + + if (iter.n_children () > 4) + { + running = iter.next_value ().get_boolean (); + if (reset_running) + running = false; + timestamp = iter.next_value ().get_int64 (); + enabled = iter.next_value ().get_boolean (); + } + } + + public Variant to_variant () + { + var vb = new VariantBuilder (new VariantType ( + "(sssa("+Utils.SIG_EVENT+")bxb)")); + + vb.add ("s", unique_id); + vb.add ("s", name); + vb.add ("s", description); + if (event_templates != null && event_templates.length > 0) + { + vb.add_value (Events.to_variant (event_templates)); + } + else + { + vb.open (new VariantType ("a("+Utils.SIG_EVENT+")")); + vb.close (); + } + + vb.add ("b", running); + vb.add ("x", timestamp); + vb.add ("b", enabled); + + return vb.end (); + } + } + + namespace DataSources + { + internal const string SIG_DATASOURCES = + "a(sssa("+Utils.SIG_EVENT+")bxb)"; + + public static GenericArray from_variant ( + Variant sources_variant) throws DataModelError + { + var sources = new GenericArray (); + + warn_if_fail ( + sources_variant.get_type_string() == SIG_DATASOURCES); + foreach (Variant ds_variant in sources_variant) + { + sources.add (new DataSource.from_variant (ds_variant)); + } + + return sources; + } + + public static Variant to_variant ( + HashTable sources) + { + var vb = new VariantBuilder (new VariantType (SIG_DATASOURCES)); + + List data_sources = sources.get_values (); + data_sources.sort ((a, b) => + { + return strcmp (a.unique_id, b.unique_id); + }); + + foreach (unowned DataSource ds in data_sources) + { + vb.add_value (ds.to_variant ()); + } + + return vb.end (); + } + } + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/datamodel.vala b/libzeitgeist/datamodel.vala new file mode 100644 index 0000000..ae03e62 --- /dev/null +++ b/libzeitgeist/datamodel.vala @@ -0,0 +1,798 @@ +/* datamodel.vala + * + * Copyright © 2011 Collabora Ltd. + * By Seif Lotfy + * By Siegfried-Angel Gevatter Pujals + * Copyright © 2011 Manish Sinha + * Copyright © 2012 Canonical Ltd. + * By Siegfried-A. Gevatter + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + // FIXME: move errors.vala to libzeitgeist/ and put this in there... + //[DBus (name = "org.gnome.zeitgeist.DataModelError")] + public errordomain DataModelError { + INVALID_SIGNATURE, + TOO_MANY_RESULTS + } + + private void assert_sig (bool condition, string error_message) + throws DataModelError + { + if (unlikely (!condition)) + throw new DataModelError.INVALID_SIGNATURE (error_message); + } + + [CCode (type_signature = "(xx)")] + public class TimeRange: Object + { + public int64 start { get; private set; } + public int64 end { get; private set; } + + public TimeRange (int64 start_msec, int64 end_msec) + { + start = start_msec; + end = end_msec; + } + + public TimeRange.anytime () + { + this (0, int64.MAX); + } + + public TimeRange.to_now () + { + this (0, Timestamp.now ()); + } + + public TimeRange.from_now () + { + this (Timestamp.now (), int64.MAX); + } + + public TimeRange.from_variant (Variant variant) + throws DataModelError + { + assert_sig (variant.get_type_string () == "(xx)", + "Invalid D-Bus signature."); + + int64 start_msec = 0; + int64 end_msec = 0; + + variant.get ("(xx)", &start_msec, &end_msec); + + this (start_msec, end_msec); + } + + public Variant to_variant () + { + return new Variant ("(xx)", start, end); + } + + public TimeRange? intersect (TimeRange time_range) + { + var result = new TimeRange(0,0); + if (start < time_range.start) + if (end < time_range.start) + return null; + else + result.start = time_range.start; + else + if (start > time_range.end) + return null; + else + result.start = start; + + if (end < time_range.end) + if (end < time_range.start) + return null; + else + result.end = end; + else + if (start > time_range.end) + return null; + else + result.end = time_range.end; + return result; + } + } + + public enum ResultType + { + MOST_RECENT_EVENTS = 0, // All events with the most + // recent events first + LEAST_RECENT_EVENTS = 1, // All events with the oldest + // ones first + MOST_RECENT_SUBJECTS = 2, // One event for each subject + // only, ordered with the + // most recent events first + LEAST_RECENT_SUBJECTS = 3, // One event for each subject + // only, ordered with oldest + // events first + MOST_POPULAR_SUBJECTS = 4, // One event for each subject + // only, ordered by the + // popularity of the subject + LEAST_POPULAR_SUBJECTS = 5, // One event for each subject + // only, ordered ascendingly + // by popularity of the + // subject + MOST_POPULAR_ACTOR = 6, // The last event of each + // different actor ordered + // by the popularity of the + // actor + LEAST_POPULAR_ACTOR = 7, // The last event of each + // different actor, ordered + // ascendingly by the + // popularity of the actor + MOST_RECENT_ACTOR = 8, // The actor that has been used + // to most recently + LEAST_RECENT_ACTOR = 9, // The actor that has been used + // to least recently + MOST_RECENT_ORIGIN = 10, // The last event of each + // different subject origin. + LEAST_RECENT_ORIGIN = 11, // The last event of each + // different subject origin, + // ordered by least + // recently used first + MOST_POPULAR_ORIGIN = 12, // The last event of each + // different subject origin, + // ordered by the + // popularity of the origins + LEAST_POPULAR_ORIGIN = 13, // The last event of each + // different subject origin, + // ordered ascendingly by + // the popularity of the + // origin + OLDEST_ACTOR = 14, // The first event of each + // different actor + MOST_RECENT_SUBJECT_INTERPRETATION = 15, // One event for each subject + // interpretation only, + // ordered with the most + // recent events first + LEAST_RECENT_SUBJECT_INTERPRETATION = 16, // One event for each subject + // interpretation only, + // ordered with the least + // recent events first + MOST_POPULAR_SUBJECT_INTERPRETATION = 17, // One event for each subject + // interpretation only, + // ordered by the popularity + // of the subject + // interpretation + LEAST_POPULAR_SUBJECT_INTERPRETATION = 18, // One event for each subject + // interpretation only, + // ordered ascendingly by + // popularity of the subject + // interpretation + MOST_RECENT_MIMETYPE = 19, // One event for each mimetype + // only ordered with the + // most recent events first + LEAST_RECENT_MIMETYPE = 20, // One event for each mimetype + // only ordered with the + // least recent events first + MOST_POPULAR_MIMETYPE = 21, // One event for each mimetype + // only ordered by the + // popularity of the mimetype + LEAST_POPULAR_MIMETYPE = 22, // One event for each mimetype + // only ordered ascendingly + // by popularity of the + // mimetype + MOST_RECENT_CURRENT_URI = 23, // One event for each subject + // only by current_uri + // instead of uri ordered + // with the most recent + // events first + LEAST_RECENT_CURRENT_URI = 24, // One event for each subject + // only by current_uri + // instead of uri ordered + // with oldest events first + MOST_POPULAR_CURRENT_URI = 25, // One event for each subject + // only by current_uri + // instead of uri ordered + // by the popularity of the + // subject + LEAST_POPULAR_CURRENT_URI = 26, // One event for each subject + // only by current_uri + // instead of uri + // ordered ascendingly by + // popularity of the subject + MOST_RECENT_EVENT_ORIGIN = 27, // The last event of each + // different origin + LEAST_RECENT_EVENT_ORIGIN = 28, // The last event of each + // different origin, ordered + // by least recently used + // first + MOST_POPULAR_EVENT_ORIGIN = 29, // The last event of each + // different origin ordered + // by the popularity of the + // origins + LEAST_POPULAR_EVENT_ORIGIN = 30; // The last event of each + // different origin, ordered + // ascendingly by the + // popularity of the origin + + /* + * Returns true if the results for the given result_type will be sorted + * ascendantly by date, false if they'll be sorted descendingly. + **/ + public static bool is_sort_order_asc (ResultType result_type) + { + switch (result_type) + { + // FIXME: Why are LEAST_POPULAR_* using ASC? + case ResultType.LEAST_RECENT_EVENTS: + case ResultType.LEAST_RECENT_EVENT_ORIGIN: + case ResultType.LEAST_POPULAR_EVENT_ORIGIN: + case ResultType.LEAST_RECENT_SUBJECTS: + case ResultType.LEAST_POPULAR_SUBJECTS: + case ResultType.LEAST_RECENT_CURRENT_URI: + case ResultType.LEAST_POPULAR_CURRENT_URI: + case ResultType.LEAST_RECENT_ACTOR: + case ResultType.LEAST_POPULAR_ACTOR: + case ResultType.OLDEST_ACTOR: + case ResultType.LEAST_RECENT_ORIGIN: + case ResultType.LEAST_POPULAR_ORIGIN: + case ResultType.LEAST_RECENT_SUBJECT_INTERPRETATION: + case ResultType.LEAST_POPULAR_SUBJECT_INTERPRETATION: + case ResultType.LEAST_RECENT_MIMETYPE: + case ResultType.LEAST_POPULAR_MIMETYPE: + return true; + + case ResultType.MOST_RECENT_EVENTS: + case ResultType.MOST_RECENT_EVENT_ORIGIN: + case ResultType.MOST_POPULAR_EVENT_ORIGIN: + case ResultType.MOST_RECENT_SUBJECTS: + case ResultType.MOST_POPULAR_SUBJECTS: + case ResultType.MOST_RECENT_CURRENT_URI: + case ResultType.MOST_POPULAR_CURRENT_URI: + case ResultType.MOST_RECENT_ACTOR: + case ResultType.MOST_POPULAR_ACTOR: + case ResultType.MOST_RECENT_ORIGIN: + case ResultType.MOST_POPULAR_ORIGIN: + case ResultType.MOST_RECENT_SUBJECT_INTERPRETATION: + case ResultType.MOST_POPULAR_SUBJECT_INTERPRETATION: + case ResultType.MOST_RECENT_MIMETYPE: + case ResultType.MOST_POPULAR_MIMETYPE: + return false; + + default: + warning ("Unrecognized ResultType: %u", (uint) result_type); + return true; + } + } + } + + /* + * An enumeration class used to define how query results should + * be returned from the Zeitgeist engine. + */ + public enum RelevantResultType + { + RECENT = 0, // All uris with the most recent uri first + RELATED = 1, // All uris with the most related one first + } + + /** + * Enumeration class defining the possible values for the storage + * state of an event subject. + * + * The StorageState enumeration can be used to control whether or + * not matched events must have their subjects available to the user. + * Fx. not including deleted files, files on unplugged USB drives, + * files available only when a network is available etc. + */ + public enum StorageState + { + NOT_AVAILABLE = 0, // The storage medium of the events + // subjects must not be available to the user + AVAILABLE = 1, // The storage medium of all event subjects + // must be immediately available to the user + ANY = 2 // The event subjects may or may not be available + } + + private bool check_field_match (string? property, + string? template_property, bool is_symbol = false, + bool can_wildcard = false) + { + var matches = false; + var is_negated = false; + var parsed = template_property; + + if (parsed != null) + is_negated = Utils.parse_negation (ref parsed); + + if (Utils.is_empty_string (parsed)) + { + return true; + } + else if (parsed == property) + { + matches = true; + } + else if (is_symbol && property != null && + Symbol.get_all_parents (property).find_custom (parsed, strcmp) != null) + { + matches = true; + } + else if (can_wildcard && Utils.parse_wildcard (ref parsed)) + { + if (property != null && property.has_prefix (parsed)) + matches = true; + } + + return (is_negated) ? !matches : matches; + } + + public class Event : Object + { + public const string SIGNATURE = "asaasay"; + + private static StringChunk url_store; + + public uint32 id { get; set; } + public int64 timestamp { get; set; } + public string? origin { get; set; } + + public string? actor + { + get { return _actor; } + set { _actor = (value != null) ? url_store.insert_const (value) : null; } + } + public string? interpretation + { + get { return _interpretation; } + set { _interpretation = (value != null) ? url_store.insert_const (value) : null; } + } + public string? manifestation + { + get { return _manifestation; } + set { _manifestation = (value != null) ? url_store.insert_const (value) : null; } + } + + private unowned string? _actor; + private unowned string? _interpretation; + private unowned string? _manifestation; + + public GenericArray subjects { get; set; } + public ByteArray? payload { get; set; } + + static construct + { + url_store = new StringChunk (4096); + } + + construct + { + subjects = new GenericArray (); + } + + public int num_subjects () + { + return subjects.length; + } + + public void add_subject (Subject subject) + { + subjects.add (subject); + } + + public void take_subject (owned Subject subject) + { + subjects.add ((owned) subject); + } + + public Event.full (string? interpretation=null, + string? manifestation=null, string? actor=null, + string? origin=null, ...) + { + this.interpretation = interpretation; + this.manifestation = manifestation; + this.actor = actor; + this.origin = origin; + + // FIXME: We can't use this until Vala bug #647097 is fixed + /* + var subjects = va_list (); + unowned Subject subject; + while ((subject = subjects.arg ()) != null) + add_subject (subject); + */ + } + + public Event.from_variant (Variant event_variant) throws DataModelError { + assert_sig (event_variant.get_type_string () == "(" + + Utils.SIG_EVENT + ")", "Invalid D-Bus signature."); + + VariantIter iter = event_variant.iterator (); + + assert_sig (iter.n_children () >= 3, "Incomplete event struct."); + VariantIter event_array = iter.next_value ().iterator (); + VariantIter subjects_array = iter.next_value ().iterator (); + Variant payload_variant = iter.next_value (); + + var event_props = event_array.n_children (); + assert_sig (event_props >= 5, "Missing event information."); + id = (uint32) uint64.parse (event_array.next_value().get_string ()); + var str_timestamp = event_array.next_value().get_string (); + if (str_timestamp == "") + timestamp = Timestamp.now (); + else + timestamp = int64.parse (str_timestamp); + interpretation = event_array.next_value ().get_string (); + manifestation = event_array.next_value ().get_string (); + actor = event_array.next_value ().get_string (); + // let's keep this compatible with older clients + if (event_props >= 6) + origin = event_array.next_value ().get_string (); + else + origin = ""; + + for (int i = 0; i < subjects_array.n_children (); ++i) { + Variant subject_variant = subjects_array.next_value (); + subjects.add (new Subject.from_variant (subject_variant)); + } + + // Parse payload... + uint payload_length = (uint) payload_variant.n_children (); + if (payload_length > 0) + { + payload = new ByteArray.sized (payload_length); + unowned uint8[] data = (uint8[]?) payload_variant.get_data (); + data.length = (int) payload_length; + payload.append (data); + } + } + + public Variant to_variant () + { + var vb = new VariantBuilder (new VariantType ("("+Utils.SIG_EVENT+")")); + + vb.open (new VariantType ("as")); + vb.add ("s", id == 0 ? "" : id.to_string ()); + vb.add ("s", timestamp.to_string ()); + vb.add ("s", interpretation != null ? interpretation : ""); + vb.add ("s", manifestation != null ? manifestation : ""); + vb.add ("s", actor != null ? actor : ""); + vb.add ("s", origin != null ? origin : ""); + vb.close (); + + vb.open (new VariantType ("aas")); + for (int i = 0; i < subjects.length; ++i) { + vb.add_value (subjects[i].to_variant ()); + } + vb.close (); + + if (payload != null) + { + Variant payload_variant = Variant.new_from_data ( + new VariantType ("ay"), payload.data, false); + // FIXME: somehow adding the payload_variant is not working + vb.add_value (payload_variant); + } + else + { + vb.open (new VariantType ("ay")); + vb.close (); + } + + Variant event_variant = vb.end ().get_normal_form (); + Variant ret = optimize_variant_allocation (event_variant); + return ret; + } + + private Variant optimize_variant_allocation (Variant event_variant) { + // FIXME: this uses g_new0, we dont need the mem to be zero-filled + uchar[] data = new uchar[event_variant.get_size ()]; + event_variant.store (data); + unowned uchar[] data_copy = data; + + Variant ret = Variant.new_from_data ( + new VariantType ("("+Utils.SIG_EVENT+")"), + data_copy, true, (owned) data); + return ret; + } + + public void debug_print () + { + stdout.printf ("id: %d\t" + + "timestamp: %" + int64.FORMAT + "\n" + + "actor: %s\n" + + "interpretation: %s\n" + + "manifestation: %s\n" + + "origin: %s\n" + + "num subjects: %d\n", + id, timestamp, actor, interpretation, + manifestation, origin, subjects.length); + for (int i = 0; i < subjects.length; i++) + { + var s = subjects[i]; + stdout.printf (" Subject #%d:\n" + + " uri: %s\n" + + " interpretation: %s\n" + + " manifestation: %s\n" + + " mimetype: %s\n" + + " origin: %s\n" + + " text: %s\n" + + " current_uri: %s\n" + + " storage: %s\n", + i, s.uri, s.interpretation, s.manifestation, + s.mimetype, s.origin, s.text, s.current_uri, + s.storage); + } + } + + + public bool matches_template (Event template_event) + { + /** + Return True if this event matches *event_template*. The + matching is done where unset fields in the template is + interpreted as wild cards. Interpretations and manifestations + are also matched if they are children of the types specified + in `event_template`. If the template has more than one + subject, this event matches if at least one of the subjects + on this event matches any single one of the subjects on the + template. + */ + + //Check if interpretation is child of template_event or same + if (!check_field_match (this.interpretation, template_event.interpretation, true)) + return false; + //Check if manifestation is child of template_event or same + if (!check_field_match (this.manifestation, template_event.manifestation, true)) + return false; + //Check if actor is equal to template_event actor + if (!check_field_match (this.actor, template_event.actor, false, true)) + return false; + //Check if origin is equal to template_event origin + if (!check_field_match (this.origin, template_event.origin, false, true)) + return false; + + if (template_event.subjects.length == 0) + return true; + + for (int i = 0; i < this.subjects.length; i++) + for (int j = 0; j < template_event.subjects.length; j++) + if (this.subjects[i].matches_template (template_event.subjects[j])) + return true; + + return false; + } + + } + + namespace Events + { + + public static GenericArray from_variant (Variant vevents) + throws DataModelError + { + GenericArray events = new GenericArray (); + + assert (vevents.get_type_string () == "a("+Utils.SIG_EVENT+")"); + + foreach (Variant event in vevents) + { + events.add (new Event.from_variant (event)); + } + + return events; + } + + public static Variant to_variant (GenericArray events) + { + var vb = new VariantBuilder(new VariantType("a("+Utils.SIG_EVENT+")")); + + for (int i = 0; i < events.length; ++i) + { + if (events[i] != null) + { + vb.add_value (events[i].to_variant ()); + } + else + { + vb.add_value (get_null_event_variant ()); + } + } + + return vb.end (); + } + + /* Same as to_variant but raises an exception if the variant size + * exceeds `limit' bytes. + * */ + public static Variant to_variant_with_limit (GenericArray events, + size_t limit=Utils.MAX_DBUS_RESULT_SIZE) throws DataModelError + { + var vb = new VariantBuilder(new VariantType("a("+Utils.SIG_EVENT+")")); + + size_t variant_size = 0; + + for (int i = 0; i < events.length; ++i) + { + Variant event_variant; + + if (events[i] != null) + { + event_variant = events[i].to_variant (); + } + else + { + event_variant = get_null_event_variant (); + } + + variant_size += event_variant.get_size(); + if (variant_size > limit) + { + size_t avg_event_size = variant_size / (i+1); + string error_message = ("Query exceeded size limit of % " + + size_t.FORMAT + "MiB (roughly ~%d events).").printf ( + limit / 1024 / 1024, limit / avg_event_size); + warning (error_message); + throw new DataModelError.TOO_MANY_RESULTS (error_message); + } + + vb.add_value (event_variant); + } + + return vb.end (); + } + + private static Variant get_null_event_variant () + { + var vb = new VariantBuilder (new VariantType ("("+Utils.SIG_EVENT+")")); + vb.open (new VariantType ("as")); + vb.close (); + vb.open (new VariantType ("aas")); + vb.close (); + vb.open (new VariantType ("ay")); + vb.close (); + return vb.end (); + } + + } + + public class Subject : Object + { + private static StringChunk url_store; + + public string? uri { get; set; } + public string? origin { get; set; } + public string? text { get; set; } + public string? storage { get; set; } + // FIXME: current_uri is often the same as uri, we don't need to waste + // memory for it + public string? current_uri { get; set; } + + public string? mimetype + { + get { return _mimetype; } + set { _mimetype = (value != null) ? url_store.insert_const (value) : null; } + } + public string? interpretation + { + get { return _interpretation; } + set { _interpretation = (value != null) ? url_store.insert_const (value) : null; } + } + public string? manifestation + { + get { return _manifestation; } + set { _manifestation = (value != null) ? url_store.insert_const (value) : null; } + } + + private unowned string? _mimetype; + private unowned string? _interpretation; + private unowned string? _manifestation; + + static construct + { + url_store = new StringChunk (4096); + } + + public Subject.full (string? uri=null, + string? interpretation=null, string? manifestation=null, + string? mimetype=null, string? origin=null, string? text=null, + string? storage=null, string? current_uri=null) + { + this.interpretation = interpretation; + this.manifestation = manifestation; + this.mimetype = mimetype; + this.origin = origin; + this.text = text; + this.storage = storage; + this.current_uri = current_uri; + } + + public Subject.from_variant (Variant subject_variant) + throws DataModelError + { + VariantIter iter = subject_variant.iterator(); + + var subject_props = iter.n_children (); + assert_sig (subject_props >= 7, "Missing subject information"); + uri = iter.next_value().get_string (); + interpretation = iter.next_value().get_string (); + manifestation = iter.next_value().get_string (); + origin = iter.next_value().get_string (); + mimetype = iter.next_value().get_string (); + text = iter.next_value().get_string (); + storage = iter.next_value().get_string (); + // let's keep this compatible with older clients + if (subject_props >= 8) + current_uri = iter.next_value().get_string (); + else + current_uri = ""; + } + + public Variant to_variant () + { + /* The FAST version */ + char* ptr_arr[8]; + ptr_arr[0] = uri != null ? uri : ""; + ptr_arr[1] = interpretation != null ? interpretation : ""; + ptr_arr[2] = manifestation != null ? manifestation : ""; + ptr_arr[3] = origin != null ? origin : ""; + ptr_arr[4] = mimetype != null ? mimetype : ""; + ptr_arr[5] = text != null ? text : ""; + ptr_arr[6] = storage != null ? storage : ""; + ptr_arr[7] = current_uri != null ? current_uri : ""; + return new Variant.strv ((string[]) ptr_arr); + /* The NICE version */ + /* + var vb = new VariantBuilder (new VariantType ("as")); + vb.add ("s", uri ?? ""); + vb.add ("s", interpretation ?? ""); + vb.add ("s", manifestation ?? ""); + vb.add ("s", origin ?? ""); + vb.add ("s", mimetype ?? ""); + vb.add ("s", text ?? ""); + vb.add ("s", storage ?? ""); + vb.add ("s", current_uri ?? ""); + + return vb.end (); + */ + } + + public bool matches_template (Subject template_subject) + { + /** + Return True if this Subject matches *subject_template*. Empty + fields in the template are treated as wildcards. + Interpretations and manifestations are also matched if they are + children of the types specified in `subject_template`. + */ + if (!check_field_match (this.uri, template_subject.uri, false, true)) + return false; + if (!check_field_match (this.current_uri, template_subject.current_uri, false, true)) + return false; + if (!check_field_match (this.interpretation, template_subject.interpretation, true)) + return false; + if (!check_field_match (this.manifestation, template_subject.manifestation, true)) + return false; + if (!check_field_match (this.origin, template_subject.origin, false, true)) + return false; + if (!check_field_match (this.mimetype, template_subject.mimetype, false, true)) + return false; + + return true; + } + + } + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/index.vala b/libzeitgeist/index.vala new file mode 100644 index 0000000..fee98b6 --- /dev/null +++ b/libzeitgeist/index.vala @@ -0,0 +1,215 @@ +/* + * Copyright © 2012 Canonical Ltd. + * By Siegfried-A. Gevatter + * + * Based upon a C implementation (© 2010-2012 Canonical Ltd) by: + * Mikkel Kamstrup Erlandsen + * Michal Hruby + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + +/** + * Query the Zeitgeist Full Text Search Extension + * + * include: zeitgeist.h + */ +public class Index : QueuedProxyWrapper +{ + private RemoteSimpleIndexer proxy; + + /** + * Create a new index that interfaces with the default event index of the + * Zeitgeist daemon. + * + * Create a new #ZeitgeistIndex instance. The index will start to connect + * to Zeitgeist asynchronously. You can however start calling methods on + * the returned instance immediately, any method calls issued before the + * connection has been established will simply be queued and executed once + * the connection is up. + * + * Returns: A reference to a newly allocated index. Free with g_object_unref(). + */ + public Index () + { + Bus.get_proxy (BusType.SESSION, + Utils.ENGINE_DBUS_NAME, "/org/gnome/zeitgeist/index/activity", 0, + null, (obj, res) => + { + try + { + proxy = Bus.get_proxy.end (res); + proxy_acquired (proxy); + } + catch (IOError err) + { + critical ("Unable to connect to Zeitgeist FTS: %s", + err.message); + proxy_unavailable(); + } + }); + } + + protected override void on_connection_established () + { + } + + protected override void on_connection_lost () { + } + + /** + * Perform a full text search possibly restricted to a #ZeitgeistTimeRange + * and/or set of event templates. + * + * The default boolean operator is %AND. Thus the query + * foo bar will be interpreted as + * foo AND bar. To exclude a term from the result + * set prepend it with a minus sign - eg foo -bar. + * Phrase queries can be done by double quoting the string + * "foo is a bar". You can truncate terms by appending + * a *. + * + * There are a few keys you can prefix to a term or phrase to search within + * a specific set of metadata. They are used like + * key:value. The keys name and + * title search strictly within the text field of the + * event subjects. The key app searches within the + * application name or description that is found in the actor attribute of + * the events. Lastly you can use the site key to search + * within the domain name of the subject URIs. + * + * You can also control the results with the boolean operators + * AND and OR and you may + * use brackets, ( and ), to control the operator precedence. + * + * FIXME: how do we put documentation into _finish? + * The total hit count of the query will be available via the returned + * result set by calling zeitgeist_result_set_estimated_matches(). This will + * often be bigger than the actual number of events held in the result set, + * which is limited by the @num_events parameter passed to + * zeitgeist_index_search(). + * + * @param self The #ZeitgeistIndex you want to query + * @param query The search string to send to Zeitgeist + * @param time_range Restrict matched events to ones within this time + * range. If you are not interested in restricting the timerange pass + * zeitgeist_time_range_new_anytime() as Zeitgeist will detect + * this and optimize the query accordingly + * @param event_templates Restrict matches events to ones matching these + * templates + * @param offset Offset into the result set to read events from + * @param num_events Maximal number of events to retrieve + * @param result_type The #ZeitgeistResultType determining the sort order. + * You may pass #ZEITGEIST_RESULT_TYPE_RELEVANCY to this + * method to have the results ordered by relevancy calculated + * in relation to @query + * @param cancellable A #GCancellable used to cancel the call or %NULL + * @param callback A #GAsyncReadyCallback to invoke when the search results + * are ready + * @param user_data User data to pass back with @callback + */ + public async ResultSet search ( + string query, + TimeRange time_range, + GenericArray event_templates, + uint32 offset, + uint32 num_events, + ResultType result_type, + Cancellable? cancellable=null) throws Error + { + yield wait_for_proxy (search.callback); + + Variant result; + uint matches; + + yield proxy.search (query, time_range.to_variant (), + Events.to_variant (event_templates), offset, num_events, + result_type, out result, out matches, cancellable); + + return new SimpleResultSet (Events.from_variant (result), matches); + } + + /** + * Perform a full text search possibly restricted to a #ZeitgeistTimeRange + * and/or set of event templates. As opposed to zeitgeist_index_search(), + * this call will also return numeric relevancies of the events + * in the #ZeitgeistResultSet. + * + * See zeitgeist_index_search() for more details on how to create the + * query. + * + * @param self The #ZeitgeistIndex you want to query + * @param query The search string to send to Zeitgeist + * @param time_range Restrict matched events to ones within this time + * range. If you are not interested in restricting the timerange pass + * zeitgeist_time_range_new_anytime() as Zeitgeist will detect + * this and optimize the query accordingly + * @param event_templates Restrict matched events to ones matching these + * templates + * @param storage_state Filter the events by availability of the storage + * medium. + * @param offset Offset into the result set to read events from + * @param num_events Maximal number of events to retrieve + * @param result_type The #ZeitgeistResultType determining the sort order + * You may pass #ZEITGEIST_RESULT_TYPE_RELEVANCY to this method to + * have the results ordered by relevancy calculated in relation + * to "query" + * @param cancellable A #GCancellable used to cancel the call or %NULL + * @param callback A #GAsyncReadyCallback to invoke when the searc + * results are ready + * @param user_data User data to pass back with @callback + */ + public async ResultSet search_with_relevancies ( + string query, + TimeRange time_range, + GenericArray event_templates, + StorageState storage_state, + uint32 offset, + uint32 num_events, + ResultType result_type, + Cancellable? cancellable=null, + out double[] relevancies) throws Error + { + yield wait_for_proxy (search_with_relevancies.callback); + + Variant result; + Variant relevancies_variant; + uint matches; + + yield proxy.search_with_relevancies (query, time_range.to_variant (), + Events.to_variant (event_templates), storage_state, offset, + num_events, result_type, out relevancies_variant, out result, + out matches, cancellable); + + relevancies = new double[relevancies_variant.n_children ()]; + VariantIter iter = relevancies_variant.iterator (); + for (int i = 0; i < iter.n_children (); ++i) + { + double relevancy; + iter.next ("d", out relevancy); + relevancies[i] = relevancy; + } + + return new SimpleResultSet (Events.from_variant (result), matches); + } + +} + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/log.vala b/libzeitgeist/log.vala new file mode 100644 index 0000000..e01f91a --- /dev/null +++ b/libzeitgeist/log.vala @@ -0,0 +1,256 @@ +/* + * Copyright © 2012 Canonical Ltd. + * By Siegfried-A. Gevatter + * + * Based upon a C implementation (© 2010-2012 Canonical Ltd) by: + * Mikkel Kamstrup Erlandsen + * Michal Hruby + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + +/** + * SECTION:zeitgeist-log + * + * Primary access point for talking to the Zeitgeist daemon + * + * include: zeitgeist.h + * + * #ZeitgeistLog encapsulates the low level access to the Zeitgeist daemon. + * You can use it to manage the log by inserting and deleting entries as well + * as do queries on the logged data. + * + * It's important to realize that the #ZeitgeistLog class does not expose + * any API that does synchronous communications with the message bus - + * everything is asynchronous. To ease development some of the methods have + * variants that are "fire and forget" ignoring the normal return value, so + * that callbacks does not have to be set up. + */ +public class Log : QueuedProxyWrapper +{ + private static Log default_instance; + + private RemoteLog proxy; + private Variant? engine_version; + private HashTable monitors; + + public Log () + { + warning ("hi! requesting proxy..."); + monitors = new HashTable(direct_hash, direct_equal); + Bus.get_proxy (BusType.SESSION, Utils.ENGINE_DBUS_NAME, + Utils.ENGINE_DBUS_PATH, 0, null, (obj, res) => + { + warning ("ok! proxy acquired!"); + try + { + proxy = Bus.get_proxy.end (res); + proxy_acquired (proxy); + } + catch (IOError err) + { + critical ("Unable to connect to Zeitgeist: %s", + err.message); + proxy_unavailable(); + } + }); + } + + public static Log get_default () + { + if (default_instance == null) + default_instance = new Log (); + return default_instance; + } + + protected override void on_connection_established () + { + // Reinstate all active monitors + foreach (unowned Monitor monitor in monitors.get_keys ()) + { + reinstall_monitor (monitor); + } + + // Update our cached version property + engine_version = proxy.version; + warn_if_fail (engine_version.get_type_string () == "(iii)"); + } + + protected override void on_connection_lost () { + } + + /* + public async void insert_events (Cancellable? cancellable=null, ...) + throws Error + { + var lalala = va_list (); + // FIXME: variadic async functions are broken! This generates: + // static gboolean zeitgeist_log_insert_events_co (ZeitgeistLogInsertEventsData* _data_) { + // ... + // va_start (_data_->lalala, cancellable); + // ... + // } + yield insert_events_valist (cancellable, lalala); + } + + public async void insert_events_valist (Cancellable? cancellable=null, + va_list events) throws Error + { + Event event = events.arg (); + } + */ + + /* + public async void insert_events_no_reply (...) throws Error + { + } + */ + + public async void insert_events_from_ptrarray (GenericArray events, + Cancellable? cancellable=null) throws Error + { + yield wait_for_proxy (insert_events_from_ptrarray.callback); + yield proxy.insert_events (Events.to_variant (events), cancellable); + } + + public async ResultSet find_events ( + TimeRange time_range, + GenericArray event_templates, + StorageState storage_state, + uint32 num_events, + ResultType result_type, + Cancellable? cancellable=null) throws Error + { + yield wait_for_proxy (find_events.callback); + var result = yield proxy.find_events (time_range.to_variant (), + Events.to_variant (event_templates), storage_state, + num_events, result_type, cancellable); + return new SimpleResultSet (Events.from_variant (result)); + } + + public async uint32[] find_event_ids ( + TimeRange time_range, + GenericArray event_templates, + StorageState storage_state, + uint32 num_events, + ResultType result_type, + Cancellable? cancellable=null) throws Error + { + yield wait_for_proxy (find_event_ids.callback); + return yield proxy.find_event_ids (time_range.to_variant (), + Events.to_variant (event_templates), storage_state, + num_events, result_type, cancellable); + } + + public async ResultSet get_events (uint32[] event_ids, + Cancellable? cancellable=null) throws Error + { + yield wait_for_proxy (get_events.callback); + var result = yield proxy.get_events (event_ids, cancellable); + return new SimpleResultSet (Events.from_variant (result)); + } + + public async void find_related_uris ( + TimeRange time_range, + GenericArray event_templates, + GenericArray result_event_templates, + StorageState storage_state, + uint32 num_events, + ResultType result_type, + Cancellable? cancellable=null) throws Error + { + } + + public async void delete_events (uint32[] event_ids, + Cancellable? cancellable=null) throws Error + { + yield wait_for_proxy (delete_events.callback); + yield proxy.delete_events (event_ids, cancellable); + } + + public async void quit (Cancellable? cancellable=null) throws Error + { + yield wait_for_proxy (quit.callback); + yield proxy.quit (cancellable); + } + + public async void install_monitor (Monitor monitor) throws Error + { + // FIXME + //monitor.destroy.connect (() => {}); + + // Save the monitor's registration id (0 = not registered) + monitors.insert(monitor, 0); + + if (is_connected) + install_monitor (monitor); + } + + private void reinstall_monitor (Monitor monitor) + requires (is_connected) + { + if (monitors.lookup (monitor) == 0) + { + // FIXME: make async! + DBusConnection conn = Bus.get_sync (BusType.SESSION); + + uint registration_id = conn.register_object ( + monitor.get_path (), monitor); + monitors.insert (monitor, registration_id); + } + + proxy.install_monitor ( + monitor.get_path (), + monitor.get_time_range ().to_variant (), + Events.to_variant (monitor.get_templates ())); + } + + public async void remove_monitor (Monitor monitor) throws Error + { + } + + // FIXME: + // monitor_removed_cb: + // unregister_object() + + /** + * Gets version of currently running Zeitgeist daemon. + * + * This method will return the version of Zeitgeist daemon this instance is + * connected to. If you call this method right after zeitgeist_log_new(), + * only zeros will be returned, a valid version number will only be returned + * once this instance successfully connected to the Zeitgeist daemon - ie. + * the value of the "is-connected" property must be TRUE (you can connect + * to the "notify::is-connected" signal otherwise). + * + * @param self A #ZeitgeistLog instance + * @param major Location for the major version + * @param minor Location for the minor version + * @param micro: Location for the micro version + */ + public void get_version (out int major, out int minor, out int micro) { + major = minor = micro = 0; + if (engine_version != null) + engine_version.get ("(iii)", &major, &minor, µ); + } + +} + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/mimetype.vala b/libzeitgeist/mimetype.vala new file mode 100644 index 0000000..b8b0263 --- /dev/null +++ b/libzeitgeist/mimetype.vala @@ -0,0 +1,367 @@ +/* datamodel.vala + * + * Copyright © 2011 Collabora Ltd. + * By Siegfried-Angel Gevatter Pujals + * Copyright © 2010 Canonical, Ltd. + * By Mikkel Kamstrup Erlandsen + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +using Zeitgeist; + +namespace Zeitgeist +{ + + private static bool mimetypes_loaded = false; + private static bool schemes_loaded = false; + + private static HashTable? mimetypes = null; + private static SList mimetypes_regexs; + private static SList schemes; + + [Compact] + private class MimeRegex + { + public Regex regex; + public string interpretation_uri; + + public MimeRegex (string mimetype_regex, string interpretation_uri) + throws RegexError + { + this.regex = new Regex (mimetype_regex, 0, 0); + this.interpretation_uri = interpretation_uri; + } + } + + [Compact] + private class UriScheme + { + public string uri_scheme; + public string manifestation_uri; + + public UriScheme (string uri_scheme, string manifestation_uri) + { + this.uri_scheme = uri_scheme; + this.manifestation_uri = manifestation_uri; + } + } + + /** + * zeitgeist_register_mimetype: + * + * Associate a MIME-type with a given interpretation type. Registered + * MIME-types can be looked up with zeitgeist_interpretation_for_mimetype(). + * + * You can register a regular expression as mimetype if instead of this + * function you invoke zeitgeist_register_mimetype_regex(). + * + * MIME-types are first looked up by their exact name and then if none is + * found the regular expressions will be checked as fallbacks. + * + * This library will install a wide range a common mimetypes for you, so + * unless you have very specific needs you will normally not have to call + * this function. + * + * FIXME: link to list of interpretations + * + * @param mimetype A MIME-type string. Eg. //text/plain// + * @param interpretation_uri A URI defining the subject interpretation + * type to associate with "mimetype" + */ + public void register_mimetype (string mimetype, string interpretation_uri) + { + if (mimetypes == null) + mimetypes = new HashTable(str_hash, str_equal); + + mimetypes.insert (mimetype, interpretation_uri); + } + + /** + * zeitgeist_register_mimetype_regex: + * + * Associate a range of MIME-types with a given interpretation type. + * Registered MIME-types can be looked up with + * zeitgeist_interpretation_for_mimetype(). + * + * If you only need to register one specific MIME-type, it is more efficient + * to use zeitgeist_register_mimetype() instead of this function. + * + * MIME-types are first looked up by their exact name and then if none is + * found the regular expressions will be checked as fallbacks. + * + * This library will install a wide range a common mimetypes for you, so + * unless you have very specific needs you will normally not have to call + * this function. + * + * FIXME: link to list of interpretations + * + * @param mimetype A regular expression matching a certain range of + * mimetypes. Eg. //text/.* // to match all //text// subtypes. + * @param interpretation_uri A URI defining the subject interpretation + * type to associate with the matched MIME-types + */ + public void register_mimetype_regex (string mimetype_regex, + string interpretation_uri) + { + try + { + var entry = new MimeRegex (mimetype_regex, interpretation_uri); + mimetypes_regexs.append ((owned) entry); + } catch (RegexError e) { + warning ("Couldn't register mimetype regex: %s", e.message); + } + } + + /** + * zeitgeist_interpretation_for_mimetype: + * + * Look up the subject interpretation type associated with @mimetype. + * FIXME: link to list of interpretations + * + * @param mimetype A MIME-type string. Eg. //text/plain// + * + * @return A URI defining the subject interpretation type associated with + * "mimetype" or %NULL in case "mimetype" is unknown + */ + public unowned string? interpretation_for_mimetype (string mimetype) + { + ensure_mimetypes_loaded (); + + unowned string? interpretation = mimetypes.lookup (mimetype); + if (interpretation != null) + return interpretation; + + foreach (unowned MimeRegex mime_regex in mimetypes_regexs) + { + if (mime_regex.regex.match (mimetype, 0)) + return mime_regex.interpretation_uri; + } + + return null; + } + + /** + * zeitgeist_register_uri_scheme: + * + * Associate a URI scheme with a given subject manifestation type. + * You can find the manifestation type of a given URI by passing it to + * zeitgeist_manifestation_for_uri(). + * + * This library will install a range a common URI schemes for you, so unless + * you have very specific needs you will normally not have to call this + * function. + * + * FIXME: link to list of manifestations + * + * @param uri_scheme A URI scheme such as //http:\/\/// + * @param manifestation_uri A URI defining the subject manifestation type + * to associate with "uri_scheme" + */ + public void register_uri_scheme (string uri_scheme, + string manifestation_type) + { + var scheme = new UriScheme (uri_scheme, manifestation_type); + schemes.append ((owned) scheme); + } + + /** + * zeitgeist_manifestation_for_uri + * + * Look up a subject manifestation type for a given URI. Eg. if you pass in + * //file:\/\/\/tmp/foo.txt// you will get back + * ZEITGEIST_NFO_FILE_DATA_OBJECT. + * + * FIXME: link to list of manifestations + * + * @param uri An URI + * + * @return A subject manifestation type for @uri or %NULL in case no + * suitable manifestation type is known + */ + public unowned string? manifestation_for_uri (string uri) { + ensure_schemes_loaded (); + + foreach (unowned UriScheme scheme in schemes) + { + if (uri.has_prefix (scheme.uri_scheme)) + return scheme.manifestation_uri; + } + + return null; + } + + private static void ensure_mimetypes_loaded () + { + if (mimetypes_loaded) + return; + + try { + register_mimetype ("application/ecmascript", NFO.SOURCE_CODE); + register_mimetype ("application/javascript", NFO.SOURCE_CODE); + register_mimetype ("application/json", NFO.SOURCE_CODE); + register_mimetype ("application/ms-excel", NFO.SPREADSHEET); + register_mimetype ("application/ms-powerpoint", NFO.PRESENTATION); + register_mimetype ("application/msexcel", NFO.SPREADSHEET); + register_mimetype ("application/msword", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype ("application/ogg", NFO.AUDIO); + register_mimetype ("application/pdf", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype ("application/postscript", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype ("application/ps", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype ("application/rtf", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype ("application/soap+xml", NFO.SOURCE_CODE); + register_mimetype ("application/vnd.corel-draw", NFO.VECTOR_IMAGE); + register_mimetype ("application/vnd.ms-excel", NFO.SPREADSHEET); + register_mimetype ("application/vnd.ms-powerpoint", NFO.PRESENTATION); + register_mimetype ("application/x-7z-compressed", NFO.ARCHIVE); + register_mimetype ("application/x-abiword", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype ("application/x-applix-presents", NFO.PRESENTATION); + register_mimetype ("application/x-applix-spreadsheet", NFO.SPREADSHEET); + register_mimetype ("application/x-applix-word", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype ("application/x-archive", NFO.ARCHIVE); + register_mimetype ("application/x-bzip", NFO.ARCHIVE); + register_mimetype ("application/x-bzip-compressed-tar", NFO.ARCHIVE); + register_mimetype ("application/x-cd-image", NFO.FILESYSTEM_IMAGE); + register_mimetype ("application/x-compressed-tar", NFO.ARCHIVE); + register_mimetype ("application/x-csh", NFO.SOURCE_CODE); + register_mimetype ("application/x-deb", NFO.SOFTWARE); + register_mimetype ("application/x-designer", NFO.SOURCE_CODE); + register_mimetype ("application/x-desktop", NFO.SOFTWARE); + register_mimetype ("application/x-dia-diagram", NFO.SOURCE_CODE); + register_mimetype ("application/x-executable", NFO.SOFTWARE); + register_mimetype ("application/x-fluid", NFO.SOURCE_CODE); + register_mimetype ("application/x-glade", NFO.SOURCE_CODE); + register_mimetype ("application/x-gnucash", NFO.SPREADSHEET); + register_mimetype ("application/x-gnumeric", NFO.SPREADSHEET); + register_mimetype ("application/x-gzip", NFO.ARCHIVE); + register_mimetype ("application/x-java-archive", NFO.SOURCE_CODE); + register_mimetype ("application/x-javascript", NFO.SOURCE_CODE); + register_mimetype ("application/x-killustrator", NFO.VECTOR_IMAGE); + register_mimetype ("application/x-kpresenter", NFO.PRESENTATION); + register_mimetype ("application/x-kspread", NFO.SPREADSHEET); + register_mimetype ("application/x-kword", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype ("application/x-lzma", NFO.ARCHIVE); + register_mimetype ("application/x-lzma-compressed-tar", NFO.ARCHIVE); + register_mimetype ("application/x-m4", NFO.SOURCE_CODE); + register_mimetype ("application/x-ms-dos-executable", NFO.SOFTWARE); + register_mimetype ("application/x-perl", NFO.SOURCE_CODE); + register_mimetype ("application/x-php", NFO.SOURCE_CODE); + register_mimetype ("application/x-rpm", NFO.SOFTWARE); + register_mimetype ("application/x-ruby", NFO.SOURCE_CODE); + register_mimetype ("application/x-shellscript", NFO.SOURCE_CODE); + register_mimetype ("application/x-shockwave-flash", NFO.EXECUTABLE); + register_mimetype ("application/x-sql", NFO.SOURCE_CODE); + register_mimetype ("application/x-stuffit", NFO.ARCHIVE); + register_mimetype ("application/xhtml+xml", NFO.SOURCE_CODE); + register_mimetype ("application/xml", NFO.SOURCE_CODE); + register_mimetype ("application/xml-dtd", NFO.SOURCE_CODE); + register_mimetype ("application/zip", NFO.ARCHIVE); + register_mimetype ("audio/x-scpls", NFO.MEDIA_LIST); + register_mimetype ("image/gif", NFO.RASTER_IMAGE); + register_mimetype ("image/jpeg", NFO.RASTER_IMAGE); + register_mimetype ("image/pjpeg", NFO.RASTER_IMAGE); + register_mimetype ("image/png", NFO.RASTER_IMAGE); + register_mimetype ("image/svg+xml", NFO.VECTOR_IMAGE); + register_mimetype ("image/tiff", NFO.RASTER_IMAGE); + register_mimetype ("image/vnd.microsoft.icon", NFO.ICON); + register_mimetype ("image/x-xcf", NFO.RASTER_IMAGE); + register_mimetype ("inode/directory", NFO.FOLDER); + register_mimetype ("message/alternative", NMO.EMAIL); + register_mimetype ("message/partial", NMO.EMAIL); + register_mimetype ("message/related", NMO.EMAIL); + register_mimetype ("text/css", NFO.SOURCE_CODE); + register_mimetype ("text/csv", NFO.TEXT_DOCUMENT); + register_mimetype ("text/html", NFO.HTML_DOCUMENT); + register_mimetype ("text/javascript", NFO.SOURCE_CODE); + register_mimetype ("text/plain", NFO.TEXT_DOCUMENT); + register_mimetype ("text/vcard", NCO.CONTACT); + register_mimetype ("text/x-c", NFO.SOURCE_CODE); + register_mimetype ("text/x-c++", NFO.SOURCE_CODE); + register_mimetype ("text/x-c++src", NFO.SOURCE_CODE); + register_mimetype ("text/x-chdr", NFO.SOURCE_CODE); + register_mimetype ("text/x-copying", NFO.SOURCE_CODE); + register_mimetype ("text/x-credits", NFO.SOURCE_CODE); + register_mimetype ("text/x-csharp", NFO.SOURCE_CODE); + register_mimetype ("text/x-csrc", NFO.SOURCE_CODE); + register_mimetype ("text/x-dsrc", NFO.SOURCE_CODE); + register_mimetype ("text/x-eiffel", NFO.SOURCE_CODE); + register_mimetype ("text/x-gettext-translation", NFO.SOURCE_CODE); + register_mimetype ("text/x-gettext-translation-template", NFO.SOURCE_CODE); + register_mimetype ("text/x-haskell", NFO.SOURCE_CODE); + register_mimetype ("text/x-idl", NFO.SOURCE_CODE); + register_mimetype ("text/x-java", NFO.SOURCE_CODE); + register_mimetype ("text/x-jquery-tmpl", NFO.SOURCE_CODE); + register_mimetype ("text/x-latex", NFO.SOURCE_CODE); + register_mimetype ("text/x-lisp", NFO.SOURCE_CODE); + register_mimetype ("text/x-lua", NFO.SOURCE_CODE); + register_mimetype ("text/x-m4", NFO.SOURCE_CODE); + register_mimetype ("text/x-makefile", NFO.SOURCE_CODE); + register_mimetype ("text/x-objcsrc", NFO.SOURCE_CODE); + register_mimetype ("text/x-ocaml", NFO.SOURCE_CODE); + register_mimetype ("text/x-pascal", NFO.SOURCE_CODE); + register_mimetype ("text/x-patch", NFO.SOURCE_CODE); + register_mimetype ("text/x-python", NFO.SOURCE_CODE); + register_mimetype ("text/x-sql", NFO.SOURCE_CODE); + register_mimetype ("text/x-tcl", NFO.SOURCE_CODE); + register_mimetype ("text/x-tex", NFO.SOURCE_CODE); + register_mimetype ("text/x-troff", NFO.SOURCE_CODE); + register_mimetype ("text/x-vala", NFO.SOURCE_CODE); + register_mimetype ("text/x-vhdl", NFO.SOURCE_CODE); + register_mimetype ("text/xml", NFO.SOURCE_CODE); + + register_mimetype_regex (".*/x-dvi", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype_regex ("application/vnd.ms-excel.*", NFO.SPREADSHEET); + register_mimetype_regex ("application/vnd.ms-powerpoint.*", NFO.PRESENTATION); + register_mimetype_regex ("application/vnd.oasis.opendocument.graphics.*", NFO.VECTOR_IMAGE); + register_mimetype_regex ("application/vnd.oasis.opendocument.presentation.*", NFO.PRESENTATION); + register_mimetype_regex ("application/vnd.oasis.opendocument.spreadsheet.*", NFO.SPREADSHEET); + register_mimetype_regex ("application/vnd.oasis.opendocument.text.*", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype_regex ("application/vnd.openxmlformats-officedocument.presentationml.presentation.*", NFO.PRESENTATION); + register_mimetype_regex ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.*", NFO.SPREADSHEET); + register_mimetype_regex ("application/vnd.openxmlformats-officedocument.wordprocessingml.document.*", NFO.PAGINATED_TEXT_DOCUMENT); + register_mimetype_regex ("application/vnd\\..*", NFO.DOCUMENT); + register_mimetype_regex ("application/x-applix-.*", NFO.DOCUMENT); + register_mimetype_regex ("audio/.*", NFO.AUDIO); + register_mimetype_regex ("image/.*", NFO.IMAGE); + register_mimetype_regex ("video/.*", NFO.VIDEO); + } catch (RegexError e) { + // This won't happen. + assert (false); + } + + mimetypes_loaded = true; + } + + private static void ensure_schemes_loaded () + { + if (schemes_loaded) + return; + + register_uri_scheme ("file://", NFO.FILE_DATA_OBJECT); + register_uri_scheme ("http://", NFO.WEB_DATA_OBJECT); + register_uri_scheme ("https://", NFO.WEB_DATA_OBJECT); + register_uri_scheme ("ssh://", NFO.REMOTE_DATA_OBJECT); + register_uri_scheme ("sftp://", NFO.REMOTE_DATA_OBJECT); + register_uri_scheme ("ftp://", NFO.REMOTE_DATA_OBJECT); + register_uri_scheme ("dav://", NFO.REMOTE_DATA_OBJECT); + register_uri_scheme ("davs://", NFO.REMOTE_DATA_OBJECT); + register_uri_scheme ("smb://", NFO.REMOTE_DATA_OBJECT); + + schemes_loaded = true; + } + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/monitor.vala b/libzeitgeist/monitor.vala new file mode 100644 index 0000000..762bc81 --- /dev/null +++ b/libzeitgeist/monitor.vala @@ -0,0 +1,156 @@ +/* + * Copyright © 2012 Canonical Ltd. + * By Siegfried-A. Gevatter + * + * Based upon a C implementation (© 2010 Canonical Ltd) by: + * Mikkel Kamstrup Erlandsen + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +/** + * SECTION:zeitgeist-monitor + * + * Listens for updates to the Zeitgeist event log + * + * include: zeitgeist.h + * + * A #ZeitgeistMonitor listens for updates to the Zeitgeist event log + * matching a given set of templates and with timestamps in some predefined + * time range. + * + * A monitor must be installed into the running Zeitgeist daemon by calling + * zeitgeist_log_install_monitor(). The monitor will not emit any of the + * ::events-added or ::events-deleted signals before this. + */ + +namespace Zeitgeist +{ + +public class Monitor : Object, RemoteMonitor +{ + + private static int monitor_counter = 0; + + private TimeRange time_range; + private GenericArray templates; + + // Client side D-Bus path the monitor lives under + private string monitor_path; + + /** + * ZeitgeistMonitor::events-inserted: + * + * Emitted when events matching the event templates and with timestamps + * within the time range of the monitor has been inserted into the log. + * + * @param time_range A #ZeitgeistTimeRange that specifies the minimum and + * maximum of the timestamps in @events + * @param events A #ZeitgeistResultSet holding the "ZeitgeistEvent"s that + * have been inserted into the log + */ + public signal void events_inserted (TimeRange time_range, + ResultSet events); + + /** + * ZeitgeistMonitor::events-deleted: + * + * Emitted when events with timestamps within the time range of this + * monitor have been deleted from the log. Note that the deleted events + * may not match the event templates for the monitor. + * + * @param time_range A #ZeitgeistTimeRange that specifies the minimum and + * maximum timestamps of the deleted events + * @param event_ids A #GArray of #guint32s holding the IDs of the + * deleted events + */ + public signal void events_deleted (TimeRange time_range, + uint32[] event_ids); + + /** + * zeitgeist_monitor_new + * + * Create a new monitor. Before you can receive signals from the monitor you + * need to install it in the running Zeitgeist daemon by calling + * zeitgeist_log_install_monitor(). + * + * @param time_range The monitor will only listen for events with + * timestamps within this time range. Note that it is legal for + * applications to insert events that are "in the past". + * @param event_templates A #GPtrArray of #ZeitgeistEvents. + * Only listen for events that match any of these templates. + * + * @return A reference to a newly allocated monitor + */ + public Monitor (TimeRange time_range, GenericArray event_templates) + { + this.time_range = time_range; + this.templates = event_templates; + this.monitor_path = "/org/gnome/zeitgeist/monitor/%i".printf ( + monitor_counter++); + } + + public TimeRange get_time_range () + { + return time_range; + } + + public GenericArray get_templates () + { + return templates; + } + + public ObjectPath get_path () + { + return new ObjectPath (monitor_path); + } + + public async void notify_insert ( + Variant time_range, + Variant events) + { + try + { + SimpleResultSet result_set = new SimpleResultSet ( + Events.from_variant (events)); + events_inserted (new TimeRange.from_variant (time_range), + result_set); + } + catch (DataModelError err) + { + warning ("%s", err.message); + } + } + + public async void notify_delete ( + Variant time_range, + uint32[] event_ids) + { + try + { + events_deleted (new TimeRange.from_variant (time_range), + event_ids); + } + catch (DataModelError err) + { + warning ("%s", err.message); + } + } + +} + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/ontology-uris.vala.in b/libzeitgeist/ontology-uris.vala.in new file mode 100644 index 0000000..79ca408 --- /dev/null +++ b/libzeitgeist/ontology-uris.vala.in @@ -0,0 +1,22 @@ +/* ontology-uris.vala + * + * Copyright © 2009-2011 The Zeitgeist Team + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +// *insert-auto-generated-code* + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/ontology.vala.in b/libzeitgeist/ontology.vala.in new file mode 100644 index 0000000..f8250cc --- /dev/null +++ b/libzeitgeist/ontology.vala.in @@ -0,0 +1,172 @@ +/* ontology.vala + * + * Copyright © 2011 Collabora Ltd. + * By Seif Lotfy + * By Siegfried-Angel Gevatter Pujals + * Copyright © 2011 Michal Hruby + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + + namespace Symbol + { + private static HashTable all_symbols = null; + private static bool initialized = false; + + public static unowned string get_display_name (string symbol_uri) + { + initialize_symbols (); + + var symbol = all_symbols.lookup (symbol_uri); + if (symbol == null) return symbol_uri; + + return symbol.display_name; + } + + public static unowned string get_description(string symbol_uri) + { + initialize_symbols (); + + var symbol = all_symbols.lookup (symbol_uri); + if (symbol == null) return ""; + + return symbol.description; + } + + public static List get_all_parents(string symbol_uri) + { + initialize_symbols (); + + var results = new List (); + var symbol = all_symbols.lookup (symbol_uri); + if (symbol == null) return results; + + foreach (unowned string uri in symbol.parents) + { + results.append (uri); + // Recursively get the other parents + foreach (string parent_uri in get_all_parents (uri)) + if (results.index (parent_uri) > -1) + results.append (parent_uri); + } + + return results; + } + + public static List get_all_children (string symbol_uri) + { + initialize_symbols (); + + var results = new List (); + var symbol = all_symbols.lookup (symbol_uri); + if (symbol == null) return results; + + foreach (unowned string uri in symbol.all_children) + results.append (uri); + + return results; + } + + public static List get_children (string symbol_uri) + { + initialize_symbols (); + var results = new List (); + var symbol = all_symbols.lookup (symbol_uri); + if (symbol == null) return results; + + foreach (unowned string uri in symbol.children) + results.append(uri); + + return results; + } + + public static List get_parents (string symbol_uri) + { + initialize_symbols (); + + var results = new List(); + var symbol = all_symbols.lookup (symbol_uri); + if (symbol == null) return results; + + foreach (unowned string uri in symbol.parents) + results.append (uri); + + return results; + } + + public static bool is_a (string symbol_uri, string parent_uri) + { + initialize_symbols (); + + foreach (unowned string uri in get_all_parents (symbol_uri)) + if (parent_uri == uri) + return true; + return false; + } + + private static void initialize_symbols () + { + if (initialized) return; + initialized = true; + // *insert-auto-generated-code* + } + + } + + private class Symbol.Info + { + public List parents; + public List children; + public List all_children; + public string uri; + public string display_name; + public string description; + + private Info (string uri, string display_name, string description, + string[] parents, string[] children, string[] all_children) + { + this.uri = uri; + this.display_name = display_name; + this.description = description; + this.parents = new List (); + for (int i = 0; i < parents.length; i++) + this.parents.append (parents[i]); + this.children = new List (); + for (int i = 0; i < children.length; i++) + this.children.append (children[i]); + this.all_children = new List (); + for (int i = 0; i < all_children.length; i++) + this.all_children.append (all_children[i]); + } + + internal static void register (string uri, string display_name, + string description, string[] parents, string[] children, + string[] all_children) + { + if (all_symbols == null) + all_symbols = new HashTable (str_hash, str_equal); + Info symbol = new Info (uri, display_name, description, + parents, children, all_children); + all_symbols.insert (uri, symbol); + } + + } + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/queued-proxy-wrapper.vala b/libzeitgeist/queued-proxy-wrapper.vala new file mode 100644 index 0000000..de7578b --- /dev/null +++ b/libzeitgeist/queued-proxy-wrapper.vala @@ -0,0 +1,95 @@ +/* + * Copyright © 2012 Canonical Ltd. + * By Siegfried-A. Gevatter + * + * Based upon a C implementation (© 2010-2012 Canonical Ltd) by: + * Mikkel Kamstrup Erlandsen + * Michal Hruby + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + +// FIXME: private or something +public abstract class QueuedProxyWrapper : Object +{ + public bool proxy_created { get; private set; default = false; } + public bool is_connected { get; private set; default = false; } + + protected SList method_dispatch_queue; + + protected class QueuedMethod + { + + public SourceFunc queued_method { public /*owned*/ get; private /*owned*/ set; } + + public QueuedMethod (SourceFunc callback) + { + queued_method = callback; + } + + } + + protected void proxy_acquired(Object proxy) { + is_connected = true; + proxy_created = true; + proxy.notify["g-name-owner"].connect (name_owner_changed); + on_connection_established (); + process_queued_methods (); + } + + protected void proxy_unavailable() { + // FIXME: process_queued_methods() with manual error callbacks + } + + protected void process_queued_methods () + { + warning ("Processing queued methods..."); + method_dispatch_queue.reverse (); + foreach (QueuedMethod m in method_dispatch_queue) + m.queued_method (); + method_dispatch_queue = null; + } + + protected void name_owner_changed (ParamSpec pspec) + { + string? name_owner = null; // FIXME: .get_name_owner (); + this.is_connected = name_owner != null; + + if (this.is_connected) + on_connection_established (); + else + on_connection_lost (); + } + + protected abstract void on_connection_established (); + protected abstract void on_connection_lost (); + + protected async void wait_for_proxy (SourceFunc callback) { + if (likely (proxy_created)) + return; + if (method_dispatch_queue == null) + method_dispatch_queue = new SList (); + method_dispatch_queue.prepend (new QueuedMethod (callback)); + yield; + } + +} + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/remote.vala b/libzeitgeist/remote.vala new file mode 100644 index 0000000..00e0f38 --- /dev/null +++ b/libzeitgeist/remote.vala @@ -0,0 +1,157 @@ +/* remote.vala + * + * Copyright © 2011-2012 Collabora Ltd. + * By Siegfried-Angel Gevatter Pujals + * Copyright © 2011 Michal Hruby + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + public struct VersionStruct + { + int major; + int minor; + int micro; + } + + [DBus (name = "org.gnome.zeitgeist.Log")] + public interface RemoteLog : Object + { + + [DBus (signature = "(xx)")] + public async abstract Variant delete_events ( + uint32[] event_ids, + Cancellable? cancellable=null, + BusName? sender=null + ) throws Error; + + public async abstract uint32[] find_event_ids ( + [DBus (signature = "(xx)")] Variant time_range, + [DBus (signature = "a(asaasay)")] Variant event_templates, + uint storage_state, uint num_events, uint result_type, + Cancellable? cancellable=null, BusName? sender=null + ) throws Error; + + [DBus (signature = "a(asaasay)")] + public async abstract Variant find_events ( + [DBus (signature = "(xx)")] Variant time_range, + [DBus (signature = "a(asaasay)")] Variant event_templates, + uint storage_state, uint num_events, uint result_type, + Cancellable? cancellable=null, BusName? sender=null + ) throws Error; + + public async abstract string[] find_related_uris ( + [DBus (signature = "(xx)")] Variant time_range, + [DBus (signature = "a(asaasay)")] Variant event_templates, + [DBus (signature = "a(asaasay)")] Variant result_event_templates, + uint storage_state, uint num_events, uint result_type, + BusName? sender=null + ) throws Error; + + [DBus (signature = "a(asaasay)")] + public async abstract Variant get_events ( + uint32[] event_ids, + Cancellable? cancellable=null, + BusName? sender=null + ) throws Error; + + public async abstract uint32[] insert_events ( + [DBus (signature = "a(asaasay)")] Variant events, + Cancellable? cancellable=null, + BusName? sender=null + ) throws Error; + + public async abstract void install_monitor ( + ObjectPath monitor_path, + [DBus (signature = "(xx)")] Variant time_range, + [DBus (signature = "a(asaasay)")] Variant event_templates, + BusName? owner=null + ) throws Error; + + public async abstract void remove_monitor ( + ObjectPath monitor_path, + BusName? owner=null + ) throws Error; + + public async abstract void quit ( + Cancellable? cancellable=null + ) throws Error; + + [DBus (name = "extensions")] + public abstract string[] extensions { owned get; } + + [DBus (name = "version")] + public abstract VersionStruct version { owned get; } + + } + + [DBus (name = "org.gnome.zeitgeist.Monitor")] + public interface RemoteMonitor : Object + { + + public async abstract void notify_insert ( + [DBus (signature = "(xx)")] Variant time_range, + [DBus (signature = "a(asaasay)")] Variant events + ) throws Error; + + public async abstract void notify_delete ( + [DBus (signature = "(xx)")] Variant time_range, + uint32[] event_ids + ) throws IOError; + + } + + [DBus (name = "org.gnome.zeitgeist.Index")] + public interface RemoteSimpleIndexer : Object + { + public abstract async void search ( + string query_string, + [DBus (signature = "(xx)")] Variant time_range, + [DBus (signature = "a(asaasay)")] Variant filter_templates, + uint offset, uint count, uint result_type, + [DBus (signature = "a(asaasay)")] out Variant events, + out uint matches, Cancellable? cancellable=null) throws Error; + public abstract async void search_with_relevancies ( + string query_string, + [DBus (signature = "(xx)")] Variant time_range, + [DBus (signature = "a(asaasay)")] Variant filter_templates, + uint storage_state, uint offset, uint count, uint result_type, + [DBus (signature = "a(asaasay)")] out Variant events, + out double[] relevancies, out uint matches, + Cancellable? cancellable=null) throws Error; + } + + /* FIXME: Remove this! Only here because of a bug in Vala (see ext-fts) */ + [DBus (name = "org.freedesktop.NetworkManager")] + internal interface NetworkManagerDBus : Object + { + [DBus (name = "state")] + public abstract uint32 state () throws IOError; + public signal void state_changed (uint32 state); + } + + /* FIXME: Remove this! Only here because of a bug in Vala (see ext-fts) */ + [DBus (name = "net.connman.Manager")] + internal interface ConnmanManagerDBus : Object + { + public abstract string get_state () throws IOError; + public signal void state_changed (string state); + } + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/result-set.vala b/libzeitgeist/result-set.vala new file mode 100644 index 0000000..f0add26 --- /dev/null +++ b/libzeitgeist/result-set.vala @@ -0,0 +1,132 @@ +/* + * Copyright © 2012 Canonical Ltd. + * By Siegfried-A. Gevatter + * + * Based upon a C implementation (© 2009 Canonical Ltd) by: + * Mikkel Kamstrup Erlandsen + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + +/** + * Cursor-like interface for results sets + * + * include: zeitgeist.h + * + * Interface for results returned by zeitgeist_log_find_events(), + * zeitgeist_log_get_events(), and zeitgeist_index_search(). + * + * This interface utilizes a cursor-like metaphor. You advance the cursor + * by calling zeitgeist_result_set_next() or adjust it manually by calling + * zeitgeist_result_set_seek(). + * + * Calling zeitgeist_result_set_next() will also return the event at the + * current cursor position. You may retrieve the current event without advancing + * the cursor by calling zeitgeist_result_set_peek(). + * + */ +public interface ResultSet : Object +{ + + /** + * Get the number of #ZeitgeistEvents held in a #ZeitgeistResultSet. + * Unlike the number obtained from zeitgeist_result_set_estimated_matches() the + * size of the result set is always equal to the number of times you can call + * zeitgeist_result_set_next(). + * + * @param self The #ZeitgeistResultSet to get the size of + * + * @return The number of events held in the result set + */ + public abstract uint size (); + + /** + * FIXME: this is not true for _find_events/_get_events(): + * Get an estimated total number of matches that would have been for the query + * that generated the result set had it not been restricted in size. + * + * For zeitgeist_log_find_events() and zeitgeist_log_get_events() this will + * always be the same as zeitgeist_result_set_size(). For cases like + * zeitgeist_index_search() where you specify a subset of the hits to retrieve + * the estimated match count will often be bigger than the result set size. + * + * @param self The #ZeitgeistResultSet to get the number of estimated + * matches on + * @return The number of events that matched the query + */ + public abstract uint estimated_matches (); + + /** + * Get the current event from the result set and advance the cursor. + * To ensure that calls to this method will succeed you can call + * zeitgeist_result_set_has_next(). + * + * To retrieve the current event without advancing the cursor call + * zeitgeist_result_set_peek() in stead of this method. + * + * @param self The #ZeitgeistResultSet to get an event from + * + * @return The #ZeitgeistEvent at the current cursor position + */ + public abstract Event next (); + + /** + * Check if a call to zeitgeist_result_set_next() will succeed. + * + * @param self The #ZeitgeistResultSet to check + * + * @return %TRUE if and only if more events can be retrieved by calling + * zeitgeist_result_set_next() + */ + public abstract bool has_next (); + + /** + * Get the event at the current cursor position. + * + * To retrieve the current event and advance the cursor position call + * zeitgeist_result_set_next() in stead of this method. + * + * @param self The #ZeitgeistResultSet to get an event from + * + * @return The #ZeitgeistEvent at the current cursor position + */ + public abstract Event peek (); + + /** + * Set the cursor position. Following calls to zeitgeist_result_set_peek() + * or zeitgeist_result_set_next() will read the event at position @pos. + * + * @param self The #ZeitgeistResultSet to seek in + * @param pos The position to seek to + */ + public abstract void seek (uint pos); + + /** + * Get the current position of the cursor. + * + * @param self The #ZeitgeistResultSet to check the cursor position for + * + * @return The current position of the cursor + */ + public abstract uint tell (); + +} + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/simple-result-set.vala b/libzeitgeist/simple-result-set.vala new file mode 100644 index 0000000..249fbcd --- /dev/null +++ b/libzeitgeist/simple-result-set.vala @@ -0,0 +1,80 @@ +/* simple-result-set.vala + * + * Copyright © 2012 Canonical Ltd. + * By Siegfried-A. Gevatter + * + * Based upon a C implementation (© 2009 Canonical Ltd) by: + * Mikkel Kamstrup Erlandsen + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + +internal class SimpleResultSet : Object, ResultSet +{ + + private GenericArray events; + private uint num_estimated_matches; + private uint cursor; + + internal SimpleResultSet (GenericArray events, uint matches=-1) + { + this.events = events; + num_estimated_matches = (matches >= 0) ? matches : events.length; + cursor = 0; + } + + public uint size () + { + return events.length; + } + + public uint estimated_matches () + { + return num_estimated_matches; + } + + public Event next () + { + return events.get (cursor++); + } + + public bool has_next () + { + return cursor < events.length; + } + + public Event peek () + { + return events.get (cursor); + } + + public void seek (uint pos) + { + cursor = pos; + } + + public uint tell () + { + return cursor; + } + +} + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/timestamp.vala b/libzeitgeist/timestamp.vala new file mode 100644 index 0000000..fa53fa7 --- /dev/null +++ b/libzeitgeist/timestamp.vala @@ -0,0 +1,227 @@ +/* datamodel.vala + * + * Copyright © 2012 Collabora Ltd. + * By Siegfried-Angel Gevatter Pujals + * Copyright © 2010 Canonical, Ltd. + * By Mikkel Kamstrup Erlandsen + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +using Zeitgeist; + +/** + * SECTION:zeitgeist-timestamp + * + * Convenience functions for dealing with timestamps and dates + * + * include: zeitgeist.h + * + * A suite of convenience functions for dealing with timestamps and dates. + * + * Zeitgeist timestamps are represented as ''gint64''s with the number + * of milliseconds since the Unix Epoch. + */ +namespace Zeitgeist.Timestamp +{ + /** + * A second represented as a Zeitgeist timestamp (ie. 1000ms) + */ + public const int64 SECOND = 1000; + + /** + * A minute represented as a Zeitgeist timestamp (ie. 60000ms) + */ + public const int64 MINUTE = 60000; + + /** + * An hour represented as a Zeitgeist timestamp (ie. 3600000ms) + */ + public const int64 HOUR = 3600000; + + /** + * A day represented as a Zeitgeist timestamp (ie. 86400000ms) + */ + public const int64 DAY = 86400000; + + /** + * A week represented as a Zeitgeist timestamp (ie. 604800000ms) + */ + public const int64 WEEK = 604800000; + + /** + * A year represented as a Zeitgeist timestamp (ie. 31556952000ms). + * Be warned that a year is not 365 days, but in fact 365.2425 days, + * to account for leap years. + */ + public const int64 YEAR = 31556952000; + + /** + * ... + * + * @return number of milliseconds since the Unix Epoch + */ + public int64 from_timeval (TimeVal timeval) + { + return timeval.tv_sec * 1000 + timeval.tv_usec / 1000; + } + + /** + * ... + * + * Write a Zeitgeist timestamp to a #GTimeVal instance. Note that Zeitgeist + * uses only a millisecond resolution for where #GTimeVal uses a microsecond + * resolution, meaning that the lower three digits of @tv.tv_usec will + * be 0. + */ + public TimeVal to_timeval (int64 timestamp) + { + TimeVal timeval = TimeVal(); + timeval.tv_sec = (long) timestamp / 1000; + timeval.tv_usec = (long) (timestamp % 1000) * 1000; + return timeval; + } + + /** + * ... + * + * @return the timestamp for the current system time, in milliseconds + * since the Unix Epoch + */ + public int64 now () // FIXME: for_now in C + { + return from_timeval (TimeVal ()); + } + + /** + * Parse a timestamp from an ISO8601-encoded string. + * + * @param datetime a string containing an ISO8601-conforming datetime + * + * @return the timestamp represented by the given string, or -1 if + * it can't be parsed + */ + public int64 from_iso8601 (string datetime) + { + TimeVal timeval = TimeVal(); + if (timeval.from_iso8601 (datetime)) + return from_timeval (timeval); + else + return -1; + } + + /** + * Convert a timestamp to a human-readable ISO8601 format + * + * @param timestamp a timestamp in milliseconds since the Unix Epoch + * + * @return a newly allocated string containing the ISO8601 version of + * the given timestamp + */ + public string to_iso8601 (int64 timestamp) + { + TimeVal timeval = to_timeval (timestamp); + return timeval.to_iso8601 (); + } + + /** + * Convert a ''GDate'' to a Zeitgeist timestamp + * + * @param date the date to convert + * + * @return the given date expressed as a timestamp in milliseconds since + * the Epoch. The timestamp is guaranteed to be roudned off to the + * midnight of the given date. + */ + public int64 from_date (Date date) + { + int64 julian = date.get_julian (); + return prev_midnight (julian*DAY - 1969*YEAR); + } + + /** + * Convert a day, month, year tuple into a Zeitgeist timestamp + * + * @param day the day of the month + * @param month the month of the year + * @param year the year + * + * @return the given date (rounded off to the midnight), expressed as + * a timestamp in milliseconds since the Epoch, or -1 in case + * the provided parameters don't constitute a valid date. + */ + public int64 from_dmy (DateDay day, DateMonth month, DateYear year) + { + Date date = Date(); + date.set_dmy (day, month, year); + return from_date (date); + } + + /** + * Write a timetsamp to a ''GDate'' structure + */ + public void to_date (int64 timestamp, out Date date) + { + TimeVal timeval = to_timeval (timestamp); + date.set_time_val (timeval); + } + + /** + * Calculate the timestamp for the next midnight after the given timestamp. + * + * If is is already midnight (down to the millisecond), this method will + * return the value for the next midnight. In other words, you can call + * this method recursively in order to iterate, forwards in time, over + * midnights. + * + * @param timestamp the Zeitgeist timestamp to find the next midnight for + * + * @return the timestamp for the next midnight after the given timestamp + */ + public int64 next_midnight (int64 timestamp) + { + int64 remainder = timestamp % DAY; + if (remainder == 0) + return timestamp + DAY; + else + return (timestamp - remainder) + DAY; + } + + /** + * Calculate the timestamp for the midnight just before the given + * timestamp. + * + * If is is already midnight (down to the millisecond), this method will + * return the value for the previous midnight. In other words, you can + * call this method recursively in order to iterate, backwards in time, + * over midnights. + * + * @param timestamp the Zeitgeist timestamp to find the previous + * midnight for + * + * @return the timestamp for the midnight just before the given timestamp + */ + public int64 prev_midnight (int64 timestamp) + { + int64 remainder = timestamp % DAY; + if (remainder == 0) + return timestamp - DAY; + else + return (timestamp - remainder); + } + +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/utils.vala b/libzeitgeist/utils.vala new file mode 100644 index 0000000..c4b7a5c --- /dev/null +++ b/libzeitgeist/utils.vala @@ -0,0 +1,189 @@ +/* utils.vala + * + * Copyright © 2011 Collabora Ltd. + * By Seif Lotfy + * By Siegfried-Angel Gevatter Pujals + * Copyright © 2011 Michal Hruby + * Copyright © 2011 Manish Sinha + * + * This program 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 2.1 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License + * along with this program. If not, see . + * + */ + +namespace Zeitgeist +{ + namespace Utils + { + // Paths + private static string DATA_PATH; + private static string DATABASE_FILE_PATH; + private static string DATABASE_FILE_BACKUP_PATH; + private static string LOCAL_EXTENSIONS_PATH; + + private const string DATA_FOLDER = "zeitgeist"; + private const string DATABASE_BASENAME = "activity.sqlite"; + private const string USER_EXTENSION_PATH = ""; + + // D-Bus + public const string ENGINE_DBUS_NAME = "org.gnome.zeitgeist.Engine"; + public const string ENGINE_DBUS_PATH = "/org/gnome/zeitgeist/log/activity"; + public const string SIG_EVENT = "asaasay"; + public const size_t MAX_DBUS_RESULT_SIZE = 4 * 1024 * 1024; // 4MiB + + // configure runtime cache for events + // default size is 2000 + public const uint CACHE_SIZE = 0; + + public unowned string get_data_path () + { + if (DATA_PATH != null) return DATA_PATH; + + DATA_PATH = Environment.get_variable ("ZEITGEIST_DATA_PATH") ?? + get_default_data_path (); + + if (!FileUtils.test (DATA_PATH, FileTest.IS_DIR)) + { + DirUtils.create_with_parents (DATA_PATH, 0755); + } + + debug ("DATA_PATH = %s", DATA_PATH); + + return DATA_PATH; + } + + public string get_default_data_path () + { + return Path.build_filename (Environment.get_user_data_dir (), + DATA_FOLDER); + } + + public unowned string get_database_file_path () + { + if (DATABASE_FILE_PATH != null) return DATABASE_FILE_PATH; + + DATABASE_FILE_PATH = + Environment.get_variable ("ZEITGEIST_DATABASE_PATH") ?? + Path.build_filename (get_data_path (), DATABASE_BASENAME); + + debug ("DATABASE_FILE_PATH = %s", DATABASE_FILE_PATH); + + return DATABASE_FILE_PATH; + } + + public unowned string get_database_file_backup_path () + { + if (DATABASE_FILE_BACKUP_PATH != null) + return DATABASE_FILE_BACKUP_PATH; + + DATABASE_FILE_BACKUP_PATH = + Environment.get_variable ("ZEITGEIST_DATABASE_BACKUP_PATH") ?? + Path.build_filename (get_data_path (), + DATABASE_BASENAME + ".bck"); + + debug ("DATABASE_FILE_BACKUP_PATH = %s", DATABASE_FILE_BACKUP_PATH); + + return DATABASE_FILE_BACKUP_PATH; + } + + public string get_database_file_retire_name () + { + return DATABASE_BASENAME + ".%s.bck".printf ( + new DateTime.now_local ().format ("%Y%m%d-%H%M%S")); + } + + public unowned string get_local_extensions_path () + { + if (LOCAL_EXTENSIONS_PATH != null) return LOCAL_EXTENSIONS_PATH; + + LOCAL_EXTENSIONS_PATH = Path.build_filename (get_data_path (), + "extensions"); + + debug ("LOCAL_EXTENSIONS_PATH = %s", LOCAL_EXTENSIONS_PATH); + + return LOCAL_EXTENSIONS_PATH; + } + + public bool using_in_memory_database () + { + return get_database_file_path () == ":memory:"; + } + + public void backup_database () throws Error + { + File original; + File destination; + original = File.new_for_path (get_database_file_path ()); + destination = File.new_for_path (get_database_file_backup_path ()); + + message ("Backing up database to \"%s\" for schema upgrade...", + get_database_file_backup_path ()); + original.copy (destination, FileCopyFlags.OVERWRITE, null, null); + } + + /** + * Check if the value starts with the negation operator. If it does, + * remove the operator from the value and return true. Otherwise, + * return false. + */ + public static bool parse_negation (ref string val) + { + if (!val.has_prefix ("!")) + return false; + val = val.substring (1); + return true; + } + + /** + * Check if the value starts with the noexpand operator. If it does, + * remove the operator from the value and return true. Otherwise, + * return false. + * + * Check for the negation operator before calling this function. + */ + public static bool parse_noexpand (ref string val) + { + if (!val.has_prefix ("+")) + return false; + val = val.substring (1); + return true; + } + + + /** + * Check if the value ends with the wildcard character. If it does, + * remove the wildcard character from the value and return true. + * Otherwise, return false. + */ + public static bool parse_wildcard (ref string val) + { + if (!val.has_suffix ("*")) + return false; + unowned uint8[] val_data = val.data; + val_data[val_data.length-1] = '\0'; + return true; + } + + /** + * Return true if a string is empty (null or containing just a null + * byte). + */ + public static bool is_empty_string (string? s) + { + return s == null || s == ""; + } + + } +} + +// vim:expandtab:ts=4:sw=4 diff --git a/libzeitgeist/zeitgeist-2.0.pc.in b/libzeitgeist/zeitgeist-2.0.pc.in new file mode 100644 index 0000000..99c97aa --- /dev/null +++ b/libzeitgeist/zeitgeist-2.0.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libzeigeist +Description: C bindings for Zeitgeist +Requires: glib-2.0 +Version: @LIBZEITGEIST_VERSION@ +Libs: -L${libdir} -lzeitgeist +Cflags: -I${includedir}/zeitgeist-2.0 diff --git a/src/Makefile.am b/src/Makefile.am index bdb4a3b..f06a13e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,6 +5,7 @@ bin_PROGRAMS = zeitgeist-daemon AM_CPPFLAGS = \ $(ZEITGEIST_CFLAGS) \ -include $(CONFIG_HEADER) \ + -I $(top_srcdir)/libzeitgeist \ -w \ $(NULL) @@ -15,6 +16,7 @@ AM_VALAFLAGS = \ --pkg sqlite3 \ --pkg posix \ --pkg gmodule-2.0 \ + $(top_srcdir)/libzeitgeist/zeitgeist-private.vapi \ $(top_srcdir)/config.vapi \ $(NULL) @@ -36,24 +38,18 @@ extensions_VALASOURCES = \ zeitgeist_daemon_VALASOURCES = \ zeitgeist-daemon.vala \ - datamodel.vala \ db-reader.vala \ engine.vala \ - remote.vala \ extension.vala \ extension-collection.vala \ extension-store.vala \ logging.vala \ notify.vala \ sql.vala \ - utils.vala \ errors.vala \ table-lookup.vala \ sql-schema.vala \ where-clause.vala \ - ontology.vala \ - ontology-uris.vala \ - mimetype.vala \ $(NULL) zeitgeist_daemon_SOURCES = \ @@ -64,6 +60,7 @@ zeitgeist_daemon_SOURCES = \ zeitgeist_daemon_LDADD = \ $(ZEITGEIST_LIBS) \ + $(top_builddir)/libzeitgeist/libzeitgeist-2.0.la \ $(NULL) zeitgeist_daemon_LDFLAGS = -export-dynamic -no-undefined @@ -79,19 +76,9 @@ extensions_vala.stamp: zeitgeist-engine_vala.stamp $(extensions_VALASOURCES) $(VALAC) $(AM_VALAFLAGS) $(VALAFLAGS) $(EXT_FLAGS) -C zeitgeist-engine.vapi $(ext_src) || exit 1;) @touch "$@" -# FIXME: can we make this depend on $(ontology_trig_DATA)? -ontology_vala.stamp: ontology.vala.in ontology-uris.vala.in - $(AM_V_GEN)$(top_srcdir)/data/ontology2code --vala - @touch "$@" - -ontology.vala ontology-uris.vala: ontology_vala.stamp - EXTRA_DIST = \ $(zeitgeist_daemon_VALASOURCES) \ $(extensions_VALASOURCES) \ - ontology_vala.stamp \ - ontology.vala.in \ - ontology-uris.vala.in \ zeitgeist-engine.h \ zeitgeist-engine.vapi \ zeitgeist-engine_vala.stamp \ @@ -99,8 +86,6 @@ EXTRA_DIST = \ $(NULL) DISTCLEANFILES = \ - ontology.vala \ - ontology-uris.vala \ $(NULL) distclean-local: @@ -109,4 +94,3 @@ distclean-local: VALA_V = $(VALA_V_$(V)) VALA_V_ = $(VALA_V_$(AM_DEFAULT_VERBOSITY)) VALA_V_0 = @echo " VALAC " $^; - diff --git a/src/datamodel.vala b/src/datamodel.vala deleted file mode 100644 index 7d62bcf..0000000 --- a/src/datamodel.vala +++ /dev/null @@ -1,806 +0,0 @@ -/* datamodel.vala - * - * Copyright © 2011 Collabora Ltd. - * By Seif Lotfy - * By Siegfried-Angel Gevatter Pujals - * Copyright © 2011 Manish Sinha - * Copyright © 2012 Canonical Ltd. - * By Siegfried-A. Gevatter - * - * This program 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 2.1 of the License, or - * (at your option) any later version. - * - * 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 Lesser General Public License - * along with this program. If not, see . - * - */ - -namespace Zeitgeist -{ - private void assert_sig (bool condition, string error_message) - throws EngineError - { - if (unlikely (!condition)) - throw new EngineError.INVALID_SIGNATURE (error_message); - } - - namespace Timestamp - { - public static int64 now () - { - return from_timeval (TimeVal ()); - } - - public static int64 from_timeval (TimeVal tv) - { - int64 result; - result = ((int64) tv.tv_sec) * 1000; - result += ((int64) tv.tv_usec) / 1000; - - return result; - } - } - - [CCode (type_signature = "(xx)")] - public class TimeRange: Object - { - public int64 start { get; private set; } - public int64 end { get; private set; } - - public TimeRange (int64 start_msec, int64 end_msec) - { - start = start_msec; - end = end_msec; - } - - public TimeRange.anytime () - { - this (0, int64.MAX); - } - - public TimeRange.to_now () - { - this (0, Timestamp.now ()); - } - - public TimeRange.from_now () - { - this (Timestamp.now (), int64.MAX); - } - - public TimeRange.from_variant (Variant variant) - throws EngineError - { - assert_sig (variant.get_type_string () == "(xx)", - "Invalid D-Bus signature."); - - int64 start_msec = 0; - int64 end_msec = 0; - - variant.get ("(xx)", &start_msec, &end_msec); - - this (start_msec, end_msec); - } - - public Variant to_variant () - { - return new Variant ("(xx)", start, end); - } - - public TimeRange? intersect (TimeRange time_range) - { - var result = new TimeRange(0,0); - if (start < time_range.start) - if (end < time_range.start) - return null; - else - result.start = time_range.start; - else - if (start > time_range.end) - return null; - else - result.start = start; - - if (end < time_range.end) - if (end < time_range.start) - return null; - else - result.end = end; - else - if (start > time_range.end) - return null; - else - result.end = time_range.end; - return result; - } - } - - public enum ResultType - { - MOST_RECENT_EVENTS = 0, // All events with the most - // recent events first - LEAST_RECENT_EVENTS = 1, // All events with the oldest - // ones first - MOST_RECENT_SUBJECTS = 2, // One event for each subject - // only, ordered with the - // most recent events first - LEAST_RECENT_SUBJECTS = 3, // One event for each subject - // only, ordered with oldest - // events first - MOST_POPULAR_SUBJECTS = 4, // One event for each subject - // only, ordered by the - // popularity of the subject - LEAST_POPULAR_SUBJECTS = 5, // One event for each subject - // only, ordered ascendingly - // by popularity of the - // subject - MOST_POPULAR_ACTOR = 6, // The last event of each - // different actor ordered - // by the popularity of the - // actor - LEAST_POPULAR_ACTOR = 7, // The last event of each - // different actor, ordered - // ascendingly by the - // popularity of the actor - MOST_RECENT_ACTOR = 8, // The actor that has been used - // to most recently - LEAST_RECENT_ACTOR = 9, // The actor that has been used - // to least recently - MOST_RECENT_ORIGIN = 10, // The last event of each - // different subject origin. - LEAST_RECENT_ORIGIN = 11, // The last event of each - // different subject origin, - // ordered by least - // recently used first - MOST_POPULAR_ORIGIN = 12, // The last event of each - // different subject origin, - // ordered by the - // popularity of the origins - LEAST_POPULAR_ORIGIN = 13, // The last event of each - // different subject origin, - // ordered ascendingly by - // the popularity of the - // origin - OLDEST_ACTOR = 14, // The first event of each - // different actor - MOST_RECENT_SUBJECT_INTERPRETATION = 15, // One event for each subject - // interpretation only, - // ordered with the most - // recent events first - LEAST_RECENT_SUBJECT_INTERPRETATION = 16, // One event for each subject - // interpretation only, - // ordered with the least - // recent events first - MOST_POPULAR_SUBJECT_INTERPRETATION = 17, // One event for each subject - // interpretation only, - // ordered by the popularity - // of the subject - // interpretation - LEAST_POPULAR_SUBJECT_INTERPRETATION = 18, // One event for each subject - // interpretation only, - // ordered ascendingly by - // popularity of the subject - // interpretation - MOST_RECENT_MIMETYPE = 19, // One event for each mimetype - // only ordered with the - // most recent events first - LEAST_RECENT_MIMETYPE = 20, // One event for each mimetype - // only ordered with the - // least recent events first - MOST_POPULAR_MIMETYPE = 21, // One event for each mimetype - // only ordered by the - // popularity of the mimetype - LEAST_POPULAR_MIMETYPE = 22, // One event for each mimetype - // only ordered ascendingly - // by popularity of the - // mimetype - MOST_RECENT_CURRENT_URI = 23, // One event for each subject - // only by current_uri - // instead of uri ordered - // with the most recent - // events first - LEAST_RECENT_CURRENT_URI = 24, // One event for each subject - // only by current_uri - // instead of uri ordered - // with oldest events first - MOST_POPULAR_CURRENT_URI = 25, // One event for each subject - // only by current_uri - // instead of uri ordered - // by the popularity of the - // subject - LEAST_POPULAR_CURRENT_URI = 26, // One event for each subject - // only by current_uri - // instead of uri - // ordered ascendingly by - // popularity of the subject - MOST_RECENT_EVENT_ORIGIN = 27, // The last event of each - // different origin - LEAST_RECENT_EVENT_ORIGIN = 28, // The last event of each - // different origin, ordered - // by least recently used - // first - MOST_POPULAR_EVENT_ORIGIN = 29, // The last event of each - // different origin ordered - // by the popularity of the - // origins - LEAST_POPULAR_EVENT_ORIGIN = 30; // The last event of each - // different origin, ordered - // ascendingly by the - // popularity of the origin - - /* - * Returns true if the results for the given result_type will be sorted - * ascendantly by date, false if they'll be sorted descendingly. - **/ - public static bool is_sort_order_asc (ResultType result_type) - { - switch (result_type) - { - // FIXME: Why are LEAST_POPULAR_* using ASC? - case ResultType.LEAST_RECENT_EVENTS: - case ResultType.LEAST_RECENT_EVENT_ORIGIN: - case ResultType.LEAST_POPULAR_EVENT_ORIGIN: - case ResultType.LEAST_RECENT_SUBJECTS: - case ResultType.LEAST_POPULAR_SUBJECTS: - case ResultType.LEAST_RECENT_CURRENT_URI: - case ResultType.LEAST_POPULAR_CURRENT_URI: - case ResultType.LEAST_RECENT_ACTOR: - case ResultType.LEAST_POPULAR_ACTOR: - case ResultType.OLDEST_ACTOR: - case ResultType.LEAST_RECENT_ORIGIN: - case ResultType.LEAST_POPULAR_ORIGIN: - case ResultType.LEAST_RECENT_SUBJECT_INTERPRETATION: - case ResultType.LEAST_POPULAR_SUBJECT_INTERPRETATION: - case ResultType.LEAST_RECENT_MIMETYPE: - case ResultType.LEAST_POPULAR_MIMETYPE: - return true; - - case ResultType.MOST_RECENT_EVENTS: - case ResultType.MOST_RECENT_EVENT_ORIGIN: - case ResultType.MOST_POPULAR_EVENT_ORIGIN: - case ResultType.MOST_RECENT_SUBJECTS: - case ResultType.MOST_POPULAR_SUBJECTS: - case ResultType.MOST_RECENT_CURRENT_URI: - case ResultType.MOST_POPULAR_CURRENT_URI: - case ResultType.MOST_RECENT_ACTOR: - case ResultType.MOST_POPULAR_ACTOR: - case ResultType.MOST_RECENT_ORIGIN: - case ResultType.MOST_POPULAR_ORIGIN: - case ResultType.MOST_RECENT_SUBJECT_INTERPRETATION: - case ResultType.MOST_POPULAR_SUBJECT_INTERPRETATION: - case ResultType.MOST_RECENT_MIMETYPE: - case ResultType.MOST_POPULAR_MIMETYPE: - return false; - - default: - warning ("Unrecognized ResultType: %u", (uint) result_type); - return true; - } - } - } - - /* - * An enumeration class used to define how query results should - * be returned from the Zeitgeist engine. - */ - public enum RelevantResultType - { - RECENT = 0, // All uris with the most recent uri first - RELATED = 1, // All uris with the most related one first - } - - /** - * Enumeration class defining the possible values for the storage - * state of an event subject. - * - * The StorageState enumeration can be used to control whether or - * not matched events must have their subjects available to the user. - * Fx. not including deleted files, files on unplugged USB drives, - * files available only when a network is available etc. - */ - public enum StorageState - { - NOT_AVAILABLE = 0, // The storage medium of the events - // subjects must not be available to the user - AVAILABLE = 1, // The storage medium of all event subjects - // must be immediately available to the user - ANY = 2 // The event subjects may or may not be available - } - - private bool check_field_match (string? property, - string? template_property, bool is_symbol = false, - bool can_wildcard = false) - { - var matches = false; - var is_negated = false; - var parsed = template_property; - - if (parsed != null) - is_negated = Utils.parse_negation (ref parsed); - - if (Utils.is_empty_string (parsed)) - { - return true; - } - else if (parsed == property) - { - matches = true; - } - else if (is_symbol && property != null && - Symbol.get_all_parents (property).find_custom (parsed, strcmp) != null) - { - matches = true; - } - else if (can_wildcard && Utils.parse_wildcard (ref parsed)) - { - if (property != null && property.has_prefix (parsed)) - matches = true; - } - - return (is_negated) ? !matches : matches; - } - - public class Event : Object - { - private static StringChunk url_store; - - public uint32 id { get; set; } - public int64 timestamp { get; set; } - public string? origin { get; set; } - - public string? actor - { - get { return _actor; } - set { _actor = (value != null) ? url_store.insert_const (value) : null; } - } - public string? interpretation - { - get { return _interpretation; } - set { _interpretation = (value != null) ? url_store.insert_const (value) : null; } - } - public string? manifestation - { - get { return _manifestation; } - set { _manifestation = (value != null) ? url_store.insert_const (value) : null; } - } - - private unowned string? _actor; - private unowned string? _interpretation; - private unowned string? _manifestation; - - public GenericArray subjects { get; set; } - public ByteArray? payload { get; set; } - - static construct - { - url_store = new StringChunk (4096); - } - - construct - { - subjects = new GenericArray (); - } - - public int num_subjects () - { - return subjects.length; - } - - public void add_subject (Subject subject) - { - subjects.add (subject); - } - - public void take_subject (owned Subject subject) - { - subjects.add ((owned) subject); - } - - public Event.full (string? interpretation=null, - string? manifestation=null, string? actor=null, - string? origin=null, ...) - { - this.interpretation = interpretation; - this.manifestation = manifestation; - this.actor = actor; - this.origin = origin; - - // FIXME: We can't use this until Vala bug #647097 is fixed - /* - var subjects = va_list (); - unowned Subject subject; - while ((subject = subjects.arg ()) != null) - add_subject (subject); - */ - } - - public Event.from_variant (Variant event_variant) throws EngineError { - assert_sig (event_variant.get_type_string () == "(" + - Utils.SIG_EVENT + ")", "Invalid D-Bus signature."); - - VariantIter iter = event_variant.iterator (); - - assert_sig (iter.n_children () >= 3, "Incomplete event struct."); - VariantIter event_array = iter.next_value ().iterator (); - VariantIter subjects_array = iter.next_value ().iterator (); - Variant payload_variant = iter.next_value (); - - var event_props = event_array.n_children (); - assert_sig (event_props >= 5, "Missing event information."); - id = (uint32) uint64.parse (event_array.next_value().get_string ()); - var str_timestamp = event_array.next_value().get_string (); - if (str_timestamp == "") - timestamp = Timestamp.now (); - else - timestamp = int64.parse (str_timestamp); - interpretation = event_array.next_value ().get_string (); - manifestation = event_array.next_value ().get_string (); - actor = event_array.next_value ().get_string (); - // let's keep this compatible with older clients - if (event_props >= 6) - origin = event_array.next_value ().get_string (); - else - origin = ""; - - for (int i = 0; i < subjects_array.n_children (); ++i) { - Variant subject_variant = subjects_array.next_value (); - subjects.add (new Subject.from_variant (subject_variant)); - } - - // Parse payload... - uint payload_length = (uint) payload_variant.n_children (); - if (payload_length > 0) - { - payload = new ByteArray.sized (payload_length); - unowned uint8[] data = (uint8[]?) payload_variant.get_data (); - data.length = (int) payload_length; - payload.append (data); - } - } - - public Variant to_variant () - { - var vb = new VariantBuilder (new VariantType ("("+Utils.SIG_EVENT+")")); - - vb.open (new VariantType ("as")); - vb.add ("s", id == 0 ? "" : id.to_string ()); - vb.add ("s", timestamp.to_string ()); - vb.add ("s", interpretation != null ? interpretation : ""); - vb.add ("s", manifestation != null ? manifestation : ""); - vb.add ("s", actor != null ? actor : ""); - vb.add ("s", origin != null ? origin : ""); - vb.close (); - - vb.open (new VariantType ("aas")); - for (int i = 0; i < subjects.length; ++i) { - vb.add_value (subjects[i].to_variant ()); - } - vb.close (); - - if (payload != null) - { - Variant payload_variant = Variant.new_from_data ( - new VariantType ("ay"), payload.data, false, payload); - // FIXME: somehow adding the payload_variant is not working - vb.add_value (payload_variant); - } - else - { - vb.open (new VariantType ("ay")); - vb.close (); - } - - Variant event_variant = vb.end ().get_normal_form (); - Variant ret = optimize_variant_allocation (event_variant); - return ret; - } - - private Variant optimize_variant_allocation (Variant event_variant) { - // FIXME: this uses g_new0, we dont need the mem to be zero-filled - uchar[] data = new uchar[event_variant.get_size ()]; - event_variant.store (data); - unowned uchar[] data_copy = data; - - Variant ret = Variant.new_from_data ( - new VariantType ("("+Utils.SIG_EVENT+")"), - data_copy, true, (owned) data); - return ret; - } - - public void debug_print () - { - stdout.printf ("id: %d\t" + - "timestamp: %" + int64.FORMAT + "\n" + - "actor: %s\n" + - "interpretation: %s\n" + - "manifestation: %s\n" + - "origin: %s\n" + - "num subjects: %d\n", - id, timestamp, actor, interpretation, - manifestation, origin, subjects.length); - for (int i = 0; i < subjects.length; i++) - { - var s = subjects[i]; - stdout.printf (" Subject #%d:\n" + - " uri: %s\n" + - " interpretation: %s\n" + - " manifestation: %s\n" + - " mimetype: %s\n" + - " origin: %s\n" + - " text: %s\n" + - " current_uri: %s\n" + - " storage: %s\n", - i, s.uri, s.interpretation, s.manifestation, - s.mimetype, s.origin, s.text, s.current_uri, - s.storage); - } - } - - - public bool matches_template (Event template_event) - { - /** - Return True if this event matches *event_template*. The - matching is done where unset fields in the template is - interpreted as wild cards. Interpretations and manifestations - are also matched if they are children of the types specified - in `event_template`. If the template has more than one - subject, this event matches if at least one of the subjects - on this event matches any single one of the subjects on the - template. - */ - - //Check if interpretation is child of template_event or same - if (!check_field_match (this.interpretation, template_event.interpretation, true)) - return false; - //Check if manifestation is child of template_event or same - if (!check_field_match (this.manifestation, template_event.manifestation, true)) - return false; - //Check if actor is equal to template_event actor - if (!check_field_match (this.actor, template_event.actor, false, true)) - return false; - //Check if origin is equal to template_event origin - if (!check_field_match (this.origin, template_event.origin, false, true)) - return false; - - if (template_event.subjects.length == 0) - return true; - - for (int i = 0; i < this.subjects.length; i++) - for (int j = 0; j < template_event.subjects.length; j++) - if (this.subjects[i].matches_template (template_event.subjects[j])) - return true; - - return false; - } - - } - - namespace Events - { - - public static GenericArray from_variant (Variant vevents) - throws EngineError - { - GenericArray events = new GenericArray (); - - assert (vevents.get_type_string () == "a("+Utils.SIG_EVENT+")"); - - foreach (Variant event in vevents) - { - events.add (new Event.from_variant (event)); - } - - return events; - } - - public static Variant to_variant (GenericArray events) - { - var vb = new VariantBuilder(new VariantType("a("+Utils.SIG_EVENT+")")); - - for (int i = 0; i < events.length; ++i) - { - if (events[i] != null) - { - vb.add_value (events[i].to_variant ()); - } - else - { - vb.add_value (get_null_event_variant ()); - } - } - - return vb.end (); - } - - /* Same as to_variant but raises an exception if the variant size - * exceeds `limit' bytes. - * */ - public static Variant to_variant_with_limit (GenericArray events, - size_t limit=Utils.MAX_DBUS_RESULT_SIZE) throws EngineError - { - var vb = new VariantBuilder(new VariantType("a("+Utils.SIG_EVENT+")")); - - size_t variant_size = 0; - - for (int i = 0; i < events.length; ++i) - { - Variant event_variant; - - if (events[i] != null) - { - event_variant = events[i].to_variant (); - } - else - { - event_variant = get_null_event_variant (); - } - - variant_size += event_variant.get_size(); - if (variant_size > limit) - { - size_t avg_event_size = variant_size / (i+1); - string error_message = ("Query exceeded size limit of % " + - size_t.FORMAT + "MiB (roughly ~%d events).").printf ( - limit / 1024 / 1024, limit / avg_event_size); - warning (error_message); - throw new EngineError.TOO_MANY_RESULTS (error_message); - } - - vb.add_value (event_variant); - } - - return vb.end (); - } - - private static Variant get_null_event_variant () - { - var vb = new VariantBuilder (new VariantType ("("+Utils.SIG_EVENT+")")); - vb.open (new VariantType ("as")); - vb.close (); - vb.open (new VariantType ("aas")); - vb.close (); - vb.open (new VariantType ("ay")); - vb.close (); - return vb.end (); - } - - } - - public class Subject : Object - { - private static StringChunk url_store; - - public string? uri { get; set; } - public string? origin { get; set; } - public string? text { get; set; } - public string? storage { get; set; } - // FIXME: current_uri is often the same as uri, we don't need to waste - // memory for it - public string? current_uri { get; set; } - - public string? mimetype - { - get { return _mimetype; } - set { _mimetype = (value != null) ? url_store.insert_const (value) : null; } - } - public string? interpretation - { - get { return _interpretation; } - set { _interpretation = (value != null) ? url_store.insert_const (value) : null; } - } - public string? manifestation - { - get { return _manifestation; } - set { _manifestation = (value != null) ? url_store.insert_const (value) : null; } - } - - private unowned string? _mimetype; - private unowned string? _interpretation; - private unowned string? _manifestation; - - static construct - { - url_store = new StringChunk (4096); - } - - public Subject.full (string? uri=null, - string? interpretation=null, string? manifestation=null, - string? mimetype=null, string? origin=null, string? text=null, - string? storage=null, string? current_uri=null) - { - this.interpretation = interpretation; - this.manifestation = manifestation; - this.mimetype = mimetype; - this.origin = origin; - this.text = text; - this.storage = storage; - this.current_uri = current_uri; - } - - public Subject.from_variant (Variant subject_variant) - throws EngineError - { - VariantIter iter = subject_variant.iterator(); - - var subject_props = iter.n_children (); - assert_sig (subject_props >= 7, "Missing subject information"); - uri = iter.next_value().get_string (); - interpretation = iter.next_value().get_string (); - manifestation = iter.next_value().get_string (); - origin = iter.next_value().get_string (); - mimetype = iter.next_value().get_string (); - text = iter.next_value().get_string (); - storage = iter.next_value().get_string (); - // let's keep this compatible with older clients - if (subject_props >= 8) - current_uri = iter.next_value().get_string (); - else - current_uri = ""; - } - - public Variant to_variant () - { - /* The FAST version */ - char* ptr_arr[8]; - ptr_arr[0] = uri != null ? uri : ""; - ptr_arr[1] = interpretation != null ? interpretation : ""; - ptr_arr[2] = manifestation != null ? manifestation : ""; - ptr_arr[3] = origin != null ? origin : ""; - ptr_arr[4] = mimetype != null ? mimetype : ""; - ptr_arr[5] = text != null ? text : ""; - ptr_arr[6] = storage != null ? storage : ""; - ptr_arr[7] = current_uri != null ? current_uri : ""; - return new Variant.strv ((string[]) ptr_arr); - /* The NICE version */ - /* - var vb = new VariantBuilder (new VariantType ("as")); - vb.add ("s", uri ?? ""); - vb.add ("s", interpretation ?? ""); - vb.add ("s", manifestation ?? ""); - vb.add ("s", origin ?? ""); - vb.add ("s", mimetype ?? ""); - vb.add ("s", text ?? ""); - vb.add ("s", storage ?? ""); - vb.add ("s", current_uri ?? ""); - - return vb.end (); - */ - } - - public bool matches_template (Subject template_subject) - { - /** - Return True if this Subject matches *subject_template*. Empty - fields in the template are treated as wildcards. - Interpretations and manifestations are also matched if they are - children of the types specified in `subject_template`. - */ - if (!check_field_match (this.uri, template_subject.uri, false, true)) - return false; - if (!check_field_match (this.current_uri, template_subject.current_uri, false, true)) - return false; - if (!check_field_match (this.interpretation, template_subject.interpretation, true)) - return false; - if (!check_field_match (this.manifestation, template_subject.manifestation, true)) - return false; - if (!check_field_match (this.origin, template_subject.origin, false, true)) - return false; - if (!check_field_match (this.mimetype, template_subject.mimetype, false, true)) - return false; - - return true; - } - - } - -} - -// vim:expandtab:ts=4:sw=4 diff --git a/src/errors.vala b/src/errors.vala index b0c23a7..960cd21 100644 --- a/src/errors.vala +++ b/src/errors.vala @@ -32,8 +32,6 @@ namespace Zeitgeist EXISTING_INSTANCE, INVALID_ARGUMENT, INVALID_KEY, - INVALID_SIGNATURE, // FIXME: change from EngineError to sth. + public - TOO_MANY_RESULTS, } // vala doesn't include proper headers, this fixes it diff --git a/src/extension-collection.vala b/src/extension-collection.vala index 2a1baa2..03f4e36 100644 --- a/src/extension-collection.vala +++ b/src/extension-collection.vala @@ -52,7 +52,7 @@ namespace Zeitgeist #if BUILTIN_EXTENSIONS RegisterExtensionFunc[] builtins = { - data_source_registry_init, + data_source_registry_extension_init, blacklist_init, histogram_init, storage_monitor_init, @@ -116,6 +116,11 @@ namespace Zeitgeist { type_name = (string) ((char*) type_name + 9); } + if (type_name.has_suffix ("Extension")) + { + string type_no_suffix = (string) type_name.slice(0, type_name.length - 9); + type_name = type_no_suffix; + } bool enabled = !(type_name in disabled_extensions); if (!enabled) message ("Skipping %s (disabled)", type_name); @@ -189,7 +194,7 @@ namespace Zeitgeist } #if BUILTIN_EXTENSIONS - private extern static Type data_source_registry_init (TypeModule mod); + private extern static Type data_source_registry_extension_init (TypeModule mod); private extern static Type blacklist_init (TypeModule mod); private extern static Type histogram_init (TypeModule mod); private extern static Type storage_monitor_init (TypeModule mod); diff --git a/src/logging.vala b/src/logging.vala index 1ef293d..ba2e8a2 100644 --- a/src/logging.vala +++ b/src/logging.vala @@ -137,13 +137,13 @@ namespace Zeitgeist } } if (discarded != 0) - Log.set_handler (null, discarded, () => {}); + GLib.Log.set_handler (null, discarded, () => {}); if (log_file != null) Logging.log_file = FileStream.open (log_file, "a"); LogLevelFlags logged = ~discarded & ~LogLevelFlags.FLAG_RECURSION; - Log.set_handler (null, logged, log_handler); + GLib.Log.set_handler (null, logged, log_handler); } } diff --git a/src/mimetype.vala b/src/mimetype.vala deleted file mode 100644 index ae983d7..0000000 --- a/src/mimetype.vala +++ /dev/null @@ -1,358 +0,0 @@ -/* datamodel.vala - * - * Copyright © 2011 Collabora Ltd. - * By Siegfried-Angel Gevatter Pujals - * Copyright © 2010 Canonical, Ltd. - * By Mikkel Kamstrup Erlandsen - * - * This program 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 2.1 of the License, or - * (at your option) any later version. - * - * 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 Lesser General Public License - * along with this program. If not, see . - * - */ - -using Zeitgeist; - -namespace Zeitgeist -{ - - private static bool mimetypes_loaded = false; - private static bool schemes_loaded = false; - - private static HashTable? mimetypes = null; - private static SList mimetypes_regexs; - private static SList schemes; - - [Compact] - private class MimeRegex - { - public Regex regex; - public string interpretation_uri; - - public MimeRegex (string mimetype_regex, string interpretation_uri) - throws RegexError - { - this.regex = new Regex (mimetype_regex, 0, 0); - this.interpretation_uri = interpretation_uri; - } - } - - [Compact] - private class UriScheme - { - public string uri_scheme; - public string manifestation_uri; - - public UriScheme (string uri_scheme, string manifestation_uri) - { - this.uri_scheme = uri_scheme; - this.manifestation_uri = manifestation_uri; - } - } - - /** - * zeitgeist_register_mimetype: - * @mimetype: A MIME-type string. Eg. text/plain - * @interpretation_uri: A URI defining the subject interpretation type to - * associate with @mimetype - * - * Associate a MIME-type with a given interpretation type. Registered - * MIME-types can be looked up with zeitgeist_interpretation_for_mimetype(). - * - * You can register a regular expression as mimetype if instead of this - * function you invoke zeitgeist_register_mimetype_regex(). - * - * MIME-types are first looked up by their exact name and then if none is - * found the regular expressions will be checked as fallbacks. - * - * This library will install a wide range a common mimetypes for you, so - * unless you have very specific needs you will normally not have to call - * this function. - * - * FIXME: link to list of interpretations - */ - public void register_mimetype (string mimetype, string interpretation_uri) - { - if (mimetypes == null) - mimetypes = new HashTable(str_hash, str_equal); - - mimetypes.insert (mimetype, interpretation_uri); - } - - /** - * zeitgeist_register_mimetype_regex: - * @mimetype: A regular expression matching a certain range of mimetypes. - * Eg. text/.* to match all - * text subtypes. - * @interpretation_uri: A URI defining the subject interpretation type to - * associate with the matched MIME-types - * - * Associate a range of MIME-types with a given interpretation type. - * Registered MIME-types can be looked up with - * zeitgeist_interpretation_for_mimetype(). - * - * If you only need to register one specific MIME-type, it is more efficient - * to use zeitgeist_register_mimetype() instead of this function. - * - * MIME-types are first looked up by their exact name and then if none is - * found the regular expressions will be checked as fallbacks. - * - * This library will install a wide range a common mimetypes for you, so - * unless you have very specific needs you will normally not have to call - * this function. - * - * FIXME: link to list of interpretations - */ - public void register_mimetype_regex (string mimetype_regex, - string interpretation_uri) throws RegexError - { - var entry = new MimeRegex (mimetype_regex, interpretation_uri); - mimetypes_regexs.append ((owned) entry); - } - - /** - * zeitgeist_interpretation_for_mimetype: - * @mimetype: A MIME-type string. Eg. text/plain - * - * Look up the subject interpretation type associated with @mimetype. - * FIXME: link to list of interpretations - * - * Returns: A URI defining the subject interpretation type associated with - * @mimetype or %NULL in case @mimetype is unknown. - */ - public unowned string? interpretation_for_mimetype (string mimetype) - { - ensure_mimetypes_loaded (); - - unowned string? interpretation = mimetypes.lookup (mimetype); - if (interpretation != null) - return interpretation; - - foreach (unowned MimeRegex mime_regex in mimetypes_regexs) - { - if (mime_regex.regex.match (mimetype, 0)) - return mime_regex.interpretation_uri; - } - - return null; - } - - /** - * zeitgeist_register_uri_scheme: - * @uri_scheme: A URI scheme such as http:// - * @manifestation_uri: A URI defining the subject manifestation type - * to associate with @uri_scheme - * - * Associate a URI scheme with a given subject manifestation type. - * You can find the manifestation type of a given URI by passing it to - * zeitgeist_manifestation_for_uri(). - * - * This library will install a range a common URI schemes for you, so unless - * you have very specific needs you will normally not have to call this - * function. - * - * FIXME: link to list of manifestations - */ - public void register_uri_scheme (string uri_scheme, - string manifestation_type) - { - var scheme = new UriScheme (uri_scheme, manifestation_type); - schemes.append ((owned) scheme); - } - - /** - * zeitgeist_manifestation_for_uri: - * @uri: An URI - * - * Look up a subject manifestation type for a given URI. Eg. if you pass in - * file:///tmp/foo.txt you will get back - * #ZEITGEIST_NFO_FILE_DATA_OBJECT. - * - * FIXME: link to list of manifestations - * - * Returns: A subject manifestation type for @uri or %NULL in case no - * suitable manifestation type is known - */ - public unowned string? manifestation_for_uri (string uri) { - ensure_schemes_loaded (); - - foreach (unowned UriScheme scheme in schemes) - { - if (uri.has_prefix (scheme.uri_scheme)) - return scheme.manifestation_uri; - } - - return null; - } - - private static void ensure_mimetypes_loaded () - { - if (mimetypes_loaded) - return; - - try { - register_mimetype ("application/ecmascript", NFO.SOURCE_CODE); - register_mimetype ("application/javascript", NFO.SOURCE_CODE); - register_mimetype ("application/json", NFO.SOURCE_CODE); - register_mimetype ("application/ms-excel", NFO.SPREADSHEET); - register_mimetype ("application/ms-powerpoint", NFO.PRESENTATION); - register_mimetype ("application/msexcel", NFO.SPREADSHEET); - register_mimetype ("application/msword", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype ("application/ogg", NFO.AUDIO); - register_mimetype ("application/pdf", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype ("application/postscript", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype ("application/ps", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype ("application/rtf", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype ("application/soap+xml", NFO.SOURCE_CODE); - register_mimetype ("application/vnd.corel-draw", NFO.VECTOR_IMAGE); - register_mimetype ("application/vnd.ms-excel", NFO.SPREADSHEET); - register_mimetype ("application/vnd.ms-powerpoint", NFO.PRESENTATION); - register_mimetype ("application/x-7z-compressed", NFO.ARCHIVE); - register_mimetype ("application/x-abiword", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype ("application/x-applix-presents", NFO.PRESENTATION); - register_mimetype ("application/x-applix-spreadsheet", NFO.SPREADSHEET); - register_mimetype ("application/x-applix-word", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype ("application/x-archive", NFO.ARCHIVE); - register_mimetype ("application/x-bzip", NFO.ARCHIVE); - register_mimetype ("application/x-bzip-compressed-tar", NFO.ARCHIVE); - register_mimetype ("application/x-cd-image", NFO.FILESYSTEM_IMAGE); - register_mimetype ("application/x-compressed-tar", NFO.ARCHIVE); - register_mimetype ("application/x-csh", NFO.SOURCE_CODE); - register_mimetype ("application/x-deb", NFO.SOFTWARE); - register_mimetype ("application/x-designer", NFO.SOURCE_CODE); - register_mimetype ("application/x-desktop", NFO.SOFTWARE); - register_mimetype ("application/x-dia-diagram", NFO.SOURCE_CODE); - register_mimetype ("application/x-executable", NFO.SOFTWARE); - register_mimetype ("application/x-fluid", NFO.SOURCE_CODE); - register_mimetype ("application/x-glade", NFO.SOURCE_CODE); - register_mimetype ("application/x-gnucash", NFO.SPREADSHEET); - register_mimetype ("application/x-gnumeric", NFO.SPREADSHEET); - register_mimetype ("application/x-gzip", NFO.ARCHIVE); - register_mimetype ("application/x-java-archive", NFO.SOURCE_CODE); - register_mimetype ("application/x-javascript", NFO.SOURCE_CODE); - register_mimetype ("application/x-killustrator", NFO.VECTOR_IMAGE); - register_mimetype ("application/x-kpresenter", NFO.PRESENTATION); - register_mimetype ("application/x-kspread", NFO.SPREADSHEET); - register_mimetype ("application/x-kword", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype ("application/x-lzma", NFO.ARCHIVE); - register_mimetype ("application/x-lzma-compressed-tar", NFO.ARCHIVE); - register_mimetype ("application/x-m4", NFO.SOURCE_CODE); - register_mimetype ("application/x-ms-dos-executable", NFO.SOFTWARE); - register_mimetype ("application/x-perl", NFO.SOURCE_CODE); - register_mimetype ("application/x-php", NFO.SOURCE_CODE); - register_mimetype ("application/x-rpm", NFO.SOFTWARE); - register_mimetype ("application/x-ruby", NFO.SOURCE_CODE); - register_mimetype ("application/x-shellscript", NFO.SOURCE_CODE); - register_mimetype ("application/x-shockwave-flash", NFO.EXECUTABLE); - register_mimetype ("application/x-sql", NFO.SOURCE_CODE); - register_mimetype ("application/x-stuffit", NFO.ARCHIVE); - register_mimetype ("application/xhtml+xml", NFO.SOURCE_CODE); - register_mimetype ("application/xml", NFO.SOURCE_CODE); - register_mimetype ("application/xml-dtd", NFO.SOURCE_CODE); - register_mimetype ("application/zip", NFO.ARCHIVE); - register_mimetype ("audio/x-scpls", NFO.MEDIA_LIST); - register_mimetype ("image/gif", NFO.RASTER_IMAGE); - register_mimetype ("image/jpeg", NFO.RASTER_IMAGE); - register_mimetype ("image/pjpeg", NFO.RASTER_IMAGE); - register_mimetype ("image/png", NFO.RASTER_IMAGE); - register_mimetype ("image/svg+xml", NFO.VECTOR_IMAGE); - register_mimetype ("image/tiff", NFO.RASTER_IMAGE); - register_mimetype ("image/vnd.microsoft.icon", NFO.ICON); - register_mimetype ("image/x-xcf", NFO.RASTER_IMAGE); - register_mimetype ("inode/directory", NFO.FOLDER); - register_mimetype ("message/alternative", NMO.EMAIL); - register_mimetype ("message/partial", NMO.EMAIL); - register_mimetype ("message/related", NMO.EMAIL); - register_mimetype ("text/css", NFO.SOURCE_CODE); - register_mimetype ("text/csv", NFO.TEXT_DOCUMENT); - register_mimetype ("text/html", NFO.HTML_DOCUMENT); - register_mimetype ("text/javascript", NFO.SOURCE_CODE); - register_mimetype ("text/plain", NFO.TEXT_DOCUMENT); - register_mimetype ("text/vcard", NCO.CONTACT); - register_mimetype ("text/x-c", NFO.SOURCE_CODE); - register_mimetype ("text/x-c++", NFO.SOURCE_CODE); - register_mimetype ("text/x-c++src", NFO.SOURCE_CODE); - register_mimetype ("text/x-chdr", NFO.SOURCE_CODE); - register_mimetype ("text/x-copying", NFO.SOURCE_CODE); - register_mimetype ("text/x-credits", NFO.SOURCE_CODE); - register_mimetype ("text/x-csharp", NFO.SOURCE_CODE); - register_mimetype ("text/x-csrc", NFO.SOURCE_CODE); - register_mimetype ("text/x-dsrc", NFO.SOURCE_CODE); - register_mimetype ("text/x-eiffel", NFO.SOURCE_CODE); - register_mimetype ("text/x-gettext-translation", NFO.SOURCE_CODE); - register_mimetype ("text/x-gettext-translation-template", NFO.SOURCE_CODE); - register_mimetype ("text/x-haskell", NFO.SOURCE_CODE); - register_mimetype ("text/x-idl", NFO.SOURCE_CODE); - register_mimetype ("text/x-java", NFO.SOURCE_CODE); - register_mimetype ("text/x-jquery-tmpl", NFO.SOURCE_CODE); - register_mimetype ("text/x-latex", NFO.SOURCE_CODE); - register_mimetype ("text/x-lisp", NFO.SOURCE_CODE); - register_mimetype ("text/x-lua", NFO.SOURCE_CODE); - register_mimetype ("text/x-m4", NFO.SOURCE_CODE); - register_mimetype ("text/x-makefile", NFO.SOURCE_CODE); - register_mimetype ("text/x-objcsrc", NFO.SOURCE_CODE); - register_mimetype ("text/x-ocaml", NFO.SOURCE_CODE); - register_mimetype ("text/x-pascal", NFO.SOURCE_CODE); - register_mimetype ("text/x-patch", NFO.SOURCE_CODE); - register_mimetype ("text/x-python", NFO.SOURCE_CODE); - register_mimetype ("text/x-sql", NFO.SOURCE_CODE); - register_mimetype ("text/x-tcl", NFO.SOURCE_CODE); - register_mimetype ("text/x-tex", NFO.SOURCE_CODE); - register_mimetype ("text/x-troff", NFO.SOURCE_CODE); - register_mimetype ("text/x-vala", NFO.SOURCE_CODE); - register_mimetype ("text/x-vhdl", NFO.SOURCE_CODE); - register_mimetype ("text/xml", NFO.SOURCE_CODE); - - register_mimetype_regex (".*/x-dvi", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype_regex ("application/vnd.ms-excel.*", NFO.SPREADSHEET); - register_mimetype_regex ("application/vnd.ms-powerpoint.*", NFO.PRESENTATION); - register_mimetype_regex ("application/vnd.oasis.opendocument.graphics.*", NFO.VECTOR_IMAGE); - register_mimetype_regex ("application/vnd.oasis.opendocument.presentation.*", NFO.PRESENTATION); - register_mimetype_regex ("application/vnd.oasis.opendocument.spreadsheet.*", NFO.SPREADSHEET); - register_mimetype_regex ("application/vnd.oasis.opendocument.text.*", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype_regex ("application/vnd.openxmlformats-officedocument.presentationml.presentation.*", NFO.PRESENTATION); - register_mimetype_regex ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.*", NFO.SPREADSHEET); - register_mimetype_regex ("application/vnd.openxmlformats-officedocument.wordprocessingml.document.*", NFO.PAGINATED_TEXT_DOCUMENT); - register_mimetype_regex ("application/vnd\\..*", NFO.DOCUMENT); - register_mimetype_regex ("application/x-applix-.*", NFO.DOCUMENT); - register_mimetype_regex ("audio/.*", NFO.AUDIO); - register_mimetype_regex ("image/.*", NFO.IMAGE); - register_mimetype_regex ("video/.*", NFO.VIDEO); - } catch (RegexError e) { - // This won't happen. - assert (false); - } - - mimetypes_loaded = true; - } - - private static void ensure_schemes_loaded () - { - if (schemes_loaded) - return; - - register_uri_scheme ("file://", NFO.FILE_DATA_OBJECT); - register_uri_scheme ("http://", NFO.WEB_DATA_OBJECT); - register_uri_scheme ("https://", NFO.WEB_DATA_OBJECT); - register_uri_scheme ("ssh://", NFO.REMOTE_DATA_OBJECT); - register_uri_scheme ("sftp://", NFO.REMOTE_DATA_OBJECT); - register_uri_scheme ("ftp://", NFO.REMOTE_DATA_OBJECT); - register_uri_scheme ("dav://", NFO.REMOTE_DATA_OBJECT); - register_uri_scheme ("davs://", NFO.REMOTE_DATA_OBJECT); - register_uri_scheme ("smb://", NFO.REMOTE_DATA_OBJECT); - - schemes_loaded = true; - } - -} - -// vim:expandtab:ts=4:sw=4 diff --git a/src/ontology-uris.vala.in b/src/ontology-uris.vala.in deleted file mode 100644 index 79ca408..0000000 --- a/src/ontology-uris.vala.in +++ /dev/null @@ -1,22 +0,0 @@ -/* ontology-uris.vala - * - * Copyright © 2009-2011 The Zeitgeist Team - * - * This program 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 2.1 of the License, or - * (at your option) any later version. - * - * 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 Lesser General Public License - * along with this program. If not, see . - * - */ - -// *insert-auto-generated-code* - -// vim:expandtab:ts=4:sw=4 diff --git a/src/ontology.vala.in b/src/ontology.vala.in deleted file mode 100644 index f8250cc..0000000 --- a/src/ontology.vala.in +++ /dev/null @@ -1,172 +0,0 @@ -/* ontology.vala - * - * Copyright © 2011 Collabora Ltd. - * By Seif Lotfy - * By Siegfried-Angel Gevatter Pujals - * Copyright © 2011 Michal Hruby - * - * This program 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 2.1 of the License, or - * (at your option) any later version. - * - * 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 Lesser General Public License - * along with this program. If not, see . - * - */ - -namespace Zeitgeist -{ - - namespace Symbol - { - private static HashTable all_symbols = null; - private static bool initialized = false; - - public static unowned string get_display_name (string symbol_uri) - { - initialize_symbols (); - - var symbol = all_symbols.lookup (symbol_uri); - if (symbol == null) return symbol_uri; - - return symbol.display_name; - } - - public static unowned string get_description(string symbol_uri) - { - initialize_symbols (); - - var symbol = all_symbols.lookup (symbol_uri); - if (symbol == null) return ""; - - return symbol.description; - } - - public static List get_all_parents(string symbol_uri) - { - initialize_symbols (); - - var results = new List (); - var symbol = all_symbols.lookup (symbol_uri); - if (symbol == null) return results; - - foreach (unowned string uri in symbol.parents) - { - results.append (uri); - // Recursively get the other parents - foreach (string parent_uri in get_all_parents (uri)) - if (results.index (parent_uri) > -1) - results.append (parent_uri); - } - - return results; - } - - public static List get_all_children (string symbol_uri) - { - initialize_symbols (); - - var results = new List (); - var symbol = all_symbols.lookup (symbol_uri); - if (symbol == null) return results; - - foreach (unowned string uri in symbol.all_children) - results.append (uri); - - return results; - } - - public static List get_children (string symbol_uri) - { - initialize_symbols (); - var results = new List (); - var symbol = all_symbols.lookup (symbol_uri); - if (symbol == null) return results; - - foreach (unowned string uri in symbol.children) - results.append(uri); - - return results; - } - - public static List get_parents (string symbol_uri) - { - initialize_symbols (); - - var results = new List(); - var symbol = all_symbols.lookup (symbol_uri); - if (symbol == null) return results; - - foreach (unowned string uri in symbol.parents) - results.append (uri); - - return results; - } - - public static bool is_a (string symbol_uri, string parent_uri) - { - initialize_symbols (); - - foreach (unowned string uri in get_all_parents (symbol_uri)) - if (parent_uri == uri) - return true; - return false; - } - - private static void initialize_symbols () - { - if (initialized) return; - initialized = true; - // *insert-auto-generated-code* - } - - } - - private class Symbol.Info - { - public List parents; - public List children; - public List all_children; - public string uri; - public string display_name; - public string description; - - private Info (string uri, string display_name, string description, - string[] parents, string[] children, string[] all_children) - { - this.uri = uri; - this.display_name = display_name; - this.description = description; - this.parents = new List (); - for (int i = 0; i < parents.length; i++) - this.parents.append (parents[i]); - this.children = new List (); - for (int i = 0; i < children.length; i++) - this.children.append (children[i]); - this.all_children = new List (); - for (int i = 0; i < all_children.length; i++) - this.all_children.append (all_children[i]); - } - - internal static void register (string uri, string display_name, - string description, string[] parents, string[] children, - string[] all_children) - { - if (all_symbols == null) - all_symbols = new HashTable (str_hash, str_equal); - Info symbol = new Info (uri, display_name, description, - parents, children, all_children); - all_symbols.insert (uri, symbol); - } - - } - -} - -// vim:expandtab:ts=4:sw=4 diff --git a/src/remote.vala b/src/remote.vala deleted file mode 100644 index af3e5bc..0000000 --- a/src/remote.vala +++ /dev/null @@ -1,152 +0,0 @@ -/* remote.vala - * - * Copyright © 2011 Collabora Ltd. - * By Siegfried-Angel Gevatter Pujals - * Copyright © 2011 Michal Hruby - * - * This program 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 2.1 of the License, or - * (at your option) any later version. - * - * 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 Lesser General Public License - * along with this program. If not, see . - * - */ - -namespace Zeitgeist -{ - public struct VersionStruct - { - int major; - int minor; - int micro; - } - - [DBus (name = "org.gnome.zeitgeist.Log")] - public interface RemoteLog : Object - { - - [DBus (signature = "(xx)")] - public abstract Variant delete_events ( - uint32[] event_ids, - BusName sender - ) throws Error; - - public abstract uint32[] find_event_ids ( - [DBus (signature = "(xx)")] Variant time_range, - [DBus (signature = "a(asaasay)")] Variant event_templates, - uint storage_state, uint num_events, uint result_type, - BusName sender - ) throws Error; - - [DBus (signature = "a(asaasay)")] - public abstract Variant find_events ( - [DBus (signature = "(xx)")] Variant time_range, - [DBus (signature = "a(asaasay)")] Variant event_templates, - uint storage_state, uint num_events, uint result_type, - BusName sender - ) throws Error; - - public abstract string[] find_related_uris ( - [DBus (signature = "(xx)")] Variant time_range, - [DBus (signature = "a(asaasay)")] Variant event_templates, - [DBus (signature = "a(asaasay)")] Variant result_event_templates, - uint storage_state, uint num_events, uint result_type, - BusName sender - ) throws Error; - - [DBus (signature = "a(asaasay)")] - public abstract Variant get_events ( - uint32[] event_ids, - BusName sender - ) throws Error; - - public abstract uint32[] insert_events ( - [DBus (signature = "a(asaasay)")] Variant events, - BusName sender - ) throws Error; - - public abstract void install_monitor ( - ObjectPath monitor_path, - [DBus (signature = "(xx)")] Variant time_range, - [DBus (signature = "a(asaasay)")] Variant event_templates, - BusName owner - ) throws Error; - - public abstract void remove_monitor ( - ObjectPath monitor_path, - BusName owner - ) throws Error; - - public abstract void quit () throws Error; - - [DBus (name = "extensions")] - public abstract string[] extensions { owned get; } - - [DBus (name = "version")] - public abstract VersionStruct version { owned get; } - - } - - [DBus (name = "org.gnome.zeitgeist.Monitor")] - public interface RemoteMonitor : Object - { - - public async abstract void notify_insert ( - [DBus (signature = "(xx)")] Variant time_range, - [DBus (signature = "a(asaasay)")] Variant events - ) throws IOError, EngineError; - - public async abstract void notify_delete ( - [DBus (signature = "(xx)")] Variant time_range, - uint32[] event_ids - ) throws IOError; - - } - - /* FIXME: Remove this! Only here because of a bug in Vala (see ext-fts) */ - [DBus (name = "org.gnome.zeitgeist.Index")] - public interface RemoteSimpleIndexer : Object - { - public abstract async void search ( - string query_string, - [DBus (signature = "(xx)")] Variant time_range, - [DBus (signature = "a(asaasay)")] Variant filter_templates, - uint offset, uint count, uint result_type, - [DBus (signature = "a(asaasay)")] out Variant events, - out uint matches) throws Error; - public abstract async void search_with_relevancies ( - string query_string, - [DBus (signature = "(xx)")] Variant time_range, - [DBus (signature = "a(asaasay)")] Variant filter_templates, - uint storage_state, uint offset, uint count, uint result_type, - [DBus (signature = "a(asaasay)")] out Variant events, - out double[] relevancies, out uint matches) throws Error; - } - - /* FIXME: Remove this! Only here because of a bug in Vala (see ext-fts) */ - [DBus (name = "org.freedesktop.NetworkManager")] - public interface NetworkManagerDBus : Object - { - [DBus (name = "state")] - public abstract uint32 state () throws IOError; - public signal void state_changed (uint32 state); - } - - /* FIXME: Remove this! Only here because of a bug in Vala (see ext-fts) */ - [DBus (name = "net.connman.Manager")] - public interface ConnmanManagerDBus : Object - { - public abstract string get_state () throws IOError; - public signal void state_changed (string state); - } - -} - -// vim:expandtab:ts=4:sw=4 diff --git a/src/sql.vala b/src/sql.vala index eab9289..a5bc770 100644 --- a/src/sql.vala +++ b/src/sql.vala @@ -144,7 +144,7 @@ namespace Zeitgeist.SQLite // The database disk image is malformed warning ("It looks like your database is corrupt. " + "It will be renamed and a new one will be created."); - Utils.retire_database (); + retire_database (); open_database (false); } else if (rc == Sqlite.PERM || rc == Sqlite.CANTOPEN) @@ -167,6 +167,23 @@ namespace Zeitgeist.SQLite } } + private static void retire_database () throws EngineError + { + try + { + File dbfile = File.new_for_path ( + Utils.get_database_file_path ()); + dbfile.set_display_name ( + Utils.get_database_file_retire_name ()); + } + catch (Error err) + { + string message = "Could not rename database: %s".printf ( + err.message); + throw new EngineError.DATABASE_RETIRE_FAILED (message); + } + } + public uint32 get_last_id () throws EngineError { int last_id = -1; diff --git a/src/utils.vala b/src/utils.vala deleted file mode 100644 index a72b06e..0000000 --- a/src/utils.vala +++ /dev/null @@ -1,203 +0,0 @@ -/* utils.vala - * - * Copyright © 2011 Collabora Ltd. - * By Seif Lotfy - * By Siegfried-Angel Gevatter Pujals - * Copyright © 2011 Michal Hruby - * Copyright © 2011 Manish Sinha - * - * This program 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 2.1 of the License, or - * (at your option) any later version. - * - * 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 Lesser General Public License - * along with this program. If not, see . - * - */ - -namespace Zeitgeist -{ - namespace Utils - { - // Paths - private static string DATA_PATH; - private static string DATABASE_FILE_PATH; - private static string DATABASE_FILE_BACKUP_PATH; - private static string LOCAL_EXTENSIONS_PATH; - - public const string DATA_FOLDER = "zeitgeist"; - public const string DATABASE_BASENAME = "activity.sqlite"; - public const string USER_EXTENSION_PATH = ""; - - // D-Bus - public const string DBUS_INTERFACE = ""; - public const string SIG_EVENT = "asaasay"; - public const size_t MAX_DBUS_RESULT_SIZE = 4 * 1024 * 1024; // 4MiB - - // configure runtime cache for events - // default size is 2000 - public const uint CACHE_SIZE = 0; - - public unowned string get_data_path () - { - if (DATA_PATH != null) return DATA_PATH; - - DATA_PATH = Environment.get_variable ("ZEITGEIST_DATA_PATH") ?? - get_default_data_path (); - - if (!FileUtils.test (DATA_PATH, FileTest.IS_DIR)) - { - DirUtils.create_with_parents (DATA_PATH, 0755); - } - - debug ("DATA_PATH = %s", DATA_PATH); - - return DATA_PATH; - } - - public string get_default_data_path () - { - return Path.build_filename (Environment.get_user_data_dir (), - DATA_FOLDER); - } - - public unowned string get_database_file_path () - { - if (DATABASE_FILE_PATH != null) return DATABASE_FILE_PATH; - - DATABASE_FILE_PATH = - Environment.get_variable ("ZEITGEIST_DATABASE_PATH") ?? - Path.build_filename (get_data_path (), DATABASE_BASENAME); - - debug ("DATABASE_FILE_PATH = %s", DATABASE_FILE_PATH); - - return DATABASE_FILE_PATH; - } - - public unowned string get_database_file_backup_path () - { - if (DATABASE_FILE_BACKUP_PATH != null) - return DATABASE_FILE_BACKUP_PATH; - - DATABASE_FILE_BACKUP_PATH = - Environment.get_variable ("ZEITGEIST_DATABASE_BACKUP_PATH") ?? - Path.build_filename (get_data_path (), - DATABASE_BASENAME + ".bck"); - - debug ("DATABASE_FILE_BACKUP_PATH = %s", DATABASE_FILE_BACKUP_PATH); - - return DATABASE_FILE_BACKUP_PATH; - } - - public string get_database_file_retire_name () - { - return DATABASE_BASENAME + ".%s.bck".printf ( - new DateTime.now_local ().format ("%Y%m%d-%H%M%S")); - } - - public unowned string get_local_extensions_path () - { - if (LOCAL_EXTENSIONS_PATH != null) return LOCAL_EXTENSIONS_PATH; - - LOCAL_EXTENSIONS_PATH = Path.build_filename (get_data_path (), - "extensions"); - - debug ("LOCAL_EXTENSIONS_PATH = %s", LOCAL_EXTENSIONS_PATH); - - return LOCAL_EXTENSIONS_PATH; - } - - public bool using_in_memory_database () - { - return get_database_file_path () == ":memory:"; - } - - public void backup_database () throws Error - { - File original; - File destination; - original = File.new_for_path (get_database_file_path ()); - destination = File.new_for_path (get_database_file_backup_path ()); - - message ("Backing up database to \"%s\" for schema upgrade...", - get_database_file_backup_path ()); - original.copy (destination, FileCopyFlags.OVERWRITE, null, null); - } - - public void retire_database () throws EngineError - { - try - { - File dbfile = File.new_for_path (get_database_file_path ()); - dbfile.set_display_name (get_database_file_retire_name ()); - } - catch (Error err) - { - string message = "Could not rename database: %s".printf ( - err.message); - throw new EngineError.DATABASE_RETIRE_FAILED (message); - } - } - - /** - * Check if the value starts with the negation operator. If it does, - * remove the operator from the value and return true. Otherwise, - * return false. - */ - public static bool parse_negation (ref string val) - { - if (!val.has_prefix ("!")) - return false; - val = val.substring (1); - return true; - } - - /** - * Check if the value starts with the noexpand operator. If it does, - * remove the operator from the value and return true. Otherwise, - * return false. - * - * Check for the negation operator before calling this function. - */ - public static bool parse_noexpand (ref string val) - { - if (!val.has_prefix ("+")) - return false; - val = val.substring (1); - return true; - } - - - /** - * Check if the value ends with the wildcard character. If it does, - * remove the wildcard character from the value and return true. - * Otherwise, return false. - */ - public static bool parse_wildcard (ref string val) - { - if (!val.has_suffix ("*")) - return false; - unowned uint8[] val_data = val.data; - val_data[val_data.length-1] = '\0'; - return true; - } - - /** - * Return true if a string is empty (null or containing just a null - * byte). - */ - public static bool is_empty_string (string? s) - { - return s == null || s == ""; - } - - } -} - -// vim:expandtab:ts=4:sw=4 diff --git a/src/zeitgeist-daemon.vala b/src/zeitgeist-daemon.vala index 9bea3a0..1fc5bdf 100644 --- a/src/zeitgeist-daemon.vala +++ b/src/zeitgeist-daemon.vala @@ -34,7 +34,6 @@ namespace Zeitgeist public class Daemon : Object, RemoteLog { - const string DBUS_NAME = "org.gnome.zeitgeist.Engine"; private static bool show_version_info = false; private static bool show_options = false; private static bool no_datahub = false; @@ -132,20 +131,20 @@ namespace Zeitgeist notifications = MonitorManager.get_default (); } - public Variant get_events (uint32[] event_ids, BusName sender) - throws Error + public async Variant get_events (uint32[] event_ids, Cancellable? cancellable, + BusName? sender=null) throws Error { var timer = new Timer (); GenericArray events = engine.get_events (event_ids); - debug ("%s executed in %f seconds", Log.METHOD, timer.elapsed ()); + debug ("%s executed in %f seconds", GLib.Log.METHOD, timer.elapsed ()); return Events.to_variant_with_limit (events); } - public string[] find_related_uris (Variant time_range, + public async string[] find_related_uris (Variant time_range, Variant event_templates, Variant result_event_templates, uint storage_state, uint num_events, uint result_type, - BusName sender) throws Error + BusName? sender=null) throws Error { return engine.find_related_uris ( new TimeRange.from_variant (time_range), @@ -154,37 +153,40 @@ namespace Zeitgeist storage_state, num_events, result_type); } - public uint32[] find_event_ids (Variant time_range, + public async uint32[] find_event_ids (Variant time_range, Variant event_templates, uint storage_state, uint num_events, uint result_type, - BusName sender) throws Error + Cancellable? cancellable=null, + BusName? sender=null) throws Error { var timer = new Timer (); var ids = engine.find_event_ids ( new TimeRange.from_variant (time_range), Events.from_variant(event_templates), storage_state, num_events, result_type, sender); - debug ("%s executed in %f seconds", Log.METHOD, timer.elapsed ()); + debug ("%s executed in %f seconds", GLib.Log.METHOD, timer.elapsed ()); return ids; } - public Variant find_events (Variant time_range, + public async Variant find_events (Variant time_range, Variant event_templates, uint storage_state, uint num_events, uint result_type, - BusName sender) throws Error + Cancellable? cancellable=null, + BusName? sender=null) throws Error { var timer = new Timer (); var events = engine.find_events ( new TimeRange.from_variant (time_range), Events.from_variant (event_templates), storage_state, num_events, result_type, sender); - debug ("%s executed in %f seconds", Log.METHOD, timer.elapsed ()); + debug ("%s executed in %f seconds", GLib.Log.METHOD, timer.elapsed ()); return Events.to_variant_with_limit (events); } - public uint32[] insert_events ( + public async uint32[] insert_events ( Variant vevents, - BusName sender) throws Error + Cancellable? cancellable=null, + BusName? sender=null) throws Error { var events = Events.from_variant (vevents); @@ -208,8 +210,8 @@ namespace Zeitgeist return event_ids; } - public Variant delete_events (uint32[] event_ids, BusName sender) - throws Error + public async Variant delete_events (uint32[] event_ids, + Cancellable? cancellable=null, BusName? sender=null) throws Error { TimeRange? time_range = engine.delete_events (event_ids, sender); if (time_range != null) @@ -225,7 +227,7 @@ namespace Zeitgeist return time_range.to_variant (); } - public void quit () throws Error + public async void quit (Cancellable? cancellable=null) throws Error { do_quit (); } @@ -236,19 +238,21 @@ namespace Zeitgeist mainloop.quit (); } - public void install_monitor (ObjectPath monitor_path, + public async void install_monitor (ObjectPath monitor_path, Variant time_range, Variant event_templates, - BusName owner) throws Error + BusName? owner=null) throws Error { + assert (owner != null); notifications.install_monitor (owner, monitor_path, new TimeRange.from_variant (time_range), Events.from_variant (event_templates)); } - public void remove_monitor (ObjectPath monitor_path, BusName owner) + public async void remove_monitor (ObjectPath monitor_path, BusName? owner=null) throws Error { + assert (owner != null); notifications.remove_monitor (owner, monitor_path); } @@ -256,7 +260,7 @@ namespace Zeitgeist { connection = conn; log_register_id = conn.register_object ( - "/org/gnome/zeitgeist/log/activity", this); + Utils.ENGINE_DBUS_PATH, this); } public void unregister_dbus_object () @@ -273,7 +277,8 @@ namespace Zeitgeist try { var running_instance = conn.get_proxy_sync ( - DBUS_NAME, "/org/gnome/zeitgeist/log/activity"); + Utils.ENGINE_DBUS_NAME, Utils.ENGINE_DBUS_PATH); + running_instance.quit (); return true; } @@ -349,7 +354,7 @@ namespace Zeitgeist var proxy = connection.get_proxy_sync ( "org.freedesktop.DBus", "/org/freedesktop/DBus", DBusProxyFlags.DO_NOT_LOAD_PROPERTIES); - name_owned = proxy.name_has_owner (DBUS_NAME); + name_owned = proxy.name_has_owner (Utils.ENGINE_DBUS_NAME); } catch (IOError err) { @@ -397,7 +402,7 @@ namespace Zeitgeist } uint owner_id = Bus.own_name_on_connection (connection, - DBUS_NAME, + Utils.ENGINE_DBUS_NAME, BusNameOwnerFlags.NONE, name_acquired_callback, name_lost_callback); diff --git a/test/direct/Makefile.am b/test/direct/Makefile.am index 468c97c..115e5ed 100644 --- a/test/direct/Makefile.am +++ b/test/direct/Makefile.am @@ -21,21 +21,21 @@ TESTS = \ SRC_FILES = \ $(top_srcdir)/src/db-reader.vala \ $(top_srcdir)/src/engine.vala \ - $(top_srcdir)/src/utils.vala \ + $(top_srcdir)/libzeitgeist/utils.vala \ $(top_srcdir)/src/errors.vala \ $(top_srcdir)/src/extension-store.vala \ $(top_srcdir)/src/notify.vala \ $(top_srcdir)/src/table-lookup.vala \ - $(top_srcdir)/src/datamodel.vala \ + $(top_srcdir)/libzeitgeist/datamodel.vala \ $(top_srcdir)/src/where-clause.vala \ - $(top_srcdir)/src/remote.vala \ + $(top_srcdir)/libzeitgeist/remote.vala \ $(top_srcdir)/src/sql-schema.vala \ $(top_srcdir)/src/extension.vala \ $(top_srcdir)/src/extension-collection.vala \ $(top_srcdir)/src/sql.vala \ - $(top_srcdir)/src/ontology.vala \ - $(top_srcdir)/src/ontology-uris.vala \ - $(top_srcdir)/src/mimetype.vala \ + $(top_srcdir)/libzeitgeist/ontology.vala \ + $(top_srcdir)/libzeitgeist/ontology-uris.vala \ + $(top_srcdir)/libzeitgeist/mimetype.vala \ $(NULL) datamodel-test: datamodel-test.vala $(SRC_FILES) diff --git a/test/direct/marshalling-test.vala b/test/direct/marshalling-test.vala index d5f1c54..7c9ec6d 100644 --- a/test/direct/marshalling-test.vala +++ b/test/direct/marshalling-test.vala @@ -120,7 +120,7 @@ void corrupt_events_test () { new Event.from_variant (v); } - catch (EngineError.INVALID_SIGNATURE err) { + catch (DataModelError.INVALID_SIGNATURE err) { error_thrown = true; } assert (error_thrown); @@ -153,7 +153,7 @@ void corrupt_subjects_test () { new Subject.from_variant (v); } - catch (EngineError.INVALID_SIGNATURE err) + catch (DataModelError.INVALID_SIGNATURE err) { error_thrown = true; } @@ -166,7 +166,7 @@ void corrupt_subjects_test () { new Subject.from_variant (v); } - catch (EngineError.INVALID_SIGNATURE err) + catch (DataModelError.INVALID_SIGNATURE err) { error_thrown = true; } @@ -181,7 +181,7 @@ void corrupt_timerange_test () { new TimeRange.from_variant (v); } - catch (EngineError.INVALID_SIGNATURE err) + catch (DataModelError.INVALID_SIGNATURE err) { error_thrown = true; }