preparation for new hildon (desktop and widgets) support
[simple-launcher] / launcher-item.cc
1 // This file is a part of Simple Launcher
2 //
3 // Copyright (C) 2006, 2007, Mikhail Sobolev
4 //
5 // Simple Launcher is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License version 2 as published by
7 // the Free Software Foundation.
8 //
9 // This program is distributed in the hope that it will be useful, but WITHOUT
10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12 // more details.
13 //
14 // You should have received a copy of the GNU General Public License along with
15 // this program; if not, write to the Free Software Foundation, Inc., 51
16 // Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 #include <string>
19
20 #include <libintl.h>
21 #include <math.h>
22
23 #include <glib/gmem.h>
24 #include <glib/gkeyfile.h>
25
26 #include "launcher-item.h"
27
28 GtkIconTheme *LauncherItem::ourTheme = NULL;
29
30 static const char *DESKTOP_ENTRY_GROUP = "Desktop Entry",
31                   *DESKTOP_ENTRY_TYPE_FIELD = "Type",
32                   *DESKTOP_ENTRY_ICON_FIELD = "Icon",
33                   *DESKTOP_ENTRY_NAME_FIELD = "Name",
34                   *DESKTOP_ENTRY_COMMENT_FIELD = "Comment",
35                   *DESKTOP_ENTRY_EXEC_FIELD = "Exec",
36                   *DESKTOP_ENTRY_SERVICE_FIELD = "X-Osso-Service",
37                   *DESKTOP_ENTRY_TEXT_DOMAIN = "X-Text-Domain";
38
39 static const char *DEFAULT_TEXT_DOMAIN = "maemo-af-desktop";
40 static const char *DEFAULT_APP_ICON = "qgn_list_gene_default_app";
41
42 class GKeyFileWrapper {
43 public:
44   GKeyFileWrapper() {
45     myKeyFile = g_key_file_new();
46   }
47
48  ~GKeyFileWrapper() {
49     if (myKeyFile != NULL) {
50       g_key_file_free(myKeyFile);
51     }
52   }
53
54   bool load(const std::string& name) {
55     GError *error = NULL;
56     bool result = g_key_file_load_from_file(myKeyFile, name.c_str(), G_KEY_FILE_NONE, &error);
57
58     if (error != NULL) {
59       g_error_free(error);
60     }
61
62     return result;
63   }
64
65   std::string getString(const gchar *group, const gchar *itemName) {
66     gchar *tempo = g_key_file_get_string(myKeyFile, group, itemName, NULL);
67     std::string result;
68
69     if (tempo != NULL) {
70       result.assign(tempo);
71
72       g_free(tempo);
73     }
74
75     return result;
76   }
77
78   std::string getLocaleString(const gchar *group, const gchar *itemName) {
79     gchar *tempo = g_key_file_get_locale_string(myKeyFile, group, itemName, NULL, NULL);
80     std::string result;
81
82     if (tempo != NULL) {
83       result.assign(tempo);
84
85       g_free(tempo);
86     }
87
88     return result;
89   }
90
91 private:
92   GKeyFile *myKeyFile;
93 };
94
95 LauncherItem::LauncherItem(): myEnabled(false) {
96 }
97
98 LauncherItem::~LauncherItem() {
99 }
100
101 std::string LauncherItem::translateString(const std::string& what) const {
102   if (what.empty()) {
103     return what;
104   } else {
105     return dgettext(myTextDomain.empty() ? DEFAULT_TEXT_DOMAIN : myTextDomain.c_str(), what.c_str());
106   }
107 }
108
109 bool LauncherItem::load(const std::string& filename) {
110   GKeyFileWrapper key_file;
111
112   for (;;) {
113     myFileName = filename;
114
115     if (!key_file.load(filename)) {
116       break;
117     }
118
119     if (key_file.getString(DESKTOP_ENTRY_GROUP, DESKTOP_ENTRY_TYPE_FIELD) != "Application") {
120       break;
121     }
122
123     myName = key_file.getLocaleString(DESKTOP_ENTRY_GROUP, DESKTOP_ENTRY_NAME_FIELD);
124     myComment = key_file.getLocaleString(DESKTOP_ENTRY_GROUP, DESKTOP_ENTRY_COMMENT_FIELD);
125     myIcon = key_file.getString(DESKTOP_ENTRY_GROUP, DESKTOP_ENTRY_ICON_FIELD);
126     myService = key_file.getString(DESKTOP_ENTRY_GROUP, DESKTOP_ENTRY_SERVICE_FIELD);
127     myExec = key_file.getString(DESKTOP_ENTRY_GROUP, DESKTOP_ENTRY_EXEC_FIELD);
128     myTextDomain = key_file.getString(DESKTOP_ENTRY_GROUP, DESKTOP_ENTRY_TEXT_DOMAIN);
129
130     break;
131   }
132
133   return (myEnabled = checkSanity());
134 }
135
136 // The function below is taken verbatim from exo library -- xfce supporting library
137 static GdkPixbuf *exo_gdk_pixbuf_scale_ratio(GdkPixbuf *source, gint dest_size) {
138   gdouble wratio, hratio;
139   gint    source_width, source_height;
140   gint    dest_width, dest_height;
141
142   source_width = gdk_pixbuf_get_width(source);
143   source_height = gdk_pixbuf_get_height(source);
144
145   wratio = (gdouble)source_width / (gdouble)dest_size;
146   hratio = (gdouble)source_height / (gdouble)dest_size;
147
148   if (hratio > wratio) {
149     dest_width = (gint)rint(source_width / hratio);
150     dest_height = dest_size;
151   } else {
152     dest_width = dest_size;
153     dest_height = (gint)rint(source_height / wratio);
154   }
155
156   return gdk_pixbuf_scale_simple(source, MAX(dest_width, 1), MAX(dest_height, 1), GDK_INTERP_BILINEAR);
157 }
158
159 GdkPixbuf *LauncherItem::getIcon(int icon_size) const {
160   if (ourTheme == NULL) {
161     ourTheme = gtk_icon_theme_get_default();
162   }
163
164   GdkPixbuf *pixbuf = NULL;
165   GError *error = NULL;
166
167   if (!myIcon.empty()) {
168     pixbuf = gtk_icon_theme_load_icon(ourTheme, myIcon.c_str(), icon_size, GTK_ICON_LOOKUP_NO_SVG, &error);
169
170     if (error != NULL) {
171       g_error_free(error);
172       error = NULL;
173     }
174   }
175
176   if (pixbuf == NULL) {
177     pixbuf = gtk_icon_theme_load_icon(ourTheme, DEFAULT_APP_ICON, icon_size, GTK_ICON_LOOKUP_NO_SVG, &error);
178
179     if (error != NULL) {
180       g_error_free(error);
181       error = NULL;
182     }
183   }
184
185   if (pixbuf != NULL) {
186     GdkPixbuf *tempo;
187
188     if (gdk_pixbuf_get_width(pixbuf) > icon_size || gdk_pixbuf_get_height(pixbuf) > icon_size) {
189       tempo = exo_gdk_pixbuf_scale_ratio(pixbuf, icon_size);
190     } else {
191       tempo = gdk_pixbuf_copy(pixbuf);
192     }
193
194     g_object_unref(pixbuf);
195
196     pixbuf = tempo;
197   }
198
199   return pixbuf;
200 }
201
202 // vim:ts=2:sw=2:et