/* * Copyright © 2014 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * 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 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 . * * Authored by: Pete Woods */ #include #include #include #include using namespace std; namespace lomiri { namespace gmenuharness { namespace { static void gdbus_connection_deleter(GDBusConnection* connection) { // if (!g_dbus_connection_is_closed(connection)) // { // g_dbus_connection_close_sync(connection, nullptr, nullptr); // } g_clear_object(&connection); } } struct MenuMatcher::Parameters::Priv { string m_busName; vector> m_actions; string m_menuObjectPath; }; MenuMatcher::Parameters::Parameters(const string& busName, const vector>& actions, const string& menuObjectPath) : p(new Priv) { p->m_busName = busName; p->m_actions = actions; p->m_menuObjectPath = menuObjectPath; } MenuMatcher::Parameters::~Parameters() { } MenuMatcher::Parameters::Parameters(const Parameters& other) : p(new Priv) { *this = other; } MenuMatcher::Parameters::Parameters(Parameters&& other) { *this = move(other); } MenuMatcher::Parameters& MenuMatcher::Parameters::operator=(const Parameters& other) { p->m_busName = other.p->m_busName; p->m_actions = other.p->m_actions; p->m_menuObjectPath = other.p->m_menuObjectPath; return *this; } MenuMatcher::Parameters& MenuMatcher::Parameters::operator=(Parameters&& other) { p = move(other.p); return *this; } struct MenuMatcher::Priv { Priv(const Parameters& parameters) : m_parameters(parameters) { } Parameters m_parameters; vector m_items; shared_ptr m_system; shared_ptr m_session; shared_ptr m_menu; map> m_actions; }; MenuMatcher::MenuMatcher(const Parameters& parameters) : p(new Priv(parameters)) { p->m_system.reset(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, nullptr), &gdbus_connection_deleter); g_dbus_connection_set_exit_on_close(p->m_system.get(), false); p->m_session.reset(g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, nullptr), &gdbus_connection_deleter); g_dbus_connection_set_exit_on_close(p->m_session.get(), false); p->m_menu.reset( G_MENU_MODEL( g_dbus_menu_model_get( p->m_session.get(), p->m_parameters.p->m_busName.c_str(), p->m_parameters.p->m_menuObjectPath.c_str())), &g_object_deleter); for (const auto& action : p->m_parameters.p->m_actions) { shared_ptr actionGroup( G_ACTION_GROUP( g_dbus_action_group_get( p->m_session.get(), p->m_parameters.p->m_busName.c_str(), action.second.c_str())), &g_object_deleter); p->m_actions[action.first] = actionGroup; } } MenuMatcher::~MenuMatcher() { } MenuMatcher& MenuMatcher::item(const MenuItemMatcher& item) { p->m_items.emplace_back(item); return *this; } void MenuMatcher::match(MatchResult& matchResult) const { vector location; while (true) { MatchResult childMatchResult(matchResult.createChild()); int menuSize = g_menu_model_get_n_items(p->m_menu.get()); if (p->m_items.size() > (unsigned int) menuSize) { childMatchResult.failure( location, "Row count mismatch, expected " + to_string(p->m_items.size()) + " but found " + to_string(menuSize)); } else { for (size_t i = 0; i < p->m_items.size(); ++i) { const auto& matcher = p->m_items.at(i); matcher.match(childMatchResult, location, p->m_menu, p->m_actions, i); } } if (childMatchResult.success()) { matchResult.merge(childMatchResult); break; } else { if (matchResult.hasTimedOut()) { matchResult.merge(childMatchResult); break; } menuWaitForItems(p->m_menu); } } } MatchResult MenuMatcher::match() const { MatchResult matchResult; match(matchResult); return matchResult; } } // namespace gmenuharness } // namespace lomiri