Back to index

unity  6.0.0
FavoriteStoreGSettings.cpp
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003 * Copyright (C) 2010 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: Neil Jagdish Patel <neil.patel@canonical.com>
00018 */
00019 
00020 #include <gio/gdesktopappinfo.h>
00021 #include <NuxCore/Logger.h>
00022 #include <UnityCore/DesktopUtilities.h>
00023 
00024 #include "FavoriteStoreGSettings.h"
00025 #include "FavoriteStorePrivate.h"
00026 
00027 #include "config.h"
00028 
00036 namespace unity
00037 {
00038 namespace internal
00039 {
00040 
00041 namespace
00042 {
00043 
00044 nux::logging::Logger logger("unity.favorites");
00045 
00046 const char* SETTINGS_NAME = "com.canonical.Unity.Launcher";
00047 
00048 void on_settings_updated(GSettings* settings,
00049                          const gchar* key,
00050                          FavoriteStoreGSettings* self);
00051 
00052 }
00053 
00054 FavoriteStoreGSettings::FavoriteStoreGSettings()
00055   : settings_(g_settings_new(SETTINGS_NAME))
00056   , ignore_signals_(false)
00057 {
00058   Init();
00059 }
00060 
00061 FavoriteStoreGSettings::FavoriteStoreGSettings(GSettingsBackend* backend)
00062   : settings_(g_settings_new_with_backend(SETTINGS_NAME, backend))
00063   , ignore_signals_(false)
00064 {
00065   Init();
00066 }
00067 
00068 void FavoriteStoreGSettings::Init()
00069 {
00070   g_signal_connect(settings_, "changed", G_CALLBACK(on_settings_updated), this);
00071   Refresh();
00072 }
00073 
00074 
00075 void FavoriteStoreGSettings::Refresh()
00076 {
00077   FillList(favorites_);
00078 }
00079 
00080 void FavoriteStoreGSettings::FillList(FavoriteList& list)
00081 {
00082   list.clear();
00083 
00084   gchar** favs = g_settings_get_strv(settings_, "favorites");
00085 
00086   for (int i = 0; favs[i] != NULL; ++i)
00087   {
00088     // We will be storing either full /path/to/desktop/files or foo.desktop id's
00089     if (favs[i][0] == '/')
00090     {
00091       if (g_file_test(favs[i], G_FILE_TEST_EXISTS))
00092       {
00093         list.push_back(favs[i]);
00094       }
00095       else
00096       {
00097         LOG_WARNING(logger) << "Unable to load desktop file: "
00098                             << favs[i];
00099       }
00100     }
00101     else
00102     {
00103       glib::Object<GDesktopAppInfo> info(g_desktop_app_info_new(favs[i]));
00104       const char* filename = 0;
00105       if (info)
00106         filename = g_desktop_app_info_get_filename(info);
00107 
00108       if (filename)
00109       {
00110         list.push_back(filename);
00111       }
00112       else
00113       {
00114         LOG_WARNING(logger) << "Unable to load GDesktopAppInfo for '" << favs[i] << "'";
00115       }
00116     }
00117   }
00118 
00119   g_strfreev(favs);
00120 }
00121 
00122 FavoriteList const&  FavoriteStoreGSettings::GetFavorites()
00123 {
00124   return favorites_;
00125 }
00126 
00127 void FavoriteStoreGSettings::AddFavorite(std::string const& desktop_path, int position)
00128 {
00129   int size = favorites_.size();
00130   if (desktop_path.empty() || position > size)
00131     return;
00132 
00133   if (position < 0)
00134   {
00135     // It goes on the end.
00136     favorites_.push_back(desktop_path);
00137   }
00138   else
00139   {
00140     FavoriteList::iterator pos = favorites_.begin();
00141     std::advance(pos, position);
00142     favorites_.insert(pos, desktop_path);
00143   }
00144 
00145   SaveFavorites(favorites_);
00146   Refresh();
00147 }
00148 
00149 void FavoriteStoreGSettings::RemoveFavorite(std::string const& desktop_path)
00150 {
00151   if (desktop_path.empty() || desktop_path[0] != '/')
00152     return;
00153 
00154   FavoriteList::iterator pos = std::find(favorites_.begin(), favorites_.end(), desktop_path);
00155   if (pos == favorites_.end())
00156   {
00157     return;
00158   }
00159 
00160   favorites_.erase(pos);
00161   SaveFavorites(favorites_);
00162   Refresh();
00163 }
00164 
00165 void FavoriteStoreGSettings::MoveFavorite(std::string const& desktop_path, int position)
00166 {
00167   int size = favorites_.size();
00168   if (desktop_path.empty() || position > size)
00169     return;
00170 
00171   FavoriteList::iterator pos = std::find(favorites_.begin(), favorites_.end(), desktop_path);
00172   if (pos == favorites_.end())
00173   {
00174     return;
00175   }
00176 
00177   favorites_.erase(pos);
00178   if (position < 0)
00179   {
00180     // It goes on the end.
00181     favorites_.push_back(desktop_path);
00182   }
00183   else
00184   {
00185     FavoriteList::iterator insert_pos = favorites_.begin();
00186     std::advance(insert_pos, position);
00187     favorites_.insert(insert_pos, desktop_path);
00188   }
00189 
00190   SaveFavorites(favorites_);
00191   Refresh();
00192 }
00193 
00194 void FavoriteStoreGSettings::SetFavorites(FavoriteList const& favorites)
00195 {
00196   SaveFavorites(favorites);
00197   Refresh();
00198 }
00199 
00200 void FavoriteStoreGSettings::SaveFavorites(FavoriteList const& favorites, bool ignore)
00201 {
00202   const int size = favorites.size();
00203   const char* favs[size + 1];
00204   favs[size] = NULL;
00205 
00206   int index = 0;
00207   // Since we don't always save the full path, we store the values we are
00208   // actually going to save in a different list.
00209   auto system_dirs = DesktopUtilities::GetDataDirectories();
00210   FavoriteList values;
00211   for (FavoriteList::const_iterator i = favorites.begin(), end = favorites.end();
00212        i != end; ++i, ++index)
00213   {
00214     // By using insert we get the iterator to the newly inserted string value.
00215     // That way we can use the c_str() method to access the const char* for
00216     // the string that we are going to save.  This way we know that the pointer
00217     // is valid for the lifetime of the favs array usage in the method call to
00218     // set the settings, and that we aren't referencing a temporary.
00219     std::string const& desktop_id = DesktopUtilities::GetDesktopID(system_dirs, *i);
00220     FavoriteList::iterator iter = values.insert(values.end(), desktop_id);
00221     favs[index] = iter->c_str();
00222   }
00223 
00224   ignore_signals_ = ignore;
00225   if (!g_settings_set_strv(settings_, "favorites", favs))
00226   {
00227     LOG_WARNING(logger) << "Saving favorites failed.";
00228   }
00229   ignore_signals_ = false;
00230 }
00231 
00232 void FavoriteStoreGSettings::Changed(std::string const& key)
00233 {
00234   if (ignore_signals_ or key != "favorites")
00235     return;
00236 
00237   FavoriteList old(favorites_);
00238   FillList(favorites_);
00239 
00240   auto newbies = impl::GetNewbies(old, favorites_);
00241 
00242   for (auto it : favorites_)
00243   {
00244     if (std::find(newbies.begin(), newbies.end(), it) == newbies.end())
00245       continue;
00246 
00247     std::string pos;
00248     bool before;
00249 
00250     impl::GetSignalAddedInfo(favorites_, newbies , it, pos, before);
00251     favorite_added.emit(it, pos, before);
00252   }
00253 
00254   for (auto it : impl::GetRemoved(old, favorites_))
00255   {
00256     favorite_removed.emit(it);
00257   }
00258 
00259   if (impl::NeedToBeReordered(old, favorites_))
00260     reordered.emit();
00261 
00262 }
00263 
00264 namespace
00265 {
00266 
00267 void on_settings_updated(GSettings* settings,
00268                          const gchar* key,
00269                          FavoriteStoreGSettings* self)
00270 {
00271   if (settings and key)
00272   {
00273     self->Changed(key);
00274   }
00275 }
00276 
00277 } // anonymous namespace
00278 
00279 } // namespace internal
00280 } // namespace unity