]> sjero.net Git - linphone/commitdiff
history chat delete
authorMargaux Clerc <margaux.clerc@belledonne-communications.com>
Thu, 7 Mar 2013 15:08:04 +0000 (16:08 +0100)
committerMargaux Clerc <margaux.clerc@belledonne-communications.com>
Thu, 7 Mar 2013 15:13:15 +0000 (16:13 +0100)
update README for macos

README.macos
coreapi/chat.c
coreapi/linphonecore.h
coreapi/message_storage.c
gtk/chat.c
gtk/friendlist.c
gtk/propertybox.c

index 29666f440fe90e4ac69f39013b1bf45f692d40c2..bb78575bf5f9613d9467fb8c2f962ca8a3810b29 100644 (file)
@@ -39,6 +39,9 @@ You need:
 - Install additional librairies required for wizard (linphone.org account creation assistant)
  $ sudo port install libsoup
  
+ - Install sqlite3 for message storage
+ $ sudo port install sqlite3
  ** WARNING 2013-03-06 glib-networking is currently broken in macports - generates crashes or hangs when used in a bundle **
  As a temporary workaround, build a newer version by yourself:
  $ wget http://ftp.gnome.org/pub/gnome/sources/glib-networking/2.34/glib-networking-2.34.2.tar.xz
index 5f79849dc4fe6de20b0f02c7b0eccdd809d64f38..046c3473368ff9d0999284f9dd80fa875a287ee4 100644 (file)
@@ -182,10 +182,10 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
                linphone_chat_message_set_external_body_url(msg, sal_msg->url);
        }
        linphone_address_destroy(addr);
-       linphone_chat_room_message_received(cr,lc,msg);
        linphone_core_set_history_message(cr,to,from,INCOMING,
                                msg->message,my_ctime_r(&msg->time,buf),NOT_READ,
                                LinphoneChatMessageStateDelivered);
+       linphone_chat_room_message_received(cr,lc,msg);
        ms_free(cleanfrom);
        ms_free(from);
 }
index c1054922d19109d90aa7c82ebc2532609789ccd4..49074db3e8141fb30f09b9fd93558fa5655201a4 100644 (file)
@@ -1420,6 +1420,7 @@ int linphone_core_get_video_dscp(const LinphoneCore *lc);
 
 MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message);
 void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read);
+void linphone_core_delete_history(LinphoneCore *lc,const char *from);
 
 #ifdef __cplusplus
 }
index 90665c26c29e5c08af8d4ac09dc698801489e732..3d6c45d93ce7c8dcb33c6499faffd447caf84075 100644 (file)
@@ -1,82 +1,82 @@
-/*
-message_storage.c
-Copyright (C) 2012  Belledonne Communications, Grenoble, France
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-*/
-
-#include "private.h"
-#include "linphonecore.h"
-
-#ifdef WIN32
-
-static inline char *my_ctime_r(const time_t *t, char *buf){
-       strcpy(buf,ctime(t));
-       return buf;
-}
-
-#else
-#define my_ctime_r ctime_r
-#endif
-
-#ifdef MSG_STORAGE_ENABLED
-
-#include "sqlite3.h"
-
+/*\r
+message_storage.c\r
+Copyright (C) 2012  Belledonne Communications, Grenoble, France\r
+\r
+This program is free software; you can redistribute it and/or\r
+modify it under the terms of the GNU General Public License\r
+as published by the Free Software Foundation; either version 2\r
+of the License, or (at your option) any later version.\r
+\r
+This program is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with this program; if not, write to the Free Software\r
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
+*/\r
+\r
+#include "private.h"\r
+#include "linphonecore.h"\r
+\r
+#ifdef WIN32\r
+\r
+static inline char *my_ctime_r(const time_t *t, char *buf){\r
+       strcpy(buf,ctime(t));\r
+       return buf;\r
+}\r
+\r
+#else\r
+#define my_ctime_r ctime_r\r
+#endif\r
+\r
+#ifdef MSG_STORAGE_ENABLED\r
+\r
+#include "sqlite3.h"\r
+\r
 static const char *days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};\r
-static const char *months[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
-
-#define CONFIG_FILE ".linphone-history.db"
-
-char *linphone_message_storage_get_config_file(const char *filename){
-       const int path_max=1024;
-       char *config_file=(char *)malloc(path_max*sizeof(char));
-       if (filename==NULL) filename=CONFIG_FILE;
-       /*try accessing a local file first if exists*/
-       if (access(CONFIG_FILE,F_OK)==0){
-               snprintf(config_file,path_max,"%s",filename);
-       }else{
-#ifdef WIN32
-               const char *appdata=getenv("APPDATA");
-               if (appdata){
-                       snprintf(config_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR);
-                       CreateDirectory(config_file,NULL);
-                       snprintf(config_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename);
-               }
-#else
-               const char *home=getenv("HOME");
-               if (home==NULL) home=".";
-               snprintf(config_file,path_max,"%s/%s",home,filename);
-#endif
-       }
-       return config_file;
-}
-
-void create_chat_message(char **argv, void *data){
-       LinphoneChatRoom *cr = (LinphoneChatRoom *)data;
-       LinphoneChatMessage* new_message = linphone_chat_room_create_message(cr,argv[4]);
+static const char *months[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};\r
+\r
+#define CONFIG_FILE ".linphone-history.db"\r
+\r
+char *linphone_message_storage_get_config_file(const char *filename){\r
+       const int path_max=1024;\r
+       char *config_file=(char *)malloc(path_max*sizeof(char));\r
+       if (filename==NULL) filename=CONFIG_FILE;\r
+       /*try accessing a local file first if exists*/\r
+       if (access(CONFIG_FILE,F_OK)==0){\r
+               snprintf(config_file,path_max,"%s",filename);\r
+       }else{\r
+#ifdef WIN32\r
+               const char *appdata=getenv("APPDATA");\r
+               if (appdata){\r
+                       snprintf(config_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR);\r
+                       CreateDirectory(config_file,NULL);\r
+                       snprintf(config_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename);\r
+               }\r
+#else\r
+               const char *home=getenv("HOME");\r
+               if (home==NULL) home=".";\r
+               snprintf(config_file,path_max,"%s/%s",home,filename);\r
+#endif\r
+       }\r
+       return config_file;\r
+}\r
+\r
+void create_chat_message(char **argv, void *data){\r
+       LinphoneChatRoom *cr = (LinphoneChatRoom *)data;\r
+       LinphoneChatMessage* new_message = linphone_chat_room_create_message(cr,argv[4]);\r
        struct tm ret={0};\r
        char tmp1[80]={0};\r
-       char tmp2[80]={0};
-       
-       if(atoi(argv[3])==INCOMING){
-               linphone_chat_message_set_from(new_message,linphone_address_new(argv[2]));
-       } else {
-               linphone_chat_message_set_from(new_message,linphone_address_new(argv[1]));
-       }
-
+       char tmp2[80]={0};\r
+       \r
+       if(atoi(argv[3])==INCOMING){\r
+               linphone_chat_message_set_from(new_message,linphone_address_new(argv[2]));\r
+       } else {\r
+               linphone_chat_message_set_from(new_message,linphone_address_new(argv[1]));\r
+       }\r
+\r
        if(argv[5]!=NULL){\r
                int i,j;\r
                sscanf(argv[5],"%3c %3c%d%d:%d:%d %d",tmp1,tmp2,&ret.tm_mday,\r
@@ -87,108 +87,116 @@ void create_chat_message(char **argv, void *data){
                }\r
                for(j=0;j<12;j++) { \r
                        if(strcmp(tmp2,months[j])==0) ret.tm_mon=j; \r
-               }
-       }
-       new_message->time=argv[5]!=NULL ? mktime(&ret) : time(NULL);
-       new_message->state=atoi(argv[7]);
-       cr->messages_hist=ms_list_prepend(cr->messages_hist,(void *)new_message);
-}
-
-static int callback(void *data, int argc, char **argv, char **colName){
-    create_chat_message(argv,data);
-    return 0;
-}
-
-void linphone_sql_request_message(sqlite3 *db,const char *stmt,void *data){
-       char* errmsg;
-       int ret;
-       ret=sqlite3_exec(db,stmt,callback,data,&errmsg);
-       if(ret != SQLITE_OK) {
-               printf("Error in creation: %s.\n", errmsg);
-       }
-}
-
-void linphone_sql_request(sqlite3* db,const char *stmt){
-       char* errmsg;
-       int ret;
-       ret=sqlite3_exec(db,stmt,0,0,&errmsg);
-       if(ret != SQLITE_OK) {
-               printf("Error in creation: %s.\n", errmsg);
-       }
-}
-
-void linphone_core_set_history_message(LinphoneChatRoom *cr,const char *local_contact,const char *remote_contact, 
-                     int direction, const char *message,const char *date, int read, int state){
-       LinphoneCore *lc=linphone_chat_room_get_lc(cr);
-       char *buf=sqlite3_mprintf("insert into history values(NULL,%Q,%Q,%i,%Q,%Q,%i,%i);",
-                                       local_contact,remote_contact,direction,message,date,read,state);
-       linphone_sql_request(lc->db,buf);
-}
-
-void linphone_core_set_message_state(LinphoneChatRoom *cr,const char *message, int state, time_t date){
-       LinphoneCore *lc=linphone_chat_room_get_lc(cr);
-       char time_str[26];
-       char *buf=sqlite3_mprintf("update history set status=%i where message = %Q and time = %Q;",
-                      state,message,my_ctime_r(&date,time_str));
-       linphone_sql_request(lc->db,buf);
-}
-
-void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read){
-       LinphoneCore *lc=linphone_chat_room_get_lc(cr);
-       char *buf=sqlite3_mprintf("update history set read=%i where remoteContact = %Q;",
-                      read,from);
-       linphone_sql_request(lc->db,buf);
-}
-
-MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message){
-       LinphoneCore *lc=linphone_chat_room_get_lc(cr);
-       cr->messages_hist = NULL;
-       char *buf=sqlite3_mprintf("select * from history where remoteContact = %Q order by id DESC limit %i ;",to,nb_message);
-       linphone_sql_request_message(lc->db,buf,(void *)cr);
-       return cr->messages_hist;
-}
-
-void linphone_close_storage(sqlite3* db){
-       sqlite3_close(db);
-}
-
-void linphone_create_table(sqlite3* db){
-       char* errmsg;
-       int ret;
-       ret=sqlite3_exec(db,"CREATE TABLE if not exists history (id INTEGER PRIMARY KEY AUTOINCREMENT, localContact TEXT NOT NULL, remoteContact TEXT NOT NULL, direction INTEGER, message TEXT, time TEXT NOT NULL, read INTEGER, status INTEGER);",
-               0,0,&errmsg);
-       if(ret != SQLITE_OK) {
-               printf("Error in creation: %s.\n", errmsg);
-       }
-}
-
-sqlite3 * linphone_message_storage_init(){
-       int ret;
-       char *errmsg;
-       sqlite3 *db;
-       char *filename;
-       filename=linphone_message_storage_get_config_file(NULL);
-       ret=sqlite3_open(filename,&db);
-       if(ret != SQLITE_OK) {
-               printf("Error in the opening: %s.\n", errmsg);
-               sqlite3_close(db);
-       }
-       linphone_create_table(db);
-       return db;
-}
-#else 
-
-void linphone_core_set_history_message(LinphoneChatRoom *cr,const char *local_contact,const char *remote_contact, 
-                     int direction, const char *message,const char *date, int read, int state){
-}
-
-void linphone_core_set_message_state(LinphoneChatRoom *cr,const char *message, int state, time_t date){
-}
-
-void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read){
-}
-
-MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message){
-       return NULL;
-}
+               }\r
+       }\r
+       new_message->time=argv[5]!=NULL ? mktime(&ret) : time(NULL);\r
+       new_message->state=atoi(argv[7]);\r
+       cr->messages_hist=ms_list_prepend(cr->messages_hist,(void *)new_message);\r
+}\r
+\r
+static int callback(void *data, int argc, char **argv, char **colName){\r
+    create_chat_message(argv,data);\r
+    return 0;\r
+}\r
+\r
+void linphone_sql_request_message(sqlite3 *db,const char *stmt,void *data){\r
+       char* errmsg;\r
+       int ret;\r
+       ret=sqlite3_exec(db,stmt,callback,data,&errmsg);\r
+       if(ret != SQLITE_OK) {\r
+               printf("Error in creation: %s.\n", errmsg);\r
+       }\r
+}\r
+\r
+void linphone_sql_request(sqlite3* db,const char *stmt){\r
+       char* errmsg;\r
+       int ret;\r
+       ret=sqlite3_exec(db,stmt,0,0,&errmsg);\r
+       if(ret != SQLITE_OK) {\r
+               printf("Error in creation: %s.\n", errmsg);\r
+       }\r
+}\r
+\r
+void linphone_core_set_history_message(LinphoneChatRoom *cr,const char *local_contact,const char *remote_contact, \r
+                     int direction, const char *message,const char *date, int read, int state){\r
+       LinphoneCore *lc=linphone_chat_room_get_lc(cr);\r
+       char *buf=sqlite3_mprintf("insert into history values(NULL,%Q,%Q,%i,%Q,%Q,%i,%i);",\r
+                                       local_contact,remote_contact,direction,message,date,read,state);\r
+       linphone_sql_request(lc->db,buf);\r
+}\r
+\r
+void linphone_core_set_message_state(LinphoneChatRoom *cr,const char *message, int state, time_t date){\r
+       LinphoneCore *lc=linphone_chat_room_get_lc(cr);\r
+       char time_str[26];\r
+       char *buf=sqlite3_mprintf("update history set status=%i where message = %Q and time = %Q;",\r
+                      state,message,my_ctime_r(&date,time_str));\r
+       linphone_sql_request(lc->db,buf);\r
+}\r
+\r
+void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read){\r
+       LinphoneCore *lc=linphone_chat_room_get_lc(cr);\r
+       char *buf=sqlite3_mprintf("update history set read=%i where remoteContact = %Q;",\r
+                      read,from);\r
+       linphone_sql_request(lc->db,buf);\r
+}\r
+\r
+void linphone_core_delete_history(LinphoneCore *lc,const char *from){\r
+       char *buf=sqlite3_mprintf("delete from history where remoteContact = %Q;",from);\r
+       linphone_sql_request(lc->db,buf);\r
+}\r
+\r
+MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message){\r
+       LinphoneCore *lc=linphone_chat_room_get_lc(cr);\r
+       cr->messages_hist = NULL;\r
+       char *buf=sqlite3_mprintf("select * from history where remoteContact = %Q order by id DESC limit %i ;",to,nb_message);\r
+       linphone_sql_request_message(lc->db,buf,(void *)cr);\r
+       return cr->messages_hist;\r
+}\r
+\r
+void linphone_close_storage(sqlite3* db){\r
+       sqlite3_close(db);\r
+}\r
+\r
+void linphone_create_table(sqlite3* db){\r
+       char* errmsg;\r
+       int ret;\r
+       ret=sqlite3_exec(db,"CREATE TABLE if not exists history (id INTEGER PRIMARY KEY AUTOINCREMENT, localContact TEXT NOT NULL, remoteContact TEXT NOT NULL, direction INTEGER, message TEXT, time TEXT NOT NULL, read INTEGER, status INTEGER);",\r
+               0,0,&errmsg);\r
+       if(ret != SQLITE_OK) {\r
+               printf("Error in creation: %s.\n", errmsg);\r
+       }\r
+}\r
+\r
+sqlite3 * linphone_message_storage_init(){\r
+       int ret;\r
+       char *errmsg;\r
+       sqlite3 *db;\r
+       char *filename;\r
+       filename=linphone_message_storage_get_config_file(NULL);\r
+       ret=sqlite3_open(filename,&db);\r
+       if(ret != SQLITE_OK) {\r
+               printf("Error in the opening: %s.\n", errmsg);\r
+               sqlite3_close(db);\r
+       }\r
+       linphone_create_table(db);\r
+       return db;\r
+}\r
+#else \r
+\r
+void linphone_core_set_history_message(LinphoneChatRoom *cr,const char *local_contact,const char *remote_contact, \r
+                     int direction, const char *message,const char *date, int read, int state){\r
+}\r
+\r
+void linphone_core_set_message_state(LinphoneChatRoom *cr,const char *message, int state, time_t date){\r
+}\r
+\r
+void linphone_core_set_messages_flag_read(LinphoneChatRoom *cr,const char *from, int read){\r
+}\r
+\r
+MSList *linphone_chat_room_get_history(const char *to,LinphoneChatRoom *cr,int nb_message){\r
+       return NULL;\r
+}\r
+\r
+void linphone_core_delete_history(LinphoneCore *lc,const char *from){\r
+}\r
 #endif
\ No newline at end of file
index c93d9828c27afa7ca87a0965775b750ac9ce98d3..b3a5ecfdc4340935ae2c33de040f46072380f2ee 100644 (file)
@@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include <gtkosxapplication.h>
 #endif
 
+#define NB_MSG_HIST 250
+
 void linphone_gtk_quit_chatroom(LinphoneChatRoom *cr) {
        GtkWidget *main_window=linphone_gtk_get_main_window ();
        GtkWidget *nb=linphone_gtk_get_widget(main_window,"viewswitch");
@@ -302,7 +304,7 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres
                                        "margin","indent",10,NULL);
        gtk_text_buffer_create_tag(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)),
                                        "bg","paragraph-background-gdk",&colorb,NULL);
-       messages = linphone_chat_room_get_history(with_str,cr,10);
+       messages = linphone_chat_room_get_history(with_str,cr,NB_MSG_HIST);
        display_history_message(chat_view,messages,with);
        button = linphone_gtk_get_widget(chat_view,"send");
        g_signal_connect_swapped(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_send_text,NULL);
@@ -339,7 +341,7 @@ void linphone_gtk_load_chatroom(LinphoneChatRoom *cr,const LinphoneAddress *uri,
                udpate_tab_chat_header(chat_view,uri,cr);
                g_object_set_data(G_OBJECT(chat_view),"cr",cr);
                g_object_set_data(G_OBJECT(linphone_gtk_get_widget(main_window,"contact_list")),"chatview",(gpointer)chat_view);
-               messages = linphone_chat_room_get_history(uri_only,cr,10);
+               messages = linphone_chat_room_get_history(uri_only,cr,NB_MSG_HIST);
                g_object_set_data(G_OBJECT(chat_view),"from_message",uri_str);
                display_history_message(chat_view,messages,uri);
        }
index 6ef3266103a730d4808ba48ddb35473a0ec6ce12..4ae86dfabe85ffb77b09595d5fd260a679b612cb 100644 (file)
@@ -165,6 +165,21 @@ void linphone_gtk_remove_contact(GtkWidget *button){
        }
 }
 
+void linphone_gtk_delete_history(GtkWidget *button){
+       GtkWidget *w=gtk_widget_get_toplevel(button);
+       GtkTreeSelection *select;
+       GtkTreeIter iter;
+       GtkTreeModel *model;
+       LinphoneFriend *lf=NULL;
+       select = gtk_tree_view_get_selection(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"contact_list")));
+       if (gtk_tree_selection_get_selected (select, &model, &iter))
+       {
+               gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
+               linphone_core_delete_history(linphone_gtk_get_core(),linphone_address_as_string_uri_only(linphone_friend_get_address(lf)));
+               linphone_gtk_show_friends();
+       }
+}
+
 static void linphone_gtk_call_selected(GtkTreeView *treeview){
        linphone_gtk_set_selection_to_uri_bar(treeview);
        linphone_gtk_start_call(linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(treeview)),
@@ -786,6 +801,7 @@ static GtkWidget *linphone_gtk_create_contact_menu(GtkWidget *contact_list){
        gchar *text_label=NULL;
        gchar *edit_label=NULL;
        gchar *delete_label=NULL;
+       gchar *delete_hist_label=NULL;
        gchar *name=NULL;
        GtkTreeSelection *select;
        GtkTreeIter iter;
@@ -808,6 +824,7 @@ static GtkWidget *linphone_gtk_create_contact_menu(GtkWidget *contact_list){
                text_label=g_strdup_printf(_("Send text to %s"),name);
                edit_label=g_strdup_printf(_("Edit contact '%s'"),name);
                delete_label=g_strdup_printf(_("Delete contact '%s'"),name);
+               delete_hist_label=g_strdup_printf(_("Delete chat history of '%s'"),name);
                g_free(name);
        }
        if (call_label){
@@ -847,6 +864,15 @@ static GtkWidget *linphone_gtk_create_contact_menu(GtkWidget *contact_list){
                g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_remove_contact,contact_list);
        }
 
+       if (delete_hist_label){
+               menu_item=gtk_image_menu_item_new_with_label(delete_hist_label);
+               image=gtk_image_new_from_stock(GTK_STOCK_CLEAR,GTK_ICON_SIZE_MENU);
+               gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
+               gtk_widget_show(image);
+               gtk_widget_show(menu_item);
+               gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
+               g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_delete_history,contact_list);
+       }
 
        if (ssc && (sip_setup_context_get_capabilities(ssc) & SIP_SETUP_CAP_BUDDY_LOOKUP)) {
                gchar *tmp=g_strdup_printf(_("Add new contact from %s directory"),linphone_proxy_config_get_domain(cfg));
index 8481bef7e6532dae73ce02b8bd58c0c4cafa67be..1c189e0b8ba1ca5c58231333e8e9ee5385634bb2 100644 (file)
@@ -778,6 +778,7 @@ static LangCodes supported_langs[]={
        {       "zh_TW" ,       N_("Traditional Chinese")       },
        {       "nb_NO" ,       N_("Norwegian") },
        {       "he"    ,       N_("Hebrew")    },
+       {       "sr"    ,       N_("Serbian")   },
        {       NULL    ,       NULL            }
 };