SF.net SVN: geany:[4887] trunk
eht16 at users.sourceforge.net
eht16 at xxxxx
Sun May 9 15:47:40 UTC 2010
Revision: 4887
http://geany.svn.sourceforge.net/geany/?rev=4887&view=rev
Author: eht16
Date: 2010-05-09 15:47:39 +0000 (Sun, 09 May 2010)
Log Message:
-----------
Add support for creating PHP classes (patch by Ondrej Donek, thanks).
Modified Paths:
--------------
trunk/ChangeLog
trunk/THANKS
trunk/plugins/classbuilder.c
trunk/src/about.c
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2010-05-08 15:41:00 UTC (rev 4886)
+++ trunk/ChangeLog 2010-05-09 15:47:39 UTC (rev 4887)
@@ -1,3 +1,9 @@
+2010-05-09 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
+
+ * THANKS, src/about.c, plugins/classbuilder.c:
+ Add support for creating PHP classes (patch by Ondrej Donek, thanks).
+
+
2010-05-08 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* src/highlighting.c:
Modified: trunk/THANKS
===================================================================
--- trunk/THANKS 2010-05-08 15:41:00 UTC (rev 4886)
+++ trunk/THANKS 2010-05-09 15:47:39 UTC (rev 4887)
@@ -77,6 +77,7 @@
Can Koy <cankoy(at)ymail(dot)com> - Multiple changes/improvements
Yoann Le Montagner <yoann(dot)le-montagner(at)m4x(dot)org> - set VTE bold color
Dimitar Zhekov <hamster(at)mbox(dot)contact(dot)bg> - matching brace improvements patch
+Ondrej Donek <ondrejd(at)gmail(dot)com> - Support for creating PHP classes with the classbuilder plugin
Translators:
------------
Modified: trunk/plugins/classbuilder.c
===================================================================
--- trunk/plugins/classbuilder.c 2010-05-08 15:41:00 UTC (rev 4886)
+++ trunk/plugins/classbuilder.c 2010-05-09 15:47:39 UTC (rev 4887)
@@ -27,8 +27,7 @@
#include "geanyplugin.h"
-
-GeanyData *geany_data;
+GeanyData *geany_data;
GeanyFunctions *geany_functions;
@@ -44,7 +43,8 @@
enum
{
GEANY_CLASS_TYPE_CPP,
- GEANY_CLASS_TYPE_GTK
+ GEANY_CLASS_TYPE_GTK,
+ GEANY_CLASS_TYPE_PHP
};
typedef struct _ClassInfo ClassInfo;
@@ -67,6 +67,11 @@
gchar *constructor_impl;
gchar *destructor_impl;
gchar *gtk_destructor_registration;
+ // These are needed only for PHP classes
+ gchar *namespace_decl;
+ gchar *implements_decl;
+ gchar *abstract_decl;
+ gchar *singleton_impl;
};
typedef struct _CreateClassDialog
@@ -83,6 +88,11 @@
GtkWidget *create_constructor_box;
GtkWidget *create_destructor_box;
GtkWidget *gtk_constructor_type_entry;
+ // These are needed only for PHP classes
+ GtkWidget *class_namespace_entry;
+ GtkWidget *class_implements_entry;
+ GtkWidget *create_isabstract_box;
+ GtkWidget *create_issingleton_box;
} CreateClassDialog;
@@ -184,7 +194,19 @@
{constructor_impl}\n\
";
+static const gchar templates_php_class_source[] = "<?php\n\
+{fileheader}\n\
+{namespace_decl}\n\
+{base_include}\n\
+{abstract_decl}class {class_name}{base_decl}{implements_decl}\n\{\n\
+{singleton_impl}\
+{constructor_impl}\
+{destructor_impl}\n\
+ // ...\n\n\
+}\n\
+";
+
static void cc_dlg_on_set_sensitive_toggled(GtkWidget *toggle_button, GtkWidget *target_widget);
static void cc_dlg_on_class_name_entry_changed(GtkWidget *entry, CreateClassDialog *cc_dlg);
static void cc_dlg_on_base_name_entry_changed(GtkWidget *entry, CreateClassDialog *cc_dlg);
@@ -298,6 +320,21 @@
utils_string_replace_all(template, "{gtk_destructor_registration}",
class_info->gtk_destructor_registration);
break;
+
+ case GEANY_CLASS_TYPE_PHP:
+ fileheader = templates_get_template_fileheader(GEANY_FILETYPES_PHP, class_info->source);
+ template = g_string_new(templates_php_class_source);
+ utils_string_replace_all(template, "{fileheader}", fileheader);
+ utils_string_replace_all(template, "{namespace_decl}", class_info->namespace_decl);
+ utils_string_replace_all(template, "{base_include}", class_info->base_include);
+ utils_string_replace_all(template, "{abstract_decl}", class_info->abstract_decl);
+ utils_string_replace_all(template, "{class_name}", class_info->class_name);
+ utils_string_replace_all(template, "{base_decl}", class_info->base_decl);
+ utils_string_replace_all(template, "{implements_decl}", class_info->implements_decl);
+ utils_string_replace_all(template, "{constructor_impl}", class_info->constructor_impl);
+ utils_string_replace_all(template, "{destructor_impl}", class_info->destructor_impl);
+ utils_string_replace_all(template, "{singleton_impl}", class_info->singleton_impl);
+ break;
}
g_free(fileheader);
@@ -331,7 +368,25 @@
g_signal_connect_swapped(cc_dlg->dialog, "destroy", G_CALLBACK(g_free), (gpointer)cc_dlg);
main_box = ui_dialog_vbox_new(GTK_DIALOG(cc_dlg->dialog));
-
+
+ if (type == GEANY_CLASS_TYPE_PHP)
+ {
+ frame = ui_frame_new_with_alignment(_("Namespace"), &align);
+ gtk_container_add(GTK_CONTAINER(main_box), frame);
+
+ vbox = gtk_vbox_new(FALSE, 10);
+ gtk_container_add(GTK_CONTAINER(align), vbox);
+
+ hbox = gtk_hbox_new(FALSE, 10);
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);
+
+ label = gtk_label_new(_("Namespace:"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ cc_dlg->class_namespace_entry = gtk_entry_new();
+ gtk_box_pack_start(GTK_BOX(hbox), cc_dlg->class_namespace_entry, TRUE, TRUE, 0);
+ }
+
frame = ui_frame_new_with_alignment(_("Class"), &align);
gtk_container_add(GTK_CONTAINER(main_box), frame);
@@ -348,25 +403,28 @@
gtk_box_pack_start(GTK_BOX(hbox), cc_dlg->class_name_entry, TRUE, TRUE, 0);
g_signal_connect(cc_dlg->class_name_entry, "changed",
G_CALLBACK(cc_dlg_on_class_name_entry_changed), cc_dlg);
-
+
+ if (type != GEANY_CLASS_TYPE_PHP)
+ {
+ hbox = gtk_hbox_new(FALSE, 10);
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);
+
+ label = gtk_label_new(_("Header file:"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ cc_dlg->header_entry = gtk_entry_new();
+ gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->header_entry);
+ }
+
hbox = gtk_hbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(vbox), hbox);
-
- label = gtk_label_new(_("Header file:"));
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- cc_dlg->header_entry = gtk_entry_new();
- gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->header_entry);
-
- hbox = gtk_hbox_new(FALSE, 10);
- gtk_container_add(GTK_CONTAINER(vbox), hbox);
-
+
label = gtk_label_new(_("Source file:"));
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
+
cc_dlg->source_entry = gtk_entry_new();
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->source_entry);
-
+
frame = ui_frame_new_with_alignment(_("Inheritance"), &align);
gtk_container_add(GTK_CONTAINER(main_box), frame);
@@ -387,20 +445,26 @@
G_CALLBACK(cc_dlg_on_base_name_entry_changed), (gpointer)cc_dlg);
hbox = gtk_hbox_new(FALSE, 10);
- gtk_container_add(GTK_CONTAINER(vbox), hbox);
-
- label = gtk_label_new(_("Base header:"));
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);
+
+ if (type == GEANY_CLASS_TYPE_PHP)
+ label = gtk_label_new(_("Base source:"));
+ else
+ label = gtk_label_new(_("Base header:"));
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
+
cc_dlg->base_header_entry = gtk_entry_new();
if (type == GEANY_CLASS_TYPE_GTK)
gtk_entry_set_text(GTK_ENTRY(cc_dlg->base_header_entry), "glib-object.h");
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->base_header_entry);
-
- cc_dlg->base_header_global_box = gtk_check_button_new_with_label(_("Global"));
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box), TRUE);
- gtk_box_pack_end(GTK_BOX(hbox), cc_dlg->base_header_global_box, FALSE, FALSE, 0);
-
+
+ if (type != GEANY_CLASS_TYPE_PHP)
+ {
+ cc_dlg->base_header_global_box = gtk_check_button_new_with_label(_("Global"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box), TRUE);
+ gtk_box_pack_end(GTK_BOX(hbox), cc_dlg->base_header_global_box, FALSE, FALSE, 0);
+ }
+
if (type == GEANY_CLASS_TYPE_GTK)
{
hbox = gtk_hbox_new(FALSE, 10);
@@ -413,7 +477,19 @@
gtk_entry_set_text(GTK_ENTRY(cc_dlg->base_gtype_entry), "G_TYPE_OBJECT");
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->base_gtype_entry);
}
-
+
+ if (type == GEANY_CLASS_TYPE_PHP)
+ {
+ hbox = gtk_hbox_new(FALSE, 10);
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);
+
+ label = gtk_label_new(_("Implements:"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ cc_dlg->class_implements_entry = gtk_entry_new();
+ gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->class_implements_entry);
+ }
+
frame = ui_frame_new_with_alignment(_("Options"), &align);
gtk_container_add(GTK_CONTAINER(main_box), frame);
@@ -429,7 +505,19 @@
cc_dlg->create_destructor_box = gtk_check_button_new_with_label(_("Create destructor"));
gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->create_destructor_box);
-
+
+ if (type == GEANY_CLASS_TYPE_PHP)
+ {
+ hbox = gtk_hbox_new(FALSE, 10);
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);
+
+ cc_dlg->create_isabstract_box = gtk_check_button_new_with_label(_("Is abstract"));
+ gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->create_isabstract_box);
+
+ cc_dlg->create_issingleton_box = gtk_check_button_new_with_label(_("Is singleton"));
+ gtk_container_add(GTK_CONTAINER(hbox), cc_dlg->create_issingleton_box);
+ }
+
if (type == GEANY_CLASS_TYPE_GTK)
{
hbox = gtk_hbox_new(FALSE, 10);
@@ -472,6 +560,7 @@
static void cc_dlg_on_class_name_entry_changed(GtkWidget *entry, CreateClassDialog *cc_dlg)
{
+ gchar *class_name;
gchar *class_name_down;
gchar *class_header;
gchar *class_source;
@@ -480,16 +569,20 @@
g_return_if_fail(GTK_IS_ENTRY(entry));
g_return_if_fail(cc_dlg != NULL);
- class_name_down = g_ascii_strdown(gtk_entry_get_text(GTK_ENTRY(entry)), -1);
+ class_name = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
+ class_name_down = g_ascii_strdown(class_name, -1);
class_header = g_strconcat(class_name_down, ".h", NULL);
if (cc_dlg->class_type == GEANY_CLASS_TYPE_CPP)
class_source = g_strconcat(class_name_down, ".cpp", NULL);
+ else if (cc_dlg->class_type == GEANY_CLASS_TYPE_PHP)
+ class_source = g_strconcat(class_name, ".php", NULL);
else
class_source = g_strconcat(class_name_down, ".c", NULL);
gtk_entry_set_text(GTK_ENTRY(cc_dlg->header_entry), class_header);
gtk_entry_set_text(GTK_ENTRY(cc_dlg->source_entry), class_source);
-
+
+ g_free(class_name);
g_free(class_name_down);
g_free(class_header);
g_free(class_source);
@@ -525,7 +618,7 @@
g_return_if_fail(entry != NULL);
g_return_if_fail(GTK_IS_ENTRY(entry));
g_return_if_fail(cc_dlg != NULL);
-
+
base_name_splitted = str_case_split(gtk_entry_get_text(GTK_ENTRY(entry)), '_');
if (! g_ascii_strncasecmp(gtk_entry_get_text(GTK_ENTRY(entry)), "gtk", 3))
/*tmp = g_strconcat("gtk/", gtk_entry_get_text(GTK_ENTRY(entry)), ".h", NULL);*/
@@ -533,9 +626,16 @@
tmp = g_strdup("gtk/gtk.h");
else if (utils_str_equal(gtk_entry_get_text(GTK_ENTRY(entry)), "GObject"))
tmp = g_strdup("glib-object.h");
+ else if (cc_dlg->class_type == GEANY_CLASS_TYPE_PHP)
+ tmp = g_strconcat(gtk_entry_get_text(GTK_ENTRY(entry)), ".php", NULL);
else
tmp = g_strconcat(gtk_entry_get_text(GTK_ENTRY(entry)), ".h", NULL);
- base_header = g_ascii_strdown(tmp, -1);
+
+ if (cc_dlg->class_type == GEANY_CLASS_TYPE_PHP)
+ base_header = g_strdup(tmp);
+ else
+ base_header = g_ascii_strdown(tmp, -1);
+
g_free(tmp);
gtk_entry_set_text(GTK_ENTRY(cc_dlg->base_header_entry), base_header);
@@ -584,12 +684,21 @@
if (! utils_str_equal(gtk_entry_get_text(GTK_ENTRY(cc_dlg->base_name_entry)), ""))
{
class_info->base_name = g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg->base_name_entry)));
- class_info->base_include = g_strdup_printf("\n#include %c%s%c\n",
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box)) ?
+ if (class_info->type != GEANY_CLASS_TYPE_PHP)
+ {
+ class_info->base_include = g_strdup_printf("\n#include %c%s%c\n",
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box)) ?
'<' : '\"',
- gtk_entry_get_text(GTK_ENTRY(cc_dlg->base_header_entry)),
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box)) ?
+ gtk_entry_get_text(GTK_ENTRY(cc_dlg->base_header_entry)),
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->base_header_global_box)) ?
'>' : '\"');
+ }
+ else
+ {
+ class_info->base_include = g_strdup_printf("\nrequire_once \"%s\";\n",
+ gtk_entry_get_text(GTK_ENTRY(cc_dlg->base_header_entry)));
+ class_info->base_decl = g_strdup_printf(" extends %s", class_info->base_name);
+ }
}
else
{
@@ -697,8 +806,110 @@
}
break;
}
+ case GEANY_CLASS_TYPE_PHP:
+ {
+ gchar *tmp;
+
+ class_info->source = g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg->source_entry)));
+
+ tmp = g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg->class_namespace_entry)));
+ if (! utils_str_equal(tmp, ""))
+ class_info->namespace_decl = g_strdup_printf("namespace %s;", tmp);
+ else
+ class_info->namespace_decl = g_strdup("");
+
+ tmp = g_strdup(gtk_entry_get_text(GTK_ENTRY(cc_dlg->class_implements_entry)));
+ if (! utils_str_equal(tmp, ""))
+ class_info->implements_decl = g_strdup_printf(" implements %s", tmp);
+ else
+ class_info->implements_decl = g_strdup("");
+ g_free(tmp);
+
+ if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_constructor_box)) &&
+ ! gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_isabstract_box)))
+ {
+ class_info->constructor_impl = g_strdup_printf("\n"
+ "\t/**\n"
+ "\t * Constructor of class %s.\n"
+ "\t *\n"
+ "\t * @return void\n"
+ "\t */\n"
+ "\tpublic function __construct()\n"
+ "\t{\n"
+ "\t\t// ...\n"
+ "\t}\n",
+ class_info->class_name);
+ }
+ else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_constructor_box)) &&
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_isabstract_box)))
+ {
+ class_info->constructor_impl = g_strdup_printf("\n"
+ "\t/**\n"
+ "\t * Constructor of class %s.\n"
+ "\t *\n"
+ "\t * @return void\n"
+ "\t */\n"
+ "\tprotected function __construct()\n"
+ "\t{\n"
+ "\t\t// ...\n"
+ "\t}\n",
+ class_info->class_name);
+ }
+ else
+ class_info->constructor_impl = g_strdup("");
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_destructor_box)))
+ {
+ class_info->destructor_impl = g_strdup_printf("\n"
+ "\t/**\n"
+ "\t * Destructor of class %s.\n"
+ "\t *\n"
+ "\t * @return void\n"
+ "\t */\n"
+ "\tpublic function __destruct()\n"
+ "\t{\n"
+ "\t\t// ...\n"
+ "\t}\n",
+ class_info->class_name);
+ }
+ else
+ class_info->destructor_impl = g_strdup("");
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_isabstract_box)))
+ class_info->abstract_decl = g_strdup("abstract ");
+ else
+ class_info->abstract_decl = g_strdup("");
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cc_dlg->create_issingleton_box)))
+ {
+ class_info->singleton_impl = g_strdup_printf("\n"
+ "\t/**\n"
+ "\t * Holds instance of self.\n"
+ "\t * \n"
+ "\t * @var %s\n"
+ "\t */\n"
+ "\tprotected static $kInstance = null;\n\n"
+ "\t/**\n"
+ "\t * Returns instance of self.\n"
+ "\t * \n"
+ "\t * @return %s\n"
+ "\t */\n"
+ "\tpublic static function getInstance() {\n"
+ "\t\tif(!(self::$kInstance instanceof %s)) {\n"
+ "\t\t\tself::$kInstance = new self();\n"
+ "\t\t}\n"
+ "\t\treturn self::$kInstance;\n"
+ "\t}\n",
+ class_info->class_name,
+ class_info->class_name,
+ class_info->class_name);
+ }
+ else
+ class_info->singleton_impl = g_strdup("");
+ break;
+ }
}
-
+
/* only create the files if the filename is not empty */
if (! utils_str_equal(class_info->source, ""))
{
@@ -708,7 +919,8 @@
g_free(text);
}
- if (! utils_str_equal(class_info->header, ""))
+ if (! utils_str_equal(class_info->header, "") &&
+ class_info->type != GEANY_CLASS_TYPE_PHP)
{
text = get_template_class_header(class_info);
doc = document_new_file(class_info->header, NULL, NULL);
@@ -721,7 +933,9 @@
class_info->header, class_info->header_guard, class_info->source, class_info->base_decl,
class_info->constructor_decl, class_info->constructor_impl,
class_info->gtk_destructor_registration, class_info->destructor_decl,
- class_info->destructor_impl, class_info->base_gtype, class_info, NULL);
+ class_info->destructor_impl, class_info->base_gtype,
+ class_info->namespace_decl, class_info->implements_decl,
+ class_info->abstract_decl, class_info->singleton_impl, class_info, NULL);
return TRUE;
}
@@ -742,12 +956,21 @@
}
+static void
+on_menu_create_php_class_activate (GtkMenuItem *menuitem,
+ gpointer user_data)
+{
+ show_dialog_create_class(GEANY_CLASS_TYPE_PHP);
+}
+
+
void plugin_init(GeanyData *data)
{
GtkWidget *menu_create_class1;
GtkWidget *menu_create_class1_menu;
GtkWidget *menu_create_cpp_class;
GtkWidget *menu_create_gtk_class;
+ GtkWidget *menu_create_php_class;
menu_create_class1 = ui_image_menu_item_new (GTK_STOCK_ADD, _("Create Cla_ss"));
gtk_container_add (GTK_CONTAINER (geany->main_widgets->tools_menu), menu_create_class1);
@@ -760,6 +983,9 @@
menu_create_gtk_class = gtk_menu_item_new_with_mnemonic (_("_GTK+ Class"));
gtk_container_add (GTK_CONTAINER (menu_create_class1_menu), menu_create_gtk_class);
+
+ menu_create_php_class = gtk_menu_item_new_with_mnemonic (_("_PHP Class"));
+ gtk_container_add (GTK_CONTAINER (menu_create_class1_menu), menu_create_php_class);
g_signal_connect(menu_create_cpp_class, "activate",
G_CALLBACK (on_menu_create_cpp_class_activate),
@@ -767,6 +993,9 @@
g_signal_connect(menu_create_gtk_class, "activate",
G_CALLBACK (on_menu_create_gtk_class_activate),
NULL);
+ g_signal_connect(menu_create_php_class, "activate",
+ G_CALLBACK (on_menu_create_php_class_activate),
+ NULL);
gtk_widget_show_all(menu_create_class1);
Modified: trunk/src/about.c
===================================================================
--- trunk/src/about.c 2010-05-08 15:41:00 UTC (rev 4886)
+++ trunk/src/about.c 2010-05-09 15:47:39 UTC (rev 4887)
@@ -89,8 +89,8 @@
"Giuseppe Torelli, Guillaume de Rorthais, Guillaume Hoffmann, Herbert Voss, Jason Oster, "
"Jean-François Wauthy, Jeff Pohlmeyer, Jesse Mayes, John Gabriele, Jon Senior, Jon Strait, Josef Whiter, "
"Jörn Reder, Kelvin Gardiner, Kevin Ellwood, Kristoffer A. Tjernås, Lex Trotman, Marko Peric, Matti Mårds, "
-"Moritz Barsnick, Peter Strand, Philipp Gildein, Pierre Joye, Rob van der Linde, Robert McGinley, "
-"Roland Baudin, Ross McKay, S Jagannathan, Saleem Abdulrasool, "
+"Moritz Barsnick, Ondrej Donek, Peter Strand, Philipp Gildein, Pierre Joye, Rob van der Linde, "
+"Robert McGinley, Roland Baudin, Ross McKay, S Jagannathan, Saleem Abdulrasool, "
"Sebastian Kraft, Shiv, Slava Semushin, Stefan Oltmanns, Tamim, Thomas Martitz, Tomás Vírseda, "
"Tyler Mulligan, Walery Studennikov, Yura Siamashka";
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Commits
mailing list