Merge branch 'use-libfm'
authorAndriy Grytsenko <andrej@rep.kiev.ua>
Sat, 15 Feb 2014 11:51:29 +0000 (13:51 +0200)
committerAndriy Grytsenko <andrej@rep.kiev.ua>
Sat, 15 Feb 2014 11:51:29 +0000 (13:51 +0200)
Conflicts:
src/plugin.h

47 files changed:
configure.ac
data/Makefile.am
data/ui/launchbar.glade
data/ui/panel-pref.glade
src/Makefile.am
src/conf.c [new file with mode: 0644]
src/conf.h [new file with mode: 0644]
src/configurator.c
src/gtk-run.c
src/icon-grid.c
src/menu-policy.c
src/misc.c
src/misc.h
src/panel.c
src/panel.h
src/plugin.c
src/plugin.h
src/plugins/batt/batt.c
src/plugins/cpu/cpu.c
src/plugins/cpufreq/cpufreq.c
src/plugins/dclock.c
src/plugins/deskno/deskno.c
src/plugins/dirmenu.c
src/plugins/image.c
src/plugins/indicator/indicator.c
src/plugins/kbled/kbled.c
src/plugins/launchbar.c
src/plugins/menu.c
src/plugins/monitors/monitors.c
src/plugins/netstat/netstat.c
src/plugins/netstatus/netstatus-icon.c
src/plugins/netstatus/netstatus.c
src/plugins/pager.c
src/plugins/separator.c
src/plugins/space.c
src/plugins/taskbar.c
src/plugins/test.c
src/plugins/thermal/thermal.c
src/plugins/tray.c
src/plugins/volume/volume.c
src/plugins/volumealsa/volumealsa.c
src/plugins/wincmd.c
src/plugins/wnckpager/wnckpager.c
src/plugins/xkb/xkb-plugin.c
src/plugins/xkb/xkb.h
src/private.h [new file with mode: 0644]
src/xml-purge.c [deleted file]

index 439ace8..8dcc393 100644 (file)
@@ -34,9 +34,9 @@ esac],[])
 
 if test "x$enable_gtk3" = "xyes" ; then
   CFLAGS="$CFLAGS -DENABLE_GTK3"
-  pkg_modules="$pkg_modules gtk+-3.0"
+  pkg_modules="$pkg_modules gtk+-3.0 libfm-gtk3 >= 1.2.0"
 else
-  pkg_modules="$pkg_modules gtk+-2.0 >= 2.16.0"
+  pkg_modules="$pkg_modules gtk+-2.0 >= 2.16.0 libfm-gtk >= 1.2.0"
 fi
 
 pkg_modules="$pkg_modules \
@@ -44,7 +44,6 @@ pkg_modules="$pkg_modules \
              gthread-2.0 \
              gmodule-2.0 \
              libmenu-cache"
-#             libstartup-notification-1.0"
 PKG_CHECK_MODULES(PACKAGE, [$pkg_modules])
 AC_SUBST(PACKAGE_CFLAGS)
 AC_SUBST(PACKAGE_LIBS)
@@ -119,16 +118,6 @@ AC_ARG_ENABLE(man,
        [enable_man=no]
 )
 
-AC_ARG_ENABLE([cast-checks],
-    AS_HELP_STRING([--enable-cast-checks],
-               [enable Glib casting checks (default: disable)]),
-               cast_checks=$enableval, cast_checks="no")
-G_CAST_CHECKS=""
-if test x"$cast_checks" = "xno"; then
-    G_CAST_CHECKS="-DG_DISABLE_CAST_CHECKS"
-fi
-AC_SUBST(G_CAST_CHECKS)
-
 dnl linker tweaking
 # The function of the link flag --as-needed is to prevent unnecesary linking.
 # Example: A -> B -> C
@@ -387,6 +376,29 @@ fi
 
 AM_CONDITIONAL(ENABLE_REGENERATE_MAN, test "x$enable_man" != "xno")
 
+AC_ARG_ENABLE(debug,
+    [AC_HELP_STRING([--enable-debug],
+        [enable debug support @<:@default=no@:>@])],
+    [enable_debug="${enableval}"],
+    [enable_debug=no]
+)
+if test "$enable_debug" = "yes"; then
+    # turn on debug and disable optimization
+    CPPFLAGS="$CPPFLAGS -DG_ENABLE_DEBUG -O0 -g"
+    case "$CC" in
+    gcc*)
+        CPPFLAGS="$CPPFLAGS -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Werror=implicit-function-declaration"
+        ;;
+    *)
+        ;;
+    esac
+    dnl Be more strict on portability
+    #CPPFLAGS="$CPPFLAGS -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=700"
+else
+    # turn off glib debug checks
+    CPPFLAGS="$CPPFLAGS -DG_DISABLE_ASSERT -DG_DISABLE_CHECKS -DG_DISABLE_CAST_CHECKS"
+fi
+
 AC_CONFIG_FILES([
     lxpanel.pc
     Makefile
index ced3d8a..fd0ca31 100644 (file)
@@ -24,13 +24,12 @@ ui_in_files= \
 
 ui_DATA = $(ui_in_files:.glade=.ui)
 
-# Generate GtkBuilder UI files from Glade files
-%.ui: %.glade
-       cp $< $@
-       $(top_builddir)/src/xml-purge $@
+# Purge GtkBuilder UI files
+.glade.ui:
+       sed 's/<!--.*-->//' < $< | sed ':a;N;$$!ba;s/ *\n *</</g' > $@
 
 CLEANFILES = \
-        $(ui_DATA)
+       $(ui_DATA)
 
 
 lxpanel_images_DATA = \
index 2ba6450..f6efa8c 100644 (file)
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <child>
-                  <object class="GtkScrolledWindow" id="scroll2">
+                  <object class="GtkScrolledWindow" id="menu_view_window">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
                     <property name="hscrollbar_policy">automatic</property>
                     <property name="vscrollbar_policy">automatic</property>
                     <property name="shadow_type">etched-in</property>
                     <child>
-                      <object class="GtkTreeView" id="menu_view">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="model">menu_store</property>
-                        <property name="headers_clickable">False</property>
-                        <property name="search_column">1</property>
-                        <child>
-                          <object class="GtkTreeViewColumn" id="menu_col">
-                            <property name="title">Available Applications</property>
-                            <property name="expand">True</property>
-                          </object>
-                        </child>
-                      </object>
+                      <placeholder/>
                     </child>
                   </object>
                   <packing>
index f3a9f2d..e734537 100644 (file)
                 <property name="can_focus">True</property>
                 <property name="can_default">True</property>
                 <property name="receives_default">False</property>
+                <property name="use_action_appearance">False</property>
                 <property name="use_stock">True</property>
               </object>
               <packing>
                                             <property name="visible">True</property>
                                             <property name="can_focus">True</property>
                                             <property name="receives_default">False</property>
+                                            <property name="use_action_appearance">False</property>
                                             <property name="active">True</property>
                                             <property name="draw_indicator">True</property>
                                           </object>
                                             <property name="visible">True</property>
                                             <property name="can_focus">True</property>
                                             <property name="receives_default">False</property>
+                                            <property name="use_action_appearance">False</property>
                                             <property name="draw_indicator">True</property>
                                             <property name="group">edge_bottom</property>
                                           </object>
                                             <property name="visible">True</property>
                                             <property name="can_focus">True</property>
                                             <property name="receives_default">False</property>
+                                            <property name="use_action_appearance">False</property>
                                             <property name="draw_indicator">True</property>
                                             <property name="group">edge_bottom</property>
                                           </object>
                                             <property name="visible">True</property>
                                             <property name="can_focus">True</property>
                                             <property name="receives_default">False</property>
+                                            <property name="use_action_appearance">False</property>
                                             <property name="draw_indicator">True</property>
                                             <property name="group">edge_bottom</property>
                                           </object>
                                             <property name="visible">True</property>
                                             <property name="can_focus">True</property>
                                             <property name="receives_default">False</property>
+                                            <property name="use_action_appearance">False</property>
                                             <property name="active">True</property>
                                             <property name="draw_indicator">True</property>
                                           </object>
                                             <property name="visible">True</property>
                                             <property name="can_focus">True</property>
                                             <property name="receives_default">False</property>
+                                            <property name="use_action_appearance">False</property>
                                             <property name="draw_indicator">True</property>
                                             <property name="group">alignment_left</property>
                                           </object>
                                             <property name="visible">True</property>
                                             <property name="can_focus">True</property>
                                             <property name="receives_default">False</property>
+                                            <property name="use_action_appearance">False</property>
                                             <property name="draw_indicator">True</property>
                                             <property name="group">alignment_left</property>
                                           </object>
                               </object>
                               <packing>
                                 <property name="x_options">GTK_FILL</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                                 <property name="top_attach">1</property>
                                 <property name="bottom_attach">2</property>
                                 <property name="x_options">GTK_FILL</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                                 <property name="top_attach">1</property>
                                 <property name="bottom_attach">2</property>
                                 <property name="x_options">GTK_FILL</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                                 <property name="left_attach">1</property>
                                 <property name="right_attach">2</property>
                                 <property name="x_options">GTK_FILL</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                                 <property name="top_attach">1</property>
                                 <property name="bottom_attach">2</property>
                                 <property name="x_options">GTK_FILL</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                                 <property name="left_attach">2</property>
                                 <property name="right_attach">3</property>
                                 <property name="x_options">GTK_FILL</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                               <packing>
                                 <property name="top_attach">2</property>
                                 <property name="bottom_attach">3</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
+                                <property name="use_action_appearance">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="active">True</property>
                                 <property name="draw_indicator">True</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
+                                    <property name="use_action_appearance">False</property>
                                     <property name="use_underline">True</property>
                                     <property name="draw_indicator">True</property>
                                     <property name="group">bg_none</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
+                                    <property name="use_action_appearance">False</property>
                                     <property name="use_alpha">True</property>
                                     <property name="color">#000000000000</property>
                                   </object>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
+                                    <property name="use_action_appearance">False</property>
                                     <property name="use_underline">True</property>
                                     <property name="draw_indicator">True</property>
                                     <property name="group">bg_none</property>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
+                                    <property name="use_action_appearance">False</property>
                                     <property name="use_underline">True</property>
                                     <property name="draw_indicator">True</property>
                                   </object>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">True</property>
+                                    <property name="use_action_appearance">False</property>
                                     <property name="color">#000000000000</property>
                                   </object>
                                   <packing>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
+                                    <property name="use_action_appearance">False</property>
                                     <property name="use_underline">True</property>
                                     <property name="draw_indicator">True</property>
                                   </object>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
                         <property name="use_stock">True</property>
                       </object>
                       <packing>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
                         <property name="use_stock">True</property>
                       </object>
                       <packing>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
                         <property name="use_stock">True</property>
                       </object>
                       <packing>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
                         <property name="use_stock">True</property>
                       </object>
                       <packing>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
+                        <property name="use_action_appearance">False</property>
                         <property name="use_stock">True</property>
                       </object>
                       <packing>
                                 <property name="right_attach">2</property>
                                 <property name="top_attach">2</property>
                                 <property name="bottom_attach">3</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                                 <property name="right_attach">2</property>
                                 <property name="top_attach">1</property>
                                 <property name="bottom_attach">2</property>
-                                <property name="y_options"/>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkEntry" id="file_manager">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="invisible_char">●</property>
-                                <property name="primary_icon_activatable">False</property>
-                                <property name="secondary_icon_activatable">False</property>
-                                <property name="primary_icon_sensitive">True</property>
-                                <property name="secondary_icon_sensitive">True</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                                 <property name="top_attach">2</property>
                                 <property name="bottom_attach">3</property>
                                 <property name="x_options">GTK_FILL</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                                 <property name="top_attach">1</property>
                                 <property name="bottom_attach">2</property>
                                 <property name="x_options">GTK_FILL</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                             <child>
                               </object>
                               <packing>
                                 <property name="x_options">GTK_FILL</property>
-                                <property name="y_options"/>
+                                <property name="y_options"></property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkVBox" id="vbox13">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <child>
+                                  <object class="GtkEntry" id="file_manager">
+                                    <property name="can_focus">True</property>
+                                    <property name="invisible_char">●</property>
+                                    <property name="invisible_char_set">True</property>
+                                    <property name="primary_icon_activatable">False</property>
+                                    <property name="secondary_icon_activatable">False</property>
+                                    <property name="primary_icon_sensitive">True</property>
+                                    <property name="secondary_icon_sensitive">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">True</property>
+                                    <property name="fill">True</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkComboBox" id="fm_combobox">
+                                    <property name="visible">True</property>
+                                  </object>
+                                  <packing>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="left_attach">1</property>
+                                <property name="right_attach">2</property>
+                                <property name="y_options"></property>
                               </packing>
                             </child>
                           </object>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
+                                <property name="use_action_appearance">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
                               </object>
                                 <property name="visible">True</property>
                                 <property name="can_focus">True</property>
                                 <property name="receives_default">False</property>
+                                <property name="use_action_appearance">False</property>
                                 <property name="use_underline">True</property>
                                 <property name="draw_indicator">True</property>
                               </object>
                                     <property name="visible">True</property>
                                     <property name="can_focus">True</property>
                                     <property name="receives_default">False</property>
+                                    <property name="use_action_appearance">False</property>
                                     <property name="draw_indicator">True</property>
                                   </object>
                                   <packing>
index c75e24b..5226fb1 100644 (file)
@@ -23,22 +23,30 @@ MENU_SOURCES = gtk-run.c
 endif
 
 lxpanel_SOURCES = \
-       misc.c misc.h \
+       misc.c \
        bg.c bg.h  \
        configurator.c \
        dbg.c dbg.h \
        ev.c ev.h \
        gtkbar.h gtkbar.c \
-       icon-grid.h icon-grid.c \
+       icon-grid.c \
        menu-policy.h menu-policy.c \
-       panel.c panel.h \
-       plugin.c plugin.h \
+       panel.c \
+       plugin.c \
+       private.h \
+       conf.c \
        $(MENU_SOURCES)
 
+lxpanel_includedir = $(includedir)/lxpanel
+lxpanel_include_HEADERS = \
+       plugin.h \
+       panel.h \
+       misc.h \
+       icon-grid.h \
+       conf.h
+
 if BUILD_PLUGIN_LOADER
 DYNAMIC_FLAGS = -export-dynamic
-lxpanel_includedir = $(includedir)/lxpanel
-lxpanel_include_HEADERS = $(top_srcdir)/include/lxpanel/plugin.h
 endif
 lxpanel_LDFLAGS = $(DYNAMIC_FLAGS)
 
@@ -51,11 +59,5 @@ lxpanel_LDADD = \
 lxpanelctl_SOURCES = lxpanelctl.c lxpanelctl.h
 lxpanelctl_LDADD = $(X11_LIBS) $(INTLLIBS)
 
-noinst_PROGRAMS=xml-purge
-xml_purge_SOURCES=xml-purge.c
-xml_purge_CFLAGS=@PACKAGE_CFLAGS@
-xml_purge_LDADD=@PACKAGE_LIBS@
-
-
 EXTRA_DIST = \
        plugins/icon.xpm
diff --git a/src/conf.c b/src/conf.c
new file mode 100644 (file)
index 0000000..e5d91e1
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+ * Copyright (c) 2014 LxDE Developers, see the file AUTHORS for details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "conf.h"
+#include "private.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+struct _config_setting_t
+{
+    config_setting_t *next;
+    config_setting_t *parent;
+    PanelConfType type;
+    PanelConfSaveHook hook;
+    gpointer hook_data;
+    char *name;
+    union {
+        gint num; /* for integer or boolean */
+        gchar *str; /* for string */
+        config_setting_t *first; /* for group or list */
+    };
+};
+
+struct _PanelConf
+{
+    config_setting_t *root;
+};
+
+static config_setting_t *_config_setting_t_new(config_setting_t *parent, int index,
+                                               const char *name, PanelConfType type)
+{
+    config_setting_t *s;
+    s = g_slice_new0(config_setting_t);
+    s->type = type;
+    s->name = g_strdup(name);
+    if (parent == NULL || (parent->type != PANEL_CONF_TYPE_GROUP && parent->type != PANEL_CONF_TYPE_LIST))
+        return s;
+    s->parent = parent;
+    if (parent->first == NULL || index == 0)
+    {
+        s->next = parent->first;
+        parent->first = s;
+    }
+    else
+    {
+        for (parent = parent->first; parent->next && index != 1; parent = parent->next)
+            index--;
+        /* FIXME: check if index is out of range? */
+        s->next = parent->next;
+        parent->next = s;
+    }
+    return s;
+}
+
+/* frees data, not removes from parent */
+static void _config_setting_t_free(config_setting_t *setting)
+{
+    g_free(setting->name);
+    switch (setting->type)
+    {
+    case PANEL_CONF_TYPE_STRING:
+        g_free(setting->str);
+        break;
+    case PANEL_CONF_TYPE_GROUP:
+    case PANEL_CONF_TYPE_LIST:
+        while (setting->first)
+        {
+            config_setting_t *s = setting->first;
+            setting->first = s->next;
+            _config_setting_t_free(s);
+        }
+        break;
+    case PANEL_CONF_TYPE_INT:
+        break;
+    }
+    g_slice_free(config_setting_t, setting);
+}
+
+/* the same as above but removes from parent */
+static void _config_setting_t_remove(config_setting_t *setting)
+{
+    g_return_if_fail(setting->parent);
+    g_return_if_fail(setting->parent->type == PANEL_CONF_TYPE_GROUP || setting->parent->type == PANEL_CONF_TYPE_LIST);
+    /* remove from parent */
+    if (setting->parent->first == setting)
+        setting->parent->first = setting->next;
+    else
+    {
+        config_setting_t *s = setting->parent->first;
+        while (s->next != NULL && s->next != setting)
+            s = s->next;
+        g_assert(s->next != NULL);
+        s->next = setting->next;
+    }
+    /* free the data */
+    _config_setting_t_free(setting);
+}
+
+PanelConf *config_new(void)
+{
+    PanelConf *c = g_slice_new(PanelConf);
+    c->root = _config_setting_t_new(NULL, -1, NULL, PANEL_CONF_TYPE_GROUP);
+    return c;
+}
+
+void config_destroy(PanelConf * config)
+{
+    _config_setting_t_free(config->root);
+    g_slice_free(PanelConf, config);
+}
+
+gboolean config_read_file(PanelConf * config, const char * filename)
+{
+    FILE *f = fopen(filename, "r");
+    size_t size;
+    char *buff, *c, *name, *end;
+    config_setting_t *s, *parent;
+
+    if (f == NULL)
+        return FALSE;
+    fseek(f, 0L, SEEK_END);
+    size = ftell(f);
+    rewind(f);
+    buff = g_malloc(size + 1);
+    size = fread(buff, 1, size, f);
+    fclose(f);
+    buff[size] = '\0';
+    name = NULL;
+    parent = config->root;
+    for (c = buff; *c; )
+    {
+        switch(*c)
+        {
+        case '#':
+_skip_all:
+            while (*c && *c != '\n')
+                c++;
+            if (!*c)
+                break;
+            /* continue with EOL */
+        case '\n':
+            name = NULL;
+            c++;
+            break;
+        case ' ':
+        case '\t':
+            if (name)
+                *c = '\0';
+            c++;
+            break;
+        case '=': /* scalar value follows */
+            if (name)
+                *c++ = '\0';
+            else
+            {
+                g_warning("config: invalid scalar definition");
+                goto _skip_all;
+            }
+            while (*c == ' ' || *c == '\t')
+                c++; /* skip spaces after '=' */
+            if (name == NULL || *c == '\0' || *c == '\n') /* invalid statement */
+                break;
+            size = strtol(c, &end, 10);
+            while (*end == ' ' || *end == '\t')
+                c++; /* skip trailing spaces */
+            if (*end == '\0' || *end == '\n')
+            {
+                s = config_setting_add(parent, name, PANEL_CONF_TYPE_INT);
+                if (s)
+                {
+                    s->num = (int)size;
+                    /* g_debug("config loader: got new int %s: %d", name, s->num); */
+                }
+                else
+                    g_warning("config: duplicate setting '%s' conflicts, ignored", name);
+            }
+            else
+            {
+                for (end = c; *end && *end != '\n'; )
+                    end++;
+                s = config_setting_add(parent, name, PANEL_CONF_TYPE_STRING);
+                if (s)
+                {
+                    g_free(s->str);
+                    s->str = g_strndup(c, end - c);
+                    /* g_debug("config loader: got new string %s: %s", name, s->str); */
+                }
+                else
+                    g_warning("config: duplicate setting '%s' conflicts, ignored", name);
+            }
+            c = end;
+            break;
+        case '{':
+            parent = config_setting_add(parent, "", PANEL_CONF_TYPE_LIST);
+            if (name)
+            {
+                *c = '\0';
+                s = config_setting_add(parent, name, PANEL_CONF_TYPE_GROUP);
+            }
+            else
+                s = NULL;
+            c++;
+            if (s)
+            {
+                parent = s;
+                /* g_debug("config loader: group '%s' added", name); */
+            }
+            else
+                g_warning("config: invalid group '%s' in config file ignored", name);
+            name = NULL;
+            break;
+        case '}':
+            c++;
+            if (parent->parent)
+                parent = parent->parent; /* go up, to anonymous list */
+            if (parent->type == PANEL_CONF_TYPE_LIST)
+                parent = parent->parent; /* go to upper group */
+            name = NULL;
+            break;
+        default:
+            if (name == NULL)
+                name = c;
+            c++;
+        }
+    }
+    g_free(buff);
+    return TRUE;
+}
+
+#define SETTING_INDENT "  "
+
+static void _config_write_setting(const config_setting_t *setting, GString *buf,
+                                  GString *out, FILE *f)
+{
+    gint indent = buf->len;
+    config_setting_t *s;
+
+    switch (setting->type)
+    {
+    case PANEL_CONF_TYPE_INT:
+        g_string_append_printf(buf, "%s=%d\n", setting->name, setting->num);
+        break;
+    case PANEL_CONF_TYPE_STRING:
+        if (!setting->str) /* don't save NULL strings */
+            return;
+        g_string_append_printf(buf, "%s=%s\n", setting->name, setting->str);
+        break;
+    case PANEL_CONF_TYPE_GROUP:
+        if (!out && setting->hook) /* plugin does not support settings */
+        {
+            lxpanel_put_line(f, "%s%s {", buf->str, setting->name);
+            setting->hook(setting, f, setting->hook_data);
+            lxpanel_put_line(f, "%s}", buf->str);
+            /* old settings ways are kinda weird... */
+        }
+        else
+        {
+            if (out)
+            {
+                g_string_append(out, buf->str);
+                g_string_append(out, setting->name);
+                g_string_append(out, " {\n");
+            }
+            else
+                fprintf(f, "%s%s {\n", buf->str, setting->name);
+            g_string_append(buf, SETTING_INDENT);
+            for (s = setting->first; s; s = s->next)
+                _config_write_setting(s, buf, out, f);
+            g_string_truncate(buf, indent);
+            if (out)
+            {
+                g_string_append(out, buf->str);
+                g_string_append(out, "}\n");
+            }
+            else
+                fprintf(f, "%s}\n", buf->str);
+        }
+        return;
+    case PANEL_CONF_TYPE_LIST:
+        if (setting->name[0] != '\0')
+        {
+            g_warning("only anonymous lists are supported in panel config, got \"%s\"",
+                      setting->name);
+            return;
+        }
+        for (s = setting->first; s; s = s->next)
+            _config_write_setting(s, buf, out, f);
+        return;
+    }
+    if (out)
+        g_string_append(out, buf->str);
+    else
+        fputs(buf->str, f);
+    g_string_truncate(buf, indent);
+}
+
+gboolean config_write_file(PanelConf * config, const char * filename)
+{
+    FILE *f = fopen(filename, "w");
+    GString *str;
+    if (f == NULL)
+        return FALSE;
+    fputs("# lxpanel <profile> config file. Manually editing is not recommended.\n"
+          "# Use preference dialog in lxpanel to adjust config when you can.\n\n", f);
+    str = g_string_sized_new(128);
+    _config_write_setting(config_setting_get_member(config->root, ""), str, NULL, f);
+    /* FIXME: handle errors */
+    fclose(f);
+    g_string_free(str, TRUE);
+    return TRUE;
+}
+
+/* it is used for old plugins only */
+char * config_setting_to_string(const config_setting_t * setting)
+{
+    GString *val, *buf;
+    g_return_val_if_fail(setting, NULL);
+    val = g_string_sized_new(128);
+    buf = g_string_sized_new(128);
+    _config_write_setting(setting, val, buf, NULL);
+    g_string_free(val, TRUE);
+    return g_string_free(buf, FALSE);
+}
+
+config_setting_t * config_root_setting(const PanelConf * config)
+{
+    return config->root;
+}
+
+static inline config_setting_t * _config_setting_get_member(const config_setting_t * setting, const char * name)
+{
+    config_setting_t *s;
+    for (s = setting->first; s; s = s->next)
+        if (g_strcmp0(s->name, name) == 0)
+            break;
+    return s;
+}
+
+config_setting_t * config_setting_get_member(const config_setting_t * setting, const char * name)
+{
+    g_return_val_if_fail(name && setting, NULL);
+    g_return_val_if_fail(setting->type == PANEL_CONF_TYPE_GROUP, NULL);
+    return _config_setting_get_member(setting, name);
+}
+
+config_setting_t * config_setting_get_elem(const config_setting_t * setting, unsigned int index)
+{
+    config_setting_t *s;
+    g_return_val_if_fail(setting, NULL);
+    g_return_val_if_fail(setting->type == PANEL_CONF_TYPE_LIST || setting->type == PANEL_CONF_TYPE_GROUP, NULL);
+    for (s = setting->first; s && index > 0; s = s->next)
+        index--;
+    return s;
+}
+
+const char * config_setting_get_name(const config_setting_t * setting)
+{
+    return setting->name;
+}
+
+config_setting_t * config_setting_get_parent(const config_setting_t * setting)
+{
+    return setting->parent;
+}
+
+int config_setting_get_int(const config_setting_t * setting)
+{
+    if (!setting || setting->type != PANEL_CONF_TYPE_INT)
+        return 0;
+    return setting->num;
+}
+
+const char * config_setting_get_string(const config_setting_t * setting)
+{
+    if (!setting || setting->type != PANEL_CONF_TYPE_STRING)
+        return NULL;
+    return setting->str;
+}
+
+gboolean config_setting_lookup_int(const config_setting_t * setting,
+                                   const char * name, int * value)
+{
+    config_setting_t *sub;
+
+    g_return_val_if_fail(name && setting && value, FALSE);
+    g_return_val_if_fail(setting->type == PANEL_CONF_TYPE_GROUP, FALSE);
+    sub = _config_setting_get_member(setting, name);
+    if (!sub || sub->type != PANEL_CONF_TYPE_INT)
+        return FALSE;
+    *value = sub->num;
+    return TRUE;
+}
+
+gboolean config_setting_lookup_string(const config_setting_t * setting,
+                                      const char * name, const char ** value)
+{
+    config_setting_t *sub;
+
+    g_return_val_if_fail(name && setting && value, FALSE);
+    g_return_val_if_fail(setting->type == PANEL_CONF_TYPE_GROUP, FALSE);
+    sub = _config_setting_get_member(setting, name);
+    if (!sub || sub->type != PANEL_CONF_TYPE_STRING)
+        return FALSE;
+    *value = sub->str;
+    return TRUE;
+}
+
+/* returns either new or existing setting struct, NULL on error */
+config_setting_t * config_setting_add(config_setting_t * parent, const char * name, PanelConfType type)
+{
+    config_setting_t *s;
+    if (parent == NULL || (parent->type != PANEL_CONF_TYPE_GROUP && parent->type != PANEL_CONF_TYPE_LIST))
+        return NULL;
+    if (type == PANEL_CONF_TYPE_LIST)
+    {
+        if (!name || name[0])
+            /* only anonymous lists are supported */
+            return NULL;
+    }
+    else if (name == NULL || name[0] == '\0')
+        /* other types should be not anonymous */
+        return NULL;
+    if (parent->type == PANEL_CONF_TYPE_GROUP &&
+        (s = _config_setting_get_member(parent, name)))
+        return (s->type == type) ? s : NULL;
+    return _config_setting_t_new(parent, -1, name, type);
+}
+
+gboolean config_setting_move_member(config_setting_t * setting, config_setting_t * parent, const char * name)
+{
+    config_setting_t *s;
+
+    g_return_val_if_fail(setting && setting->parent, FALSE);
+    if (parent == NULL || name == NULL || parent->type != PANEL_CONF_TYPE_GROUP)
+        return FALSE;
+    s = _config_setting_get_member(parent, name);
+    if (s) /* we cannot rename/move to this name, it exists already */
+        return (s == setting);
+    if (setting->parent == parent) /* it's just renaming thing */
+        goto _rename;
+    /* remove from old parent */
+    if (setting->parent->first == setting)
+        setting->parent->first = setting->next;
+    else
+    {
+        for (s = setting->parent->first; s->next; s = s->next)
+            if (s->next == setting)
+                break;
+        g_assert(s->next);
+        s->next = setting->next;
+    }
+    /* add to new parent */
+    setting->next = NULL;
+    setting->parent = parent;
+    if (parent->first == NULL)
+        parent->first = setting;
+    else
+    {
+        s = parent->first;
+        while (s->next)
+            s = s->next;
+        s->next = setting;
+    }
+    /* rename if need */
+    if (g_strcmp0(setting->name, name) != 0)
+    {
+_rename:
+        g_free(setting->name);
+        setting->name = g_strdup(name);
+    }
+    return TRUE;
+}
+
+gboolean config_setting_move_elem(config_setting_t * setting, config_setting_t * parent, int index)
+{
+    config_setting_t *s, *prev;
+
+    g_return_val_if_fail(setting && setting->parent, FALSE);
+    if (parent == NULL || parent->type != PANEL_CONF_TYPE_LIST)
+        return FALSE;
+    if (setting->type != PANEL_CONF_TYPE_GROUP) /* we support only list of groups now */
+        return FALSE;
+    /* let check the place */
+    if (index != 0)
+    {
+        if ((prev = parent->first))
+            for ( ; index != 1 && prev->next; prev = prev->next)
+                index--;
+        if (index > 1) /* too few elements yet */
+        {
+_out_of_range:
+            g_warning("config_setting_move_elem: index out of range");
+            return FALSE;
+        }
+        if (prev && prev->next == setting) /* it is already there */
+            return TRUE;
+        if (prev == setting) /* special case: we moving it +1, swapping with next */
+        {
+            if (prev->next == NULL)
+                goto _out_of_range;
+            prev = prev->next;
+        }
+    }
+    else if (parent->first == setting) /* it is already there */
+        return TRUE;
+    /* remove from old parent */
+    if (setting->parent->first == setting)
+        setting->parent->first = setting->next;
+    else
+    {
+        for (s = setting->parent->first; s->next; s = s->next)
+            if (s->next == setting)
+                break;
+        g_assert(s->next);
+        s->next = setting->next;
+    }
+    /* add to new parent */
+    setting->parent = parent;
+    if (index == 0)
+    {
+        setting->next = parent->first;
+        parent->first = setting;
+    }
+    else
+    {
+        setting->next = prev->next;
+        prev->next = setting;
+    }
+    /* don't rename  */
+    return TRUE;
+}
+
+gboolean config_setting_set_int(config_setting_t * setting, int value)
+{
+    if (!setting || setting->type != PANEL_CONF_TYPE_INT)
+        return FALSE;
+    setting->num = value;
+    return TRUE;
+}
+
+gboolean config_setting_set_string(config_setting_t * setting, const char * value)
+{
+    if (!setting || setting->type != PANEL_CONF_TYPE_STRING)
+        return FALSE;
+    g_free(setting->str);
+    setting->str = g_strdup(value);
+    return TRUE;
+}
+
+gboolean config_setting_remove(config_setting_t * parent, const char * name)
+{
+    config_setting_t *s = config_setting_get_member(parent, name);
+    if (s == NULL)
+        return FALSE;
+    _config_setting_t_remove(s);
+    return TRUE;
+}
+
+gboolean config_setting_remove_elem(config_setting_t * parent, unsigned int index)
+{
+    config_setting_t *s = config_setting_get_elem(parent, index);
+    if (s == NULL)
+        return FALSE;
+    _config_setting_t_remove(s);
+    return TRUE;
+}
+
+gboolean config_setting_destroy(config_setting_t * setting)
+{
+    if (setting == NULL || setting->parent == NULL)
+        return FALSE;
+    _config_setting_t_remove(setting);
+    return TRUE;
+}
+
+PanelConfType config_setting_type(const config_setting_t * setting)
+{
+    return setting->type;
+}
+
+void config_setting_set_save_hook(config_setting_t * setting, PanelConfSaveHook hook,
+                                  gpointer user_data)
+{
+    setting->hook = hook;
+    setting->hook_data = user_data;
+}
diff --git a/src/conf.h b/src/conf.h
new file mode 100644 (file)
index 0000000..8b82f20
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014 LxDE Developers, see the file AUTHORS for details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* This is a config file parser with API similar to one used by libconfig
+   for convenience but contents of the file is the own config format
+   therefore it is much more restricted than libconfig is.
+   Strings cannot be numeric and are not quoted (similarly to INI file format).
+   Groups cannot be inside other group but only inside an anonymous list.
+   That anonymous list is the only list type which is supported and there
+   can be only one anonymous member in any group. */
+
+#ifndef __CONF_H__
+#define __CONF_H__ 1
+
+#include <glib.h>
+#include <stdio.h>
+
+G_BEGIN_DECLS
+
+typedef struct _config_setting_t config_setting_t;
+typedef struct _PanelConf PanelConf;
+
+typedef enum
+{
+    PANEL_CONF_TYPE_GROUP,
+    PANEL_CONF_TYPE_INT,
+    PANEL_CONF_TYPE_STRING,
+    PANEL_CONF_TYPE_LIST
+} PanelConfType;
+
+typedef void (*PanelConfSaveHook)(const config_setting_t * setting, FILE * f, gpointer user_data);
+
+PanelConf *config_new(void);
+void config_destroy(PanelConf * config);
+gboolean config_read_file(PanelConf * config, const char * filename);
+gboolean config_write_file(PanelConf * config, const char * filename);
+char * config_setting_to_string(const config_setting_t * setting);
+
+config_setting_t * config_root_setting(const PanelConf * config);
+config_setting_t * config_setting_get_member(const config_setting_t * setting, const char * name);
+config_setting_t * config_setting_get_elem(const config_setting_t * setting, unsigned int index);
+const char * config_setting_get_name(const config_setting_t * setting);
+config_setting_t * config_setting_get_parent(const config_setting_t * setting);
+
+int config_setting_get_int(const config_setting_t * setting);
+const char * config_setting_get_string(const config_setting_t * setting);
+
+gboolean config_setting_lookup_int(const config_setting_t * setting,
+                                   const char * name, int * value);
+gboolean config_setting_lookup_string(const config_setting_t * setting,
+                                      const char * name, const char ** value);
+
+config_setting_t * config_setting_add(config_setting_t * parent, const char * name, PanelConfType type);
+
+gboolean config_setting_move_member(config_setting_t * setting, config_setting_t * parent, const char * name);
+gboolean config_setting_move_elem(config_setting_t * setting, config_setting_t * parent, int index);
+
+gboolean config_setting_set_int(config_setting_t * setting, int value);
+gboolean config_setting_set_string(config_setting_t * setting, const char * value);
+gboolean config_setting_remove(config_setting_t * parent, const char * name);
+gboolean config_setting_remove_elem(config_setting_t * parent, unsigned int index);
+gboolean config_setting_destroy(config_setting_t * setting);
+
+PanelConfType config_setting_type(const config_setting_t * setting);
+#define config_setting_is_group(_s) config_setting_type(_s) == PANEL_CONF_TYPE_GROUP
+#define config_setting_is_list(_s) config_setting_type(_s) == PANEL_CONF_TYPE_LIST
+#define config_setting_is_scalar(_s) \
+        (config_setting_type(_s) == PANEL_CONF_TYPE_INT || \
+         config_setting_type(_s) == PANEL_CONF_TYPE_STRING)
+
+void config_setting_set_save_hook(config_setting_t * setting, PanelConfSaveHook hook, gpointer user_data);
+
+G_END_DECLS
+
+#endif /* __CONF_H__ */
index a0ac34f..1482f7f 100644 (file)
@@ -21,8 +21,7 @@
 #include "config.h"
 #endif
 
-#include "plugin.h"
-#include "panel.h"
+#include "private.h"
 #include "misc.h"
 #include "bg.h"
 #include <stdlib.h>
@@ -31,6 +30,7 @@
 #include <unistd.h>
 #include <string.h>
 #include <glib/gi18n.h>
+#include <libfm/fm-gtk.h>
 
 #include "dbg.h"
 
@@ -44,7 +44,6 @@ enum{
 void panel_configure(Panel* p, int sel_page );
 void restart(void);
 void gtk_run(void);
-void panel_config_save(Panel* panel);
 static void logout(void);
 static void save_global_config();
 
@@ -58,14 +57,34 @@ Command commands[] = {
     { NULL, NULL },
 };
 
-static char* file_manager_cmd = NULL;
-static char* terminal_cmd = NULL;
 static char* logout_cmd = NULL;
 
 extern GSList* all_panels;
 extern gchar *cprofile;
 extern int config;
 
+/* macros to update config */
+#define UPDATE_GLOBAL_INT(panel,name,val) do { \
+    config_setting_t *_s = config_setting_add(config_setting_get_elem(config_setting_get_member(config_root_setting(panel->config),""),\
+                                                                      0),\
+                                              name,PANEL_CONF_TYPE_INT);\
+    if (_s) config_setting_set_int(_s,val); } while(0)
+
+#define UPDATE_GLOBAL_STRING(panel,name,val) do { \
+    config_setting_t *_s = config_setting_add(config_setting_get_elem(config_setting_get_member(config_root_setting(panel->config),""),\
+                                                                      0),\
+                                              name,PANEL_CONF_TYPE_STRING);\
+    if (_s) config_setting_set_string(_s,val); } while(0)
+
+#define UPDATE_GLOBAL_COLOR(panel,name,val) do { \
+    config_setting_t *_s = config_setting_add(config_setting_get_elem(config_setting_get_member(config_root_setting(panel->config),""),\
+                                                                      0),\
+                                              name,PANEL_CONF_TYPE_INT);\
+    if (_s) { \
+        char _c[8];\
+        snprintf(_c, sizeof(_c), "#%06x",val);\
+        config_setting_set_string(_s,_c); } } while(0)
+
 /* GtkColotButton expects a number between 0 and 65535, but p->alpha has range
  * 0 to 255, and (2^(2n) - 1) / (2^n - 1) = 2^n + 1 = 257, with n = 8. */
 static guint16 const alpha_scale_factor = 257;
@@ -77,6 +96,7 @@ static void update_opt_menu(GtkWidget *w, int ind);
 static void update_toggle_button(GtkWidget *w, gboolean n);
 static void modify_plugin( GtkTreeView* view );
 static gboolean on_entry_focus_out( GtkWidget* edit, GdkEventFocus *evt, gpointer user_data );
+static gboolean on_entry_focus_out2( GtkWidget* edit, GdkEventFocus *evt, gpointer user_data );
 
 static void
 response_event(GtkDialog *widget, gint arg1, Panel* panel )
@@ -134,6 +154,7 @@ static void set_edge(Panel* p, int edge)
     p->edge = edge;
     update_panel_geometry(p);
     panel_set_panel_configuration_changed(p);
+    UPDATE_GLOBAL_STRING(p, "edge", num2str(edge_pair, edge, "none"));
 }
 
 static void edge_bottom_toggle(GtkToggleButton *widget, Panel *p)
@@ -165,6 +186,7 @@ static void set_monitor(GtkAdjustment *widget, Panel *p)
     p->monitor = gtk_adjustment_get_value(widget);
     update_panel_geometry(p);
     panel_set_panel_configuration_changed(p);
+    UPDATE_GLOBAL_INT(p, "monitor", p->monitor);
 }
 
 static void set_alignment(Panel* p, int align)
@@ -173,6 +195,7 @@ static void set_alignment(Panel* p, int align)
         gtk_widget_set_sensitive(p->margin_control, (align != ALLIGN_CENTER));
     p->allign = align;
     update_panel_geometry(p);
+    UPDATE_GLOBAL_STRING(p, "allign", num2str(allign_pair, align, "none"));
 }
 
 static void align_left_toggle(GtkToggleButton *widget, Panel *p)
@@ -198,6 +221,7 @@ set_margin( GtkSpinButton* spin,  Panel* p  )
 {
     p->margin = (int)gtk_spin_button_get_value(spin);
     update_panel_geometry(p);
+    UPDATE_GLOBAL_INT(p, "margin", p->margin);
 }
 
 static void
@@ -205,6 +229,7 @@ set_width(  GtkSpinButton* spin, Panel* p )
 {
     p->width = (int)gtk_spin_button_get_value(spin);
     update_panel_geometry(p);
+    UPDATE_GLOBAL_INT(p, "width", p->width);
 }
 
 static void
@@ -212,6 +237,7 @@ set_height( GtkSpinButton* spin, Panel* p )
 {
     p->height = (int)gtk_spin_button_get_value(spin);
     update_panel_geometry(p);
+    UPDATE_GLOBAL_INT(p, "height", p->height);
 }
 
 static void set_width_type( GtkWidget *item, Panel* p )
@@ -246,8 +272,11 @@ static void set_width_type( GtkWidget *item, Panel* p )
         return;
 
     update_panel_geometry(p);
+    UPDATE_GLOBAL_STRING(p, "widthtype", num2str(width_pair, widthtype, "none"));
 }
 
+/* FIXME: heighttype and spacing and RoundCorners */
+
 static void set_log_level( GtkWidget *cbox, Panel* p)
 {
     configured_log_level = gtk_combo_box_get_active(GTK_COMBO_BOX(cbox));
@@ -255,6 +284,7 @@ static void set_log_level( GtkWidget *cbox, Panel* p)
         log_level = configured_log_level;
     ERR("panel-pref: log level configured to %d, log_level is now %d\n",
             configured_log_level, log_level);
+    UPDATE_GLOBAL_INT(p, "loglevel", configured_log_level);
 }
 
 static void transparency_toggle( GtkWidget *b, Panel* p)
@@ -275,6 +305,8 @@ static void transparency_toggle( GtkWidget *b, Panel* p)
         p->transparent = 1;
         p->background = 0;
         panel_update_background( p );
+        UPDATE_GLOBAL_INT(p, "transparent", p->transparent);
+        UPDATE_GLOBAL_INT(p, "background", p->background);
     }
     RET();
 }
@@ -286,6 +318,7 @@ static void background_file_helper(Panel * p, GtkWidget * toggle, GtkFileChooser
     {
         g_free(p->background_file);
         p->background_file = file;
+        UPDATE_GLOBAL_STRING(p, "backgroundfile", p->background_file);
     }
 
     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)))
@@ -295,6 +328,8 @@ static void background_file_helper(Panel * p, GtkWidget * toggle, GtkFileChooser
             p->transparent = FALSE;
             p->background = TRUE;
             panel_update_background(p);
+            UPDATE_GLOBAL_INT(p, "transparent", p->transparent);
+            UPDATE_GLOBAL_INT(p, "background", p->background);
         }
     }
 }
@@ -322,6 +357,8 @@ background_disable_toggle( GtkWidget *b, Panel* p )
             p->transparent = 0;
             /* Update background immediately. */
             panel_update_background( p );
+            UPDATE_GLOBAL_INT(p, "transparent", p->transparent);
+            UPDATE_GLOBAL_INT(p, "background", p->background);
         }
     }
 
@@ -333,6 +370,8 @@ on_font_color_set( GtkColorButton* clr,  Panel* p )
 {
     gtk_color_button_get_color( clr, &p->gfontcolor );
     panel_set_panel_configuration_changed(p);
+    p->fontcolor = gcolor2rgb24(&p->gfontcolor);
+    UPDATE_GLOBAL_COLOR(p, "fontcolor", p->fontcolor);
 }
 
 static void
@@ -342,6 +381,8 @@ on_tint_color_set( GtkColorButton* clr,  Panel* p )
     p->tintcolor = gcolor2rgb24(&p->gtintcolor);
     p->alpha = gtk_color_button_get_alpha( clr ) / alpha_scale_factor;
     panel_update_background( p );
+    UPDATE_GLOBAL_COLOR(p, "tintcolor", p->tintcolor);
+    UPDATE_GLOBAL_INT(p, "alpha", p->alpha);
 }
 
 static void
@@ -354,6 +395,7 @@ on_use_font_color_toggled( GtkToggleButton* btn,   Panel* p )
         gtk_widget_set_sensitive( clr, FALSE );
     p->usefontcolor = gtk_toggle_button_get_active( btn );
     panel_set_panel_configuration_changed(p);
+    UPDATE_GLOBAL_INT(p, "usefontcolor", p->usefontcolor);
 }
 
 static void
@@ -361,6 +403,7 @@ on_font_size_set( GtkSpinButton* spin, Panel* p )
 {
     p->fontsize = (int)gtk_spin_button_get_value(spin);
     panel_set_panel_configuration_changed(p);
+    UPDATE_GLOBAL_INT(p, "fontsize", p->fontsize);
 }
 
 static void
@@ -373,6 +416,7 @@ on_use_font_size_toggled( GtkToggleButton* btn,   Panel* p )
         gtk_widget_set_sensitive( clr, FALSE );
     p->usefontsize = gtk_toggle_button_get_active( btn );
     panel_set_panel_configuration_changed(p);
+    UPDATE_GLOBAL_INT(p, "usefontsize", p->usefontsize);
 }
 
 
@@ -382,6 +426,7 @@ set_dock_type(GtkToggleButton* toggle,  Panel* p )
     p->setdocktype = gtk_toggle_button_get_active(toggle) ? 1 : 0;
     panel_set_dock_type( p );
     update_panel_geometry(p);
+    UPDATE_GLOBAL_INT(p, "setdocktype", p->setdocktype);
 }
 
 static void
@@ -389,6 +434,7 @@ set_strut(GtkToggleButton* toggle,  Panel* p )
 {
     p->setstrut = gtk_toggle_button_get_active(toggle) ? 1 : 0;
     update_panel_geometry(p);
+    UPDATE_GLOBAL_INT(p, "setpartialstrut", p->setstrut);
 }
 
 static void
@@ -396,6 +442,7 @@ set_autohide(GtkToggleButton* toggle,  Panel* p )
 {
     p->autohide = gtk_toggle_button_get_active(toggle) ? 1 : 0;
     update_panel_geometry(p);
+    UPDATE_GLOBAL_INT(p, "autohide", p->autohide);
 }
 
 static void
@@ -403,6 +450,7 @@ set_height_when_minimized( GtkSpinButton* spin,  Panel* p  )
 {
     p->height_when_hidden = (int)gtk_spin_button_get_value(spin);
     update_panel_geometry(p);
+    UPDATE_GLOBAL_INT(p, "heightwhenhidden", p->height_when_hidden);
 }
 
 static void
@@ -410,6 +458,7 @@ set_icon_size( GtkSpinButton* spin,  Panel* p  )
 {
     p->icon_size = (int)gtk_spin_button_get_value(spin);
     panel_set_panel_configuration_changed(p);
+    UPDATE_GLOBAL_INT(p, "iconsize", p->icon_size);
 }
 
 static void
@@ -417,15 +466,17 @@ on_sel_plugin_changed( GtkTreeSelection* tree_sel, GtkWidget* label )
 {
     GtkTreeIter it;
     GtkTreeModel* model;
-    Plugin* pl;
+    GtkWidget* pl;
 
     if( gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
     {
         GtkTreeView* view = gtk_tree_selection_get_tree_view( tree_sel );
         GtkWidget *edit_btn = GTK_WIDGET(g_object_get_data( G_OBJECT(view), "edit_btn" ));
+        LXPanelPluginInit *init;
         gtk_tree_model_get( model, &it, COL_DATA, &pl, -1 );
-        gtk_label_set_text( GTK_LABEL(label), _(pl->class->description) );
-        gtk_widget_set_sensitive( edit_btn, pl->class->config != NULL );
+        init = PLUGIN_CLASS(pl);
+        gtk_label_set_text( GTK_LABEL(label), _(init->description) );
+        gtk_widget_set_sensitive( edit_btn, init->config != NULL );
     }
 }
 
@@ -438,24 +489,32 @@ on_plugin_expand_toggled(GtkCellRendererToggle* render, char* path, GtkTreeView*
     model = gtk_tree_view_get_model( view );
     if( gtk_tree_model_get_iter( model, &it, tp ) )
     {
-        Plugin* pl;
+        GtkWidget* pl;
         gboolean old_expand, expand, fill;
         guint padding;
         GtkPackType pack_type;
+        LXPanelPluginInit *init;
+        Panel *panel;
 
         gtk_tree_model_get( model, &it, COL_DATA, &pl, COL_EXPAND, &expand, -1 );
+        init = PLUGIN_CLASS(pl);
+        panel = PLUGIN_PANEL(pl);
 
-        if (pl->class->expand_available)
+        if (init->expand_available)
         {
+            config_setting_t *s = g_object_get_qdata(G_OBJECT(pl), lxpanel_plugin_qconf);
             /* Only honor "stretch" if allowed by the plugin. */
             expand = ! expand;
-            pl->expand = expand;
             gtk_list_store_set( GTK_LIST_STORE(model), &it, COL_EXPAND, expand, -1 );
 
             /* Query the old packing of the plugin widget.
              * Apply the new packing with only "expand" modified. */
-            gtk_box_query_child_packing( GTK_BOX(pl->panel->box), pl->pwid, &old_expand, &fill, &padding, &pack_type );
-            gtk_box_set_child_packing( GTK_BOX(pl->panel->box), pl->pwid, expand, fill, padding, pack_type );
+            gtk_box_query_child_packing( GTK_BOX(panel->box), pl, &old_expand, &fill, &padding, &pack_type );
+            gtk_box_set_child_packing( GTK_BOX(panel->box), pl, expand, fill, padding, pack_type );
+            if (expand)
+                config_setting_set_int(config_setting_add(s, "expand", PANEL_CONF_TYPE_INT), 1);
+            else
+                config_setting_remove(s, "expand");
         }
     }
     gtk_tree_path_free( tp );
@@ -465,10 +524,10 @@ static void on_stretch_render(GtkTreeViewColumn * column, GtkCellRenderer * rend
 {
     /* Set the control visible depending on whether stretch is available for the plugin.
      * The g_object_set method is touchy about its parameter, so we can't pass the boolean directly. */
-    Plugin * pl;
+    GtkWidget * pl;
     gtk_tree_model_get(model, iter, COL_DATA, &pl, -1);
     g_object_set(renderer,
-        "visible", ((pl->class->expand_available) ? TRUE : FALSE),
+        "visible", ((PLUGIN_CLASS(pl)->expand_available) ? TRUE : FALSE),
         NULL);
 }
 
@@ -478,7 +537,7 @@ static void init_plugin_list( Panel* p, GtkTreeView* view, GtkWidget* label )
     GtkTreeViewColumn* col;
     GtkCellRenderer* render;
     GtkTreeSelection* tree_sel;
-    GListl;
+    GList *plugins, *l;
     GtkTreeIter it;
 
     g_object_set_data( G_OBJECT(view), "panel", p );
@@ -501,17 +560,21 @@ static void init_plugin_list( Panel* p, GtkTreeView* view, GtkWidget* label )
     gtk_tree_view_append_column( view, col );
 
     list = gtk_list_store_new( N_COLS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER );
-    for( l = p->plugins; l; l = l->next )
+    plugins = gtk_container_get_children(GTK_CONTAINER(p->box));
+    for( l = plugins; l; l = l->next )
     {
         GtkTreeIter it;
-        Plugin* pl = (Plugin*)l->data;
+        gboolean expand;
+        GtkWidget *w = (GtkWidget*)l->data;
+        gtk_container_child_get(GTK_CONTAINER(p->box), w, "expand", &expand, NULL);
         gtk_list_store_append( list, &it );
         gtk_list_store_set( list, &it,
-                            COL_NAME, _(pl->class->name),
-                            COL_EXPAND, pl->expand,
-                            COL_DATA, pl,
+                            COL_NAME, _(PLUGIN_CLASS(w)->name),
+                            COL_EXPAND, expand,
+                            COL_DATA, w,
                             -1);
     }
+    g_list_free(plugins);
     gtk_tree_view_set_model( view, GTK_TREE_MODEL( list ) );
     g_signal_connect( view, "row-activated",
                       G_CALLBACK(modify_plugin), NULL );
@@ -557,31 +620,27 @@ static void on_add_plugin_response( GtkDialog* dlg,
         if( gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
         {
             char* type = NULL;
-            Plugin* pl;
+            GtkWidget *pl;
+            config_setting_t *cfg;
+            config_setting_t *s = config_setting_get_member(config_root_setting(p->config), "");
+            cfg = config_setting_add(s, "Plugin", PANEL_CONF_TYPE_GROUP);
             gtk_tree_model_get( model, &it, 1, &type, -1 );
-            if ((pl = plugin_load(type)) != NULL)
+            s = config_setting_add(cfg, "type", PANEL_CONF_TYPE_STRING);
+            config_setting_set_string(s, type);
+            if ((pl = lxpanel_add_plugin(p, type, cfg, -1)))
             {
                 GtkTreePath* tree_path;
+                gboolean expand;
 
-                pl->panel = p;
-                if (pl->class->expand_default) pl->expand = TRUE;
-                plugin_start( pl, NULL );
-                p->plugins = g_list_append(p->plugins, pl);
                 panel_config_save(p);
 
-                if (pl->pwid)
-                {
-                    gtk_widget_show(pl->pwid);
-
-                    /* update background of the newly added plugin */
-                    plugin_widget_set_background( pl->pwid, pl->panel );
-                }
-
+                plugin_widget_set_background(pl, p);
+                gtk_container_child_get(GTK_CONTAINER(p->box), pl, "expand", &expand, NULL);
                 model = gtk_tree_view_get_model( _view );
                 gtk_list_store_append( GTK_LIST_STORE(model), &it );
                 gtk_list_store_set( GTK_LIST_STORE(model), &it,
-                                    COL_NAME, _(pl->class->name),
-                                    COL_EXPAND, pl->expand,
+                                    COL_NAME, _(PLUGIN_CLASS(pl)->name),
+                                    COL_EXPAND, expand,
                                     COL_DATA, pl, -1 );
                 tree_sel = gtk_tree_view_get_selection( _view );
                 gtk_tree_selection_select_iter( tree_sel, &it );
@@ -591,6 +650,8 @@ static void on_add_plugin_response( GtkDialog* dlg,
                     gtk_tree_path_free( tree_path );
                 }
             }
+            else /* free unused setting */
+                config_setting_destroy(cfg);
             g_free( type );
         }
     }
@@ -600,17 +661,20 @@ static void on_add_plugin_response( GtkDialog* dlg,
 static void on_add_plugin( GtkButton* btn, GtkTreeView* _view )
 {
     GtkWidget* dlg, *parent_win, *scroll;
-    GList* classes;
-    GList* tmp;
+    GHashTable *classes;
+    GList *plugins;
     GtkTreeViewColumn* col;
     GtkCellRenderer* render;
     GtkTreeView* view;
     GtkListStore* list;
     GtkTreeSelection* tree_sel;
+    GHashTableIter iter;
+    gpointer key, val;
 
     Panel* p = (Panel*) g_object_get_data( G_OBJECT(_view), "panel" );
 
-    classes = plugin_get_available_classes();
+    classes = lxpanel_get_all_types();
+    plugins = gtk_container_get_children(GTK_CONTAINER(p->box));
 
     parent_win = gtk_widget_get_toplevel( GTK_WIDGET(_view) );
     dlg = gtk_dialog_new_with_buttons( _("Add plugin to panel"),
@@ -651,15 +715,18 @@ static void on_add_plugin( GtkButton* btn, GtkTreeView* _view )
 
     /* Populate list of available plugins.
      * Omit plugins that can only exist once per system if it is already configured. */
-    for( tmp = classes; tmp; tmp = tmp->next ) {
-        PluginClass* pc = (PluginClass*)tmp->data;
-        if (( ! pc->one_per_system ) || ( ! pc->one_per_system_instantiated))
+    g_hash_table_iter_init(&iter, classes);
+    while(g_hash_table_iter_next(&iter, &key, &val))
+    {
+        register LXPanelPluginInit *init = val;
+        if (!init->one_per_system || !_class_is_present(init))
         {
             GtkTreeIter it;
             gtk_list_store_append( list, &it );
+            /* it is safe to put classes data here - they will be valid until restart */
             gtk_list_store_set( list, &it,
-                                0, _(pc->name),
-                                1, pc->type,
+                                0, _(init->name),
+                                1, key,
                                 -1 );
             /* g_debug( "%s (%s)", pc->type, _(pc->name) ); */
         }
@@ -678,7 +745,7 @@ static void on_add_plugin( GtkButton* btn, GtkTreeView* _view )
                       G_CALLBACK(on_add_plugin_row_activated), (gpointer) dlg);
 
     g_object_set_data( G_OBJECT(dlg), "avail-plugins", view );
-    g_object_weak_ref( G_OBJECT(dlg), (GWeakNotify) plugin_class_list_free, classes );
+    g_list_free(plugins);
 
     gtk_window_set_default_size( GTK_WINDOW(dlg), 320, 400 );
     gtk_widget_show_all( dlg );
@@ -690,7 +757,7 @@ static void on_remove_plugin( GtkButton* btn, GtkTreeView* view )
     GtkTreePath* tree_path;
     GtkTreeModel* model;
     GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
-    Plugin* pl;
+    GtkWidget* pl;
 
     Panel* p = (Panel*) g_object_get_data( G_OBJECT(view), "panel" );
 
@@ -704,8 +771,10 @@ static void on_remove_plugin( GtkButton* btn, GtkTreeView* view )
         gtk_tree_selection_select_path( tree_sel, tree_path );
         gtk_tree_path_free( tree_path );
 
-        p->plugins = g_list_remove( p->plugins, pl );
-        plugin_delete(pl);
+        config_setting_destroy(g_object_get_qdata(G_OBJECT(pl), lxpanel_plugin_qconf));
+        /* reset conf pointer because the widget still may be referenced by configurator */
+        g_object_set_qdata(G_OBJECT(pl), lxpanel_plugin_qconf, NULL);
+        gtk_widget_destroy(pl);
         panel_config_save(p);
     }
 }
@@ -715,34 +784,28 @@ void modify_plugin( GtkTreeView* view )
     GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
     GtkTreeModel* model;
     GtkTreeIter it;
-    Plugin* pl;
+    GtkWidget* pl;
+    LXPanelPluginInit *init;
 
     if( ! gtk_tree_selection_get_selected( tree_sel, &model, &it ) )
         return;
 
     gtk_tree_model_get( model, &it, COL_DATA, &pl, -1 );
-    if( pl->class->config )
-        pl->class->config( pl, GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))) );
+    init = PLUGIN_CLASS(pl);
+    if (init->config)
+        init->config(PLUGIN_PANEL(pl), pl, GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))));
 }
 
-static int get_widget_index(    Panel* p, Plugin* pl )
+static int get_widget_index(Panel* p, GtkWidget* pl)
 {
-    GList* l;
-    int i;
-    for( i = 0, l = p->plugins; l; l = l->next )
-    {
-        Plugin* _pl = (Plugin*)l->data;
-        if( _pl == pl )
-            return i;
-        if( _pl->pwid )
-            ++i;
-    }
-    return -1;
+    GList *plugins = gtk_container_get_children(GTK_CONTAINER(p->box));
+    int i = g_list_index(plugins, pl);
+    g_list_free(plugins);
+    return i;
 }
 
 static void on_moveup_plugin(  GtkButton* btn, GtkTreeView* view )
 {
-    GList *l;
     GtkTreeIter it, prev;
     GtkTreeModel* model = gtk_tree_view_get_model( view );
     GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
@@ -757,24 +820,20 @@ static void on_moveup_plugin(  GtkButton* btn, GtkTreeView* view )
     do{
         if( gtk_tree_selection_iter_is_selected(tree_sel, &it) )
         {
-            Plugin* pl;
+            GtkWidget* pl;
+            config_setting_t *s;
             gtk_tree_model_get( model, &it, COL_DATA, &pl, -1 );
             gtk_list_store_move_before( GTK_LIST_STORE( model ),
                                         &it, &prev );
 
-            i = 0;
-            for( l = panel->plugins; l; l = l->next, ++i )
-            {
-                if( l->data == pl  )
-                {
-                    panel->plugins = g_list_insert( panel->plugins, pl, i - 1);
-                    panel->plugins = g_list_delete_link( panel->plugins, l);
-                }
-            }
-            if( pl->pwid )
-            {
-                gtk_box_reorder_child( GTK_BOX(panel->box), pl->pwid, get_widget_index( panel, pl ) );
-            }
+            i = get_widget_index(panel, pl);
+            s = g_object_get_qdata(G_OBJECT(pl), lxpanel_plugin_qconf);
+            /* reorder in config, 0 is Global */
+            if (i == 0)
+                i = 1;
+            config_setting_move_elem(s, config_setting_get_parent(s), i);
+            /* reorder in panel */
+            gtk_box_reorder_child(GTK_BOX(panel->box), pl, i - 1);
             panel_config_save(panel);
             return;
         }
@@ -784,11 +843,11 @@ static void on_moveup_plugin(  GtkButton* btn, GtkTreeView* view )
 
 static void on_movedown_plugin(  GtkButton* btn, GtkTreeView* view )
 {
-    GList *l;
     GtkTreeIter it, next;
     GtkTreeModel* model;
     GtkTreeSelection* tree_sel = gtk_tree_view_get_selection( view );
-    Plugin* pl;
+    GtkWidget* pl;
+    config_setting_t *s;
     int i;
 
     Panel* panel = (Panel*) g_object_get_data( G_OBJECT(view), "panel" );
@@ -804,19 +863,12 @@ static void on_movedown_plugin(  GtkButton* btn, GtkTreeView* view )
 
     gtk_list_store_move_after( GTK_LIST_STORE( model ), &it, &next );
 
-    i = 0;
-    for( l = panel->plugins; l; l = l->next, ++i )
-    {
-        if( l->data == pl  )
-        {
-            panel->plugins = g_list_insert( panel->plugins, pl, i + 2);
-            panel->plugins = g_list_delete_link( panel->plugins, l);
-        }
-    }
-    if( pl->pwid )
-    {
-        gtk_box_reorder_child( GTK_BOX(panel->box), pl->pwid, get_widget_index( panel, pl ) );
-    }
+    i = get_widget_index(panel, pl) + 1;
+    s = g_object_get_qdata(G_OBJECT(pl), lxpanel_plugin_qconf);
+    /* reorder in config, 0 is Global */
+    config_setting_move_elem(s, config_setting_get_parent(s), i + 1);
+    /* reorder in panel */
+    gtk_box_reorder_child(GTK_BOX(panel->box), pl, i);
     panel_config_save(panel);
 }
 
@@ -853,10 +905,24 @@ update_toggle_button(GtkWidget *w, gboolean n)
     RET();
 }
 
+static void on_app_chooser_destroy(GtkComboBox *fm, gpointer _unused)
+{
+    gboolean is_changed;
+    GAppInfo *app = fm_app_chooser_combo_box_dup_selected_app(fm, &is_changed);
+    if(app)
+    {
+        if(is_changed)
+            g_app_info_set_as_default_for_type(app, "inode/directory", NULL);
+        g_object_unref(app);
+    }
+}
+
 void panel_configure( Panel* p, int sel_page )
 {
     GtkBuilder* builder;
     GtkWidget *w, *w2, *tint_clr;
+    FmMimeType *mt;
+    GtkComboBox *fm;
     GdkScreen *screen;
     gint monitors;
 
@@ -1081,19 +1147,18 @@ void panel_configure( Panel* p, int sel_page )
         init_plugin_list( p, GTK_TREE_VIEW(plugin_list), w );
     }
     /* advanced, applications */
-    w = (GtkWidget*)gtk_builder_get_object( builder, "file_manager" );
-    if (file_manager_cmd)
-        gtk_entry_set_text( GTK_ENTRY(w), file_manager_cmd );
-    g_signal_connect( w, "focus-out-event",
-                      G_CALLBACK(on_entry_focus_out),
-                      &file_manager_cmd);
+    mt = fm_mime_type_from_name("inode/directory");
+    fm = GTK_COMBO_BOX(gtk_builder_get_object(builder, "fm_combobox"));
+    fm_app_chooser_combo_box_setup_for_mime_type(fm, mt);
+    fm_mime_type_unref(mt);
+    g_signal_connect(fm, "destroy", G_CALLBACK(on_app_chooser_destroy), NULL);
 
     w = (GtkWidget*)gtk_builder_get_object( builder, "term" );
-    if (terminal_cmd)
-        gtk_entry_set_text( GTK_ENTRY(w), terminal_cmd );
+    if (fm_config->terminal)
+        gtk_entry_set_text( GTK_ENTRY(w), fm_config->terminal );
     g_signal_connect( w, "focus-out-event",
-                      G_CALLBACK(on_entry_focus_out),
-                      &terminal_cmd);
+                      G_CALLBACK(on_entry_focus_out2),
+                      &fm_config->terminal);
 
     /* If we are under LXSession, setting logout command is not necessary. */
     w = (GtkWidget*)gtk_builder_get_object( builder, "logout" );
@@ -1123,67 +1188,9 @@ void panel_configure( Panel* p, int sel_page )
     g_object_unref(builder);
 }
 
-void
-panel_global_config_save( Panel* p, FILE *fp)
-{
-    fprintf(fp, "# lxpanel <profile> config file. Manually editing is not recommended.\n"
-                "# Use preference dialog in lxpanel to adjust config when you can.\n\n");
-    lxpanel_put_line(fp, "Global {");
-    lxpanel_put_str(fp, "edge", num2str(edge_pair, p->edge, "none"));
-    lxpanel_put_int(fp, "monitor", p->monitor);
-    lxpanel_put_str(fp, "allign", num2str(allign_pair, p->allign, "none"));
-    lxpanel_put_int(fp, "margin", p->margin);
-    lxpanel_put_str(fp, "widthtype", num2str(width_pair, p->widthtype, "none"));
-    lxpanel_put_int(fp, "width", p->width);
-    lxpanel_put_int(fp, "height", p->height);
-    lxpanel_put_bool(fp, "transparent", p->transparent );
-    lxpanel_put_line(fp, "tintcolor=#%06x", gcolor2rgb24(&p->gtintcolor));
-    lxpanel_put_int(fp, "alpha", p->alpha);
-    lxpanel_put_bool(fp, "autohide", p->autohide);
-    lxpanel_put_int(fp, "heightwhenhidden", p->height_when_hidden);
-    lxpanel_put_bool(fp, "setdocktype", p->setdocktype);
-    lxpanel_put_bool(fp, "setpartialstrut", p->setstrut);
-    lxpanel_put_bool(fp, "usefontcolor", p->usefontcolor);
-    lxpanel_put_int(fp, "fontsize", p->fontsize);
-    lxpanel_put_line(fp, "fontcolor=#%06x", gcolor2rgb24(&p->gfontcolor));
-    lxpanel_put_bool(fp, "usefontsize", p->usefontsize);
-    lxpanel_put_bool(fp, "background", p->background );
-    lxpanel_put_str(fp, "backgroundfile", p->background_file);
-    lxpanel_put_int(fp, "iconsize", p->icon_size);
-    lxpanel_put_int(fp, "loglevel", configured_log_level);
-    lxpanel_put_line(fp, "}\n");
-}
-
-void
-panel_plugin_config_save( Panel* p, FILE *fp)
-{
-    GList* l;
-    for( l = p->plugins; l; l = l->next )
-    {
-        Plugin* pl = (Plugin*)l->data;
-        lxpanel_put_line( fp, "Plugin {" );
-        lxpanel_put_line( fp, "type = %s", pl->class->type );
-        if( pl->expand )
-            lxpanel_put_bool( fp, "expand", TRUE );
-        if( pl->padding > 0 )
-            lxpanel_put_int( fp, "padding", pl->padding );
-        if( pl->border > 0 )
-            lxpanel_put_int( fp, "border", pl->border );
-
-        if( pl->class->save )
-        {
-            lxpanel_put_line( fp, "Config {" );
-            pl->class->save( pl, fp );
-            lxpanel_put_line( fp, "}" );
-        }
-        lxpanel_put_line( fp, "}\n" );
-    }
-}
-
 void panel_config_save( Panel* p )
 {
     gchar *fname, *dir;
-    FILE *fp;
 
     dir = get_config_file( cprofile, "panels", FALSE );
     fname = g_build_filename( dir, p->name, NULL );
@@ -1193,15 +1200,11 @@ void panel_config_save( Panel* p )
         g_mkdir_with_parents( dir, 0755 );
     g_free( dir );
 
-    if (!(fp = fopen(fname, "w"))) {
+    if (!config_write_file(p->config, fname)) {
         ERR("can't open for write %s:", fname);
         g_free( fname );
-        perror(NULL);
         RET();
     }
-    panel_global_config_save(p, fp);
-    panel_plugin_config_save(p, fp);
-    fclose(fp);
     g_free( fname );
 
     /* save the global config file */
@@ -1228,9 +1231,9 @@ void logout(void)
         l_logout_cmd = "lxsession-logout";
 
     if( l_logout_cmd )
-        spawn_command_async(NULL, NULL, l_logout_cmd);
+        fm_launch_command_simple(NULL, NULL, 0, l_logout_cmd, NULL);
     else
-        show_error( NULL, _("Logout command is not set") );
+        fm_show_error(NULL, NULL, _("Logout command is not set"));
 }
 
 static void notify_apply_config( GtkWidget* widget )
@@ -1241,7 +1244,7 @@ static void notify_apply_config( GtkWidget* widget )
     dlg = gtk_widget_get_toplevel( widget );
     apply_func = g_object_get_data( G_OBJECT(dlg), "apply_func" );
     if( apply_func )
-        (*apply_func)( g_object_get_data(G_OBJECT(dlg), "plugin") );
+        (*apply_func)( g_object_get_data(G_OBJECT(dlg), "apply_func_data") );
 }
 
 static gboolean on_entry_focus_out( GtkWidget* edit, GdkEventFocus *evt, gpointer user_data )
@@ -1255,6 +1258,20 @@ static gboolean on_entry_focus_out( GtkWidget* edit, GdkEventFocus *evt, gpointe
     return FALSE;
 }
 
+/* the same but affects fm_config instead of panel config */
+static gboolean on_entry_focus_out2( GtkWidget* edit, GdkEventFocus *evt, gpointer user_data )
+{
+    char** val = (char**)user_data;
+    const char *new_val;
+    new_val = gtk_entry_get_text(GTK_ENTRY(edit));
+    if (g_strcmp0(*val, new_val) == 0) /* not changed */
+        return FALSE;
+    g_free( *val );
+    *val = (new_val && *new_val) ? g_strdup( new_val ) : NULL;
+    fm_config_save(fm_config, NULL);
+    return FALSE;
+}
+
 static void on_spin_changed( GtkSpinButton* spin, gpointer user_data )
 {
     int* val = (int*)user_data;
@@ -1302,48 +1319,51 @@ static void on_browse_btn_clicked(GtkButton* btn, GtkEntry* entry)
     gtk_widget_destroy(fc);
 }
 
-static void generic_config_dlg_save(gpointer panel_gpointer,GObject *where_the_object_was)
+/* if the plugin was destroyed then destroy the dialog opened for it */
+static void on_plugin_destroy(GtkWidget *plugin, GtkDialog *dlg)
 {
-    Panel *panel = (Panel *)(panel_gpointer);
-    panel_config_save(panel);
+    gtk_dialog_response(dlg, GTK_RESPONSE_CLOSE);
 }
 
 /* Handler for "response" signal from standard configuration dialog. */
-static void generic_config_dlg_response(GtkWidget * widget, int response, Plugin * plugin)
-{
-    plugin->panel->plugin_pref_dialog = NULL;
-    gtk_widget_destroy(widget);
+static void generic_config_dlg_response(GtkWidget * dlg, int response, Panel * panel)
+{
+    gpointer plugin = g_object_get_data(G_OBJECT(dlg), "plugin");
+    if (plugin)
+        g_signal_handlers_disconnect_by_func(plugin, on_plugin_destroy, dlg);
+    g_object_set_data(G_OBJECT(dlg), "plugin", NULL);
+    panel->plugin_pref_dialog = NULL;
+    gtk_widget_destroy(dlg);
+    panel_config_save(panel);
 }
 
 /* Parameters: const char* name, gpointer ret_value, GType type, ....NULL */
-GtkWidget* create_generic_config_dlg( const char* title, GtkWidget* parent,
-                                      GSourceFunc apply_func, Plugin * plugin,
-                                      const char* name, ... )
+static GtkWidget *_lxpanel_generic_config_dlg(const char *title, Panel *p,
+                                              GSourceFunc apply_func,
+                                              gpointer plugin, GtkWidget *widget,
+                                              const char *name, va_list args)
 {
-    va_list args;
-    Panel* p = plugin->panel;
     GtkWidget* dlg = gtk_dialog_new_with_buttons( title, NULL, 0,
                                                   GTK_STOCK_CLOSE,
                                                   GTK_RESPONSE_CLOSE,
                                                   NULL );
     panel_apply_icon(GTK_WINDOW(dlg));
 
-    g_signal_connect( dlg, "response", G_CALLBACK(generic_config_dlg_response), plugin);
-    g_object_weak_ref(G_OBJECT(dlg), generic_config_dlg_save, p);
+    g_signal_connect( dlg, "response", G_CALLBACK(generic_config_dlg_response), p);
+    g_signal_connect(widget, "destroy", G_CALLBACK(on_plugin_destroy), dlg);
+    g_object_set_data(G_OBJECT(dlg), "plugin", widget);
     if( apply_func )
         g_object_set_data( G_OBJECT(dlg), "apply_func", apply_func );
-    if( plugin )
-        g_object_set_data( G_OBJECT(dlg), "plugin", plugin );
+    g_object_set_data( G_OBJECT(dlg), "apply_func_data", plugin );
 
     gtk_box_set_spacing( GTK_BOX(GTK_DIALOG(dlg)->vbox), 4 );
 
-    va_start( args, name );
     while( name )
     {
         GtkWidget* label = gtk_label_new( name );
         GtkWidget* entry = NULL;
         gpointer val = va_arg( args, gpointer );
-        enum _PluginConfType type = va_arg( args, enum _PluginConfType );
+        PluginConfType type = va_arg( args, PluginConfType );
         switch( type )
         {
             case CONF_TYPE_STR:
@@ -1418,20 +1438,51 @@ GtkWidget* create_generic_config_dlg( const char* title, GtkWidget* parent,
         }
         name = va_arg( args, const char* );
     }
-    va_end( args );
 
     gtk_container_set_border_width( GTK_CONTAINER(dlg), 8 );
 
     /* If there is already a plugin configuration dialog open, close it.
      * Then record this one in case the panel or plugin is deleted. */
     if (p->plugin_pref_dialog != NULL)
-        gtk_widget_destroy(p->plugin_pref_dialog);
+        gtk_dialog_response(GTK_DIALOG(p->plugin_pref_dialog), GTK_RESPONSE_CLOSE);
     p->plugin_pref_dialog = dlg;
 
     gtk_widget_show_all( dlg );
     return dlg;
 }
 
+/* new plugins API -- apply_func() gets GtkWidget* */
+GtkWidget *lxpanel_generic_config_dlg(const char *title, Panel *panel,
+                                      GSourceFunc apply_func, GtkWidget *plugin,
+                                      const char *name, ...)
+{
+    GtkWidget *dlg;
+    va_list args;
+
+    if (plugin == NULL)
+        return NULL;
+    va_start(args, name);
+    dlg = _lxpanel_generic_config_dlg(title, panel, apply_func, plugin, plugin, name, args);
+    va_end(args);
+    return dlg;
+}
+
+/* for old plugins compatibility -- apply_func() gets Plugin* */
+GtkWidget* create_generic_config_dlg( const char* title, GtkWidget* parent,
+                                      GSourceFunc apply_func, Plugin * plugin,
+                                      const char* name, ... )
+{
+    GtkWidget *dlg;
+    va_list args;
+
+    if (plugin == NULL)
+        return NULL;
+    va_start(args, name);
+    dlg = _lxpanel_generic_config_dlg(title, plugin->panel, apply_func, plugin, plugin->pwid, name, args);
+    va_end(args);
+    return dlg;
+}
+
 char* get_config_file( const char* profile, const char* file_name, gboolean is_global )
 {
     char* path;
@@ -1467,8 +1518,6 @@ void load_global_config()
 
     if( loaded )
     {
-        file_manager_cmd = g_key_file_get_string( kf, command_group, "FileManager", NULL );
-        terminal_cmd = g_key_file_get_string( kf, command_group, "Terminal", NULL );
         logout_cmd = g_key_file_get_string( kf, command_group, "Logout", NULL );
     }
     g_key_file_free( kf );
@@ -1481,10 +1530,6 @@ static void save_global_config()
     if( f )
     {
         fprintf( f, "[%s]\n", command_group );
-        if( file_manager_cmd )
-            fprintf( f, "FileManager=%s\n", file_manager_cmd );
-        if( terminal_cmd )
-            fprintf( f, "Terminal=%s\n", terminal_cmd );
         if( logout_cmd )
             fprintf( f, "Logout=%s\n", logout_cmd );
         fclose( f );
@@ -1493,22 +1538,27 @@ static void save_global_config()
 
 void free_global_config()
 {
-    g_free( file_manager_cmd );
-    g_free( terminal_cmd );
     g_free( logout_cmd );
 }
 
-extern const char*
+/* this is dirty and should be removed later */
+const char*
 lxpanel_get_file_manager()
 {
-    return file_manager_cmd ? file_manager_cmd : "pcmanfm %s";
-}
-
-extern const char*
-lxpanel_get_terminal()
-{
-    return terminal_cmd ? terminal_cmd : "lxterminal -e %s";
+    GAppInfo *app = g_app_info_get_default_for_type("inode/directory", TRUE);
+    static char *exec = NULL;
+    const char *c, *x;
+
+    if (!app)
+        return "pcmanfm %s";
+    c = g_app_info_get_commandline(app);
+    x = strchr(c, ' '); /* skip all arguments */
+    g_free(exec);
+    if (x)
+        exec = g_strndup(c, x - c);
+    else
+        exec = g_strdup(c);
+    return exec;
 }
 
-
 /* vim: set sw=4 et sts=4 : */
index c46aae0..0bfdc72 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "misc.h"
 #include <menu-cache.h>
+#include <libfm/fm-gtk.h>
 
 static GtkWidget* win = NULL; /* the run dialog */
 static MenuCache* menu_cache = NULL;
@@ -147,10 +148,8 @@ static void setup_auto_complete_with_data(ThreadData* data)
     GtkEntryCompletion* comp = gtk_entry_completion_new();
     gtk_entry_completion_set_minimum_key_length( comp, 2 );
     gtk_entry_completion_set_inline_completion( comp, TRUE );
-#if GTK_CHECK_VERSION( 2, 8, 0 )
     gtk_entry_completion_set_popup_set_width( comp, TRUE );
     gtk_entry_completion_set_popup_single_match( comp, FALSE );
-#endif
     store = gtk_list_store_new( 1, G_TYPE_STRING );
 
     for( l = data->files; l; l = l->next )
@@ -256,7 +255,7 @@ static void on_response( GtkDialog* dlg, gint response, gpointer user_data )
     GtkEntry* entry = (GtkEntry*)user_data;
     if( G_LIKELY(response == GTK_RESPONSE_OK) )
     {
-        if (!spawn_command_async(GTK_WINDOW(dlg), NULL, gtk_entry_get_text(entry)))
+        if (!fm_launch_command_simple(GTK_WINDOW(dlg), NULL, 0, gtk_entry_get_text(entry), NULL))
         {
             g_signal_stop_emission_by_name( dlg, "response" );
             return;
@@ -292,9 +291,14 @@ static void on_entry_changed( GtkEntry* entry, GtkImage* img )
     if( app )
     {
         int w, h;
+        const char *name = menu_cache_item_get_icon(MENU_CACHE_ITEM(app));
+        FmIcon * fm_icon;
         GdkPixbuf* pix;
+
         gtk_icon_size_lookup(GTK_ICON_SIZE_DIALOG, &w, &h);
-        pix = lxpanel_load_icon(menu_cache_item_get_icon(MENU_CACHE_ITEM(app)), w, h, TRUE);
+        fm_icon = fm_icon_from_name(name ? name : "application-x-executable");
+        pix = fm_pixbuf_from_icon_with_fallback(fm_icon, h, "application-x-executable");
+        g_object_unref(fm_icon);
         gtk_image_set_from_pixbuf(img, pix);
         g_object_unref(pix);
     }
index 23f25d5..e2a42d5 100644 (file)
@@ -21,8 +21,7 @@
 #include <string.h>
 
 #include "icon-grid.h"
-#include "panel.h"
-#include "plugin.h"
+#include "private.h"
 
 static gboolean icon_grid_placement(IconGrid * ig);
 static void icon_grid_geometry(IconGrid * ig, gboolean layout);
index 4e630cd..8f82336 100644 (file)
@@ -20,7 +20,7 @@
 #include <glib.h>
 
 #include "menu-policy.h"
-#include "panel.h"
+#include "private.h"
 
 guint32 visibility_flags = 0;
 
index 697f34f..9ea497c 100644 (file)
 #include <string.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <libfm/fm-gtk.h>
 
 #include "misc.h"
-#include "panel.h"
+#include "private.h"
 
 #include "dbg.h"
 
 /* data used by themed images buttons */
 typedef struct {
-    char* fname;
+    FmIcon *icon;
     guint theme_changed_handler;
     GdkPixbuf* pixbuf;
     GdkPixbuf* hilight;
     gulong hicolor;
-    int dw, dh; /* desired size */
-    gboolean keep_ratio;
+    gint size; /* desired size */
 } ImgData;
 
 static GQuark img_data_id = 0;
 
 static void on_theme_changed(GtkIconTheme* theme, GtkWidget* img);
-static void _gtk_image_set_from_file_scaled( GtkWidget* img, const gchar *file, gint width, gint height, gboolean keep_ratio);
+static void _gtk_image_set_from_file_scaled(GtkWidget *img, ImgData *data);
 
 /* X11 data types */
 Atom a_UTF8_STRING;
@@ -195,16 +195,9 @@ pair bool_pair[] = {
     { 1, "1" },
     { 0, NULL },
 };
-pair pos_pair[] = {
-    { POS_NONE, "none" },
-    { POS_START, "start" },
-    { POS_END,  "end" },
-    { 0, NULL},
-};
-
 
 int
-str2num(pair *p, gchar *str, int defval)
+str2num(pair *p, const gchar *str, int defval)
 {
     ENTER;
     for (;p && p->str; p++) {
@@ -214,8 +207,8 @@ str2num(pair *p, gchar *str, int defval)
     RET(defval);
 }
 
-gchar *
-num2str(pair *p, int num, gchar *defval)
+const gchar *
+num2str(pair *p, int num, const gchar *defval)
 {
     ENTER;
     for (;p && p->str; p++) {
@@ -315,42 +308,6 @@ lxpanel_get_line(char**fp, line *s)
     return s->type;
 }
 
-int
-get_line_as_is(char** fp, line *s)
-{
-    gchar *tmp, *tmp2;
-
-    ENTER;
-    if (!fp) {
-        s->type = LINE_NONE;
-        RET(s->type);
-    }
-    s->type = LINE_NONE;
-    while (buf_gets(s->str, s->len, fp)) {
-        g_strstrip(s->str);
-        if (s->str[0] == '#' || s->str[0] == 0)
-        continue;
-        DBG( ">> %s\n", s->str);
-        if (!g_ascii_strcasecmp(s->str, "}")) {
-            s->type = LINE_BLOCK_END;
-            DBG( "        : line_block_end\n");
-            break;
-        }
-        for (tmp = s->str; isalnum(*tmp); tmp++);
-        for (tmp2 = tmp; isspace(*tmp2); tmp2++);
-        if (*tmp2 == '=') {
-            s->type = LINE_VAR;
-        } else if  (*tmp2 == '{') {
-            s->type = LINE_BLOCK_START;
-        } else {
-            DBG( "        : ? <%c>\n", *tmp2);
-        }
-        break;
-    }
-    RET(s->type);
-
-}
-
 void resolve_atoms()
 {
     static const char* atom_names[ N_ATOMS ];
@@ -533,8 +490,8 @@ char **
 get_utf8_property_list(Window win, Atom atom, int *count)
 {
     Atom type;
-    int format, i;
-    gulong nitems;
+    int format;
+    gulong nitems, i;
     gulong bytes_after;
     gchar *s, **retval = NULL;
     int result;
@@ -555,7 +512,7 @@ get_utf8_property_list(Window win, Atom atom, int *count)
                 (*count)++;
         }
         retval = g_new0 (char*, *count + 2);
-        for (i = 0, s = val; i < *count; i++, s = s +  strlen (s) + 1) {
+        for (i = 0, s = val; (int)i < *count; i++, s = s +  strlen (s) + 1) {
             retval[i] = g_strdup(s);
         }
         if (val[nitems-1]) {
@@ -894,7 +851,7 @@ calculate_position(Panel *np)
 }
 
 gchar *
-expand_tilda(gchar *file)
+expand_tilda(const gchar *file)
 {
     ENTER;
     RET((file[0] == '~') ?
@@ -918,7 +875,7 @@ expand_tilda(gchar *file)
 /* DestroyNotify handler for image data in _gtk_image_new_from_file_scaled. */
 static void img_data_free(ImgData * data)
 {
-    g_free(data->fname);
+    g_object_unref(data->icon);
     if (data->theme_changed_handler != 0)
         g_signal_handler_disconnect(gtk_icon_theme_get_default(), data->theme_changed_handler);
     if (data->pixbuf != NULL)
@@ -932,10 +889,11 @@ static void img_data_free(ImgData * data)
 static void on_theme_changed(GtkIconTheme * theme, GtkWidget * img)
 {
     ImgData * data = (ImgData *) g_object_get_qdata(G_OBJECT(img), img_data_id);
-    _gtk_image_set_from_file_scaled(img, data->fname, data->dw, data->dh, data->keep_ratio);
+    _gtk_image_set_from_file_scaled(img, data);
 }
 
-void fb_button_set_from_file(GtkWidget * btn, const char * img_file, gint width, gint height, gboolean keep_ratio)
+/* consumes reference on icon */
+static void _lxpanel_button_set_icon(GtkWidget* btn, FmIcon* icon, gint size)
 {
     /* Locate the image within the button. */
     GtkWidget * child = gtk_bin_get_child(GTK_BIN(btn));
@@ -952,22 +910,39 @@ void fb_button_set_from_file(GtkWidget * btn, const char * img_file, gint width,
     if (img != NULL)
     {
         ImgData * data = (ImgData *) g_object_get_qdata(G_OBJECT(img), img_data_id);
-        g_free(data->fname);
-        data->fname = g_strdup(img_file);
-        data->dw = width;
-        data->dh = height;
-        data->keep_ratio = keep_ratio;
-        _gtk_image_set_from_file_scaled(img, data->fname, data->dw, data->dh, data->keep_ratio);
+
+        if (icon != data->icon || size != data->size) /* something was changed */
+        {
+            g_object_unref(data->icon);
+            data->icon = icon;
+            data->size = size;
+            _gtk_image_set_from_file_scaled(img, data);
+        }
+        else
+            g_object_unref(icon);
     }
+    else
+        g_object_unref(icon);
 }
 
-static void _gtk_image_set_from_file_scaled(GtkWidget * img, const gchar * file, gint width, gint height, gboolean keep_ratio)
+void lxpanel_button_set_icon(GtkWidget* btn, const gchar *name, gint size)
 {
-    ImgData * data = (ImgData *) g_object_get_qdata(G_OBJECT(img), img_data_id);
-    data->dw = width;
-    data->dh = height;
-    data->keep_ratio = keep_ratio;
+    _lxpanel_button_set_icon(btn, fm_icon_from_name(name), size);
+}
+
+void lxpanel_button_update_icon(GtkWidget* btn, FmIcon *icon, gint size)
+{
+    _lxpanel_button_set_icon(btn, g_object_ref(icon), size);
+}
+
+/* parameters width and keep_ratio are unused, kept for backward compatibility */
+void fb_button_set_from_file(GtkWidget * btn, const char * img_file, gint width, gint height, gboolean keep_ratio)
+{
+    lxpanel_button_set_icon(btn, img_file, height);
+}
 
+static void _gtk_image_set_from_file_scaled(GtkWidget * img, ImgData * data)
+{
     if (data->pixbuf != NULL)
     {
         g_object_unref(data->pixbuf);
@@ -981,68 +956,53 @@ static void _gtk_image_set_from_file_scaled(GtkWidget * img, const gchar * file,
         data->hilight = NULL;
     }
 
-    /* if they are the same string, eliminate unnecessary copy. */
-    gboolean themed = FALSE;
-    if (file != NULL)
+    if (G_LIKELY(G_IS_THEMED_ICON(data->icon)))
+        data->pixbuf = fm_pixbuf_from_icon_with_fallback(data->icon, data->size,
+                                                         "application-x-executable");
+    else
     {
-        if (data->fname != file)
-        {
-            g_free(data->fname);
-            data->fname = g_strdup(file);
-        }
-
-        if (g_file_test(file, G_FILE_TEST_EXISTS))
-        {
-            GdkPixbuf * pb_scaled = gdk_pixbuf_new_from_file_at_scale(file, width, height, keep_ratio, NULL);
-            if (pb_scaled != NULL)
-                data->pixbuf = pb_scaled;
-        }
-        else
-        {
-            data->pixbuf = lxpanel_load_icon(file, width, height, keep_ratio);
-            themed = TRUE;
-        }
+        char *file = g_icon_to_string(fm_icon_get_gicon(data->icon));
+        data->pixbuf = gdk_pixbuf_new_from_file_at_scale(file, -1, data->size, TRUE, NULL);
+        g_free(file);
     }
 
     if (data->pixbuf != NULL)
     {
         /* Set the pixbuf into the image widget. */
         gtk_image_set_from_pixbuf((GtkImage *)img, data->pixbuf);
-        if (themed)
-        {
-            /* This image is loaded from icon theme.  Update the image if the icon theme is changed. */
-            if (data->theme_changed_handler == 0)
-                data->theme_changed_handler = g_signal_connect(gtk_icon_theme_get_default(), "changed", G_CALLBACK(on_theme_changed), img);
-        }
-        else
-        {
-            /* This is not loaded from icon theme.  Disconnect the signal handler. */
-            if (data->theme_changed_handler != 0)
-            {
-                g_signal_handler_disconnect(gtk_icon_theme_get_default(), data->theme_changed_handler);
-                data->theme_changed_handler = 0;
-            }
-        }
     }
     else
     {
         /* No pixbuf available.  Set the "missing image" icon. */
         gtk_image_set_from_stock(GTK_IMAGE(img), GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_BUTTON);
     }
-    return;
 }
 
-GtkWidget * _gtk_image_new_from_file_scaled(const gchar * file, gint width, gint height, gboolean keep_ratio)
+/* consumes reference on icon */
+static GtkWidget *_gtk_image_new_for_icon(FmIcon *icon, gint size)
 {
     GtkWidget * img = gtk_image_new();
     ImgData * data = g_new0(ImgData, 1);
+
+    data->icon = icon;
+    data->size = size;
     if (img_data_id == 0)
         img_data_id = g_quark_from_static_string("ImgData");
     g_object_set_qdata_full(G_OBJECT(img), img_data_id, data, (GDestroyNotify) img_data_free);
-    _gtk_image_set_from_file_scaled(img, file, width, height, keep_ratio);
+    _gtk_image_set_from_file_scaled(img, data);
+    if (G_IS_THEMED_ICON(data->icon))
+    {
+        /* This image is loaded from icon theme.  Update the image if the icon theme is changed. */
+        data->theme_changed_handler = g_signal_connect(gtk_icon_theme_get_default(), "changed", G_CALLBACK(on_theme_changed), img);
+    }
     return img;
 }
 
+/* parameters width and keep_ratio are unused, kept for backward compatibility */
+GtkWidget * _gtk_image_new_from_file_scaled(const gchar * file, gint width, gint height, gboolean keep_ratio)
+{
+    return _gtk_image_new_for_icon(fm_icon_from_name(file), height);
+}
 
 void
 get_button_spacing(GtkRequisition *req, GtkContainer *parent, gchar *name)
@@ -1145,20 +1105,16 @@ static gboolean fb_button_leave(GtkImage * widget, GdkEventCrossing * event, gpo
 }
 
 
-GtkWidget * fb_button_new_from_file(
-    gchar * image_file, int width, int height, gulong highlight_color, gboolean keep_ratio)
-{
-    return fb_button_new_from_file_with_label(image_file, width, height, highlight_color, keep_ratio, NULL, NULL);
-}
-
-GtkWidget * fb_button_new_from_file_with_label(
-    gchar * image_file, int width, int height, gulong highlight_color, gboolean keep_ratio, Panel * panel, gchar * label)
+/* consumes reference on icon */
+static GtkWidget *_lxpanel_button_new_for_icon(Panel *panel, FmIcon *icon,
+                                               gint size, gulong highlight_color,
+                                               gchar *label)
 {
     GtkWidget * event_box = gtk_event_box_new();
     gtk_container_set_border_width(GTK_CONTAINER(event_box), 0);
     GTK_WIDGET_UNSET_FLAGS(event_box, GTK_CAN_FOCUS);
 
-    GtkWidget * image = _gtk_image_new_from_file_scaled(image_file, width, height, keep_ratio);
+    GtkWidget * image = _gtk_image_new_for_icon(icon, size);
     gtk_misc_set_padding(GTK_MISC(image), 0, 0);
     gtk_misc_set_alignment(GTK_MISC(image), 0, 0);
     if (highlight_color != 0)
@@ -1192,6 +1148,34 @@ GtkWidget * fb_button_new_from_file_with_label(
     return event_box;
 }
 
+GtkWidget *lxpanel_button_new_for_icon(Panel *panel, const gchar *name, GdkColor *color, gchar *label)
+{
+    gulong highlight_color = color ? gcolor2rgb24(color) : PANEL_ICON_HIGHLIGHT;
+    return _lxpanel_button_new_for_icon(panel, fm_icon_from_name(name),
+                                        panel->icon_size, highlight_color, label);
+}
+
+GtkWidget *lxpanel_button_new_for_fm_icon(Panel *panel, FmIcon *icon, GdkColor *color, gchar *label)
+{
+    gulong highlight_color = color ? gcolor2rgb24(color) : PANEL_ICON_HIGHLIGHT;
+    return _lxpanel_button_new_for_icon(panel, g_object_ref(icon),
+                                        panel->icon_size, highlight_color, label);
+}
+
+/* parameters width and keep_ratio are unused, kept for backward compatibility */
+GtkWidget * fb_button_new_from_file(
+    const gchar * image_file, int width, int height, gulong highlight_color, gboolean keep_ratio)
+{
+    return fb_button_new_from_file_with_label(image_file, width, height, highlight_color, keep_ratio, NULL, NULL);
+}
+
+/* parameters width and keep_ratio are unused, kept for backward compatibility */
+GtkWidget * fb_button_new_from_file_with_label(
+    const gchar * image_file, int width, int height, gulong highlight_color, gboolean keep_ratio, Panel * panel, gchar * label)
+{
+    return _lxpanel_button_new_for_icon(panel, fm_icon_from_name(image_file), height, highlight_color, label);
+}
+
 char* translate_exec_to_cmd( const char* exec, const char* icon,
                              const char* title, const char* fpath )
 {
@@ -1247,187 +1231,30 @@ char* translate_exec_to_cmd( const char* exec, const char* icon,
  any plugin with a layout box. Since GtkHBox cannot be changed to GtkVBox,
  recreating a new box to replace the old one is required.
 */
+/* for compatibility with old plugins */
 GtkWidget* recreate_box( GtkBox* oldbox, GtkOrientation orientation )
 {
-    GtkBox* newbox;
-    GList *child, *children;
-    GtkWidget* (*my_box_new) (gboolean homogeneous, gint spacing);
-
-    if( GTK_IS_HBOX(oldbox) ) {
-        if( orientation == GTK_ORIENTATION_HORIZONTAL )
-            return GTK_WIDGET(oldbox);
-    }
-    else {
-        if( orientation == GTK_ORIENTATION_VERTICAL )
-            return GTK_WIDGET(oldbox);
-    }
-    my_box_new = (orientation == GTK_ORIENTATION_HORIZONTAL ? gtk_hbox_new : gtk_vbox_new);
-
-    newbox = GTK_BOX(my_box_new( gtk_box_get_homogeneous(oldbox),
-                                 gtk_box_get_spacing(oldbox) ));
-    gtk_container_set_border_width (GTK_CONTAINER (newbox),
-                                    gtk_container_get_border_width(GTK_CONTAINER(oldbox)) );
-    children = gtk_container_get_children( GTK_CONTAINER (oldbox) );
-    for( child = children; child; child = child->next ) {
-        gboolean expand, fill;
-        guint padding;
-        GtkWidget* w = GTK_WIDGET(child->data);
-        gtk_box_query_child_packing( oldbox, w,
-                                     &expand, &fill, &padding, NULL );
-        /* g_debug( "repack %s, expand=%d, fill=%d", gtk_widget_get_name(w), expand, fill ); */
-        g_object_ref( w );
-        gtk_container_remove( GTK_CONTAINER (oldbox), w );
-        gtk_box_pack_start( newbox, w, expand, fill, padding );
-        g_object_unref( w );
-    }
-    g_list_free( children );
-    gtk_widget_show_all( GTK_WIDGET(newbox) );
-    gtk_widget_destroy( GTK_WIDGET(oldbox) );
-    return GTK_WIDGET(newbox);
+    gtk_orientable_set_orientation(GTK_ORIENTABLE(oldbox), orientation);
+    return GTK_WIDGET(oldbox);
 }
 
+/* for compatibility with old plugins */
 void show_error( GtkWindow* parent_win, const char* msg )
 {
-    GtkWidget* dlg = gtk_message_dialog_new( parent_win,
-                                             GTK_DIALOG_MODAL,
-                                             GTK_MESSAGE_ERROR,
-                                             GTK_BUTTONS_OK, "%s", msg );
-    gtk_dialog_run( (GtkDialog*)dlg );
-    gtk_widget_destroy( dlg );
-}
-
-/* Try to load an icon from a named file via the freedesktop.org data directories path.
- * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html */
-static GdkPixbuf * load_icon_file(const char * file_name, int height, int width)
-{
-    GdkPixbuf * icon = NULL;
-    const gchar ** dirs = (const gchar **) g_get_system_data_dirs();
-    const gchar ** dir;
-    for (dir = dirs; ((*dir != NULL) && (icon == NULL)); dir++)
-    {
-        char * file_path = g_build_filename(*dir, "pixmaps", file_name, NULL);
-        icon = gdk_pixbuf_new_from_file_at_scale(file_path, height, width, TRUE, NULL);
-        g_free(file_path);
-    }
-    return icon;
-}
-
-/* Try to load an icon from the current theme. */
-static GdkPixbuf * load_icon_from_theme(GtkIconTheme * theme, const char * icon_name, int width, int height)
-{
-    GdkPixbuf * icon = NULL;
-
-    /* Look up the icon in the current theme. */
-    GtkIconInfo * icon_info = gtk_icon_theme_lookup_icon(theme, icon_name, height, GTK_ICON_LOOKUP_USE_BUILTIN);
-    if (icon_info != NULL)
-    {
-        /* If that succeeded, get the filename of the icon.
-         * If that succeeds, load the icon from the specified file.
-         * Otherwise, try to get the builtin icon. */
-        const char * file = gtk_icon_info_get_filename(icon_info);
-        if (file != NULL)
-            icon = gdk_pixbuf_new_from_file(file, NULL);
-        else
-        {
-            icon = gtk_icon_info_get_builtin_pixbuf(icon_info);
-            g_object_ref(icon);
-        }
-        gtk_icon_info_free(icon_info);
-
-        /* If the icon is not sized properly, take a trip through the scaler.
-         * The lookup above takes the desired size, so we get the closest result possible. */
-        if (icon != NULL)
-        {
-            if ((height != gdk_pixbuf_get_height(icon)) || (width != gdk_pixbuf_get_width(icon)))
-            {
-                /* Handle case of unspecified width; gdk_pixbuf_scale_simple does not. */
-                if (width < 0)
-                {
-                    int pixbuf_width = gdk_pixbuf_get_width(icon);
-                    int pixbuf_height = gdk_pixbuf_get_height(icon);
-                    width = height * pixbuf_width / pixbuf_height;
-                }
-                GdkPixbuf * scaled = gdk_pixbuf_scale_simple(icon, width, height, GDK_INTERP_BILINEAR);
-                g_object_unref(icon);
-                icon = scaled;
-            }
-        }
-    }
-    return icon;
+    fm_show_error(parent_win, NULL, msg);
 }
 
+/* old plugins compatibility mode, use fm_pixbuf_from_icon_with_fallback() instead */
 GdkPixbuf * lxpanel_load_icon(const char * name, int width, int height, gboolean use_fallback)
 {
+    FmIcon * fm_icon;
     GdkPixbuf * icon = NULL;
 
-    if (name != NULL)
-    {
-        if (g_path_is_absolute(name))
-        {
-            /* Absolute path.
-             * To prevent the ugly icon, try to search icon from icon theme first,
-             * instead of loading icon from pixmaps dir */
-            GtkIconTheme * theme = gtk_icon_theme_get_default();
-            char *sub_suffix = strrchr(name, '.');
-            char *sub_deli = strrchr(name, '/');
-            int sub_len = sub_suffix - sub_deli - 1;
-            if (sub_len > 0) {
-                char *icon_name = g_strndup(&sub_deli[1], sub_len);
-                //LOG(LOG_ALL, "lxpanel: icon_name:%s\n", icon_name);
-                icon = load_icon_from_theme(theme, icon_name, width, height);
-                g_free(icon_name);
-            }
-
-            if (icon == NULL) {
-                /* Still not found... */
-                //LOG(LOG_ALL, "lxpanel: icon from theme not found\n");
-                icon = gdk_pixbuf_new_from_file_at_scale(name, width, height, TRUE, NULL);
-            }
-        }
-        else
-        {
-            /* Relative path. */
-            GtkIconTheme * theme = gtk_icon_theme_get_default();
-            char * suffix = strrchr(name, '.');
-            if ((suffix != NULL)
-            && ((g_ascii_strcasecmp(&suffix[1], "png") == 0)
-              || (g_ascii_strcasecmp(&suffix[1], "svg") == 0)
-              || (g_ascii_strcasecmp(&suffix[1], "xpm") == 0)))
-            {
-                /* The file extension indicates it could be in the system pixmap directories.
-                 * But in order to keep the icons in line with the icon theme, it's better to check
-                 * the icon in the current icon theme. Remove the suffix first. */
-                char * icon_name = g_strndup(name, suffix - name);
-                //LOG(LOG_ALL, "lxpanel: icon_name.suffix:%s.%s\n", icon_name, suffix);
-                icon = load_icon_from_theme(theme, icon_name, width, height);
-                g_free(icon_name);
-
-                /* Check the icon can be found in icon theme */
-                if (icon == NULL)
-                {
-                    /* Not found in icon theme, try to load from file directly */
-                    //LOG(LOG_ALL, "lxpanel: icon from theme not found\n");
-                    icon = load_icon_file(name, width, height);
-                }
-            }
-            else
-            {
-                /* No file extension.  It could be an icon name in the icon theme. */
-                //LOG(LOG_ALL, "lxpanel: icon has name:%s\n", name);
-                icon = load_icon_from_theme(theme, name, width, height);
-            }
-        }
-    }
-
-    /* Fall back to generic icons. */
-    if ((icon == NULL) && (use_fallback))
-    {
-        LOG(LOG_ALL, "lxpanel: using fallback icon for '%s'\n", name);
-        GtkIconTheme * theme = gtk_icon_theme_get_default();
-        icon = load_icon_from_theme(theme, "application-x-executable", width, height);
-        if (icon == NULL)
-            icon = load_icon_from_theme(theme, "gnome-mime-application-x-executable", width, height);
-    }
+    fm_icon = fm_icon_from_name(name ? name : "application-x-executable");
+    /* well, we don't use parameter width and not really use cache here */
+    icon = fm_pixbuf_from_icon_with_fallback(fm_icon, height,
+                            use_fallback ? "application-x-executable" : NULL);
+    g_object_unref(fm_icon);
     return icon;
 }
 
@@ -1593,7 +1420,7 @@ gboolean spawn_command_async(GtkWindow *parent_window, gchar const* workdir,
     if (err)
     {
         ERR("%s\n", err->message);
-        show_error(parent_window, err->message);
+        fm_show_error(parent_window, NULL, err->message);
         g_error_free(err);
     }
 
@@ -1602,6 +1429,7 @@ gboolean spawn_command_async(GtkWindow *parent_window, gchar const* workdir,
     return !err;
 }
 
+/* FIXME: this should be replaced with fm_launch_file_simple() */
 gboolean lxpanel_launch_app(const char* exec, GList* files, gboolean in_terminal, char const* in_workdir)
 {
     GError *error = NULL;
@@ -1613,7 +1441,7 @@ gboolean lxpanel_launch_app(const char* exec, GList* files, gboolean in_terminal
     {
        char * escaped_cmd = g_shell_quote(cmd);
         char* term_cmd;
-        const char* term = lxpanel_get_terminal();
+        const char* term = fm_config->terminal ? fm_config->terminal : "lxterminal";
         if( strstr(term, "%s") )
             term_cmd = g_strdup_printf(term, escaped_cmd);
         else
index 2353a88..2b4bda1 100644 (file)
 #include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 #include <stdio.h>
+#include <libfm/fm.h>
 
 #include "panel.h"
-#include "plugin.h"
-
-enum _PluginConfType {
-    CONF_TYPE_STR,
-    CONF_TYPE_INT,
-    CONF_TYPE_BOOL,
-    CONF_TYPE_FILE,
-    CONF_TYPE_FILE_ENTRY,
-    CONF_TYPE_DIRECTORY_ENTRY,
-    CONF_TYPE_TRIM
-};
-
-enum { LINE_NONE, LINE_BLOCK_START, LINE_BLOCK_END, LINE_VAR };
 
+/* Decoded value of WM_STATE property. */
 typedef struct {
-    int num, len, type;
-    gchar str[256];
-    gchar *t[3];
-} line;
-
-
+    unsigned int modal : 1;
+    unsigned int sticky : 1;
+    unsigned int maximized_vert : 1;
+    unsigned int maximized_horz : 1;
+    unsigned int shaded : 1;
+    unsigned int skip_taskbar : 1;
+    unsigned int skip_pager : 1;
+    unsigned int hidden : 1;
+    unsigned int fullscreen : 1;
+    unsigned int above : 1;
+    unsigned int below : 1;
+} NetWMState;
+
+/* Decoded value of _NET_WM_WINDOW_TYPE property. */
 typedef struct {
-    int num;
-    gchar *str;
-} pair;
-
-extern pair allign_pair[];
-extern pair edge_pair[];
-extern pair width_pair[];
-extern pair height_pair[];
-extern pair bool_pair[];
-extern pair pos_pair[];
-
-int str2num(pair *p, gchar *str, int defval);
-gchar *num2str(pair *p, int num, gchar *defval);
-
-extern int lxpanel_get_line(char **fp, line *s);
-extern int lxpanel_put_line(FILE* fp, const char* format, ...);
-#define lxpanel_put_str(fp, name, val) (G_UNLIKELY( !(val) || !*(val) )) ? 0 : lxpanel_put_line(fp, "%s=%s", name, val)
-#define lxpanel_put_bool(fp, name, val) lxpanel_put_line(fp, "%s=%c", name, (val) ? '1' : '0')
-#define lxpanel_put_int(fp, name, val) lxpanel_put_line(fp, "%s=%d", name, val)
-//extern int lxpanel_put_str( FILE* fp, const char* name, const char* val );
-//extern int lxpanel_put_bool( FILE* fp, const char* name, gboolean val );
-//extern int lxpanel_put_int( FILE* fp, const char* name, int val );
-int get_line_as_is(char **fp, line *s);
+    unsigned int desktop : 1;
+    unsigned int dock : 1;
+    unsigned int toolbar : 1;
+    unsigned int menu : 1;
+    unsigned int utility : 1;
+    unsigned int splash : 1;
+    unsigned int dialog : 1;
+    unsigned int normal : 1;
+} NetWMWindowType;
 
 void Xclimsg(Window win, Atom type, long l0, long l1, long l2, long l3, long l4);
 void Xclimsgwm(Window win, Atom type, Atom arg);
@@ -90,46 +73,29 @@ void get_net_wm_window_type(Window win, NetWMWindowType *nwwt);
 GPid get_net_wm_pid(Window win);
 
 void calculate_position(Panel *np);
-gchar *expand_tilda(gchar *file);
+gchar *expand_tilda(const gchar *file);
 
-GtkWidget *_gtk_image_new_from_file_scaled(const gchar *file, gint width,
-                                           gint height, gboolean keep_ratio);
 void get_button_spacing(GtkRequisition *req, GtkContainer *parent, gchar *name);
 guint32 gcolor2rgb24(GdkColor *color);
-GtkWidget * fb_button_new_from_file(
-    gchar * image_file, int width, int height, gulong highlight_color, gboolean keep_ratio);
-GtkWidget * fb_button_new_from_file_with_label(
-    gchar * image_file, int width, int height, gulong highlight_color, gboolean keep_ratio, Panel * panel, gchar * label);
-
-char* translate_exec_to_cmd( const char* exec, const char* icon,
-                             const char* title, const char* fpath );
+GtkWidget *lxpanel_button_new_for_icon(Panel *panel, const gchar *name, GdkColor *color, gchar *label);
+GtkWidget *lxpanel_button_new_for_fm_icon(Panel *panel, FmIcon *icon, GdkColor *color, gchar *label);
+void lxpanel_button_set_icon(GtkWidget* btn, const gchar *name, gint size);
+void lxpanel_button_update_icon(GtkWidget* btn, FmIcon *icon, gint size);
 
-/*
- This function is used to re-create a new box with different
- orientation from the old one, add all children of the old one to
- the new one, and then destroy the old box.
- It's mainly used when we need to change the orientation of the panel or
- any plugin with a layout box. Since GtkHBox cannot be changed to GtkVBox,
- recreating a new box to replace the old one is required.
-*/
-GtkWidget* recreate_box( GtkBox* oldbox, GtkOrientation orientation );
-
-void show_error( GtkWindow* parent_win, const char* msg );
-
-/* Parameters: const char* name, gpointer ret_value, GType type, ....NULL */
-GtkWidget* create_generic_config_dlg( const char* title, GtkWidget* parent,
-                              GSourceFunc apply_func, Plugin * plugin,
-                      const char* name, ... );
-
-
-char* get_config_file( const char* profile, const char* file_name, gboolean is_global );
-
-extern GtkMenu* lxpanel_get_panel_menu( Panel* panel, Plugin* plugin, gboolean use_sub_menu );
-
-extern GdkPixbuf* lxpanel_load_icon( const char* name, int width, int height, gboolean use_fallback );
-
-void fb_button_set_from_file(GtkWidget* btn, const char* img_file, gint width, gint height, gboolean keep_ratio);
+typedef enum {
+    CONF_TYPE_STR,
+    CONF_TYPE_INT,
+    CONF_TYPE_BOOL,
+    CONF_TYPE_FILE,
+    CONF_TYPE_FILE_ENTRY,
+    CONF_TYPE_DIRECTORY_ENTRY,
+    CONF_TYPE_TRIM
+} PluginConfType;
 
-gboolean lxpanel_launch_app(const char* exec, GList* files, gboolean in_terminal, char const* in_workdir);
+/* Parameters: const char* name, gpointer ret_value, PluginConfType type, ....NULL */
+extern GtkWidget *lxpanel_generic_config_dlg(const char *title, Panel *panel,
+                                             GSourceFunc apply_func,
+                                             GtkWidget *plugin,
+                                             const char *name, ...);
 
 #endif
index 4069e3a..e2fef72 100644 (file)
@@ -30,9 +30,9 @@
 #include <locale.h>
 #include <string.h>
 #include <gdk/gdkx.h>
+#include <libfm/fm-gtk.h>
 
-#include "plugin.h"
-#include "panel.h"
+#include "private.h"
 #include "misc.h"
 #include "bg.h"
 
@@ -52,9 +52,8 @@ GSList* all_panels = NULL;  /* a single-linked list storing all panels */
 
 gboolean is_restarting = FALSE;
 
-static int panel_start( Panel *p, char **fp );
+static int panel_start(Panel *p);
 static void panel_start_gui(Panel *p);
-void panel_config_save(Panel* panel);   /* defined in configurator.c */
 
 gboolean is_in_lxde = FALSE;
 
@@ -112,6 +111,7 @@ static Panel* panel_allocate(void)
     p->spacing = 0;
     p->icon_size = PANEL_ICON_SIZE;
     p->icon_theme = gtk_icon_theme_get_default();
+    p->config = config_new();
     return p;
 }
 
@@ -442,20 +442,18 @@ void panel_determine_background_pixmap(Panel * p, GtkWidget * widget, GdkWindow
  * This function should only be called after the panel has been realized. */
 void panel_update_background(Panel * p)
 {
+    GList *plugins, *l;
+
     /* Redraw the top level widget. */
     panel_determine_background_pixmap(p, p->topgwin, p->topgwin->window);
     gdk_window_clear(p->topgwin->window);
     gtk_widget_queue_draw(p->topgwin);
 
     /* Loop over all plugins redrawing each plugin. */
-    GList * l;
-    for (l = p->plugins; l != NULL; l = l->next)
-    {
-        Plugin * pl = (Plugin *) l->data;
-        if (pl->pwid != NULL)
-            plugin_widget_set_background(pl->pwid, p);
-    }
-
+    plugins = gtk_container_get_children(GTK_CONTAINER(p->box));
+    for (l = plugins; l != NULL; l = l->next)
+        plugin_widget_set_background(l->data, p);
+    g_list_free(plugins);
 }
 
 static gboolean delay_update_background( Panel* p )
@@ -496,9 +494,9 @@ panel_size_req(GtkWidget *widget, GtkRequisition *req, Panel *p)
         gtk_widget_size_request(p->box, req);
 
     if (p->widthtype == WIDTH_REQUEST)
-        p->width = (p->orientation == ORIENT_HORIZ) ? req->width : req->height;
+        p->width = (p->orientation == GTK_ORIENTATION_HORIZONTAL) ? req->width : req->height;
     if (p->heighttype == HEIGHT_REQUEST)
-        p->height = (p->orientation == ORIENT_HORIZ) ? req->height : req->width;
+        p->height = (p->orientation == GTK_ORIENTATION_HORIZONTAL) ? req->height : req->width;
 
     calculate_position(p);
 
@@ -512,9 +510,9 @@ panel_size_alloc(GtkWidget *widget, GtkAllocation *a, Panel *p)
 {
     ENTER;
     if (p->widthtype == WIDTH_REQUEST)
-        p->width = (p->orientation == ORIENT_HORIZ) ? a->width : a->height;
+        p->width = (p->orientation == GTK_ORIENTATION_HORIZONTAL) ? a->width : a->height;
     if (p->heighttype == HEIGHT_REQUEST)
-        p->height = (p->orientation == ORIENT_HORIZ) ? a->height : a->width;
+        p->height = (p->orientation == GTK_ORIENTATION_HORIZONTAL) ? a->height : a->width;
     calculate_position(p);
 
     if (a->width == p->aw && a->height == p->ah && a->x == p->ax && a->y == p ->ay) {
@@ -555,19 +553,22 @@ static gboolean panel_button_press_event_with_panel(GtkWidget *widget, GdkEventB
 {
     if (event->button == 3)     /* right button */
     {
-        GtkMenu* popup = (GtkMenu*) lxpanel_get_panel_menu(panel, NULL, FALSE);
+        GtkMenu* popup = (GtkMenu*) lxpanel_get_plugin_menu(panel, NULL, FALSE);
         gtk_menu_popup(popup, NULL, NULL, NULL, NULL, event->button, event->time);
         return TRUE;
     }    
     return FALSE;
 }
 
-static void panel_popupmenu_config_plugin( GtkMenuItem* item, Plugin* plugin )
+static void panel_popupmenu_config_plugin( GtkMenuItem* item, GtkWidget* plugin )
 {
-    plugin->class->config( plugin, GTK_WINDOW(plugin->panel->topgwin) );
+    LXPanelPluginInit *init = PLUGIN_CLASS(plugin);
+    Panel *panel = PLUGIN_PANEL(plugin);
+
+    init->config(panel, plugin, GTK_WINDOW(panel->topgwin));
 
     /* FIXME: this should be more elegant */
-    plugin->panel->config_changed = TRUE;
+    panel->config_changed = TRUE;
 }
 
 static void panel_popupmenu_add_item( GtkMenuItem* item, Panel* panel )
@@ -576,9 +577,9 @@ static void panel_popupmenu_add_item( GtkMenuItem* item, Panel* panel )
     panel_configure( panel, 2 );
 }
 
-static void panel_popupmenu_remove_item( GtkMenuItem* item, Plugin* plugin )
+static void panel_popupmenu_remove_item( GtkMenuItem* item, GtkWidget* plugin )
 {
-    Panel* panel = plugin->panel;
+    Panel* panel = PLUGIN_PANEL(plugin);
 
     /* If the configuration dialog is open, there will certainly be a crash if the
      * user manipulates the Configured Plugins list, after we remove this entry.
@@ -588,10 +589,12 @@ static void panel_popupmenu_remove_item( GtkMenuItem* item, Plugin* plugin )
         gtk_widget_destroy(panel->pref_dialog);
         panel->pref_dialog = NULL;
     }
+    config_setting_destroy(g_object_get_qdata(G_OBJECT(plugin), lxpanel_plugin_qconf));
+    /* reset conf pointer because the widget still may be referenced by configurator */
+    g_object_set_qdata(G_OBJECT(plugin), lxpanel_plugin_qconf, NULL);
 
-    panel->plugins = g_list_remove( panel->plugins, plugin );
-    panel_config_save( plugin->panel );
-    plugin_delete(plugin);
+    panel_config_save(panel);
+    gtk_widget_destroy(plugin);
 }
 
 /* FIXME: Potentially we can support multiple panels at the same edge,
@@ -651,6 +654,7 @@ static void panel_popupmenu_create_panel( GtkMenuItem* item, Panel* panel )
         }
     }
 
+    panel_destroy(new_panel);
     ERR("Error adding panel: There is no room for another panel. All the edges are taken.\n");
     err = gtk_message_dialog_new(NULL,0,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,_("There is no room for another panel. All the edges are taken."));
     gtk_dialog_run(GTK_DIALOG(err));
@@ -660,6 +664,10 @@ static void panel_popupmenu_create_panel( GtkMenuItem* item, Panel* panel )
 found_edge:
     new_panel->name = gen_panel_name(new_panel->edge,new_panel->monitor);
 
+    /* create new config with first group "Global" */
+    config_setting_add(config_setting_add(config_root_setting(new_panel->config),
+                                          "", PANEL_CONF_TYPE_LIST),
+                       "Global", PANEL_CONF_TYPE_GROUP);
     panel_configure(new_panel, 0);
     panel_normalize_configuration(new_panel);
     panel_start_gui(new_panel);
@@ -764,11 +772,11 @@ void panel_apply_icon( GtkWindow *w )
     gtk_window_set_icon(w, window_icon);
 }
 
-GtkMenu* lxpanel_get_panel_menu( Panel* panel, Plugin* plugin, gboolean use_sub_menu )
+GtkMenu* lxpanel_get_plugin_menu( Panel* panel, GtkWidget* plugin, gboolean use_sub_menu )
 {
     GtkWidget  *menu_item, *img;
     GtkMenu *ret,*menu;
-    
+    LXPanelPluginInit *init;
     char* tmp;
     ret = menu = GTK_MENU(gtk_menu_new());
 
@@ -780,8 +788,9 @@ GtkMenu* lxpanel_get_panel_menu( Panel* panel, Plugin* plugin, gboolean use_sub_
 
     if( plugin )
     {
+        init = PLUGIN_CLASS(plugin);
         img = gtk_image_new_from_stock( GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU );
-        tmp = g_strdup_printf( _("Remove \"%s\" From Panel"), _(plugin->class->name) );
+        tmp = g_strdup_printf( _("Remove \"%s\" From Panel"), _(init->name) );
         menu_item = gtk_image_menu_item_new_with_label( tmp );
         g_free( tmp );
         gtk_image_menu_item_set_image( (GtkImageMenuItem*)menu_item, img );
@@ -837,12 +846,12 @@ GtkMenu* lxpanel_get_panel_menu( Panel* panel, Plugin* plugin, gboolean use_sub_
         gtk_menu_shell_prepend(GTK_MENU_SHELL(ret), menu_item);
 
         img = gtk_image_new_from_stock( GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU );
-        tmp = g_strdup_printf( _("\"%s\" Settings"), _(plugin->class->name) );
+        tmp = g_strdup_printf( _("\"%s\" Settings"), _(init->name) );
         menu_item = gtk_image_menu_item_new_with_label( tmp );
         g_free( tmp );
         gtk_image_menu_item_set_image( (GtkImageMenuItem*)menu_item, img );
         gtk_menu_shell_prepend(GTK_MENU_SHELL(ret), menu_item);
-        if( plugin->class->config )
+        if( init->config )
             g_signal_connect( menu_item, "activate", G_CALLBACK(panel_popupmenu_config_plugin), plugin );
         else
             gtk_widget_set_sensitive( menu_item, FALSE );
@@ -854,6 +863,12 @@ GtkMenu* lxpanel_get_panel_menu( Panel* panel, Plugin* plugin, gboolean use_sub_
     return ret;
 }
 
+/* for old plugins compatibility */
+GtkMenu* lxpanel_get_panel_menu( Panel* panel, Plugin* plugin, gboolean use_sub_menu )
+{
+    return lxpanel_get_plugin_menu(panel, plugin->pwid, use_sub_menu);
+}
+
 /****************************************************
  *         panel creation                           *
  ****************************************************/
@@ -1024,7 +1039,7 @@ panel_start_gui(Panel *p)
           (GCallback) panel_configure_event, p);
 
     gtk_widget_add_events( p->topgwin, GDK_BUTTON_PRESS_MASK );
-    g_signal_connect(G_OBJECT (p->topgwin), "button_press_event",
+    g_signal_connect(G_OBJECT (p->topgwin), "button-press-event",
           (GCallback) panel_button_press_event_with_panel, p);
 
     g_signal_connect (G_OBJECT (p->topgwin), "realize",
@@ -1177,29 +1192,29 @@ void panel_draw_label_text(Panel * p, GtkWidget * label, char * text, gboolean b
 
 void panel_set_panel_configuration_changed(Panel *p)
 {
-    GListl;
+    GList *plugins, *l;
 
-    int previous_orientation = p->orientation;
+    GtkOrientation previous_orientation = p->orientation;
     p->orientation = (p->edge == EDGE_TOP || p->edge == EDGE_BOTTOM)
-        ? ORIENT_HORIZ : ORIENT_VERT;
+        ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
 
-    if (previous_orientation != p->orientation)
+    /* either first run or orientation was changed */
+    if (p->my_box_new == NULL || previous_orientation != p->orientation)
     {
         panel_adjust_geometry_terminology(p);
-        if (previous_orientation != ORIENT_NONE)
-            p->height = ((p->orientation == ORIENT_HORIZ) ? PANEL_HEIGHT_DEFAULT : PANEL_WIDTH_DEFAULT);
+        p->height = ((p->orientation == GTK_ORIENTATION_HORIZONTAL) ? PANEL_HEIGHT_DEFAULT : PANEL_WIDTH_DEFAULT);
         if (p->height_control != NULL)
             gtk_spin_button_set_value(GTK_SPIN_BUTTON(p->height_control), p->height);
         if ((p->widthtype == WIDTH_PIXEL) && (p->width_control != NULL))
         {
-            int value = ((p->orientation == ORIENT_HORIZ) ? gdk_screen_width() : gdk_screen_height());
+            int value = ((p->orientation == GTK_ORIENTATION_HORIZONTAL) ? gdk_screen_width() : gdk_screen_height());
             gtk_spin_button_set_range(GTK_SPIN_BUTTON(p->width_control), 0, value);
             gtk_spin_button_set_value(GTK_SPIN_BUTTON(p->width_control), value);
         }
 
     }
 
-    if (p->orientation == ORIENT_HORIZ) {
+    if (p->orientation == GTK_ORIENTATION_HORIZONTAL) {
         p->my_box_new = gtk_hbox_new;
         p->my_separator_new = gtk_vseparator_new;
     } else {
@@ -1210,17 +1225,7 @@ void panel_set_panel_configuration_changed(Panel *p)
     /* recreate the main layout box */
     if (p->box != NULL)
     {
-#if GTK_CHECK_VERSION(2,16,0)
-        GtkOrientation bo = (p->orientation == ORIENT_HORIZ) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
-        gtk_orientable_set_orientation(GTK_ORIENTABLE(p->box), bo);
-#else
-        GtkBox * newbox = GTK_BOX(recreate_box(GTK_BOX(p->box), p->orientation));
-        if (GTK_WIDGET(newbox) != p->box)
-        {
-            p->box = GTK_WIDGET(newbox);
-            gtk_container_add(GTK_CONTAINER(p->topgwin), GTK_WIDGET(newbox));
-        }
-#endif
+        gtk_orientable_set_orientation(GTK_ORIENTABLE(p->box), p->orientation);
     }
 
     /* NOTE: This loop won't be executed when panel started since
@@ -1228,94 +1233,87 @@ void panel_set_panel_configuration_changed(Panel *p)
        This is used when the orientation of the panel is changed
        from the config dialog, and plugins should be re-layout.
     */
-    for( l = p->plugins; l; l = l->next ) {
-        Plugin* pl = (Plugin*)l->data;
-        if( pl->class->panel_configuration_changed ) {
-            pl->class->panel_configuration_changed( pl );
-        }
+    plugins = p->box ? gtk_container_get_children(GTK_CONTAINER(p->box)) : NULL;
+    for( l = plugins; l; l = l->next ) {
+        GtkWidget *w = (GtkWidget*)l->data;
+        LXPanelPluginInit *init = PLUGIN_CLASS(w);
+        if (init->reconfigure)
+            init->reconfigure(p, w);
     }
+    g_list_free(plugins);
 }
 
 static int
-panel_parse_global(Panel *p, char **fp)
+panel_parse_global(Panel *p, config_setting_t *cfg)
 {
-    line s;
-    s.len = 256;
+    const char *str;
+    gint i;
 
-    if( G_LIKELY( fp ) )
+    /* check Global config */
+    if (!cfg || strcmp(config_setting_get_name(cfg), "Global") != 0)
     {
-        while (lxpanel_get_line(fp, &s) != LINE_NONE) {
-            if (s.type == LINE_VAR) {
-                if (!g_ascii_strcasecmp(s.t[0], "edge")) {
-                    p->edge = str2num(edge_pair, s.t[1], EDGE_NONE);
-                } else if (!g_ascii_strcasecmp(s.t[0], "allign")) {
-                    p->allign = str2num(allign_pair, s.t[1], ALLIGN_NONE);
-                } else if (!g_ascii_strcasecmp(s.t[0], "monitor")) {
-                    p->monitor = atoi(s.t[1]);
-                } else if (!g_ascii_strcasecmp(s.t[0], "margin")) {
-                    p->margin = atoi(s.t[1]);
-                } else if (!g_ascii_strcasecmp(s.t[0], "widthtype")) {
-                    p->widthtype = str2num(width_pair, s.t[1], WIDTH_NONE);
-                } else if (!g_ascii_strcasecmp(s.t[0], "width")) {
-                    p->width = atoi(s.t[1]);
-                } else if (!g_ascii_strcasecmp(s.t[0], "heighttype")) {
-                    p->heighttype = str2num(height_pair, s.t[1], HEIGHT_NONE);
-                } else if (!g_ascii_strcasecmp(s.t[0], "height")) {
-                    p->height = atoi(s.t[1]);
-                } else if (!g_ascii_strcasecmp(s.t[0], "spacing")) {
-                    p->spacing = atoi(s.t[1]);
-                } else if (!g_ascii_strcasecmp(s.t[0], "SetDockType")) {
-                    p->setdocktype = str2num(bool_pair, s.t[1], 0);
-                } else if (!g_ascii_strcasecmp(s.t[0], "SetPartialStrut")) {
-                    p->setstrut = str2num(bool_pair, s.t[1], 0);
-                } else if (!g_ascii_strcasecmp(s.t[0], "RoundCorners")) {
-                    p->round_corners = str2num(bool_pair, s.t[1], 0);
-                } else if (!g_ascii_strcasecmp(s.t[0], "Transparent")) {
-                    p->transparent = str2num(bool_pair, s.t[1], 0);
-                } else if (!g_ascii_strcasecmp(s.t[0], "Alpha")) {
-                    p->alpha = atoi(s.t[1]);
-                    if (p->alpha > 255)
-                        p->alpha = 255;
-                } else if (!g_ascii_strcasecmp(s.t[0], "AutoHide")) {
-                    p->autohide = str2num(bool_pair, s.t[1], 0);
-                } else if (!g_ascii_strcasecmp(s.t[0], "HeightWhenHidden")) {
-                    p->height_when_hidden = atoi(s.t[1]);
-                } else if (!g_ascii_strcasecmp(s.t[0], "TintColor")) {
-                    if (!gdk_color_parse (s.t[1], &p->gtintcolor))
-                        gdk_color_parse ("white", &p->gtintcolor);
-                    p->tintcolor = gcolor2rgb24(&p->gtintcolor);
-                    DBG("tintcolor=%x\n", p->tintcolor);
-                } else if (!g_ascii_strcasecmp(s.t[0], "useFontColor")) {
-                    p->usefontcolor = str2num(bool_pair, s.t[1], 0);
-                } else if (!g_ascii_strcasecmp(s.t[0], "FontColor")) {
-                    if (!gdk_color_parse (s.t[1], &p->gfontcolor))
-                        gdk_color_parse ("black", &p->gfontcolor);
-                    p->fontcolor = gcolor2rgb24(&p->gfontcolor);
-                    DBG("fontcolor=%x\n", p->fontcolor);
-                } else if (!g_ascii_strcasecmp(s.t[0], "useFontSize")) {
-                    p->usefontsize = str2num(bool_pair, s.t[1], 0);
-                } else if (!g_ascii_strcasecmp(s.t[0], "FontSize")) {
-                    p->fontsize = atoi(s.t[1]);                    
-                } else if (!g_ascii_strcasecmp(s.t[0], "Background")) {
-                    p->background = str2num(bool_pair, s.t[1], 0);
-                } else if( !g_ascii_strcasecmp(s.t[0], "BackgroundFile") ) {
-                    p->background_file = g_strdup( s.t[1] );
-                } else if (!g_ascii_strcasecmp(s.t[0], "IconSize")) {
-                    p->icon_size = atoi(s.t[1]);
-                } else if (!g_ascii_strcasecmp(s.t[0], "LogLevel")) {
-                    configured_log_level = atoi(s.t[1]);
-                    if (!log_level_set_on_commandline)
-                        log_level = configured_log_level;
-                } else {
-                    ERR( "lxpanel: %s - unknown var in Global section\n", s.t[0]);
-                }
-            } else if (s.type == LINE_BLOCK_END) {
-                break;
-            } else {
-                ERR( "lxpanel: illegal in this context %s\n", s.str);
-                RET(0);
-            }
-        }
+        ERR( "lxpanel: Global section not found\n");
+        RET(0);
+    }
+    if (config_setting_lookup_string(cfg, "edge", &str))
+        p->edge = str2num(edge_pair, str, EDGE_NONE);
+    if (config_setting_lookup_string(cfg, "allign", &str))
+        p->allign = str2num(allign_pair, str, ALLIGN_NONE);
+    config_setting_lookup_int(cfg, "monitor", &p->monitor);
+    config_setting_lookup_int(cfg, "margin", &p->margin);
+    if (config_setting_lookup_string(cfg, "widthtype", &str))
+        p->widthtype = str2num(width_pair, str, WIDTH_NONE);
+    config_setting_lookup_int(cfg, "width", &p->width);
+    if (config_setting_lookup_string(cfg, "heighttype", &str))
+        p->heighttype = str2num(height_pair, str, HEIGHT_NONE);
+    config_setting_lookup_int(cfg, "height", &p->height);
+    if (config_setting_lookup_int(cfg, "spacing", &i) && i > 0)
+        p->spacing = i;
+    if (config_setting_lookup_int(cfg, "setdocktype", &i))
+        p->setdocktype = i != 0;
+    if (config_setting_lookup_int(cfg, "setpartialstrut", &i))
+        p->setstrut = i != 0;
+    if (config_setting_lookup_int(cfg, "RoundCorners", &i))
+        p->round_corners = i != 0;
+    if (config_setting_lookup_int(cfg, "transparent", &i))
+        p->transparent = i != 0;
+    if (config_setting_lookup_int(cfg, "alpha", &p->alpha))
+    {
+        if (p->alpha > 255)
+            p->alpha = 255;
+    }
+    if (config_setting_lookup_int(cfg, "autohide", &i))
+        p->autohide = i != 0;
+    config_setting_lookup_int(cfg, "heightwhenhidden", &p->height_when_hidden);
+    if (config_setting_lookup_string(cfg, "tintcolor", &str))
+    {
+        if (!gdk_color_parse (str, &p->gtintcolor))
+            gdk_color_parse ("white", &p->gtintcolor);
+        p->tintcolor = gcolor2rgb24(&p->gtintcolor);
+            DBG("tintcolor=%x\n", p->tintcolor);
+    }
+    if (config_setting_lookup_int(cfg, "usefontcolor", &i))
+        p->usefontcolor = i != 0;
+    if (config_setting_lookup_string(cfg, "fontcolor", &str))
+    {
+        if (!gdk_color_parse (str, &p->gfontcolor))
+            gdk_color_parse ("black", &p->gfontcolor);
+        p->fontcolor = gcolor2rgb24(&p->gfontcolor);
+            DBG("fontcolor=%x\n", p->fontcolor);
+    }
+    if (config_setting_lookup_int(cfg, "usefontsize", &i))
+        p->usefontsize = i != 0;
+    if (config_setting_lookup_int(cfg, "fontsize", &i) && i > 0)
+        p->fontsize = i;
+    if (config_setting_lookup_int(cfg, "background", &i))
+        p->background = i != 0;
+    if (config_setting_lookup_string(cfg, "backgroundfile", &str))
+        p->background_file = g_strdup(str);
+    config_setting_lookup_int(cfg, "iconsize", &p->icon_size);
+    if (config_setting_lookup_int(cfg, "loglevel", &configured_log_level))
+    {
+        if (!log_level_set_on_commandline)
+            log_level = configured_log_level;
     }
 
     panel_normalize_configuration(p);
@@ -1324,123 +1322,50 @@ panel_parse_global(Panel *p, char **fp)
 }
 
 static int
-panel_parse_plugin(Panel *p, char **fp)
+panel_parse_plugin(Panel *p, config_setting_t *cfg)
 {
-    line s;
-    Plugin *plug = NULL;
-    gchar *type = NULL;
-    int expand , padding, border;
-    char* pconfig = NULL;
+    const char *type = NULL;
 
     ENTER;
-    s.len = 256;
-    border = expand = padding = 0;
-    while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
-        if (s.type == LINE_NONE) {
-            ERR( "lxpanel: bad line %s\n", s.str);
-            goto error;
-        }
-        if (s.type == LINE_VAR) {
-            if (!g_ascii_strcasecmp(s.t[0], "type")) {
-                type = g_strdup(s.t[1]);
-                DBG("plug %s\n", type);
-            } else if (!g_ascii_strcasecmp(s.t[0], "expand"))
-                expand = str2num(bool_pair,  s.t[1], 0);
-            else if (!g_ascii_strcasecmp(s.t[0], "padding"))
-                padding = atoi(s.t[1]);
-            else if (!g_ascii_strcasecmp(s.t[0], "border"))
-                border = atoi(s.t[1]);
-            else {
-                ERR( "lxpanel: unknown var %s\n", s.t[0]);
-            }
-        } else if (s.type == LINE_BLOCK_START) {
-            if (!g_ascii_strcasecmp(s.t[0], "Config")) {
-                pconfig = *fp;
-                int pno = 1;
-                while (pno) {
-                    get_line_as_is(fp, &s);
-                    if (s.type == LINE_NONE) {
-                        ERR( "lxpanel: unexpected eof\n");
-                        goto error;
-                    } else if (s.type == LINE_BLOCK_START) {
-                        pno++;
-                    } else if (s.type == LINE_BLOCK_END) {
-                        pno--;
-                    }
-                }
-            } else {
-                ERR( "lxpanel: unknown block %s\n", s.t[0]);
-                goto error;
-            }
-        } else {
-            ERR( "lxpanel: illegal in this context %s\n", s.str);
-            goto error;
-        }
-    }
+    config_setting_lookup_string(cfg, "type", &type);
+    DBG("plug %s\n", type);
 
-    if (!type || !(plug = plugin_load(type))) {
+    if (!type || lxpanel_add_plugin(p, type, cfg, -1) == NULL) {
         ERR( "lxpanel: can't load %s plugin\n", type);
         goto error;
     }
-
-    plug->panel = p;
-    if (plug->class->expand_available) plug->expand = expand;
-    plug->padding = padding;
-    plug->border = border;
-    DBG("starting\n");
-    if (!plugin_start(plug, pconfig ? &pconfig : NULL)) {
-        ERR( "lxpanel: can't start plugin %s\n", type);
-        goto error;
-    }
-    DBG("plug %s\n", type);
-    p->plugins = g_list_append(p->plugins, plug);
-
-    g_free( type );
     RET(1);
 
- error:
-    if (plug != NULL)
-        plugin_unload(plug);
-    g_free(type);
+error:
     RET(0);
 }
 
-int panel_start( Panel *p, char **fp )
+int panel_start( Panel *p )
 {
-    line s;
+    config_setting_t *list, *s;
+    int i;
 
     /* parse global section */
     ENTER;
-    s.len = 256;
 
-    if ((lxpanel_get_line(fp, &s) != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Global")) {
-        ERR( "lxpanel: config file must start from Global section\n");
-        RET(0);
-    }
-    if (!panel_parse_global(p, fp))
+    list = config_setting_get_member(config_root_setting(p->config), "");
+    if (!list || !panel_parse_global(p, config_setting_get_elem(list, 0)))
         RET(0);
 
     panel_start_gui(p);
 
-    while (lxpanel_get_line(fp, &s) != LINE_NONE) {
-        if ((s.type  != LINE_BLOCK_START) || g_ascii_strcasecmp(s.t[0], "Plugin")) {
-            ERR( "lxpanel: expecting Plugin section\n");
-            RET(0);
-        }
-        panel_parse_plugin(p, fp);
-    }
+    for (i = 1; (s = config_setting_get_elem(list, i)) != NULL; )
+        if (strcmp(config_setting_get_name(s), "Plugin") == 0 &&
+            panel_parse_plugin(p, s)) /* success on plugin start */
+            i++;
+        else /* remove invalid data from config */
+            config_setting_remove_elem(list, i);
 
     /* update backgrond of panel and all plugins */
     panel_update_background( p );
     return 1;
 }
 
-static void
-delete_plugin(gpointer data, gpointer udata)
-{
-    plugin_delete((Plugin *)data);
-}
-
 void panel_destroy(Panel *p)
 {
     ENTER;
@@ -1448,10 +1373,8 @@ void panel_destroy(Panel *p)
     if (p->pref_dialog != NULL)
         gtk_widget_destroy(p->pref_dialog);
     if (p->plugin_pref_dialog != NULL)
-    {
-        gtk_widget_destroy(p->plugin_pref_dialog);
-        p->plugin_pref_dialog = NULL;
-    }
+        /* just close the dialog, it will do all required cleanup */
+        gtk_dialog_response(GTK_DIALOG(p->plugin_pref_dialog), GTK_RESPONSE_CLOSE);
 
     if (p->bg != NULL)
     {
@@ -1461,20 +1384,18 @@ void panel_destroy(Panel *p)
 
     if( p->config_changed )
         panel_config_save( p );
-
-    g_list_foreach(p->plugins, delete_plugin, NULL);
-    g_list_free(p->plugins);
-    p->plugins = NULL;
+    config_destroy(p->config);
 
     if( p->system_menus ){
         do{
         } while ( g_source_remove_by_user_data( p->system_menus ) );
     }
 
-    gtk_window_group_remove_window( win_grp, GTK_WINDOW(  p->topgwin ) );
-
     if( p->topgwin )
+    {
+        gtk_window_group_remove_window( win_grp, GTK_WINDOW(  p->topgwin ) );
         gtk_widget_destroy(p->topgwin);
+    }
     g_free(p->workarea);
     g_free( p->background_file );
     g_slist_free( p->system_menus );
@@ -1489,26 +1410,19 @@ void panel_destroy(Panel *p)
 
 Panel* panel_new( const char* config_file, const char* config_name )
 {
-    char *fp, *pfp; /* point to current position of profile data in memory */
     Panel* panel = NULL;
 
-    if( G_LIKELY(config_file) )
+    if (G_LIKELY(config_file))
     {
-        g_file_get_contents( config_file, &fp, NULL, NULL );
-        if( fp )
+        panel = panel_allocate();
+        panel->name = g_strdup(config_name);
+        g_debug("starting panel from file %s",config_file);
+        if (!config_read_file(panel->config, config_file) ||
+            !panel_start(panel))
         {
-            panel = panel_allocate();
-            panel->orientation = ORIENT_NONE;
-            panel->name = g_strdup( config_name );
-            pfp = fp;
-
-            if (! panel_start( panel, &pfp )) {
-                ERR( "lxpanel: can't start panel\n");
-                panel_destroy( panel );
-                panel = NULL;
-            }
-
-            g_free( fp );
+            ERR( "lxpanel: can't start panel\n");
+            panel_destroy( panel );
+            panel = NULL;
         }
     }
     return panel;
@@ -1723,6 +1637,12 @@ int main(int argc, char *argv[], char *env[])
 restart:
     is_restarting = FALSE;
 
+    /* init LibFM */
+    fm_gtk_init(NULL);
+
+    /* prepare modules data */
+    _prepare_modules();
+
     load_global_config();
 
        /* NOTE: StructureNotifyMask is required by XRandR
@@ -1752,6 +1672,9 @@ restart:
 
     free_global_config();
 
+    _unload_modules();
+    fm_gtk_finalize();
+
     if( is_restarting )
         goto restart;
 
@@ -1762,3 +1685,64 @@ restart:
 
     return 0;
 }
+
+extern GtkOrientation panel_get_orientation(Panel *panel)
+{
+    return panel->orientation;
+}
+
+extern gint panel_get_icon_size(Panel *panel)
+{
+    return panel->icon_size;
+}
+
+extern gint panel_get_height(Panel *panel)
+{
+    return panel->height;
+}
+
+extern GtkWindow *panel_get_toplevel_window(Panel *panel)
+{
+    return GTK_WINDOW(panel->topgwin);
+}
+
+extern GtkStyle *panel_get_defstyle(Panel *panel)
+{
+    return panel->defstyle;
+}
+
+extern GtkIconTheme *panel_get_icon_theme(Panel *panel)
+{
+    return panel->icon_theme;
+}
+
+extern GtkWidget *panel_box_new(Panel *panel, gboolean homogeneous, gint spacing)
+{
+    return panel->my_box_new(homogeneous, spacing);
+}
+
+extern GtkWidget *panel_separator_new(Panel *panel)
+{
+    return panel->my_separator_new();
+}
+
+gboolean _class_is_present(LXPanelPluginInit *init)
+{
+    GSList *sl;
+
+    for (sl = all_panels; sl; sl = sl->next )
+    {
+        Panel *panel = (Panel*)sl->data;
+        GList *plugins, *p;
+
+        plugins = gtk_container_get_children(GTK_CONTAINER(panel->box));
+        for (p = plugins; p; p = p->next)
+            if (PLUGIN_CLASS(p->data) == init)
+            {
+                g_list_free(plugins);
+                return TRUE;
+            }
+        g_list_free(plugins);
+    }
+    return FALSE;
+}
index cc523ab..8d0455b 100644 (file)
 
 #include <X11/Xlib.h>
 #include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include "config.h"
-
-#include "bg.h"
-#include "ev.h"
-
-enum { ALLIGN_NONE, ALLIGN_LEFT, ALLIGN_CENTER, ALLIGN_RIGHT  };
-enum { EDGE_NONE=0, EDGE_LEFT, EDGE_RIGHT, EDGE_TOP, EDGE_BOTTOM };
-enum { WIDTH_NONE, WIDTH_REQUEST, WIDTH_PIXEL, WIDTH_PERCENT };
-enum { HEIGHT_NONE, HEIGHT_PIXEL, HEIGHT_REQUEST };
-enum {
-    ORIENT_NONE = -1,
-    ORIENT_VERT = GTK_ORIENTATION_VERTICAL,
-    ORIENT_HORIZ = GTK_ORIENTATION_HORIZONTAL
-};
-enum { POS_NONE, POS_START, POS_END };
-
-#define PANEL_ICON_SIZE               24       /* Default size of panel icons */
-#define PANEL_HEIGHT_DEFAULT          26       /* Default height of horizontal panel */
-#define PANEL_WIDTH_DEFAULT           150      /* Default "height" of vertical panel */
-#define PANEL_HEIGHT_MAX              200      /* Maximum height of panel */
-#define PANEL_HEIGHT_MIN              16       /* Minimum height of panel */
-#define PANEL_ICON_HIGHLIGHT          0x202020 /* Constant to pass to icon loader */
-
-/* to check if we are in LXDE */
-extern gboolean is_in_lxde;
-
-/* Context of a panel on a given edge. */
-typedef struct _Panel {
-    char* name;
-    GtkWidget * topgwin;               /* Main panel window */
-    Window topxwin;                    /* Main panel's X window   */
-    GdkDisplay * display;              /* Main panel's GdkDisplay */
-    GtkStyle * defstyle;
-    GtkIconTheme* icon_theme; /*Default icon theme*/
-
-    GtkWidget * box;                   /* Top level widget */
-
-    GtkRequisition requisition;
-    GtkWidget *(*my_box_new) (gboolean, gint);
-    GtkWidget *(*my_separator_new) ();
-
-    FbBg *bg;
-    int alpha;
-    guint32 tintcolor;
-    guint32 fontcolor;
-    GdkColor gtintcolor;
-    GdkColor gfontcolor;
-
-    int ax, ay, aw, ah;  /* prefferd allocation of a panel */
-    int cx, cy, cw, ch;  /* current allocation (as reported by configure event) allocation */
-    int allign, edge, margin;
-    int orientation;
-    int widthtype, width;
-    int heighttype, height;
-    gint monitor;
-    gulong strut_size;                 /* Values for WM_STRUT_PARTIAL */
-    gulong strut_lower;
-    gulong strut_upper;
-    int strut_edge;
-
-    guint config_changed : 1;
-    guint self_destroy : 1;
-    guint setdocktype : 1;
-    guint setstrut : 1;
-    guint round_corners : 1;
-    guint usefontcolor : 1;
-    guint usefontsize : 1;
-    guint fontsize;    
-    guint transparent : 1;
-    guint background : 1;
-    guint spacing;
-
-    guint autohide : 1;
-    guint visible : 1;
-    int height_when_hidden;
-    guint hide_timeout;
-    int icon_size;                     /* Icon size */
-
-    int desknum;
-    int curdesk;
-    guint32 *workarea;
-    int wa_len;
-
-    char* background_file;
-
-    GList * plugins;                   /* List of all plugins */
-    GSList * system_menus;             /* List of plugins having menus */
-
-    GtkWidget* plugin_pref_dialog;     /* Plugin preference dialog */
-    GtkWidget* pref_dialog;            /* preference dialog */
-    GtkWidget* margin_control;         /* Margin control in preference dialog */
-    GtkWidget* height_label;           /* Label of height control */
-    GtkWidget* width_label;            /* Label of width control */
-    GtkWidget* alignment_left_label;   /* Label of alignment: left control */
-    GtkWidget* alignment_right_label;  /* Label of alignment: right control */
-    GtkWidget* height_control;         /* Height control in preference dialog */
-    GtkWidget* width_control;          /* Width control in preference dialog */
-} Panel;
-
-/* Decoded value of WM_STATE property. */
-typedef struct {
-    unsigned int modal : 1;
-    unsigned int sticky : 1;
-    unsigned int maximized_vert : 1;
-    unsigned int maximized_horz : 1;
-    unsigned int shaded : 1;
-    unsigned int skip_taskbar : 1;
-    unsigned int skip_pager : 1;
-    unsigned int hidden : 1;
-    unsigned int fullscreen : 1;
-    unsigned int above : 1;
-    unsigned int below : 1;
-} NetWMState;
-
-/* Decoded value of _NET_WM_WINDOW_TYPE property. */
-typedef struct {
-    unsigned int desktop : 1;
-    unsigned int dock : 1;
-    unsigned int toolbar : 1;
-    unsigned int menu : 1;
-    unsigned int utility : 1;
-    unsigned int splash : 1;
-    unsigned int dialog : 1;
-    unsigned int normal : 1;
-} NetWMWindowType;
-
-typedef struct {
-    char *name;
-    char *disp_name;
-    void (*cmd)(void);
-} Command;
-
-extern Command commands[];
 
 extern gchar *cprofile;
 
@@ -213,14 +78,7 @@ extern Atom a_MANAGER;
 
 extern Atom a_LXPANEL_CMD; /* for private client message */
 
-extern int verbose;
-
-/* if current window manager is EWMH conforming. */
-extern gboolean is_ewmh_supported;
-
-extern FbEv *fbev;
-
-#define FBPANEL_WIN(win)  gdk_window_lookup(win)
+typedef struct _Panel Panel;
 
 extern void panel_apply_icon(GtkWindow *w);
 extern void panel_destroy(Panel *p);
@@ -239,7 +97,16 @@ extern void panel_update_background( Panel* p );
 extern int panel_handle_x_error(Display * d, XErrorEvent * ev);
 extern int panel_handle_x_error_swallow_BadWindow_BadDrawable(Display * d, XErrorEvent * ev);
 
-extern const char* lxpanel_get_file_manager();
-extern const char* lxpanel_get_terminal();
+void panel_config_save(Panel *p); /* defined in configurator.c */
+
+/* Accessors APIs for Panel* */
+extern GtkOrientation panel_get_orientation(Panel *panel);
+extern gint panel_get_icon_size(Panel *panel);
+extern gint panel_get_height(Panel *panel);
+extern GtkWindow *panel_get_toplevel_window(Panel *panel);
+extern GtkStyle *panel_get_defstyle(Panel *panel);
+extern GtkIconTheme *panel_get_icon_theme(Panel *panel);
+extern GtkWidget *panel_box_new(Panel *panel, gboolean homogeneous, gint spacing);
+extern GtkWidget *panel_separator_new(Panel *panel);
 
 #endif
index 83440e8..c95815c 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
+ * Copyright (c) 2006-2014 LxDE Developers, see the file AUTHORS for details.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
 #include "config.h"
 #endif
 
-#include "plugin.h"
+#include "private.h"
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
 #include "bg.h"
 
 #include <glib-object.h>
+#include <glib/gi18n.h>
+#include <libfm/fm-gtk.h>
 
 //#define DEBUG
 #include "dbg.h"
 
-static GList * pcl = NULL;                     /* List of PluginClass structures */
-
 static void register_plugin_class(PluginClass * pc, gboolean dynamic);
 static void init_plugin_class_list(void);
-static PluginClass * plugin_find_class(const char * type);
-static PluginClass * plugin_load_dynamic(const char * type, const gchar * path);
 static void plugin_class_unref(PluginClass * pc);
 
+GQuark lxpanel_plugin_qdata;
+static GHashTable *_all_types = NULL;
+
 /* Dynamic parameter for static (built-in) plugins must be FALSE so we will not try to unload them */
 #define REGISTER_STATIC_PLUGIN_CLASS(pc) \
 do {\
@@ -51,22 +52,65 @@ do {\
     register_plugin_class(&pc, FALSE);\
 } while (0)
 
+/* The same for new plugins type - they will be not unloaded by FmModule */
+#define REGISTER_STATIC_MODULE(pc) do { \
+    extern LXPanelPluginInit lxpanel_static_plugin_##pc; \
+    lxpanel_register_plugin_type(#pc, &lxpanel_static_plugin_##pc); } while (0)
+
+static inline LXPanelPluginInit *_find_plugin(const char *name)
+{
+    return g_hash_table_lookup(_all_types, name);
+}
+
+static void _old_plugin_config(Panel *panel, GtkWidget *instance, GtkWindow *parent)
+{
+    LXPanelPluginInit *init = PLUGIN_CLASS(instance);
+    Plugin * plugin;
+
+    g_return_if_fail(init != NULL && init->new_instance == NULL);
+    plugin = lxpanel_plugin_get_data(instance);
+    if (plugin->class->config)
+        plugin->class->config(plugin, parent);
+}
+
+static void _old_plugin_reconfigure(Panel *panel, GtkWidget *instance)
+{
+    LXPanelPluginInit *init = PLUGIN_CLASS(instance);
+    Plugin * plugin;
+
+    g_return_if_fail(init != NULL && init->new_instance == NULL);
+    plugin = lxpanel_plugin_get_data(instance);
+    if (plugin->class->panel_configuration_changed)
+        plugin->class->panel_configuration_changed(plugin);
+}
+
 /* Register a PluginClass. */
 static void register_plugin_class(PluginClass * pc, gboolean dynamic)
 {
-    pcl = g_list_append(pcl, pc);
+    LXPanelPluginInit *init = g_new0(LXPanelPluginInit, 1);
+    init->_reserved1 = pc;
+    init->name = pc->name;
+    init->description = pc->description;
+    if (pc->config)
+        init->config = _old_plugin_config;
+    if (pc->panel_configuration_changed)
+        init->reconfigure = _old_plugin_reconfigure;
+    init->one_per_system = pc->one_per_system;
+    init->expand_available = pc->expand_available;
+    init->expand_default = pc->expand_default;
     pc->dynamic = dynamic;
+    g_hash_table_insert(_all_types, g_strdup(pc->type), init);
 }
 
 /* Initialize the static plugins. */
 static void init_plugin_class_list(void)
 {
 #ifdef STATIC_SEPARATOR
-    REGISTER_STATIC_PLUGIN_CLASS(separator_plugin_class);
+    REGISTER_STATIC_MODULE(separator);
 #endif
 
 #ifdef STATIC_LAUNCHBAR
-    REGISTER_STATIC_PLUGIN_CLASS(launchbar_plugin_class);
+    REGISTER_STATIC_MODULE(launchbar);
 #endif
 
 #ifdef STATIC_LAUNCHTASKBAR
@@ -74,15 +118,15 @@ static void init_plugin_class_list(void)
 #endif
 
 #ifdef STATIC_DCLOCK
-    REGISTER_STATIC_PLUGIN_CLASS(dclock_plugin_class);
+    REGISTER_STATIC_MODULE(dclock);
 #endif
 
 #ifdef STATIC_WINCMD
-    REGISTER_STATIC_PLUGIN_CLASS(wincmd_plugin_class);
+    REGISTER_STATIC_MODULE(wincmd);
 #endif
 
 #ifdef STATIC_DIRMENU
-    REGISTER_STATIC_PLUGIN_CLASS(dirmenu_plugin_class);
+    REGISTER_STATIC_MODULE(dirmenu);
 #endif
 
 #ifdef STATIC_TASKBAR
@@ -104,25 +148,12 @@ static void init_plugin_class_list(void)
 #endif
 
 #ifdef STATIC_SPACE
-    REGISTER_STATIC_PLUGIN_CLASS(space_plugin_class);
+    REGISTER_STATIC_MODULE(space);
 #endif
 }
 
-/* Look up a plugin class by name. */
-static PluginClass * plugin_find_class(const char * type)
-{
-    GList * tmp;
-    for (tmp = pcl; tmp != NULL; tmp = g_list_next(tmp))
-    {
-        PluginClass * pc = (PluginClass *) tmp->data;
-        if (g_ascii_strcasecmp(type, pc->type) == 0)
-            return pc;
-    }
-    return NULL;
-}
-
 /* Load a dynamic plugin. */
-static PluginClass * plugin_load_dynamic(const char * type, const gchar * path)
+static void plugin_load_dynamic(const char * type, const gchar * path)
 {
     PluginClass * pc = NULL;
 
@@ -144,103 +175,14 @@ static PluginClass * plugin_load_dynamic(const char * type, const gchar * path)
         {
             g_module_close(m);
             ERR("%s.so is not a lxpanel plugin\n", type);
-            return NULL;
+            return;
         }
 
         /* Register the newly loaded and valid plugin. */
         pc->gmodule = m;
         register_plugin_class(pc, TRUE);
+        pc->count = 1;
     }
-    return pc;
-}
-
-/* Create an instance of a plugin with a specified name, loading it if external. */
-Plugin * plugin_load(char * type)
-{
-    /* Initialize static plugins on first call. */
-    if (pcl == NULL)
-        init_plugin_class_list();
-
-    /* Look up the PluginClass. */
-    PluginClass * pc = plugin_find_class(type);
-
-#ifndef DISABLE_PLUGINS_LOADING
-    /* If not found and dynamic loading is available, try to locate an external plugin. */
-    if ((pc == NULL) && (g_module_supported()))
-    {
-        gchar path[PATH_MAX];
-        g_snprintf(path, sizeof(path), PACKAGE_LIB_DIR "/lxpanel/plugins/%s.so", type);
-        pc = plugin_load_dynamic(type, path);
-    }
-#endif  /* DISABLE_PLUGINS_LOADING */
-
-    /* If not found, return failure. */
-    if (pc == NULL)
-        return NULL;
-
-    /* Instantiate the plugin */
-    Plugin * plug = g_new0(Plugin, 1);
-    plug->class = pc;
-    pc->count += 1;
-    return plug;
-}
-
-/* Configure and start a plugin by calling its constructor. */
-int plugin_start(Plugin * pl, char ** fp)
-{
-    /* Call the constructor.
-     * It is responsible for parsing the parameters, and setting "pwid" to the top level widget. */
-    if ( ! pl->class->constructor(pl, fp))
-        return 0;
-
-    /* If this plugin can only be instantiated once, count the instantiation.
-     * This causes the configuration system to avoid displaying the plugin as one that can be added. */
-    if (pl->class->one_per_system)
-        pl->class->one_per_system_instantiated = TRUE;
-
-    /* If the plugin has a top level widget, add it to the panel's container. */
-    if (pl->pwid != NULL)
-    {
-        gtk_widget_set_name(pl->pwid, pl->class->type);
-        gtk_box_pack_start(GTK_BOX(pl->panel->box), pl->pwid, pl->expand, TRUE, pl->padding);
-        gtk_container_set_border_width(GTK_CONTAINER(pl->pwid), pl->border);
-        gtk_widget_show(pl->pwid);
-    }
-    return 1;
-}
-
-/* Unload a plugin if initialization fails. */
-void plugin_unload(Plugin * pl)
-{
-    plugin_class_unref(pl->class);
-    g_free(pl);
-}
-
-/* Delete a plugin. */
-void plugin_delete(Plugin * pl)
-{
-    Panel * p = pl->panel;
-    PluginClass * pc = pl->class;
-
-    /* If a plugin configuration dialog is open, close it. */
-    if (p->plugin_pref_dialog != NULL)
-    {
-        gtk_widget_destroy(p->plugin_pref_dialog);
-        p->plugin_pref_dialog = NULL;
-    }
-
-    /* Run the destructor and then destroy the top level widget.
-     * This prevents problems with the plugin destroying child widgets. */
-    pc->destructor(pl);
-    if (pl->pwid != NULL)
-        gtk_widget_destroy(pl->pwid);
-
-    /* Data structure bookkeeping. */
-    pc->one_per_system_instantiated = FALSE;
-    plugin_class_unref(pc);
-
-    /* Free the Plugin structure. */
-    g_free(pl);
 }
 
 /* Unreference a dynamic plugin. */
@@ -253,29 +195,15 @@ static void plugin_class_unref(PluginClass * pc)
     && (pc->dynamic)
     && ( ! pc->not_unloadable))
     {
-        pcl = g_list_remove(pcl, pc);
         g_module_close(pc->gmodule);
     }
 }
 
-/* Get a list of all available plugin classes.
- * Returns a newly allocated GList which should be freed with plugin_class_list_free(list). */
-GList * plugin_get_available_classes(void)
+/* Loads all available old type plugins. Should be removed in future releases. */
+static void plugin_get_available_classes(void)
 {
     /* Initialize static plugins on first call. */
-    if (pcl == NULL)
-        init_plugin_class_list();
-
-    /* Loop over all classes to formulate the result.
-     * Increase the reference count; it will be decreased in plugin_class_list_free. */
-    GList * classes = NULL;
-    GList * l;
-    for (l = pcl; l != NULL; l = l->next)
-    {
-        PluginClass * pc = (PluginClass *) l->data;
-        classes = g_list_prepend(classes, pc);
-        pc->count += 1;
-    }
+    init_plugin_class_list();
 
 #ifndef DISABLE_PLUGINS_LOADING
     GDir * dir = g_dir_open(PACKAGE_LIB_DIR "/lxpanel/plugins", 0, NULL);
@@ -287,16 +215,11 @@ GList * plugin_get_available_classes(void)
             if (g_str_has_suffix(file, ".so"))
             {
                 char * type = g_strndup(file, strlen(file) - 3);
-                if (plugin_find_class(type) == NULL)
+                if (_find_plugin(type) == NULL)
                 {
                     /* If it has not been loaded, do it.  If successful, add it to the result. */
                     char * path = g_build_filename(PACKAGE_LIB_DIR "/lxpanel/plugins", file, NULL );
-                    PluginClass * pc = plugin_load_dynamic(type, path);
-                    if (pc != NULL)
-                    {
-                        pc->count += 1;
-                        classes = g_list_prepend(classes, pc);
-                    }
+                    plugin_load_dynamic(type, path);
                     g_free(path);
                 }
                 g_free(type);
@@ -305,14 +228,6 @@ GList * plugin_get_available_classes(void)
         g_dir_close(dir);
     }
 #endif
-    return classes;
-}
-
-/* Free the list allocated by plugin_get_available_classes. */
-void plugin_class_list_free(GList * list)
-{
-   g_list_foreach(list, (GFunc) plugin_class_unref, NULL);
-   g_list_free(list);
 }
 
 /* Recursively set the background of all widgets on a panel background configuration change. */
@@ -359,19 +274,25 @@ void plugin_widget_set_background(GtkWidget * w, Panel * p)
 
 /* Handler for "button_press_event" signal with Plugin as parameter.
  * External so can be used from a plugin. */
-gboolean plugin_button_press_event(GtkWidget *widget, GdkEventButton *event, Plugin *plugin)
+gboolean lxpanel_plugin_button_press_event(GtkWidget *plugin, GdkEventButton *event, Panel *panel)
 {
-    if (event->button == 3)     /* right button */
+    if (event->button == 3) /* right button */
     {
-        GtkMenu* popup = (GtkMenu*) lxpanel_get_panel_menu(plugin->panel, plugin, FALSE);
+        GtkMenu* popup = (GtkMenu*)lxpanel_get_plugin_menu(panel, plugin, FALSE);
         gtk_menu_popup(popup, NULL, NULL, NULL, NULL, event->button, event->time);
         return TRUE;
-    }    
+    }
     return FALSE;
 }
 
+/* for old plugins compatibility */
+gboolean plugin_button_press_event(GtkWidget *widget, GdkEventButton *event, Plugin *plugin)
+{
+    return lxpanel_plugin_button_press_event(plugin->pwid, event, PLUGIN_PANEL(plugin->pwid));
+}
+
 /* Helper for position-calculation callback for popup menus. */
-void plugin_popup_set_position_helper(Plugin * p, GtkWidget * near, GtkWidget * popup, GtkRequisition * popup_req, gint * px, gint * py)
+void lxpanel_plugin_popup_set_position_helper(Panel * p, GtkWidget * near, GtkWidget * popup, GtkRequisition * popup_req, gint * px, gint * py)
 {
     /* Get the origin of the requested-near widget in screen coordinates. */
     gint x, y;
@@ -381,7 +302,7 @@ void plugin_popup_set_position_helper(Plugin * p, GtkWidget * near, GtkWidget *
 
     /* Dispatch on edge to lay out the popup menu with respect to the button.
      * Also set "push-in" to avoid any case where it might flow off screen. */
-    switch (p->panel->edge)
+    switch (p->edge)
     {
         case EDGE_TOP:          y += near->allocation.height;         break;
         case EDGE_BOTTOM:       y -= popup_req->height;                break;
@@ -392,13 +313,18 @@ void plugin_popup_set_position_helper(Plugin * p, GtkWidget * near, GtkWidget *
     *py = y;
 }
 
+/* for old plugins compatibility */
+void plugin_popup_set_position_helper(Plugin * p, GtkWidget * near, GtkWidget * popup, GtkRequisition * popup_req, gint * px, gint * py)
+{
+    lxpanel_plugin_popup_set_position_helper(p->panel, near, popup, popup_req, px, py);
+}
+
 /* Adjust the position of a popup window to ensure that it is not hidden by the panel.
  * It is observed that some window managers do not honor the strut that is set on the panel. */
-void plugin_adjust_popup_position(GtkWidget * popup, Plugin * plugin)
+void lxpanel_plugin_adjust_popup_position(GtkWidget * popup, GtkWidget * parent)
 {
     /* Initialize. */
-    Panel * p = plugin->panel;
-    GtkWidget * parent = plugin->pwid;
+    Panel * p = PLUGIN_PANEL(parent);
 
     /* Get the coordinates of the plugin top level widget. */
     int x = p->cx + parent->allocation.x;
@@ -430,3 +356,237 @@ void plugin_adjust_popup_position(GtkWidget * popup, Plugin * plugin)
     /* Move the popup to position. */
     gdk_window_move(popup->window, x, y);
 }
+
+/* for old plugins compatibility */
+void plugin_adjust_popup_position(GtkWidget * popup, Plugin * plugin)
+{
+    lxpanel_plugin_adjust_popup_position(popup, plugin->pwid);
+}
+
+/* Open a specified path in a file manager. */
+static gboolean _open_dir_in_file_manager(GAppLaunchContext* ctx, GList* folder_infos,
+                                          gpointer user_data, GError** err)
+{
+    FmFileInfo *fi = folder_infos->data; /* only first is used */
+    GAppInfo *app = g_app_info_get_default_for_type("inode/directory", TRUE);
+    GFile *gf;
+    gboolean ret;
+
+    if (app == NULL)
+    {
+        g_set_error_literal(err, G_SHELL_ERROR, G_SHELL_ERROR_EMPTY_STRING,
+                            _("No file manager is configured."));
+        return FALSE;
+    }
+    gf = fm_path_to_gfile(fm_file_info_get_path(fi));
+    folder_infos = g_list_prepend(NULL, gf);
+    ret = fm_app_info_launch(app, folder_infos, ctx, err);
+    g_list_free(folder_infos);
+    g_object_unref(gf);
+    g_object_unref(app);
+    return ret;
+}
+
+gboolean lxpanel_launch_path(Panel *panel, FmPath *path)
+{
+    return fm_launch_path_simple(NULL, NULL, path, _open_dir_in_file_manager, NULL);
+}
+
+#if GLIB_CHECK_VERSION(2, 32, 0)
+static GRecMutex _mutex;
+#else
+static GStaticRecMutex _mutex = G_STATIC_REC_MUTEX_INIT;
+#endif
+
+#ifndef DISABLE_PLUGINS_LOADING
+FM_MODULE_DEFINE_TYPE(lxpanel_gtk, LXPanelPluginInit, 1)
+
+static gboolean fm_module_callback_lxpanel_gtk(const char *name, gpointer init, int ver)
+{
+    /* ignore ver for now, only 1 exists */
+    return lxpanel_register_plugin_type(name, init);
+}
+#endif
+
+static gboolean old_plugins_loaded = FALSE;
+
+void _prepare_modules(void)
+{
+    _all_types = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+    lxpanel_plugin_qdata = g_quark_from_static_string("LXPanel::plugin-data");
+    lxpanel_plugin_qinit = g_quark_from_static_string("LXPanel::plugin-init");
+    lxpanel_plugin_qconf = g_quark_from_static_string("LXPanel::plugin-conf");
+    lxpanel_plugin_qpanel = g_quark_from_static_string("LXPanel::plugin-panel");
+#ifndef DISABLE_PLUGINS_LOADING
+    fm_modules_add_directory(PACKAGE_LIB_DIR "/lxpanel/plugins");
+    fm_module_register_lxpanel_gtk();
+#endif
+}
+
+void _unload_modules(void)
+{
+    GHashTableIter iter;
+    gpointer key, val;
+
+#ifndef DISABLE_PLUGINS_LOADING
+    fm_module_unregister_type("lxpanel_gtk");
+#endif
+    g_hash_table_iter_init(&iter, _all_types);
+    while(g_hash_table_iter_next(&iter, &key, &val))
+    {
+        register LXPanelPluginInit *init = val;
+        if (init->new_instance == NULL) /* old type of plugin */
+        {
+            plugin_class_unref(init->_reserved1);
+            g_free(val);
+        }
+    }
+    g_hash_table_destroy(_all_types);
+    old_plugins_loaded = FALSE;
+}
+
+gboolean lxpanel_register_plugin_type(const char *name, LXPanelPluginInit *init)
+{
+    LXPanelPluginInit *data;
+
+    /* validate it */
+    if (init->new_instance == NULL || name == NULL || name[0] == '\0')
+        return FALSE;
+#if GLIB_CHECK_VERSION(2, 32, 0)
+    g_rec_mutex_lock(&_mutex);
+#else
+    g_static_rec_mutex_lock(&_mutex);
+#endif
+    /* test if it's registered already */
+    data = _find_plugin(name);
+    if (data == NULL)
+    {
+        if (init->init)
+            init->init();
+        g_hash_table_insert(_all_types, g_strdup(name), init);
+    }
+#if GLIB_CHECK_VERSION(2, 32, 0)
+    g_rec_mutex_unlock(&_mutex);
+#else
+    g_static_rec_mutex_unlock(&_mutex);
+#endif
+    return (data == NULL);
+}
+
+static void _old_plugin_save_hook(const config_setting_t * setting, FILE * f, gpointer user_data)
+{
+    Plugin *pl = user_data;
+    PluginClass *pc = pl->class;
+    if (pc->save)
+        pc->save(pl, f);
+}
+
+/* This is called right before Plugin instance is destroyed */
+static void _old_plugin_destroy(gpointer data)
+{
+    Plugin *pl = data;
+
+    /* Run the destructor. */
+    pl->class->destructor(pl);
+    plugin_class_unref(pl->class);
+
+    /* Free the Plugin structure. */
+    g_free(pl);
+}
+
+//static void on_size_allocate(GtkWidget *widget, GdkRectangle *allocation, Panel *p)
+//{
+//    _queue_panel_calculate_size(p);
+//}
+
+GtkWidget *lxpanel_add_plugin(Panel *p, const char *name, config_setting_t *cfg, gint at)
+{
+    LXPanelPluginInit *init;
+    GtkWidget *widget;
+    config_setting_t *s, *pconf;
+    gint expand, padding = 0, border = 0, i;
+
+    CHECK_MODULES();
+    if (!old_plugins_loaded)
+        plugin_get_available_classes();
+    old_plugins_loaded = TRUE;
+    init = _find_plugin(name);
+    if (init == NULL)
+        return NULL;
+    /* prepare widget settings */
+    if (!init->expand_available)
+        expand = 0;
+    else if ((s = config_setting_get_member(cfg, "expand")))
+        expand = config_setting_get_int(s);
+    else
+        expand = init->expand_default;
+    s = config_setting_get_member(cfg, "padding");
+    if (s)
+        padding = config_setting_get_int(s);
+    s = config_setting_get_member(cfg, "border");
+    if (s)
+        border = config_setting_get_int(s);
+    /* prepare config and create it if need */
+    s = config_setting_add(cfg, "", PANEL_CONF_TYPE_LIST);
+    for (i = 0; (pconf = config_setting_get_elem(s, i)); i++)
+        if (strcmp(config_setting_get_name(pconf), "Config") == 0)
+            break;
+    if (!pconf)
+        pconf = config_setting_add(s, "Config", PANEL_CONF_TYPE_GROUP);
+    /* If this plugin can only be instantiated once, count the instantiation.
+     * This causes the configuration system to avoid displaying the plugin as one that can be added. */
+    if (init->new_instance) /* new style of plugin */
+    {
+        widget = init->new_instance(p, pconf);
+        if (widget == NULL)
+            return widget;
+        if (init->button_press_event)
+            g_signal_connect(widget, "button-press-event",
+                             G_CALLBACK(init->button_press_event), p);
+        else
+            g_signal_connect(widget, "button-press-event",
+                             G_CALLBACK(lxpanel_plugin_button_press_event), p);
+    }
+    else
+    {
+        Plugin *pl = g_new0(Plugin, 1);
+        PluginClass *pc = init->_reserved1;
+        char *conf = config_setting_to_string(pconf), *fp;
+
+        pl->class = pc;
+        pl->panel = p;
+        widget = NULL;
+        fp = &conf[9]; /* skip "Config {\n" */
+        /* g_debug("created conf: %s",conf); */
+    /* Call the constructor.
+     * It is responsible for parsing the parameters, and setting "pwid" to the top level widget. */
+        if (pc->constructor(pl, &fp))
+            widget = pl->pwid;
+        g_free(conf);
+
+        if (widget == NULL) /* failed */
+        {
+            g_free(pl);
+            return widget;
+        }
+
+        pc->count += 1;
+        config_setting_set_save_hook(pconf, _old_plugin_save_hook, pl);
+        lxpanel_plugin_set_data(widget, pl, _old_plugin_destroy);
+    }
+    gtk_widget_set_name(widget, init->name);
+    gtk_box_pack_start(GTK_BOX(p->box), widget, expand, TRUE, padding);
+    gtk_container_set_border_width(GTK_CONTAINER(widget), border);
+//    g_signal_connect(widget, "size-allocate", G_CALLBACK(on_size_allocate), p);
+    gtk_widget_show(widget);
+    g_object_set_qdata(G_OBJECT(widget), lxpanel_plugin_qconf, cfg);
+    g_object_set_qdata(G_OBJECT(widget), lxpanel_plugin_qinit, init);
+    g_object_set_qdata(G_OBJECT(widget), lxpanel_plugin_qpanel, p);
+    return widget;
+}
+
+/* transfer none - note that not all fields are valid there */
+GHashTable *lxpanel_get_all_types(void)
+{
+    return _all_types;
+}
index 9a9a1d9..6dad0cf 100644 (file)
@@ -1,5 +1,5 @@
-/**
- * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
+/*
+ * Copyright (c) 2014 LxDE Developers, see the file AUTHORS for details.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifndef PLUGIN_H
-#define PLUGIN_H
+#ifndef __PLUGIN_H__
+#define __PLUGIN_H__ 1
 
-#include <gmodule.h>
+#include <libfm/fm.h>
 
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-#include <stdio.h>
 #include "panel.h"
+#include "conf.h"
 
-struct _Plugin;
-
-/* Support for external plugin versioning.
- * Plugins must invoke PLUGINCLASS_VERSIONING when they instantiate PluginClass. */
-#define PLUGINCLASS_VERSION 1
-#define PLUGINCLASS_VERSIONING \
-    .structure_size = sizeof(PluginClass), \
-    .structure_version = PLUGINCLASS_VERSION
-
-/* Representative of an available plugin. */
-typedef struct {
+G_BEGIN_DECLS
 
-    /* Keep these first.  Do not make unnecessary changes in structure layout. */
-    unsigned short structure_size;             /* Structure size, for versioning support */
-    unsigned short structure_version;          /* Structure version, for versioning support */
+/* New plugins style which uses FmModule loader, our module type is "lxpanel_gtk" */
 
-    char * fname;                              /* Plugin file pathname */
-    int count;                                 /* Reference count */
-    GModule * gmodule;                         /* Associated GModule structure */
+#define FM_MODULE_lxpanel_gtk_VERSION 1 /* version of this API */
 
-    int dynamic : 1;                           /* True if dynamically loaded */
-    int unused_invisible : 1;                  /* Unused; reserved bit */
-    int not_unloadable : 1;                    /* Not unloadable due to GModule restriction */
-    int one_per_system : 1;                    /* Special: only one possible per system, such as system tray */
-    int one_per_system_instantiated : 1;       /* True if one instance exists */
-    int expand_available : 1;                  /* True if "stretch" option is available */
-    int expand_default : 1;                    /* True if "stretch" option is default */
+/**
+ * @init: (allow-none): callback on lxpanel start
+ * @finalize: (allow-none): callback on lxpanel exit
+ * @name: name to represent plugin in lists
+ * @description: tooltip on the plugin in lists
+ * @new_instance: callback to create new plugin instance in panel
+ * @config: (allow-none): callback to show configuration dialog
+ * @reconfigure: (allow-none): callback to apply panel configuration change
+ * @button_press_event: (allow-none): callback on "button-press-event" signal
+ */
+typedef struct {
+    /*< public >*/
+    void (*init)(void);         /* optional startup */
+    void (*finalize)(void);     /* optional finalize */
+    char *name;                 /* name to represent in lists */
+    char *description;          /* tooltip text */
+    GtkWidget *(*new_instance)(Panel *panel, config_setting_t *settings);
+    void (*config)(Panel *panel, GtkWidget *instance, GtkWindow *parent);
+    void (*reconfigure)(Panel *panel, GtkWidget *instance);
+    gboolean (*button_press_event)(GtkWidget *widget, GdkEventButton *event, Panel *panel);
+    int one_per_system : 1;     /* True to disable more than one instance */
+    int expand_available : 1;   /* True if "stretch" option is available */
+    int expand_default : 1;     /* True if "stretch" option is default */
+    /*< private >*/
+    gpointer _reserved1;
+    gpointer _reserved2;
+} LXPanelPluginInit; /* constant data */
 
-    /* These fields point within the plugin image. */
-    char * type;                               /* Internal name of plugin, to match external filename */
-    char * name;                               /* Display name of plugin for selection UI */
-    char * version;                            /* Version of plugin */
-    char * description;                                /* Brief textual description of plugin for selection UI */
+extern LXPanelPluginInit fm_module_init_lxpanel_gtk;
 
-    int (*constructor)(struct _Plugin * plugin, char ** fp);           /* Create an instance of the plugin */
-    void (*destructor)(struct _Plugin * plugin);                       /* Destroy an instance of the plugin */
-    void (*config)(struct _Plugin * plugin, GtkWindow * parent);       /* Request the plugin to display its configuration dialog */
-    void (*save)(struct _Plugin * plugin, FILE * fp);                  /* Request the plugin to save its configuration to a file */
-    void (*panel_configuration_changed)(struct _Plugin * plugin);      /* Request the plugin to do a full redraw after a panel configuration change */
-} PluginClass;
+extern GQuark lxpanel_plugin_qdata; /* access to plugin private data */
+#define lxpanel_plugin_get_data(_i) g_object_get_qdata(G_OBJECT(_i),lxpanel_plugin_qdata)
+#define lxpanel_plugin_set_data(_i,_data,_destructor) g_object_set_qdata_full(G_OBJECT(_i),lxpanel_plugin_qdata,_data,_destructor)
 
-/* Representative of a loaded and active plugin attached to a panel. */
-typedef struct _Plugin {
-    PluginClass * class;                       /* Back pointer to PluginClass */
-    Panel * panel;                             /* Back pointer to Panel */
-    GtkWidget * pwid;                          /* Top level widget; plugin allocates, but plugin mechanism, not plugin itself, destroys this */
-    int expand;                                        /* Expand ("stretch") setting for container */
-    int padding;                               /* Padding setting for container */
-    int border;                                        /* Border setting for container */
-    gpointer priv;                             /* Private context for plugin; plugin frees this in its destructor */
-} Plugin;
+/* register new plugin type - can be called from plugins init() too */
+extern gboolean lxpanel_register_plugin_type(const char *name, LXPanelPluginInit *init);
 
-extern Plugin * plugin_load(char * type);              /* Create an instance of a plugin, loading it if necessary */
-extern int plugin_start(Plugin * this, char ** fp);    /* Configure and start a plugin by calling its constructor */
-extern void plugin_unload(Plugin * pl);                        /* Delete an instance of a plugin if initialization fails */
-extern void plugin_delete(Plugin * pl);                        /* Delete an instance of a plugin */
-extern GList * plugin_get_available_classes(void);     /* Get a list of all plugin classes; free with plugin_class_list_free */
-extern void plugin_class_list_free(GList * list);      /* Free the list allocated by plugin_get_available_classes */
-extern void plugin_widget_set_background(GtkWidget * w, Panel * p);
-                                                       /* Recursively set the background of all widgets on a panel background configuration change */
-extern gboolean plugin_button_press_event(GtkWidget *widget, GdkEventButton *event, Plugin *plugin);
-                                                        /* Handler for "button_press_event" signal with Plugin as parameter */
-extern void plugin_popup_set_position_helper(Plugin * p, GtkWidget * near, GtkWidget * popup, GtkRequisition * popup_req, gint * px, gint * py);
-                                                       /* Helper for position-calculation callback for popup menus */
-extern void plugin_adjust_popup_position(GtkWidget * popup, Plugin * plugin);
-                                                       /* Helper to move popup windows away from the panel */
+/* few helper functions */
+extern GtkMenu* lxpanel_get_plugin_menu(Panel* panel, GtkWidget* plugin, gboolean use_sub_menu);
+extern gboolean lxpanel_plugin_button_press_event(GtkWidget *plugin, GdkEventButton *event, Panel *panel);
+                       /* Handler for "button_press_event" signal with Plugin as parameter */
+extern void lxpanel_plugin_adjust_popup_position(GtkWidget * popup, GtkWidget * plugin);
+                       /* Helper to move popup windows away from the panel */
+extern void lxpanel_plugin_popup_set_position_helper(Panel * p, GtkWidget * near, GtkWidget * popup, GtkRequisition * popup_req, gint * px, gint * py);
+                       /* Helper for position-calculation callback for popup menus */
+extern void plugin_widget_set_background(GtkWidget * plugin, Panel * p);
+                       /* Recursively set the background of all widgets on a panel background configuration change */
+extern gboolean lxpanel_launch_path(Panel *panel, FmPath *path);
 
-/* FIXME: optional definitions */
-#define STATIC_SEPARATOR
-#define STATIC_LAUNCHBAR
-#define STATIC_LAUNCHTASKBAR
-#define STATIC_DCLOCK
-#define STATIC_WINCMD
-#define STATIC_DIRMENU
-#define STATIC_TASKBAR
-#define STATIC_PAGER
-#define STATIC_TRAY
-#define STATIC_MENU
-#define STATIC_SPACE
-#define STATIC_ICONS
+G_END_DECLS
 
-#endif
+#endif /* __PLUGIN_H__ */
index 6809c6a..954436d 100644 (file)
@@ -48,7 +48,7 @@
 #include "batt_sys.h"
 #include "misc.h" /* used for the line struct */
 #include "panel.h" /* used to determine panel orientation */
-#include "plugin.h"
+#include "private.h"
 
 /* The last MAX_SAMPLES samples are averaged when charge rates are evaluated.
    This helps prevent spikes in the "time left" values the user sees. */
@@ -267,7 +267,7 @@ void update_display(lx_battery *lx_b, gboolean repaint) {
 
     int chargeLevel = lx_b->b->percentage * (lx_b->length - 2 * lx_b->border) / 100;
 
-    if (lx_b->orientation == ORIENT_HORIZ) {
+    if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL) {
 
        /* Draw the battery bar vertically, using color 1 for the left half and
           color 2 for the right half */
@@ -361,7 +361,7 @@ static gint configureEvent(GtkWidget *widget, GdkEventConfigure *event,
     /* Update the plugin's dimensions */
     lx_b->width = widget->allocation.width;
     lx_b->height = widget->allocation.height;
-    if (lx_b->orientation == ORIENT_HORIZ) {
+    if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL) {
         lx_b->length = lx_b->height;
         lx_b->thickness = lx_b->width;
     }
@@ -420,7 +420,7 @@ constructor(Plugin *p, char **fp)
 
     gtk_container_add( (GtkContainer*)p->pwid, lx_b->drawingArea );
 
-    if ((lx_b->orientation = p->panel->orientation) == ORIENT_HORIZ) {
+    if ((lx_b->orientation = p->panel->orientation) == GTK_ORIENTATION_HORIZONTAL) {
         lx_b->height = lx_b->length = 20;
         lx_b->thickness = lx_b->width = 8;
     }
@@ -432,11 +432,11 @@ constructor(Plugin *p, char **fp)
 
     gtk_widget_show(lx_b->drawingArea);
 
-    g_signal_connect (G_OBJECT (lx_b->drawingArea), "button_press_event",
+    g_signal_connect (G_OBJECT (lx_b->drawingArea), "button-press-event",
             G_CALLBACK(buttonPressEvent), (gpointer) p);
-    g_signal_connect (G_OBJECT (lx_b->drawingArea),"configure_event",
+    g_signal_connect (G_OBJECT (lx_b->drawingArea),"configure-event",
           G_CALLBACK (configureEvent), (gpointer) lx_b);
-    g_signal_connect (G_OBJECT (lx_b->drawingArea), "expose_event",
+    g_signal_connect (G_OBJECT (lx_b->drawingArea), "expose-event",
           G_CALLBACK (exposeEvent), (gpointer) lx_b);
 
     sem_init(&(lx_b->alarmProcessLock), 0, 1);
@@ -482,7 +482,7 @@ constructor(Plugin *p, char **fp)
                     lx_b->requestedBorder = atoi(s.t[1]);
                 else if (!g_ascii_strcasecmp(s.t[0], "Size")) {
                     lx_b->thickness = MAX(1, atoi(s.t[1]));
-                    if (lx_b->orientation == ORIENT_HORIZ)
+                    if (lx_b->orientation == GTK_ORIENTATION_HORIZONTAL)
                         lx_b->width = lx_b->thickness;
                     else
                         lx_b->height = lx_b->thickness;
@@ -609,7 +609,7 @@ static void applyConfig(Plugin* p)
             (MIN(b->length, b->thickness) - 1) / 2);
 
     /* Resize the widget */
-    if (b->orientation == ORIENT_HORIZ)
+    if (b->orientation == GTK_ORIENTATION_HORIZONTAL)
         b->width = b->thickness;
     else
         b->height = b->thickness;
index d495487..7857eb5 100644 (file)
@@ -28,7 +28,7 @@
 #include <stdlib.h>
 #include <glib/gi18n.h>
 
-#include "plugin.h"
+#include "private.h"
 #include "panel.h"
 #include "misc.h"
 
index bebbaee..e923d28 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "panel.h"
 #include "misc.h"
-#include "plugin.h"
+#include "private.h"
 
 #include "dbg.h"
 
@@ -359,7 +359,7 @@ cpufreq_constructor(Plugin *p, char** fp)
     gtk_object_sink( cf->tip );
 #endif
 
-    g_signal_connect (G_OBJECT (p->pwid), "button_press_event", G_CALLBACK (clicked), (gpointer) p);
+    g_signal_connect (G_OBJECT (p->pwid), "button-press-event", G_CALLBACK (clicked), (gpointer) p);
 
     cf->has_cpufreq = 0;
 
index 06ac01c..3bffefb 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
+ * Copyright (c) 2006-2014 LxDE Developers, see the file AUTHORS for details.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include "plugin.h"
+#include "misc.h"
+
+#include <libfm/fm-gtk.h>
+
 #include <time.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <string.h>
 #include <glib/gi18n.h>
 
-#include "panel.h"
-#include "misc.h"
-#include "plugin.h"
-
 #include "dbg.h"
 
 #define DEFAULT_TIP_FORMAT    "%A %x"
@@ -35,7 +36,9 @@
 
 /* Private context for digital clock plugin. */
 typedef struct {
-    Plugin * plugin;                           /* Back pointer to Plugin */
+    GtkWidget * plugin;                                /* Back pointer to plugin */
+    Panel * panel;
+    config_setting_t *settings;
     GtkWidget * clock_label;                   /* Label containing clock value */
     GtkWidget * clock_icon;                    /* Icon when icon_only */
     GtkWidget * calendar_window;               /* Calendar window, if it is being displayed */
@@ -57,22 +60,14 @@ typedef struct {
     char * prev_tooltip_value;                 /* Previous value of tooltip */
 } DClockPlugin;
 
-static void dclock_popup_map(GtkWidget * widget, DClockPlugin * dc);
-static GtkWidget * dclock_create_calendar(DClockPlugin * dc);
-static gboolean dclock_button_press_event(GtkWidget * widget, GdkEventButton * evt, Plugin * plugin);
-static void dclock_timer_set(DClockPlugin * dc);
 static gboolean dclock_update_display(DClockPlugin * dc);
-static int dclock_constructor(Plugin * p, char ** fp);
-static void dclock_destructor(Plugin * p);
-static void dclock_apply_configuration(Plugin * p);
-static void dclock_configure(Plugin * p, GtkWindow * parent);
-static void dclock_save_configuration(Plugin * p, FILE * fp);
-static void dclock_panel_configuration_changed(Plugin * p);
+static void dclock_destructor(gpointer user_data);
+static gboolean dclock_apply_configuration(gpointer user_data);
 
 /* Handler for "map" signal on popup window. */
 static void dclock_popup_map(GtkWidget * widget, DClockPlugin * dc)
 {
-    plugin_adjust_popup_position(widget, dc->plugin);
+    lxpanel_plugin_adjust_popup_position(widget, dc->plugin);
 }
 
 /* Display a window containing the standard calendar widget. */
@@ -107,17 +102,19 @@ static GtkWidget * dclock_create_calendar(DClockPlugin * dc)
 }
 
 /* Handler for "button-press-event" event from main widget. */
-static gboolean dclock_button_press_event(GtkWidget * widget, GdkEventButton * evt, Plugin * plugin)
+static gboolean dclock_button_press_event(GtkWidget * widget, GdkEventButton * evt, Panel * panel)
 {
-    DClockPlugin * dc = (DClockPlugin *) plugin->priv;
+    DClockPlugin * dc;
 
     /* Standard right-click handling. */
-    if (plugin_button_press_event(widget, evt, plugin))
+    if (lxpanel_plugin_button_press_event(widget, evt, panel))
         return TRUE;
 
+    dc = lxpanel_plugin_get_data(widget);
+
     /* If an action is set, execute it. */
     if (dc->action != NULL)
-        spawn_command_async(NULL, NULL, dc->action);
+        fm_launch_command_simple(NULL, NULL, 0, dc->action, NULL);
 
     /* If no action is set, toggle the presentation of the calendar. */
     else
@@ -211,7 +208,7 @@ static gboolean dclock_update_display(DClockPlugin * dc)
         gchar * utf8 = g_locale_to_utf8(((newlines_converted != NULL) ? newlines_converted : clock_value), -1, NULL, NULL, NULL);
         if (utf8 != NULL)
         {
-            panel_draw_label_text(dc->plugin->panel, dc->clock_label, utf8, dc->bold, 1, TRUE);
+            panel_draw_label_text(dc->panel, dc->clock_label, utf8, dc->bold, 1, TRUE);
             g_free(utf8);
         }
         g_free(newlines_converted);
@@ -221,7 +218,7 @@ static gboolean dclock_update_display(DClockPlugin * dc)
     gchar * utf8 = g_locale_to_utf8(tooltip_value, -1, NULL, NULL, NULL);
     if (utf8 != NULL)
     {
-        gtk_widget_set_tooltip_text(dc->plugin->pwid, utf8);
+        gtk_widget_set_tooltip_text(dc->plugin, utf8);
         g_free(utf8);
     }
 
@@ -281,56 +278,39 @@ static gboolean dclock_update_display(DClockPlugin * dc)
 }
 
 /* Plugin constructor. */
-static int dclock_constructor(Plugin * p, char ** fp)
+static GtkWidget *dclock_constructor(Panel *panel, config_setting_t *settings)
 {
     /* Allocate and initialize plugin context and set into Plugin private data pointer. */
     DClockPlugin * dc = g_new0(DClockPlugin, 1);
-    p->priv = dc;
-    dc->plugin = p;
+    GtkWidget * p;
+    const char *str;
+    int tmp_int;
 
     /* Load parameters from the configuration file. */
-    line s;
-    s.len = 256;
-    if (fp != NULL)
-    {
-        while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END)
-        {
-            if (s.type == LINE_NONE)
-            {
-                ERR( "dclock: illegal token %s\n", s.str);
-                return 0;
-            }
-            if (s.type == LINE_VAR)
-            {
-                if (g_ascii_strcasecmp(s.t[0], "ClockFmt") == 0)
-                    dc->clock_format = g_strdup(s.t[1]);
-                else if (g_ascii_strcasecmp(s.t[0], "TooltipFmt") == 0)
-                    dc->tooltip_format = g_strdup(s.t[1]);
-                else if (g_ascii_strcasecmp(s.t[0], "Action") == 0)
-                    dc->action = g_strdup(s.t[1]);
-                else if (g_ascii_strcasecmp(s.t[0], "BoldFont") == 0)
-                    dc->bold = str2num(bool_pair, s.t[1], 0);
-                else if (g_ascii_strcasecmp(s.t[0], "IconOnly") == 0)
-                    dc->icon_only = str2num(bool_pair, s.t[1], 0);
-                else if (g_ascii_strcasecmp(s.t[0], "CenterText") == 0)
-                    dc->center_text = str2num(bool_pair, s.t[1], 0);
-                else
-                    ERR( "dclock: unknown var %s\n", s.t[0]);
-            }
-            else
-            {
-                ERR( "dclock: illegal in this context %s\n", s.str);
-                return 0;
-            }
-        }
-    }
+    if (config_setting_lookup_string(settings, "ClockFmt", &str))
+        dc->clock_format = g_strdup(str);
+    if (config_setting_lookup_string(settings, "TooltipFmt", &str))
+        dc->tooltip_format = g_strdup(str);
+    if (config_setting_lookup_string(settings, "Action", &str))
+        dc->action = g_strdup(str);
+    if (config_setting_lookup_int(settings, "BoldFont", &tmp_int))
+        dc->bold = tmp_int != 0;
+    if (config_setting_lookup_int(settings, "IconOnly", &tmp_int))
+        dc->icon_only = tmp_int != 0;
+    if (config_setting_lookup_int(settings, "CenterText", &tmp_int))
+        dc->center_text = tmp_int != 0;
+
+    /* Save construction pointers */
+    dc->panel = panel;
+    dc->settings = settings;
 
     /* Allocate top level widget and set into Plugin widget pointer. */
-    p->pwid = gtk_event_box_new();
+    dc->plugin = p = gtk_event_box_new();
+    lxpanel_plugin_set_data(p, dc, dclock_destructor);
 
     /* Allocate a horizontal box as the child of the top level. */
     GtkWidget * hbox = gtk_hbox_new(TRUE, 0);
-    gtk_container_add(GTK_CONTAINER(p->pwid), hbox);
+    gtk_container_add(GTK_CONTAINER(p), hbox);
     gtk_widget_show(hbox);
 
     /* Create a label and an image as children of the horizontal box.
@@ -342,9 +322,6 @@ static int dclock_constructor(Plugin * p, char ** fp)
     dc->clock_icon = gtk_image_new();
     gtk_container_add(GTK_CONTAINER(hbox), dc->clock_icon);
 
-    /* Connect signals. */
-    g_signal_connect(G_OBJECT (p->pwid), "button_press_event", G_CALLBACK(dclock_button_press_event), (gpointer) p);
-
     /* Initialize the clock display. */
     if (dc->clock_format == NULL)
         dc->clock_format = g_strdup(_(DEFAULT_CLOCK_FORMAT));
@@ -353,14 +330,13 @@ static int dclock_constructor(Plugin * p, char ** fp)
     dclock_apply_configuration(p);
 
     /* Show the widget and return. */
-    gtk_widget_show(p->pwid);
-    return 1;
+    return p;
 }
 
 /* Plugin destructor. */
-static void dclock_destructor(Plugin * p)
+static void dclock_destructor(gpointer user_data)
 {
-    DClockPlugin * dc = (DClockPlugin *) p->priv;
+    DClockPlugin * dc = user_data;
 
     /* Remove the timer. */
     if (dc->timer != 0)
@@ -380,16 +356,17 @@ static void dclock_destructor(Plugin * p)
 }
 
 /* Callback when the configuration dialog has recorded a configuration change. */
-static void dclock_apply_configuration(Plugin * p)
+static gboolean dclock_apply_configuration(gpointer user_data)
 {
-    DClockPlugin * dc = (DClockPlugin *) p->priv;
+    GtkWidget * p = user_data;
+    DClockPlugin * dc = lxpanel_plugin_get_data(p);
 
     /* Set up the icon or the label as the displayable widget. */
     if (dc->icon_only)
     {
-               if(panel_image_set_icon_theme(p->panel, dc->clock_icon, "clock") != FALSE) {
-                       panel_image_set_from_file(p->panel, dc->clock_icon, PACKAGE_DATA_DIR "/lxpanel/images/clock.png");
-               }
+        if(panel_image_set_icon_theme(dc->panel, dc->clock_icon, "clock") != FALSE) {
+            panel_image_set_from_file(dc->panel, dc->clock_icon, PACKAGE_DATA_DIR "/lxpanel/images/clock.png");
+        }
         gtk_widget_show(dc->clock_icon);
         gtk_widget_hide(dc->clock_label);
     }
@@ -398,14 +375,14 @@ static void dclock_apply_configuration(Plugin * p)
         gtk_widget_show(dc->clock_label);
         gtk_widget_hide(dc->clock_icon);
     }
-    
+
     if (dc->center_text)
     {
-           gtk_label_set_justify(GTK_LABEL(dc->clock_label), GTK_JUSTIFY_CENTER);
+        gtk_label_set_justify(GTK_LABEL(dc->clock_label), GTK_JUSTIFY_CENTER);
     }
     else
     {
-           gtk_label_set_justify(GTK_LABEL(dc->clock_label), GTK_JUSTIFY_LEFT);
+        gtk_label_set_justify(GTK_LABEL(dc->clock_label), GTK_JUSTIFY_LEFT);
     }
 
     /* Rerun the experiment to determine update interval and update the display. */
@@ -423,16 +400,32 @@ static void dclock_apply_configuration(Plugin * p)
         gtk_widget_destroy(dc->calendar_window);
         dc->calendar_window = NULL;
     }
+
+    /* Save configuration */
+    config_setting_set_string(config_setting_add(dc->settings, "ClockFmt",
+                                              PANEL_CONF_TYPE_STRING),
+                              dc->clock_format);
+    config_setting_set_string(config_setting_add(dc->settings, "TooltipFmt",
+                                              PANEL_CONF_TYPE_STRING),
+                              dc->tooltip_format);
+    config_setting_set_string(config_setting_add(dc->settings, "Action",
+                                              PANEL_CONF_TYPE_STRING),
+                              dc->action);
+    config_setting_set_int(config_setting_add(dc->settings, "BoldFont",
+                                              PANEL_CONF_TYPE_INT), dc->bold);
+    config_setting_set_int(config_setting_add(dc->settings, "IconOnly",
+                                              PANEL_CONF_TYPE_INT), dc->icon_only);
+    config_setting_set_int(config_setting_add(dc->settings, "CenterText",
+                                              PANEL_CONF_TYPE_INT), dc->center_text);
+    return FALSE;
 }
 
 /* Callback when the configuration dialog is to be shown. */
-static void dclock_configure(Plugin * p, GtkWindow * parent)
+static void dclock_configure(Panel *panel, GtkWidget *p, GtkWindow *parent)
 {
-    DClockPlugin * dc = (DClockPlugin *) p->priv;
-    GtkWidget * dlg = create_generic_config_dlg(
-        _(p->class->name),
-        GTK_WIDGET(parent),
-        (GSourceFunc) dclock_apply_configuration, (gpointer) p,
+    DClockPlugin * dc = lxpanel_plugin_get_data(p);
+    GtkWidget * dlg = lxpanel_generic_config_dlg(_("Digital Clock"), panel,
+        dclock_apply_configuration, p,
         _("Clock Format"), &dc->clock_format, CONF_TYPE_STR,
         _("Tooltip Format"), &dc->tooltip_format, CONF_TYPE_STR,
         _("Format codes: man 3 strftime; \%n for line break"), NULL, CONF_TYPE_TRIM,
@@ -444,37 +437,19 @@ static void dclock_configure(Plugin * p, GtkWindow * parent)
     gtk_window_present(GTK_WINDOW(dlg));
 }
 
-/* Callback when the configuration is to be saved. */
-static void dclock_save_configuration(Plugin * p, FILE * fp)
-{
-    DClockPlugin * dc = (DClockPlugin *) p->priv;
-    lxpanel_put_str(fp, "ClockFmt", dc->clock_format);
-    lxpanel_put_str(fp, "TooltipFmt", dc->tooltip_format);
-    lxpanel_put_str(fp, "Action", dc->action);
-    lxpanel_put_int(fp, "BoldFont", dc->bold);
-    lxpanel_put_int(fp, "IconOnly", dc->icon_only);
-    lxpanel_put_int(fp, "CenterText", dc->center_text);
-}
-
 /* Callback when panel configuration changes. */
-static void dclock_panel_configuration_changed(Plugin * p)
+static void dclock_reconfigure(Panel *panel, GtkWidget *p)
 {
     dclock_apply_configuration(p);
 }
 
 /* Plugin descriptor. */
-PluginClass dclock_plugin_class = {
-
-    PLUGINCLASS_VERSIONING,
-
-    .type = "dclock",
+LXPanelPluginInit lxpanel_static_plugin_dclock = {
     .name = N_("Digital Clock"),
-    .version = "1.0",
     .description = N_("Display digital clock and tooltip"),
 
-    .constructor = dclock_constructor,
-    .destructor  = dclock_destructor,
+    .new_instance = dclock_constructor,
     .config = dclock_configure,
-    .save = dclock_save_configuration,
-    .panel_configuration_changed = dclock_panel_configuration_changed
+    .reconfigure = dclock_reconfigure,
+    .button_press_event = dclock_button_press_event
 };
index 686391d..ba82c57 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "panel.h"
 #include "misc.h"
-#include "plugin.h"
+#include "private.h"
 
 #include "dbg.h"
 
@@ -164,10 +164,10 @@ static int deskno_constructor(Plugin * p, char ** fp)
     gtk_container_add(GTK_CONTAINER(p->pwid), dc->label);
 
     /* Connect signals.  Note use of window manager event object. */
-    g_signal_connect(p->pwid, "button_press_event", G_CALLBACK(deskno_button_press_event), p);
-    g_signal_connect(G_OBJECT(fbev), "current_desktop", G_CALLBACK(deskno_name_update), (gpointer) dc);
-    g_signal_connect(G_OBJECT(fbev), "desktop_names", G_CALLBACK(deskno_redraw), (gpointer) dc);
-    g_signal_connect(G_OBJECT(fbev), "number_of_desktops", G_CALLBACK(deskno_redraw), (gpointer) dc);
+    g_signal_connect(p->pwid, "button-press-event", G_CALLBACK(deskno_button_press_event), p);
+    g_signal_connect(G_OBJECT(fbev), "current-desktop", G_CALLBACK(deskno_name_update), (gpointer) dc);
+    g_signal_connect(G_OBJECT(fbev), "desktop-names", G_CALLBACK(deskno_redraw), (gpointer) dc);
+    g_signal_connect(G_OBJECT(fbev), "number-of-desktops", G_CALLBACK(deskno_redraw), (gpointer) dc);
 
     /* Initialize value and show the widget. */
     deskno_redraw(NULL, dc);
index c3f5ff3..4cf5400 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
+ * Copyright (c) 2006-2014 LxDE Developers, see the file AUTHORS for details.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <stdlib.h>
 #include <unistd.h>
 
-#include <gdk-pixbuf/gdk-pixbuf.h>
 #include <glib/gi18n.h>
+#include <libfm/fm-gtk.h>
 #include <string.h>
 
-#include "panel.h"
 #include "misc.h"
 #include "plugin.h"
-#include "dbg.h"
 
 /* Temporary for sort of directory names. */
 typedef struct _directory_name {
@@ -37,63 +35,35 @@ typedef struct _directory_name {
 
 /* Private context for directory menu plugin. */
 typedef struct {
-    Plugin * plugin;                   /* Back pointer to plugin */
+    Panel * panel; /* The panel and settings are required to apply config */
+    config_setting_t * settings;
     char * image;                      /* Icon for top level widget */
     char * path;                       /* Top level path for widget */
     char * name;                       /* User's label for widget */
     GdkPixbuf * folder_icon;           /* Icon for folders */
 } DirMenuPlugin;
 
-static void dirmenu_open_in_file_manager(Plugin * p, const char * path);
-static void dirmenu_open_in_terminal(Plugin * p, const char * path);
-static void dirmenu_menuitem_open_directory(GtkWidget * item, Plugin * p);
-static void dirmenu_menuitem_open_in_terminal(GtkWidget * item, Plugin * p);
-static void dirmenu_menuitem_select(GtkMenuItem * item, Plugin * p);
-static void dirmenu_menuitem_deselect(GtkMenuItem * item, Plugin * p);
-void dirmenu_menu_selection_done(GtkWidget * menu, Plugin * p);
-static void dirmenu_popup_set_position(GtkWidget * menu, gint * px, gint * py, gboolean * push_in, Plugin * p);
-static GtkWidget * dirmenu_create_menu(Plugin * p, const char * path, gboolean open_at_top);
-static void dirmenu_show_menu(GtkWidget * widget, Plugin * p, int btn, guint32 time);
-static gboolean dirmenu_button_press_event(GtkWidget * widget, GdkEventButton * event, Plugin * p);
-static int dirmenu_constructor(Plugin * p, char ** fp);
-static void dirmenu_destructor(Plugin * p);
-static void dirmenu_apply_configuration_to_children(GtkWidget * w, DirMenuPlugin * dm);
-static void dirmenu_apply_configuration(Plugin * p);
-static void dirmenu_configure(Plugin * p, GtkWindow * parent);
-static void dirmenu_save_configuration(Plugin * p, FILE * fp);
-static void dirmenu_panel_configuration_changed(Plugin * p);
-
-/* Open a specified path in a file manager. */
-static void dirmenu_open_in_file_manager(Plugin * p, const char * path)
-{
-    char * quote = g_shell_quote(path);
-    const char * fm = lxpanel_get_file_manager();
-    char * cmd = ((strstr(fm, "%s") != NULL) ? g_strdup_printf(fm, quote) : g_strdup_printf("%s %s", fm, quote));
-    g_free(quote);
-    spawn_command_async(NULL, NULL, cmd);
-    g_free(cmd);
-}
+static GtkWidget * dirmenu_create_menu(DirMenuPlugin * dm, const char * path, gboolean open_at_top);
+static void dirmenu_destructor(gpointer user_data);
+static gboolean dirmenu_apply_configuration(gpointer user_data);
 
-/* Open a specified path in a terminal. */
-static void dirmenu_open_in_terminal(Plugin * p, const char * path)
-{
-    spawn_command_async(NULL, path, lxpanel_get_terminal());
-}
 
 /* Handler for activate event on popup Open menu item. */
-static void dirmenu_menuitem_open_directory(GtkWidget * item, Plugin * p)
+static void dirmenu_menuitem_open_directory(GtkWidget * item, DirMenuPlugin * dm)
 {
-    dirmenu_open_in_file_manager(p, g_object_get_data(G_OBJECT(gtk_widget_get_parent(item)), "path"));
+    FmPath *path = fm_path_new_for_str(g_object_get_data(G_OBJECT(gtk_widget_get_parent(item)), "path"));
+    lxpanel_launch_path(dm->panel, path);
+    fm_path_unref(path);
 }
 
 /* Handler for activate event on popup Open In Terminal menu item. */
-static void dirmenu_menuitem_open_in_terminal(GtkWidget * item, Plugin * p)
+static void dirmenu_menuitem_open_in_terminal(GtkWidget * item, DirMenuPlugin * dm)
 {
-    dirmenu_open_in_terminal(p, g_object_get_data(G_OBJECT(gtk_widget_get_parent(item)), "path"));
+    fm_terminal_launch(g_object_get_data(G_OBJECT(gtk_widget_get_parent(item)), "path"), NULL);
 }
 
 /* Handler for select event on popup menu item. */
-static void dirmenu_menuitem_select(GtkMenuItem * item, Plugin * p)
+static void dirmenu_menuitem_select(GtkMenuItem * item, DirMenuPlugin * dm)
 {
     GtkWidget * sub = gtk_menu_item_get_submenu(item);
     if (sub != NULL)
@@ -107,7 +77,7 @@ static void dirmenu_menuitem_select(GtkMenuItem * item, Plugin * p)
                 (char *) g_object_get_data(G_OBJECT(parent), "path"),
                 (char *) g_object_get_data(G_OBJECT(item), "name"),
                 NULL);
-            sub = dirmenu_create_menu(p, path, TRUE);
+            sub = dirmenu_create_menu(dm, path, TRUE);
             g_free(path);
             gtk_menu_item_set_submenu(item, sub);
         }
@@ -115,35 +85,34 @@ static void dirmenu_menuitem_select(GtkMenuItem * item, Plugin * p)
 }
 
 /* Handler for deselect event on popup menu item. */
-static void dirmenu_menuitem_deselect(GtkMenuItem * item, Plugin * p)
+static void dirmenu_menuitem_deselect(GtkMenuItem * item, DirMenuPlugin * dm)
 {
     /* Delete old menu on deselect to save resource. */
     gtk_menu_item_set_submenu(item, gtk_menu_new());
 }
 
 /* Handler for selection-done event on popup menu. */
-void dirmenu_menu_selection_done(GtkWidget * menu, Plugin * p)
+static void dirmenu_menu_selection_done(GtkWidget * menu, DirMenuPlugin * dm)
 {
     gtk_widget_destroy(menu);
 }
 
 /* Position-calculation callback for popup menu. */
-static void dirmenu_popup_set_position(GtkWidget * menu, gint * px, gint * py, gboolean * push_in, Plugin * p)
+static void dirmenu_popup_set_position(GtkWidget * menu, gint * px, gint * py, gboolean * push_in, GtkWidget * p)
 {
+    DirMenuPlugin * dm = lxpanel_plugin_get_data(p);
     /* Get the allocation of the popup menu. */
     GtkRequisition popup_req;
     gtk_widget_size_request(menu, &popup_req);
 
     /* Determine the coordinates. */
-    plugin_popup_set_position_helper(p, p->pwid, menu, &popup_req, px, py);
+    lxpanel_plugin_popup_set_position_helper(dm->panel, p, menu, &popup_req, px, py);
     *push_in = TRUE;
 }
 
 /* Create a menu populated with all subdirectories. */
-static GtkWidget * dirmenu_create_menu(Plugin * p, const char * path, gboolean open_at_top)
+static GtkWidget * dirmenu_create_menu(DirMenuPlugin * dm, const char * path, gboolean open_at_top)
 {
-    DirMenuPlugin * dm = (DirMenuPlugin *) p->priv;
-
     /* Create a menu. */
     GtkWidget * menu = gtk_menu_new();
 
@@ -153,7 +122,7 @@ static GtkWidget * dirmenu_create_menu(Plugin * p, const char * path, gboolean o
         int h;
         gtk_icon_size_lookup_for_settings(gtk_widget_get_settings(menu), GTK_ICON_SIZE_MENU, &w, &h);
         dm->folder_icon = gtk_icon_theme_load_icon(
-            p->panel->icon_theme,
+            panel_get_icon_theme(dm->panel),
             "gnome-fs-directory", MAX(w, h), 0, NULL);
         if (dm->folder_icon == NULL)
             dm->folder_icon = gtk_widget_render_icon(menu, GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
@@ -229,15 +198,15 @@ static GtkWidget * dirmenu_create_menu(Plugin * p, const char * path, gboolean o
         g_free(dir_cursor);
 
         /* Connect signals. */
-        g_signal_connect(G_OBJECT(item), "select", G_CALLBACK(dirmenu_menuitem_select), p);
-        g_signal_connect(G_OBJECT(item), "deselect", G_CALLBACK(dirmenu_menuitem_deselect), p);
+        g_signal_connect(G_OBJECT(item), "select", G_CALLBACK(dirmenu_menuitem_select), dm);
+        g_signal_connect(G_OBJECT(item), "deselect", G_CALLBACK(dirmenu_menuitem_deselect), dm);
     }
 
     /* Create "Open" and "Open in Terminal" items. */
     GtkWidget * item = gtk_image_menu_item_new_from_stock( GTK_STOCK_OPEN, NULL );
-    g_signal_connect(item, "activate", G_CALLBACK(dirmenu_menuitem_open_directory), p);
+    g_signal_connect(item, "activate", G_CALLBACK(dirmenu_menuitem_open_directory), dm);
     GtkWidget * term = gtk_menu_item_new_with_mnemonic( _("Open in _Terminal") );
-    g_signal_connect(term, "activate", G_CALLBACK(dirmenu_menuitem_open_in_terminal), p);
+    g_signal_connect(term, "activate", G_CALLBACK(dirmenu_menuitem_open_in_terminal), dm);
 
     /* Insert or append based on caller's preference. */
     if (open_at_top)
@@ -258,101 +227,78 @@ static GtkWidget * dirmenu_create_menu(Plugin * p, const char * path, gboolean o
 }
 
 /* Show a menu of subdirectories. */
-static void dirmenu_show_menu(GtkWidget * widget, Plugin * p, int btn, guint32 time)
+static void dirmenu_show_menu(GtkWidget * widget, DirMenuPlugin * dm, int btn, guint32 time)
 {
-    DirMenuPlugin * dm = (DirMenuPlugin *) p->priv;
-
     /* Create a menu populated with all subdirectories. */
-    GtkWidget * menu = dirmenu_create_menu(
-        p,
-        ((dm->path != NULL) ? expand_tilda(dm->path) : g_get_home_dir()),
-        FALSE);
-    g_signal_connect(menu, "selection-done", G_CALLBACK(dirmenu_menu_selection_done), NULL);
+    GtkWidget * menu = dirmenu_create_menu(dm, dm->path, FALSE);
+    g_signal_connect(menu, "selection-done", G_CALLBACK(dirmenu_menu_selection_done), dm);
 
     /* Show the menu.  Use a positioning function to get it placed next to the top level widget. */
-    gtk_menu_popup(GTK_MENU(menu), NULL, NULL, (GtkMenuPositionFunc) dirmenu_popup_set_position, p, btn, time);
+    gtk_menu_popup(GTK_MENU(menu), NULL, NULL, (GtkMenuPositionFunc) dirmenu_popup_set_position, widget, btn, time);
 }
 
 /* Handler for button-press-event on top level widget. */
-static gboolean dirmenu_button_press_event(GtkWidget * widget, GdkEventButton * event, Plugin * p)
+static gboolean dirmenu_button_press_event(GtkWidget * widget, GdkEventButton * event, Panel * p)
 {
-    DirMenuPlugin * dm = (DirMenuPlugin *) p->priv;
+    DirMenuPlugin * dm = lxpanel_plugin_get_data(widget);
 
     /* Standard left-click handling. */
-    if (plugin_button_press_event(widget, event, p))
+    if (lxpanel_plugin_button_press_event(widget, event, p))
         return TRUE;
 
     if (event->button == 1)
     {
-        dirmenu_show_menu(widget, p, event->button, event->time);
+        dirmenu_show_menu(widget, dm, event->button, event->time);
     }
     else
     {
-        dirmenu_open_in_terminal(p, ((dm->path != NULL) ? expand_tilda(dm->path) : g_get_home_dir()));
+        fm_terminal_launch(dm->path, NULL);
     }
     return TRUE;
 }
 
 /* Plugin constructor. */
-static int dirmenu_constructor(Plugin * p, char ** fp)
+static GtkWidget *dirmenu_constructor(Panel *panel, config_setting_t *settings)
 {
     /* Allocate and initialize plugin context and set into Plugin private data pointer. */
     DirMenuPlugin * dm = g_new0(DirMenuPlugin, 1);
-    dm->plugin = p;
-    p->priv = dm;
+    GtkWidget * p;
+    const char *str;
 
     /* Load parameters from the configuration file. */
-    line s;
-    s.len = 256;
-    if (fp != NULL)
-    {
-        while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END)
-        {
-            if (s.type == LINE_NONE)
-            {
-                ERR( "dirmenu: illegal token %s\n", s.str);
-                return 0;
-            }
-            if (s.type == LINE_VAR)
-            {
-                if (g_ascii_strcasecmp(s.t[0], "image") == 0)
-                    dm->image = g_strdup(s.t[1]);
-                else if (g_ascii_strcasecmp(s.t[0], "path") == 0)
-                    dm->path = g_strdup(s.t[1]);
-               else if (g_ascii_strcasecmp(s.t[0], "name") == 0)
-                    dm->name = g_strdup( s.t[1] );
-                else
-                    ERR( "dirmenu: unknown var %s\n", s.t[0]);
-            }
-            else
-            {
-                ERR( "dirmenu: illegal in this context %s\n", s.str);
-                return 0;
-            }
-        }
-    }
+    if (config_setting_lookup_string(settings, "image", &str))
+        dm->image = g_strdup(str);
+    if (config_setting_lookup_string(settings, "path", &str))
+        dm->path = expand_tilda(str);
+    else
+        dm->path = g_strdup(fm_get_home_dir());
+    if (config_setting_lookup_string(settings, "name", &str))
+        dm->name = g_strdup(str);
+
+    /* Save construction pointers */
+    dm->panel = panel;
+    dm->settings = settings;
 
     /* Allocate top level widget and set into Plugin widget pointer.
      * It is not known why, but the button text will not draw if it is edited from empty to non-empty
      * unless this strategy of initializing it with a non-empty value first is followed. */
-    p->pwid = fb_button_new_from_file_with_label(
-        ((dm->image != NULL) ? dm->image : "file-manager"),
-        p->panel->icon_size, p->panel->icon_size, PANEL_ICON_HIGHLIGHT, TRUE, p->panel, "Temp");
-    gtk_container_set_border_width(GTK_CONTAINER(p->pwid), 0);
-    g_signal_connect(p->pwid, "button_press_event", G_CALLBACK(dirmenu_button_press_event), p);
+    p = lxpanel_button_new_for_icon(panel,
+                            ((dm->image != NULL) ? dm->image : "file-manager"),
+                            NULL, "Temp");
+    lxpanel_plugin_set_data(p, dm, dirmenu_destructor);
+    gtk_container_set_border_width(GTK_CONTAINER(p), 0);
 
     /* Initialize the widget. */
     dirmenu_apply_configuration(p);
 
     /* Show the widget and return. */
-    gtk_widget_show(p->pwid);
-    return 1;
+    return p;
 }
 
 /* Plugin destructor. */
-static void dirmenu_destructor(Plugin * p)
+static void dirmenu_destructor(gpointer user_data)
 {
-    DirMenuPlugin * dm = (DirMenuPlugin *) p->priv;
+    DirMenuPlugin * dm = (DirMenuPlugin *)user_data;
 
     /* Release a reference on the folder icon if held. */
     if (dm->folder_icon)
@@ -369,38 +315,57 @@ static void dirmenu_destructor(Plugin * p)
 static void dirmenu_apply_configuration_to_children(GtkWidget * w, DirMenuPlugin * dm)
 {
     if (GTK_IS_CONTAINER(w))
-       gtk_container_foreach(GTK_CONTAINER(w), (GtkCallback) dirmenu_apply_configuration_to_children, (gpointer) dm);
+        gtk_container_foreach(GTK_CONTAINER(w), (GtkCallback) dirmenu_apply_configuration_to_children, (gpointer) dm);
     else if (GTK_IS_LABEL(w))
     {
         if (dm->name == NULL)
-           gtk_label_set_text(GTK_LABEL(w), NULL);
+            gtk_label_set_text(GTK_LABEL(w), NULL);
         else
-            panel_draw_label_text(dm->plugin->panel, w, dm->name, FALSE, 1, TRUE);
+            panel_draw_label_text(dm->panel, w, dm->name, FALSE, 1, TRUE);
     }
 }
 
 /* Callback when the configuration dialog has recorded a configuration change. */
-static void dirmenu_apply_configuration(Plugin * p)
+static gboolean dirmenu_apply_configuration(gpointer user_data)
 {
-    DirMenuPlugin * dm = (DirMenuPlugin *) p->priv;
-
-    fb_button_set_from_file(p->pwid,
-        ((dm->image != NULL) ? dm->image : "file-manager"),
-        ((dm->image != NULL) ? -1 : p->panel->icon_size), p->panel->icon_size, TRUE);
+    GtkWidget * p = user_data;
+    DirMenuPlugin * dm = lxpanel_plugin_get_data(p);
+    char * path = dm->path;
+
+    /* Normalize path */
+    if (path == NULL)
+        dm->path = g_strdup(fm_get_home_dir());
+    else if (path[0] == '~')
+    {
+        dm->path = expand_tilda(path);
+        g_free(path);
+    }
 
-    gtk_widget_set_tooltip_text(p->pwid, ((dm->path != NULL) ? expand_tilda(dm->path) : g_get_home_dir()));
-    gtk_container_foreach(GTK_CONTAINER(p->pwid), (GtkCallback) dirmenu_apply_configuration_to_children, (gpointer) dm);
+    /* Save configuration */
+    config_setting_set_string(config_setting_add(dm->settings, "path",
+                                                 PANEL_CONF_TYPE_STRING),
+                              dm->path);
+    config_setting_set_string(config_setting_add(dm->settings, "name",
+                                                 PANEL_CONF_TYPE_STRING),
+                              dm->name);
+    config_setting_set_string(config_setting_add(dm->settings, "image",
+                                                 PANEL_CONF_TYPE_STRING),
+                              dm->image);
+
+    lxpanel_button_set_icon(p, ((dm->image != NULL) ? dm->image : "file-manager"),
+                            panel_get_icon_size(dm->panel));
+
+    gtk_widget_set_tooltip_text(p, dm->path);
+    gtk_container_foreach(GTK_CONTAINER(p), (GtkCallback) dirmenu_apply_configuration_to_children, (gpointer) dm);
+    return FALSE;
 }
 
 /* Callback when the configuration dialog is to be shown. */
-static void dirmenu_configure(Plugin * p, GtkWindow * parent)
+static void dirmenu_configure(Panel *panel, GtkWidget *p, GtkWindow *parent)
 {
-
-    DirMenuPlugin * dm = (DirMenuPlugin *) p->priv;
-    GtkWidget * dlg = create_generic_config_dlg(
-        _(p->class->name),
-        GTK_WIDGET(parent),
-        (GSourceFunc) dirmenu_apply_configuration, (gpointer) p,
+    DirMenuPlugin * dm = lxpanel_plugin_get_data(p);
+    GtkWidget * dlg = lxpanel_generic_config_dlg(_("Directory Menu"),
+        panel, dirmenu_apply_configuration, p,
         _("Directory"), &dm->path, CONF_TYPE_DIRECTORY_ENTRY,
         _("Label"), &dm->name, CONF_TYPE_STR,
         _("Icon"), &dm->image, CONF_TYPE_FILE_ENTRY,
@@ -408,39 +373,19 @@ static void dirmenu_configure(Plugin * p, GtkWindow * parent)
     gtk_window_present(GTK_WINDOW(dlg));
 }
 
-/* Callback when the configuration is to be saved. */
-static void dirmenu_save_configuration(Plugin * p, FILE * fp)
-{
-    DirMenuPlugin * dm = (DirMenuPlugin *) p->priv;
-    lxpanel_put_str(fp, "path", dm->path);
-    lxpanel_put_str(fp, "name", dm->name);
-    lxpanel_put_str(fp, "image", dm->image);
-}
-
 /* Callback when panel configuration changes. */
-static void dirmenu_panel_configuration_changed(Plugin * p)
+static void dirmenu_panel_configuration_changed(Panel *panel, GtkWidget *p)
 {
-    DirMenuPlugin * dm = (DirMenuPlugin *) p->priv;
-    fb_button_set_from_file(p->pwid,
-        ((dm->image != NULL) ? dm->image : "file-manager"),
-        p->panel->icon_size, p->panel->icon_size, TRUE);
     dirmenu_apply_configuration(p);
 }
 
 /* Plugin descriptor. */
-PluginClass dirmenu_plugin_class = {
-
-    PLUGINCLASS_VERSIONING,
-
-    .type = "dirmenu",
+LXPanelPluginInit lxpanel_static_plugin_dirmenu = {
     .name = N_("Directory Menu"),
-    .version = "1.0",
     .description = N_("Browse directory tree via menu (Author = PCMan)"),
 
-    .constructor = dirmenu_constructor,
-    .destructor  = dirmenu_destructor,
+    .new_instance = dirmenu_constructor,
     .config = dirmenu_configure,
-    .save = dirmenu_save_configuration,
-    .panel_configuration_changed = dirmenu_panel_configuration_changed
-
+    .reconfigure = dirmenu_panel_configuration_changed,
+    .button_press_event = dirmenu_button_press_event
 };
index e637978..37ceac6 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "panel.h"
 #include "misc.h"
-#include "plugin.h"
+#include "private.h"
 
 #include "dbg.h"
 
@@ -106,7 +106,7 @@ image_constructor(Plugin *p, char **fp)
         wid = gtk_label_new("?");
     } else {
         float ratio;
-        ratio = (p->panel->orientation == ORIENT_HORIZ) ?
+        ratio = (p->panel->orientation == GTK_ORIENTATION_HORIZONTAL) ?
             (float) (p->panel->ah - 2) / (float) gdk_pixbuf_get_height(gp)
             : (float) (p->panel->aw - 2) / (float) gdk_pixbuf_get_width(gp);
         gps =  gdk_pixbuf_scale_simple (gp,
index 15c6191..b1e90da 100644 (file)
@@ -28,7 +28,7 @@ TODO : vertical support (r354)
 
 */
 
-#include "plugin.h"
+#include "private.h"
 
 #include "misc.h"
 #include "panel.h"
index 45d2841..640596f 100644 (file)
@@ -32,7 +32,7 @@
 #include "dbg.h"
 #include "panel.h"
 #include "misc.h"
-#include "plugin.h"
+#include "private.h"
 #include "icon-grid.h"
 
 static const char * on_icons_theme[] = {
@@ -189,8 +189,7 @@ static int kbled_constructor(Plugin * p, char ** fp)
 
     /* Allocate an icon grid manager to manage the container.
      * Then allocate three images for the three indications, but make them visible only when the configuration requests. */
-    GtkOrientation bo = (p->panel->orientation == ORIENT_HORIZ) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
-    kl->icon_grid = icon_grid_new(p->panel, p->pwid, bo, p->panel->icon_size, p->panel->icon_size, 0, 0, p->panel->height); 
+    kl->icon_grid = icon_grid_new(p->panel, p->pwid, p->panel->orientation, p->panel->icon_size, p->panel->icon_size, 0, 0, p->panel->height); 
     int i;
     for (i = 0; i < 3; i++)
     {
@@ -277,8 +276,7 @@ static void kbled_panel_configuration_changed(Plugin * p)
 {
     /* Set orientation into the icon grid. */
     KeyboardLEDPlugin * kl = (KeyboardLEDPlugin *) p->priv;
-    GtkOrientation bo = (p->panel->orientation == ORIENT_HORIZ) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
-    icon_grid_set_geometry(kl->icon_grid, bo, p->panel->icon_size, p->panel->icon_size, 0, 0, p->panel->height);
+    icon_grid_set_geometry(kl->icon_grid, p->panel->orientation, p->panel->icon_size, p->panel->icon_size, 0, 0, p->panel->height);
 
     /* Do a full redraw. */
     int current_state = kl->current_state;
index 748d608..cd0ebac 100644 (file)
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <glib/gi18n.h>
 
-#include <menu-cache.h>
+#include <libfm/fm-gtk.h>
 
-#include "panel.h"
 #include "misc.h"
 #include "plugin.h"
 #include "icon-grid.h"
-#include "menu-policy.h"
 
-#include "dbg.h"
+#define PANEL_ICON_SIZE 24 /* see the private.h */
 
 /* Drag and drop target info. */
 enum {
@@ -72,70 +70,39 @@ enum {
 
 static const char DESKTOP_ENTRY[] = "Desktop Entry";
 
+typedef struct LaunchbarPlugin LaunchbarPlugin;
+
 /* Representative of one launch button.
  * Note that the launch parameters come from the specified desktop file, or from the configuration file.
  * This structure is also used during the "add to launchbar" dialog to hold menu items. */
 typedef struct {
-    Plugin * plugin;                   /* Back pointer to plugin */
+    LaunchbarPlugin * p;               /* Back pointer to plugin */
     GtkWidget * widget;                        /* Pointer to button */
     GtkWidget * image_widget;          /* Pointer to image */
-    gchar * desktop_id;                        /* Name of application (desktop file name less the .desktop) */
-    gchar * image;                     /* Image icon (from Icon entry) */
-    gchar * action;                    /* Action (from Exec entry) */
-    gchar * tooltip;                   /* Tooltip (from Name entry) */
-    gchar * path;                       /* Working directory requested in .desktop file */
-    guchar use_terminal : 1;           /* True if Terminal=true or from configuration file */
-    guchar customize_image : 1;                /* True if image icon from configuration file */
-    guchar customize_action : 1;       /* True if action from configuration file */
-    guchar customize_tooltip : 1;      /* True if tooltip from configuration file */
-    guchar customize_path : 1;         /* True if path from configuration file */
+    FmFileInfo * fi;                   /* Launcher application descriptor */
+    config_setting_t * settings;       /* Pointer to settings */
 } LaunchButton;
 
 /* Private context for launchbar plugin. */
-typedef struct {
+struct LaunchbarPlugin {
+    GtkWidget * plugin;                        /* Back pointer to plugin */
+    config_setting_t * settings;
+    Panel * panel;                     /* Back pointer to panel */
     IconGrid * icon_grid;              /* Icon grid managing the container */
     GSList * buttons;                  /* Launchbar buttons */
     GtkWidget * config_dlg;            /* Configuration dialog */
     LaunchButton * bootstrap_button;   /* Bootstrapping button for empty launchbar */
+    FmIcon * add_icon;                 /* Icon for bootstrap_button */
     GtkWidget     *p_button_add, *p_button_remove, *p_label_menu_app_exec, *p_label_def_app_exec;
-} LaunchbarPlugin;
-
-void panel_config_save(Panel * panel);  /* defined in configurator.c */
+};
 
-static void launchbutton_free(LaunchButton * btn);
-static gboolean launchbutton_press_event(GtkWidget * widget, GdkEventButton * event, LaunchButton * b);
-static void launchbutton_drag_data_received_event(
-    GtkWidget * widget,
-    GdkDragContext * context,
-    gint x,
-    gint y,
-    GtkSelectionData * sd,
-    guint info,
-    guint time,
-    LaunchButton * b);
-static void launchbutton_build_bootstrap(Plugin * p);
-static void launchbutton_build_gui(Plugin * p, LaunchButton * btn);
-static int launchbutton_constructor(Plugin * p, char ** fp);
-static int launchbar_constructor(Plugin * p, char ** fp);
-static void launchbar_destructor(Plugin * p);
-static void launchbar_configure_add_button(GtkButton * widget, Plugin * p);
-static void launchbar_configure_remove_button(GtkButton * widget, Plugin * p);
-static void launchbar_configure_move_up_button(GtkButton * widget, Plugin * p);
-static void launchbar_configure_move_down_button(GtkButton * widget, Plugin * p);
-static void launchbar_configure_response(GtkDialog * dlg, int response, Plugin * p);
-static void launchbar_configure_initialize_list(Plugin * p, GtkWidget * dlg, GtkTreeView * view, gboolean from_menu);
-static void launchbar_configure(Plugin * p, GtkWindow * parent);
-static void launchbar_save_configuration(Plugin * p, FILE * fp);
-static void launchbar_panel_configuration_changed(Plugin * p);
+static void launchbar_configure(Panel *panel, GtkWidget *p, GtkWindow *parent);
+static void launchbar_destructor(gpointer user_data);
 
 /* Deallocate a LaunchButton. */
 static void launchbutton_free(LaunchButton * btn)
 {
-    g_free(btn->desktop_id);
-    g_free(btn->image);
-    g_free(btn->action);
-    g_free(btn->tooltip);
-    g_free(btn->path);
+    fm_file_info_unref(btn->fi);
     g_free(btn);
 }
 
@@ -165,92 +132,53 @@ static void on_defined_view_cursor_changed(GtkTreeView *p_treeview, gpointer p_d
     {
         LaunchButton * p_btn;
         gtk_tree_model_get(p_treemodel, &tree_iter_sel, COL_BTN, &p_btn, -1);
-        if( (p_btn != NULL) && (p_btn->action != NULL) )
+        if( (p_btn != NULL) && (p_btn->fi != NULL) )
         {
             GString *p_gstring = g_string_new("");
-            g_string_printf(p_gstring, "<i>Exec =</i>  %s", p_btn->action);
+            g_string_printf(p_gstring, "<i>%s</i>", fm_file_info_get_disp_name(p_btn->fi));
             gtk_label_set_markup(GTK_LABEL(lb->p_label_def_app_exec), p_gstring->str);
             g_string_free(p_gstring, TRUE/*free also gstring->str*/);
-            gtk_widget_set_visible(lb->p_label_def_app_exec, TRUE);
             label_set = TRUE;
         }
     }
-    if(!label_set)
-    {
-        gtk_widget_set_visible(lb->p_label_def_app_exec, FALSE);
-    }
+    gtk_widget_set_visible(lb->p_label_def_app_exec, label_set);
+    gtk_widget_set_sensitive(lb->p_button_remove, label_set);
 }
 
 static void on_menu_view_cursor_changed(GtkTreeView *p_treeview, gpointer p_data)
 {
     gboolean  label_set = FALSE;
     LaunchbarPlugin *lb = (LaunchbarPlugin *)p_data;
-    GtkTreeIter  tree_iter_sel;
-    GtkTreeModel* p_treemodel = gtk_tree_view_get_model(p_treeview);
-    GtkTreeSelection *p_treeselection = gtk_tree_view_get_selection(p_treeview);
-    if(gtk_tree_selection_get_selected(p_treeselection,
-                                       (GtkTreeModel **)(&p_treemodel),
-                                       &tree_iter_sel))
-    {
-        LaunchButton * p_btn;
-        gtk_tree_model_get(p_treemodel, &tree_iter_sel, COL_BTN, &p_btn, -1);
-        if( (p_btn != NULL) && (p_btn->action != NULL) )
-        {
-            GString *p_gstring = g_string_new("");
-            g_string_printf(p_gstring, "<i>Exec =</i>  %s", p_btn->action);
-            gtk_label_set_markup(GTK_LABEL(lb->p_label_menu_app_exec), p_gstring->str);
-            g_string_free(p_gstring, TRUE/*free also gstring->str*/);
-            gtk_widget_set_visible(lb->p_label_menu_app_exec, TRUE);
-            label_set = TRUE;
-        }
-    }
-    if(!label_set)
-    {
-        gtk_widget_set_visible(lb->p_label_menu_app_exec, FALSE);
-    }
-}
+    GAppInfo *app = fm_app_menu_view_dup_selected_app(p_treeview);
 
-static gboolean on_menu_view_button_press_event(GtkWidget *p_widget, GdkEventButton *p_event, gpointer p_data)
-{
-    if(p_event->button == 1)
+    if (app)
     {
-        if(p_event->type == GDK_2BUTTON_PRESS)
-        {
-            LaunchbarPlugin *lb = (LaunchbarPlugin *)p_data;
-            gtk_button_clicked(GTK_BUTTON(lb->p_button_add));
-        }
-    }
-    else if(p_event->button == 2)
-    {
-        GtkTreePath  *p_tree_path;
-        if(gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(p_widget),
-                                         p_event->x, p_event->y,
-                                         &p_tree_path,
-                                         NULL, NULL, NULL))
-        {
-            if(gtk_tree_view_row_expanded(GTK_TREE_VIEW(p_widget), p_tree_path))
-                gtk_tree_view_collapse_row(GTK_TREE_VIEW(p_widget), p_tree_path);
-            else
-                gtk_tree_view_expand_row(GTK_TREE_VIEW(p_widget), p_tree_path, FALSE);
-            gtk_tree_path_free(p_tree_path);
-        }
+        GString *p_gstring = g_string_new("");
+        if (g_app_info_get_description(app))
+            g_string_printf(p_gstring, "<i>%s</i>", g_app_info_get_description(app));
+        else
+            g_string_printf(p_gstring, "<i>%s</i>", g_app_info_get_name(app));
+        gtk_label_set_markup(GTK_LABEL(lb->p_label_menu_app_exec), p_gstring->str);
+        g_string_free(p_gstring, TRUE/*free also gstring->str*/);
+        label_set = TRUE;
     }
-    return FALSE;
+    gtk_widget_set_visible(lb->p_label_menu_app_exec, label_set);
+    gtk_widget_set_sensitive(lb->p_button_add, label_set);
 }
 
 /* Handler for "button-press-event" event from launchbar button. */
 static gboolean launchbutton_press_event(GtkWidget * widget, GdkEventButton * event, LaunchButton * b)
 {
     /* Standard right-click handling. */
-    if (plugin_button_press_event(widget, event, b->plugin))
+    if (lxpanel_plugin_button_press_event(b->p->plugin, event, b->p->panel))
         return TRUE;
 
     if (event->button == 1)    /* left button */
     {
-        if (b->desktop_id == NULL)     /* The bootstrap button */
-            launchbar_configure(b->plugin, NULL);
-        else if (b->action != NULL)
-            lxpanel_launch_app(b->action, NULL, b->use_terminal, b->path);
+        if (b->fi == NULL)     /* The bootstrap button */
+            launchbar_configure(b->p->panel, b->p->plugin, NULL);
+        else
+            lxpanel_launch_path(b->p->panel, fm_file_info_get_path(b->fi));
     }
     return TRUE;
 }
@@ -266,70 +194,30 @@ static void launchbutton_drag_data_received_event(
     guint time,
     LaunchButton * b)
 {
-    if (!b->action)
-    {
-        LOG(LOG_WARN, "launchbar: Button '%s' has no action (%s)\n",
-                b->desktop_id, b->action);
-        return;
-    }
-#if GTK_CHECK_VERSION(2,14,0)
     if (gtk_selection_data_get_length(sd) > 0)
-#else
-    if (sd->lengh > 0)
-#endif
     {
         if (info == TARGET_URILIST)
         {
-#if GTK_CHECK_VERSION(2,14,0)
-            gchar * s = (gchar *) gtk_selection_data_get_data(sd);
-#else
-            gchar * s = (gchar *) sd->data;
-#endif
-#if GTK_CHECK_VERSION(2,14,0)
-            gchar * end = s + gtk_selection_data_get_length(sd);
-#else
-            gchar * end = s + sd->lenght;
-#endif
-            gchar * str = g_strdup(b->action);
-            while (s < end)
-            {
-                while (s < end && g_ascii_isspace(*s))
-                    s++;
-                gchar * e = s;
-                while (e < end && !g_ascii_isspace(*e))
-                    e++;
-                if (s != e)
-                {
-                    *e = 0;
-                    s = g_filename_from_uri(s, NULL, NULL);
-                    if (s)
-                    {
-                        gchar * tmp = g_strconcat(str, " '", s, "'", NULL);
-                        g_free(str);
-                        g_free(s);
-                        str = tmp;
-                    }
-                }
-                s = e+1;
-            }
+            gchar **uris = gtk_selection_data_get_uris(sd);
+            FmPathList *files = fm_path_list_new_from_uris(uris);
 
-            spawn_command_async(NULL, NULL, str);
-            g_free(str);
+            g_strfreev(uris);
+            fm_launch_desktop_entry_simple(NULL, NULL, b->fi, files);
+            fm_path_list_unref(files);
         }
     }
 }
 
 /* Build the graphic elements for the bootstrap launchbar button. */
-static void launchbutton_build_bootstrap(Plugin * p)
+static void launchbutton_build_bootstrap(LaunchbarPlugin * lb)
 {
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
-
     if (lb->bootstrap_button == NULL)
     {
+        GdkPixbuf * icon;
         /* Build a button that has the stock "Add" icon.
          * The "desktop-id" being NULL is the marker that this is the bootstrap button. */
         lb->bootstrap_button = g_new0(LaunchButton, 1);
-        lb->bootstrap_button->plugin = p;
+        lb->bootstrap_button->p = lb;
 
         /* Create an event box. */
         GtkWidget * event_box = gtk_event_box_new();
@@ -343,8 +231,10 @@ static void launchbutton_build_bootstrap(Plugin * p)
         g_signal_connect(event_box, "button-press-event", G_CALLBACK(launchbutton_press_event), lb->bootstrap_button);
 
         /* Create an image containing the stock "Add" icon as a child of the event box. */
-        lb->bootstrap_button->image_widget = gtk_image_new_from_pixbuf(
-            lxpanel_load_icon(GTK_STOCK_ADD, p->panel->icon_size, p->panel->icon_size, FALSE));
+        lb->add_icon = fm_icon_from_name(GTK_STOCK_ADD);
+        icon = fm_pixbuf_from_icon(lb->add_icon, panel_get_icon_size(lb->panel));
+        lb->bootstrap_button->image_widget = gtk_image_new_from_pixbuf(icon);
+        g_object_unref(icon);
         gtk_misc_set_padding(GTK_MISC(lb->bootstrap_button->image_widget), 0, 0);
         gtk_misc_set_alignment(GTK_MISC(lb->bootstrap_button->image_widget), 0, 0);
         gtk_container_add(GTK_CONTAINER(event_box), lb->bootstrap_button->image_widget);
@@ -356,75 +246,46 @@ static void launchbutton_build_bootstrap(Plugin * p)
         icon_grid_set_visible(lb->icon_grid, lb->bootstrap_button->widget, TRUE);
 }
 
-static gboolean load_app_key_file(gchar *filepath, GKeyFile *p_gkeyfile)
+/* Build the graphic elements for a launchbar button.  The desktop_id field is already established. */
+static LaunchButton *launchbutton_build_gui(LaunchbarPlugin * lb, FmPath * id)
 {
-    gboolean loaded;
-    if (g_path_is_absolute(filepath))
+    /* Try to get the file data */
+    FmFileInfoJob *job = fm_file_info_job_new(NULL, FM_FILE_INFO_JOB_NONE);
+    FmFileInfo *fi;
+    LaunchButton *btn;
+    GtkWidget *button;
+
+    fm_file_info_job_add(job, id);
+    if (!fm_job_run_sync(FM_JOB(job)))
     {
-        loaded = g_key_file_load_from_file(p_gkeyfile, filepath, G_KEY_FILE_NONE, NULL );
+        g_warning("launchbar: problem running file info job\n");
+        g_object_unref(job);
+        return NULL;
     }
-    else
+    fi = fm_file_info_list_pop_head(job->file_infos);
+    g_object_unref(job);
+    if (fi == NULL)
     {
-        /* Load from the freedesktop.org specified data directories. */
-        gchar * full_id = g_strconcat("applications/", filepath, NULL);
-        loaded = g_key_file_load_from_data_dirs(
-            p_gkeyfile, full_id, &filepath, G_KEY_FILE_NONE, NULL);
-        g_free(full_id);
+        g_warning("launchbar: desktop entry does not exist\n");
+        return NULL;
     }
-    return loaded;
-}
-
-
-/* Build the graphic elements for a launchbar button.  The desktop_id field is already established. */
-static void launchbutton_build_gui(Plugin * p, LaunchButton * btn)
-{
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
 
-    if (btn->desktop_id != NULL)
-    {
-        /* There is a valid desktop file name.  Try to open it. */
-        GKeyFile * desktop = g_key_file_new();
-        gboolean loaded = load_app_key_file(btn->desktop_id, desktop);
-
-        if (loaded)
-        {
-            /* Desktop file located.  Get Icon, Name, Exec, and Terminal parameters. */
-            gchar * icon = g_key_file_get_string(desktop, DESKTOP_ENTRY, "Icon", NULL);
-            gchar * title = g_key_file_get_locale_string(desktop, DESKTOP_ENTRY, "Name", NULL, NULL);
-            if ((btn->image == NULL) && (icon != NULL))
-                btn->image = icon;
-
-            if ( ! btn->customize_action )
-            {
-                gchar * exec = g_key_file_get_string(desktop, DESKTOP_ENTRY, "Exec", NULL);
-                btn->action = translate_exec_to_cmd(exec, icon, title, btn->desktop_id);
-                g_free(exec);
-            }
-
-            btn->use_terminal = g_key_file_get_boolean(desktop, DESKTOP_ENTRY, "Terminal", NULL);
-
-            if ( ! btn->customize_tooltip)
-                btn->tooltip = title;
-            if (btn->image != icon)
-                g_free(icon);
-            if (btn->tooltip != title)
-                g_free(title);
-        }
-
-        g_key_file_free(desktop);
-    }
+    /* Allocate the LaunchButton structure. */
+    btn = g_new0(LaunchButton, 1);
+    btn->p = lb;
+    btn->fi = fi;
 
     /* Create a button with the specified icon. */
-    GtkWidget * button = fb_button_new_from_file(btn->image, p->panel->icon_size, p->panel->icon_size, PANEL_ICON_HIGHLIGHT, TRUE);
+    button = lxpanel_button_new_for_fm_icon(lb->panel, fm_file_info_get_icon(fi),
+                                            NULL, NULL);
     btn->widget = button;
 #if GLIB_CHECK_VERSION(2,18,0)
      gtk_widget_set_can_focus(button, FALSE);
 #else
      GTK_WIDGET_UNSET_FLAGS(button, GTK_CAN_FOCUS);
 #endif
-    
-    if (btn->tooltip != NULL)
-        gtk_widget_set_tooltip_text(button, btn->tooltip);
+
+    gtk_widget_set_tooltip_text(button, fm_file_info_get_disp_name(fi));
 
     /* Add the button to the icon grid. */
     icon_grid_add(lb->icon_grid, button, TRUE);
@@ -448,76 +309,32 @@ static void launchbutton_build_gui(Plugin * p, LaunchButton * btn)
 
     /* Show the widget and return. */
     gtk_widget_show(button);
-    plugin_widget_set_background(button, p->panel);
+    plugin_widget_set_background(button, lb->panel);
+    return btn;
 }
 
 /* Read the configuration file entry for a launchbar button and create it. */
-static int launchbutton_constructor(Plugin * p, char ** fp)
+static gboolean launchbutton_constructor(LaunchbarPlugin * lb, config_setting_t * s)
 {
-    /* Allocate the LaunchButton structure. */
-    LaunchButton * btn = g_new0(LaunchButton, 1);
-    btn->plugin = p;
+    LaunchButton *btn;
+    const char *str;
+    FmPath *path;
 
-    /* Read parameters from the configuration file. */
-    line s;
-    s.len = 256;
-    if (fp != NULL)
-    {
-        while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END)
-        {
-            if (s.type == LINE_NONE)
-            {
-                ERR( "launchbar: illegal token %s\n", s.str);
-                launchbutton_free(btn);
-                return 0;
-            }
-            if (s.type == LINE_VAR)
-            {
-                if (g_ascii_strcasecmp(s.t[0], "id") == 0)
-                    btn->desktop_id = g_strdup(s.t[1]);
-                else if (g_ascii_strcasecmp(s.t[0], "image") == 0)
-                {
-                    btn->customize_image = TRUE;
-                    btn->image = expand_tilda(g_strdup(s.t[1]));
-                }
-                else if (g_ascii_strcasecmp(s.t[0], "tooltip") == 0)
-                {
-                    btn->customize_tooltip = TRUE;
-                    btn->tooltip = g_strdup(s.t[1]);
-                }
-                else if (g_ascii_strcasecmp(s.t[0], "path") == 0)
-                {
-                    btn->customize_path = TRUE;
-                    btn->path = g_strdup(s.t[1]);
-                }
-                else if (g_ascii_strcasecmp(s.t[0], "action") == 0)
-                {
-                    btn->customize_action = TRUE;
-                    btn->action = g_strdup(s.t[1]);
-                }
-                else if (g_ascii_strcasecmp(s.t[0], "terminal") == 0)
-                {
-                    btn->use_terminal = str2num(bool_pair, s.t[1], 0);
-                }
-                else
-                    ERR( "launchbar: unknown var %s\n", s.t[0]);
-            }
-            else
-            {
-                ERR( "launchbar: illegal in this context %s\n", s.str);
-                launchbutton_free(btn);
-                return 0;
-            }
-        }
-    }
+    /* Read parameters from the configuration file and validate. */
+    if (!config_setting_lookup_string(s, "id", &str) || str[0] == '\0')
+        return FALSE;
 
     /* Build the structures and return. */
-    launchbutton_build_gui(p, btn);
-    return 1;
+    path = fm_path_new_for_str(str);
+    btn = launchbutton_build_gui(lb, path);
+    fm_path_unref(path);
+    if (btn)
+        btn->settings = s;
+    return (btn != NULL);
 }
 
 /* Plugin constructor. */
-static int launchbar_constructor(Plugin * p, char ** fp)
+static GtkWidget *launchbar_constructor(Panel *panel, config_setting_t *settings)
 {
     static gchar * launchbar_rc = "style 'launchbar-style'\n"
         "{\n"
@@ -527,71 +344,68 @@ static int launchbar_constructor(Plugin * p, char ** fp)
         "GtkButton::default-outside-border = { 0, 0, 0, 0 }\n"
         "}\n"
         "widget '*launchbar*' style 'launchbar-style'";
+    GtkWidget *p;
+    LaunchbarPlugin * lb;
+    config_setting_t *s;
+    GtkOrientation bo;
 
     gtk_rc_parse_string(launchbar_rc);
 
     /* Allocate plugin context and set into Plugin private data pointer. */
-    LaunchbarPlugin * lb = g_new0(LaunchbarPlugin, 1);
-    p->priv = lb;
+    lb = g_new0(LaunchbarPlugin, 1);
+
+    /* Save construction pointers */
+    lb->panel = panel;
+    lb->settings = settings;
 
     /* Allocate top level widget and set into Plugin widget pointer. */
-    p->pwid = gtk_event_box_new();
+    lb->plugin = p = gtk_event_box_new();
+    lxpanel_plugin_set_data(p, lb, launchbar_destructor);
 #if GLIB_CHECK_VERSION(2,18,0)
-    gtk_widget_set_has_window(p->pwid, FALSE);
+    gtk_widget_set_has_window(p, FALSE);
 #else
-    GTK_WIDGET_SET_FLAGS(p->pwid, GTK_NO_WINDOW);
+    GTK_WIDGET_SET_FLAGS(p, GTK_NO_WINDOW);
 #endif
-    gtk_widget_set_name(p->pwid, "launchbar");
+    gtk_widget_set_name(p, "launchbar");
 
     /* Allocate an icon grid manager to manage the container. */
-    GtkOrientation bo = (p->panel->orientation == ORIENT_HORIZ) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
-    lb->icon_grid = icon_grid_new(p->panel, p->pwid, bo, p->panel->icon_size, p->panel->icon_size, 3, 0, p->panel->height);
+    lb->icon_grid = icon_grid_new(panel, p, panel_get_orientation(panel),
+                                  panel_get_icon_size(panel),
+                                  panel_get_icon_size(panel), 3, 0, panel_get_height(panel));
 
     /* Read parameters from the configuration file. */
-    if (fp != NULL)
+    settings = config_setting_get_member(settings, "");
+    if (settings && config_setting_is_list(settings))
     {
-        line s;
-        s.len = 256;
-        while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END)
+        guint i;
+
+        for (i = 0; (s = config_setting_get_elem(settings, i)) != NULL; )
         {
-            if (s.type == LINE_NONE)
+            if (strcmp(config_setting_get_name(s), "Button") != 0)
             {
-                ERR( "launchbar: illegal token %s\n", s.str);
-                return FALSE;
+                g_warning("launchbar: illegal token %s\n", config_setting_get_name(s));
+                config_setting_destroy(s);
             }
-            if (s.type == LINE_BLOCK_START)
+            else if (!launchbutton_constructor(lb, s))
             {
-                if (g_ascii_strcasecmp(s.t[0], "button") == 0)
-                {
-                    if ( ! launchbutton_constructor(p, fp))
-                    {
-                        ERR( "launchbar: can't init button\n");
-                        return FALSE;
-                    }
-                }
-                else
-                {
-                    ERR( "launchbar: unknown var %s\n", s.t[0]);
-                    return FALSE;
-                }
-            }
-        else
-            {
-                ERR( "launchbar: illegal in this context %s\n", s.str);
-                return FALSE;
+                g_warning( "launchbar: can't init button\n");
+                /* FIXME: show failed id to the user instead */
+                config_setting_destroy(s);
             }
+            else /* success, accept the setting */
+                i++;
         }
     }
 
     if (lb->buttons == NULL)
-        launchbutton_build_bootstrap(p);
-    return TRUE;
+        launchbutton_build_bootstrap(lb);
+    return p;
 }
 
 /* Plugin destructor. */
-static void launchbar_destructor(Plugin * p)
+static void launchbar_destructor(gpointer user_data)
 {
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
+    LaunchbarPlugin * lb = (LaunchbarPlugin *)user_data;
 
     /* Free the launchbar. */
     g_slist_foreach(lb->buttons, (GFunc) launchbutton_free, NULL);
@@ -599,55 +413,57 @@ static void launchbar_destructor(Plugin * p)
 
     /* Free the bootstrap button if it exists. */
     if (lb->bootstrap_button != NULL)
-        g_free(lb->bootstrap_button);
+        launchbutton_free(lb->bootstrap_button);
 
     /* Ensure that the configuration dialog is dismissed. */
     if (lb->config_dlg != NULL)
         gtk_widget_destroy(lb->config_dlg);
 
+    if (lb->add_icon != NULL)
+        g_object_unref(lb->add_icon);
+
     /* Deallocate all memory. */
     g_free(lb);
 }
 
 /* Handler for "clicked" action on launchbar configuration dialog "Add" button. */
-static void launchbar_configure_add_button(GtkButton * widget, Plugin * p)
+static void launchbar_configure_add_button(GtkButton * widget, LaunchbarPlugin * lb)
 {
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
     GtkTreeView * menu_view = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(lb->config_dlg), "menu_view"));
     GtkTreeView * defined_view = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(lb->config_dlg), "defined_view"));
-    GtkTreeModel * list;
-    GtkTreeIter it;
-    if (gtk_tree_selection_get_selected(gtk_tree_view_get_selection(menu_view), &list, &it))
+    FmPath * sel_path = fm_app_menu_view_dup_selected_app_desktop_path(menu_view);
+    LaunchButton * btn;
+
+    if (sel_path != NULL && (btn = launchbutton_build_gui(lb, sel_path)) != NULL)
     {
-        LaunchButton * btn;
-        gtk_tree_model_get(list, &it, COL_BTN, &btn, -1);
-        if( btn == NULL )
-            return;
-
-        /* We have located a selected button.
-         * Add a launch button to the launchbar and refresh the view in the configuration dialog. */
-        LaunchButton * defined_button = g_new0(LaunchButton, 1);
-        defined_button->plugin = p;
-        defined_button->desktop_id = g_strdup(btn->desktop_id);
-        launchbutton_build_gui(p, defined_button);
         GtkListStore * list = GTK_LIST_STORE(gtk_tree_view_get_model(defined_view));
         GtkTreeIter it;
         GdkPixbuf* pix;
+        char *path;
         gtk_list_store_append(list, &it);
-        pix = lxpanel_load_icon(btn->image, PANEL_ICON_SIZE, PANEL_ICON_SIZE, TRUE);
+        pix = fm_pixbuf_from_icon(fm_file_info_get_icon(btn->fi), PANEL_ICON_SIZE);
         gtk_list_store_set(list, &it,
             COL_ICON, pix,
-            COL_TITLE, ((btn->tooltip != NULL) ? btn->tooltip : btn->action),
-            COL_BTN, defined_button,
+            COL_TITLE, fm_file_info_get_disp_name(btn->fi),
+            COL_BTN, btn,
             -1);
         g_object_unref(pix);
+        path = fm_path_to_str(sel_path);
+        /* g_debug("*** path '%s'",path); */
+        btn->settings = config_setting_add(config_setting_add(lb->settings, "",
+                                                              PANEL_CONF_TYPE_LIST),
+                                           "Button", PANEL_CONF_TYPE_GROUP);
+        config_setting_set_string(config_setting_add(btn->settings, "id",
+                                                     PANEL_CONF_TYPE_STRING),
+                                  path);
+        g_free(path);
+        fm_path_unref(sel_path);
     }
 }
 
 /* Handler for "clicked" action on launchbar configuration dialog "Remove" button. */
-static void launchbar_configure_remove_button(GtkButton * widget, Plugin * p)
+static void launchbar_configure_remove_button(GtkButton * widget, LaunchbarPlugin * lb)
 {
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
     GtkTreeView * defined_view = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(lb->config_dlg), "defined_view"));
     GtkTreeModel * list;
     GtkTreeIter it;
@@ -661,21 +477,19 @@ static void launchbar_configure_remove_button(GtkButton * widget, Plugin * p)
         gtk_list_store_remove(GTK_LIST_STORE(list), &it);
         icon_grid_remove(lb->icon_grid, btn->widget);
         lb->buttons = g_slist_remove(lb->buttons, btn);
+        config_setting_destroy(btn->settings);
         launchbutton_free(btn);
-        
         gtk_widget_set_visible(lb->p_label_def_app_exec, FALSE);
 
         /* Put the bootstrap button back if the list becomes empty. */
         if (lb->buttons == NULL)
-            launchbutton_build_bootstrap(p);
+            launchbutton_build_bootstrap(lb);
     }
 }
 
 /* Handler for "clicked" action on launchbar configuration dialog "Move Up" button. */
-static void launchbar_configure_move_up_button(GtkButton * widget, Plugin * p)
+static void launchbar_configure_move_up_button(GtkButton * widget, LaunchbarPlugin * lb)
 {
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
-
     GtkTreeView * defined_view = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(lb->config_dlg), "defined_view"));
     GtkTreeModel * list;
     GtkTreeIter it;
@@ -697,6 +511,9 @@ static void launchbar_configure_move_up_button(GtkButton * widget, Plugin * p)
                 lb->buttons = g_slist_insert(lb->buttons, btn, i);
                 gtk_list_store_move_before(GTK_LIST_STORE(list), &it, &it2);
                 icon_grid_reorder_child(lb->icon_grid, btn->widget, i);
+                config_setting_move_elem(btn->settings,
+                                         config_setting_get_member(lb->settings, ""),
+                                         i);
             }
         }
         gtk_tree_path_free(path);
@@ -704,10 +521,8 @@ static void launchbar_configure_move_up_button(GtkButton * widget, Plugin * p)
 }
 
 /* Handler for "clicked" action on launchbar configuration dialog "Move Down" button. */
-static void launchbar_configure_move_down_button(GtkButton * widget, Plugin * p)
+static void launchbar_configure_move_down_button(GtkButton * widget, LaunchbarPlugin * lb)
 {
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
-
     GtkTreeView * defined_view = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(lb->config_dlg), "defined_view"));
     GtkTreeModel * list;
     GtkTreeIter it;
@@ -730,153 +545,26 @@ static void launchbar_configure_move_down_button(GtkButton * widget, Plugin * p)
                 lb->buttons = g_slist_insert(lb->buttons, btn, i + 1);
                 gtk_list_store_move_after(GTK_LIST_STORE(list), &it, &it2);
                 icon_grid_reorder_child( lb->icon_grid, btn->widget, i);
+                config_setting_move_elem(btn->settings,
+                                         config_setting_get_member(lb->settings, ""),
+                                         i);
             }
         }
         gtk_tree_path_free(path);
     }
 }
 
-static void launchbar_configure_free_btns_in_model(GtkTreeModel* model, GtkTreeIter *parent_it)
-{
-    GtkTreeIter it;
-    if (gtk_tree_model_iter_children(model, &it, parent_it))
-    {
-        do
-        {
-            LaunchButton * btn;
-            gtk_tree_model_get(model, &it, COL_BTN, &btn, -1);
-            if(G_LIKELY(btn))
-                launchbutton_free(btn);
-            if( gtk_tree_model_iter_has_child(model, &it) )
-                launchbar_configure_free_btns_in_model(model, &it);
-        }
-        while (gtk_tree_model_iter_next(model, &it));
-    }
-}
-
 /* Handler for "response" signal from launchbar configuration dialog. */
-static void launchbar_configure_response(GtkDialog * dlg, int response, Plugin * p)
+static void launchbar_configure_response(GtkDialog * dlg, int response, LaunchbarPlugin * lb)
 {
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
-
-    /* Deallocate LaunchButtons that were loaded from the menu. */
-    GtkTreeView * menu_view = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(lb->config_dlg), "menu_view"));
-    GtkTreeModel * model = gtk_tree_view_get_model(menu_view);
-    launchbar_configure_free_btns_in_model(model, NULL);
-
     /* Deallocate the configuration dialog. */
     lb->config_dlg = NULL;
     gtk_widget_destroy(GTK_WIDGET(dlg));
 }
 
-static void launchbar_configure_update_icons(GtkTreeStore* tree, GtkTreeIter* parent_it)
-{
-    GtkTreeIter it;
-    if(gtk_tree_model_iter_children(GTK_TREE_MODEL(tree), &it, parent_it))
-    {
-        do
-        {
-            char* name;
-            GdkPixbuf* pix;
-            gtk_tree_model_get(GTK_TREE_MODEL(tree), &it, COL_ICON, &pix, -1);
-            if(!pix)
-            {
-              gtk_tree_model_get(GTK_TREE_MODEL(tree), &it, COL_ICON_NAME, &name, -1);
-              pix = lxpanel_load_icon(name, PANEL_ICON_SIZE, PANEL_ICON_SIZE, TRUE);
-              gtk_tree_store_set(tree, &it, COL_ICON, pix, -1);
-              g_free(name);
-            }
-            if(pix)
-                g_object_unref(pix);
-        }while(gtk_tree_model_iter_next(GTK_TREE_MODEL(tree), &it));
-    }
-}
-
-static void on_app_tree_row_expanded(GtkTreeView* view, GtkTreeIter* it, GtkTreePath* tp, gpointer user_data)
-{
-    launchbar_configure_update_icons((GtkTreeStore*)user_data, it);
-}
-
-static void launchbar_configure_add_menu_recursive(GtkTreeStore * tree, GtkTreeIter* parent_it, MenuCacheDir * menu_dir)
-{
-    /* Iterate over all menu items in this directory. */
-    GSList * l;
-    for (l = menu_cache_dir_get_children(menu_dir); l != NULL; l = l->next)
-    {
-        /* Get the next menu item. */
-        MenuCacheItem * item = MENU_CACHE_ITEM(l->data);
-        switch (menu_cache_item_get_type(item))
-        {
-            case MENU_CACHE_TYPE_NONE:
-            case MENU_CACHE_TYPE_SEP:
-                break;
-
-            case MENU_CACHE_TYPE_APP:
-                {
-                /* If an application, build a LaunchButton data structure so we can identify
-                 * the button in the handler.  In this application, the desktop_id is the
-                 * fully qualified desktop file path.  The image and tooltip are what is displayed in the view. */
-                LaunchButton * btn = g_new0(LaunchButton, 1);
-                btn->desktop_id = menu_cache_item_get_file_path(item);
-                btn->image = g_strdup(menu_cache_item_get_icon(item));
-                btn->tooltip = g_strdup(menu_cache_item_get_name(item));
-                btn->path = g_strdup(menu_cache_app_get_working_dir(MENU_CACHE_APP(item)));
-
-                GKeyFile * desktop = g_key_file_new();
-                gboolean loaded = load_app_key_file(btn->desktop_id, desktop);
-                btn->action = loaded ? g_key_file_get_string(desktop, DESKTOP_ENTRY, "Exec", NULL) : NULL;
-
-                /* Add the row to the view. */
-                GtkTreeIter it;
-                gtk_tree_store_append(tree, &it, parent_it);
-                gtk_tree_store_set(tree, &it,
-                    COL_ICON_NAME, menu_cache_item_get_icon(item),
-                    COL_TITLE, menu_cache_item_get_name(item),
-                    COL_BTN, btn,
-                    -1);
-                }
-                break;
-
-            case MENU_CACHE_TYPE_DIR:
-                {
-                GtkTreeIter it;
-                gtk_tree_store_append(tree, &it, parent_it);
-                gtk_tree_store_set(tree, &it,
-                    COL_ICON_NAME, menu_cache_item_get_icon(item),
-                    COL_TITLE, menu_cache_item_get_name(item),
-                    -1);
-                /* If a directory, recursively add its menu items. */
-                launchbar_configure_add_menu_recursive(tree, &it, MENU_CACHE_DIR(item));
-                }
-                break;
-        }
-    }
-    if(!parent_it)
-        launchbar_configure_update_icons(tree, parent_it);
-}
-
-static void destroy_menu_cache(gpointer* param, GObject* tree)
-{
-    MenuCache* mc = (MenuCache*)param[0];
-    gpointer id = param[1];
-    menu_cache_remove_reload_notify(mc, id);
-    menu_cache_unref(mc);
-    g_slice_free1(sizeof(gpointer) * 2, param);
-}
-
-static void on_menu_cache_reload(MenuCache* menu_cache, gpointer tree)
-{
-    MenuCacheDir * dir = menu_cache_get_root_dir(menu_cache);
-    gtk_tree_store_clear(tree);
-    if(dir)
-        launchbar_configure_add_menu_recursive(tree, NULL, dir);
-}
-
 /* Initialize the list of existing launchbar buttons when the configuration dialog is shown. */
-static void launchbar_configure_initialize_list(Plugin * p, GtkWidget * dlg, GtkTreeView * view, gboolean from_menu)
+static void launchbar_configure_initialize_list(LaunchbarPlugin * lb, GtkWidget * dlg, GtkTreeView * view)
 {
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
-
     /* Set the selection mode. */
     gtk_tree_selection_set_mode(gtk_tree_view_get_selection(view), GTK_SELECTION_BROWSE);
 
@@ -893,58 +581,36 @@ static void launchbar_configure_initialize_list(Plugin * p, GtkWidget * dlg, Gtk
     gtk_tree_view_column_pack_start(col, render, TRUE);
     gtk_tree_view_column_add_attribute(col, render, "text", COL_TITLE);
 
-    if (from_menu)
-    {
-        GtkTreeStore* tree = GTK_TREE_STORE(gtk_tree_view_get_model(view));
-        /* Initialize from all menu items. */
-        guint32 flags;
-        MenuCache *menu_cache = panel_menu_cache_new(&flags);
-
-        g_signal_connect(view, "row-expanded", G_CALLBACK(on_app_tree_row_expanded), tree);
+    /* Establish the column data types. */
+    GtkListStore* list = GTK_LIST_STORE(gtk_tree_view_get_model(view));
 
-        if (menu_cache != NULL)
-        {
-            MenuCacheDir * dir = menu_cache_get_root_dir(menu_cache);
-            gpointer id = menu_cache_add_reload_notify(menu_cache, on_menu_cache_reload, tree);
-            gpointer *param = g_slice_alloc(sizeof(gpointer) * 2);
-            if(dir)
-                launchbar_configure_add_menu_recursive(tree, NULL, dir);
-            param[0] = menu_cache;
-            param[1] = id;
-            g_object_weak_ref(G_OBJECT(tree), (GWeakNotify)destroy_menu_cache, param);
-        }
-        g_object_set_data(G_OBJECT(dlg), "menu_view", view);
-    }
-    else
+    /* Initialize from defined launchbar buttons. */
+    GSList* l;
+    for (l = lb->buttons; l != NULL; l = l->next)
     {
-        /* Establish the column data types. */
-        GtkListStore* list = GTK_LIST_STORE(gtk_tree_view_get_model(view));
-
-        /* Initialize from defined launchbar buttons. */
-        GSList* l;
-        for (l = lb->buttons; l != NULL; l = l->next)
-        {
-            LaunchButton * btn = (LaunchButton *) l->data;
-            GtkTreeIter it;
-            gtk_list_store_append(list, &it);
-            gtk_list_store_set(list, &it,
-                COL_ICON, lxpanel_load_icon(btn->image, PANEL_ICON_SIZE, PANEL_ICON_SIZE, TRUE),
-                COL_TITLE, ((btn->tooltip != NULL) ? btn->tooltip : btn->action),
-                COL_BTN, btn,
-                -1);
-        }
-        g_object_set_data(G_OBJECT(dlg), "defined_view", view);
+        LaunchButton * btn = (LaunchButton *) l->data;
+        GdkPixbuf * pix;
+        GtkTreeIter it;
+        gtk_list_store_append(list, &it);
+        pix = fm_pixbuf_from_icon(fm_file_info_get_icon(btn->fi), PANEL_ICON_SIZE);
+        gtk_list_store_set(list, &it,
+            COL_ICON, pix,
+            COL_TITLE, fm_file_info_get_disp_name(btn->fi),
+            COL_BTN, btn,
+            -1);
+        g_object_unref(pix);
     }
+    g_object_set_data(G_OBJECT(dlg), "defined_view", view);
 }
 
 /* Callback when the configuration dialog is to be shown. */
-static void launchbar_configure(Plugin * p, GtkWindow * parent)
+static void launchbar_configure(Panel *panel, GtkWidget *p, GtkWindow *parent)
 {
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
+    LaunchbarPlugin * lb = lxpanel_plugin_get_data(p);
 
     if (lb->config_dlg == NULL)
     {
-        GtkWidget *dlg, *btn, *defined_view, *menu_view;
+        GtkWidget *dlg, *btn, *defined_view, *menu_view, *menu_view_window;
         GtkBuilder *builder = gtk_builder_new();
 
         gtk_builder_add_from_file(builder, PACKAGE_UI_DIR "/launchbar.ui", NULL);
@@ -952,108 +618,90 @@ static void launchbar_configure(Plugin * p, GtkWindow * parent)
         panel_apply_icon(GTK_WINDOW(dlg));
 
         defined_view = (GtkWidget*)gtk_builder_get_object(builder, "defined_view");
-        menu_view = (GtkWidget*)gtk_builder_get_object(builder, "menu_view");
+        menu_view_window = (GtkWidget*)gtk_builder_get_object(builder, "menu_view_window");
+        if (menu_view_window == NULL) /* fallback for old glade file */
+        {
+            menu_view_window = (GtkWidget*)gtk_builder_get_object(builder, "scroll2");
+            gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(menu_view_window)));
+        }
+        menu_view = GTK_WIDGET(fm_app_menu_view_new());
+        gtk_container_add(GTK_CONTAINER(menu_view_window), menu_view);
+        gtk_widget_show(menu_view);
         lb->p_label_def_app_exec = (GtkWidget*)gtk_builder_get_object(builder, "label_def_app_exec");
         lb->p_label_menu_app_exec = (GtkWidget*)gtk_builder_get_object(builder, "label_menu_app_exec");
 
         /* Connect signals. */
-        g_signal_connect(dlg, "response", G_CALLBACK(launchbar_configure_response), p);
+        g_signal_connect(dlg, "response", G_CALLBACK(launchbar_configure_response), lb);
 
         lb->p_button_add = (GtkWidget*)gtk_builder_get_object(builder, "add");
-        g_signal_connect(lb->p_button_add, "clicked", G_CALLBACK(launchbar_configure_add_button), p);
+        g_signal_connect(lb->p_button_add, "clicked", G_CALLBACK(launchbar_configure_add_button), lb);
 
         lb->p_button_remove = (GtkWidget*)gtk_builder_get_object(builder, "remove");
-        g_signal_connect(lb->p_button_remove, "clicked", G_CALLBACK(launchbar_configure_remove_button), p);
+        g_signal_connect(lb->p_button_remove, "clicked", G_CALLBACK(launchbar_configure_remove_button), lb);
 
         btn = (GtkWidget*)gtk_builder_get_object(builder, "up");
-        g_signal_connect(btn, "clicked", G_CALLBACK(launchbar_configure_move_up_button), p);
+        g_signal_connect(btn, "clicked", G_CALLBACK(launchbar_configure_move_up_button), lb);
 
         btn = (GtkWidget*)gtk_builder_get_object(builder, "down");
-        g_signal_connect(btn, "clicked", G_CALLBACK(launchbar_configure_move_down_button), p);
+        g_signal_connect(btn, "clicked", G_CALLBACK(launchbar_configure_move_down_button), lb);
 
         g_signal_connect(defined_view, "button-press-event", G_CALLBACK(on_defined_view_button_press_event), lb);
         g_signal_connect(defined_view, "cursor-changed", G_CALLBACK(on_defined_view_cursor_changed), lb);
-        g_signal_connect(menu_view, "button-press-event", G_CALLBACK(on_menu_view_button_press_event), lb);
         g_signal_connect(menu_view, "cursor-changed", G_CALLBACK(on_menu_view_cursor_changed), lb);
 
         gtk_window_present(GTK_WINDOW(dlg));
         lb->config_dlg = dlg;
 
         /* Establish a callback when the dialog completes. */
-        g_object_weak_ref(G_OBJECT(dlg), (GWeakNotify) panel_config_save, p->panel);
+        g_object_weak_ref(G_OBJECT(dlg), (GWeakNotify) panel_config_save, panel);
 
         /* Initialize the tree view contents. */
-        launchbar_configure_initialize_list(p, dlg, GTK_TREE_VIEW(defined_view), FALSE);
-        launchbar_configure_initialize_list(p, dlg, GTK_TREE_VIEW(menu_view), TRUE);
+        launchbar_configure_initialize_list(lb, dlg, GTK_TREE_VIEW(defined_view));
+        g_object_set_data(G_OBJECT(dlg), "menu_view", menu_view);
 
         gtk_widget_set_visible(lb->p_label_menu_app_exec, FALSE);
         gtk_widget_set_visible(lb->p_label_def_app_exec, FALSE);
+        gtk_widget_set_sensitive(lb->p_button_add, FALSE);
+        gtk_widget_set_sensitive(lb->p_button_remove, FALSE);
 
         g_object_unref(builder);
         return;
     }
 }
 
-/* Callback when the configuration is to be saved. */
-static void launchbar_save_configuration(Plugin * p, FILE * fp)
-{
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
-    GSList * l;
-    for (l = lb->buttons; l != NULL; l = l->next)
-    {
-        LaunchButton * btn = (LaunchButton *) l->data;
-        lxpanel_put_line(fp, "Button {");
-        if (btn->desktop_id != NULL)
-            lxpanel_put_str(fp, "id", btn->desktop_id);
-        if (btn->customize_image)
-            lxpanel_put_str(fp, "image", btn->image);
-        if(btn->customize_tooltip)
-            lxpanel_put_str(fp, "tooltip", btn->tooltip);
-        if(btn->customize_path)
-            lxpanel_put_str(fp, "path", btn->path);
-        if (btn->customize_action)
-            lxpanel_put_str(fp, "action", btn->action);
-        if (btn->use_terminal)
-            lxpanel_put_bool(fp, "terminal", TRUE);
-        lxpanel_put_line(fp, "}");
-    }
-}
-
 /* Callback when panel configuration changes. */
-static void launchbar_panel_configuration_changed(Plugin * p)
+static void launchbar_panel_configuration_changed(Panel *panel, GtkWidget *p)
 {
     /* Set orientation into the icon grid. */
-    LaunchbarPlugin * lb = (LaunchbarPlugin *) p->priv;
-    GtkOrientation bo = (p->panel->orientation == ORIENT_HORIZ) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
-    icon_grid_set_geometry(lb->icon_grid, bo, p->panel->icon_size, p->panel->icon_size, 3, 0, p->panel->height);
+    LaunchbarPlugin * lb = lxpanel_plugin_get_data(p);
+    icon_grid_set_geometry(lb->icon_grid, panel_get_orientation(panel),
+                           panel_get_icon_size(panel), panel_get_icon_size(panel),
+                           3, 0, panel_get_height(panel));
 
     /* Reset all the images to resize them. */
     GSList * l;
     for (l = lb->buttons; l != NULL; l = l->next)
     {
         LaunchButton * btn = (LaunchButton *) l->data;
-        fb_button_set_from_file(btn->widget, btn->image, p->panel->icon_size, p->panel->icon_size, TRUE);
+        lxpanel_button_update_icon(btn->widget, fm_file_info_get_icon(btn->fi),
+                                   panel_get_icon_size(panel));
     }
 
     /* Reset the bootstrap button. */
     if (lb->bootstrap_button != NULL)
-        gtk_image_set_from_pixbuf(GTK_IMAGE(lb->bootstrap_button->image_widget),
-            lxpanel_load_icon(GTK_STOCK_ADD, p->panel->icon_size, p->panel->icon_size, FALSE));
+    {
+        GdkPixbuf * icon = fm_pixbuf_from_icon(lb->add_icon, panel_get_icon_size(panel));
+        gtk_image_set_from_pixbuf(GTK_IMAGE(lb->bootstrap_button->image_widget), icon);
+        g_object_unref(icon);
+    }
 }
 
 /* Plugin descriptor. */
-PluginClass launchbar_plugin_class = {
-
-    PLUGINCLASS_VERSIONING,
-
-    .type = "launchbar",
+LXPanelPluginInit lxpanel_static_plugin_launchbar = {
     .name = N_("Application Launch Bar"),
-    .version = "2.0",
     .description = N_("Bar with buttons to launch application"),
 
-    .constructor = launchbar_constructor,
-    .destructor  = launchbar_destructor,
+    .new_instance = launchbar_constructor,
     .config = launchbar_configure,
-    .save = launchbar_save_configuration,
-    .panel_configuration_changed = launchbar_panel_configuration_changed
+    .reconfigure = launchbar_panel_configuration_changed
 };
index a400435..bbc0ecb 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "panel.h"
 #include "misc.h"
-#include "plugin.h"
+#include "private.h"
 #include "bg.h"
 #include "menu-policy.h"
 
@@ -131,11 +131,7 @@ menu_pos(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, GtkWidget *widget)
 #endif
     ENTER;
     p = g_object_get_data(G_OBJECT(widget), "plugin");
-#if GTK_CHECK_VERSION(2,14,0)
     gdk_window_get_origin(gtk_widget_get_window(widget), &ox, &oy);
-#else
-    gdk_window_get_origin(widget->window, &ox, &oy);
-#endif
 #if GTK_CHECK_VERSION(2,20,0)
     GtkRequisition requisition;
     gtk_widget_get_requisition(GTK_WIDGET(menu), &requisition);
@@ -146,7 +142,7 @@ menu_pos(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, GtkWidget *widget)
     w = GTK_WIDGET(menu)->requisition.width;
     h = GTK_WIDGET(menu)->requisition.height;
 #endif
-    if (p->panel->orientation == ORIENT_HORIZ) {
+    if (p->panel->orientation == GTK_ORIENTATION_HORIZONTAL) {
         *x = ox;
         if (*x + w > gdk_screen_width())
 #if GTK_CHECK_VERSION(2,18,0)
@@ -400,22 +396,14 @@ static void restore_grabs(GtkWidget *w, gpointer data)
     if (xgrab_shell && (GTK_MENU_SHELL (xgrab_shell)->have_xgrab))
 #endif
      {
-#if GTK_CHECK_VERSION(2,14,0)
         if (gdk_pointer_grab (gtk_widget_get_window(xgrab_shell), TRUE,
-#else
-        if (gdk_pointer_grab (xgrab_shell->window, TRUE,
-#endif
                     GDK_BUTTON_PRESS_MASK |
                     GDK_BUTTON_RELEASE_MASK |
                     GDK_ENTER_NOTIFY_MASK |
                     GDK_LEAVE_NOTIFY_MASK,
                     NULL, NULL, 0) == 0)
         {
-#if GTK_CHECK_VERSION(2,14,0)
             if (gdk_keyboard_grab (gtk_widget_get_window(xgrab_shell), TRUE,
-#else
-            if (gdk_keyboard_grab (xgrab_shell->window, TRUE,
-#endif
                     GDK_CURRENT_TIME) == 0)
 #if GTK_CHECK_VERSION(2,18,0)
                 gtk_widget_grab_focus (xgrab_shell);
@@ -786,6 +774,7 @@ read_item(Plugin *p, char** fp)
     if (fname) {
         GtkWidget *img;
 
+        /* FIXME: use FmIcon cache and fm_pixbuf_from_icon() API */
         img = _gtk_image_new_from_file_scaled(fname, m->iconsize, m->iconsize, TRUE);
         gtk_widget_show(img);
         gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
@@ -966,6 +955,7 @@ read_submenu(Plugin *p, char** fp, gboolean as_item)
         mi = gtk_image_menu_item_new_with_label(name);
         if (fname) {
             GtkWidget *img;
+            /* FIXME: use FmIcon cache and fm_pixbuf_from_icon() API */
             img = _gtk_image_new_from_file_scaled(fname, m->iconsize, m->iconsize, TRUE);
             gtk_widget_show(img);
             gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img);
index a2adbb6..b4661aa 100644 (file)
@@ -68,7 +68,7 @@
 #include <stdlib.h>
 #include <glib/gi18n.h>
 
-#include "plugin.h"
+#include "private.h"
 #include "panel.h"
 #include "misc.h"
 
@@ -610,7 +610,7 @@ monitors_constructor(Plugin *p, char **fp)
     p->pwid = gtk_hbox_new(TRUE, 2);
     gtk_container_set_border_width(GTK_CONTAINER(p->pwid), 1);
     GTK_WIDGET_SET_FLAGS(p->pwid, GTK_NO_WINDOW);
-    g_signal_connect(G_OBJECT(p->pwid), "button_press_event", G_CALLBACK(monitors_button_press_event), (gpointer) p);
+    g_signal_connect(G_OBJECT(p->pwid), "button-press-event", G_CALLBACK(monitors_button_press_event), (gpointer) p);
 
     /* Apply options */
     line s;
index 9bc1d7a..949c228 100644 (file)
@@ -36,7 +36,7 @@
 #include "wireless.h"
 #include "panel.h"
 #include "misc.h"
-#include "plugin.h"
+#include "private.h"
 #include "dbg.h"
 
 /* 1 second */
@@ -385,7 +385,7 @@ static void refresh_systray(netstat *ns, NETDEVLIST_PTR netdev_list)
                 ni->netdev_list = ptr;
 
                 ptr->info.status_icon = create_statusicon(ns->mainw, select_icon(ptr->info.plug, ptr->info.connected, ptr->info.status), tooltip, select_icon_theme(ptr->info.plug, ptr->info.connected, ptr->info.status));
-                g_signal_connect(ptr->info.status_icon->main, "button_press_event", G_CALLBACK(menupopup), ni);
+                g_signal_connect(ptr->info.status_icon->main, "button-press-event", G_CALLBACK(menupopup), ni);
                 g_object_weak_ref(G_OBJECT(ptr->info.status_icon->main), g_free_weaknotify, ni);
             } else {
                 set_statusicon_tooltips(ptr->info.status_icon, tooltip);
index d1a252f..af7eb67 100644 (file)
@@ -385,11 +385,7 @@ netstatus_icon_name_changed (NetstatusIface *iface __attribute__((unused)),
       tip = _("Network Connection");
     }
 
-#if GTK_CHECK_VERSION(2,12,0)
   gtk_widget_set_tooltip_text(GTK_WIDGET (icon), tip);
-#else
-  gtk_tooltips_set_tip (icon->priv->tooltips, GTK_WIDGET (icon), tip, NULL);
-#endif
 
   g_free (freeme);
 }
@@ -615,11 +611,8 @@ netstatus_icon_size_allocate (GtkWidget     *widget,
   GtkAllocation  child_allocation;
   GObjectClass  *klass;
   int            size;
-#if GTK_CHECK_VERSION(2,14,0)
   GdkWindow     *window = gtk_widget_get_window(widget);
   guint border_width = gtk_container_get_border_width(GTK_CONTAINER (widget));
-#else
-#endif
 
   if (icon->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
     size = allocation->height;
@@ -635,32 +628,19 @@ netstatus_icon_size_allocate (GtkWidget     *widget,
 
   if (GTK_WIDGET_REALIZED (widget))
     {
-#if GTK_CHECK_VERSION(2,14,0)
       gdk_window_move_resize (window,
                               allocation->x + border_width,
                               allocation->y + border_width,
                               MAX (allocation->width - border_width * 2, 0),
                                          MAX (allocation->height - border_width * 2, 0));
-#else
-      gdk_window_move_resize (widget->window,
-                              allocation->x + GTK_CONTAINER (widget)->border_width,
-                              allocation->y + GTK_CONTAINER (widget)->border_width,
-                              MAX (allocation->width - GTK_CONTAINER (widget)->border_width * 2, 0),
-                                         MAX (allocation->height - GTK_CONTAINER (widget)->border_width * 2, 0));
-#endif
     }
 
   klass = get_box_class (icon->priv->orientation);
 
   child_allocation.x = 0;
   child_allocation.y = 0;
-#if GTK_CHECK_VERSION(2,14,0)
   child_allocation.width  = MAX (allocation->width  - border_width * 2, 0);
   child_allocation.height = MAX (allocation->height - border_width * 2, 0);
-#else
-  child_allocation.width  = MAX (allocation->width  - GTK_CONTAINER (widget)->border_width * 2, 0);
-  child_allocation.height = MAX (allocation->height - GTK_CONTAINER (widget)->border_width * 2, 0);
-#endif
 
   if (GTK_WIDGET_CLASS (klass)->size_allocate)
     GTK_WIDGET_CLASS (klass)->size_allocate (widget, &child_allocation);
index e7bde94..422df45 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "panel.h"
 #include "misc.h"
-#include "plugin.h"
+#include "private.h"
 
 #include "dbg.h"
 
index 0617f1a..48831f9 100644 (file)
@@ -34,7 +34,7 @@
 
 #include "panel.h"
 #include "misc.h"
-#include "plugin.h"
+#include "private.h"
 #include "icon-grid.h"
 
 #include "dbg.h"
@@ -423,10 +423,10 @@ static void desk_new(PagerPlugin * pg, int desktop_number)
     gtk_widget_add_events (d->da, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
 
     /* Connect signals. */
-    g_signal_connect(G_OBJECT(d->da), "expose_event", G_CALLBACK(desk_expose_event), (gpointer) d);
-    g_signal_connect(G_OBJECT(d->da), "configure_event", G_CALLBACK(desk_configure_event), (gpointer) d);
+    g_signal_connect(G_OBJECT(d->da), "expose-event", G_CALLBACK(desk_expose_event), (gpointer) d);
+    g_signal_connect(G_OBJECT(d->da), "configure-event", G_CALLBACK(desk_configure_event), (gpointer) d);
     g_signal_connect(G_OBJECT(d->da), "scroll-event", G_CALLBACK(desk_scroll_event), (gpointer) d);
-    g_signal_connect(G_OBJECT(d->da), "button_press_event", G_CALLBACK(desk_button_press_event), (gpointer) d);
+    g_signal_connect(G_OBJECT(d->da), "button-press-event", G_CALLBACK(desk_button_press_event), (gpointer) d);
 
     /* Show the widget. */
     gtk_widget_show(d->da);
@@ -768,8 +768,7 @@ static int pager_constructor(Plugin * plug, char ** fp)
     gtk_container_set_border_width(GTK_CONTAINER(plug->pwid), 0);
 
     /* Create an icon grid manager to manage the drawing areas within the container. */
-    GtkOrientation bo = (plug->panel->orientation == ORIENT_HORIZ) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
-    pg->icon_grid = icon_grid_new(plug->panel, plug->pwid, bo,
+    pg->icon_grid = icon_grid_new(plug->panel, plug->pwid, plug->panel->orientation,
         (plug->panel->icon_size - BORDER_WIDTH * 2) * pg->aspect_ratio,
         plug->panel->icon_size - BORDER_WIDTH * 2,
         1, BORDER_WIDTH,
@@ -825,8 +824,7 @@ static void pager_panel_configuration_changed(Plugin * p)
 {
     /* Reset the icon grid orientation. */
     PagerPlugin * pg = (PagerPlugin *) p->priv;
-    GtkOrientation bo = (p->panel->orientation == ORIENT_HORIZ) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL;
-    icon_grid_set_geometry(pg->icon_grid, bo,
+    icon_grid_set_geometry(pg->icon_grid, p->panel->orientation,
         (p->panel->icon_size - BORDER_WIDTH * 2) * pg->aspect_ratio,
         p->panel->icon_size - BORDER_WIDTH * 2,
         1, BORDER_WIDTH,
index 7612ce2..cd7dd53 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
+ * Copyright (c) 2006-2014 LxDE Developers, see the file AUTHORS for details.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include "panel.h"
-#include "misc.h"
 #include "plugin.h"
 
 #include <glib/gi18n.h>
 
-#include "dbg.h"
-
-static int separator_constructor(Plugin * p, char ** fp);
-static void separator_destructor(Plugin * p);
-static void separator_panel_configuration_changed(Plugin * p);
-
 /* Plugin constructor. */
-static int separator_constructor(Plugin * p, char ** fp)
+static GtkWidget *separator_constructor(Panel *panel, config_setting_t *settings)
 {
-    /* Load parameters from the configuration file. */
-    line s;
-    s.len = 256;
-    if (fp != NULL)
-    {
-        while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END)
-        {
-            ERR( "separator: illegal in this context %s\n", s.str);
-            return 0;
-        }
-    }
+    GtkWidget *instance, *sep;
 
     /* Allocate top level widget and set into Plugin widget pointer. */
-    p->pwid = gtk_event_box_new();
+    instance = gtk_event_box_new();
 #if GTK_CHECK_VERSION(2,18,0)
-    gtk_widget_set_has_window(p->pwid, FALSE);
+    gtk_widget_set_has_window(instance, FALSE);
 #else
-    GTK_WIDGET_SET_FLAGS(p->pwid, GTK_NO_WINDOW);
+    GTK_WIDGET_SET_FLAGS(instance, GTK_NO_WINDOW);
 #endif
-    gtk_widget_add_events(p->pwid, GDK_BUTTON_PRESS_MASK);
-    gtk_container_set_border_width(GTK_CONTAINER(p->pwid), 1);
+    gtk_widget_add_events(instance, GDK_BUTTON_PRESS_MASK);
+    gtk_container_set_border_width(GTK_CONTAINER(instance), 1);
 
     /* Allocate separator as a child of top level. */
-    GtkWidget * sep = p->panel->my_separator_new();
-    gtk_container_add(GTK_CONTAINER(p->pwid), sep);
-
-    /* Connect signals. */
-    g_signal_connect(p->pwid, "button-press-event", G_CALLBACK(plugin_button_press_event), p);
+    sep = panel_separator_new(panel);
+    gtk_container_add(GTK_CONTAINER(instance), sep);
+    gtk_widget_show(sep);
 
     /* Show the widget and return. */
-    gtk_widget_show_all(p->pwid);
-    return 1;
-}
-
-/* Plugin destructor. */
-static void separator_destructor(Plugin * p)
-{
+    return instance;
 }
 
 /* Callback when panel configuration changes. */
-static void separator_panel_configuration_changed(Plugin * p)
+static void separator_reconfigure(Panel *panel, GtkWidget *instance)
 {
     /* Determine if the orientation changed in a way that requires action. */
-    GtkWidget * sep = gtk_bin_get_child(GTK_BIN(p->pwid));
+    GtkWidget * sep = gtk_bin_get_child(GTK_BIN(instance));
     if (GTK_IS_VSEPARATOR(sep))
     {
-        if (p->panel->orientation == GTK_ORIENTATION_HORIZONTAL)
+        if (panel_get_orientation(panel) == GTK_ORIENTATION_HORIZONTAL)
             return;
     }
     else
     {
-        if (p->panel->orientation == GTK_ORIENTATION_VERTICAL)
+        if (panel_get_orientation(panel) == GTK_ORIENTATION_VERTICAL)
             return;
     }
 
     /* If the orientation changed, recreate the separator. */
     gtk_widget_destroy(sep);
-    sep = p->panel->my_separator_new();
+    sep = panel_separator_new(panel);
     gtk_widget_show(sep);
-    gtk_container_add(GTK_CONTAINER(p->pwid), sep);
+    gtk_container_add(GTK_CONTAINER(instance), sep);
 }
 
 /* Plugin descriptor. */
-PluginClass separator_plugin_class = {
-
-    PLUGINCLASS_VERSIONING,
-
-    .type = "separator",
+LXPanelPluginInit lxpanel_static_plugin_separator = {
     .name = N_("Separator"),
-    .version = "1.0",
     .description = N_("Add a separator to the panel"),
 
-    .constructor = separator_constructor,
-    .destructor  = separator_destructor,