Hello.
Here is templates support patches for libfm and pcmanfm.
In libfm src/gtk two files added fm-templates.{c,h}.
0001-Templates-support-in-libfm.patch - is for libfm
0001-Templates-support-through-libfm.patch - is for pcmanfm
There is still lack of templates list update support (but not so much
work left).
Do we need to handle icons for templates in menu? It can be not efficient.
>From cf84f69e895660459c38feef9e51b0d7750861e7 Mon Sep 17 00:00:00 2001
From: Alexander Varnin <[email protected]>
Date: Sun, 4 Jul 2010 00:06:12 +0400
Subject: [PATCH] Templates support through libfm
---
src/desktop.c | 6 ++--
src/main-win-ui.c | 3 +-
src/main-win.c | 44 +++++++++++++++++++-------
src/pcmanfm.c | 86 -----------------------------------------------------
src/pcmanfm.h | 4 --
5 files changed, 37 insertions(+), 106 deletions(-)
diff --git a/src/desktop.c b/src/desktop.c
index 10d2ba3..d0f03fb 100644
--- a/src/desktop.c
+++ b/src/desktop.c
@@ -1879,10 +1879,10 @@ void on_create_new(GtkAction* act, gpointer user_data)
{
const char* name = gtk_action_get_name(act);
if( strcmp(name, "NewFolder") == 0 )
- name = TEMPL_NAME_FOLDER;
+ name = FM_TEMPL_NAME_FOLDER;
else if( strcmp(name, "NewBlank") == 0 )
- name = TEMPL_NAME_BLANK;
- pcmanfm_create_new(NULL, fm_path_get_desktop(), name);
+ name = FM_TEMPL_NAME_BLANK;
+ fm_templates_dialog(NULL, fm_path_get_desktop(), name);
}
void on_sort_type(GtkAction* act, GtkRadioAction *cur, gpointer user_data)
diff --git a/src/main-win-ui.c b/src/main-win-ui.c
index 6072af0..5606d23 100644
--- a/src/main-win-ui.c
+++ b/src/main-win-ui.c
@@ -100,6 +100,7 @@ static const char main_menu_xml[] =
"<menu action='CreateNew'>"
"<menuitem action='NewFolder'/>"
"<menuitem action='NewBlank'/>"
+ "<separator/>"
"</menu>"
"<separator/>"
"<menuitem action='Paste'/>"
@@ -170,7 +171,7 @@ static GtkActionEntry main_win_actions[]=
/* for popup menu */
{"CreateNew", GTK_STOCK_NEW, NULL, NULL, NULL, NULL},
{"NewFolder", "folder", N_("Folder"), NULL, NULL, G_CALLBACK(on_create_new)},
- {"NewBlank", "text-x-generic", N_("Blank FIle"), NULL, NULL, G_CALLBACK(on_create_new)},
+ {"NewBlank", "text-x-generic", N_("Blank File"), NULL, NULL, G_CALLBACK(on_create_new)},
{"Prop", GTK_STOCK_PROPERTIES, NULL, NULL, NULL, G_CALLBACK(on_prop)}
};
diff --git a/src/main-win.c b/src/main-win.c
index 2b627ba..026703e 100644
--- a/src/main-win.c
+++ b/src/main-win.c
@@ -466,6 +466,32 @@ static void on_places_chdir(FmPlacesView* view, guint button, FmPath* path, FmMa
fm_main_win_chdir(win, path);
}
+// Templates related stuff
+
+void on_create_new(GtkAction* action, FmMainWin* win)
+{
+ FmFolderView* fv = FM_FOLDER_VIEW(win->folder_view);
+ const char* name = gtk_action_get_name(action);
+
+ if( strcmp(name, "NewFolder") == 0 )
+ name = FM_TEMPL_NAME_FOLDER;
+ else if( strcmp(name, "NewBlank") == 0 )
+ name = FM_TEMPL_NAME_BLANK;
+ fm_templates_dialog(GTK_WINDOW(win), fm_folder_view_get_cwd(fv), name);
+}
+
+static void on_add_template(GtkAction *act, void *param)
+{
+ gchar *name;
+ FmMainWin * self = (FmMainWin*)param;
+
+ g_signal_connect(act, "activate", on_create_new, param);
+ name = gtk_action_get_name(act);
+ gtk_ui_manager_add_ui(self->ui, gtk_ui_manager_new_merge_id(self->ui), "/popup/CreateNew", name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
+}
+
+// End of templates related stuff
+
static void fm_main_win_init(FmMainWin *self)
{
GtkWidget *vbox, *menubar, *toolitem, *scroll;
@@ -474,6 +500,9 @@ static void fm_main_win_init(FmMainWin *self)
GtkAction* act;
GtkAccelGroup* accel_grp;
GtkShadowType shadow_type;
+ FmTemplates *templates_menu;
+ FmTemplateCallbacks templates_callback = {.add=on_add_template, 0,
+ .param = self};
pcmanfm_ref();
all_wins = g_slist_prepend(all_wins, self);
@@ -583,6 +612,9 @@ static void fm_main_win_init(FmMainWin *self)
g_object_unref(act_grp);
self->ui = ui;
+ templates_menu = fm_templates_new(&self->parent, templates_callback);
+ gtk_ui_manager_insert_action_group(self->ui, fm_templates_get_actgrp(templates_menu), 0);
+
gtk_container_add( (GtkContainer*)self, vbox );
gtk_widget_show_all(vbox);
@@ -1252,18 +1284,6 @@ void on_page_removed(GtkNotebook* nb, GtkWidget* page, guint num, FmMainWin* win
gtk_notebook_set_show_tabs(nb, FALSE);
}
-void on_create_new(GtkAction* action, FmMainWin* win)
-{
- FmFolderView* fv = FM_FOLDER_VIEW(win->folder_view);
- const char* name = gtk_action_get_name(action);
-
- if( strcmp(name, "NewFolder") == 0 )
- name = TEMPL_NAME_FOLDER;
- else if( strcmp(name, "NewBlank") == 0 )
- name = TEMPL_NAME_BLANK;
- pcmanfm_create_new(GTK_WINDOW(win), fm_folder_view_get_cwd(fv), name);
-}
-
FmMainWin* fm_main_win_get_last_active()
{
return all_wins ? (FmMainWin*)all_wins->data : NULL;
diff --git a/src/pcmanfm.c b/src/pcmanfm.c
index 0486843..bd937ad 100644
--- a/src/pcmanfm.c
+++ b/src/pcmanfm.c
@@ -651,89 +651,3 @@ void pcmanfm_open_folder_in_terminal(GtkWindow* parent, FmPath* dir)
g_object_unref(app);
}
}
-
-/* FIXME: Need to load content of ~/Templates and list available templates in popup menus. */
-void pcmanfm_create_new(GtkWindow* parent, FmPath* cwd, const char* templ)
-{
- GError* err = NULL;
- FmPath* dest;
- char* basename;
-_retry:
- basename = fm_get_user_input(parent, _("Create New..."), _("Enter a name for the newly created file:"), _("New"));
- if(!basename)
- return;
-
- dest = fm_path_new_child(cwd, basename);
- g_free(basename);
-
- if( templ == TEMPL_NAME_FOLDER )
- {
- GFile* gf = fm_path_to_gfile(dest);
- if(!g_file_make_directory(gf, NULL, &err))
- {
- if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
- {
- fm_path_unref(dest);
- g_error_free(err);
- g_object_unref(gf);
- err = NULL;
- goto _retry;
- }
- fm_show_error(parent, err->message);
- g_error_free(err);
- }
-
- if(!err) /* select the newly created file */
- {
- /*FIXME: this doesn't work since the newly created file will
- * only be shown after file-created event was fired on its
- * folder's monitor and after FmFolder handles it in idle
- * handler. So, we cannot select it since it's not yet in
- * the folder model now. */
- /* fm_folder_view_select_file_path(fv, dest); */
- }
- g_object_unref(gf);
- }
- else if( templ == TEMPL_NAME_BLANK )
- {
- GFile* gf = fm_path_to_gfile(dest);
- GFileOutputStream* f = g_file_create(gf, G_FILE_CREATE_NONE, NULL, &err);
- if(f)
- {
- g_output_stream_close(G_OUTPUT_STREAM(f), NULL, NULL);
- g_object_unref(f);
- }
- else
- {
- if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
- {
- fm_path_unref(dest);
- g_error_free(err);
- g_object_unref(gf);
- err = NULL;
- goto _retry;
- }
- fm_show_error(parent, err->message);
- g_error_free(err);
- }
-
- if(!err) /* select the newly created file */
- {
- /*FIXME: this doesn't work since the newly created file will
- * only be shown after file-created event was fired on its
- * folder's monitor and after FmFolder handles it in idle
- * handler. So, we cannot select it since it's not yet in
- * the folder model now. */
- /* fm_folder_view_select_file_path(fv, dest); */
- }
- g_object_unref(gf);
- }
- else /* templates in ~/Templates */
- {
- FmPath* dir = fm_path_new(g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES));
- FmPath* template = fm_path_new_child(dir, templ);
- fm_copy_file(template, cwd);
- fm_path_unref(template);
- }
- fm_path_unref(dest);
-}
diff --git a/src/pcmanfm.h b/src/pcmanfm.h
index 649b424..b3f04c4 100644
--- a/src/pcmanfm.h
+++ b/src/pcmanfm.h
@@ -41,10 +41,6 @@ void pcmanfm_save_config();
void pcmanfm_open_folder_in_terminal(GtkWindow* parent, FmPath* dir);
-#define TEMPL_NAME_FOLDER NULL
-#define TEMPL_NAME_BLANK (const char*)-1
-void pcmanfm_create_new(GtkWindow* parent, FmPath* cwd, const char* templ);
-
G_END_DECLS
#endif
--
1.7.0.4
>From 77c8f786ae3dd9ec9d26b24100e77138d2d98f40 Mon Sep 17 00:00:00 2001
From: Alexander Varnin <[email protected]>
Date: Sun, 4 Jul 2010 00:00:10 +0400
Subject: [PATCH] Templates support in libfm
---
src/Makefile.am | 2 +
src/fm-gtk.h | 1 +
src/gtk/fm-templates.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++
src/gtk/fm-templates.h | 55 +++++++++++++++
4 files changed, 232 insertions(+), 0 deletions(-)
create mode 100644 src/gtk/fm-templates.c
create mode 100644 src/gtk/fm-templates.h
diff --git a/src/Makefile.am b/src/Makefile.am
index f13f20d..ff71040 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -84,6 +84,7 @@ libfm_gtk_SOURCES = \
gtk/fm-thumbnail.c \
gtk/fm-tab-label.c \
gtk/fm-gtk-marshal.c \
+ gtk/fm-templates.c \
$(NULL)
libfmincludedir = $(includedir)/libfm/libfm
@@ -138,6 +139,7 @@ libfmgtkinclude_HEADERS = \
gtk/fm-thumbnail.h \
gtk/fm-tab-label.h \
gtk/fm-gtk-marshal.h \
+ gtk/fm-templates.h \
$(NULL)
pkginclude_HEADERS = \
diff --git a/src/fm-gtk.h b/src/fm-gtk.h
index 3df64bc..369f57a 100644
--- a/src/fm-gtk.h
+++ b/src/fm-gtk.h
@@ -42,6 +42,7 @@
#include "fm-app-menu-view.h"
#include "fm-thumbnail.h"
#include "fm-tab-label.h"
+#include "fm-templates.h"
G_BEGIN_DECLS
diff --git a/src/gtk/fm-templates.c b/src/gtk/fm-templates.c
new file mode 100644
index 0000000..0f1af91
--- /dev/null
+++ b/src/gtk/fm-templates.c
@@ -0,0 +1,174 @@
+#include <glib/gi18n.h>
+ #include <sys/stat.h>
+
+#include "fm-templates.h"
+#include "fm-gtk-utils.h"
+
+void fm_templates_dialog(GtkWindow* parent, FmPath* cwd, const char* templ)
+{
+ GError* err = NULL;
+ FmPath* dest;
+ char* basename;
+ GFile* gf;
+_retry:
+ basename = fm_get_user_input(parent, _("Create New..."), _("Enter a name for the newly created file:"),
+ (((templ == FM_TEMPL_NAME_FOLDER)||(templ == FM_TEMPL_NAME_BLANK)) ? _("New") : templ));
+ if(!basename)
+ return;
+
+ dest = fm_path_new_child(cwd, basename);
+ g_free(basename);
+
+ gf = fm_path_to_gfile(dest);
+
+ if( templ == FM_TEMPL_NAME_FOLDER )
+ {
+ if(!g_file_make_directory(gf, NULL, &err))
+ {
+ if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
+ {
+ fm_path_unref(dest);
+ g_error_free(err);
+ g_object_unref(gf);
+ err = NULL;
+ goto _retry;
+ }
+ fm_show_error(parent, err->message);
+ g_error_free(err);
+ }
+
+ if(!err) /* select the newly created file */
+ {
+ /*FIXME: this doesn't work since the newly created file will
+ * only be shown after file-created event was fired on its
+ * folder's monitor and after FmFolder handles it in idle
+ * handler. So, we cannot select it since it's not yet in
+ * the folder model now. */
+ /* fm_folder_view_select_file_path(fv, dest); */
+ }
+ }
+ else if( templ == FM_TEMPL_NAME_BLANK )
+ {
+ GFileOutputStream* f = g_file_create(gf, G_FILE_CREATE_NONE, NULL, &err);
+ if(f)
+ {
+ g_output_stream_close(G_OUTPUT_STREAM(f), NULL, NULL);
+ g_object_unref(f);
+ }
+ else
+ {
+ if(err->domain == G_IO_ERROR && err->code == G_IO_ERROR_EXISTS)
+ {
+ fm_path_unref(dest);
+ g_error_free(err);
+ g_object_unref(gf);
+ err = NULL;
+ goto _retry;
+ }
+ fm_show_error(parent, err->message);
+ g_error_free(err);
+ }
+
+ if(!err) /* select the newly created file */
+ {
+ /*FIXME: this doesn't work since the newly created file will
+ * only be shown after file-created event was fired on its
+ * folder's monitor and after FmFolder handles it in idle
+ * handler. So, we cannot select it since it's not yet in
+ * the folder model now. */
+ /* fm_folder_view_select_file_path(fv, dest); */
+ }
+ }
+ else /* templates in ~/Templates */
+ {
+ FmPath *dir, *template_path;
+ GFile* src;
+
+ dir = fm_path_new(g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES));
+ template_path = fm_path_new_child(dir, templ);
+ src = fm_path_to_gfile(template_path);
+
+ if(!g_file_copy(src, gf, G_FILE_COPY_ALL_METADATA, 0,0,0,0))
+ fm_show_error(parent, _("Error creating template"));
+
+ fm_path_unref(template_path);
+ }
+ g_object_unref(gf);
+ fm_path_unref(dest);
+}
+
+
+static void fm_template_add_item(FmTemplates *self, char *name)
+{
+ GtkAction *act;
+ act = gtk_action_new (name, N_(name), 0,0);
+ gtk_action_group_add_action(self->act_grp, act);
+ if(self->callback.add)
+ self->callback.add(act, self->callback.param);
+}
+
+static time_t get_templates_mtime()
+{
+ struct stat buf;
+ gchar *dir = g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES);
+ if(stat(dir, &buf)!=0)
+ return 0;
+ if(!S_ISDIR(buf.st_mode))
+ return 0;
+ return buf.st_mtime;
+}
+
+static void update_templates(FmTemplates *templates)
+{
+ FmDirListJob *job;
+ FmPath * templates_path;
+
+ templates_path = fm_path_new(g_get_user_special_dir(G_USER_DIRECTORY_TEMPLATES));
+ job = fm_dir_list_job_new(templates_path);
+ fm_path_unref(templates_path);
+ //g_signal_connect(FM_JOB(job), "finished", G_CALLBACK(on_templates_list_finished), templates);
+ fm_job_run_sync(FM_JOB(job));
+
+ if(templates->mtime==0)
+ {
+ GList *l;
+
+ for(l=fm_list_peek_head_link( fm_dir_dist_job_get_files(job) );l;l=l->next)
+ if(!fm_file_info_is_dir(l->data))
+ fm_template_add_item(templates, ((FmFileInfo*)l->data)->disp_name);
+ }
+ else
+ {
+ time_t ctime;
+//FIXME: Add or remove new templates on change
+ printf("FIXME: Template list changed\n");
+ }
+ templates->mtime = get_templates_mtime();
+ g_object_unref(G_OBJECT(job));
+}
+
+gboolean fm_templates_updated(FmTemplates *tmpl)
+{
+ time_t mtime;
+ mtime = get_templates_mtime();
+ if(mtime==tmpl->mtime)
+ return FALSE;
+ update_templates(tmpl);
+ return TRUE;
+}
+
+FmTemplates* fm_templates_new (GtkWindow *parent, FmTemplateCallbacks callbacks)
+{
+ FmTemplates *tmpl;
+
+ tmpl = g_slice_new(FmTemplates);
+ tmpl->parent_window = parent;
+ tmpl->mtime = 0;
+ tmpl->callback = callbacks;
+
+ tmpl->act_grp = gtk_action_group_new("Templates");
+
+ update_templates(tmpl);
+
+ return tmpl;
+}
diff --git a/src/gtk/fm-templates.h b/src/gtk/fm-templates.h
new file mode 100644
index 0000000..aba0506
--- /dev/null
+++ b/src/gtk/fm-templates.h
@@ -0,0 +1,55 @@
+#ifndef __FM_TEMPLATES_H__
+#define __FM_TEMPLATES_H__
+
+#include "fm-folder.h"
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef void (*FmTemplateGuiCallback)(void *obj, void *param);
+typedef struct _FmTemplates FmTemplates;
+typedef struct _FmTemplateCallbacks FmTemplateCallbacks;
+
+struct _FmTemplateCallbacks
+{
+ FmTemplateGuiCallback add,remove;
+ void *param;
+};
+
+/**
+ * FmTemplates:
+ * This structure controls action group, related with templates folder.
+ */
+struct _FmTemplates
+{
+ GtkActionGroup *act_grp;
+ GtkWindow *parent_window;
+ time_t mtime;
+
+ FmTemplateCallbacks callback;
+};
+
+/**
+ * function(fm_templates_new)
+ * Initialises FmTemplates object
+ *
+ */
+FmTemplates* fm_templates_new (GtkWindow *parent, FmTemplateCallbacks callbacks);
+
+gboolean fm_templates_updated(FmTemplates*);
+
+#define fm_templates_get_actgrp(t) (t->act_grp)
+
+/**
+ * function(fm_templates_dialog)
+ * Runs dialog, that asks user to choose name for template, and then creates template.
+ */
+
+#define FM_TEMPL_NAME_FOLDER (char*)0
+#define FM_TEMPL_NAME_BLANK (char*)1
+
+void fm_templates_dialog(GtkWindow* parent, FmPath* target_dir, const char* templ);
+
+G_END_DECLS
+
+#endif
--
1.7.0.4
------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first
_______________________________________________
Pcmanfm-develop mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/pcmanfm-develop