--- gtk+-2.2.4/gtk/gtkfilesel.c.old Wed Oct 15 21:17:31 2003 +++ gtk+-2.2.4/gtk/gtkfilesel.c Sat Jan 24 11:59:52 2004 @@ -41,8 +41,11 @@ #ifdef HAVE_PWD_H #include #endif +#include +#include #include /* Include early to get G_OS_WIN32 etc */ +#include #if defined(G_PLATFORM_WIN32) #include @@ -55,8 +58,10 @@ #endif #include "gdk/gdkkeysyms.h" +#include "gdk/x11/gdkx.h" #include "gtkbutton.h" #include "gtkcellrenderertext.h" +#include "gtkcellrendererpixbuf.h" #include "gtkentry.h" #include "gtkfilesel.h" #include "gtkhbox.h" @@ -78,6 +83,15 @@ #include "gtkmessagedialog.h" #include "gtkdnd.h" #include "gtkeventbox.h" +#include "gtktoolbar.h" +#include "gtkimage.h" +#include "gtktogglebutton.h" +#include "gtkarrow.h" +#include "gtkbin.h" +#undef GTK_DISABLE_DEPRECATED +# include "gtklist.h" +# include "gtkcombo.h" +#define GTK_DISABLE_DEPRECATED #define WANT_HPANED 1 #include "gtkhpaned.h" @@ -95,7 +109,7 @@ #include /* For cygwin_conv_to_posix_path */ #endif -#define DIR_LIST_WIDTH 180 +#define DIR_LIST_WIDTH 150 #define DIR_LIST_HEIGHT 180 #define FILE_LIST_WIDTH 180 #define FILE_LIST_HEIGHT 180 @@ -232,6 +246,8 @@ GList* directory_sent_storage; struct _CompletionUserDir *user_directories; + + GtkEntry *filter_entry; }; enum { @@ -246,7 +262,13 @@ }; enum { - FILE_COLUMN + FILE_COLUMN, + ICON_COLUMN, + TYPE_COLUMN, + SIZE_COLUMN, + SIZE_DATA_COLUMN, + DATE_COLUMN, + DATE_DATA_COLUMN }; /* File completion functions which would be external, were they used @@ -393,6 +415,10 @@ gpointer user_data); static void gtk_file_selection_update_fileops (GtkFileSelection *filesel); +static void filter_chosen_callback (GtkWidget *w, + gpointer user_data); +static void filter_chosen_selected_callback (GtkWidget *w, + GtkBin *item); static void gtk_file_selection_file_activate (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, @@ -413,12 +439,424 @@ static void gtk_file_selection_update_history_menu (GtkFileSelection *fs, gchar *current_dir); +static void gtk_file_selection_back (GtkWidget *widget, gpointer data); +static void gtk_file_selection_up (GtkWidget *widget, gpointer data); +static void gtk_file_selection_refresh (GtkWidget *widget, gpointer data); +static void gtk_file_selection_home (GtkWidget *widget, gpointer data); +static void gtk_file_selection_desktop (GtkWidget *widget, gpointer data); +static void gtk_file_selection_launch_terminal (GtkWidget *widget, GtkFileSelection *fs); +static void gtk_file_selection_launch_fm (GtkWidget *widget, GtkFileSelection *fs); static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data); static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data); static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data); static void free_selected_names (GPtrArray *names); +static void reload_bookmarks (GtkWidget *bookmarks_button, GtkWidget *fs); + +static gboolean simple_mode = FALSE; +static gchar *global_last_dir = NULL; +extern gboolean _gtk_fnmatch_show_hidden; + + +#define GNOME_VFS_FILE_INFO_GET_MIME_TYPE (1 << 0) +#define GNOME_VFS_FILE_INFO_FORCE_FAST_MIME_TYPE (1 << 1) +typedef struct _GnomeVFSFileInfo GnomeVFSFileInfo; +static GModule *gnome_mod = NULL; +static gboolean vfs_initialized = FALSE; +static GnomeVFSFileInfo* (*gnome_vfs_file_info_new) (void); +static gint (*gnome_vfs_get_file_info) (const gchar *text_uri, GnomeVFSFileInfo *info, gint options); +static const char* (*gnome_vfs_file_info_get_mime_type) (GnomeVFSFileInfo *info); +static const char* (*gnome_vfs_mime_get_description) (const gchar *mime_type); +static const char* (*gnome_vfs_mime_get_icon) (const gchar *mime_type); +static void (*gnome_vfs_file_info_unref) (GnomeVFSFileInfo *info); + +static gboolean icon_theme_initialized = FALSE; +typedef struct _GnomeIconTheme GnomeIconTheme; +static GnomeIconTheme* (*gnome_icon_theme_new) (void); +static char* (*gnome_icon_theme_lookup_icon) (GnomeIconTheme *theme, const char *icon_name, + int size, gpointer icon_data, int *base_size); +static void (*gnome_icon_theme_append_search_path) (GnomeIconTheme *theme, const char *path); +static GSList *icon_theme_paths = NULL; + +#define GNOME_FILE_DOMAIN_PIXMAP 4 +typedef struct _GnomeProgram GnomeProgram; +static GnomeProgram* (*gnome_program_get) (void); +static gchar* (*gnome_program_locate_file) (GnomeProgram *program, gint domain, const gchar *filename, + gboolean only_if_exists, GSList **ret_locations); + +typedef struct _GConfClient GConfClient; +typedef struct _GConfEntry GConfEntry; +#define GCONF_CLIENT_PRELOAD_NONE 0 +typedef void (*GConfClientNotifyFunc) (GConfClient* client, + guint cnxn_id, + GConfEntry *entry, + gpointer user_data); +static gboolean gconf_initialized = FALSE; +static gchar *gconf_hidden_key = NULL; +static GConfClient* (*gconf_client_get_default) (void); +static gboolean (*gconf_client_dir_exists) (GConfClient* client, + const gchar* dir, GError** err); +static gboolean (*gconf_client_get_bool) (GConfClient* client, const gchar* key, GError** err); +static void (*gconf_client_add_dir) (GConfClient* client, + const gchar* dir, + gint preload, + GError** err); +static guint (*gconf_client_notify_add) (GConfClient* client, + const gchar* namespace_section, + GConfClientNotifyFunc func, + gpointer user_data, + GFreeFunc destroy_notify, + GError** err); +static void (*gconf_client_notify_remove) (GConfClient* client, guint cnxn); + +static gboolean sn_launch_app (const gchar *name, const gchar *description, + const gchar *icon, gchar **argv); + + +static const guint8 new_folder_icon[] = +{ "" + /* Pixbuf magic (0x47646b50) */ + "GdkP" + /* length: header (24) + pixel_data (1622) */ + "\0\0\6n" + /* pixdata_type (0x2010002) */ + "\2\1\0\2" + /* rowstride (96) */ + "\0\0\0`" + /* width (24) */ + "\0\0\0\30" + /* height (24) */ + "\0\0\0\30" + /* pixel_data: */ + "\251\0\0\0\0\3\0\0\0!\0\0\0\377\0\0\0T\206\0\0\0\0\1\16\16\16Y\207\0" + "\0\0\377\2\0\0\0O\6\7\6\3\203\0\0\0\0\10\11\10\0P\7\7\0p\0\0\0\377\310" + "\305\0\363\0\0\0\377\11\11\0=\35\34\0\214\0\0\0\13\203\0\0\0\0\1\0\0" + "\0\377\206\216\222|\377\3fiX\377\0\0\0\377\1\2\1J\203\0\0\0\0\10\7\7" + "\0p\0\0\0\377\266\261\0\377\367\363\0\377\306\303\0\377\0\0\0\3771.\0" + "\277\0\0\0\20\203\0\0\0\0\11\0\0\0\377\241\244\214\377\204\207o\377\204" + "\206n\377\203\205m\377\202\204m\377\200\204l\377\205\210u\377gh[\377" + "\205\0\0\0\377\1\266\261\0\377\202\373\367\0\377\5\372\366\0\377\332" + "\326\0\377\0\0\0\377\0\0\0p\0\0\0\6\202\0\0\0\0\11\0\0\0\377\216\222" + "|\377twa\377swa\377sv`\377ru`\377qs_\377or]\377rrb\377\203ruc\377\3\0" + "\0\0\377\310\304\1\377\367\363\0\377\203\373\367\0\377\4\370\364\0\377" + "\307\305\2\377\0\0\0\377\0\0\0D\202\0\0\0\0\2\0\0\0\377\216\222|\377" + "\202hjW\377\202giV\377\1VXH\377\207\0\0\0\377\1\307\304\0\377\202\373" + "\367\0\377\5\371\365\0\377\340\334\0\377\36\35\0\377\0\0\0\377\0\0\0" + "\16\202\0\0\0\0\2\0\0\0\377\216\222|\377\202]`N\377\202\\_M\377\17\0" + "\0\0\377\242\243\233\377\330\331\314\377\326\327\312\377\322\324\307" + "\377\321\323\306\377\320\321\304\377\225\225\210\377\0\0\0\377\330\324" + "\0\377\355\351\0\377\337\333\0\377\0\0\0\37700\30\377\0\0\0\377\203\0" + "\0\0\0\206\0\0\0\377\2\247\250\241\377\333\334\317\377\205\303\305\261" + "\377\10ghO\377cc\"\377\0\0\0\377\310\305\3\377\0\0\0\377\77A\"\37741" + "\2\377\0\0\0\377\203\0\0\0\0\11\0\0\0\377\320\321\304\377\331\332\316" + "\377\331\331\315\377\327\330\314\377\327\327\312\377\326\327\311\377" + "\276\300\254\377\276\301\254\377\202\276\301\255\377\12\276\300\254\377" + "\277\301\255\377\266\267\245\377\257\260\236\377\233\235\215\377\0\0" + "\0\377LN<\377\272\273\247\377\203\205o\377\0\0\0\377\203\0\0\0\0\4\0" + "\0\0\377\327\330\314\377\272\274\250\377\273\274\250\377\205\272\274" + "\250\377\2\273\274\251\377\272\274\251\377\205\272\274\250\377\5\220" + "\221\201\377\272\274\251\377\272\274\250\377\217\221\177\377\0\0\0\377" + "\203\0\0\0\0\6\0\0\0\377\327\330\314\377\265\267\244\377\266\267\245" + "\377\266\270\244\377\265\267\244\377\202\266\270\244\377\2\265\267\244" + "\377\266\267\244\377\202\266\270\244\377\203\266\267\244\377\6\266\270" + "\244\377\266\267\244\377\265\270\244\377\266\270\244\377\214\216y\377" + "\0\0\0\377\203\0\0\0\0\2\0\0\0\377\327\330\314\377\203\261\263\240\377" + "\1\262\263\237\377\205\261\263\240\377\5\261\262\240\377\261\263\240" + "\377\262\263\240\377\261\263\240\377\262\262\240\377\203\261\263\240" + "\377\2\203\205u\377\0\0\0\377\203\0\0\0\0\2\0\0\0\377\327\330\314\377" + "\202\255\256\233\377\2\254\256\233\377\255\257\233\377\202\255\256\233" + "\377\1\254\256\234\377\202\255\256\234\377\204\255\256\233\377\6\255" + "\256\234\377\255\256\233\377\255\256\234\377\254\257\234\377\177\201" + "r\377\0\0\0\377\202\0\0\0\0\5\0\0\0\1\0\0\0\377\327\330\314\377\250\252" + "\227\377\251\252\227\377\210\250\252\227\377\3\250\251\227\377\250\252" + "\230\377\251\252\227\377\202\250\252\227\377\4\251\252\227\377\250\252" + "\227\377|~o\377\0\0\0\377\202\0\0\0\1\3\0\0\0\5\0\0\0\377\327\330\314" + "\377\202\244\245\222\377\202\243\245\223\377\202\244\245\223\377\4\244" + "\245\222\377\244\245\223\377\244\246\223\377\244\245\222\377\202\243" + "\245\223\377\2\244\245\222\377\244\245\223\377\202\243\245\223\377\10" + "\244\246\223\377{}m\377\0\0\0\377\0\0\0\6\0\0\0\5\0\0\0\21\0\0\0\377" + "\327\330\314\377\202\237\240\216\377\202\240\241\217\377\4\237\240\217" + "\377\237\241\216\377\237\240\216\377\237\241\217\377\202\237\241\216" + "\377\202\240\241\216\377\202\237\241\217\377\14\240\241\217\377\237\241" + "\216\377\240\241\217\377yzl\377\0\0\0\377\0\0\0\21\0\0\0\10\0\0\0\33" + "\0\0\0\377\327\330\314\377\233\234\212\377\232\234\212\377\204\233\234" + "\212\377\2\233\235\213\377\233\234\212\377\203\232\234\212\377\202\233" + "\234\212\377\20\233\234\213\377\233\234\212\377\232\234\212\377\233\234" + "\212\377wxj\377\0\0\0\377\0\0\0\31\0\0\0\12\0\0\0/\0\0\0\377\327\330" + "\314\377\227\227\206\377\227\230\206\377\226\227\206\377\227\230\206" + "\377\226\227\206\377\204\227\230\206\377\3\226\230\206\377\226\227\206" + "\377\227\227\206\377\205\226\230\206\377\10yzl\377\0\0\0\377\0\0\0-\0" + "\0\0\10\0\0\0""1\0\0\0\377\327\330\314\377\224\226\201\377\202\224\225" + "\202\377\1\222\223\202\377\202\222\223\201\377\3\221\223\201\377\222" + "\223\201\377\221\223\201\377\203\222\223\201\377\15\222\223\202\377\222" + "\223\201\377\222\223\202\377\222\224\201\377\222\223\201\377wxj\377\0" + "\0\0\377\0\0\0""0\0\0\0\4\0\0\0*\0\0\0\377\327\330\314\377\222\222|\377" + "\202\222\223|\377\5\215\216~\377\215\216}\377\216\217~\377\215\217}\377" + "\216\217}\377\202\215\217}\377\4\215\217~\377\215\216}\377\215\217~\377" + "\216\216}\377\202\216\217}\377\34\215\216}\377vxi\377\0\0\0\377\0\0\0" + "*\0\0\0\1\0\0\0\4\0\0\0\377\231\233\211\377\222\226|\377\221\224{\377" + "\216\221x\377\210\212y\377\206\210w\377\205\206u\377\202\203s\377\200" + "\201r\377}\177o\377|~o\377z|m\377y{l\377xyk\377vxi\377uwi\377uwh\377" + "vxi\377^`T\377\0\0\0\377\0\0\0\37\202\0\0\0\0\1\0\0\0\214\223\0\0\0\377" + "\2\0\0\0\204\0\0\0\16\202\0\0\0\0\5\0\0\0\12\0\0\0\15\0\0\0\23\0\0\0" + "\24\0\0\0\25\203\0\0\0\26\1\0\0\0\27\207\0\0\0\30\202\0\0\0\31\4\0\0" + "\0\26\0\0\0\22\0\0\0\13\0\0\0\6"}; + +#ifdef __SUNPRO_C +#pragma align 4 (desktop_icon) +#endif +#ifdef __GNUC__ +static const guint8 desktop_icon[] __attribute__ ((__aligned__ (4))) = +#else +static const guint8 desktop_icon[] = +#endif +{ "" + /* Pixbuf magic (0x47646b50) */ + "GdkP" + /* length: header (24) + pixel_data (1571) */ + "\0\0\6;" + /* pixdata_type (0x2010002) */ + "\2\1\0\2" + /* rowstride (96) */ + "\0\0\0`" + /* width (24) */ + "\0\0\0\30" + /* height (24) */ + "\0\0\0\30" + /* pixel_data: */ + "\311\0\0\0\0\26\300\262\235\33\334\323\304\321\312\275\243\377\276\256" + "\217\377\212\200v\377\230\220\233\377\236\225\242\377\230\217\234\377" + "\223\212\230\377\220\207\225\377\217\205\224\377\215\204\222\377\216" + "\204\223\377\214\202\221\377\212\200\217\377\200v\206\377pee\377\265" + "\260\247\377\354\351\341\377\321\306\257\377xoa\312ZOK\23\202\0\0\0\0" + "\26\302\265\236@\343\334\320\366\263\244\210\377[RH\377;1\77\377UF\\" + "\377VF]\377RCZ\377ZMa\377_Qf\377j^p\377obu\377{o\200\377MBR\377M>T\377" + "O@W\377J;Q\377G=I\377\217\213\212\377\315\301\252\377YQE\355B;66\202" + "\0\0\0\0\17\332\321\301H\306\300\270\376@86\3775*;\377J;R\377O@W\377" + "\206|\214\377\222\216\225\377\253\250\255\377\303\300\305\377\333\331" + "\334\377\346\344\346\377\366\365\366\377PPQ\3772'7\377\202L\217\205\224\357L0D\377@2G" + "\3774)9\3534)91\263\255\265Y~tu\370A3E\377J;R\377L\377\337\253Q\377\307{\24\377\267c\1\377t0\1\377D\31" + "\5\377\21\11\11\377\17\13\20\377\23\17\24\377FA=\377\311\304\273\377" + "\346\340\327\377\306\271\243\377\221\203s\3776,7\275\253\243\230\371" + "rlb\377^WL\377WND\377E=9\377#\34$\377'\36+\377+#(\377\226wC\377\330\236" + "B\377\310x\17\377\247X\2\377h'\1\377/\22\6\377\14\7\10\377\11\7\12\377" + "\24\17\26\377#\35#\377XON\377\207|t\377\203ys\377\201ul\377PEF\377%\36" + "'\350f_Yd(#%d\26\22\31d\33\26\37d+#,d'\40+d)#-h\232\225h\306\337\247" + "F\377\306r\10\377\232J\0\371]\40\1\366\31\10\1\362\2\1\2\354\3\2\3\310" + "\11\7\12\231\26\21\31y\40\32$i%\36*d\203&\37+d\2!\32%d\26\21\31d\206" + "\0\0\0\0\13\312\324\2447\334\332\257\363eS'\377p6\2\373E\26\0\356\11" + "\3\0\343\0\0\0\312\0\0\0\206\0\0\0D\0\0\0\35\0\0\0\6\215\0\0\0\0\12r" + "rW\245MH7\374\14\13\2\324\40\17\0\311\5\2\0\306\0\0\0\242\0\0\0W\0\0" + "\0(\0\0\0\17\0\0\0\3\216\0\0\0\0\11\27\27\21""1\7\6\2E\10\7\1X\0\0\0" + "\177\0\0\0f\0\0\0""7\0\0\0\24\0\0\0\5\0\0\0\1\220\0\0\0\0\5\0\0\0\1\0" + "\0\0\24\0\0\0\25\0\0\0\14\0\0\0\4\274\0\0\0\0"}; + +static const guint8 terminal_icon[] = +{ "" + /* Pixbuf magic (0x47646b50) */ + "GdkP" + /* length: header (24) + pixel_data (1990) */ + "\0\0\7\336" + /* pixdata_type (0x2010002) */ + "\2\1\0\2" + /* rowstride (96) */ + "\0\0\0`" + /* width (24) */ + "\0\0\0\30" + /* height (24) */ + "\0\0\0\30" + /* pixel_data: */ + "\231\0\0\0\0\3\0\0\0\2\0\0\0\4\0\0\0\5\220\0\0\0\6\12\0\0\0\5\0\0\0\4" + "\0\0\0\2\0\0\0\0\0\0\0\2B@A\304\201\202\201\377|||\377{||\377|{{\377" + "\203|}}\377\25{|z\377yyx\377xxw\377wxv\377wvu\377qrp\377mli\377jig\377" + "ged\377cca\377_^\\\377ec^\377'&$\312\0\0\0\17\0\0\0\3\0\0\0\4\204\203" + "\203\377\366\363\351\377\365\361\350\377\376\374\362\377\377\377\367" + "\377\202\377\377\370\377\13\377\377\367\377\377\376\366\377\377\374\364" + "\377\376\370\357\377\371\364\352\377\363\356\344\377\357\351\337\377" + "\345\340\327\377\335\327\315\377\324\315\304\377\310\303\270\377\202" + "\270\263\251\377\13\77\77:\377\0\0\0%\0\0\0\10\0\0\0\6||{\377\364\360" + "\346\377\202\200z\377EDA\377HEC\377FCA\377EC@\377\203EB@\377\177EC@\377" + "DC\77\377DB\77\377C@=\377A>;\377<;8\377;95\37720/\377qng\377\253\247" + "\235\377751\377\0\0\0""5\0\0\0\13\0\0\0\6||}\377\373\367\355\377DB\77" + "\377HMI\377qwr\377sxt\377y}y\377tyu\377mrn\377bic\377Y^Z\377KQL\377B" + "FC\377>B\77\3779=:\377061\377',(\377\22\30\24\377UTO\377\250\242\230" + "\37744/\377\0\0\0:\0\0\0\15\0\0\0\6zzy\377\367\363\353\377CA>\377puq" + "\377\264\267\264\377\257\260\257\377\243\246\243\377\223\230\223\377" + "\204\210\204\377qwq\377_d_\377SWS\377PVP\377LQL\377HMH\377=:\377svs\377\244\247\244\377\223\225\223\377" + "\211\215\211\377\201\206\201\377sxs\377glg\377bhb\377`f`\377\\a\\\377" + "V\\V\377PVP\377CHC\3776<6\377\37$\40\377TPK\377\226\223\210\377..*\377" + "\0\0\0<\0\0\0\16\0\0\0\6yyy\377\350\344\332\377>;8\377kpl\377\214\216" + "\214\377}\202}\377x\177x\377v~v\377x~x\377t{t\377pxp\377msm\377glg\377" + "aga\377W]W\377JMJ\3779>9\377\"&#\377QMG\377\214\211\177\377,+'\377\0" + "\0\0<\0\0\0\16\0\0\0\6rsr\377\337\332\317\377;85\377cgd\377rwr\377lq" + "l\377pvp\377}\203}\377\202\207\202\377\177\206\177\377|\202|\377t|t\377" + "ouo\377hmh\377]b]\377MSM\377=@=\377\177#'$\377NHD\377\203\200u\377)(" + "%\377\0\0\0<\0\0\0\16\0\0\0\6qpo\377\324\317\304\377763\377RYS\377X^" + "X\377djd\377t|t\377\200\205\200\377\205\212\205\377\204\212\204\377\201" + "\211\201\377{\201{\377u{u\377lrl\377_e_\377OTO\377<@<\377\"'#\377JGA" + "\377|vk\377&$\"\377\0\0\0<\0\0\0\16\0\0\0\6onm\377\312\305\271\37763" + "0\377JPK\377\232\236\232\377V]V\377ini\377y\177y\377\202\211\202\377" + "\203\211\203\377\201\207\201\377|\203|\377v|v\377lql\377_e_\377MRM\377" + "\377roe\377%#\37\377\0\0\0<\0\0\0\16\0\0\0\6mlk\377" + "\276\267\255\3772/,\377DLE\377\344\345\344\377\376\377\376\377\274\277" + "\274\377{\201{\377y~y\377~\204~\377{\203{\377y\177y\377rxr\377gng\377" + "\\b\\\377KPK\377:>:\377#(%\377GC;\377kf]\377\"!\35\377\0\0\0<\0\0\0\16" + "\0\0\0\6ffc\377\260\254\240\377/,(\377>D\77\377]a]\377\241\244\241\377" + "\377\377\377\377\233\237\233\377ele\377dld\377djd\377cic\377bgb\377\\" + "a\\\377QVQ\377BIB\3777:7\377\"%#\377D@:\377d_V\377\37\36\33\377\0\0\0" + "<\0\0\0\16\0\0\0\6`^]\377\246\240\226\377*(%\377=D>\377\377\377\377\377" + "\215\220\215\377OTO\377RXR\377\206\213\206\377\316\321\316\377\320\322" + "\320\377\220\224\220\377OVO\377JQJ\377AEA\3778=8\377.3.\377\36#\37\377" + "C\77""8\377]XN\377\35\33\30\377\0\0\0<\0\0\0\16\0\0\0\6\177[ZV\377\230" + "\222\206\377#!\36\377.71\377082\3774<6\377BHC\377FKH\377BHC\377;A=\377" + "6>7\3776<7\3776=8\377274\377,1.\377&,(\377\40#\"\377\21\27\24\377>:4" + "\377SPF\377\33\32\26\377\0\0\0<\0\0\0\16\0\0\0\6WUS\377\210\202w\377" + "li`\377WSM\377WUM\377WTN\377UQJ\377TPI\377RNG\377RNE\377OKD\377NIC\377" + "LHA\377KG\77\377JD<\377HD:\377FC:\377C\77""5\377hdU\377RNC\377\33\33" + "\27\377\0\0\0<\0\0\0\16\0\0\0\6RQO\377yti\377vrf\377yui\377zsi\377ws" + "i\377vqg\377qlb\377oi^\377ieY\377c_U\377_\\P\377\\YM\377XVJ\377VRF\377" + "RND\377TQG\377eaX\377MJ@\377QNC\377\33\33\27\377\0\0\0<\0\0\0\16\0\0" + "\0\6RPK\376upd\377pj_\377lh\\\377lg\\\377hdZ\377fbW\377b^R\377_[O\377" + "[WK\377ZUJ\377WRG\377TQE\377RND\377QLB\377MJ\77\377ZVM\377A<3\377HF;" + "\377URF\377\"!\34\377\0\0\0""9\0\0\0\15\0\0\0\5!\40\36\316!\37\33\377" + "omg\375ljc\377qoh\377vsm\377xvo\377zwq\377xvn\377tpk\377qnh\377kid\377" + "jfa\377eb]\377a_W\377\\ZT\377[YR\377\\[T\377UQK\376\31\31\25\377\21\20" + "\16\336\0\0\0/\0\0\0\12\0\0\0\2\0\0\0\24\0\0\0s/.,\372#\"\35\377)'$\377" + "./*\377642\377\26""896\377763\377541\37732/\37710-\377,-(\377)(%\377" + "$\"\37\377\40\40\33\377\37\36\31\377\40\36\32\377\34\33\27\374\0\0\0" + "\221\0\0\0>\0\0\0\31\0\0\0\5\0\0\0\1\0\0\0\6\0\0\0\25\0\0\0.\0\0\0B\0" + "\0\0J\203\0\0\0K\207\0\0\0L\202\0\0\0K\6\0\0\0J\0\0\0C\0\0\0/\0\0\0\26" + "\0\0\0\6\0\0\0\1\202\0\0\0\0\3\0\0\0\4\0\0\0\12\0\0\0\21\204\0\0\0\24" + "\207\0\0\0\25\203\0\0\0\24\4\0\0\0\21\0\0\0\12\0\0\0\4\0\0\0\1\205\0" + "\0\0\0\203\0\0\0\1\213\0\0\0\2\202\0\0\0\1\204\0\0\0\0"}; + +static const guint8 fm_icon[] = +{ "" + /* Pixbuf magic (0x47646b50) */ + "GdkP" + /* length: header (24) + pixel_data (1756) */ + "\0\0\6\364" + /* pixdata_type (0x2010002) */ + "\2\1\0\2" + /* rowstride (96) */ + "\0\0\0`" + /* width (24) */ + "\0\0\0\30" + /* height (24) */ + "\0\0\0\30" + /* pixel_data: */ + "\210\0\0\0\0\1\340\247\2123\204\340\247\212Z\1\340\247\2128\217\0\0\0" + "\0\14\375\274\232\13\366\270\227c\361\265\216\263\355\256s\336\351\253" + "k\377\353\254c\377\354\257l\377\354\263w\377\357\270\201\342\363\273" + "\220\263\367\270\226l\377\303\240\14\212\0\0\0\0\20\376\277\236\13\357" + "\260\213g\352\243t\342\345\231R\377\353\230>\377\356\237D\377\360\251" + "P\377\361\261U\377\364\276`\377\365\305f\377\370\320v\377\370\311f\377" + "\351\231M\377\360\264\202\353\366\303\237g\377\301\241\21\206\0\0\0\0" + "\24\377\304\244\1\357\261\224_\345\242|\310\337\214M\377\342\213@\377" + "\345\220D\377\346\222D\377\344\224F\377\344\231F\377\347\242I\377\361" + "\263V\377\364\276`\377\365\312n\377\366\307d\377\345\201)\377\347\223" + "9\377\362\316\203\377\361\277\226\313\357\261\224h\377\302\241\3\204" + "\0\0\0\0\24\353\256\221Z\325\212c\377\324w9\377\326}A\377\323yE\377\317" + "s\77\377\311e7\377\302_2\377\271g-\377\313x1\377\340\2108\377\345\221" + "9\377\356\250E\377\360\253H\377\331l)\377\335r!\377\356\255R\377\370" + "\330\202\377\346\261~\377\357\263\225h\203\0\0\0\0\26\325\231|c\310|" + "Z\361\300c5\377\277h>\377\267`8\377\257U4\377\254O-\377\254G*\377\255" + "G(\377\254W(\377\265g+\377\315r.\377\331|/\377\345\2167\377\347\222;" + "\377\306P&\377\324b#\377\340\2034\377\367\314d\377\354\242\77\377\355" + "\265\211\363\367\271\233T\202\0\0\0\0\177\314\214o\377\245R1\377\250" + "W6\377\236M0\377\227D*\377\225A)\377\241F-\377\247A+\377\254A'\377\266" + "Q-\377\267].\377\276l/\377\315w1\377\334\2106\377\350\213:\377\324l3" + "\377\311U$\377\331m*\377\353\235@\377\346\204'\377\355\260[\377\360\275" + "\223\265\375\275\235\7\0\0\0\0\316\220t\377\231P6\377\211A*\377\204;" + "'\377\212=&\377\221\77&\377\241I.\377\256L3\377\254D)\377\276[6\377\301" + "i<\377\273p9\377\301q;\377\265j4\377\274c.\377\316m0\377\275Q(\377\310" + "]$\377\333s2\377\337v'\377\353\234F\377\360\310\201\377\372\277\2332" + "\0\0\0\0\324\231}\241\232U@\377u3!\377y7#\377\204<&\377\223C+\377\240" + "L1\377\265^=\377\270V6\377\302d>\377\305pH\377\273oI\377\257gJ\377\234" + "Z\77\377\216I2\377\2058\40\377\2158\"\377\263M&\377\320b-\377\326f%\377" + "\343\215E\377\370\315a\377\363\274\221\263\0\0\0\0\337\246\211A\317\224" + "y\353q5&\377t3!\377|8$\377\222E,\377\241L4\377\254X8\377\262]<\377\257" + "_B\377\266oP\377\277\201_\377\311\212m\377\321\210p\377\273nT\377\211" + "\77%\377}3\35\377\265\\3\377\315k6\377\317^%\377\344\215I\377\354\235" + "5\377\353\243h\371\341\252\214R\0\0\0\0\360\263\224L\260v`\377t6#\377" + "{7#\377\216@(\377\230E.\377\234K1\377\231K2\377\223H2\377\233T>\377\256" + "mT\377\264v]\377\251iN\377\270vX\377\303\203\\\377\325\225^\377\315|" + "L\377\303n>\377\327{G\377\337~A\377\330e\37\377\343\220L\377\340\252" + "\207\300\0\0\0\0\377\304\241\0\360\264\226J\303\210m\353\206D/\377\203" + ";%\377\204=)\377\21\201>,\377~;-\377\207A6\377\257mQ\377\273uK\377\266" + "n@\377\272pG\377\236X1\377\223S7\377\332\233x\377\332\214_\377\314{L" + "\377\336\205Q\377\310Y\"\377\330l1\377\352\237N\377\340\243w\377\203" + "\0\0\0\0\25\375\275\235\77\312\213q\237\226UA\376o2#\377n3#\377i/%\377" + "\250dH\377\306xJ\377\274o>\377\311~D\377\317\177C\377\267f7\377\207C" + "%\377\222X7\377\361\277\200\377\337\220Y\377\324wA\377\322k4\377\350" + "\243p\377\343\217B\377\333\235u\377\205\0\0\0\0\23\362\264\225\201\247" + "nY\320xG8\377yE7\377\305sD\377\245\\1\377\257c1\377\314zD\377\270z\\" + "\377\267{W\377\276}S\377\206M3\377\323\224e\377\336\216[\377\335\215" + "[\377\355\270\212\377\345\232P\377\334z3\377\325\230v\377\206\0\0\0\0" + "\22\360\262\222#\302\220w\330\260y^\377\273h8\377\210H+\377\177\77&\377" + "\301z\\\377\273\203g\377\250xk\377\320\211W\377\266}Y\377\334\222U\377" + "\350\243e\377\340\223Z\377\335\210=\377\330u1\377\343\226`\377\312\223" + "r\377\207\0\0\0\0\21\262\206o7\252v`\377\242P+\377l5#\377M)\37\377\256" + "t]\377h5\40\377{J9\377\320}\77\377\343\251u\377\331\205J\377\323|D\377" + "\331\200B\377\334\202\77\377\361\274\216\377\356\247m\377\265\204h\377" + "\207\0\0\0\0\21\202bQ7\262\202g\377\235Q-\377U)\35\377J*\"\377nJ=\377" + "\257y`\377\263rA\377\344\247f\377\305}Z\377\310h,\377\332\221X\377\330" + "\203P\377\342\231c\377\337\217K\377\352\245v\377\211hW\351\207\0\0\0" + "\0\21T\77""4\34\310\232\201\311\240\\=\377Y(\30\377G$\40\377D\"\33\377" + "c<4\377\211[C\377\204D3\377\250R&\377\264[.\377\271c5\377\307m8\377\314" + "i+\377\332\202A\377\320\240\206\377\207dSZ\210\0\0\0\0\20\230s`u\315" + "\216m\373r;&\377E\40\32\377J'\37\377P&\36\377T\"\32\377{;#\377\204=!" + "\377\272m@\377\301m@\377\312k:\377\332\207Q\377\350\253x\377\240xe\277" + "YB7\17\211\0\0\0\0\16\367\274\234\221\266wU\377X%\31\377U)\37\377b2\37" + "\377^+\37\377\216M)\377\230J)\377\252T.\377\300nA\377\317yE\377\347\233" + "d\377\241x^\377/$\36Z\212\0\0\0\0\16\377\303\241\7\324\233{\251\303\204" + "^\377\215K(\377u5\36\377\207A#\377\222@\40\377\243T0\377\271a5\377\314" + "q=\377\325\215f\377\237t`\310D4+_K8.\1\213\0\0\0\0\13\201`P@\220kW\373" + "\326\222d\377\277h3\377\267e5\377\271],\377\303k:\377\327\214^\377\335" + "\241y\377\240yd\255\250~h\13\216\0\0\0\0\11\\E9\15\215kY~\340\250\212" + "\263\345\253\216\263\355\261\222\263\342\251\214\263\212hW\263\207eU" + ")}]M\6\234\0\0\0\0"}; + #ifndef G_PLATFORM_WIN32 #define compare_utf8_filenames(a, b) strcmp(a, b) @@ -640,6 +1078,143 @@ } } +static gchar * +read_line_from_command (gchar *command) +{ + gchar *argv[] = { "/bin/sh", "-c", command, NULL }; + gint output, pid; + GIOChannel *io; + gchar *data = NULL, *line; + gsize term; + + if (!g_spawn_async_with_pipes (NULL, argv, NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &pid, NULL, &output, NULL, NULL)) + return g_strdup (""); + + io = g_io_channel_unix_new (output); + g_io_channel_set_close_on_unref (io, TRUE); + g_io_channel_read_line (io, &data, NULL, &term, NULL); + g_io_channel_unref (io); + + if (!data) return NULL; + line = g_strndup (data, term); + g_free (data); + return line; +} + +static void +notify_show_hidden (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer fs) +{ + _gtk_fnmatch_show_hidden = gconf_client_get_bool (gconf_client_get_default (), + gconf_hidden_key, NULL); + gtk_file_selection_refresh (NULL, GTK_FILE_SELECTION (fs)); +} + +static void +widget_force_hide (GtkWidget *widget) +{ + g_signal_stop_emission_by_name (widget, "show"); + gtk_widget_hide (widget); +} + +static void bookmarks_popup_pos (GtkMenu *menu, gint *x, gint *y, gboolean push_in, GtkWidget *button); + +static gboolean +handle_key_presses (GtkFileSelection *fs, GdkEventKey *event) +{ + if ((event->state & GDK_CONTROL_MASK) && event->keyval == GDK_l) + { + GtkCombo *combo; + + combo = (GtkCombo *) g_object_get_data (G_OBJECT (fs), "__combo"); + gtk_widget_grab_focus (combo->entry); + } + else if ((event->state & GDK_MOD1_MASK) && event->keyval == GDK_Left) + gtk_file_selection_back (NULL, fs); + else if ((event->state & GDK_MOD1_MASK) && event->keyval == GDK_Up) + gtk_file_selection_up (NULL, fs); + else if ((event->state & GDK_CONTROL_MASK) && event->keyval == GDK_r) + gtk_file_selection_refresh (NULL, fs); + else if ((event->state & GDK_MOD1_MASK) && event->keyval == GDK_Home) + gtk_file_selection_home (NULL, fs); + else if ((event->state & GDK_MOD1_MASK) && event->keyval == GDK_b) + { + GtkWidget *button, *menu; + + button = (GtkWidget *) g_object_get_data (G_OBJECT (fs), "__bookmarks_button"); + menu = (GtkWidget *) g_object_get_data (G_OBJECT (fs), "__bookmarks"); + + g_object_set (button, "active", TRUE, NULL); + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, + (GtkMenuPositionFunc) bookmarks_popup_pos, button, + 1, event->time); + } + else if ((event->state & GDK_CONTROL_MASK) && (event->state & GDK_SHIFT_MASK) && event->keyval == GDK_N) + gtk_file_selection_create_dir (NULL, fs); + else if ((event->state & GDK_CONTROL_MASK) && event->keyval == GDK_t) + gtk_file_selection_launch_terminal (NULL, fs); + else if ((event->state & GDK_CONTROL_MASK) && event->keyval == GDK_f) + gtk_file_selection_launch_fm (NULL, fs); + else + return FALSE; + + return TRUE; +} + +static void +history_combo_activate (GtkEntry *entry, GtkFileSelection *fs) +{ + gchar *dir; + gint len; + + if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (entry), "__busy"))) + return; + g_object_set_data (G_OBJECT (entry), "__busy", GINT_TO_POINTER (TRUE)); + + dir = (gchar *) gtk_entry_get_text (entry); + if (dir[strlen (dir) - 1] != G_DIR_SEPARATOR) + dir = g_strdup_printf ("%s%c", dir, G_DIR_SEPARATOR); + else + dir = g_strdup (dir); + gtk_file_selection_populate (fs, dir, FALSE, FALSE); + + g_free (dir); + dir = (gchar *) gtk_entry_get_text (entry); + len = strlen (dir); + if (len > 1 && dir[len - 1] == G_DIR_SEPARATOR) + { + dir = g_strndup (dir, len - 1); + gtk_entry_set_text (entry, dir); + } + + if ((gpointer) gtk_window_get_focus (GTK_WINDOW (fs)) == (gpointer) entry) + gtk_widget_grab_focus (fs->selection_entry); + g_object_set_data (G_OBJECT (entry), "__busy", GINT_TO_POINTER (FALSE)); +} + +static void +history_combo_selected (GtkList *list, GtkBin *item, GtkFileSelection *fs) +{ + GtkCombo *combo; + GList *nav_history; + const gchar *current, *entry, *selected; + + if (!GTK_WIDGET_HAS_FOCUS (item)) + return; + + nav_history = (GList *) g_object_get_data (G_OBJECT (fs), "__nav_history"); + if (!nav_history) return; + current = (const gchar *) g_list_last (nav_history)->data; + + combo = GTK_COMBO (g_object_get_data (G_OBJECT (fs), "__combo")); + entry = gtk_entry_get_text (GTK_ENTRY (combo->entry)); + selected = gtk_label_get_text (GTK_LABEL (gtk_bin_get_child (item))); + + if (strcmp (entry, selected) == 0 && strcmp (entry, current) != 0) + history_combo_activate (GTK_ENTRY (combo->entry), fs); +} + static gboolean grab_default (GtkWidget *widget) { @@ -648,61 +1223,651 @@ } static void +popup_deactivate (GtkMenuShell *menu, + gpointer button) +{ + g_object_set (button, "active", FALSE, NULL); +} + +static void +back_menu_activate (GtkWidget *item, + gpointer dp) +{ + GtkWidget *fs; + GList *nav_history; + gint i, l, d; + gchar *dir; + + fs = GTK_WIDGET (g_object_get_data (G_OBJECT (item), "fs")); + nav_history = g_object_get_data (G_OBJECT (fs), "__nav_history"); + l = (gint) g_list_length (nav_history); + d = GPOINTER_TO_INT (dp); + dir = g_strdup_printf ("%s/", (gchar *) g_list_nth_data (nav_history, d)); + + for (i = l - 1; i >= d; i--) + { + GList *nth = g_list_nth (nav_history, i); + g_free (nth->data); + nav_history = g_list_remove_link (nav_history, nth); + } + g_object_set_data (G_OBJECT (fs), "__nav_history", nav_history); + gtk_file_selection_populate (GTK_FILE_SELECTION (fs), dir, FALSE, FALSE); + g_free (dir); +} + +static void +update_nav_history_popup (GtkWidget *fs) +{ + GList *nav_history; + GtkWidget *back_dropdown; + GtkWidget *menu; + guint i, l; + + nav_history = g_object_get_data (G_OBJECT (fs), "__nav_history"); + back_dropdown = g_object_get_data (G_OBJECT (fs), "__back_dropdown"); + menu = g_object_get_data (G_OBJECT (back_dropdown), "menu"); + + if (menu) gtk_widget_destroy (menu); + menu = gtk_menu_new (); + l = g_list_length (nav_history); + for (i = l - 1; i > 0; i--) + { + GtkWidget *item; + + item = gtk_menu_item_new_with_label ((gchar *) g_list_nth_data (nav_history, + i - 1)); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + g_object_set_data (G_OBJECT (item), "fs", fs); + g_signal_connect (item, "activate", G_CALLBACK (back_menu_activate), + GINT_TO_POINTER ((gint) (i - 1))); + } + gtk_widget_show_all (menu); + g_object_set_data (G_OBJECT (back_dropdown), "menu", menu); + + g_signal_connect (menu, "deactivate", G_CALLBACK (popup_deactivate), + back_dropdown); +} + +static void +back_popup_pos (GtkMenu *menu, + gint *x, + gint *y, + gboolean push_in, + GtkWidget *button) +{ + gdk_window_get_origin (button->window, x, y); + *x += button->allocation.x; + *y += button->allocation.y + button->requisition.height - 1; +} + +static gboolean +back_menu (GtkWidget *button, + GdkEventButton *event, + gpointer data) +{ + GtkWidget *menu; + + if (event->button != 1) return FALSE; + g_object_set (button, "active", TRUE, NULL); + menu = g_object_get_data (G_OBJECT (button), "menu"); + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, + (GtkMenuPositionFunc) back_popup_pos, button, + 1, event->time); + return TRUE; +} + +static void +bookmarks_item_clicked (GtkWidget *widget, + gchar *dir) +{ + GtkFileSelection *fs = GTK_FILE_SELECTION (g_object_get_data (G_OBJECT (widget), "fs")); + gchar *realDir; + + realDir = g_strdup_printf ("%s/", dir); + gtk_file_selection_populate (fs, realDir, FALSE, FALSE); + g_free (realDir); +} + +static void +bookmarks_popup_pos (GtkMenu *menu, + gint *x, + gint *y, + gboolean push_in, + GtkWidget *button) +{ + gdk_window_get_origin (button->window, x, y); + *x += button->allocation.x; + *y += button->allocation.y + button->requisition.height - 1; +} + +static gboolean +bookmarks_popup (GtkWidget *widget, + GdkEventButton *event, + GtkMenu *menu) +{ + if (event->button != 1) return FALSE; + g_object_set (widget, "active", TRUE, NULL); + gtk_menu_popup (menu, NULL, NULL, + (GtkMenuPositionFunc) bookmarks_popup_pos, widget, + 1, event->time); + return TRUE; +} + +static void +bookmarks_add (GtkWidget *item, GtkWidget *bookmarks_button) +{ + GtkWidget *fs = gtk_widget_get_toplevel (bookmarks_button); + gchar *filename; + GIOChannel *io; + + filename = g_strdup_printf ("%s/.gtk-bookmarks", g_get_home_dir ()); + io = g_io_channel_new_file (filename, "a", NULL); + if (io) + { + GList *nav_history; + gchar *dir; + + nav_history = g_object_get_data (G_OBJECT (fs), "__nav_history"); + dir = (gchar *) g_list_last (nav_history)->data; + g_io_channel_write_chars (io, dir, strlen (dir), NULL, NULL); + g_io_channel_write_chars (io, "\n", strlen ("\n"), NULL, NULL); + g_io_channel_unref (io); + + reload_bookmarks (bookmarks_button, fs); + } + else + { + GtkWidget *dialog; + + dialog = gtk_message_dialog_new (GTK_WINDOW (fs), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "Unable to write to %s", filename); + g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); + gtk_widget_show (dialog); + } + g_free (filename); +} + +static void +bookmarks_edit (GtkWidget *item, + GtkWidget *bookmarks_button) +{ + GtkWidget *fs = gtk_widget_get_toplevel (bookmarks_button); + GtkWidget *dialog; + gchar *filename, *prog; + + filename = g_strdup_printf ("%s/.gtk-bookmarks", g_get_home_dir ()); + prog = g_find_program_in_path ("gedit"); + if (prog) + { + gboolean use_sn; + gchar *argv[] = {"gedit", NULL, NULL}; + + g_free (prog); + use_sn = (system ("gedit --version | awk '{ver=$3;if($3>2.2)exit 0;else exit 1}'") == 0); + argv[1] = filename; + + if (!g_file_test (filename, G_FILE_TEST_EXISTS)) + { + FILE *f; + f = fopen (filename, "w"); + if (f) fclose (f); + } + + if (use_sn) + { + gchar *icon = NULL; + GnomeProgram *app; + + if (icon_theme_initialized && (app = gnome_program_get ())) + icon = gnome_program_locate_file (app, GNOME_FILE_DOMAIN_PIXMAP, + "gedit-icon.png", FALSE, NULL); + else + { + gchar *prefix; + + prefix = read_line_from_command ("pkg-config --variable=prefix libgnomeui-2.0"); + if (*prefix == '\0') + icon = g_strdup ("/usr/share/pixmaps/gedit-icon.png"); + else + icon = g_strdup_printf ("%s/share/pixmaps/gedit-icon.png", prefix); + g_free (prefix); + } + + sn_launch_app ("Text Editor", "Starting Text Editor", icon, argv); + if (icon) g_free (icon); + } + else + g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); + + g_free (filename); + return; + } + + dialog = gtk_message_dialog_new (GTK_WINDOW (fs), + GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + "The bookmark editor hasn't been implemented yet.\n" + "Please open your favorite text editor and edit:\n" + "%s", filename); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 8); + g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); + gtk_widget_show (dialog); + g_free (filename); +} + +static void +reload_bookmarks (GtkWidget *bookmarks_button, GtkWidget *fs) +{ + GtkWidget *menu, *add, *edit; + GtkTooltips *tips = NULL; + gchar *filename; + GIOChannel *io; + gulong signal; + + /* Destroy the previous menu */ + menu = g_object_get_data (G_OBJECT (fs), "__bookmarks"); + if (menu) + gtk_widget_destroy (menu); + signal = (gulong) GPOINTER_TO_INT (g_object_get_data (G_OBJECT (fs), "__bookmarks_signal")); + if (signal > 0) + g_signal_handler_disconnect (bookmarks_button, signal); + + + /* Create the menu */ + menu = gtk_menu_new (); + gtk_menu_set_title (GTK_MENU (menu), _("Bookmarks")); + add = gtk_menu_item_new_with_mnemonic (_("_Add to bookmarks")); + edit = gtk_menu_item_new_with_mnemonic (_("_Edit bookmarks...")); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), add); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), edit); + + g_signal_connect (add, "activate", G_CALLBACK (bookmarks_add), + bookmarks_button); + g_signal_connect (edit, "activate", G_CALLBACK (bookmarks_edit), + bookmarks_button); + + tips = gtk_tooltips_new (); + g_signal_connect_swapped (menu, "destroy", G_CALLBACK (gtk_object_destroy), tips); + + /* Load the bookmark file */ + filename = g_strdup_printf ("%s/.gtk-bookmarks", g_get_home_dir ()); + io = g_io_channel_new_file (filename, "r", NULL); + if (io) + { + gchar *tmp, *dir; + gsize term; + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), + gtk_menu_item_new ()); + while (g_io_channel_read_line (io, &tmp, NULL, &term, NULL) == G_IO_STATUS_NORMAL) + { + GtkWidget *item; + + dir = g_strndup (tmp, term); + g_free (tmp); + if (strlen (dir) == 0) + { + g_free (dir); + continue; + } + + item = gtk_menu_item_new_with_label (g_path_get_basename (dir)); + gtk_tooltips_set_tip (tips, item, dir, NULL); + g_object_set_data (G_OBJECT (item), "fs", fs); + g_signal_connect (item, "activate", G_CALLBACK (bookmarks_item_clicked), + dir); + g_signal_connect_swapped (item, "destroy", G_CALLBACK (g_free), dir); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + } + + g_io_channel_unref (io); + } + g_free (filename); + + + gtk_widget_show_all (menu); + signal = g_signal_connect (bookmarks_button, "button-press-event", + G_CALLBACK (bookmarks_popup), menu); + g_signal_connect (menu, "deactivate", G_CALLBACK (popup_deactivate), + bookmarks_button); + g_object_set_data (G_OBJECT (fs), "__bookmarks", menu); + g_object_set_data (G_OBJECT (fs), "__bookmarks_signal", GINT_TO_POINTER ((int) signal)); +} + +static void +sort_by_anything (GtkTreeViewColumn *column, GtkTreeView *view, gint sort_column, GtkSortType default_sort) +{ + GtkTreeModel *model = gtk_tree_view_get_model (view); + GList *list, *cols = gtk_tree_view_get_columns (view); + gint sort_id; + GtkSortType sort_type; + + for (list = cols; list; list = list->next) + { + GtkTreeViewColumn *col = (GtkTreeViewColumn *) list->data; + gtk_tree_view_column_set_sort_indicator (col, FALSE); + } + g_list_free (cols); + + gtk_tree_view_column_set_sort_indicator (column, TRUE); + gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), &sort_id, &sort_type); + if (sort_id == sort_column) + { + sort_type = (sort_type == GTK_SORT_ASCENDING) ? GTK_SORT_DESCENDING : GTK_SORT_ASCENDING; + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), sort_column, sort_type); + gtk_tree_view_column_set_sort_order (column, sort_type); + } + else + { + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), sort_column, default_sort); + gtk_tree_view_column_set_sort_order (column, default_sort); + } + + /* Save sort option */ + +} + +static void +sort_by_name (GtkTreeViewColumn *column, GtkTreeView *view) +{ + sort_by_anything (column, view, FILE_COLUMN, GTK_SORT_ASCENDING); +} + +static void +sort_by_type (GtkTreeViewColumn *column, GtkTreeView *view) +{ + sort_by_anything (column, view, TYPE_COLUMN, GTK_SORT_ASCENDING); +} + +static void +sort_by_size (GtkTreeViewColumn *column, GtkTreeView *view) +{ + sort_by_anything (column, view, SIZE_DATA_COLUMN, GTK_SORT_DESCENDING); +} + +static void +sort_by_date (GtkTreeViewColumn *column, GtkTreeView *view) +{ + sort_by_anything (column, view, DATE_DATA_COLUMN, GTK_SORT_DESCENDING); +} + +static gint +default_sort_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) +{ + return 0; +} + +static void gtk_file_selection_init (GtkFileSelection *filesel) { + GtkWidget *toolbar; + GtkWidget *back; + GtkWidget *back_dropdown; + GtkWidget *back_dropdown_arrow; + GtkWidget *bookmarks; + GtkWidget *bookmarks_icon; GtkWidget *entry_vbox; GtkWidget *label; GtkWidget *list_hbox, *list_container; GtkWidget *confirm_area; GtkWidget *pulldown_hbox; + GtkWidget *combo; GtkWidget *scrolled_win; GtkWidget *eventbox; - GtkWidget *spacer; + GtkWidget *vbox, *hbox; + GtkWidget *filter_combo; GtkDialog *dialog; GtkListStore *model; GtkTreeViewColumn *column; + GParamSpec *action_area_border; + GParamSpec *toolbar_shadow; + GdkPixbuf *icon; gtk_widget_push_composite_child (); + simple_mode = (g_getenv ("GTK_FILESEL_SIMPLE") && strcmp (g_getenv ("GTK_FILESEL_SIMPLE"), "1") == 0); + + /* Dirty hack to use gconf, gnome-vfs and libgnomeui without depending on them */ + if (!gnome_mod && g_module_supported ()) + { + gnome_mod = g_module_open (NULL, G_MODULE_BIND_LAZY); + gboolean (*gnome_vfs_initialized) (void); + gboolean (*gnome_vfs_init) (void); + + if (!gnome_mod) goto stop_mod; + + if (g_module_symbol (gnome_mod, "gconf_client_get_default", (gpointer *) &gconf_client_get_default) + && g_module_symbol (gnome_mod, "gconf_client_dir_exists", (gpointer *) &gconf_client_dir_exists) + && g_module_symbol (gnome_mod, "gconf_client_get_bool", (gpointer *) &gconf_client_get_bool) + && g_module_symbol (gnome_mod, "gconf_client_add_dir", (gpointer *) &gconf_client_add_dir) + && g_module_symbol (gnome_mod, "gconf_client_notify_add", (gpointer *) &gconf_client_notify_add) + && g_module_symbol (gnome_mod, "gconf_client_notify_remove", (gpointer *) &gconf_client_notify_remove) + && gconf_client_get_default ()) + { + gconf_initialized = TRUE; + if (gconf_client_dir_exists (gconf_client_get_default (), "/desktop/gnome/file_views", NULL)) + gconf_hidden_key = "/desktop/gnome/file_views/show_hidden_files"; /* GNOME 2.2 */ + else + gconf_hidden_key = "/apps/nautilus/preferences/show_hidden_files"; /* GNOME 2.2 */ + + + _gtk_fnmatch_show_hidden = gconf_client_get_bool (gconf_client_get_default (), + gconf_hidden_key, NULL); + gconf_client_add_dir (gconf_client_get_default (), + gconf_hidden_key, + GCONF_CLIENT_PRELOAD_NONE, + NULL); + } + + if (simple_mode) goto stop_mod; + + if (g_module_symbol (gnome_mod, "gnome_vfs_initialized", (gpointer *) &gnome_vfs_initialized) + && g_module_symbol (gnome_mod, "gnome_vfs_init", (gpointer *) &gnome_vfs_init)) + { + vfs_initialized = (*gnome_vfs_initialized) (); + if (!vfs_initialized) + vfs_initialized = gnome_vfs_init (); + + if (!vfs_initialized + || !g_module_symbol (gnome_mod, "gnome_vfs_file_info_new", (gpointer *) &gnome_vfs_file_info_new) + || !g_module_symbol (gnome_mod, "gnome_vfs_get_file_info", (gpointer *) &gnome_vfs_get_file_info) + || !g_module_symbol (gnome_mod, "gnome_vfs_file_info_get_mime_type", (gpointer *) &gnome_vfs_file_info_get_mime_type) + || !g_module_symbol (gnome_mod, "gnome_vfs_mime_get_description", (gpointer *) &gnome_vfs_mime_get_description) + || !g_module_symbol (gnome_mod, "gnome_vfs_mime_get_icon", (gpointer *) &gnome_vfs_mime_get_icon) + || !g_module_symbol (gnome_mod, "gnome_vfs_file_info_unref", (gpointer *) &gnome_vfs_file_info_unref)) + vfs_initialized = FALSE; + + if (vfs_initialized + && g_module_symbol (gnome_mod, "gnome_icon_theme_new", (gpointer *) &gnome_icon_theme_new) + && g_module_symbol (gnome_mod, "gnome_icon_theme_lookup_icon", (gpointer *) &gnome_icon_theme_lookup_icon) + && g_module_symbol (gnome_mod, "gnome_icon_theme_append_search_path", (gpointer *) &gnome_icon_theme_append_search_path)) + icon_theme_initialized = TRUE; + + if (icon_theme_initialized + && g_module_symbol (gnome_mod, "gnome_program_get", (gpointer *) &gnome_program_get) + && g_module_symbol (gnome_mod, "gnome_program_locate_file", (gpointer *) &gnome_program_locate_file)) + { + GnomeProgram *app = gnome_program_get (); + + if (app) + gnome_program_locate_file (app, GNOME_FILE_DOMAIN_PIXMAP, "document-icons", FALSE, &icon_theme_paths); + } + } + } + stop_mod: + + if (gconf_initialized) + { + guint id = gconf_client_notify_add (gconf_client_get_default (), + gconf_hidden_key, + notify_show_hidden, + filesel, NULL, NULL); + g_object_set_data (G_OBJECT (filesel), "__notify_show_hidden", GINT_TO_POINTER ((gint) id)); + } + else + { + gchar *show_hidden; + + show_hidden = read_line_from_command ("gconftool-2 --get /desktop/gnome/file_views/show_hidden_files"); + if (strcmp (show_hidden, "") == 0) + { + /* GNOME 2.0 */ + g_free (show_hidden); + show_hidden = read_line_from_command ("gconftool-2 --get /apps/nautilus/preferences/show_hidden_files"); + _gtk_fnmatch_show_hidden = (strcmp (show_hidden, "true") == 0); + } + else + /* GNOME 2.2 */ + _gtk_fnmatch_show_hidden = (strcmp (show_hidden, "true") == 0); + g_free (show_hidden); + } + + dialog = GTK_DIALOG (filesel); + g_signal_connect (filesel, "key-press-event", G_CALLBACK (handle_key_presses), NULL); filesel->cmpl_state = cmpl_init_state (); /* The dialog-sized vertical box */ filesel->main_vbox = dialog->vbox; - gtk_container_set_border_width (GTK_CONTAINER (filesel), 10); + gtk_box_set_spacing (GTK_BOX (dialog->vbox), 6); + gtk_container_set_border_width (GTK_CONTAINER (filesel), 12); + + /* The toolbar */ + toolbar = gtk_toolbar_new (); + gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS); + g_object_set_data (G_OBJECT (filesel), "__toolbar", toolbar); + gtk_box_pack_start (GTK_BOX (filesel->main_vbox), toolbar, + FALSE, FALSE, 0); + /* Get rid of the border shadow */ + toolbar_shadow = gtk_widget_class_find_style_property (GTK_WIDGET_GET_CLASS (toolbar), + "shadow_type"); + G_PARAM_SPEC_ENUM (toolbar_shadow)->default_value = GTK_SHADOW_NONE; + g_object_set_data (G_OBJECT (toolbar), "__force_no_shadow", GINT_TO_POINTER (TRUE)); + + + back = gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), + GTK_STOCK_GO_BACK, + _("Go to the previous visited location (Alt+Left)"), NULL, + G_CALLBACK (gtk_file_selection_back), filesel, -1); + g_object_set_data (G_OBJECT (filesel), "__back", back); + + back_dropdown = gtk_toggle_button_new (); + gtk_button_set_relief (GTK_BUTTON (back_dropdown), GTK_RELIEF_NONE); + GTK_WIDGET_UNSET_FLAGS (back_dropdown, GTK_CAN_FOCUS); + back_dropdown_arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN); + gtk_widget_set_size_request (back_dropdown_arrow, 10, 24); + gtk_container_add (GTK_CONTAINER (back_dropdown), back_dropdown_arrow); + gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), back_dropdown, NULL, NULL); + g_object_set_data (G_OBJECT (filesel), "__back_dropdown", back_dropdown); + g_signal_connect (back_dropdown, "button-press-event", + G_CALLBACK (back_menu), NULL); + + gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), + GTK_STOCK_GO_UP, + _("Go to the parent directory (Alt+Up)"), NULL, + G_CALLBACK (gtk_file_selection_up), filesel, -1); + gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), + GTK_STOCK_REFRESH, + _("Display the latest contents of the current location (Ctrl+R)"), NULL, + G_CALLBACK (gtk_file_selection_refresh), filesel, -1); + gtk_toolbar_insert_space (GTK_TOOLBAR (toolbar), -1); + gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar), + GTK_STOCK_HOME, + _("Go to the home location (Alt+Home)"), NULL, + G_CALLBACK (gtk_file_selection_home), filesel, -1); + + icon = gdk_pixbuf_new_from_inline (sizeof (desktop_icon), + (const guint8 *) desktop_icon, + FALSE, NULL); + gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), + _("Desktop"), + _("Go to the desktop location"), NULL, + gtk_image_new_from_pixbuf (icon), + G_CALLBACK (gtk_file_selection_desktop), filesel); + + bookmarks = gtk_toggle_button_new (); + g_object_set_data (G_OBJECT (filesel), "__bookmarks_button", bookmarks); + gtk_button_set_relief (GTK_BUTTON (bookmarks), GTK_RELIEF_NONE); + GTK_WIDGET_UNSET_FLAGS (bookmarks, GTK_CAN_FOCUS); + bookmarks_icon = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_container_add (GTK_CONTAINER (bookmarks), bookmarks_icon); + gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), bookmarks, _("Bookmarks (Alt+B)"), NULL); + + gtk_toolbar_insert_space (GTK_TOOLBAR (toolbar), -1); + + gtk_widget_realize (bookmarks); + reload_bookmarks (bookmarks, GTK_WIDGET (filesel)); + /* The horizontal box containing create, rename etc. buttons */ filesel->button_area = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (filesel->button_area), GTK_BUTTONBOX_START); gtk_box_set_spacing (GTK_BOX (filesel->button_area), 0); - gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->button_area, - FALSE, FALSE, 0); + gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), filesel->button_area, NULL, NULL); gtk_widget_show (filesel->button_area); + gtk_widget_show_all (toolbar); gtk_file_selection_show_fileop_buttons (filesel); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 12); + + + /* The terminal and file manager buttons */ + gtk_toolbar_insert_space (GTK_TOOLBAR (toolbar), -1); + + icon = gdk_pixbuf_new_from_inline (sizeof (terminal_icon), + (const guint8 *) terminal_icon, + FALSE, NULL); + gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), + _("Terminal"), + _("Launch a terminal in this folder (Ctrl+T)"), NULL, + gtk_image_new_from_pixbuf (icon), + G_CALLBACK (gtk_file_selection_launch_terminal), filesel); + icon = gdk_pixbuf_new_from_inline (sizeof (fm_icon), + (const guint8 *) fm_icon, + FALSE, NULL); + gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), + _("File Manager"), + _("Launch a file manager in this folder (Ctrl+F)"), NULL, + gtk_image_new_from_pixbuf (icon), + G_CALLBACK (gtk_file_selection_launch_fm), filesel); + /* hbox for pulldown menu */ + vbox = gtk_vbox_new (FALSE, 12); + gtk_box_pack_start (GTK_BOX (filesel->main_vbox), vbox, TRUE, TRUE, 0); pulldown_hbox = gtk_hbox_new (TRUE, 5); - gtk_box_pack_start (GTK_BOX (filesel->main_vbox), pulldown_hbox, FALSE, FALSE, 0); - gtk_widget_show (pulldown_hbox); + gtk_box_pack_start (GTK_BOX (vbox), pulldown_hbox, FALSE, TRUE, 0); + gtk_widget_show_all (vbox); /* Pulldown menu */ filesel->history_pulldown = gtk_option_menu_new (); - gtk_widget_show (filesel->history_pulldown); + g_signal_connect (filesel->history_pulldown, "show", G_CALLBACK (widget_force_hide), NULL); gtk_box_pack_start (GTK_BOX (pulldown_hbox), filesel->history_pulldown, - FALSE, FALSE, 0); + TRUE, TRUE, 0); - /* The horizontal box containing the directory and file listboxes */ + combo = gtk_combo_new (); + gtk_combo_set_case_sensitive (GTK_COMBO (combo), TRUE); + gtk_combo_set_value_in_list (GTK_COMBO (combo), FALSE, FALSE); + gtk_combo_disable_activate (GTK_COMBO (combo)); + gtk_combo_set_use_arrows (GTK_COMBO (combo), FALSE); + g_signal_connect (GTK_COMBO (combo)->entry, "activate", + G_CALLBACK (history_combo_activate), filesel); + g_signal_connect (GTK_COMBO (combo)->list, "select-child", + G_CALLBACK (history_combo_selected), filesel); + gtk_widget_show (combo); + g_object_set_data (G_OBJECT (filesel), "__combo", combo); + gtk_box_pack_start (GTK_BOX (pulldown_hbox), combo, TRUE, TRUE, 0); - spacer = gtk_hbox_new (FALSE, 0); - gtk_widget_set_size_request (spacer, -1, 5); - gtk_box_pack_start (GTK_BOX (filesel->main_vbox), spacer, FALSE, FALSE, 0); - gtk_widget_show (spacer); + /* The horizontal box containing the directory and file listboxes */ - list_hbox = gtk_hbox_new (FALSE, 5); - gtk_box_pack_start (GTK_BOX (filesel->main_vbox), list_hbox, TRUE, TRUE, 0); + list_hbox = gtk_hbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (vbox), list_hbox, TRUE, TRUE, 0); gtk_widget_show (list_hbox); if (WANT_HPANED) list_container = g_object_new (GTK_TYPE_HPANED, @@ -713,11 +1878,6 @@ else list_container = list_hbox; - spacer = gtk_hbox_new (FALSE, 0); - gtk_widget_set_size_request (spacer, -1, 5); - gtk_box_pack_start (GTK_BOX (filesel->main_vbox), spacer, FALSE, FALSE, 0); - gtk_widget_show (spacer); - /* The directories list */ model = gtk_list_store_new (1, G_TYPE_STRING); @@ -734,6 +1894,12 @@ gtk_tree_view_column_set_widget (column, label); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_append_column (GTK_TREE_VIEW (filesel->dir_list), column); + if (!simple_mode) + { + /* The files are already being sorted by qsort when in simple mode */ + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), DIR_COLUMN, GTK_SORT_ASCENDING); + gtk_tree_view_column_set_sort_order (column, GTK_SORT_DESCENDING); + } gtk_widget_set_size_request (filesel->dir_list, DIR_LIST_WIDTH, DIR_LIST_HEIGHT); @@ -749,27 +1915,64 @@ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 0); if (GTK_IS_PANED (list_container)) - gtk_paned_pack1 (GTK_PANED (list_container), scrolled_win, TRUE, TRUE); + gtk_paned_pack1 (GTK_PANED (list_container), scrolled_win, FALSE, TRUE); else gtk_container_add (GTK_CONTAINER (list_container), scrolled_win); gtk_widget_show (filesel->dir_list); gtk_widget_show (scrolled_win); /* The files list */ - model = gtk_list_store_new (1, G_TYPE_STRING); + model = gtk_list_store_new (7, + G_TYPE_STRING, /* FILE_COLUMN */ + GDK_TYPE_PIXBUF, /* ICON_COLUMN */ + G_TYPE_STRING, /* TYPE_COLUMN */ + G_TYPE_STRING, /* SIZE_COLUMN */ + G_TYPE_UINT, /* SIZE_DATA_COLUMN */ + G_TYPE_STRING, /* DATE_COLUMN */ + G_TYPE_UINT); /* DATE_DATA_COLUMN */ filesel->file_list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model)); + gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (filesel->file_list), !simple_mode); + gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model), default_sort_func, NULL, NULL); + if (!simple_mode) + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (filesel->file_list), TRUE); g_object_unref (model); + + if (g_getenv ("GTK_FILESEL_NO_ICONS") && strcmp (g_getenv ("GTK_FILESEL_NO_ICONS"), "1") == 0) + icon_theme_initialized = FALSE; + if (g_getenv ("GTK_FILESEL_NO_MIME") && strcmp (g_getenv ("GTK_FILESEL_NO_MIME"), "1") == 0) + { + vfs_initialized = FALSE; + icon_theme_initialized = FALSE; + } + + if (!simple_mode && icon_theme_initialized) + { + column = gtk_tree_view_column_new_with_attributes ("", + gtk_cell_renderer_pixbuf_new (), + "pixbuf", ICON_COLUMN, + NULL); + g_object_set (column, "reorderable", TRUE, NULL); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column (GTK_TREE_VIEW (filesel->file_list), column); + } + + column = gtk_tree_view_column_new_with_attributes (_("Files"), gtk_cell_renderer_text_new (), "text", FILE_COLUMN, NULL); + g_signal_connect (column, "clicked", G_CALLBACK (sort_by_name), filesel->file_list); label = gtk_label_new_with_mnemonic (_("_Files")); gtk_label_set_mnemonic_widget (GTK_LABEL (label), filesel->file_list); gtk_widget_show (label); gtk_tree_view_column_set_widget (column, label); gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); gtk_tree_view_append_column (GTK_TREE_VIEW (filesel->file_list), column); + g_object_set (column, "clickable", !simple_mode, "resizable", !simple_mode, "reorderable", !simple_mode, NULL); + g_object_set_data (G_OBJECT (filesel), "__file_column", column); + /* if (!simple_mode) + gtk_tree_view_column_set_sort_indicator (column, TRUE); */ gtk_widget_set_size_request (filesel->file_list, FILE_LIST_WIDTH, FILE_LIST_HEIGHT); @@ -778,6 +1981,54 @@ g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (filesel->file_list)), "changed", G_CALLBACK (gtk_file_selection_file_changed), filesel); + + if (!simple_mode && vfs_initialized) + { + column = gtk_tree_view_column_new_with_attributes (_("Type"), + gtk_cell_renderer_text_new (), + "text", TYPE_COLUMN, + NULL); + g_signal_connect (column, "clicked", G_CALLBACK (sort_by_type), filesel->file_list); + label = gtk_label_new_with_mnemonic (_("_Type")); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), filesel->file_list); + gtk_widget_show (label); + gtk_tree_view_column_set_widget (column, label); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column (GTK_TREE_VIEW (filesel->file_list), column); + g_object_set (column, "clickable", !simple_mode, "resizable", !simple_mode, "reorderable", !simple_mode, NULL); + } + + + column = gtk_tree_view_column_new_with_attributes (_("Size"), + gtk_cell_renderer_text_new (), + "text", SIZE_COLUMN, + NULL); + g_signal_connect (column, "clicked", G_CALLBACK (sort_by_size), filesel->file_list); + label = gtk_label_new_with_mnemonic (_("_Size")); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), filesel->file_list); + gtk_widget_show (label); + gtk_tree_view_column_set_widget (column, label); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + if (!simple_mode) + gtk_tree_view_append_column (GTK_TREE_VIEW (filesel->file_list), column); + g_object_set (column, "clickable", !simple_mode, "resizable", !simple_mode, "reorderable", !simple_mode, NULL); + + + column = gtk_tree_view_column_new_with_attributes (_("Last Modified"), + gtk_cell_renderer_text_new (), + "text", DATE_COLUMN, + NULL); + g_signal_connect (column, "clicked", G_CALLBACK (sort_by_date), filesel->file_list); + label = gtk_label_new_with_mnemonic (_("Last _Modified")); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), filesel->file_list); + gtk_widget_show (label); + gtk_tree_view_column_set_widget (column, label); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + if (!simple_mode) + gtk_tree_view_append_column (GTK_TREE_VIEW (filesel->file_list), column); + g_object_set (column, "clickable", !simple_mode, "resizable", !simple_mode, "reorderable", !simple_mode, NULL); + + /* gtk_clist_column_titles_passive (GTK_CLIST (filesel->file_list)); */ scrolled_win = gtk_scrolled_window_new (NULL, NULL); @@ -798,6 +2049,10 @@ /* The OK/Cancel button area */ confirm_area = dialog->action_area; + action_area_border = gtk_widget_class_find_style_property ( + GTK_WIDGET_GET_CLASS (dialog), + "action_area_border"); + G_PARAM_SPEC_INT (action_area_border)->default_value = 0; /* The Cancel button */ filesel->cancel_button = gtk_dialog_add_button (dialog, @@ -811,7 +2066,7 @@ gtk_widget_grab_default (filesel->ok_button); /* The selection entry widget */ - entry_vbox = gtk_vbox_new (FALSE, 2); + entry_vbox = gtk_vbox_new (FALSE, 6); gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 2); gtk_widget_show (entry_vbox); @@ -821,7 +2076,7 @@ gtk_container_add (GTK_CONTAINER (eventbox), label); gtk_box_pack_start (GTK_BOX (entry_vbox), eventbox, FALSE, FALSE, 0); gtk_widget_show (label); - gtk_widget_show (eventbox); + g_signal_connect (eventbox, "show", G_CALLBACK (widget_force_hide), NULL); filesel->selection_entry = gtk_entry_new (); g_signal_connect (filesel->selection_entry, "key_press_event", @@ -843,6 +2098,51 @@ gtk_label_set_mnemonic_widget (GTK_LABEL (filesel->selection_text), filesel->selection_entry); + + /* The filter combo box */ + hbox = gtk_hbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (entry_vbox), hbox, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("Filter:")), FALSE, TRUE, 0); + + filter_combo = gtk_combo_new (); + do + { + GList *items = NULL; + items = g_list_append (items, _(" *")); + items = g_list_append (items, _(" *.txt")); + items = g_list_append (items, _(" *.xml/*.xhtml/*.html/*.sgml/" + "*.[Tt]e[Xx]/*.me")); + items = g_list_append (items, _(" *.abw/*.sxw/*.kwd/" + "*.doc/*.wpd")); + items = g_list_append (items, _(" *.gnumeric/*.sxc/*.ksp/*.xls")); + items = g_list_append (items, _(" *.pdf/*.ps/*.dvi")); + items = g_list_append (items, _(" *.jpg/*.gif/*.xpm/*.png/*.bmp/*.xbm/*.xcf")); + items = g_list_append (items, _(" *.mp3/*.ogg/*.wav/*.cdda/*.rm/*.ram")); + items = g_list_append (items, _("