Back to index

unity  6.0.0
Hud.cpp
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003  * Copyright (C) 2011 Canonical Ltd
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 3 as
00007  * published by the Free Software Foundation.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  *
00017  * Authored by: Gordon Allott <gord.allott@canonical.com>
00018  */
00019 //
00020 #include "Hud.h"
00021 
00022 #include <gio/gio.h>
00023 #include <glib.h>
00024 #include <NuxCore/Logger.h>
00025 #include "GLibWrapper.h"
00026 #include "GLibDBusProxy.h"
00027 
00028 #include "config.h"
00029 
00030 #include <sigc++/bind.h>
00031 
00032 namespace unity
00033 {
00034 namespace hud
00035 {
00036 
00037 namespace
00038 {
00039 nux::logging::Logger logger("unity.hud.hud");
00040 const int request_number_of_results = 6;
00041 }
00042 
00043 // Impl classes
00044 class HudImpl
00045 {
00046 public:
00047   HudImpl(std::string const& dbus_name,
00048           std::string const& dbus_path,
00049           Hud *parent)
00050   : query_key_(NULL)
00051   , proxy_(dbus_name, dbus_path, "com.canonical.hud")
00052   , parent_(parent)
00053   {
00054     LOG_DEBUG(logger) << "Hud init with name: " << dbus_name << "and path: " << dbus_path;
00055     proxy_.connected.connect([&]() {
00056       LOG_DEBUG(logger) << "Hud Connected";
00057       parent_->connected = true;
00058     });
00059 
00060     proxy_.Connect("UpdatedQuery", sigc::mem_fun(this, &HudImpl::UpdateQueryCallback));
00061   }
00062 
00063   void QueryCallback(GVariant* data);
00064   void UpdateQueryCallback(GVariant* data);
00065   void BuildQueries(GVariant* query_array);
00066   void ExecuteByKey(GVariant* key, unsigned int timestamp);
00067   void ExecuteQueryByStringCallback(GVariant* query, unsigned int timestamp);
00068   void CloseQuery();
00069 
00070   GVariant* query_key_;
00071   Hud::Queries queries_;
00072   glib::DBusProxy proxy_;
00073   Hud* parent_;
00074 };
00075 
00076 void HudImpl::ExecuteByKey(GVariant* key, unsigned int timestamp)
00077 {
00078   LOG_DEBUG(logger) << "Executing by Key";
00079 
00080   GVariantBuilder tuple;
00081   g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE);
00082   g_variant_builder_add_value(&tuple, g_variant_new_variant(key));
00083   g_variant_builder_add_value(&tuple, g_variant_new_uint32(timestamp));
00084 
00085   proxy_.Call("ExecuteQuery", g_variant_builder_end(&tuple));
00086 }
00087 
00088 void HudImpl::ExecuteQueryByStringCallback(GVariant* query, unsigned int timestamp)
00089 {
00090   if (g_variant_n_children(query) < 3)
00091   {
00092     LOG_ERROR(logger) << "Received (" << g_variant_n_children(query) << ") children in a query, expected 3";
00093     return;
00094   }
00095 
00096   queries_.clear();
00097 
00098   GVariant* query_key = g_variant_get_child_value(query, 2);
00099   query_key_ = query_key;
00100 
00101   GVariant* queries = g_variant_get_child_value(query, 1);
00102   BuildQueries(queries);
00103   g_variant_unref(queries);
00104 
00105   if (queries_.empty() == false)
00106   {
00107     // we now execute based off the first result
00108     ExecuteByKey(queries_.front()->key, timestamp);
00109     CloseQuery();
00110   }
00111 }
00112 
00113 void HudImpl::QueryCallback(GVariant* query)
00114 {
00115   if (g_variant_n_children(query) < 3)
00116   {
00117     LOG_ERROR(logger) << "Received (" << g_variant_n_children(query) << ") children in a query, expected 3";
00118     return;
00119   }
00120   queries_.clear();
00121 
00122   // extract the information from the GVariants
00123   GVariant* target = g_variant_get_child_value(query, 0);
00124   g_variant_unref(target);
00125 
00126   GVariant* query_key = g_variant_get_child_value(query, 2);
00127   query_key_ = query_key;
00128 
00129   GVariant* queries = g_variant_get_child_value(query, 1);
00130   BuildQueries(queries);
00131   g_variant_unref(queries);
00132 
00133   parent_->queries_updated.emit(queries_);
00134 }
00135 
00136 void HudImpl::UpdateQueryCallback(GVariant* query)
00137 {
00138   if (g_variant_n_children(query) < 3)
00139   {
00140     LOG_ERROR(logger) << "Received (" << g_variant_n_children(query) << ") children in a query, expected 3";
00141     return;
00142   }
00143   // as we are expecting an update, we want to check
00144   // and make sure that we are the actual receivers of
00145   // the signal
00146 
00147   GVariant* query_key = g_variant_get_child_value(query, 2);
00148   if (query_key_ && g_variant_equal(query_key_, query_key))
00149   {
00150     queries_.clear();
00151     GVariant* queries = g_variant_get_child_value(query, 1);
00152     BuildQueries(queries);
00153     g_variant_unref(queries);
00154     parent_->queries_updated.emit(queries_);
00155   }
00156 }
00157 
00158 void HudImpl::BuildQueries(GVariant* query_array)
00159 {
00160   GVariantIter iter;
00161   g_variant_iter_init(&iter, query_array);
00162   gchar* formatted_text;
00163   gchar* icon;
00164   gchar* item_icon;
00165   gchar* completion_text;
00166   gchar* shortcut;
00167   GVariant* key = NULL;
00168 
00169   while (g_variant_iter_loop(&iter, "(sssssv)",
00170          &formatted_text, &icon, &item_icon, &completion_text, &shortcut, &key))
00171   {
00172     queries_.push_back(Query::Ptr(new Query(formatted_text,
00173                                             icon,
00174                                             item_icon,
00175                                             completion_text,
00176                                             shortcut,
00177                                             key)));
00178   }
00179 }
00180 
00181 void HudImpl::CloseQuery()
00182 {
00183   if (query_key_ == NULL)
00184   {
00185     LOG_WARN(logger) << "Attempted to close the hud connection without starting it";
00186   }
00187   else
00188   {
00189     GVariant* paramaters = g_variant_new("(v)", query_key_);
00190     proxy_.Call("CloseQuery", paramaters);
00191     g_variant_unref(query_key_);
00192     query_key_ = NULL;
00193     queries_.clear();
00194   }
00195 }
00196 
00197 
00198 Hud::Hud(std::string const& dbus_name,
00199          std::string const& dbus_path)
00200     : connected(false)
00201     , pimpl_(new HudImpl(dbus_name, dbus_path, this))
00202 {
00203   pimpl_->parent_ = this;
00204 }
00205 
00206 Hud::~Hud()
00207 {
00208   delete pimpl_;
00209 }
00210 
00211 void Hud::RequestQuery(std::string const& search_string)
00212 {
00213   LOG_DEBUG(logger) << "Getting Query: " << search_string;
00214   if (pimpl_->query_key_ != NULL)
00215   {
00216     CloseQuery();
00217   }
00218 
00219   GVariant* paramaters = g_variant_new("(si)",
00220                                        search_string.c_str(),
00221                                        request_number_of_results);
00222   pimpl_->proxy_.Call("StartQuery", paramaters, sigc::mem_fun(this->pimpl_, &HudImpl::QueryCallback));
00223 }
00224 
00225 
00226 void Hud::ExecuteQuery(Query::Ptr query, unsigned int timestamp)
00227 {
00228   LOG_DEBUG(logger) << "Executing query: " << query->formatted_text;
00229   pimpl_->ExecuteByKey(query->key, timestamp);
00230 }
00231 
00232 void Hud::ExecuteQueryBySearch(std::string execute_string, unsigned int timestamp)
00233 {
00234   //Does a search then executes the result based on that search
00235   LOG_DEBUG(logger) << "Executing by string" << execute_string;
00236   if (pimpl_->query_key_ != NULL)
00237   {
00238     CloseQuery();
00239   }
00240 
00241   GVariant* paramaters = g_variant_new("(si)",
00242                                        execute_string.c_str(),
00243                                        1);
00244 
00245   auto functor = sigc::mem_fun(this->pimpl_, &HudImpl::ExecuteQueryByStringCallback);
00246 
00247   pimpl_->proxy_.Call("StartQuery", paramaters, sigc::bind(functor, timestamp));
00248 }
00249 
00250 void Hud::CloseQuery()
00251 {
00252   //Send close hint to the hud
00253   pimpl_->CloseQuery();
00254 }
00255 
00256 }
00257 }