hud-14.10+17.10.20170619/0000775000175000017500000000000013121716557015311 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tools-vala/0000775000175000017500000000000013121716557017372 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tools-vala/hud-gtk.vala0000664000175000017500000001377313121713174021605 0ustar didrocksdidrocks00000000000000extern 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); #if VALA_0_36 model.remove(ref iter); #else model.remove(iter); #endif } 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); #if VALA_0_36 appstack_model.remove(ref iter); #else appstack_model.remove(iter); #endif } 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.10+17.10.20170619/tools-vala/CMakeLists.txt0000664000175000017500000000314313121713174022123 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/tools-vala/hud-gtk.ui0000664000175000017500000002147713121713174021277 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/common/0000775000175000017500000000000013121716557016601 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/common/ActionGroup.cpp0000664000175000017500000000306413121713174021532 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/ActionGroup.h0000664000175000017500000000256313121713174021202 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/WindowInfo.cpp0000664000175000017500000000354713121713174021371 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/AppstackModel.h0000664000175000017500000000236613121713174021500 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/Description.h0000664000175000017500000000252713121713174021233 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/HudDee.h0000664000175000017500000000260013121713174020076 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/NameObject.cpp0000664000175000017500000000373513121713174021314 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/WindowInfo.h0000664000175000017500000000314013121713174021023 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/ResultsModel.h0000664000175000017500000000247113121713174021370 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/shared-values.h0000664000175000017500000000166213121713174021512 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/common/HudDee.cpp0000664000175000017500000000347413121713174020443 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/GDBusHelper.h0000664000175000017500000000330713121713174021051 0ustar didrocksdidrocks00000000000000/* * Copyright (C) 2015 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 COMMON_GDBUSHELPER_H_ #define COMMON_GDBUSHELPER_H_ #include static inline GDBusConnection * newSessionBusConnection(GCancellable* cancellable) { GError *error = NULL; gchar *address = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SESSION, NULL, &error); if (!address) { g_assert(error != NULL); if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_CANCELLED) { } g_error_free(error); return NULL; } error = NULL; GDBusConnection* connection = g_dbus_connection_new_for_address_sync(address, (GDBusConnectionFlags) (G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), NULL, cancellable, &error); g_free(address); if (connection == NULL) { g_assert(error != NULL); if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_CANCELLED) { } g_error_free(error); return NULL; } g_dbus_connection_set_exit_on_close(connection, FALSE); return connection; } #endif // COMMON_GDBUSHELPER_H_ hud-14.10+17.10.20170619/common/Suggestion.h0000664000175000017500000000327113121713174021074 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/ResultsModel.cpp0000664000175000017500000000572313121713174021726 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/Action.h0000664000175000017500000000246413121713174020165 0ustar didrocksdidrocks00000000000000/* * 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_ */ hud-14.10+17.10.20170619/common/DBusTypes.h0000664000175000017500000000351413121713174020627 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/query-columns.h0000664000175000017500000000516413121713174021573 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/CMakeLists.txt0000664000175000017500000000150113121713174021326 0ustar didrocksdidrocks00000000000000 ########################### # 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.10+17.10.20170619/common/NameObject.h0000664000175000017500000000304513121713174020753 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/Action.cpp0000664000175000017500000000277313121713174020523 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/AppstackModel.cpp0000664000175000017500000000431513121713174022027 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/DBusTypes.cpp0000664000175000017500000000455113121713174021164 0ustar didrocksdidrocks00000000000000/* * 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"); 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.10+17.10.20170619/common/MenuModel.cpp0000664000175000017500000000273213121713174021166 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/Suggestion.cpp0000664000175000017500000000765013121713174021434 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/Localisation.h0000664000175000017500000000157513121713174021373 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/Description.cpp0000664000175000017500000000307313121713174021563 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/common/MenuModel.h0000664000175000017500000000251113121713174020626 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/0000775000175000017500000000000013121716557016751 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/service/WindowContext.cpp0000664000175000017500000000151713121713174022265 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/QueryImpl.h0000664000175000017500000000576513121713174021056 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/QGSettingsSearchSettings.cpp0000664000175000017500000000300513121713174024342 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/Voice.cpp0000664000175000017500000000146313121713174020516 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/VoiceImpl.h0000664000175000017500000000212013121713174020774 0ustar didrocksdidrocks00000000000000/* * 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 namespace hud { namespace service { class VoiceImpl: public Voice { Q_OBJECT public: explicit VoiceImpl(); virtual ~VoiceImpl(); QString listen(const QList& commands) override; private: }; } // namespace service } // namespace hud #endif // HUD_SERVICE_VOICEIMPL_H_ hud-14.10+17.10.20170619/service/ApplicationListImpl.cpp0000664000175000017500000001222013121713174023363 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/ItemStore.h0000664000175000017500000000474113121713174021033 0ustar didrocksdidrocks00000000000000/* * 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; QMap m_mnemonic2DocumentId; }; } } #endif /* HUD_SERVICE_ITEMSTORE_H_ */ hud-14.10+17.10.20170619/service/WindowImpl.cpp0000664000175000017500000000712413121713174021542 0ustar didrocksdidrocks00000000000000/* * 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.newDBusMenuWindowCollector(windowId); 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.10+17.10.20170619/service/Collector.cpp0000664000175000017500000000220213121713174021367 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/DBusMenuWindowCollector.h0000664000175000017500000000403613121713174023636 0ustar didrocksdidrocks00000000000000/* * Copyright (C) 2016 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: Andrea Azzarone */ #ifndef HUD_SERVICE_DBUSMENUWINDOWCOLLECTOR_H_ #define HUD_SERVICE_DBUSMENUWINDOWCOLLECTOR_H_ #include class ComCanonicalAppMenuRegistrarInterface; class ComCanonicalUnityWindowStackInterface; namespace qtgmenu { class QtGMenuImporter; } namespace hud { namespace service { class Factory; class DBusMenuWindowCollector: public Collector, public std::enable_shared_from_this { Q_OBJECT public: typedef std::shared_ptr Ptr; DBusMenuWindowCollector(unsigned int windowId, QSharedPointer windowStack, QSharedPointer registrar, Factory &factory); virtual ~DBusMenuWindowCollector(); 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() override; private: void windowRegistered(const QString &service, const QDBusObjectPath &menuObjectPath); Collector::Ptr m_am_collector; Collector::Ptr m_collector; unsigned int m_windowId; QSharedPointer m_registrar; Factory &m_factory; }; } } #endif /* HUD_SERVICE_DBUSMENUWINDOWCOLLECTOR_H_ */ hud-14.10+17.10.20170619/service/DBusMenuCollector.h0000664000175000017500000000332413121713174022445 0ustar didrocksdidrocks00000000000000/* * Copyright (C) 2013-2016 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 * Andrea Azzarone */ #ifndef HUD_SERVICE_DBUSMENUCOLLECTOR_H_ #define HUD_SERVICE_DBUSMENUCOLLECTOR_H_ #include #include class DBusMenuImporter; QT_BEGIN_NAMESPACE class QMenu; QT_END_NAMESPACE namespace hud { namespace service { class DBusMenuCollector: public Collector, public std::enable_shared_from_this { public: typedef std::shared_ptr Ptr; DBusMenuCollector(const QString &service, const QDBusObjectPath &menuObjectPath); virtual ~DBusMenuCollector(); virtual bool isValid() const override; virtual QList activate() override; protected: virtual void deactivate() override; void openMenu(QMenu *menu, unsigned int &limit); void hideMenu(QMenu *menu, unsigned int &limit); QWeakPointer m_collectorToken; QSharedPointer m_menuImporter; QString m_service; QDBusObjectPath m_path; }; } } #endif /* HUD_SERVICE_DBUSMENUCOLLECTOR_H_ */ hud-14.10+17.10.20170619/service/GMenuWindowCollector.h0000664000175000017500000000323513121713174023167 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/UsageTracker.h0000664000175000017500000000237713121713174021503 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/SignalHandler.cpp0000664000175000017500000000524013121713174022161 0ustar didrocksdidrocks00000000000000/* * 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, Qt::QueuedConnection); m_socketNotifierTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, this); connect(m_socketNotifierTerm, &QSocketNotifier::activated, this, &SignalHandler::handleSigTerm, Qt::QueuedConnection); } 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.10+17.10.20170619/service/Query.cpp0000664000175000017500000000151213121713174020551 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/ApplicationList.cpp0000664000175000017500000000153113121713174022544 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/Voice.h0000664000175000017500000000232013121713174020154 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/GMenuWindowCollector.cpp0000664000175000017500000000655113121713174023526 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/Window.h0000664000175000017500000000354413121713174020367 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/QGSettingsSearchSettings.h0000664000175000017500000000235313121713174024014 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/Result.cpp0000664000175000017500000000361513121713174020730 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/Window.cpp0000664000175000017500000000155513121713174020722 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/WindowImpl.h0000664000175000017500000000466113121713174021212 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/HudServiceImpl.cpp0000664000175000017500000001342713121713174022337 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/WindowContext.h0000664000175000017500000000351213121713174021727 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/QueryImpl.cpp0000664000175000017500000001644513121713174021406 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/HardCodedSearchSettings.cpp0000664000175000017500000000336313121713174024136 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/WindowContextImpl.h0000664000175000017500000000270313121713174022552 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/ItemStore.cpp0000664000175000017500000002341413121713174021364 0ustar didrocksdidrocks00000000000000/* * 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("&&", "&"); } static QChar getMnemonic(const QAction *action) { int ampersandIndex = action->text().indexOf(SINGLE_AMPERSAND); if (ampersandIndex < 0 || ampersandIndex >= action->text().length() - 1) { return 0; } return action->text()[ampersandIndex+1].toLower(); } 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; } bool searchByMnemonic(action->property("searchByMnemonic").toBool()); 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); if (searchByMnemonic) { QChar mnemonic = getMnemonic(action); m_mnemonic2DocumentId[mnemonic] = 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()); if (queryLength == 1 && m_mnemonic2DocumentId.contains(query[0])) { int docId = m_mnemonic2DocumentId[query[0]]; addResult(docId, stringMatcher, queryLength, 1.0, results); } 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.10+17.10.20170619/service/Item.h0000664000175000017500000000224113121713174020007 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/SignalHandler.h0000664000175000017500000000254513121713174021633 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/DBusMenuWindowCollector.cpp0000664000175000017500000000752213121713174024174 0ustar didrocksdidrocks00000000000000/* * Copyright (C) 2016 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: Andrea Azzarone */ #include #include #include #include #include #include using namespace hud::common; using namespace hud::service; DBusMenuWindowCollector::DBusMenuWindowCollector(unsigned int windowId, QSharedPointer windowStack, QSharedPointer registrar, Factory &factory) : m_windowId(windowId), m_registrar(registrar), m_factory(factory) { connect(registrar.data(), SIGNAL(WindowRegistered(uint, const QString &, const QDBusObjectPath &)), this, SLOT(WindowRegistered(uint, const QString &, const QDBusObjectPath &))); QDBusPendingReply windowDBusAddressReply( windowStack->GetWindowBusAddress(windowId)); // Window action menu windowDBusAddressReply.waitForFinished(); if (!windowDBusAddressReply.isError()) { QStringList windowDBusAddress(windowDBusAddressReply); if (windowDBusAddress.size() == 2) { const QString &name = windowDBusAddress.at(0); const QString &path = windowDBusAddress.at(1); if (!name.isEmpty() && !path.isEmpty()) m_am_collector = factory.newDBusMenuCollector(name, QDBusObjectPath(path)); } } // AppMenu QDBusPendingReply windowReply = registrar->GetMenuForWindow(m_windowId); windowReply.waitForFinished(); if (windowReply.isError()) { return; } windowRegistered(windowReply.argumentAt<0>(), windowReply.argumentAt<1>()); } DBusMenuWindowCollector::~DBusMenuWindowCollector() { } bool DBusMenuWindowCollector::isValid() const { return m_collector || m_am_collector; } static void setPropertyForAllActions(QMenu *menu) { if (!menu) return; for (QAction *action : menu->actions()) { if (!action->isEnabled()) { continue; } if (action->isSeparator()) { continue; } action->setProperty("searchByMnemonic", true); setPropertyForAllActions(action->menu()); } } QList DBusMenuWindowCollector::activate() { QList ret; if (m_am_collector) { QList tokens = m_am_collector->activate(); for (CollectorToken::Ptr token : tokens) { setPropertyForAllActions(token->menu()); } ret.append(tokens); } if (m_collector) { ret.append(m_collector->activate()); } return ret; } void DBusMenuWindowCollector::deactivate() { } void DBusMenuWindowCollector::WindowRegistered(uint windowId, const QString &service, const QDBusObjectPath &menuObjectPath) { // Simply ignore updates for other windows if (windowId != m_windowId) { return; } windowRegistered(service, menuObjectPath); } void DBusMenuWindowCollector::windowRegistered(const QString &service, const QDBusObjectPath &menuObjectPath) { if (service.isEmpty()) { return; } disconnect(m_registrar.data(), SIGNAL(WindowRegistered(uint, const QString &, const QDBusObjectPath &)), this, SLOT(WindowRegistered(uint, const QString &, const QDBusObjectPath &))); m_collector = m_factory.newDBusMenuCollector(service, menuObjectPath); } hud-14.10+17.10.20170619/service/ApplicationListImpl.h0000664000175000017500000000466513121713174023046 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/SqliteUsageTracker.cpp0000664000175000017500000001000213121713174023200 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/CMakeLists.txt0000664000175000017500000000400113121713174021474 0ustar didrocksdidrocks00000000000000 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 DBusMenuWindowCollector.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} ${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.10+17.10.20170619/service/WindowContextImpl.cpp0000664000175000017500000000312313121713174023102 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/HudServiceImpl.h0000664000175000017500000000521313121713174021776 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/Item.cpp0000664000175000017500000000376313121713174020354 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/ApplicationList.h0000664000175000017500000000271613121713174022217 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/HudService.h0000664000175000017500000000226413121713174021157 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/VoiceImpl.cpp0000664000175000017500000000162413121713174021337 0ustar didrocksdidrocks00000000000000/* * 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() { } VoiceImpl::~VoiceImpl() { } QString VoiceImpl::listen(const QList&) { return QString(); } hud-14.10+17.10.20170619/service/SqliteUsageTracker.h0000664000175000017500000000306513121713174022660 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/SearchSettings.cpp0000664000175000017500000000152513121713174022376 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/main.cpp0000664000175000017500000000252613121713174020376 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/Factory.cpp0000664000175000017500000001374413121713174021065 0ustar didrocksdidrocks00000000000000/* * 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 #include using namespace hud::common; using namespace hud::service; Factory::Factory() : m_sessionBus(QDBusConnection::sessionBus()), m_queryCounter(0) { DBusTypes::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; } QSharedPointer Factory::gSessionBus() { return QSharedPointer(g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr), &g_object_unref); } 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()) { m_voice.reset(new VoiceImpl()); } 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(const QString &service, const QDBusObjectPath &menuObjectPath) { return Collector::Ptr(new DBusMenuCollector(service, menuObjectPath)); } Collector::Ptr Factory::newGMenuCollector(const QString &name, const QMap &actions, const QDBusObjectPath &menuPath) { return Collector::Ptr(new GMenuCollector(name, actions, menuPath, *this)); } QSharedPointer Factory::newQtGMenuImporter( const QString& service, const QDBusObjectPath& menu_path, const QMap& action_paths) { return QSharedPointer( new qtgmenu::QtGMenuImporter(service, menu_path, action_paths, sessionBus(), gSessionBus())); } Collector::Ptr Factory::newGMenuWindowCollector(unsigned int windowId, const QString &applicationId) { return Collector::Ptr( new GMenuWindowCollector(windowId, applicationId, singletonWindowStack(), *this)); } Collector::Ptr Factory::newDBusMenuWindowCollector(unsigned int windowId) { return Collector::Ptr( new DBusMenuWindowCollector(windowId, singletonWindowStack(), singletonAppmenu(), *this)); } hud-14.10+17.10.20170619/service/Application.h0000664000175000017500000000277513121713174021370 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/GMenuCollector.cpp0000664000175000017500000000405413121713174022332 0ustar didrocksdidrocks00000000000000/* * 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; GMenuCollector::GMenuCollector(const QString &name, const QMap &actions, const QDBusObjectPath &menuPath, Factory& factory) : m_name(name), m_actions(actions), m_menuPath(menuPath) { m_importer = factory.newQtGMenuImporter(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.10+17.10.20170619/service/HardCodedSearchSettings.h0000664000175000017500000000265713121713174023610 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/Result.h0000664000175000017500000000340513121713174020372 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/ApplicationImpl.cpp0000664000175000017500000001240113121713174022530 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/Collector.h0000664000175000017500000000320713121713174021042 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/SearchSettings.h0000664000175000017500000000235613121713174022046 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/UsageTracker.cpp0000664000175000017500000000151213121713174022024 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/GMenuCollector.h0000664000175000017500000000340413121713174021775 0ustar didrocksdidrocks00000000000000/* * 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 Factory; 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, Factory& factory); 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; QSharedPointer m_importer; std::shared_ptr m_menu; }; } } #endif /* HUD_SERVICE_GMENUCOLLECTOR_H_ */ hud-14.10+17.10.20170619/service/Query.h0000664000175000017500000000357613121713174020232 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/HudService.cpp0000664000175000017500000000154413121713174021512 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/ApplicationImpl.h0000664000175000017500000000526613121713174022210 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/Application.cpp0000664000175000017500000000164313121713174021714 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/service/DBusMenuCollector.cpp0000664000175000017500000000652013121713174023001 0ustar didrocksdidrocks00000000000000/* * Copyright (C) 2013-2016 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 * Andrea Azzarone */ #include #include #include #include #include using namespace hud::service; DBusMenuCollector::DBusMenuCollector(const QString &service, const QDBusObjectPath &menuObjectPath) : m_service(service), m_path(menuObjectPath) { if (m_service.isEmpty()) { return; } m_menuImporter.reset( new DBusMenuImporter(m_service, m_path.path(), DBusMenuImporterType::SYNCHRONOUS)); CollectorToken::Ptr collectorToken(m_collectorToken); if(collectorToken) { collectorToken->changed(); } } DBusMenuCollector::~DBusMenuCollector() { } 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(); } } hud-14.10+17.10.20170619/service/Factory.h0000664000175000017500000000724713121713174020533 0ustar didrocksdidrocks00000000000000/* * 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 #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 gSessionBus(); 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(const QString &service, const QDBusObjectPath &menuObjectPath); virtual Collector::Ptr newGMenuCollector(const QString &name, const QMap &actions, const QDBusObjectPath &menuPath); QSharedPointer newQtGMenuImporter( const QString& service, const QDBusObjectPath& menu_path, const QMap& action_paths); virtual Collector::Ptr newGMenuWindowCollector(unsigned int windowId, const QString &applicationId); virtual Collector::Ptr newDBusMenuWindowCollector(unsigned int windowId); 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.10+17.10.20170619/COPYING0000664000175000017500000010437413121713174016345 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/libqtgmenu/0000775000175000017500000000000013121716557017460 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/libqtgmenu/QtGMenuExporter.h0000664000175000017500000000244513121713174022677 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libqtgmenu/QtGMenuExporter.cpp0000664000175000017500000000211413121713174023223 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libqtgmenu/QtGMenuImporter.h0000664000175000017500000000441313121713174022665 0ustar didrocksdidrocks00000000000000/* * 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 #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, const QDBusConnection& connection, QSharedPointer, QObject* parent = 0 ); QtGMenuImporter( const QString& service, const QDBusObjectPath& menu_path, const QMap& action_paths, const QDBusConnection& connection, QSharedPointer, 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.10+17.10.20170619/libqtgmenu/CMakeLists.txt0000664000175000017500000000043513121713174022212 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/libqtgmenu/QtGMenuImporter.cpp0000664000175000017500000000441613121713174023223 0ustar didrocksdidrocks00000000000000/* * 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, const QDBusConnection& connection, QSharedPointer gconnection, QObject* parent ) : QObject( parent ) { QMap action_paths; action_paths[action_prefix] = action_path; d.reset( new QtGMenuImporterPrivate( service, menu_path, action_paths, *this, connection, gconnection ) ); } QtGMenuImporter::QtGMenuImporter( const QString& service, const QDBusObjectPath& menu_path, const QMap& action_paths, const QDBusConnection& connection, QSharedPointer gconnection, QObject* parent ) : QObject( parent ), d( new QtGMenuImporterPrivate( service, menu_path, action_paths, *this, connection, gconnection ) ) { } 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.10+17.10.20170619/libqtgmenu/internal/0000775000175000017500000000000013121716557021274 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/libqtgmenu/internal/QtGMenuModel.cpp0000664000175000017500000005145313121713174024301 0ustar didrocksdidrocks00000000000000/* * 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 int MAX_NUM_CHILDREN = 100; 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 = std::min( MAX_NUM_CHILDREN, 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, 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; } // Limit the menus exported to avoid memory wastage if ( m_size + (added - removed) > MAX_NUM_CHILDREN ) { added = MAX_NUM_CHILDREN - (m_size - removed); } // 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.10+17.10.20170619/libqtgmenu/internal/QtGActionGroup.cpp0000664000175000017500000001552213121713174024643 0ustar didrocksdidrocks00000000000000/* * 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 ) ) { g_action_group_activate_action( m_action_group.data(), action_utf.constData(), g_variant_new_string( action_utf.constData() ) ); } } } 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.10+17.10.20170619/libqtgmenu/internal/CMakeLists.txt0000664000175000017500000000061013121713174024021 0ustar didrocksdidrocks00000000000000set( 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.10+17.10.20170619/libqtgmenu/internal/QtGMenuModel.h0000664000175000017500000000746013121713174023745 0ustar didrocksdidrocks00000000000000/* * 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, 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.10+17.10.20170619/libqtgmenu/internal/QtGMenuUtils.cpp0000664000175000017500000001550013121713174024332 0ustar didrocksdidrocks00000000000000/* * 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.mid( index + 1 )); } } hud-14.10+17.10.20170619/libqtgmenu/internal/QtGMenuImporterPrivate.cpp0000664000175000017500000001360413121713174026371 0ustar didrocksdidrocks00000000000000/* * 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 qtgmenu; QtGMenuImporterPrivate::QtGMenuImporterPrivate( const QString& service, const QDBusObjectPath& menu_path, const QMap& action_paths, QtGMenuImporter& parent, const QDBusConnection& connection, QSharedPointer gconnection) : QObject( 0 ), m_service_watcher( service, connection, QDBusServiceWatcher::WatchForOwnerChange ), m_parent( parent ), m_connection ( gconnection ), 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.10+17.10.20170619/libqtgmenu/internal/QtGMenuUtils.h0000664000175000017500000000225213121713174023777 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libqtgmenu/internal/QtGMenuImporterPrivate.h0000664000175000017500000000440513121713174026035 0ustar didrocksdidrocks00000000000000/* * 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, const QDBusConnection& connection, QSharedPointer gconnection); 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.10+17.10.20170619/libqtgmenu/internal/QtGActionGroup.h0000664000175000017500000000474613121713174024316 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud/0000775000175000017500000000000013121716557016560 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/libhud/libhud.map0000664000175000017500000000004013121713174020510 0ustar didrocksdidrocks00000000000000{ global: hud_*; local: *; }; hud-14.10+17.10.20170619/libhud/action-publisher.c0000664000175000017500000006500213121713174022167 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud/action-publisher.h0000664000175000017500000002054613121713174022200 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud/manager.h0000664000175000017500000000757313121713174020347 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud/hud.pc.in0000664000175000017500000000033613121713174020263 0ustar didrocksdidrocks00000000000000libdir=@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.10+17.10.20170619/libhud/CMakeLists.txt0000664000175000017500000000751413121713174021317 0ustar didrocksdidrocks00000000000000 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" ) set_target_properties(hud PROPERTIES LINK_FLAGS "${ldflags} -Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/libhud.map") set_target_properties(hud PROPERTIES LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/libhud.map") 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.10+17.10.20170619/libhud/marshal.list0000664000175000017500000000002513121713174021071 0ustar didrocksdidrocks00000000000000VOID: STRING, STRING hud-14.10+17.10.20170619/libhud/manager.c0000664000175000017500000005244213121713174020335 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud/hud.h0000664000175000017500000000213213121713174017477 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/README0000664000175000017500000000000013121713174016147 0ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/NEWS0000664000175000017500000000002713121713174015777 0ustar didrocksdidrocks00000000000000 No NEWS is good news hud-14.10+17.10.20170619/AUTHORS0000664000175000017500000000003013121713174016342 0ustar didrocksdidrocks00000000000000# Generate by Makefile hud-14.10+17.10.20170619/ChangeLog0000664000175000017500000000003013121713174017044 0ustar didrocksdidrocks00000000000000# Generated by Makefile hud-14.10+17.10.20170619/libhud-client/0000775000175000017500000000000013121716557020034 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/libhud-client/enum-types.h.in0000664000175000017500000000333413121713174022713 0ustar didrocksdidrocks00000000000000/*** 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.10+17.10.20170619/libhud-client/connection.c0000664000175000017500000003112013121713174022324 0ustar didrocksdidrocks00000000000000/* * 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); return; } data->cb(data->con, query_object, results_name, appstack_name, data->user_data); g_free(data); g_free(query_object); g_free(results_name); g_free(appstack_name); 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.10+17.10.20170619/libhud-client/connection.h0000664000175000017500000001141413121713174022335 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/hud-client.pc.in0000664000175000017500000000040613121713174023011 0ustar didrocksdidrocks00000000000000libdir=@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.10+17.10.20170619/libhud-client/action-muxer.h0000664000175000017500000000323213121713174022610 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/HudToolbarModel.h0000664000175000017500000000231313121713174023220 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/enum-types.c.in0000664000175000017500000000501613121713174022705 0ustar didrocksdidrocks00000000000000/*** 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.10+17.10.20170619/libhud-client/HudClient.cpp0000664000175000017500000002603313121713174022413 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/hud-client.h0000664000175000017500000000166413121713174022240 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/HudToolbarModel.cpp0000664000175000017500000000532413121713174023560 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/toolbar-items.h0000664000175000017500000000320713121713174022760 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/action-muxer.c0000664000175000017500000004071113121713174022606 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/CMakeLists.txt0000664000175000017500000001111613121713174022564 0ustar didrocksdidrocks00000000000000 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 ) set_target_properties(hud-client PROPERTIES LINK_FLAGS "${ldflags} -Wl,--version-script,${CMAKE_CURRENT_SOURCE_DIR}/libhud-client.map") set_target_properties(hud-client PROPERTIES LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/libhud-client.map") 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.10+17.10.20170619/libhud-client/query.h0000664000175000017500000001627513121713174021355 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/connection-private.h0000664000175000017500000000210513121713174024002 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/param.c0000664000175000017500000003167213121713174021301 0ustar didrocksdidrocks00000000000000/* * 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->dbus_address, g_free); 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.10+17.10.20170619/libhud-client/libhud-client.map0000664000175000017500000000023713121713174023250 0ustar didrocksdidrocks00000000000000{ global: hud_*; extern "C++" { hud::*; vtable?for?hud::*; typeinfo?for?hud::*; typeinfo?name?for?hud::*; }; local: *; extern "C++" { *; }; }; hud-14.10+17.10.20170619/libhud-client/param.h0000664000175000017500000000760213121713174021302 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/query.c0000664000175000017500000007043113121713174021342 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-client/HudClient.h0000664000175000017500000000425413121713174022061 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/CMakeLists.txt0000664000175000017500000001531413121713174020045 0ustar didrocksdidrocks00000000000000project(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) # 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(UseGlibGeneration) include(UseGdbusCodegen) include(UseConstantBuilder) find_package(GSettings) 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}) 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) find_package(CoverageReport) enable_coverage_report( TARGETS hud-generated hud hud-cli hud-cli-appstack hud-cli-param hud-cli-toolbar hud-client-generated hud-client hud-common hud-gtk hud-service hud-service-exec qtgmenu window-stack-bridge window-stack-bridge-bin dbusmenu-json-loader hud-test-interface qtgmenu-test-app test-integration-tests test-libhud-application test-libhud-client-unit-tests test-libhud-unit-tests test-menu-input-model-deep test-menu-input-model-shortcuts test-menu-input-model-simple test-menu-input-model-toolbar-all test-menu-input-model-toolbar-dynamic test-menu-input-model-toolbar-undo test-menu-input-model-toolbar-unknown test-qtgmenu-unit-tests test-service-unit-tests test-utils test-window-stack-bridge-unit-tests FILTER ${CMAKE_SOURCE_DIR}/tests/* ${CMAKE_BINARY_DIR}/* TESTS dbusmenu-json-loader hud-test-interface qtgmenu-test-app test-integration-tests test-libhud-application test-libhud-client-unit-tests test-libhud-unit-tests test-menu-input-model-deep test-menu-input-model-shortcuts test-menu-input-model-simple test-menu-input-model-toolbar-all test-menu-input-model-toolbar-dynamic test-menu-input-model-toolbar-undo test-menu-input-model-toolbar-unknown test-qtgmenu-unit-tests test-service-unit-tests test-utils test-window-stack-bridge-unit-tests ) endif() add_subdirectory(tools-vala) if(${ENABLE_DOCUMENTATION}) add_subdirectory(docs) endif() hud-14.10+17.10.20170619/tests/0000775000175000017500000000000013121716557016453 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/run-under-xvfb.sh0000775000175000017500000000173613121713174021673 0ustar didrocksdidrocks00000000000000#!/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.10+17.10.20170619/tests/integration/0000775000175000017500000000000013121716557020776 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/integration/CMakeLists.txt0000664000175000017500000000065113121713174023530 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/tests/integration/TestHud.cpp0000664000175000017500000003501213121713174023053 0ustar didrocksdidrocks00000000000000/* * 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()); if ((toolbarModel.data(index, Qt::UserRole + 1).toBool()) != enabled) { QSignalSpy spy(&toolbarModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &, const QVector &))); ASSERT_TRUE(spy.wait()); } 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.10+17.10.20170619/tests/testutils/0000775000175000017500000000000013121716557020513 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/testutils/MockHudService.h0000664000175000017500000000313013121713174023524 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/testutils/MockHudService.cpp0000664000175000017500000001031413121713174024061 0ustar didrocksdidrocks00000000000000/* * 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", "sssooi", "ret = ('" + m_dbus.sessionConnection().baseService() + "', 'hud', '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.10+17.10.20170619/tests/testutils/CMakeLists.txt0000664000175000017500000000054313121713174023245 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/tests/testutils/main.cpp0000664000175000017500000000244513121713174022140 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/testutils/RawDBusTransformer.h0000664000175000017500000000236513121713174024414 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/testutils/RawDBusTransformer.cpp0000664000175000017500000000401513121713174024741 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/good-app-info/0000775000175000017500000000000013121716557021112 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/good-app-info/testapp100.desktop.hud-app-info0000664000175000017500000000026413121713174026666 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/good-app-info/testapp.desktop.hud-app-info0000664000175000017500000000025713121713174026447 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/good-app-info/tons-of-entries.hud-app-info0000664000175000017500000001172213121713174026352 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/CMakeLists.txt0000664000175000017500000000537113121713174021211 0ustar didrocksdidrocks00000000000000set(CMAKE_AUTOMOC OFF) find_package(GMock REQUIRED) set(CMAKE_AUTOMOC ON) 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.10+17.10.20170619/tests/menus/0000775000175000017500000000000013121716557017602 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/menus/test-menu-input-model-shortcuts.c0000664000175000017500000000674113121713174026156 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tests/menus/test-menu-input-model-deep.c0000664000175000017500000000466313121713174025036 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tests/menus/FakeTouchApplication.cpp0000664000175000017500000001525013121713174024336 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/menus/FakeTouchApplication.h0000664000175000017500000000305213121713174024000 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/menus/test-menu-input-model-toolbar-undo.c0000664000175000017500000000402213121713174026513 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tests/menus/CMakeLists.txt0000664000175000017500000000574313121713174022343 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/tests/menus/dbusmenu-json-loader.c0000664000175000017500000000410613121713174023774 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tests/menus/test-menu-input-model-toolbar-unknown.c0000664000175000017500000000402513121713174027250 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tests/menus/test-menu-input-model-toolbar-dynamic.c0000664000175000017500000000716413121713174027204 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tests/menus/test-libhud-application.cpp0000664000175000017500000000240613121713174025025 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/menus/test-menu-input-model-toolbar-all.c0000664000175000017500000000432413121713174026323 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tests/menus/test-menu-input-model-simple.c0000664000175000017500000000514013121713174025401 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tests/unit/0000775000175000017500000000000013121716557017432 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/unit/service/0000775000175000017500000000000013121716557021072 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/unit/service/TestApplication.cpp0000664000175000017500000001603413121713174024675 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/service/TestQuery.cpp0000664000175000017500000001357513121713174023546 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/service/Mocks.h0000664000175000017500000001127213121713174022312 0ustar didrocksdidrocks00000000000000/* * 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_METHOD1(newDBusMenuWindowCollector, Collector::Ptr(unsigned int)); 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.10+17.10.20170619/tests/unit/service/TestHudService.cpp0000664000175000017500000001753413121713174024501 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/service/TestApplicationList.cpp0000664000175000017500000002105013121713174025523 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/service/TestUsageTracker.cpp0000664000175000017500000000605213121713174025011 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/service/CMakeLists.txt0000664000175000017500000000076313121713174023630 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/tests/unit/service/TestVoice.cpp0000664000175000017500000000235113121713174023474 0ustar didrocksdidrocks00000000000000/* * 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: }; TEST_F( TestVoice, DoesNothingReally ) { // check that signals are patched through VoiceImpl VoiceImpl voice; EXPECT_EQ(QString(), voice.listen(QList())); } } // namespace hud-14.10+17.10.20170619/tests/unit/service/TestItemStore.cpp0000664000175000017500000002077213121713174024351 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/service/TestWindow.cpp0000664000175000017500000002252113121713174023677 0ustar didrocksdidrocks00000000000000/* * 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)); dbusmenuWindowCollector.reset(new NiceMock()); ON_CALL(*dbusmenuWindowCollector, 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, newDBusMenuWindowCollector(1234)).Times( 1).WillOnce(Return(dbusmenuWindowCollector)); 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 dbusmenuWindowCollector; 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 dbusmenuWindowCollectorMenu; CollectorToken::Ptr dbusmenuWindowCollectorToken( new CollectorToken(dbusmenuWindowCollector, &dbusmenuWindowCollectorMenu)); EXPECT_CALL(*dbusmenuWindowCollector, activate()).Times(1).WillOnce( Return(QList() << dbusmenuWindowCollectorToken)); WindowToken::Ptr token(window->activate()); EXPECT_EQ(QList() << dbusmenuWindowCollectorToken, token->tokens()); } TEST_F(TestWindow, ActivateOnlyWithGMenu) { Window::Ptr window(createWindow()); ON_CALL(*dbusmenuWindowCollector, 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(*dbusmenuWindowCollector, 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(*dbusmenuWindowCollector, 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 dbusmenuWindowCollectorMenu; CollectorToken::Ptr dbusmenuWindowCollectorToken( new CollectorToken(dbusmenuWindowCollector, &dbusmenuWindowCollectorMenu)); EXPECT_CALL(*dbusmenuWindowCollector, activate()).Times(1).WillOnce( Return(QList() << dbusmenuWindowCollectorToken)); 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() << dbusmenuWindowCollectorToken << 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(*dbusmenuWindowCollector, activate()).Times(1).WillOnce( Return(QList() << dbusmenuWindowCollectorToken)); EXPECT_CALL(*allWindowsCollector, activate()).Times(1).WillOnce( Return(QList() << allWindowsCollectorToken)); WindowToken::Ptr tokenChanged(window->activate()); EXPECT_NE(token, tokenChanged); EXPECT_EQ( QList() << dbusmenuWindowCollectorToken << 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.10+17.10.20170619/tests/unit/libhud/0000775000175000017500000000000013121716557020701 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/unit/libhud/TestActionDescription.cpp0000664000175000017500000000455613121713174025670 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/libhud/TestActionPublisher.cpp0000664000175000017500000001543513121713174025340 0ustar didrocksdidrocks00000000000000/* * 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.reset(g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL), &g_object_unref); } virtual ~TestActionPublisher() { } DBusTestRunner dbus; DBusMock mock; MockHudService hud; QSharedPointer 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) { QSharedPointer application(g_application_new("app.id", G_APPLICATION_FLAGS_NONE), &g_object_unref); ASSERT_TRUE(g_application_register(application.data(), NULL, NULL)); QSharedPointer publisher(hud_action_publisher_new_for_application( application.data()), &g_object_unref); ASSERT_TRUE(publisher.data()); } TEST_F(TestActionPublisher, AddActionGroup) { QSharedPointer application(g_application_new("app.id", G_APPLICATION_FLAGS_NONE), &g_object_unref); ASSERT_TRUE(g_application_register(application.data(), NULL, NULL)); QSharedPointer publisher(hud_action_publisher_new_for_application( application.data()), &g_object_unref); ASSERT_TRUE(publisher.data()); // FIXME Waiting in tests QTestEventLoop::instance().enterLoopMSecs(100); { GList* groups = hud_action_publisher_get_action_groups(publisher.data()); 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.data(), "prefix", "/object/path"); // FIXME Waiting in tests QTestEventLoop::instance().enterLoopMSecs(100); { GList* groups = hud_action_publisher_get_action_groups(publisher.data()); 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 QSharedPointer v(g_variant_new_string("/object/path"), &g_variant_unref); hud_action_publisher_remove_action_group(publisher.data(), "prefix", v.data()); } TEST_F(TestActionPublisher, AddDescription) { QSharedPointer application(g_application_new("app.id", G_APPLICATION_FLAGS_NONE), &g_object_unref); ASSERT_TRUE(g_application_register(application.data(), NULL, NULL)); QSharedPointer publisher(hud_action_publisher_new_for_application( application.data()), &g_object_unref); ASSERT_TRUE(publisher.data()); QSharedPointer description( hud_action_description_new("hud.simple-action", g_variant_new_string("Foo")), &hud_action_description_unref); hud_action_description_set_attribute_value(description.data(), G_MENU_ATTRIBUTE_LABEL, g_variant_new_string("Simple Action")); hud_action_publisher_add_description(publisher.data(), description.data()); // FIXME Waiting in tests QTestEventLoop::instance().enterLoopMSecs(100); { GMenuModel *model = G_MENU_MODEL( g_dbus_menu_model_get(connection.data(), DBUS_NAME, "/com/canonical/hud/publisher")); ASSERT_TRUE(model); EXPECT_EQ(0, g_menu_model_get_n_items(model)); g_object_unref(model); } QSharedPointer paramdesc(hud_action_description_new( "hud.simple-action", NULL), &hud_action_description_unref); hud_action_description_set_attribute_value(paramdesc.data(), G_MENU_ATTRIBUTE_LABEL, g_variant_new_string("Parameterized Action")); hud_action_publisher_add_description(publisher.data(), paramdesc.data()); QSharedPointer menu (g_menu_new(), &g_object_unref); QSharedPointer item1( g_menu_item_new("Item One", "hud.simple-action"), &g_object_unref); QSharedPointer item2( g_menu_item_new("Item Two", "hud.simple-action"), &g_object_unref); QSharedPointer item3( g_menu_item_new("Item Three", "hud.simple-action"), &g_object_unref); g_menu_append_item(menu.data(), item1.data()); g_menu_append_item(menu.data(), item2.data()); g_menu_append_item(menu.data(), item3.data()); hud_action_description_set_parameterized(paramdesc.data(), G_MENU_MODEL(menu.data())); // FIXME Waiting in tests QTestEventLoop::instance().enterLoopMSecs(100); { GMenuModel *model = G_MENU_MODEL( g_dbus_menu_model_get(connection.data(), 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-14.10+17.10.20170619/tests/unit/libhud/TestManager.cpp0000664000175000017500000001366413121713174023621 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/libhud/CMakeLists.txt0000664000175000017500000000062413121713174023433 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/tests/unit/qtgmenu/0000775000175000017500000000000013121716557021112 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/unit/qtgmenu/TestQtGMenu.cpp0000664000175000017500000005063313121713174023775 0ustar didrocksdidrocks00000000000000/* * 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 #undef signals #include using namespace qtgmenu; using namespace testing; using namespace QtDBusTest; namespace { class TestQtGMenu : public QObject, public Test { Q_OBJECT protected: TestQtGMenu() : m_connection(newSessionBusConnection(nullptr), &g_object_unref), m_importer( c_service, QDBusObjectPath( c_path ), "app", QDBusObjectPath( c_path ), dbus.sessionConnection(), m_connection ), 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 ) ) ) { dbus.startServices(); } void ownBus() { m_owner_id = g_bus_own_name_on_connection( m_connection.data(), c_service, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL ); } void SetUp() override { m_menu.reset(g_menu_new(), &g_object_unref); m_actions.reset(g_simple_action_group_new(), &g_object_unref); } void TearDown() override { UnexportGMenu(); if (m_owner_id > 0) { 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() { // build m_menu QSharedPointer menus_section(g_menu_new(), &g_object_unref); g_menu_append_section( m_menu.data(), "Menus", G_MENU_MODEL( menus_section.data() ) ); // export menu m_menu_export_id = g_dbus_connection_export_menu_model( m_connection.data(), c_path, G_MENU_MODEL( m_menu.data() ), NULL ); // export actions m_actions_export_id = g_dbus_connection_export_action_group( m_connection.data(), c_path, G_ACTION_GROUP( m_actions.data() ), NULL ); ownBus(); if (m_items_changed_spy.isEmpty()) { ASSERT_TRUE(m_items_changed_spy.wait()); } ASSERT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); //-- build file menu QSharedPointer file_submenu(g_menu_new(), &g_object_unref); QSharedPointer files_section(g_menu_new(), &g_object_unref); QSharedPointer menu_item(g_menu_item_new( "New", "app.new" ), &g_object_unref); g_menu_item_set_attribute_value( menu_item.data(), "accel", g_variant_new_string( "N" ) ); g_menu_append_item( files_section.data(), menu_item.data() ); g_menu_append( files_section.data(), "Open", "app.open" ); g_menu_append_section( file_submenu.data(), "Files", G_MENU_MODEL( files_section.data() ) ); QSharedPointer mod_section(g_menu_new(), &g_object_unref); g_menu_append( mod_section.data(), "Lock", "app.lock" ); g_menu_append_section( file_submenu.data(), "Modify", G_MENU_MODEL( mod_section.data() ) ); g_menu_append_submenu( menus_section.data(), "File", G_MENU_MODEL( file_submenu.data() ) ); if (m_items_changed_spy.isEmpty()) { ASSERT_TRUE(m_items_changed_spy.wait()); } ASSERT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); //-- build edit menu QSharedPointer edit_submenu(g_menu_new(), &g_object_unref); QSharedPointer style_submenu(g_menu_new(), &g_object_unref); g_menu_append( style_submenu.data(), "Plain", "app.text_plain" ); g_menu_append( style_submenu.data(), "Bold", "app.text_bold" ); g_menu_append_submenu( menus_section.data(), "Edit", G_MENU_MODEL( edit_submenu.data() ) ); if (m_items_changed_spy.isEmpty()) { ASSERT_TRUE(m_items_changed_spy.wait()); } ASSERT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); g_menu_append_submenu( edit_submenu.data(), "Style", G_MENU_MODEL( style_submenu.data() ) ); if (m_items_changed_spy.isEmpty()) { ASSERT_TRUE(m_items_changed_spy.wait()); } ASSERT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); //-- stateless m_action_added_spy.clear(); QSharedPointer action(g_simple_action_new( "new", nullptr ), &g_object_unref); m_exported_actions.push_back( std::make_pair( action, g_signal_connect( action.data(), "activate", G_CALLBACK( ActivateAction ), this ) ) ); g_action_map_add_action( G_ACTION_MAP( m_actions.data() ), G_ACTION( action.data() ) ); if (m_action_added_spy.isEmpty()) { ASSERT_TRUE(m_action_added_spy.wait()); } ASSERT_FALSE( m_action_added_spy.empty() ); m_action_added_spy.clear(); action.reset(g_simple_action_new( "open", nullptr ), &g_object_unref); m_exported_actions.push_back( std::make_pair( action, g_signal_connect( action.data(), "activate", G_CALLBACK( ActivateAction ), this ) ) ); g_action_map_add_action( G_ACTION_MAP( m_actions.data() ), G_ACTION( action.data() ) ); if (m_action_added_spy.isEmpty()) { ASSERT_TRUE(m_action_added_spy.wait()); } ASSERT_FALSE( m_action_added_spy.empty() ); m_action_added_spy.clear(); //-- boolean state action.reset(g_simple_action_new_stateful( "lock", nullptr, g_variant_new_boolean( false ) ), &g_object_unref); m_exported_actions.push_back( std::make_pair( action, g_signal_connect( action.data(), "activate", G_CALLBACK( ActivateAction ), this ) ) ); g_action_map_add_action( G_ACTION_MAP( m_actions.data() ), G_ACTION( action.data() ) ); if (m_action_added_spy.isEmpty()) { ASSERT_TRUE(m_action_added_spy.wait()); } ASSERT_FALSE( m_action_added_spy.empty() ); m_action_added_spy.clear(); //-- string param + state action.reset(g_simple_action_new_stateful( "text_plain", G_VARIANT_TYPE_STRING, g_variant_new_string( "app.text_plain" ) ), &g_object_unref); m_exported_actions.push_back( std::make_pair( action, g_signal_connect( action.data(), "activate", G_CALLBACK( ActivateAction ), this ) ) ); g_action_map_add_action( G_ACTION_MAP( m_actions.data() ), G_ACTION( action.data() ) ); if (m_action_added_spy.isEmpty()) { ASSERT_TRUE(m_action_added_spy.wait()); } ASSERT_FALSE( m_action_added_spy.empty() ); m_action_added_spy.clear(); action.reset(g_simple_action_new_stateful( "text_bold", G_VARIANT_TYPE_STRING, g_variant_new_string( "app.text_plain" ) ), &g_object_unref); m_exported_actions.push_back( std::make_pair( action, g_signal_connect( action.data(), "activate", G_CALLBACK( ActivateAction ), this ) ) ); g_action_map_add_action( G_ACTION_MAP( m_actions.data() ), G_ACTION( action.data() ) ); if (m_action_added_spy.isEmpty()) { ASSERT_TRUE(m_action_added_spy.wait()); } ASSERT_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.data(), action.second ); } // unexport menu if (m_menu_export_id > 0) { g_dbus_connection_unexport_menu_model( m_connection.data(), m_menu_export_id ); } m_importer.Refresh(); EXPECT_EQ( 0, GetGMenuSize() ); // unexport actions if (m_actions_export_id > 0) { g_dbus_connection_unexport_action_group( m_connection.data(), 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"; DBusTestRunner dbus; guint m_owner_id = 0; guint m_menu_export_id = 0; guint m_actions_export_id = 0; QSharedPointer m_connection; QSharedPointer m_menu; QSharedPointer m_actions; 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< QSharedPointer, gulong > > m_exported_actions; }; TEST_F( TestQtGMenu, DISABLED_ExportImportGMenu ) { // no menu exported EXPECT_EQ( 0, GetGMenuSize() ); // export menu m_menu_export_id = g_dbus_connection_export_menu_model( m_connection.data(), c_path, G_MENU_MODEL( m_menu.data() ), NULL ); ownBus(); // add 1 item m_items_changed_spy.clear(); g_menu_append( m_menu.data(), "New", "app.new" ); if (m_items_changed_spy.isEmpty()) { ASSERT_TRUE(m_items_changed_spy.wait()); } ASSERT_FALSE( m_items_changed_spy.empty() ); EXPECT_NE( nullptr, m_importer.GetQMenu() ); ASSERT_EQ( 1, GetGMenuSize() ); // add 2 items m_items_changed_spy.clear(); g_menu_append( m_menu.data(), "Add", "app.add" ); if (m_items_changed_spy.isEmpty()) { ASSERT_TRUE(m_items_changed_spy.wait()); } ASSERT_FALSE( m_items_changed_spy.empty() ); m_items_changed_spy.clear(); g_menu_append( m_menu.data(), "Del", "app.del" ); if (m_items_changed_spy.isEmpty()) { ASSERT_TRUE(m_items_changed_spy.wait()); } ASSERT_FALSE( m_items_changed_spy.empty() ); ASSERT_EQ( 3, GetGMenuSize() ); // remove 1 item m_items_changed_spy.clear(); g_menu_remove( m_menu.data(), 2 ); if (m_items_changed_spy.isEmpty()) { ASSERT_TRUE(m_items_changed_spy.wait()); } ASSERT_FALSE( m_items_changed_spy.empty() ); ASSERT_EQ( 2, GetGMenuSize() ); } TEST_F( TestQtGMenu, DISABLED_ExportImportGActions ) { // no actions exported EXPECT_EQ( 0, GetGActionCount() ); // export actions m_actions_export_id = g_dbus_connection_export_action_group( m_connection.data(), c_path, G_ACTION_GROUP( m_actions.data() ), NULL ); ownBus(); // 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.data() ), G_ACTION( action ) ); if (m_action_added_spy.isEmpty()) { ASSERT_TRUE(m_action_added_spy.wait()); } ASSERT_FALSE( m_action_added_spy.empty() ); EXPECT_EQ( "new", m_action_added_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_NE( nullptr, m_importer.GetGActionGroup() ); EXPECT_EQ( 1, GetGActionCount() ); // disable / enable action m_action_enabled_spy.clear(); g_simple_action_set_enabled( action, false ); if (m_action_enabled_spy.isEmpty()) { ASSERT_TRUE(m_action_enabled_spy.wait()); } ASSERT_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 ); if (m_action_enabled_spy.isEmpty()) { ASSERT_TRUE(m_action_enabled_spy.wait()); } ASSERT_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() ); // change action state m_action_state_changed_spy.clear(); g_action_change_state( G_ACTION( action ), g_variant_new_boolean( true ) ); if (m_action_state_changed_spy.isEmpty()) { ASSERT_TRUE(m_action_state_changed_spy.wait()); } ASSERT_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 ) ); if (m_action_state_changed_spy.isEmpty()) { ASSERT_TRUE(m_action_state_changed_spy.wait()); } ASSERT_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 m_action_added_spy.clear(); action = g_simple_action_new_stateful( "add", G_VARIANT_TYPE_BOOLEAN, FALSE ); g_action_map_add_action( G_ACTION_MAP( m_actions.data() ), G_ACTION( action ) ); if (m_action_added_spy.isEmpty()) { ASSERT_TRUE(m_action_added_spy.wait()); } ASSERT_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.data() ), G_ACTION( action ) ); if (m_action_added_spy.isEmpty()) { ASSERT_TRUE(m_action_added_spy.wait()); } ASSERT_FALSE( m_action_added_spy.empty() ); EXPECT_EQ( "del", m_action_added_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( 3, GetGActionCount() ); // remove 1 action m_action_removed_spy.clear(); g_action_map_remove_action( G_ACTION_MAP( m_actions.data() ), "del" ); if (m_action_removed_spy.isEmpty()) { ASSERT_TRUE(m_action_removed_spy.wait()); } ASSERT_FALSE( m_action_removed_spy.empty() ); EXPECT_EQ( "del", m_action_removed_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( 2, GetGActionCount() ); } TEST_F( TestQtGMenu, DISABLED_QMenuStructure ) { ExportGMenu(); // import QMenu std::shared_ptr< QMenu > menu = m_importer.GetQMenu(); ASSERT_NE( nullptr, menu ); ASSERT_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 ); ASSERT_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 ); ASSERT_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 ); ASSERT_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() ); } TEST_F( TestQtGMenu, DISABLED_QMenuActionTriggers ) { ExportGMenu(); // import QMenu std::shared_ptr< QMenu > menu = m_importer.GetQMenu(); EXPECT_NE( nullptr, m_importer.GetQMenu() ); // trigger file menu items ASSERT_FALSE(menu->actions().empty()); QMenu* file_menu = menu->actions().at( 0 )->menu(); ASSERT_NE( nullptr, file_menu ); m_action_activated_spy.clear(); file_menu->actions().at( 0 )->trigger(); if (m_action_activated_spy.isEmpty()) { ASSERT_TRUE(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(); if (m_action_activated_spy.isEmpty()) { ASSERT_TRUE(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(); if (m_action_activated_spy.isEmpty()) { ASSERT_TRUE(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() ); // 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 ); m_action_activated_spy.clear(); style_submenu->actions().at( 0 )->trigger(); if (m_action_activated_spy.isEmpty()) { ASSERT_TRUE(m_action_activated_spy.wait()); } ASSERT_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(); if (m_action_activated_spy.isEmpty()) { ASSERT_TRUE(m_action_activated_spy.wait()); } ASSERT_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() ); } TEST_F( TestQtGMenu, DISABLED_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() ); m_action_enabled_spy.clear(); g_simple_action_set_enabled( m_exported_actions[0].first.data(), false ); if (m_action_enabled_spy.isEmpty()) { ASSERT_TRUE(m_action_enabled_spy.wait()); } EXPECT_FALSE( file_menu->actions().at( 0 )->isEnabled() ); m_action_enabled_spy.clear(); g_simple_action_set_enabled( m_exported_actions[0].first.data(), true ); if (m_action_enabled_spy.isEmpty()) { ASSERT_TRUE(m_action_enabled_spy.wait()); } EXPECT_TRUE( file_menu->actions().at( 0 )->isEnabled() ); } } // namespace #include hud-14.10+17.10.20170619/tests/unit/qtgmenu/CMakeLists.txt0000664000175000017500000000074013121713174023643 0ustar didrocksdidrocks00000000000000set( 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.10+17.10.20170619/tests/unit/qtgmenu/main.cpp0000664000175000017500000000170213121713174022532 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/libhud-client/0000775000175000017500000000000013121716557022155 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/unit/libhud-client/TestParam.cpp0000664000175000017500000000437013121713174024555 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/libhud-client/TestQuery.cpp0000664000175000017500000003012313121713174024615 0ustar didrocksdidrocks00000000000000/* * 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) { dbus.startServices(); hud.loadMethods(); } void createQuery() { QSignalSpy querySpy(this, SIGNAL(modelsReady())); /* Create a query */ query.reset(hud_client_query_new("test"), &g_object_unref); /* Wait for the models to be ready */ g_signal_connect(G_OBJECT(query.data()), 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.data()))); ASSERT_TRUE(DEE_IS_MODEL(hud_client_query_get_appstack_model(query.data()))); } void createQuery(HudClientConnection *client_connection) { QSignalSpy querySpy(this, SIGNAL(modelsReady())); /* Create a query */ query.reset( hud_client_query_new_for_connection("test", client_connection), &g_object_unref); /* Wait for the models to be ready */ g_signal_connect(G_OBJECT(query.data()), 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.data()))); ASSERT_TRUE(DEE_IS_MODEL(hud_client_query_get_appstack_model(query.data()))); } virtual ~TestQuery() { } 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; QSharedPointer query; }; TEST_F(TestQuery, Create) { createQuery(); EXPECT_STREQ("test", hud_client_query_get_query(query.data())); HudClientConnection * client_connection = NULL; gchar * search = NULL; g_object_get(G_OBJECT(query.data()), "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.data())); /* Make sure the connection is the same */ HudClientConnection *testcon = NULL; g_object_get(G_OBJECT(query.data()), "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.data(), "test2"); EXPECT_STREQ("test2", hud_client_query_get_query(query.data())); 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.data()), "voice-query-finished", G_CALLBACK(callbackVoiceQueryFinished), this); QSignalSpy queryFinishedSpy(this, SIGNAL(queryFinished())); hud_client_query_voice_query(query.data()); 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.data(), "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.data(), 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.data(), 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.data(), 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.data(), 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.data(), 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.data(), 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.data(), HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query.data(), HUD_CLIENT_QUERY_TOOLBAR_HELP)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query.data(), HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query.data(), 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.data(), HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query.data(), HUD_CLIENT_QUERY_TOOLBAR_HELP)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query.data(), HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES)); EXPECT_TRUE( hud_client_query_toolbar_item_active(query.data(), 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.data(), HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query.data(), HUD_CLIENT_QUERY_TOOLBAR_HELP)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query.data(), HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES)); EXPECT_FALSE( hud_client_query_toolbar_item_active(query.data(), 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.data(), HUD_CLIENT_QUERY_TOOLBAR_FULLSCREEN)); EXPECT_TRUE( hud_client_query_toolbar_item_active(query.data(), HUD_CLIENT_QUERY_TOOLBAR_HELP)); EXPECT_TRUE( hud_client_query_toolbar_item_active(query.data(), HUD_CLIENT_QUERY_TOOLBAR_PREFERENCES)); EXPECT_TRUE( hud_client_query_toolbar_item_active(query.data(), HUD_CLIENT_QUERY_TOOLBAR_UNDO)); /* Check the array */ QSharedPointer toolbar(hud_client_query_get_active_toolbar(query.data()), &g_array_unref); 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.data(), 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.10+17.10.20170619/tests/unit/libhud-client/TestHudClient.cpp0000664000175000017500000001372113121713174025374 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/libhud-client/TestConnection.cpp0000664000175000017500000000550213121713174025612 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/libhud-client/CMakeLists.txt0000664000175000017500000000066713121713174024716 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/tests/unit/CMakeLists.txt0000664000175000017500000000030313121713174022156 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/tests/unit/window-stack-bridge/0000775000175000017500000000000013121716557023276 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/unit/window-stack-bridge/TestBamfWindowStack.cpp0000664000175000017500000002665113121713174027667 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tests/unit/window-stack-bridge/CMakeLists.txt0000664000175000017500000000074713121713174026036 0ustar didrocksdidrocks00000000000000if(${ENABLE_BAMF}) if(${ENABLE_BAMF}) list(APPEND UNIT_TESTS_SRC TestBamfWindowStack.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.10+17.10.20170619/tests/data/0000775000175000017500000000000013121716557017364 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/data/test-indicator-source-session.json0000664000175000017500000000032413121713174026156 0ustar didrocksdidrocks00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Session Time' }, { "id": 2, "label": 'bar' }, { "id": 3, "label": 'xxx' } ] }hud-14.10+17.10.20170619/tests/data/test-menu-input-shortcuts.json0000664000175000017500000000052113121713174025357 0ustar didrocksdidrocks00000000000000{"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.10+17.10.20170619/tests/data/test-dbus-message-count.json0000664000175000017500000024424313121713174024742 0ustar didrocksdidrocks00000000000000{ "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.10+17.10.20170619/tests/data/test-indicator-source-messages.json0000664000175000017500000000032513121713174026303 0ustar didrocksdidrocks00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Messages Time' }, { "id": 2, "label": 'foz' }, { "id": 3, "label": 'vvv' } ] }hud-14.10+17.10.20170619/tests/data/test-indicator-source-users.json0000664000175000017500000000032213121713174025632 0ustar didrocksdidrocks00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Users Time' }, { "id": 2, "label": 'baz' }, { "id": 3, "label": 'yyy' } ] }hud-14.10+17.10.20170619/tests/data/test-indicator-source-sound.json0000664000175000017500000000032213121713174025621 0ustar didrocksdidrocks00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Sound Time' }, { "id": 2, "label": 'biz' }, { "id": 3, "label": 'www' } ] }hud-14.10+17.10.20170619/tests/data/valgrind.suppression0000664000175000017500000001576313121713174023512 0ustar didrocksdidrocks00000000000000 { Google test internals Memcheck:Leak ... fun:*_ZN7testing8internal* ... } ############################## # Valgrind doesn't like dlopen ############################## { Memcheck:Leak match-leak-kinds: definite fun:malloc ... fun:dlopen* } { Memcheck:Leak match-leak-kinds: possible fun:calloc fun:g_malloc0 ... fun:_dl_init ... } ############################### # 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.* } { Memcheck:Leak match-leak-kinds: possible ... obj:/usr/lib/*/libQt5Widgets.so.* fun:_ZN13QStyleFactory6createERK7QString fun:_ZN12QApplication5styleEv } ########################## # Fontconfig ########################## { Memcheck:Leak fun:malloc ... fun:FcValueSave ... } { Memcheck:Leak match-leak-kinds: definite fun:malloc obj:/usr/lib/*/libfontconfig.so.* ... fun:FcConfigParseAndLoad ... } { Memcheck:Leak match-leak-kinds: possible fun:malloc obj:/usr/lib/*/libfontconfig.so.* ... fun:FcConfigSubstituteWithPat ... } { Memcheck:Leak match-leak-kinds: definite fun:realloc ... obj:/usr/lib/*/libfontconfig.so.* ... fun:FcPatternAddInteger ... } { Memcheck:Leak fun:realloc ... obj:/usr/lib/*/libfontconfig.so.* ... fun:FcFontRenderPrepare ... } { Memcheck:Leak fun:realloc ... obj:/usr/lib/*/libfontconfig.so.* ... fun:FcPatternAddBool ... } ############################## # Dee ############################## { Memcheck:Leak match-leak-kinds: definite fun:malloc fun:g_malloc ... obj:/usr/lib/*/libdee-1.0.so.* ... fun:g_simple_async_result_complete ... } { Memcheck:Leak match-leak-kinds: definite fun:malloc fun:g_malloc fun:g_strdup fun:dee_serializable_register_parser ... } { Memcheck:Leak match-leak-kinds: definite fun:malloc fun:g_malloc ... obj:/usr/lib/*/libdee-1.0.so.* ... fun:g_simple_async_result_complete ... fun:g_main_context_* ... } ############################### # Pango ############################### { Memcheck:Leak match-leak-kinds: possible fun:calloc fun:g_malloc0 fun:pango_language_from_string fun:pango_script_get_sample_language ... } ############################### # 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 match-leak-kinds: possible fun:calloc fun:g_malloc0 fun:g_closure_new_simple fun:g_cclosure_new fun:g_signal_connect_data ... } { Memcheck:Leak match-leak-kinds: possible fun:calloc fun:g_malloc0 fun:g_closure_new_simple ... } { Memcheck:Leak match-leak-kinds: possible fun:calloc fun:g_malloc0 fun:g_closure_new_simple fun:g_cclosure_new_swap ... } { Memcheck:Leak match-leak-kinds: possible fun:realloc fun:g_realloc ... fun:g_closure_add_invalidate_notifier ... } { Memcheck:Leak match-leak-kinds: definite fun:malloc fun:g_malloc ... fun:g_type_create_instance ... } { Memcheck:Leak match-leak-kinds: possible fun:malloc fun:g_malloc ... fun:g_type_add_interface_dynamic fun:g_type_module_add_interface ... } { Memcheck:Leak match-leak-kinds: possible fun:malloc fun:g_malloc ... fun:g_type_register_dynamic ... } { Memcheck:Leak match-leak-kinds: definite,possible fun:malloc fun:g_malloc ... fun:g_type_class_ref ... } { Memcheck:Leak match-leak-kinds: possible fun:calloc fun:g_malloc* ... fun:g_type_create_instance } { Memcheck:Leak match-leak-kinds: possible fun:malloc fun:realloc fun:g_realloc ... fun:g_closure_add_invalidate_notifier fun:g_source_set_closure ... } { Memcheck:Leak match-leak-kinds: definite fun:malloc fun:g_malloc fun:g_strconcat fun:g_application_constructed ... } { Memcheck:Leak match-leak-kinds: definite fun:malloc fun:g_malloc fun:g_slice_alloc ... fun:g_main_context_dispatch ... fun:g_main_loop_run ... fun:start_thread fun:clone } ################### # GTK ################### { Memcheck:Cond fun:g_utf8_offset_to_pointer ... obj:/usr/lib/*/libgtk-x11-* ... } hud-14.10+17.10.20170619/tests/data/test-menu-input-simple.json0000664000175000017500000000006113121713174024611 0ustar didrocksdidrocks00000000000000{"submenu": [ {"id": 1, "label": "Simple"} ]} hud-14.10+17.10.20170619/tests/data/test-indicator-source-datetime.json0000664000175000017500000000032113121713174026264 0ustar didrocksdidrocks00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Date Time' }, { "id": 2, "label": 'foo' }, { "id": 3, "label": 'zzz' } ] }hud-14.10+17.10.20170619/tests/data/test-app-indicator-source-two.json0000664000175000017500000000034513121713174026065 0ustar didrocksdidrocks00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Hello There 2' }, { "id": 2, "label": 'Goodbye 2' }, { "id": 3, "label": 'Hallo Again 2' } ] }hud-14.10+17.10.20170619/tests/data/com.canonical.hud.test.xml0000664000175000017500000000056213121713174024342 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/data/test-source.json0000664000175000017500000000175713121713174022536 0ustar didrocksdidrocks00000000000000{ "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.10+17.10.20170619/tests/data/test-app-indicator-source-one.json0000664000175000017500000000033713121713174026036 0ustar didrocksdidrocks00000000000000{ "id": 0, "submenu": [ { "id": 1, "label": 'Hello There' }, { "id": 2, "label": 'Goodbye' }, { "id": 3, "label": 'Hallo Again' } ] }hud-14.10+17.10.20170619/tests/bad-app-info/0000775000175000017500000000000013121716557020710 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/bad-app-info/item-no-name.hud-app-info0000664000175000017500000000024213121713174025375 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/bad-app-info/missing-desktop.hud-app-info0000664000175000017500000000015713121713174026234 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/bad-app-info/missing-menus.hud-app-info0000664000175000017500000000023113121713174025703 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/bad-app-info/menu-no-name.hud-app-info0000664000175000017500000000024213121713174025403 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/bad-app-info/item-no-count.hud-app-info0000664000175000017500000000024413121713174025607 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/bad-app-info/multiple-menus.hud-app-info0000664000175000017500000000040113121713174026064 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/bad-app-info/dual-headers.hud-app-info0000664000175000017500000000005213121713174025444 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/keyword-mapping/0000775000175000017500000000000013121716557021570 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/keyword-mapping/locale/0000775000175000017500000000000013121716557023027 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/keyword-mapping/locale/en_FAKELANG/0000775000175000017500000000000013121716557024661 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/keyword-mapping/locale/en_FAKELANG/LC_MESSAGES/0000775000175000017500000000000013121716557026446 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/keyword-mapping/gnome-terminal-en_FAKELANG.po0000664000175000017500000000225113121713174026666 0ustar didrocksdidrocks00000000000000# 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.10+17.10.20170619/tests/keyword-mapping/hud/0000775000175000017500000000000013121716557022350 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/keyword-mapping/hud/keywords/0000775000175000017500000000000013121716557024217 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/keyword-mapping/hud/keywords/gnome-terminal.xml0000664000175000017500000000045513121713174027653 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/tests/testapps/0000775000175000017500000000000013121716557020316 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/testapps/qtgmenu/0000775000175000017500000000000013121716557021776 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tests/testapps/qtgmenu/MainWindow.cpp0000664000175000017500000000131713121713174024550 0ustar didrocksdidrocks00000000000000#include #include MainWindow::MainWindow(const QString &name, const QDBusObjectPath &actionPath, const QDBusObjectPath &menuPath, const QDBusConnection& connection, QSharedPointer gconnection) : m_menu_importer( name, menuPath, "", actionPath, connection, gconnection) { 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.10+17.10.20170619/tests/testapps/qtgmenu/MainWindow.h0000664000175000017500000000111713121713174024213 0ustar didrocksdidrocks00000000000000#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(const QString &name, const QDBusObjectPath &actionPath, const QDBusObjectPath &menuPath, const QDBusConnection& connection, QSharedPointer gconnection); ~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.10+17.10.20170619/tests/testapps/qtgmenu/CMakeLists.txt0000664000175000017500000000026713121713174024533 0ustar didrocksdidrocks00000000000000add_executable( qtgmenu-test-app MainWindow.cpp main.cpp ) qt5_use_modules( qtgmenu-test-app Widgets ) target_link_libraries( qtgmenu-test-app qtgmenu ) hud-14.10+17.10.20170619/tests/testapps/qtgmenu/main.cpp0000664000175000017500000000234713121713174023424 0ustar didrocksdidrocks00000000000000/* * 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] ), QDBusConnection::sessionBus(), QSharedPointer(g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr), &g_object_unref) ); mainWindow.show(); return application.exec(); } hud-14.10+17.10.20170619/tests/testapps/CMakeLists.txt0000664000175000017500000000003213121713174023041 0ustar didrocksdidrocks00000000000000add_subdirectory(qtgmenu) hud-14.10+17.10.20170619/build.sh0000775000175000017500000000272513121713174016745 0ustar didrocksdidrocks00000000000000#! /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.10+17.10.20170619/data/0000775000175000017500000000000013121716557016222 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/data/org.ayatana.bamf.view.xml0000664000175000017500000000717313121713174023025 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/data/window-stack-bridge.service.in0000664000175000017500000000022313121713174024042 0ustar didrocksdidrocks00000000000000[Unit] Description=Window Stack Bridge PartOf=graphical-session.target [Service] ExecStart=@pkglibexecdir@/window-stack-bridge Restart=on-failure hud-14.10+17.10.20170619/data/com.canonical.hud.query.xml0000664000175000017500000000421413121713174023364 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/data/com.canonical.hud.xml0000664000175000017500000000415113121713174022220 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/data/com.canonical.hud.Application.xml0000664000175000017500000000222113121713174024456 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/data/hud.service.in0000664000175000017500000000022213121713174020755 0ustar didrocksdidrocks00000000000000[Unit] Description=Unity HUD PartOf=graphical-session.target [Service] Type=dbus BusName=com.canonical.hud ExecStart=@pkglibexecdir@/hud-service hud-14.10+17.10.20170619/data/hud-gui.desktop0000664000175000017500000000030113121713174021141 0ustar didrocksdidrocks00000000000000[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.10+17.10.20170619/data/com.canonical.AppMenu.Registrar.xml0000664000175000017500000000540313121713174024747 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/data/com.canonical.indicator.appmenu.hud.search.gschema.xml0000664000175000017500000000553613121713174030521 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/data/CMakeLists.txt0000664000175000017500000000312113121713174020747 0ustar didrocksdidrocks00000000000000 ########################### # 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} ) ########################### # Systemd Unit ########################### # where to install pkg_get_variable(SYSTEMD_USER_DIR systemd systemduserunitdir) message (STATUS "${SYSTEMD_USER_DIR} is the systemd user unit file install dir") set(pkglibexecdir "${CMAKE_INSTALL_FULL_LIBEXECDIR}/hud") configure_file("hud.service.in" "hud.service" @ONLY ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/hud.service" DESTINATION "${SYSTEMD_USER_DIR}" ) ########################### # Window Stack Bridge ########################### configure_file( "window-stack-bridge.service.in" "window-stack-bridge.service" @ONLY ) install( FILES "${CMAKE_CURRENT_BINARY_DIR}/window-stack-bridge.service" DESTINATION "${SYSTEMD_USER_DIR}" ) ########################### # 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.10+17.10.20170619/data/com.canonical.hud.service.in0000664000175000017500000000014313121713174023462 0ustar didrocksdidrocks00000000000000[D-BUS Service] Name=com.canonical.hud Exec=@pkglibexecdir@/hud-service SystemdService=hud.service hud-14.10+17.10.20170619/data/org.ayatana.bamf.xml0000664000175000017500000000611413121713174022046 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/data/com.canonical.indicator.appmenu.hud.gschema.xml0000664000175000017500000000117513121713174027250 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/data/com.canonical.Unity.WindowStack.xml0000664000175000017500000000344313121713174025007 0ustar didrocksdidrocks00000000000000 hud-14.10+17.10.20170619/docs/0000775000175000017500000000000013121716557016241 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/docs/HUD Architecture.svg0000664000175000017500000012624713121713174022011 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/docs/devel/0000775000175000017500000000000013121716557017340 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/docs/devel/hud.types0000664000175000017500000000041013121713174021171 0ustar didrocksdidrocks00000000000000hud_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.10+17.10.20170619/docs/devel/hud-docs.xml0000664000175000017500000000332013121713174021556 0ustar didrocksdidrocks00000000000000 ]> hud-service Hacking Guide Data Types Queries, Results, Items Sources Utility API Object Hierarchy API Index Index of deprecated API hud-14.10+17.10.20170619/docs/devel/hud-sections.txt0000664000175000017500000000577013121713174022507 0ustar didrocksdidrocks00000000000000
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.10+17.10.20170619/docs/devel/hud-overview.xml0000664000175000017500000001231013121713174022473 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/docs/libhud/0000775000175000017500000000000013121716557017510 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/docs/libhud/libhud-sections.txt0000664000175000017500000000263613121713174023344 0ustar didrocksdidrocks00000000000000
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.10+17.10.20170619/docs/libhud/CMakeLists.txt0000664000175000017500000000125413121713174022242 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/docs/libhud/libhud.types0000664000175000017500000000012313121713174022031 0ustar didrocksdidrocks00000000000000hud_action_description_get_type hud_action_publisher_get_type hud_manager_get_type hud-14.10+17.10.20170619/docs/libhud/libhud-docs.xml0000664000175000017500000000200013121713174022407 0ustar didrocksdidrocks00000000000000 ]> libhud Docs Data Types Object Hierarchy API Index Index of deprecated API hud-14.10+17.10.20170619/docs/man/0000775000175000017500000000000013121716557017014 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/docs/man/hud-list-applications.xml0000664000175000017500000000171213121713174023744 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/docs/man/hud-dump-application.xml0000664000175000017500000000203713121713174023554 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/docs/man/CMakeLists.txt0000664000175000017500000000142613121713174021547 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/docs/man/hud-cli.xml0000664000175000017500000000152013121713174021051 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/docs/man/hud-verify-app-info.xml0000664000175000017500000000154613121713174023325 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/docs/libhud-client.msc0000664000175000017500000000103013121713174021452 0ustar didrocksdidrocks00000000000000msc { 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.10+17.10.20170619/docs/libhud-client/0000775000175000017500000000000013121716557020764 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/docs/libhud-client/libhud-client.types0000664000175000017500000000007113121713174024563 0ustar didrocksdidrocks00000000000000hud_client_query_get_type hud_client_connection_get_type hud-14.10+17.10.20170619/docs/libhud-client/libhud-client-docs.xml0000664000175000017500000000204613121713174025151 0ustar didrocksdidrocks00000000000000 ]> libhud-client Docs Data Types Object Hierarchy API Index Index of deprecated API hud-14.10+17.10.20170619/docs/libhud-client/CMakeLists.txt0000664000175000017500000000154213121713174023516 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/docs/libhud-client/libhud-client-sections.txt0000664000175000017500000000461613121713174026074 0ustar didrocksdidrocks00000000000000
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.10+17.10.20170619/docs/CMakeLists.txt0000664000175000017500000000043613121713174020774 0ustar didrocksdidrocks00000000000000include(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.10+17.10.20170619/docs/libhud-communication.msc0000664000175000017500000000077213121713174023055 0ustar didrocksdidrocks00000000000000msc { 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.10+17.10.20170619/docs/libhud-gtk/0000775000175000017500000000000013121716557020273 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/docs/libhud-gtk/libhud-gtk-docs.xml0000664000175000017500000000172213121713174023767 0ustar didrocksdidrocks00000000000000 ]> libhud-gtk Docs Data Types Object Hierarchy API Index Index of deprecated API hud-14.10+17.10.20170619/docs/libhud-gtk/CMakeLists.txt0000664000175000017500000000123413121713174023023 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/docs/libhud-gtk/libhud-gtk-sections.txt0000664000175000017500000000052213121713174024702 0ustar didrocksdidrocks00000000000000
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.10+17.10.20170619/docs/libhud-gtk/libhud-gtk.types0000664000175000017500000000003113121713174023375 0ustar didrocksdidrocks00000000000000hud_gtk_manager_get_type hud-14.10+17.10.20170619/po/0000775000175000017500000000000013121716557015727 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/po/POTFILES.skip0000664000175000017500000000030013121713174020025 0ustar didrocksdidrocks00000000000000src/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.10+17.10.20170619/po/POTFILES.in0000664000175000017500000000077613121713174017506 0ustar didrocksdidrocks00000000000000data/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.10+17.10.20170619/cmake/0000775000175000017500000000000013121716557016371 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/cmake/FindGObjectIntrospection.cmake0000664000175000017500000000376513121713174024275 0ustar didrocksdidrocks00000000000000# - 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.10+17.10.20170619/cmake/GlibGenerationTemplates.cmake0000664000175000017500000000307713121713174024142 0ustar didrocksdidrocks00000000000000message(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.10+17.10.20170619/cmake/FindVala.cmake0000664000175000017500000000442213121713174021051 0ustar didrocksdidrocks00000000000000# - 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.10+17.10.20170619/cmake/COPYING-CMAKE-SCRIPTS0000664000175000017500000000245713121713174021367 0ustar didrocksdidrocks00000000000000Redistribution 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.10+17.10.20170619/cmake/GtkDocScanGObjWrapper.cmake0000664000175000017500000000242213121713174023446 0ustar didrocksdidrocks00000000000000cmake_minimum_required(VERSION 2.6) if(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.10+17.10.20170619/cmake/UseVala.cmake0000664000175000017500000002067413121713174020734 0ustar didrocksdidrocks00000000000000# - 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.10+17.10.20170619/cmake/UseGObjectIntrospection.cmake0000664000175000017500000000746513121713174024152 0ustar didrocksdidrocks00000000000000# 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.10+17.10.20170619/cmake/UseMscgen.cmake0000664000175000017500000000237213121713174021260 0ustar didrocksdidrocks00000000000000cmake_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.10+17.10.20170619/cmake/UseGtkDoc.cmake0000664000175000017500000002147713121713174021226 0ustar didrocksdidrocks00000000000000# 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.10+17.10.20170619/cmake/UseConstantBuilder.cmake0000664000175000017500000000123213121713174023136 0ustar didrocksdidrocks00000000000000cmake_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.10+17.10.20170619/cmake/UseGdbusCodegen.cmake0000664000175000017500000000214613121713174022374 0ustar didrocksdidrocks00000000000000cmake_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.10+17.10.20170619/cmake/FindGtkDoc.cmake0000664000175000017500000000443413121713174021344 0ustar didrocksdidrocks00000000000000# 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.10+17.10.20170619/cmake/ListOperations.cmake0000664000175000017500000000073513121713174022347 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/cmake/ConstantBuilderTemplates.cmake0000664000175000017500000000073313121713174024345 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/cmake/UseGlibGeneration.cmake0000664000175000017500000000544513121713174022741 0ustar didrocksdidrocks00000000000000cmake_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.10+17.10.20170619/libhud-gtk/0000775000175000017500000000000013121716557017343 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/libhud-gtk/hud-gtk.pc.in0000664000175000017500000000037213121713174021631 0ustar didrocksdidrocks00000000000000libdir=@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.10+17.10.20170619/libhud-gtk/manager.h0000664000175000017500000000621413121713174021121 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-gtk/CMakeLists.txt0000664000175000017500000000343713121713174022102 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/libhud-gtk/manager.c0000664000175000017500000001676213121713174021125 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/libhud-gtk/hud-gtk.h0000664000175000017500000000214013121713174021044 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/tools/0000775000175000017500000000000013121716557016451 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tools/hud-cli-param.c0000664000175000017500000001356313121713174021240 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tools/hud-cli.c0000664000175000017500000000624013121713174020134 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tools/hud-cli-toolbar.c0000664000175000017500000000226213121713174021574 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/tools/hudkeywords/0000775000175000017500000000000013121716557021021 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tools/hudkeywords/README0000664000175000017500000000012013121713174021662 0ustar didrocksdidrocks00000000000000A tool for creating translation (po) and XML keyword files associated with HUD. hud-14.10+17.10.20170619/tools/hudkeywords/setup.py0000775000175000017500000000235713121713174022535 0ustar didrocksdidrocks00000000000000#!/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.10+17.10.20170619/tools/hudkeywords/hudkeywords/0000775000175000017500000000000013121716557023371 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tools/hudkeywords/hudkeywords/cli.py0000664000175000017500000000650113121713174024504 0ustar didrocksdidrocks00000000000000# 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.10+17.10.20170619/tools/hudkeywords/hudkeywords/po.py0000664000175000017500000000715713121713174024363 0ustar didrocksdidrocks00000000000000# 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.10+17.10.20170619/tools/hudkeywords/hudkeywords/__init__.py0000664000175000017500000000000013121713174025460 0ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tools/hudkeywords/CMakeLists.txt0000664000175000017500000000230613121713174023552 0ustar didrocksdidrocks00000000000000find_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.10+17.10.20170619/tools/hudkeywords/tests/0000775000175000017500000000000013121716557022163 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tools/hudkeywords/tests/cli_test.py0000664000175000017500000000335513121713174024341 0ustar didrocksdidrocks00000000000000# 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.10+17.10.20170619/tools/hudkeywords/tests/__init__.py0000664000175000017500000000366013121713174024271 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/tools/hudkeywords/tests/po_test.py0000664000175000017500000000363413121713174024210 0ustar didrocksdidrocks00000000000000# 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.10+17.10.20170619/tools/hudkeywords/bin/0000775000175000017500000000000013121716557021571 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/tools/hudkeywords/bin/hudkeywords0000775000175000017500000000153413121713174024062 0ustar didrocksdidrocks00000000000000#!/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.10+17.10.20170619/tools/CMakeLists.txt0000664000175000017500000000237313121713174021206 0ustar didrocksdidrocks00000000000000 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.10+17.10.20170619/tools/hud-cli-appstack.c0000664000175000017500000000622313121713174021741 0ustar didrocksdidrocks00000000000000/* 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.10+17.10.20170619/window-stack-bridge/0000775000175000017500000000000013121716557021155 5ustar didrocksdidrocks00000000000000hud-14.10+17.10.20170619/window-stack-bridge/BamfWindowStack.cpp0000664000175000017500000001670013121713174024700 0ustar didrocksdidrocks00000000000000/* * 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; } QString BamfWindow::service() const { return m_window.service(); } QString BamfWindow::path() const { return m_window.path(); } 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; } QStringList BamfWindowStack::GetWindowBusAddress(uint windowId) { const auto window = m_windowsById[windowId]; if (window == nullptr) { sendErrorReply(QDBusError::InvalidArgs, "Unable to find windowId"); return {}; } return {window->service(), window->path()}; } 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.10+17.10.20170619/window-stack-bridge/BamfWindowStack.h0000664000175000017500000000464313121713174024350 0ustar didrocksdidrocks00000000000000/* * 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(); QString service() const; QString path() const; 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; QStringList GetWindowBusAddress(uint windowId) 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.10+17.10.20170619/window-stack-bridge/CMakeLists.txt0000664000175000017500000000235013121713174023705 0ustar didrocksdidrocks00000000000000 if(${ENABLE_BAMF}) add_definitions( -DENABLE_BAMF=1 ) endif() if(${ENABLE_BAMF}) 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() 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 ) 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.10+17.10.20170619/window-stack-bridge/main.cpp0000664000175000017500000000260313121713174022576 0ustar didrocksdidrocks00000000000000/* * 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.10+17.10.20170619/window-stack-bridge/WindowStack.h0000664000175000017500000000155413121713174023560 0ustar didrocksdidrocks00000000000000/* * 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; #endif #endif /* WINDOWSTACK_H_ */ hud-14.10+17.10.20170619/window-stack-bridge/AbstractWindowStack.h0000664000175000017500000000357413121713174025250 0ustar didrocksdidrocks00000000000000/* * 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; virtual QStringList GetWindowBusAddress(uint windowId) = 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.10+17.10.20170619/window-stack-bridge/AbstractWindowStack.cpp0000664000175000017500000000321613121713174025574 0ustar didrocksdidrocks00000000000000/* * 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); }