missing easy ways to replace LXDE icon from Menu (Panel)

The standard panel of LXDE - http://wiki.lxde.org/en/LXPanel
Locked
nitrofurano
Posts: 38
Joined: Sat Sep 27, 2008 11:18 pm

missing easy ways to replace LXDE icon from Menu (Panel)

Post by nitrofurano »

the LXDE wide icon appears too weird on the Panel, would be interesting being more easy to replace it to any other, like our custom one, or distributions like Ubuntu being able to set their icon there, or using the Gnome icon from the icons theme.
firmit
Posts: 32
Joined: Mon Sep 15, 2008 7:08 pm

Re: missing easy ways to replace LXDE icon from Menu (Panel)

Post by firmit »

~/.config/lxpanel/LXDE/panels/panels

Code: Select all

(..)
Plugin {
    type = menu
    Config {
        image=/usr/share/lxde/images/lxde-icon.png
        system {  }
        separator { }
        item {  command=run  }
        separator { }
        item {
            image=gnome-logout
            command=logout
        }
    }
}
(...)
Just change the image= to whatever you want. But yes - it would not be a bad thing for this to be edited via GUI (edit plugin i.e.). Or maybe this should be some kind of global setting (theme - lxappearance),
nitrofurano
Posts: 38
Joined: Sat Sep 27, 2008 11:18 pm

Re: missing easy ways to replace LXDE icon from Menu (Panel)

Post by nitrofurano »

thanks! =)
delirium
Posts: 30
Joined: Tue Oct 07, 2008 11:15 am

Re: missing easy ways to replace LXDE icon from Menu (Panel)

Post by delirium »

This menu.c would do the job! (lxpanel restart or plugin reload required for changes to take effekt)

Code: Select all

/**
 * Copyright (c) 2006 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.
 */

#include <stdlib.h>
#include <string.h>

#include <gdk-pixbuf/gdk-pixbuf.h>
#include <glib.h>
#include <glib/gi18n.h>

#include "panel.h"
#include "misc.h"
#include "plugin.h"
#include "bg.h"

#include "ptk-app-menu.h"

#include "dbg.h"

/*
 * SuxPanel version 0.1
 * Copyright (c) 2003 Leandro Pereira <leandro@linuxmag.com.br>
 */

/*
 * menu style code was taken from suxpanel
 */

typedef struct {
    GtkTooltips *tips;
    GtkWidget *menu, *box, *bg, *label;
    char *fname, *caption;
    gulong handler_id;
    int iconsize, paneliconsize;
    GSList *files;
    gboolean has_system_menu;
    char* config_data;
    int sysmenu_pos;
    char *config_start, *config_end;
    
} menup;

static guint idle_loader = 0;

static void
menu_destructor(Plugin *p)
{
    menup *m = (menup *)p->priv;

    ENTER;

    if( G_UNLIKELY( idle_loader ) )
    {
        g_source_remove( idle_loader );
        idle_loader = 0;
    }
    if( m->has_system_menu )
        p->panel->system_menus = g_slist_remove( p->panel->system_menus, p );

    g_signal_handler_disconnect(G_OBJECT(m->bg), m->handler_id);
    gtk_widget_destroy(m->menu);
    /* The widget is destroyed in plugin_stop().
    gtk_widget_destroy(m->box);
    */
    g_free(m->fname);
    g_free(m->caption);
    g_free(m);
    RET();
}

static void
spawn_app(GtkWidget *widget, gpointer data)
{
    GError *error = NULL;

    ENTER;
    if (data) {
        if (! g_spawn_command_line_async(data, &error) ) {
            ERR("can't spawn %s\nError is %s\n", (char *)data, error->message);
            g_error_free (error);
        }
    }
    RET();
}


static void
run_command(GtkWidget *widget, void (*cmd)(void))
{
    ENTER;
    cmd();
    RET();
}

static void
menu_pos(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, GtkWidget *widget)
{
    int ox, oy, w, h;
    Plugin *p;

    ENTER;
    p = g_object_get_data(G_OBJECT(widget), "plugin");
    gdk_window_get_origin(widget->window, &ox, &oy);
    w = GTK_WIDGET(menu)->requisition.width;
    h = GTK_WIDGET(menu)->requisition.height;
    if (p->panel->orientation == ORIENT_HORIZ) {
        *x = ox;
        if (*x + w > gdk_screen_width())
            *x = ox + widget->allocation.width - w;
        *y = oy - h;
        if (*y < 0)
            *y = oy + widget->allocation.height;
    } else {
        *x = ox + widget->allocation.width;
        if (*x > gdk_screen_width())
            *x = ox - w;
        *y = oy;
        if (*y + h >  gdk_screen_height())
            *y = oy + widget->allocation.height - h;
    }
    DBG("widget: x,y=%d,%d  w,h=%d,%d\n", ox, oy,
          widget->allocation.width, widget->allocation.height );
    DBG("w-h %d %d\n", w, h);
    *push_in = TRUE;
    RET();
}

static void
reload_system_menu( GtkMenu* menu )
{
    GList *children, *child;
    GtkMenuItem* item;
    GtkWidget* sub_menu;
    gint idx;
    children = gtk_container_get_children( GTK_CONTAINER(menu) );
    for( child = children, idx = 0; child; child = child->next, ++idx ) {
        item = GTK_MENU_ITEM( child->data );
        if( ptk_app_menu_item_has_data( item ) ) {
            do {
                item = GTK_MENU_ITEM( child->data );
                child = child->next;
                gtk_widget_destroy( GTK_WIDGET(item) );
            }while( child && ptk_app_menu_item_has_data( child->data ) );
            ptk_app_menu_insert_items( menu, idx );
            if( ! child )
                break;
        }
        else if( ( sub_menu = gtk_menu_item_get_submenu( item ) ) ) {
            reload_system_menu( GTK_MENU(sub_menu) );
        }
    }
    g_list_free( children );
}

static void show_menu( GtkWidget* widget, Plugin* p, int btn, guint32 time )
{
    menup* m = (menup*)p->priv;
    /* reload system menu items if needed */
    if( m->has_system_menu && ptk_app_menu_need_reload() ) {
        GSList* l;
        /* FIXME: Reload all system menus here.
                  This is dirty, but I don't know any better way. */
        for( l = p->panel->system_menus; l; l = l->next ) {
            Plugin* _p = (Plugin*)l->data;
            menup* _m = (menup*)_p->priv;
            reload_system_menu( GTK_MENU(_m->menu) );
        }
    }
    gtk_menu_popup(GTK_MENU(m->menu),
                   NULL, NULL,
                   (GtkMenuPositionFunc)menu_pos, widget,
                   btn, time);
}

static gboolean
my_button_pressed(GtkWidget *widget, GdkEventButton *event, Plugin* plugin)
{
    ENTER;

    if( event->button == 3 )  /* right button */
    {
        GtkMenu* popup = lxpanel_get_panel_menu( plugin->panel, plugin, FALSE );
        gtk_menu_popup( popup, NULL, NULL, NULL, NULL, event->button, event->time );
        return TRUE;
    }

    if ((event->type == GDK_BUTTON_PRESS)
          && (event->x >=0 && event->x < widget->allocation.width)
          && (event->y >=0 && event->y < widget->allocation.height)) {
        show_menu( widget, plugin, event->button, event->time );
    }
    RET(TRUE);
}

gboolean show_system_menu( gpointer system_menu )
{
    Plugin* p = (Plugin*)system_menu;
    menup* m = (menup*)p->priv;
    show_menu( m->bg, p, 0, GDK_CURRENT_TIME );
    return FALSE;
}

static GtkWidget *
make_button(Plugin *p, gchar *fname, gchar *name, GdkColor* tint, GtkWidget *menu)
{
    int w, h;
    char* title = NULL;
    menup *m;

    ENTER;
    m = (menup *)p->priv;
    m->menu = menu;
    if (p->panel->orientation == ORIENT_HORIZ) {
        w = 10000;
        h = p->panel->ah;
    } else {
        w = p->panel->aw;
        h = 10000;
    }

    if( name )
    {
        /* load the name from *.directory file if needed */
        if( g_str_has_suffix( name, ".directory" ) )
        {
            GKeyFile* kf = g_key_file_new();
            char* dir_file = g_build_filename( "desktop-directories", name, NULL );
            if( g_key_file_load_from_data_dirs( kf, dir_file, NULL, 0, NULL ) )
            {
                title = g_key_file_get_locale_string( kf, "Desktop Entry", "Name", NULL, NULL );
            }
            g_free( dir_file );
            g_key_file_free( kf );
        }
        else
            title = name;

        /* FIXME: handle orientation problems */
        if (p->panel->usefontcolor)
            m->bg = fb_button_new_from_file_with_colorlabel(fname, w, h, gcolor2rgb24(tint),
                p->panel->fontcolor, TRUE, title);
        else
            m->bg = fb_button_new_from_file_with_label(fname, w, h, gcolor2rgb24(tint), TRUE, title);

        if( title != name )
            g_free( title );
    }
    else
    {
        m->bg = fb_button_new_from_file(fname, w, h, gcolor2rgb24(tint), TRUE );
    }

    gtk_widget_show(m->bg);
    gtk_box_pack_start(GTK_BOX(m->box), m->bg, FALSE, FALSE, 0);

    m->handler_id = g_signal_connect (G_OBJECT (m->bg), "button-press-event",
          G_CALLBACK (my_button_pressed), p);
    g_object_set_data(G_OBJECT(m->bg), "plugin", p);

    RET(m->bg);
}


static GtkWidget *
read_item(Plugin *p, char** fp)
{
    line s;
    gchar *name, *fname, *action;
    GtkWidget *item;
    menup *m = (menup *)p->priv;
    Command *cmd_entry = NULL;

    ENTER;
    s.len = 256;
    name = fname = action = NULL;

    if( fp )
    {
        while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
            if (s.type == LINE_VAR) {
                if (!g_ascii_strcasecmp(s.t[0], "image"))
                    fname = m->fname = expand_tilda(s.t[1]);
                else if (!g_ascii_strcasecmp(s.t[0], "name"))
                    name = g_strdup(s.t[1]);
                else if (!g_ascii_strcasecmp(s.t[0], "action"))
                    action = g_strdup(s.t[1]);
                else if (!g_ascii_strcasecmp(s.t[0], "command")) {
                    Command *tmp;

                    for (tmp = commands; tmp->name; tmp++) {
                        if (!g_ascii_strcasecmp(s.t[1], tmp->name)) {
                            cmd_entry = tmp;
                            break;
                        }
                    }
                } else {
                    ERR( "menu/item: unknown var %s\n", s.t[0]);
                    goto error;
                }
            }
        }
    }
    /* menu button */
    if( cmd_entry ) /* built-in commands */
    {
        item = gtk_image_menu_item_new_with_label( _(cmd_entry->disp_name) );
        g_signal_connect(G_OBJECT(item), "activate", (GCallback)run_command, cmd_entry->cmd);
    }
    else
    {
        item = gtk_image_menu_item_new_with_label(name ? name : "");
        if (action) {
            g_signal_connect(G_OBJECT(item), "activate", (GCallback)spawn_app, action);
        }
    }
    gtk_container_set_border_width(GTK_CONTAINER(item), 0);
    g_free(name);
    if (fname) {
        GtkWidget *img;

        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);
        g_free(fname);
    }
    RET(item);

 error:
    g_free(fname);
    g_free(name);
    g_free(action);
    RET(NULL);
}

static GtkWidget *
read_separator(Plugin *p, char **fp)
{
    line s;

    ENTER;
    s.len = 256;
    if( fp )
    {
        while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
            ERR("menu: error - separator can not have paramteres\n");
            RET(NULL);
        }
    }
    RET(gtk_separator_menu_item_new());
}

static gboolean on_idle( Panel* p )
{
    GSList* l;
    /* Reload all system menus here.
        This is dirty, but I don't know any better way. */
    for( l = p->system_menus; l; l = l->next ) {
        Plugin* _p = (Plugin*)l->data;
        menup* _m = (menup*)_p->priv;
        reload_system_menu( GTK_MENU(_m->menu) );
    }
    idle_loader = 0;
    return FALSE;   /* remove the handler */
}

static void
read_system_menu(GtkMenu* menu, Plugin *p, char** fp)
{
   line s;
   menup *m = (menup *)p->priv;
    GtkWidget* fake;

   ENTER;
   s.len = 256;
   if( fp )
   {
        while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
            ERR("menu: error - system can not have paramteres\n");
            RET();
        }
   }

   /* ptk_app_menu_insert_items( menu, -1 ); */
   /* Don't load the real system menu here to speed up startup.
    * Let's add a fake item to cheat PtkAppMenu as a place holder,
    * and we utilize reload_system_menu() to load the real menu later. */
    fake = gtk_separator_menu_item_new();
    PTK_APP_MENU_ITEM_ID = g_quark_from_static_string( "PtkAppMenuItem" );
    g_object_set_qdata( fake, PTK_APP_MENU_ITEM_ID, GUINT_TO_POINTER(TRUE) );
   gtk_menu_shell_append( menu, fake);

   m->has_system_menu = TRUE;

   p->panel->system_menus = g_slist_append( p->panel->system_menus, p );

    if( idle_loader == 0 )  /* delay the loading, and do it in idle handler */
        idle_loader = g_idle_add( (GSourceFunc)on_idle, p->panel );

   RET();
}

static void
read_include(Plugin *p, char **fp)
{
    ENTER;
#if 0
    gchar *name;
    line s;
    menup *m = (menup *)p->priv;
    /* FIXME: this is disabled */
    ENTER;
    s.len = 256;
    name = NULL;
    if( fp )
    {
        while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
            if (s.type == LINE_VAR) {
                if (!g_ascii_strcasecmp(s.t[0], "name"))
                    name = expand_tilda(s.t[1]);
                else  {
                    ERR( "menu/include: unknown var %s\n", s.t[0]);
                    RET();
                }
            }
        }
    }
    if ((fp = fopen(name, "r"))) {
        LOG(LOG_INFO, "Including %s\n", name);
        m->files = g_slist_prepend(m->files, fp);
        p->fp = fp;
    } else {
        ERR("Can't include %s\n", name);
    }
    if (name) g_free(name);
#endif
    RET();
}

static GtkWidget *
read_submenu(Plugin *p, char** fp, gboolean as_item)
{
    line s;
    GtkWidget *mi, *menu;
    gchar name[256], *fname;
    menup *m = (menup *)p->priv;
    GdkColor color={0, 0, 36 * 0xffff / 0xff, 96 * 0xffff / 0xff};

    ENTER;


    s.len = 256;
    menu = gtk_menu_new ();
    gtk_container_set_border_width(GTK_CONTAINER(menu), 0);

    fname = 0;
    name[0] = 0;
    while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
        if (s.type == LINE_BLOCK_START) {
            mi = NULL;
            if (!g_ascii_strcasecmp(s.t[0], "item")) {
                mi = read_item(p, fp);
            } else if (!g_ascii_strcasecmp(s.t[0], "separator")) {
                mi = read_separator(p, fp);
            } else if (!g_ascii_strcasecmp(s.t[0], "system")) {
                read_system_menu(GTK_MENU(menu), p, fp); /* add system menu items */
                continue;
            } else if (!g_ascii_strcasecmp(s.t[0], "menu")) {
                mi = read_submenu(p, fp, TRUE);
            } else if (!g_ascii_strcasecmp(s.t[0], "include")) {
                read_include(p, fp);
                continue;
            } else {
                ERR("menu: unknown block %s\n", s.t[0]);
                goto error;
            }
            if (!mi) {
                ERR("menu: can't create menu item\n");
                goto error;
            }
            gtk_widget_show(mi);
            gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
        } else if (s.type == LINE_VAR) {
            m->config_start = *fp;
            if (!g_ascii_strcasecmp(s.t[0], "image"))
                fname = m->fname = expand_tilda(s.t[1]);
            else if (!g_ascii_strcasecmp(s.t[0], "name"))
                strcpy(name, s.t[1]);
	    /* FIXME: tintcolor will not be saved.  */
            else if (!g_ascii_strcasecmp(s.t[0], "tintcolor"))
                gdk_color_parse( s.t[1], &color);
            else {
                ERR("menu: unknown var %s\n", s.t[0]);
                goto error;
            }
        } else if (s.type == LINE_NONE) {
            if (m->files) {
                /*
                  fclose(p->fp);
                  p->fp = m->files->data;
                */
                m->files = g_slist_delete_link(m->files, m->files);
            }
        }  else {
            ERR("menu: illegal in this context %s\n", s.str);
            goto error;
        }
    }
    if (as_item) {
        mi = gtk_image_menu_item_new_with_label(name ? name : "");
        if (fname) {
            GtkWidget *img;
            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);
            g_free(fname);
        }
        gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), menu);
        RET(mi);
    } else {
        m->fname = g_strdup(fname);
        m->caption = g_strdup(name);
        mi = make_button(p, fname, name, &color, menu);
        if (fname)
            g_free(fname);
        RET(mi);
    }

 error:
    // FIXME: we need to recursivly destroy all child menus and their items
    gtk_widget_destroy(menu);
    g_free(fname);
    g_free(name);
    RET(NULL);
}

static int
menu_constructor(Plugin *p, char **fp)
{
    menup *m;
    static char default_config[] =
        "image=" PACKAGE_DATA_DIR "/lxpanel/images/my-computer.png\n"
        "system {\n"
        "}\n"
        "separator {\n"
        "}\n"
        "item {\n"
            "command=run\n"
        "}\n"
        "separator {\n"
        "}\n"
        "item {\n"
            "image=gnome-logout\n"
            "command=logout\n"
        "}\n"
        "}\n";
    char *config_start, *config_end, *config_default = default_config;

    ENTER;
    m = g_new0(menup, 1);
    g_return_val_if_fail(m != NULL, 0);
    m->fname = NULL;
    m->caption = NULL;
    p->priv = m;

    //gtk_rc_parse_string(menu_rc);
    if  (p->panel->orientation == ORIENT_HORIZ)
        m->paneliconsize = p->panel->ah
            - 2* GTK_WIDGET(p->panel->box)->style->ythickness;
    else
        m->paneliconsize = p->panel->aw
            - 2* GTK_WIDGET(p->panel->box)->style->xthickness;
    m->iconsize = 22;

    m->box = gtk_hbox_new(FALSE, 0);
    gtk_container_set_border_width(GTK_CONTAINER(m->box), 0);

    if( ! fp )
        fp = &config_default;

    m->config_start = *fp;
    if (!read_submenu(p, fp, FALSE)) {
        ERR("menu: plugin init failed\n");
        goto error;
    }
    m->config_end = *fp - 1;
    while( *m->config_end != '}' && m->config_end > m->config_start ) {
        --m->config_end;
    }
    if( *m->config_end == '}' )
        --m->config_end;

    m->config_data = g_strndup( m->config_start,
                                (m->config_end-m->config_start) );

    p->pwid = m->box;

    RET(1);

 error:
    menu_destructor(p);
    RET(0);
}

static void save_config( Plugin* p, FILE* fp )
{
    menup* menu = (menup*)p->priv;
    lxpanel_put_str( fp, "name", menu->caption );
    lxpanel_put_str( fp, "image", menu->fname );
    if( menu->config_data ) {
        char** lines = g_strsplit( menu->config_data, "\n", 0 );
        char** line;
        for( line = lines; *line; ++line ) {
            g_strstrip( *line );
            if( **line )
                lxpanel_put_line( fp, *line );
        }
        g_strfreev( lines );
    }
}

static void apply_config(Plugin* p)
{
    /* FIXME: update menu for new setting */
}

static void menu_config( Plugin *p, GtkWindow* parent )
{
    GtkWidget* dlg;
    menup* menu = (menup*)p->priv;
    dlg = create_generic_config_dlg( _(p->class->name),
                                     GTK_WIDGET(parent),
                                    (GSourceFunc) apply_config, (gpointer) p,
                                     _("Icon"), &menu->fname, G_TYPE_STRING,
                                     _("Caption"), &menu->caption, G_TYPE_STRING,
                                     NULL );
    gtk_window_present( GTK_WINDOW(dlg) );
}

PluginClass menu_plugin_class = {
    fname: NULL,
    count: 0,

    type : "menu",
    name : N_("Menu"),
    version: "1.1",
    description : N_("Provide Menu"),

    constructor : menu_constructor,
    destructor  : menu_destructor,
    config : menu_config, 
    save : save_config
};

Locked