Browse Source

Add new plugin directory menu.

Plugin to walk to a directory tree using a menu. Folders
are loaded on the fly and desktop files are handled
like menu items (unix only).
It is also possible to set a file pattern to allow files
in the menu (instead of only directories). The files are
opened in the default handler.
upstream/xfce4-panel-4.10.1
Nick Schermer 12 years ago
parent
commit
c0b237af66
  1. 8
      configure.ac.in
  2. 1
      plugins/Makefile.am
  3. 87
      plugins/directorymenu/Makefile.am
  4. 235
      plugins/directorymenu/directorymenu-dialog.glade
  5. 856
      plugins/directorymenu/directorymenu.c
  6. 8
      plugins/directorymenu/directorymenu.desktop.in
  7. 42
      plugins/directorymenu/directorymenu.h
  8. 22
      plugins/directorymenu/xfce4-popup-directorymenu.in
  9. 3
      po/POTFILES.in

8
configure.ac.in

@ -111,11 +111,18 @@ XDT_CHECK_PACKAGE([XFCONF], [libxfconf-0], [4.7.1])
XDT_CHECK_PACKAGE([EXO], [exo-1], [0.5.1])
XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.14.0])
XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.18.0])
XDT_CHECK_PACKAGE([GIO], [gio-2.0], [2.18.0])
XDT_CHECK_PACKAGE([GMODULE], [gmodule-2.0], [2.18.0])
XDT_CHECK_PACKAGE([DBUS], [dbus-glib-1], [0.73])
XDT_CHECK_PACKAGE([CAIRO], [cairo], [1.0.0])
XDT_CHECK_PACKAGE([LIBWNCK], [libwnck-1.0], [2.22])
dnl **********************************
dnl *** Optional GIO UNIX features ***
dnl **********************************
XDT_CHECK_OPTIONAL_PACKAGE([GIO_UNIX], [gio-unix-2.0],
[2.18.0], [gio-unix], [GIO UNIX features])
dnl *************************
dnl *** Check for gtk-doc ***
dnl *************************
@ -199,6 +206,7 @@ wrapper/Makefile
plugins/Makefile
plugins/actions/Makefile
plugins/clock/Makefile
plugins/directorymenu/Makefile
plugins/launcher/Makefile
plugins/pager/Makefile
plugins/separator/Makefile

1
plugins/Makefile.am

@ -2,6 +2,7 @@
SUBDIRS = \
actions \
clock \
directorymenu \
launcher \
pager \
separator \

87
plugins/directorymenu/Makefile.am

@ -0,0 +1,87 @@
INCLUDES = \
-I$(top_srcdir) \
-DG_LOG_DOMAIN=\"libdirectorymenu\" \
$(PLATFORM_CPPFLAGS)
plugindir = $(libdir)/xfce4/panel-plugins
plugin_LTLIBRARIES = \
libdirectorymenu.la
libdirectorymenu_built_sources = \
directorymenu-dialog_ui.h
libdirectorymenu_la_SOURCES = \
$(libdirectorymenu_built_sources) \
directorymenu.c \
directorymenu.h
libdirectorymenu_la_CFLAGS = \
$(GTK_CFLAGS) \
$(EXO_CFLAGS) \
$(XFCONF_CFLAGS) \
$(LIBXFCE4UTIL_CFLAGS) \
$(LIBXFCE4UI_CFLAGS) \
$(GIO_CFLAGS) \
$(GIO_UNIX_CFLAGS) \
$(PLATFORM_CFLAGS)
libdirectorymenu_la_LDFLAGS = \
-avoid-version \
-module \
-no-undefined \
-export-symbols-regex '^xfce_panel_module_(preinit|init|construct)' \
$(PLATFORM_LDFLAGS)
libdirectorymenu_la_LIBADD = \
$(top_builddir)/libxfce4panel/libxfce4panel-$(LIBXFCE4PANEL_VERSION_API).la \
$(top_builddir)/common/libpanel-common.la \
$(EXO_LIBS) \
$(GTK_LIBS) \
$(LIBXFCE4UTIL_LIBS) \
$(LIBXFCE4UI_LIBS) \
$(GIO_LIBS) \
$(GIO_UNIX_LIBS) \
$(XFCONF_LIBS)
libdirectorymenu_la_DEPENDENCIES = \
$(top_builddir)/libxfce4panel/libxfce4panel-$(LIBXFCE4PANEL_VERSION_API).la \
$(top_builddir)/common/libpanel-common.la
#
# xfce4-popup-directorymenu script
#
bin_SCRIPTS = \
xfce4-popup-directorymenu
xfce4-popup-directorymenu: xfce4-popup-directorymenu.in Makefile
$(AM_V_GEN) sed -e "s,\@bindir\@,$(bindir),g" $< >$@
#
# .desktop file
#
desktopdir = $(datadir)/xfce4/panel-plugins
desktop_in_files = directorymenu.desktop.in
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
@INTLTOOL_DESKTOP_RULE@
EXTRA_DIST = \
directorymenu-dialog.glade \
$(desktop_in_files)
DISTCLEANFILES = \
$(desktop_DATA)
if MAINTAINER_MODE
BUILT_SOURCES = \
$(libdirectorymenu_built_sources)
DISTCLEANFILES += \
$(libdirectorymenu_built_sources)
directorymenu-dialog_ui.h: directorymenu-dialog.glade
$(AM_V_GEN) exo-csource --static --strip-comments --strip-content --name=directorymenu_dialog_ui $< >$@
endif
# vi:set ts=8 sw=8 noet ai nocindent syntax=automake:

235
plugins/directorymenu/directorymenu-dialog.glade

@ -0,0 +1,235 @@
<?xml version="1.0"?>
<interface>
<requires lib="gtk+" version="2.14"/>
<!-- interface-requires libxfce4ui 0.0 -->
<!-- interface-naming-policy toplevel-contextual -->
<object class="XfceTitledDialog" id="dialog">
<property name="title" translatable="yes">Directory Menu</property>
<property name="icon_name">gtk-properties</property>
<property name="type_hint">normal</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox2">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFrame" id="frame3">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment3">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<property name="column_spacing">12</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkFileChooserButton" id="base-directory">
<property name="visible">True</property>
<property name="action">select-folder</property>
<property name="local_only">False</property>
<property name="title" translatable="yes">Select A Directory</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Base Directory:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">base-directory</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Icon:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">icon-button</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<child>
<object class="GtkButton" id="icon-button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Appearance</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkTable" id="table2">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<property name="column_spacing">12</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkEntry" id="file-pattern">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip_text" translatable="yes">Enter a list of patterns that will be used to determine which files are visible in a directory. If you specify more than one pattern here, the list items must be separated with semicolons (e.g. *.txt;*.doc).</property>
<property name="invisible_char">&#x2022;</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_File Pattern:</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">file-pattern</property>
</object>
<packing>
<property name="x_options">GTK_FILL</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="hidden-files">
<property name="label" translatable="yes">Show _hidden files</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="label" translatable="yes">Filtering</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area2">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="close-button">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">close-button</action-widget>
</action-widgets>
</object>
<object class="GtkSizeGroup" id="sizegroup1">
<widgets>
<widget name="label7"/>
<widget name="label2"/>
<widget name="label4"/>
</widgets>
</object>
</interface>

856
plugins/directorymenu/directorymenu.c

@ -0,0 +1,856 @@
/*
* Copyright (C) 2010 Nick Schermer <nick@xfce.org>
*
* This library 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 library 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 Library General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <exo/exo.h>
#include <libxfce4ui/libxfce4ui.h>
#include <libxfce4panel/libxfce4panel.h>
#include <common/panel-xfconf.h>
#include <common/panel-builder.h>
#include <common/panel-private.h>
#ifdef HAVE_GIO_UNIX
#include <gio/gdesktopappinfo.h>
#endif
#include "directorymenu.h"
#include "directorymenu-dialog_ui.h"
#define DEFAULT_ICON_NAME "folder"
struct _DirectoryMenuPluginClass
{
XfcePanelPluginClass __parent__;
};
struct _DirectoryMenuPlugin
{
XfcePanelPlugin __parent__;
GtkWidget *button;
GtkWidget *icon;
GFile *base_directory;
gchar *icon_name;
gchar *file_pattern;
guint hidden_files : 1;
GSList *patterns;
/* temp item we store here when the
* properties dialog is opened */
GtkWidget *dialog_icon;
};
enum
{
PROP_0,
PROP_BASE_DIRECTORY,
PROP_ICON_NAME,
PROP_FILE_PATTERN,
PROP_HIDDEN_FILES
};
static void directory_menu_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void directory_menu_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void directory_menu_plugin_construct (XfcePanelPlugin *panel_plugin);
static void directory_menu_plugin_free_file_patterns (DirectoryMenuPlugin *plugin);
static void directory_menu_plugin_free_data (XfcePanelPlugin *panel_plugin);
static void directory_menu_plugin_configure_plugin (XfcePanelPlugin *panel_plugin);
static gboolean directory_menu_plugin_remote_event (XfcePanelPlugin *panel_plugin,
const gchar *name,
const GValue *value);
static void directory_menu_plugin_menu (GtkWidget *button,
DirectoryMenuPlugin *plugin);
/* define the plugin */
XFCE_PANEL_DEFINE_PLUGIN (DirectoryMenuPlugin, directory_menu_plugin)
static GQuark menu_file = 0;
static void
directory_menu_plugin_class_init (DirectoryMenuPluginClass *klass)
{
XfcePanelPluginClass *plugin_class;
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = directory_menu_plugin_get_property;
gobject_class->set_property = directory_menu_plugin_set_property;
plugin_class = XFCE_PANEL_PLUGIN_CLASS (klass);
plugin_class->construct = directory_menu_plugin_construct;
plugin_class->free_data = directory_menu_plugin_free_data;
plugin_class->configure_plugin = directory_menu_plugin_configure_plugin;
plugin_class->remote_event = directory_menu_plugin_remote_event;
g_object_class_install_property (gobject_class,
PROP_BASE_DIRECTORY,
g_param_spec_string ("base-directory",
NULL, NULL,
NULL,
EXO_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_ICON_NAME,
g_param_spec_string ("icon-name",
NULL, NULL,
NULL,
EXO_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_FILE_PATTERN,
g_param_spec_string ("file-pattern",
NULL, NULL,
"",
EXO_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_HIDDEN_FILES,
g_param_spec_boolean ("hidden-files",
NULL, NULL,
FALSE,
EXO_PARAM_READWRITE));
menu_file = g_quark_from_static_string ("dir-menu-file");
}
static void
directory_menu_plugin_init (DirectoryMenuPlugin *plugin)
{
plugin->button = xfce_panel_create_toggle_button ();
xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), plugin->button);
gtk_container_add (GTK_CONTAINER (plugin), plugin->button);
gtk_button_set_relief (GTK_BUTTON (plugin->button), GTK_RELIEF_NONE);
g_signal_connect (G_OBJECT (plugin->button), "toggled",
G_CALLBACK (directory_menu_plugin_menu), plugin);
plugin->icon = xfce_panel_image_new_from_source (DEFAULT_ICON_NAME);
gtk_container_add (GTK_CONTAINER (plugin->button), plugin->icon);
gtk_widget_show (plugin->icon);
}
static void
directory_menu_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
DirectoryMenuPlugin *plugin = XFCE_DIRECTORY_MENU_PLUGIN (object);
gchar *str;
switch (prop_id)
{
case PROP_BASE_DIRECTORY:
if (g_file_is_native (plugin->base_directory))
str = g_file_get_path (plugin->base_directory);
else
str = g_file_get_uri (plugin->base_directory);
g_value_take_string (value, str);
break;
case PROP_ICON_NAME:
g_value_set_string (value, plugin->icon_name);
break;
case PROP_FILE_PATTERN:
g_value_set_string (value, exo_str_is_empty (plugin->file_pattern) ?
"" : plugin->file_pattern);
break;
case PROP_HIDDEN_FILES:
g_value_set_boolean (value, plugin->hidden_files);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
directory_menu_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
DirectoryMenuPlugin *plugin = XFCE_DIRECTORY_MENU_PLUGIN (object);
gchar *display_name;
gchar **array;
guint i;
GFile *base_directory;
const gchar *path;
switch (prop_id)
{
case PROP_BASE_DIRECTORY:
path = g_value_get_string (value);
if (exo_str_is_empty (path))
path = g_get_home_dir ();
if (plugin->base_directory != NULL)
g_object_unref (G_OBJECT (plugin->base_directory));
plugin->base_directory = g_file_new_for_commandline_arg (path);
base_directory = g_file_new_for_commandline_arg (g_value_get_string (value));
display_name = g_file_get_parse_name (plugin->base_directory);
gtk_widget_set_tooltip_text (plugin->button, display_name);
g_free (display_name);
break;
case PROP_ICON_NAME:
g_free (plugin->icon_name);
plugin->icon_name = g_value_dup_string (value);
xfce_panel_image_set_from_source (XFCE_PANEL_IMAGE (plugin->icon),
exo_str_is_empty (plugin->icon_name) ? DEFAULT_ICON_NAME : plugin->icon_name);
break;
case PROP_FILE_PATTERN:
g_free (plugin->file_pattern);
plugin->file_pattern = g_value_dup_string (value);
directory_menu_plugin_free_file_patterns (plugin);
array = g_strsplit (plugin->file_pattern, ";", -1);
if (G_LIKELY (array != NULL))
{
for (i = 0; array[i] != NULL; i++)
if (!exo_str_is_empty (array[i]))
plugin->patterns = g_slist_prepend (plugin->patterns,
g_pattern_spec_new (array[i]));
g_strfreev (array);
}
break;
case PROP_HIDDEN_FILES:
plugin->hidden_files = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
directory_menu_plugin_construct (XfcePanelPlugin *panel_plugin)
{
DirectoryMenuPlugin *plugin = XFCE_DIRECTORY_MENU_PLUGIN (panel_plugin);
const PanelProperty properties[] =
{
{ "base-directory", G_TYPE_STRING },
{ "icon-name", G_TYPE_STRING },
{ "file-pattern", G_TYPE_STRING },
{ "hidden-files", G_TYPE_BOOLEAN },
{ NULL }
};
xfce_panel_plugin_menu_show_configure (XFCE_PANEL_PLUGIN (plugin));
/* bind all properties */
panel_properties_bind (NULL, G_OBJECT (plugin),
xfce_panel_plugin_get_property_base (panel_plugin),
properties, FALSE);
if (plugin->base_directory == NULL)
g_object_set (G_OBJECT (plugin), "base-directory", g_get_home_dir (), NULL);
gtk_widget_show (plugin->button);
}
static void
directory_menu_plugin_free_file_patterns (DirectoryMenuPlugin *plugin)
{
GSList *li;
panel_return_if_fail (XFCE_IS_DIRECTORY_MENU_PLUGIN (plugin));
for (li = plugin->patterns; li != NULL; li = li->next)
g_pattern_spec_free (li->data);
g_slist_free (plugin->patterns);
plugin->patterns = NULL;
}
static void
directory_menu_plugin_free_data (XfcePanelPlugin *panel_plugin)
{
DirectoryMenuPlugin *plugin = XFCE_DIRECTORY_MENU_PLUGIN (panel_plugin);
g_object_unref (G_OBJECT (plugin->base_directory));
g_free (plugin->icon_name);
g_free (plugin->file_pattern);
directory_menu_plugin_free_file_patterns (plugin);
}
static void
directory_menu_plugin_configure_plugin_file_set (GtkFileChooserButton *button,
DirectoryMenuPlugin *plugin)
{
gchar *uri;
panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (button));
panel_return_if_fail (XFCE_IS_DIRECTORY_MENU_PLUGIN (plugin));
uri = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (button));
g_object_set (G_OBJECT (plugin), "base-directory", uri, NULL);
g_free (uri);
}
static void
directory_menu_plugin_configure_plugin_icon_chooser (GtkWidget *button,
DirectoryMenuPlugin *plugin)
{
GtkWidget *chooser;
gchar *icon;
panel_return_if_fail (XFCE_IS_DIRECTORY_MENU_PLUGIN (plugin));
panel_return_if_fail (XFCE_IS_PANEL_IMAGE (plugin->dialog_icon));
chooser = exo_icon_chooser_dialog_new (_("Select An Icon"),
GTK_WINDOW (gtk_widget_get_toplevel (button)),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
gtk_dialog_set_alternative_button_order (GTK_DIALOG (chooser),
GTK_RESPONSE_ACCEPT,
GTK_RESPONSE_CANCEL, -1);
if (!exo_str_is_empty (plugin->icon_name))
exo_icon_chooser_dialog_set_icon (EXO_ICON_CHOOSER_DIALOG (chooser), plugin->icon_name);
if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
{
icon = exo_icon_chooser_dialog_get_icon (EXO_ICON_CHOOSER_DIALOG (chooser));
g_object_set (G_OBJECT (plugin), "icon-name", icon, NULL);
xfce_panel_image_set_from_source (XFCE_PANEL_IMAGE (plugin->dialog_icon), icon);
g_free (icon);
}
gtk_widget_destroy (chooser);
}
static void
directory_menu_plugin_configure_plugin (XfcePanelPlugin *panel_plugin)
{
DirectoryMenuPlugin *plugin = XFCE_DIRECTORY_MENU_PLUGIN (panel_plugin);
GtkBuilder *builder;
GObject *dialog, *object;
const gchar *icon_name = plugin->icon_name;
if (exo_str_is_empty (icon_name))
icon_name = DEFAULT_ICON_NAME;
/* setup the dialog */
PANEL_BUILDER_LINK_4UI
builder = panel_builder_new (panel_plugin, directorymenu_dialog_ui,
directorymenu_dialog_ui_length, &dialog);
if (G_UNLIKELY (builder == NULL))
return;
object = gtk_builder_get_object (builder, "base-directory");
panel_return_if_fail (GTK_IS_FILE_CHOOSER_BUTTON (object));
if (!gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (object),
plugin->base_directory, NULL))
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (object), g_get_home_dir ());
g_signal_connect (G_OBJECT (object), "current-folder-changed",
G_CALLBACK (directory_menu_plugin_configure_plugin_file_set), plugin);
object = gtk_builder_get_object (builder, "icon-button");
panel_return_if_fail (GTK_IS_BUTTON (object));
g_signal_connect (G_OBJECT (object), "clicked",
G_CALLBACK (directory_menu_plugin_configure_plugin_icon_chooser), plugin);
plugin->dialog_icon = xfce_panel_image_new_from_source (icon_name);
g_object_set (G_OBJECT (plugin->dialog_icon), "size", 48, NULL);
gtk_container_add (GTK_CONTAINER (object), plugin->dialog_icon);
g_object_add_weak_pointer (G_OBJECT (plugin->dialog_icon), (gpointer) &plugin->dialog_icon);
gtk_widget_show (plugin->dialog_icon);
object = gtk_builder_get_object (builder, "file-pattern");
panel_return_if_fail (GTK_IS_ENTRY (object));
exo_mutual_binding_new (G_OBJECT (plugin), "file-pattern",
G_OBJECT (object), "text");
object = gtk_builder_get_object (builder, "hidden-files");
panel_return_if_fail (GTK_IS_CHECK_BUTTON (object));
exo_mutual_binding_new (G_OBJECT (plugin), "hidden-files",
G_OBJECT (object), "active");
gtk_widget_show (GTK_WIDGET (dialog));
}
static gboolean
directory_menu_plugin_remote_event (XfcePanelPlugin *panel_plugin,
const gchar *name,
const GValue *value)
{
DirectoryMenuPlugin *plugin = XFCE_DIRECTORY_MENU_PLUGIN (panel_plugin);
panel_return_val_if_fail (value == NULL || G_IS_VALUE (value), FALSE);
if (strcmp (name, "popup") == 0
&& GTK_WIDGET_VISIBLE (panel_plugin)
&& !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (plugin->button)))
{
/* show the menu */
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), TRUE);
/* don't popup another menu */
return TRUE;
}
return FALSE;
}
static void
directory_menu_plugin_selection_done (GtkWidget *menu,
GtkWidget *button)
{
panel_return_if_fail (GTK_IS_TOGGLE_BUTTON (button));
panel_return_if_fail (GTK_IS_MENU (menu));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
/* delay destruction so we can handle the activate event first */
exo_gtk_object_destroy_later (GTK_OBJECT (menu));
}
static gint
directory_menu_plugin_menu_sort (gconstpointer a,
gconstpointer b)
{
GFileType type_a = g_file_info_get_file_type (G_FILE_INFO (a));
GFileType type_b = g_file_info_get_file_type (G_FILE_INFO (b));
if (type_a != type_b)
{
/* sort directories before files */
if (type_a == G_FILE_TYPE_DIRECTORY)
return -1;
else if (type_b == G_FILE_TYPE_DIRECTORY)
return 1;
}
return g_utf8_collate (g_file_info_get_display_name (G_FILE_INFO (a)),
g_file_info_get_display_name (G_FILE_INFO (b)));
}
#ifdef HAVE_GIO_UNIX
static void
directory_menu_plugin_menu_launch_desktop_file (GtkWidget *mi,
GAppInfo *info)
{
GdkAppLaunchContext *context;
GIcon *icon;
GError *error = NULL;
panel_return_if_fail (G_IS_APP_INFO (info));
panel_return_if_fail (GTK_IS_WIDGET (mi));
context = gdk_app_launch_context_new ();
gdk_app_launch_context_set_screen (context, gtk_widget_get_screen (mi));
gdk_app_launch_context_set_timestamp (context, gtk_get_current_event_time ());
icon = g_app_info_get_icon (info);
if (G_LIKELY (icon != NULL))
gdk_app_launch_context_set_icon (context, icon);
if (!g_app_info_launch (info, NULL, G_APP_LAUNCH_CONTEXT (context), &error))
{
xfce_dialog_show_error (NULL, error, _("Failed to launch application \"%s\""),
g_app_info_get_executable (info));
g_error_free (error);
}
g_object_unref (G_OBJECT (context));
}
#endif
static void
directory_menu_plugin_menu_launch (GtkWidget *mi,
GFile *file)
{
GAppInfo *appinfo;
GError *error = NULL;
gchar *display_name;
GList fake_list = { NULL, };
GdkAppLaunchContext *context;
GFileInfo *info;
const gchar *message;
gboolean result;
panel_return_if_fail (G_IS_FILE (file));
panel_return_if_fail (GTK_IS_WIDGET (mi));
info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
G_FILE_QUERY_INFO_NONE, NULL, &error);
if (G_UNLIKELY (info == NULL))
{
message = _("Failed to query content type for \"%s\"");
goto err;
}
appinfo = g_app_info_get_default_for_type (g_file_info_get_content_type (info),
!g_file_is_native (file));
g_object_unref (G_OBJECT (info));
if (G_LIKELY (appinfo == NULL))
{
message = _("No default application found for \"%s\"");
goto err;
}
fake_list.data = file;
context = gdk_app_launch_context_new ();
gdk_app_launch_context_set_screen (context, gtk_widget_get_screen (mi));
gdk_app_launch_context_set_timestamp (context, gtk_get_current_event_time ());
result = g_app_info_launch (appinfo, &fake_list, G_APP_LAUNCH_CONTEXT (context), &error);
g_object_unref (G_OBJECT (context));
g_object_unref (G_OBJECT (appinfo));
if (G_UNLIKELY (!result))
{
message = _("Failed to launch default application for \"%s\"");
goto err;
}
return;
err:
display_name = g_file_get_parse_name (file);
xfce_dialog_show_error (NULL, error, message, display_name);
g_free (display_name);
g_error_free (error);
}
static void
directory_menu_plugin_menu_open (GtkWidget *mi,
GFile *dir,
const gchar *category)
{
GError *error = NULL;
gchar *path;
path = g_file_get_path (dir);
if (!exo_execute_preferred_application_on_screen (category, NULL, path, NULL,
gtk_widget_get_screen (mi),
&error))
{
xfce_dialog_show_error (NULL, error,
_("Failed to open preferred application category \"%s\""), category);
g_error_free (error);
}
g_free (path);
}
static void
directory_menu_plugin_menu_open_terminal (GtkWidget *mi,
GFile *dir)
{
panel_return_if_fail (GTK_IS_WIDGET (mi));
panel_return_if_fail (G_IS_FILE (dir));
directory_menu_plugin_menu_open (mi, dir, "TerminalEmulator");
}
static void
directory_menu_plugin_menu_open_folder (GtkWidget *mi,
GFile *dir)
{
panel_return_if_fail (GTK_IS_WIDGET (mi));
panel_return_if_fail (G_IS_FILE (dir));
directory_menu_plugin_menu_open (mi, dir, "FileManager");
}
static void
directory_menu_plugin_menu_unload (GtkWidget *menu)
{
/* delay destruction so we can handle the activate event first */
gtk_container_foreach (GTK_CONTAINER (menu),
(GtkCallback) exo_gtk_object_destroy_later, NULL);
}
static void
directory_menu_plugin_menu_load (GtkWidget *menu,
DirectoryMenuPlugin *plugin)
{
GFileEnumerator *iter;
GFileInfo *info;
GtkWidget *mi;
const gchar *display_name;
GSList *li, *infos = NULL;
GIcon *icon;
GtkWidget *image;
GtkWidget *submenu;
GFile *file;
GFile *dir;
gboolean visible;
GFileType file_type;
#ifdef HAVE_GIO_UNIX
GDesktopAppInfo *desktopinfo;
gchar *path;
const gchar *description;
#endif
panel_return_if_fail (XFCE_IS_DIRECTORY_MENU_PLUGIN (plugin));
panel_return_if_fail (GTK_IS_MENU (menu));
dir = g_object_get_qdata (G_OBJECT (menu), menu_file);
panel_return_if_fail (G_IS_FILE (dir));
if (G_UNLIKELY (dir == NULL))
return;
mi = gtk_image_menu_item_new_with_label (_("Open Folder"));
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
g_signal_connect_data (G_OBJECT (mi), "activate",
G_CALLBACK (directory_menu_plugin_menu_open_folder),
g_object_ref (dir), (GClosureNotify) g_object_unref, 0);
gtk_widget_show (mi);
image = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
gtk_widget_show (image);
mi = gtk_image_menu_item_new_with_label (_("Open in Terminal"));
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
g_signal_connect_data (G_OBJECT (mi), "activate",
G_CALLBACK (directory_menu_plugin_menu_open_terminal),
g_object_ref (dir), (GClosureNotify) g_object_unref, 0);
gtk_widget_show (mi);
image = gtk_image_new_from_icon_name ("terminal", GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
gtk_widget_show (image);
iter = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
"," G_FILE_ATTRIBUTE_STANDARD_NAME
"," G_FILE_ATTRIBUTE_STANDARD_TYPE
"," G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN
"," G_FILE_ATTRIBUTE_STANDARD_ICON,
G_FILE_QUERY_INFO_NONE, NULL, NULL);
if (G_LIKELY (iter != NULL))
{
for (;;)
{
info = g_file_enumerator_next_file (iter, NULL, NULL);
if (G_UNLIKELY (info == NULL))
break;
/* skip hidden files if disabled by the user */
if (!plugin->hidden_files
&& g_file_info_get_is_hidden (info))
continue;
/* if the file is not a directory, check the file patterns */
if (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY)
{
if (plugin->patterns == NULL)
continue;
visible = FALSE;
display_name = g_file_info_get_display_name (info);
if (G_LIKELY (display_name != NULL))
for (li = plugin->patterns; !visible && li != NULL; li = li->next)
if (g_pattern_match_string (li->data, display_name))
visible = TRUE;
if (!visible)
continue;
}
infos = g_slist_insert_sorted (infos, info, directory_menu_plugin_menu_sort);
}
if (G_LIKELY (infos != NULL))
{
mi = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
gtk_widget_show (mi);
}
for (li = infos; li != NULL; li = li->next)
{
info = G_FILE_INFO (li->data);
file_type = g_file_info_get_file_type (info);
display_name = g_file_info_get_display_name (info);
if (G_UNLIKELY (display_name == NULL))
continue;
file = g_file_get_child (dir, g_file_info_get_name (info));
icon = NULL;
#ifdef HAVE_GIO_UNIX
/* for native desktop files we make an exception and try
* to load them like a normal menu */
if (G_UNLIKELY (file_type != G_FILE_TYPE_DIRECTORY
&& g_file_is_native (file)
&& g_str_has_suffix (display_name, ".desktop")))
{
path = g_file_get_path (file);
desktopinfo = g_desktop_app_info_new_from_filename (path);
g_free (path);
if (G_LIKELY (desktopinfo != NULL))
{
display_name = g_app_info_get_display_name (G_APP_INFO (desktopinfo));
icon = g_app_info_get_icon (G_APP_INFO (desktopinfo));
}
}
#endif
mi = gtk_image_menu_item_new_with_label (display_name);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
gtk_widget_show (mi);
if (G_LIKELY (icon == NULL))
icon = g_file_info_get_icon (info);
if (G_LIKELY (icon != NULL))
{
image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
gtk_widget_show (image);
}
/* set a submenu for directories */
if (G_LIKELY (file_type == G_FILE_TYPE_DIRECTORY))
{
submenu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), submenu);
g_object_set_qdata_full (G_OBJECT (submenu), menu_file, file, g_object_unref);
g_signal_connect (G_OBJECT (submenu), "show",
G_CALLBACK (directory_menu_plugin_menu_load), plugin);
g_signal_connect_after (G_OBJECT (submenu), "hide",
G_CALLBACK (directory_menu_plugin_menu_unload), NULL);
}
#ifdef HAVE_GIO_UNIX
else if (G_UNLIKELY (desktopinfo != NULL))
{
description = g_app_info_get_description (G_APP_INFO (desktopinfo));
if (!exo_str_is_empty (description))
gtk_widget_set_tooltip_text (mi, description);
g_signal_connect_data (G_OBJECT (mi), "activate",
G_CALLBACK (directory_menu_plugin_menu_launch_desktop_file),
desktopinfom (GClosureNotify) g_object_unref, 0);
g_object_unref (G_OBJECT (file));
}
#endif
else
{
g_signal_connect_data (G_OBJECT (mi), "activate",
G_CALLBACK (directory_menu_plugin_menu_launch), file,
(GClosureNotify) g_object_unref, 0);
}
}
g_slist_free (infos);
g_object_unref (G_OBJECT (iter));
}
}
static void
directory_menu_plugin_menu (GtkWidget *button,
DirectoryMenuPlugin *plugin)
{
GtkWidget *menu;
panel_return_if_fail (XFCE_IS_DIRECTORY_MENU_PLUGIN (plugin));
panel_return_if_fail (plugin->button == button);
if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
return;
menu = gtk_menu_new ();
g_signal_connect (G_OBJECT (menu), "deactivate",
G_CALLBACK (directory_menu_plugin_selection_done), button);
g_object_set_qdata_full (G_OBJECT (menu), menu_file,
g_object_ref (plugin->base_directory),
g_object_unref);
directory_menu_plugin_menu_load (menu, plugin);
gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
xfce_panel_plugin_position_menu, plugin,
1, gtk_get_current_event_time ());
}

8
plugins/directorymenu/directorymenu.desktop.in

@ -0,0 +1,8 @@
[Xfce Panel]
Type=X-XFCE-PanelPlugin
Encoding=UTF-8
_Name=Directory Menu
_Comment=Show a directory tree in a menu
Icon=folder
X-XFCE-Module=directorymenu
X-XFCE-Internal=TRUE

42
plugins/directorymenu/directorymenu.h

@ -0,0 +1,42 @@
/*
* Copyright (C) 2010 Nick Schermer <nick@xfce.org>
*
* 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., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __XFCE_DIRECTORY_MENU_PLUGIN_H__
#define __XFCE_DIRECTORY_MENU_PLUGIN_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
typedef struct _DirectoryMenuPluginClass DirectoryMenuPluginClass;
typedef struct _DirectoryMenuPlugin DirectoryMenuPlugin;
#define XFCE_TYPE_DIRECTORY_MENU_PLUGIN (directory_menu_plugin_get_type ())
#define XFCE_DIRECTORY_MENU_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_DIRECTORY_MENU_PLUGIN, DirectoryMenuPlugin))
#define XFCE_DIRECTORY_MENU_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_DIRECTORY_MENU_PLUGIN, DirectoryMenuPluginClass))
#define XFCE_IS_DIRECTORY_MENU_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_DIRECTORY_MENU_PLUGIN))
#define XFCE_IS_DIRECTORY_MENU_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_DIRECTORY_MENU_PLUGIN))
#define XFCE_DIRECTORY_MENU_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_DIRECTORY_MENU_PLUGIN, DirectoryMenuPluginClass))
GType directory_menu_plugin_get_type (void) G_GNUC_CONST;
void directory_menu_plugin_register_type (XfcePanelTypeModule *type_module);
G_END_DECLS
#endif /* !__XFCE_DIRECTORY_MENU_PLUGIN_H__ */

22
plugins/directorymenu/xfce4-popup-directorymenu.in

@ -0,0 +1,22 @@
#!/bin/sh
#
# Copyright (C) 2010 Nick Schermer <nick@xfce.org>
#
# This library 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 library 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 Library General Public License
# along with this library; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
#
exec @bindir@/xfce4-panel --plugin-event=directorymenu:popup
# vim:set ts=2 sw=2 et ai:

3
po/POTFILES.in

@ -72,6 +72,9 @@ plugins/clock/clock.c
plugins/clock/clock.desktop.in
plugins/clock/clock.h
plugins/directorymenu/directorymenu.c
plugins/directorymenu/directorymenu.desktop.in
plugins/launcher/launcher-dialog.c
plugins/launcher/launcher-dialog.h
plugins/launcher/launcher-dialog.glade

Loading…
Cancel
Save