hud-14.04+14.04.20140604/0000755000015301777760000000000012343624372014706 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tools/0000755000015301777760000000000012343624372016046 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tools/hud-cli-toolbar.c0000644000015301777760000000226212343623451021176 0ustar pbusernogroup00000000000000/* Small utility to excersise the HUD from the command line Copyright 2011 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include int main (int argc, char *argv[]) { #ifndef GLIB_VERSION_2_36 g_type_init (); #endif const gchar * action = "help"; if (argc == 2) { action = argv[1]; } g_print("\ntoolbar action: %s\n", action); HudClientQuery * client_query = NULL; client_query = hud_client_query_new(""); hud_client_query_execute_toolbar_item(client_query, hud_client_query_toolbar_items_get_value_from_nick(action), 0); g_clear_object(&client_query); return 0; } hud-14.04+14.04.20140604/tools/hudkeywords/0000755000015301777760000000000012343624372020416 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tools/hudkeywords/setup.py0000755000015301777760000000235712343623451022137 0ustar pbusernogroup00000000000000#!/usr/bin/env python # Copyright (C) 2005-2012 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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 General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import os from setuptools import setup def read(fname): return open(os.path.join(os.path.dirname(__file__), fname)).read() setup(name='hudkeywords', version='1.0', description='HUD keywords tool', license='GNU GPL v2', author='Pete Woods', author_email='pete.woods@canonical.com', scripts=['bin/hudkeywords'], packages=['hudkeywords'], url='http://launchpad.net/hud', long_description=read('README'), test_suite='tests' ) hud-14.04+14.04.20140604/tools/hudkeywords/tests/0000755000015301777760000000000012343624372021560 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tools/hudkeywords/tests/po_test.py0000644000015301777760000000363412343623451023612 0ustar pbusernogroup00000000000000# Copyright (C) 2005-2012 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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 General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import unittest, os, tests from hudkeywords.po import PoFile from tempfile import mkstemp class TestPoFile(unittest.TestCase): def test_save(self): po = PoFile(self.infile) po.save(self.outfile) with os.fdopen(self.outhandle, 'r') as f: self.assertMultiLineEqual(f.read(), tests.PO_OUTPUT) def test_save_xml(self): po = PoFile(self.infile) po.save_xml(self.outfile) with os.fdopen(self.outhandle, 'r') as f: self.assertMultiLineEqual(f.read(), tests.XML_OUTPUT) def test_save_xml_existing(self): with open(self.outfile, 'w') as f: f.write(tests.XML_INPUT) po = PoFile(self.infile) po.save_xml(self.outfile) with open(self.outfile, 'r') as f: self.assertMultiLineEqual(tests.XML_OUTPUT_EXISTING, f.read()) def setUp(self): self.maxDiff = None self.inhandle, self.infile = mkstemp() with os.fdopen(self.inhandle, 'w') as f: f.write(tests.INPUT) self.outhandle, self.outfile = mkstemp() def tearDown(self): os.remove(self.infile) os.remove(self.outfile)hud-14.04+14.04.20140604/tools/hudkeywords/tests/__init__.py0000644000015301777760000000366012343623451023673 0ustar pbusernogroup00000000000000 INPUT = r'''# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: hellogt 1.2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-11-21 14:24+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" "Language: \n" #: hellogt.cxx:16 msgid "hello, world!" msgstr "" #: hellogt.cxx:17 hellogt.cxx:19 msgid "another string" msgstr "" #: hellogt.cxx:20 msgid "another string 2" msgstr "" ''' PO_OUTPUT = INPUT + r''' #: hellogt.cxx:16 msgid "hud-keywords:hello, world!" msgstr "" #: hellogt.cxx:17 hellogt.cxx:19 msgid "hud-keywords:another string" msgstr "" #: hellogt.cxx:20 msgid "hud-keywords:another string 2" msgstr "" ''' XML_OUTPUT = r''' ''' XML_INPUT = r''' ''' XML_OUTPUT_EXISTING = r''' '''hud-14.04+14.04.20140604/tools/hudkeywords/tests/cli_test.py0000644000015301777760000000335512343623451023743 0ustar pbusernogroup00000000000000# Copyright (C) 2005-2012 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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 General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import unittest, os, subprocess, tests from tempfile import mkstemp class TestCli(unittest.TestCase): def test_save(self): subprocess.call(["bin/hudkeywords", self.infile], env={"PYTHONPATH": "."}) with open(self.infile, 'r') as f: self.assertMultiLineEqual(f.read(), tests.PO_OUTPUT) def test_save_xml(self): subprocess.call(["bin/hudkeywords", self.infile, "-x", self.outfile], env={"PYTHONPATH": "."}) with open(self.infile, 'r') as f: self.assertMultiLineEqual(f.read(), tests.PO_OUTPUT) with os.fdopen(self.outhandle, 'r') as f: self.assertMultiLineEqual(f.read(), tests.XML_OUTPUT) def setUp(self): self.maxDiff = None self.inhandle, self.infile = mkstemp() with os.fdopen(self.inhandle, 'w') as f: f.write(tests.INPUT) self.outhandle, self.outfile = mkstemp() def tearDown(self): os.remove(self.infile) os.remove(self.outfile) hud-14.04+14.04.20140604/tools/hudkeywords/bin/0000755000015301777760000000000012343624372021166 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tools/hudkeywords/bin/hudkeywords0000755000015301777760000000153412343623451023464 0ustar pbusernogroup00000000000000#!/usr/bin/env python # Copyright (C) 2005-2012 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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 General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import sys from hudkeywords import cli if __name__ == '__main__': sys.exit(cli.main())hud-14.04+14.04.20140604/tools/hudkeywords/hudkeywords/0000755000015301777760000000000012343624372022766 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tools/hudkeywords/hudkeywords/__init__.py0000644000015301777760000000000012343623451025062 0ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tools/hudkeywords/hudkeywords/cli.py0000644000015301777760000000650112343623451024106 0ustar pbusernogroup00000000000000# Copyright (C) 2005-2012 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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 General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ''' hudkeywords.cli -- shortdesc hudkeywords.cli is a description It defines classes_and_methods ''' import sys import os from argparse import ArgumentParser from argparse import RawDescriptionHelpFormatter import po __all__ = [] __version__ = 1.0 class CLIError(BaseException): '''Generic exception to raise and log different fatal errors.''' def __init__(self, msg): super(CLIError).__init__(type(self)) self.msg = "Error: %s" % msg def main(argv=None): # IGNORE:C0111 '''Command line options.''' if argv is None: argv = sys.argv else: sys.argv.extend(argv) program_name = os.path.basename(sys.argv[0]) program_version = "v%s" % __version__ program_version_message = '%%(prog)s %s' % (program_version) program_shortdesc = 'Simple python tool for creating po and keyword XML files for HUD.' try: # Setup argument parser parser = ArgumentParser(description=program_shortdesc, formatter_class=RawDescriptionHelpFormatter) parser.add_argument("pofile", help="The PO file to add hud-keyword: entries to") parser.add_argument("-v", "--verbose", dest="verbose", action="count", help="set verbosity level") parser.add_argument("-x", "--xmloutput", dest="xmloutput", help="Write out a keyword mapping file into this XML file") parser.add_argument('-V', '--version', action='version', version=program_version_message) # Process arguments args = parser.parse_args() if not os.path.exists(args.pofile): raise CLIError("PO file [{}] does not exist.".format(args.pofile)) if args.verbose > 0: print("Reading PO file [{}]".format(args.pofile)) po_file = po.PoFile(args.pofile) if args.verbose > 0: print("Updating PO file [{}]".format(args.pofile)) po_file.save(args.pofile) if args.xmloutput: if args.verbose > 0: print("Writing to XML output file [{}]".format(args.xmloutput)) po_file.save_xml(args.xmloutput); return 0 except KeyboardInterrupt: ### handle keyboard interrupt ### return 0 except CLIError, e: indent = len(program_name) * " " sys.stderr.write(program_name + ": " + e.msg + "\n") sys.stderr.write(indent + " for help use --help\n") return 2 except Exception, e: indent = len(program_name) * " " sys.stderr.write(program_name + ": " + repr(e) + "\n") sys.stderr.write(indent + " for help use --help\n") return 2 hud-14.04+14.04.20140604/tools/hudkeywords/hudkeywords/po.py0000644000015301777760000000715712343623451023765 0ustar pbusernogroup00000000000000# Copyright (C) 2005-2012 Canonical Ltd # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 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 General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ''' Created on 10 Dec 2012 ''' import polib, os, sys from lxml import etree from lxml.etree import Element, ElementTree, SubElement class PoFile: def __init__(self, infile): self.original = polib.pofile(infile) self.po = polib.pofile(infile) self._add_keyword_entries() def _add_keyword_entries(self): new_entries = [] for entry in self.po: if entry.obsolete: continue # Don't add keyword entries again if entry.msgid.startswith(u'hud-keywords:'): continue new_entry = polib.POEntry( msgid = u'hud-keywords:{}'.format(entry.msgid), msgstr = u'', tcomment = entry.tcomment, occurrences = entry.occurrences, flags = entry.flags, previous_msgctxt = entry.previous_msgctxt, previous_msgid = entry.previous_msgid, previous_msgid_plural = entry.previous_msgid_plural, ) # Don't add entries that are already there if new_entry not in self.po: new_entries.append(new_entry) for entry in new_entries: self.po.append(entry) def save(self, path): self.po.save(path) def _read_existing_mappings(self, path): existing = {} if os.path.exists(path) and os.path.getsize(path) > 0: keyword_mapping = etree.parse(path).getroot() for mapping in keyword_mapping.xpath('//keywordMapping/mapping'): original = mapping.get('original') keywords = [] for keyword in mapping: keywords.append(keyword.get('name')) existing[original] = keywords return existing def save_xml(self, path): existing = self._read_existing_mappings(path) keyword_mapping = Element('keywordMapping') for entry in self.original: # No point adding obsolete entries if entry.obsolete: continue # Don't add keyword entries again if entry.msgid.startswith(u'hud-keywords:'): continue mapping = SubElement(keyword_mapping, 'mapping', original=entry.msgid) # Either use the old mappings or add some blank ones if entry.msgid in existing: for keyword in existing[entry.msgid]: SubElement(mapping, 'keyword', name=keyword) else: SubElement(mapping, 'keyword', name='') SubElement(mapping, 'keyword', name='') ElementTree(keyword_mapping).write(path, encoding='utf-8', xml_declaration=True, pretty_print=True) hud-14.04+14.04.20140604/tools/hudkeywords/CMakeLists.txt0000644000015301777760000000230612343623451023154 0ustar pbusernogroup00000000000000find_program(PYTHON "python") if (PYTHON) set(PYTHON_ROOT ${CMAKE_INSTALL_PREFIX}) set(PYTHON_PREFIX ".") if(DEFINED DEBIAN_TARGET_DIR) set(PYTHON_ROOT ${DEBIAN_TARGET_DIR}) set(PYTHON_PREFIX "usr") set(PYTHON_LAYOUT "--install-layout=deb") endif() set(SETUP_PY ${CMAKE_CURRENT_SOURCE_DIR}/setup.py) file(GLOB_RECURSE DEPS *.py) set(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build") add_custom_command( OUTPUT ${OUTPUT} COMMAND ${PYTHON} ${SETUP_PY} build --build-base ${OUTPUT} --build-temp ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${DEPS} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_custom_target(target ALL DEPENDS ${OUTPUT}) install(CODE " execute_process( COMMAND ${PYTHON} ${SETUP_PY} build --build-base ${OUTPUT} --build-temp ${CMAKE_CURRENT_BINARY_DIR} install --root=${PYTHON_ROOT} --prefix=${PYTHON_PREFIX} ${PYTHON_LAYOUT} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) ") add_test(hudkeywords-check ${PYTHON} ${SETUP_PY} test) set_tests_properties(hudkeywords-check PROPERTIES WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endif()hud-14.04+14.04.20140604/tools/hudkeywords/README0000644000015301777760000000012012343623451021264 0ustar pbusernogroup00000000000000A tool for creating translation (po) and XML keyword files associated with HUD. hud-14.04+14.04.20140604/tools/hud-cli-appstack.c0000644000015301777760000000622312343623451021343 0ustar pbusernogroup00000000000000/* Small utility to excersise the HUD from the command line Copyright 2011 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include static void print_suggestions(const char * query); static void models_ready (HudClientQuery * client_query, gpointer user_data); static HudClientQuery * client_query = NULL; int main (int argc, char *argv[]) { #ifndef GLIB_VERSION_2_36 g_type_init (); #endif const gchar * search = ""; if (argc == 2) { search = argv[1]; } printf("\nsearch token: %s\n", search); print_suggestions(search); g_clear_object(&client_query); return 0; } static void wait_for_sync_notify (GObject * object, GParamSpec * pspec, gpointer user_data) { GMainLoop * loop = (GMainLoop *)user_data; g_main_loop_quit(loop); return; } static gboolean wait_for_sync (DeeModel * model) { if (dee_shared_model_is_synchronized(DEE_SHARED_MODEL(model))) { return TRUE; } GMainLoop * loop = g_main_loop_new(NULL, FALSE); glong sig = g_signal_connect(G_OBJECT(model), "notify::synchronized", G_CALLBACK(wait_for_sync_notify), loop); g_main_loop_run(loop); g_main_loop_unref(loop); g_signal_handler_disconnect(G_OBJECT(model), sig); return dee_shared_model_is_synchronized(DEE_SHARED_MODEL(model)); } static void print_suggestions (const char *query) { if (client_query == NULL) { client_query = hud_client_query_new(query); GMainLoop * loop = g_main_loop_new(NULL, FALSE); guint sig = g_signal_connect(G_OBJECT(client_query), HUD_CLIENT_QUERY_SIGNAL_MODELS_CHANGED, G_CALLBACK(models_ready), loop); g_main_loop_run(loop); g_main_loop_unref(loop); g_signal_handler_disconnect(G_OBJECT(client_query), sig); } else { hud_client_query_set_query(client_query, query); models_ready(client_query, NULL); } return; } static void models_ready (HudClientQuery * client_query, gpointer user_data) { DeeModel * model = hud_client_query_get_appstack_model(client_query); g_return_if_fail(wait_for_sync(model)); g_print("\tApp ID\tIcon\n"); DeeModelIter * iter = NULL; int i = 0; for (iter = dee_model_get_first_iter(model); !dee_model_is_last(model, iter); iter = dee_model_next(model, iter), i++) { const gchar * id = hud_client_query_appstack_get_app_id(client_query, iter); const gchar * icon = hud_client_query_appstack_get_app_icon(client_query, iter); g_print("\t%s\t%s\n", id, icon); } if (user_data != NULL) { GMainLoop * loop = (GMainLoop *)user_data; g_main_loop_quit(loop); } return; } hud-14.04+14.04.20140604/tools/CMakeLists.txt0000644000015301777760000000237312343623451020610 0ustar pbusernogroup00000000000000 add_subdirectory(hudkeywords) include_directories(${HUD_CLIENT_INCLUDE_DIRS}) include_directories(${HUD_SERVICE_INCLUDE_DIRS}) pkg_check_modules(PANGO REQUIRED pango) include_directories(${PANGO_INCLUDE_DIRS}) ########################### # Hud CLI ########################### add_executable(hud-cli hud-cli.c) target_link_libraries(hud-cli hud-client ${PANGO_LIBRARIES} ) install( TARGETS hud-cli RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) ########################### # Hud CLI Param ########################### add_executable(hud-cli-param hud-cli-param.c) target_link_libraries(hud-cli-param hud-client ${PANGO_LIBRARIES} ) install( TARGETS hud-cli-param RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) ########################### # Hud CLI Appstack ########################### add_executable(hud-cli-appstack hud-cli-appstack.c) target_link_libraries(hud-cli-appstack hud-client ) install( TARGETS hud-cli-appstack RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) ########################### # Hud CLI Toolbar ########################### add_executable(hud-cli-toolbar hud-cli-toolbar.c) target_link_libraries(hud-cli-toolbar hud-client ) install( TARGETS hud-cli-toolbar RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" ) hud-14.04+14.04.20140604/tools/hud-cli-param.c0000644000015301777760000001356312343623451020642 0ustar pbusernogroup00000000000000/* Small utility to excersise the HUD from the command line Copyright 2011 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include static void print_suggestions(const char * query); static void models_ready (HudClientQuery * client_query, gpointer user_data); static HudClientQuery * client_query = NULL; int main (int argc, char *argv[]) { #ifndef GLIB_VERSION_2_36 g_type_init (); #endif const gchar * search = ""; if (argc == 2) { search = argv[1]; } printf("\nsearch token: %s\n", search); print_suggestions(search); g_clear_object(&client_query); return 0; } /* Notification from Dee that we can stop waiting */ static void wait_for_sync_notify (GObject * object, GParamSpec * pspec, gpointer user_data) { GMainLoop * loop = (GMainLoop *)user_data; g_main_loop_quit(loop); return; } /* Waits for the DeeModel of results to get synchoronized from the HUD service */ static gboolean wait_for_sync (DeeModel * model) { if (dee_shared_model_is_synchronized(DEE_SHARED_MODEL(model))) { return TRUE; } GMainLoop * loop = g_main_loop_new(NULL, FALSE); glong sig = g_signal_connect(G_OBJECT(model), "notify::synchronized", G_CALLBACK(wait_for_sync_notify), loop); g_main_loop_run(loop); g_main_loop_unref(loop); g_signal_handler_disconnect(G_OBJECT(model), sig); return dee_shared_model_is_synchronized(DEE_SHARED_MODEL(model)); } /* Prints out the label for each item in the model. Makes it easier to see what we've got */ static void print_model (GMenuModel * model) { int i; for (i = 0; i < g_menu_model_get_n_items(model); i++) { GVariant * vlabel = g_menu_model_get_item_attribute_value(model, i, G_MENU_ATTRIBUTE_LABEL, G_VARIANT_TYPE_STRING); if (vlabel == NULL) { g_print("\t\t(null)\n"); continue; } g_print("\t\t%s\n", g_variant_get_string(vlabel, NULL)); g_variant_unref(vlabel); } return; } /* Quit the mainloop if we get anything */ static void population_update (GMenuModel * model, gint position, gint removed, gint added, GMainLoop * loop) { g_main_loop_quit(loop); return; } /* Waiting here for the model to get populated with something before printing. In a real world scenario you'd probably be responsive to the items being added. We're a CLI tool. */ static void populated_model (GMenuModel * model) { if (g_menu_model_get_n_items(model) == 0) { GMainLoop * loop = g_main_loop_new(NULL, FALSE); gulong sig = g_signal_connect(model, "items-changed", G_CALLBACK(population_update), loop); g_main_loop_run(loop); g_main_loop_unref(loop); g_signal_handler_disconnect(model, sig); } return print_model(model); } /* Signal from the Client Param that it now has a model ready for us to look at. This doesn't mean that the model has any data in it, but that the object is available. */ static void model_ready (HudClientParam * param, GMainLoop * loop) { GMenuModel * model = hud_client_param_get_model(param); if (model != NULL) { populated_model(model); } else { g_warning("Unable to get model even after it was 'ready'"); } g_main_loop_quit(loop); return; } /* Prints out the entries from the search, but only the parameterized ones. Then it looks at each parameterized one prints out the items that are available as parameters */ static void print_suggestions (const char *query) { if (client_query == NULL) { client_query = hud_client_query_new(query); GMainLoop * loop = g_main_loop_new(NULL, FALSE); guint sig = g_signal_connect(G_OBJECT(client_query), HUD_CLIENT_QUERY_SIGNAL_MODELS_CHANGED, G_CALLBACK(models_ready), loop); g_main_loop_run(loop); g_main_loop_unref(loop); g_signal_handler_disconnect(G_OBJECT(client_query), sig); } else { hud_client_query_set_query(client_query, query); models_ready(client_query, NULL); } return; } static void models_ready (HudClientQuery * client_query, gpointer user_data) { DeeModel * model = hud_client_query_get_results_model(client_query); g_return_if_fail(wait_for_sync(model)); DeeModelIter * iter = NULL; int i = 0; for (iter = dee_model_get_first_iter(model); !dee_model_is_last(model, iter); iter = dee_model_next(model, iter), i++) { if (!hud_client_query_results_is_parameterized(client_query, iter)) { /* Only want parameterized */ continue; } const gchar * suggestion = hud_client_query_results_get_command_name(client_query, iter); gchar * clean_line = NULL; pango_parse_markup(suggestion, -1, 0, NULL, &clean_line, NULL, NULL); printf("\t%s\n", clean_line); free(clean_line); HudClientParam * param = hud_client_query_execute_param_command(client_query, hud_client_query_results_get_command_id(client_query, iter), 0); g_return_if_fail(param != NULL); GMenuModel * model = hud_client_param_get_model(param); if (model == NULL) { GMainLoop * loop = g_main_loop_new(NULL, FALSE); gulong sig = g_signal_connect(param, "model-ready", G_CALLBACK(model_ready), loop); g_main_loop_run(loop); g_main_loop_unref(loop); g_signal_handler_disconnect(param, sig); } else { populated_model(model); } hud_client_param_send_cancel(param); g_object_unref(param); } if (user_data != NULL) { GMainLoop * loop = (GMainLoop *)user_data; g_main_loop_quit(loop); } return; } hud-14.04+14.04.20140604/tools/hud-cli.c0000644000015301777760000000624012343623451017536 0ustar pbusernogroup00000000000000/* Small utility to excersise the HUD from the command line Copyright 2011 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define _GNU_SOURCE #include #include #include #include static void print_suggestions(const char * query); static void models_ready (HudClientQuery * client_query, gpointer user_data); static HudClientQuery * client_query = NULL; int main (int argc, char *argv[]) { #ifndef GLIB_VERSION_2_36 g_type_init (); #endif const gchar * search = ""; if (argc == 2) { search = argv[1]; } printf("\nsearch token: %s\n", search); print_suggestions(search); g_clear_object(&client_query); return 0; } static void wait_for_sync_notify (GObject * object, GParamSpec * pspec, gpointer user_data) { GMainLoop * loop = (GMainLoop *)user_data; g_main_loop_quit(loop); return; } static gboolean wait_for_sync (DeeModel * model) { g_return_val_if_fail(DEE_IS_SHARED_MODEL(model), FALSE); if (dee_shared_model_is_synchronized(DEE_SHARED_MODEL(model))) { return TRUE; } GMainLoop * loop = g_main_loop_new(NULL, FALSE); glong sig = g_signal_connect(G_OBJECT(model), "notify::synchronized", G_CALLBACK(wait_for_sync_notify), loop); g_main_loop_run(loop); g_main_loop_unref(loop); g_signal_handler_disconnect(G_OBJECT(model), sig); return dee_shared_model_is_synchronized(DEE_SHARED_MODEL(model)); } static void print_suggestions (const char *query) { if (client_query == NULL) { client_query = hud_client_query_new(query); GMainLoop * loop = g_main_loop_new(NULL, FALSE); guint sig = g_signal_connect(G_OBJECT(client_query), HUD_CLIENT_QUERY_SIGNAL_MODELS_CHANGED, G_CALLBACK(models_ready), loop); g_main_loop_run(loop); g_main_loop_unref(loop); g_signal_handler_disconnect(G_OBJECT(client_query), sig); } else { hud_client_query_set_query(client_query, query); models_ready(client_query, NULL); } return; } static void models_ready (HudClientQuery * client_query, gpointer user_data) { DeeModel * model = hud_client_query_get_results_model(client_query); g_return_if_fail(wait_for_sync(model)); DeeModelIter * iter = NULL; int i = 0; for (iter = dee_model_get_first_iter(model); !dee_model_is_last(model, iter); iter = dee_model_next(model, iter), i++) { const gchar * suggestion = dee_model_get_string(model, iter, 1); gchar * clean_line = NULL; pango_parse_markup(suggestion, -1, 0, NULL, &clean_line, NULL, NULL); printf("\t%s\n", clean_line); g_free(clean_line); } if (user_data != NULL) { GMainLoop * loop = (GMainLoop *)user_data; g_main_loop_quit(loop); } return; } hud-14.04+14.04.20140604/cmake/0000755000015301777760000000000012343624372015766 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/cmake/FindGObjectIntrospection.cmake0000644000015301777760000000376512343623451023677 0ustar pbusernogroup00000000000000# - try to find gobject-introspection # # Once done this will define # # INTROSPECTION_FOUND - system has gobject-introspection # INTROSPECTION_SCANNER - the gobject-introspection scanner, g-ir-scanner # INTROSPECTION_COMPILER - the gobject-introspection compiler, g-ir-compiler # INTROSPECTION_GENERATE - the gobject-introspection generate, g-ir-generate # INTROSPECTION_GIRDIR # INTROSPECTION_TYPELIBDIR # INTROSPECTION_CFLAGS # INTROSPECTION_LIBS # # Copyright (C) 2010, Pino Toscano, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. macro(_GIR_GET_PKGCONFIG_VAR _outvar _varname) execute_process( COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=${_varname} gobject-introspection-1.0 OUTPUT_VARIABLE _result RESULT_VARIABLE _null ) if (_null) else() string(REGEX REPLACE "[\r\n]" " " _result "${_result}") string(REGEX REPLACE " +$" "" _result "${_result}") separate_arguments(_result) set(${_outvar} ${_result} CACHE INTERNAL "") endif() endmacro(_GIR_GET_PKGCONFIG_VAR) find_package(PkgConfig) if(PKG_CONFIG_FOUND) if(PACKAGE_FIND_VERSION_COUNT GREATER 0) set(_gir_version_cmp ">=${PACKAGE_FIND_VERSION}") endif() pkg_check_modules(_pc_gir gobject-introspection-1.0${_gir_version_cmp}) if(_pc_gir_FOUND) set(INTROSPECTION_FOUND TRUE) _gir_get_pkgconfig_var(INTROSPECTION_SCANNER "g_ir_scanner") _gir_get_pkgconfig_var(INTROSPECTION_COMPILER "g_ir_compiler") _gir_get_pkgconfig_var(INTROSPECTION_GENERATE "g_ir_generate") _gir_get_pkgconfig_var(INTROSPECTION_GIRDIR "girdir") _gir_get_pkgconfig_var(INTROSPECTION_TYPELIBDIR "typelibdir") set(INTROSPECTION_CFLAGS "${_pc_gir_CFLAGS}") set(INTROSPECTION_LIBS "${_pc_gir_LIBS}") endif() endif() mark_as_advanced( INTROSPECTION_SCANNER INTROSPECTION_COMPILER INTROSPECTION_GENERATE INTROSPECTION_GIRDIR INTROSPECTION_TYPELIBDIR INTROSPECTION_CFLAGS INTROSPECTION_LIBS ) hud-14.04+14.04.20140604/cmake/UseVala.cmake0000644000015301777760000002067412343623451020336 0ustar pbusernogroup00000000000000# - Precompilation of Vala/Genie source files into C sources # Makes use of the parallel build ability introduced in Vala 0.11. Derived # from a similar module by Jakob Westhoff and the original GNU Make rules. # Might be a bit oversimplified. # # This module defines three functions. The first one: # # vala_init (id # [DIRECTORY dir] - Output directory (binary dir by default) # [PACKAGES package...] - Package dependencies # [OPTIONS option...] - Extra valac options # [CUSTOM_VAPIS file...]) - Custom vapi files to include in the build # [DEPENDS targets...]) - Extra dependencies for code generation # # initializes a single precompilation unit using the given arguments. # You can put files into it via the following function: # # vala_add (id source.vala # [DEPENDS source...]) - Vala/Genie source or .vapi dependencies # # Finally retrieve paths for generated C files by calling: # # vala_finish (id # [SOURCES sources_var] - Input Vala/Genie sources # [OUTPUTS outputs_var] - Output C sources # [GENERATE_HEADER id.h - Generate id.h and id_internal.h # [GENERATE_VAPI id.vapi] - Generate a vapi file # [GENERATE_SYMBOLS id.def]]) - Generate a list of public symbols # #============================================================================= # Copyright Přemysl Janouch 2011 # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. #============================================================================= find_package (Vala 0.11 REQUIRED) include (CMakeParseArguments) function (vala_init id) set (_multi_value PACKAGES OPTIONS CUSTOM_VAPIS DEPENDS) cmake_parse_arguments (arg "" "DIRECTORY" "${_multi_value}" ${ARGN}) if (arg_DIRECTORY) set (directory ${arg_DIRECTORY}) if (NOT IS_DIRECTORY ${directory}) file (MAKE_DIRECTORY ${directory}) endif (NOT IS_DIRECTORY ${directory}) else (arg_DIRECTORY) set (directory ${CMAKE_CURRENT_BINARY_DIR}) endif (arg_DIRECTORY) set (pkg_opts) foreach (pkg ${arg_PACKAGES}) list (APPEND pkg_opts "--pkg=${pkg}") endforeach (pkg) set (VALA_${id}_DIR "${directory}" PARENT_SCOPE) set (VALA_${id}_ARGS ${pkg_opts} ${arg_OPTIONS} ${arg_CUSTOM_VAPIS} PARENT_SCOPE) set (VALA_${id}_DEPENDS ${arg_DEPENDS} PARENT_SCOPE) set (VALA_${id}_SOURCES "" PARENT_SCOPE) set (VALA_${id}_OUTPUTS "" PARENT_SCOPE) set (VALA_${id}_FAST_VAPI_FILES "" PARENT_SCOPE) set (VALA_${id}_FAST_VAPI_ARGS "" PARENT_SCOPE) endfunction (vala_init) function (vala_add id file) cmake_parse_arguments (arg "" "" "DEPENDS" ${ARGN}) if (NOT IS_ABSOLUTE "${file}") set (file "${CMAKE_CURRENT_SOURCE_DIR}/${file}") endif (NOT IS_ABSOLUTE "${file}") get_filename_component (output_name "${file}" NAME) get_filename_component (output_base "${file}" NAME_WE) set (output_base "${VALA_${id}_DIR}/${output_base}") # XXX: It would be best to have it working without touching the vapi # but it appears this cannot be done in CMake. add_custom_command (OUTPUT "${output_base}.vapi" COMMAND ${VALA_COMPILER} "${file}" "--fast-vapi=${output_base}.vapi" COMMAND ${CMAKE_COMMAND} -E touch "${output_base}.vapi" DEPENDS "${file}" COMMENT "Generating a fast vapi for ${output_name}" VERBATIM) set (vapi_opts) set (vapi_depends) foreach (vapi ${arg_DEPENDS}) if (NOT IS_ABSOLUTE "${vapi}") set (vapi "${VALA_${id}_DIR}/${vapi}.vapi") endif (NOT IS_ABSOLUTE "${vapi}") list (APPEND vapi_opts "--use-fast-vapi=${vapi}") list (APPEND vapi_depends "${vapi}") endforeach (vapi) add_custom_command (OUTPUT "${output_base}.c" COMMAND ${VALA_COMPILER} "${file}" -C ${vapi_opts} ${VALA_${id}_ARGS} COMMAND ${CMAKE_COMMAND} -E touch "${output_base}.c" DEPENDS "${file}" ${vapi_depends} ${VALA_${id}_DEPENDS} WORKING_DIRECTORY "${VALA_${id}_DIR}" COMMENT "Precompiling ${output_name}" VERBATIM) set (VALA_${id}_SOURCES ${VALA_${id}_SOURCES} "${file}" PARENT_SCOPE) set (VALA_${id}_OUTPUTS ${VALA_${id}_OUTPUTS} "${output_base}.c" PARENT_SCOPE) set (VALA_${id}_FAST_VAPI_FILES ${VALA_${id}_FAST_VAPI_FILES} "${output_base}.vapi" PARENT_SCOPE) set (VALA_${id}_FAST_VAPI_ARGS ${VALA_${id}_FAST_VAPI_ARGS} "--use-fast-vapi=${output_base}.vapi" PARENT_SCOPE) endfunction (vala_add) function (vala_finish id) set (_one_value SOURCES OUTPUTS GENERATE_VAPI GENERATE_HEADER GENERATE_SYMBOLS) cmake_parse_arguments (arg "" "${_one_value}" "" ${ARGN}) if (arg_SOURCES) set (${arg_SOURCES} ${VALA_${id}_SOURCES} PARENT_SCOPE) endif (arg_SOURCES) if (arg_OUTPUTS) set (${arg_OUTPUTS} ${VALA_${id}_OUTPUTS} PARENT_SCOPE) endif (arg_OUTPUTS) set (outputs) set (export_args) if (arg_GENERATE_VAPI) if (NOT IS_ABSOLUTE "${arg_GENERATE_VAPI}") set (arg_GENERATE_VAPI "${VALA_${id}_DIR}/${arg_GENERATE_VAPI}") endif (NOT IS_ABSOLUTE "${arg_GENERATE_VAPI}") list (APPEND outputs "${arg_GENERATE_VAPI}") list (APPEND export_args "--internal-vapi=${arg_GENERATE_VAPI}") if (NOT arg_GENERATE_HEADER) message (FATAL_ERROR "Header generation required for vapi") endif (NOT arg_GENERATE_HEADER) endif (arg_GENERATE_VAPI) if (arg_GENERATE_SYMBOLS) if (NOT IS_ABSOLUTE "${arg_GENERATE_SYMBOLS}") set (arg_GENERATE_SYMBOLS "${VALA_${id}_DIR}/${arg_GENERATE_SYMBOLS}") endif (NOT IS_ABSOLUTE "${arg_GENERATE_SYMBOLS}") list (APPEND outputs "${arg_GENERATE_SYMBOLS}") list (APPEND export_args "--symbols=${arg_GENERATE_SYMBOLS}") if (NOT arg_GENERATE_HEADER) message (FATAL_ERROR "Header generation required for symbols") endif (NOT arg_GENERATE_HEADER) endif (arg_GENERATE_SYMBOLS) if (arg_GENERATE_HEADER) if (NOT IS_ABSOLUTE "${arg_GENERATE_HEADER}") set (arg_GENERATE_HEADER "${VALA_${id}_DIR}/${arg_GENERATE_HEADER}") endif (NOT IS_ABSOLUTE "${arg_GENERATE_HEADER}") get_filename_component (header_path "${arg_GENERATE_HEADER}" PATH) get_filename_component (header_name "${arg_GENERATE_HEADER}" NAME_WE) set (header_base "${header_path}/${header_name}") get_filename_component (header_ext "${arg_GENERATE_HEADER}" EXT) list (APPEND outputs "${header_base}${header_ext}" "${header_base}_internal${header_ext}") list (APPEND export_args "--header=${header_base}${header_ext}" "--internal-header=${header_base}_internal${header_ext}") endif (arg_GENERATE_HEADER) if (outputs) add_custom_command (OUTPUT ${outputs} COMMAND ${VALA_COMPILER} -C ${VALA_${id}_ARGS} ${export_args} ${VALA_${id}_FAST_VAPI_ARGS} DEPENDS ${VALA_${id}_FAST_VAPI_FILES} COMMENT "Generating vapi/headers/symbols" VERBATIM) endif (outputs) endfunction (vala_finish id) function (vapi_gen id) set (_one_value LIBRARY INPUT) set (_multi_value PACKAGES) cmake_parse_arguments (arg "" "${_one_value}" "${_multi_value}" ${ARGN}) set(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${id}.vapi") if (arg_LIBRARY) set (OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${arg_LIBRARY}.vapi") endif (arg_LIBRARY) set("${id}_OUTPUT" ${OUTPUT} PARENT_SCOPE) set(PACKAGE_LIST) foreach(PACKAGE ${arg_PACKAGES}) list(APPEND PACKAGE_LIST "--pkg" ${PACKAGE}) endforeach() add_custom_command( OUTPUT ${OUTPUT} COMMAND ${VAPI_GEN} ${PACKAGE_LIST} --library=${arg_LIBRARY} ${arg_INPUT} DEPENDS ${arg_INPUT} VERBATIM ) add_custom_target(${id} ALL DEPENDS ${OUTPUT}) endfunction (vapi_gen id) hud-14.04+14.04.20140604/cmake/Coverage.cmake0000644000015301777760000000422212343623451020520 0ustar pbusernogroup00000000000000if (CMAKE_BUILD_TYPE MATCHES coverage) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --coverage") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage") find_program(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin") if (NOT GCOVR_EXECUTABLE) message(STATUS "Gcovr binary was not found, can not generate XML coverage info.") else () message(STATUS "Gcovr found, can generate XML coverage info.") add_custom_target (coverage-xml WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND "${GCOVR_EXECUTABLE}" --exclude="test.*" --exclude="obj.*" -x -r "${CMAKE_SOURCE_DIR}" --object-directory=${CMAKE_BINARY_DIR} -o coverage.xml) endif() find_program(LCOV_EXECUTABLE lcov HINTS ${LCOV_ROOT} "${GCOVR_ROOT}/bin") find_program(GENHTML_EXECUTABLE genhtml HINTS ${GENHTML_ROOT}) if (NOT LCOV_EXECUTABLE) message(STATUS "Lcov binary was not found, can not generate HTML coverage info.") else () if(NOT GENHTML_EXECUTABLE) message(STATUS "Genthml binary not found, can not generate HTML coverage info.") else() message(STATUS "Lcov and genhtml found, can generate HTML coverage info.") add_custom_target (coverage-html WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND "${LCOV_EXECUTABLE}" --capture --output-file "${CMAKE_BINARY_DIR}/coverage.info" --no-checksum --directory "${CMAKE_BINARY_DIR}" COMMAND "${LCOV_EXECUTABLE}" --remove "${CMAKE_BINARY_DIR}/coverage.info" '/usr/*' --output-file "${CMAKE_BINARY_DIR}/coverage.info" COMMAND "${LCOV_EXECUTABLE}" --remove "${CMAKE_BINARY_DIR}/coverage.info" '${CMAKE_BINARY_DIR}/*' --output-file "${CMAKE_BINARY_DIR}/coverage.info" COMMAND "${LCOV_EXECUTABLE}" --remove "${CMAKE_BINARY_DIR}/coverage.info" '${CMAKE_SOURCE_DIR}/tests/*' --output-file "${CMAKE_BINARY_DIR}/coverage.info" COMMAND "${GENHTML_EXECUTABLE}" --prefix "${CMAKE_BINARY_DIR}" --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info ) endif() endif() endif() hud-14.04+14.04.20140604/cmake/UseGdbusCodegen.cmake0000644000015301777760000000214612343623451021776 0ustar pbusernogroup00000000000000cmake_minimum_required(VERSION 2.6) if(POLICY CMP0011) cmake_policy(SET CMP0011 NEW) endif(POLICY CMP0011) find_program(GDBUS_CODEGEN NAMES gdbus-codegen DOC "gdbus-codegen executable") if(NOT GDBUS_CODEGEN) message(FATAL_ERROR "Excutable gdbus-codegen not found") endif() function(add_gdbus_codegen) set(_one_value OUTFILES NAME PREFIX NAMESPACE SERVICE_XML) set(_multi_value DEPENDS) cmake_parse_arguments (arg "" "${_one_value}" "${_multi_value}" ${ARGN}) if(arg_PREFIX) set(PREFIX --interface-prefix ${arg_PREFIX}) endif() if(arg_NAMESPACE) set(NAMESPACE --c-namespace ${arg_NAMESPACE}) endif() add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.h" "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.c" COMMAND "${GDBUS_CODEGEN}" --generate-c-code "${arg_NAME}" ${PREFIX} ${NAMESPACE} "${arg_SERVICE_XML}" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${arg_DEPENDS} "${arg_SERVICE_XML}" ) set(${arg_OUTFILES} ${${arg_OUTFILES}} "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.c" PARENT_SCOPE) endfunction(add_gdbus_codegen) hud-14.04+14.04.20140604/cmake/UseConstantBuilder.cmake0000644000015301777760000000123212343623451022540 0ustar pbusernogroup00000000000000cmake_minimum_required(VERSION 2.6) if(POLICY CMP0011) cmake_policy(SET CMP0011 NEW) endif(POLICY CMP0011) macro(add_constant_template outfiles name const_name input) set(file_target "${CMAKE_CURRENT_BINARY_DIR}/${name}.c") add_custom_command( OUTPUT ${file_target} COMMAND ${CMAKE_COMMAND} "-Dname=${name}" "-Dfile_target=${file_target}" "-Dconst_name=${const_name}" "-Dinput=${input}" -P "${CMAKE_SOURCE_DIR}/cmake/ConstantBuilderTemplates.cmake" DEPENDS "${CMAKE_SOURCE_DIR}/cmake/ConstantBuilderTemplates.cmake" "${input}" ) list(APPEND ${outfiles} "${file_target}") endmacro(add_constant_template) hud-14.04+14.04.20140604/cmake/FindGMock.cmake0000644000015301777760000000076612343623451020577 0ustar pbusernogroup00000000000000# Build with system gmock and embedded gtest set (GMOCK_INCLUDE_DIRS "/usr/include/gmock/include" CACHE PATH "gmock source include directory") set (GMOCK_SOURCE_DIR "/usr/src/gmock" CACHE PATH "gmock source directory") set (GTEST_INCLUDE_DIRS "${GMOCK_SOURCE_DIR}/gtest/include" CACHE PATH "gtest source include directory") add_subdirectory(${GMOCK_SOURCE_DIR} "${CMAKE_CURRENT_BINARY_DIR}/gmock") set(GTEST_LIBRARIES gtest) set(GTEST_MAIN_LIBRARIES gtest_main) set(GMOCK_LIBRARIES gmock gmock_main) hud-14.04+14.04.20140604/cmake/UseGObjectIntrospection.cmake0000644000015301777760000000746512343623451023554 0ustar pbusernogroup00000000000000# Copyright (C) 2010, Pino Toscano, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. include(ListOperations) macro(_gir_list_prefix _outvar _listvar _prefix) set(${_outvar}) foreach(_item IN LISTS ${_listvar}) list(APPEND ${_outvar} ${_prefix}${_item}) endforeach() endmacro(_gir_list_prefix) macro(gir_add_introspections introspections_girs) foreach(gir IN LISTS ${introspections_girs}) set(_gir_name "${gir}") ## Transform the gir filename to something which can reference through a variable ## without automake/make complaining, eg Gtk-2.0.gir -> Gtk_2_0_gir string(REPLACE "-" "_" _gir_name "${_gir_name}") string(REPLACE "." "_" _gir_name "${_gir_name}") # Namespace and Version is either fetched from the gir filename # or the _NAMESPACE/_VERSION variable combo set(_gir_namespace "${${_gir_name}_NAMESPACE}") if (_gir_namespace STREQUAL "") string(REGEX REPLACE "([^-]+)-.*" "\\1" _gir_namespace "${gir}") endif () set(_gir_version "${${_gir_name}_VERSION}") if (_gir_version STREQUAL "") string(REGEX REPLACE ".*-([^-]+).gir" "\\1" _gir_version "${gir}") endif () # _PROGRAM is an optional variable which needs it's own --program argument set(_gir_program "${${_gir_name}_PROGRAM}") if (NOT _gir_program STREQUAL "") set(_gir_program "--program=${_gir_program}") endif () # Variables which provides a list of things _gir_list_prefix(_gir_libraries ${_gir_name}_LIBS "--library=") _gir_list_prefix(_gir_packages ${_gir_name}_PACKAGES "--pkg=") _gir_list_prefix(_gir_includes ${_gir_name}_INCLUDES "--include=") _gir_list_prefix(_gir_export_packages ${_gir_name}_EXPORT_PACKAGES "--pkg-export=") # Reuse the LIBTOOL variable from by automake if it's set set(_gir_libtool "--no-libtool") add_custom_command( COMMAND ${INTROSPECTION_SCANNER} ${INTROSPECTION_SCANNER_ARGS} --quiet --namespace=${_gir_namespace} --nsversion=${_gir_version} ${_gir_libtool} ${_gir_program} ${_gir_libraries} ${_gir_packages} ${_gir_includes} ${_gir_export_packages} ${${_gir_name}_SCANNERFLAGS} ${${_gir_name}_CFLAGS} ${${_gir_name}_FILES} --output ${CMAKE_CURRENT_BINARY_DIR}/${gir} DEPENDS ${${_gir_name}_FILES} ${${_gir_name}_LIBS} OUTPUT ${gir} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} VERBATIM ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${gir} DESTINATION share/gir-1.0) string(REPLACE ".gir" ".typelib" _typelib "${gir}") add_custom_command( COMMAND ${INTROSPECTION_COMPILER} ${INTROSPECTION_COMPILER_ARGS} --includedir=. ${CMAKE_CURRENT_BINARY_DIR}/${gir} -o ${CMAKE_CURRENT_BINARY_DIR}/${_typelib} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${gir} OUTPUT ${_typelib} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${_typelib} DESTINATION ${CMAKE_INSTALL_LIBDIR}/girepository-1.0) add_custom_target(gir-${gir} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${gir}) add_custom_target(gir-typelibs-${_typelib} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${_typelib}) endforeach() endmacro(gir_add_introspections) macro(gir_get_cflags _output) get_directory_property(_tmp_includes INCLUDE_DIRECTORIES) list_prefix(_includes _tmp_includes "-I") get_directory_property(_tmp_compile_definitions COMPILE_DEFINITIONS) list_prefix(_compile_definitions _tmp_compile_definitions "-D") set(${_output} ${_includes} ${_compile_definitions}) endmacro(gir_get_cflags) hud-14.04+14.04.20140604/cmake/FindGtkDoc.cmake0000644000015301777760000000443412343623451020746 0ustar pbusernogroup00000000000000# CMake macros to find the GtkDoc documentation system # Output variables: # # GTKDOC_FOUND ... set to 1 if GtkDoc was foung # # If GTKDOC_FOUND == 1: # # GTKDOC_SCAN_EXE ... the location of the gtkdoc-scan executable # GTKDOC_SCANGOBJ_EXE ... the location of the gtkdoc-scangobj executable # GTKDOC_MKTMPL_EXE ... the location of the gtkdoc-mktmpl executable # GTKDOC_MKDB_EXE ... the location of the gtkdoc-mkdb executable # GTKDOC_MKHTML_EXE ... the location of the gtkdoc-mkhtml executable # GTKDOC_FIXXREF_EXE ... the location of the gtkdoc-fixxref executable set(GTKDOC_FOUND 1) find_program(GTKDOC_SCAN_EXE gtkdoc-scan PATH "${GLIB_PREFIX}/bin") if(NOT GTKDOC_SCAN_EXE) message(STATUS "gtkdoc-scan not found") set(GTKDOC_FOUND 0) endif(NOT GTKDOC_SCAN_EXE) find_program(GTKDOC_SCANGOBJ_EXE gtkdoc-scangobj PATH "${GLIB_PREFIX}/bin") if(NOT GTKDOC_SCANGOBJ_EXE) message(STATUS "gtkdoc-scangobj not found") set(GTKDOC_FOUND 0) endif(NOT GTKDOC_SCANGOBJ_EXE) get_filename_component(_this_dir ${CMAKE_CURRENT_LIST_FILE} PATH) find_file(GTKDOC_SCANGOBJ_WRAPPER GtkDocScanGObjWrapper.cmake PATH ${_this_dir}) if(NOT GTKDOC_SCANGOBJ_WRAPPER) message(STATUS "GtkDocScanGObjWrapper.cmake not found") set(GTKDOC_FOUND 0) endif(NOT GTKDOC_SCANGOBJ_WRAPPER) find_program(GTKDOC_MKTMPL_EXE gtkdoc-mktmpl PATH "${GLIB_PREFIX}/bin") if(NOT GTKDOC_MKTMPL_EXE) message(STATUS "gtkdoc-mktmpl not found") set(GTKDOC_FOUND 0) endif(NOT GTKDOC_MKTMPL_EXE) find_program(GTKDOC_MKDB_EXE gtkdoc-mkdb PATH "${GLIB_PREFIX}/bin") if(NOT GTKDOC_MKDB_EXE) message(STATUS "gtkdoc-mkdb not found") set(GTKDOC_FOUND 0) endif(NOT GTKDOC_MKDB_EXE) find_program(GTKDOC_MKHTML_EXE gtkdoc-mkhtml PATH "${GLIB_PREFIX}/bin") if(NOT GTKDOC_MKHTML_EXE) message(STATUS "gtkdoc-mkhtml not found") set(GTKDOC_FOUND 0) endif(NOT GTKDOC_MKHTML_EXE) find_program(GTKDOC_FIXXREF_EXE gtkdoc-fixxref PATH "${GLIB_PREFIX}/bin") if(NOT GTKDOC_FIXXREF_EXE) message(STATUS "gtkdoc-fixxref not found") set(GTKDOC_FOUND 0) endif(NOT GTKDOC_FIXXREF_EXE) find_program(GTKDOC_CHECK_EXE gtkdoc-check PATH "${GLIB_PREFIX}/bin") if(NOT GTKDOC_CHECK_EXE) message(STATUS "gtkdoc-check not found") set(GTKDOC_FOUND 0) endif(NOT GTKDOC_CHECK_EXE) # vim:sw=4:ts=4:et:autoindent hud-14.04+14.04.20140604/cmake/GlibGenerationTemplates.cmake0000644000015301777760000000307712343623451023544 0ustar pbusernogroup00000000000000message(STATUS ${headers}) file(WRITE ${htemplate} "/*** BEGIN file-header ***/ #ifndef __${includeguard}_ENUM_TYPES_H__ #define __${includeguard}_ENUM_TYPES_H__ #include G_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from \"@filename@\" */ /*** END file-production ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void); #define ${namespace}_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) /*** END value-header ***/ /*** BEGIN file-tail ***/ G_END_DECLS #endif /* __${includeguard}_ENUM_TYPES_H__ */ /*** END file-tail ***/ ") # Write the .c template file(WRITE ${ctemplate} "/*** BEGIN file-header ***/ #include \"${name}.h\"\n") foreach(header ${headers}) file(APPEND ${ctemplate} "#include \"${header}\"\n") endforeach(header) file(APPEND ${ctemplate} " /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from \"@filename@\" */ /*** END file-production ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; if (g_once_init_enter (&g_define_type_id__volatile)) { static const G@Type@Value values[] = { /*** END value-header ***/ /*** BEGIN value-production ***/ { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }, /*** END value-production ***/ /*** BEGIN value-tail ***/ { 0, NULL, NULL } }; GType g_define_type_id = g_@type@_register_static (\"@EnumName@\", values); g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); } return g_define_type_id__volatile; } /*** END value-tail ***/ ") hud-14.04+14.04.20140604/cmake/COPYING-CMAKE-SCRIPTS0000644000015301777760000000245712343623451020771 0ustar pbusernogroup00000000000000Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. hud-14.04+14.04.20140604/cmake/FindValgrind.cmake0000644000015301777760000000132512343623451021335 0ustar pbusernogroup00000000000000 option( ENABLE_MEMCHECK_OPTION "If set to ON, enables automatic creation of memcheck targets" OFF ) find_program( VALGRIND_PROGRAM NAMES valgrind ) if(VALGRIND_PROGRAM) set(VALGRIND_PROGRAM_OPTIONS "--suppressions=${CMAKE_SOURCE_DIR}/tests/data/valgrind.suppression" "--error-exitcode=1" "--leak-check=full" "--gen-suppressions=all" "--quiet" ) endif() find_package_handle_standard_args( VALGRIND DEFAULT_MSG VALGRIND_PROGRAM ) function(add_valgrind_test NAME EXECUTABLE) if(ENABLE_MEMCHECK_OPTION AND VALGRIND_PROGRAM) add_test(${NAME} ${VALGRIND_PROGRAM} ${VALGRIND_PROGRAM_OPTIONS} "${CMAKE_CURRENT_BINARY_DIR}/${EXECUTABLE}") else() add_test(${NAME} ${EXECUTABLE}) endif() endfunction() hud-14.04+14.04.20140604/cmake/ConstantBuilderTemplates.cmake0000644000015301777760000000073312343623451023747 0ustar pbusernogroup00000000000000 file(READ "${input}" input_contents) string(REGEX REPLACE "\n" " " input_on_one_line "${input_contents}") set(new_contents "\#include \"${name}.h\"\nconst gchar * ${const_name} = \"${input_on_one_line}\";\n") if (EXISTS "${file_target}") file(READ "${file_target}" old_contents) if(NOT new_contents EQUAL old_contents) file(WRITE "${file_target}" "${new_contents}") endif() else() file(WRITE "${file_target}" "${new_contents}") endif() hud-14.04+14.04.20140604/cmake/UseMscgen.cmake0000644000015301777760000000237212343623451020662 0ustar pbusernogroup00000000000000cmake_minimum_required(VERSION 2.6) find_program(MSCGEN_EXECUTABLE NAMES mscgen DOC "mscgen executable") if(NOT MSCGEN_EXECUTABLE) message(STATUS "Excutable mscgen not found") endif() function(mscgen ID) if (MSCGEN_EXECUTABLE) set(_options INSTALL) set(_one_value INPUT_NAME OUTPUT_NAME OUTPUT_TYPE) cmake_parse_arguments (ARG "${_options}" "${_one_value}" "" ${ARGN}) set(OUTPUT_TYPE "png") if(ARG_OUTPUT_TYPE) set(OUTPUT_TYPE ${ARG_OUTPUT_TYPE}) endif() set(INPUT_NAME "${ID}.msc") if(ARG_INPUT_NAME) set(INPUT_NAME ${ARG_INPUT_NAME}) endif() set(OUTPUT_NAME "${ID}.png") if(ARG_OUTPUT_NAME) set(OUTPUT_NAME ${ARG_OUTPUT_NAME}) endif() add_custom_command( OUTPUT ${OUTPUT_NAME} COMMAND ${MSCGEN_EXECUTABLE} -T ${OUTPUT_TYPE} -i "${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_NAME}" -o "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_NAME}" DEPENDS ${INPUT_NAME} ) add_custom_target(${ID} ALL DEPENDS ${OUTPUT_NAME} ) if(ARG_INSTALL) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_NAME}" DESTINATION ${CMAKE_INSTALL_DOCDIR} ) endif() endif() endfunction(mscgen) hud-14.04+14.04.20140604/cmake/UseGtkDoc.cmake0000644000015301777760000002147712343623451020630 0ustar pbusernogroup00000000000000# CMake macros to use the GtkDoc documentation system find_package(GtkDoc) # gtk_doc_add_module(doc_prefix sourcedir # [XML xmlfile] # [FIXXREFOPTS fixxrefoption1...] # [IGNOREHEADERS header1...] # [DEPENDS depend1...] ) # # sourcedir must be the *full* path to the source directory. # # If omitted, sgmlfile defaults to the auto generated ${doc_prefix}/${doc_prefix}-docs.xml. function(gtk_doc_add_module _doc_prefix _doc_sourcedir) set (_multi_value DEPENDS XML FIXXREFOPTS IGNOREHEADERS CFLAGS LDFLAGS LDPATH SUFFIXES) cmake_parse_arguments (ARG "" "" "${_multi_value}" ${ARGN}) list(LENGTH ARG_XML _xml_file_length) if(ARG_SUFFIXES) set(_doc_source_suffixes "") foreach(_suffix ${ARG_SUFFIXES}) if(_doc_source_suffixes) set(_doc_source_suffixes "${_doc_source_suffixes},${_suffix}") else(_doc_source_suffixes) set(_doc_source_suffixes "${_suffix}") endif(_doc_source_suffixes) endforeach(_suffix) else(ARG_SUFFIXES) set(_doc_source_suffixes "h") endif(ARG_SUFFIXES) set(_do_all ALL) set(_opts_valid 1) if(NOT _xml_file_length LESS 2) message(SEND_ERROR "Must have at most one sgml file specified.") set(_opts_valid 0) endif(NOT _xml_file_length LESS 2) if(_opts_valid) # a directory to store output. set(_output_dir "${CMAKE_CURRENT_BINARY_DIR}/${_doc_prefix}") set(_output_dir_stamp "${_output_dir}/dir.stamp") # set default sgml file if not specified set(_default_xml_file "${_output_dir}/${_doc_prefix}-docs.xml") get_filename_component(_default_xml_file ${_default_xml_file} ABSOLUTE) # a directory to store html output. set(_output_html_dir "${_output_dir}/html") set(_output_html_dir_stamp "${_output_dir}/html_dir.stamp") # The output files set(_output_decl_list "${_output_dir}/${_doc_prefix}-decl-list.txt") set(_output_decl "${_output_dir}/${_doc_prefix}-decl.txt") set(_output_overrides "${_output_dir}/${_doc_prefix}-overrides.txt") set(_output_sections "${_output_dir}/${_doc_prefix}-sections.txt") set(_output_types "${_output_dir}/${_doc_prefix}.types") set(_output_signals "${_output_dir}/${_doc_prefix}.signals") set(_output_unused "${_output_dir}/${_doc_prefix}-unused.txt") set(_output_undeclared "${_output_dir}/${_doc_prefix}-undeclared.txt") set(_output_undocumented "${_output_dir}/${_doc_prefix}-undocumented.txt") set(_output_tmpl_dir "${_output_dir}/tmpl") set(_output_tmpl_stamp "${_output_dir}/tmpl.stamp") set(_output_xml_dir "${_output_dir}/xml") set(_output_sgml_stamp "${_output_dir}/sgml.stamp") set(_output_html_stamp "${_output_dir}/html.stamp") # add a command to create output directory add_custom_command( OUTPUT "${_output_dir_stamp}" "${_output_dir}" COMMAND ${CMAKE_COMMAND} -E make_directory "${_output_dir}" COMMAND ${CMAKE_COMMAND} -E touch ${_output_dir_stamp} VERBATIM) set(_ignore_headers_opt "") if(ARG_IGNOREHEADERS) set(_ignore_headers_opt "--ignore-headers=") foreach(_header ${ARG_IGNOREHEADERS}) set(_ignore_headers_opt "${_ignore_headers_opt}${_header} ") endforeach(_header ${ARG_IGNOREHEADERS}) endif(ARG_IGNOREHEADERS) # add a command to scan the input add_custom_command( OUTPUT "${_output_decl_list}" "${_output_decl}" "${_output_decl}.bak" "${_output_overrides}" "${_output_sections}" "${_output_types}" "${_output_types}.bak" DEPENDS "${_output_dir}" ${ARG_DEPENDS} COMMAND ${GTKDOC_SCAN_EXE} "--module=${_doc_prefix}" "${_ignore_headers_opt}" "--rebuild-sections" "--rebuild-types" "--source-dir=${_doc_sourcedir}" WORKING_DIRECTORY "${_output_dir}" VERBATIM) # add a command to scan the input via gtkdoc-scangobj # This is such a disgusting hack! add_custom_command( OUTPUT "${_output_signals}" DEPENDS "${_output_types}" "${ARG_DEPENDS}" COMMAND ${CMAKE_COMMAND} -D "GTKDOC_SCANGOBJ_EXE:STRING=${GTKDOC_SCANGOBJ_EXE}" -D "doc_prefix:STRING=${_doc_prefix}" -D "output_types:STRING=${_output_types}" -D "output_dir:STRING=${_output_dir}" -D "EXTRA_CFLAGS:STRING=${ARG_CFLAGS}" -D "EXTRA_LDFLAGS:STRING=${ARG_LDFLAGS}" -D "EXTRA_LDPATH:STRING=${ARG_LDPATH}" -P ${GTKDOC_SCANGOBJ_WRAPPER} WORKING_DIRECTORY "${_output_dir}" VERBATIM) # add a command to make the templates add_custom_command( OUTPUT "${_output_unused}" "${_output_undeclared}" "${_output_undocumented}" "${_output_tmpl_dir}" "${_output_tmpl_stamp}" DEPENDS "${_output_types}" "${_output_signals}" "${_output_sections}" "${_output_overrides}" ${ARG_DEPENDS} COMMAND ${CMAKE_COMMAND} -E remove_directory ${_output_tmpl_dir} COMMAND ${GTKDOC_MKTMPL_EXE} "--module=${_doc_prefix}" WORKING_DIRECTORY "${_output_dir}" VERBATIM) set(_copy_xml_if_needed "") if(ARG_XML) get_filename_component(ARG_XML ${ARG_XML} ABSOLUTE) set(_copy_xml_if_needed COMMAND ${CMAKE_COMMAND} -E copy "${ARG_XML}" "${_default_xml_file}") endif(ARG_XML) set(_remove_xml_if_needed "") if(ARG_XML) set(_remove_xml_if_needed COMMAND ${CMAKE_COMMAND} -E remove ${_default_xml_file}) endif(ARG_XML) # add a command to make the database add_custom_command( OUTPUT "${_output_sgml_stamp}" "${_default_xml_file}" DEPENDS "${_output_tmpl_stamp}" "${_output_unused}" "${_output_undeclared}" "${_output_undocumented}" ${ARG_DEPENDS} ${_remove_xml_if_needed} COMMAND ${CMAKE_COMMAND} -E remove_directory ${_output_xml_dir} COMMAND ${GTKDOC_MKDB_EXE} "--module=${_doc_prefix}" "--source-dir=${_doc_sourcedir}" "--source-suffixes=${_doc_source_suffixes}" "--output-format=xml" "--main-sgml-file=${_default_xml_file}" ${_copy_xml_if_needed} WORKING_DIRECTORY "${_output_dir}" VERBATIM) # add a command to create html directory add_custom_command( OUTPUT "${_output_html_dir_stamp}" "${_output_html_dir}" COMMAND ${CMAKE_COMMAND} -E make_directory ${_output_html_dir} COMMAND ${CMAKE_COMMAND} -E touch ${_output_html_dir_stamp} VERBATIM) # add a command to output HTML add_custom_command( OUTPUT "${_output_html_stamp}" DEPENDS "${_output_html_dir_stamp}" "${_output_sgml_stamp}" "${_output_tmpl_stamp}" "${ARG_XML}" ${ARG_DEPENDS} ${_copy_xml_if_needed} COMMAND ${GTKDOC_MKHTML_EXE} "${_doc_prefix}" "${_default_xml_file}" WORKING_DIRECTORY "${_output_html_dir}" VERBATIM) # fix output refs add_custom_target("${_doc_prefix}-gtxdoc-fixxref" DEPENDS "${_output_html_stamp}" ${ARG_DEPENDS} COMMAND ${GTKDOC_FIXXREF_EXE} "--module=${_doc_prefix}" "--module-dir=." ${ARG_FIXXREFOPTS} #${_remove_xml_if_needed} WORKING_DIRECTORY "${_output_dir}" VERBATIM) add_custom_target(doc-${_doc_prefix} ${_do_all} DEPENDS "${_doc_prefix}-gtxdoc-fixxref" ${ARG_DEPENDS}) add_test(doc-${_doc_prefix}-check ${GTKDOC_CHECK_EXE}) set_tests_properties(doc-${_doc_prefix}-check PROPERTIES ENVIRONMENT "DOC_MODULE=${_doc_prefix};DOC_MAIN_SGML_FILE=${_doc_prefix}-docs.xml;SRCDIR=${_doc_sourcedir};BUILDDIR=${_output_dir}" ) endif(_opts_valid) endfunction(gtk_doc_add_module) hud-14.04+14.04.20140604/cmake/GtkDocScanGObjWrapper.cmake0000644000015301777760000000235512343623451023055 0ustar pbusernogroup00000000000000if(NOT APPLE) # We use pkg-config to fing glib et al find_package(PkgConfig) # Find glib et al pkg_check_modules(GLIB REQUIRED glib-2.0 gobject-2.0) foreach(_flag ${EXTRA_CFLAGS} ${GLIB_CFLAGS}) set(ENV{CFLAGS} "$ENV{CFLAGS} \"${_flag}\"") endforeach(_flag) foreach(_flag ${EXTRA_LDFLAGS} ${GLIB_LDFLAGS}) set(ENV{LDFLAGS} "$ENV{LDFLAGS} \"${_flag}\"") endforeach(_flag) foreach(_flag ${EXTRA_LDPATH}) if(ENV{LD_LIBRARY_PATH}) set(ENV{LD_LIBRARY_PATH} "$ENV{LD_LIBRARY_PATH}:\"${_flag}\"") else(ENV{LD_LIBRARY_PATH}) set(ENV{LD_LIBRARY_PATH} "${_flag}") endif(ENV{LD_LIBRARY_PATH}) endforeach(_flag) message(STATUS "Executing gtkdoc-scangobj with:") message(STATUS " CFLAGS: $ENV{CFLAGS}") message(STATUS " LDFLAGS: $ENV{LDFLAGS}") message(STATUS " LDPATH: $ENV{LD_LIBRARY_PATH}") execute_process(COMMAND ${GTKDOC_SCANGOBJ_EXE} "--module=${doc_prefix}" "--types=${output_types}" "--output-dir=${output_dir}" WORKING_DIRECTORY "${output_dir}" RESULT_VARIABLE _scan_result) if(_scan_result EQUAL 0) message(STATUS "Scan succeeded.") else(_scan_result EQUAL 0) message(SEND_ERROR "Scan failed.") endif(_scan_result EQUAL 0) endif(NOT APPLE) # vim:sw=4:ts=4:et:autoindent hud-14.04+14.04.20140604/cmake/ListOperations.cmake0000644000015301777760000000073512343623451021751 0ustar pbusernogroup00000000000000 macro(list_prefix _outvar _listvar _prefix) set(${_outvar}) foreach(_item IN LISTS ${_listvar}) list(APPEND ${_outvar} ${_prefix}${_item}) endforeach() endmacro(list_prefix) macro(list_make_absolute _outvar _listvar _prefix) set(${_outvar}) foreach(_item IN LISTS ${_listvar}) if(IS_ABSOLUTE ${_item}) list(APPEND ${_outvar} ${_item}) else() list(APPEND ${_outvar} ${_prefix}${_item}) endif() endforeach() endmacro(list_make_absolute) hud-14.04+14.04.20140604/cmake/FindVala.cmake0000644000015301777760000000442212343623451020453 0ustar pbusernogroup00000000000000# - Find Vala # This module looks for valac. # This module defines the following values: # VALA_FOUND # VALA_COMPILER # VALA_VERSION # VAPI_GEN # VAPI_GEN_VERSION #============================================================================= # Copyright Přemysl Janouch 2011 # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. #============================================================================= find_program (VALA_COMPILER "valac") if (VALA_COMPILER) execute_process (COMMAND ${VALA_COMPILER} --version OUTPUT_VARIABLE VALA_VERSION) string (REGEX MATCH "[.0-9]+" VALA_VERSION "${VALA_VERSION}") endif (VALA_COMPILER) find_program (VAPI_GEN "vapigen") if (VAPI_GEN) execute_process (COMMAND ${VAPI_GEN} --version OUTPUT_VARIABLE VAPI_GEN_VERSION) string (REGEX MATCH "[.0-9]+" VAPI_GEN_VERSION "${VAPI_GEN_VERSION}") endif (VAPI_GEN) include (FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS (Vala REQUIRED_VARS VALA_COMPILER VERSION_VAR VALA_VERSION) mark_as_advanced (VALA_COMPILER VALA_VERSION VAPI_GEN) hud-14.04+14.04.20140604/cmake/UseGSettings.cmake0000644000015301777760000000371512343623451021357 0ustar pbusernogroup00000000000000# GSettings.cmake, CMake macros written for Marlin, feel free to re-use them. option (GSETTINGS_LOCALINSTALL "Install GSettings Schemas locally instead of to the GLib prefix" ${LOCAL_INSTALL}) option (GSETTINGS_COMPILE "Compile GSettings Schemas after installation" ${GSETTINGS_LOCALINSTALL}) if(GSETTINGS_LOCALINSTALL) message(STATUS "GSettings schemas will be installed locally.") endif() if(GSETTINGS_COMPILE) message(STATUS "GSettings shemas will be compiled.") endif() macro(add_schema SCHEMA_NAME) set(PKG_CONFIG_EXECUTABLE pkg-config) # Have an option to not install the schema into where GLib is if (GSETTINGS_LOCALINSTALL) SET (GSETTINGS_DIR "${CMAKE_INSTALL_PREFIX}/share/glib-2.0/schemas/") else (GSETTINGS_LOCALINSTALL) execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} glib-2.0 --variable prefix OUTPUT_VARIABLE _glib_prefix OUTPUT_STRIP_TRAILING_WHITESPACE) SET (GSETTINGS_DIR "${_glib_prefix}/share/glib-2.0/schemas/") endif (GSETTINGS_LOCALINSTALL) # Run the validator and error if it fails execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} gio-2.0 --variable glib_compile_schemas OUTPUT_VARIABLE _glib_comple_schemas OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND ${_glib_comple_schemas} --dry-run --schema-file=${CMAKE_CURRENT_SOURCE_DIR}/${SCHEMA_NAME} ERROR_VARIABLE _schemas_invalid OUTPUT_STRIP_TRAILING_WHITESPACE) if (_schemas_invalid) message (SEND_ERROR "Schema validation error: ${_schemas_invalid}") endif (_schemas_invalid) # Actually install and recomple schemas message (STATUS "GSettings schemas will be installed into ${GSETTINGS_DIR}") install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SCHEMA_NAME} DESTINATION ${GSETTINGS_DIR} OPTIONAL) if (GSETTINGS_COMPILE) install (CODE "message (STATUS \"Compiling GSettings schemas\")") install (CODE "execute_process (COMMAND ${_glib_comple_schemas} ${GSETTINGS_DIR})") endif () endmacro() hud-14.04+14.04.20140604/cmake/UseGlibGeneration.cmake0000644000015301777760000000544512343623451022343 0ustar pbusernogroup00000000000000cmake_minimum_required(VERSION 2.6) if(POLICY CMP0011) cmake_policy(SET CMP0011 NEW) endif(POLICY CMP0011) find_program(GLIB_MKENUMS glib-mkenums) find_program(GLIB_GENMARSHAL glib-genmarshal) macro(add_glib_marshal outfiles name prefix otherinclude) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" COMMAND ${GLIB_GENMARSHAL} --header "--prefix=${prefix}" "${CMAKE_CURRENT_SOURCE_DIR}/${name}.list" > "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.list" ) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" COMMAND echo "\\#include \\\"${otherinclude}\\\"" > "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" COMMAND echo "\\#include \\\"glib-object.h\\\"" >> "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" COMMAND echo "\\#include \\\"${name}.h\\\"" >> "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" COMMAND ${GLIB_GENMARSHAL} --body "--prefix=${prefix}" "${CMAKE_CURRENT_SOURCE_DIR}/${name}.list" >> "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.list" "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" ) list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c") endmacro(add_glib_marshal) macro(add_glib_enumtypes_t outfiles name htemplate ctemplate) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" COMMAND ${GLIB_MKENUMS} --template "${htemplate}" ${ARGN} > "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${ARGN} "${htemplate}" ) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" COMMAND ${GLIB_MKENUMS} --template "${ctemplate}" ${ARGN} > "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${ARGN} ${ctemplate} "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" ) list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c") endmacro(add_glib_enumtypes_t) macro(add_glib_enumtypes outfiles name namespace includeguard) set(htemplate "${CMAKE_CURRENT_BINARY_DIR}/${name}.h.template") set(ctemplate "${CMAKE_CURRENT_BINARY_DIR}/${name}.c.template") # Write the .h template add_custom_command( OUTPUT ${htemplate} ${ctemplate} COMMAND ${CMAKE_COMMAND} "-Dctemplate=${ctemplate}" "-Dhtemplate=${htemplate}" "-Dname=${name}" "-Dnamespace=${namespace}" "-Dincludeguard=${includeguard}" "\"-Dheaders=${ARGN}\"" -P "${CMAKE_SOURCE_DIR}/cmake/GlibGenerationTemplates.cmake" DEPENDS "${CMAKE_SOURCE_DIR}/cmake/GlibGenerationTemplates.cmake" ${headers} ) add_glib_enumtypes_t(${outfiles} ${name} ${htemplate} ${ctemplate} ${ARGN}) endmacro(add_glib_enumtypes) hud-14.04+14.04.20140604/window-stack-bridge/0000755000015301777760000000000012343624372020552 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/window-stack-bridge/AbstractWindowStack.h0000644000015301777760000000347612343623451024653 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef ABSTRACTWINDOWSTACK_H_ #define ABSTRACTWINDOWSTACK_H_ #include #include #include #include #include #include #include class WindowStackAdaptor; class Q_DECL_EXPORT AbstractWindowStack: public QObject, protected QDBusContext { Q_OBJECT public: explicit AbstractWindowStack(const QDBusConnection &connection, QObject *parent = 0); virtual ~AbstractWindowStack(); public: Q_DECL_EXPORT static void registerMetaTypes(); public Q_SLOTS: virtual QString GetAppIdFromPid(uint pid) = 0; virtual hud::common::WindowInfoList GetWindowStack() = 0; virtual QStringList GetWindowProperties(uint windowId, const QString &appId, const QStringList &names) = 0; Q_SIGNALS: void FocusedWindowChanged(uint windowId, const QString &appId, uint stage); void WindowCreated(uint windowId, const QString &appId); void WindowDestroyed(uint windowId, const QString &appId); protected: void registerOnBus(); QScopedPointer m_adaptor; QDBusConnection m_connection; }; #endif /* ABSTRACTWINDOWSTACK_H_ */ hud-14.04+14.04.20140604/window-stack-bridge/BamfWindowStack.cpp0000644000015301777760000001605212343623451024302 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include using namespace hud::common; BamfWindow::BamfWindow(const QString &path, const QDBusConnection &connection) : m_window(DBusTypes::BAMF_DBUS_NAME, path, connection), m_view( DBusTypes::BAMF_DBUS_NAME, path, connection), m_error(false), m_windowId( 0) { QDBusPendingReply windowIdReply(m_window.GetXid()); windowIdReply.waitForFinished(); if (windowIdReply.isError()) { qWarning() << _("Could not get window ID for") << path << windowIdReply.error(); m_error = true; return; } else { m_windowId = windowIdReply; } QStringList parents; QDBusPendingReply parentsReply(m_view.Parents()); parentsReply.waitForFinished(); if (parentsReply.isError()) { qWarning() << _("Error getting parents for") << path << parentsReply.error(); m_error = true; return; } else { parents = parentsReply; } if (!parents.empty()) { OrgAyatanaBamfApplicationInterface application( DBusTypes::BAMF_DBUS_NAME, parents.first(), m_window.connection()); QDBusPendingReply desktopFileReply(application.DesktopFile()); desktopFileReply.waitForFinished(); if (desktopFileReply.isError()) { qWarning() << _("Could not get desktop file for") << path << desktopFileReply.error(); m_error = true; return; } else { QString desktopFile(desktopFileReply); if (!desktopFile.isEmpty()) { m_applicationId = QFileInfo(desktopFile).baseName(); } } } if (m_applicationId.isEmpty()) { m_applicationId = QString::number(m_windowId); } } BamfWindow::~BamfWindow() { } unsigned int BamfWindow::windowId() { return m_windowId; } const QString & BamfWindow::applicationId() { return m_applicationId; } bool BamfWindow::isError() const { return m_error; } const QString BamfWindow::xProp(const QString &property) { QDBusPendingReply propertyReply(m_window.Xprop(property)); propertyReply.waitForFinished(); if (propertyReply.isError()) { qWarning() << "Could not get window property" << property << m_window.path(); return QString(); } else { return propertyReply; } } BamfWindowStack::WindowPtr BamfWindowStack::addWindow(const QString& path) { WindowPtr window(new BamfWindow(path, m_connection)); if (!window->isError()) { m_windows[path] = window; m_windowsById[window->windowId()] = window; } return window; } BamfWindowStack::WindowPtr BamfWindowStack::removeWindow(const QString& path) { WindowPtr window(m_windows.take(path)); if (!window.isNull()) { m_windowsById.remove(window->windowId()); } return window; } BamfWindowStack::BamfWindowStack(const QDBusConnection &connection, QObject *parent) : AbstractWindowStack(connection, parent), m_matcher( DBusTypes::BAMF_DBUS_NAME, DBusTypes::BAMF_MATCHER_DBUS_PATH, connection) { QDBusConnectionInterface* interface = connection.interface(); if (!interface->isServiceRegistered(DBusTypes::BAMF_DBUS_NAME)) { QDBusReply reply( interface->startService(DBusTypes::BAMF_DBUS_NAME)); } registerOnBus(); connect(&m_matcher, SIGNAL(ActiveWindowChanged(const QString&, const QString&)), this, SLOT(ActiveWindowChanged(const QString&, const QString&))); connect(&m_matcher, SIGNAL(ViewClosed(const QString&, const QString&)), this, SLOT(ViewClosed(const QString&, const QString&))); connect(&m_matcher, SIGNAL(ViewOpened(const QString&, const QString&)), this, SLOT(ViewOpened(const QString&, const QString&))); QDBusPendingReply windowPathsReply(m_matcher.WindowPaths()); windowPathsReply.waitForFinished(); if (windowPathsReply.isError()) { qWarning() << _("Could not get window paths") << windowPathsReply.error(); } else { QStringList windowPaths(windowPathsReply); for (const QString &path : windowPaths) { addWindow(path); } } } BamfWindowStack::~BamfWindowStack() { } QString BamfWindowStack::GetAppIdFromPid(uint pid) { Q_UNUSED(pid); // FIXME Not implemented sendErrorReply(QDBusError::NotSupported, "GetAppIdFromPid method not implemented"); return QString(); } WindowInfoList BamfWindowStack::GetWindowStack() { WindowInfoList results; QDBusPendingReply stackReply( m_matcher.WindowStackForMonitor(-1)); stackReply.waitForFinished(); if (stackReply.isError()) { qWarning() << "Failed to get BAMF window stack" << stackReply.error(); return results; } QStringList stack(stackReply); for (const QString &path : stack) { const auto window(m_windows[path]); if (window) { results << WindowInfo(window->windowId(), window->applicationId(), false); } } QDBusPendingReply activeWindowReply(m_matcher.ActiveWindow()); activeWindowReply.waitForFinished(); if (activeWindowReply.isError()) { qWarning() << "Failed to get BAMF active window" << activeWindowReply.error(); return results; } const auto window(m_windows[activeWindowReply]); if (window) { const uint windowId(window->windowId()); for (WindowInfo &windowInfo : results) { if (windowInfo.window_id == windowId) { windowInfo.focused = true; } } } return results; } QStringList BamfWindowStack::GetWindowProperties(uint windowId, const QString &appId, const QStringList &names) { Q_UNUSED(appId); QStringList result; const auto window = m_windowsById[windowId]; if (window == nullptr) { sendErrorReply(QDBusError::InvalidArgs, "Unable to find windowId"); return result; } for (const QString &name : names) { if (window) { result << window->xProp(name); } else { result << QString(); } } return result; } void BamfWindowStack::ActiveWindowChanged(const QString &oldWindowPath, const QString &newWindowPath) { Q_UNUSED(oldWindowPath); if (!newWindowPath.isEmpty()) { const auto window(m_windows[newWindowPath]); if (window) { FocusedWindowChanged(window->windowId(), window->applicationId(), WindowInfo::MAIN); } } } void BamfWindowStack::ViewClosed(const QString &path, const QString &type) { if (type == "window") { WindowPtr window(removeWindow(path)); if (!window.isNull()) { WindowDestroyed(window->windowId(), window->applicationId()); } } } void BamfWindowStack::ViewOpened(const QString &path, const QString &type) { if (type == "window") { WindowPtr window(addWindow(path)); if (!window->isError()) { WindowCreated(window->windowId(), window->applicationId()); } } } hud-14.04+14.04.20140604/window-stack-bridge/AbstractWindowStack.cpp0000644000015301777760000000321612343623451025176 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include using namespace hud::common; AbstractWindowStack::AbstractWindowStack(const QDBusConnection &connection, QObject *parent) : QObject(parent), m_adaptor(new WindowStackAdaptor(this)), m_connection( connection) { WindowInfo::registerMetaTypes(); } void AbstractWindowStack::registerOnBus() { if (!m_connection.registerObject(DBusTypes::WINDOW_STACK_DBUS_PATH, this)) { throw std::logic_error( _("Unable to register window stack object on DBus")); } if (!m_connection.registerService(DBusTypes::WINDOW_STACK_DBUS_NAME)) { throw std::logic_error( _("Unable to register window stack service on DBus")); } } AbstractWindowStack::~AbstractWindowStack() { m_connection.unregisterObject(DBusTypes::WINDOW_STACK_DBUS_PATH); } hud-14.04+14.04.20140604/window-stack-bridge/BamfWindowStack.h0000644000015301777760000000446512343623451023754 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef BAMFWINDOWSTACK_H_ #define BAMFWINDOWSTACK_H_ #include #include #include #include #include class Q_DECL_EXPORT BamfWindow { public: explicit BamfWindow(const QString &path, const QDBusConnection &connection); virtual ~BamfWindow(); unsigned int windowId(); const QString & applicationId(); const QString xProp(const QString &property); bool isError() const; protected: OrgAyatanaBamfWindowInterface m_window; OrgAyatanaBamfViewInterface m_view; bool m_error; unsigned int m_windowId; QString m_applicationId; }; class Q_DECL_EXPORT BamfWindowStack: public AbstractWindowStack { Q_OBJECT public: typedef QSharedPointer WindowPtr; BamfWindowStack(const QDBusConnection &connection, QObject *parent = 0); virtual ~BamfWindowStack(); public Q_SLOTS: QString GetAppIdFromPid(uint pid) override; hud::common::WindowInfoList GetWindowStack() override; QStringList GetWindowProperties(uint windowId, const QString &appId, const QStringList &names) override; protected Q_SLOTS: void ActiveWindowChanged(const QString &oldWindow, const QString &newWindow); void ViewClosed(const QString &path, const QString &type); void ViewOpened(const QString &path, const QString &type); WindowPtr addWindow(const QString& path); WindowPtr removeWindow(const QString& path); protected: OrgAyatanaBamfMatcherInterface m_matcher; QMap m_windows; QMap m_windowsById; }; #endif /* BAMFWINDOWSTACK_H_ */ hud-14.04+14.04.20140604/window-stack-bridge/main.cpp0000644000015301777760000000260312343623451022200 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include using namespace std; static void exitQt(int sig) { Q_UNUSED(sig); QCoreApplication::exit(0); } int main(int argc, char *argv[]) { QCoreApplication application(argc, argv); setlocale(LC_ALL, ""); bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain(GETTEXT_PACKAGE); signal(SIGINT, &exitQt); signal(SIGTERM, &exitQt); try { WindowStack windowStack(QDBusConnection::sessionBus()); return application.exec(); } catch (std::exception &e) { qWarning() << _("Window Stack Bridge:") << e.what(); return application.exec(); } } hud-14.04+14.04.20140604/window-stack-bridge/CMakeLists.txt0000644000015301777760000000301012343623451023301 0ustar pbusernogroup00000000000000 if(${ENABLE_BAMF}) add_definitions( -DENABLE_BAMF=1 ) elseif(${ENABLE_PLATFORM_API}) add_definitions( -DENABLE_PLATFORM_API=1 ) set(PLATFORM_API_LIBRARIES "-lubuntu_application_api") endif() if(${ENABLE_BAMF} OR ${ENABLE_PLATFORM_API}) set( WINDOW_STACK_BRIDGE_SOURCES AbstractWindowStack.cpp ) if(${ENABLE_BAMF}) list(APPEND WINDOW_STACK_BRIDGE_SOURCES BamfWindowStack.cpp) qt5_add_dbus_interface( WINDOW_STACK_BRIDGE_SOURCES ${BAMF_XML} BamfInterface ) qt5_add_dbus_interface( WINDOW_STACK_BRIDGE_SOURCES ${BAMF_VIEW_XML} BamfViewInterface ) endif() if(${ENABLE_PLATFORM_API}) list(APPEND WINDOW_STACK_BRIDGE_SOURCES PlatformApiWindowStack.cpp) endif() qt5_add_dbus_adaptor( WINDOW_STACK_BRIDGE_SOURCES ${WINDOW_STACK_XML} AbstractWindowStack.h AbstractWindowStack WindowStackAdaptor ) set_source_files_properties( "${DATA_DIR}/org.freedesktop.Notifications.xml" PROPERTIES INCLUDE "DBusTypes.h" ) add_library( window-stack-bridge STATIC ${WINDOW_STACK_BRIDGE_SOURCES} ) qt5_use_modules( window-stack-bridge Core DBus ) target_link_libraries( window-stack-bridge hud-common ${PLATFORM_API_LIBRARIES} ) add_executable( window-stack-bridge-bin main.cpp ) set_target_properties( window-stack-bridge-bin PROPERTIES OUTPUT_NAME window-stack-bridge ) qt5_use_modules( window-stack-bridge-bin Core ) target_link_libraries( window-stack-bridge-bin window-stack-bridge ) install( TARGETS window-stack-bridge-bin RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/hud" ) endif()hud-14.04+14.04.20140604/window-stack-bridge/PlatformApiWindowStack.cpp0000644000015301777760000001003512343623451025646 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include using namespace hud::common; PlatformApiWindowStack::PlatformApiWindowStack( const QDBusConnection &connection, QObject *parent) : AbstractWindowStack(connection, parent) { if (qgetenv("QT_QPA_PLATFORM") != "ubuntu") { throw std::logic_error( _("Incorrect QPA environment for Ubuntu platform API")); } registerOnBus(); m_observer_definition.on_session_requested = on_session_requested_cb; m_observer_definition.on_session_born = on_session_born_cb; m_observer_definition.on_session_unfocused = on_session_unfocused_cb; m_observer_definition.on_session_focused = on_session_focused_cb; m_observer_definition.on_session_died = on_session_died_cb; m_observer_definition.on_keyboard_geometry_changed = 0; m_observer_definition.on_session_requested_fullscreen = 0; m_observer_definition.context = reinterpret_cast(this); ubuntu_ui_session_install_session_lifecycle_observer( &m_observer_definition); } PlatformApiWindowStack::~PlatformApiWindowStack() { } QString PlatformApiWindowStack::GetAppIdFromPid(uint pid) { // FIXME Not implemented qDebug() << "GetAppIdFromPid"; return QString(); } QList PlatformApiWindowStack::GetWindowStack() { // FIXME Not implemented qDebug() << "GetWindowStack"; return QList(); } QStringList PlatformApiWindowStack::GetWindowProperties(uint windowId, const QString &appId, const QStringList &names) { // FIXME Not implemented qDebug() << "GetWindowProperties:" << windowId << appId << names; return QStringList(); } void PlatformApiWindowStack::onSessionRequested( ubuntu_ui_well_known_application app) { // FIXME Not implemented qDebug() << "onSessionRequested"; } void PlatformApiWindowStack::onSessionBorn(ubuntu_ui_session_properties props) { // FIXME Not implemented qDebug() << "onSessionBorn"; //session_properties_get_window_id } void PlatformApiWindowStack::onSessionUnfocused( ubuntu_ui_session_properties props) { // FIXME Not implemented qDebug() << "onSessionUnfocused"; } void PlatformApiWindowStack::onSessionFocused( ubuntu_ui_session_properties props) { // FIXME Not implemented qDebug() << "onSessionFocused"; } void PlatformApiWindowStack::onSessionDied(ubuntu_ui_session_properties props) { // FIXME Not implemented qDebug() << "onSessionDied"; } void PlatformApiWindowStack::on_session_requested_cb( ubuntu_ui_well_known_application app, void* context) { reinterpret_cast(context)->onSessionRequested( app); } void PlatformApiWindowStack::on_session_born_cb( ubuntu_ui_session_properties props, void* context) { reinterpret_cast(context)->onSessionBorn(props); } void PlatformApiWindowStack::on_session_unfocused_cb( ubuntu_ui_session_properties props, void* context) { reinterpret_cast(context)->onSessionUnfocused( props); } void PlatformApiWindowStack::on_session_focused_cb( ubuntu_ui_session_properties props, void* context) { reinterpret_cast(context)->onSessionFocused( props); } void PlatformApiWindowStack::on_session_died_cb( ubuntu_ui_session_properties props, void* context) { reinterpret_cast(context)->onSessionDied(props); } hud-14.04+14.04.20140604/window-stack-bridge/PlatformApiWindowStack.h0000644000015301777760000000423712343623451025322 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef PLATFORMAPIWINDOWSTACK_H_ #define PLATFORMAPIWINDOWSTACK_H_ #include #include class Q_DECL_EXPORT PlatformApiWindowStack: public AbstractWindowStack { Q_OBJECT public: explicit PlatformApiWindowStack(const QDBusConnection &connection, QObject *parent = 0); virtual ~PlatformApiWindowStack(); public Q_SLOTS: virtual QString GetAppIdFromPid(uint pid); virtual QList GetWindowStack(); virtual QStringList GetWindowProperties(uint windowId, const QString &appId, const QStringList &names); protected: static void on_session_requested_cb(ubuntu_ui_well_known_application app, void* context); void onSessionRequested(ubuntu_ui_well_known_application app); static void on_session_born_cb(ubuntu_ui_session_properties props, void* context); void onSessionBorn(ubuntu_ui_session_properties props); static void on_session_unfocused_cb(ubuntu_ui_session_properties props, void* context); void onSessionUnfocused(ubuntu_ui_session_properties props); static void on_session_focused_cb(ubuntu_ui_session_properties props, void* context); void onSessionFocused(ubuntu_ui_session_properties props); static void on_session_died_cb(ubuntu_ui_session_properties props, void* context); void onSessionDied(ubuntu_ui_session_properties props); ubuntu_ui_session_lifecycle_observer m_observer_definition; }; #endif /* PLATFORMAPIWINDOWSTACK_H_ */ hud-14.04+14.04.20140604/window-stack-bridge/WindowStack.h0000644000015301777760000000172612343623451023163 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef WINDOWSTACK_H_ #define WINDOWSTACK_H_ #ifdef ENABLE_BAMF #include typedef BamfWindowStack WindowStack; #elif ENABLE_PLATFORM_API #include typedef PlatformApiWindowStack WindowStack; #endif #endif /* WINDOWSTACK_H_ */ hud-14.04+14.04.20140604/tests/0000755000015301777760000000000012343624372016050 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/bad-app-info/0000755000015301777760000000000012343624372020305 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/bad-app-info/missing-menus.hud-app-info0000644000015301777760000000023112343623451025305 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/bad-app-info/missing-desktop.hud-app-info0000644000015301777760000000015712343623451025636 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/bad-app-info/item-no-count.hud-app-info0000644000015301777760000000024412343623451025211 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/bad-app-info/menu-no-name.hud-app-info0000644000015301777760000000024212343623451025005 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/bad-app-info/item-no-name.hud-app-info0000644000015301777760000000024212343623451024777 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/bad-app-info/multiple-menus.hud-app-info0000644000015301777760000000040112343623451025466 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/bad-app-info/dual-headers.hud-app-info0000644000015301777760000000005212343623451025046 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/integration/0000755000015301777760000000000012343624372020373 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/integration/TestHud.cpp0000644000015301777760000003445112343623451022463 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace hud::common; using namespace hud::client; using namespace std; using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; namespace { class TestHud: public Test { protected: typedef QPair ResultPair; TestHud() : mock(dbus) { mock.registerCustomMock(DBusTypes::BAMF_DBUS_NAME, DBusTypes::BAMF_MATCHER_DBUS_PATH, "org.ayatana.bamf.control", QDBusConnection::SessionBus); mock.registerCustomMock(DBusTypes::WINDOW_STACK_DBUS_NAME, DBusTypes::WINDOW_STACK_DBUS_PATH, ComCanonicalUnityWindowStackInterface::staticInterfaceName(), QDBusConnection::SessionBus); mock.registerCustomMock(DBusTypes::APPMENU_REGISTRAR_DBUS_NAME, DBusTypes::APPMENU_REGISTRAR_DBUS_PATH, "com.canonical.AppMenu.Registrar", QDBusConnection::SessionBus); dbus.startServices(); } virtual ~TestHud() { } static void EXPECT_RESULT(const QList &results, int index, const QString &name, const QVariant &value) { const QVariantList &result(results.at(index)); EXPECT_EQ(name, result.at(0).toString()); EXPECT_EQ(value, result.at(1).value().variant()); } OrgFreedesktopDBusMockInterface & bamfMatcherMock() { return mock.mockInterface(DBusTypes::BAMF_DBUS_NAME, DBusTypes::BAMF_MATCHER_DBUS_PATH, "org.ayatana.bamf.control", QDBusConnection::SessionBus); } OrgFreedesktopDBusMockInterface & windowStackMock() { return mock.mockInterface(DBusTypes::WINDOW_STACK_DBUS_NAME, DBusTypes::WINDOW_STACK_DBUS_PATH, ComCanonicalUnityWindowStackInterface::staticInterfaceName(), QDBusConnection::SessionBus); } OrgFreedesktopDBusMockInterface & appmenuRegstrarMock() { return mock.mockInterface(DBusTypes::APPMENU_REGISTRAR_DBUS_NAME, DBusTypes::APPMENU_REGISTRAR_DBUS_PATH, "com.canonical.AppMenu.Registrar", QDBusConnection::SessionBus); } void startHud() { hud.reset( new QProcessDBusService(DBusTypes::HUD_SERVICE_DBUS_NAME, QDBusConnection::SessionBus, HUD_SERVICE_BINARY, QStringList())); hud->start(dbus.sessionConnection()); } void startDBusMenu(const QString &name, const QString &path, const QString &json) { menuService.reset( new QProcessDBusService(name, QDBusConnection::SessionBus, DBUSMENU_JSON_LOADER, QStringList() << name << path << json)); menuService->start(dbus.sessionConnection()); } void startGMenu(const QString &name, const QString &path, const QString &model) { menuService.reset( new QProcessDBusService(name, QDBusConnection::SessionBus, model, QStringList() << name << path)); menuService->start(dbus.sessionConnection()); } void startLibHud(const QString &applicationId, const QString &name, const QString &path, const QString &model) { menuService.reset( new QProcessDBusService(name, QDBusConnection::SessionBus, model, QStringList() << applicationId << name << path)); menuService->start(dbus.sessionConnection()); } QDBusConnection connection() { return dbus.sessionConnection(); } static ResultPair result(const QAbstractListModel &results, uint i) { QModelIndex index = results.index(i); return ResultPair(results.data(index, 1).toString(), results.data(index, 3).toString()); } void EXPECT_TOOLBAR(const QAbstractListModel &toolbarModel, int i, const QString &icon, HudClientQueryToolbarItems item, bool enabled) { QModelIndex index = toolbarModel.index(i); EXPECT_EQ(icon, toolbarModel.data(index, Qt::DecorationRole).toString()); EXPECT_EQ(item, toolbarModel.data(index, Qt::UserRole).toInt()); EXPECT_EQ(enabled, toolbarModel.data(index, Qt::UserRole + 1).toBool()); } DBusTestRunner dbus; DBusMock mock; QSharedPointer hud; QSharedPointer menuService; }; TEST_F(TestHud, SearchDBusMenuContext) { startDBusMenu("menu.name", "/menu", JSON_SOURCE); windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = [(0, 'app0', True, 0)]").waitForFinished(); // There are no GMenus in this test windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowProperties", "usas", "as", "ret = []\n" "for arg in args[2]:\n" " ret.append('')").waitForFinished(); appmenuRegstrarMock().AddMethod(DBusTypes::APPMENU_REGISTRAR_DBUS_NAME, "GetMenuForWindow", "u", "so", "ret = ('menu.name', '/menu')").waitForFinished(); startHud(); HudClient client; QSignalSpy modelsChangedSpy(&client, SIGNAL(modelsChanged())); modelsChangedSpy.wait(); QSignalSpy countChangedSpy(client.results(), SIGNAL(countChanged())); client.setQuery("piece hook"); countChangedSpy.wait(); QAbstractListModel &results(*client.results()); if(results.rowCount() != 3) { countChangedSpy.wait(); } ASSERT_EQ(3, results.rowCount()); EXPECT_EQ(ResultPair("stray slash", "piece hook"), result(results, 0)); EXPECT_EQ(ResultPair("swift sad", "piece hook"), result(results, 1)); EXPECT_EQ(ResultPair("bowl", "link"), result(results, 2)); } TEST_F(TestHud, SearchDBusMenuOneResult) { startDBusMenu("menu.name", "/menu", JSON_SHORTCUTS); windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = [(0, 'app0', True, 0)]").waitForFinished(); // There are no GMenus in this test windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowProperties", "usas", "as", "ret = []\n" "for arg in args[2]:\n" " ret.append('')").waitForFinished(); appmenuRegstrarMock().AddMethod(DBusTypes::APPMENU_REGISTRAR_DBUS_NAME, "GetMenuForWindow", "u", "so", "ret = ('menu.name', '/menu')").waitForFinished(); startHud(); HudClient client; QSignalSpy modelsChangedSpy(&client, SIGNAL(modelsChanged())); modelsChangedSpy.wait(); QSignalSpy countChangedSpy(client.results(), SIGNAL(countChanged())); client.setQuery("quit"); countChangedSpy.wait(); QAbstractListModel &results(*client.results()); if(results.rowCount() == 0) { countChangedSpy.wait(); } ASSERT_EQ(1, results.rowCount()); EXPECT_EQ(ResultPair("Quiter", ""), result(results, 0)); } TEST_F(TestHud, SearchGMenuOneResult) { startGMenu("menu.name", "/menu", MODEL_SHORTCUTS); windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = [(0, 'app0', True, 0)]").waitForFinished(); windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowProperties", "usas", "as", "ret = []\n" "if args[0] == 0:\n" " ret.append('menu.name')\n" " ret.append('')\n" " ret.append('/menu')\n" " ret.append('')\n" " ret.append('')\n" " ret.append('/menu')\n" "else:\n" " for arg in args[2]:\n" " ret.append('')").waitForFinished(); // There are no DBusMenus in this test appmenuRegstrarMock().AddMethod(DBusTypes::APPMENU_REGISTRAR_DBUS_NAME, "GetMenuForWindow", "u", "so", "ret = ('', '/')").waitForFinished(); startHud(); HudClient client; QSignalSpy modelsChangedSpy(&client, SIGNAL(modelsChanged())); modelsChangedSpy.wait(); QSignalSpy countChangedSpy(client.results(), SIGNAL(countChanged())); client.setQuery("closr"); countChangedSpy.wait(); QAbstractListModel &results(*client.results()); if(results.rowCount() == 0) { countChangedSpy.wait(); } ASSERT_EQ(1, results.rowCount()); EXPECT_EQ(ResultPair("Close", ""), result(results, 0)); } TEST_F(TestHud, SearchLibHudOneResult) { windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = [(0, 'app0', True, 0)]").waitForFinished(); // No GMenu windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowProperties", "usas", "as", "ret = []\n" "for arg in args[2]:\n" " ret.append('')").waitForFinished(); // There are no DBusMenus in this test appmenuRegstrarMock().AddMethod(DBusTypes::APPMENU_REGISTRAR_DBUS_NAME, "GetMenuForWindow", "u", "so", "ret = ('', '/')").waitForFinished(); startHud(); startLibHud("app0", "test.app", "/test", MODEL_LIBHUD); ComCanonicalHudTestInterface libhudTestInterface("test.app", "/test", dbus.sessionConnection()); HudClient client; QSignalSpy modelsChangedSpy(&client, SIGNAL(modelsChanged())); modelsChangedSpy.wait(); QSignalSpy countChangedSpy(client.results(), SIGNAL(countChanged())); client.setQuery("quitter"); countChangedSpy.wait(); QAbstractListModel &results(*client.results()); if(results.rowCount() == 0) { countChangedSpy.wait(); } ASSERT_EQ(1, results.rowCount()); EXPECT_EQ(ResultPair("quiter", ""), result(results, 0)); const QAbstractListModel &toolbarModel(*client.toolBarModel()); ASSERT_EQ(5, toolbarModel.rowCount()); EXPECT_TOOLBAR(toolbarModel, 0, "graphics/close.png", HUD_CLIENT_QUERY_TOOLBAR_QUIT, false); EXPECT_TOOLBAR(toolbarModel, 1, "graphics/undo.png", HUD_CLIENT_QUERY_TOOLBAR_UNDO, true); EXPECT_TOOLBAR(toolbarModel, 2, "graphics/help.png", HUD_CLIENT_QUERY_TOOLBAR_HELP, true); EXPECT_TOOLBAR(toolbarModel, 3, "graphics/view-fullscreen.png", HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN, false); EXPECT_TOOLBAR(toolbarModel, 4, "graphics/settings.png", HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES, false); QSignalSpy actionInvokedSpy(&libhudTestInterface, SIGNAL(ActionInvoked(const QString &))); client.executeToolBarAction(HUD_CLIENT_QUERY_TOOLBAR_UNDO); actionInvokedSpy.wait(); EXPECT_EQ(QVariantList() << QVariant("undoer"), actionInvokedSpy.at(0)); } TEST_F(TestHud, ExecuteGMenuAction) { startGMenu("menu.name", "/menu", MODEL_SHORTCUTS); ComCanonicalHudTestInterface gmenuTestInterface("menu.name", "/menu", dbus.sessionConnection()); windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = [(0, 'app0', True, 0)]").waitForFinished(); windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowProperties", "usas", "as", "ret = []\n" "if args[0] == 0:\n" " ret.append('menu.name')\n" " ret.append('')\n" " ret.append('/menu')\n" " ret.append('')\n" " ret.append('')\n" " ret.append('/menu')\n" "else:\n" " for arg in args[2]:\n" " ret.append('')").waitForFinished(); // There are no DBusMenus in this test appmenuRegstrarMock().AddMethod(DBusTypes::APPMENU_REGISTRAR_DBUS_NAME, "GetMenuForWindow", "u", "so", "ret = ('', '/')").waitForFinished(); startHud(); HudClient client; QSignalSpy modelsChangedSpy(&client, SIGNAL(modelsChanged())); modelsChangedSpy.wait(); QSignalSpy countChangedSpy(client.results(), SIGNAL(countChanged())); client.setQuery("closr"); countChangedSpy.wait(); QAbstractListModel &results(*client.results()); if(results.rowCount() == 0) { countChangedSpy.wait(); } ASSERT_EQ(1, results.rowCount()); EXPECT_EQ(ResultPair("Close", ""), result(results, 0)); QSignalSpy actionInvokedSpy(&gmenuTestInterface, SIGNAL(ActionInvoked(const QString &))); QSignalSpy executedSpy(&client, SIGNAL(commandExecuted())); client.executeCommand(0); EXPECT_FALSE(executedSpy.isEmpty()); actionInvokedSpy.wait(); ASSERT_FALSE(actionInvokedSpy.isEmpty()); EXPECT_EQ(QVariantList() << QVariant("close"), actionInvokedSpy.at(0)); } TEST_F(TestHud, ExecuteParameterized) { windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = [(0, 'app0', True, 0)]").waitForFinished(); // No GMenu windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowProperties", "usas", "as", "ret = []\n" "for arg in args[2]:\n" " ret.append('')").waitForFinished(); // There are no DBusMenus in this test appmenuRegstrarMock().AddMethod(DBusTypes::APPMENU_REGISTRAR_DBUS_NAME, "GetMenuForWindow", "u", "so", "ret = ('', '/')").waitForFinished(); startHud(); startLibHud("app0", "test.app", "/test", MODEL_LIBHUD); ComCanonicalHudTestInterface gmenuTestInterface("test.app", "/test", dbus.sessionConnection()); QSignalSpy actionInvokedSpy(&gmenuTestInterface, SIGNAL( ParameterizedActionInvoked(const QString &, const QDBusVariant &))); HudClient client; QSignalSpy modelsChangedSpy(&client, SIGNAL(modelsChanged())); modelsChangedSpy.wait(); QSignalSpy countChangedSpy(client.results(), SIGNAL(countChanged())); client.setQuery("fruiy"); countChangedSpy.wait(); QAbstractListModel &results(*client.results()); if(results.rowCount() == 0) { countChangedSpy.wait(); } ASSERT_EQ(1, results.rowCount()); ASSERT_EQ(ResultPair("fruit", ""), result(results, 0)); QSignalSpy executedSpy(&client, SIGNAL(showParametrizedAction(const QString &, const QVariant &))); client.executeCommand(0); executedSpy.wait(); ASSERT_FALSE(executedSpy.isEmpty()); QVariantMap parameters; parameters["hud.apple"] = 1.0; parameters["hud.banana"] = 2.0; parameters["hud.cranberry"] = 3.0; client.executeParametrizedAction(parameters); for (uint count(0); count < 5; ++count) { actionInvokedSpy.wait(); if (actionInvokedSpy.size() == 5) { break; } } ASSERT_EQ(5, actionInvokedSpy.size()); EXPECT_RESULT(actionInvokedSpy, 0, "apple", QVariant(1.0)); EXPECT_RESULT(actionInvokedSpy, 1, "banana", QVariant(2.0)); EXPECT_RESULT(actionInvokedSpy, 2, "cranberry", QVariant(3.0)); EXPECT_RESULT(actionInvokedSpy, 3, "fruit", QVariant("s")); EXPECT_RESULT(actionInvokedSpy, 4, "fruit", QVariant("s")); } } // namespace hud-14.04+14.04.20140604/tests/integration/CMakeLists.txt0000644000015301777760000000065112343623451023132 0ustar pbusernogroup00000000000000 add_definitions( -pedantic -Wall -Wextra ) set( INTEGRATION_TESTS_SRC TestHud.cpp ) add_executable( test-integration-tests ${INTEGRATION_TESTS_SRC} ) target_link_libraries( test-integration-tests test-utils hud-common hud-client ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} ${QTDBUSTEST_LIBRARIES} ${QTDBUSMOCK_LIBRARIES} ) qt5_use_modules(test-integration-tests Test ) add_hud_test( test-integration-tests ) hud-14.04+14.04.20140604/tests/data/0000755000015301777760000000000012343624372016761 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/data/test-indicator-source-sound.json0000644000015301777760000000032212343623451025223 0ustar pbusernogroup00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Sound Time' }, { "id": 2, "label": 'biz' }, { "id": 3, "label": 'www' } ] }hud-14.04+14.04.20140604/tests/data/test-menu-input-shortcuts.json0000644000015301777760000000052112343623451024761 0ustar pbusernogroup00000000000000{"submenu": [ {"id": 1, "label": "Save", "shortcut": [["Control", "S"]]}, {"id": 2, "label": "Quiter", "shortcut": [["Control", "Alt", "Q"]]}, {"id": 3, "label": "Emacs", "shortcut": [["Control", "X"], ["Control", "W"]]}, {"id": 4, "label": "Close", "shortcut": [["Super", "W"]]}, {"id": 5, "label": "Nothing"} ]} hud-14.04+14.04.20140604/tests/data/test-indicator-source-users.json0000644000015301777760000000032212343623451025234 0ustar pbusernogroup00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Users Time' }, { "id": 2, "label": 'baz' }, { "id": 3, "label": 'yyy' } ] }hud-14.04+14.04.20140604/tests/data/test-menu-input-simple.json0000644000015301777760000000006112343623451024213 0ustar pbusernogroup00000000000000{"submenu": [ {"id": 1, "label": "Simple"} ]} hud-14.04+14.04.20140604/tests/data/test-indicator-source-messages.json0000644000015301777760000000032512343623451025705 0ustar pbusernogroup00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Messages Time' }, { "id": 2, "label": 'foz' }, { "id": 3, "label": 'vvv' } ] }hud-14.04+14.04.20140604/tests/data/com.canonical.hud.test.xml0000644000015301777760000000056212343623451023744 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/data/valgrind.suppression0000644000015301777760000000535412343623451023107 0ustar pbusernogroup00000000000000############################### # Qt's usage of GLib ############################### { Ignore pthreads Memcheck:Leak ... fun:pthread_create@@* } { Glib memalign Memcheck:Leak ... fun:posix_memalign } { Ignore glib mainloop Memcheck:Leak ... fun:g_main_context_push_thread_default } { Ignore glib main context Memcheck:Leak ... fun:g_main_context_new } { Memcheck:Leak ... fun:_ZN19QApplicationPrivate9constructEv } { Memcheck:Cond ... fun:_ZN19QApplicationPrivate9constructEv fun:main } { Memcheck:Leak ... fun:_ZN22QGuiApplicationPrivate25createPlatformIntegrationEv } { Memcheck:Leak fun:realloc ... obj:/usr/lib/*/libpango-*.so.* fun:pango_layout_get_unknown_glyphs_count } { Memcheck:Leak fun:realloc ... fun:pango_itemize_with_base_dir obj:/usr/lib/*/libpango-*.so.* } ########################## # Fontconfig ########################## { Memcheck:Leak ... fun:FcConfigParseAndLoad } { Memcheck:Leak fun:realloc ... obj:/usr/lib/*/libfontconfig.so.* fun:FcFontRenderPrepare } { Memcheck:Leak fun:realloc ... obj:/usr/lib/*/libfontconfig.so.* fun:FcPatternAddBool } ############################### # GObject rules ############################### { Memcheck:Leak ... fun:g_type_register_static } { Memcheck:Leak ... fun:g_type_register_fundamental } { Memcheck:Leak ... fun:type_node_fundamental_new_W } { Memcheck:Leak ... fun:type_data_make_W } { Memcheck:Leak ... fun:g_type_add_interface_static } { Memcheck:Leak ... fun:type_iface_vtable_base_init_Wm } { Memcheck:Leak ... fun:g_dbus_interface_skeleton_class_intern_init } { Memcheck:Leak ... fun:g_signal_type_cclosure_new } { Memcheck:Leak fun:calloc fun:g_malloc0 fun:g_type_class_ref } { Memcheck:Leak fun:realloc fun:g_realloc } { Memcheck:Leak fun:malloc fun:realloc fun:g_realloc } { Memcheck:Leak fun:calloc fun:g_malloc0 } hud-14.04+14.04.20140604/tests/data/test-dbus-message-count.json0000644000015301777760000024424312343623451024344 0ustar pbusernogroup00000000000000{ "id": 0, "children-display": 'submenu', "submenu": [ { "id": 5, "children-display": 'submenu', "label": 'File', "submenu": [ { "id": 6, "label": 'Quit', "shortcut": [['Control', 'q']] }, { "id": 7, "label": 'Close all', "shortcut": [['Control', 'Shift', 'w']] }, { "id": 8, "label": 'Close', "shortcut": [['Control', 'w']] }, { "id": 9, "type": 'separator' }, { "id": 10, "label": 'Send by Email...' }, { "id": 11, "label": 'Print...', "shortcut": [['Control', 'p']] }, { "id": 12, "label": 'Page Setup' }, { "id": 13, "type": 'separator' }, { "id": 14, "label": 'Revert' }, { "id": 15, "label": 'Save as Template...' }, { "id": 16, "label": 'Save a Copy...' }, { "id": 17, "label": 'Save As...', "shortcut": [['Control', 'Shift', 's']] }, { "id": 18, "label": 'Save', "shortcut": [['Control', 's']] }, { "id": 19, "type": 'separator' }, { "id": 20, "children-display": 'submenu', "label": 'Open Recent', "submenu": [ { "id": 21, "label": 'Document History' }, { "id": 22, "type": 'separator' }, { "id": 23, "label": 'giggity.jpg', "shortcut": [['Control', '2']] }, { "id": 24, "label": 'Icon Height.svg', "shortcut": [['Control', '1']] } ] }, { "id": 25, "label": 'Open Location...' }, { "id": 26, "label": 'Open as Layers...', "shortcut": [['Control', 'Alt', 'o']] }, { "id": 27, "label": 'Open...', "shortcut": [['Control', 'o']] }, { "id": 28, "children-display": 'submenu', "label": 'Create', "submenu": [ { "id": 29, "children-display": 'submenu', "label": 'Web Page Themes', "submenu": [ { "id": 30, "children-display": 'submenu', "label": 'Classic.Gimp.Org', "submenu": [ { "id": 31, "label": 'Tube Sub-Sub-Button Label...' }, { "id": 32, "label": 'Tube Sub-Button Label...' }, { "id": 33, "label": 'Tube Button Label...' }, { "id": 34, "label": 'Small Header...' }, { "id": 35, "label": 'General Tube Labels...' }, { "id": 36, "label": 'Big Header...' } ] }, { "id": 37, "children-display": 'submenu', "label": 'Beveled Pattern', "submenu": [ { "id": 38, "label": 'Hrule...' }, { "id": 39, "label": 'Heading...' }, { "id": 40, "label": 'Button...' }, { "id": 41, "label": 'Bullet...' }, { "id": 42, "label": 'Arrow...' } ] }, { "id": 43, "children-display": 'submenu', "label": 'Alien Glow', "submenu": [ { "id": 44, "label": 'Hrule...' }, { "id": 45, "label": 'Button...' }, { "id": 46, "label": 'Bullet...' }, { "id": 47, "label": 'Arrow...' } ] } ] }, { "id": 48, "children-display": 'submenu', "label": 'Patterns', "submenu": [ { "id": 49, "label": 'Truchet...' }, { "id": 50, "label": 'Swirly...' }, { "id": 51, "label": 'Swirl-Tile...' }, { "id": 52, "label": 'Render Map...' }, { "id": 53, "label": 'Land...' }, { "id": 54, "label": 'Flatland...' }, { "id": 55, "label": 'Camouflage...' }, { "id": 56, "label": '3D Truchet...' } ] }, { "id": 57, "children-display": 'submenu', "label": 'Logos', "submenu": [ { "id": 58, "label": 'Web Title Header...' }, { "id": 59, "label": 'Textured...' }, { "id": 60, "label": 'Text Circle...' }, { "id": 61, "label": 'Starscape...' }, { "id": 62, "label": 'Speed Text...' }, { "id": 63, "label": 'SOTA Chrome...' }, { "id": 64, "label": 'Particle Trace...' }, { "id": 65, "label": 'Newsprint Text...' }, { "id": 66, "label": 'Neon...' }, { "id": 67, "label": 'Imigre-26...' }, { "id": 68, "label": 'Gradient Bevel...' }, { "id": 69, "label": 'Glowing Hot...' }, { "id": 70, "label": 'Glossy...' }, { "id": 71, "label": 'Frosty...' }, { "id": 72, "label": 'Crystal...' }, { "id": 73, "label": 'Cool Metal...' }, { "id": 74, "label": 'Comic Book...' }, { "id": 75, "label": 'Chrome...' }, { "id": 76, "label": 'Chip Away...' }, { "id": 77, "label": 'Chalk...' }, { "id": 78, "label": 'Carved...' }, { "id": 79, "label": 'Bovination...' }, { "id": 80, "label": 'Blended...' }, { "id": 81, "label": 'Basic I...' }, { "id": 82, "label": 'Basic II...' }, { "id": 83, "label": 'Alien Neon...' }, { "id": 84, "label": 'Alien Glow...' }, { "id": 85, "label": '3D Outline...' } ] }, { "id": 86, "children-display": 'submenu', "label": 'Buttons', "submenu": [ { "id": 87, "label": 'Simple Beveled Button...' }, { "id": 88, "label": 'Round Button...' } ] }, { "id": 89, "type": 'separator' }, { "id": 90, "children-display": 'submenu', "label": 'xscanimage', "submenu": [ { "id": 91, "enabled": false, "label": 'Device dialog...' } ] }, { "id": 92, "label": 'Screenshot...' }, { "id": 93, "label": 'From Clipboard', "shortcut": [['Control', 'Shift', 'v']] } ] }, { "id": 94, "label": 'New...', "shortcut": [['Control', 'n']] } ] }, { "id": 95, "children-display": 'submenu', "label": 'Edit', "submenu": [ { "id": 96, "label": 'Units' }, { "id": 97, "label": 'Modules' }, { "id": 98, "label": 'Keyboard Shortcuts' }, { "id": 99, "label": 'Preferences' }, { "id": 100, "type": 'separator' }, { "id": 101, "enabled": false, "label": 'Stroke Path...' }, { "id": 102, "enabled": false, "label": 'Stroke Selection...' }, { "id": 103, "label": 'Fill with Pattern', "shortcut": [['Control', 'semicolon']] }, { "id": 104, "label": 'Fill with BG Color', "shortcut": [['Control', 'period']] }, { "id": 105, "label": 'Fill with FG Color', "shortcut": [['Control', 'comma']] }, { "id": 106, "label": 'Clear', "shortcut": [['Delete']] }, { "id": 107, "type": 'separator' }, { "id": 108, "children-display": 'submenu', "label": 'Buffer', "submenu": [ { "id": 109, "label": 'Paste Named...' }, { "id": 110, "label": 'Copy Visible Named...' }, { "id": 111, "label": 'Copy Named...' }, { "id": 112, "label": 'Cut Named...' } ] }, { "id": 113, "children-display": 'submenu', "label": 'Paste as', "submenu": [ { "id": 114, "label": 'New Pattern...' }, { "id": 115, "label": 'New Brush...' }, { "id": 116, "label": 'New Layer' }, { "id": 117, "label": 'New Image', "shortcut": [['Control', 'Shift', 'v']] } ] }, { "id": 118, "label": 'Paste Into' }, { "id": 119, "label": 'Paste', "shortcut": [['Control', 'v']] }, { "id": 120, "label": 'Copy Visible', "shortcut": [['Control', 'Shift', 'c']] }, { "id": 121, "label": 'Copy', "shortcut": [['Control', 'c']] }, { "id": 122, "label": 'Cut', "shortcut": [['Control', 'x']] }, { "id": 123, "type": 'separator' }, { "id": 124, "label": 'Undo History' }, { "id": 3, "enabled": false, "label": '_Fade...' }, { "id": 2, "enabled": false, "label": '_Redo', "shortcut": [['Control', 'y']] }, { "id": 1, "enabled": false, "label": '_Undo', "shortcut": [['Control', 'z']] } ] }, { "id": 125, "children-display": 'submenu', "label": 'Select', "submenu": [ { "id": 126, "enabled": false, "label": 'To Path' }, { "id": 127, "label": 'Save to Channel' }, { "id": 128, "label": 'Toggle Quick Mask', "shortcut": [['Shift', 'q']], "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 129, "type": 'separator' }, { "id": 130, "label": 'Distort...' }, { "id": 131, "enabled": false, "label": 'Border...' }, { "id": 132, "enabled": false, "label": 'Grow...' }, { "id": 133, "enabled": false, "label": 'Shrink...' }, { "id": 134, "enabled": false, "label": 'Sharpen' }, { "id": 135, "enabled": false, "label": 'Feather...' }, { "id": 136, "type": 'separator' }, { "id": 137, "label": 'Selection Editor' }, { "id": 138, "enabled": false, "label": 'From Path', "shortcut": [['Shift', 'v']] }, { "id": 139, "label": 'By Color', "shortcut": [['Shift', 'o']] }, { "id": 140, "enabled": false, "label": 'Float', "shortcut": [['Control', 'Shift', 'l']] }, { "id": 141, "label": 'Invert', "shortcut": [['Control', 'i']] }, { "id": 142, "enabled": false, "label": 'None', "shortcut": [['Control', 'Shift', 'a']] }, { "id": 143, "label": 'All', "shortcut": [['Control', 'a']] } ] }, { "id": 144, "children-display": 'submenu', "label": 'View', "submenu": [ { "id": 145, "label": 'Show Statusbar', "toggle-state": 1, "toggle-type": 'checkmark' }, { "id": 146, "label": 'Show Scrollbars', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 147, "label": 'Show Rulers', "shortcut": [['Control', 'Shift', 'r']], "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 148, "label": 'Show Menubar', "toggle-state": 1, "toggle-type": 'checkmark' }, { "id": 149, "children-display": 'submenu', "label": 'Padding Color', "submenu": [ { "id": 150, "label": 'As in Preferences' }, { "id": 151, "type": 'separator' }, { "id": 152, "label": 'Select Custom Color...' }, { "id": 153, "label": 'Dark Check Color' }, { "id": 154, "label": 'Light Check Color' }, { "id": 155, "label": 'From Theme' } ] }, { "id": 156, "type": 'separator' }, { "id": 157, "label": 'Snap to Active Path', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 158, "label": 'Snap to Canvas Edges', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 159, "label": 'Snap to Grid', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 160, "label": 'Snap to Guides', "toggle-state": 1, "toggle-type": 'checkmark' }, { "id": 161, "type": 'separator' }, { "id": 162, "label": 'Show Sample Points', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 163, "label": 'Show Grid', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 164, "label": 'Show Guides', "shortcut": [['Control', 'Shift', 't']], "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 165, "label": 'Show Layer Boundary', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 166, "label": 'Show Selection', "shortcut": [['Control', 't']], "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 167, "type": 'separator' }, { "id": 168, "label": 'Display Filters...' }, { "id": 169, "label": 'Navigation Window' }, { "id": 170, "type": 'separator' }, { "id": 171, "children-display": 'submenu', "label": 'Fullscreen', "shortcut": [['F11']], "toggle-state": 0, "toggle-type": 'checkmark', "submenu": [ { "id": 172, "label": 'Open Display...' } ] }, { "id": 173, "label": 'Shrink Wrap', "shortcut": [['Control', 'e']] }, { "id": 174, "type": 'separator' }, { "id": 175, "children-display": 'submenu', "label": '_Zoom (67%)', "submenu": [ { "id": 176, "label": 'Othe_r (67%)...', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 177, "type": 'separator' }, { "id": 178, "label": '1:16 (6.25%)', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 179, "label": '1:8 (12.5%)', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 180, "label": '1:4 (25%)', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 181, "label": '1:2 (50%)', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 182, "label": '1:1 (100%)', "shortcut": [['1']], "toggle-state": 1, "toggle-type": 'checkmark' }, { "id": 183, "label": '2:1 (200%)', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 184, "label": '4:1 (400%)', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 185, "label": '8:1 (800%)', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 186, "label": '16:1 (1600%)', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 187, "type": 'separator' }, { "id": 188, "label": 'Fill Window' }, { "id": 189, "label": 'Fit Image in Window', "shortcut": [['Control', 'Shift', 'e']] }, { "id": 190, "label": 'Zoom In', "shortcut": [['plus']] }, { "id": 191, "label": 'Zoom Out', "shortcut": [['minus']] }, { "id": 4, "label": 'Re_vert Zoom (67%)', "shortcut": [['grave']] } ] }, { "id": 192, "label": 'Dot for Dot', "toggle-state": 1, "toggle-type": 'checkmark' }, { "id": 193, "label": 'New View' } ] }, { "id": 194, "children-display": 'submenu', "label": 'Image', "submenu": [ { "id": 195, "label": 'Image Properties', "shortcut": [['Alt', 'Return']] }, { "id": 196, "label": 'Configure Grid...' }, { "id": 197, "children-display": 'submenu', "label": 'Guides', "submenu": [ { "id": 198, "label": 'Remove all Guides' }, { "id": 199, "label": 'New Guides from Selection' }, { "id": 200, "label": 'New Guide...' }, { "id": 201, "label": 'New Guide (by Percent)...' } ] }, { "id": 202, "type": 'separator' }, { "id": 203, "label": 'Align Visible Layers...' }, { "id": 204, "label": 'Flatten Image' }, { "id": 205, "label": 'Merge Visible Layers...', "shortcut": [['Control', 'm']] }, { "id": 206, "type": 'separator' }, { "id": 207, "label": 'Zealous Crop' }, { "id": 208, "label": 'Autocrop Image' }, { "id": 209, "enabled": false, "label": 'Crop to Selection' }, { "id": 210, "type": 'separator' }, { "id": 211, "label": 'Scale Image...' }, { "id": 212, "label": 'Print Size...' }, { "id": 213, "enabled": false, "label": 'Fit Canvas to Selection' }, { "id": 214, "label": 'Fit Canvas to Layers' }, { "id": 215, "label": 'Canvas Size...' }, { "id": 216, "type": 'separator' }, { "id": 217, "children-display": 'submenu', "label": 'Transform', "submenu": [ { "id": 218, "label": 'Guillotine' }, { "id": 219, "type": 'separator' }, { "id": 220, "label": 'Rotate 180?' }, { "id": 221, "label": 'Rotate 90? counter-clockwise' }, { "id": 222, "label": 'Rotate 90? clockwise' }, { "id": 223, "type": 'separator' }, { "id": 224, "label": 'Flip Vertically' }, { "id": 225, "label": 'Flip Horizontally' } ] }, { "id": 226, "children-display": 'submenu', "label": 'Mode', "submenu": [ { "id": 227, "label": 'Convert to Color Profile...' }, { "id": 228, "label": 'Assign Color Profile...' }, { "id": 229, "type": 'separator' }, { "id": 230, "label": 'Indexed...', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 231, "label": 'Grayscale', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 232, "label": 'RGB', "toggle-state": 1, "toggle-type": 'checkmark' } ] }, { "id": 233, "label": 'Duplicate', "shortcut": [['Control', 'd']] } ] }, { "id": 234, "children-display": 'submenu', "label": 'Layer', "submenu": [ { "id": 235, "label": 'Autocrop Layer' }, { "id": 236, "enabled": false, "label": 'Crop to Selection' }, { "id": 237, "label": 'Scale Layer...' }, { "id": 238, "label": 'Layer to Image Size' }, { "id": 239, "label": 'Layer Boundary Size...' }, { "id": 240, "type": 'separator' }, { "id": 241, "children-display": 'submenu', "label": 'Transform', "submenu": [ { "id": 242, "label": 'Offset...', "shortcut": [['Control', 'Shift', 'o']] }, { "id": 243, "type": 'separator' }, { "id": 244, "label": 'Arbitrary Rotation...' }, { "id": 245, "label": 'Rotate 180?' }, { "id": 246, "label": 'Rotate 90? counter-clockwise' }, { "id": 247, "label": 'Rotate 90? clockwise' }, { "id": 248, "type": 'separator' }, { "id": 249, "label": 'Flip Vertically' }, { "id": 250, "label": 'Flip Horizontally' } ] }, { "id": 251, "children-display": 'submenu', "label": 'Transparency', "submenu": [ { "id": 252, "label": 'Intersect with Selection' }, { "id": 253, "label": 'Subtract from Selection' }, { "id": 254, "label": 'Add to Selection' }, { "id": 255, "label": 'Alpha to Selection' }, { "id": 256, "type": 'separator' }, { "id": 257, "label": 'Threshold Alpha...' }, { "id": 258, "label": 'Semi-Flatten' }, { "id": 259, "label": 'Color to Alpha...' }, { "id": 260, "label": 'Remove Alpha Channel' }, { "id": 261, "enabled": false, "label": 'Add Alpha Channel' } ] }, { "id": 262, "children-display": 'submenu', "label": 'Mask', "submenu": [ { "id": 263, "enabled": false, "label": 'Intersect with Selection' }, { "id": 264, "enabled": false, "label": 'Subtract from Selection' }, { "id": 265, "enabled": false, "label": 'Add to Selection' }, { "id": 266, "enabled": false, "label": 'Mask to Selection' }, { "id": 267, "type": 'separator' }, { "id": 268, "enabled": false, "label": 'Disable Layer Mask', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 269, "enabled": false, "label": 'Edit Layer Mask', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 270, "enabled": false, "label": 'Show Layer Mask', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 271, "type": 'separator' }, { "id": 272, "enabled": false, "label": 'Delete Layer Mask' }, { "id": 273, "enabled": false, "label": 'Apply Layer Mask' }, { "id": 274, "label": 'Add Layer Mask...' } ] }, { "id": 275, "children-display": 'submenu', "label": 'Stack', "submenu": [ { "id": 276, "label": 'Reverse Layer Order' }, { "id": 277, "type": 'separator' }, { "id": 278, "enabled": false, "label": 'Layer to Bottom' }, { "id": 279, "enabled": false, "label": 'Layer to Top' }, { "id": 280, "enabled": false, "label": 'Lower Layer' }, { "id": 281, "enabled": false, "label": 'Raise Layer' }, { "id": 282, "type": 'separator' }, { "id": 283, "enabled": false, "label": 'Select Bottom Layer', "shortcut": [['End']] }, { "id": 284, "enabled": false, "label": 'Select Top Layer', "shortcut": [['Home']] }, { "id": 285, "enabled": false, "label": 'Select Next Layer', "shortcut": [['Page_Down']] }, { "id": 286, "enabled": false, "label": 'Select Previous Layer', "shortcut": [['Page_Up']] } ] }, { "id": 287, "children-display": 'submenu', "type": 'separator', "submenu": [ { "id": 288, "enabled": false, "label": 'Empty' } ] }, { "id": 289, "label": 'Delete Layer' }, { "id": 290, "enabled": false, "label": 'Merge Down' }, { "id": 291, "enabled": false, "label": 'Anchor Layer', "shortcut": [['Control', 'h']] }, { "id": 292, "label": 'Duplicate Layer', "shortcut": [['Control', 'Shift', 'd']] }, { "id": 293, "label": 'New from Visible' }, { "id": 294, "label": 'New Layer...', "shortcut": [['Control', 'Shift', 'n']] } ] }, { "id": 295, "children-display": 'submenu', "label": 'Colors', "submenu": [ { "id": 296, "label": 'Retinex...' }, { "id": 297, "label": 'Maximum RGB...' }, { "id": 298, "enabled": false, "label": 'Hot...' }, { "id": 299, "label": 'Filter Pack...' }, { "id": 300, "label": 'Color to Alpha...' }, { "id": 301, "label": 'Colorify...' }, { "id": 302, "type": 'separator' }, { "id": 303, "children-display": 'submenu', "label": 'Info', "submenu": [ { "id": 304, "label": 'Smooth Palette...' }, { "id": 305, "label": 'Colorcube Analysis...' }, { "id": 306, "label": 'Border Average...' }, { "id": 307, "label": 'Histogram' } ] }, { "id": 308, "children-display": 'submenu', "label": 'Map', "submenu": [ { "id": 309, "label": 'Sample Colorize...' }, { "id": 310, "label": 'Rotate Colors...' }, { "id": 311, "label": 'Palette Map' }, { "id": 312, "label": 'Gradient Map' }, { "id": 313, "label": 'Color Exchange...' }, { "id": 314, "label": 'Alien Map...' }, { "id": 315, "type": 'separator' }, { "id": 316, "enabled": false, "label": 'Set Colormap...' }, { "id": 317, "enabled": false, "label": 'Rearrange Colormap...' } ] }, { "id": 318, "children-display": 'submenu', "label": 'Components', "submenu": [ { "id": 319, "enabled": false, "label": 'Recompose' }, { "id": 320, "label": 'Decompose...' }, { "id": 321, "enabled": false, "label": 'Compose...' }, { "id": 322, "label": 'Channel Mixer...' } ] }, { "id": 323, "children-display": 'submenu', "label": 'Auto', "submenu": [ { "id": 324, "label": 'Stretch HSV' }, { "id": 325, "label": 'Stretch Contrast' }, { "id": 326, "label": 'Normalize' }, { "id": 327, "label": 'Color Enhance' }, { "id": 328, "label": 'White Balance' }, { "id": 329, "label": 'Equalize' } ] }, { "id": 330, "type": 'separator' }, { "id": 331, "label": 'Use GEGL', "toggle-state": 0, "toggle-type": 'checkmark' }, { "id": 332, "type": 'separator' }, { "id": 333, "label": 'Value Invert' }, { "id": 334, "label": 'Invert' }, { "id": 335, "type": 'separator' }, { "id": 336, "label": 'Desaturate...' }, { "id": 337, "label": 'Posterize...' }, { "id": 338, "label": 'Curves...' }, { "id": 339, "label": 'Levels...' }, { "id": 340, "label": 'Threshold...' }, { "id": 341, "label": 'Brightness-Contrast...' }, { "id": 342, "label": 'Colorize...' }, { "id": 343, "label": 'Hue-Saturation...' }, { "id": 344, "label": 'Color Balance...' } ] }, { "id": 345, "children-display": 'submenu', "label": 'Tools', "submenu": [ { "id": 346, "label": 'Swap Colors', "shortcut": [['x']] }, { "id": 347, "label": 'Default Colors', "shortcut": [['d']] }, { "id": 348, "label": 'Toolbox', "shortcut": [['Control', 'b']] }, { "id": 349, "type": 'separator' }, { "id": 350, "label": 'GEGL Operation...' }, { "id": 351, "label": 'Text', "shortcut": [['t']] }, { "id": 352, "label": 'Measure', "shortcut": [['Shift', 'm']] }, { "id": 353, "label": 'Zoom', "shortcut": [['z']] }, { "id": 354, "label": 'Color Picker', "shortcut": [['o']] }, { "id": 355, "label": 'Paths', "shortcut": [['b']] }, { "id": 356, "children-display": 'submenu', "label": 'Color Tools', "submenu": [ { "id": 357, "label": 'Desaturate...' }, { "id": 358, "label": 'Posterize...' }, { "id": 359, "label": 'Curves...' }, { "id": 360, "label": 'Levels...' }, { "id": 361, "label": 'Threshold...' }, { "id": 362, "label": 'Brightness-Contrast...' }, { "id": 363, "label": 'Colorize...' }, { "id": 364, "label": 'Hue-Saturation...' }, { "id": 365, "label": 'Color Balance...' } ] }, { "id": 366, "children-display": 'submenu', "label": 'Transform Tools', "submenu": [ { "id": 367, "label": 'Flip', "shortcut": [['Shift', 'f']] }, { "id": 368, "label": 'Perspective', "shortcut": [['Shift', 'p']] }, { "id": 369, "label": 'Shear', "shortcut": [['Shift', 's']] }, { "id": 370, "label": 'Scale', "shortcut": [['Shift', 't']] }, { "id": 371, "label": 'Rotate', "shortcut": [['Shift', 'r']] }, { "id": 372, "label": 'Crop', "shortcut": [['Shift', 'c']] }, { "id": 373, "label": 'Move', "shortcut": [['m']] }, { "id": 374, "label": 'Align', "shortcut": [['q']] } ] }, { "id": 375, "children-display": 'submenu', "label": 'Paint Tools', "submenu": [ { "id": 376, "label": 'Dodge / Burn', "shortcut": [['Shift', 'd']] }, { "id": 377, "label": 'Smudge', "shortcut": [['s']] }, { "id": 378, "label": 'Blur / Sharpen', "shortcut": [['Shift', 'u']] }, { "id": 379, "label": 'Perspective Clone' }, { "id": 380, "label": 'Heal', "shortcut": [['h']] }, { "id": 381, "label": 'Clone', "shortcut": [['c']] }, { "id": 382, "label": 'Ink', "shortcut": [['k']] }, { "id": 383, "label": 'Airbrush', "shortcut": [['a']] }, { "id": 384, "label": 'Eraser', "shortcut": [['Shift', 'e']] }, { "id": 385, "label": 'Paintbrush', "shortcut": [['p']] }, { "id": 386, "label": 'Pencil', "shortcut": [['n']] }, { "id": 387, "label": 'Blend', "shortcut": [['l']] }, { "id": 388, "label": 'Bucket Fill', "shortcut": [['Shift', 'b']] } ] }, { "id": 389, "children-display": 'submenu', "label": 'Selection Tools', "submenu": [ { "id": 390, "label": 'Intelligent Scissors', "shortcut": [['i']] }, { "id": 391, "label": 'By Color Select', "shortcut": [['Shift', 'o']] }, { "id": 392, "label": 'Fuzzy Select', "shortcut": [['u']] }, { "id": 393, "label": 'Foreground Select' }, { "id": 394, "label": 'Free Select', "shortcut": [['f']] }, { "id": 395, "label": 'Ellipse Select', "shortcut": [['e']] }, { "id": 396, "label": 'Rectangle Select', "shortcut": [['r']] } ] } ] }, { "id": 397, "children-display": 'submenu', "label": 'Filters', "submenu": [ { "id": 398, "children-display": 'submenu', "label": 'Script-Fu', "submenu": [ { "id": 399, "label": 'Start Server...' }, { "id": 400, "label": 'Refresh Scripts' }, { "id": 401, "label": 'Console' } ] }, { "id": 402, "children-display": 'submenu', "label": 'Python-Fu', "submenu": [ { "id": 403, "label": 'Console' } ] }, { "id": 404, "type": 'separator' }, { "id": 405, "children-display": 'submenu', "label": 'Alpha to Logo', "submenu": [ { "id": 406, "label": 'Textured...' }, { "id": 407, "label": 'Particle Trace...' }, { "id": 408, "label": 'Neon...' }, { "id": 409, "label": 'Gradient Bevel...' }, { "id": 410, "label": 'Glowing Hot...' }, { "id": 411, "label": 'Glossy...' }, { "id": 412, "label": 'Frosty...' }, { "id": 413, "label": 'Cool Metal...' }, { "id": 414, "label": 'Comic Book...' }, { "id": 415, "label": 'Chrome...' }, { "id": 416, "label": 'Chip Away...' }, { "id": 417, "label": 'Chalk...' }, { "id": 418, "label": 'Bovination...' }, { "id": 419, "label": 'Blended...' }, { "id": 420, "label": 'Basic I...' }, { "id": 421, "label": 'Basic II...' }, { "id": 422, "label": 'Alien Neon...' }, { "id": 423, "label": 'Alien Glow...' }, { "id": 424, "label": '3D Outline...' } ] }, { "id": 425, "type": 'separator' }, { "id": 426, "children-display": 'submenu', "label": 'Animation', "submenu": [ { "id": 427, "label": 'Unoptimize' }, { "id": 428, "label": 'Playback...' }, { "id": 429, "label": 'Optimize (for GIF)' }, { "id": 430, "label": 'Optimize (Difference)' }, { "id": 431, "type": 'separator' }, { "id": 432, "label": 'Waves...' }, { "id": 433, "label": 'Spinning Globe...' }, { "id": 434, "label": 'Rippling...' }, { "id": 435, "label": 'Burn-In...' }, { "id": 436, "label": 'Blend...' } ] }, { "id": 437, "children-display": 'submenu', "label": 'Web', "submenu": [ { "id": 438, "label": 'Slice...' }, { "id": 439, "label": 'Semi-Flatten' }, { "id": 440, "label": 'Image Map...' } ] }, { "id": 441, "children-display": 'submenu', "label": 'Render', "submenu": [ { "id": 442, "label": 'Spyrogimp...' }, { "id": 443, "label": 'Sphere Designer...' }, { "id": 444, "label": 'Line Nova...' }, { "id": 445, "label": 'Lava...' }, { "id": 446, "label": 'Gfig...' }, { "id": 447, "label": 'Fractal Explorer...' }, { "id": 448, "label": 'Circuit...' }, { "id": 449, "type": 'separator' }, { "id": 450, "children-display": 'submenu', "label": 'Pattern', "submenu": [ { "id": 451, "label": 'Sinus...' }, { "id": 452, "label": 'Qbist...' }, { "id": 453, "label": 'Maze...' }, { "id": 454, "label": 'Jigsaw...' }, { "id": 455, "label": 'Grid...' }, { "id": 456, "label": 'Diffraction Patterns...' }, { "id": 457, "label": 'CML Explorer...' }, { "id": 458, "label": 'Checkerboard...' } ] }, { "id": 459, "children-display": 'submenu', "label": 'Nature', "submenu": [ { "id": 460, "label": 'IFS Fractal...' }, { "id": 461, "label": 'Flame...' } ] }, { "id": 462, "children-display": 'submenu', "label": 'Clouds', "submenu": [ { "id": 463, "label": 'Solid Noise...' }, { "id": 464, "label": 'Plasma...' }, { "id": 465, "label": 'Fog...' }, { "id": 466, "label": 'Difference Clouds...' } ] } ] }, { "id": 467, "children-display": 'submenu', "label": 'Map', "submenu": [ { "id": 468, "label": 'Warp...' }, { "id": 469, "label": 'Tile...' }, { "id": 470, "label": 'Small Tiles...' }, { "id": 471, "label": 'Paper Tile...' }, { "id": 472, "label": 'Map Object...' }, { "id": 473, "label": 'Make Seamless' }, { "id": 474, "label": 'Illusion...' }, { "id": 475, "label": 'Fractal Trace...' }, { "id": 476, "label": 'Displace...' }, { "id": 477, "label": 'Bump Map...' } ] }, { "id": 478, "children-display": 'submenu', "label": 'Decor', "submenu": [ { "id": 479, "enabled": false, "label": 'Stencil Chrome...' }, { "id": 480, "enabled": false, "label": 'Stencil Carve...' }, { "id": 481, "enabled": false, "label": 'Slide...' }, { "id": 482, "enabled": false, "label": 'Round Corners...' }, { "id": 483, "label": 'Old Photo...' }, { "id": 484, "label": 'Fuzzy Border...' }, { "id": 485, "label": 'Coffee Stain...' }, { "id": 486, "label": 'Add Border...' }, { "id": 487, "label": 'Add Bevel...' } ] }, { "id": 488, "children-display": 'submenu', "label": 'Artistic', "submenu": [ { "id": 489, "label": 'Weave...' }, { "id": 490, "label": 'Van Gogh (LIC)...' }, { "id": 491, "label": 'Softglow...' }, { "id": 492, "label": 'Predator...' }, { "id": 493, "label": 'Photocopy...' }, { "id": 494, "label": 'Oilify...' }, { "id": 495, "label": 'GIMPressionist...' }, { "id": 496, "label": 'Cubism...' }, { "id": 497, "label": 'Clothify...' }, { "id": 498, "label": 'Cartoon...' }, { "id": 499, "label": 'Apply Canvas...' } ] }, { "id": 500, "children-display": 'submenu', "label": 'Combine', "submenu": [ { "id": 501, "label": 'Filmstrip...' }, { "id": 502, "label": 'Depth Merge...' } ] }, { "id": 503, "children-display": 'submenu', "label": 'Generic', "submenu": [ { "id": 504, "label": 'Erode' }, { "id": 505, "label": 'Dilate' }, { "id": 506, "label": 'Convolution Matrix...' } ] }, { "id": 507, "children-display": 'submenu', "label": 'Edge-Detect', "submenu": [ { "id": 508, "label": 'Sobel...' }, { "id": 509, "label": 'Neon...' }, { "id": 510, "label": 'Laplace' }, { "id": 511, "label": 'Edge...' }, { "id": 512, "label": 'Difference of Gaussians...' } ] }, { "id": 513, "children-display": 'submenu', "label": 'Noise', "submenu": [ { "id": 514, "label": 'Spread...' }, { "id": 515, "label": 'Slur...' }, { "id": 516, "label": 'RGB Noise...' }, { "id": 517, "label": 'Pick...' }, { "id": 518, "label": 'Hurl...' }, { "id": 519, "label": 'HSV Noise...' } ] }, { "id": 520, "children-display": 'submenu', "label": 'Light and Shadow', "submenu": [ { "id": 521, "label": 'Glass Tile...' }, { "id": 522, "label": 'Apply Lens...' }, { "id": 523, "type": 'separator' }, { "id": 524, "label": 'Xach-Effect...' }, { "id": 525, "label": 'Perspective...' }, { "id": 526, "label": 'Drop Shadow...' }, { "id": 527, "type": 'separator' }, { "id": 528, "label": 'Supernova...' }, { "id": 529, "label": 'Sparkle...' }, { "id": 530, "label": 'Lighting Effects...' }, { "id": 531, "label": 'Lens Flare...' }, { "id": 532, "label": 'Gradient Flare...' } ] }, { "id": 533, "children-display": 'submenu', "label": 'Distorts', "submenu": [ { "id": 534, "label": 'Wind...' }, { "id": 535, "label": 'Whirl and Pinch...' }, { "id": 536, "label": 'Waves...' }, { "id": 537, "label": 'Video...' }, { "id": 538, "label": 'Value Propagate...' }, { "id": 539, "label": 'Shift...' }, { "id": 540, "label": 'Ripple...' }, { "id": 541, "label": 'Polar Coordinates...' }, { "id": 542, "label": 'Pagecurl...' }, { "id": 543, "label": 'Newsprint...' }, { "id": 544, "label": 'Mosaic...' }, { "id": 545, "label": 'Lens Distortion...' }, { "id": 546, "label": 'IWarp...' }, { "id": 547, "label": 'Erase Every Other Row...' }, { "id": 548, "label": 'Engrave...' }, { "id": 549, "label": 'Emboss...' }, { "id": 550, "label": 'Curve Bend...' }, { "id": 551, "label": 'Blinds...' } ] }, { "id": 552, "children-display": 'submenu', "label": 'Enhance', "submenu": [ { "id": 553, "label": 'Unsharp Mask...' }, { "id": 554, "label": 'Sharpen...' }, { "id": 555, "label": 'Red Eye Removal...' }, { "id": 556, "enabled": false, "label": 'NL Filter...' }, { "id": 557, "label": 'Destripe...' }, { "id": 558, "label": 'Despeckle...' }, { "id": 559, "label": 'Deinterlace...' }, { "id": 560, "label": 'Antialias' } ] }, { "id": 561, "children-display": 'submenu', "label": 'Blur', "submenu": [ { "id": 562, "label": 'Tileable Blur...' }, { "id": 563, "label": 'Selective Gaussian Blur...' }, { "id": 564, "label": 'Pixelize...' }, { "id": 565, "label": 'Motion Blur...' }, { "id": 566, "label": 'Gaussian Blur...' }, { "id": 567, "label": 'Blur' } ] }, { "id": 568, "type": 'separator' }, { "id": 569, "label": 'Reset all Filters' }, { "id": 570, "children-display": 'submenu', "enabled": false, "label": 'Re-Show Last', "shortcut": [['Control', 'Shift', 'f']], "submenu": [ { "id": 571, "enabled": false, "label": 'Empty' } ] }, { "id": 572, "enabled": false, "label": 'Repeat Last', "shortcut": [['Control', 'f']] } ] }, { "id": 573, "children-display": 'submenu', "label": 'Windows', "submenu": [ { "id": 574, "label": 'Toolbox', "shortcut": [['Control', 'b']] }, { "id": 575, "type": 'separator' }, { "id": 576, "children-display": 'submenu', "label": 'Dockable Dialogs', "submenu": [ { "id": 577, "label": 'Error Console' }, { "id": 578, "label": 'Tools' }, { "id": 579, "label": 'Templates' }, { "id": 580, "label": 'Document History' }, { "id": 581, "label": 'Images' }, { "id": 582, "type": 'separator' }, { "id": 583, "label": 'Buffers' }, { "id": 584, "label": 'Fonts' }, { "id": 585, "label": 'Palettes' }, { "id": 586, "label": 'Gradients', "shortcut": [['Control', 'g']] }, { "id": 587, "label": 'Patterns', "shortcut": [['Control', 'Shift', 'p']] }, { "id": 588, "label": 'Brushes', "shortcut": [['Control', 'Shift', 'b']] }, { "id": 589, "label": 'Colors' }, { "id": 590, "type": 'separator' }, { "id": 591, "label": 'Sample Points' }, { "id": 592, "label": 'Pointer' }, { "id": 593, "label": 'Undo History' }, { "id": 594, "label": 'Navigation' }, { "id": 595, "label": 'Selection Editor' }, { "id": 596, "label": 'Histogram' }, { "id": 597, "label": 'Colormap' }, { "id": 598, "label": 'Paths' }, { "id": 599, "label": 'Channels' }, { "id": 600, "label": 'Layers', "shortcut": [['Control', 'l']] }, { "id": 601, "type": 'separator' }, { "id": 602, "label": 'Device Status' }, { "id": 603, "label": 'Tool Options' } ] }, { "id": 604, "children-display": 'submenu', "label": 'Recently Closed Docks', "submenu": [ { "id": 605, "enabled": false, "label": 'Empty' } ] } ] }, { "id": 606, "children-display": 'submenu', "label": 'Help', "submenu": [ { "id": 607, "children-display": 'submenu', "label": 'User Manual', "submenu": [ { "id": 608, "label": 'Working with Digital Camera Photos' }, { "id": 609, "label": 'Using Paths' }, { "id": 610, "label": 'Preparing your Images for the Web' }, { "id": 611, "label": 'How to Use Dialogs' }, { "id": 612, "label": 'Drawing Simple Objects' }, { "id": 613, "label": 'Create, Open and Save Files' }, { "id": 614, "label": 'Basic Concepts' } ] }, { "id": 615, "children-display": 'submenu', "label": 'GIMP Online', "submenu": [ { "id": 616, "label": 'User Manual Web Site' }, { "id": 617, "label": 'Plug-in Registry' }, { "id": 618, "label": 'Main Web Site' }, { "id": 619, "label": 'Developer Web Site' } ] }, { "id": 620, "type": 'separator' }, { "id": 621, "label": 'Procedure Browser' }, { "id": 622, "label": 'Plug-In Browser' }, { "id": 623, "type": 'separator' }, { "id": 624, "label": 'About' }, { "id": 625, "label": 'Tip of the Day' }, { "id": 626, "label": 'Context Help', "shortcut": [['Shift', 'F1']] }, { "id": 627, "label": 'Help', "shortcut": [['F1']] } ] } ] } hud-14.04+14.04.20140604/tests/data/test-app-indicator-source-one.json0000644000015301777760000000033712343623451025440 0ustar pbusernogroup00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Hello There' }, { "id": 2, "label": 'Goodbye' }, { "id": 3, "label": 'Hallo Again' } ] }hud-14.04+14.04.20140604/tests/data/test-indicator-source-datetime.json0000644000015301777760000000032112343623451025666 0ustar pbusernogroup00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Date Time' }, { "id": 2, "label": 'foo' }, { "id": 3, "label": 'zzz' } ] }hud-14.04+14.04.20140604/tests/data/test-indicator-source-session.json0000644000015301777760000000032412343623451025560 0ustar pbusernogroup00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Session Time' }, { "id": 2, "label": 'bar' }, { "id": 3, "label": 'xxx' } ] }hud-14.04+14.04.20140604/tests/data/test-source.json0000644000015301777760000000175712343623451022140 0ustar pbusernogroup00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'link', "submenu": [ { "id": 2, "label": 'bowl' }, { "id": 3, "label": 'mine let' } ] }, { "id": 4, "label": 'dare', "submenu": [ { "id": 5, "label": 'mess strand' } ] }, { "id": 6, "label": 'piece hook', "submenu": [ { "id": 7, "label": 'stray slash' }, { "id": 8, "label": 'swift sad' } ] }, { "id": 9, "label": 'spaghetti', "submenu": [ { "id": 10, "label": 'itch step' }, { "id": 11, "label": 'any rash' } ] } ] }hud-14.04+14.04.20140604/tests/data/test-app-indicator-source-two.json0000644000015301777760000000034512343623451025467 0ustar pbusernogroup00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Hello There 2' }, { "id": 2, "label": 'Goodbye 2' }, { "id": 3, "label": 'Hallo Again 2' } ] }hud-14.04+14.04.20140604/tests/unit/0000755000015301777760000000000012343624372017027 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/unit/window-stack-bridge/0000755000015301777760000000000012343624372022673 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/unit/window-stack-bridge/CMakeLists.txt0000644000015301777760000000114212343623451025426 0ustar pbusernogroup00000000000000 if(${ENABLE_BAMF} OR ${ENABLE_PLATFORM_API}) if(${ENABLE_BAMF}) list(APPEND UNIT_TESTS_SRC TestBamfWindowStack.cpp) endif() if(${ENABLE_PLATFORM_API}) list(APPEND UNIT_TESTS_SRC TestPlatformApiWindowStack.cpp) endif() add_executable( test-window-stack-bridge-unit-tests ${UNIT_TESTS_SRC} ) target_link_libraries( test-window-stack-bridge-unit-tests test-utils window-stack-bridge ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} ${QTDBUSTEST_LIBRARIES} ${QTDBUSMOCK_LIBRARIES} ) qt5_use_modules( test-window-stack-bridge-unit-tests Test ) add_hud_test( test-window-stack-bridge-unit-tests ) endif() hud-14.04+14.04.20140604/tests/unit/window-stack-bridge/TestBamfWindowStack.cpp0000644000015301777760000002665112343623451027271 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include using namespace std; using namespace testing; using namespace hud::common; using namespace QtDBusTest; using namespace QtDBusMock; namespace { class TestBamfWindowStack: public Test { protected: TestBamfWindowStack() : mock(dbus) { mock.registerCustomMock(DBusTypes::BAMF_DBUS_NAME, DBusTypes::BAMF_MATCHER_DBUS_PATH, OrgAyatanaBamfMatcherInterface::staticInterfaceName(), QDBusConnection::SessionBus); dbus.startServices(); } virtual ~TestBamfWindowStack() { } OrgFreedesktopDBusMockInterface & bamfMatcherMock() { return mock.mockInterface(DBusTypes::BAMF_DBUS_NAME, DBusTypes::BAMF_MATCHER_DBUS_PATH, OrgAyatanaBamfMatcherInterface::staticInterfaceName(), QDBusConnection::SessionBus); } OrgFreedesktopDBusMockInterface & windowMock(uint id) { return mock.mockInterface(DBusTypes::BAMF_DBUS_NAME, windowPath(id), OrgAyatanaBamfWindowInterface::staticInterfaceName(), QDBusConnection::SessionBus); } static void addMethod(QList &methods, const QString &name, const QString &inSig, const QString &outSig, const QString &code) { Method method; method.setName(name); method.setInSig(inSig); method.setOutSig(outSig); method.setCode(code); methods << method; } static QString applicationPath(uint id) { return QString("/org/ayatana/bamf/application%1").arg(id); } static QString windowPath(uint id) { return QString("/org/ayatana/bamf/window%1").arg(id); } void createApplication(uint applicationId) { QVariantMap properties; QList methods; addMethod(methods, "DesktopFile", "", "s", QString("ret = '/usr/share/applications/appid-%1.desktop'").arg( applicationId)); bamfMatcherMock().AddObject(applicationPath(applicationId), OrgAyatanaBamfApplicationInterface::staticInterfaceName(), properties, methods).waitForFinished(); } void createWindow(uint windowId, uint applicationId, bool propertyMethod = true) { QVariantMap properties; QList methods; addMethod(methods, "GetXid", "", "u", QString("ret = %1").arg(windowId)); if (propertyMethod) { addMethod(methods, "Xprop", "s", "s", "ret = 'foo'"); } bamfMatcherMock().AddObject(windowPath(windowId), OrgAyatanaBamfWindowInterface::staticInterfaceName(), properties, methods).waitForFinished(); QList viewMethods; addMethod(viewMethods, "Parents", "", "as", QString("ret = ['%1']").arg(applicationPath(applicationId))); windowMock(windowId).AddMethods("org.ayatana.bamf.view", viewMethods).waitForFinished(); } void createMatcherMethods(uint windowCount, uint activeWindow) { bamfMatcherMock().AddMethod( OrgAyatanaBamfMatcherInterface::staticInterfaceName(), "ActiveWindow", "", "s", QString("ret = '%1'").arg(windowPath(activeWindow))).waitForFinished(); QString windowStack("ret = ["); if (windowCount > 0) { windowStack.append(QString("'%1'").arg(windowPath(activeWindow))); for (uint i(0); i < windowCount; ++i) { if (i != activeWindow) { windowStack.append(",\'"); windowStack.append(windowPath(i)); windowStack.append('\''); } } } windowStack.append(']'); bamfMatcherMock().AddMethod( OrgAyatanaBamfMatcherInterface::staticInterfaceName(), "WindowPaths", "", "as", windowStack).waitForFinished(); bamfMatcherMock().AddMethod( OrgAyatanaBamfMatcherInterface::staticInterfaceName(), "WindowStackForMonitor", "i", "as", windowStack).waitForFinished(); } void windowChanged(const QString &oldPath, const QString &newPath) { bamfMatcherMock().EmitSignal( OrgAyatanaBamfMatcherInterface::staticInterfaceName(), "ActiveWindowChanged", "ss", QVariantList() << oldPath << ""); bamfMatcherMock().EmitSignal( OrgAyatanaBamfMatcherInterface::staticInterfaceName(), "ActiveWindowChanged", "ss", QVariantList() << "" << newPath); } void windowClosed(const QString &closedPath, const QString &newPath) { bamfMatcherMock().EmitSignal( OrgAyatanaBamfMatcherInterface::staticInterfaceName(), "ActiveWindowChanged", "ss", QVariantList() << closedPath << newPath); bamfMatcherMock().EmitSignal( OrgAyatanaBamfMatcherInterface::staticInterfaceName(), "ViewClosed", "ss", QVariantList() << closedPath << "window"); } void windowOpened(const QString &oldPath, const QString &openedPath) { bamfMatcherMock().EmitSignal( OrgAyatanaBamfMatcherInterface::staticInterfaceName(), "ViewOpened", "ss", QVariantList() << openedPath << "window"); bamfMatcherMock().EmitSignal( OrgAyatanaBamfMatcherInterface::staticInterfaceName(), "ActiveWindowChanged", "ss", QVariantList() << oldPath << openedPath); } DBusTestRunner dbus; DBusMock mock; }; TEST_F(TestBamfWindowStack, ExportsDBusInterface) { bamfMatcherMock().AddMethod( OrgAyatanaBamfMatcherInterface::staticInterfaceName(), "WindowPaths", "", "as", "ret = []").waitForFinished(); BamfWindowStack windowStack(dbus.sessionConnection()); ComCanonicalUnityWindowStackInterface windowStackInterface( DBusTypes::WINDOW_STACK_DBUS_NAME, DBusTypes::WINDOW_STACK_DBUS_PATH, dbus.sessionConnection()); ASSERT_TRUE(windowStackInterface.isValid()); } TEST_F(TestBamfWindowStack, HandlesEmptyWindowStack) { createMatcherMethods(0, 0); BamfWindowStack windowStack(dbus.sessionConnection()); QList windowInfos(windowStack.GetWindowStack()); EXPECT_TRUE(windowInfos.empty()); } TEST_F(TestBamfWindowStack, OverDBus) { createApplication(0); createWindow(0, 0); createWindow(1, 0); createMatcherMethods(2, 0); BamfWindowStack windowStack(dbus.sessionConnection()); ComCanonicalUnityWindowStackInterface windowStackInterface( DBusTypes::WINDOW_STACK_DBUS_NAME, DBusTypes::WINDOW_STACK_DBUS_PATH, dbus.sessionConnection()); QDBusPendingReply reply( windowStackInterface.GetWindowStack()); QDBusPendingCallWatcher watcher(reply); QSignalSpy spy(&watcher, SIGNAL(finished(QDBusPendingCallWatcher *))); spy.wait(); EXPECT_FALSE(spy.isEmpty()); QList windowInfos(reply); ASSERT_EQ(2, windowInfos.size()); EXPECT_EQ(WindowInfo(0, "appid-0", true, WindowInfo::MAIN), windowInfos.at(0)); EXPECT_EQ(WindowInfo(1, "appid-0", false, WindowInfo::MAIN), windowInfos.at(1)); } TEST_F(TestBamfWindowStack, HandlesTwoWindows) { createApplication(0); createWindow(0, 0); createWindow(1, 0); createMatcherMethods(2, 0); BamfWindowStack windowStack(dbus.sessionConnection()); QList windowInfos(windowStack.GetWindowStack()); ASSERT_EQ(2, windowInfos.size()); EXPECT_EQ(WindowInfo(0, "appid-0", true, WindowInfo::MAIN), windowInfos.at(0)); EXPECT_EQ(WindowInfo(1, "appid-0", false, WindowInfo::MAIN), windowInfos.at(1)); } TEST_F(TestBamfWindowStack, HandlesMissingWindow) { createMatcherMethods(1, 0); qDebug() << "EXPECTED ERROR BELOW"; BamfWindowStack windowStack(dbus.sessionConnection()); qDebug() << "EXPECTED ERROR ABOVE"; QList windowInfos(windowStack.GetWindowStack()); ASSERT_EQ(0, windowInfos.size()); } TEST_F(TestBamfWindowStack, GetWindowPropertiesForBrokenWindow) { createWindow(0, 0, false); createApplication(0); createMatcherMethods(1, 0); BamfWindowStack windowStack(dbus.sessionConnection()); qDebug() << "EXPECTED ERROR BELOW"; QStringList properties( windowStack.GetWindowProperties(0, "unknown", QStringList() << "some-random-property")); qDebug() << "EXPECTED ERROR ABOVE"; ASSERT_EQ(QStringList() << "", properties); } TEST_F(TestBamfWindowStack, HandlesTwoApplications) { // app 0 createApplication(0); createWindow(0, 0); createWindow(1, 0); createWindow(2, 0); // app 1 createApplication(1); createWindow(3, 1); createWindow(4, 1); createMatcherMethods(5, 0); BamfWindowStack windowStack(dbus.sessionConnection()); QList windowInfos(windowStack.GetWindowStack()); ASSERT_EQ(5, windowInfos.size()); EXPECT_EQ(WindowInfo(0, "appid-0", true, WindowInfo::MAIN), windowInfos.at(0)); EXPECT_EQ(WindowInfo(1, "appid-0", false, WindowInfo::MAIN), windowInfos.at(1)); EXPECT_EQ(WindowInfo(2, "appid-0", false, WindowInfo::MAIN), windowInfos.at(2)); EXPECT_EQ(WindowInfo(3, "appid-1", false, WindowInfo::MAIN), windowInfos.at(3)); EXPECT_EQ(WindowInfo(4, "appid-1", false, WindowInfo::MAIN), windowInfos.at(4)); } TEST_F(TestBamfWindowStack, FocusedWindowChanged) { // app 0 createApplication(0); createWindow(0, 0); createWindow(1, 0); createWindow(2, 0); // app 1 createApplication(1); createWindow(3, 1); createWindow(4, 1); createMatcherMethods(5, 3); BamfWindowStack windowStack(dbus.sessionConnection()); QSignalSpy windowChangedSpy(&windowStack, SIGNAL(FocusedWindowChanged(uint, const QString &, uint))); windowChanged(windowPath(0), windowPath(3)); windowChangedSpy.wait(); ASSERT_EQ(1, windowChangedSpy.size()); EXPECT_EQ(QVariantList() << uint(3) << "appid-1" << uint(0), windowChangedSpy.at(0)); { QList windowInfos(windowStack.GetWindowStack()); ASSERT_EQ(5, windowInfos.size()); EXPECT_EQ(WindowInfo(3, "appid-1", true, WindowInfo::MAIN), windowInfos.at(0)); EXPECT_EQ(WindowInfo(0, "appid-0", false, WindowInfo::MAIN), windowInfos.at(1)); EXPECT_EQ(WindowInfo(1, "appid-0", false, WindowInfo::MAIN), windowInfos.at(2)); EXPECT_EQ(WindowInfo(2, "appid-0", false, WindowInfo::MAIN), windowInfos.at(3)); EXPECT_EQ(WindowInfo(4, "appid-1", false, WindowInfo::MAIN), windowInfos.at(4)); } } TEST_F(TestBamfWindowStack, WindowDestroyed) { // app 0 createApplication(0); createWindow(0, 0); createWindow(1, 0); createWindow(2, 0); // app 1 createApplication(1); createWindow(3, 1); createWindow(4, 1); createMatcherMethods(5, 4); BamfWindowStack windowStack(dbus.sessionConnection()); QSignalSpy windowDestroyedSpy(&windowStack, SIGNAL(WindowDestroyed(uint, const QString &))); windowClosed(windowPath(4), windowPath(0)); windowDestroyedSpy.wait(); ASSERT_EQ(1, windowDestroyedSpy.size()); EXPECT_EQ(QVariantList() << uint(4) << "appid-1", windowDestroyedSpy.at(0)); } TEST_F(TestBamfWindowStack, WindowCreated) { // app 0 createApplication(0); createWindow(0, 0); createWindow(1, 0); createWindow(2, 0); // app 1 createApplication(1); createWindow(3, 1); createWindow(4, 1); createMatcherMethods(5, 4); BamfWindowStack windowStack(dbus.sessionConnection()); QSignalSpy windowCreatedSpy(&windowStack, SIGNAL(WindowCreated(uint, const QString &))); createWindow(5, 1); windowOpened(windowPath(4), windowPath(5)); windowCreatedSpy.wait(); ASSERT_EQ(1, windowCreatedSpy.size()); EXPECT_EQ(QVariantList() << uint(5) << "appid-1", windowCreatedSpy.at(0)); } } // namespace hud-14.04+14.04.20140604/tests/unit/window-stack-bridge/TestPlatformApiWindowStack.cpp0000644000015301777760000000254712343623451030640 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include using namespace std; using namespace testing; using namespace hud::common; using namespace QtDBusTest; using namespace QtDBusMock; namespace { class TestPlatformApiWindowStack: public Test { protected: TestPlatformApiWindowStack() : mock(dbus) { } virtual ~TestPlatformApiWindowStack() { } DBusTestRunner dbus; DBusMock mock; }; TEST_F(TestPlatformApiWindowStack, ExportsDBusInterface) { } } // namespace hud-14.04+14.04.20140604/tests/unit/service/0000755000015301777760000000000012343624372020467 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/unit/service/TestApplicationList.cpp0000644000015301777760000002105012343623451025125 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include #include using namespace std; using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::service; using namespace hud::service::test; namespace { class TestApplicationList: public Test { protected: TestApplicationList() : mock(dbus) { factory.setSessionBus(dbus.sessionConnection()); mock.registerCustomMock(DBusTypes::WINDOW_STACK_DBUS_NAME, DBusTypes::WINDOW_STACK_DBUS_PATH, ComCanonicalUnityWindowStackInterface::staticInterfaceName(), QDBusConnection::SessionBus); dbus.startServices(); windowStack.reset( new ComCanonicalUnityWindowStackInterface( DBusTypes::WINDOW_STACK_DBUS_NAME, DBusTypes::WINDOW_STACK_DBUS_PATH, dbus.sessionConnection())); windowStackWatcher.reset( new QDBusServiceWatcher(DBusTypes::WINDOW_STACK_DBUS_NAME, dbus.sessionConnection(), QDBusServiceWatcher::WatchForUnregistration)); } virtual ~TestApplicationList() { } virtual OrgFreedesktopDBusMockInterface & windowStackMock() { return mock.mockInterface(DBusTypes::WINDOW_STACK_DBUS_NAME, DBusTypes::WINDOW_STACK_DBUS_PATH, ComCanonicalUnityWindowStackInterface::staticInterfaceName(), QDBusConnection::SessionBus); } DBusTestRunner dbus; DBusMock mock; NiceMock factory; QSharedPointer windowStack; QSharedPointer windowStackWatcher; }; TEST_F(TestApplicationList, CreatesSingleApplicationOnStartup) { windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = [(0, 'app0', True, 0)]").waitForFinished(); QSharedPointer application( new NiceMock()); QDBusObjectPath path(QDBusObjectPath("/path/app/0")); ON_CALL(*application, path()).WillByDefault(ReturnRef(path)); EXPECT_CALL(*application, addWindow(0)); EXPECT_CALL(factory, newApplication(QString("app0"))).WillOnce( Return(application)); ApplicationListImpl applicationList(factory, windowStack, windowStackWatcher); ASSERT_EQ(1, applicationList.applications().size()); EXPECT_EQ(NameObject("app0", path), applicationList.applications().at(0)); } TEST_F(TestApplicationList, CreatesSingleApplicationWithMultipleWindowsOnStartup) { windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = [(0, 'app0', True, 0), (1, 'app0', False, 0)]").waitForFinished(); QSharedPointer application( new NiceMock()); QDBusObjectPath path(QDBusObjectPath("/path/app/0")); ON_CALL(*application, path()).WillByDefault(ReturnRef(path)); EXPECT_CALL(*application, addWindow(0)); EXPECT_CALL(*application, addWindow(1)); EXPECT_CALL(factory, newApplication(QString("app0"))).WillOnce( Return(application)); ApplicationListImpl applicationList(factory, windowStack, windowStackWatcher); ASSERT_EQ(1, applicationList.applications().size()); EXPECT_EQ(NameObject("app0", path), applicationList.applications().at(0)); } TEST_F(TestApplicationList, CreatesMultipleApplicationOnStartup) { windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = [(123, 'app0', True, 0), (456, 'app1', False, 0)]").waitForFinished(); QSharedPointer application0( new NiceMock()); QDBusObjectPath path0(QDBusObjectPath("/path/app/0")); ON_CALL(*application0, path()).WillByDefault(ReturnRef(path0)); EXPECT_CALL(*application0, addWindow(123)); QSharedPointer application1( new NiceMock()); QDBusObjectPath path1(QDBusObjectPath("/path/app/1")); ON_CALL(*application1, path()).WillByDefault(ReturnRef(path1)); EXPECT_CALL(*application1, addWindow(456)); EXPECT_CALL(factory, newApplication(QString("app0"))).WillOnce( Return(application0)); EXPECT_CALL(factory, newApplication(QString("app1"))).WillOnce( Return(application1)); ApplicationListImpl applicationList(factory, windowStack, windowStackWatcher); QList applications = applicationList.applications(); ASSERT_EQ(2, applications.size()); EXPECT_EQ(NameObject("app0", path0), applications.at(0)); EXPECT_EQ(NameObject("app1", path1), applications.at(1)); } TEST_F(TestApplicationList, RemovesApplicationWhenAllWindowsClosed) { windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = [(0, 'app0', True, 0), (1, 'app0', False, 0)]").waitForFinished(); QSharedPointer application( new NiceMock()); QDBusObjectPath path(QDBusObjectPath("/path/app/0")); ON_CALL(*application, path()).WillByDefault(ReturnRef(path)); ON_CALL(*application, isEmpty()).WillByDefault(Return(false)); EXPECT_CALL(factory, newApplication(QString("app0"))).WillOnce( Return(application)); EXPECT_CALL(*application, addWindow(0)); EXPECT_CALL(*application, addWindow(1)); ApplicationListImpl applicationList(factory, windowStack, windowStackWatcher); ASSERT_EQ(1, applicationList.applications().size()); EXPECT_EQ(NameObject("app0", path), applicationList.applications().at(0)); EXPECT_CALL(*application, removeWindow(1)); applicationList.WindowDestroyed(1, "app0"); ASSERT_EQ(1, applicationList.applications().size()); EXPECT_EQ(NameObject("app0", path), applicationList.applications().at(0)); ON_CALL(*application, isEmpty()).WillByDefault(Return(true)); EXPECT_CALL(*application, removeWindow(0)); applicationList.WindowDestroyed(0, "app0"); ASSERT_TRUE(applicationList.applications().isEmpty()); } TEST_F(TestApplicationList, StartsEmptyThenAddsAndRemovesApplications) { windowStackMock().AddMethod(DBusTypes::WINDOW_STACK_DBUS_NAME, "GetWindowStack", "", "a(usbu)", "ret = []").waitForFinished(); QSharedPointer application0( new NiceMock()); QDBusObjectPath path0(QDBusObjectPath("/path/app/0")); ON_CALL(*application0, path()).WillByDefault(ReturnRef(path0)); ON_CALL(*application0, isEmpty()).WillByDefault(Return(false)); QSharedPointer application1( new NiceMock()); QDBusObjectPath path1(QDBusObjectPath("/path/app/1")); ON_CALL(*application1, path()).WillByDefault(ReturnRef(path1)); ON_CALL(*application1, isEmpty()).WillByDefault(Return(false)); ApplicationListImpl applicationList(factory, windowStack, windowStackWatcher); ASSERT_TRUE(applicationList.applications().isEmpty()); EXPECT_CALL(factory, newApplication(QString("app0"))).WillOnce( Return(application0)); EXPECT_CALL(*application0, addWindow(123)); applicationList.WindowCreated(123, "app0"); ASSERT_EQ(1, applicationList.applications().size()); EXPECT_EQ(NameObject("app0", path0), applicationList.applications().at(0)); EXPECT_CALL(factory, newApplication(QString("app1"))).WillOnce( Return(application1)); EXPECT_CALL(*application1, addWindow(456)); applicationList.WindowCreated(456, "app1"); ASSERT_EQ(2, applicationList.applications().size()); EXPECT_EQ(NameObject("app0", path0), applicationList.applications().at(0)); EXPECT_EQ(NameObject("app1", path1), applicationList.applications().at(1)); ON_CALL(*application1, isEmpty()).WillByDefault(Return(true)); EXPECT_CALL(*application1, removeWindow(456)); applicationList.WindowDestroyed(456, "app1"); ASSERT_EQ(1, applicationList.applications().size()); EXPECT_EQ(NameObject("app0", path0), applicationList.applications().at(0)); ON_CALL(*application0, isEmpty()).WillByDefault(Return(true)); EXPECT_CALL(*application0, removeWindow(123)); applicationList.WindowDestroyed(123, "app0"); ASSERT_TRUE(applicationList.applications().isEmpty()); } } // namespace hud-14.04+14.04.20140604/tests/unit/service/TestQuery.cpp0000644000015301777760000001357512343623451023150 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include #include using namespace std; using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::service; using namespace hud::service::test; namespace { class TestQuery: public QObject, public Test { Q_OBJECT protected: TestQuery() : mock(dbus) { windowToken.reset(new NiceMock()); ON_CALL(*windowToken, toolbarItems()).WillByDefault( Return(QStringList())); ON_CALL(*windowToken, commands()).WillByDefault( Return( QList() << (QStringList() << "command1" << "command2"))); window.reset(new NiceMock()); ON_CALL(*window, activate()).WillByDefault(Return(windowToken)); application.reset(new NiceMock()); appId = "app-id"; appIcon = "app-icon"; ON_CALL(*application, id()).WillByDefault(ReturnRef(appId)); ON_CALL(*application, icon()).WillByDefault(ReturnRef(appIcon)); applicationList.reset(new NiceMock()); ON_CALL(*applicationList, focusedApplication()).WillByDefault( Return(application)); ON_CALL(*applicationList, focusedWindow()).WillByDefault( Return(window)); voice.reset(new NiceMock()); hudService.reset(new NiceMock); } virtual ~TestQuery() { } Q_SIGNALS: void queryClosed(const QDBusObjectPath &path); protected: DBusTestRunner dbus; DBusMock mock; QString appId; QString appIcon; QSharedPointer hudService; QSharedPointer voice; QSharedPointer applicationList; QSharedPointer application; QSharedPointer window; QSharedPointer windowToken; }; TEST_F(TestQuery, Create) { QList expectedResults; expectedResults << Result(0, "command name", Result::HighlightList() << Result::Highlight(0, 1), "description field", Result::HighlightList() << Result::Highlight(2, 3), "shortcut field", 100, false); QString queryString("query"); EXPECT_CALL(*window, activate()).WillOnce(Return(windowToken)); EXPECT_CALL(*windowToken, search(queryString, Query::EmptyBehaviour::SHOW_SUGGESTIONS, _)).WillOnce( Invoke( [&expectedResults](const QString &, Query::EmptyBehaviour, QList &results) { results.append(expectedResults); })); QueryImpl query(0, queryString, "keep.alive", Query::EmptyBehaviour::SHOW_SUGGESTIONS, *hudService, applicationList, voice, dbus.sessionConnection()); const QList results(query.results()); ASSERT_EQ(expectedResults.size(), results.size()); ASSERT_EQ(expectedResults.at(0).id(), results.at(0).id()); ASSERT_EQ(expectedResults.at(0).commandName(), results.at(0).commandName()); ASSERT_EQ(expectedResults.at(0).description(), results.at(0).description()); } TEST_F(TestQuery, ExecuteCommand) { QueryImpl query(0, "query", "keep.alive", Query::EmptyBehaviour::SHOW_SUGGESTIONS, *hudService, applicationList, voice, dbus.sessionConnection()); EXPECT_CALL(*windowToken, execute(123)); query.ExecuteCommand(QDBusVariant(123), 12345); } TEST_F(TestQuery, CloseWhenSenderDies) { // a random dbus service that we're going to tell the query to watch QScopedPointer keepAliveService( new QProcessDBusService("keep.alive", QDBusConnection::SessionBus, MODEL_SIMPLE, QStringList() << "keep.alive" << "/")); keepAliveService->start(dbus.sessionConnection()); Query::Ptr query( new QueryImpl(0, "query", "keep.alive", Query::EmptyBehaviour::SHOW_SUGGESTIONS, *hudService, applicationList, voice, dbus.sessionConnection())); EXPECT_CALL(*hudService, closeQuery(query->path())).WillOnce( Invoke([this, query](const QDBusObjectPath &path) { this->queryClosed(path); return query; })); QSignalSpy queryClosedSpy(this, SIGNAL(queryClosed(const QDBusObjectPath &))); // kill the service the query should be watching keepAliveService.reset(); // wait for the query to request close queryClosedSpy.wait(); // check that it tried to closed itself using the HudService interface ASSERT_EQ(1, queryClosedSpy.size()); EXPECT_EQ(query->path(), queryClosedSpy.at(0).at(0).value()); } TEST_F(TestQuery, VoiceQuery) { QueryImpl query(0, "query", "keep.alive", Query::EmptyBehaviour::SHOW_SUGGESTIONS, *hudService, applicationList, voice, dbus.sessionConnection()); EXPECT_CALL(*voice, listen(QList() << (QStringList() << "command1" << "command2"))).WillOnce( Return("voice query")); // call VoiceQuery while MockWindow appears focused QString voiceQuery; query.VoiceQuery(voiceQuery); EXPECT_EQ("voice query", voiceQuery.toStdString()); // return null when focusedWindow() is requested EXPECT_CALL(*applicationList, focusedWindow()).WillOnce( Return(Window::Ptr())); // call VoiceQuery again with no window focused voiceQuery = ""; query.VoiceQuery(voiceQuery); EXPECT_EQ("", voiceQuery.toStdString()); } } // namespace #include "TestQuery.moc" hud-14.04+14.04.20140604/tests/unit/service/TestWindow.cpp0000644000015301777760000002231412343623451023301 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include using namespace std; using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::service; using namespace hud::service::test; namespace { class TestWindow: public Test { protected: TestWindow() : mock(dbus) { factory.setSessionBus(dbus.sessionConnection()); usageTracker.reset(new NiceMock()); ON_CALL(factory, singletonUsageTracker()).WillByDefault( Return(usageTracker)); allWindowsContext.reset(new NiceMock()); ON_CALL(*allWindowsContext, activeCollector()).WillByDefault( Return(Collector::Ptr())); allWindowsCollector.reset(new NiceMock()); ON_CALL(*allWindowsCollector, isValid()).WillByDefault(Return(true)); dbusMenuCollector.reset(new NiceMock()); ON_CALL(*dbusMenuCollector, isValid()).WillByDefault(Return(true)); gmenuWindowCollector.reset(new NiceMock()); ON_CALL(*gmenuWindowCollector, isValid()).WillByDefault(Return(true)); windowCollector.reset(new NiceMock()); ON_CALL(*windowCollector, isValid()).WillByDefault(Return(true)); } virtual ~TestWindow() { } Window::Ptr createWindow() { EXPECT_CALL(factory, newDBusMenuCollector(1234, QString("application-id"))).Times( 1).WillOnce(Return(dbusMenuCollector)); EXPECT_CALL(factory, newGMenuWindowCollector(1234, QString("application-id"))).Times( 1).WillOnce(Return(gmenuWindowCollector)); return Window::Ptr( new WindowImpl(1234, "application-id", allWindowsContext, factory)); } DBusTestRunner dbus; DBusMock mock; NiceMock factory; QSharedPointer usageTracker; QSharedPointer allWindowsContext; shared_ptr allWindowsCollector; shared_ptr dbusMenuCollector; shared_ptr gmenuWindowCollector; shared_ptr windowCollector; }; TEST_F(TestWindow, TrysDBusMenuAndGMenu) { createWindow(); } TEST_F(TestWindow, ActivateOnlyWithDBusMenu) { Window::Ptr window(createWindow()); ON_CALL(*gmenuWindowCollector, isValid()).WillByDefault(Return(false)); ON_CALL(*allWindowsCollector, isValid()).WillByDefault(Return(false)); ON_CALL(*windowCollector, isValid()).WillByDefault(Return(false)); QMenu dbusMenuCollectorMenu; CollectorToken::Ptr dbusMenuCollectorToken( new CollectorToken(dbusMenuCollector, &dbusMenuCollectorMenu)); EXPECT_CALL(*dbusMenuCollector, activate()).Times(1).WillOnce( Return(QList() << dbusMenuCollectorToken)); WindowToken::Ptr token(window->activate()); EXPECT_EQ(QList() << dbusMenuCollectorToken, token->tokens()); } TEST_F(TestWindow, ActivateOnlyWithGMenu) { Window::Ptr window(createWindow()); ON_CALL(*dbusMenuCollector, isValid()).WillByDefault(Return(false)); ON_CALL(*allWindowsCollector, isValid()).WillByDefault(Return(false)); ON_CALL(*windowCollector, isValid()).WillByDefault(Return(false)); QMenu gmenuWindowCollectorMenu; CollectorToken::Ptr gmenuWindowCollectorToken( new CollectorToken(gmenuWindowCollector, &gmenuWindowCollectorMenu)); EXPECT_CALL(*gmenuWindowCollector, activate()).Times(1).WillOnce( Return(QList() << gmenuWindowCollectorToken)); WindowToken::Ptr token(window->activate()); EXPECT_EQ(QList() << gmenuWindowCollectorToken, token->tokens()); } TEST_F(TestWindow, ActivateOnlyWithValidAllWindowsContext) { Window::Ptr window(createWindow()); ON_CALL(*dbusMenuCollector, isValid()).WillByDefault(Return(false)); ON_CALL(*gmenuWindowCollector, isValid()).WillByDefault(Return(false)); ON_CALL(*windowCollector, isValid()).WillByDefault(Return(false)); QMenu allWindowsCollectorMenu; CollectorToken::Ptr allWindowsCollectorToken( new CollectorToken(allWindowsCollector, &allWindowsCollectorMenu)); EXPECT_CALL(*allWindowsCollector, activate()).Times(1).WillOnce( Return(QList() << allWindowsCollectorToken)); ON_CALL(*allWindowsContext, activeCollector()).WillByDefault( Return(allWindowsCollector)); WindowToken::Ptr token(window->activate()); EXPECT_EQ(QList() << allWindowsCollectorToken, token->tokens()); } TEST_F(TestWindow, ActivateOnlyWithValidWindowContext) { Window::Ptr window(createWindow()); ON_CALL(*dbusMenuCollector, isValid()).WillByDefault(Return(false)); ON_CALL(*gmenuWindowCollector, isValid()).WillByDefault(Return(false)); ON_CALL(*allWindowsCollector, isValid()).WillByDefault(Return(false)); WindowContext::MenuDefinition definition("bus.name"); definition.actionPath = QDBusObjectPath("/action/path"); definition.actionPrefix = "hud"; definition.menuPath = QDBusObjectPath("/menu/path"); QMap actions; actions[definition.actionPrefix] = definition.actionPath; EXPECT_CALL(factory, newGMenuCollector(definition.name, actions, definition.menuPath)).Times( 1).WillOnce(Return(windowCollector)); window->addMenu("context_1", definition); window->setContext("context_1"); QMenu windowCollectorMenu; CollectorToken::Ptr windowCollectorToken( new CollectorToken(windowCollector, &windowCollectorMenu)); EXPECT_CALL(*windowCollector, activate()).Times(1).WillOnce( Return(QList() << windowCollectorToken)); WindowToken::Ptr token(window->activate()); EXPECT_EQ(QList() << windowCollectorToken, token->tokens()); } TEST_F(TestWindow, ActivateWithMultipleCollectorsThenChange) { Window::Ptr window(createWindow()); ON_CALL(*windowCollector, isValid()).WillByDefault(Return(false)); QMenu gmenuWindowCollectorMenu; CollectorToken::Ptr gmenuWindowCollectorToken( new CollectorToken(gmenuWindowCollector, &gmenuWindowCollectorMenu)); EXPECT_CALL(*gmenuWindowCollector, activate()).Times(1).WillOnce( Return(QList() << gmenuWindowCollectorToken)); QMenu dbusMenuCollectorMenu; CollectorToken::Ptr dbusMenuCollectorToken( new CollectorToken(dbusMenuCollector, &dbusMenuCollectorMenu)); EXPECT_CALL(*dbusMenuCollector, activate()).Times(1).WillOnce( Return(QList() << dbusMenuCollectorToken)); QMenu allWindowsCollectorMenu; CollectorToken::Ptr allWindowsCollectorToken( new CollectorToken(allWindowsCollector, &allWindowsCollectorMenu)); EXPECT_CALL(*allWindowsCollector, activate()).Times(1).WillOnce( Return(QList() << allWindowsCollectorToken)); ON_CALL(*allWindowsContext, activeCollector()).WillByDefault( Return(allWindowsCollector)); WindowToken::Ptr token(window->activate()); EXPECT_EQ( QList() << dbusMenuCollectorToken << gmenuWindowCollectorToken << allWindowsCollectorToken, token->tokens()); // The gmenu window collector is going to give a different token now QMenu gmenuWindowCollectorMenuChanged; CollectorToken::Ptr gmenuWindowCollectorTokenChanged( new CollectorToken(gmenuWindowCollector, &gmenuWindowCollectorMenuChanged)); EXPECT_CALL(*gmenuWindowCollector, activate()).Times(1).WillOnce( Return(QList() << gmenuWindowCollectorTokenChanged)); // Re-prime the other collectors EXPECT_CALL(*dbusMenuCollector, activate()).Times(1).WillOnce( Return(QList() << dbusMenuCollectorToken)); EXPECT_CALL(*allWindowsCollector, activate()).Times(1).WillOnce( Return(QList() << allWindowsCollectorToken)); WindowToken::Ptr tokenChanged(window->activate()); EXPECT_NE(token, tokenChanged); EXPECT_EQ( QList() << dbusMenuCollectorToken << gmenuWindowCollectorTokenChanged << allWindowsCollectorToken, tokenChanged->tokens()); } TEST_F(TestWindow, Context) { WindowContextImpl context(factory); WindowContext::MenuDefinition definition("bus.name"); definition.actionPath = QDBusObjectPath("/action/path"); definition.actionPrefix = "hud"; definition.menuPath = QDBusObjectPath("/menu/path"); QMap actions; actions[definition.actionPrefix] = definition.actionPath; EXPECT_CALL(factory, newGMenuCollector(definition.name, actions, definition.menuPath)).Times( 1).WillOnce(Return(windowCollector)); context.addMenu("context_1", definition); EXPECT_FALSE(context.activeCollector()); context.setContext("context_1"); EXPECT_EQ(windowCollector, context.activeCollector()); } } // namespace hud-14.04+14.04.20140604/tests/unit/service/TestApplication.cpp0000644000015301777760000001603412343623451024277 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include #include using namespace std; using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::service; using namespace hud::service::test; namespace { class TestApplication: public Test { protected: TestApplication() : mock(dbus) { factory.setSessionBus(dbus.sessionConnection()); allWindowsContext.reset(new NiceMock()); EXPECT_CALL(factory, newWindowContext()).WillOnce( Return(allWindowsContext)); } virtual ~TestApplication() { } static void addAction(QList &actions, unsigned int windowId, const QString &context, const QString &prefix, const QDBusObjectPath &object) { hud::common::Action action; action.m_windowId = windowId; action.m_context = context; action.m_prefix = prefix; action.m_object = object; actions << action; } static void addMenu(QList &descriptions, unsigned int windowId, const QString &context, const QDBusObjectPath &object) { hud::common::Description description; description.m_windowId = windowId; description.m_context = context; description.m_object = object; descriptions << description; } DBusTestRunner dbus; DBusMock mock; NiceMock factory; QSharedPointer allWindowsContext; }; TEST_F(TestApplication, DBusInterfaceIsExported) { ApplicationImpl application("application-id", factory, dbus.sessionConnection()); ComCanonicalHudApplicationInterface applicationInterface( dbus.sessionConnection().baseService(), DBusTypes::applicationPath("application-id"), dbus.sessionConnection()); ASSERT_TRUE(applicationInterface.isValid()); //FIXME desktop path will return something when it's actually implemented EXPECT_EQ(QString(), applicationInterface.desktopPath()); } TEST_F(TestApplication, AddsWindow) { ApplicationImpl application("application-id", factory, dbus.sessionConnection()); EXPECT_TRUE(application.isEmpty()); QSharedPointer window(new NiceMock()); EXPECT_CALL(factory, newWindow(4567, QString("application-id"), _)).WillOnce( Return(window)); application.addWindow(4567); EXPECT_FALSE(application.isEmpty()); } TEST_F(TestApplication, HandlesDeleteUnknownWindow) { ApplicationImpl application("application-id", factory, dbus.sessionConnection()); EXPECT_TRUE(application.isEmpty()); QSharedPointer window(new NiceMock()); application.removeWindow(4567); EXPECT_TRUE(application.isEmpty()); } TEST_F(TestApplication, DeletesWindow) { ApplicationImpl application("application-id", factory, dbus.sessionConnection()); QSharedPointer window0(new NiceMock()); QSharedPointer window1(new NiceMock()); EXPECT_CALL(factory, newWindow(0, QString("application-id"), _)).WillOnce( Return(window0)); application.addWindow(0); EXPECT_FALSE(application.isEmpty()); EXPECT_CALL(factory, newWindow(1, QString("application-id"), _)).WillOnce( Return(window1)); application.addWindow(1); EXPECT_FALSE(application.isEmpty()); application.removeWindow(0); EXPECT_FALSE(application.isEmpty()); application.removeWindow(1); EXPECT_TRUE(application.isEmpty()); } TEST_F(TestApplication, AddSourcesToAllWindowsContext) { ApplicationImpl application("application-id", factory, dbus.sessionConnection()); QList actions; addAction(actions, 0, "context1", "prefix", QDBusObjectPath("/actions1")); addAction(actions, 0, "context2", "prefix", QDBusObjectPath("/actions1")); QList descriptions; addMenu(descriptions, 0, "context1", QDBusObjectPath("/menu1")); addMenu(descriptions, 0, "context2", QDBusObjectPath("/menu2")); WindowContext::MenuDefinition menuDefinition1("local"); menuDefinition1.actionPath = QDBusObjectPath("/actions1"); menuDefinition1.actionPrefix = "prefix"; menuDefinition1.menuPath = QDBusObjectPath("/menu1"); WindowContext::MenuDefinition menuDefinition2("local"); menuDefinition2.actionPath = QDBusObjectPath("/actions1"); menuDefinition2.actionPrefix = "prefix"; menuDefinition2.menuPath = QDBusObjectPath("/menu2"); EXPECT_CALL(*allWindowsContext, addMenu(QString("context1"), menuDefinition1)); EXPECT_CALL(*allWindowsContext, addMenu(QString("context2"), menuDefinition2)); application.AddSources(actions, descriptions); } TEST_F(TestApplication, AddSourcesToAllWindowsContextAndWindow) { ApplicationImpl application("application-id", factory, dbus.sessionConnection()); QSharedPointer window1(new NiceMock()); EXPECT_CALL(factory, newWindow(1, QString("application-id"), _)).WillOnce( Return(window1)); application.addWindow(1); QList actions; addAction(actions, 0, "context1", "prefix", QDBusObjectPath("/actions1")); addAction(actions, 0, "context2", "prefix", QDBusObjectPath("/actions1")); addAction(actions, 1, "context1", "prefix", QDBusObjectPath("/actions2")); QList descriptions; addMenu(descriptions, 0, "context1", QDBusObjectPath("/menu1")); addMenu(descriptions, 0, "context2", QDBusObjectPath("/menu2")); addMenu(descriptions, 1, "context1", QDBusObjectPath("/menu3")); WindowContext::MenuDefinition menuDefinition1("local"); menuDefinition1.actionPath = QDBusObjectPath("/actions1"); menuDefinition1.actionPrefix = "prefix"; menuDefinition1.menuPath = QDBusObjectPath("/menu1"); WindowContext::MenuDefinition menuDefinition2("local"); menuDefinition2.actionPath = QDBusObjectPath("/actions1"); menuDefinition2.actionPrefix = "prefix"; menuDefinition2.menuPath = QDBusObjectPath("/menu2"); WindowContext::MenuDefinition menuDefinition3("local"); menuDefinition3.actionPath = QDBusObjectPath("/actions2"); menuDefinition3.actionPrefix = "prefix"; menuDefinition3.menuPath = QDBusObjectPath("/menu3"); EXPECT_CALL(*allWindowsContext, addMenu(QString("context1"), menuDefinition1)); EXPECT_CALL(*allWindowsContext, addMenu(QString("context2"), menuDefinition2)); EXPECT_CALL(*window1, addMenu(QString("context1"), menuDefinition3)); application.AddSources(actions, descriptions); } } // namespace hud-14.04+14.04.20140604/tests/unit/service/TestUsageTracker.cpp0000644000015301777760000000605212343623451024413 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include using namespace std; using namespace testing; using namespace hud::service; namespace { class TestUsageTracker: public Test { protected: }; TEST_F(TestUsageTracker, BasicBehaviour) { SqliteUsageTracker usageTracker; usageTracker.markUsage("app-id-1", "entry1"); usageTracker.markUsage("app-id-1", "entry1"); usageTracker.markUsage("app-id-1", "entry2"); usageTracker.markUsage("app-id-1", "entry2"); usageTracker.markUsage("app-id-1", "entry2"); usageTracker.markUsage("app-id-1", "entry3"); usageTracker.markUsage("app-id-2", "entry1"); usageTracker.markUsage("app-id-2", "entry2"); usageTracker.markUsage("app-id-2", "entry2"); EXPECT_EQ(2, usageTracker.usage("app-id-1", "entry1")); EXPECT_EQ(3, usageTracker.usage("app-id-1", "entry2")); EXPECT_EQ(1, usageTracker.usage("app-id-1", "entry3")); EXPECT_EQ(1, usageTracker.usage("app-id-2", "entry1")); EXPECT_EQ(2, usageTracker.usage("app-id-2", "entry2")); } TEST_F(TestUsageTracker, SavesThingsBetweenRuns) { QTemporaryDir temporaryDir; ASSERT_TRUE(temporaryDir.isValid()); qputenv("HUD_STORE_USAGE_DATA", "TRUE"); qputenv("HUD_CACHE_DIR", temporaryDir.path().toUtf8()); { SqliteUsageTracker usageTracker; usageTracker.markUsage("app-id-1", "entry1"); usageTracker.markUsage("app-id-1", "entry1"); usageTracker.markUsage("app-id-1", "entry2"); usageTracker.markUsage("app-id-1", "entry2"); usageTracker.markUsage("app-id-1", "entry2"); usageTracker.markUsage("app-id-1", "entry3"); usageTracker.markUsage("app-id-2", "entry1"); usageTracker.markUsage("app-id-2", "entry2"); usageTracker.markUsage("app-id-2", "entry2"); EXPECT_EQ(2, usageTracker.usage("app-id-1", "entry1")); EXPECT_EQ(3, usageTracker.usage("app-id-1", "entry2")); EXPECT_EQ(1, usageTracker.usage("app-id-1", "entry3")); EXPECT_EQ(1, usageTracker.usage("app-id-2", "entry1")); EXPECT_EQ(2, usageTracker.usage("app-id-2", "entry2")); } { SqliteUsageTracker usageTracker; EXPECT_EQ(2, usageTracker.usage("app-id-1", "entry1")); EXPECT_EQ(3, usageTracker.usage("app-id-1", "entry2")); EXPECT_EQ(1, usageTracker.usage("app-id-1", "entry3")); EXPECT_EQ(1, usageTracker.usage("app-id-2", "entry1")); EXPECT_EQ(2, usageTracker.usage("app-id-2", "entry2")); } qputenv("HUD_STORE_USAGE_DATA", "FALSE"); } } // namespace hud-14.04+14.04.20140604/tests/unit/service/TestItemStore.cpp0000644000015301777760000002077212343623451023753 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include using namespace std; using namespace testing; using namespace hud::service; using namespace hud::service::test; namespace { class TestItemStore: public Test { protected: TestItemStore() { usageTracker.reset(new NiceMock()); searchSettings.reset(new HardCodedSearchSettings()); store.reset(new ItemStore("app-id", usageTracker, searchSettings)); } /* Test a set of strings */ string search(const QString &query) { QList results; store->search(query, Query::EmptyBehaviour::SHOW_SUGGESTIONS, results); QString result; if (!results.isEmpty()) { result = results.at(0).commandName(); } return result.toStdString(); } ItemStore::Ptr store; QSharedPointer usageTracker; QSharedPointer searchSettings; }; /* Ensure the base calculation works */ TEST_F(TestItemStore, DistanceSubfunction) { QMenu root; QMenu file("File"); file.addAction("Open"); file.addAction("New"); file.addAction("Print"); file.addAction("Print Preview"); root.addMenu(&file); store->indexMenu(&root); EXPECT_EQ("Print Preview", search("Print Pre")); } /* Ensure that we can handle some misspelling */ TEST_F(TestItemStore, DistanceMisspelll) { QMenu root; QMenu file("File"); file.addAction("Open"); file.addAction("New"); file.addAction("Print"); file.addAction("Print Preview"); root.addMenu(&file); store->indexMenu(&root); EXPECT_EQ("Print Preview", search("Prnt Pr")); EXPECT_EQ("Print Preview", search("Print Preiw")); EXPECT_EQ("Print Preview", search("Prnt Pr")); } /* Ensure that we can find print with short strings */ TEST_F(TestItemStore, DistancePrintIssues) { QMenu root; QMenu file("File"); file.addAction("New"); file.addAction("Open"); file.addAction("Print..."); root.addMenu(&file); QMenu edit("Edit"); edit.addAction("Undo"); root.addMenu(&edit); QMenu help("Help"); help.addAction("About"); help.addAction("Empty"); root.addMenu(&help); store->indexMenu(&root); EXPECT_EQ("Print...", search("Pr")); EXPECT_EQ("Print...", search("Print")); EXPECT_EQ("Print...", search("Print...")); } /* Not finished word yet */ TEST_F(TestItemStore, UnfinishedWord) { QMenu root; root.addAction("Open Terminal"); root.addAction("Open Tab"); store->indexMenu(&root); EXPECT_EQ("Open Terminal", search("open ter")); EXPECT_EQ("Open Terminal", search("open term")); EXPECT_EQ("Open Terminal", search("open termi")); EXPECT_EQ("Open Terminal", search("open termin")); EXPECT_EQ("Open Terminal", search("open termina")); EXPECT_EQ("Open Terminal", search("open terminal")); } /* Not finished word yet */ TEST_F(TestItemStore, UnfinishedWord2) { QMenu root; root.addAction("Change Topic"); store->indexMenu(&root); EXPECT_EQ("Change Topic", search("cha")); } /* A variety of strings that should have predictable results */ TEST_F(TestItemStore, DistanceVariety) { QMenu root; QMenu date("Date"); date.addAction("House Cleaning"); root.addMenu(&date); QMenu file("File"); file.addAction("Close Window"); root.addMenu(&file); QMenu edit("Edit"); edit.addAction("Keyboard Shortcuts..."); root.addMenu(&edit); QMenu vpn("VPN Configuration"); vpn.addAction("Configure VPN..."); QMenu network("Network"); network.addMenu(&vpn); root.addMenu(&network); store->indexMenu(&root); EXPECT_EQ("House Cleaning", search("House")); EXPECT_EQ("House Cleaning", search("House C")); EXPECT_EQ("House Cleaning", search("House Cle")); EXPECT_EQ("House Cleaning", search("House Clean")); EXPECT_EQ("House Cleaning", search("Clean House")); } /* A variety of strings that should have predictable results */ TEST_F(TestItemStore, DistanceFrenchPref) { QMenu root; QMenu file("Fichier"); file.addAction("aperçu avant impression"); root.addMenu(&file); QMenu connection("Connexion au réseau..."); root.addMenu(&connection); QMenu edit("Edition"); edit.addAction("préférences"); root.addMenu(&edit); store->indexMenu(&root); EXPECT_EQ("préférences", search("préférences")); EXPECT_EQ("préférences", search("pré")); EXPECT_EQ("préférences", search("préf")); EXPECT_EQ("préférences", search("préfé")); EXPECT_EQ("préférences", search("pref")); } /* Check to make sure the returned hits are not dups and the proper number */ TEST_F(TestItemStore, DistanceDups) { QMenu root; root.addAction("Inflated"); root.addAction("Confluated"); root.addAction("Sublimated"); root.addAction("Sadated"); root.addAction("Situated"); root.addAction("Infatuated"); store->indexMenu(&root); EXPECT_EQ("Inflated", search("ted inf")); } /* Check to make sure 'Save' matches better than 'Save As...' for "save" */ TEST_F(TestItemStore, DistanceExtraTerms) { QMenu root; QMenu file("File"); file.addAction("Banana"); file.addAction("Save All"); file.addAction("Save"); file.addAction("Save As..."); file.addAction("Apple"); root.addMenu(&file); store->indexMenu(&root); EXPECT_EQ("Save", search("save")); } TEST_F(TestItemStore, BlankSearchFrequentlyUsedItems) { QMenu root; QMenu file("&File"); file.addAction("&One"); file.addAction("&Two"); file.addAction("T&hree"); file.addAction("Fou&r"); root.addMenu(&file); store->indexMenu(&root); ON_CALL(*usageTracker, usage(QString("app-id"), QString("File||One"))).WillByDefault( Return(2)); ON_CALL(*usageTracker, usage(QString("app-id"), QString("File||Two"))).WillByDefault( Return(0)); ON_CALL(*usageTracker, usage(QString("app-id"), QString("File||Three"))).WillByDefault( Return(4)); ON_CALL(*usageTracker, usage(QString("app-id"), QString("File||Four"))).WillByDefault( Return(3)); QList results; store->search("", Query::EmptyBehaviour::SHOW_SUGGESTIONS, results); ASSERT_EQ(4, results.size()); EXPECT_EQ(QString("Three"), results.at(0).commandName()); EXPECT_EQ(QString("Four"), results.at(1).commandName()); EXPECT_EQ(QString("One"), results.at(2).commandName()); EXPECT_EQ(QString("Two"), results.at(3).commandName()); } TEST_F(TestItemStore, BlankSearchNoSuggestions) { QMenu root; QMenu file("&File"); file.addAction("&One"); file.addAction("&Two"); file.addAction("T&hree"); file.addAction("Fou&r"); root.addMenu(&file); store->indexMenu(&root); ON_CALL(*usageTracker, usage(QString("app-id"), QString("File||One"))).WillByDefault( Return(2)); ON_CALL(*usageTracker, usage(QString("app-id"), QString("File||Two"))).WillByDefault( Return(0)); ON_CALL(*usageTracker, usage(QString("app-id"), QString("File||Three"))).WillByDefault( Return(4)); ON_CALL(*usageTracker, usage(QString("app-id"), QString("File||Four"))).WillByDefault( Return(3)); QList results; store->search("", Query::EmptyBehaviour::NO_SUGGESTIONS, results); ASSERT_TRUE(results.empty()); } TEST_F(TestItemStore, ExecuteMarksHistory) { QMenu root; QMenu file("File"); file.addAction("Save As..."); file.addAction("Save"); root.addMenu(&file); store->indexMenu(&root); EXPECT_CALL(*usageTracker, markUsage(QString("app-id"), QString("File||Save As..."))); store->execute(0); } TEST_F(TestItemStore, ChangeSearchSettings) { QMenu root; QMenu file("&File"); file.addAction("Apple"); file.addAction("Banana"); file.addAction("Can Cherry"); root.addMenu(&file); store->indexMenu(&root); EXPECT_EQ("Banana", search("Ban")); searchSettings->setEndDropPenalty(100); EXPECT_EQ("Can Cherry", search("Ban")); } TEST_F(TestItemStore, DeletedActions) { QMenu root; QMenu file("&File"); file.addAction("Apple"); file.addAction("Banana"); file.addAction("Can Cherry"); root.addMenu(&file); store->indexMenu(&root); file.clear(); root.clear(); // It should not crash! :) EXPECT_EQ("", search("flibble")); // It should not crash! :) EXPECT_EQ("", search("")); } } // namespace hud-14.04+14.04.20140604/tests/unit/service/CMakeLists.txt0000644000015301777760000000076312343623451023232 0ustar pbusernogroup00000000000000 set( UNIT_TESTS_SRC TestApplication.cpp TestApplicationList.cpp TestHudService.cpp TestItemStore.cpp TestQuery.cpp TestUsageTracker.cpp TestVoice.cpp TestWindow.cpp ) add_executable( test-service-unit-tests ${UNIT_TESTS_SRC} ) qt5_use_modules( test-service-unit-tests Test ) target_link_libraries( test-service-unit-tests test-utils hud-service ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} ${QTDBUSTEST_LIBRARIES} ${QTDBUSMOCK_LIBRARIES} ) add_hud_test( test-service-unit-tests ) hud-14.04+14.04.20140604/tests/unit/service/TestHudService.cpp0000644000015301777760000001753412343623451024103 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include using namespace std; using namespace testing; using namespace QtDBusTest; using namespace hud::common; using namespace hud::service; using namespace hud::service::test; namespace { class TestHudService: public Test { protected: TestHudService() { factory.setSessionBus(dbus.sessionConnection()); applicationList.reset(new NiceMock()); } virtual ~TestHudService() { } DBusTestRunner dbus; NiceMock factory; QSharedPointer applicationList; }; TEST_F(TestHudService, OpenCloseQuery) { HudServiceImpl hudService(factory, applicationList, dbus.sessionConnection()); QDBusObjectPath queryPath("/path/query0"); QString resultsModel("com.canonical.hud.results0"); QString appstackModel("com.canonical.hud.appstack0"); QSharedPointer query(new NiceMock()); ON_CALL(*query, path()).WillByDefault(ReturnRef(queryPath)); ON_CALL(*query, resultsModel()).WillByDefault(Return(resultsModel)); ON_CALL(*query, appstackModel()).WillByDefault(Return(appstackModel)); EXPECT_CALL(factory, newQuery(QString("query text"), QString("local"), Query::EmptyBehaviour::SHOW_SUGGESTIONS)).Times( 1).WillOnce(Return(query)); QString resultsName; QString appstackName; int modelRevision; EXPECT_EQ(queryPath, hudService.CreateQuery("query text", resultsName, appstackName, modelRevision)); EXPECT_EQ(resultsModel, resultsName); EXPECT_EQ(appstackModel, appstackName); EXPECT_EQ(0, modelRevision); EXPECT_EQ(QList() << queryPath, hudService.openQueries()); hudService.closeQuery(queryPath); EXPECT_EQ(QList(), hudService.openQueries()); } TEST_F(TestHudService, CloseUnknownQuery) { HudServiceImpl hudService(factory, applicationList, dbus.sessionConnection()); QDBusObjectPath queryPath("/path/query0"); EXPECT_EQ(QList(), hudService.openQueries()); hudService.closeQuery(queryPath); EXPECT_EQ(QList(), hudService.openQueries()); } TEST_F(TestHudService, CreateMultipleQueries) { HudServiceImpl hudService(factory, applicationList, dbus.sessionConnection()); QDBusObjectPath queryPath0("/path/query0"); QString resultsModel0("com.canonical.hud.results0"); QString appstackModel0("com.canonical.hud.appstack0"); QSharedPointer query0(new NiceMock()); ON_CALL(*query0, path()).WillByDefault(ReturnRef(queryPath0)); ON_CALL(*query0, resultsModel()).WillByDefault(Return(resultsModel0)); ON_CALL(*query0, appstackModel()).WillByDefault(Return(appstackModel0)); QDBusObjectPath queryPath1("/path/query1"); QString resultsModel1("com.canonical.hud.results1"); QString appstackModel1("com.canonical.hud.appstack1"); QSharedPointer query1(new NiceMock()); ON_CALL(*query1, path()).WillByDefault(ReturnRef(queryPath1)); ON_CALL(*query1, resultsModel()).WillByDefault(Return(resultsModel1)); ON_CALL(*query1, appstackModel()).WillByDefault(Return(appstackModel1)); EXPECT_CALL(factory, newQuery(QString("query0"), QString("local"), Query::EmptyBehaviour::SHOW_SUGGESTIONS)).Times( 1).WillOnce(Return(query0)); EXPECT_CALL(factory, newQuery(QString("query1"), QString("local"), Query::EmptyBehaviour::SHOW_SUGGESTIONS)).Times( 1).WillOnce(Return(query1)); int modelRevision; QString resultsName; QString appstackName; EXPECT_EQ(queryPath0, hudService.CreateQuery("query0", resultsName, appstackName, modelRevision)); EXPECT_EQ(resultsModel0, resultsName); EXPECT_EQ(appstackModel0, appstackName); EXPECT_EQ(0, modelRevision); EXPECT_EQ(QList() << queryPath0, hudService.openQueries()); EXPECT_EQ(queryPath1, hudService.CreateQuery("query1", resultsName, appstackName, modelRevision)); EXPECT_EQ(resultsModel1, resultsName); EXPECT_EQ(appstackModel1, appstackName); EXPECT_EQ(0, modelRevision); EXPECT_EQ(QList() << queryPath0 << queryPath1, hudService.openQueries()); hudService.closeQuery(queryPath0); EXPECT_EQ(QList() << queryPath1, hudService.openQueries()); hudService.closeQuery(queryPath1); EXPECT_EQ(QList(), hudService.openQueries()); } TEST_F(TestHudService, LegacyQuery) { QSharedPointer application( new NiceMock()); QString icon("app0-icon"); ON_CALL(*application, icon()).WillByDefault(ReturnRef(icon)); ON_CALL(*applicationList, focusedApplication()).WillByDefault( Return(application)); HudServiceImpl hudService(factory, applicationList, dbus.sessionConnection()); QDBusObjectPath queryPath("/path/query0"); QList results; results << Result(1, "command1", Result::HighlightList() << Result::Highlight(1, 4) << Result::Highlight(5, 6), "descripton1", Result::HighlightList() << Result::Highlight(0, 3), "shortcut1", 10, false); results << Result(2, "simon & garfunkel", Result::HighlightList() << Result::Highlight(4, 8), "descripton2", Result::HighlightList(), "shortcut2", 20, false); QSharedPointer query(new NiceMock()); ON_CALL(*query, path()).WillByDefault(ReturnRef(queryPath)); ON_CALL(*query, results()).WillByDefault(ReturnRef(results)); EXPECT_CALL(factory, newQuery(QString("query text"), QString("local"), Query::EmptyBehaviour::NO_SUGGESTIONS)).Times( 1).WillOnce(Return(query)); QList suggestions; QDBusVariant querykey; EXPECT_EQ("query text", hudService.StartQuery("query text", 3, suggestions, querykey)); EXPECT_EQ(QList() << queryPath, hudService.openQueries()); EXPECT_EQ(queryPath.path(), querykey.variant().toString()); ASSERT_EQ(2, suggestions.size()); { const Suggestion &suggestion(suggestions.at(0)); EXPECT_EQ(1, suggestion.m_id); EXPECT_EQ(QString("command1 (descripton1)"), suggestion.m_description); EXPECT_EQ(QString("app0-icon"), suggestion.m_icon); } { const Suggestion &suggestion(suggestions.at(1)); EXPECT_EQ(2, suggestion.m_id); EXPECT_EQ(QString("simon & garfunkel (descripton2)"), suggestion.m_description); EXPECT_EQ(QString("app0-icon"), suggestion.m_icon); } // We don't close legacy queries when the close method is called EXPECT_CALL(*query, UpdateQuery(QString())).Times(1); hudService.CloseQuery(querykey); EXPECT_EQ(QList() << queryPath, hudService.openQueries()); QDBusVariant itemKey(qulonglong(1)); EXPECT_CALL(*query, ExecuteCommand(itemKey, 12345)).Times(1); hudService.ExecuteQuery(itemKey, 12345); EXPECT_TRUE(hudService.openQueries().isEmpty()); } TEST_F(TestHudService, RegisterApplication) { QDBusObjectPath path("/foo"); QSharedPointer application( new NiceMock()); ON_CALL(*application, path()).WillByDefault(ReturnRef(path)); EXPECT_CALL(*applicationList, ensureApplication(QString("app-id"))).WillOnce( Return(application)); HudServiceImpl hudService(factory, applicationList, dbus.sessionConnection()); EXPECT_EQ(path, hudService.RegisterApplication("app-id")); } } // namespace hud-14.04+14.04.20140604/tests/unit/service/Mocks.h0000644000015301777760000001130512343623451021711 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_TEST_MOCKS_H_ #define HUD_SERVICE_TEST_MOCKS_H_ #include #include #include namespace hud { namespace service { namespace test { class MockFactory: public Factory { public: MOCK_METHOD0(singletonApplicationList, ApplicationList::Ptr()); MOCK_METHOD0(sessionBus, QDBusConnection()); MOCK_METHOD3(newQuery, Query::Ptr( const QString &, const QString &, Query::EmptyBehaviour)); MOCK_METHOD1(newApplication, Application::Ptr(const QString &)); MOCK_METHOD0(newWindowContext, WindowContext::Ptr()); MOCK_METHOD3(newWindow, Window::Ptr(unsigned int, const QString &, WindowContext::Ptr)); MOCK_METHOD0(singletonUsageTracker, UsageTracker::Ptr()); MOCK_METHOD2(newDBusMenuCollector, Collector::Ptr(unsigned int, const QString &)); MOCK_METHOD2(newGMenuWindowCollector, Collector::Ptr(unsigned int, const QString &)); MOCK_METHOD3(newGMenuCollector, Collector::Ptr(const QString &, const QMap &, const QDBusObjectPath &)); }; class MockHudService: public HudService { public: MOCK_METHOD1(closeQuery, Query::Ptr(const QDBusObjectPath &)); }; class MockQuery: public Query { public: MOCK_CONST_METHOD0(appstackModel, QString()); MOCK_CONST_METHOD0(currentQuery, QString()); MOCK_CONST_METHOD0(resultsModel, QString()); MOCK_CONST_METHOD0(toolbarItems, QStringList()); MOCK_CONST_METHOD0(path, const QDBusObjectPath &()); MOCK_CONST_METHOD0(results, const QList &()); MOCK_METHOD1(UpdateQuery, int(const QString &)); MOCK_METHOD2(ExecuteCommand, void(const QDBusVariant &, uint)); }; class MockApplicationList: public ApplicationList { public: MOCK_CONST_METHOD0(applications, QList()); MOCK_CONST_METHOD0(focusedApplication, Application::Ptr()); MOCK_CONST_METHOD0(focusedWindow, Window::Ptr()); MOCK_METHOD1(ensureApplication, Application::Ptr(const QString &)); }; class MockApplication: public Application { public: MOCK_CONST_METHOD0(id, const QString &()); MOCK_METHOD0(icon, const QString &()); MOCK_METHOD1(addWindow, void(unsigned int)); MOCK_METHOD1(removeWindow, void(unsigned int)); MOCK_METHOD1(window, Window::Ptr(unsigned int)); MOCK_CONST_METHOD0(isEmpty, bool()); MOCK_CONST_METHOD0(path, const QDBusObjectPath &()); }; class MockWindowToken: public WindowToken { public: MOCK_METHOD3(search, void(const QString &, Query::EmptyBehaviour emptyBehaviour, QList &)); MOCK_METHOD1(execute, void(unsigned long long)); MOCK_METHOD1(executeToolbar, void(const QString &)); MOCK_METHOD5(executeParameterized, QString(unsigned long long, QString &, QString &, QDBusObjectPath &, QDBusObjectPath &)); MOCK_CONST_METHOD0(commands, QList()); MOCK_CONST_METHOD0(toolbarItems, QStringList()); MOCK_CONST_METHOD0(tokens, const QList &()); }; class MockWindowContext: public WindowContext { public: MOCK_METHOD1(setContext, void(const QString &)); MOCK_METHOD2(addMenu, void(const QString &, const MenuDefinition &)); MOCK_METHOD0(activeCollector, Collector::Ptr()); }; class MockWindow: public Window { public: MOCK_METHOD0(activate, WindowToken::Ptr()); MOCK_METHOD1(setContext, void(const QString &)); MOCK_METHOD2(search, void(const QString &, QList &)); MOCK_METHOD2(addMenu, void(const QString &, const MenuDefinition &)); MOCK_METHOD0(activeCollector, Collector::Ptr()); }; class MockUsageTracker: public UsageTracker { public: MOCK_METHOD2(markUsage, void(const QString &, const QString &)); MOCK_CONST_METHOD2(usage, unsigned int(const QString &, const QString &)); }; class MockVoice: public Voice { public: MOCK_METHOD1(listen, QString(const QList &)); }; class MockCollector: public Collector { public: MOCK_CONST_METHOD0(isValid, bool()); MOCK_METHOD0(activate, QList()); MOCK_METHOD2(search, void(const QString &, QList &)); protected: MOCK_METHOD0(deactivate, void()); }; } } } #endif /* HUD_SERVICE_TEST_MOCKS_H_ */ hud-14.04+14.04.20140604/tests/unit/service/TestVoice.cpp0000644000015301777760000000711612343623451023102 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include #include #include #include #include using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::service; namespace { class TestVoice: public Test { protected: TestVoice() : mock(dbus) { mock.registerCustomMock(DBusTypes::UNITY_VOICE_DBUS_NAME, DBusTypes::UNITY_VOICE_DBUS_PATH, ComCanonicalUnityVoiceInterface::staticInterfaceName(), QDBusConnection::SessionBus); dbus.startServices(); voice_interface.reset( new ComCanonicalUnityVoiceInterface( DBusTypes::UNITY_VOICE_DBUS_NAME, DBusTypes::UNITY_VOICE_DBUS_PATH, dbus.sessionConnection())); } virtual ~TestVoice() { } virtual OrgFreedesktopDBusMockInterface & unityVoiceMock() { return mock.mockInterface(DBusTypes::UNITY_VOICE_DBUS_NAME, DBusTypes::UNITY_VOICE_DBUS_PATH, ComCanonicalUnityVoiceInterface::staticInterfaceName(), QDBusConnection::SessionBus); } DBusTestRunner dbus; DBusMock mock; QSharedPointer voice_interface; }; TEST_F( TestVoice, Signals ) { // check that signals are patched through VoiceImpl VoiceImpl voice(voice_interface); QSignalSpy m_heard_something_spy(&voice, SIGNAL( HeardSomething() )); QSignalSpy m_listening_spy(&voice, SIGNAL( Listening() )); QSignalSpy m_loading_spy(&voice, SIGNAL( Loading() )); EXPECT_TRUE(m_heard_something_spy.empty()); emit voice_interface->HeardSomething(); EXPECT_FALSE(m_heard_something_spy.empty()); EXPECT_TRUE(m_listening_spy.empty()); emit voice_interface->Listening(); EXPECT_FALSE(m_listening_spy.empty()); EXPECT_TRUE(m_loading_spy.empty()); emit voice_interface->Loading(); EXPECT_FALSE(m_loading_spy.empty()); } TEST_F( TestVoice, ListenNoCommands ) { // call listen() with an empty commands list VoiceImpl voice(voice_interface); QList commands; unityVoiceMock().AddMethod(DBusTypes::UNITY_VOICE_DBUS_NAME, "listen", "aas", "s", "ret = 'new file'").waitForFinished(); EXPECT_NE("new file", voice.listen(commands)); unityVoiceMock().AddMethod(DBusTypes::UNITY_VOICE_DBUS_NAME, "listen", "aas", "s", "ret = 'open file'").waitForFinished(); EXPECT_NE("open file", voice.listen(commands)); } TEST_F( TestVoice, Listen ) { // call listen() with a valid commands list VoiceImpl voice(voice_interface); QList commands; commands.append( { "new", "file" }); commands.append( { "open", "file" }); unityVoiceMock().AddMethod(DBusTypes::UNITY_VOICE_DBUS_NAME, "listen", "aas", "s", "ret = 'new file'").waitForFinished(); EXPECT_EQ("new file", voice.listen(commands)); unityVoiceMock().AddMethod(DBusTypes::UNITY_VOICE_DBUS_NAME, "listen", "aas", "s", "ret = 'open file'").waitForFinished(); EXPECT_EQ("open file", voice.listen(commands)); } } // namespace hud-14.04+14.04.20140604/tests/unit/libhud/0000755000015301777760000000000012343624372020276 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/unit/libhud/TestManager.cpp0000644000015301777760000001366412343623451023223 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include #include using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::testutils; namespace { class TestManager: public Test { protected: TestManager() : mock(dbus), hud(dbus, mock) { dbus.startServices(); hud.loadMethods(); connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); } virtual ~TestManager() { g_object_unref(connection); } void EXPECT_CALL(const QList &spy, int index, const QString &name, const QVariantList &args) { QVariant args2(QVariant::fromValue(args)); ASSERT_LT(index, spy.size()); const QVariantList &call(spy.at(index)); EXPECT_EQ(name, call.at(0).toString()); EXPECT_EQ(args2.toString().toStdString(), call.at(1).toString().toStdString()); } DBusTestRunner dbus; DBusMock mock; MockHudService hud; GDBusConnection *connection; }; TEST_F(TestManager, Create) { QSignalSpy hudSpy(&hud.hudInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); HudManager *manager = hud_manager_new("test.app"); hudSpy.wait(); EXPECT_CALL(hudSpy, 0, "RegisterApplication", QVariantList() << QString("test.app")); // FIXME Waiting in tests - need to wait for reply to get to the manager QTestEventLoop::instance().enterLoopMSecs(100); g_object_unref(manager); } TEST_F(TestManager, CreateWithApplication) { GApplication *application = g_application_new("app.id", G_APPLICATION_FLAGS_NONE); ASSERT_TRUE(g_application_register(application, NULL, NULL)); QSignalSpy hudSpy(&hud.hudInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); QSignalSpy applicationSpy(&hud.applicationInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); HudManager *manager = hud_manager_new_for_application(application); hudSpy.wait(); applicationSpy.wait(); g_object_unref(manager); EXPECT_CALL(hudSpy, 0, "RegisterApplication", QVariantList() << QString("app.id")); QVariantList &args(applicationSpy[0]); RawDBusTransformer::transform(args); QVariantList expectedArgs; QVariantList args1; args1 << uint(0) << "action-publisher-context-0" << "app" << QVariant::fromValue(QDBusObjectPath("/app/id")); expectedArgs << QVariant::fromValue(args1); QVariantList args2; args2 << uint(0) << "action-publisher-context-0" << QVariant::fromValue( QDBusObjectPath("/com/canonical/hud/publisher")); expectedArgs << QVariant::fromValue(args2); EXPECT_CALL(applicationSpy, 0, "AddSources", expectedArgs); g_object_unref(application); } TEST_F(TestManager, AddActions) { QSignalSpy hudSpy(&hud.hudInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); QSignalSpy applicationSpy(&hud.applicationInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); HudManager *manager = hud_manager_new("test.app"); hudSpy.wait(); HudActionPublisher *publisher = hud_action_publisher_new( HUD_ACTION_PUBLISHER_ALL_WINDOWS, "test-add-context"); hud_action_publisher_add_action_group(publisher, "app", "/app/object"); hud_manager_add_actions(manager, publisher); applicationSpy.wait(); QVariantList &args(applicationSpy[0]); RawDBusTransformer::transform(args); QVariantList expectedArgs; QVariantList args1; args1 << uint(0) << "test-add-context" << "app" << QVariant::fromValue(QDBusObjectPath("/app/object")); expectedArgs << QVariant::fromValue(args1); QVariantList args2; args2 << uint(0) << "test-add-context" << QVariant::fromValue( QDBusObjectPath("/com/canonical/hud/publisher1")); expectedArgs << QVariant::fromValue(args2); EXPECT_CALL(applicationSpy, 0, "AddSources", expectedArgs); g_object_unref(publisher); g_object_unref(manager); } /** * the remove_actions method does nothing at the moment */ TEST_F(TestManager, RemoveActions) { QSignalSpy hudSpy(&hud.hudInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); QSignalSpy applicationSpy(&hud.applicationInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); HudManager *manager = hud_manager_new("app-id"); hudSpy.wait(); HudActionPublisher *publisher = hud_action_publisher_new( HUD_ACTION_PUBLISHER_ALL_WINDOWS, "test-context"); hud_action_publisher_add_action_group(publisher, "app", "/app/object"); hud_manager_add_actions(manager, publisher); applicationSpy.wait(); QVariantList &args(applicationSpy[0]); RawDBusTransformer::transform(args); QVariantList expectedArgs; QVariantList args1; args1 << uint(0) << "test-context" << "app" << QVariant::fromValue(QDBusObjectPath("/app/object")); expectedArgs << QVariant::fromValue(args1); QVariantList args2; args2 << uint(0) << "test-context" << QVariant::fromValue( QDBusObjectPath("/com/canonical/hud/publisher2")); expectedArgs << QVariant::fromValue(args2); EXPECT_CALL(applicationSpy, 0, "AddSources", expectedArgs); hud_manager_remove_actions(manager, publisher); // FIXME Waiting in tests QTestEventLoop::instance().enterLoopMSecs(100); g_object_unref(publisher); g_object_unref(manager); } } hud-14.04+14.04.20140604/tests/unit/libhud/TestActionDescription.cpp0000644000015301777760000000455612343623451025272 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::testutils; namespace { class TestActionDescription: public Test { protected: TestActionDescription() : mock(dbus), hud(dbus, mock) { dbus.startServices(); hud.loadMethods(); } virtual ~TestActionDescription() { } DBusTestRunner dbus; DBusMock mock; MockHudService hud; }; TEST_F(TestActionDescription, WithAttributeValue) { HudActionDescription *description = hud_action_description_new( "hud.simple-action", g_variant_new_string("Foo")); hud_action_description_set_attribute_value(description, G_MENU_ATTRIBUTE_LABEL, g_variant_new_string("Simple Action")); EXPECT_STREQ("hud.simple-action", hud_action_description_get_action_name(description)); EXPECT_STREQ("Foo", g_variant_get_string( hud_action_description_get_action_target(description), 0)); hud_action_description_unref(description); } TEST_F(TestActionDescription, WithAttribute) { HudActionDescription *description = hud_action_description_new( "hud.simple-action", g_variant_new_string("Bar")); hud_action_description_set_attribute(description, G_MENU_ATTRIBUTE_LABEL, "s", "Simple Action"); EXPECT_STREQ("hud.simple-action", hud_action_description_get_action_name(description)); EXPECT_STREQ("Bar", g_variant_get_string( hud_action_description_get_action_target(description), 0)); hud_action_description_unref(description); } } // namespace hud-14.04+14.04.20140604/tests/unit/libhud/TestActionPublisher.cpp0000644000015301777760000001444312343623451024740 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::testutils; namespace { class TestActionPublisher: public Test { protected: TestActionPublisher() : mock(dbus), hud(dbus, mock) { dbus.startServices(); hud.loadMethods(); connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); } virtual ~TestActionPublisher() { g_object_unref(connection); } DBusTestRunner dbus; DBusMock mock; MockHudService hud; GDBusConnection *connection; }; TEST_F(TestActionPublisher, NewForId) { { HudActionPublisher *publisher = hud_action_publisher_new( HUD_ACTION_PUBLISHER_ALL_WINDOWS, HUD_ACTION_PUBLISHER_NO_CONTEXT); ASSERT_TRUE(publisher); EXPECT_EQ(HUD_ACTION_PUBLISHER_ALL_WINDOWS, hud_action_publisher_get_window_id(publisher)); EXPECT_TRUE(hud_action_publisher_get_context_id(publisher)); g_object_unref(publisher); } { HudActionPublisher *publisher = hud_action_publisher_new(123, HUD_ACTION_PUBLISHER_NO_CONTEXT); ASSERT_TRUE(publisher); EXPECT_EQ(123, hud_action_publisher_get_window_id(publisher)); g_object_unref(publisher); } } TEST_F(TestActionPublisher, NewForApplication) { GApplication *application = g_application_new("app.id", G_APPLICATION_FLAGS_NONE); ASSERT_TRUE(g_application_register(application, NULL, NULL)); HudActionPublisher *publisher = hud_action_publisher_new_for_application( application); EXPECT_TRUE(publisher); g_object_unref(application); g_object_unref(publisher); } TEST_F(TestActionPublisher, AddActionGroup) { GApplication *application = g_application_new("app.id", G_APPLICATION_FLAGS_NONE); ASSERT_TRUE(g_application_register(application, NULL, NULL)); HudActionPublisher *publisher = hud_action_publisher_new_for_application( application); ASSERT_TRUE(publisher); // FIXME Waiting in tests QTestEventLoop::instance().enterLoopMSecs(100); { GList* groups = hud_action_publisher_get_action_groups(publisher); ASSERT_EQ(1, g_list_length(groups)); { HudActionPublisherActionGroupSet *group = (HudActionPublisherActionGroupSet *) g_list_nth_data(groups, 0); EXPECT_STREQ("/app/id", group->path); EXPECT_STREQ("app", group->prefix); } } hud_action_publisher_add_action_group(publisher, "prefix", "/object/path"); // FIXME Waiting in tests QTestEventLoop::instance().enterLoopMSecs(100); { GList* groups = hud_action_publisher_get_action_groups(publisher); ASSERT_EQ(2, g_list_length(groups)); { HudActionPublisherActionGroupSet *group = (HudActionPublisherActionGroupSet *) g_list_nth_data(groups, 0); EXPECT_STREQ("/object/path", group->path); EXPECT_STREQ("prefix", group->prefix); } { HudActionPublisherActionGroupSet *group = (HudActionPublisherActionGroupSet *) g_list_nth_data(groups, 1); EXPECT_STREQ("/app/id", group->path); EXPECT_STREQ("app", group->prefix); } //FIXME This code causes the test suite to fail // GMenuModel *model = // G_MENU_MODEL(g_dbus_menu_model_get( // connection, // DBUS_NAME, "/com/canonical/hud/publisher")); // // ASSERT_TRUE(model); // EXPECT_EQ(0, g_menu_model_get_n_items(model)); // g_object_unref(model); } // FIXME This API method currently does nothing hud_action_publisher_remove_action_group(publisher, "prefix", g_variant_new_string("/object/path")); g_object_unref(publisher); g_object_unref(application); } TEST_F(TestActionPublisher, AddDescription) { GApplication *application = g_application_new("app.id", G_APPLICATION_FLAGS_NONE); ASSERT_TRUE(g_application_register(application, NULL, NULL)); HudActionPublisher *publisher = hud_action_publisher_new_for_application( application); ASSERT_TRUE(publisher); HudActionDescription *description = hud_action_description_new( "hud.simple-action", g_variant_new_string("Foo")); hud_action_description_set_attribute_value(description, G_MENU_ATTRIBUTE_LABEL, g_variant_new_string("Simple Action")); hud_action_publisher_add_description(publisher, description); // FIXME Waiting in tests QTestEventLoop::instance().enterLoopMSecs(100); { GMenuModel *model = G_MENU_MODEL( g_dbus_menu_model_get(connection, DBUS_NAME, "/com/canonical/hud/publisher")); ASSERT_TRUE(model); EXPECT_EQ(0, g_menu_model_get_n_items(model)); g_object_unref(model); } HudActionDescription *paramdesc = hud_action_description_new( "hud.simple-action", NULL); hud_action_description_set_attribute_value(paramdesc, G_MENU_ATTRIBUTE_LABEL, g_variant_new_string("Parameterized Action")); hud_action_publisher_add_description(publisher, paramdesc); GMenu * menu = g_menu_new(); g_menu_append_item(menu, g_menu_item_new("Item One", "hud.simple-action")); g_menu_append_item(menu, g_menu_item_new("Item Two", "hud.simple-action")); g_menu_append_item(menu, g_menu_item_new("Item Three", "hud.simple-action")); hud_action_description_set_parameterized(paramdesc, G_MENU_MODEL(menu)); // FIXME Waiting in tests QTestEventLoop::instance().enterLoopMSecs(100); { GMenuModel *model = G_MENU_MODEL( g_dbus_menu_model_get(connection, DBUS_NAME, "/com/canonical/hud/publisher")); EXPECT_TRUE(model); EXPECT_EQ(0, g_menu_model_get_n_items(model)); EXPECT_TRUE(g_menu_model_is_mutable(model)); g_object_unref(model); } hud_action_description_unref(paramdesc); hud_action_description_unref(description); g_object_unref(application); g_object_unref(publisher); } } hud-14.04+14.04.20140604/tests/unit/libhud/CMakeLists.txt0000644000015301777760000000062412343623451023035 0ustar pbusernogroup00000000000000 set( UNIT_TESTS_SRC TestManager.cpp TestActionDescription.cpp TestActionPublisher.cpp ) add_executable( test-libhud-unit-tests ${UNIT_TESTS_SRC} ) target_link_libraries( test-libhud-unit-tests test-utils hud ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} ${QTDBUSTEST_LIBRARIES} ${QTDBUSMOCK_LIBRARIES} ) qt5_use_modules( test-libhud-unit-tests Test ) add_hud_test( test-libhud-unit-tests ) hud-14.04+14.04.20140604/tests/unit/libhud-client/0000755000015301777760000000000012343624372021552 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/unit/libhud-client/TestHudClient.cpp0000644000015301777760000001372112343623451024776 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include #include using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::client; using namespace hud::common; using namespace hud::testutils; namespace { class TestHudClient: public Test { protected: TestHudClient() : mock(dbus), hud(dbus, mock) { dbus.startServices(); hud.loadMethods(); } void createQuery() { client.reset(new HudClient()); QSignalSpy modelsChangedSpy(client.data(), SIGNAL(modelsChanged())); modelsChangedSpy.wait(); } virtual ~TestHudClient() { } void EXPECT_CALL(const QList &spy, int index, const QString &name, const QVariantList &args) { QVariant args2(QVariant::fromValue(args)); ASSERT_LT(index, spy.size()); const QVariantList &call(spy.at(index)); EXPECT_EQ(name, call.at(0).toString()); EXPECT_EQ(args2.toString().toStdString(), call.at(1).toString().toStdString()); } void updateInterfaceProperty(const QString &name, const QString &path, const QString &interface, const QString &property, const QVariant &value) { QDBusInterface propertyInterface(name, path, "org.freedesktop.DBus.Properties", dbus.sessionConnection()); propertyInterface.callWithArgumentList(QDBus::Block, "Set", QVariantList() << interface << property << value); OrgFreedesktopDBusMockInterface mockInterface(name, path, dbus.sessionConnection()); QVariantMap propertyMap; propertyMap[property] = value; mockInterface.EmitSignal("org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", QVariantList() << interface << propertyMap << QStringList()).waitForFinished(); } Q_SIGNALS: void modelsReady(); void queryFinished(); protected: DBusTestRunner dbus; DBusMock mock; MockHudService hud; QScopedPointer client; }; TEST_F(TestHudClient, Update) { QSignalSpy remoteQuerySpy(&hud.queryInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); createQuery(); client->setQuery("test2"); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "UpdateQuery", QVariantList() << "test2"); } TEST_F(TestHudClient, Voice) { QSignalSpy remoteQuerySpy(&hud.queryInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); createQuery(); /* Call the voice query */ QSignalSpy queryFinishedSpy(client.data(), SIGNAL(voiceQueryFinished(const QString &))); client->startVoiceQuery(); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "VoiceQuery", QVariantList()); queryFinishedSpy.wait(); ASSERT_EQ(1, queryFinishedSpy.size()); EXPECT_EQ(QVariantList() << "voice query", queryFinishedSpy.at(0)); } TEST_F(TestHudClient, UpdateApp) { QSignalSpy remoteQuerySpy(&hud.queryInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); createQuery(); /* Set App ID */ client->setAppstackApp("application-id"); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "UpdateApp", QVariantList() << "application-id"); } //TEST_F(TestHudClient, ExecuteCommand) { // QSignalSpy remoteQuerySpy(&hud.queryInterface(), // SIGNAL(MethodCalled(const QString &, const QVariantList &))); // // createQuery(); // // /* Execute a command */ // client->executeCommand(0); // // remoteQuerySpy.wait(); // EXPECT_CALL(remoteQuerySpy, 0, "ExecuteCommand", // QVariantList() << qulonglong(0) << uint(0)); //} // //TEST_F(TestHudClient, ExecuteParameterized) { // QSignalSpy remoteQuerySpy(&hud.queryInterface(), // SIGNAL(MethodCalled(const QString &, const QVariantList &))); // // createQuery(); // // /* Execute a parameterized command */ // HudClientParam *param = hud_client_query_execute_param_command(query, // g_variant_new_variant(g_variant_new_uint64(4321)), 1234); // // remoteQuerySpy.wait(); // EXPECT_CALL(remoteQuerySpy, 0, "ExecuteParameterized", // QVariantList() << qulonglong(4321) << uint(1234)); // // g_object_unref(param); //} // //TEST_F(TestHudClient, ExecuteToolbar) { // QSignalSpy remoteQuerySpy(&hud.queryInterface(), // SIGNAL(MethodCalled(const QString &, const QVariantList &))); // // createQuery(); // // /* Start attacking the toolbar */ // hud_client_query_execute_toolbar_item(query, // HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN, 12345); // remoteQuerySpy.wait(); // EXPECT_CALL(remoteQuerySpy, 0, "ExecuteToolbar", // QVariantList() << "fullscreen" << uint(1234)); // remoteQuerySpy.clear(); // // hud_client_query_execute_toolbar_item(query, HUD_CLIENT_QUERY_TOOLBAR_HELP, // 12); // remoteQuerySpy.wait(); // EXPECT_CALL(remoteQuerySpy, 0, "ExecuteToolbar", // QVariantList() << "help" << uint(12)); // remoteQuerySpy.clear(); // // hud_client_query_execute_toolbar_item(query, // HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES, 312); // remoteQuerySpy.wait(); // EXPECT_CALL(remoteQuerySpy, 0, "ExecuteToolbar", // QVariantList() << "preferences" << uint(312)); // remoteQuerySpy.clear(); // // hud_client_query_execute_toolbar_item(query, HUD_CLIENT_QUERY_TOOLBAR_UNDO, // 53312); // remoteQuerySpy.wait(); // EXPECT_CALL(remoteQuerySpy, 0, "ExecuteToolbar", // QVariantList() << "undo" << uint(53312)); // remoteQuerySpy.clear(); //} // }// namespace hud-14.04+14.04.20140604/tests/unit/libhud-client/TestQuery.cpp0000644000015301777760000002742312343623451024230 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include #include #include using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::testutils; namespace { class TestQuery: public QObject, public Test { Q_OBJECT protected: TestQuery() : mock(dbus), hud(dbus, mock), query(nullptr) { dbus.startServices(); hud.loadMethods(); } void createQuery() { QSignalSpy querySpy(this, SIGNAL(modelsReady())); /* Create a query */ query = hud_client_query_new("test"); /* Wait for the models to be ready */ g_signal_connect(G_OBJECT(query), HUD_CLIENT_QUERY_SIGNAL_MODELS_CHANGED, G_CALLBACK(callbackModelsReady), this); querySpy.wait(); /* Check the models */ ASSERT_TRUE(DEE_IS_MODEL(hud_client_query_get_results_model(query))); ASSERT_TRUE(DEE_IS_MODEL(hud_client_query_get_appstack_model(query))); } void createQuery(HudClientConnection *client_connection) { QSignalSpy querySpy(this, SIGNAL(modelsReady())); /* Create a query */ query = hud_client_query_new_for_connection("test", client_connection); /* Wait for the models to be ready */ g_signal_connect(G_OBJECT(query), HUD_CLIENT_QUERY_SIGNAL_MODELS_CHANGED, G_CALLBACK(callbackModelsReady), this); querySpy.wait(); /* Check the models */ ASSERT_TRUE(DEE_IS_MODEL(hud_client_query_get_results_model(query))); ASSERT_TRUE(DEE_IS_MODEL(hud_client_query_get_appstack_model(query))); } virtual ~TestQuery() { g_clear_object(&query); } void EXPECT_CALL(const QList &spy, int index, const QString &name, const QVariantList &args) { QVariant args2(QVariant::fromValue(args)); ASSERT_LT(index, spy.size()); const QVariantList &call(spy.at(index)); EXPECT_EQ(name, call.at(0).toString()); EXPECT_EQ(args2.toString().toStdString(), call.at(1).toString().toStdString()); } static void callbackModelsReady(HudClientQuery *query, gpointer user_data) { Q_UNUSED(query); TestQuery *self = static_cast(user_data); self->modelsReady(); } static void callbackVoiceQueryFinished(HudClientQuery *query, GDBusMethodInvocation *invocation, gpointer user_data) { Q_UNUSED(query); Q_UNUSED(invocation); TestQuery *self = static_cast(user_data); self->queryFinished(); } void updateInterfaceProperty(const QString &name, const QString &path, const QString &interface, const QString &property, const QVariant &value) { QDBusInterface propertyInterface(name, path, "org.freedesktop.DBus.Properties", dbus.sessionConnection()); propertyInterface.callWithArgumentList(QDBus::Block, "Set", QVariantList() << interface << property << value); OrgFreedesktopDBusMockInterface mockInterface(name, path, dbus.sessionConnection()); QVariantMap propertyMap; propertyMap[property] = value; mockInterface.EmitSignal("org.freedesktop.DBus.Properties", "PropertiesChanged", "sa{sv}as", QVariantList() << interface << propertyMap << QStringList()).waitForFinished(); } Q_SIGNALS: void modelsReady(); void queryFinished(); protected: DBusTestRunner dbus; DBusMock mock; MockHudService hud; HudClientQuery *query; }; TEST_F(TestQuery, Create) { createQuery(); EXPECT_STREQ("test", hud_client_query_get_query(query)); HudClientConnection * client_connection = NULL; gchar * search = NULL; g_object_get(G_OBJECT(query), "query", &search, "connection", &client_connection, NULL); EXPECT_STREQ("test", search); ASSERT_TRUE(HUD_CLIENT_IS_CONNECTION(client_connection)); g_free(search); g_object_unref(client_connection); } TEST_F(TestQuery, Custom) { /* Create a connection */ HudClientConnection *clientConnection = hud_client_connection_new( DBUS_NAME, DBUS_PATH); ASSERT_TRUE(HUD_CLIENT_IS_CONNECTION(clientConnection)); createQuery(clientConnection); EXPECT_STREQ("test", hud_client_query_get_query(query)); /* Make sure the connection is the same */ HudClientConnection *testcon = NULL; g_object_get(G_OBJECT(query), "connection", &testcon, NULL); ASSERT_TRUE(HUD_CLIENT_IS_CONNECTION(testcon)); ASSERT_EQ(testcon, clientConnection); g_object_unref(testcon); /* Clean up */ g_object_unref(clientConnection); } TEST_F(TestQuery, Update) { QSignalSpy remoteQuerySpy(&hud.queryInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); createQuery(); hud_client_query_set_query(query, "test2"); EXPECT_STREQ("test2", hud_client_query_get_query(query)); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "UpdateQuery", QVariantList() << "test2"); } TEST_F(TestQuery, Voice) { QSignalSpy remoteQuerySpy(&hud.queryInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); createQuery(); /* Call the voice query */ g_signal_connect(G_OBJECT(query), "voice-query-finished", G_CALLBACK(callbackVoiceQueryFinished), this); QSignalSpy queryFinishedSpy(this, SIGNAL(queryFinished())); hud_client_query_voice_query(query); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "VoiceQuery", QVariantList()); queryFinishedSpy.wait(); EXPECT_EQ(1, queryFinishedSpy.size()); } TEST_F(TestQuery, UpdateApp) { QSignalSpy remoteQuerySpy(&hud.queryInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); createQuery(); /* Set App ID */ hud_client_query_set_appstack_app(query, "application-id"); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "UpdateApp", QVariantList() << "application-id"); } TEST_F(TestQuery, ExecuteCommand) { QSignalSpy remoteQuerySpy(&hud.queryInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); createQuery(); /* Execute a command */ hud_client_query_execute_command(query, g_variant_new_variant(g_variant_new_uint64(4321)), 1234); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "ExecuteCommand", QVariantList() << qulonglong(4321) << uint(1234)); } TEST_F(TestQuery, ExecuteParameterized) { QSignalSpy remoteQuerySpy(&hud.queryInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); createQuery(); /* Execute a parameterized command */ HudClientParam *param = hud_client_query_execute_param_command(query, g_variant_new_variant(g_variant_new_uint64(4321)), 1234); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "ExecuteParameterized", QVariantList() << qulonglong(4321) << uint(1234)); g_object_unref(param); } TEST_F(TestQuery, ExecuteToolbar) { QSignalSpy remoteQuerySpy(&hud.queryInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); createQuery(); /* Start attacking the toolbar */ hud_client_query_execute_toolbar_item(query, HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN, 12345); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "ExecuteToolbar", QVariantList() << "fullscreen" << uint(1234)); remoteQuerySpy.clear(); hud_client_query_execute_toolbar_item(query, HUD_CLIENT_QUERY_TOOLBAR_HELP, 12); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "ExecuteToolbar", QVariantList() << "help" << uint(12)); remoteQuerySpy.clear(); hud_client_query_execute_toolbar_item(query, HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES, 312); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "ExecuteToolbar", QVariantList() << "preferences" << uint(312)); remoteQuerySpy.clear(); hud_client_query_execute_toolbar_item(query, HUD_CLIENT_QUERY_TOOLBAR_UNDO, 53312); remoteQuerySpy.wait(); EXPECT_CALL(remoteQuerySpy, 0, "ExecuteToolbar", QVariantList() << "undo" << uint(53312)); remoteQuerySpy.clear(); } TEST_F(TestQuery, ToolbarEnabled) { QSignalSpy remoteQuerySpy(&hud.queryInterface(), SIGNAL(MethodCalled(const QString &, const QVariantList &))); createQuery(); /* Test toolbar disabled */ EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_HELP)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_UNDO)); /* Set an 'undo' item */ updateInterfaceProperty(DBusTypes::HUD_SERVICE_DBUS_NAME, MockHudService::QUERY_PATH, "com.canonical.hud.query", "ToolbarItems", QStringList() << "undo"); QTestEventLoop::instance().enterLoopMSecs(100); EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_HELP)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES)); EXPECT_TRUE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_UNDO)); /* Set an 'invalid' item */ updateInterfaceProperty(DBusTypes::HUD_SERVICE_DBUS_NAME, MockHudService::QUERY_PATH, "com.canonical.hud.query", "ToolbarItems", QStringList() << "invalid"); QTestEventLoop::instance().enterLoopMSecs(100); EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_HELP)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_UNDO)); /* Set all items */ updateInterfaceProperty(DBusTypes::HUD_SERVICE_DBUS_NAME, MockHudService::QUERY_PATH, "com.canonical.hud.query", "ToolbarItems", QStringList() << "fullscreen" << "undo" << "help" << "preferences"); QTestEventLoop::instance().enterLoopMSecs(100); EXPECT_TRUE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN)); EXPECT_TRUE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_HELP)); EXPECT_TRUE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES)); EXPECT_TRUE( hud_client_query_toolbar_item_active(query, HUD_CLIENT_QUERY_TOOLBAR_UNDO)); /* Check the array */ GArray * toolbar = hud_client_query_get_active_toolbar(query); ASSERT_EQ(4, toolbar->len); bool found_undo = false; bool found_help = false; bool found_prefs = false; bool found_full = false; for (uint i = 0; i < toolbar->len; ++i) { switch (g_array_index(toolbar, int, i)) { case HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN: EXPECT_FALSE(found_full); found_full = true; break; case HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES: EXPECT_FALSE(found_prefs); found_prefs = true; break; case HUD_CLIENT_QUERY_TOOLBAR_UNDO: EXPECT_FALSE(found_undo); found_undo = true; break; case HUD_CLIENT_QUERY_TOOLBAR_HELP: EXPECT_FALSE(found_help); found_help = true; break; default: EXPECT_FALSE(true); } } EXPECT_TRUE(found_undo); EXPECT_TRUE(found_help); EXPECT_TRUE(found_prefs); EXPECT_TRUE(found_full); } } #include "TestQuery.moc" hud-14.04+14.04.20140604/tests/unit/libhud-client/TestConnection.cpp0000644000015301777760000000550212343623451025214 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::testutils; namespace { class TestConnection: public QObject, public Test { Q_OBJECT protected: TestConnection() : mock(dbus), hud(dbus, mock), query(nullptr) { dbus.startServices(); hud.loadMethods(); } virtual ~TestConnection() { } static void callbackConnectionCreateQuery(HudClientConnection *con, const gchar *query_path, const gchar *results_name, const gchar *appstack_name, gpointer user_data) { Q_UNUSED(con); TestConnection *self = static_cast(user_data); self->queryPath = QString::fromUtf8(query_path); self->resultsName = QString::fromUtf8(results_name); self->appstackName = QString::fromUtf8(appstack_name); self->connectionCreateQuery(); } Q_SIGNALS: void connectionCreateQuery(); protected: DBusTestRunner dbus; DBusMock mock; MockHudService hud; HudClientQuery *query; QString queryPath; QString resultsName; QString appstackName; }; TEST_F(TestConnection, Create) { /* Create a connection */ HudClientConnection *client_connection = hud_client_connection_new( DBUS_NAME, DBUS_PATH); ASSERT_TRUE(HUD_CLIENT_IS_CONNECTION(client_connection)); QSignalSpy querySpy(this, SIGNAL(connectionCreateQuery())); hud_client_connection_new_query(client_connection, "test", callbackConnectionCreateQuery, this); querySpy.wait(); EXPECT_FALSE(queryPath.isEmpty()); EXPECT_FALSE(resultsName.isEmpty()); EXPECT_FALSE(appstackName.isEmpty()); EXPECT_STREQ(DBUS_NAME, hud_client_connection_get_address(client_connection)); gchar *address = NULL; gchar *path = NULL; g_object_get(G_OBJECT(client_connection), "address", &address, "path", &path, NULL); EXPECT_STREQ(DBUS_NAME, address); EXPECT_STREQ(DBUS_PATH, path); g_free(address); g_free(path); g_object_unref(client_connection); } } #include "TestConnection.moc" hud-14.04+14.04.20140604/tests/unit/libhud-client/CMakeLists.txt0000644000015301777760000000066712343623451024320 0ustar pbusernogroup00000000000000 set( UNIT_TESTS_SRC TestConnection.cpp TestHudClient.cpp TestParam.cpp TestQuery.cpp ) add_executable( test-libhud-client-unit-tests ${UNIT_TESTS_SRC} ) target_link_libraries( test-libhud-client-unit-tests test-utils hud-client ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} ${QTDBUSTEST_LIBRARIES} ${QTDBUSMOCK_LIBRARIES} ) qt5_use_modules( test-libhud-client-unit-tests Test ) add_hud_test( test-libhud-client-unit-tests ) hud-14.04+14.04.20140604/tests/unit/libhud-client/TestParam.cpp0000644000015301777760000000437012343623451024157 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include #include #include #include using namespace testing; using namespace QtDBusTest; using namespace QtDBusMock; using namespace hud::common; using namespace hud::testutils; namespace { class TestParam: public Test { protected: TestParam() : mock(dbus) { dbus.startServices(); } virtual ~TestParam() { } void startDBusMenu(const QString &name, const QString &path, const QString &json) { menuService.reset( new QProcessDBusService(name, QDBusConnection::SessionBus, DBUSMENU_JSON_LOADER, QStringList() << name << path << json)); menuService->start(dbus.sessionConnection()); } protected: DBusTestRunner dbus; DBusMock mock; QSharedPointer menuService; }; TEST_F(TestParam, Create) { HudClientParam *param = hud_client_param_new("app.dbus.name", "prefix", "base_action", "/action/path", "/model/path", 1); EXPECT_TRUE(param); g_object_unref(param); } TEST_F(TestParam, GetActions) { startDBusMenu("app.dbus.name", "/menu", JSON_SOURCE_ONE); HudClientParam* param = hud_client_param_new("app.dbus.name", "prefix", "base_action", "/action/path", "/model/path", 1); GActionGroup *action_group = hud_client_param_get_actions(param); EXPECT_TRUE(action_group); g_object_unref(param); } } hud-14.04+14.04.20140604/tests/unit/CMakeLists.txt0000644000015301777760000000030312343623451021560 0ustar pbusernogroup00000000000000 add_definitions( -pedantic -Wall -Wextra ) add_subdirectory(libhud) add_subdirectory(libhud-client) add_subdirectory(qtgmenu) add_subdirectory(service) add_subdirectory(window-stack-bridge) hud-14.04+14.04.20140604/tests/unit/qtgmenu/0000755000015301777760000000000012343624372020507 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/unit/qtgmenu/TestQtGMenu.cpp0000644000015301777760000004355612343623523023405 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include #include #include #include #include #undef signals #include using namespace qtgmenu; using namespace testing; namespace { class TestQtGMenu : public QObject, public Test { Q_OBJECT protected: TestQtGMenu() : m_importer( c_service, QDBusObjectPath( c_path ), "app", QDBusObjectPath( c_path ) ), m_items_changed_spy( &m_importer, SIGNAL( MenuItemsChanged() ) ), m_action_added_spy( &m_importer, SIGNAL( ActionAdded( QString ) ) ), m_action_removed_spy( &m_importer, SIGNAL( ActionRemoved( QString ) ) ), m_action_enabled_spy( &m_importer, SIGNAL( ActionEnabled( QString, bool ) ) ), m_action_state_changed_spy( &m_importer, SIGNAL( ActionStateChanged( QString, QVariant ) ) ), m_action_activated_spy( this, SIGNAL( ActionActivated( QString, QVariant ) ) ) { m_owner_id = g_bus_own_name( G_BUS_TYPE_SESSION, c_service, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL, NULL ); m_connection = g_bus_get_sync( G_BUS_TYPE_SESSION, NULL, NULL ); m_menu = g_menu_new(); m_actions = g_simple_action_group_new(); } virtual ~TestQtGMenu() { g_object_unref( m_actions ); g_object_unref( m_menu ); g_object_unref( m_connection ); g_bus_unown_name( m_owner_id ); } int GetGMenuSize() { QSharedPointer menu = m_importer.GetGMenuModel(); if( !menu ) { return 0; } gint item_count = g_menu_model_get_n_items( G_MENU_MODEL( menu.data() ) ); return item_count; } int GetGActionCount() { QSharedPointer actions = m_importer.GetGActionGroup(); if( !actions ) { return 0; } gchar** actions_list = g_action_group_list_actions( actions.data() ); int action_count = 0; while( actions_list[action_count] != nullptr ) { ++action_count; } g_strfreev( actions_list ); return action_count; } static void ActivateAction( GSimpleAction* simple, GVariant* parameter, gpointer user_data ) { TestQtGMenu* self = reinterpret_cast< TestQtGMenu* >( user_data ); const gchar* action_name = g_action_get_name( G_ACTION( simple ) ); emit self->ActionActivated( action_name, QtGMenuUtils::GVariantToQVariant( parameter ) ); } void ExportGMenu() { // export menu m_menu_export_id = g_dbus_connection_export_menu_model( m_connection, c_path, G_MENU_MODEL( m_menu ), NULL ); // build m_menu GMenu* menus_section = g_menu_new(); g_menu_append_section( m_menu, "Menus", G_MENU_MODEL( menus_section ) ); m_items_changed_spy.wait(); EXPECT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); //-- build file menu GMenu* file_submenu = g_menu_new(); GMenu* files_section = g_menu_new(); GMenuItem* menu_item = g_menu_item_new( "New", "app.new" ); g_menu_item_set_attribute_value( menu_item, "accel", g_variant_new_string( "N" ) ); g_menu_append_item( files_section, menu_item ); g_object_unref( menu_item ); g_menu_append( files_section, "Open", "app.open" ); g_menu_append_section( file_submenu, "Files", G_MENU_MODEL( files_section ) ); g_object_unref( files_section ); GMenu* mod_section = g_menu_new(); g_menu_append( mod_section, "Lock", "app.lock" ); g_menu_append_section( file_submenu, "Modify", G_MENU_MODEL( mod_section ) ); g_object_unref( mod_section ); g_menu_append_submenu( menus_section, "File", G_MENU_MODEL( file_submenu ) ); m_items_changed_spy.wait(); EXPECT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); g_object_unref( file_submenu ); //-- build edit menu GMenu* edit_submenu = g_menu_new(); GMenu* style_submenu = g_menu_new(); g_menu_append( style_submenu, "Plain", "app.text_plain" ); g_menu_append( style_submenu, "Bold", "app.text_bold" ); g_menu_append_submenu( menus_section, "Edit", G_MENU_MODEL( edit_submenu ) ); m_items_changed_spy.wait(); EXPECT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); g_menu_append_submenu( edit_submenu, "Style", G_MENU_MODEL( style_submenu ) ); m_items_changed_spy.wait(); EXPECT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); g_object_unref( style_submenu ); g_object_unref( edit_submenu ); g_object_unref( menus_section ); // export actions m_actions_export_id = g_dbus_connection_export_action_group( m_connection, c_path, G_ACTION_GROUP( m_actions ), NULL ); //-- stateless GSimpleAction* action = g_simple_action_new( "new", nullptr ); m_exported_actions.push_back( std::make_pair( action, g_signal_connect( action, "activate", G_CALLBACK( ActivateAction ), this ) ) ); g_action_map_add_action( G_ACTION_MAP( m_actions ), G_ACTION( action ) ); m_action_added_spy.wait(); EXPECT_FALSE( m_action_added_spy.empty() ); m_action_added_spy.clear(); action = g_simple_action_new( "open", nullptr ); m_exported_actions.push_back( std::make_pair( action, g_signal_connect( action, "activate", G_CALLBACK( ActivateAction ), this ) ) ); g_action_map_add_action( G_ACTION_MAP( m_actions ), G_ACTION( action ) ); m_action_added_spy.wait(); EXPECT_FALSE( m_action_added_spy.empty() ); m_action_added_spy.clear(); //-- boolean state action = g_simple_action_new_stateful( "lock", nullptr, g_variant_new_boolean( false ) ); m_exported_actions.push_back( std::make_pair( action, g_signal_connect( action, "activate", G_CALLBACK( ActivateAction ), this ) ) ); g_action_map_add_action( G_ACTION_MAP( m_actions ), G_ACTION( action ) ); m_action_added_spy.wait(); EXPECT_FALSE( m_action_added_spy.empty() ); m_action_added_spy.clear(); //-- string param + state action = g_simple_action_new_stateful( "text_plain", G_VARIANT_TYPE_STRING, g_variant_new_string( "app.text_plain" ) ); m_exported_actions.push_back( std::make_pair( action, g_signal_connect( action, "activate", G_CALLBACK( ActivateAction ), this ) ) ); g_action_map_add_action( G_ACTION_MAP( m_actions ), G_ACTION( action ) ); m_action_added_spy.wait(); EXPECT_FALSE( m_action_added_spy.empty() ); m_action_added_spy.clear(); action = g_simple_action_new_stateful( "text_bold", G_VARIANT_TYPE_STRING, g_variant_new_string( "app.text_plain" ) ); m_exported_actions.push_back( std::make_pair( action, g_signal_connect( action, "activate", G_CALLBACK( ActivateAction ), this ) ) ); g_action_map_add_action( G_ACTION_MAP( m_actions ), G_ACTION( action ) ); m_action_added_spy.wait(); EXPECT_FALSE( m_action_added_spy.empty() ); m_action_added_spy.clear(); } void UnexportGMenu() { // disconnect signal handlers for( auto& action : m_exported_actions ) { g_signal_handler_disconnect( action.first, action.second ); } // unexport menu g_dbus_connection_unexport_menu_model( m_connection, m_menu_export_id ); m_importer.Refresh(); EXPECT_EQ( 0, GetGMenuSize() ); // unexport actions g_dbus_connection_unexport_action_group( m_connection, m_actions_export_id ); m_importer.Refresh(); EXPECT_EQ( 0, GetGActionCount() ); } Q_SIGNALS: void ActionActivated( QString action_name, QVariant parameter ); protected: constexpr static const char* c_service = "com.canonical.qtgmenu"; constexpr static const char* c_path = "/com/canonical/qtgmenu"; guint m_owner_id = 0; guint m_menu_export_id = 0; guint m_actions_export_id = 0; GDBusConnection* m_connection = nullptr; GMenu* m_menu = nullptr; GSimpleActionGroup* m_actions = nullptr; QtGMenuImporter m_importer; QSignalSpy m_items_changed_spy; QSignalSpy m_action_added_spy; QSignalSpy m_action_removed_spy; QSignalSpy m_action_enabled_spy; QSignalSpy m_action_state_changed_spy; QSignalSpy m_action_activated_spy; std::vector< std::pair< GSimpleAction*, gulong > > m_exported_actions; }; TEST_F( TestQtGMenu, ExportImportGMenu ) { // no menu exported EXPECT_EQ( 0, GetGMenuSize() ); // export menu m_menu_export_id = g_dbus_connection_export_menu_model( m_connection, c_path, G_MENU_MODEL( m_menu ), NULL ); // add 1 item g_menu_append( m_menu, "New", "app.new" ); m_items_changed_spy.wait(); EXPECT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); EXPECT_NE( nullptr, m_importer.GetQMenu() ); EXPECT_EQ( 1, GetGMenuSize() ); // add 2 items g_menu_append( m_menu, "Add", "app.add" ); m_items_changed_spy.wait(); EXPECT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); g_menu_append( m_menu, "Del", "app.del" ); m_items_changed_spy.wait(); EXPECT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); EXPECT_EQ( 3, GetGMenuSize() ); // remove 1 item g_menu_remove( m_menu, 2 ); m_items_changed_spy.wait(); EXPECT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); EXPECT_EQ( 2, GetGMenuSize() ); // unexport menu g_dbus_connection_unexport_menu_model( m_connection, m_menu_export_id ); m_importer.Refresh(); EXPECT_EQ( 0, GetGMenuSize() ); } TEST_F( TestQtGMenu, ExportImportGActions ) { // no actions exported EXPECT_EQ( 0, GetGActionCount() ); // export actions m_actions_export_id = g_dbus_connection_export_action_group( m_connection, c_path, G_ACTION_GROUP( m_actions ), NULL ); // add 1 action GSimpleAction* action = g_simple_action_new_stateful( "new", nullptr, g_variant_new_boolean( false ) ); g_action_map_add_action( G_ACTION_MAP( m_actions ), G_ACTION( action ) ); m_action_added_spy.wait(); EXPECT_FALSE( m_action_added_spy.empty() ); EXPECT_EQ( "new", m_action_added_spy.at( 0 ).at( 0 ).toString().toStdString() ); m_action_added_spy.clear(); EXPECT_NE( nullptr, m_importer.GetGActionGroup() ); EXPECT_EQ( 1, GetGActionCount() ); // disable / enable action g_simple_action_set_enabled( action, false ); m_action_enabled_spy.wait(); EXPECT_FALSE( m_action_enabled_spy.empty() ); EXPECT_EQ( "app.new", m_action_enabled_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "false", m_action_enabled_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_enabled_spy.clear(); g_simple_action_set_enabled( action, true ); m_action_enabled_spy.wait(); EXPECT_FALSE( m_action_enabled_spy.empty() ); EXPECT_EQ( "app.new", m_action_enabled_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "true", m_action_enabled_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_enabled_spy.clear(); // change action state g_action_change_state( G_ACTION( action ), g_variant_new_boolean( true ) ); m_action_state_changed_spy.wait(); EXPECT_FALSE( m_action_state_changed_spy.empty() ); EXPECT_EQ( "new", m_action_state_changed_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "true", m_action_state_changed_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_state_changed_spy.clear(); g_action_change_state( G_ACTION( action ), g_variant_new_boolean( false ) ); m_action_state_changed_spy.wait(); EXPECT_FALSE( m_action_state_changed_spy.empty() ); EXPECT_EQ( "new", m_action_state_changed_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "false", m_action_state_changed_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_state_changed_spy.clear(); // add 2 actions action = g_simple_action_new_stateful( "add", G_VARIANT_TYPE_BOOLEAN, FALSE ); g_action_map_add_action( G_ACTION_MAP( m_actions ), G_ACTION( action ) ); m_action_added_spy.wait(); EXPECT_FALSE( m_action_added_spy.empty() ); EXPECT_EQ( "add", m_action_added_spy.at( 0 ).at( 0 ).toString().toStdString() ); m_action_added_spy.clear(); action = g_simple_action_new_stateful( "del", G_VARIANT_TYPE_BOOLEAN, FALSE ); g_action_map_add_action( G_ACTION_MAP( m_actions ), G_ACTION( action ) ); m_action_added_spy.wait(); EXPECT_FALSE( m_action_added_spy.empty() ); EXPECT_EQ( "del", m_action_added_spy.at( 0 ).at( 0 ).toString().toStdString() ); m_action_added_spy.clear(); EXPECT_EQ( 3, GetGActionCount() ); // remove 1 action g_action_map_remove_action( G_ACTION_MAP( m_actions ), "del" ); m_action_removed_spy.wait(); EXPECT_FALSE( m_action_removed_spy.empty() ); EXPECT_EQ( "del", m_action_removed_spy.at( 0 ).at( 0 ).toString().toStdString() ); m_action_removed_spy.clear(); EXPECT_EQ( 2, GetGActionCount() ); // unexport actions g_dbus_connection_unexport_action_group( m_connection, m_actions_export_id ); m_importer.Refresh(); EXPECT_EQ( 0, GetGActionCount() ); } TEST_F( TestQtGMenu, QMenuStructure ) { ExportGMenu(); // import QMenu std::shared_ptr< QMenu > menu = m_importer.GetQMenu(); ASSERT_NE( nullptr, menu ); EXPECT_EQ( 2, menu->actions().size() ); EXPECT_EQ( "File", menu->actions().at( 0 )->text() ); EXPECT_EQ( "Edit", menu->actions().at( 1 )->text() ); // check file menu structure QMenu* file_menu = menu->actions().at( 0 )->menu(); ASSERT_NE( nullptr, file_menu ); EXPECT_EQ( 4, file_menu->actions().size() ); EXPECT_EQ( "File", file_menu->title() ); EXPECT_EQ( "New", file_menu->actions().at( 0 )->text() ); EXPECT_EQ( "Ctrl+N", file_menu->actions().at( 0 )->shortcut().toString().toStdString() ); EXPECT_EQ( "Open", file_menu->actions().at( 1 )->text() ); EXPECT_TRUE( file_menu->actions().at( 2 )->isSeparator() ); EXPECT_EQ( "Lock", file_menu->actions().at( 3 )->text() ); // check edit menu structure QMenu* edit_menu = menu->actions().at( 1 )->menu(); ASSERT_NE( nullptr, edit_menu ); EXPECT_EQ( 1, edit_menu->actions().size() ); EXPECT_EQ( "Edit", edit_menu->title() ); EXPECT_EQ( "Style", edit_menu->actions().at( 0 )->text() ); // check style submenu structure QMenu* style_submenu = edit_menu->actions().at( 0 )->menu(); ASSERT_NE( nullptr, style_submenu ); EXPECT_EQ( 2, style_submenu->actions().size() ); EXPECT_EQ( "Style", style_submenu->title() ); EXPECT_EQ( "Plain", style_submenu->actions().at( 0 )->text() ); EXPECT_EQ( "Bold", style_submenu->actions().at( 1 )->text() ); UnexportGMenu(); } TEST_F( TestQtGMenu, QMenuActionTriggers ) { ExportGMenu(); // import QMenu std::shared_ptr< QMenu > menu = m_importer.GetQMenu(); EXPECT_NE( nullptr, m_importer.GetQMenu() ); // trigger file menu items QMenu* file_menu = menu->actions().at( 0 )->menu(); ASSERT_NE( nullptr, file_menu ); file_menu->actions().at( 0 )->trigger(); m_action_activated_spy.wait(); ASSERT_FALSE( m_action_activated_spy.empty() ); EXPECT_EQ( "new", m_action_activated_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "", m_action_activated_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_activated_spy.clear(); file_menu->actions().at( 1 )->trigger(); m_action_activated_spy.wait(); ASSERT_FALSE( m_action_activated_spy.empty() ); EXPECT_EQ( "open", m_action_activated_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "", m_action_activated_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_activated_spy.clear(); file_menu->actions().at( 3 )->trigger(); m_action_activated_spy.wait(); ASSERT_FALSE( m_action_activated_spy.empty() ); EXPECT_EQ( "lock", m_action_activated_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "", m_action_activated_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_activated_spy.clear(); // trigger edit menu items QMenu* edit_menu = menu->actions().at( 1 )->menu(); ASSERT_NE( nullptr, edit_menu ); QMenu* style_submenu = edit_menu->actions().at( 0 )->menu(); ASSERT_NE( nullptr, style_submenu ); style_submenu->actions().at( 0 )->trigger(); m_action_activated_spy.wait(); EXPECT_FALSE( m_action_activated_spy.empty() ); EXPECT_EQ( "text_plain", m_action_activated_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "text_plain", m_action_activated_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_activated_spy.clear(); style_submenu->actions().at( 1 )->trigger(); m_action_activated_spy.wait(); EXPECT_FALSE( m_action_activated_spy.empty() ); EXPECT_EQ( "text_bold", m_action_activated_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "text_bold", m_action_activated_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_activated_spy.clear(); UnexportGMenu(); } TEST_F( TestQtGMenu, QMenuActionStates ) { ExportGMenu(); // import QMenu std::shared_ptr< QMenu > menu = m_importer.GetQMenu(); EXPECT_NE( nullptr, m_importer.GetQMenu() ); // enable / disable menu items QMenu* file_menu = menu->actions().at( 0 )->menu(); ASSERT_NE( nullptr, file_menu ); EXPECT_TRUE( file_menu->actions().at( 0 )->isEnabled() ); g_simple_action_set_enabled( m_exported_actions[0].first, false ); m_action_enabled_spy.wait(); EXPECT_FALSE( file_menu->actions().at( 0 )->isEnabled() ); g_simple_action_set_enabled( m_exported_actions[0].first, true ); m_action_enabled_spy.wait(); EXPECT_TRUE( file_menu->actions().at( 0 )->isEnabled() ); UnexportGMenu(); } } // namespace #include hud-14.04+14.04.20140604/tests/unit/qtgmenu/main.cpp0000644000015301777760000000170212343623451022134 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include #include int main( int argc, char **argv ) { qputenv("QT_QPA_PLATFORM", "minimal"); QApplication application( argc, argv ); ::testing::InitGoogleTest( &argc, argv ); return RUN_ALL_TESTS(); } hud-14.04+14.04.20140604/tests/unit/qtgmenu/CMakeLists.txt0000644000015301777760000000074012343623451023245 0ustar pbusernogroup00000000000000set( UNIT_TESTS_SRC TestQtGMenu.cpp ) add_executable( test-qtgmenu-unit-tests ${UNIT_TESTS_SRC} ) qt5_use_modules( test-qtgmenu-unit-tests Test ) add_library( qtgmenu-test-main main.cpp ) target_link_libraries( test-qtgmenu-unit-tests qtgmenu-test-main qtgmenu ${GIO2_LIBRARIES} ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} ${QTDBUSTEST_LIBRARIES} ${QTDBUSMOCK_LIBRARIES} ) add_hud_test( test-qtgmenu-unit-tests ) hud-14.04+14.04.20140604/tests/testutils/0000755000015301777760000000000012343624372020110 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/testutils/MockHudService.h0000644000015301777760000000313012343623451023126 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_TESTUTILS_MOCKHUDSERVICE_H_ #define HUD_TESTUTILS_MOCKHUDSERVICE_H_ #include #include #include namespace hud { namespace common { class AppstackModel; class ResultsModel; } namespace testutils { class Q_DECL_EXPORT MockHudService { public: static const QString QUERY_PATH; MockHudService(QtDBusTest::DBusTestRunner &dbus, QtDBusMock::DBusMock &mock); virtual ~MockHudService(); void loadMethods(); OrgFreedesktopDBusMockInterface & hudInterface(); OrgFreedesktopDBusMockInterface & applicationInterface(); OrgFreedesktopDBusMockInterface & queryInterface(); protected: QtDBusTest::DBusTestRunner &m_dbus; QtDBusMock::DBusMock &m_mock; QScopedPointer m_appstack; QScopedPointer m_results; }; } } #endif /* HUD_TESTUTILS_MOCKHUDSERVICE_H_ */ hud-14.04+14.04.20140604/tests/testutils/RawDBusTransformer.h0000644000015301777760000000236512343623451024016 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef RAWDBUSTRANSFORMER_H_ #define RAWDBUSTRANSFORMER_H_ #include #include #include namespace hud { namespace testutils { class RawDBusTransformer { private: explicit RawDBusTransformer(); virtual ~RawDBusTransformer(); public: static void transform(QVariantList &list); static void transform(QVariantMap &map); static void transform(QVariant &variant); static QVariant transform(const QDBusArgument & value); }; } /* namespace testutils */ } /* namespace hud */ #endif /* RAWDBUSTRANSFORMER_H_ */ hud-14.04+14.04.20140604/tests/testutils/MockHudService.cpp0000644000015301777760000001021112343623451023457 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include using namespace hud::common; using namespace hud::testutils; using namespace QtDBusTest; using namespace QtDBusMock; MockHudService::MockHudService(DBusTestRunner &dbus, DBusMock &mock) : m_dbus(dbus), m_mock(mock) { mock.registerCustomMock(DBusTypes::HUD_SERVICE_DBUS_NAME, DBusTypes::HUD_SERVICE_DBUS_PATH, DBusTypes::HUD_SERVICE_DBUS_NAME, QDBusConnection::SessionBus); } const QString MockHudService::QUERY_PATH("/com/canonical/hud/query0"); static void addMethod(QList &methods, const QString &name, const QString &inSig, const QString &outSig, const QString &code) { Method method; method.setName(name); method.setInSig(inSig); method.setOutSig(outSig); method.setCode(code); methods << method; } OrgFreedesktopDBusMockInterface & MockHudService::hudInterface() { return m_mock.mockInterface(DBusTypes::HUD_SERVICE_DBUS_NAME, DBusTypes::HUD_SERVICE_DBUS_PATH, DBusTypes::HUD_SERVICE_DBUS_NAME, QDBusConnection::SessionBus); } OrgFreedesktopDBusMockInterface & MockHudService::applicationInterface() { return m_mock.mockInterface(DBusTypes::HUD_SERVICE_DBUS_NAME, "/app/object", "com.canonical.hud.Application", QDBusConnection::SessionBus); } OrgFreedesktopDBusMockInterface & MockHudService::queryInterface() { return m_mock.mockInterface(DBusTypes::HUD_SERVICE_DBUS_NAME, QUERY_PATH, "com.canonical.hud.query", QDBusConnection::SessionBus); } void MockHudService::loadMethods() { OrgFreedesktopDBusMockInterface &hud(hudInterface()); { QVariantMap properties; properties["ResultsModel"] = "com.canonical.hud.query0.results"; properties["AppstackModel"] = "com.canonical.hud.query0.appstack"; properties["ToolbarItems"] = QStringList(); QList methods; addMethod(methods, "UpdateQuery", "s", "i", "ret = 1"); addMethod(methods, "VoiceQuery", "", "is", "ret = (1, 'voice query')"); addMethod(methods, "UpdateApp", "s", "i", "ret = 1"); addMethod(methods, "CloseQuery", "", "", ""); addMethod(methods, "ExecuteCommand", "vu", "", ""); addMethod(methods, "ExecuteParameterized", "vu", "sooi", "ret = ('action', '/action/path', '/model/path', 1)"); addMethod(methods, "ExecuteToolbar", "su", "", ""); hud.AddObject(QUERY_PATH, "com.canonical.hud.query", properties, methods).waitForFinished(); } m_results.reset(new ResultsModel(0)); m_results->beginChangeset(); m_results->addResult(0, "result1", QList>(), "description1", QList>(), "shortcut", 1, false); m_results->endChangeset(); m_appstack.reset(new AppstackModel(0)); m_appstack->beginChangeset(); m_appstack->addApplication("application-id", "icon", AppstackModel::ITEM_TYPE_FOCUSED_APP); m_appstack->endChangeset(); // Mock application { QVariantMap properties; QList methods; addMethod(methods, "AddSources", "a(usso)a(uso)", "", ""); hud.AddObject("/app/object", "com.canonical.hud.Application", properties, methods).waitForFinished(); } /* query */ hud.AddMethod(DBusTypes::HUD_SERVICE_DBUS_NAME, "CreateQuery", "s", "ossi", "ret = ('/com/canonical/hud/query0', 'com.canonical.hud.query0.results', 'com.canonical.hud.query0.appstack', dbus.Int32(0))").waitForFinished(); /* id */ hud.AddMethod(DBusTypes::HUD_SERVICE_DBUS_NAME, "RegisterApplication", "s", "o", "ret = ('/app/object')").waitForFinished(); } MockHudService::~MockHudService() { } hud-14.04+14.04.20140604/tests/testutils/RawDBusTransformer.cpp0000644000015301777760000000401512343623451024343 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include using namespace hud::testutils; RawDBusTransformer::RawDBusTransformer() { } RawDBusTransformer::~RawDBusTransformer() { } QVariant RawDBusTransformer::transform(const QDBusArgument & value) { switch (value.currentType()) { case QDBusArgument::ArrayType: { value.beginArray(); QVariantList list = transform(value).toList(); value.endArray(); return list; } case QDBusArgument::MapType: { QVariantMap map; value >> map; transform(map); return map; } case QDBusArgument::StructureType: { value.beginStructure(); QVariantList list; while (!value.atEnd()) { list << value.asVariant(); } value.endStructure(); return list; } default: break; } return QVariant(); } void RawDBusTransformer::transform(QVariant &variant) { if (variant.canConvert()) { QVariantList list = variant.toList(); transform(list); variant = list; } else if (variant.canConvert()) { QDBusArgument value(variant.value()); variant = transform(value); } } void RawDBusTransformer::transform(QVariantMap &map) { for (auto it(map.begin()); it != map.end(); ++it) { transform(*it); } } void RawDBusTransformer::transform(QVariantList &list) { for (auto it(list.begin()); it != list.end(); ++it) { transform(*it); } } hud-14.04+14.04.20140604/tests/testutils/main.cpp0000644000015301777760000000244512343623451021542 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include int main(int argc, char **argv) { qputenv("QT_QPA_PLATFORM", "minimal"); qputenv("HUD_IGNORE_SEARCH_SETTINGS", "1"); qputenv("HUD_STORE_USAGE_DATA", "FALSE"); // qputenv("LANG", "C.UTF-8"); unsetenv("LC_ALL"); setlocale(LC_ALL, ""); bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain(GETTEXT_PACKAGE); QApplication application(argc, argv); hud::common::DBusTypes::registerMetaTypes(); QtDBusMock::DBusMock::registerMetaTypes(); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } hud-14.04+14.04.20140604/tests/testutils/CMakeLists.txt0000644000015301777760000000054312343623451022647 0ustar pbusernogroup00000000000000 add_definitions( -pedantic -Wall -Wextra ) set( TEST_UTILS_SRC MockHudService.cpp RawDBusTransformer.cpp main.cpp ) qt5_add_dbus_interface( TEST_UTILS_SRC ${HUD_TEST_XML} HudTestInterface ) add_library( test-utils SHARED ${TEST_UTILS_SRC} ) qt5_use_modules( test-utils Core Widgets ) target_link_libraries( test-utils hud-common ) hud-14.04+14.04.20140604/tests/testapps/0000755000015301777760000000000012343624372017713 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/testapps/CMakeLists.txt0000644000015301777760000000003212343623451022443 0ustar pbusernogroup00000000000000add_subdirectory(qtgmenu) hud-14.04+14.04.20140604/tests/testapps/qtgmenu/0000755000015301777760000000000012343624372021373 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/testapps/qtgmenu/MainWindow.cpp0000644000015301777760000000114712343623451024153 0ustar pbusernogroup00000000000000#include #include MainWindow::MainWindow(const QString &name, const QDBusObjectPath &actionPath, const QDBusObjectPath &menuPath) : m_menu_importer( name, menuPath, "", actionPath ) { m_refresh_connection = connect( &m_menu_importer, SIGNAL( MenuItemsChanged() ), this, SLOT( RefreshMenus() ) ); } MainWindow::~MainWindow() { disconnect( m_refresh_connection ); } void MainWindow::RefreshMenus() { menuBar()->clear(); m_top_menu = m_menu_importer.GetQMenu(); if( m_top_menu ) { menuBar()->addActions( m_top_menu->actions() ); } menuBar()->repaint(); } hud-14.04+14.04.20140604/tests/testapps/qtgmenu/main.cpp0000644000015301777760000000214012343623451023015 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include #include #include int main( int argc, char **argv ) { QApplication application( argc, argv ); if(argc != 4) { qWarning() << "Usage:" << argv[0] << "BUS_NAME ACTION_PATH MENU_PATH"; return 1; } MainWindow mainWindow(argv[1], QDBusObjectPath( argv[2] ), QDBusObjectPath( argv[3] ) ); mainWindow.show(); return application.exec(); } hud-14.04+14.04.20140604/tests/testapps/qtgmenu/CMakeLists.txt0000644000015301777760000000026712343623451024135 0ustar pbusernogroup00000000000000add_executable( qtgmenu-test-app MainWindow.cpp main.cpp ) qt5_use_modules( qtgmenu-test-app Widgets ) target_link_libraries( qtgmenu-test-app qtgmenu ) hud-14.04+14.04.20140604/tests/testapps/qtgmenu/MainWindow.h0000644000015301777760000000075212343623451023621 0ustar pbusernogroup00000000000000#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(const QString &name, const QDBusObjectPath &actionPath, const QDBusObjectPath &menuPath); ~MainWindow(); private Q_SLOTS: void RefreshMenus(); private: qtgmenu::QtGMenuImporter m_menu_importer; std::shared_ptr< QMenu > m_top_menu = nullptr; QMetaObject::Connection m_refresh_connection; }; #endif hud-14.04+14.04.20140604/tests/good-app-info/0000755000015301777760000000000012343624372020507 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/good-app-info/testapp.desktop.hud-app-info0000644000015301777760000000025712343623451026051 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/good-app-info/tons-of-entries.hud-app-info0000644000015301777760000001172212343623451025754 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/good-app-info/testapp100.desktop.hud-app-info0000644000015301777760000000026412343623451026270 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/run-under-xvfb.sh0000755000015301777760000000173612343623451021275 0ustar pbusernogroup00000000000000#!/bin/bash if [ "x$DISPLAY" == "x" ]; then Xvfb -ac -noreset -screen 0 800x600x16 -help 2>/dev/null 1>&2 XID=`for id in 101 102 103 104 105 106 107 197 199 211 223 227 293 307 308 309 310 311 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 4703 4721 4723 4729 4733 4751 9973 9974 9975 9976 9977 9978 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 ; do test -e /tmp/.X$id-lock || { echo $id; exit 0; }; done; exit 1` { Xvfb -ac -noreset -screen 0 800x600x16 :$XID -screen 0 800x600x16 -nolisten tcp -auth /dev/null >/dev/null 2>&1 & trap "kill -15 $! " 0 HUP INT QUIT TRAP USR1 PIPE TERM ; } || { echo "Gtk+Tests:ERROR: Failed to start Xvfb environment for X11 target tests."; exit 1; } DISPLAY=:$XID export DISPLAY echo "Setting up XVFB on $DISPLAY" fi export QT_QPA_PLATFORM="minimal" # Run specified arguments $@ hud-14.04+14.04.20140604/tests/CMakeLists.txt0000644000015301777760000000542212343623451020610 0ustar pbusernogroup00000000000000set(CMAKE_AUTOMOC OFF) include(FindGMock) set(CMAKE_AUTOMOC ON) find_package("Valgrind" REQUIRED) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${GMOCK_INCLUDE_DIRS}) include_directories(${GTEST_INCLUDE_DIRS}) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") add_definitions(-DHUD_SERVICE_BINARY="${CMAKE_BINARY_DIR}/service/hud-service") add_definitions(-DTEST_LOCALEDIR="${CMAKE_CURRENT_BINARY_DIR}/data") set(TEST_DATADIR "${CMAKE_CURRENT_SOURCE_DIR}/data") add_definitions(-DTEST_DATADIR="${TEST_DATADIR}") add_definitions(-DDATA_DIR="${DATA_DIR}") set(HUD_TEST_XML "${TEST_DATADIR}/com.canonical.hud.test.xml") ####################### # Test Fixtures ####################### add_definitions(-DJSON_SIMPLE="${TEST_DATADIR}/test-menu-input-simple.json") add_definitions(-DJSON_SHORTCUTS="${TEST_DATADIR}/test-menu-input-shortcuts.json") add_definitions(-DJSON_SOURCE_ONE="${TEST_DATADIR}/test-app-indicator-source-one.json") add_definitions(-DJSON_SOURCE_TWO="${TEST_DATADIR}/test-app-indicator-source-two.json") add_definitions(-DJSON_SOURCE_SESSION="${TEST_DATADIR}/test-indicator-source-session.json") add_definitions(-DJSON_SOURCE_DATETIME="${TEST_DATADIR}/test-indicator-source-datetime.json") add_definitions(-DJSON_SOURCE_SOUND="${TEST_DATADIR}/test-indicator-source-sound.json") add_definitions(-DJSON_SOURCE="${TEST_DATADIR}/test-source.json") add_definitions(-DDBUSMENU_JSON_LOADER="${CMAKE_CURRENT_BINARY_DIR}/menus/dbusmenu-json-loader") add_definitions(-DMODEL_DEEP="${CMAKE_CURRENT_BINARY_DIR}/menus/test-menu-input-model-deep") add_definitions(-DMODEL_SIMPLE="${CMAKE_CURRENT_BINARY_DIR}/menus/test-menu-input-model-simple") add_definitions(-DMODEL_SHORTCUTS="${CMAKE_CURRENT_BINARY_DIR}/menus/test-menu-input-model-shortcuts") add_definitions(-DMODEL_TOOLBAR_UNDO="${CMAKE_CURRENT_BINARY_DIR}/menus/test-menu-input-model-toolbar-undo") add_definitions(-DMODEL_TOOLBAR_UNKNOWN="${CMAKE_CURRENT_BINARY_DIR}/menus/test-menu-input-model-toolbar-unknown") add_definitions(-DMODEL_TOOLBAR_ALL="${CMAKE_CURRENT_BINARY_DIR}/menus/test-menu-input-model-toolbar-all") add_definitions(-DMODEL_TOOLBAR_DYNAMIC="${CMAKE_CURRENT_BINARY_DIR}/menus/test-menu-input-model-toolbar-dynamic") add_definitions(-DMODEL_LIBHUD="${CMAKE_CURRENT_BINARY_DIR}/menus/test-libhud-application") ######################## # Tests ######################## set(TEST_RUNNER "${CMAKE_CURRENT_SOURCE_DIR}/run-under-xvfb.sh") function(add_hud_test NAME) add_test( ${NAME} ${TEST_RUNNER} qdbus-simple-test-runner "${CMAKE_CURRENT_BINARY_DIR}/${NAME}" ) set_tests_properties( ${NAME} PROPERTIES ENVIRONMENT "GTEST_OUTPUT=xml:${CMAKE_CURRENT_BINARY_DIR}/" ) endfunction() add_subdirectory(integration) add_subdirectory(menus) add_subdirectory(testapps) add_subdirectory(testutils) add_subdirectory(unit) hud-14.04+14.04.20140604/tests/keyword-mapping/0000755000015301777760000000000012343624372021165 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/keyword-mapping/locale/0000755000015301777760000000000012343624372022424 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/keyword-mapping/locale/en_FAKELANG/0000755000015301777760000000000012343624372024256 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/keyword-mapping/locale/en_FAKELANG/LC_MESSAGES/0000755000015301777760000000000012343624372026043 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/keyword-mapping/gnome-terminal-en_FAKELANG.po0000644000015301777760000000225112343623451026270 0ustar pbusernogroup00000000000000# British translation for gnome-terminal. # Abigail Brady , 2002. # Gareth Owen , David Lodge , 2004. # Philip Withnall , 2009, 2010. # Bruce Cowan , 2009, 2010. # Bruce Cowan , 2011, 2012. msgid "" msgstr "" "Project-Id-Version: gnome-terminal\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-03-16 14:03+0000\n" "PO-Revision-Date: 2012-03-16 14:03+0100\n" "Last-Translator: Bruce Cowan \n" "Language-Team: British English \n" "Language: en_FAKELANG\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Virtaal 0.7.1\n" "X-Project-Style: gnome\n" #. File menu #: ../src/terminal-window.c:1797 ../src/terminal-window.c:1809 #: ../src/terminal-window.c:1956 msgid "Open _Terminal" msgstr "Open _Terminal" #: ../src/terminal-window.c:1798 ../src/terminal-window.c:1812 #: ../src/terminal-window.c:1959 msgid "Open Ta_b" msgstr "Open Ta_b" msgid "hud-keywords:Open Ta_b" msgstr "More Tabs; Gimme a Tab Bro; Giv Tab Plz" hud-14.04+14.04.20140604/tests/keyword-mapping/hud/0000755000015301777760000000000012343624372021745 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/keyword-mapping/hud/keywords/0000755000015301777760000000000012343624372023614 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/keyword-mapping/hud/keywords/gnome-terminal.xml0000644000015301777760000000045512343623451027255 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/tests/menus/0000755000015301777760000000000012343624372017177 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tests/menus/test-menu-input-model-shortcuts.c0000644000015301777760000000674112343623451025560 0ustar pbusernogroup00000000000000/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include static void action_callback(GSimpleAction *simple, G_GNUC_UNUSED GVariant *parameter, G_GNUC_UNUSED gpointer user_data) { gchar *name = NULL; g_object_get(simple, "name", &name, NULL); hud_test_com_canonical_hud_test_emit_action_invoked( HUD_TEST_COM_CANONICAL_HUD_TEST(user_data), name); g_free(name); } int main(int argv, char ** argc) { if (argv != 3) { g_print( "'%s ' is how you should use this program.\n", argc[0]); return 1; } #ifndef GLIB_VERSION_2_36 g_type_init (); #endif GMenu * menu = g_menu_new(); GMenuItem * mi = NULL; mi = g_menu_item_new("Save", "unity.save"); g_menu_item_set_attribute_value(mi, "accel", g_variant_new_string("S")); g_menu_append_item(menu, mi); mi = g_menu_item_new("Quiter", "unity.quiter"); g_menu_item_set_attribute_value(mi, "accel", g_variant_new_string("Q")); g_menu_append_item(menu, mi); mi = g_menu_item_new("Close", "unity.close"); g_menu_item_set_attribute_value(mi, "accel", g_variant_new_string("W")); g_menu_append_item(menu, mi); mi = g_menu_item_new("Nothing", "unity.nothing"); g_menu_append_item(menu, mi); GSimpleAction *save = g_simple_action_new("save", NULL); GSimpleAction *quiter = g_simple_action_new("quiter", NULL); GSimpleAction *close = g_simple_action_new("close", NULL); GSimpleAction *nothing = g_simple_action_new("nothing", NULL); GSimpleActionGroup * ag = g_simple_action_group_new(); g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(save)); g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(quiter)); g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(close)); g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(nothing)); HudTestComCanonicalHudTest *test_interface = hud_test_com_canonical_hud_test_skeleton_new(); GError *error = NULL; if (!g_dbus_interface_skeleton_export( G_DBUS_INTERFACE_SKELETON (test_interface), g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL), argc[2], &error)) { g_error("Failed to export test interface"); } g_signal_connect(save, "activate", G_CALLBACK(action_callback), test_interface); g_signal_connect(quiter, "activate", G_CALLBACK(action_callback), test_interface); g_signal_connect(close, "activate", G_CALLBACK(action_callback), test_interface); g_signal_connect(nothing, "activate", G_CALLBACK(action_callback), test_interface); GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_export_action_group(session, argc[2], G_ACTION_GROUP(ag), NULL); g_dbus_connection_export_menu_model(session, argc[2], G_MENU_MODEL(menu), NULL); g_bus_own_name(G_BUS_TYPE_SESSION, argc[1], 0, NULL, NULL, NULL, NULL, NULL); GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); return 0; } hud-14.04+14.04.20140604/tests/menus/FakeTouchApplication.h0000644000015301777760000000305212343623451023402 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef FAKETOUCHAPPLICATION_H_ #define FAKETOUCHAPPLICATION_H_ #include #include #include class TestAdaptor; class FakeTouchApplication: public QObject { public: static const constexpr char *UNITY_ACTION_EXPORT_PATH = "/com/canonical/unity/actions"; explicit FakeTouchApplication(const QString &applicationId, const QDBusConnection &connection, const QString &dbusName, const QString &dbusPath); ~FakeTouchApplication(); static void actionCallback(GSimpleAction *simple, GVariant *parameter, gpointer user_data); protected: QSharedPointer m_adaptor; QDBusConnection m_connection; GDBusConnection *m_sessionBus; HudManager *m_hudManager; GSimpleActionGroup *m_actionGroup; HudActionPublisher *m_actionPublisher; uint m_exportId; }; #endif /* FAKETOUCHAPPLICATION_H_ */ hud-14.04+14.04.20140604/tests/menus/test-menu-input-model-simple.c0000644000015301777760000000514012343623451025003 0ustar pbusernogroup00000000000000/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include int main (int argv, char ** argc) { if (!(argv == 3 || argv == 4)) { g_print("'%s [Is Application]' is how you should use this program.\n", argc[0]); return 1; } #ifndef GLIB_VERSION_2_36 g_type_init (); #endif gboolean is_application = (argv == 4 && !g_strcmp0(argc[3], "TRUE")); GMenu * menu = g_menu_new(); GMenuItem * item = NULL; GMenuItem * ditem = NULL; if (is_application) { item = g_menu_item_new("Simple", "app.simple"); ditem = g_menu_item_new("Disable", "app.disable"); } else { item = g_menu_item_new("Simple", "simple"); ditem = g_menu_item_new("Disable", "disable"); } g_menu_item_set_attribute_value(item, "description", g_variant_new_string("A simple description")); g_menu_item_set_attribute_value(item, "keywords", g_variant_new_string("hard;difficult;;challenging;")); g_menu_append_item(menu, item); g_menu_append_item(menu, ditem); GSimpleActionGroup * ag = g_simple_action_group_new(); g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(g_simple_action_new("simple", G_VARIANT_TYPE_BOOLEAN))); GSimpleAction * disable = g_simple_action_new("disable", NULL); g_simple_action_set_enabled(disable, FALSE); g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(disable)); GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_debug("Exporting Simple Action Group"); g_dbus_connection_export_action_group(session, argc[2], G_ACTION_GROUP(ag), NULL); g_debug("Exporting Simple Menu"); g_dbus_connection_export_menu_model(session, argc[2], G_MENU_MODEL(menu), NULL); g_debug("Investing in name ownership '%s'", argc[1]); g_bus_own_name(G_BUS_TYPE_SESSION, argc[1], 0, NULL, NULL, NULL, NULL, NULL); g_debug("Looping"); GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); return 0; } hud-14.04+14.04.20140604/tests/menus/test-menu-input-model-deep.c0000644000015301777760000000466312343623451024440 0ustar pbusernogroup00000000000000/* Copyright 2013 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include static const gchar * menuitems[] = { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", NULL }; static GMenu * items (const gchar * action, int entry) { if (menuitems[entry + 1] == NULL) { GMenu * menu = g_menu_new(); g_menu_append(menu, menuitems[entry], action); return menu; } GMenu * recursemenu = items(action, entry + 1); GMenu * menu = g_menu_new(); g_menu_append_submenu(menu, menuitems[entry], G_MENU_MODEL(recursemenu)); return menu; } int main (int argv, char ** argc) { if (!(argv == 3 || argv == 4)) { g_print("'%s [Is Application]' is how you should use this program.\n", argc[0]); return 1; } #ifndef GLIB_VERSION_2_36 g_type_init (); #endif gboolean is_application = (argv == 4 && !g_strcmp0(argc[3], "TRUE")); GMenu * menu = NULL; if (is_application) { menu = items("app.simple", 0); g_menu_append(menu, "Base", "app.simple"); } else { menu = items("simple", 0); g_menu_append(menu, "Base", "simple"); } GSimpleActionGroup * ag = g_simple_action_group_new(); if (is_application) g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(g_simple_action_new("app.simple", G_VARIANT_TYPE_BOOLEAN))); else g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(g_simple_action_new("simple", G_VARIANT_TYPE_BOOLEAN))); GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_export_action_group(session, argc[2], G_ACTION_GROUP(ag), NULL); g_dbus_connection_export_menu_model(session, argc[2], G_MENU_MODEL(menu), NULL); g_bus_own_name(G_BUS_TYPE_SESSION, argc[1], 0, NULL, NULL, NULL, NULL, NULL); GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); return 0; } hud-14.04+14.04.20140604/tests/menus/test-menu-input-model-toolbar-all.c0000644000015301777760000000432412343623451025725 0ustar pbusernogroup00000000000000/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include int main (int argv, char ** argc) { if (!(argv == 3 || argv == 4)) { g_print("'%s [Is Application]' is how you should use this program.\n", argc[0]); return 1; } #ifndef GLIB_VERSION_2_36 g_type_init (); #endif gboolean is_application = (argv == 4 && !g_strcmp0(argc[3], "TRUE")); GMenu * menu = g_menu_new(); gchar * toolbars[4] = { "undo", "preferences", "fullscreen", "help", }; int i; for (i = 0; i < 4; i++) { gchar * name = g_strdup_printf("Simple %d", i); GMenuItem * item = NULL; if (is_application) item = g_menu_item_new(name, "app.simple"); else item = g_menu_item_new(name, "simple"); g_free(name); g_menu_item_set_attribute_value(item, "hud-toolbar-item", g_variant_new_string(toolbars[i])); g_menu_append_item(menu, item); } GSimpleActionGroup * ag = g_simple_action_group_new(); if (is_application) g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(g_simple_action_new("app.simple", G_VARIANT_TYPE_BOOLEAN))); else g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(g_simple_action_new("simple", G_VARIANT_TYPE_BOOLEAN))); GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_export_action_group(session, argc[2], G_ACTION_GROUP(ag), NULL); g_dbus_connection_export_menu_model(session, argc[2], G_MENU_MODEL(menu), NULL); g_bus_own_name(G_BUS_TYPE_SESSION, argc[1], 0, NULL, NULL, NULL, NULL, NULL); GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); return 0; } hud-14.04+14.04.20140604/tests/menus/FakeTouchApplication.cpp0000644000015301777760000001525012343623451023740 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include FakeTouchApplication::FakeTouchApplication(const QString &applicationId, const QDBusConnection &connection, const QString &dbusName, const QString &dbusPath) : m_adaptor(new TestAdaptor(this)), m_connection(connection), m_exportId( 0) { if (!m_connection.registerObject(dbusPath, this)) { throw std::logic_error("Unable to register test object on DBus"); } if (!m_connection.registerService(dbusName)) { throw std::logic_error("Unable to register test service on DBus"); } GError *error = NULL; m_sessionBus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); if (error != NULL) { qWarning( "%s:\n" "\tCould not get session bus. Actions will not be available through D-Bus.\n" "\tReason: %s", __PRETTY_FUNCTION__, error->message); g_error_free(error); error = NULL; } m_hudManager = hud_manager_new(qPrintable(applicationId)); QStringList actionNames; actionNames << "save" << "quiter" << "close" << "nothing" << "undoer" << "helper"; // hud_action_description_set_attribute_value(desc, "hud-toolbar-item", g_variant_new_string("fullscreen")); // hud_action_description_set_attribute_value(desc, "hud-toolbar-item", g_variant_new_string("help")); // hud_action_description_set_attribute_value(desc, "hud-toolbar-item", g_variant_new_string("quit")); // hud_action_description_set_attribute_value(desc, "hud-toolbar-item", g_variant_new_string("settings")); // hud_action_description_set_attribute_value(desc, "hud-toolbar-item", g_variant_new_string("undo")); QMap toolbarNames; toolbarNames["undoer"] = "undo"; toolbarNames["helper"] = "help"; m_actionGroup = g_simple_action_group_new(); for (const QString &name : actionNames) { GSimpleAction *action = g_simple_action_new(qPrintable(name), NULL); g_signal_connect(action, "activate", G_CALLBACK(actionCallback), this); g_action_map_add_action(G_ACTION_MAP(m_actionGroup), G_ACTION(action)); } GSimpleAction *action = g_simple_action_new("fruit", G_VARIANT_TYPE_STRING); g_signal_connect(action, "activate", G_CALLBACK(actionCallback), this); g_action_map_add_action(G_ACTION_MAP(m_actionGroup), G_ACTION(action)); QStringList parameterizedActionNames; parameterizedActionNames << "apple" << "banana" << "cranberry"; for (const QString &name : parameterizedActionNames) { GSimpleAction *action = g_simple_action_new(qPrintable(name), G_VARIANT_TYPE_DOUBLE); g_signal_connect(action, "activate", G_CALLBACK(actionCallback), this); g_action_map_add_action(G_ACTION_MAP(m_actionGroup), G_ACTION(action)); } /* create a new HUD context */ m_actionPublisher = hud_action_publisher_new( HUD_ACTION_PUBLISHER_ALL_WINDOWS, "action_context_0"); hud_action_publisher_add_action_group(m_actionPublisher, "hud", UNITY_ACTION_EXPORT_PATH); hud_manager_add_actions(m_hudManager, m_actionPublisher); hud_manager_switch_window_context(m_hudManager, m_actionPublisher); for (const QString &name : actionNames) { HudActionDescription *desc = hud_action_description_new( qPrintable(QString("hud.%1").arg(name)), NULL); hud_action_description_set_attribute_value(desc, G_MENU_ATTRIBUTE_LABEL, g_variant_new_string(qPrintable(name))); hud_action_description_set_attribute_value(desc, "description", g_variant_new_string( qPrintable(QString("%1 description").arg(name)))); // hud_action_description_set_attribute_value(desc, "keywords", // g_variant_new_string(qPrintable(action->keywords()))); if (toolbarNames.contains(name)) { hud_action_description_set_attribute_value(desc, "hud-toolbar-item", g_variant_new_string(qPrintable(toolbarNames[name]))); } hud_action_publisher_add_description(m_actionPublisher, desc); } { HudActionDescription *desc = hud_action_description_new("hud.fruit", NULL); hud_action_description_set_attribute_value(desc, G_MENU_ATTRIBUTE_LABEL, g_variant_new_string("fruit")); hud_action_description_set_attribute_value(desc, "commitLabel", g_variant_new_string("choose fruit")); GMenu *menu = g_menu_new(); for (const QString &name : parameterizedActionNames) { GMenuItem* mi = g_menu_item_new(qPrintable(name), qPrintable(QString("hud.%1").arg(name))); g_menu_item_set_attribute_value(mi, "parameter-type", g_variant_new_string("slider")); g_menu_append_item(menu, mi); g_object_unref(mi); } hud_action_description_set_parameterized(desc, G_MENU_MODEL(menu)); hud_action_publisher_add_description(m_actionPublisher, desc); g_object_unref(menu); } if (m_sessionBus) { m_exportId = g_dbus_connection_export_action_group(m_sessionBus, UNITY_ACTION_EXPORT_PATH, G_ACTION_GROUP(m_actionGroup), &error); if (m_exportId == 0) { Q_ASSERT(error != NULL); qWarning( "%s:\n" "\tCould not export the main action group. Actions will not be available through D-Bus.\n" "\tReason: %s", __PRETTY_FUNCTION__, error->message); g_error_free(error); error = NULL; } } } FakeTouchApplication::~FakeTouchApplication() { g_dbus_connection_unexport_action_group(m_sessionBus, m_exportId); g_object_unref(m_actionPublisher); g_object_unref(m_actionGroup); g_object_unref(m_hudManager); g_object_unref(m_sessionBus); } void FakeTouchApplication::actionCallback(GSimpleAction *simple, GVariant *parameter, G_GNUC_UNUSED gpointer user_data) { FakeTouchApplication * self = static_cast(user_data); gchar *name = NULL; g_object_get(simple, "name", &name, NULL); if (parameter) { if (g_variant_is_of_type(parameter, G_VARIANT_TYPE_DOUBLE)) { self->m_adaptor->ParameterizedActionInvoked(name, QDBusVariant(g_variant_get_double(parameter))); } else if (g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) { self->m_adaptor->ParameterizedActionInvoked(name, QDBusVariant(g_variant_get_type_string(parameter))); } else { qWarning() << "unknown param type" << g_variant_get_type_string(parameter); } } else { self->m_adaptor->ActionInvoked(name); } g_free(name); } hud-14.04+14.04.20140604/tests/menus/test-menu-input-model-toolbar-dynamic.c0000644000015301777760000000716412343623451026606 0ustar pbusernogroup00000000000000/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include GMenu * menu = NULL; GSimpleActionGroup * ag = NULL; GMenuItem * undo_item = NULL; GMenuItem * pref_item = NULL; GMenuItem * full_item = NULL; GMenuItem * help_item = NULL; GAction * undo_action = NULL; GAction * pref_action = NULL; GAction * full_action = NULL; GAction * help_action = NULL; void undo_activated (void) { g_debug("Undo Activated"); g_simple_action_set_enabled(G_SIMPLE_ACTION(full_action), TRUE); return; } void prefs_activated (void) { g_debug("Preferences Activated"); g_menu_append_item(menu, help_item); return; } int main (int argv, char ** argc) { if (argv != 3) { g_print("'%s ' is how you should use this program.\n", argc[0]); return 1; } #ifndef GLIB_VERSION_2_36 g_type_init (); #endif g_debug("Dynamic Toolbar Starting"); menu = g_menu_new(); ag = g_simple_action_group_new(); /* UNDO, enables full item */ undo_item = g_menu_item_new("Undo Item", "undo"); g_menu_item_set_attribute_value(undo_item, "hud-toolbar-item", g_variant_new_string("undo")); g_menu_append_item(menu, undo_item); undo_action = G_ACTION(g_simple_action_new("undo", NULL)); g_signal_connect(G_OBJECT(undo_action), "activate", G_CALLBACK(undo_activated), NULL); g_action_map_add_action(G_ACTION_MAP(ag), undo_action); /* Peferences, adds the help item */ pref_item = g_menu_item_new("Preferences Item", "preferences"); g_menu_item_set_attribute_value(pref_item, "hud-toolbar-item", g_variant_new_string("preferences")); g_menu_append_item(menu, pref_item); pref_action = G_ACTION(g_simple_action_new("preferences", NULL)); g_signal_connect(G_OBJECT(pref_action), "activate", G_CALLBACK(prefs_activated), NULL); g_action_map_add_action(G_ACTION_MAP(ag), pref_action); /* Fullscreen, starts disabled */ full_item = g_menu_item_new("Fullscreen Item", "fullscreen"); g_menu_item_set_attribute_value(full_item, "hud-toolbar-item", g_variant_new_string("fullscreen")); g_menu_append_item(menu, full_item); full_action = G_ACTION(g_simple_action_new("fullscreen", NULL)); g_simple_action_set_enabled(G_SIMPLE_ACTION(full_action), FALSE); g_action_map_add_action(G_ACTION_MAP(ag), full_action); /* Help, not added at first */ help_item = g_menu_item_new("Help Item", "help"); g_menu_item_set_attribute_value(help_item, "hud-toolbar-item", g_variant_new_string("help")); /* NO! Can't you read! g_menu_append_item(menu, help_item); */ help_action = G_ACTION(g_simple_action_new("help", NULL)); g_action_map_add_action(G_ACTION_MAP(ag), help_action); /* All the rest of the boring stuff */ GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_export_action_group(session, argc[2], G_ACTION_GROUP(ag), NULL); g_dbus_connection_export_menu_model(session, argc[2], G_MENU_MODEL(menu), NULL); g_bus_own_name(G_BUS_TYPE_SESSION, argc[1], 0, NULL, NULL, NULL, NULL, NULL); GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); return 0; } hud-14.04+14.04.20140604/tests/menus/test-menu-input-model-toolbar-undo.c0000644000015301777760000000402212343623451026115 0ustar pbusernogroup00000000000000/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include int main (int argv, char ** argc) { if (!(argv == 3 || argv == 4)) { g_print("'%s [Is Application]' is how you should use this program.\n", argc[0]); return 1; } #ifndef GLIB_VERSION_2_36 g_type_init (); #endif gboolean is_application = (argv == 4 && !g_strcmp0(argc[3], "TRUE")); GMenu * menu = g_menu_new(); GMenuItem * item = NULL; if (is_application) item = g_menu_item_new("Simple", "app.simple"); else item = g_menu_item_new("Simple", "simple"); g_menu_item_set_attribute_value(item, "hud-toolbar-item", g_variant_new_string("undo")); g_menu_append_item(menu, item); GSimpleActionGroup * ag = g_simple_action_group_new(); if (is_application) g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(g_simple_action_new("app.simple", G_VARIANT_TYPE_BOOLEAN))); else g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(g_simple_action_new("simple", G_VARIANT_TYPE_BOOLEAN))); GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_export_action_group(session, argc[2], G_ACTION_GROUP(ag), NULL); g_dbus_connection_export_menu_model(session, argc[2], G_MENU_MODEL(menu), NULL); g_bus_own_name(G_BUS_TYPE_SESSION, argc[1], 0, NULL, NULL, NULL, NULL, NULL); GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); return 0; } hud-14.04+14.04.20140604/tests/menus/CMakeLists.txt0000644000015301777760000000574312343623451021745 0ustar pbusernogroup00000000000000 add_gdbus_codegen( OUTFILES HUD_TEST_INTERFACE_SOURCES NAME test-iface PREFIX com.canonical.hud.test. NAMESPACE HudTest SERVICE_XML ${HUD_TEST_XML} ) add_library( hud-test-interface STATIC ${HUD_TEST_INTERFACE_SOURCES} ) ####################### # Fake Touch App ####################### set(TEST_LIBHUD_APPLICATION_SOURCES test-libhud-application.cpp FakeTouchApplication.cpp ) qt5_add_dbus_adaptor( TEST_LIBHUD_APPLICATION_SOURCES ${HUD_TEST_XML} FakeTouchApplication.h FakeTouchApplication TestAdaptor ) add_executable(test-libhud-application ${TEST_LIBHUD_APPLICATION_SOURCES} ) target_link_libraries(test-libhud-application test-utils hud ) ####################### # Dbus JSON Loader ####################### pkg_check_modules(DBUSMENU_JSONLOADER REQUIRED dbusmenu-jsonloader-0.4) include_directories(${DBUSMENU_JSONLOADER_INCLUDE_DIRS}) add_executable(dbusmenu-json-loader dbusmenu-json-loader.c) target_link_libraries(dbusmenu-json-loader ${DBUSMENU_JSONLOADER_LIBRARIES} ) ####################### # Menu input model deep ####################### add_executable(test-menu-input-model-deep test-menu-input-model-deep.c) target_link_libraries(test-menu-input-model-deep ${GOBJECT2_LIBRARIES} ${GIO2_LIBRARIES} ) ######################### # Menu input model simple ######################### add_executable(test-menu-input-model-simple test-menu-input-model-simple.c) target_link_libraries(test-menu-input-model-simple ${GOBJECT2_LIBRARIES} ${GIO2_LIBRARIES} ) ############################ # Menu input model shortcuts ############################ add_executable(test-menu-input-model-shortcuts test-menu-input-model-shortcuts.c) target_link_libraries(test-menu-input-model-shortcuts ${GOBJECT2_LIBRARIES} ${GIO2_LIBRARIES} hud-test-interface ) #################################### # Menu input model toolbar undo item #################################### add_executable(test-menu-input-model-toolbar-undo test-menu-input-model-toolbar-undo.c) target_link_libraries(test-menu-input-model-toolbar-undo ${GOBJECT2_LIBRARIES} ${GIO2_LIBRARIES} ) ####################################### # Menu input model toolbar unknown item ####################################### add_executable(test-menu-input-model-toolbar-unknown test-menu-input-model-toolbar-unknown.c) target_link_libraries(test-menu-input-model-toolbar-unknown ${GOBJECT2_LIBRARIES} ${GIO2_LIBRARIES} ) #################################### # Menu input model toolbar all items #################################### add_executable(test-menu-input-model-toolbar-all test-menu-input-model-toolbar-all.c) target_link_libraries(test-menu-input-model-toolbar-all ${GOBJECT2_LIBRARIES} ${GIO2_LIBRARIES} ) ######################################## # Menu input model toolbar dynamic items ######################################## add_executable(test-menu-input-model-toolbar-dynamic test-menu-input-model-toolbar-dynamic.c) target_link_libraries(test-menu-input-model-toolbar-dynamic ${GOBJECT2_LIBRARIES} ${GIO2_LIBRARIES} )hud-14.04+14.04.20140604/tests/menus/dbusmenu-json-loader.c0000644000015301777760000000410612343623451023376 0ustar pbusernogroup00000000000000/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define G_LOG_DOMAIN "dbusmenu-json-loader" #include #include #include gchar * name = NULL; static void name_got (G_GNUC_UNUSED GDBusConnection * con, const gchar * name, G_GNUC_UNUSED gpointer user_data) { g_debug("Got name: %s", name); return; } static void name_lost (G_GNUC_UNUSED GDBusConnection * con, const gchar * name, G_GNUC_UNUSED gpointer user_data) { g_message("Lost (or unable to get) name: %s", name); return; } static gboolean setup_dbusmenu (gpointer user_data) { g_bus_own_name(G_BUS_TYPE_SESSION, name, 0, NULL, name_got, name_lost, NULL, NULL); GMainLoop * loop = (GMainLoop *)user_data; g_main_loop_quit(loop); return FALSE; } int main (int argv, char ** argc) { if (argv != 4) { g_print("'%s ' is how you should use this program.\n", argc[0]); return 1; } #ifndef GLIB_VERSION_2_36 g_type_init(); #endif DbusmenuMenuitem * root = dbusmenu_json_build_from_file(argc[3]); g_return_val_if_fail(root != NULL, FALSE); DbusmenuServer * server = dbusmenu_server_new(argc[2]); dbusmenu_server_set_root(server, root); name = argc[1]; GMainLoop * temploop = g_main_loop_new(NULL, FALSE); g_timeout_add(100, setup_dbusmenu, temploop); g_main_loop_run(temploop); g_main_loop_unref(temploop); GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); return 0; } hud-14.04+14.04.20140604/tests/menus/test-libhud-application.cpp0000644000015301777760000000240612343623451024427 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include static void exitQt(int sig) { Q_UNUSED(sig); QCoreApplication::exit(0); } int main(int argc, char **argv) { QCoreApplication application(argc, argv); if (argc != 4) { qCritical() << argv[0] << "APP_ID DBUS_NAME DBUS_PATH is how you should use this program.\n"; return 1; } signal(SIGINT, &exitQt); signal(SIGTERM, &exitQt); FakeTouchApplication fakeApp(argv[1], QDBusConnection::sessionBus(), argv[2], argv[3]); return application.exec(); } hud-14.04+14.04.20140604/tests/menus/test-menu-input-model-toolbar-unknown.c0000644000015301777760000000402512343623451026652 0ustar pbusernogroup00000000000000/* Copyright 2012 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include int main (int argv, char ** argc) { if (!(argv == 3 || argv == 4)) { g_print("'%s [Is Application]' is how you should use this program.\n", argc[0]); return 1; } #ifndef GLIB_VERSION_2_36 g_type_init (); #endif gboolean is_application = (argv == 4 && !g_strcmp0(argc[3], "TRUE")); GMenu * menu = g_menu_new(); GMenuItem * item = NULL; if (is_application) item = g_menu_item_new("Simple", "app.simple"); else item = g_menu_item_new("Simple", "simple"); g_menu_item_set_attribute_value(item, "hud-toolbar-item", g_variant_new_string("unknown")); g_menu_append_item(menu, item); GSimpleActionGroup * ag = g_simple_action_group_new(); if (is_application) g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(g_simple_action_new("app.simple", G_VARIANT_TYPE_BOOLEAN))); else g_action_map_add_action(G_ACTION_MAP(ag), G_ACTION(g_simple_action_new("simple", G_VARIANT_TYPE_BOOLEAN))); GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); g_dbus_connection_export_action_group(session, argc[2], G_ACTION_GROUP(ag), NULL); g_dbus_connection_export_menu_model(session, argc[2], G_MENU_MODEL(menu), NULL); g_bus_own_name(G_BUS_TYPE_SESSION, argc[1], 0, NULL, NULL, NULL, NULL, NULL); GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); return 0; } hud-14.04+14.04.20140604/build.sh0000755000015301777760000000272512343623451016347 0ustar pbusernogroup00000000000000#! /bin/bash set -e ECLIPSE=false CLEAN=false SOURCEDIR="$PWD" BRANCHNAME=`basename $SOURCEDIR` BUILDDIR="$SOURCEDIR/../$BRANCHNAME-build" usage() { echo "usage: $0 [OPTIONS] [BUILD_TYPE]\n" >&2 echo "Script to build hud. If BUILD_TYPE is not specified, it defaults to \"Debug\".\n" >&2 echo "OPTIONS:" >&2 echo " -e, --eclipse Generate Eclipse projects" >&2 echo " -c, --clean Clean the build tree before building" >&2 echo >&2 exit 1 } ARGS=`getopt -n$0 -u -a --longoptions="eclipse,clean,help" -o "sch" -- "$@"` [ $? -ne 0 ] && usage eval set -- "$ARGS" while [ $# -gt 0 ] do case "$1" in -e|--eclipse) ECLIPSE=true;; -c|--clean) CLEAN=true;; -h|--help) usage;; --) shift;break;; esac shift done [ $# -gt 1 ] && usage BUILD_TYPE="Debug" [ $# -eq 1 ] && BUILD_TYPE="$1" if [ -f "/usr/bin/ninja" ] ; then if $ECLIPSE; then GENERATOR="Eclipse CDT4 - Ninja" else GENERATOR="Ninja" fi BUILD_COMMAND="ninja" else if $ECLIPSE; then GENERATOR="Eclipse CDT4 - Unix Makefiles" else GENERATOR="Unix Makefiles" fi BUILD_COMMAND="make" fi echo "Using $BUILD_COMMAND to build" if $CLEAN; then rm -rf $BUILDDIR fi mkdir -p $BUILDDIR ( cd $BUILDDIR cmake "$SOURCEDIR" -G "$GENERATOR" \ -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ -DCMAKE_CXX_COMPILER_ARG1="-std=c++11" \ -DLOCAL_INSTALL=ON \ -DCMAKE_INSTALL_PREFIX="$SOURCEDIR/../$BRANCHNAME-install" $BUILD_COMMAND ) hud-14.04+14.04.20140604/service/0000755000015301777760000000000012343624372016346 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/service/Item.h0000644000015301777760000000224112343623451017411 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_ITEM_H_ #define HUD_SERVICE_ITEM_H_ #include #include #include namespace hud { namespace service { class Item { public: typedef QSharedPointer Ptr; Item(const QMenu *root, const QList &index, int lastIndex); virtual ~Item(); QList context() const; QAction *action() const; protected: const QMenu *m_root; QList m_index; int m_lastIndex; }; } } #endif /* HUD_SERVICE_ITEM_H_ */ hud-14.04+14.04.20140604/service/ApplicationList.cpp0000644000015301777760000000153112343623451022146 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; ApplicationList::ApplicationList() { } ApplicationList::~ApplicationList() { } hud-14.04+14.04.20140604/service/QGSettingsSearchSettings.h0000644000015301777760000000235312343623451023416 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_QGSETTINGSSEARCHSETTINGS_H_ #define HUD_SERVICE_QGSETTINGSSEARCHSETTINGS_H_ #include #include namespace hud { namespace service { class QGSettingsSearchSettings: public SearchSettings { public: QGSettingsSearchSettings(); virtual ~QGSettingsSearchSettings(); uint addPenalty() const; uint dropPenalty() const; uint endDropPenalty() const; uint swapPenalty() const; protected: QGSettings m_settings; }; } } #endif /* HUD_SERVICE_QGSETTINGSSEARCHSETTINGS_H_ */ hud-14.04+14.04.20140604/service/UsageTracker.cpp0000644000015301777760000000151212343623451021426 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; UsageTracker::UsageTracker() { } UsageTracker::~UsageTracker() { } hud-14.04+14.04.20140604/service/ApplicationListImpl.h0000644000015301777760000000466512343623451022450 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_APPLICATIONLISTIMPL_H_ #define HUD_SERVICE_APPLICATIONLISTIMPL_H_ #include #include #include #include #include #include namespace hud { namespace service { class Factory; class ApplicationListImpl: public ApplicationList { Q_OBJECT public: ApplicationListImpl(Factory &factory, QSharedPointer windowStack, QSharedPointer windowStackWatcher); virtual ~ApplicationListImpl(); QList applications() const override; Application::Ptr focusedApplication() const override; Window::Ptr focusedWindow() const override; Application::Ptr ensureApplication(const QString &applicationId) override; public Q_SLOTS: void FocusedWindowChanged(uint windowId, const QString &applicationId, uint stage); void WindowCreated(uint windowId, const QString &applicationId); void WindowDestroyed(uint windowId, const QString &applicationId); protected Q_SLOTS: void serviceUnregistered(const QString &service); protected: void ensureApplicationWithWindow(uint windowId, const QString& applicationId); void removeWindow(uint windowId, const QString& applicationId); void setFocusedWindow(Application::Ptr application, uint windowId); static bool isIgnoredApplication(const QString &applicationId); QSharedPointer m_windowStack; QSharedPointer m_windowStackWatcher; Factory &m_factory; QMap m_applications; Application::Ptr m_focusedApplication; uint m_focusedWindowId; }; } } #endif /* HUD_SERVICE_APPLICATIONLIST_IMPLH_ */ hud-14.04+14.04.20140604/service/WindowContext.h0000644000015301777760000000351212343623451021331 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_WINDOWCONTEXT_H_ #define HUD_SERVICE_WINDOWCONTEXT_H_ #include #include #include #include #include namespace qtgmenu { class QtGMenuImporter; } namespace hud { namespace service { class WindowContext: public QObject { Q_OBJECT public: struct MenuDefinition { explicit MenuDefinition() { } explicit MenuDefinition(const QString &name) : name(name) { } bool operator==(const MenuDefinition &other) const { return name == other.name && actionPath == other.actionPath && actionPrefix == other.actionPrefix && menuPath == other.menuPath; } QString name; QDBusObjectPath actionPath; QString actionPrefix; QDBusObjectPath menuPath; }; typedef QSharedPointer Ptr; explicit WindowContext(); virtual ~WindowContext(); virtual void setContext(const QString &context) = 0; virtual void addMenu(const QString &context, const MenuDefinition &menuDefinition) = 0; virtual Collector::Ptr activeCollector() = 0; Q_SIGNALS: void contextChanged(); }; } } #endif /* HUD_SERVICE_WINDOWCONTEXT_H_ */ hud-14.04+14.04.20140604/service/GMenuWindowCollector.cpp0000644000015301777760000000655112343623451023130 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include using namespace hud::service; using namespace qtgmenu; static const QStringList GMENU_WINDOW_PROPERTIES( { "_GTK_UNIQUE_BUS_NAME", "_GTK_APP_MENU_OBJECT_PATH", "_GTK_MENUBAR_OBJECT_PATH", "_GTK_APPLICATION_OBJECT_PATH", "_GTK_WINDOW_OBJECT_PATH", "_UNITY_OBJECT_PATH" }); GMenuWindowCollector::GMenuWindowCollector(unsigned int windowId, const QString &applicationId, QSharedPointer windowStack, Factory &factory) : m_windowStack(windowStack) { QDBusPendingReply windowPropertiesReply( windowStack->GetWindowProperties(windowId, applicationId, GMENU_WINDOW_PROPERTIES)); windowPropertiesReply.waitForFinished(); if (windowPropertiesReply.isError()) { qWarning() << windowPropertiesReply.error(); return; } QStringList windowProperties(windowPropertiesReply); if (windowProperties.isEmpty()) { return; } m_busName = windowProperties.at(0); // We're using the existence of the bus name property to determine // if this window has GMenus available at all. if (m_busName.isEmpty()) { return; } QSet menus; QMap actions; if (!windowProperties.at(1).isEmpty()) { // _GTK_APP_MENU_OBJECT_PATH -> menu menus << QDBusObjectPath(windowProperties.at(1)); } if (!windowProperties.at(2).isEmpty()) { // _GTK_MENUBAR_OBJECT_PATH -> menu menus << QDBusObjectPath(windowProperties.at(2)); } if (!windowProperties.at(3).isEmpty()) { // _GTK_APPLICATION_OBJECT_PATH -> actions with prefix "app" actions["app"] = QDBusObjectPath(windowProperties.at(3)); } if (!windowProperties.at(4).isEmpty()) { // _GTK_WINDOW_OBJECT_PATH -> actions with prefix "win" actions["win"] = QDBusObjectPath(windowProperties.at(4)); } if (!windowProperties.at(5).isEmpty()) { // _UNITY_OBJECT_PATH -> menu + action with prefix "unity" menus << QDBusObjectPath(windowProperties.at(5)); actions["unity"] = QDBusObjectPath(windowProperties.at(5)); } if (!actions.isEmpty()) { for (const QDBusObjectPath &menu : menus) { m_collectors << factory.newGMenuCollector(m_busName, actions, menu); } } } GMenuWindowCollector::~GMenuWindowCollector() { } bool GMenuWindowCollector::isValid() const { return !m_collectors.isEmpty(); } QList GMenuWindowCollector::activate() { QList tokens; for (Collector::Ptr collector : m_collectors) { tokens.append(collector->activate()); } return tokens; } void GMenuWindowCollector::deactivate() { } hud-14.04+14.04.20140604/service/DBusMenuCollector.cpp0000644000015301777760000001073112343623523022402 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include using namespace hud::common; using namespace hud::service; DBusMenuCollector::DBusMenuCollector(unsigned int windowId, QSharedPointer registrar) : m_windowId(windowId), m_registrar(registrar) { connect(registrar.data(), SIGNAL(WindowRegistered(uint, const QString &, const QDBusObjectPath &)), this, SLOT( WindowRegistered(uint, const QString &, const QDBusObjectPath &))); QDBusPendingReply windowReply = registrar->GetMenuForWindow(m_windowId); windowReply.waitForFinished(); if (windowReply.isError()) { return; } windowRegistered(windowReply.argumentAt<0>(), windowReply.argumentAt<1>()); } DBusMenuCollector::~DBusMenuCollector() { } void DBusMenuCollector::windowRegistered(const QString &service, const QDBusObjectPath &menuObjectPath) { if (service.isEmpty()) { return; } m_service = service; m_path = menuObjectPath; disconnect(m_registrar.data(), SIGNAL( WindowRegistered(uint, const QString &, const QDBusObjectPath &)), this, SLOT( WindowRegistered(uint, const QString &, const QDBusObjectPath &))); m_menuImporter.reset( new DBusMenuImporter(m_service, m_path.path(), DBusMenuImporterType::SYNCHRONOUS)); CollectorToken::Ptr collectorToken(m_collectorToken); if(collectorToken) { collectorToken->changed(); } } bool DBusMenuCollector::isValid() const { return !m_menuImporter.isNull(); } void DBusMenuCollector::openMenu(QMenu *menu, unsigned int &limit) { --limit; if (limit == 0) { QString error = "Hit DBusMenu safety valve opening menu at " + m_service + " " + m_path.path(); throw std::logic_error(error.toStdString()); } if (!menu) { return; } menu->aboutToShow(); for (int i(0); m_menuImporter && i < menu->actions().size(); ++i) { QAction *action = menu->actions().at(i); if (!action->isEnabled()) { continue; } if (action->isSeparator()) { continue; } QMenu *child(action->menu()); if (child) { openMenu(child, limit); } } } void DBusMenuCollector::hideMenu(QMenu *menu, unsigned int &limit) { --limit; if (limit == 0) { QString error = "Hit DBusMenu safety valve closing menu at " + m_service + " " + m_path.path(); throw std::logic_error(error.toStdString()); } for (int i(0); i < menu->actions().size(); ++i) { QAction *action = menu->actions().at(i); QMenu *child(action->menu()); if (child) { hideMenu(child, limit); } } menu->aboutToHide(); if(!m_menuImporter) { return; } } QList DBusMenuCollector::activate() { CollectorToken::Ptr collectorToken(m_collectorToken); if(m_menuImporter.isNull()) { return QList(); } if (collectorToken.isNull()) { try { unsigned int limit(50); openMenu(m_menuImporter->menu(), limit); } catch (std::logic_error &e) { qDebug() << e.what(); } if(m_menuImporter.isNull()) { return QList(); } collectorToken.reset( new CollectorToken(shared_from_this(), m_menuImporter->menu())); m_collectorToken = collectorToken; } return QList() << collectorToken; } void DBusMenuCollector::deactivate() { if(m_menuImporter.isNull()) { return; } try { unsigned int limit(50); hideMenu(m_menuImporter->menu(), limit); } catch (std::logic_error &e) { qDebug() << e.what(); } } void DBusMenuCollector::WindowRegistered(uint windowId, const QString &service, const QDBusObjectPath &menuObjectPath) { // Simply ignore updates for other windows if (windowId != m_windowId) { return; } windowRegistered(service, menuObjectPath); } hud-14.04+14.04.20140604/service/Collector.cpp0000644000015301777760000000220212343623451020771 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; Collector::Collector(QObject *parent) : QObject(parent) { } Collector::~Collector() { } CollectorToken::CollectorToken(Collector::Ptr collector, QMenu *menu) : m_collector(collector), m_menu(menu) { } CollectorToken::~CollectorToken() { if (Collector::Ptr collector = m_collector.lock()) { collector->deactivate(); } } QMenu * CollectorToken::menu() { return m_menu; } hud-14.04+14.04.20140604/service/HudService.cpp0000644000015301777760000000154412343623451021114 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; HudService::HudService(QObject *parent) : QObject(parent) { } HudService::~HudService() { } hud-14.04+14.04.20140604/service/GMenuCollector.cpp0000644000015301777760000000377112343623451021741 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include using namespace hud::service; using namespace qtgmenu; GMenuCollector::GMenuCollector(const QString &name, const QMap &actions, const QDBusObjectPath &menuPath) : m_name(name), m_actions(actions), m_menuPath(menuPath) { m_importer.reset(new QtGMenuImporter(m_name, m_menuPath, actions)); connect(m_importer.data(), SIGNAL(MenuItemsChanged()), this, SLOT(menuItemsChanged())); } GMenuCollector::~GMenuCollector() { } bool GMenuCollector::isValid() const { return !m_menuPath.path().isEmpty(); } QList GMenuCollector::activate() { CollectorToken::Ptr collectorToken(m_collectorToken); std::shared_ptr menu(m_importer->GetQMenu()); if (collectorToken.isNull() || menu != m_menu) { m_menu = menu; collectorToken.reset( new CollectorToken(shared_from_this(), m_menu ? m_menu.get() : nullptr)); m_collectorToken = collectorToken; } return QList() << collectorToken; } void GMenuCollector::deactivate() { } void GMenuCollector::menuItemsChanged() { CollectorToken::Ptr collectorToken(m_collectorToken); if (collectorToken) { collectorToken->changed(); } } hud-14.04+14.04.20140604/service/Window.cpp0000644000015301777760000000155512343623451020324 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; WindowToken::WindowToken() { } WindowToken::~WindowToken() { } Window::Window() { } Window::~Window() { } hud-14.04+14.04.20140604/service/ApplicationImpl.h0000644000015301777760000000526612343623451021612 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_APPLICATIONIMPL_H_ #define HUD_SERVICE_APPLICATIONIMPL_H_ #include #include #include #include #include #include #include #include #include #include #include class ApplicationAdaptor; namespace hud { namespace service { class Factory; class Q_DECL_EXPORT ApplicationImpl: public Application, protected QDBusContext { Q_OBJECT public: ApplicationImpl(const QString &applicationId, Factory &factory, const QDBusConnection &connection, QObject *parent = 0); virtual ~ApplicationImpl(); const QString & id() const override; void addWindow(unsigned int windowId) override; void removeWindow(unsigned int windowId) override; Window::Ptr window(unsigned int windowId) override; bool isEmpty() const override; const QDBusObjectPath & path() const override; Q_PROPERTY(QList ActionGroups READ actionGroups) QList actionGroups() const; Q_PROPERTY(QString DesktopPath READ desktopPath) const QString & desktopPath(); Q_PROPERTY(QString Icon READ icon) const QString & icon() override; Q_PROPERTY(QList MenuModels READ menuModels) QList menuModels() const; public Q_SLOTS: void AddSources(const QList &actions, const QList &descriptions); void SetWindowContext(uint window, const QString &context); protected: WindowContext::Ptr windowContext(unsigned int windowId); QString messageSender(); QScopedPointer m_adaptor; QDBusConnection m_connection; QDBusObjectPath m_path; QString m_applicationId; Factory &m_factory; WindowContext::Ptr m_allWindowsContext; QMap m_windows; QString m_desktopPath; QString m_icon; }; } } #endif /* HUD_SERVICE_APPLICATIONIMPL_H_ */ hud-14.04+14.04.20140604/service/WindowContext.cpp0000644000015301777760000000151712343623451021667 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; WindowContext::WindowContext() { } WindowContext::~WindowContext() { } hud-14.04+14.04.20140604/service/SearchSettings.h0000644000015301777760000000235612343623451021450 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #ifndef HUD_SERVICE_SEARCHSETTINGS_H_ #define HUD_SERVICE_SEARCHSETTINGS_H_ namespace hud { namespace service { class SearchSettings: public QObject { Q_OBJECT public: typedef QSharedPointer Ptr; SearchSettings(); virtual ~SearchSettings(); virtual uint addPenalty() const = 0; virtual uint dropPenalty() const = 0; virtual uint endDropPenalty() const = 0; virtual uint swapPenalty() const = 0; Q_SIGNALS: void changed(); }; } } #endif /* HUD_SERVICE_SEARCHSETTINGS_H_ */ hud-14.04+14.04.20140604/service/Result.h0000644000015301777760000000340512343623451017774 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_RESULT_H_ #define HUD_SERVICE_RESULT_H_ #include #include #include namespace hud { namespace service { class Result { public: typedef QPair Highlight; typedef QList HighlightList; explicit Result(); Result(qulonglong id, const QString &commandName, const HighlightList &commandHighlights, const QString &description, const HighlightList &descriptionHighlights, const QString &shortcut, int distance, bool parameterized); virtual ~Result(); qulonglong id() const; const QString & commandName() const; const HighlightList & commandHighlights() const; const QString & description() const; const HighlightList & descriptionHighlights() const; const QString & shortcut() const; int distance() const; bool parameterized() const; protected: uint64_t m_id; QString m_commandName; HighlightList m_commandHighlights; QString m_description; HighlightList m_descriptionHighlights; QString m_shortcut; int m_distance; bool m_parameterized; }; } } #endif /* HUD_SERVICE_RESULT_H_ */ hud-14.04+14.04.20140604/service/VoiceImpl.cpp0000644000015301777760000000444012343623451020740 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include using namespace hud::service; VoiceImpl::VoiceImpl( QSharedPointer voiceInterface) : m_voiceInterface(voiceInterface), m_isListening(false) { // connect voice interface signals to local signals connect(m_voiceInterface.data(), SIGNAL( HeardSomething() ), this, SIGNAL( HeardSomething() )); connect(m_voiceInterface.data(), SIGNAL( Listening() ), this, SIGNAL( Listening() )); connect(m_voiceInterface.data(), SIGNAL( Loading() ), this, SIGNAL( Loading() )); } VoiceImpl::~VoiceImpl() { } QString VoiceImpl::listen(const QList& commands) { // return immediately if no commands were supplied if (commands.isEmpty() || m_isListening) { return QString(); } // call voice interface listen() asynchronously m_isListening = true; QDBusPendingCall listen_async = m_voiceInterface->asyncCall("listen", QVariant::fromValue(commands)); // connect a call watcher to the async call QDBusPendingCallWatcher watcher(listen_async, this); connect(&watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(listenFinished(QDBusPendingCallWatcher*))); // wait for async call to complete m_listenWait.exec(); m_isListening = false; // return query set by listenFinished return m_query; } void VoiceImpl::listenFinished(QDBusPendingCallWatcher *call) { QDBusPendingReply query = *call; // set m_query accordingly if (query.isError()) { qWarning() << query.error(); m_query = ""; } else { m_query = query; } // notify listen() that the async call is complete m_listenWait.quit(); } hud-14.04+14.04.20140604/service/WindowImpl.h0000644000015301777760000000466112343623451020614 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_WINDOWIMPL_H_ #define HUD_SERVICE_WINDOWIMPL_H_ #include #include #include #include #include #include #include namespace hud { namespace service { class Factory; class WindowImpl; class Q_DECL_EXPORT WindowTokenImpl: public WindowToken { Q_OBJECT friend WindowImpl; public: WindowTokenImpl(const QList &tokens, ItemStore::Ptr itemStore); virtual ~WindowTokenImpl(); void search(const QString &query, Query::EmptyBehaviour emptyBehaviour, QList &results) override; void execute(unsigned long long commandId) override; QString executeParameterized(unsigned long long commandId, QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath) override; void executeToolbar(const QString &item) override; QList commands() const override; QStringList toolbarItems() const override; const QList & tokens() const override; protected Q_SLOTS: void childChanged(); protected: ItemStore::Ptr m_items; QList m_tokens; QTimer m_timer; }; class WindowImpl: public WindowContextImpl, public Window { friend WindowTokenImpl; public: WindowImpl(unsigned int windowId, const QString &applicationId, WindowContext::Ptr allWindowsContext, Factory &factory); virtual ~WindowImpl(); virtual WindowToken::Ptr activate(); protected: QString m_applicationId; WindowContext::Ptr m_allWindowsContext; Collector::Ptr m_dbusMenuCollector; Collector::Ptr m_gMenuCollector; QWeakPointer m_windowToken; }; } } #endif /* HUD_SERVICE_WINDOWIMPL_H_ */ hud-14.04+14.04.20140604/service/DBusMenuCollector.h0000644000015301777760000000406712343623451022054 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_DBUSMENUCOLLECTOR_H_ #define HUD_SERVICE_DBUSMENUCOLLECTOR_H_ #include #include #include class ComCanonicalAppMenuRegistrarInterface; class DBusMenuImporter; QT_BEGIN_NAMESPACE class QMenu; QT_END_NAMESPACE namespace hud { namespace service { class DBusMenuCollector: public Collector, public std::enable_shared_from_this< DBusMenuCollector> { Q_OBJECT public: typedef std::shared_ptr Ptr; DBusMenuCollector(unsigned int windowId, QSharedPointer appmenu); virtual ~DBusMenuCollector(); virtual bool isValid() const override; virtual QList activate() override; protected Q_SLOTS: void WindowRegistered(uint windowId, const QString &service, const QDBusObjectPath &menuObjectPath); protected: virtual void deactivate(); void windowRegistered(const QString &service, const QDBusObjectPath &menuObjectPath); protected: void openMenu(QMenu *menu, unsigned int &limit); void hideMenu(QMenu *menu, unsigned int &limit); unsigned int m_windowId; QSharedPointer m_registrar; QWeakPointer m_collectorToken; QSharedPointer m_menuImporter; QString m_service; QDBusObjectPath m_path; }; } } #endif /* HUD_SERVICE_DBUSMENUCOLLECTOR_H_ */ hud-14.04+14.04.20140604/service/QueryImpl.h0000644000015301777760000000576512343623451020460 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_QUERYIMPL_H_ #define HUD_SERVICE_QUERYIMPL_H_ #include #include #include #include #include #include #include #include #include #include #include class QueryAdaptor; namespace hud { namespace service { class HudService; class Q_DECL_EXPORT QueryImpl: public Query, protected QDBusContext { Q_OBJECT public: QueryImpl(unsigned int id, const QString &query, const QString &sender, EmptyBehaviour emptyBehaviour, HudService &service, ApplicationList::Ptr applicationList, Voice::Ptr voice, const QDBusConnection &connection, QObject *parent = 0); virtual ~QueryImpl(); const QDBusObjectPath & path() const override; const QList & results() const override; QString appstackModel() const override; QString currentQuery() const override; QString resultsModel() const override; Q_PROPERTY(QStringList ToolbarItems READ toolbarItems) QStringList toolbarItems() const override; public Q_SLOTS: void CloseQuery(); void ExecuteCommand(const QDBusVariant &item, uint timestamp); QString ExecuteParameterized(const QDBusVariant &item, uint timestamp, QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath, int &modelSection); void ExecuteToolbar(const QString &item, uint timestamp); int UpdateApp(const QString &app); int UpdateQuery(const QString &query); int VoiceQuery(QString &query); protected Q_SLOTS: void serviceUnregistered(const QString &service); void refresh(); protected: void updateToken(Window::Ptr window); void notifyPropertyChanged(const QString& interface, const QString& propertyName); QScopedPointer m_adaptor; QDBusConnection m_connection; QDBusObjectPath m_path; HudService &m_service; EmptyBehaviour m_emptyBehaviour; ApplicationList::Ptr m_applicationList; Voice::Ptr m_voice; QString m_query; QDBusServiceWatcher m_serviceWatcher; QSharedPointer m_resultsModel; QSharedPointer m_appstackModel; QList m_results; WindowToken::Ptr m_windowToken; }; } } #endif /* HUD_SERVICE_QUERYIMPL_H_ */ hud-14.04+14.04.20140604/service/WindowImpl.cpp0000644000015301777760000000713512343623451021146 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include using namespace hud::service; WindowTokenImpl::WindowTokenImpl(const QList &tokens, ItemStore::Ptr itemStore) : m_items(itemStore), m_tokens(tokens) { m_timer.setSingleShot(true); connect(&m_timer, SIGNAL(timeout()), this, SIGNAL(changed())); for (CollectorToken::Ptr token : tokens) { connect(token.data(), SIGNAL(changed()), this, SLOT(childChanged())); m_items->indexMenu(token->menu()); } } WindowTokenImpl::~WindowTokenImpl() { } void WindowTokenImpl::childChanged() { m_timer.start(); } const QList & WindowTokenImpl::tokens() const { return m_tokens; } void WindowTokenImpl::search(const QString &query, Query::EmptyBehaviour emptyBehaviour, QList &results) { m_items->search(query, emptyBehaviour, results); } void WindowTokenImpl::execute(unsigned long long commandId) { m_items->execute(commandId); } QString WindowTokenImpl::executeParameterized(unsigned long long commandId, QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath) { return m_items->executeParameterized(commandId, prefix, baseAction, actionPath, modelPath); } void WindowTokenImpl::executeToolbar(const QString &item) { m_items->executeToolbar(item); } QList WindowTokenImpl::commands() const { return m_items->commands(); } QStringList WindowTokenImpl::toolbarItems() const { return m_items->toolbarItems(); } WindowImpl::WindowImpl(unsigned int windowId, const QString &applicationId, WindowContext::Ptr allWindowsContext, Factory &factory) : WindowContextImpl(factory), m_applicationId(applicationId), m_allWindowsContext( allWindowsContext) { m_dbusMenuCollector = factory.newDBusMenuCollector(windowId, applicationId); m_gMenuCollector = factory.newGMenuWindowCollector(windowId, applicationId); } WindowImpl::~WindowImpl() { } WindowToken::Ptr WindowImpl::activate() { WindowToken::Ptr windowToken(m_windowToken); QList collectors; collectors << m_dbusMenuCollector << m_gMenuCollector << m_allWindowsContext->activeCollector() << activeCollector(); QList tokens; for (Collector::Ptr collector : collectors) { if (collector && collector->isValid()) { tokens.append(collector->activate()); } } bool newToken(false); if (windowToken) { // If we have an existing token if (tokens != windowToken->tokens()) { // If any of the sub-tokens have changed newToken = true; } } else { // We don't have an existing token newToken = true; } if (newToken) { windowToken = m_factory.newWindowToken(m_applicationId, tokens); m_windowToken = windowToken; connect(this, SIGNAL(contextChanged()), windowToken.data(), SLOT(childChanged())); connect(m_allWindowsContext.data(), SIGNAL(contextChanged()), windowToken.data(), SLOT(childChanged())); } return windowToken; } hud-14.04+14.04.20140604/service/HardCodedSearchSettings.cpp0000644000015301777760000000336312343623451023540 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; HardCodedSearchSettings::HardCodedSearchSettings() { } HardCodedSearchSettings::~HardCodedSearchSettings() { } uint HardCodedSearchSettings::addPenalty() const { return m_addPenalty; } uint HardCodedSearchSettings::dropPenalty() const { return m_dropPenalty; } uint HardCodedSearchSettings::endDropPenalty() const { return m_endDropPenalty; } uint HardCodedSearchSettings::swapPenalty() const { return m_swapPenalty; } void HardCodedSearchSettings::setAddPenalty(uint penalty) { if (m_addPenalty != penalty) { m_addPenalty = penalty; changed(); } } void HardCodedSearchSettings::setDropPenalty(uint penalty) { if (m_dropPenalty != penalty) { m_dropPenalty = penalty; changed(); } } void HardCodedSearchSettings::setEndDropPenalty(uint penalty) { if (m_endDropPenalty != penalty) { m_endDropPenalty = penalty; changed(); } } void HardCodedSearchSettings::setSwapPenalty(uint penalty) { if (m_swapPenalty != penalty) { m_swapPenalty = penalty; changed(); } } hud-14.04+14.04.20140604/service/Result.cpp0000644000015301777760000000361512343623451020332 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; Result::Result() : m_id(0), m_distance(0), m_parameterized(false) { } Result::Result(qulonglong id, const QString &commandName, const HighlightList &commandHighlights, const QString &description, const HighlightList &descriptionHighlights, const QString &shortcut, int distance, bool parameterized) : m_id(id), m_commandName(commandName), m_commandHighlights( commandHighlights), m_description(description), m_descriptionHighlights( descriptionHighlights), m_shortcut(shortcut), m_distance( distance), m_parameterized(parameterized) { } Result::~Result() { } qulonglong Result::id() const { return m_id; } const QString & Result::commandName() const { return m_commandName; } const Result::HighlightList & Result::commandHighlights() const { return m_commandHighlights; } const QString & Result::description() const { return m_description; } const Result::HighlightList & Result::descriptionHighlights() const { return m_descriptionHighlights; } const QString & Result::shortcut() const { return m_shortcut; } int Result::distance() const { return m_distance; } bool Result::parameterized() const { return m_parameterized; } hud-14.04+14.04.20140604/service/Voice.h0000644000015301777760000000232012343623451017556 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #ifndef HUD_SERVICE_VOICE_H_ #define HUD_SERVICE_VOICE_H_ #include #include namespace hud { namespace service { class ItemStore; class Voice: public QObject { Q_OBJECT public: explicit Voice(); virtual ~Voice(); virtual QString listen(const QList& commands) = 0; Q_SIGNALS: void HeardSomething(); void Listening(); void Loading(); public: using Ptr = QSharedPointer< Voice >; }; } // namespace service } // namespace hud #endif // HUD_SERVICE_VOICE_H_ hud-14.04+14.04.20140604/service/ApplicationImpl.cpp0000644000015301777760000001240112343623451022132 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include using namespace hud::common; using namespace hud::service; ApplicationImpl::ApplicationImpl(const QString &applicationId, Factory &factory, const QDBusConnection &connection, QObject *parent) : Application(parent), m_adaptor(new ApplicationAdaptor(this)), m_connection( connection), m_path(DBusTypes::applicationPath(applicationId)), m_applicationId( applicationId), m_factory(factory) { if (!m_connection.registerObject(m_path.path(), this)) { throw std::logic_error(_("Unable to register HUD object on DBus")); } m_allWindowsContext = m_factory.newWindowContext(); } ApplicationImpl::~ApplicationImpl() { m_connection.unregisterObject(m_path.path()); } const QString & ApplicationImpl::id() const { return m_applicationId; } void ApplicationImpl::addWindow(unsigned int windowId) { if (m_windows.contains(windowId)) { qWarning() << "Adding already known window" << windowId << "to application" << m_applicationId; return; } m_windows[windowId] = m_factory.newWindow(windowId, m_applicationId, m_allWindowsContext); } void ApplicationImpl::removeWindow(unsigned int windowId) { if (!m_windows.contains(windowId)) { qWarning() << "Removing unknown window" << windowId << "from application" << m_applicationId; return; } m_windows.remove(windowId); } Window::Ptr ApplicationImpl::window(unsigned int windowId) { return m_windows[windowId]; } WindowContext::Ptr ApplicationImpl::windowContext(unsigned int windowId) { if (windowId == WINDOW_ID_ALL_WINDOWS) { return m_allWindowsContext; } return m_windows[windowId]; } bool ApplicationImpl::isEmpty() const { return m_windows.isEmpty(); } const QDBusObjectPath & ApplicationImpl::path() const { return m_path; } const QString & ApplicationImpl::desktopPath() { if (m_desktopPath.isEmpty()) { QString desktopFile(QString("%1.desktop").arg(m_applicationId)); QStringList xdgDataDirs( QString::fromUtf8(qgetenv("XDG_DATA_DIRS")).split(':')); for (const QString &dir : xdgDataDirs) { QString desktopPath( QDir(QDir(dir).filePath("applications")).filePath( desktopFile)); if (QFile::exists(desktopPath)) { m_desktopPath = desktopPath; break; } } } return m_desktopPath; } const QString & ApplicationImpl::icon() { if (m_icon.isEmpty()) { QString path(desktopPath()); if (!path.isEmpty()) { QSettings settings(path, QSettings::IniFormat); settings.beginGroup("Desktop Entry"); m_icon = settings.value("Icon").toString(); settings.endGroup(); } } return m_icon; } QList ApplicationImpl::actionGroups() const { return QList(); } QList ApplicationImpl::menuModels() const { return QList(); } QString ApplicationImpl::messageSender() { QString sender("local"); if (calledFromDBus()) { sender = message().service(); } return sender; } /** * Window ID 0 is the "all windows" context */ void ApplicationImpl::AddSources(const QList &actions, const QList &descriptions) { QString name(messageSender()); QMap, WindowContext::MenuDefinition> definitions; for (const Action &action : actions) { WindowContext::MenuDefinition definition(name); definition.actionPath = action.m_object; definition.actionPrefix = action.m_prefix; QPair id(action.m_windowId, action.m_context); definitions[id] = definition; } for (const Description &description : descriptions) { QPair id(description.m_windowId, description.m_context); if (definitions.contains(id)) { WindowContext::MenuDefinition &definition(definitions[id]); definition.menuPath = description.m_object; } else { WindowContext::MenuDefinition definition(name); definition.menuPath = description.m_object; definitions[id] = definition; } } for (auto it(definitions.constBegin()); it != definitions.constEnd(); ++it) { const QPair &id(it.key()); WindowContext::Ptr window = windowContext(id.first); if (window.isNull()) { qWarning() << "Tried to add model source for unknown window context" << id.first; continue; } window->addMenu(id.second, it.value()); } } void ApplicationImpl::SetWindowContext(uint windowId, const QString &context) { WindowContext::Ptr window = windowContext(windowId); if (window.isNull()) { qWarning() << "Tried to set context on unknown window context" << windowId << m_applicationId; return; } window->setContext(context); } hud-14.04+14.04.20140604/service/ItemStore.h0000644000015301777760000000466712343623451020444 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_ITEMSTORE_H_ #define HUD_SERVICE_ITEMSTORE_H_ #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QDBusObjectPath; QT_END_NAMESPACE namespace hud { namespace service { class ItemStore: public QObject { Q_OBJECT public: typedef QSharedPointer Ptr; ItemStore(const QString &applicationId, UsageTracker::Ptr usageTracker, SearchSettings::Ptr searchSettings); virtual ~ItemStore(); void indexMenu(const QMenu *menu); void search(const QString &query, Query::EmptyBehaviour emptyBehaviour, QList &results); void execute(unsigned long long commandId); QString executeParameterized(unsigned long long commandId, QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath); void executeToolbar(const QString &item); QList commands() const; QStringList toolbarItems() const; protected Q_SLOTS: void settingChanged(); protected: void indexMenu(const QMenu *menu, const QMenu *root, const QStringList &stack, const QList &index); void addResult(DocumentID id, const QStringMatcher &stringMatcher, const int queryLength, const double relevancy, QList &results); void executeItem(Item::Ptr item); Columbus::Corpus m_corpus; Columbus::Matcher m_matcher; QString m_applicationId; UsageTracker::Ptr m_usageTracker; DocumentID m_nextId; SearchSettings::Ptr m_settings; QMap m_items; QMap m_toolbarItems; }; } } #endif /* HUD_SERVICE_ITEMSTORE_H_ */ hud-14.04+14.04.20140604/service/Collector.h0000644000015301777760000000320712343623451020444 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_COLLECTOR_H_ #define HUD_SERVICE_COLLECTOR_H_ #include #include #include #include #include namespace hud { namespace service { class Collector; class DBusMenuCollector; class GMenuCollector; class CollectorToken: public QObject { Q_OBJECT public: CollectorToken(std::shared_ptr collector, QMenu *menu); typedef QSharedPointer Ptr; virtual ~CollectorToken(); QMenu *menu(); Q_SIGNALS: void changed(); protected: std::weak_ptr m_collector; QMenu *m_menu; }; class Collector: public QObject { Q_OBJECT friend CollectorToken; public: typedef std::shared_ptr Ptr; explicit Collector(QObject *parent = 0); virtual ~Collector(); virtual bool isValid() const = 0; virtual QList activate() = 0; protected: virtual void deactivate() = 0; }; } } #endif /* HUD_SERVICE_COLLECTOR_H_ */ hud-14.04+14.04.20140604/service/GMenuCollector.h0000644000015301777760000000333712343623451021404 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_GMENUCOLLECTOR_H_ #define HUD_SERVICE_GMENUCOLLECTOR_H_ #include #include class ComCanonicalUnityWindowStackInterface; namespace qtgmenu { class QtGMenuImporter; } namespace hud { namespace service { class Q_DECL_EXPORT GMenuCollector: public Collector, public std::enable_shared_from_this { Q_OBJECT public: typedef std::shared_ptr Ptr; GMenuCollector(const QString &name, const QMap &actions, const QDBusObjectPath &menuPath); virtual ~GMenuCollector(); virtual bool isValid() const override; virtual QList activate() override; protected Q_SLOTS: void menuItemsChanged(); protected: void deactivate(); QWeakPointer m_collectorToken; QString m_name; QMap m_actions; QDBusObjectPath m_menuPath; QScopedPointer m_importer; std::shared_ptr m_menu; }; } } #endif /* HUD_SERVICE_GMENUCOLLECTOR_H_ */ hud-14.04+14.04.20140604/service/Voice.cpp0000644000015301777760000000146312343623451020120 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include using namespace hud::service; Voice::Voice() { } Voice::~Voice() { } hud-14.04+14.04.20140604/service/Application.cpp0000644000015301777760000000164312343623451021316 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; Application::Application(QObject *parent) : QObject(parent) { } Application::~Application() { } const unsigned int Application::WINDOW_ID_ALL_WINDOWS(0); hud-14.04+14.04.20140604/service/WindowContextImpl.cpp0000644000015301777760000000312312343623451022504 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include using namespace hud::service; using namespace qtgmenu; WindowContextImpl::WindowContextImpl(Factory &factory) : m_factory(factory) { } WindowContextImpl::~WindowContextImpl() { } void WindowContextImpl::setContext(const QString &context) { if (m_context == context) { return; } m_context = context; m_activeCollector = m_collectors[context]; contextChanged(); } void WindowContextImpl::addMenu(const QString &context, const MenuDefinition &menuDefinition) { QMap actions; actions[menuDefinition.actionPrefix] = menuDefinition.actionPath; m_collectors[context] = m_factory.newGMenuCollector(menuDefinition.name, actions, menuDefinition.menuPath); } Collector::Ptr WindowContextImpl::activeCollector() { return m_activeCollector; } hud-14.04+14.04.20140604/service/ApplicationListImpl.cpp0000644000015301777760000001222012343623451022765 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include using namespace hud::common; using namespace hud::service; static QList IGNORED_APPLICATION_IDS = { "", "compiz", "hud-gui", "unknown" }; ApplicationListImpl::ApplicationListImpl(Factory &factory, QSharedPointer windowStack, QSharedPointer windowStackWatcher) : m_windowStack(windowStack), m_windowStackWatcher(windowStackWatcher), m_factory( factory), m_focusedWindowId(0) { QDBusPendingReply> windowsReply( m_windowStack->GetWindowStack()); if (windowsReply.isError()) { qWarning() << windowsReply.error(); return; } QList windows(windowsReply); for (const WindowInfo &window : windows) { ensureApplicationWithWindow(window.window_id, window.app_id); if (window.focused) { //FIXME Stage is wrong FocusedWindowChanged(window.window_id, window.app_id, 0); } } connect(m_windowStack.data(), SIGNAL(FocusedWindowChanged(uint, const QString &, uint)), this, SLOT(FocusedWindowChanged(uint, const QString &, uint))); connect(m_windowStack.data(), SIGNAL(WindowCreated(uint, const QString &)), this, SLOT(WindowCreated(uint, const QString &))); connect(m_windowStack.data(), SIGNAL(WindowDestroyed(uint, const QString &)), this, SLOT(WindowDestroyed(uint, const QString &))); } ApplicationListImpl::~ApplicationListImpl() { } void ApplicationListImpl::serviceUnregistered(const QString &service) { Q_UNUSED(service); m_focusedApplication.reset(); m_applications.clear(); m_focusedWindowId = 0; } bool ApplicationListImpl::isIgnoredApplication(const QString &applicationId) { if (IGNORED_APPLICATION_IDS.contains(applicationId)) { return true; } return false; } Application::Ptr ApplicationListImpl::ensureApplication( const QString &applicationId) { if (isIgnoredApplication(applicationId)) { return Application::Ptr(); } Application::Ptr application(m_applications[applicationId]); if (application.isNull()) { application = m_factory.newApplication(applicationId); m_applications[applicationId] = application; } return application; } void ApplicationListImpl::ensureApplicationWithWindow(uint windowId, const QString& applicationId) { Application::Ptr application(ensureApplication(applicationId)); if (!application.isNull()) { application->addWindow(windowId); } } void ApplicationListImpl::removeWindow(uint windowId, const QString& applicationId) { if (isIgnoredApplication(applicationId)) { return; } Application::Ptr application(m_applications[applicationId]); if (application.isNull()) { qWarning() << "Attempt to remove window" << windowId << "from non-existent application" << applicationId; return; } application->removeWindow(windowId); // If the application has no windows left, then the best // we can do is assume it has been closed. if (application->isEmpty()) { m_applications.remove(applicationId); // If this was the focused application if (application == m_focusedApplication) { setFocusedWindow(Application::Ptr(), 0); } } } void ApplicationListImpl::setFocusedWindow(Application::Ptr application, uint windowId) { m_focusedApplication = application; m_focusedWindowId = windowId; focusedWindowChanged(); } void ApplicationListImpl::FocusedWindowChanged(uint windowId, const QString &applicationId, uint stage) { Q_UNUSED(stage); if (isIgnoredApplication(applicationId)) { return; } setFocusedWindow(m_applications[applicationId], windowId); } void ApplicationListImpl::WindowCreated(uint windowId, const QString &applicationId) { ensureApplicationWithWindow(windowId, applicationId); } void ApplicationListImpl::WindowDestroyed(uint windowId, const QString &applicationId) { removeWindow(windowId, applicationId); } QList ApplicationListImpl::applications() const { QList results; for (auto i(m_applications.cbegin()); i != m_applications.cend(); ++i) { Application::Ptr application(i.value()); if (application) { results << NameObject(i.key(), application->path()); } } return results; } Application::Ptr ApplicationListImpl::focusedApplication() const { return m_focusedApplication; } Window::Ptr ApplicationListImpl::focusedWindow() const { Window::Ptr window; Application::Ptr application(focusedApplication()); if (!application.isNull()) { window = application->window(m_focusedWindowId); } return window; } hud-14.04+14.04.20140604/service/HudServiceImpl.cpp0000644000015301777760000001342712343623523021741 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include using namespace hud::common; using namespace hud::service; HudServiceImpl::HudServiceImpl(Factory &factory, ApplicationList::Ptr applicationList, const QDBusConnection &connection, QObject *parent) : HudService(parent), m_adaptor(new HudAdaptor(this)), m_connection( connection), m_factory(factory), m_applicationList( applicationList) { if (!m_connection.registerObject(DBusTypes::HUD_SERVICE_DBUS_PATH, this)) { throw std::logic_error(_("Unable to register HUD object on DBus")); } if (!m_connection.registerService(DBusTypes::HUD_SERVICE_DBUS_NAME)) { throw std::logic_error(_("Unable to register HUD service on DBus")); } } HudServiceImpl::~HudServiceImpl() { m_connection.unregisterObject(DBusTypes::HUD_SERVICE_DBUS_PATH); } QDBusObjectPath HudServiceImpl::RegisterApplication(const QString &id) { Application::Ptr application(m_applicationList->ensureApplication(id)); if(application.isNull()) { sendErrorReply(QDBusError::InvalidArgs, "Invalid application ID"); return QDBusObjectPath(); } return application->path(); } QList HudServiceImpl::applications() const { return m_applicationList->applications(); } QList HudServiceImpl::openQueries() const { return m_queries.keys(); } Query::Ptr HudServiceImpl::createQuery(const QString &query, const QString &sender, Query::EmptyBehaviour emptyBehaviour) { Query::Ptr hudQuery(m_factory.newQuery(query, sender, emptyBehaviour)); m_queries[hudQuery->path()] = hudQuery; return hudQuery; } QDBusObjectPath HudServiceImpl::CreateQuery(const QString &query, QString &resultsName, QString &appstackName, int &modelRevision) { QString sender(messageSender()); Query::Ptr hudQuery( createQuery(query, sender, Query::EmptyBehaviour::SHOW_SUGGESTIONS)); resultsName = hudQuery->resultsModel(); appstackName = hudQuery->appstackModel(); modelRevision = 0; return hudQuery->path(); } Query::Ptr HudServiceImpl::closeQuery(const QDBusObjectPath &path) { return m_queries.take(path); } QString HudServiceImpl::messageSender() { QString sender("local"); if (calledFromDBus()) { sender = message().service(); } return sender; } /* * Legacy interface below here */ QString HudServiceImpl::StartQuery(const QString &queryString, int entries, QList &suggestions, QDBusVariant &querykey) { QString sender(messageSender()); QPair> entry(m_legacyQueries[sender]); Query::Ptr query(entry.first); QSharedPointer legacyTimeout(entry.second); if (query.isNull()) { query = createQuery(queryString, sender, Query::EmptyBehaviour::NO_SUGGESTIONS); legacyTimeout.reset(new QTimer()); legacyTimeout->setInterval(2000); legacyTimeout->setSingleShot(true); connect(legacyTimeout.data(), SIGNAL(timeout()), this, SLOT(legacyTimeout())); m_legacyQueries[sender] = qMakePair(query, legacyTimeout); } else { query->UpdateQuery(queryString); legacyTimeout->stop(); legacyTimeout->setProperty("sender", QVariant()); } // The legacy API only allows you to search the current application Application::Ptr application(m_applicationList->focusedApplication()); QString icon; if (!application.isNull()) { icon = application->icon(); } int count(0); for (const Result &result : query->results()) { if (count >= entries) { break; } suggestions << Suggestion(result.id(), result.commandName(), result.commandHighlights(), result.description(), result.descriptionHighlights(), icon); ++count; } querykey.setVariant(query->path().path()); return queryString; } void HudServiceImpl::ExecuteQuery(const QDBusVariant &itemKey, uint timestamp) { Q_UNUSED(timestamp); QString sender(messageSender()); QPair> entry(m_legacyQueries.take(sender)); Query::Ptr query(entry.first); QSharedPointer legacyTimeout(entry.second); if (!query.isNull()) { legacyTimeout->stop(); legacyTimeout->setProperty("sender", QVariant()); query->ExecuteCommand(itemKey, timestamp); closeQuery(query->path()); } } void HudServiceImpl::CloseQuery(const QDBusVariant &querykey) { Q_UNUSED(querykey); QString sender(messageSender()); // We don't actually close legacy queries, or we'd be constructing // and destructing them during the search, due to the way that // Unity7 uses the API. QPair> entry(m_legacyQueries[sender]); Query::Ptr query(entry.first); QSharedPointer legacyTimeout(entry.second); if (!query.isNull()) { query->UpdateQuery(QString()); legacyTimeout->start(); legacyTimeout->setProperty("sender", sender); } } void HudServiceImpl::legacyTimeout() { QObject *timer(sender()); if (!timer) { return; } QVariant from(timer->property("sender")); if (from.isNull()) { return; } QString sender(from.toString()); QPair> entry(m_legacyQueries.take(sender)); Query::Ptr query(entry.first); if (query) { closeQuery(query->path()); } } hud-14.04+14.04.20140604/service/Factory.cpp0000644000015301777760000001301012343623451020451 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY{} without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace hud::common; using namespace hud::service; Factory::Factory() : m_sessionBus(QDBusConnection::sessionBus()), m_queryCounter(0) { DBusTypes::registerMetaTypes(); LibUnityVoice::UnityVoice::registerMetaTypes(); } Factory::~Factory() { } void Factory::setSessionBus(const QDBusConnection &sessionBus) { m_sessionBus = sessionBus; } HudService::Ptr Factory::singletonHudService() { if (m_hudService.isNull()) { m_hudService.reset( new HudServiceImpl(*this, singletonApplicationList(), sessionBus())); } return m_hudService; } QSharedPointer Factory::singletonWindowStack() { if (m_windowStack.isNull()) { m_windowStack.reset( new ComCanonicalUnityWindowStackInterface( DBusTypes::WINDOW_STACK_DBUS_NAME, DBusTypes::WINDOW_STACK_DBUS_PATH, sessionBus())); } return m_windowStack; } QSharedPointer Factory::windowStackWatcher() { return QSharedPointer( new QDBusServiceWatcher(DBusTypes::WINDOW_STACK_DBUS_NAME, sessionBus(), QDBusServiceWatcher::WatchForUnregistration)); } QSharedPointer Factory::singletonAppmenu() { if (m_appmenu.isNull()) { m_appmenu.reset( new ComCanonicalAppMenuRegistrarInterface( DBusTypes::APPMENU_REGISTRAR_DBUS_NAME, DBusTypes::APPMENU_REGISTRAR_DBUS_PATH, sessionBus())); } return m_appmenu; } QDBusConnection Factory::sessionBus() { return m_sessionBus; } Query::Ptr Factory::newQuery(const QString &query, const QString &sender, Query::EmptyBehaviour emptyBehaviour) { return Query::Ptr( new QueryImpl(m_queryCounter++, query, sender, emptyBehaviour, *singletonHudService(), singletonApplicationList(), singletonVoice(), sessionBus())); } ApplicationList::Ptr Factory::singletonApplicationList() { if (m_applicationList.isNull()) { m_applicationList.reset( new ApplicationListImpl(*this, singletonWindowStack(), windowStackWatcher())); } return m_applicationList; } UsageTracker::Ptr Factory::singletonUsageTracker() { if (m_usageTracker.isNull()) { m_usageTracker.reset(new SqliteUsageTracker()); } return m_usageTracker; } SearchSettings::Ptr Factory::singletonSearchSettings() { if (m_searchSettings.isNull()) { if (qEnvironmentVariableIsSet("HUD_IGNORE_SEARCH_SETTINGS")) { m_searchSettings.reset(new HardCodedSearchSettings()); } else { m_searchSettings.reset(new QGSettingsSearchSettings()); } } return m_searchSettings; } Voice::Ptr Factory::singletonVoice() { if (m_voice.isNull()) { QSharedPointer voiceInterface( new ComCanonicalUnityVoiceInterface( DBusTypes::UNITY_VOICE_DBUS_NAME, DBusTypes::UNITY_VOICE_DBUS_PATH, sessionBus())); m_voice.reset(new VoiceImpl(voiceInterface)); } return m_voice; } Application::Ptr Factory::newApplication(const QString &applicationId) { return Application::Ptr( new ApplicationImpl(applicationId, *this, sessionBus())); } ItemStore::Ptr Factory::newItemStore(const QString &applicationId) { return ItemStore::Ptr( new ItemStore(applicationId, singletonUsageTracker(), singletonSearchSettings())); } Window::Ptr Factory::newWindow(unsigned int windowId, const QString &applicationId, WindowContext::Ptr allwindowsContext) { return Window::Ptr( new WindowImpl(windowId, applicationId, allwindowsContext, *this)); } WindowToken::Ptr Factory::newWindowToken(const QString &applicationId, QList tokens) { return WindowToken::Ptr(new WindowTokenImpl(tokens, newItemStore(applicationId))); } WindowContext::Ptr Factory::newWindowContext() { return WindowContext::Ptr(new WindowContextImpl(*this)); } Collector::Ptr Factory::newDBusMenuCollector(unsigned int windowId, const QString &applicationId) { Q_UNUSED(applicationId); return Collector::Ptr(new DBusMenuCollector(windowId, singletonAppmenu())); } Collector::Ptr Factory::newGMenuCollector(const QString &name, const QMap &actions, const QDBusObjectPath &menuPath) { return Collector::Ptr(new GMenuCollector(name, actions, menuPath)); } Collector::Ptr Factory::newGMenuWindowCollector(unsigned int windowId, const QString &applicationId) { return Collector::Ptr( new GMenuWindowCollector(windowId, applicationId, singletonWindowStack(), *this)); } hud-14.04+14.04.20140604/service/SignalHandler.cpp0000644000015301777760000000516412343623451021570 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include using namespace hud::service; int SignalHandler::sigintFd[2]; int SignalHandler::sigtermFd[2]; SignalHandler::SignalHandler(QObject *parent) : QObject(parent) { if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigintFd)) { qFatal("Couldn't create INT socketpair"); } if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigtermFd)) { qFatal("Couldn't create TERM socketpair"); } m_socketNotifierInt = new QSocketNotifier(sigintFd[1], QSocketNotifier::Read, this); connect(m_socketNotifierInt, &QSocketNotifier::activated, this, &SignalHandler::handleSigInt); m_socketNotifierTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, this); connect(m_socketNotifierTerm, &QSocketNotifier::activated, this, &SignalHandler::handleSigTerm); } void SignalHandler::intSignalHandler(int) { char a = 1; ::write(sigintFd[0], &a, sizeof(a)); } void SignalHandler::termSignalHandler(int) { char a = 1; ::write(sigtermFd[0], &a, sizeof(a)); } int SignalHandler::setupUnixSignalHandlers() { struct sigaction sigint, sigterm; sigint.sa_handler = SignalHandler::intSignalHandler; sigemptyset(&sigint.sa_mask); sigint.sa_flags = 0; sigint.sa_flags |= SA_RESTART; if (sigaction(SIGINT, &sigint, 0) > 0) return 1; sigterm.sa_handler = SignalHandler::termSignalHandler; sigemptyset(&sigterm.sa_mask); sigterm.sa_flags |= SA_RESTART; if (sigaction(SIGTERM, &sigterm, 0) > 0) return 2; return 0; } void SignalHandler::handleSigTerm() { m_socketNotifierTerm->setEnabled(false); char tmp; ::read(sigtermFd[1], &tmp, sizeof(tmp)); QCoreApplication::exit(0); m_socketNotifierTerm->setEnabled(true); } void SignalHandler::handleSigInt() { m_socketNotifierInt->setEnabled(false); char tmp; ::read(sigintFd[1], &tmp, sizeof(tmp)); QCoreApplication::exit(0); m_socketNotifierInt->setEnabled(true); } hud-14.04+14.04.20140604/service/GMenuWindowCollector.h0000644000015301777760000000323512343623451022571 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_GMENUWINDOWCOLLECTOR_H_ #define HUD_SERVICE_GMENUWINDOWCOLLECTOR_H_ #include #include class ComCanonicalUnityWindowStackInterface; namespace qtgmenu { class QtGMenuImporter; } namespace hud { namespace service { class Factory; class GMenuWindowCollector: public Collector, public std::enable_shared_from_this { public: typedef std::shared_ptr Ptr; GMenuWindowCollector(unsigned int windowId, const QString &applicationId, QSharedPointer windowStack, Factory &factory); virtual ~GMenuWindowCollector(); virtual bool isValid() const override; virtual QList activate() override; protected: virtual void deactivate(); QSharedPointer m_windowStack; QString m_busName; QList m_collectors; }; } } #endif /* HUD_SERVICE_GMENUWINDOWCOLLECTOR_H_ */ hud-14.04+14.04.20140604/service/Query.cpp0000644000015301777760000000151212343623451020153 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; Query::Query(QObject *parent) : QObject(parent) { } Query::~Query() { } hud-14.04+14.04.20140604/service/SqliteUsageTracker.h0000644000015301777760000000306512343623451022262 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_SQLITEUSAGETRACKER_H_ #define HUD_SERVICE_SQLITEUSAGETRACKER_H_ #include #include #include #include #include namespace hud { namespace service { class SqliteUsageTracker: public UsageTracker { Q_OBJECT public: SqliteUsageTracker(); virtual ~SqliteUsageTracker(); void markUsage(const QString &applicationId, const QString &entry) override; unsigned int usage(const QString &applicationId, const QString &entry) const override; protected Q_SLOTS: void loadFromDatabase(); protected: typedef QPair UsagePair; QMap m_usage; QTimer m_timer; QSqlDatabase m_db; QScopedPointer m_insert; QScopedPointer m_query; QScopedPointer m_delete; }; } } #endif /* HUD_SERVICE_SQLITEUSAGETRACKER_H_ */ hud-14.04+14.04.20140604/service/main.cpp0000644000015301777760000000252612343623451020000 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include using namespace std; using namespace hud::service; int main(int argc, char *argv[]) { qputenv("QT_QPA_PLATFORM", "minimal"); QApplication application(argc, argv); setlocale(LC_ALL, ""); bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain(GETTEXT_PACKAGE); try { Factory factory; factory.singletonHudService(); SignalHandler handler; handler.setupUnixSignalHandlers(); return application.exec(); } catch (std::exception &e) { qWarning() << _("Hud Service:") << e.what(); return 1; } } hud-14.04+14.04.20140604/service/HardCodedSearchSettings.h0000644000015301777760000000265712343623451023212 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_HARDCODEDSEARCHSETTINGS_H_ #define HUD_SERVICE_HARDCODEDSEARCHSETTINGS_H_ #include namespace hud { namespace service { class HardCodedSearchSettings: public SearchSettings { public: HardCodedSearchSettings(); virtual ~HardCodedSearchSettings(); uint addPenalty() const; void setAddPenalty(uint penalty); uint dropPenalty() const; void setDropPenalty(uint penalty); uint endDropPenalty() const; void setEndDropPenalty(uint penalty); uint swapPenalty() const; void setSwapPenalty(uint penalty); protected: uint m_addPenalty = 100; uint m_dropPenalty = 100; uint m_endDropPenalty = 20; uint m_swapPenalty = 150; }; } } #endif /* HUD_SERVICE_HARDCODEDSEARCHSETTINGS_H_ */ hud-14.04+14.04.20140604/service/CMakeLists.txt0000644000015301777760000000377512343623451021117 0ustar pbusernogroup00000000000000 add_definitions( -pedantic -Wall -Wextra ) ########################### # Lib Hud Service ########################### set(HUD_SERVICE_LIB_SOURCES Application.cpp ApplicationImpl.cpp ApplicationList.cpp ApplicationListImpl.cpp Collector.cpp DBusMenuCollector.cpp Factory.cpp GMenuCollector.cpp GMenuWindowCollector.cpp HardCodedSearchSettings.cpp HudService.cpp HudServiceImpl.cpp Item.cpp ItemStore.cpp QGSettingsSearchSettings.cpp Query.cpp QueryImpl.cpp Result.cpp SearchSettings.cpp SignalHandler.cpp SqliteUsageTracker.cpp UsageTracker.cpp Voice.cpp VoiceImpl.cpp Window.cpp WindowImpl.cpp WindowContext.cpp WindowContextImpl.cpp ) qt5_add_dbus_adaptor( HUD_SERVICE_LIB_SOURCES ${HUD_SERVICE_XML} service/HudServiceImpl.h hud::service::HudServiceImpl HudAdaptor ) qt5_add_dbus_adaptor( HUD_SERVICE_LIB_SOURCES ${HUD_QUERY_XML} service/QueryImpl.h hud::service::QueryImpl QueryAdaptor ) qt5_add_dbus_adaptor( HUD_SERVICE_LIB_SOURCES ${HUD_APP_XML} service/ApplicationImpl.h hud::service::ApplicationImpl ApplicationAdaptor ) qt5_add_dbus_interface( HUD_SERVICE_LIB_SOURCES ${APPMENU_REGISTRAR_XML} AppmenuRegistrarInterface ) add_library(hud-service STATIC ${HUD_SERVICE_LIB_SOURCES} ) target_link_libraries(hud-service hud-common qtgmenu ${DBUSMENU_LIBRARIES} ${GOBJECT2_LIBRARIES} ${DEE_LIBRARIES} ${COLUMBUS_LIBRARIES} ${UNITYVOICE_LIBRARIES} ${GSETTINGS_QT_LIBRARIES} ) qt5_use_modules( hud-service Core DBus Widgets Sql ) ########################### # Hud Service Executable ########################### add_executable(hud-service-exec main.cpp ) set_target_properties(hud-service-exec PROPERTIES OUTPUT_NAME "hud-service" ) target_link_libraries(hud-service-exec hud-service ) qt5_use_modules( hud-service-exec Core ) ########################### # Installation ########################### install( TARGETS hud-service-exec RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/hud" ) hud-14.04+14.04.20140604/service/Factory.h0000644000015301777760000000644212343623451020131 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_FACTORY_H_ #define HUD_SERVICE_FACTORY_H_ #include #include #include #include #include #include #include #include #include #include #include #include class ComCanonicalUnityWindowStackInterface; class ComCanonicalAppMenuRegistrarInterface; QT_BEGIN_NAMESPACE class QDBusServiceWatcher; QT_END_NAMESPACE namespace hud { namespace service { class Factory { public: explicit Factory(); virtual ~Factory(); void setSessionBus(const QDBusConnection &sessionBus); virtual HudService::Ptr singletonHudService(); virtual QDBusConnection sessionBus(); virtual QSharedPointer singletonWindowStack(); virtual QSharedPointer windowStackWatcher(); virtual QSharedPointer singletonAppmenu(); virtual Query::Ptr newQuery(const QString &query, const QString &sender, Query::EmptyBehaviour emptyBehaviour); virtual ApplicationList::Ptr singletonApplicationList(); virtual UsageTracker::Ptr singletonUsageTracker(); virtual SearchSettings::Ptr singletonSearchSettings(); virtual Voice::Ptr singletonVoice(); virtual Application::Ptr newApplication(const QString &applicationId); virtual ItemStore::Ptr newItemStore(const QString &applicationId); virtual Window::Ptr newWindow(unsigned int windowId, const QString &applicationId, WindowContext::Ptr allwindowsContext); virtual WindowContext::Ptr newWindowContext(); virtual WindowToken::Ptr newWindowToken(const QString &applicationId, QList tokens); virtual Collector::Ptr newDBusMenuCollector(unsigned int windowId, const QString &applicationId); virtual Collector::Ptr newGMenuCollector(const QString &name, const QMap &actions, const QDBusObjectPath &menuPath); virtual Collector::Ptr newGMenuWindowCollector(unsigned int windowId, const QString &applicationId); protected: QDBusConnection m_sessionBus; unsigned int m_queryCounter; HudService::Ptr m_hudService; ApplicationList::Ptr m_applicationList; UsageTracker::Ptr m_usageTracker; SearchSettings::Ptr m_searchSettings; Voice::Ptr m_voice; QSharedPointer m_windowStack; QSharedPointer m_appmenu; }; } } #endif /* HUD_SERVICE_FACTORY_H_ */ hud-14.04+14.04.20140604/service/VoiceImpl.h0000644000015301777760000000261712343623451020411 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #ifndef HUD_SERVICE_VOICEIMPL_H_ #define HUD_SERVICE_VOICEIMPL_H_ #include #include namespace hud { namespace service { class VoiceImpl: public Voice { Q_OBJECT public: explicit VoiceImpl( QSharedPointer voiceInterface); virtual ~VoiceImpl(); QString listen(const QList& commands) override; private Q_SLOTS: void listenFinished(QDBusPendingCallWatcher *call); private: QSharedPointer m_voiceInterface; QString m_query; QEventLoop m_listenWait; bool m_isListening = false; }; } // namespace service } // namespace hud #endif // HUD_SERVICE_VOICEIMPL_H_ hud-14.04+14.04.20140604/service/ApplicationList.h0000644000015301777760000000271612343623451021621 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_APPLICATIONLIST_H_ #define HUD_SERVICE_APPLICATIONLIST_H_ #include #include #include #include #include namespace hud { namespace service { class Factory; class ApplicationList: public QObject { Q_OBJECT public: typedef QSharedPointer Ptr; explicit ApplicationList(); virtual ~ApplicationList(); virtual QList applications() const = 0; virtual Application::Ptr focusedApplication() const = 0; virtual Window::Ptr focusedWindow() const = 0; virtual Application::Ptr ensureApplication( const QString &applicationId) = 0; Q_SIGNALS: void focusedWindowChanged(); }; } } #endif /* HUD_SERVICE_APPLICATIONLIST_H_ */ hud-14.04+14.04.20140604/service/Item.cpp0000644000015301777760000000376312343623451017756 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include using namespace hud::service; Item::Item(const QMenu *root, const QList &index, int lastIndex) : m_root(root), m_index(index), m_lastIndex(lastIndex) { } Item::~Item() { } QList Item::context() const { QList context; const QMenu *menu(m_root); const QList &index(m_index); for (int i : index) { QList actions(menu->actions()); if (i >= actions.size()) { qWarning() << "Action could not be found" << m_index << m_lastIndex; break; } QAction *action(actions.at(i)); context.append(action); menu = action->menu(); } return context; } QAction * Item::action() const { const QMenu *menu(m_root); const QList &index(m_index); for (int i : index) { QList actions(menu->actions()); if (i >= actions.size()) { qWarning() << "Action could not be found" << m_index << m_lastIndex; return nullptr; } QAction *action(actions.at(i)); menu = action->menu(); } if (menu == nullptr) { qWarning() << "Menu could not be found" << m_index << m_lastIndex; return nullptr; } QList actions(menu->actions()); if (m_lastIndex >= actions.size()) { qWarning() << "Action could not be found" << m_index << m_lastIndex; return nullptr; } return actions.at(m_lastIndex); } hud-14.04+14.04.20140604/service/UsageTracker.h0000644000015301777760000000237712343623451021105 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_USAGETRACKER_H_ #define HUD_SERVICE_USAGETRACKER_H_ #include #include QT_BEGIN_NAMESPACE class QString; QT_END_NAMESPACE namespace hud { namespace service { class UsageTracker: public QObject { public: typedef QSharedPointer Ptr; UsageTracker(); virtual ~UsageTracker(); virtual void markUsage(const QString &applicationId, const QString &entry) = 0; virtual unsigned int usage(const QString &applicationId, const QString &entry) const = 0; }; } } #endif /* HUD_SERVICE_USAGETRACKER_H_ */ hud-14.04+14.04.20140604/service/SqliteUsageTracker.cpp0000644000015301777760000001000212343623451022602 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include using namespace hud::service; /* * One day in milliseconds */ static const int ONE_DAY = 86400000; SqliteUsageTracker::SqliteUsageTracker() { // once each day, clear out the old database entries m_timer.setTimerType(Qt::VeryCoarseTimer); m_timer.setInterval(ONE_DAY); connect(&m_timer, SIGNAL(timeout()), this, SLOT(loadFromDatabase())); m_timer.start(); // Should we store user history bool storeHistory(false); if (qEnvironmentVariableIsEmpty("HUD_STORE_USAGE_DATA")) { QGSettings settings("com.canonical.indicator.appmenu.hud", "/com/canonical/indicator/appmenu/hud/"); storeHistory = settings.get("storeUsageData").toBool(); } else { storeHistory = qgetenv("HUD_STORE_USAGE_DATA") == "TRUE"; } if (QSqlDatabase::contains("usage-tracker")) { m_db = QSqlDatabase::database("usage-tracker"); } else { m_db = QSqlDatabase::addDatabase("QSQLITE", "usage-tracker"); } if (storeHistory) { QDir cacheDirectory; if (qEnvironmentVariableIsSet("HUD_CACHE_DIR")) { cacheDirectory = qgetenv("HUD_CACHE_DIR"); } else { cacheDirectory = QDir::home().filePath(".cache"); } cacheDirectory.mkpath("indicator-appmenu"); QDir appmenuIndicatorDirectory( cacheDirectory.filePath("indicator-appmenu")); m_db.setDatabaseName( appmenuIndicatorDirectory.filePath("hud-usage-log.sqlite")); } else { m_db.setDatabaseName(":memory:"); } m_db.open(); // it's important to construct these against the newly open database m_insert.reset(new QSqlQuery(m_db)); m_query.reset(new QSqlQuery(m_db)); m_delete.reset(new QSqlQuery(m_db)); // Create the database schema if it doesn't exist QSqlQuery create(m_db); create.prepare( "create table if not exists usage (application text, entry text, timestamp datetime)"); create.exec(); create.prepare( "create index if not exists application_index on usage (application, entry)"); create.exec(); // Prepare our SQL statements m_insert->prepare( "insert into usage (application, entry, timestamp) values (?, ?, date('now', 'utc'))"); m_query->prepare( "select application, entry, count(*) from usage where timestamp > date('now', 'utc', '-30 days') group by application, entry"); m_delete->prepare( "delete from usage where timestamp < date('now', 'utc', '-30 days')"); loadFromDatabase(); } SqliteUsageTracker::~SqliteUsageTracker() { m_db.close(); } void SqliteUsageTracker::loadFromDatabase() { // Clear our in-memory cache m_usage.clear(); // Delete entries older than 30 days m_delete->exec(); m_query->exec(); while (m_query->next()) { UsagePair pair(m_query->value(0).toString(), m_query->value(1).toString()); m_usage[pair] = m_query->value(2).toInt(); } } void SqliteUsageTracker::markUsage(const QString &applicationId, const QString &entry) { UsagePair pair(applicationId, entry); if (m_usage.contains(pair)) { // increment if we have an existing entry ++(*m_usage.find(pair)); } else { // just one usage otherwise m_usage[pair] = 1; } // write out the data to sqlite m_insert->bindValue(0, applicationId); m_insert->bindValue(1, entry); m_insert->exec(); } unsigned int SqliteUsageTracker::usage(const QString &applicationId, const QString &entry) const { return m_usage[UsagePair(applicationId, entry)]; } hud-14.04+14.04.20140604/service/WindowContextImpl.h0000644000015301777760000000270312343623451022154 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_WINDOWCONTEXTIMPL_H_ #define HUD_SERVICE_WINDOWCONTEXTIMPL_H_ #include #include #include #include namespace hud { namespace service { class Factory; class WindowContextImpl: public virtual WindowContext { public: explicit WindowContextImpl(Factory &factory); virtual ~WindowContextImpl(); void setContext(const QString &context) override; void addMenu(const QString &context, const MenuDefinition &menuDefinition) override; Collector::Ptr activeCollector() override; protected: Factory &m_factory; QString m_context; QMap m_collectors; Collector::Ptr m_activeCollector; }; } } #endif /* HUD_SERVICE_WINDOWCONTEXTIMPL_H_ */ hud-14.04+14.04.20140604/service/HudServiceImpl.h0000644000015301777760000000521312343623523021400 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_HUDSERVICEIMPL_H_ #define HUD_SERVICE_HUDSERVICEIMPL_H_ #include #include #include #include #include #include #include #include #include class HudAdaptor; namespace hud { namespace service { class Factory; class Q_DECL_EXPORT HudServiceImpl: public HudService, protected QDBusContext { Q_OBJECT public: typedef QSharedPointer Ptr; HudServiceImpl(Factory &factory, ApplicationList::Ptr applicationList, const QDBusConnection &connection, QObject *parent = 0); virtual ~HudServiceImpl(); Q_PROPERTY(QList Applications READ applications) QList applications() const; Q_PROPERTY(QList OpenQueries READ openQueries) QList openQueries() const; Query::Ptr closeQuery(const QDBusObjectPath &path) override; public Q_SLOTS: QDBusObjectPath RegisterApplication(const QString &id); QDBusObjectPath CreateQuery(const QString &query, QString &resultsName, QString &appstackName, int &modelRevision); /* * Legacy interface below here */ QString StartQuery(const QString &query, int entries, QList &suggestions, QDBusVariant &querykey); void ExecuteQuery(const QDBusVariant &key, uint timestamp); void CloseQuery(const QDBusVariant &querykey); protected Q_SLOTS: void legacyTimeout(); protected: Query::Ptr createQuery(const QString &query, const QString &service, Query::EmptyBehaviour emptyBehaviour); QScopedPointer m_adaptor; QDBusConnection m_connection; Factory &m_factory; QMap m_queries; QMap>> m_legacyQueries; QSharedPointer m_applicationList; QString messageSender(); }; } } #endif /* HUD_SERVICE_HUDSERVICEIMPL_H_ */ hud-14.04+14.04.20140604/service/ItemStore.cpp0000644000015301777760000002220412343623451020762 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include using namespace hud::service; using namespace Columbus; static const QRegularExpression SINGLE_AMPERSAND("(?addPenalty()); errorValues.setDeletionError(m_settings->dropPenalty()); errorValues.setEndDeletionError(m_settings->endDropPenalty()); errorValues.setTransposeError(m_settings->swapPenalty()); } static QString convertActionText(const QAction *action) { return action->text().remove(SINGLE_AMPERSAND).replace("&&", "&"); } void ItemStore::indexMenu(const QMenu *menu, const QMenu *root, const QStringList &stack, const QList &index) { int i(-1); for (QAction *action : menu->actions()) { ++i; if (!action->isEnabled()) { continue; } if (action->isSeparator()) { continue; } QStringList text( convertActionText(action).remove(BAD_CHARACTERS).split( WHITESPACE)); bool isParameterized(action->property("isParameterized").toBool()); // We don't descend into parameterized actions QMenu *child(action->menu()); if (!isParameterized && child) { QStringList childStack(stack); childStack << text; QList childIndex(index); childIndex << i; indexMenu(child, root, childStack, childIndex); } else { Document document(m_nextId); WordList command; for (const QString &word : text) { command.addWord(Word(word.toUtf8().constData())); } document.addText(Word("command"), command); WordList wordList; QVariant keywords(action->property("keywords")); QStringList context; if (!keywords.isNull()) { context = keywords.toString().split(WHITESPACE_OR_SEMICOLON); } else { context = stack; } for (const QString &word : context) { wordList.addWord(Word(word.toUtf8().constData())); } document.addText(Word("context"), wordList); m_corpus.addDocument(document); Item::Ptr item(new Item(root, index, i)); m_items[m_nextId] = item; QVariant toolbarItem(action->property("hud-toolbar-item")); if (!toolbarItem.isNull()) { m_toolbarItems[toolbarItem.toString()] = item; } ++m_nextId; } } } void ItemStore::indexMenu(const QMenu *menu) { if (menu == nullptr) { return; } indexMenu(menu, menu, QStringList(), QList()); m_matcher.index(m_corpus); } static void findHighlights(Result::HighlightList &highlights, const QStringMatcher &matcher, int length, const QString &s) { if (length > 0) { int idx = matcher.indexIn(s); while (idx != -1) { highlights << Result::Highlight(idx, idx + length); idx = matcher.indexIn(s, idx + length); } } } static QString convertToEntry(Item::Ptr item, const QAction *action) { QString result; for (const QAction *context : item->context()) { result.append(convertActionText(context)); result.append("||"); } result.append(convertActionText(action)); return result; } void ItemStore::search(const QString &query, Query::EmptyBehaviour emptyBehaviour, QList &results) { QStringMatcher stringMatcher(query, Qt::CaseInsensitive); if (query.isEmpty()) { if (emptyBehaviour == Query::EmptyBehaviour::NO_SUGGESTIONS) { return; } QMap tempResults; for (auto it(m_items.constBegin()); it != m_items.constEnd(); ++it) { const QAction* action = it.value()->action(); if (action) { tempResults.insertMulti( m_usageTracker->usage(m_applicationId, convertToEntry(it.value(), action)), it.key()); } } int maxResults = std::min(m_items.size(), 20); int count = 0; QMapIterator it(tempResults); it.toBack(); while (count < maxResults && it.hasPrevious()) { it.previous(); addResult(it.value(), stringMatcher, 0, 0, results); ++count; } } else { QString cleanQuery(query); cleanQuery.remove(BAD_CHARACTERS); WordList queryList; for (const QString &word : cleanQuery.split(WHITESPACE)) { queryList.addWord(Word(word.toUtf8().constData())); } try { MatchResults matchResults( m_matcher.onlineMatch(queryList, Word("command"))); int queryLength(query.length()); size_t maxResults = std::min(matchResults.size(), size_t(20)); for (size_t i(0); i < maxResults; ++i) { DocumentID id(matchResults.getDocumentID(i)); double relevancy(matchResults.getRelevancy(i)); addResult(id, stringMatcher, queryLength, relevancy, results); } } catch (std::invalid_argument &e) { } } } void ItemStore::addResult(DocumentID id, const QStringMatcher &stringMatcher, const int queryLength, const double relevancy, QList &results) { Item::Ptr item(m_items[id]); const QAction *action(item->action()); if (!action) { return; } QString commandName(convertActionText(action)); Result::HighlightList commandHighlights; findHighlights(commandHighlights, stringMatcher, queryLength, commandName); QString description; QVariant keywords(action->property("keywords")); if (!keywords.isNull()) { description = keywords.toString().replace(";", _(", ")); } else { bool first(true); for (const QAction *a : item->context()) { if (first) { first = false; } else { description.append(_(", ")); } description.append(convertActionText(a)); } } Result::HighlightList descriptionHighlights; findHighlights(descriptionHighlights, stringMatcher, queryLength, description); bool isParameterized(action->property("isParameterized").toBool()); results << Result(id, commandName, commandHighlights, description, descriptionHighlights, action->shortcut().toString(), relevancy * 100, isParameterized); } void ItemStore::executeItem(Item::Ptr item) { if (item.isNull()) { qWarning() << "Tried to execute unknown command"; return; } QAction *action(item->action()); if (action == nullptr) { qWarning() << "Tried to execute unknown command"; return; } action->activate(QAction::ActionEvent::Trigger); m_usageTracker->markUsage(m_applicationId, convertToEntry(item, action)); } void ItemStore::execute(unsigned long long int commandId) { Item::Ptr item(m_items[commandId]); executeItem(item); } QString ItemStore::executeParameterized(unsigned long long commandId, QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath) { Item::Ptr item(m_items[commandId]); if (item.isNull()) { qWarning() << "Tried to execute unknown parameterized command" << commandId; return QString(); } QAction *action(item->action()); if (action == nullptr) { qWarning() << "Tried to execute unknown parameterized command" << commandId; return QString(); } QString name = action->property("actionName").toString(); int index = name.indexOf( '.' ); if (index == -1) { baseAction = name; } else { prefix = name.left(index); baseAction = name.right(name.size() - index - 1); } actionPath = QDBusObjectPath(action->property("actionsPath").toString()); modelPath = QDBusObjectPath(action->property("menuPath").toString()); m_usageTracker->markUsage(m_applicationId, convertToEntry(item, action)); return action->property("busName").toString(); } void ItemStore::executeToolbar(const QString &name) { executeItem(m_toolbarItems[name]); } QList ItemStore::commands() const { QList commandsList; for (uint i = 0; i < m_corpus.size(); ++i) { QStringList command; const WordList& words = m_corpus.getDocument(i).getText( Word("command")); for (uint j = 0; j < words.size(); ++j) { command.append(words[j].asUtf8().c_str()); } commandsList.append(command); } return commandsList; } QStringList ItemStore::toolbarItems() const { return m_toolbarItems.keys(); } hud-14.04+14.04.20140604/service/Query.h0000644000015301777760000000357612343623451017634 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_QUERY_H_ #define HUD_SERVICE_QUERY_H_ #include #include #include #include #include #include class QueryAdaptor; namespace hud { namespace service { class HudService; class Q_DECL_EXPORT Query: public QObject { Q_OBJECT public: typedef QSharedPointer Ptr; enum class EmptyBehaviour { SHOW_SUGGESTIONS, NO_SUGGESTIONS, }; explicit Query(QObject *parent = 0); virtual ~Query(); Q_PROPERTY(QString AppstackModel READ appstackModel) virtual QString appstackModel() const = 0; Q_PROPERTY(QString CurrentQuery READ currentQuery) virtual QString currentQuery() const = 0; Q_PROPERTY(QString ResultsModel READ resultsModel) virtual QString resultsModel() const = 0; Q_PROPERTY(QStringList ToolbarItems READ toolbarItems) virtual QStringList toolbarItems() const = 0; virtual const QDBusObjectPath & path() const = 0; virtual const QList & results() const = 0; public Q_SLOTS: virtual int UpdateQuery(const QString &query) = 0; virtual void ExecuteCommand(const QDBusVariant &item, uint timestamp) = 0; }; } } #endif /* HUD_SERVICE_QUERY_H_ */ hud-14.04+14.04.20140604/service/SearchSettings.cpp0000644000015301777760000000152512343623451022000 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include using namespace hud::service; SearchSettings::SearchSettings() { } SearchSettings::~SearchSettings() { } hud-14.04+14.04.20140604/service/QGSettingsSearchSettings.cpp0000644000015301777760000000300512343623451023744 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include using namespace hud::service; QGSettingsSearchSettings::QGSettingsSearchSettings() : m_settings("com.canonical.indicator.appmenu.hud.search", "/com/canonical/indicator/appmenu/hud/search/") { connect(&m_settings, SIGNAL(changed(const QString&)), this, SIGNAL(changed())); } QGSettingsSearchSettings::~QGSettingsSearchSettings() { } uint QGSettingsSearchSettings::addPenalty() const { return m_settings.get("addPenalty").toUInt(); } uint QGSettingsSearchSettings::dropPenalty() const { return m_settings.get("dropPenalty").toUInt(); } uint QGSettingsSearchSettings::endDropPenalty() const { return m_settings.get("endDropPenalty").toUInt(); } uint QGSettingsSearchSettings::swapPenalty() const { return m_settings.get("swapPenalty").toUInt(); } hud-14.04+14.04.20140604/service/QueryImpl.cpp0000644000015301777760000001644512343623451021010 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include using namespace hud::common; using namespace hud::service; QueryImpl::QueryImpl(unsigned int id, const QString &query, const QString &sender, EmptyBehaviour emptyBehaviour, HudService &service, ApplicationList::Ptr applicationList, Voice::Ptr voice, const QDBusConnection &connection, QObject *parent) : Query(parent), m_adaptor(new QueryAdaptor(this)), m_connection( connection), m_path(DBusTypes::queryPath(id)), m_service( service), m_emptyBehaviour(emptyBehaviour), m_applicationList( applicationList), m_voice(voice), m_query(query), m_serviceWatcher( sender, m_connection, QDBusServiceWatcher::WatchForUnregistration) { connect(&m_serviceWatcher, SIGNAL(serviceUnregistered(const QString &)), this, SLOT(serviceUnregistered(const QString &))); connect(m_applicationList.data(), SIGNAL(focusedWindowChanged()), this, SLOT(refresh())); m_resultsModel.reset(new ResultsModel(id)); m_appstackModel.reset(new AppstackModel(id)); refresh(); if (!m_connection.registerObject(m_path.path(), this)) { throw std::logic_error( _("Unable to register HUD query object on DBus")); } connect(m_voice.data(), SIGNAL(HeardSomething()), m_adaptor.data(), SIGNAL(VoiceQueryHeardSomething())); connect(m_voice.data(), SIGNAL(Listening()), m_adaptor.data(), SIGNAL(VoiceQueryListening())); connect(m_voice.data(), SIGNAL(Loading()), m_adaptor.data(), SIGNAL(VoiceQueryLoading())); } QueryImpl::~QueryImpl() { m_connection.unregisterObject(m_path.path()); } const QDBusObjectPath & QueryImpl::path() const { return m_path; } const QList & QueryImpl::results() const { return m_results; } QString QueryImpl::appstackModel() const { return QString::fromStdString(m_appstackModel->name()); } QString QueryImpl::currentQuery() const { return m_query; } QString QueryImpl::resultsModel() const { return QString::fromStdString(m_resultsModel->name()); } QStringList QueryImpl::toolbarItems() const { if (!m_windowToken) { return QStringList(); } return m_windowToken->toolbarItems(); } void QueryImpl::ExecuteToolbar(const QString &item, uint timestamp) { Q_UNUSED(timestamp); if (!m_windowToken) { return; } return m_windowToken->executeToolbar(item); } void QueryImpl::notifyPropertyChanged(const QString& interface, const QString& propertyName) { QDBusMessage signal = QDBusMessage::createSignal(m_path.path(), "org.freedesktop.DBus.Properties", "PropertiesChanged"); signal << interface; QVariantMap changedProps; changedProps.insert(propertyName, property(qPrintable(propertyName))); signal << changedProps; signal << QStringList(); m_connection.send(signal); } void QueryImpl::CloseQuery() { m_service.closeQuery(m_path); } void QueryImpl::ExecuteCommand(const QDBusVariant &item, uint timestamp) { Q_UNUSED(timestamp); if (!item.variant().canConvert()) { qWarning() << "Failed to execute command - invalid item key" << item.variant(); sendErrorReply(QDBusError::InvalidArgs, "Failed to execute command - invalid item key"); return; } qulonglong commandId(item.variant().toULongLong()); m_windowToken->execute(commandId); } /** * The inputs to this function are: * - ulongint Item, which is the numerical index of the action * - uint, timestamp * * The outputs are: * - string busName, bus name to connect to * - string prefix, the prefix the gmenu is using * - string baseAction, name of the action group * - path actionPath, where we can find the action group * - path modelPath, where we can find the menu * - int modelSection, not used */ QString QueryImpl::ExecuteParameterized(const QDBusVariant &item, uint timestamp, QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath, int &modelSection) { Q_UNUSED(timestamp); if (!item.variant().canConvert()) { qWarning() << "Failed to execute command - invalid item key" << item.variant(); sendErrorReply(QDBusError::InvalidArgs, "Failed to execute command - invalid item key"); return QString(); } qulonglong commandId(item.variant().toULongLong()); modelSection = 1; return m_windowToken->executeParameterized(commandId, prefix, baseAction, actionPath, modelPath); } /** * This means that the user has clicked on an application * in the HUD user interface. */ int QueryImpl::UpdateApp(const QString &app) { qDebug() << "UpdateApp" << app; return 0; } int QueryImpl::UpdateQuery(const QString &query) { if (m_query == query) { return 0; } m_query = query; refresh(); return 0; } void QueryImpl::updateToken(Window::Ptr window) { m_windowToken = window->activate(); connect(m_windowToken.data(), SIGNAL(changed()), this, SLOT(refresh())); } void QueryImpl::refresh() { // First clear the old results m_results.clear(); // Now check for an active window Window::Ptr window(m_applicationList->focusedWindow()); if (window) { // Hold onto a token for the active window updateToken(window); m_windowToken->search(m_query, m_emptyBehaviour, m_results); notifyPropertyChanged("com.canonical.hud.query", "ToolbarItems"); } // Convert to results list to Dee model m_resultsModel->beginChangeset(); for (const Result &result : m_results) { m_resultsModel->addResult(result.id(), result.commandName(), result.commandHighlights(), result.description(), result.descriptionHighlights(), result.shortcut(), result.distance(), result.parameterized()); } m_resultsModel->endChangeset(); // Now check for an active application Application::Ptr application(m_applicationList->focusedApplication()); m_appstackModel->beginChangeset(); if (application) { m_appstackModel->addApplication(application->id(), application->icon(), AppstackModel::ITEM_TYPE_FOCUSED_APP); } //TODO Apps other than the foreground one m_appstackModel->endChangeset(); } int QueryImpl::VoiceQuery(QString &query) { Window::Ptr window(m_applicationList->focusedWindow()); if (window.isNull()) { qWarning() << "No focused window for voice query"; return 0; } // Hold onto a token for the active window updateToken(window); // Get the list of commands from the current window token QList commandsList(m_windowToken->commands()); // Listen for speech, and set result query = m_voice->listen(commandsList); // Update the query accordingly UpdateQuery(query); return 0; } void QueryImpl::serviceUnregistered(const QString &service) { Q_UNUSED(service); CloseQuery(); } hud-14.04+14.04.20140604/service/Window.h0000644000015301777760000000354412343623451017771 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_WINDOW_H_ #define HUD_SERVICE_WINDOW_H_ #include #include #include #include namespace hud { namespace service { class WindowToken: public QObject { Q_OBJECT public: typedef QSharedPointer Ptr; virtual ~WindowToken(); virtual void search(const QString &query, Query::EmptyBehaviour emptyBehaviour, QList &results) = 0; virtual void execute(unsigned long long commandId) = 0; virtual QString executeParameterized(unsigned long long commandId, QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath) = 0; virtual void executeToolbar(const QString &item) = 0; virtual QList commands() const = 0; virtual QStringList toolbarItems() const = 0; virtual const QList & tokens() const = 0; Q_SIGNALS: void changed(); protected: explicit WindowToken(); }; class Window: public virtual WindowContext { public: typedef QSharedPointer Ptr; explicit Window(); virtual ~Window(); virtual WindowToken::Ptr activate() = 0; }; } } #endif /* HUD_SERVICE_WINDOW_H_ */ hud-14.04+14.04.20140604/service/HudService.h0000644000015301777760000000226412343623451020561 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_SERVICE_H_ #define HUD_SERVICE_SERVICE_H_ #include #include #include class HudAdaptor; namespace hud { namespace service { class Factory; class Q_DECL_EXPORT HudService: public QObject { public: typedef QSharedPointer Ptr; explicit HudService(QObject *parent = 0); virtual ~HudService(); virtual Query::Ptr closeQuery(const QDBusObjectPath &path) = 0; }; } } #endif /* HUD_SERVICE_SERVICE_H_ */ hud-14.04+14.04.20140604/service/SignalHandler.h0000644000015301777760000000254512343623451021235 0ustar pbusernogroup00000000000000/* * Copyright (C) 2014 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_SIGNALHANDLER_H_ #define HUD_SERVICE_SIGNALHANDLER_H_ #include #include namespace hud { namespace service { class SignalHandler: public QObject { Q_OBJECT public: SignalHandler(QObject *parent = 0); ~SignalHandler() = default; static int setupUnixSignalHandlers(); protected Q_SLOTS: void handleSigInt(); void handleSigTerm(); protected: static void intSignalHandler(int unused); static void termSignalHandler(int unused); static int sigintFd[2]; static int sigtermFd[2]; QSocketNotifier *m_socketNotifierInt; QSocketNotifier *m_socketNotifierTerm; }; } } #endif /* HUD_SERVICE_SIGNALHANDLER_H_ */ hud-14.04+14.04.20140604/service/Application.h0000644000015301777760000000277512343623451020772 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_SERVICE_APPLICATION_H_ #define HUD_SERVICE_APPLICATION_H_ #include #include #include #include namespace hud { namespace service { class Application: public QObject { Q_OBJECT public: static const unsigned int WINDOW_ID_ALL_WINDOWS; typedef QSharedPointer Ptr; explicit Application(QObject *parent = 0); virtual ~Application(); virtual const QString & id() const = 0; virtual const QString & icon() = 0; virtual void addWindow(unsigned int windowId) = 0; virtual void removeWindow(unsigned int windowId) = 0; virtual Window::Ptr window(unsigned int windowId) = 0; virtual bool isEmpty() const = 0; virtual const QDBusObjectPath & path() const = 0; }; } } #endif /* HUD_SERVICE_APPLICATION_H_ */ hud-14.04+14.04.20140604/libhud/0000755000015301777760000000000012343624372016155 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/libhud/manager.c0000644000015301777760000005244212343623451017737 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of either or both of the following licences: * * 1) the GNU Lesser General Public License version 3, as published by * the Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, * see * * Author: Ryan Lortie */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "manager.h" #include "action-publisher.h" #include "service-iface.h" #include "app-iface.h" struct _HudManagerPrivate { gchar * application_id; GApplication * application; HudActionPublisher * app_pub; GCancellable * connection_cancel; GDBusConnection * session; _HudServiceIfaceComCanonicalHud * service_proxy; _HudAppIfaceComCanonicalHudApplication * app_proxy; GVariantBuilder * todo_add_acts; GVariantBuilder * todo_add_desc; GHashTable * todo_active_contexts; guint todo_idle; GList * publishers; GHashTable * active_contexts; }; #define HUD_MANAGER_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), HUD_TYPE_MANAGER, HudManagerPrivate)) enum { PROP_0 = 0, PROP_APP_ID, PROP_APPLICATION }; static void hud_manager_class_init (HudManagerClass *klass); static void hud_manager_init (HudManager *self); static void hud_manager_constructed (GObject *object); static void hud_manager_dispose (GObject *object); static void hud_manager_finalize (GObject *object); static void set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec); static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec); static void bus_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data); G_DEFINE_TYPE (HudManager, hud_manager, G_TYPE_OBJECT) /* Initialize Class */ static void hud_manager_class_init (HudManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (HudManagerPrivate)); object_class->constructed = hud_manager_constructed; object_class->dispose = hud_manager_dispose; object_class->finalize = hud_manager_finalize; object_class->set_property = set_property; object_class->get_property = get_property; g_object_class_install_property (object_class, PROP_APP_ID, g_param_spec_string(HUD_MANAGER_PROP_APP_ID, "ID for the application, typically the desktop file name", "A unique identifier for the application. Usually this aligns with the desktop file name or package name of the app.", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_APPLICATION, g_param_spec_object(HUD_MANAGER_PROP_APPLICATION, "Instance of #GApplication if used for this application", "GApplication object", G_TYPE_APPLICATION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); return; } /* Initialize Instance */ static void hud_manager_init (HudManager *self) { self->priv = HUD_MANAGER_GET_PRIVATE(self); self->priv->connection_cancel = g_cancellable_new(); g_bus_get(G_BUS_TYPE_SESSION, self->priv->connection_cancel, bus_get_cb, self); self->priv->todo_active_contexts = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref); self->priv->active_contexts = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_object_unref); return; } /* Construct the object */ static void hud_manager_constructed (GObject * object) { HudManager * manager = HUD_MANAGER(object); manager->priv->todo_idle = 0; if (manager->priv->application) { manager->priv->app_pub = hud_action_publisher_new(HUD_ACTION_PUBLISHER_ALL_WINDOWS, HUD_ACTION_PUBLISHER_NO_CONTEXT); hud_action_publisher_add_action_group(manager->priv->app_pub, "app", g_application_get_dbus_object_path (manager->priv->application)); hud_manager_add_actions(manager, manager->priv->app_pub); } return; } /* Clearing out a builder by finishing and freeing the results */ static void variant_builder_dispose (gpointer user_data) { if (user_data == NULL) { return; } GVariantBuilder * builder; builder = (GVariantBuilder *)user_data; GVariant * output; output = g_variant_builder_end(builder); g_variant_ref_sink(output); g_variant_unref(output); g_variant_builder_unref(builder); return; } /* Clean up refs */ static void hud_manager_dispose (GObject *object) { HudManager * manager = HUD_MANAGER(object); if (manager->priv->connection_cancel) { g_cancellable_cancel(manager->priv->connection_cancel); g_clear_object(&manager->priv->connection_cancel); } g_clear_pointer(&manager->priv->todo_add_acts, variant_builder_dispose); g_clear_pointer(&manager->priv->todo_add_desc, variant_builder_dispose); if (manager->priv->todo_idle != 0) { g_source_remove(manager->priv->todo_idle); manager->priv->todo_idle = 0; } g_clear_object(&manager->priv->session); g_clear_object(&manager->priv->service_proxy); g_clear_object(&manager->priv->app_proxy); g_list_free_full(manager->priv->publishers, g_object_unref); g_hash_table_remove_all(manager->priv->todo_active_contexts); g_hash_table_remove_all(manager->priv->active_contexts); g_clear_object(&manager->priv->app_pub); g_clear_object(&manager->priv->application); G_OBJECT_CLASS (hud_manager_parent_class)->dispose (object); return; } /* Free Memory */ static void hud_manager_finalize (GObject *object) { HudManager * manager = HUD_MANAGER(object); g_clear_pointer(&manager->priv->application_id, g_free); g_clear_pointer(&manager->priv->todo_active_contexts, g_hash_table_destroy); g_clear_pointer(&manager->priv->active_contexts, g_hash_table_destroy); G_OBJECT_CLASS (hud_manager_parent_class)->finalize (object); return; } /* Standard setting of props */ static void set_property (GObject * obj, guint id, const GValue * value, G_GNUC_UNUSED GParamSpec * pspec) { HudManager * manager = HUD_MANAGER(obj); switch (id) { case PROP_APP_ID: if (manager->priv->application == NULL) { g_clear_pointer(&manager->priv->application_id, g_free); manager->priv->application_id = g_value_dup_string(value); } else { g_debug("Application ID being set on HUD Manager already initialized with a GApplication"); } break; case PROP_APPLICATION: g_clear_object(&manager->priv->application); if (g_value_get_object(value) != NULL) { g_clear_pointer(&manager->priv->application_id, g_free); manager->priv->application = g_value_dup_object(value); manager->priv->application_id = g_strdup(g_application_get_application_id(manager->priv->application)); } break; default: g_warning("Unknown property %d.", id); return; } return; } /* Standard getting of props */ static void get_property (GObject * obj, guint id, GValue * value, G_GNUC_UNUSED GParamSpec * pspec) { HudManager * manager = HUD_MANAGER(obj); switch (id) { case PROP_APP_ID: g_value_set_string(value, manager->priv->application_id); break; case PROP_APPLICATION: g_value_set_object(value, manager->priv->application); break; default: g_warning("Unknown property %d.", id); return; } return; } /* Callback from adding sources */ static void add_sources_cb (GObject * obj, GAsyncResult * res, G_GNUC_UNUSED gpointer user_data) { GError * error = NULL; _hud_app_iface_com_canonical_hud_application_call_add_sources_finish((_HudAppIfaceComCanonicalHudApplication *)obj, res, &error); if (error != NULL) { g_warning("Unable to add sources: %s", error->message); g_error_free(error); /* TODO: Handle error */ return; } return; } static gboolean activate_todo_context (G_GNUC_UNUSED gpointer key, gpointer value, gpointer user_data) { HudManager * manager = HUD_MANAGER(user_data); HudActionPublisher *pub = HUD_ACTION_PUBLISHER(value); hud_manager_switch_window_context(manager, pub); return TRUE; } /* Take the todo queues and make them into DBus messages */ static void process_todo_queues (HudManager * manager) { if (manager->priv->todo_add_acts == NULL && manager->priv->todo_add_desc == NULL && g_hash_table_size(manager->priv->todo_active_contexts) == 0) { /* Nothing to process */ return; } if (manager->priv->app_proxy == NULL) { g_warning("Can't process TODO queues without an application proxy"); return; } GVariant * actions = NULL; GVariant * descriptions = NULL; /* Build an actions list */ if (manager->priv->todo_add_acts != NULL) { actions = g_variant_builder_end(manager->priv->todo_add_acts); g_variant_builder_unref(manager->priv->todo_add_acts); manager->priv->todo_add_acts = NULL; } else { actions = g_variant_new_array(G_VARIANT_TYPE("(usso)"), NULL, 0); } /* Build a descriptions list */ if (manager->priv->todo_add_desc != NULL) { descriptions = g_variant_builder_end(manager->priv->todo_add_desc); g_variant_builder_unref(manager->priv->todo_add_desc); manager->priv->todo_add_desc = NULL; } else { descriptions = g_variant_new_array(G_VARIANT_TYPE("(uso)"), NULL, 0); } /* Should never happen, but let's get useful error messages if it does */ g_return_if_fail(actions != NULL); g_return_if_fail(descriptions != NULL); _hud_app_iface_com_canonical_hud_application_call_add_sources(manager->priv->app_proxy, actions, descriptions, NULL, /* cancelable */ add_sources_cb, manager); g_hash_table_foreach_remove(manager->priv->todo_active_contexts, activate_todo_context, manager); return; } /* Application proxy callback */ static void application_proxy_cb (G_GNUC_UNUSED GObject * obj, GAsyncResult * res, gpointer user_data) { GError * error = NULL; _HudAppIfaceComCanonicalHudApplication * proxy = _hud_app_iface_com_canonical_hud_application_proxy_new_finish(res, &error); if (error != NULL) { g_warning("Unable to get app proxy: %s", error->message); g_error_free(error); return; } HudManager * manager = HUD_MANAGER(user_data); manager->priv->app_proxy = proxy; g_clear_object(&manager->priv->connection_cancel); process_todo_queues(manager); return; } /* Callback from getting the HUD service proxy */ static void register_app_cb (GObject * obj, GAsyncResult * res, gpointer user_data) { GError * error = NULL; gchar * object = NULL; _hud_service_iface_com_canonical_hud_call_register_application_finish ((_HudServiceIfaceComCanonicalHud *)obj, &object, res, &error); if (error != NULL) { g_warning("Unable to register app: %s", error->message); g_error_free(error); return; } HudManager * manager = HUD_MANAGER(user_data); _hud_app_iface_com_canonical_hud_application_proxy_new(manager->priv->session, G_DBUS_PROXY_FLAGS_NONE, "com.canonical.hud", object, manager->priv->connection_cancel, application_proxy_cb, manager); g_free(object); return; } static gboolean insert_active_context_to_todo (G_GNUC_UNUSED gpointer key, gpointer value, gpointer user_data) { HudManager * manager = HUD_MANAGER(user_data); HudActionPublisher *pub = HUD_ACTION_PUBLISHER(value); g_hash_table_insert(manager->priv->todo_active_contexts, GUINT_TO_POINTER(hud_action_publisher_get_window_id(pub)), g_object_ref(pub)); return TRUE; } /* Watch the name change to make sure we're robust to it */ static void notify_name_owner (GObject * gobject, G_GNUC_UNUSED GParamSpec * pspec, gpointer user_data) { HudManager * manager = HUD_MANAGER(user_data); gchar * name_owner = g_dbus_proxy_get_name_owner(G_DBUS_PROXY(gobject)); if (name_owner == NULL) { /* We've lost it */ /* Remove the stale proxy */ g_clear_object(&manager->priv->app_proxy); /* Make sure we're set upto do the async dance again */ if (manager->priv->connection_cancel == NULL) { manager->priv->connection_cancel = g_cancellable_new(); } /* Put the current publishers on the todo list */ GList * old_publishers = manager->priv->publishers; manager->priv->publishers = NULL; GList * pub; for (pub = old_publishers; pub != NULL; pub = g_list_next(pub)) { hud_manager_add_actions(manager, HUD_ACTION_PUBLISHER(pub->data)); } g_list_free_full(old_publishers, g_object_unref); g_hash_table_foreach_remove(manager->priv->active_contexts, insert_active_context_to_todo, manager); return; } g_free(name_owner); /* We've got a new name owner, so we need to register */ _hud_service_iface_com_canonical_hud_call_register_application(manager->priv->service_proxy, manager->priv->application_id, manager->priv->connection_cancel, register_app_cb, manager); return; } /* Callback from getting the HUD service proxy */ static void service_proxy_cb (G_GNUC_UNUSED GObject * obj, GAsyncResult * res, gpointer user_data) { GError * error = NULL; _HudServiceIfaceComCanonicalHud * proxy = _hud_service_iface_com_canonical_hud_proxy_new_finish(res, &error); if (error != NULL) { g_critical("Unable to get session bus: %s", error->message); g_error_free(error); return; } HudManager * manager = HUD_MANAGER(user_data); manager->priv->service_proxy = proxy; g_signal_connect(G_OBJECT(proxy), "notify::g-name-owner", G_CALLBACK(notify_name_owner), manager); notify_name_owner(G_OBJECT(proxy), NULL, manager); return; } /* Callback from getting the session bus */ static void bus_get_cb (G_GNUC_UNUSED GObject * obj, GAsyncResult * res, gpointer user_data) { GError * error = NULL; GDBusConnection * con = g_bus_get_finish(res, &error); if (error != NULL) { g_critical("Unable to get session bus: %s", error->message); g_error_free(error); return; } HudManager * manager = HUD_MANAGER(user_data); manager->priv->session = con; _hud_service_iface_com_canonical_hud_proxy_new(con, G_DBUS_PROXY_FLAGS_NONE, "com.canonical.hud", "/com/canonical/hud", manager->priv->connection_cancel, service_proxy_cb, manager); return; } /** * hud_manager_new: * @application_id: Unique identifier of the application, usually desktop file name * * Creates a new #HudManager object. * * Return value: (transfer full): New #HudManager */ HudManager * hud_manager_new (const gchar * application_id) { g_return_val_if_fail(application_id != NULL, NULL); return g_object_new(HUD_TYPE_MANAGER, HUD_MANAGER_PROP_APP_ID, application_id, NULL); } /** * hud_manager_new_for_application: * @application: #GApplication that we can use to get the ID and some actions from * * Creates a new #HudManager object using the application ID in th * @application object. Also exports the default actions there in * the "app" namespace. * * Return value: (transfer full): New #HudManager */ HudManager * hud_manager_new_for_application (GApplication * application) { g_return_val_if_fail(G_IS_APPLICATION(application), NULL); return g_object_new(HUD_TYPE_MANAGER, HUD_MANAGER_PROP_APPLICATION, application, NULL); } /* Idle handler */ static gboolean todo_handler (gpointer user_data) { HudManager * manager = HUD_MANAGER(user_data); process_todo_queues(manager); manager->priv->todo_idle = 0; return FALSE; } /** * hud_manager_add_actions: * @manager: A #HudManager object * @pub: Action publisher object tracking the descriptions and action groups * * Sets up a set of actions and descriptions for a specific user * context. This could be a window or a tab, depending on how the * application works. */ void hud_manager_add_actions (HudManager * manager, HudActionPublisher * pub) { g_return_if_fail(HUD_IS_MANAGER(manager)); g_return_if_fail(HUD_IS_ACTION_PUBLISHER(pub)); /* Add to our list of publishers */ manager->priv->publishers = g_list_prepend(manager->priv->publishers, g_object_ref(pub)); /* Set up watching for new groups */ /* TODO */ /* Grab the window and context IDs for each of them */ GVariant * winid = g_variant_new_uint32(hud_action_publisher_get_window_id(pub)); GVariant * conid = g_variant_new_string(hud_action_publisher_get_context_id(pub)); g_variant_ref_sink(winid); g_variant_ref_sink(conid); /* Send the current groups out */ GList * ags_list = hud_action_publisher_get_action_groups(pub); /* Build the variant builder if it doesn't exist */ if (ags_list != NULL && manager->priv->todo_add_acts == NULL) { manager->priv->todo_add_acts = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); } /* Grab the action groups and add them to the todo queue */ GList * paction_group = NULL; for (paction_group = ags_list; paction_group != NULL; paction_group = g_list_next(paction_group)) { HudActionPublisherActionGroupSet * set = (HudActionPublisherActionGroupSet *)paction_group->data; g_variant_builder_open(manager->priv->todo_add_acts, G_VARIANT_TYPE_TUPLE); g_variant_builder_add_value(manager->priv->todo_add_acts, winid); g_variant_builder_add_value(manager->priv->todo_add_acts, conid); g_variant_builder_add_value(manager->priv->todo_add_acts, g_variant_new_string(set->prefix)); g_variant_builder_add_value(manager->priv->todo_add_acts, g_variant_new_object_path(set->path)); g_variant_builder_close(manager->priv->todo_add_acts); } /* Grab the description and add them to the todo queue */ const gchar * descpath = hud_action_publisher_get_description_path(pub); /* Build the variant builder if it doesn't exist */ if (descpath != NULL && manager->priv->todo_add_desc == NULL) { manager->priv->todo_add_desc = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); } if (descpath != NULL) { g_variant_builder_open(manager->priv->todo_add_desc, G_VARIANT_TYPE_TUPLE); g_variant_builder_add_value(manager->priv->todo_add_desc, winid); g_variant_builder_add_value(manager->priv->todo_add_desc, conid); g_variant_builder_add_value(manager->priv->todo_add_desc, g_variant_new_object_path(descpath)); g_variant_builder_close(manager->priv->todo_add_desc); } /* Should be if we're all set up */ if (manager->priv->connection_cancel == NULL && manager->priv->todo_idle == 0) { manager->priv->todo_idle = g_idle_add(todo_handler, manager); } g_variant_unref(winid); winid = NULL; g_variant_unref(conid); conid = NULL; return; } /** * hud_manager_remove_actions: * @manager: A #HudManager object * @pub: Action publisher object tracking the descriptions and action groups * * Removes actions for being watched by the HUD. Should be done when the object * is remove. Does not require @pub to be a valid object so it can be used * with weak pointer style destroy. */ void hud_manager_remove_actions (HudManager * manager, G_GNUC_UNUSED HudActionPublisher * pub) { g_return_if_fail(HUD_IS_MANAGER(manager)); /* TODO: We need DBus API for this */ /* TODO: make sure to check if the removed publisher was in the active_contexts or todo_active_contexts */ return; } /* Callback from setting the window context. Not much we can do, just reporting errors */ static void set_window_context_cb (G_GNUC_UNUSED GObject * obj, GAsyncResult *res, G_GNUC_UNUSED gpointer user_data) { GError * error = NULL; _hud_app_iface_com_canonical_hud_application_call_set_window_context_finish((_HudAppIfaceComCanonicalHudApplication *)obj, res, &error); if (error != NULL) { g_warning("Unable to set context for window: %s", error->message); g_error_free(error); } return; } /** * hud_manager_switch_window_context: * @manager: A #HudManager object * @pub: Action publisher object tracking the descriptions and action groups * * Tells the HUD service that a window should use a different context of * actions with the current window. This allows the application to export * sets of actions and switch them easily with a single dbus message. */ void hud_manager_switch_window_context (HudManager * manager, HudActionPublisher * pub) { g_return_if_fail(HUD_IS_MANAGER(manager)); g_return_if_fail(HUD_IS_ACTION_PUBLISHER(pub)); if (manager->priv->app_proxy == NULL) { g_debug("Unable to send context change now, caching for reconnection"); g_hash_table_insert(manager->priv->todo_active_contexts, GUINT_TO_POINTER(hud_action_publisher_get_window_id(pub)), g_object_ref(pub)); return; } g_hash_table_insert(manager->priv->active_contexts, GUINT_TO_POINTER(hud_action_publisher_get_window_id(pub)), g_object_ref(pub)); _hud_app_iface_com_canonical_hud_application_call_set_window_context(manager->priv->app_proxy, hud_action_publisher_get_window_id(pub), hud_action_publisher_get_context_id(pub), NULL, /* cancellable */ set_window_context_cb, NULL); return; } hud-14.04+14.04.20140604/libhud/action-publisher.h0000644000015301777760000002054612343623451021602 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of either or both of the following licences: * * 1) the GNU Lesser General Public License version 3, as published by * the Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, * see * * Author: Ryan Lortie */ #if !defined (_HUD_H_INSIDE) && !defined (HUD_COMPILATION) #error "Only can be included directly." #endif #ifndef __HUD_ACTION_PUBLISHER_H__ #define __HUD_ACTION_PUBLISHER_H__ #pragma GCC visibility push(default) #include G_BEGIN_DECLS #define HUD_TYPE_ACTION_PUBLISHER (hud_action_publisher_get_type ()) #define HUD_ACTION_PUBLISHER(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ HUD_TYPE_ACTION_PUBLISHER, HudActionPublisher)) #define HUD_IS_ACTION_PUBLISHER(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ HUD_TYPE_ACTION_PUBLISHER)) /** * HUD_ACTION_PUBLISHER_SIGNAL_ACTION_GROUP_ADDED: * * Define for the string to access the signal HudActionPublisher::action-group-added */ #define HUD_ACTION_PUBLISHER_SIGNAL_ACTION_GROUP_ADDED "action-group-added" /** * HUD_ACTION_PUBLISHER_SIGNAL_ACTION_GROUP_REMOVED: * * Define for the string to access the signal HudActionPublisher::action-group-removed */ #define HUD_ACTION_PUBLISHER_SIGNAL_ACTION_GROUP_REMOVED "action-group-removed" GType hud_action_description_get_type (void); #define HUD_TYPE_ACTION_DESCRIPTION (hud_action_description_get_type ()) #define HUD_ACTION_DESCRIPTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ HUD_TYPE_ACTION_DESCRIPTION, HudActionDescription)) #define HUD_IS_ACTION_DESCRIPTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ HUD_TYPE_ACTION_DESCRIPTION)) /** * HUD_ACTION_PUBLISHER_NO_CONTEXT: * * Can be passed to hud_action_publisher_new() to request that it build * it's own context. */ #define HUD_ACTION_PUBLISHER_NO_CONTEXT (NULL) /** * HUD_ACTION_PUBLISHER_ALL_WINDOWS: * * Can be passed to hud_action_publisher_new() to request that these actions * apply to all windows for the application. */ #define HUD_ACTION_PUBLISHER_ALL_WINDOWS (0) typedef struct _HudActionDescription HudActionDescription; typedef struct _HudActionPublisher HudActionPublisher; typedef struct _HudActionPublisherActionGroupSet HudActionPublisherActionGroupSet; /** * HudActionPublisher: * * An object representing the actions that are published for a * particular context within the application. Most often this is * a window, but could also be used for tabs or other modal style * user contexts in the application. */ /** * HudActionPublisherActionGroupSet: * @prefix: Action prefix for the action group * @path: Path that the action group is exported on DBus * * A set of properties of that describe the action group. */ struct _HudActionPublisherActionGroupSet { gchar * prefix; gchar * path; }; GType hud_action_publisher_get_type (void) G_GNUC_CONST; HudActionPublisher * hud_action_publisher_new (guint window_id, const gchar * context_id); HudActionPublisher * hud_action_publisher_new_for_application (GApplication *application); void hud_action_publisher_add_description (HudActionPublisher *publisher, HudActionDescription *description); void hud_action_publisher_add_action_group (HudActionPublisher *publisher, const gchar *prefix, const gchar *object_path); void hud_action_publisher_remove_action_group (HudActionPublisher *publisher, const gchar *prefix, GVariant *identifier); guint hud_action_publisher_get_window_id (HudActionPublisher *publisher); const gchar * hud_action_publisher_get_context_id (HudActionPublisher *publisher); GList * hud_action_publisher_get_action_groups (HudActionPublisher *publisher); const gchar * hud_action_publisher_get_description_path (HudActionPublisher *publisher); /* Description */ HudActionDescription * hud_action_description_new (const gchar *action_name, GVariant *action_target); HudActionDescription * hud_action_description_ref (HudActionDescription *description); void hud_action_description_unref (HudActionDescription *description); const gchar * hud_action_description_get_action_name (HudActionDescription *description); GVariant * hud_action_description_get_action_target (HudActionDescription *description); void hud_action_description_set_attribute_value (HudActionDescription *description, const gchar *attribute_name, GVariant *value); void hud_action_description_set_attribute (HudActionDescription *description, const gchar *attribute_name, const gchar *format_string, ...); void hud_action_description_set_parameterized (HudActionDescription *parent, GMenuModel *child); /** * SECTION:action-publisher * @short_description: Publish action data to the HUD * @stability: Stable * @include: libhud/action-publisher.h * * Each context in the application should have a #HudActionPublisher * object to represents the actions that are available to the user * when that window and context are visible. This acts as a set of * actions that can be activated by either the window manager changing * focus or the application changing contexts. * * On each action publisher there exits several action groups which can * be separated by allowing different prefixes for those action groups. * A particular prefix should only be used once per action publisher, but * an action group can by used by several action publishers. * * The values describing the action, including the label and description that * show up in the HUD are set via creating a #HudActionDescription for a * action. Each action can have more than one description if there * is a reason to do so. But, it is probably better to use the keywords * attribute in the majority cases. */ G_END_DECLS #pragma GCC visibility pop #endif /* __HUD_ACTION_PUBLISHER_H__ */ hud-14.04+14.04.20140604/libhud/hud.pc.in0000644000015301777760000000033612343623451017665 0ustar pbusernogroup00000000000000libdir=@libdir@ includedir=@includedir@ Cflags: -I${includedir}/libhud-@apiversion@ Requires: glib-2.0 gio-2.0 Libs: -L${libdir} -lhud Name: libhud Description: A library to submit items into the HUD Version: @VERSION@ hud-14.04+14.04.20140604/libhud/marshal.list0000644000015301777760000000002512343623451020473 0ustar pbusernogroup00000000000000VOID: STRING, STRING hud-14.04+14.04.20140604/libhud/hud.h0000644000015301777760000000213212343623451017101 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of either or both of the following licences: * * 1) the GNU Lesser General Public License version 3, as published by * the Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, * see * * Author: Ryan Lortie */ #ifndef __HUD_H__ #define __HUD_H__ #define _HUD_H_INSIDE #include #include #undef _HUD_H_INSIDE #endif /* __HUD_H__ */ hud-14.04+14.04.20140604/libhud/action-publisher.c0000644000015301777760000006500212343623451021571 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of either or both of the following licences: * * 1) the GNU Lesser General Public License version 3, as published by * the Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, * see * * Author: Ryan Lortie */ #include "action-publisher.h" #include "manager.h" #include "marshal.h" #include typedef GMenuModelClass HudAuxClass; typedef struct { GMenuModel parent_instance; HudActionPublisher *publisher; } HudAux; static void hud_aux_init_action_group_iface (GActionGroupInterface *iface); static void hud_aux_init_remote_action_group_iface (GRemoteActionGroupInterface *iface); G_DEFINE_TYPE_WITH_CODE (HudAux, _hud_aux, G_TYPE_MENU_MODEL, G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, hud_aux_init_action_group_iface) G_IMPLEMENT_INTERFACE (G_TYPE_REMOTE_ACTION_GROUP, hud_aux_init_remote_action_group_iface)) typedef GObjectClass HudActionPublisherClass; struct _HudActionPublisher { GObject parent_instance; guint window_id; gchar * context_id; GDBusConnection *bus; GApplication *application; gint export_id; gchar *path; GSequence *descriptions; HudAux *aux; GList * action_groups; }; enum { SIGNAL_ACTION_GROUP_ADDED, SIGNAL_ACTION_GROUP_REMOVED, N_SIGNALS }; guint hud_action_publisher_signals[N_SIGNALS]; G_DEFINE_TYPE (HudActionPublisher, hud_action_publisher, G_TYPE_OBJECT) typedef GObjectClass HudActionDescriptionClass; struct _HudActionDescription { GObject parent_instance; gchar *identifier; gchar *action; GVariant *target; GHashTable *attrs; GHashTable *links; }; guint hud_action_description_changed_signal; G_DEFINE_TYPE (HudActionDescription, hud_action_description, G_TYPE_OBJECT) static gboolean hud_aux_is_mutable (G_GNUC_UNUSED GMenuModel *model) { return TRUE; } static gint hud_aux_get_n_items (GMenuModel *model) { HudAux *aux = (HudAux *) model; return g_sequence_get_length (aux->publisher->descriptions); } static void hud_aux_get_item_attributes (GMenuModel *model, gint item_index, GHashTable **attributes) { HudAux *aux = (HudAux *) model; GSequenceIter *iter; HudActionDescription *description; iter = g_sequence_get_iter_at_pos (aux->publisher->descriptions, item_index); description = g_sequence_get (iter); *attributes = g_hash_table_ref (description->attrs); } static void hud_aux_get_item_links (GMenuModel *model, gint item_index, GHashTable **links) { HudAux *aux = (HudAux *) model; GSequenceIter *iter; HudActionDescription *description; iter = g_sequence_get_iter_at_pos (aux->publisher->descriptions, item_index); description = g_sequence_get (iter); if (description->links != NULL) *links = g_hash_table_ref(description->links); else *links = g_hash_table_new (NULL, NULL); } static void _hud_aux_init (G_GNUC_UNUSED HudAux *aux) { } static void hud_aux_init_action_group_iface (G_GNUC_UNUSED GActionGroupInterface *iface) { } static void hud_aux_init_remote_action_group_iface (G_GNUC_UNUSED GRemoteActionGroupInterface *iface) { } static void hud_action_publisher_action_group_set_destroy (gpointer data) { HudActionPublisherActionGroupSet *group = data; g_free(group->prefix); g_free(group->path); g_free(group); } static void _hud_aux_class_init (HudAuxClass *class) { class->is_mutable = hud_aux_is_mutable; class->get_n_items = hud_aux_get_n_items; class->get_item_attributes = hud_aux_get_item_attributes; class->get_item_links = hud_aux_get_item_links; } static void hud_action_publisher_dispose (GObject *object) { HudActionPublisher *self = HUD_ACTION_PUBLISHER(object); g_clear_object(&self->aux); g_clear_object(&self->application); if (self->export_id != 0) { g_debug("Un-exporting menu model at with id [%d]", self->export_id); g_dbus_connection_unexport_menu_model (self->bus, self->export_id); } g_clear_pointer(&self->path, g_free); g_clear_pointer(&self->descriptions, g_sequence_free); g_list_free_full(self->action_groups, (GDestroyNotify)hud_action_publisher_action_group_set_destroy); g_clear_object(&self->bus); G_OBJECT_CLASS (hud_action_publisher_parent_class)->dispose (object); } static void hud_action_publisher_finalize (GObject *object) { g_clear_pointer (&HUD_ACTION_PUBLISHER(object)->context_id, g_free); G_OBJECT_CLASS (hud_action_publisher_parent_class)->finalize (object); return; } static void hud_action_publisher_init (HudActionPublisher *publisher) { static guint64 next_id; publisher->descriptions = g_sequence_new (g_object_unref); publisher->aux = g_object_new (_hud_aux_get_type (), NULL); publisher->aux->publisher = publisher; publisher->bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); if (!publisher->bus) return; do { guint64 id = next_id++; GError *error = NULL; if (id == 0) publisher->path = g_strdup_printf ("/com/canonical/hud/publisher"); else publisher->path = g_strdup_printf ("/com/canonical/hud/publisher%" G_GUINT64_FORMAT, id); publisher->export_id = g_dbus_connection_export_menu_model (publisher->bus, publisher->path, G_MENU_MODEL (publisher->aux), &error); g_debug("Exporting menu model at [%s] with id [%d]", publisher->path, publisher->export_id); if (!publisher->export_id) { /* try again... */ g_debug("Exporting failed: %s", error->message); g_error_free(error); error = NULL; g_free (publisher->path); publisher->path = NULL; } } while (publisher->path == NULL); } static void hud_action_publisher_class_init (HudActionPublisherClass *class) { class->dispose = hud_action_publisher_dispose; class->finalize = hud_action_publisher_finalize; /** * HudActionPublisher::action-group-added: * @param1: Prefix for the action group * @param2: Path group is exported on DBus * * Emitted when a new action group is added to the publisher */ hud_action_publisher_signals[SIGNAL_ACTION_GROUP_ADDED] = g_signal_new (HUD_ACTION_PUBLISHER_SIGNAL_ACTION_GROUP_ADDED, HUD_TYPE_ACTION_PUBLISHER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _hud_marshal_VOID__STRING_STRING, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); /** * HudActionPublisher::action-group-removed: * @param1: Prefix for the action group * @param2: Path group is exported on DBus * * Emitted when a new action group is removed from the publisher */ hud_action_publisher_signals[SIGNAL_ACTION_GROUP_REMOVED] = g_signal_new (HUD_ACTION_PUBLISHER_SIGNAL_ACTION_GROUP_REMOVED, HUD_TYPE_ACTION_PUBLISHER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, _hud_marshal_VOID__STRING_STRING, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); } /** * hud_action_publisher_new_for_application: * @application: A #GApplication object * * Creates a new #HudActionPublisher and automatically registers the * default actions under the "app" prefix. * * Return value: (transfer full): A new #HudActionPublisher object */ HudActionPublisher * hud_action_publisher_new_for_application (GApplication *application) { HudActionPublisher *publisher; g_return_val_if_fail (G_IS_APPLICATION (application), NULL); g_return_val_if_fail (g_application_get_application_id (application), NULL); g_return_val_if_fail (g_application_get_is_registered (application), NULL); g_return_val_if_fail (!g_application_get_is_remote (application), NULL); publisher = g_object_new (HUD_TYPE_ACTION_PUBLISHER, NULL); publisher->application = g_object_ref (application); hud_action_publisher_add_action_group (publisher, "app", g_application_get_dbus_object_path (application)); return publisher; } static guint context_count = 0; /** * hud_action_publisher_new: * @window_id: (allow-none): A window ID * @context_id: (allow-none): A context ID * * Creates a new #HudActionPublisher based on the window ID passed * in via @window_id and context ID from @context_id. * * Either one of them can be not used by passing in eithe of the * defines #HUD_ACTION_PUBLISHER_ALL_WINDOWS or #HUD_ACTION_PUBLISHER_NO_CONTEXT * for the appropriate parameter. * * Return value: (transfer full): A new #HudActionPublisher object */ HudActionPublisher * hud_action_publisher_new (guint window_id, const gchar * context_id) { HudActionPublisher * publisher; publisher = g_object_new (HUD_TYPE_ACTION_PUBLISHER, NULL); publisher->window_id = window_id; if (context_id != NULL) { publisher->context_id = g_strdup(context_id); } else { publisher->context_id = g_strdup_printf("action-publisher-context-%d", context_count++); } return publisher; } static gchar * format_identifier (const gchar *action_name, GVariant *action_target) { gchar *targetstr; gchar *identifier; if (action_target) { targetstr = g_variant_print (action_target, TRUE); identifier = g_strdup_printf ("%s(%s)", action_name, targetstr); g_free (targetstr); } else identifier = g_strdup_printf ("%s()", action_name); return identifier; } static gint compare_descriptions (gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer user_data) { const HudActionDescription *da = a; const HudActionDescription *db = b; return strcmp (da->identifier, db->identifier); } static void description_changed (HudActionDescription *description, G_GNUC_UNUSED const gchar *attribute_name, gpointer user_data) { HudActionPublisher *publisher = user_data; GSequenceIter *iter; iter = g_sequence_lookup (publisher->descriptions, description, compare_descriptions, NULL); g_assert (g_sequence_get (iter) == description); g_menu_model_items_changed (G_MENU_MODEL (publisher->aux), g_sequence_iter_get_position (iter), 1, 1); } static void disconnect_handler (gpointer data, gpointer user_data) { HudActionPublisher *publisher = user_data; HudActionDescription *description = data; #pragma GCC diagnostic ignored "-Wpedantic" g_signal_handlers_disconnect_by_func (description, description_changed, publisher); #pragma GCC diagnostic pop } /** * hud_action_publisher_add_description: * @publisher: the #HudActionPublisher * @description: an action description * * Adds @description to the list of actions that the application exports * to the HUD. * * If the application is already exporting an action with the same name * and target value as @description then it will be replaced. * * You should only use this API for situations like recent documents and * bookmarks. */ void hud_action_publisher_add_description (HudActionPublisher *publisher, HudActionDescription *description) { GSequenceIter *iter; iter = g_sequence_lookup (publisher->descriptions, description, compare_descriptions, NULL); if (iter == NULL) { /* We are not replacing -- add new. */ iter = g_sequence_insert_sorted (publisher->descriptions, description, compare_descriptions, NULL); /* Signal that we added the items */ g_menu_model_items_changed (G_MENU_MODEL (publisher->aux), g_sequence_iter_get_position (iter), 0, 1); } else { /* We are replacing an existing item. */ disconnect_handler (g_sequence_get (iter), publisher); g_sequence_set (iter, description); /* A replace is 1 remove and 1 add */ g_menu_model_items_changed (G_MENU_MODEL (publisher->aux), g_sequence_iter_get_position (iter), 1, 1); } g_object_ref (description); g_signal_connect (description, "changed", G_CALLBACK (description_changed), publisher); } /** * hud_action_publisher_remove_description: * @publisher: the #HudActionPublisher * @action_name: an action name * @action_target: (allow-none): an action target * * Removes the action descriptions that has the name @action_name and * the target value @action_target (including the possibility of %NULL). **/ void hud_action_publisher_remove_description (HudActionPublisher *publisher, const gchar *action_name, GVariant *action_target) { HudActionDescription tmp; GSequenceIter *iter; tmp.identifier = format_identifier (action_name, action_target); iter = g_sequence_lookup (publisher->descriptions, &tmp, compare_descriptions, NULL); g_free (tmp.identifier); if (iter) { gint position; position = g_sequence_iter_get_position (iter); disconnect_handler (g_sequence_get (iter), publisher); g_sequence_remove (iter); g_menu_model_items_changed (G_MENU_MODEL (publisher->aux), position, 1, 0); } } /** * hud_action_publisher_remove_descriptions: * @publisher: the #HudActionPublisher * @action_name: an action name * * Removes all action descriptions that has the name @action_name and * any target value. **/ void hud_action_publisher_remove_descriptions (HudActionPublisher *publisher, const gchar *action_name) { HudActionDescription before, after; GSequenceIter *start, *end; before.identifier = (gchar *) action_name; after.identifier = g_strconcat (action_name, "~", NULL); start = g_sequence_search (publisher->descriptions, &before, compare_descriptions, NULL); end = g_sequence_search (publisher->descriptions, &after, compare_descriptions, NULL); g_free (after.identifier); if (start != end) { gint s, e; s = g_sequence_iter_get_position (start); e = g_sequence_iter_get_position (end); g_sequence_foreach_range (start, end, disconnect_handler, publisher); g_sequence_remove_range (start, end); g_menu_model_items_changed (G_MENU_MODEL (publisher->aux), s, e - s, 0); } } /** * hud_action_publisher_add_action_group: * @publisher: a #HudActionPublisher * @prefix: the action prefix for the group (like "app") * @object_path: the object path of the exported group * * Informs the HUD of the existance of an action group. * * The action group must be published on the shared session bus * connection of this process at @object_path. * * The @prefix defines the type of action group. Currently "app" and * "win" are supported. For example, if the exported action group * contained a "quit" action and you wanted to refer to it as "app.quit" * from action descriptions, then you would use the @prefix "app" here. * * @identifier is a piece of identifying information, depending on which * @prefix is used. Currently, this should be %NULL for the "app" * @prefix and should be a uint32 specifying the window ID (eg: XID) for * the "win" @prefix. * * You do not need to manually export your action groups if you are * using #GApplication. **/ void hud_action_publisher_add_action_group (HudActionPublisher *publisher, const gchar *prefix, const gchar *object_path) { g_return_if_fail(HUD_IS_ACTION_PUBLISHER(publisher)); g_return_if_fail(prefix != NULL); g_return_if_fail(object_path != NULL); HudActionPublisherActionGroupSet * group = g_new0(HudActionPublisherActionGroupSet, 1); group->prefix = g_strdup(prefix); group->path = g_strdup(object_path); publisher->action_groups = g_list_prepend(publisher->action_groups, group); return; } /** * hud_action_publisher_remove_action_group: * @publisher: a #HudActionPublisher * @prefix: the action prefix for the group (like "app") * @identifier: (allow-none): an identifier, or %NULL * * Informs the HUD that an action group no longer exists. * * This reverses the effect of a previous call to * hud_action_publisher_add_action_group() with the same parameters. */ void hud_action_publisher_remove_action_group (G_GNUC_UNUSED HudActionPublisher *publisher, G_GNUC_UNUSED const gchar *prefix, G_GNUC_UNUSED GVariant *identifier) { //hud_manager_remove_actions (publisher->application_id, prefix, identifier); } /** * hud_action_publisher_get_window_id: * @publisher: A #HudActionPublisher object * * Gets the window ID for this publisher * * Return value: The Window ID associtaed with this action publisher */ guint hud_action_publisher_get_window_id (HudActionPublisher *publisher) { g_return_val_if_fail(HUD_IS_ACTION_PUBLISHER(publisher), 0); return publisher->window_id; } /** * hud_action_publisher_get_context_id: * @publisher: A #HudActionPublisher object * * Gets the context ID for this publisher * * Return value: The context ID associtaed with this action publisher */ const gchar * hud_action_publisher_get_context_id (HudActionPublisher *publisher) { g_return_val_if_fail(HUD_IS_ACTION_PUBLISHER(publisher), 0); return publisher->context_id; } /** * hud_action_publisher_get_action_groups: * @publisher: A #HudActionPublisher object * * Grabs the action groups for this publisher * * Return value: (transfer container) (element-type HudActionPublisherActionGroupSet *): The groups in this publisher */ GList * hud_action_publisher_get_action_groups (HudActionPublisher *publisher) { g_return_val_if_fail(HUD_IS_ACTION_PUBLISHER(publisher), NULL); /* TODO: Flesh out */ return publisher->action_groups; } /** * hud_action_publisher_get_description_path: * @publisher: A #HudActionPublisher object * * Grabs the object path of the description for this publisher * * Return value: The object path of the descriptions */ const gchar * hud_action_publisher_get_description_path (HudActionPublisher *publisher) { g_return_val_if_fail(HUD_IS_ACTION_PUBLISHER(publisher), NULL); return publisher->path; } /** * HudActionDescription: * * A description of an action that is accessible from the HUD. This is * an opaque structure type and all accesses must be made via the API. **/ static void hud_action_description_finalize (GObject *object) { HudActionDescription *description = HUD_ACTION_DESCRIPTION (object); g_free (description->identifier); g_free (description->action); if (description->target) g_variant_unref (description->target); g_hash_table_unref (description->attrs); g_clear_pointer(&description->links, g_hash_table_unref); G_OBJECT_CLASS (hud_action_description_parent_class) ->finalize (object); } static void hud_action_description_init (HudActionDescription *description) { description->attrs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); } static void hud_action_description_class_init (HudActionDescriptionClass *class) { class->finalize = hud_action_description_finalize; /** * HudActionDescription::changed: * @param1: Name of changed property * * Emitted when a property of the action description gets * changed. */ hud_action_description_changed_signal = g_signal_new ("changed", HUD_TYPE_ACTION_DESCRIPTION, G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); } /** * hud_action_description_new: * @action_name: a (namespaced) action name * @action_target: an action target * * Creates a new #HudActionDescription. * * The situations in which you want to do this are limited to "dynamic" * types of actions -- things like bookmarks or recent documents. * * Use hud_action_publisher_add_descriptions_from_file() to take care of * the bulk of the actions in your application. * * Returns: a new #HudActionDescription with no attributes **/ HudActionDescription * hud_action_description_new (const gchar *action_name, GVariant *action_target) { HudActionDescription *description; g_return_val_if_fail (action_name != NULL, NULL); description = g_object_new (HUD_TYPE_ACTION_DESCRIPTION, NULL); description->action = g_strdup (action_name); description->target = action_target ? g_variant_ref_sink (action_target) : NULL; description->identifier = format_identifier (action_name, action_target); g_hash_table_insert (description->attrs, g_strdup ("action"), g_variant_ref_sink (g_variant_new_string (action_name))); if (action_target) g_hash_table_insert (description->attrs, g_strdup ("target"), g_variant_ref_sink (action_target)); return description; } /** * hud_action_description_set_attribute_value: * @description: a #HudActionDescription * @attribute_name: an attribute name * @value: (allow-none): the new value for the attribute * * Sets or unsets an attribute on @description. * * You may not change the "action" or "target" attributes. * * If @value is non-%NULL then it is the new value for attribute. A * %NULL @value unsets @attribute_name. * * @value is consumed if it is floating. **/ void hud_action_description_set_attribute_value (HudActionDescription *description, const gchar *attribute_name, GVariant *value) { /* Don't allow setting the action or target as these form the * identity of the description and are stored separately... */ g_return_if_fail (!g_str_equal (attribute_name, "action")); g_return_if_fail (!g_str_equal (attribute_name, "target")); if (value) g_hash_table_insert (description->attrs, g_strdup (attribute_name), g_variant_ref_sink (value)); else g_hash_table_remove (description->attrs, attribute_name); g_signal_emit (description, hud_action_description_changed_signal, g_quark_try_string (attribute_name), attribute_name); } /** * hud_action_description_set_attribute: * @description: a #HudActionDescription * @attribute_name: an attribute name * @format_string: (allow-none): a #GVariant format string * @...: arguments to @format_string * * Sets or unsets an attribute on @description. * * You may not change the "action" or "target" attributes. * * If @format_string is non-%NULL then this call is equivalent to * g_variant_new() and hud_action_description_set_attribute_value(). * * If @format_string is %NULL then this call is equivalent to * hud_action_description_set_attribute_value() with a %NULL value. **/ void hud_action_description_set_attribute (HudActionDescription *description, const gchar *attribute_name, const gchar *format_string, ...) { GVariant *value; if (format_string != NULL) { va_list ap; va_start (ap, format_string); value = g_variant_new_va (format_string, NULL, &ap); va_end (ap); } else value = NULL; hud_action_description_set_attribute_value (description, attribute_name, value); } /** * hud_action_description_get_action_name: * @description: a #HudActionDescription * * Gets the action name of @description. * * This, together with the action target, uniquely identify an action * description. * * Returns: (transfer none): the action name **/ const gchar * hud_action_description_get_action_name (HudActionDescription *description) { return description->action; } /** * hud_action_description_get_action_target: * @description: a #HudActionDescription * * Gets the action target of @description (ie: the #GVariant that will * be passed to invocations of the action). * * This may be %NULL. * * This, together with the action name, uniquely identify an action * description. * * Returns: (transfer none): the target value **/ GVariant * hud_action_description_get_action_target (HudActionDescription *description) { return description->target; } /** * hud_action_description_set_parameterized: * @parent: a #HudActionDescription * @child: The child #GMenuModel to add * * A function to put one action description as a child for the first * one. This is used for parameterized actions where one can set up * children that are displayed on the 'dialog' mode of the HUD. */ void hud_action_description_set_parameterized (HudActionDescription * parent, GMenuModel * child) { g_return_if_fail(HUD_IS_ACTION_DESCRIPTION(parent)); g_return_if_fail(child == NULL || G_IS_MENU_MODEL(child)); /* NULL is allowed to clear it */ if (parent->links == NULL) { parent->links = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref); } if (child != NULL) { g_hash_table_insert(parent->links, g_strdup(G_MENU_LINK_SUBMENU), g_object_ref(child)); } else { g_hash_table_remove(parent->links, G_MENU_LINK_SUBMENU); } g_signal_emit (parent, hud_action_description_changed_signal, g_quark_try_string (G_MENU_LINK_SUBMENU), G_MENU_LINK_SUBMENU); return; } /** * hud_action_description_ref: * @description: A #HudActionDescription * * Increase the reference count to an action description * * Return value: (transfer none): Value of @description */ HudActionDescription * hud_action_description_ref (HudActionDescription * description) { g_return_val_if_fail(HUD_IS_ACTION_DESCRIPTION(description), NULL); return HUD_ACTION_DESCRIPTION(g_object_ref(description)); } /** * hud_action_description_unref: * @description: A #HudActionDescription * * Decrease the reference count to an action description */ void hud_action_description_unref (HudActionDescription * description) { g_return_if_fail(HUD_IS_ACTION_DESCRIPTION(description)); g_object_unref(description); } hud-14.04+14.04.20140604/libhud/CMakeLists.txt0000644000015301777760000000716512343623451020723 0ustar pbusernogroup00000000000000 add_compiler_export_flags() set(HUD_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) set(HUD_INCLUDE_DIRS ${HUD_INCLUDE_DIRS} PARENT_SCOPE ) include_directories(${HUD_INCLUDE_DIRS}) # FIXME Would rather not include this include_directories(${HUD_SRC_DIR}) add_definitions( -DHUD_COMPILATION=1 ) ########################### # Version Information ########################### set(API_VERSION 2) set(ABI_VERSION 2) ########################### # Generated Lib Hud ########################### set(HUD_GENERATED_HEADERS app-iface.h service-iface.h marshal.h ) set(HUD_GENERATED_SOURCES ) add_gdbus_codegen( OUTFILES HUD_GENERATED_SOURCES NAME service-iface PREFIX com.canonical.hud. NAMESPACE _HudServiceIface SERVICE_XML ${HUD_SERVICE_XML} ) add_gdbus_codegen( OUTFILES HUD_GENERATED_SOURCES NAME app-iface PREFIX com.canonical.hud.Application. NAMESPACE _HudAppIface SERVICE_XML ${HUD_APP_XML} ) add_glib_marshal(HUD_GENERATED_SOURCES marshal _hud_marshal marshal.h ) add_library(hud-generated STATIC ${HUD_GENERATED_SOURCES}) target_link_libraries(hud-generated ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES} ${GIO2_LIBRARIES} ) ########################### # Lib Hud ########################### set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") set(HUD_MAIN_HEADERS hud.h ) set(HUD_HEADERS manager.h action-publisher.h ${HUD_HEADERS} ) set(HUD_SOURCES manager.c action-publisher.c ) add_library(hud SHARED ${HUD_SOURCES}) set_target_properties(hud PROPERTIES VERSION ${API_VERSION}.0.0 SOVERSION ${ABI_VERSION} OUTPUT_NAME "hud" ) set_target_properties( hud PROPERTIES COMPILE_FLAGS "-Wpedantic -Wall -Wextra" ) target_link_libraries(hud hud-generated ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES} -Wl,--no-undefined ) ########################### # Pkg Config ########################### set(HUD_PC "hud-${API_VERSION}.pc") set(apiversion "${API_VERSION}") set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}") set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}") set(VERSION "${ABI_VERSION}") configure_file("hud.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/${HUD_PC}" @ONLY) ########################### # GObject Introspection ########################### if(${INTROSPECTION_FOUND}) include(UseGObjectIntrospection) set(INTROSPECTION_GIRS) set(_introspection_files ${HUD_SOURCES} ${HUD_HEADERS}) set(Hud_2_gir "hud") set(Hud_2_gir_INCLUDES GObject-2.0) gir_get_cflags(_cflags) set(Hud_2_gir_CFLAGS ${_cflags}) set(Hud_2_gir_LIBS hud) list_make_absolute(_abs_introspection_files _introspection_files "${CMAKE_CURRENT_SOURCE_DIR}/") set(Hud_2_gir_FILES ${_abs_introspection_files}) set(Hud_2_gir_SCANNERFLAGS --c-include "hud.h") set(Hud_2_gir_EXPORT_PACKAGES "hud-${API_VERSION}") list(APPEND INTROSPECTION_GIRS Hud-2.gir) gir_add_introspections(INTROSPECTION_GIRS) else() message("Not performing GIR as required tools not found") endif() ########################### # libhud Vala ########################### if(${VALA_FOUND}) if(${INTROSPECTION_FOUND}) vapi_gen(hud-vapi INPUT Hud-2.gir PACKAGES gio-2.0 LIBRARY Hud-2 ) install( FILES ${hud-vapi_OUTPUT} DESTINATION "${CMAKE_INSTALL_DATADIR}/vala/vapi" ) endif() endif() ########################### # Installation ########################### install( FILES ${HUD_MAIN_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/libhud-${API_VERSION}" ) install( FILES ${HUD_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/libhud-${API_VERSION}/libhud" ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${HUD_PC}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" ) install( TARGETS hud LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) hud-14.04+14.04.20140604/libhud/manager.h0000644000015301777760000000757312343623451017751 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of either or both of the following licences: * * 1) the GNU Lesser General Public License version 3, as published by * the Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, * see * * Author: Ted Gould */ #ifndef __HUD_MANAGER_H__ #define __HUD_MANAGER_H__ #pragma GCC visibility push(default) #include #include "action-publisher.h" G_BEGIN_DECLS #define HUD_TYPE_MANAGER (hud_manager_get_type ()) #define HUD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HUD_TYPE_MANAGER, HudManager)) #define HUD_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HUD_TYPE_MANAGER, HudManagerClass)) #define HUD_IS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HUD_TYPE_MANAGER)) #define HUD_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HUD_TYPE_MANAGER)) #define HUD_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HUD_TYPE_MANAGER, HudManagerClass)) /** * HUD_MANAGER_PROP_APPLICATION: * * Define for the string to lookup HudManager:application. */ #define HUD_MANAGER_PROP_APPLICATION "application" /** * HUD_MANAGER_PROP_APP_ID: * * Define for the string to lookup HudManager:app-id. */ #define HUD_MANAGER_PROP_APP_ID "app-id" typedef struct _HudManager HudManager; typedef struct _HudManagerClass HudManagerClass; typedef struct _HudManagerPrivate HudManagerPrivate; /** * HudManagerClass: * @parent_class: The #GObject class * * Class data for #HudManager */ struct _HudManagerClass { GObjectClass parent_class; }; /** * HudManager: * * Instance data for the HUD Manager object. This object * tracks the information exported to the HUD for a specific * application. */ struct _HudManager { GObject parent; HudManagerPrivate * priv; }; GType hud_manager_get_type (void); HudManager * hud_manager_new (const gchar * application_id); HudManager * hud_manager_new_for_application (GApplication * application); void hud_manager_add_actions (HudManager * manager, HudActionPublisher * pub); void hud_manager_remove_actions (HudManager * manager, HudActionPublisher * pub); void hud_manager_switch_window_context (HudManager * manager, HudActionPublisher * pub); /** * SECTION:manager * @short_description: Manage data exported to HUD for the application * @stability: Stable * @include: libhud/manager.h * * Applications that are exporting data to the HUD can export data * for every window or context in the application. This includes * application internal structures like tabs or views on the various * data inside the application. The HUD manager allows for registering * and managing all the actions that are exported to the HUD for the * application. */ G_END_DECLS #pragma GCC visibility pop #endif /* __HUD_MANAGER_H__ */ hud-14.04+14.04.20140604/data/0000755000015301777760000000000012343624372015617 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/data/com.canonical.hud.service.in0000644000015301777760000000012412343623451023063 0ustar pbusernogroup00000000000000[D-BUS Service] Name=com.canonical.hud Exec=@pkglibexecdir@/dbus-activation-hack.sh hud-14.04+14.04.20140604/data/com.canonical.Unity.WindowStack.xml0000644000015301777760000000317412343623451024412 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/data/window-stack-bridge.conf.in0000644000015301777760000000106512343623451022736 0ustar pbusernogroup00000000000000description "Window Stack Bridge" start on started dbus stop on desktop-end pre-start script if [ -z $DBUS_SESSION_BUS_ADDRESS ]; then echo "Working around missing DBUS_SESSION_BUS_ADDRESS variable" printf "DuplicateSignature\0DBusSessionAddressNotSet" | /usr/share/apport/recoverable_problem -p `pidof -s -o 1 init` . "${HOME}/.cache/upstart/dbus-session" initctl set-env "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" fi end script exec @pkglibexecdir@/window-stack-bridge hud-14.04+14.04.20140604/data/com.canonical.hud.query.xml0000644000015301777760000000421412343623451022766 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/data/dbus-activation-hack.sh.in0000755000015301777760000000066012343623451022562 0ustar pbusernogroup00000000000000#!/bin/sh # This is a quick hack to make it so that DBus activation works as the # DBus daemon holds onto the PID until the name gets registered. So we # need the PID to exist until then. 10 seconds should be more that enough # time for the service to register the name. # # This can go away if we get DBus Activation for Upstart if [ "x$UPSTART_SESSION" != "x" ]; then start hud sleep 10 else @pkglibexecdir@/hud-service fi hud-14.04+14.04.20140604/data/com.canonical.hud.xml0000644000015301777760000000415112343623451021622 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/data/com.canonical.indicator.appmenu.hud.gschema.xml0000644000015301777760000000117512343623451026652 0ustar pbusernogroup00000000000000 true Whether to store usage data When the HUD executes operations it stores the execution in order to make the future results better. Some users could choose to not want this data to be stored. If that is the case they should disable this property. hud-14.04+14.04.20140604/data/org.ayatana.bamf.view.xml0000644000015301777760000000717312343623451022427 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/data/hud-gui.desktop0000644000015301777760000000030112343623451020543 0ustar pbusernogroup00000000000000[Desktop Entry] Name=Hud Gui Comment=Test user interface for HUD TryExec=hud-gtk Exec=hud-gtk Icon= Type=Application Categories=Utility; StartupNotify=true OnlyShowIn=Unity; Keywords= Actions= hud-14.04+14.04.20140604/data/com.canonical.AppMenu.Registrar.xml0000644000015301777760000000540312343623451024351 0ustar pbusernogroup00000000000000 An interface to register a menu from an application's window to be displayed in another window.  This manages that association between XWindow Window IDs and the dbus address and object that provides the menu using the dbusmenu dbus interface. The XWindow ID of the window The object on the dbus interface implementing the dbusmenu interface A method to allow removing a window from the database. Windows will also be removed when the client drops off DBus so this is not required. It is polite though. And important for testing. The XWindow ID of the window Gets the registered menu for a given window ID. The XWindow ID of the window to get The address of the connection on DBus (e.g. :1.23 or org.example.service) The path to the object which implements the com.canonical.dbusmenu interface. hud-14.04+14.04.20140604/data/com.canonical.hud.Application.xml0000644000015301777760000000222112343623451024060 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/data/com.canonical.indicator.appmenu.hud.search.gschema.xml0000644000015301777760000000553612343623451030123 0ustar pbusernogroup00000000000000 50 The penalty given to a menu item being in an indicator In order to have the application's menu items appear higher in the search results a slight penalty is given to the indicator menu items. This value represents the percentage of that penalty so a value of '50' is a 50% additional to the calculated distance. 100 Penalty for extra characters added to the search The penalty for each extra character in the search string that does not appear in the text of a menu item. This penalty would be applied if the user typed "fiile" when searching against the menu item "File", for example. 100 Penalty applied if a character is dropped The penalty for each character dropped from the search string, as compared with the text of a menu item. This only applies to missing characters that are not at the end of the search term. This penalty would be applied if the user typed "fle" when searching against the menu item "File", for example. 20 Penalty applied if a character is dropped from the end The penalty for each missing character at the end of a search term. This penalty would be applied if the user typed "fil" when searching against the menu item "File", for example. 150 Penalty applied when the characters are not the same The penalty for each substituted character in the search term. The penalty would be applied if the user typed "fike" when searching against the menu item "File", for example. 30 The highest distance value that is shown in the results After the distances are calculated (including the indicator penalty) then all values above this max are dropped. This means that the history for those entries aren't looked up as well. hud-14.04+14.04.20140604/data/CMakeLists.txt0000644000015301777760000000343012343623451020354 0ustar pbusernogroup00000000000000 ########################### # Dbus Interfaces ########################### install( FILES com.canonical.hud.query.xml com.canonical.hud.xml DESTINATION ${DBUSIFACEDIR} ) ########################### # Dbus Services ########################### set(HUD_SERVICE "${CMAKE_CURRENT_BINARY_DIR}/com.canonical.hud.service" ) set(pkglibexecdir "${CMAKE_INSTALL_FULL_LIBEXECDIR}/hud") configure_file("com.canonical.hud.service.in" "${HUD_SERVICE}" @ONLY ) install( FILES "${HUD_SERVICE}" DESTINATION ${DBUSSERVICEDIR} ) ########################### # Upstart Job ########################### set(HUD_UPSTART "${CMAKE_CURRENT_BINARY_DIR}/hud.conf" ) set(pkglibexecdir "${CMAKE_INSTALL_FULL_LIBEXECDIR}/hud") configure_file("hud.conf.in" "${HUD_UPSTART}" @ONLY ) install( FILES "${HUD_UPSTART}" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions" ) set(pkglibexecdir "${CMAKE_INSTALL_FULL_LIBEXECDIR}/hud") configure_file("dbus-activation-hack.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/dbus-activation-hack.sh" @ONLY ) install( PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/dbus-activation-hack.sh" DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/hud" ) ########################### # Window Stack Bridge ########################### configure_file( "window-stack-bridge.conf.in" "window-stack-bridge.conf" @ONLY ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/window-stack-bridge.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions" ) ########################### # GSettings ########################### add_schema ("com.canonical.indicator.appmenu.hud.gschema.xml") add_schema ("com.canonical.indicator.appmenu.hud.search.gschema.xml") ########################### # Desktop files ########################### install( FILES hud-gui.desktop DESTINATION "${CMAKE_INSTALL_DATADIR}/applications" ) hud-14.04+14.04.20140604/data/hud.conf.in0000644000015301777760000000125312343623523017651 0ustar pbusernogroup00000000000000description "Unity HUD" # Currently started by the dbus service file # start on dbus-activation com.canonical.hud stop on desktop-end start on started dbus and ((xsession SESSION=ubuntu-touch) or (xsession SESSION=ubuntu-touch-surfaceflinger) or (xsession SESSION=ubuntu)) pre-start script if [ -z $DBUS_SESSION_BUS_ADDRESS ]; then echo "Working around missing DBUS_SESSION_BUS_ADDRESS variable" printf "DuplicateSignature\0DBusSessionAddressNotSet" | /usr/share/apport/recoverable_problem -p `pidof -s -o 1 init` . "${HOME}/.cache/upstart/dbus-session" initctl set-env "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" fi end script exec @pkglibexecdir@/hud-service hud-14.04+14.04.20140604/data/org.ayatana.bamf.xml0000644000015301777760000000611412343623451021450 0ustar pbusernogroup00000000000000 hud-14.04+14.04.20140604/NEWS0000644000015301777760000000002712343623451015401 0ustar pbusernogroup00000000000000 No NEWS is good news hud-14.04+14.04.20140604/libhud-client/0000755000015301777760000000000012343624372017431 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/libhud-client/HudClient.h0000644000015301777760000000425412343623451021463 0ustar pbusernogroup00000000000000/* * Copyright (C) 2012, 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef HUDCLIENT_H #define HUDCLIENT_H #include #include #include QT_BEGIN_NAMESPACE class QAbstractItemModel; class QAbstractListModel; class QString; QT_END_NAMESPACE namespace hud { namespace client { class Q_DECL_EXPORT HudClient: public QObject { class Priv; friend Priv; Q_OBJECT public: explicit HudClient(); ~HudClient(); Q_PROPERTY(QAbstractListModel* results READ results) QAbstractListModel * results() const; Q_PROPERTY(QAbstractListModel* appstack READ appstack) QAbstractListModel * appstack() const; Q_PROPERTY(QAbstractListModel* toolBarModel READ toolBarModel) QAbstractListModel * toolBarModel() const; Q_INVOKABLE void executeCommand(int index); Q_INVOKABLE void setQuery(const QString &newQuery); Q_INVOKABLE void setAppstackApp(const QString &applicationId); Q_INVOKABLE void startVoiceQuery(); Q_INVOKABLE void executeParametrizedAction(const QVariant &values); Q_INVOKABLE void updateParametrizedAction(const QVariant &values); Q_INVOKABLE void cancelParametrizedAction(); Q_INVOKABLE void executeToolBarAction(HudClientQueryToolbarItems action); Q_SIGNALS: void voiceQueryLoading(); void voiceQueryListening(); void voiceQueryHeardSomething(); void voiceQueryFailed(); void voiceQueryFinished(const QString &query); void commandExecuted(); void showParametrizedAction(const QString &action, const QVariant &items); void modelsChanged(); protected: QScopedPointer p; }; } } Q_DECLARE_METATYPE(HudClientQueryToolbarItems) #endif hud-14.04+14.04.20140604/libhud-client/HudToolbarModel.h0000644000015301777760000000231312343623451022622 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef HUDTOOLBARMODEL_H #define HUDTOOLBARMODEL_H #include #include typedef struct _HudClientQuery HudClientQuery; namespace hud { namespace client { class HudToolBarModel: public QAbstractListModel { class Priv; Q_OBJECT public: explicit HudToolBarModel(HudClientQuery *query); ~HudToolBarModel(); int rowCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &parent, int role) const; QHash roleNames() const; void updatedByBackend(); private: QScopedPointer p; }; } } #endif hud-14.04+14.04.20140604/libhud-client/param.c0000644000015301777760000003160412343623451020676 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "param.h" #include #include struct _HudClientParamPrivate { GDBusConnection * session; gchar * dbus_address; gchar * base_action; gchar * action_path; gchar * model_path; gint model_section; /* These are the ones we care about */ GMenuModel * model; GActionGroup * base_actions; GActionGroup * actions; /* This is what we need to get those */ GDBusMenuModel * base_model; gulong base_model_changes; gulong action_added; GList * queued_commands; }; /* Signals */ enum { MODEL_READY, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; /* Prototypes */ static void hud_client_param_class_init (HudClientParamClass *klass); static void hud_client_param_init (HudClientParam *self); static void hud_client_param_dispose (GObject *object); static void hud_client_param_finalize (GObject *object); static void action_write_state (HudClientParam * param, const gchar * action); static void base_model_items (GMenuModel * model, gint position, gint removed, gint added, gpointer user_data); /* Boiler plate */ #define HUD_CLIENT_PARAM_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), HUD_CLIENT_TYPE_PARAM, HudClientParamPrivate)) G_DEFINE_TYPE (HudClientParam, hud_client_param, G_TYPE_OBJECT) /* Code */ static void hud_client_param_class_init (HudClientParamClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (HudClientParamPrivate)); object_class->dispose = hud_client_param_dispose; object_class->finalize = hud_client_param_finalize; /** * HudClientParam::model-ready: * @arg0: The #HudClientParam object. * * Emitted when the model can be used. It may also be updating, but * the base item is there. */ signals[MODEL_READY] = g_signal_new(HUD_CLIENT_PARAM_SIGNAL_MODEL_READY, G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(HudClientParamClass, model_ready), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); return; } static void hud_client_param_init (HudClientParam *self) { self->priv = HUD_CLIENT_PARAM_GET_PRIVATE(self); self->priv->session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); return; } static void hud_client_param_dispose (GObject *object) { HudClientParam * param = HUD_CLIENT_PARAM(object); action_write_state(param, "end"); if (param->priv->base_model_changes != 0) { g_signal_handler_disconnect(param->priv->base_model, param->priv->base_model_changes); param->priv->base_model_changes = 0; } if (param->priv->action_added != 0) { g_signal_handler_disconnect(param->priv->actions, param->priv->action_added); param->priv->action_added = 0; } g_clear_object(¶m->priv->base_model); g_clear_object(¶m->priv->model); g_clear_object(¶m->priv->base_actions); g_clear_object(¶m->priv->actions); g_clear_object(¶m->priv->session); G_OBJECT_CLASS (hud_client_param_parent_class)->dispose (object); return; } static void hud_client_param_finalize (GObject *object) { HudClientParam * param = HUD_CLIENT_PARAM(object); g_list_free_full(param->priv->queued_commands, g_free); param->priv->queued_commands = NULL; g_clear_pointer(¶m->priv->base_action, g_free); g_clear_pointer(¶m->priv->action_path, g_free); g_clear_pointer(¶m->priv->model_path, g_free); G_OBJECT_CLASS (hud_client_param_parent_class)->finalize (object); return; } /* Writes to the base action a particular state */ static void action_write_state (HudClientParam * param, const gchar * action) { /* This shows that they're not interested in these events, which is fine, perhaps a bit lonely, but fine. */ if (param->priv->base_action == NULL) { return; } if (!g_action_group_has_action(param->priv->actions, param->priv->base_action)) { if (param->priv->action_added != 0) { /* We're looking for the action, queue the command */ param->priv->queued_commands = g_list_append(param->priv->queued_commands, g_strdup(action)); return; } else { /* Uhm, oh, my! We shouldn't be here */ g_warning("We've got an action name, but it doesn't exist, and we've given up looking. Why would we give up?"); return; } } const GVariantType * type = g_action_group_get_action_parameter_type(param->priv->actions, param->priv->base_action); GVariant * action_param = NULL; if (g_variant_type_equal(type, G_VARIANT_TYPE_STRING)) { action_param = g_variant_new_string(action); } else if (g_variant_type_equal(type, G_VARIANT_TYPE("(ssav)"))) { GVariantBuilder tuple; g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE); g_variant_builder_add_value(&tuple, g_variant_new_string(action)); g_variant_builder_add_value(&tuple, g_variant_new_string("")); g_variant_builder_add_value(&tuple, g_variant_new_array(G_VARIANT_TYPE_VARIANT, NULL, 0)); action_param = g_variant_builder_end(&tuple); } if (action_param == NULL) { gchar * typestring = g_variant_type_dup_string(type); g_warning("Unable to signal to a action with the parameter type of: %s", typestring); g_free(typestring); return; } g_action_group_activate_action(param->priv->actions, param->priv->base_action, action_param); return; } /* Look at the items changed and make sure we're getting the item that we expect. Then signal. */ static void base_model_items (G_GNUC_UNUSED GMenuModel * model, gint position, gint removed, G_GNUC_UNUSED gint added, gpointer user_data) { g_return_if_fail(position == 0); g_return_if_fail(removed == 0); g_return_if_fail(HUD_CLIENT_IS_PARAM(user_data)); HudClientParam * param = HUD_CLIENT_PARAM(user_data); int i = 0; if(param->priv->base_action != NULL) { for(; i < g_menu_model_get_n_items(G_MENU_MODEL(param->priv->base_model)); ++i) { gchar *action = NULL; g_menu_model_get_item_attribute(G_MENU_MODEL(param->priv->base_model), i, "action", "s", &action); if(g_str_has_suffix(action, param->priv->base_action)) { g_free(action); break; } g_free(action); } } param->priv->model = g_menu_model_get_item_link(G_MENU_MODEL(param->priv->base_model), i, G_MENU_LINK_SUBMENU); if(param->priv->model == NULL) { g_warning("linked sub-model could not be found"); return; } g_signal_emit(param, signals[MODEL_READY], 0); if (param->priv->base_model_changes != 0) { g_signal_handler_disconnect(param->priv->base_model, param->priv->base_model_changes); param->priv->base_model_changes = 0; } return; } /* Look to see if our base item gets added to the actions list on the service side */ static void action_added (G_GNUC_UNUSED GActionGroup * group, const gchar * action_name, gpointer user_data) { g_return_if_fail(HUD_CLIENT_IS_PARAM(user_data)); HudClientParam * param = HUD_CLIENT_PARAM(user_data); if (g_strcmp0(param->priv->base_action, action_name) != 0) { /* This is not the action we're looking for */ return; } /* We don't need to know again */ if (param->priv->action_added != 0) { g_signal_handler_disconnect(param->priv->actions, param->priv->action_added); param->priv->action_added = 0; } /* Now process the queue */ GList * command; for (command = param->priv->queued_commands; command != NULL; command = g_list_next(command)) { action_write_state(param, (gchar *)command->data); } /* And clear it */ g_list_free_full(param->priv->queued_commands, g_free); param->priv->queued_commands = NULL; return; } /** * hud_client_param_new: * @dbus_address: The address on dbus to find the actions * @prefix: The prefix the menu is using * @base_action: The action to send events for the dialog on * @action_path: DBus path to the action object * @model_path: DBus path to the menu model object * @model_section: Section of the model to use * * Create a new #HudClientParam object for adjusting a specified * paramaterized dialog. * * Return value: (transfer full): A new #HudClientParam dialog */ HudClientParam * hud_client_param_new (const gchar * dbus_address, const gchar *prefix, const gchar * base_action, const gchar * action_path, const gchar * model_path, gint model_section) { g_return_val_if_fail(dbus_address != NULL, NULL); /* NOTE: base_action is not required -- though probably a NULL string */ g_return_val_if_fail(g_variant_is_object_path(action_path), NULL); g_return_val_if_fail(g_variant_is_object_path(model_path), NULL); HudClientParam * param = g_object_new(HUD_CLIENT_TYPE_PARAM, NULL); param->priv->dbus_address = g_strdup(dbus_address); param->priv->action_path = g_strdup(action_path); param->priv->model_path = g_strdup(model_path); param->priv->model_section = model_section; /* Keep the value NULL if we've got an empty string */ if (base_action != NULL && base_action[0] != '\0') { if (prefix != NULL && prefix[0] != '\0') { param->priv->base_action = g_strdup_printf("%s.%s", prefix, base_action); } else { param->priv->base_action = g_strdup(base_action); } } g_warn_if_fail(model_section == 1); param->priv->base_model = g_dbus_menu_model_get(param->priv->session, param->priv->dbus_address, param->priv->model_path); if (g_menu_model_get_n_items(G_MENU_MODEL(param->priv->base_model)) == 0) { param->priv->base_model_changes = g_signal_connect(G_OBJECT(param->priv->base_model), "items-changed", G_CALLBACK(base_model_items), param); } else { base_model_items(G_MENU_MODEL(param->priv->base_model), 0, 0, 1, param); } GDBusActionGroup * dbus_ag = g_dbus_action_group_get(param->priv->session, param->priv->dbus_address, param->priv->action_path); param->priv->base_actions = G_ACTION_GROUP(dbus_ag); GActionMuxer *muxer = g_action_muxer_new(); g_action_muxer_insert(muxer, "hud", param->priv->base_actions); param->priv->actions = G_ACTION_GROUP(muxer); /* Looking for a base action here */ if (param->priv->base_action != NULL && !g_action_group_has_action(param->priv->actions, param->priv->base_action)) { param->priv->action_added = g_signal_connect(G_OBJECT(param->priv->actions), "action-added", G_CALLBACK(action_added), param); } else { action_write_state(param, "start"); } return param; } /** * hud_client_param_get_actions: * @param: The #HudClientParam to query * * The object path to the actions * * Return value: (transfer none): A #GActionGroup that has the actions in it */ GActionGroup * hud_client_param_get_actions (HudClientParam * param) { g_return_val_if_fail(HUD_CLIENT_IS_PARAM(param), NULL); return param->priv->actions; } /** * hud_client_param_get_model: * @param: The #HudClientParam to query * * The object path to the model * * Return value: (transfer none): The menu model of the pane */ GMenuModel * hud_client_param_get_model (HudClientParam * param) { g_return_val_if_fail(HUD_CLIENT_IS_PARAM(param), NULL); return param->priv->model; } /** * hud_client_param_send_reset: * @param: The #HudClientParam to query * * Send the command to the application to reset the values * of the actions in the pane. */ void hud_client_param_send_reset (HudClientParam * param) { g_return_if_fail(HUD_CLIENT_IS_PARAM(param)); action_write_state(param, "reset"); return; } /** * hud_client_param_send_cancel: * @param: The #HudClientParam to query * * Send the command to the application to cancel the values * of the actions in the panel and expect it to close soon. */ void hud_client_param_send_cancel (HudClientParam * param) { g_return_if_fail(HUD_CLIENT_IS_PARAM(param)); action_write_state(param, "cancel"); return; } /** * hud_client_param_send_commit: * @param: The #HudClientParam to query * * Tell the application that the user has requested the values * be applied. This doesn't mean that there isn't a dialog * still open, when it closes "end" will be sent. */ void hud_client_param_send_commit (HudClientParam * param) { g_return_if_fail(HUD_CLIENT_IS_PARAM(param)); action_write_state(param, "commit"); return; } hud-14.04+14.04.20140604/libhud-client/action-muxer.h0000644000015301777760000000323212343623451022212 0ustar pbusernogroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel * Ryan Lortie */ #ifndef __G_ACTION_MUXER_H__ #define __G_ACTION_MUXER_H__ #include #define G_TYPE_ACTION_MUXER (g_action_muxer_get_type ()) #define G_ACTION_MUXER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_ACTION_MUXER, GActionMuxer)) #define G_IS_ACTION_MUXER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_ACTION_MUXER)) typedef struct _GActionMuxer GActionMuxer; GType g_action_muxer_get_type (void) G_GNUC_CONST; GActionMuxer * g_action_muxer_new (void); void g_action_muxer_insert (GActionMuxer *muxer, const gchar *prefix, GActionGroup *group); void g_action_muxer_remove (GActionMuxer *muxer, const gchar *prefix); GActionGroup * g_action_muxer_get (GActionMuxer *muxer, const gchar *prefix); #endif hud-14.04+14.04.20140604/libhud-client/action-muxer.c0000644000015301777760000004071112343623451022210 0ustar pbusernogroup00000000000000/* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel * Ryan Lortie */ #include #include /* * SECTION:gactionmuxer * @short_description: Aggregate several action groups * * #GActionMuxer is a #GActionGroup that is capable of containing other * #GActionGroup instances. * * The typical use is aggregating all of the actions applicable to a * particular context into a single action group, with namespacing. * * Consider the case of two action groups -- one containing actions * applicable to an entire application (such as 'quit') and one * containing actions applicable to a particular window in the * application (such as 'fullscreen'). * * In this case, each of these action groups could be added to a * #GActionMuxer with the prefixes "app" and "win", respectively. This * would expose the actions as "app.quit" and "win.fullscreen" on the * #GActionGroup interface presented by the #GActionMuxer. * * Activations and state change requests on the #GActionMuxer are wired * through to the underlying action group in the expected way. */ typedef GObjectClass GActionMuxerClass; struct _GActionMuxer { GObject parent; GActionGroup *global_actions; GHashTable *groups; /* prefix -> subgroup */ GHashTable *reverse; /* subgroup -> prefix */ }; static void g_action_muxer_group_init (GActionGroupInterface *iface); static void g_action_muxer_dispose (GObject *object); static void g_action_muxer_finalize (GObject *object); static void g_action_muxer_disconnect_group (GActionMuxer *muxer, GActionGroup *subgroup); static gchar ** g_action_muxer_list_actions (GActionGroup *group); static void g_action_muxer_activate_action (GActionGroup *group, const gchar *action_name, GVariant *parameter); static void g_action_muxer_change_action_state (GActionGroup *group, const gchar *action_name, GVariant *value); static gboolean g_action_muxer_query_action (GActionGroup *group, const gchar *action_name, gboolean *enabled, const GVariantType **parameter_type, const GVariantType **state_type, GVariant **state_hint, GVariant **state); static void g_action_muxer_action_added (GActionGroup *group, gchar *action_name, gpointer user_data); static void g_action_muxer_action_removed (GActionGroup *group, gchar *action_name, gpointer user_data); static void g_action_muxer_action_state_changed (GActionGroup *group, gchar *action_name, GVariant *value, gpointer user_data); static void g_action_muxer_action_enabled_changed (GActionGroup *group, gchar *action_name, gboolean enabled, gpointer user_data); G_DEFINE_TYPE_WITH_CODE (GActionMuxer, g_action_muxer, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, g_action_muxer_group_init)) static void g_action_muxer_class_init (GObjectClass *klass) { klass->dispose = g_action_muxer_dispose; klass->finalize = g_action_muxer_finalize; } static void g_action_muxer_init (GActionMuxer *muxer) { muxer->global_actions = NULL; muxer->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); muxer->reverse = g_hash_table_new (g_direct_hash, g_direct_equal); } static void g_action_muxer_group_init (GActionGroupInterface *iface) { iface->list_actions = g_action_muxer_list_actions; iface->activate_action = g_action_muxer_activate_action; iface->change_action_state = g_action_muxer_change_action_state; iface->query_action = g_action_muxer_query_action; } static void g_action_muxer_dispose (GObject *object) { GActionMuxer *muxer = G_ACTION_MUXER (object); GHashTableIter it; GActionGroup *subgroup; if (muxer->global_actions) { g_action_muxer_disconnect_group (muxer, muxer->global_actions); g_clear_object (&muxer->global_actions); } g_hash_table_iter_init (&it, muxer->groups); while (g_hash_table_iter_next (&it, NULL, (gpointer *) &subgroup)) g_action_muxer_disconnect_group (muxer, subgroup); g_hash_table_remove_all (muxer->groups); g_hash_table_remove_all (muxer->reverse); } static void g_action_muxer_finalize (GObject *object) { GActionMuxer *muxer = G_ACTION_MUXER (object); g_hash_table_unref (muxer->groups); g_hash_table_unref (muxer->reverse); G_OBJECT_CLASS (g_action_muxer_parent_class)->finalize (object); } static GActionGroup * g_action_muxer_lookup_group (GActionMuxer *muxer, const gchar *full_name, const gchar **action_name) { const gchar *sep; GActionGroup *group; sep = strchr (full_name, '.'); if (sep) { gchar *prefix; prefix = g_strndup (full_name, sep - full_name); group = g_hash_table_lookup (muxer->groups, prefix); g_free (prefix); if (action_name) *action_name = sep + 1; } else { group = muxer->global_actions; if (action_name) *action_name = full_name; } return group; } static gchar * g_action_muxer_lookup_full_name (GActionMuxer *muxer, GActionGroup *subgroup, const gchar *action_name) { gpointer prefix; if (subgroup == muxer->global_actions) return g_strdup (action_name); if (g_hash_table_lookup_extended (muxer->reverse, subgroup, NULL, &prefix)) return g_strdup_printf ("%s.%s", (gchar *) prefix, action_name); return NULL; } static void g_action_muxer_disconnect_group (GActionMuxer *muxer, GActionGroup *subgroup) { gchar **actions; gchar **action; actions = g_action_group_list_actions (subgroup); for (action = actions; *action; action++) g_action_muxer_action_removed (subgroup, *action, muxer); g_strfreev (actions); #pragma GCC diagnostic ignored "-Wpedantic" g_signal_handlers_disconnect_by_func (subgroup, (gpointer) g_action_muxer_action_added, muxer); g_signal_handlers_disconnect_by_func (subgroup, (gpointer) g_action_muxer_action_removed, muxer); g_signal_handlers_disconnect_by_func (subgroup, (gpointer) g_action_muxer_action_enabled_changed, muxer); g_signal_handlers_disconnect_by_func (subgroup, (gpointer) g_action_muxer_action_state_changed, muxer); #pragma GCC diagnostic pop } static gchar ** g_action_muxer_list_actions (GActionGroup *group) { GActionMuxer *muxer = G_ACTION_MUXER (group); GHashTableIter it; GArray *all_actions; gchar *prefix; GActionGroup *subgroup; gchar **actions; gchar **a; all_actions = g_array_sized_new (TRUE, FALSE, sizeof (gchar *), 8); if (muxer->global_actions) { actions = g_action_group_list_actions (muxer->global_actions); for (a = actions; *a; a++) { gchar *name = g_strdup (*a); g_array_append_val (all_actions, name); } g_strfreev (actions); } g_hash_table_iter_init (&it, muxer->groups); while (g_hash_table_iter_next (&it, (gpointer *) &prefix, (gpointer *) &subgroup)) { actions = g_action_group_list_actions (subgroup); for (a = actions; *a; a++) { gchar *full_name = g_strdup_printf ("%s.%s", prefix, *a); g_array_append_val (all_actions, full_name); } g_strfreev (actions); } return (gchar **) g_array_free (all_actions, FALSE); } static void g_action_muxer_activate_action (GActionGroup *group, const gchar *action_name, GVariant *parameter) { GActionMuxer *muxer = G_ACTION_MUXER (group); GActionGroup *subgroup; const gchar *action; g_return_if_fail (action_name != NULL); subgroup = g_action_muxer_lookup_group (muxer, action_name, &action); if (subgroup) g_action_group_activate_action (subgroup, action, parameter); } static void g_action_muxer_change_action_state (GActionGroup *group, const gchar *action_name, GVariant *value) { GActionMuxer *muxer = G_ACTION_MUXER (group); GActionGroup *subgroup; const gchar *action; g_return_if_fail (action_name != NULL); subgroup = g_action_muxer_lookup_group (muxer, action_name, &action); if (subgroup) g_action_group_change_action_state (subgroup, action, value); } static gboolean g_action_muxer_query_action (GActionGroup *group, const gchar *action_name, gboolean *enabled, const GVariantType **parameter_type, const GVariantType **state_type, GVariant **state_hint, GVariant **state) { GActionMuxer *muxer = G_ACTION_MUXER (group); GActionGroup *subgroup; const gchar *action; g_return_val_if_fail (action_name != NULL, FALSE); subgroup = g_action_muxer_lookup_group (muxer, action_name, &action); if (!subgroup) return FALSE; return g_action_group_query_action (subgroup, action, enabled, parameter_type, state_type, state_hint, state); } static void g_action_muxer_action_added (GActionGroup *group, gchar *action_name, gpointer user_data) { GActionMuxer *muxer = user_data; gchar *full_name; full_name = g_action_muxer_lookup_full_name (muxer, group, action_name); if (full_name) { g_action_group_action_added (G_ACTION_GROUP (muxer), full_name); g_free (full_name); } } static void g_action_muxer_action_removed (GActionGroup *group, gchar *action_name, gpointer user_data) { GActionMuxer *muxer = user_data; gchar *full_name; full_name = g_action_muxer_lookup_full_name (muxer, group, action_name); if (full_name) { g_action_group_action_removed (G_ACTION_GROUP (muxer), full_name); g_free (full_name); } } static void g_action_muxer_action_state_changed (GActionGroup *group, gchar *action_name, GVariant *value, gpointer user_data) { GActionMuxer *muxer = user_data; gchar *full_name; full_name = g_action_muxer_lookup_full_name (muxer, group, action_name); if (full_name) { g_action_group_action_state_changed (G_ACTION_GROUP (muxer), full_name, value); g_free (full_name); } } static void g_action_muxer_action_enabled_changed (GActionGroup *group, gchar *action_name, gboolean enabled, gpointer user_data) { GActionMuxer *muxer = user_data; gchar *full_name; full_name = g_action_muxer_lookup_full_name (muxer, group, action_name); if (full_name) { g_action_group_action_enabled_changed (G_ACTION_GROUP (muxer), full_name, enabled); g_free (full_name); } } /* * g_action_muxer_new: * * Creates a new #GActionMuxer. */ GActionMuxer * g_action_muxer_new (void) { return g_object_new (G_TYPE_ACTION_MUXER, NULL); } /* * g_action_muxer_insert: * @muxer: a #GActionMuxer * @prefix: (allow-none): the prefix string for the action group, or NULL * @group: (allow-none): a #GActionGroup, or NULL * * Adds the actions in @group to the list of actions provided by @muxer. * @prefix is prefixed to each action name, such that for each action * x in @group, there is an equivalent action * @prefix.x in @muxer. * * For example, if @prefix is "app" and @group contains an * action called "quit", then @muxer will now contain an * action called "app.quit". * * If @prefix is NULL, the actions in @group will be added * to @muxer without prefix. * * If @group is NULL, this function has the same effect as * calling g_action_muxer_remove() with @prefix. * * There may only be one group per prefix (including the * NULL-prefix). If a group has been added with @prefix in * a previous call to this function, it will be removed. * * @prefix must not contain a dot ('.'). */ void g_action_muxer_insert (GActionMuxer *muxer, const gchar *prefix, GActionGroup *group) { gchar *prefix_copy; gchar **actions; gchar **action; g_return_if_fail (G_IS_ACTION_MUXER (muxer)); g_return_if_fail (G_IS_ACTION_GROUP (group)); g_action_muxer_remove (muxer, prefix); if (prefix) { prefix_copy = g_strdup (prefix); g_hash_table_insert (muxer->groups, prefix_copy, g_object_ref (group)); g_hash_table_insert (muxer->reverse, group, prefix_copy); } else muxer->global_actions = g_object_ref (group); actions = g_action_group_list_actions (group); for (action = actions; *action; action++) g_action_muxer_action_added (group, *action, muxer); g_strfreev (actions); g_signal_connect (group, "action-added", G_CALLBACK (g_action_muxer_action_added), muxer); g_signal_connect (group, "action-removed", G_CALLBACK (g_action_muxer_action_removed), muxer); g_signal_connect (group, "action-enabled-changed", G_CALLBACK (g_action_muxer_action_enabled_changed), muxer); g_signal_connect (group, "action-state-changed", G_CALLBACK (g_action_muxer_action_state_changed), muxer); } /* * g_action_muxer_remove: * @muxer: a #GActionMuxer * @prefix: (allow-none): the prefix of the action group to remove, or NULL * * Removes a #GActionGroup from the #GActionMuxer. */ void g_action_muxer_remove (GActionMuxer *muxer, const gchar *prefix) { GActionGroup *subgroup; g_return_if_fail (G_IS_ACTION_MUXER (muxer)); subgroup = prefix ? g_hash_table_lookup (muxer->groups, prefix) : muxer->global_actions; if (!subgroup) return; g_action_muxer_disconnect_group (muxer, subgroup); if (prefix) { g_hash_table_remove (muxer->groups, prefix); g_hash_table_remove (muxer->reverse, subgroup); } else g_clear_object (&muxer->global_actions); } /* * g_action_muxer_get: * @muxer: a #GActionMuxer * @prefix: (allow-none): the prefix of the action group to get, or NULL * * Looks for an action group and returns it if found * * Return value: (transfer none): Action group that matches @prefix */ GActionGroup * g_action_muxer_get (GActionMuxer * muxer, const gchar * prefix) { g_return_val_if_fail (G_IS_ACTION_MUXER (muxer), NULL); return prefix ? g_hash_table_lookup (muxer->groups, prefix) : muxer->global_actions; } hud-14.04+14.04.20140604/libhud-client/query.c0000644000015301777760000007043112343623451020744 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "query.h" #include "connection.h" #include "connection-private.h" #include "query-iface.h" #include "enum-types.h" #include "common/query-columns.h" #include "common/shared-values.h" struct _HudClientQueryPrivate { _HudQueryComCanonicalHudQuery * proxy; HudClientConnection * connection; guint connection_changed_sig; gchar * query; DeeModel * results; DeeModel * appstack; GArray * toolbar; }; #define HUD_CLIENT_QUERY_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), HUD_CLIENT_TYPE_QUERY, HudClientQueryPrivate)) enum { PROP_0 = 0, PROP_CONNECTION, PROP_QUERY }; #define PROP_CONNECTION_S "connection" #define PROP_QUERY_S "query" static void hud_client_query_class_init (HudClientQueryClass *klass); static void hud_client_query_init (HudClientQuery *self); static void hud_client_query_constructed (GObject *object); static void hud_client_query_dispose (GObject *object); static void hud_client_query_finalize (GObject *object); static void set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec); static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec); static void connection_status (HudClientConnection * connection, gboolean connected, HudClientQuery * query); static void new_query_cb (HudClientConnection * connection, const gchar * path, const gchar * results, const gchar * appstack, gpointer user_data); G_DEFINE_TYPE (HudClientQuery, hud_client_query, G_TYPE_OBJECT) static guint signal_toolbar_updated = 0; static guint hud_client_query_signal_voice_query_loading; static guint hud_client_query_signal_voice_query_failed; static guint hud_client_query_signal_voice_query_listening; static guint hud_client_query_signal_voice_query_heard_something; static guint hud_client_query_signal_voice_query_finished; static guint hud_client_query_signal_models_changed = 0; static void hud_client_query_class_init (HudClientQueryClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (HudClientQueryPrivate)); object_class->dispose = hud_client_query_dispose; object_class->finalize = hud_client_query_finalize; object_class->constructed = hud_client_query_constructed; object_class->set_property = set_property; object_class->get_property = get_property; g_object_class_install_property (object_class, PROP_CONNECTION, g_param_spec_object(PROP_CONNECTION_S, "Connection to the HUD service", "HUD service connection", HUD_CLIENT_TYPE_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_QUERY, g_param_spec_string(PROP_QUERY_S, "Query to the HUD service", "HUD query", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); /** * HudClientQuery::toolbar-updated: * * The active items in the toolbar changed. Please requery. */ signal_toolbar_updated = g_signal_new (HUD_CLIENT_QUERY_SIGNAL_TOOLBAR_UPDATED, HUD_CLIENT_TYPE_QUERY, G_SIGNAL_RUN_LAST, 0, /* offset */ NULL, NULL, /* Accumulator */ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); /** * HudClientQuery::voice-query-loading: * * The voice recognition toolkit is loading, and not ready for speech yet. */ hud_client_query_signal_voice_query_loading = g_signal_new ( "voice-query-loading", HUD_CLIENT_TYPE_QUERY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * HudClientQuery::voice-query-failed: * * The voice recognition toolkit has failed to connect to the audio device. * The specific cause is provided as an argument. */ hud_client_query_signal_voice_query_failed = g_signal_new ( "voice-query-failed", HUD_CLIENT_TYPE_QUERY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING ); /** * HudClientQuery::voice-query-listening: * * The voice recognition toolkit is active and listening for speech. */ hud_client_query_signal_voice_query_listening = g_signal_new ( "voice-query-listening", HUD_CLIENT_TYPE_QUERY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * HudClientQuery::voice-query-heard-something: * * The voice recognition toolkit has heard an utterance. */ hud_client_query_signal_voice_query_heard_something = g_signal_new ( "voice-query-heard-something", HUD_CLIENT_TYPE_QUERY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * HudClientQuery::voice-query-finished: * * The voice recognition toolkit has completed and has a (possibly empty) result. */ hud_client_query_signal_voice_query_finished = g_signal_new ( "voice-query-finished", HUD_CLIENT_TYPE_QUERY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING ); /** * HudClientQuery::models-changed: * * Something has caused the models to be changed, you should probably * figure out their state again. */ hud_client_query_signal_models_changed = g_signal_new ( HUD_CLIENT_QUERY_SIGNAL_MODELS_CHANGED, HUD_CLIENT_TYPE_QUERY, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE ); return; } static void hud_client_query_init (HudClientQuery *self) { self->priv = HUD_CLIENT_QUERY_GET_PRIVATE(self); self->priv->toolbar = g_array_new(FALSE, /* zero terminated */ FALSE, /* clear */ sizeof(HudClientQueryToolbarItems)); return; } static void set_property (GObject * obj, guint id, const GValue * value, G_GNUC_UNUSED GParamSpec * pspec) { HudClientQuery * self = HUD_CLIENT_QUERY(obj); switch (id) { case PROP_CONNECTION: g_clear_object(&self->priv->connection); self->priv->connection = g_value_dup_object(value); break; case PROP_QUERY: hud_client_query_set_query(self, g_value_get_string(value)); break; default: g_warning("Unknown property %d.", id); return; } return; } static void get_property (GObject * obj, guint id, GValue * value, G_GNUC_UNUSED GParamSpec * pspec) { HudClientQuery * self = HUD_CLIENT_QUERY(obj); switch (id) { case PROP_CONNECTION: g_value_set_object(value, self->priv->connection); break; case PROP_QUERY: g_value_set_string(value, self->priv->query); break; default: g_warning("Unknown property %d.", id); return; } return; } static void hud_client_query_voice_query_loading (G_GNUC_UNUSED _HudQueryComCanonicalHudQuery *object, gpointer user_data) { g_signal_emit(user_data, hud_client_query_signal_voice_query_loading, 0); } static void hud_client_query_voice_query_listening (G_GNUC_UNUSED _HudQueryComCanonicalHudQuery *object, gpointer user_data) { g_signal_emit(user_data, hud_client_query_signal_voice_query_listening, 0); } static void hud_client_query_voice_query_heard_something (G_GNUC_UNUSED _HudQueryComCanonicalHudQuery *object, gpointer user_data) { g_signal_emit(user_data, hud_client_query_signal_voice_query_heard_something, 0); } static void hud_client_query_constructed (GObject *object) { HudClientQuery * cquery = HUD_CLIENT_QUERY(object); G_OBJECT_CLASS (hud_client_query_parent_class)->constructed (object); if (cquery->priv->connection == NULL) { cquery->priv->connection = hud_client_connection_get_ref(); } cquery->priv->connection_changed_sig = g_signal_connect(cquery->priv->connection, HUD_CLIENT_CONNECTION_SIGNAL_CONNECTION_STATUS, G_CALLBACK(connection_status), cquery); if(cquery->priv->query == NULL) { cquery->priv->query = g_strdup(""); } connection_status(cquery->priv->connection, hud_client_connection_connected(cquery->priv->connection), cquery); return; } /* Handles the connection status of the HUD service, once we're connected we can do all kinds of fun stuff */ static void connection_status (G_GNUC_UNUSED HudClientConnection * connection, gboolean connected, HudClientQuery * cquery) { g_clear_object(&cquery->priv->results); g_clear_object(&cquery->priv->appstack); g_clear_object(&cquery->priv->proxy); g_signal_emit(G_OBJECT(cquery), hud_client_query_signal_models_changed, 0); if (!connected) { return; } hud_client_connection_new_query(cquery->priv->connection, cquery->priv->query, new_query_cb, g_object_ref(cquery)); return; } /* Go through the toolbar and put the right items in the array */ static void parse_toolbar (_HudQueryComCanonicalHudQuery * proxy, G_GNUC_UNUSED GParamSpec * paramspec, HudClientQuery * query) { if (query->priv->toolbar->len > 0) { g_array_remove_range(query->priv->toolbar, 0, query->priv->toolbar->len); } const gchar * const * items = NULL; items = _hud_query_com_canonical_hud_query_get_toolbar_items(proxy); int i; for (i = 0; items != NULL && items[i] != NULL; i++) { HudClientQueryToolbarItems item = hud_client_query_toolbar_items_get_value_from_nick(items[i]); if (item == HUD_CLIENT_QUERY_TOOLBAR_INVALID) continue; g_array_append_val(query->priv->toolbar, item); } g_signal_emit(G_OBJECT(query), signal_toolbar_updated, 0, NULL); return; } static void new_query_cb (G_GNUC_UNUSED HudClientConnection * connection, const gchar * path, const gchar * results, const gchar * appstack, gpointer user_data) { if (path == NULL || results == NULL || appstack == NULL) { g_object_unref(user_data); return; } HudClientQuery * cquery = HUD_CLIENT_QUERY(user_data); GError * error = NULL; cquery->priv->proxy = _hud_query_com_canonical_hud_query_proxy_new_for_bus_sync( G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, hud_client_connection_get_address(cquery->priv->connection), path, NULL, /* GCancellable */ &error /* GError */ ); if (cquery->priv->proxy == NULL) { g_debug("Unable to get proxy after getting query path: %s", error->message); g_error_free(error); g_object_unref(cquery); return; } /* Set up our models */ cquery->priv->results = dee_shared_model_new(results); dee_model_set_schema_full(cquery->priv->results, results_model_schema, G_N_ELEMENTS(results_model_schema)); cquery->priv->appstack = dee_shared_model_new(appstack); dee_model_set_schema_full(cquery->priv->appstack, appstack_model_schema, G_N_ELEMENTS(appstack_model_schema)); /* Watch for voice signals */ g_signal_connect_object (cquery->priv->proxy, "voice-query-loading", G_CALLBACK (hud_client_query_voice_query_loading), G_OBJECT(cquery), 0); g_signal_connect_object (cquery->priv->proxy, "voice-query-listening", G_CALLBACK (hud_client_query_voice_query_listening), G_OBJECT(cquery), 0); g_signal_connect_object (cquery->priv->proxy, "voice-query-heard-something", G_CALLBACK (hud_client_query_voice_query_heard_something), G_OBJECT(cquery), 0); /* Watch for toolbar callbacks */ g_signal_connect (cquery->priv->proxy, "notify::toolbar-items", G_CALLBACK(parse_toolbar), cquery); /* Figure out toolbar */ parse_toolbar(cquery->priv->proxy, NULL, cquery); g_signal_emit(G_OBJECT(cquery), hud_client_query_signal_models_changed, 0); g_object_unref(cquery); return; } static void hud_client_query_dispose (GObject *object) { HudClientQuery * self = HUD_CLIENT_QUERY(object); /* We don't care anymore, we're dying! */ if (self->priv->connection_changed_sig != 0) { g_signal_handler_disconnect(self->priv->connection, self->priv->connection_changed_sig); self->priv->connection_changed_sig = 0; } if (self->priv->proxy != NULL) { _hud_query_com_canonical_hud_query_call_close_query_sync(self->priv->proxy, NULL, NULL); } g_clear_object(&self->priv->results); g_clear_object(&self->priv->appstack); g_clear_object(&self->priv->proxy); g_clear_object(&self->priv->connection); G_OBJECT_CLASS (hud_client_query_parent_class)->dispose (object); return; } static void hud_client_query_finalize (GObject *object) { HudClientQuery * self = HUD_CLIENT_QUERY(object); g_clear_pointer(&self->priv->query, g_free); g_clear_pointer(&self->priv->toolbar, g_array_unref); G_OBJECT_CLASS (hud_client_query_parent_class)->finalize (object); return; } /* Try and start the service using dbus activation. If we're waiting for it to start and send this again, we should be fine. */ static void dbus_start_service (HudClientQuery * query) { if (query->priv->connection == NULL) { /* Oh, we don't even have a connection, let's not try */ return; } GDBusConnection * bus = hud_client_connection_get_bus(query->priv->connection); if (bus == NULL) { /* No bus yet */ return; } g_dbus_connection_call (bus, "org.freedesktop.DBus", "/", "org.freedesktop.DBus", "StartServiceByName", g_variant_new ("(su)", DBUS_NAME, 0), G_VARIANT_TYPE ("(u)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); /* callback */ return; } /** * hud_client_query_new: * @query: String to build the initial set of results from * * Startes a query with the HUD using a specific string. This * will block until the query is created. * * Return value: (transfer full): A new #HudClientQuery object */ HudClientQuery * hud_client_query_new (const gchar * query) { return HUD_CLIENT_QUERY(g_object_new(HUD_CLIENT_TYPE_QUERY, PROP_QUERY_S, query, NULL )); } /** * hud_client_query_new_for_connection: * @query: String to build the initial set of results from * @connection: A custom #HudClientConnection to a non-default HUD service * * Very similar to hud_client_query_new() except that it uses a * custom connection. This is mostly for testing, though it is * available if you need it. * * Return value: (transfer full): A new #HudClientQuery object */ HudClientQuery * hud_client_query_new_for_connection (const gchar * query, HudClientConnection * connection) { return HUD_CLIENT_QUERY(g_object_new(HUD_CLIENT_TYPE_QUERY, PROP_CONNECTION_S, connection, PROP_QUERY_S, query, NULL )); } /** * hud_client_query_set_query: * @cquery: A #HudClientQuery * @query: New query string * * This revises the query to be the new query string. Updates can * be seen through the #DeeModel's. */ void hud_client_query_set_query (HudClientQuery * cquery, const gchar * query) { g_return_if_fail(HUD_CLIENT_IS_QUERY(cquery)); g_clear_pointer(&cquery->priv->query, g_free); cquery->priv->query = g_strdup(query); if (cquery->priv->proxy != NULL) { gint revision = 0; _hud_query_com_canonical_hud_query_call_update_query_sync(cquery->priv->proxy, cquery->priv->query, &revision, NULL, NULL); } else { dbus_start_service(cquery); } g_object_notify(G_OBJECT(cquery), PROP_QUERY_S); return; } /** * hud_client_query_get_query: * @cquery: A #HudClientQuery * * Accessor for the current query string. * * Return value: (transfer none): Query string */ const gchar * hud_client_query_get_query (HudClientQuery * cquery) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); return cquery->priv->query; } static void hud_client_query_voice_query_callback (G_GNUC_UNUSED GObject *source, GAsyncResult *result, gpointer user_data) { g_assert(HUD_CLIENT_IS_QUERY(user_data)); HudClientQuery *cquery = HUD_CLIENT_QUERY(user_data); gint revision = 0; gchar *query = NULL; GError *error = NULL; if (!_hud_query_com_canonical_hud_query_call_voice_query_finish (cquery->priv->proxy, &revision, &query, result, &error)) { g_warning("Voice query failed to finish: [%s]", error->message); g_signal_emit (user_data, hud_client_query_signal_voice_query_failed, 0 /* details */, error->message); g_error_free(error); return; } g_clear_pointer(&cquery->priv->query, g_free); cquery->priv->query = query; g_object_notify (G_OBJECT(cquery), PROP_QUERY_S); g_signal_emit (user_data, hud_client_query_signal_voice_query_finished, 0 /* details */, query); } /** * hud_client_query_voice_query: * @cquery: A #HudClientQuery * * Execute a HUD query using voice recognition. * * Will cause a series of signals to be emitted indicating progress: * - voice-query-loading - the voice recognition toolkit is loading. * - voice-query-failed - the voice recognition toolkit has failed to initialize. * - voice-query-listening - the voice recognition toolkit is listening to speech. * - voice-query-heard-something - the voice recognition toolkit has heard a complete utterance. * - voice-query-finished - the voice recognition toolkit has completed, and has a (possibly empty) result. */ void hud_client_query_voice_query (HudClientQuery * cquery) { g_return_if_fail(HUD_CLIENT_IS_QUERY(cquery)); if (cquery->priv->proxy != NULL) { g_debug("Running voice query"); _hud_query_com_canonical_hud_query_call_voice_query (cquery->priv->proxy, NULL, hud_client_query_voice_query_callback, cquery); } } /** * hud_client_query_get_results_model: * @cquery: A #HudClientQuery * * Accessor for the current results model. * * Return value: (transfer none): Results Model */ DeeModel * hud_client_query_get_results_model (HudClientQuery * cquery) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); return cquery->priv->results; } /** * hud_client_query_get_appstack_model: * @cquery: A #HudClientQuery * * Accessor for the current appstack model. * * Return value: (transfer none): Appstack Model */ DeeModel * hud_client_query_get_appstack_model (HudClientQuery * cquery) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); return cquery->priv->appstack; } /** * hud_client_query_toolbar_item_active: * @cquery: A #HudClientQuery * @item: Item to check for * * Checks to see if a particular toolbar item is implemented by the * application and should be shown to the user as available for use. * * Return value: Whether this @item is active. */ gboolean hud_client_query_toolbar_item_active (HudClientQuery * cquery, HudClientQueryToolbarItems item) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), FALSE); guint i = 0; for (i = 0; i < cquery->priv->toolbar->len; i++) { HudClientQueryToolbarItems local = g_array_index(cquery->priv->toolbar, HudClientQueryToolbarItems, i); if (local == item) { return TRUE; } } return FALSE; } /** * hud_client_query_get_active_toolbar: * @cquery: A #HudClientQuery * * Gets a list of all the active toolbar items as an array. Array should be * free'd after use. * * Return value: (transfer full) (element-type HudClientQueryToolbarItems): A * list of the active toolbar items. */ GArray * hud_client_query_get_active_toolbar (HudClientQuery * cquery) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); return g_array_ref(cquery->priv->toolbar); } /** * hud_client_query_set_appstack_app: * @cquery: A #HudClientQuery * @application_id: New application to get results from * * This revises the query application to be application_id. Updates can * be seen through the #DeeModel's. */ void hud_client_query_set_appstack_app (HudClientQuery * cquery, const gchar * application_id) { g_return_if_fail(HUD_CLIENT_IS_QUERY(cquery)); if (cquery->priv->proxy != NULL) { gint revision = 0; _hud_query_com_canonical_hud_query_call_update_app_sync(cquery->priv->proxy, application_id, &revision, NULL, NULL); } return; } /** * hud_client_query_execute_command: * @cquery: A #HudClientQuery * @command_key: The key from the results model for the entry to activate * @timestamp: Timestamp for the user event * * Executes a particular entry from the results model. The @command_key * should be grabbed from the table and passed to this function to activate * it. This function will block until the command is activated. */ void hud_client_query_execute_command (HudClientQuery * cquery, GVariant * command_key, guint timestamp) { g_return_if_fail(HUD_CLIENT_IS_QUERY(cquery)); g_return_if_fail(command_key != NULL); GError *error = NULL; if (!_hud_query_com_canonical_hud_query_call_execute_command_sync(cquery->priv->proxy, command_key, timestamp, NULL, &error)) { g_warning("Error executing command [%s]", error->message); g_error_free(error); } return; } /** * hud_client_query_execute_param_command: * @cquery: A #HudClientQuery * @command_key: The key from the results model for the entry to activate * @timestamp: Timestamp for the user event * * Executes a command that results in a parameterized dialog * which is controlled using the returned #HudClientParam object. * When created this sends the "opened" event to the application. * * Return Value: (transfer full): Object to control the parameterized dialog. */ HudClientParam * hud_client_query_execute_param_command (HudClientQuery * cquery, GVariant * command_key, guint timestamp) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); g_return_val_if_fail(command_key != NULL, NULL); gchar * sender = NULL; gchar * prefix = NULL; gchar * base_action = NULL; gchar * action_path = NULL; gchar * model_path = NULL; gint section = 0; GError * error = NULL; _hud_query_com_canonical_hud_query_call_execute_parameterized_sync(cquery->priv->proxy, command_key, timestamp, &sender, &prefix, &base_action, &action_path, &model_path, §ion, NULL, &error); if (error != NULL) { g_warning("Unable to execute paramereterized action: %s", error->message); g_error_free(error); return NULL; } HudClientParam * param = hud_client_param_new(sender, prefix, base_action, action_path, model_path, section); g_free(prefix); g_free(sender); g_free(base_action); g_free(action_path); g_free(model_path); return param; } /** * hud_client_query_execute_toolbar_item: * @cquery: A #HudClientQuery * @item: Which toolbar item is being activated * @timestamp: Timestamp for the user event * * Executes a particular item in the tool bar. The item should * be active before passing this. */ void hud_client_query_execute_toolbar_item (HudClientQuery * cquery, HudClientQueryToolbarItems item, guint timestamp) { g_return_if_fail(HUD_CLIENT_IS_QUERY(cquery)); _hud_query_com_canonical_hud_query_call_execute_toolbar_sync(cquery->priv->proxy, hud_client_query_toolbar_items_get_nick(item), timestamp, NULL, NULL); return; } /** * hud_client_query_appstack_get_app_id: * @cquery: A #HudClientQuery * @row: Which row in the table to grab the ID from * * Get the application ID for a given row in the appstack table. * * Return value: The application ID */ const gchar * hud_client_query_appstack_get_app_id (HudClientQuery * cquery, DeeModelIter * row) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); g_return_val_if_fail(row != NULL, NULL); return dee_model_get_string(cquery->priv->appstack, row, HUD_QUERY_APPSTACK_APPLICATION_ID); } /** * hud_client_query_appstack_get_app_icon: * @cquery: A #HudClientQuery * @row: Which row in the table to grab the icon from * * Get the application icon for a given row in the appstack table. * * Return value: The application icon */ const gchar * hud_client_query_appstack_get_app_icon (HudClientQuery * cquery, DeeModelIter * row) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); g_return_val_if_fail(row != NULL, NULL); return dee_model_get_string(cquery->priv->appstack, row, HUD_QUERY_APPSTACK_ICON_NAME); } /** * hud_client_query_results_get_command_id: * @cquery: A #HudClientQuery * @row: Which row in the table to grab the ID from * * Get the command ID for a given row in the results table. * * Return value: (transfer full): The command ID */ GVariant * hud_client_query_results_get_command_id (HudClientQuery * cquery, DeeModelIter * row) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); g_return_val_if_fail(row != NULL, NULL); return dee_model_get_value(cquery->priv->results, row, HUD_QUERY_RESULTS_COMMAND_ID); } /** * hud_client_query_results_get_command_name: * @cquery: A #HudClientQuery * @row: Which row in the table to grab the name from * * Get the human readable command name for a given row in the results table. * * Return value: The command name */ const gchar * hud_client_query_results_get_command_name (HudClientQuery * cquery, DeeModelIter * row) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); g_return_val_if_fail(row != NULL, NULL); return dee_model_get_string(cquery->priv->results, row, HUD_QUERY_RESULTS_COMMAND_NAME); } /** * hud_client_query_results_get_command_highlights: * @cquery: A #HudClientQuery * @row: Which row in the table to grab the highlights from * * Get the command highlights for a row in the table with start and * stop characters in an array. * * Return value: (transfer full): The command highlights as a variant of type "a(ii)" */ GVariant * hud_client_query_results_get_command_highlights (HudClientQuery * cquery, DeeModelIter * row) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); g_return_val_if_fail(row != NULL, NULL); return dee_model_get_value(cquery->priv->results, row, HUD_QUERY_RESULTS_COMMAND_HIGHLIGHTS); } /** * hud_client_query_results_get_description: * @cquery: A #HudClientQuery * @row: Which row in the table to grab the description from * * Get the human readable description for the command in the given row in the results table. * * Return value: The description */ const gchar * hud_client_query_results_get_description (HudClientQuery * cquery, DeeModelIter * row) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); g_return_val_if_fail(row != NULL, NULL); return dee_model_get_string(cquery->priv->results, row, HUD_QUERY_RESULTS_DESCRIPTION); } /** * hud_client_query_results_get_description_highlights: * @cquery: A #HudClientQuery * @row: Which row in the table to grab the highlights from * * Get the description highlights for a row in the table with start and * stop characters in an array. * * Return value: (transfer full): The description highlights as a variant of type "a(ii)" */ GVariant * hud_client_query_results_get_description_highlights (HudClientQuery * cquery, DeeModelIter * row) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); g_return_val_if_fail(row != NULL, NULL); return dee_model_get_value(cquery->priv->results, row, HUD_QUERY_RESULTS_DESCRIPTION_HIGHLIGHTS); } /** * hud_client_query_results_get_shortcut: * @cquery: A #HudClientQuery * @row: Which row in the table to grab the shortcut from * * Get the human readable shortcut for the command in the given row in the results table. * * Return value: The shortcut */ const gchar * hud_client_query_results_get_shortcut (HudClientQuery * cquery, DeeModelIter * row) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), NULL); g_return_val_if_fail(row != NULL, NULL); return dee_model_get_string(cquery->priv->results, row, HUD_QUERY_RESULTS_SHORTCUT); } /** * hud_client_query_results_is_parameterized: * @cquery: A #HudClientQuery * @row: Which row in the table to check if the command is parameterized * * Check to see if the given command is parameterized * * Return value: Whether the command in the row is parameterized */ gboolean hud_client_query_results_is_parameterized (HudClientQuery * cquery, DeeModelIter * row) { g_return_val_if_fail(HUD_CLIENT_IS_QUERY(cquery), FALSE); g_return_val_if_fail(row != NULL, FALSE); return dee_model_get_bool(cquery->priv->results, row, HUD_QUERY_RESULTS_PARAMETERIZED); } hud-14.04+14.04.20140604/libhud-client/connection.c0000644000015301777760000003100012343623451021723 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "connection.h" #include "service-iface.h" #include "common/shared-values.h" struct _HudClientConnectionPrivate { _HudServiceComCanonicalHud * proxy; GDBusConnection * bus; gchar * address; gchar * path; gboolean connected; gulong name_owner_sig; GCancellable * cancellable; }; #define HUD_CLIENT_CONNECTION_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), HUD_CLIENT_TYPE_CONNECTION, HudClientConnectionPrivate)) enum { PROP_0 = 0, PROP_ADDRESS, PROP_PATH }; #define PROP_ADDRESS_S "address" #define PROP_PATH_S "path" static void hud_client_connection_class_init (HudClientConnectionClass *klass); static void hud_client_connection_init (HudClientConnection *self); static void hud_client_connection_constructed (GObject *object); static void hud_client_connection_dispose (GObject *object); static void hud_client_connection_finalize (GObject *object); static void set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec); static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec); static void name_owner_changed (GObject * object, GParamSpec * pspec, gpointer user_data); G_DEFINE_TYPE (HudClientConnection, hud_client_connection, G_TYPE_OBJECT) static guint signal_connection_status = 0; static void hud_client_connection_class_init (HudClientConnectionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (HudClientConnectionPrivate)); object_class->dispose = hud_client_connection_dispose; object_class->finalize = hud_client_connection_finalize; object_class->constructed = hud_client_connection_constructed; object_class->set_property = set_property; object_class->get_property = get_property; g_object_class_install_property (object_class, PROP_ADDRESS, g_param_spec_string(PROP_ADDRESS_S, "Address on DBus for the HUD service", "The DBus address of the HUD service we should connect to.", DBUS_NAME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PATH, g_param_spec_string(PROP_PATH_S, "Path on DBus for the HUD service", "The DBus path of the HUD service we should connect to.", DBUS_PATH, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); /** * HudClientConnection::connection-status: * * Called when the connection status changes in some way. */ signal_connection_status = g_signal_new (HUD_CLIENT_CONNECTION_SIGNAL_CONNECTION_STATUS, HUD_CLIENT_TYPE_CONNECTION, G_SIGNAL_RUN_LAST, 0, /* offset */ NULL, NULL, /* Collectors */ g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); return; } static void hud_client_connection_init (HudClientConnection *self) { self->priv = HUD_CLIENT_CONNECTION_GET_PRIVATE(self); self->priv->connected = FALSE; self->priv->cancellable = g_cancellable_new(); GError * error = NULL; self->priv->bus = g_bus_get_sync(G_BUS_TYPE_SESSION, self->priv->cancellable, &error); if (G_UNLIKELY(error != NULL)) { /* really should never happen */ g_warning("Unable to get session bus: %s", error->message); g_error_free(error); } return; } static void set_property (GObject * obj, guint id, const GValue * value, G_GNUC_UNUSED GParamSpec * pspec) { HudClientConnection * self = HUD_CLIENT_CONNECTION(obj); switch (id) { case PROP_ADDRESS: g_clear_pointer(&self->priv->address, g_free); self->priv->address = g_value_dup_string(value); break; case PROP_PATH: g_clear_pointer(&self->priv->path, g_free); self->priv->path = g_value_dup_string(value); break; default: g_warning("Unknown property %d.", id); return; } return; } static void get_property (GObject * obj, guint id, GValue * value, G_GNUC_UNUSED GParamSpec * pspec) { HudClientConnection * self = HUD_CLIENT_CONNECTION(obj); switch (id) { case PROP_ADDRESS: g_value_set_string(value, self->priv->address); break; case PROP_PATH: g_value_set_string(value, self->priv->path); break; default: g_warning("Unknown property %d.", id); return; } return; } static void hud_client_connection_constructed (GObject * object) { HudClientConnection * self = HUD_CLIENT_CONNECTION(object); g_return_if_fail(self->priv->address != NULL); g_return_if_fail(self->priv->path != NULL); GError * error = NULL; self->priv->proxy = _hud_service_com_canonical_hud_proxy_new_for_bus_sync( G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, self->priv->address, self->priv->path, self->priv->cancellable, &error ); if (error != NULL) { g_warning("Unable to get a HUD proxy: %s", error->message); self->priv->proxy = NULL; g_error_free(error); error = NULL; } if (self->priv->proxy != NULL) { self->priv->name_owner_sig = g_signal_connect(G_OBJECT(self->priv->proxy), "notify::g-name-owner", G_CALLBACK(name_owner_changed), self); } name_owner_changed(NULL, NULL, self); return; } static void hud_client_connection_dispose (GObject *object) { HudClientConnection * self = HUD_CLIENT_CONNECTION(object); if (self->priv->cancellable != NULL) { g_cancellable_cancel(self->priv->cancellable); g_clear_object(&self->priv->cancellable); } if (self->priv->name_owner_sig != 0) { g_signal_handler_disconnect(self->priv->proxy, self->priv->name_owner_sig); self->priv->name_owner_sig = 0; } g_clear_object(&self->priv->proxy); g_clear_object(&self->priv->bus); G_OBJECT_CLASS (hud_client_connection_parent_class)->dispose (object); return; } static void hud_client_connection_finalize (GObject *object) { HudClientConnection * self = HUD_CLIENT_CONNECTION(object); g_clear_pointer(&self->priv->address, g_free); g_clear_pointer(&self->priv->path, g_free); G_OBJECT_CLASS (hud_client_connection_parent_class)->finalize (object); return; } /* Called when the HUD service comes on or off the bus */ static void name_owner_changed (G_GNUC_UNUSED GObject * object, G_GNUC_UNUSED GParamSpec * pspec, gpointer user_data) { HudClientConnection * self = HUD_CLIENT_CONNECTION(user_data); gboolean connected = FALSE; gchar * owner = NULL; if (self->priv->proxy != NULL) { owner = g_dbus_proxy_get_name_owner(G_DBUS_PROXY(self->priv->proxy)); } if (owner != NULL) { connected = TRUE; g_free(owner); } /* Make sure we set the internal variable before signaling */ gboolean change = (connected != self->priv->connected); self->priv->connected = connected; /* Cancel anything we had running */ if (!self->priv->connected) { g_cancellable_cancel(self->priv->cancellable); } else { g_cancellable_reset(self->priv->cancellable); } /* If there was a change, make sure others know about it */ if (change) { g_signal_emit(self, signal_connection_status, 0, connected); } return; } /** * hud_client_connection_get_ref: * * Gets a reference to the default object that connects to the * default HUD service. * * Return value: (transfer full): Refence to a #HudClientConnection */ HudClientConnection * hud_client_connection_get_ref (void) { static HudClientConnection * global = NULL; if (global == NULL) { global = HUD_CLIENT_CONNECTION(g_object_new(HUD_CLIENT_TYPE_CONNECTION, NULL)); g_object_add_weak_pointer(G_OBJECT(global), (gpointer *)&global); return global; } else { return g_object_ref(global); } } /** * hud_client_connection_new: * @dbus_address: Address on DBus for the HUD service * @dbus_path: Path to the object to create stuff * * Builds a HUD Connection object that can be used to connect to a * custom HUD service. For the most part, this should only be used * in testing, though there might be other uses. It is likely if you're * using this function you'd also be interested in * hud_client_query_new_for_connection() * * Return value: (transfer full): A new #HudClientConnection */ HudClientConnection * hud_client_connection_new (const gchar * dbus_address, const gchar * dbus_path) { return HUD_CLIENT_CONNECTION(g_object_new(HUD_CLIENT_TYPE_CONNECTION, PROP_ADDRESS_S, dbus_address, PROP_PATH_S, dbus_path, NULL)); } /* Data to handle the callback */ typedef struct _new_query_data_t new_query_data_t; struct _new_query_data_t { HudClientConnection * con; HudClientConnectionNewQueryCallback cb; gpointer user_data; }; /* Called when the new query call comes back */ static void new_query_complete (GObject * object, GAsyncResult * res, gpointer user_data) { new_query_data_t * data = (new_query_data_t *)user_data; gchar * query_object = NULL; gchar * results_name = NULL; gchar * appstack_name = NULL; gint revision = 0; GError * error = NULL; _hud_service_com_canonical_hud_call_create_query_finish((_HudServiceComCanonicalHud *)object, &query_object, &results_name, &appstack_name, &revision, res, &error); if (error != NULL) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && !g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CLOSED)) { g_warning("Unable to allocate query: %s", error->message); } g_error_free(error); } data->cb(data->con, query_object, results_name, appstack_name, data->user_data); g_free(data); return; } /** * hud_client_connection_new_query: * @connection: A #HudClientConnection * @query: The initial query string * @cb: Callback when we've got the query * @user_data: Data to pass to the callback * * Function to create a new query in the HUD service and pass back * the information needed to create a #HudClientQuery object. */ void hud_client_connection_new_query (HudClientConnection * connection, const gchar * query, HudClientConnectionNewQueryCallback cb, gpointer user_data) { g_return_if_fail(HUD_CLIENT_IS_CONNECTION(connection)); new_query_data_t * data = g_new0(new_query_data_t, 1); data->con = connection; data->cb = cb; data->user_data = user_data; _hud_service_com_canonical_hud_call_create_query(connection->priv->proxy, query, connection->priv->cancellable, new_query_complete, data); } /** * hud_client_connection_get_address: * @connection: A #HudClientConnection * * Accessor to get the address of the HUD service. * * Return value: A DBus address */ const gchar * hud_client_connection_get_address (HudClientConnection * connection) { g_return_val_if_fail(HUD_CLIENT_IS_CONNECTION(connection), NULL); return connection->priv->address; } /** * hud_client_connection_connected: * @connection: A #HudClientConnection * * Accessor to get the connected status of the connection * * Return value: If we're connected or not */ gboolean hud_client_connection_connected (HudClientConnection * connection) { g_return_val_if_fail(HUD_CLIENT_IS_CONNECTION(connection), FALSE); return connection->priv->connected; } /** * hud_client_connection_get_bus: * @connection: A #HudClientConnection * * Grab the bus being used by the connection. * * Return value: (transfer none): Our bus if we have one */ GDBusConnection * hud_client_connection_get_bus (HudClientConnection * connection) { g_return_val_if_fail(HUD_CLIENT_IS_CONNECTION(connection), NULL); return connection->priv->bus; } hud-14.04+14.04.20140604/libhud-client/HudClient.cpp0000644000015301777760000002603312343623451022015 0ustar pbusernogroup00000000000000/* * Copyright (C) 2012, 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include using namespace hud::client; // Terrible hack to get around GLib. GLib stores function pointers as gpointer, which violates the C and C++ spec // because data and function pointers may have different sizes. gcc rightfully emits a warning. There is no #pragma // in gcc to selectively turn off the warning, however. This hack gets around the problem, by using a union (ick) to // convert between the two types. class ToGPointer { public: ToGPointer(void (*cb)()) { u_.cb = cb; } operator gpointer() const{ return u_.p; } private: union { void (*cb)(); gpointer p; } u_; }; #define TO_GPOINTER(cb) (ToGPointer(reinterpret_cast((cb)))) class HudClient::Priv { public: explicit Priv(HudClient &client) : m_client(client), m_clientQuery(nullptr), m_currentActionIndex(0), m_currentActionParam( nullptr) { } static void loadingCB(GObject* /*src*/, gpointer dst) { static_cast(dst)->voiceQueryLoading(); } static void listeningCB(GObject* /*src*/, gpointer dst) { static_cast(dst)->voiceQueryListening(); } static void heardSomethingCB(GObject* /*src*/, gpointer dst) { static_cast(dst)->voiceQueryHeardSomething(); } static void failedCB(GObject* /*src*/, const gchar * /*reason*/, gpointer dst) { static_cast(dst)->voiceQueryFailed(); } static void finishedCB(GObject* /*src*/, const gchar* query, gpointer dst) { static_cast(dst)->voiceQueryFinished( QString::fromUtf8(query)); } static void modelReadyCB(GObject* /*src*/, gpointer dst) { static_cast(dst)->modelReady(true); } static void modelReallyReadyCB(GObject* /*src*/, gint /*position*/, gint /*removed*/, gint /*added*/, gpointer dst) { static_cast(dst)->modelReallyReady(true); } static void modelsChangedCB(GObject* /*src*/, gpointer dst) { static_cast(dst)->queryModelsChanged(); } static void toolBarUpdatedCB(GObject* /*src*/, gpointer dst) { static_cast(dst)->updatedByBackend(); } void modelReady(bool needDisconnect) { if (needDisconnect) { g_signal_handlers_disconnect_by_func(m_currentActionParam, TO_GPOINTER(Priv::modelReadyCB), this); } GMenuModel *menuModel = hud_client_param_get_model( m_currentActionParam); if (g_menu_model_get_n_items(menuModel) == 0) { g_signal_connect(menuModel, "items-changed", G_CALLBACK(Priv::modelReallyReadyCB), this); } else { modelReallyReady(false); } } static QVariant QVariantFromGVariant(GVariant *value) { // Only handle the cases we care for now switch (g_variant_classify(value)) { case G_VARIANT_CLASS_BOOLEAN: return QVariant((bool) g_variant_get_boolean(value)); case G_VARIANT_CLASS_DOUBLE: return QVariant(g_variant_get_double(value)); case G_VARIANT_CLASS_STRING: return QVariant( QString::fromUtf8(g_variant_get_string(value, NULL))); default: return QVariant(); } } static void addAttribute(QVariantMap &properties, GMenuModel *menuModel, int item, const char *attribute) { GVariant *v = g_menu_model_get_item_attribute_value(menuModel, item, attribute, NULL); if (v == NULL) return; properties.insert(attribute, QVariantFromGVariant(v)); g_variant_unref(v); } void modelReallyReady(bool needDisconnect) { GMenuModel *menuModel = hud_client_param_get_model( m_currentActionParam); if (needDisconnect) { g_signal_handlers_disconnect_by_func(menuModel, TO_GPOINTER(Priv::modelReallyReadyCB), this); } QVariantList items; for (int i = 0; i < g_menu_model_get_n_items(menuModel); i++) { GVariant *v = g_menu_model_get_item_attribute_value(menuModel, i, "parameter-type", G_VARIANT_TYPE_STRING); if (v == NULL) continue; const QString type = QString::fromUtf8( g_variant_get_string(v, NULL)); if (type == "slider") { const char *sliderAttributes[] = { "label", "min", "max", "step", "value", "live", "action" }; QVariantMap properties; properties.insert("parameter-type", "slider"); for (uint j = 0; j < sizeof(sliderAttributes) / sizeof(sliderAttributes[0]); ++j) { addAttribute(properties, menuModel, i, sliderAttributes[j]); } items << properties; } g_variant_unref(v); } DeeModel *model = hud_client_query_get_results_model(m_clientQuery); DeeModelIter *iter = dee_model_get_iter_at_row(model, m_currentActionIndex); QString actionText = QString::fromUtf8( hud_client_query_results_get_command_name(m_clientQuery, iter)); Q_EMIT m_client.showParametrizedAction(actionText, QVariant::fromValue(items)); } void queryModelsChanged() { m_results->setModel( hud_client_query_get_results_model(m_clientQuery)); m_appstack->setModel( hud_client_query_get_appstack_model(m_clientQuery)); Q_EMIT m_client.modelsChanged(); } HudClient &m_client; HudClientQuery *m_clientQuery; QScopedPointer m_results; QScopedPointer m_appstack; QScopedPointer m_toolBarModel; int m_currentActionIndex; HudClientParam *m_currentActionParam; }; HudClient::HudClient() : p(new Priv(*this)) { p->m_clientQuery = hud_client_query_new(""); p->m_results.reset(new DeeListModel()); p->m_appstack.reset(new DeeListModel()); p->m_toolBarModel.reset(new HudToolBarModel(p->m_clientQuery)); p->m_currentActionParam = NULL; p->m_results->setModel( hud_client_query_get_results_model(p->m_clientQuery)); p->m_appstack->setModel( hud_client_query_get_appstack_model(p->m_clientQuery)); g_signal_connect(G_OBJECT(p->m_clientQuery), "voice-query-loading", G_CALLBACK(Priv::loadingCB), this); g_signal_connect(G_OBJECT(p->m_clientQuery), "voice-query-listening", G_CALLBACK(Priv::listeningCB), this); g_signal_connect(G_OBJECT(p->m_clientQuery), "voice-query-heard-something", G_CALLBACK(Priv::heardSomethingCB), this); g_signal_connect(G_OBJECT(p->m_clientQuery), "voice-query-finished", G_CALLBACK(Priv::finishedCB), this); g_signal_connect(G_OBJECT(p->m_clientQuery), "voice-query-failed", G_CALLBACK(Priv::failedCB), this); g_signal_connect(G_OBJECT(p->m_clientQuery), HUD_CLIENT_QUERY_SIGNAL_MODELS_CHANGED, G_CALLBACK(Priv::modelsChangedCB), p.data()); g_signal_connect(G_OBJECT(p->m_clientQuery), HUD_CLIENT_QUERY_SIGNAL_TOOLBAR_UPDATED, G_CALLBACK(Priv::toolBarUpdatedCB), p->m_toolBarModel.data()); } HudClient::~HudClient() { g_signal_handlers_disconnect_by_func(G_OBJECT(p->m_clientQuery), TO_GPOINTER(Priv::loadingCB), this); g_signal_handlers_disconnect_by_func(G_OBJECT(p->m_clientQuery), TO_GPOINTER(Priv::listeningCB), this); g_signal_handlers_disconnect_by_func(G_OBJECT(p->m_clientQuery), TO_GPOINTER(Priv::heardSomethingCB), this); g_signal_handlers_disconnect_by_func(G_OBJECT(p->m_clientQuery), TO_GPOINTER(Priv::finishedCB), this); g_signal_handlers_disconnect_by_func(G_OBJECT(p->m_clientQuery), TO_GPOINTER(Priv::toolBarUpdatedCB), p->m_toolBarModel.data()); g_object_unref(p->m_clientQuery); } void HudClient::setQuery(const QString &new_query) { hud_client_query_set_query(p->m_clientQuery, new_query.toUtf8().constData()); } void HudClient::setAppstackApp(const QString &applicationId) { hud_client_query_set_appstack_app(p->m_clientQuery, applicationId.toUtf8().constData()); } void HudClient::startVoiceQuery() { hud_client_query_voice_query(p->m_clientQuery); } void HudClient::executeParametrizedAction(const QVariant &values) { updateParametrizedAction(values); hud_client_param_send_commit(p->m_currentActionParam); g_object_unref(p->m_currentActionParam); p->m_currentActionParam = NULL; Q_EMIT commandExecuted(); } void HudClient::updateParametrizedAction(const QVariant &values) { if (p->m_currentActionParam != NULL) { const QVariantMap map = values.value(); GActionGroup *ag = hud_client_param_get_actions( p->m_currentActionParam); auto it = map.begin(); for (; it != map.end(); ++it) { const QString action = it.key(); const QVariant value = it.value(); const GVariantType *actionType = g_action_group_get_action_parameter_type(ag, action.toUtf8().constData()); if (g_variant_type_equal(actionType, G_VARIANT_TYPE_DOUBLE) && value.canConvert(QVariant::Double)) { g_action_group_activate_action(ag, action.toUtf8().constData(), g_variant_new_double(value.toDouble())); } else { qWarning() << "Unsuported action type in HudClient::executeParametrizedAction"; } } } else { qWarning() << "Got to HudClient::updateParametrizedAction with no m_currentActionParam"; } } void HudClient::cancelParametrizedAction() { if (p->m_currentActionParam != NULL) { hud_client_param_send_cancel(p->m_currentActionParam); g_object_unref(p->m_currentActionParam); p->m_currentActionParam = NULL; } } void HudClient::executeToolBarAction(HudClientQueryToolbarItems action) { hud_client_query_execute_toolbar_item(p->m_clientQuery, action, /* timestamp */ 0); Q_EMIT commandExecuted(); } QAbstractListModel * HudClient::results() const { return p->m_results.data(); } QAbstractListModel * HudClient::appstack() const { return p->m_appstack.data(); } QAbstractListModel * HudClient::toolBarModel() const { return p->m_toolBarModel.data(); } void HudClient::executeCommand(int index) { p->m_currentActionIndex = index; DeeModel *model = hud_client_query_get_results_model(p->m_clientQuery); DeeModelIter *iter = dee_model_get_iter_at_row(model, index); GVariant *command_key = hud_client_query_results_get_command_id(p->m_clientQuery, iter); if (hud_client_query_results_is_parameterized(p->m_clientQuery, iter)) { p->m_currentActionParam = hud_client_query_execute_param_command( p->m_clientQuery, command_key, /* timestamp */0); if (p->m_currentActionParam != NULL) { GMenuModel *menuModel = hud_client_param_get_model( p->m_currentActionParam); if (menuModel == NULL) { g_signal_connect(p->m_currentActionParam, HUD_CLIENT_PARAM_SIGNAL_MODEL_READY, G_CALLBACK(Priv::modelReadyCB), p.data()); } else { p->modelReady(false); } } else { qWarning() << "HudClient::executeCommand::Could not get the HudClientParam for parametrized action with index" << index; } } else { hud_client_query_execute_command(p->m_clientQuery, command_key, /* timestamp */ 0); Q_EMIT commandExecuted(); } g_variant_unref(command_key); } hud-14.04+14.04.20140604/libhud-client/enum-types.c.in0000644000015301777760000000501612343623451022307 0ustar pbusernogroup00000000000000/*** BEGIN file-header ***/ /* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #include "enum-types.h" /*** END file-header ***/ /*** BEGIN file-production ***/ #include "@basename@" /*** END file-production ***/ /*** BEGIN value-header ***/ /** @enum_name@_get_type: Builds a GLib type for the #@EnumName@ enumeration. Return value: A unique #GType for the #@EnumName@ enum. */ GType @enum_name@_get_type (void) { static GType etype = 0; if (G_UNLIKELY(etype == 0)) { static const G@Type@Value values[] = { /*** END value-header ***/ /*** BEGIN value-production ***/ { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, /*** END value-production ***/ /*** BEGIN value-tail ***/ { 0, NULL, NULL} }; etype = g_@type@_register_static (g_intern_static_string("@EnumName@"), values); } return etype; } /** @enum_name@_get_nick: @value: The value of @EnumName@ to get the nick of Looks up in the enum table for the nick of @value. Return value: The nick for the given value or #NULL on error */ const gchar * @enum_name@_get_nick (@EnumName@ value) { GEnumClass * class = G_ENUM_CLASS(g_type_class_ref(@enum_name@_get_type())); g_return_val_if_fail(class != NULL, NULL); const gchar * ret = NULL; GEnumValue * val = g_enum_get_value(class, value); if (val != NULL) { ret = val->value_nick; } g_type_class_unref(class); return ret; } /** @enum_name@_get_value_from_nick: @nick: The enum nick to lookup Looks up in the enum table for the value of @nick. Return value: The value for the given @nick */ @EnumName@ @enum_name@_get_value_from_nick (const gchar * nick) { GEnumClass * class = G_ENUM_CLASS(g_type_class_ref(@enum_name@_get_type())); g_return_val_if_fail(class != NULL, -1); @EnumName@ ret = -1; GEnumValue * val = g_enum_get_value_by_nick(class, nick); if (val != NULL) { ret = val->value; } g_type_class_unref(class); return ret; } /*** END value-tail ***/ hud-14.04+14.04.20140604/libhud-client/enum-types.h.in0000644000015301777760000000333412343623451022315 0ustar pbusernogroup00000000000000/*** BEGIN file-header ***/ /* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #if !defined (_HUD_CLIENT_H_INSIDE) && !defined (HUD_CLIENT_COMPILATION) #error "Only can be included directly." #endif #ifndef __HUD_CLIENT_ENUM_TYPES_H__ #define __HUD_CLIENT_ENUM_TYPES_H__ #pragma GCC visibility push(default) #include G_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN file-tail ***/ G_END_DECLS #pragma GCC visibility pop #endif /* __HUD_CLIENT_ENUM_TYPES_H__ */ /*** END file-tail ***/ /*** BEGIN file-production ***/ /* Enumerations from file: "@basename@" */ #include /*** END file-production ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) G_GNUC_CONST; const gchar * @enum_name@_get_nick (@EnumName@ value) G_GNUC_CONST; @EnumName@ @enum_name@_get_value_from_nick (const gchar * nick) G_GNUC_CONST; /** HUD_CLIENT_TYPE_@ENUMSHORT@: Gets the #GType value for the type associated with the #@EnumName@ enumerated type. */ #define HUD_CLIENT_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) /*** END value-header ***/ hud-14.04+14.04.20140604/libhud-client/toolbar-items.h0000644000015301777760000000320712343623451022362 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #ifndef LIBHUD_CLIENT_TOOLBAR_ITEMS_H_ #define LIBHUD_CLIENT_TOOLBAR_ITEMS_H_ /** * HudClientQueryToolbarItems: * @HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN: Make the application fullscreen * @HUD_CLIENT_QUERY_TOOLBAR_HELP: Help the user use the application * @HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES: Configure the application * @HUD_CLIENT_QUERY_TOOLBAR_UNDO: Revert the last user action * @HUD_CLIENT_QUERY_TOOLBAR_QUIT: Quit the application * * @short_description: Preconfigured toolbar items for the application * * The toolbar has a set of preconfigured items in it for the * application. This enum represents them. */ typedef enum { /*< prefix=HUD_CLIENT_QUERY_TOOLBAR >*/ HUD_CLIENT_QUERY_TOOLBAR_INVALID = -1, HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN, HUD_CLIENT_QUERY_TOOLBAR_HELP, HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES, HUD_CLIENT_QUERY_TOOLBAR_UNDO, HUD_CLIENT_QUERY_TOOLBAR_QUIT, } HudClientQueryToolbarItems; #endif /* LIBHUD_CLIENT_TOOLBAR_ITEMS_H_ */ hud-14.04+14.04.20140604/libhud-client/hud-client.pc.in0000644000015301777760000000040612343623451022413 0ustar pbusernogroup00000000000000libdir=@libdir@ includedir=@includedir@ Cflags: -I${includedir}/libhud-client-@apiversion@ Requires: glib-2.0 gio-2.0 Libs: -L${libdir} -lhud-client Name: libhud-client Description: A library to use the HUD. Mostly private, use with care. Version: @VERSION@ hud-14.04+14.04.20140604/libhud-client/param.h0000644000015301777760000000760212343623451020704 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #if !defined (_HUD_CLIENT_H_INSIDE) && !defined (HUD_CLIENT_COMPILATION) #error "Only can be included directly." #endif #ifndef __HUD_CLIENT_PARAM_H__ #define __HUD_CLIENT_PARAM_H__ #pragma GCC visibility push(default) #include #include #include G_BEGIN_DECLS #define HUD_CLIENT_TYPE_PARAM (hud_client_param_get_type ()) #define HUD_CLIENT_PARAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HUD_CLIENT_TYPE_PARAM, HudClientParam)) #define HUD_CLIENT_PARAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HUD_CLIENT_TYPE_PARAM, HudClientParamClass)) #define HUD_CLIENT_IS_PARAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HUD_CLIENT_TYPE_PARAM)) #define HUD_CLIENT_IS_PARAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HUD_CLIENT_TYPE_PARAM)) #define HUD_CLIENT_PARAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HUD_CLIENT_TYPE_PARAM, HudClientParamClass)) /** * HUD_CLIENT_PARAM_SIGNAL_MODEL_READY * * Signal to indicate when the model is ready */ #define HUD_CLIENT_PARAM_SIGNAL_MODEL_READY "model-ready" typedef struct _HudClientParam HudClientParam; typedef struct _HudClientParamClass HudClientParamClass; typedef struct _HudClientParamPrivate HudClientParamPrivate; /** * HudClientParamPrivate: * * Private data for #HudClientParam. */ /** * HudClientParamClass: * @parent_class: #GObjectClass * @model_ready: Slot for the model-ready signal * * Class information for #HudClientParam */ struct _HudClientParamClass { GObjectClass parent_class; /*< Private >*/ void (*model_ready) (HudClientParamClass * param, gpointer user_data); }; /** * HudClientParam: * * An object that tracks all the of the stuff needed to handle * a parameterized dialog of actions. */ struct _HudClientParam { GObject parent; HudClientParamPrivate * priv; }; GType hud_client_param_get_type (void); HudClientParam * hud_client_param_new (const gchar * dbus_address, const gchar * prefix, const gchar * base_action, const gchar * action_path, const gchar * model_path, gint model_section); GActionGroup * hud_client_param_get_actions (HudClientParam * param); GMenuModel * hud_client_param_get_model (HudClientParam * param); void hud_client_param_send_reset (HudClientParam * param); void hud_client_param_send_cancel (HudClientParam * param); void hud_client_param_send_commit (HudClientParam * param); /** SECTION:param @short_description: Track a parameterized view @stability: Unstable @include: libhud-client/param.h This makes it much easier to interact with the parameterized pane of the HUD. Provides the links to the menu model and the actions that should be shown. Also provides convienience functions for resetting it and fun stuff like that. */ G_END_DECLS #pragma GCC visibility pop #endif hud-14.04+14.04.20140604/libhud-client/HudToolbarModel.cpp0000644000015301777760000000532412343623451023162 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include using namespace hud::client; static const int ActionRole = Qt::UserRole; static const int EnabledRole = Qt::UserRole + 1; static QString iconForAction(int action) { switch (action) { case HUD_CLIENT_QUERY_TOOLBAR_QUIT: return "graphics/close.png"; case HUD_CLIENT_QUERY_TOOLBAR_UNDO: return "graphics/undo.png"; case HUD_CLIENT_QUERY_TOOLBAR_HELP: return "graphics/help.png"; case HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN: return "graphics/view-fullscreen.png"; case HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES: return "graphics/settings.png"; } return QString(); } class HudToolBarModel::Priv { public: QList m_actions; HudClientQuery *m_query; }; HudToolBarModel::HudToolBarModel(HudClientQuery *query) : p(new Priv()) { p->m_query = query; p->m_actions << HUD_CLIENT_QUERY_TOOLBAR_QUIT << HUD_CLIENT_QUERY_TOOLBAR_UNDO << HUD_CLIENT_QUERY_TOOLBAR_HELP << HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN << HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES; } HudToolBarModel::~HudToolBarModel() { } int HudToolBarModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return p->m_actions.count(); } QVariant HudToolBarModel::data(const QModelIndex &index, int role) const { const int row = index.row(); if (row >= p->m_actions.count()) return QVariant(); const HudClientQueryToolbarItems action = p->m_actions[row]; switch (role) { case Qt::DecorationRole: return iconForAction(action); break; case ActionRole: return action; break; case EnabledRole: return hud_client_query_toolbar_item_active(p->m_query, action); break; } return QVariant(); } QHash HudToolBarModel::roleNames() const { static QHash roles; if (roles.isEmpty()) { roles[Qt::DecorationRole] = "iconPath"; roles[ActionRole] = "action"; roles[EnabledRole] = "enabled"; } return roles; } void HudToolBarModel::updatedByBackend() { Q_EMIT dataChanged(index(0, 0), index(rowCount() - 1, 0), QVector() << EnabledRole); } hud-14.04+14.04.20140604/libhud-client/CMakeLists.txt0000644000015301777760000001053312343623451022170 0ustar pbusernogroup00000000000000 add_compiler_export_flags() set(HUD_CLIENT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) set(HUD_CLIENT_INCLUDE_DIRS ${HUD_CLIENT_INCLUDE_DIRS} PARENT_SCOPE ) include_directories(${HUD_CLIENT_INCLUDE_DIRS}) # FIXME would rather not include this dir include_directories(${HUD_SRC_DIR}) add_definitions( -DHUD_CLIENT_COMPILATION=1 ) ########################### # Version Information ########################### set(API_VERSION 2) set(ABI_VERSION 2) ########################### # Generated Hud Client ########################### set(HUD_CLIENT_GENERATED_HEADERS service-iface.h query-iface.h ) set(HUD_CLIENT_GENERATED_SOURCES ) add_gdbus_codegen( OUTFILES HUD_CLIENT_GENERATED_SOURCES NAME service-iface PREFIX com.canonical.hud. NAMESPACE _HudService SERVICE_XML ${HUD_SERVICE_XML} ) add_gdbus_codegen( OUTFILES HUD_CLIENT_GENERATED_SOURCES NAME query-iface PREFIX com.canonical.hud.query. NAMESPACE _HudQuery SERVICE_XML ${HUD_QUERY_XML} ) add_library(hud-client-generated STATIC ${HUD_CLIENT_GENERATED_SOURCES}) target_link_libraries(hud-client-generated ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES} ${GIO2_LIBRARIES} ${DEE_LIBRARIES} ) ########################### # Hud Client ########################### set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") set(HUD_CLIENT_MAIN_HEADERS hud-client.h ) set(HUD_CLIENT_HEADERS connection.h param.h query.h toolbar-items.h ${CMAKE_SOURCE_DIR}/common/query-columns.h ) set(HUD_CLIENT_QT_HEADERS HudClient.h HudToolbarModel.h ) set(HUD_CLIENT_SOURCES action-muxer.c connection.c param.c query.c HudClient.cpp HudToolbarModel.cpp ) add_glib_enumtypes_t(HUD_CLIENT_SOURCES enum-types enum-types.h.in enum-types.c.in ${HUD_CLIENT_HEADERS} ) list(APPEND HUD_CLIENT_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/enum-types.h) add_library(hud-client SHARED ${HUD_CLIENT_SOURCES} connection-private.h) set_target_properties(hud-client PROPERTIES VERSION ${API_VERSION}.0.0 SOVERSION ${ABI_VERSION} OUTPUT_NAME "hud-client" ) set_target_properties( hud-client PROPERTIES COMPILE_FLAGS "-Wpedantic -Wall -Wextra" ) target_link_libraries(hud-client hud-client-generated ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES} ${DEE_QT_LIBRARIES} -Wl,--no-undefined ) qt5_use_modules(hud-client Core ) ########################### # Pkg Config ########################### set(HUD_CLIENT_PC "hud-client-${API_VERSION}.pc") set(apiversion "${API_VERSION}") set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}") set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}") set(VERSION "${ABI_VERSION}") configure_file("hud-client.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/${HUD_CLIENT_PC}" @ONLY) ########################### # GObject Introspection ########################### if(${INTROSPECTION_FOUND}) include(UseGObjectIntrospection) set(INTROSPECTION_GIRS) set(_introspection_files ${HUD_CLIENT_SOURCES} ${HUD_CLIENT_HEADERS}) set(HudClient_2_gir "hud-client") set(HudClient_2_gir_INCLUDES GObject-2.0 Dee-1.0) gir_get_cflags(_cflags) set(HudClient_2_gir_CFLAGS ${_cflags}) set(HudClient_2_gir_LIBS hud-client) list_make_absolute(_abs_introspection_files _introspection_files "${CMAKE_CURRENT_SOURCE_DIR}/") set(HudClient_2_gir_FILES ${_abs_introspection_files}) set(HudClient_2_gir_SCANNERFLAGS --c-include "hud-client.h") set(HudClient_2_gir_EXPORT_PACKAGES "hud-client-${API_VERSION}") list(APPEND INTROSPECTION_GIRS HudClient-2.gir) gir_add_introspections(INTROSPECTION_GIRS) else() message("Not performing GIR as required tools not found") endif() ########################### # libhud-client Vala ########################### if(${VALA_FOUND}) if(${INTROSPECTION_FOUND}) vapi_gen(hud-client-vapi INPUT HudClient-2.gir PACKAGES gio-2.0 LIBRARY HudClient-2 ) install( FILES ${hud-client-vapi_OUTPUT} DESTINATION "${CMAKE_INSTALL_DATADIR}/vala/vapi" ) endif() endif() ########################### # Installation ########################### install( FILES ${HUD_CLIENT_MAIN_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/libhud-client-${API_VERSION}" ) install( FILES ${HUD_CLIENT_HEADERS} ${HUD_CLIENT_QT_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/libhud-client-${API_VERSION}/libhud-client" ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${HUD_CLIENT_PC}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" ) install( TARGETS hud-client LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) hud-14.04+14.04.20140604/libhud-client/query.h0000644000015301777760000001627512343623451020757 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #if !defined (_HUD_CLIENT_H_INSIDE) && !defined (HUD_CLIENT_COMPILATION) #error "Only can be included directly." #endif #ifndef __HUD_CLIENT_QUERY_H__ #define __HUD_CLIENT_QUERY_H__ #pragma GCC visibility push(default) #include #include #include #include #include G_BEGIN_DECLS #define HUD_CLIENT_TYPE_QUERY (hud_client_query_get_type ()) #define HUD_CLIENT_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HUD_CLIENT_TYPE_QUERY, HudClientQuery)) #define HUD_CLIENT_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HUD_CLIENT_TYPE_QUERY, HudClientQueryClass)) #define HUD_CLIENT_IS_QUERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HUD_CLIENT_TYPE_QUERY)) #define HUD_CLIENT_IS_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HUD_CLIENT_TYPE_QUERY)) #define HUD_CLIENT_QUERY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HUD_CLIENT_TYPE_QUERY, HudClientQueryClass)) /** * HUD_CLIENT_QUERY_SIGNAL_MODELS_CHANGED * * Signal to indicate when the models have changed */ #define HUD_CLIENT_QUERY_SIGNAL_MODELS_CHANGED "models-changed" /** * HUD_CLIENT_QUERY_SIGNAL_TOOLBAR_UPDATED * * Signal to indicate when the toolbar has been updated */ #define HUD_CLIENT_QUERY_SIGNAL_TOOLBAR_UPDATED "toolbar-updated" typedef struct _HudClientQuery HudClientQuery; typedef struct _HudClientQueryClass HudClientQueryClass; typedef struct _HudClientQueryPrivate HudClientQueryPrivate; /** * HudClientQueryPrivate: * * Private data for #HudClientQuery. */ /** * HudClientQueryClass: * @parent_class: #GObjectClass * * Class information for #HudClientQuery */ struct _HudClientQueryClass { GObjectClass parent_class; }; /** * HudClientQuery: * * Object to track a query and the models for that query. Should * be unref'd when a client is done using the query so that applications * can be told that the HUD is no longer open. */ struct _HudClientQuery { GObject parent; HudClientQueryPrivate * priv; }; GType hud_client_query_get_type (void); HudClientQuery * hud_client_query_new (const gchar * query); HudClientQuery * hud_client_query_new_for_connection (const gchar * query, HudClientConnection * connection); /* Query Tools */ void hud_client_query_set_query (HudClientQuery * cquery, const gchar * query); const gchar * hud_client_query_get_query (HudClientQuery * cquery); void hud_client_query_voice_query (HudClientQuery * cquery); /* Accessors */ DeeModel * hud_client_query_get_results_model (HudClientQuery * cquery); DeeModel * hud_client_query_get_appstack_model (HudClientQuery * cquery); gboolean hud_client_query_toolbar_item_active (HudClientQuery * cquery, HudClientQueryToolbarItems item); GArray * hud_client_query_get_active_toolbar (HudClientQuery * cquery); /* Execute and Control */ void hud_client_query_set_appstack_app (HudClientQuery * cquery, const gchar * application_id); void hud_client_query_execute_command (HudClientQuery * cquery, GVariant * command_key, guint timestamp); HudClientParam * hud_client_query_execute_param_command (HudClientQuery * cquery, GVariant * command_key, guint timestamp); void hud_client_query_execute_toolbar_item (HudClientQuery * cquery, HudClientQueryToolbarItems item, guint timestamp); /* Appstack Accessors */ const gchar * hud_client_query_appstack_get_app_id (HudClientQuery * cquery, DeeModelIter * row); const gchar * hud_client_query_appstack_get_app_icon (HudClientQuery * cquery, DeeModelIter * row); /* Results Accessors */ GVariant * hud_client_query_results_get_command_id (HudClientQuery * cquery, DeeModelIter * row); const gchar * hud_client_query_results_get_command_name (HudClientQuery * cquery, DeeModelIter * row); GVariant * hud_client_query_results_get_command_highlights (HudClientQuery * cquery, DeeModelIter * row); const gchar * hud_client_query_results_get_description (HudClientQuery * cquery, DeeModelIter * row); GVariant * hud_client_query_results_get_description_highlights (HudClientQuery * cquery, DeeModelIter * row); const gchar * hud_client_query_results_get_shortcut (HudClientQuery * cquery, DeeModelIter * row); gboolean hud_client_query_results_is_parameterized (HudClientQuery * cquery, DeeModelIter * row); /** SECTION:query @short_description: Query the HUD service for entries @stability: Unstable @include: libhud-client/query.h A query is an open query to the HUD service which provides Dee models for the results. The query can update without changing the search string (the application changes the entires) or can be udated by calling hud_client_query_set_query(). When the usage of the Query is complete it should be unreferenced as that will communicate to the applications that the HUD is closed and they should not update their items. */ G_END_DECLS #pragma GCC visibility pop #endif hud-14.04+14.04.20140604/libhud-client/connection-private.h0000644000015301777760000000210512343623451023404 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #if !defined (_HUD_CLIENT_H_INSIDE) && !defined (HUD_CLIENT_COMPILATION) #error "Only can be included directly." #endif #ifndef __HUD_CLIENT_CONNECTION_PRIVATE_H__ #define __HUD_CLIENT_CONNECTION_PRIVATE_H__ #include #include "connection.h" G_BEGIN_DECLS GDBusConnection * hud_client_connection_get_bus (HudClientConnection * connection); G_END_DECLS #endif hud-14.04+14.04.20140604/libhud-client/connection.h0000644000015301777760000001141412343623451021737 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #if !defined (_HUD_CLIENT_H_INSIDE) && !defined (HUD_CLIENT_COMPILATION) #error "Only can be included directly." #endif #ifndef __HUD_CLIENT_CONNECTION_H__ #define __HUD_CLIENT_CONNECTION_H__ #pragma GCC visibility push(default) #include G_BEGIN_DECLS #define HUD_CLIENT_TYPE_CONNECTION (hud_client_connection_get_type ()) #define HUD_CLIENT_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HUD_CLIENT_TYPE_CONNECTION, HudClientConnection)) #define HUD_CLIENT_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HUD_CLIENT_TYPE_CONNECTION, HudClientConnectionClass)) #define HUD_CLIENT_IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HUD_CLIENT_TYPE_CONNECTION)) #define HUD_CLIENT_IS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HUD_CLIENT_TYPE_CONNECTION)) #define HUD_CLIENT_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HUD_CLIENT_TYPE_CONNECTION, HudClientConnectionClass)) /** * HUD_CLIENT_CONNECTION_SIGNAL_CONNECTION_STATUS: * * Signal to notify on a change in the connection status */ #define HUD_CLIENT_CONNECTION_SIGNAL_CONNECTION_STATUS "connection-status" typedef struct _HudClientConnection HudClientConnection; typedef struct _HudClientConnectionClass HudClientConnectionClass; typedef struct _HudClientConnectionPrivate HudClientConnectionPrivate ; /** * HudClientConnectionPrivate: * * Private data for #HudClientConnection. */ /** * HudClientConnectionNewQueryCallback: * @connection: #HudClientConnection for the request * @query_path: Path to the query object on DBus * @results_name: DBus name for the results * @appstack_name: DBus name for the appstack * @user_data: Passed in user data * * Callback for the async call to create a new query */ typedef void (*HudClientConnectionNewQueryCallback) (HudClientConnection * connection, const gchar * query_path, const gchar * results_name, const gchar * appstack_name, gpointer user_data); /** * HudClientConnectionClass: * @parent_class: #GObjectClass * * Class information for #HudClientConnection */ struct _HudClientConnectionClass { GObjectClass parent_class; }; /** * HudClientConnection: * * Object to make a generic connection to a HUD service. For the most * part people should just create a #HudClientQuery and that'll use the * default HUD service. For most folks that should be enough. */ struct _HudClientConnection { GObject parent; HudClientConnectionPrivate * priv; }; GType hud_client_connection_get_type (void); HudClientConnection * hud_client_connection_get_ref (void); HudClientConnection * hud_client_connection_new (const gchar * dbus_address, const gchar * dbus_path); void hud_client_connection_new_query (HudClientConnection * connection, const gchar * query, HudClientConnectionNewQueryCallback cb, gpointer user_data); const gchar * hud_client_connection_get_address (HudClientConnection * connection); gboolean hud_client_connection_connected (HudClientConnection * connection); /** SECTION:connection @short_description: Provide a connection to the HUD service @stability: Unstable @include: libhud-client/connection.h The connection is an object to maintain a connection to the default objects on the HUD service. It provides access to the functionality there and can be used to create queries. Most users should not bother with a connection, it will be created by the #HudClientQuery if one is not provided. Most usage is for testing and using custom HUD services. */ G_END_DECLS #pragma GCC visibility pop #endif hud-14.04+14.04.20140604/libhud-client/hud-client.h0000644000015301777760000000166412343623451021642 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #ifndef __HUD_CLIENT_H__ #define __HUD_CLIENT_H__ #define _HUD_CLIENT_H_INSIDE #include #include #include #undef _HUD_CLIENT_H_INSIDE #endif /* __HUD_CLIENT_H__ */ hud-14.04+14.04.20140604/po/0000755000015301777760000000000012343624372015324 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/po/POTFILES.skip0000644000015301777760000000030012343623451017427 0ustar pbusernogroup00000000000000src/create-db.c src/gen-application-menu-registrar.xml.c src/gen-application-menu-renderer.xml.c tools-vala/hud-gtk.ui src/hud.interface.c src/indicator-appmenu-marshal.c libhud/demo/gimp.xml hud-14.04+14.04.20140604/po/POTFILES.in0000644000015301777760000000077612343623451017110 0ustar pbusernogroup00000000000000data/com.canonical.indicator.appmenu.hud.gschema.xml data/com.canonical.indicator.appmenu.hud.search.gschema.xml src/dump-app-info.c src/hudappindicatorsource.c src/hudappmenuregistrar.c src/huddbusmenucollector.c src/hud-dump-application.c src/hudindicatorsource.c src/huditem.c src/hudmenumodelcollector.c src/hudquery.c src/hudresult.c src/hud-service.c src/hudsource.c src/hudsourcelist.c src/hudstringlist.c src/hudtoken.c src/hud-verify-app-info.c src/load-app-info.c src/usage-tracker.c tools/hud-cli.c hud-14.04+14.04.20140604/libhud-gtk/0000755000015301777760000000000012343624372016740 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/libhud-gtk/manager.c0000644000015301777760000001676212343623451020527 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of either or both of the following licences: * * 1) the GNU Lesser General Public License version 3, as published by * the Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, * see * * Author: Ted Gould */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "manager.h" #include struct _HudGtkManagerPrivate { /* We'll need this later */ int dummy; }; #define HUD_GTK_MANAGER_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), HUD_GTK_TYPE_MANAGER, HudGtkManagerPrivate)) static void hud_gtk_manager_class_init (HudGtkManagerClass *klass); static void hud_gtk_manager_init (HudGtkManager *self); static void hud_gtk_manager_constructed (GObject *object); static void hud_gtk_manager_dispose (GObject *object); static void hud_gtk_manager_finalize (GObject *object); static void window_added (GApplication *application, gpointer window, gpointer user_data); static void window_removed (GApplication *application, gpointer window, gpointer user_data); G_DEFINE_TYPE (HudGtkManager, hud_gtk_manager, HUD_TYPE_MANAGER); /* Initialize Class */ static void hud_gtk_manager_class_init (HudGtkManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (HudGtkManagerPrivate)); object_class->constructed = hud_gtk_manager_constructed; object_class->dispose = hud_gtk_manager_dispose; object_class->finalize = hud_gtk_manager_finalize; return; } /* Initialize Instance */ static void hud_gtk_manager_init (HudGtkManager *self) { return; } /* Get all our vars and start building! */ static void hud_gtk_manager_constructed (GObject *object) { GtkApplication * app = NULL; g_object_get(object, HUD_MANAGER_PROP_APPLICATION, &app, NULL); g_return_if_fail(GTK_IS_APPLICATION(app)); g_signal_connect (app, "window-added", G_CALLBACK (window_added), object); g_signal_connect (app, "window-removed", G_CALLBACK (window_removed), object); return; } /* Clean up refs */ static void hud_gtk_manager_dispose (GObject *object) { G_OBJECT_CLASS (hud_gtk_manager_parent_class)->dispose (object); return; } /* Free Memory */ static void hud_gtk_manager_finalize (GObject *object) { G_OBJECT_CLASS (hud_gtk_manager_parent_class)->finalize (object); return; } static void get_window_details (gpointer window, /* GtkApplicationWindow */ gchar **object_path, guint *xid) { GApplication *application; gpointer gdk_window; g_object_get (window, "application", &application, "window", &gdk_window, NULL); g_return_if_fail (window != NULL); /* we're inside a realize/unrealize pair... */ g_return_if_fail (application != NULL); /* otherwise why are we here...? */ if (GDK_IS_X11_WINDOW (window)) { *xid = gdk_x11_window_get_xid(gdk_window); if (object_path) { guint id; id = gtk_application_window_get_id (window); *object_path = g_strdup_printf ("%s/window/%u", g_application_get_dbus_object_path (application), id); } /* Put support for other backends here */ } else { /* Fallback to an error */ g_error ("Unsupported GDK backend"); } return; } static void window_realize (gpointer window, /* GtkWidget */ gpointer user_data) { HudGtkManager * manager = user_data; gchar *object_path; guint xid; get_window_details (window, &object_path, &xid); GVariant * id = g_variant_new_uint32(xid); HudActionPublisher * publisher = hud_gtk_manager_get_publisher(manager, id); hud_action_publisher_add_action_group (publisher, "win", object_path); g_free (object_path); return; } static void window_unrealize (gpointer window, /* GtkWidget */ gpointer user_data) { HudGtkManager * manager = user_data; guint xid; get_window_details (window, NULL, &xid); GVariant * id = g_variant_new_uint32(xid); HudActionPublisher * publisher = hud_gtk_manager_get_publisher(manager, id); hud_action_publisher_remove_action_group (publisher, "win", id); return; } static void window_added (GApplication *application, /* really GtkApplication */ gpointer window, /* GtkWindow */ gpointer user_data) { HudActionPublisher *publisher = user_data; /* Can't do anything with this if it's not a GtkApplicationWindow */ if (!GTK_IS_APPLICATION_WINDOW(window)) return; /* It's not possible that the window is already realized at the time * that it is added to the application, so just watch for the signal. */ g_signal_connect (window, "realize", G_CALLBACK (window_realize), publisher); g_signal_connect (window, "unrealize", G_CALLBACK (window_unrealize), publisher); return; } static void window_removed (GApplication *application, /* really GtkApplication */ gpointer window, /* GtkWindow */ gpointer user_data) { HudActionPublisher *publisher = user_data; /* Just indiscriminately disconnect.... * If we didn't connect anything then nothing will happen. * * We're probably well on our way to destruction at this point, but it * can't hurt to clean up properly just incase someone is doing * something weird. */ g_signal_handlers_disconnect_by_func (window, window_realize, publisher); g_signal_handlers_disconnect_by_func (window, window_unrealize, publisher); return; } /** * hud_gtk_manager_new: * @app: A #GtkApplication object * * Creates a #HudGtkManager object that is connected to the @app so that * new windows get tracked and their actions automatically added to so * the HUD can access them. * * From the #GtkApplication passed as @app any #GtkApplicationWindow * added to the application will also be added as a potential target * ("win") for actions. For example, if a #GtkApplicationWindow * features an action "fullscreen" then action descriptions can speak of * "win.fullscreen". * * @app must have no windows at the time that this function is * called. * * Return value: (transfer full): A new #HudGtkManager object */ HudGtkManager * hud_gtk_manager_new (GtkApplication * app) { g_return_val_if_fail(GTK_IS_APPLICATION(app), NULL); return g_object_new(HUD_GTK_TYPE_MANAGER, HUD_MANAGER_PROP_APPLICATION, app, NULL); } /** * hud_gtk_manager_get_publisher: * @manager: A #HudGtkManager object * @id: ID of the item to find the publisher for * * Finds or creates a publisher for the specific #GtkApplicationWindow that * is referenced by @id. This can be used to add descriptions on the publisher * or additional action groups as needed. * * Return value: (transfer none): A #HudActionPublisher for the window */ HudActionPublisher * hud_gtk_manager_get_publisher (HudGtkManager * manager, GVariant * id) { /* TODO: Uhm, yes */ return NULL; } hud-14.04+14.04.20140604/libhud-gtk/hud-gtk.h0000644000015301777760000000214012343623451020446 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of either or both of the following licences: * * 1) the GNU Lesser General Public License version 3, as published by * the Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, * see * * Author: Ted Gould */ #ifndef __HUD_GTK_H__ #define __HUD_GTK_H__ #include #define _HUD_GTK_H_INSIDE #include #undef _HUD_GTK_H_INSIDE #endif /* __HUD_GTK_H__ */ hud-14.04+14.04.20140604/libhud-gtk/hud-gtk.pc.in0000644000015301777760000000037212343623451021233 0ustar pbusernogroup00000000000000libdir=@libdir@ includedir=@includedir@ Cflags: -I${includedir}/libhud-gtk-@apiversion@ Requires: glib-2.0 hud-1 Libs: -L${libdir} -lhud-gtk Name: libhud-gtk Description: A library to submit items into the HUD with GTK+ helpers Version: @VERSION@ hud-14.04+14.04.20140604/libhud-gtk/CMakeLists.txt0000644000015301777760000000343712343623451021504 0ustar pbusernogroup00000000000000 set(HUD_GTK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) set(HUD_GTK_INCLUDE_DIRS ${HUD_GTK_INCLUDE_DIRS} PARENT_SCOPE ) include_directories(${HUD_INCLUDE_DIRS}) include_directories(${HUD_GTK_INCLUDE_DIRS}) include_directories(${GTK3_INCLUDE_DIRS}) #add_definitions( -DHUD_COMPILATION=1 ) ########################### # Version Information ########################### set(API_VERSION 1) set(ABI_VERSION 1) ########################### # Lib Hud Gtk ########################### set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") set(HUD_GTK_MAIN_HEADERS hud-gtk.h ) set(HUD_GTK_HEADERS manager.h ${HUD_HEADERS} ) set(HUD_GTK_SOURCES manager.c ) add_library(hud-gtk SHARED ${HUD_GTK_SOURCES}) set_target_properties(hud-gtk PROPERTIES VERSION ${API_VERSION}.0.0 SOVERSION ${ABI_VERSION} OUTPUT_NAME "hud-gtk" ) target_link_libraries(hud-gtk hud ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES} ${GTK3_LIBRARIES} -Wl,--no-undefined ) ########################### # Pkg Config ########################### set(HUD_GTK_PC "hud-gtk-${API_VERSION}.pc") set(apiversion "${API_VERSION}") set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}") set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}") set(VERSION "${ABI_VERSION}") configure_file("hud-gtk.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/${HUD_GTK_PC}" @ONLY) ########################### # Installation ########################### install( FILES ${HUD_GTK_MAIN_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/libhud-gtk-${API_VERSION}" ) install( FILES ${HUD_GTK_HEADERS} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/libhud-gtk-${API_VERSION}/libhud-gtk" ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${HUD_GTK_PC}" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" ) install( TARGETS hud-gtk LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} )hud-14.04+14.04.20140604/libhud-gtk/manager.h0000644000015301777760000000621412343623451020523 0ustar pbusernogroup00000000000000/* * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of either or both of the following licences: * * 1) the GNU Lesser General Public License version 3, as published by * the Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, * see * * Author: Ted Gould */ #ifndef __HUD_GTK_MANAGER_H__ #define __HUD_GTK_MANAGER_H__ #include #include #pragma GCC visibility push(default) G_BEGIN_DECLS #define HUD_GTK_TYPE_MANAGER (hud_gtk_manager_get_type ()) #define HUD_GTK_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), HUD_GTK_TYPE_MANAGER, HudGtkManager)) #define HUD_GTK_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HUD_GTK_TYPE_MANAGER, HudGtkManagerClass)) #define HUD_GTK_IS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), HUD_GTK_TYPE_MANAGER)) #define HUD_GTK_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HUD_GTK_TYPE_MANAGER)) #define HUD_GTK_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HUD_GTK_TYPE_MANAGER, HudGtkManagerClass)) typedef struct _HudGtkManager HudGtkManager; typedef struct _HudGtkManagerClass HudGtkManagerClass; typedef struct _HudGtkManagerPrivate HudGtkManagerPrivate; /** * HudGtkManagerPrivate: * * Private data for #HudGtkManager. */ /** * HudGtkManagerClass: * @parent_class: #HudManagerClass * * Class data for #HudGtkManager. */ struct _HudGtkManagerClass { HudManagerClass parent_class; }; /** * HudGtkManager: * * Helper class to work with #GtkApplication to automatically * export action groups registered there to the HUD. */ struct _HudGtkManager { HudManager parent; HudGtkManagerPrivate * priv; }; GType hud_gtk_manager_get_type (void); HudGtkManager * hud_gtk_manager_new (GtkApplication * app); HudActionPublisher * hud_gtk_manager_get_publisher (HudGtkManager * manager, GVariant * id); /** * SECTION:manager * @short_description: Work with a #GtkApplication to easily export action groups * @stability: Stable * @include: libhud-gtk/manager.h * * A helper class #HudGtkManager to work with #GtkApplication and * automatically export the base action group "app." along with the * window action groups typically "win.". These can then have #HudActionDescription * objects used to describe them without having to worry about creating * and managing the #GActionGroup's. */ G_END_DECLS #pragma GCC visibility pop #endif /* __HUD_GTK_MANAGER_H__ */ hud-14.04+14.04.20140604/libqtgmenu/0000755000015301777760000000000012343624372017055 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/libqtgmenu/internal/0000755000015301777760000000000012343624372020671 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/libqtgmenu/internal/QtGMenuModel.h0000644000015301777760000000746612343623523023355 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #ifndef QTGMENUMODEL_H #define QTGMENUMODEL_H #include #include #include #include #include #include #undef signals #include namespace qtgmenu { class QtGMenuModel : public QObject { Q_OBJECT public: enum class LinkType { Root, Section, SubMenu }; QtGMenuModel( QSharedPointer connection, const QString& bus_name, const QString& menu_path, const QMap& action_paths ); virtual ~QtGMenuModel(); QSharedPointer Model() const; LinkType Type() const; QtGMenuModel* Parent() const; QSharedPointer Child( int index ) const; std::shared_ptr< QMenu > GetQMenu(); constexpr static const char* c_property_actionName = "actionName"; constexpr static const char* c_property_isParameterized = "isParameterized"; constexpr static const char* c_property_busName = "busName"; constexpr static const char* c_property_actionsPath = "actionsPath"; constexpr static const char* c_property_menuPath = "menuPath"; constexpr static const char* c_property_keywords = "keywords"; constexpr static const char* c_property_hud_toolbar_item = "hud-toolbar-item"; Q_SIGNALS: void MenuItemsChanged( QtGMenuModel* model, int index, int removed, int added ); void ActionTriggered( QString action_name, bool checked ); void MenuInvalid(); public Q_SLOTS: void ActionEnabled( QString action_name, bool enabled ); void ActionParameterized( QString action_name, bool parameterized ); private Q_SLOTS: void ActionTriggered( bool ); private: QtGMenuModel( QSharedPointer model, LinkType link_type, QtGMenuModel* parent, int index ); static QSharedPointer CreateChild( QtGMenuModel* parent_qtgmenu, QSharedPointer parent_gmenu, int child_index ); static void MenuItemsChangedCallback( GMenuModel* model, gint index, gint removed, gint added, gpointer user_data ); void ChangeMenuItems( const int index, const int added, const int removed ); void ConnectCallback(); void DisconnectCallback(); void InsertChild( QSharedPointer child, int index ); QAction* CreateAction( int index ); void AppendQMenu( std::shared_ptr< QMenu > top_menu ); void UpdateExtQMenu(); void ActionAdded( const QString& name, QAction* action ); void ActionRemoved( const QString& name, QAction* action ); void ReportRecoverableError(const int index, const int added, const int removed); private: QtGMenuModel* m_parent = nullptr; QMap< int, QSharedPointer> m_children; QSharedPointer m_model; gulong m_items_changed_handler = 0; LinkType m_link_type; int m_size = 0; QScopedPointer m_menu; QScopedPointer m_ext_menu; QSharedPointer m_connection; QString m_bus_name; QString m_menu_path; QMap m_action_paths; // a map of QActions indexed by their name and stored with a reference count std::map< QString, std::vector< QAction* > > m_actions; bool m_error_reported = false; }; } // namespace qtgmenu #endif // QTGMENUMODEL_H hud-14.04+14.04.20140604/libqtgmenu/internal/QtGMenuModel.cpp0000644000015301777760000005110112343623523023671 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include #include #include #include #include #include #include #include using namespace qtgmenu; static const QRegularExpression SINGLE_UNDERSCORE("(? connection, const QString& bus_name, const QString& menu_path, const QMap& action_paths ) : QtGMenuModel( QSharedPointer(G_MENU_MODEL( g_dbus_menu_model_get( connection.data(), bus_name.toUtf8().constData(), menu_path.toUtf8().constData() ) ), &g_object_unref ), LinkType::Root, nullptr, 0 ) { m_connection = connection; m_bus_name = bus_name; m_menu_path = menu_path; m_action_paths = action_paths; } QtGMenuModel::QtGMenuModel( QSharedPointer model, LinkType link_type, QtGMenuModel* parent, int index ) : m_parent( parent ), m_model( model ), m_link_type( link_type ), m_menu( new QMenu() ), m_ext_menu( new QMenu() ) { ConnectCallback(); if( m_parent ) { m_connection = m_parent->m_connection; m_bus_name = m_parent->m_bus_name; m_menu_path = m_parent->m_menu_path; m_action_paths = m_parent->m_action_paths; gchar* label = NULL; if( g_menu_model_get_item_attribute( m_parent->m_model.data(), index, G_MENU_ATTRIBUTE_LABEL, "s", &label ) ) { QString qlabel = QString::fromUtf8( label ); qlabel.replace( SINGLE_UNDERSCORE, "&" ); g_free( label ); m_ext_menu->setTitle( qlabel ); } gchar* action_name = NULL; QString qaction_name; if( g_menu_model_get_item_attribute( m_parent->m_model.data(), index, G_MENU_ATTRIBUTE_ACTION, "s", &action_name ) ) { qaction_name = QString::fromUtf8( action_name ); g_free( action_name ); m_ext_menu->menuAction()->setProperty( c_property_actionName, qaction_name ); } // if this model has a "commitLabel" property, it is a libhud parameterized action gchar* commit_label = NULL; if( g_menu_model_get_item_attribute( m_parent->m_model.data(), index, "commitLabel", "s", &commit_label ) ) { g_free( commit_label ); // is parameterized m_ext_menu->menuAction()->setProperty( c_property_isParameterized, true ); // dbus paths m_ext_menu->menuAction()->setProperty( c_property_busName, m_bus_name ); m_ext_menu->menuAction()->setProperty( c_property_menuPath, m_menu_path ); if( !qaction_name.isEmpty() ) { QPair split = QtGMenuUtils::splitPrefixAndName(qaction_name); const QString& prefix(split.first); if( m_action_paths.contains(prefix) ) { m_ext_menu->menuAction()->setProperty( c_property_actionsPath, m_action_paths[prefix].path() ); } } } } if( m_model ) { m_size = g_menu_model_get_n_items( m_model.data() ); } ChangeMenuItems( 0, m_size, 0 ); } QtGMenuModel::~QtGMenuModel() { if( m_model ) { if( m_size > 0 ) { ChangeMenuItems( 0, 0, m_size ); } DisconnectCallback(); } m_children.clear(); } QSharedPointer QtGMenuModel::Model() const { return m_model; } QtGMenuModel::LinkType QtGMenuModel::Type() const { return m_link_type; } QtGMenuModel* QtGMenuModel::Parent() const { return m_parent; } QSharedPointer QtGMenuModel::Child( int index ) const { if( m_children.contains( index ) ) { return m_children.value( index ); } return QSharedPointer(); } std::shared_ptr< QMenu > QtGMenuModel::GetQMenu() { auto top_menu = std::make_shared< QMenu >(); AppendQMenu( top_menu ); return top_menu; } void QtGMenuModel::ActionTriggered( bool checked ) { QAction* action = dynamic_cast< QAction* >( QObject::sender() ); emit ActionTriggered( action->property( c_property_actionName ).toString(), checked ); } void QtGMenuModel::ActionEnabled( QString action_name, bool enabled ) { auto action_it = m_actions.find( action_name ); if( action_it != end( m_actions ) ) { for( auto& action : action_it->second ) { action->setEnabled( enabled ); } } } void QtGMenuModel::ActionParameterized( QString action_name, bool parameterized ) { auto action_it = m_actions.find( action_name ); if( action_it != end( m_actions ) ) { for( auto& action : action_it->second ) { action->setProperty( c_property_isParameterized, parameterized ); } } } QSharedPointer QtGMenuModel::CreateChild( QtGMenuModel* parent_qtgmenu, QSharedPointer parent_gmenu, int child_index ) { QSharedPointer new_child; GMenuLinkIter* link_it = g_menu_model_iterate_item_links( parent_gmenu.data(), child_index ); // get the first link, if it exists, create the child accordingly if( link_it && g_menu_link_iter_next( link_it ) ) { // if link is a sub menu if( strcmp( g_menu_link_iter_get_name( link_it ), G_MENU_LINK_SUBMENU ) == 0 ) { new_child.reset( new QtGMenuModel( QSharedPointer( g_menu_link_iter_get_value(link_it), &g_object_unref), LinkType::SubMenu, parent_qtgmenu, child_index)); } // else if link is a section else if( strcmp( g_menu_link_iter_get_name( link_it ), G_MENU_LINK_SECTION ) == 0 ) { new_child.reset( new QtGMenuModel( QSharedPointer( g_menu_link_iter_get_value(link_it), &g_object_unref), LinkType::Section, parent_qtgmenu, child_index)); } } g_object_unref( link_it ); return new_child; } void QtGMenuModel::MenuItemsChangedCallback( GMenuModel* model, gint index, gint removed, gint added, gpointer user_data ) { QtGMenuModel* self = reinterpret_cast< QtGMenuModel* >( user_data ); if( self->m_model != model ) { qWarning() << "\"items-changed\" signal received from an unrecognised menu model"; return; } self->ChangeMenuItems( index, added, removed ); } void QtGMenuModel::ChangeMenuItems( const int index, const int added, const int removed ) { const int n_items = g_menu_model_get_n_items( m_model.data() ); if( index < 0 || added < 0 || removed < 0 || index + added > n_items || index + removed > m_size ) { ReportRecoverableError(index, added, removed); return; } // process removed items first (see "items-changed" on the GMenuModel man page) if( removed > 0 ) { // remove QAction from 'index' of our QMenu, 'removed' times for( int i = 0; i < removed; ++i ) { if( index < m_menu->actions().size() ) { QAction* at_action = m_menu->actions().at( index ); ActionRemoved( at_action->property( c_property_actionName ).toString(), at_action ); m_menu->removeAction( at_action ); } } // update m_children for( int i = index; i < m_size; ++i ) { // remove children from index until ( index + removed ) if( i < ( index + removed ) ) { m_children.take( i ); } // shift children from ( index + removed ) to m_size into the now empty positions else if( m_children.contains( i ) ) { m_children.insert( i - removed, m_children.take( i ) ); } } // update m_size m_size -= removed; } // now process added items if( added > 0 ) { // update m_children (start from the end and work backwards as not to overlap items as we shift them up) for( int i = m_size - 1; i >= index; --i ) { // shift 'added' items up from their current index to ( index + added ) if( m_children.contains( i ) ) { m_children.insert( i + added, m_children.take( i ) ); } } // update m_size m_size += added; // now add a new QAction to our QMenu for each new item for( int i = index; i < ( index + added ); ++i ) { QAction* at_action = nullptr; if( i < m_menu->actions().size() ) { at_action = m_menu->actions().at( i ); } // try first to create a child model QSharedPointer< QtGMenuModel > model = CreateChild( this, m_model, i ); // if this is a menu item and not a model if( !model ) { QAction* new_action = CreateAction( i ); ActionAdded( new_action->property( c_property_actionName ).toString(), new_action ); m_menu->insertAction( at_action, new_action ); } // else if this is a section model else if( model->Type() == LinkType::Section ) { InsertChild( model, i ); m_menu->insertSeparator( at_action ); } // else if this is a sub menu model else if( model->Type() == LinkType::SubMenu ) { InsertChild( model, i ); ActionAdded( model->m_ext_menu->menuAction()->property( c_property_actionName ).toString(), model->m_ext_menu->menuAction() ); m_menu->insertMenu( at_action, model->m_ext_menu.data() ); } } } // update external menu UpdateExtQMenu(); // now tell the outside world that items have changed emit MenuItemsChanged( this, index, removed, added ); } void QtGMenuModel::ConnectCallback() { if( m_model && m_items_changed_handler == 0 ) { m_items_changed_handler = g_signal_connect( m_model.data(), "items-changed", G_CALLBACK( MenuItemsChangedCallback ), this ); } } void QtGMenuModel::DisconnectCallback() { if( m_model && m_items_changed_handler != 0 ) { g_signal_handler_disconnect( m_model.data(), m_items_changed_handler ); } m_items_changed_handler = 0; } void QtGMenuModel::InsertChild( QSharedPointer child, int index ) { if( m_children.contains( index ) ) { return; } child->m_parent = this; m_children.insert( index, child ); connect( child.data(), SIGNAL( MenuItemsChanged( QtGMenuModel*, int, int, int ) ), this, SIGNAL( MenuItemsChanged( QtGMenuModel*, int, int, int ) ) ); connect( child.data(), SIGNAL( ActionTriggered( QString, bool ) ), this, SIGNAL( ActionTriggered( QString, bool ) ) ); connect( child.data(), SIGNAL( MenuInvalid() ), this, SIGNAL( MenuInvalid() ) ); // emit signal informing subscribers that this child has added all of its menu items emit MenuItemsChanged( child.data(), 0, 0, child->m_size ); } QAction* QtGMenuModel::CreateAction( int index ) { QAction* action = new QAction( m_menu.data() ); // action label gchar* label = NULL; if( g_menu_model_get_item_attribute( m_model.data(), index, G_MENU_ATTRIBUTE_LABEL, "s", &label ) ) { QString qlabel = QString::fromUtf8( label ); qlabel.replace( SINGLE_UNDERSCORE, "&" ); g_free( label ); action->setText( qlabel ); } // action name gchar* action_name = NULL; if( g_menu_model_get_item_attribute( m_model.data(), index, G_MENU_ATTRIBUTE_ACTION, "s", &action_name ) ) { QString qaction_name = QString::fromUtf8( action_name ); g_free( action_name ); action->setProperty( c_property_actionName, qaction_name ); } // is parameterized (set false by default until signal received) action->setProperty( c_property_isParameterized, false ); // dbus paths action->setProperty( c_property_busName, m_bus_name ); action->setProperty( c_property_menuPath, m_menu_path ); // action icon GVariant* icon = g_menu_model_get_item_attribute_value( m_model.data(), index, G_MENU_ATTRIBUTE_ICON, G_VARIANT_TYPE_VARIANT ); if( icon ) { g_variant_unref( icon ); } // action shortcut gchar* shortcut = NULL; if( g_menu_model_get_item_attribute( m_model.data(), index, "accel", "s", &shortcut ) ) { QString qshortcut = QString::fromUtf8( shortcut ); g_free( shortcut ); action->setShortcut( QtGMenuUtils::QStringToQKeySequence( qshortcut ) ); } // action shortcut gchar* toolbar_item = NULL; if( g_menu_model_get_item_attribute( m_model.data(), index, c_property_hud_toolbar_item, "s", &toolbar_item ) ) { QString qtoolbar_item = QString::fromUtf8( toolbar_item ); g_free( toolbar_item ); action->setProperty( c_property_hud_toolbar_item, qtoolbar_item ); } // action keywords gchar* keywords = NULL; if( g_menu_model_get_item_attribute( m_model.data(), index, c_property_keywords, "s", &keywords ) ) { QVariant qkeywords = QString::fromUtf8( keywords ); g_free( keywords ); action->setProperty( c_property_keywords, qkeywords ); } // action trigger connect( action, SIGNAL( triggered( bool ) ), this, SLOT( ActionTriggered( bool ) ) ); return action; } void QtGMenuModel::AppendQMenu( std::shared_ptr< QMenu > top_menu ) { if( m_link_type == LinkType::Root ) { for( QAction* action : m_ext_menu->actions() ) { if( !action->menu() ) { top_menu->addAction( action ); } } } else if( m_link_type == LinkType::SubMenu ) { top_menu->addAction( m_ext_menu->menuAction() ); } if( m_link_type != LinkType::SubMenu ) { for( auto& child : m_children ) { child->AppendQMenu( top_menu ); } } } void QtGMenuModel::UpdateExtQMenu() { m_ext_menu->clear(); for( int i = 0; i < m_menu->actions().size(); ++i ) { QAction* action = m_menu->actions().at( i ); if( action->isSeparator() ) { QSharedPointer child = Child( i ); if( !child || child->Type() != LinkType::Section ) { continue; } for( QAction* sub_action : child->m_ext_menu->actions() ) { m_ext_menu->addAction( sub_action ); } m_ext_menu->addSeparator(); } else { m_ext_menu->addAction( action ); } } if( m_ext_menu->actions().size() > 0 ) { QAction* last_action = m_ext_menu->actions().last(); if( last_action && last_action->isSeparator() ) { m_ext_menu->removeAction( last_action ); } } // if this is a section within a parent menu, we need to update the parent menu as well if( m_link_type == LinkType::Section && m_parent ) { m_parent->UpdateExtQMenu(); } } void QtGMenuModel::ActionAdded( const QString& name, QAction* action ) { // add action to top menu's m_actions if( m_parent ) { m_parent->ActionAdded( name, action ); } else { // check if the action name is already in our map if( m_actions.find( name ) != m_actions.end() ) { // add the QAction pointer to the list of actions under this name m_actions[name].push_back( action ); } else { // otherwise insert the new action into the map m_actions.insert( std::make_pair( name, std::vector< QAction* >{ action } ) ); } } } void QtGMenuModel::ActionRemoved( const QString& name, QAction* action ) { // remove action from top menu's m_actions if( m_parent ) { m_parent->ActionRemoved( name, action ); } else { // check if this action is actually in our map if( m_actions.find( name ) != m_actions.end() ) { // remove the QAction pointer from the list of actions under this name auto& actionList = m_actions[name]; auto actionIt = std::find( actionList.begin(), actionList.end(), action ); if( actionIt != actionList.end()) { actionList.erase( actionIt ); } // if there are no more references to this action, remove it from the map if( actionList.size() == 0 ) { m_actions.erase( name ); } } } } static void write_pair(QIODevice& device, const QString& key, const QString& value, bool last = false) { device.write(key.toUtf8()); device.write("", 1); device.write(value.toUtf8()); if( !last ) { device.write("", 1); } if( !value.isEmpty()) { qWarning() << key << " =" << value; } } void QtGMenuModel::ReportRecoverableError(const int index, const int added, const int removed) { if( m_error_reported ) { return; } // gmenumodel properties int gmenu_item_count = 0; QString gmenu_action_names; gmenu_item_count = g_menu_model_get_n_items( m_model.data() ); qWarning() << "Illegal arguments when updating GMenuModel: position =" << index << ", added =" << added << ", removed =" << removed << ", size =" << gmenu_item_count; for( int i = 0; i < gmenu_item_count; ++i ) { gchar* action_name = NULL; if( g_menu_model_get_item_attribute( m_model.data(), i, G_MENU_ATTRIBUTE_ACTION, "s", &action_name ) ) { gmenu_action_names += action_name; gmenu_action_names += ";"; g_free( action_name ); } } // parent model properties QString parent_menu_label; QString parent_menu_name; QString parent_action_names; QString parent_link_type; if( m_parent ) { parent_menu_label = m_parent->m_menu->menuAction()->text(); parent_menu_name = m_parent->m_menu->menuAction()->property( c_property_actionName ).toString(); for( QAction* action : m_parent->m_menu->actions() ) { parent_action_names += action->property( c_property_actionName ).toString() + ";"; } switch( m_parent->m_link_type ) { case LinkType::Root: parent_link_type = "root"; break; case LinkType::Section: parent_link_type = "section"; break; case LinkType::SubMenu: parent_link_type = "sub menu"; break; } } // local model properties QString menu_label; QString menu_name; QString action_names; QString link_type; QString action_paths; menu_label = m_menu->menuAction()->text(); menu_name = m_menu->menuAction()->property( c_property_actionName ).toString(); for( QAction* action : m_menu->actions() ) { action_names += action->property( c_property_actionName ).toString() + ";"; } switch( m_link_type ) { case LinkType::Root: link_type = "root"; break; case LinkType::Section: link_type = "section"; break; case LinkType::SubMenu: link_type = "sub menu"; break; } for( auto const& action : m_action_paths ) { action_paths += action.path() + ";"; } uint sender_pid = QDBusConnection::sessionBus().interface()->servicePid( m_bus_name); if( sender_pid == 0 ) { qWarning() << "Failed to read PID, cannot report error"; return; } QProcess recoverable; recoverable.setProcessChannelMode(QProcess::ForwardedChannels); recoverable.start("/usr/share/apport/recoverable_problem", QStringList() << "-p" << QString::number(sender_pid)); if (recoverable.waitForStarted()) { write_pair(recoverable, "DuplicateSignature", "GMenuModelItemsChangedInvalidIndex"); write_pair(recoverable, "BusName", m_bus_name); write_pair(recoverable, "Position", QString::number(index)); write_pair(recoverable, "Added", QString::number(added)); write_pair(recoverable, "Removed", QString::number(removed)); write_pair(recoverable, "ItemCount", QString::number(gmenu_item_count)); write_pair(recoverable, "ActionNames", gmenu_action_names); if ( m_parent ) { write_pair(recoverable, "ParentMenuLabel", parent_menu_label); write_pair(recoverable, "ParentMenuName", parent_menu_name); write_pair(recoverable, "ParentActionNames", parent_action_names); write_pair(recoverable, "ParentLinkType", parent_link_type); } write_pair(recoverable, "MenuLabel", menu_label); write_pair(recoverable, "MenuName", menu_name); write_pair(recoverable, "ActionNames", action_names); write_pair(recoverable, "LinkType", link_type); write_pair(recoverable, "MenuPath", m_menu_path); write_pair(recoverable, "ActionPaths", action_paths, true); recoverable.closeWriteChannel(); recoverable.waitForFinished(); m_error_reported = true; } else { qWarning() << "Failed to report recoverable error"; } emit MenuInvalid(); } hud-14.04+14.04.20140604/libqtgmenu/internal/QtGMenuUtils.h0000644000015301777760000000225212343623451023401 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #ifndef QTGMENUUTILS_H #define QTGMENUUTILS_H #include class _GVariant; typedef _GVariant GVariant; class QKeySequence; class QString; class QVariant; namespace qtgmenu { class QtGMenuUtils final { public: static QVariant GVariantToQVariant( GVariant* gvariant ); static QKeySequence QStringToQKeySequence( QString& shortcut ); static QPair splitPrefixAndName( const QString& name ); }; } // namespace qtgmenu #endif // QTGMENUUTILS_H hud-14.04+14.04.20140604/libqtgmenu/internal/QtGMenuImporterPrivate.cpp0000644000015301777760000001347312343623523025777 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include #include #include #include using namespace qtgmenu; QtGMenuImporterPrivate::QtGMenuImporterPrivate( const QString& service, const QDBusObjectPath& menu_path, const QMap& action_paths, QtGMenuImporter& parent ) : QObject( 0 ), m_service_watcher( service, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange ), m_parent( parent ), m_connection( g_bus_get_sync( G_BUS_TYPE_SESSION, NULL, NULL ), &g_object_unref ), m_service( service ), m_menu_path( menu_path ), m_action_paths( action_paths ) { connect( &m_service_watcher, SIGNAL( serviceRegistered( const QString& ) ), this, SLOT( ServiceRegistered() ) ); connect( &m_service_watcher, SIGNAL( serviceUnregistered( const QString& ) ), this, SLOT( ServiceUnregistered() ) ); Refresh(); } QtGMenuImporterPrivate::~QtGMenuImporterPrivate() { ClearMenuModel(); ClearActionGroups(); } QSharedPointer QtGMenuImporterPrivate::GetGMenuModel() { if( m_menu_model == nullptr ) { return QSharedPointer(); } return m_menu_model->Model(); } QSharedPointer QtGMenuImporterPrivate::GetGActionGroup( int index ) { if( index >= m_action_groups.size() || m_action_groups[index] == nullptr ) { return QSharedPointer(); } return m_action_groups[index]->ActionGroup(); } std::shared_ptr< QMenu > QtGMenuImporterPrivate::GetQMenu() { if( m_menu_model == nullptr ) { return nullptr; } return m_menu_model->GetQMenu(); } void QtGMenuImporterPrivate::Refresh() { if( !m_menu_path.path().isEmpty() ) { RefreshGMenuModel(); } if( !m_action_paths.empty() ) { RefreshGActionGroup(); } } void QtGMenuImporterPrivate::ClearMenuModel() { if( m_menu_model == nullptr ) { return; } m_menu_model->disconnect(); m_menu_actions_linked = false; m_menu_model = nullptr; } void QtGMenuImporterPrivate::ClearActionGroups() { for( auto& action_group : m_action_groups ) { action_group->disconnect(); } m_menu_actions_linked = false; m_action_groups.clear(); } void QtGMenuImporterPrivate::LinkMenuActions() { if( m_menu_model && !m_action_groups.empty() && !m_menu_actions_linked ) { for( auto& action_group : m_action_groups ) { connect( m_menu_model.get(), SIGNAL( ActionTriggered( QString, bool ) ), action_group.get(), SLOT( TriggerAction( QString, bool ) ) ); connect( m_menu_model.get(), SIGNAL( MenuItemsChanged( QtGMenuModel*, int, int, int ) ), action_group.get(), SLOT( EmitStates() ) ); connect( action_group.get(), SIGNAL( ActionEnabled( QString, bool ) ), m_menu_model.get(), SLOT( ActionEnabled( QString, bool ) ) ); connect( action_group.get(), SIGNAL( ActionParameterized( QString, bool ) ), m_menu_model.get(), SLOT( ActionParameterized( QString, bool ) ) ); } m_menu_actions_linked = true; } } void QtGMenuImporterPrivate::ServiceRegistered() { Refresh(); } void QtGMenuImporterPrivate::ServiceUnregistered() { ClearMenuModel(); ClearActionGroups(); } void QtGMenuImporterPrivate::RefreshGMenuModel() { // clear the menu model for the refresh ClearMenuModel(); QString menu_path = m_menu_path.path(); m_menu_model = std::make_shared< QtGMenuModel > ( m_connection, m_service, menu_path, m_action_paths ); connect( m_menu_model.get(), SIGNAL( MenuItemsChanged( QtGMenuModel*, int, int, int ) ), &m_parent, SIGNAL( MenuItemsChanged()) ); connect( m_menu_model.get(), SIGNAL( MenuInvalid() ), this, SLOT( MenuInvalid() ) ); } void QtGMenuImporterPrivate::RefreshGActionGroup() { // clear the action groups for the refresh ClearActionGroups(); QMapIterator action_path_it(m_action_paths); while( action_path_it.hasNext() ) { action_path_it.next(); QString action_path = action_path_it.value().path(); m_action_groups.push_back( std::make_shared(m_connection, action_path_it.key(), m_service, action_path)); auto action_group = m_action_groups.back(); connect( action_group.get(), SIGNAL( ActionAdded( QString ) ), &m_parent, SIGNAL( ActionAdded( QString ) ) ); connect( action_group.get(), SIGNAL( ActionRemoved( QString ) ), &m_parent, SIGNAL( ActionRemoved( QString ) ) ); connect( action_group.get(), SIGNAL( ActionEnabled( QString, bool ) ), &m_parent, SIGNAL( ActionEnabled( QString, bool ) ) ); connect( action_group.get(), SIGNAL( ActionStateChanged( QString, QVariant ) ), &m_parent, SIGNAL( ActionStateChanged( QString, QVariant) ) ); } LinkMenuActions(); } void QtGMenuImporterPrivate::MenuInvalid() { disconnect( &m_service_watcher, SIGNAL( serviceRegistered( const QString& ) ), this, SLOT( ServiceRegistered() ) ); disconnect( &m_service_watcher, SIGNAL( serviceUnregistered( const QString& ) ), this, SLOT( ServiceUnregistered() ) ); ServiceUnregistered(); } hud-14.04+14.04.20140604/libqtgmenu/internal/QtGMenuImporterPrivate.h0000644000015301777760000000423412343623523025437 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #ifndef QTGMENUEXPORTERPRIVATE_H #define QTGMENUEXPORTERPRIVATE_H #include #include #include #include #include #include #include #undef signals #include namespace qtgmenu { class QtGMenuImporterPrivate : public QObject { Q_OBJECT public: QtGMenuImporterPrivate( const QString& service, const QDBusObjectPath& menu_path, const QMap& action_paths, QtGMenuImporter& parent ); virtual ~QtGMenuImporterPrivate(); QSharedPointer GetGMenuModel(); QSharedPointer GetGActionGroup( int index = 0); std::shared_ptr< QMenu > GetQMenu(); void Refresh(); private: void ClearMenuModel(); void ClearActionGroups(); void LinkMenuActions(); private Q_SLOTS: void ServiceRegistered(); void ServiceUnregistered(); void RefreshGMenuModel(); void RefreshGActionGroup(); void MenuInvalid(); private: QDBusServiceWatcher m_service_watcher; QtGMenuImporter& m_parent; QSharedPointer m_connection; QString m_service; QDBusObjectPath m_menu_path; QMap m_action_paths; std::shared_ptr< QtGMenuModel > m_menu_model = nullptr; std::vector< std::shared_ptr< QtGActionGroup > > m_action_groups; bool m_menu_actions_linked = false; }; } // namespace qtgmenu #endif /* QTGMENUEXPORTERPRIVATE_H */ hud-14.04+14.04.20140604/libqtgmenu/internal/CMakeLists.txt0000644000015301777760000000061012343623451023423 0ustar pbusernogroup00000000000000set( QTGMENU_INTERNAL_SRC QtGActionGroup.cpp QtGMenuImporterPrivate.cpp QtGMenuUtils.cpp QtGMenuModel.cpp ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ) add_library( qtgmenu-internal ${QTGMENU_INTERNAL_SRC} ) target_link_libraries( qtgmenu-internal ${GIO2_LIBRARIES} ) qt5_use_modules( qtgmenu-internal Core DBus Widgets ) hud-14.04+14.04.20140604/libqtgmenu/internal/QtGActionGroup.cpp0000644000015301777760000001562112343623523024245 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include #include using namespace qtgmenu; QtGActionGroup::QtGActionGroup( QSharedPointer connection, const QString& action_prefix, const QString& service, const QString& path ) : m_action_prefix( action_prefix ), m_action_group( G_ACTION_GROUP( g_dbus_action_group_get(connection.data(), service.toUtf8().constData(), path.toUtf8().constData())), &g_object_unref) { ConnectCallbacks(); auto actions_list = g_action_group_list_actions( m_action_group.data() ); if( actions_list ) { for( int i = 0; actions_list[i]; ++i ) { emit ActionAdded( actions_list[i] ); } g_strfreev( actions_list ); } } QtGActionGroup::~QtGActionGroup() { if( m_action_group == nullptr ) { return; } auto actions_list = g_action_group_list_actions( m_action_group.data() ); if( actions_list ) { for( int i = 0; actions_list[i]; ++i ) { emit ActionRemoved( actions_list[i] ); } g_strfreev( actions_list ); } DisconnectCallbacks(); } QSharedPointer QtGActionGroup::ActionGroup() const { return m_action_group; } void QtGActionGroup::TriggerAction( QString action_name, bool checked ) { QPair split = QtGMenuUtils::splitPrefixAndName(action_name); const QString& prefix(split.first); if( prefix != m_action_prefix ) { return; } const QString& action(split.second); QByteArray action_utf = action.toUtf8(); const GVariantType* type = g_action_group_get_action_parameter_type( m_action_group.data(), action_utf.constData() ); if( type == nullptr ) { g_action_group_activate_action( m_action_group.data(), action_utf.constData(), nullptr ); } else { ///! need to evaluate and send parameter value if( g_variant_type_equal( type, G_VARIANT_TYPE_STRING ) ) { GVariant* param = g_variant_new_string( action_utf.constData() ); g_action_group_activate_action( m_action_group.data(), action_utf.constData(), param ); g_variant_unref( param ); } } } QString QtGActionGroup::FullName( const QString& prefix, const QString& action_name ) { if ( prefix.isEmpty() ) { return action_name; } else { return prefix + "." + action_name; } } void QtGActionGroup::EmitStates() { auto actions_list = g_action_group_list_actions( m_action_group.data() ); for( int i = 0; actions_list && actions_list[i]; ++i ) { gchar* action_name = actions_list[i]; bool enabled = G_ACTION_GROUP_GET_IFACE( m_action_group.data() ) ->get_action_enabled( m_action_group.data(), action_name ); emit ActionEnabled( FullName(m_action_prefix, action_name), enabled ); const GVariantType* type = g_action_group_get_action_parameter_type( m_action_group.data(), action_name ); emit ActionParameterized( FullName(m_action_prefix, action_name), type != nullptr ); } g_strfreev( actions_list ); } void QtGActionGroup::ActionAddedCallback( GActionGroup* action_group, gchar* action_name, gpointer user_data ) { QtGActionGroup* self = reinterpret_cast< QtGActionGroup* >( user_data ); emit self->ActionAdded( action_name ); bool enabled = G_ACTION_GROUP_GET_IFACE( self->m_action_group.data() ) ->get_action_enabled( self->m_action_group.data(), action_name ); if( !enabled ) emit self->ActionEnabled( FullName(self->m_action_prefix, action_name), enabled ); const GVariantType* type = g_action_group_get_action_parameter_type( self->m_action_group.data(), action_name ); if( type != nullptr ) emit self->ActionParameterized( FullName(self->m_action_prefix, action_name), type != nullptr ); } void QtGActionGroup::ActionRemovedCallback( GActionGroup* action_group, gchar* action_name, gpointer user_data ) { QtGActionGroup* self = reinterpret_cast< QtGActionGroup* >( user_data ); emit self->ActionRemoved( action_name ); } void QtGActionGroup::ActionEnabledCallback( GActionGroup* action_group, gchar* action_name, gboolean enabled, gpointer user_data ) { QtGActionGroup* self = reinterpret_cast< QtGActionGroup* >( user_data ); emit self->ActionEnabled( FullName(self->m_action_prefix, action_name), enabled ); } void QtGActionGroup::ActionStateChangedCallback( GActionGroup* action_group, gchar* action_name, GVariant* value, gpointer user_data ) { QtGActionGroup* self = reinterpret_cast< QtGActionGroup* >( user_data ); emit self->ActionStateChanged( action_name, QtGMenuUtils::GVariantToQVariant( value ) ); } void QtGActionGroup::ConnectCallbacks() { if( m_action_group && m_action_added_handler == 0 ) { m_action_added_handler = g_signal_connect( m_action_group.data(), "action-added", G_CALLBACK( ActionAddedCallback ), this ); } if( m_action_group && m_action_removed_handler == 0 ) { m_action_removed_handler = g_signal_connect( m_action_group.data(), "action-removed", G_CALLBACK( ActionRemovedCallback ), this ); } if( m_action_group && m_action_enabled_handler == 0 ) { m_action_enabled_handler = g_signal_connect( m_action_group.data(), "action-enabled-changed", G_CALLBACK( ActionEnabledCallback ), this ); } if( m_action_group && m_action_state_changed_handler == 0 ) { m_action_state_changed_handler = g_signal_connect( m_action_group.data(), "action-state-changed", G_CALLBACK( ActionStateChangedCallback ), this ); } } void QtGActionGroup::DisconnectCallbacks() { if( m_action_group && m_action_added_handler != 0 ) { g_signal_handler_disconnect( m_action_group.data(), m_action_added_handler ); } if( m_action_group && m_action_removed_handler != 0 ) { g_signal_handler_disconnect( m_action_group.data(), m_action_removed_handler ); } if( m_action_group && m_action_enabled_handler != 0 ) { g_signal_handler_disconnect( m_action_group.data(), m_action_enabled_handler ); } if( m_action_group && m_action_state_changed_handler != 0 ) { g_signal_handler_disconnect( m_action_group.data(), m_action_state_changed_handler ); } m_action_added_handler = 0; m_action_removed_handler = 0; m_action_enabled_handler = 0; m_action_state_changed_handler = 0; } hud-14.04+14.04.20140604/libqtgmenu/internal/QtGMenuUtils.cpp0000644000015301777760000001552012343623451023736 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include #include #include #undef signals #include using namespace qtgmenu; static QVariant makeBoolQVariant( GVariant* gvariant ) { bool value = ( g_variant_get_boolean( gvariant ) ? true : false ); return QVariant::fromValue( value ); } static QVariant makeIntQVariant( GVariant* gvariant ) { qint32 value = 0; if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_INT16 ) ) value = g_variant_get_int16( gvariant ); else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_INT32 ) ) value = g_variant_get_int32( gvariant ); return QVariant::fromValue( value ); } static QVariant makeUIntQVariant( GVariant* gvariant ) { quint32 value = 0; if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_BYTE ) ) value = g_variant_get_byte( gvariant ); else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_UINT16 ) ) value = g_variant_get_uint16( gvariant ); else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_UINT32 ) ) value = g_variant_get_uint32( gvariant ); return QVariant::fromValue( value ); } static QVariant makeLongLongQVariant( GVariant* gvariant ) { qint64 value = g_variant_get_int64( gvariant ); return QVariant::fromValue( value ); } static QVariant makeULongLongQVariant( GVariant* gvariant ) { quint64 value = g_variant_get_uint64( gvariant ); return QVariant::fromValue( value ); } static QVariant makeStringQVariant( GVariant* gvariant ) { const char* string = NULL; gsize length = 0; string = g_variant_get_string( gvariant, &length ); QString value( QString::fromUtf8( string, length ) ); return QVariant::fromValue( value ); } static QVariant makeStringListQVariant( GVariant* gvariant ) { int i = 0; const gchar* *stringArray = g_variant_get_strv( gvariant, NULL ); QStringList value; if( !stringArray ) return QVariant::fromValue( value ); while( stringArray[i] != NULL ) value << QString::fromUtf8( stringArray[i++] ); g_free (const_cast(stringArray)); return QVariant::fromValue( value ); } static QVariant makeVariantQVariant( GVariant* gvariant ) { return QVariant::fromValue( QtGMenuUtils::GVariantToQVariant( gvariant ) ); } static QVariant makeByteArrayQVariant( GVariant* gvariant ) { QByteArray value; GVariantIter iter; guchar* byte; g_variant_iter_init( &iter, gvariant ); while( g_variant_iter_loop( &iter, "y", &byte ) ) value.append( *byte ); return QVariant::fromValue( value ); } static QVariant makeVariantListQVariant( GVariant* gvariant ) { QVariantList value; GVariantIter iter; GVariant* var; g_variant_iter_init( &iter, gvariant ); while( g_variant_iter_loop( &iter, "v", &var ) ) value.append( QtGMenuUtils::GVariantToQVariant( var ) ); return QVariant::fromValue( value ); } static QVariant makeVariantMapQVariant( GVariant* gvariant ) { QVariantMap value; GVariantIter iter; gchar* key; GVariant* var; g_variant_iter_init( &iter, gvariant ); while( g_variant_iter_loop( &iter, "{sv}", &key, &var ) ) value.insert( QString::fromUtf8( key ), QtGMenuUtils::GVariantToQVariant( var ) ); return QVariant::fromValue( value ); } QVariant QtGMenuUtils::GVariantToQVariant( GVariant* gvariant ) { if( !gvariant ) { return QVariant(); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_BOOLEAN ) ) { return makeBoolQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_BYTE ) || g_variant_is_of_type( gvariant, G_VARIANT_TYPE_UINT16 ) || g_variant_is_of_type( gvariant, G_VARIANT_TYPE_UINT32 ) ) { return makeUIntQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_INT16 ) || g_variant_is_of_type( gvariant, G_VARIANT_TYPE_INT32 ) ) { return makeIntQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_INT64 ) ) { return makeLongLongQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_UINT64 ) ) { return makeLongLongQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_DOUBLE ) ) { return makeULongLongQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_STRING ) ) { return makeStringQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE( "as" ) ) ) { return makeStringListQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE_VARIANT ) ) { return makeVariantQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE( "ay" ) ) ) { return makeByteArrayQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE( "av" ) ) ) { return makeVariantListQVariant( gvariant ); } else if( g_variant_is_of_type( gvariant, G_VARIANT_TYPE( "a{sv}" ) ) ) { return makeVariantMapQVariant( gvariant ); } else { qCritical( ) << "Cannot convert the type " << g_variant_get_type_string( gvariant ) << " into QVariant"; } return QVariant(); } QKeySequence QtGMenuUtils::QStringToQKeySequence( QString& shortcut ) { if( shortcut.isEmpty() ) { return QKeySequence(); } shortcut.replace( "", "Ctrl+", Qt::CaseInsensitive ); shortcut.replace( "", "Ctrl+", Qt::CaseInsensitive ); shortcut.replace( "", "Shift+", Qt::CaseInsensitive ); shortcut.replace( "", "Alt+", Qt::CaseInsensitive ); shortcut.replace( "", "Meta+", Qt::CaseInsensitive ); shortcut.replace( "", "Super+", Qt::CaseInsensitive ); shortcut.replace( "", "Hyper+", Qt::CaseInsensitive ); shortcut.replace( "plus", "+", Qt::CaseInsensitive ); shortcut.replace( "minus", "-", Qt::CaseInsensitive ); shortcut.replace( "page_up", "PgUp", Qt::CaseInsensitive ); shortcut.replace( "page_down", "PgDown", Qt::CaseInsensitive ); return QKeySequence::fromString( shortcut ); } QPair QtGMenuUtils::splitPrefixAndName( const QString& name ) { int index = name.indexOf( '.' ); if( index == -1 ) { return qMakePair(QString(), name); } else { return qMakePair(name.left( index ), name.right( name.size() - index - 1 )); } } hud-14.04+14.04.20140604/libqtgmenu/internal/QtGActionGroup.h0000644000015301777760000000474612343623523023720 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #ifndef QTGACTIONGROUP_H #define QTGACTIONGROUP_H #include #include #include #undef signals #include namespace qtgmenu { class QtGActionGroup : public QObject { Q_OBJECT public: QtGActionGroup(QSharedPointer connection, const QString& action_prefix, const QString& service, const QString& path); virtual ~QtGActionGroup(); QSharedPointer ActionGroup() const; Q_SIGNALS: void ActionAdded( QString action_name ); void ActionRemoved( QString action_name ); void ActionEnabled( QString action_name, bool enabled ); void ActionParameterized( QString action_name, bool parameterized ); void ActionStateChanged( QString action_name, QVariant value ); private Q_SLOTS: void TriggerAction( QString action_name, bool checked ); void EmitStates(); private: static QString FullName( const QString& prefix, const QString& name ); static void ActionAddedCallback( GActionGroup* action_group, gchar* action_name, gpointer user_data ); static void ActionRemovedCallback( GActionGroup* action_group, gchar* action_name, gpointer user_data ); static void ActionEnabledCallback( GActionGroup* action_group, gchar* action_name, gboolean enabled, gpointer user_data ); static void ActionStateChangedCallback( GActionGroup* action_group, gchar* action_name, GVariant* value, gpointer user_data ); void ConnectCallbacks(); void DisconnectCallbacks(); private: QString m_action_prefix; QSharedPointer m_action_group; gulong m_action_added_handler = 0; gulong m_action_removed_handler = 0; gulong m_action_enabled_handler = 0; gulong m_action_state_changed_handler = 0; }; } // namespace qtgmenu #endif // QTGACTIONGROUP_H hud-14.04+14.04.20140604/libqtgmenu/QtGMenuImporter.h0000644000015301777760000000400712343623523022266 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #ifndef QTGMENUIMPORTER_H #define QTGMENUIMPORTER_H #include #include #include class QMenu; class _GMenuModel; typedef _GMenuModel GMenuModel; class _GActionGroup; typedef _GActionGroup GActionGroup; namespace qtgmenu { class QtGMenuImporterPrivate; class QtGMenuImporter final : public QObject { Q_OBJECT public: QtGMenuImporter( const QString& service, const QDBusObjectPath& menu_path, const QString& action_prefix, const QDBusObjectPath& action_path, QObject* parent = 0 ); QtGMenuImporter( const QString& service, const QDBusObjectPath& menu_path, const QMap& action_paths, QObject* parent = 0 ); virtual ~QtGMenuImporter(); QSharedPointer GetGMenuModel() const; QSharedPointer GetGActionGroup( int index = 0 ) const; std::shared_ptr< QMenu > GetQMenu() const; void Refresh(); Q_SIGNALS: void MenuItemsChanged(); void ActionAdded( QString action_name ); void ActionRemoved( QString action_name ); void ActionEnabled( QString action_name, bool enabled ); void ActionStateChanged( QString action_name, QVariant value ); private: Q_DISABLE_COPY (QtGMenuImporter) std::unique_ptr< QtGMenuImporterPrivate > d; }; } // namespace qtgmenu #endif // QTGMENUIMPORTER_H hud-14.04+14.04.20140604/libqtgmenu/QtGMenuImporter.cpp0000644000015301777760000000366412343623523022631 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include #include #include using namespace qtgmenu; QtGMenuImporter::QtGMenuImporter( const QString& service, const QDBusObjectPath& menu_path, const QString& action_prefix, const QDBusObjectPath& action_path, QObject* parent ) : QObject( parent ) { QMap action_paths; action_paths[action_prefix] = action_path; d.reset( new QtGMenuImporterPrivate( service, menu_path, action_paths, *this ) ); } QtGMenuImporter::QtGMenuImporter( const QString& service, const QDBusObjectPath& menu_path, const QMap& action_paths, QObject* parent ) : QObject( parent ), d( new QtGMenuImporterPrivate( service, menu_path, action_paths, *this ) ) { } QtGMenuImporter::~QtGMenuImporter() { } QSharedPointer QtGMenuImporter::GetGMenuModel() const { return d->GetGMenuModel(); } QSharedPointer QtGMenuImporter::GetGActionGroup( int index ) const { return d->GetGActionGroup( index ); } std::shared_ptr< QMenu > QtGMenuImporter::GetQMenu() const { return d->GetQMenu(); } void QtGMenuImporter::Refresh() { d->Refresh(); } hud-14.04+14.04.20140604/libqtgmenu/QtGMenuExporter.h0000644000015301777760000000244512343623451022301 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #ifndef QTGMENUEXPORTER_H #define QTGMENUEXPORTER_H #include #include #include class QAction; class QMenu; namespace qtgmenu { class QtGMenuExporterPrivate; class QtGMenuExporter final : public QObject { Q_OBJECT public: QtGMenuExporter( const QString& dbusObjectPath, QMenu* menu, const QDBusConnection& connection = QDBusConnection::sessionBus() ); virtual ~QtGMenuExporter(); private Q_SLOTS: private: Q_DISABLE_COPY(QtGMenuExporter) std::unique_ptr< QtGMenuExporterPrivate > d; }; } // namespace qtgmenu #endif // QTGMENUEXPORTER_H hud-14.04+14.04.20140604/libqtgmenu/CMakeLists.txt0000644000015301777760000000043512343623451021614 0ustar pbusernogroup00000000000000 add_compiler_export_flags() add_subdirectory(internal) set( QTGMENU_SRC QtGMenuExporter.cpp QtGMenuImporter.cpp ) add_library( qtgmenu ${QTGMENU_SRC} ) qt5_use_modules( qtgmenu Core DBus ) target_link_libraries( qtgmenu qtgmenu-internal ) hud-14.04+14.04.20140604/libqtgmenu/QtGMenuExporter.cpp0000644000015301777760000000211412343623451022625 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Marcus Tomlinson */ #include "QtGMenuExporter.h" #include using namespace qtgmenu; namespace qtgmenu { class QtGMenuExporterPrivate { }; } // namespace qtgmenu QtGMenuExporter::QtGMenuExporter( const QString& dbusObjectPath, QMenu* menu, const QDBusConnection& connection ) : QObject( menu ), d( new QtGMenuExporterPrivate() ) { } QtGMenuExporter::~QtGMenuExporter() { } hud-14.04+14.04.20140604/ChangeLog0000644000015301777760000000003012343623451016446 0ustar pbusernogroup00000000000000# Generated by Makefile hud-14.04+14.04.20140604/CMakeLists.txt0000644000015301777760000001272312343623451017450 0ustar pbusernogroup00000000000000project(hud C CXX) cmake_minimum_required(VERSION 2.8.9) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}") set(PACKAGE ${CMAKE_PROJECT_NAME}) set(GETTEXT_PACKAGE ${CMAKE_PROJECT_NAME}) option(ENABLE_DOCUMENTATION "Enable documentation." OFF) option(ENABLE_TESTS "Enable tests." ON) option(ENABLE_SCALABILITY_TESTS "Additional scalability tests that are potentially very slow to run." OFF) option(LOCAL_INSTALL "Support local installation." OFF) option(ENABLE_BAMF "Enable building for BAMF." ON) option(ENABLE_PLATFORM_API "Enable building for platform API." OFF) # Trick the H10enable_coverage script into enabling coverage by including the text below: # CMAKE_BUILD_TYPE coverage find_package(PkgConfig REQUIRED) include(GNUInstallDirs) include(CheckIncludeFile) include(CheckFunctionExists) include(Coverage) include(UseGlibGeneration) include(UseGdbusCodegen) include(UseConstantBuilder) include(UseGSettings) include(UseVala) # Workaround for libexecdir on debian if (EXISTS "/etc/debian_version") set(CMAKE_INSTALL_LIBEXECDIR ${CMAKE_INSTALL_LIBDIR}) set(CMAKE_INSTALL_FULL_LIBEXECDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBEXECDIR}") endif() set(HUD_QUERY_XML ${CMAKE_CURRENT_SOURCE_DIR}/data/com.canonical.hud.query.xml) set(HUD_SERVICE_XML ${CMAKE_CURRENT_SOURCE_DIR}/data/com.canonical.hud.xml) set(HUD_APP_XML ${CMAKE_CURRENT_SOURCE_DIR}/data/com.canonical.hud.Application.xml) set(WINDOW_STACK_XML "${CMAKE_CURRENT_SOURCE_DIR}/data/com.canonical.Unity.WindowStack.xml") set(APPMENU_REGISTRAR_XML "${CMAKE_CURRENT_SOURCE_DIR}/data/com.canonical.AppMenu.Registrar.xml") set(BAMF_XML "${CMAKE_CURRENT_SOURCE_DIR}/data/org.ayatana.bamf.xml") set(BAMF_VIEW_XML "${CMAKE_CURRENT_SOURCE_DIR}/data/org.ayatana.bamf.view.xml") set(HUD_TOP_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(HUD_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src") add_definitions( -DDATADIR="${CMAKE_INSTALL_FULL_DATADIR}" ) add_definitions( -DGNOMELOCALEDIR="${CMAKE_INSTALL_FULL_DATADIR}/locale" ) add_definitions( -DGETTEXT_PACKAGE="${GETTEXT_PACKAGE}" ) add_definitions( -DLIBEXECDIR="${CMAKE_INSTALL_FULL_LIBEXECDIR}" ) pkg_check_modules(GLIB2 REQUIRED glib-2.0) include_directories(${GLIB2_INCLUDE_DIRS}) pkg_check_modules(GOBJECT2 REQUIRED gobject-2.0) include_directories(${GOBJECT2_INCLUDE_DIRS}) pkg_check_modules(GIO2 REQUIRED gio-2.0) include_directories(${GIO2_INCLUDE_DIRS}) pkg_check_modules(GIO_UNIX2 REQUIRED gio-unix-2.0) include_directories(${GIO_UNIX2_INCLUDE_DIRS}) pkg_check_modules(DEE REQUIRED dee-1.0) include_directories(${DEE_INCLUDE_DIRS}) pkg_check_modules(DBUSMENU_GLIB REQUIRED dbusmenu-glib-0.4) include_directories(${DBUSMENU_GLIB_INCLUDE_DIRS}) pkg_search_module(GTK3 REQUIRED gtk+-3.0) include_directories(${GTK3_INCLUDE_DIRS}) pkg_check_modules(COLUMBUS REQUIRED libcolumbus) include_directories(${COLUMBUS_INCLUDE_DIRS}) find_package(Qt5Core REQUIRED) include_directories(${Qt5Core_INCLUDE_DIRS}) find_package(Qt5Widgets REQUIRED) include_directories(${Qt5Widgets_INCLUDE_DIRS}) find_package(Qt5DBus REQUIRED) include_directories(${Qt5DBus_INCLUDE_DIRS}) find_package(Qt5Sql REQUIRED) include_directories(${Qt5Sql_INCLUDE_DIRS}) pkg_check_modules(DEE_QT REQUIRED libdee-qt5) include_directories(${DEE_QT_INCLUDE_DIRS}) pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt REQUIRED) include_directories(${GSETTINGS_QT_INCLUDE_DIRS}) pkg_check_modules(DBUSMENU REQUIRED dbusmenu-qt5) include_directories(${DBUSMENU_INCLUDE_DIRS}) find_package(Qt5Test REQUIRED) include_directories(${Qt5Test_INCLUDE_DIRS}) pkg_check_modules(QTDBUSTEST REQUIRED libqtdbustest-1 REQUIRED) include_directories(${QTDBUSTEST_INCLUDE_DIRS}) pkg_check_modules(QTDBUSMOCK REQUIRED libqtdbusmock-1 REQUIRED) include_directories(${QTDBUSMOCK_INCLUDE_DIRS}) pkg_check_modules(UNITYVOICE REQUIRED libunityvoice-1 REQUIRED) include_directories(${UNITYVOICE_INCLUDE_DIRS}) find_package(Vala 0.12) find_package(GObjectIntrospection 0.9.12) check_include_file("signal.h" HAVE_SIGNAL_H) if(${HAVE_SIGNAL_H}) set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} "signal.h") check_function_exists(kill HAVE_KILL) endif() if(${LOCAL_INSTALL}) set(DBUSSERVICEDIR "${CMAKE_INSTALL_DATADIR}/dbus-1/services/") else() EXEC_PROGRAM(${PKG_CONFIG_EXECUTABLE} ARGS dbus-1 --variable session_bus_services_dir OUTPUT_VARIABLE DBUSSERVICEDIR ) endif() message("Installing DBus services to ${DBUSSERVICEDIR}") if(${LOCAL_INSTALL}) set(DBUSIFACEDIR "${CMAKE_INSTALL_DATADIR}/dbus-1/interfaces/") else() EXEC_PROGRAM(${PKG_CONFIG_EXECUTABLE} ARGS dbus-1 --variable interfaces_dir OUTPUT_VARIABLE DBUSIFACEDIR ) endif() message("Installing DBus interfaces to ${DBUSIFACEDIR}") include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) add_definitions( -DQT_NO_SIGNALS_SLOTS_KEYWORDS=1 ) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive") include(GenerateExportHeader) add_subdirectory(data) add_subdirectory(common) add_subdirectory(libhud-client) add_subdirectory(libhud) add_subdirectory(libhud-gtk) add_subdirectory(libqtgmenu) add_subdirectory(service) add_subdirectory(tools) add_subdirectory(window-stack-bridge) if(${ENABLE_TESTS}) enable_testing() ADD_CUSTOM_TARGET( check ${CMAKE_CTEST_COMMAND} --force-new-ctest-process --output-on-failure ) add_subdirectory(tests) endif() add_subdirectory(tools-vala) if(${ENABLE_DOCUMENTATION}) add_subdirectory(docs) endif() hud-14.04+14.04.20140604/COPYING0000644000015301777760000010437412343623451015747 0ustar pbusernogroup00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 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 General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . hud-14.04+14.04.20140604/tools-vala/0000755000015301777760000000000012343624372016767 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/tools-vala/hud-gtk.ui0000644000015301777760000002147712343623451020701 0ustar pbusernogroup00000000000000 True False True False True True 6 6 6 6 True 0 0 1 1 True True 6 6 6 6 True Idle 1 0 1 1 True True 6 6 6 6 True Voice 2 0 5 1 0 0 1 1 True True in True True 6 6 6 6 True True natural liststore False False False 0 Description 0 1 2 3 4 0 2 1 1 True True in True True 6 6 6 6 True True natural appstack_liststore False False False 0 Description 0 1 0 1 1 1 hud-14.04+14.04.20140604/tools-vala/hud-gtk.vala0000644000015301777760000001360612343623451021202 0ustar pbusernogroup00000000000000extern const string HUD_GTK_DATADIR; namespace HudGtk { public class CellRendererVariant : Gtk.CellRendererText { public Variant value { set { if (value != null) { text = value.print (false); } else { text = "(null)"; } } } } class Window : Gtk.ApplicationWindow { Gtk.Label voice_label; Gtk.ListStore model; Gtk.ListStore appstack_model; Gtk.Entry entry; HudClient.Query query; void results_row_added (Dee.Model results, Dee.ModelIter result_iter) { var pos = results.get_position(result_iter); Gtk.TreeIter iter; model.insert(out iter, (int)pos); model.set(iter, 0, query.results_get_command_name(result_iter)); model.set(iter, 1, query.results_get_description(result_iter)); model.set(iter, 2, query.results_get_shortcut(result_iter)); /* Distance isn't in the API because it's internal, but this is a debugging tool so we're leavinging here */ model.set(iter, 3, results.get_uint32(result_iter, 6)); model.set(iter, 4, Markup.escape_text(query.results_get_command_id(result_iter).print(true))); model.set(iter, 5, query.results_get_command_id(result_iter)); } void results_row_removed (Dee.Model results, Dee.ModelIter result_iter) { var pos = results.get_position(result_iter); string spath = "%d"; spath = spath.printf(pos); Gtk.TreePath path = new Gtk.TreePath.from_string(spath); Gtk.TreeIter iter; model.get_iter(out iter, path); model.remove(iter); } void appstack_results_row_added (Dee.Model results, Dee.ModelIter result_iter) { var pos = results.get_position(result_iter); Gtk.TreeIter iter; appstack_model.insert(out iter, (int)pos); appstack_model.set(iter, 0, query.appstack_get_app_id(result_iter)); appstack_model.set(iter, 1, query.appstack_get_app_icon(result_iter)); } void appstack_results_row_removed (Dee.Model results, Dee.ModelIter result_iter) { var pos = results.get_position(result_iter); string spath = "%d"; spath = spath.printf(pos); Gtk.TreePath path = new Gtk.TreePath.from_string(spath); Gtk.TreeIter iter; appstack_model.get_iter(out iter, path); appstack_model.remove(iter); } void entry_text_changed (Object object, ParamSpec pspec) { query.set_query(entry.text); } void voice_pressed (Gtk.Button button) { query.voice_query(); } void view_activated (Gtk.TreeView view, Gtk.TreePath path, Gtk.TreeViewColumn column) { Gtk.TreeIter iter; Variant key; model.get_iter (out iter, path); model.get (iter, 5, out key); query.execute_command(key, 0); } void voice_query_loading (HudClient.Query proxy) { debug("Voice query is loading"); voice_label.label = "Loading"; } void voice_query_failed (HudClient.Query proxy, string cause) { debug("Voice query failed, cause=[%s]", cause); voice_label.label = "Idle"; var dialog = new Gtk.MessageDialog(null,Gtk.DialogFlags.MODAL,Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "Voice query failed, cause=[%s]", cause); dialog.set_title("Voice query failed"); dialog.run(); dialog.destroy(); } void voice_query_listening (HudClient.Query proxy) { debug("Voice query is listening"); voice_label.label = "Listening"; } void voice_query_heard_something (HudClient.Query proxy) { debug("Voice query has heard something"); voice_label.label = "Heard Something"; } void voice_query_finished (HudClient.Query proxy, string query) { debug("Voice query is finished, query=[%s]", query); voice_label.label = "Idle"; entry.text = query; } void appstack_view_activated (Gtk.TreeView view, Gtk.TreePath path, Gtk.TreeViewColumn column) { Gtk.TreeIter iter; string key; appstack_model.get_iter (out iter, path); appstack_model.get (iter, 0, out key); query.set_appstack_app(key); } public Window (Gtk.Application application) { Object (application: application, title: "Hud"); set_default_size (500, 300); query = new HudClient.Query(""); query.models_changed.connect ( models_changed ); } void models_changed(HudClient.Query proxy) { query.models_changed.disconnect ( models_changed ); var builder = new Gtk.Builder (); try { new CellRendererVariant (); builder.add_from_file (HUD_GTK_DATADIR + "/hud-gtk.ui"); } catch (Error e) { error (e.message); } voice_label = builder.get_object ("voice-status") as Gtk.Label; query.voice_query_loading.connect ( voice_query_loading ); query.voice_query_failed.connect ( voice_query_failed ); query.voice_query_listening.connect ( voice_query_listening ); query.voice_query_heard_something.connect ( voice_query_heard_something ); query.voice_query_finished.connect ( voice_query_finished ); Dee.Model results = query.get_results_model(); results.row_added.connect (results_row_added); results.row_removed.connect (results_row_removed); Dee.Model appstack_results = query.get_appstack_model(); appstack_results.row_added.connect (appstack_results_row_added); appstack_results.row_removed.connect (appstack_results_row_removed); entry = builder.get_object ("entry") as Gtk.Entry; model = builder.get_object ("liststore") as Gtk.ListStore; entry.notify["text"].connect (entry_text_changed); (builder.get_object ("voice") as Gtk.Button).clicked.connect (voice_pressed); (builder.get_object ("treeview") as Gtk.TreeView).row_activated.connect (view_activated); add (builder.get_object ("grid") as Gtk.Widget); appstack_model = builder.get_object ("appstack_liststore") as Gtk.ListStore; (builder.get_object ("appstack_treeview") as Gtk.TreeView).row_activated.connect (appstack_view_activated); } } class Application : Gtk.Application { protected override void activate () { new Window (this).show_all (); } public Application () { Object (application_id: "com.canonical.HudGtk"); } } } int main (string[] args) { return new HudGtk.Application ().run (args); } hud-14.04+14.04.20140604/tools-vala/CMakeLists.txt0000644000015301777760000000314312343623451021525 0ustar pbusernogroup00000000000000 if(${VALA_FOUND}) if(${INTROSPECTION_FOUND}) set(HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}/hud-gtk.h") set(SYMBOLS_PATH "${CMAKE_CURRENT_BINARY_DIR}/hud-gtk.def") set(HUD_GTK_DATADIR "${CMAKE_INSTALL_FULL_DATADIR}/hud-gtk") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations") ########################### # HUD Gtk Vala Generation ########################### set(VALA_OPTIONS) foreach(DIR ${HUD_CLIENT_INCLUDE_DIRS}) list(APPEND VALA_OPTIONS "--vapidir" ${DIR}) endforeach() vala_init (hud-gtk-vala PACKAGES Dee-1.0 gtk+-3.0 HudClient-2 OPTIONS ${VALA_OPTIONS} DEPENDS hud-client-vapi ) vala_add(hud-gtk-vala hud-gtk.vala) vala_finish(hud-gtk-vala SOURCES project_VALA_SOURCES OUTPUTS project_VALA_C GENERATE_HEADER ${HEADER_PATH} GENERATE_SYMBOLS ${SYMBOLS_PATH} ) set_source_files_properties(${project_VALA_SOURCES} PROPERTIES HEADER_FILE_ONLY TRUE) set(project_SOURCES ${project_VALA_SOURCES} ${project_VALA_C} ${SYMBOLS_PATH}) ########################### # HUD Gtk Executable ########################### include_directories(${HUD_CLIENT_INCLUDE_DIRS}) add_definitions(-DHUD_GTK_DATADIR="${HUD_GTK_DATADIR}") add_executable (hud-gtk-exec ${project_SOURCES}) set_target_properties(hud-gtk-exec PROPERTIES OUTPUT_NAME "hud-gtk") target_link_libraries(hud-gtk-exec hud-client ${GTK3_LIBRARIES} ${DEE_LIBRARIES} ) ########################### # Installation ########################### install( TARGETS hud-gtk-exec RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) install( FILES hud-gtk.ui DESTINATION ${HUD_GTK_DATADIR} ) endif() endif() hud-14.04+14.04.20140604/docs/0000755000015301777760000000000012343624372015636 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/docs/devel/0000755000015301777760000000000012343624372016735 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/docs/devel/hud-docs.xml0000644000015301777760000000332012343623451021160 0ustar pbusernogroup00000000000000 ]> hud-service Hacking Guide Data Types Queries, Results, Items Sources Utility API Object Hierarchy API Index Index of deprecated API hud-14.04+14.04.20140604/docs/devel/hud-sections.txt0000644000015301777760000000577012343623451022111 0ustar pbusernogroup00000000000000
hudsettings HudSettings hud_settings hud_settings_init
hudappmenuregistrar HudAppMenuRegistrar HudAppMenuRegistrarObserverFunc hud_app_menu_registrar_add_observer hud_app_menu_registrar_get hud_app_menu_registrar_remove_observer HUD_APP_MENU_REGISTRAR HUD_IS_APP_MENU_REGISTRAR HUD_TYPE_APP_MENU_REGISTRAR hud_app_menu_registrar_get_type
huddbusmenucollector HudDbusmenuCollector hud_dbusmenu_collector_new_for_endpoint hud_dbusmenu_collector_new_for_window hud_dbusmenu_collector_set_prefix HUD_DBUSMENU_COLLECTOR HUD_IS_DBUSMENU_COLLECTOR HUD_TYPE_DBUSMENU_COLLECTOR hud_dbusmenu_collector_get_type
hudindicatorsource HudIndicatorSource hud_indicator_source_new HUD_INDICATOR_SOURCE HUD_IS_INDICATOR_SOURCE HUD_TYPE_INDICATOR_SOURCE hud_indicator_source_get_type
hudappindicatorsource HudAppIndicatorSource hud_app_indicator_source_new HUD_APP_INDICATOR_SOURCE HUD_IS_APP_INDICATOR_SOURCE HUD_TYPE_APP_INDICATOR_SOURCE hud_app_indicator_source_get_type
huditem HudItem HudItem HudItemClass hud_item_activate hud_item_construct hud_item_get_app_icon hud_item_get_enabled hud_item_get_item_icon hud_item_get_tokens hud_item_get_usage hud_item_new HUD_IS_ITEM HUD_IS_ITEM_CLASS HUD_ITEM HUD_ITEM_CLASS HUD_ITEM_GET_CLASS HUD_TYPE_ITEM HudItemPrivate hud_item_get_type
hudmenumodelcollector HudMenuModelCollector hud_menu_model_collector_get HUD_IS_MENU_MODEL_COLLECTOR HUD_MENU_MODEL_COLLECTOR HUD_TYPE_MENU_MODEL_COLLECTOR hud_menu_model_collector_get_type
hudquery HudQuery hud_query_close hud_query_get_generation hud_query_get_n_results hud_query_get_query_key hud_query_get_result_by_index hud_query_lookup hud_query_new HUD_IS_QUERY HUD_QUERY HUD_TYPE_QUERY hud_query_get_type
hudresult HudResult hud_result_get_distance hud_result_get_html_description hud_result_get_if_matched hud_result_get_item hud_result_new HUD_IS_RESULT HUD_RESULT HUD_TYPE_RESULT hud_result_get_type
hudsource HudSource HudSource HudSourceInterface hud_source_changed hud_source_search HUD_IS_SOURCE HUD_SOURCE HUD_SOURCE_GET_IFACE HUD_TYPE_SOURCE hud_source_get_type
hudsourcelist HudSourceList hud_source_list_add hud_source_list_new HUD_IS_SOURCE_LIST HUD_SOURCE_LIST HUD_TYPE_SOURCE_LIST hud_source_list_get_type
hudstringlist HudStringList hud_string_list_cons hud_string_list_cons_label hud_string_list_get_head hud_string_list_get_tail hud_string_list_pretty_print hud_string_list_ref hud_string_list_unref
hud-14.04+14.04.20140604/docs/devel/hud-overview.xml0000644000015301777760000001231012343623451022075 0ustar pbusernogroup00000000000000 Overview The HUD consists of the interface in the shell and a backend service, hud-service. This document attempts to describe the internal architecture of the service. The most important type in the service is HudSource. This is an interface. Each source is an entity against which a search can be performed. There is one interface method: hud_source_search(). This is the main mechanism by which queries are performed in the HUD. The interface also features a signal ::changed that is emitted when the result of searching may have changed. Several implementations of HudSource exist. A particular type of source that gathers possible search results is referred to as a "collector". There are two of these: HudMenuModelCollector (for GDBusMenuModel) and HudDbusmenuCollector for Dbusmenu. These "collector" sources only function when targetted at a particular endpoint (ie: a unique name and object path on D-Bus). This is only useful for searching for items in one particular set of menus. HudWindowSource acts as a multiplexer. It is responsible for determining the currently focused window and performing searches submitted to it against the correct collector for that window. Similarly, there are HudIndicatorSource and HudAppIndicatorSource for performing searches against the system and application indicators, respectively. Finally, there is HudSourceList which functions as a list of multiple other HudSources (such that performing a search against the list gives the combined result of searches performed against each of the contained sources). The hud-service initialises itself by creating the window, indicator and appindicator sources and putting each of them into a HudSourceList. This is the source against which all queries submitted to the service are executed. Collectors are essentially a collection of HudItems. Each item corresponds to an action that may appear in the results of a search made with the HUD. Items have a list of strings describing themselves (eg: ['File', 'Open'] or ['Bluetooth', 'Settings...']) and some information about their origin (eg: the desktop file of the application or indicator that created them). An item can be disabled, in which case it will never appear in the results of a search. Items are activated using hud_item_activate() which is implemented by the collector in the appropriate way. The result of performing a search is a set of HudResults. Each result refers to HudItem along with information about why that item matched, and how closely. The toplevel interface to performing a query is HudQuery. It takes a search string and a reference to a HudSource to search (which, as implemented, is always the toplevel 'list' source). It submits the search to the source then sorts the results by relevence. If the source changes, it resubmits the search. The interface of HudQuery is an ordered sequence of results. HudQuery has its own ::changed signal. hud-service is essentially a simple D-Bus interface corresponding to HudQuery as used against the toplevel source list. New queries can be created using StartQuery. Queries can be destroyed using CloseQuery. HudItems corresponding to results from the query can be activated using ExecuteQuery. Finally, the ::changed signal is reported as the UpdatedQuery D-Bus signal. hud-14.04+14.04.20140604/docs/devel/hud.types0000644000015301777760000000041012343623451020573 0ustar pbusernogroup00000000000000hud_app_indicator_source_get_type hud_app_menu_registrar_get_type hud_dbusmenu_collector_get_type hud_indicator_source_get_type hud_item_get_type hud_menu_model_collector_get_type hud_query_get_type hud_result_get_type hud_source_get_type hud_source_list_get_type hud-14.04+14.04.20140604/docs/libhud-client.msc0000644000015301777760000000103012343623451021054 0ustar pbusernogroup00000000000000msc { shell [label="Unity"], client [label="libhud-client"], hud [label="HUD Service"]; shell => client [label="query_new"]; client => hud [label="CreateQuery"]; client >> shell [label="Query Object"]; hud >> client [label="Query Path"]; client => hud [label="Build Proxy"]; hud -> client [label="Update Models"]; client -> shell [label="Models Ready"]; ---; shell box shell [label="Update Query"]; shell => client [label="Change Query"]; client => hud [label="Change Query"]; hud -> shell [label="Update Models"]; } hud-14.04+14.04.20140604/docs/man/0000755000015301777760000000000012343624372016411 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/docs/man/hud-cli.xml0000644000015301777760000000152012343623451020453 0ustar pbusernogroup00000000000000 hud-cli 1 User Commands hud-cli Tool to exercise the HUD on the command line hud-cli hud-cli search string AUTHOR Written by Ted Gould ted@canonical.com and others. BUGS Bugs should be submitted to Launchpad: hud-14.04+14.04.20140604/docs/man/hud-verify-app-info.xml0000644000015301777760000000154612343623451022727 0ustar pbusernogroup00000000000000 hud-verify-app-info 1 User Commands hud-verify-app-info Tool to verify an app-info file that is expected to be used in the HUD hud-verify-app-info path to app info file AUTHOR Written by Ted Gould ted@canonical.com and others. BUGS Bugs should be submitted to Launchpad: hud-14.04+14.04.20140604/docs/man/hud-dump-application.xml0000644000015301777760000000203712343623451023156 0ustar pbusernogroup00000000000000 hud-dump-application 1 User Commands hud-dump-application Tool to dump information on an application from the HUD usage database hud-dump-application desktop file path AUTHOR Written by Ted Gould ted@canonical.com and others. BUGS Bugs should be submitted to Launchpad: SEE ALSO hud-list-applications 1 hud-14.04+14.04.20140604/docs/man/hud-list-applications.xml0000644000015301777760000000171212343623451023346 0ustar pbusernogroup00000000000000 hud-list-applications 1 User Commands hud-list-applications Tool to list the applications in the HUD usage database hud-list-applications AUTHOR Written by Ted Gould ted@canonical.com and others. BUGS Bugs should be submitted to Launchpad: SEE ALSO hud-dump-application 1 hud-14.04+14.04.20140604/docs/man/CMakeLists.txt0000644000015301777760000000142612343623451021151 0ustar pbusernogroup00000000000000 find_program(XSLTPROC_EXECUTABLE xsltproc) macro(add_manpage name) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.1" COMMAND ${XSLTPROC_EXECUTABLE} -nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl "${CMAKE_CURRENT_SOURCE_DIR}/${name}.xml" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.xml" ) add_custom_target(${name}-man DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${name}.1") add_dependencies(man-pages ${name}-man) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/${name}.1" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1" ) endmacro() add_custom_target(man-pages ALL) add_manpage(hud-cli) add_manpage(hud-dump-application) add_manpage(hud-list-applications) add_manpage(hud-verify-app-info) hud-14.04+14.04.20140604/docs/libhud/0000755000015301777760000000000012343624372017105 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/docs/libhud/libhud-sections.txt0000644000015301777760000000263612343623451022746 0ustar pbusernogroup00000000000000
action-publisher HUD_ACTION_PUBLISHER_SIGNAL_ACTION_GROUP_ADDED HUD_ACTION_PUBLISHER_SIGNAL_ACTION_GROUP_REMOVED HudActionDescription HudActionPublisher HudActionPublisherActionGroupSet hud_action_description_get_action_name hud_action_description_get_action_target hud_action_description_new hud_action_description_ref hud_action_description_set_attribute hud_action_description_set_attribute_value hud_action_description_set_parameterized hud_action_description_unref hud_action_publisher_add_action_group hud_action_publisher_add_description hud_action_publisher_get_action_groups hud_action_publisher_get_description_path hud_action_publisher_get_id hud_action_publisher_new_for_application hud_action_publisher_new_for_id hud_action_publisher_remove_action_group HUD_ACTION_DESCRIPTION HUD_ACTION_PUBLISHER HUD_IS_ACTION_DESCRIPTION HUD_IS_ACTION_PUBLISHER HUD_TYPE_ACTION_DESCRIPTION HUD_TYPE_ACTION_PUBLISHER hud_action_description_get_type hud_action_publisher_get_type
manager HudManager HUD_MANAGER_PROP_APPLICATION HUD_MANAGER_PROP_APP_ID HudManagerClass hud_manager_add_actions hud_manager_new hud_manager_new_for_application hud_manager_remove_actions HUD_IS_MANAGER HUD_IS_MANAGER_CLASS HUD_MANAGER HUD_MANAGER_CLASS HUD_MANAGER_GET_CLASS HUD_TYPE_MANAGER HudManagerPrivate hud_manager_get_type
hud-14.04+14.04.20140604/docs/libhud/libhud-docs.xml0000644000015301777760000000200012343623451022011 0ustar pbusernogroup00000000000000 ]> libhud Docs Data Types Object Hierarchy API Index Index of deprecated API hud-14.04+14.04.20140604/docs/libhud/libhud.types0000644000015301777760000000012312343623451021433 0ustar pbusernogroup00000000000000hud_action_description_get_type hud_action_publisher_get_type hud_manager_get_type hud-14.04+14.04.20140604/docs/libhud/CMakeLists.txt0000644000015301777760000000125412343623451021644 0ustar pbusernogroup00000000000000 find_package(GtkDoc) if(GTKDOC_FOUND) get_target_property(_hud_output_name hud OUTPUT_NAME) include(UseGtkDoc) gtk_doc_add_module(libhud "${CMAKE_SOURCE_DIR}/libhud" XML libhud-docs.xml SUFFIXES h c IGNOREHEADERS hud.h app-iface.h marshal.h service-iface.h LDFLAGS -L${CMAKE_CURRENT_BINARY_DIR}/../../libhud -l${_hud_output_name} LDPATH ${CMAKE_CURRENT_BINARY_DIR}/../../libhud DEPENDS hud ) install( DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/libhud/html/" DESTINATION "${CMAKE_INSTALL_DATADIR}/gtk-doc/html/libhud" ) else() message(STATUS "gtkdoc was not found.") endif() hud-14.04+14.04.20140604/docs/libhud-client/0000755000015301777760000000000012343624372020361 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/docs/libhud-client/libhud-client-docs.xml0000644000015301777760000000204612343623451024553 0ustar pbusernogroup00000000000000 ]> libhud-client Docs Data Types Object Hierarchy API Index Index of deprecated API hud-14.04+14.04.20140604/docs/libhud-client/libhud-client.types0000644000015301777760000000007112343623451024165 0ustar pbusernogroup00000000000000hud_client_query_get_type hud_client_connection_get_type hud-14.04+14.04.20140604/docs/libhud-client/libhud-client-sections.txt0000644000015301777760000000461612343623451025476 0ustar pbusernogroup00000000000000
query HudClientQuery HudClientQueryClass hud_client_query_execute_command hud_client_query_execute_param_command hud_client_query_execute_toolbar_item hud_client_query_get_active_toolbar hud_client_query_get_appstack_model hud_client_query_get_query hud_client_query_get_results_model hud_client_query_new hud_client_query_new_for_connection hud_client_query_toolbar_item_active hud_client_query_set_appstack_app hud_client_query_set_query hud_client_query_voice_query hud_client_query_appstack_get_app_icon hud_client_query_appstack_get_app_id hud_client_query_results_get_command_highlights hud_client_query_results_get_command_id hud_client_query_results_get_command_name hud_client_query_results_get_description hud_client_query_results_get_description_highlights hud_client_query_results_get_shortcut hud_client_query_results_is_parameterized HudClientQueryPrivate HUD_CLIENT_QUERY HUD_CLIENT_QUERY_CLASS HUD_CLIENT_QUERY_GET_CLASS HUD_CLIENT_QUERY_SIGNAL_MODELS_CHANGED HUD_CLIENT_QUERY_SIGNAL_TOOLBAR_UPDATED HUD_CLIENT_TYPE_QUERY HUD_CLIENT_IS_QUERY HUD_CLIENT_IS_QUERY_CLASS hud_client_query_get_type HUD_CLIENT_TYPE_CLIENT_QUERY_TOOLBAR_ITEMS HudClientQueryToolbarItems hud_client_query_toolbar_items_get_nick hud_client_query_toolbar_items_get_type hud_client_query_toolbar_items_get_value_from_nick
connection HudClientConnection HudClientConnectionClass hud_client_connection_connected hud_client_connection_get_address hud_client_connection_get_ref hud_client_connection_new hud_client_connection_new_query HudClientConnectionPrivate HUD_CLIENT_CONNECTION HUD_CLIENT_CONNECTION_CLASS HUD_CLIENT_CONNECTION_GET_CLASS HUD_CLIENT_CONNECTION_SIGNAL_CONNECTION_STATUS HUD_CLIENT_IS_CONNECTION HUD_CLIENT_IS_CONNECTION_CLASS HUD_CLIENT_TYPE_CONNECTION hud_client_connection_get_type HudClientConnectionNewQueryCallback
param HudClientParam HudClientParamClass hud_client_param_get_actions hud_client_param_get_model hud_client_param_new hud_client_param_send_cancel hud_client_param_send_commit hud_client_param_send_reset HUD_CLIENT_IS_PARAM HUD_CLIENT_IS_PARAM_CLASS HUD_CLIENT_PARAM HUD_CLIENT_PARAM_CLASS HUD_CLIENT_PARAM_GET_CLASS HUD_CLIENT_TYPE_PARAM HudClientParamPrivate hud_client_param_get_type HUD_CLIENT_PARAM_SIGNAL_MODEL_READY
hud-14.04+14.04.20140604/docs/libhud-client/CMakeLists.txt0000644000015301777760000000154212343623451023120 0ustar pbusernogroup00000000000000 find_package(GtkDoc) if(GTKDOC_FOUND) get_target_property(_hud_client_output_name hud-client OUTPUT_NAME) include(UseGtkDoc) gtk_doc_add_module(libhud-client "${CMAKE_SOURCE_DIR}/libhud-client" XML libhud-client-docs.xml SUFFIXES h c IGNOREHEADERS HudClient.h HudToolbarModel.h action-muxer.h connection-private.h hud-client.h query-iface.h service-iface.h toolbar-items.h LDFLAGS -L${CMAKE_CURRENT_BINARY_DIR}/../../libhud-client -l${_hud_client_output_name} LDPATH ${CMAKE_CURRENT_BINARY_DIR}/../../libhud-client DEPENDS hud-client ) install( DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/libhud-client/html/" DESTINATION "${CMAKE_INSTALL_DATADIR}/gtk-doc/html/libhud-client" ) else() message(STATUS "gtkdoc was not found.") endif() hud-14.04+14.04.20140604/docs/libhud-gtk/0000755000015301777760000000000012343624372017670 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/docs/libhud-gtk/libhud-gtk-sections.txt0000644000015301777760000000052212343623451024304 0ustar pbusernogroup00000000000000
manager HudGtkManager HudGtkManagerClass hud_gtk_manager_get_publisher hud_gtk_manager_new HUD_GTK_IS_MANAGER HUD_GTK_IS_MANAGER_CLASS HUD_GTK_MANAGER HUD_GTK_MANAGER_CLASS HUD_GTK_MANAGER_GET_CLASS HUD_GTK_TYPE_MANAGER HudGtkManagerPrivate hud_gtk_manager_get_type
hud-14.04+14.04.20140604/docs/libhud-gtk/libhud-gtk.types0000644000015301777760000000003112343623451022777 0ustar pbusernogroup00000000000000hud_gtk_manager_get_type hud-14.04+14.04.20140604/docs/libhud-gtk/libhud-gtk-docs.xml0000644000015301777760000000172212343623451023371 0ustar pbusernogroup00000000000000 ]> libhud-gtk Docs Data Types Object Hierarchy API Index Index of deprecated API hud-14.04+14.04.20140604/docs/libhud-gtk/CMakeLists.txt0000644000015301777760000000123412343623451022425 0ustar pbusernogroup00000000000000 find_package(GtkDoc) if(GTKDOC_FOUND) get_target_property(_hud_output_name hud-gtk OUTPUT_NAME) include(UseGtkDoc) gtk_doc_add_module(libhud-gtk "${CMAKE_SOURCE_DIR}/libhud-gtk" XML libhud-gtk-docs.xml SUFFIXES h c IGNOREHEADERS hud-gtk.h LDFLAGS -L${CMAKE_CURRENT_BINARY_DIR}/../../libhud-gtk -l${_hud_output_name} LDPATH ${CMAKE_CURRENT_BINARY_DIR}/../../libhud-gtk DEPENDS hud-gtk ) install( DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/libhud-gtk/html/" DESTINATION "${CMAKE_INSTALL_DATADIR}/gtk-doc/html/libhud-gtk" ) else() message(STATUS "gtkdoc was not found.") endif() hud-14.04+14.04.20140604/docs/HUD Architecture.svg0000644000015301777760000012624712343623451021413 0ustar pbusernogroup00000000000000 image/svg+xml UnityGUI HUDService BAMF IndicatorAppMenu Text AreaTarget TextSuggestions FocusedWindow Window toMenu mapping Application Window Appmenu Module Actions Menu ModelData Actions Semantics 1 2 3 4 1 2 3 4 Provides the text to describe various commands in a human readable form, referencing the per window variables and which actions should be used. Standard actions for the application that are currently exported. Actions created by the window or the menu model. Descriptions of the actions generated by the appmenu module and the menus. libhud Legacy Apps hud-14.04+14.04.20140604/docs/libhud-communication.msc0000644000015301777760000000077212343623451022457 0ustar pbusernogroup00000000000000msc { app [label="Application"], libhud [label="libHUD"], hud [label="HUD Service"]; app => libhud [label="Initialize"]; libhud => hud [label="Register Application"]; hud >> libhud [label="Application Object Path"]; ---; app box app [label="Put actions on DBus"]; app => libhud [label="Register actions with HUD"]; app => libhud [label="Add descriptions"]; libhud => hud [label="Add to application"]; hud -> app [label="Introspect Actions"]; hud -> app [label="Introspect Descriptions"]; } hud-14.04+14.04.20140604/docs/CMakeLists.txt0000644000015301777760000000043612343623451020376 0ustar pbusernogroup00000000000000include(UseMscgen) add_subdirectory(man) add_subdirectory(libhud) add_subdirectory(libhud-client) add_subdirectory(libhud-gtk) install( FILES "HUD Architecture.svg" DESTINATION ${CMAKE_INSTALL_DOCDIR} ) mscgen(libhud-communication INSTALL) mscgen(libhud-client INSTALL) hud-14.04+14.04.20140604/AUTHORS0000644000015301777760000000003012343623451015744 0ustar pbusernogroup00000000000000# Generate by Makefile hud-14.04+14.04.20140604/README0000644000015301777760000000000012343623451015551 0ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/common/0000755000015301777760000000000012343624372016176 5ustar pbusernogroup00000000000000hud-14.04+14.04.20140604/common/Description.cpp0000644000015301777760000000307312343623451021165 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include using namespace hud::common; QDBusArgument & operator<<(QDBusArgument &argument, const Description &description) { argument.beginStructure(); argument << description.m_windowId << description.m_context << description.m_object; argument.endStructure(); return argument; } const QDBusArgument & operator>>(const QDBusArgument &argument, Description &description) { argument.beginStructure(); argument >> description.m_windowId >> description.m_context >> description.m_object; argument.endStructure(); return argument; } Description::Description() : m_windowId(0) { } Description::~Description() { } void Description::registerMetaTypes() { qRegisterMetaType(); qDBusRegisterMetaType(); qRegisterMetaType>(); qDBusRegisterMetaType>(); } hud-14.04+14.04.20140604/common/DBusTypes.h0000644000015301777760000000351412343623451020231 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * This library 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 Lesser 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 . * * Author: Pete Woods */ #ifndef HUD_COMMON_DBUSTYPES_H_ #define HUD_COMMON_DBUSTYPES_H_ #include #include #include #include #include #include namespace hud { namespace common { class DBusTypes { public: Q_DECL_EXPORT static const QString HUD_SERVICE_DBUS_NAME; Q_DECL_EXPORT static const QString HUD_SERVICE_DBUS_PATH; Q_DECL_EXPORT static const QString WINDOW_STACK_DBUS_NAME; Q_DECL_EXPORT static const QString WINDOW_STACK_DBUS_PATH; Q_DECL_EXPORT static const QString APPMENU_REGISTRAR_DBUS_NAME; Q_DECL_EXPORT static const QString APPMENU_REGISTRAR_DBUS_PATH; Q_DECL_EXPORT static const QString BAMF_DBUS_NAME; Q_DECL_EXPORT static const QString BAMF_MATCHER_DBUS_PATH; Q_DECL_EXPORT static const QString UNITY_VOICE_DBUS_NAME; Q_DECL_EXPORT static const QString UNITY_VOICE_DBUS_PATH; Q_DECL_EXPORT static void registerMetaTypes(); Q_DECL_EXPORT static QString queryPath(unsigned int id); Q_DECL_EXPORT static QString applicationPath(const QString &applicationId); }; } } #endif /* HUD_COMMON_DBUSTYPES_H_ */ hud-14.04+14.04.20140604/common/NameObject.h0000644000015301777760000000304512343623451020355 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_COMMON_NAMEOBJECT_H_ #define HUD_COMMON_NAMEOBJECT_H_ #include #include namespace hud { namespace common { class Q_DECL_EXPORT NameObject { public: explicit NameObject(); explicit NameObject(const QString &name, const QDBusObjectPath &object); explicit NameObject(const NameObject &other); NameObject & operator=(const NameObject &other); bool operator==(const NameObject &other) const; virtual ~NameObject(); static void registerMetaTypes(); QString m_name; QDBusObjectPath m_object; }; } } Q_DECL_EXPORT QDBusArgument &operator<<(QDBusArgument &argument, const hud::common::NameObject &nameObject); Q_DECL_EXPORT const QDBusArgument &operator>>(const QDBusArgument &argument, hud::common::NameObject &nameObject); Q_DECLARE_METATYPE(hud::common::NameObject) #endif /* HUD_COMMON_NAMEOBJECT_H_ */ hud-14.04+14.04.20140604/common/HudDee.h0000644000015301777760000000260012343623451017500 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_COMMON_HUDDEE_H_ #define HUD_COMMON_HUDDEE_H_ #include typedef struct _GVariant GVariant; typedef int (*CompareRowFunc)(GVariant** row1, GVariant** row2, void* user_data); namespace hud { namespace common { class HudDee { public: explicit HudDee(const std::string &resultsName); virtual ~HudDee(); const std::string & name() const; void beginChangeset(); void endChangeset(); protected: void setSchema(const char* const *columnSchemas, unsigned int numColumns); void appendRow(GVariant **row_members); void insertRowSorted(GVariant **row_members, CompareRowFunc cmp_func); class Priv; std::shared_ptr p; }; } } #endif /* HUD_COMMON_HUDDEE_H_ */ hud-14.04+14.04.20140604/common/Description.h0000644000015301777760000000252712343623451020635 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_COMMON_DESCRIPTION_H_ #define HUD_COMMON_DESCRIPTION_H_ #include #include namespace hud { namespace common { class Description { public: Description(); virtual ~Description(); static void registerMetaTypes(); unsigned int m_windowId; QString m_context; QDBusObjectPath m_object; }; } } Q_DECL_EXPORT QDBusArgument &operator<<(QDBusArgument &argument, const hud::common::Description &description); Q_DECL_EXPORT const QDBusArgument &operator>>(const QDBusArgument &argument, hud::common::Description &description); Q_DECLARE_METATYPE(hud::common::Description) #endif /* HUD_COMMON_DESCRIPTION_H_ */ hud-14.04+14.04.20140604/common/DBusTypes.cpp0000644000015301777760000000500512343623451020561 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include #include #include #include #include using namespace hud::common; const QString DBusTypes::HUD_SERVICE_DBUS_NAME("com.canonical.hud"); const QString DBusTypes::HUD_SERVICE_DBUS_PATH("/com/canonical/hud"); const QString DBusTypes::WINDOW_STACK_DBUS_NAME( "com.canonical.Unity.WindowStack"); const QString DBusTypes::WINDOW_STACK_DBUS_PATH( "/com/canonical/Unity/WindowStack"); const QString DBusTypes::APPMENU_REGISTRAR_DBUS_NAME( "com.canonical.AppMenu.Registrar"); const QString DBusTypes::APPMENU_REGISTRAR_DBUS_PATH( "/com/canonical/AppMenu/Registrar"); const QString DBusTypes::BAMF_DBUS_NAME("org.ayatana.bamf"); const QString DBusTypes::BAMF_MATCHER_DBUS_PATH("/org/ayatana/bamf/matcher"); const QString DBusTypes::UNITY_VOICE_DBUS_NAME("com.canonical.Unity.Voice"); const QString DBusTypes::UNITY_VOICE_DBUS_PATH("/com/canonical/Unity/Voice"); void DBusTypes::registerMetaTypes() { NameObject::registerMetaTypes(); Suggestion::registerMetaTypes(); WindowInfo::registerMetaTypes(); Action::registerMetaTypes(); ActionGroup::registerMetaTypes(); Description::registerMetaTypes(); MenuModel::registerMetaTypes(); } QString DBusTypes::queryPath(unsigned int id) { return QString("/com/canonical/hud/query/%1").arg(id); } QString DBusTypes::applicationPath(const QString &applicationId) { QString path("/com/canonical/hud/applications/"); for (const unsigned char &c : applicationId.toUtf8()) { if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) { path.append(c); } else { path.append("_"); path.append(QString().sprintf("%02x", c)); } } return path; } hud-14.04+14.04.20140604/common/WindowInfo.cpp0000644000015301777760000000354712343623451020773 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include using namespace hud::common; QDBusArgument & operator<<(QDBusArgument &a, const WindowInfo &wi) { a.beginStructure(); a << wi.window_id << wi.app_id << wi.focused << wi.stage; a.endStructure(); return a; } const QDBusArgument & operator>>(const QDBusArgument &a, WindowInfo &wi) { a.beginStructure(); uint stage; a >> wi.window_id >> wi.app_id >> wi.focused >> stage; a.endStructure(); wi.stage = static_cast(stage); return a; } WindowInfo::WindowInfo() : window_id(0), focused(false), stage(MAIN) { } WindowInfo::WindowInfo(unsigned int window_id, const QString &app_id, bool focused, Stage stage) : window_id(window_id), app_id(app_id), focused(focused), stage(stage) { } WindowInfo::~WindowInfo() { } bool WindowInfo::operator==(const WindowInfo &other) const { return (window_id == other.window_id) && (app_id == other.app_id) && (focused == other.focused) && (stage == other.stage); } void WindowInfo::registerMetaTypes() { qRegisterMetaType(); qRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); } hud-14.04+14.04.20140604/common/Action.cpp0000644000015301777760000000277312343623451020125 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include using namespace hud::common; QDBusArgument & operator<<(QDBusArgument &argument, const Action &action) { argument.beginStructure(); argument << action.m_windowId << action.m_context << action.m_prefix << action.m_object; argument.endStructure(); return argument; } const QDBusArgument & operator>>(const QDBusArgument &argument, Action &action) { argument.beginStructure(); argument >> action.m_windowId >> action.m_context >> action.m_prefix >> action.m_object; argument.endStructure(); return argument; } Action::Action() : m_windowId(0) { } Action::~Action() { } void Action::registerMetaTypes() { qRegisterMetaType(); qDBusRegisterMetaType(); qRegisterMetaType>(); qDBusRegisterMetaType>(); } hud-14.04+14.04.20140604/common/Suggestion.h0000644000015301777760000000327112343623451020476 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_COMMON_SUGGESTION_H_ #define HUD_COMMON_SUGGESTION_H_ #include #include namespace hud { namespace common { /** * sssssv * Description * Icon * 3 Blanks ?? * ID */ class Q_DECL_EXPORT Suggestion { public: explicit Suggestion(); explicit Suggestion(qulonglong id, const QString &commandName, const QList> &commandHighlights, const QString &description, const QList> &descriptionHighlights, const QString &icon); virtual ~Suggestion(); static void registerMetaTypes(); QString m_description; QString m_icon; QString m_unknown1; QString m_unknown2; QString m_unknown3; QVariant m_id; }; } } Q_DECL_EXPORT QDBusArgument &operator<<(QDBusArgument &argument, const hud::common::Suggestion &suggestion); Q_DECL_EXPORT const QDBusArgument &operator>>(const QDBusArgument &argument, hud::common::Suggestion &suggestion); Q_DECLARE_METATYPE(hud::common::Suggestion) #endif /* HUD_COMMON_SUGGESTION_H_ */ hud-14.04+14.04.20140604/common/Localisation.h0000644000015301777760000000157512343623451020775 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef DAEMON_LOCALISATION_H_ #define DAEMON_LOCALISATION_H_ #include inline char* _(const char *__msgid) { return gettext(__msgid); } #endif // DAEMON_LOCALISATION_H_ hud-14.04+14.04.20140604/common/ActionGroup.cpp0000644000015301777760000000306412343623451021134 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include using namespace hud::common; QDBusArgument & operator<<(QDBusArgument &argument, const ActionGroup &actionGroup) { argument.beginStructure(); argument << QDBusVariant(actionGroup.m_variant) << actionGroup.m_string << actionGroup.m_object; argument.endStructure(); return argument; } const QDBusArgument & operator>>(const QDBusArgument &argument, ActionGroup &actionGroup) { argument.beginStructure(); argument >> actionGroup.m_variant >> actionGroup.m_string >> actionGroup.m_object; argument.endStructure(); return argument; } ActionGroup::ActionGroup() { } ActionGroup::~ActionGroup() { } void ActionGroup::registerMetaTypes() { qRegisterMetaType(); qDBusRegisterMetaType(); qRegisterMetaType>(); qDBusRegisterMetaType>(); } hud-14.04+14.04.20140604/common/HudDee.cpp0000644000015301777760000000347412343623451020045 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include using namespace std; using namespace hud::common; class HudDee::Priv { public: Priv() : m_model(nullptr) { } ~Priv() { g_clear_object(&m_model); } DeeModel *m_model; string m_name; }; HudDee::HudDee(const string &name) : p(new Priv()) { p->m_name = name; p->m_model = dee_shared_model_new(p->m_name.data()); } HudDee::~HudDee() { } const string & HudDee::name() const { return p->m_name; } void HudDee::setSchema(const char* const *columnSchemas, unsigned int numColumns) { dee_model_set_schema_full(p->m_model, columnSchemas, numColumns); } void HudDee::beginChangeset() { dee_model_begin_changeset(p->m_model); dee_model_clear(p->m_model); } void HudDee::appendRow(GVariant **row_members) { dee_model_append_row(p->m_model, row_members); } void HudDee::insertRowSorted(GVariant **row_members, CompareRowFunc cmp_func) { dee_model_insert_row_sorted(p->m_model, row_members, cmp_func, NULL); } void HudDee::endChangeset() { // dee_shared_model_flush_revision_queue(DEE_SHARED_MODEL(p->m_model)); dee_model_end_changeset(p->m_model); } hud-14.04+14.04.20140604/common/NameObject.cpp0000644000015301777760000000373512343623451020716 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include using namespace hud::common; QDBusArgument & operator<<(QDBusArgument &argument, const NameObject &nameObject) { argument.beginStructure(); argument << nameObject.m_name << nameObject.m_object; argument.endStructure(); return argument; } const QDBusArgument & operator>>(const QDBusArgument &argument, NameObject &nameObject) { argument.beginStructure(); argument >> nameObject.m_name >> nameObject.m_object; argument.endStructure(); return argument; } namespace hud { namespace common { NameObject::NameObject() { } NameObject::NameObject(const QString &name, const QDBusObjectPath &object) : m_name(name), m_object(object) { } NameObject::NameObject(const NameObject &other) : m_name(other.m_name), m_object(other.m_object) { } NameObject & NameObject::operator=(const NameObject &other) { m_name = other.m_name; m_object = other.m_object; return *this; } bool NameObject::operator==(const NameObject &other) const { return m_name == other.m_name && m_object == other.m_object; } NameObject::~NameObject() { } void NameObject::registerMetaTypes() { qRegisterMetaType(); qDBusRegisterMetaType(); qRegisterMetaType>(); qDBusRegisterMetaType>(); } } } hud-14.04+14.04.20140604/common/MenuModel.h0000644000015301777760000000251112343623451020230 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_COMMON_MENUMODEL_H_ #define HUD_COMMON_MENUMODEL_H_ #include #include namespace hud { namespace common { class MenuModel { public: MenuModel(); virtual ~MenuModel(); static void registerMetaTypes(); //FIXME Give these proper names QVariant m_variant; QDBusObjectPath m_object; }; } } Q_DECL_EXPORT QDBusArgument &operator<<(QDBusArgument &argument, const hud::common::MenuModel &menuModel); Q_DECL_EXPORT const QDBusArgument &operator>>(const QDBusArgument &argument, hud::common::MenuModel &menuModel); Q_DECLARE_METATYPE(hud::common::MenuModel) #endif /* HUD_COMMON_MENUMODEL_H_ */ hud-14.04+14.04.20140604/common/ResultsModel.h0000644000015301777760000000247112343623451020772 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_COMMON_RESULTSMODEL_H_ #define HUD_COMMON_RESULTSMODEL_H_ #include #include #include #include namespace hud { namespace common { class ResultsModel: public HudDee { public: explicit ResultsModel(unsigned int id); virtual ~ResultsModel(); void setResults(); void addResult(qulonglong id, const QString &command, const QList> &commandHighlights, const QString &description, const QList> &descriptionHighlights, const QString &shortcut, int distance, bool parameterized); }; } } #endif /* HUD_COMMON_RESULTSMODEL_H_ */ hud-14.04+14.04.20140604/common/AppstackModel.cpp0000644000015301777760000000431512343623451021431 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * This library 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 Lesser 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 . * * Author: Pete Woods */ #include #include #include #include using namespace hud::common; const QString APPSTACK_FORMAT_STRING("com.canonical.hud.query%1.appstack"); AppstackModel::AppstackModel(unsigned int id) : HudDee(APPSTACK_FORMAT_STRING.arg(id).toStdString()) { setSchema(appstack_model_schema, G_N_ELEMENTS(appstack_model_schema)); } AppstackModel::~AppstackModel() { } static gint appstack_sort(GVariant **row1, GVariant **row2, gpointer user_data) { Q_UNUSED(user_data); gint32 type1 = g_variant_get_int32(row1[HUD_QUERY_APPSTACK_ITEM_TYPE]); gint32 type2 = g_variant_get_int32(row2[HUD_QUERY_APPSTACK_ITEM_TYPE]); /* If the types are the same, we'll sort by ID */ if (type1 == type2) { const gchar * app_id1 = g_variant_get_string( row1[HUD_QUERY_APPSTACK_APPLICATION_ID], NULL); const gchar * app_id2 = g_variant_get_string( row2[HUD_QUERY_APPSTACK_APPLICATION_ID], NULL); return g_strcmp0(app_id1, app_id2); } return type1 - type2; } void AppstackModel::addApplication(const QString &applicationId, const QString &iconName, ItemType itemType) { GVariant * columns[HUD_QUERY_APPSTACK_COUNT + 1]; columns[HUD_QUERY_APPSTACK_APPLICATION_ID] = g_variant_new_string( applicationId.toUtf8().data()); columns[HUD_QUERY_APPSTACK_ICON_NAME] = g_variant_new_string( iconName.toUtf8().data()); columns[HUD_QUERY_APPSTACK_ITEM_TYPE] = g_variant_new_int32(itemType); columns[HUD_QUERY_APPSTACK_COUNT] = NULL; insertRowSorted(columns, appstack_sort); } hud-14.04+14.04.20140604/common/query-columns.h0000644000015301777760000000516412343623451021175 0ustar pbusernogroup00000000000000/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Ted Gould */ #ifndef __QUERY_COLUMNS_H__ #define __QUERY_COLUMNS_H__ enum _HudQueryResultsColumns { HUD_QUERY_RESULTS_COMMAND_ID = 0, HUD_QUERY_RESULTS_COMMAND_NAME, HUD_QUERY_RESULTS_COMMAND_HIGHLIGHTS, HUD_QUERY_RESULTS_DESCRIPTION, HUD_QUERY_RESULTS_DESCRIPTION_HIGHLIGHTS, HUD_QUERY_RESULTS_SHORTCUT, HUD_QUERY_RESULTS_DISTANCE, HUD_QUERY_RESULTS_PARAMETERIZED, /* Last */ HUD_QUERY_RESULTS_COUNT }; typedef enum _HudQueryResultsColumns HudQueryResultsColumns; #define HUD_QUERY_RESULTS_COMMAND_ID_TYPE "v" #define HUD_QUERY_RESULTS_COMMAND_NAME_TYPE "s" #define HUD_QUERY_RESULTS_COMMAND_HIGHLIGHTS_TYPE "a(ii)" #define HUD_QUERY_RESULTS_DESCRIPTION_TYPE "s" #define HUD_QUERY_RESULTS_DESCRIPTION_HIGHLIGHTS_TYPE "a(ii)" #define HUD_QUERY_RESULTS_SHORTCUT_TYPE "s" #define HUD_QUERY_RESULTS_DISTANCE_TYPE "u" #define HUD_QUERY_RESULTS_PARAMETERIZED_TYPE "b" /* Schema that is used in the DeeModel representing the results */ static const char * results_model_schema[HUD_QUERY_RESULTS_COUNT] = { HUD_QUERY_RESULTS_COMMAND_ID_TYPE, HUD_QUERY_RESULTS_COMMAND_NAME_TYPE, HUD_QUERY_RESULTS_COMMAND_HIGHLIGHTS_TYPE, HUD_QUERY_RESULTS_DESCRIPTION_TYPE, HUD_QUERY_RESULTS_DESCRIPTION_HIGHLIGHTS_TYPE, HUD_QUERY_RESULTS_SHORTCUT_TYPE, HUD_QUERY_RESULTS_DISTANCE_TYPE, HUD_QUERY_RESULTS_PARAMETERIZED_TYPE, }; enum _HudQueryAppstackColumns { HUD_QUERY_APPSTACK_APPLICATION_ID = 0, HUD_QUERY_APPSTACK_ICON_NAME, HUD_QUERY_APPSTACK_ITEM_TYPE, /* Last */ HUD_QUERY_APPSTACK_COUNT }; typedef enum _HudQueryAppstackColumns HudQueryAppstackColumns; #define HUD_QUERY_APPSTACK_APPLICATION_ID_TYPE "s" #define HUD_QUERY_APPSTACK_ICON_NAME_TYPE "s" #define HUD_QUERY_APPSTACK_ITEM_TYPE_TYPE "i" /* Schema that is used in the DeeModel representing the appstack */ static const char * appstack_model_schema[HUD_QUERY_APPSTACK_COUNT] = { HUD_QUERY_APPSTACK_APPLICATION_ID_TYPE, HUD_QUERY_APPSTACK_ICON_NAME_TYPE, HUD_QUERY_APPSTACK_ITEM_TYPE_TYPE, }; #endif /* __QUERY_COLUMNS_H__ */ hud-14.04+14.04.20140604/common/CMakeLists.txt0000644000015301777760000000150112343623451020730 0ustar pbusernogroup00000000000000 ########################### # Hud Common ########################### set(HUD_COMMON_SOURCES AppstackModel.cpp Action.cpp ActionGroup.cpp Description.cpp DBusTypes.cpp HudDee.cpp MenuModel.cpp NameObject.cpp ResultsModel.cpp Suggestion.cpp WindowInfo.cpp ) set_source_files_properties( ${WINDOW_STACK_XML} PROPERTIES INCLUDE "common/WindowInfo.h" ) qt5_add_dbus_interface( HUD_COMMON_SOURCES ${WINDOW_STACK_XML} WindowStackInterface ) set_source_files_properties( ${HUD_APP_XML} PROPERTIES INCLUDE "common/DBusTypes.h" ) qt5_add_dbus_interface( HUD_COMMON_SOURCES ${HUD_APP_XML} ApplicationInterface ) add_library(hud-common STATIC ${HUD_COMMON_SOURCES} ) qt5_use_modules( hud-common Core DBus ) target_link_libraries( hud-common ${GLIB2_LIBRARIES} ${DEE_LIBRARIES} ) hud-14.04+14.04.20140604/common/MenuModel.cpp0000644000015301777760000000273212343623451020570 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include using namespace hud::common; QDBusArgument & operator<<(QDBusArgument &argument, const MenuModel &menuModel) { argument.beginStructure(); argument << QDBusVariant(menuModel.m_variant) << menuModel.m_object; argument.endStructure(); return argument; } const QDBusArgument & operator>>(const QDBusArgument &argument, MenuModel &menuModel) { argument.beginStructure(); argument >> menuModel.m_variant >> menuModel.m_object; argument.endStructure(); return argument; } MenuModel::MenuModel() { } MenuModel::~MenuModel() { } void MenuModel::registerMetaTypes() { qRegisterMetaType(); qDBusRegisterMetaType(); qRegisterMetaType>(); qDBusRegisterMetaType>(); } hud-14.04+14.04.20140604/common/AppstackModel.h0000644000015301777760000000236612343623451021102 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This library is free software; you can redistribute it and/or modify it under * the terms of version 3 of the GNU Lesser General Public License as published * by the Free Software Foundation. * * This library 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 Lesser 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 . * * Author: Pete Woods */ #ifndef HUD_COMMON_APPSTACKMODEL_H_ #define HUD_COMMON_APPSTACKMODEL_H_ #include #include namespace hud { namespace common { class AppstackModel: public HudDee { public: typedef enum { ITEM_TYPE_FOCUSED_APP, ITEM_TYPE_SIDESTAGE_APP, ITEM_TYPE_BACKGROUND_APP, ITEM_TYPE_INDICATOR } ItemType; explicit AppstackModel(unsigned int id); virtual ~AppstackModel(); void addApplication(const QString &applicationId, const QString &iconName, ItemType itemType); protected: }; } } #endif /* HUD_COMMON_APPSTACKMODEL_H_ */ hud-14.04+14.04.20140604/common/WindowInfo.h0000644000015301777760000000314012343623451020425 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_COMMON_WINDOWINFO_H_ #define HUD_COMMON_WINDOWINFO_H_ #include #include namespace hud { namespace common { class WindowInfo { public: enum Stage { MAIN, SIDE, WINDOWED }; unsigned int window_id; QString app_id; bool focused; unsigned int stage; explicit WindowInfo(); explicit WindowInfo(unsigned int window_id, const QString &app_id, bool focused, Stage stage = MAIN); virtual ~WindowInfo(); bool operator==(const WindowInfo &other) const; static void registerMetaTypes(); }; typedef QList WindowInfoList; } } Q_DECL_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const hud::common::WindowInfo &aidf); Q_DECL_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, hud::common::WindowInfo &aidf); Q_DECLARE_METATYPE(hud::common::WindowInfo) Q_DECLARE_METATYPE(hud::common::WindowInfoList) #endif /* HUD_COMMON_WINDOWINFO_H_ */ hud-14.04+14.04.20140604/common/ResultsModel.cpp0000644000015301777760000000572312343623451021330 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include const QString RESULTS_FORMAT_STRING("com.canonical.hud.query%1.results"); using namespace hud::common; ResultsModel::ResultsModel(unsigned int id) : HudDee(RESULTS_FORMAT_STRING.arg(id).toStdString()) { setSchema(results_model_schema, G_N_ELEMENTS(results_model_schema)); } ResultsModel::~ResultsModel() { } void ResultsModel::addResult(qulonglong id, const QString &commandName, const QList> &commandHighlights, const QString &description, const QList> &descriptionHighlights, const QString &shortcut, int distance, bool parameterized) { GVariant *actionh = NULL; if (commandHighlights.isEmpty()) { actionh = g_variant_new_array(G_VARIANT_TYPE("(ii)"), NULL, 0); } else { GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE("a(ii)")); for (const QPair &highlight : commandHighlights) { g_variant_builder_add(&builder, "(ii)", highlight.first, highlight.second); } actionh = g_variant_builder_end(&builder); } GVariant *desch = NULL; if (descriptionHighlights.isEmpty()) { desch = g_variant_new_array(G_VARIANT_TYPE("(ii)"), NULL, 0); } else { GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE("a(ii)")); for (const QPair &highlight : descriptionHighlights) { g_variant_builder_add(&builder, "(ii)", highlight.first, highlight.second); } desch = g_variant_builder_end(&builder); } GVariant *columns[HUD_QUERY_RESULTS_COUNT + 1]; columns[HUD_QUERY_RESULTS_COMMAND_ID] = g_variant_new_variant( g_variant_new_uint64(id)); columns[HUD_QUERY_RESULTS_COMMAND_NAME] = g_variant_new_string( commandName.toUtf8().data()); columns[HUD_QUERY_RESULTS_COMMAND_HIGHLIGHTS] = actionh; columns[HUD_QUERY_RESULTS_DESCRIPTION] = g_variant_new_string( description.toUtf8().data()); columns[HUD_QUERY_RESULTS_DESCRIPTION_HIGHLIGHTS] = desch; columns[HUD_QUERY_RESULTS_SHORTCUT] = g_variant_new_string( shortcut.toUtf8().data()); columns[HUD_QUERY_RESULTS_DISTANCE] = g_variant_new_uint32(distance); columns[HUD_QUERY_RESULTS_PARAMETERIZED] = g_variant_new_boolean( parameterized); columns[HUD_QUERY_RESULTS_COUNT] = NULL; appendRow(columns); } hud-14.04+14.04.20140604/common/Suggestion.cpp0000644000015301777760000000765012343623451021036 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #include #include #include #include #include using namespace hud::common; QDBusArgument & operator<<(QDBusArgument &argument, const Suggestion &suggestion) { argument.beginStructure(); argument << suggestion.m_description << suggestion.m_icon << suggestion.m_unknown1 << suggestion.m_unknown2 << suggestion.m_unknown3 << QDBusVariant(suggestion.m_id); argument.endStructure(); return argument; } const QDBusArgument & operator>>(const QDBusArgument &argument, Suggestion &suggestion) { argument.beginStructure(); argument >> suggestion.m_description >> suggestion.m_icon >> suggestion.m_unknown1 >> suggestion.m_unknown2 >> suggestion.m_unknown3 >> suggestion.m_id; argument.endStructure(); return argument; } static void append(QString &result, const QString& input, int start, int end) { QStringRef substring(input.midRef(start, end)); char *temp = g_markup_escape_text(substring.toUtf8().data(), -1); result.append(temp); g_free(temp); } /** * Builds a single line pango formatted description for * the legacy HUD UI. */ static QString buildLegacyHighlights(const QString &input, const QList> &highlights) { QString result; int current(0); for (const QPair &pair : highlights) { int start(pair.first); int stop(pair.second); // In theory there should be no overlapping, but we // want to make sure if (start < current) { qWarning() << "Overlapping highlighting. At character" << current << "and asked to highlight from" << start << "to" << stop; continue; } // Get to the start of the highlight int initialSkip = start - current; if (initialSkip > 0) { append(result, input, current, initialSkip); } result.append(""); // Copy the characters in the highlight int highlightSkip = stop - start; if (highlightSkip > 0) { append(result, input, start, highlightSkip); } else { qWarning() << "Zero character highlight!"; } result.append(""); current = stop; } int remaining(input.length() - current); if (remaining > 0) { append(result, input, current, remaining); } return result; } Suggestion::Suggestion() { } Suggestion::Suggestion(qulonglong id, const QString &commandName, const QList> &commandHighlights, const QString &description, const QList> &descriptionHighlights, const QString &icon) : m_icon(icon), m_id(id) { if (description.isEmpty()) { m_description = buildLegacyHighlights(commandName, commandHighlights); } else { QString cmdHighlights( buildLegacyHighlights(commandName, commandHighlights)); QString descHighlights( buildLegacyHighlights(description, descriptionHighlights)); // TRANSLATORS: This is what is shown for Unity7 in // the HUD entries. %1 is the command name and %2 is a // description or list of keywords that // was used to find the entry. m_description = QString(_("%1\xE2\x80\x82(%2)")).arg(cmdHighlights, descHighlights); } } Suggestion::~Suggestion() { } void Suggestion::registerMetaTypes() { qRegisterMetaType(); qDBusRegisterMetaType(); qRegisterMetaType>(); qDBusRegisterMetaType>(); } hud-14.04+14.04.20140604/common/ActionGroup.h0000644000015301777760000000256312343623451020604 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_COMMON_ACTIONGROUP_H_ #define HUD_COMMON_ACTIONGROUP_H_ #include #include namespace hud { namespace common { class ActionGroup { public: ActionGroup(); virtual ~ActionGroup(); static void registerMetaTypes(); //FIXME Give these proper names QVariant m_variant; QString m_string; QDBusObjectPath m_object; }; } } Q_DECL_EXPORT QDBusArgument &operator<<(QDBusArgument &argument, const hud::common::ActionGroup &actionGroup); Q_DECL_EXPORT const QDBusArgument &operator>>(const QDBusArgument &argument, hud::common::ActionGroup &actionGroup); Q_DECLARE_METATYPE(hud::common::ActionGroup) #endif /* HUD_COMMON_ACTIONGROUP_H_ */ hud-14.04+14.04.20140604/common/shared-values.h0000644000015301777760000000166212343623451021114 0ustar pbusernogroup00000000000000/* Values that we share between the various objects Copyright 2011 Canonical Ltd. Authors: Ted Gould This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef SHARED_VALUES_H__ #define SHARED_VALUES_H__ #define DBUS_NAME "com.canonical.hud" #define DBUS_PATH "/com/canonical/hud" #define DBUS_IFACE "com.canonical.hud" #define DB_SEPARATOR "||" #endif /* SHARED_VALUES_H__ */ hud-14.04+14.04.20140604/common/Action.h0000644000015301777760000000246412343623451017567 0ustar pbusernogroup00000000000000/* * Copyright (C) 2013 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Pete Woods */ #ifndef HUD_COMMON_ACTION_H_ #define HUD_COMMON_ACTION_H_ #include #include namespace hud { namespace common { class Action { public: Action(); virtual ~Action(); static void registerMetaTypes(); unsigned int m_windowId; QString m_context; QString m_prefix; QDBusObjectPath m_object; }; } } Q_DECL_EXPORT QDBusArgument &operator<<(QDBusArgument &argument, const hud::common::Action &action); Q_DECL_EXPORT const QDBusArgument &operator>>(const QDBusArgument &argument, hud::common::Action &action); Q_DECLARE_METATYPE(hud::common::Action) #endif /* HUD_COMMON_ACTION_H_ */