1 // This file is a part of Simple Launcher
3 // Copyright (C) 2006, 2007, 2008 Mikhail Sobolev <mss@mawhrin.net>
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.
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
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
26 #include "simple-launcher.h"
28 #define SL_APPLET_DBUS_NAME "simple-launcher"
29 #define SL_APPLET_VERSION "0.0"
31 // SimpleLauncherApplet implementation
33 char *SimpleLauncherApplet::ourDirs[] = {
34 "/usr/share/applications/hildon",
38 // SimpleLauncherApplet::SimpleLauncherApplet() : myMainSettings(myClient.getKey(SL_APPLET_GCONF_PATH)), myContext(NULL), myWidget(NULL), myParent(NULL) {
39 SimpleLauncherApplet::SimpleLauncherApplet(const std::string& base) : myContext(NULL), myWidget(NULL), myParent(NULL), myValidItems(0), myTransparent(GConfKey(base), "transparent", false), myIconSize(GConfKey(base), "icon_size", 48) {
42 bool SimpleLauncherApplet::doInit() {
43 if ((myContext = osso_initialize(SL_APPLET_DBUS_NAME, SL_APPLET_VERSION, FALSE, NULL)) == NULL) {
44 g_debug("sla-applet: failed to initialize the osso layer");
57 SimpleLauncherApplet::~SimpleLauncherApplet() {
60 // This does not seem to be necessary
61 if (myWidget != NULL) {
62 gtk_widget_destroy(myWidget);
66 if (myContext != NULL) {
67 osso_deinitialize(myContext);
72 void SimpleLauncherApplet::addItem(LauncherItems& items, const std::string& name, bool enabled) {
73 if (!items.exists(name)) {
74 LaunchableItem *item = new LaunchableItem();
84 items.add(name, item);
88 // {{{ Configuration file managment
89 static const gchar *getConfigFileName() {
90 static gchar *configFileName = NULL;
92 if (configFileName == NULL) {
93 configFileName = g_build_filename(g_get_home_dir(), ".slarc", NULL);
96 return configFileName;
99 void SimpleLauncherApplet::loadConfig() {
100 std::ifstream config(getConfigFileName());
103 char *buffer = new char [1024];
105 while (config.getline(buffer, 1024)) {
106 char *p = strchr(buffer, ',');
112 addItem(myItems, buffer, (p != NULL && (*p == '1' || *p == 'y' || *p == 'Y')));
119 void SimpleLauncherApplet::saveConfig() {
120 // TODO: make saving config an atomic operation
121 std::ofstream config(getConfigFileName());
124 for (size_t i = 0 ; i < myItems.size() ; ++i) {
125 config << myItems.name(i) << ',' << myItems[i]->isEnabled() << std::endl;
132 void SimpleLauncherApplet::updateItems(LauncherItems& items) {
133 for (int i = 0 ; ourDirs[i] != NULL ; ++i) {
134 processDirectory(items, ourDirs[i]);
138 void SimpleLauncherApplet::processDirectory(LauncherItems& items, const std::string& dirname) {
139 DIR *dir = opendir(dirname.c_str());
142 const std::string namePrefix = dirname + "/";
143 std::string shortName;
144 std::string desktopExtension = ".desktop";
147 while ((file = readdir(dir)) != 0) {
148 shortName = file->d_name;
149 if ((shortName == ".") || (shortName == "..")) {
153 if ((shortName.length() >= desktopExtension.length()) && (shortName.compare(shortName.length() - desktopExtension.length(), desktopExtension.length(), desktopExtension) == 0)) {
154 addItem(items, namePrefix+shortName, false);
162 bool SimpleLauncherApplet::initWidget() {
163 myWidget = gtk_hbox_new(false, 0);
165 if (myWidget != NULL) {
169 return myWidget != NULL;
172 void SimpleLauncherApplet::updateWidget() {
173 gtk_container_foreach(GTK_CONTAINER(myWidget), (GtkCallback)gtk_widget_destroy, NULL);
175 GtkSizeGroup *group = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
179 for (size_t i = 0 ; i < myItems.size() ; ++i) {
180 LauncherItem *item = myItems[i];
182 if (item != NULL && item->isEnabled()) {
183 GtkWidget *button = gtk_event_box_new();
185 gtk_widget_set_events(button, GDK_BUTTON_PRESS_MASK);
186 g_signal_connect(button, "button-press-event", G_CALLBACK(_button_pressed), this);
188 gtk_event_box_set_visible_window(GTK_EVENT_BOX(button), !myTransparent.value());
191 GdkPixbuf *pixbuf = item->getIcon(myIconSize.value());
192 gtk_container_add(GTK_CONTAINER(button), gtk_image_new_from_pixbuf(pixbuf));
193 g_object_unref(G_OBJECT(pixbuf));
196 gtk_object_set_user_data(GTK_OBJECT(button), item);
198 gtk_size_group_add_widget(group, button);
200 gtk_box_pack_start(GTK_BOX(myWidget), GTK_WIDGET(button), false, false, 0);
206 g_object_unref(G_OBJECT(group));
208 gtk_widget_set_size_request(myWidget, getWidth(), getHeight());
210 gtk_widget_show_all(myWidget);
213 void SimpleLauncherApplet::_button_pressed(GtkWidget *button, GdkEventButton *event, void *self) {
214 ((SimpleLauncherApplet *)self)->buttonPressed(button, event);
217 void SimpleLauncherApplet::buttonPressed(GtkWidget *button, GdkEventButton *event) {
218 if (button != NULL && event->button == 1) {
219 LaunchableItem *item = (LaunchableItem *)gtk_object_get_user_data(GTK_OBJECT(button));
222 item->activate(myContext);
227 GtkWidget *SimpleLauncherApplet::settings(GtkWindow *parent) {
228 myParent = parent; // FIXME: Ugly piece of code :(
230 GtkWidget *menuItem = gtk_menu_item_new_with_label("Launcher settings...");
232 g_signal_connect(menuItem, "activate", G_CALLBACK(_run_dialog), this);
237 void SimpleLauncherApplet::_run_dialog(GtkMenuItem *, void *self) {
238 ((SimpleLauncherApplet *)self)->runDialog();
241 void SimpleLauncherApplet::runDialog() {
242 // We update the items before using them to avoid a small memory leak
243 // FIXME: deal with the situation in a better way (figure it out first :))
244 updateItems(myItems); // User requested 'settings', let's give her the latest stuff :)
246 LauncherItems newItems = myItems;
248 // TODO: make it nicer... this code is ugly :(
249 SettingsDialog dialog(myParent, newItems, myTransparent, myIconSize);
251 switch (dialog.run()) {
252 case GTK_RESPONSE_OK:
254 dialog.updateValues(); // FIXME: hackish :( make it better
256 saveConfig(); // save it immediately!
260 case GTK_RESPONSE_CANCEL:
264 ; // FIXME: do I want to do anything in here?
267 // newItems.clear(); // TODO: do I really need it?
270 int SimpleLauncherApplet::getWidth() const {
272 return myIconSize.value() * myValidItems;
274 return myIconSize.value();
278 int SimpleLauncherApplet::getHeight() const {
279 return myIconSize.value();
282 void SimpleLauncherApplet::getBackgroundColour(double& red, double& green, double& blue, double alpha) const {
284 red = 1.0; green = 1.0; blue = 1.0;
286 alpha = myTransparent.value() ? 0.0 : 1.0;