Hi! El mié, 28-07-2004 a las 20:56, Richard Hult escribió: > On ons, 2004-07-28 at 19:52 +0200, Alvaro del Castillo wrote: > > Hi guys! > > Hi! > > > > Looks good... but why did you change the gpl header? :) > > > Reverted! > > :) > > > > There are missing spaces etc coding style wise that would be nice to get > > > fixed before committing. Other than that: > > > I have review all the code another time trying to find style issues and > > can't find them :( > > Some of them: > > + g_strfreev(versionv_new); > > missing space > > +static gboolean > +check_database_tables (GdaConnection *conn) > +{ > + GdaDataModel *res; > > too many spaces before the variables > Ok, corrected these issues ;-) > + gchar *sql_file = g_build_path (G_DIR_SEPARATOR_S, > + SQL_DIR, > + name, > + NULL); > > I think you are looking for g_build_filename () here. > devhelp is my friend .... sure! better g_build_filename (SQL_DIR, name, NULL). > + else if (upgradable && !create_tables) { > + gchar *contents; > > too many spaces > > + if (!GDA_IS_CONNECTION (conn)) { > > shouldn't that just be a NULL check? > > > > _("Database %s need to be upgraded to version: %s." > > > " Please backup the database before upgrading." > > > " Have you done the backup and want to continue?") > > > > > > The last sentence should probably be removed (likewise for one more > > > dialog). > > > > Hmmm, I think the user need to answer a clear question in the dialog. > > Without this last sentence, no question is shown to the user. I have > > left it as: "Do you want to continue?" > > Well, the dialog should inform about the problem and then the buttons > should show the choices, instead of yes/no. Perhaps something like: > > The database %s needs to be upgraded from version %s to %s. > > [ Cancel ] [ Upgrade ] Hmmm, looking to the message, it has pointed me that we haven't now a way to know in which version the database is currently. We check the VERSION using the planner binary version, so if you upgrade planner, you'll have a newer version, not the version used to store the data in the database. We need someplace in database to store the version. I will bet for a version for all the data in database, not having a different version for each project in database, because it will be too complex. What do you think? About the dialog, yes, I think richard proposal is more elegant and user oriented. I will try to implement it in such way. The yes/no was the quick way because we use this dialog in other places ;-) > > > > > _("Can't create tables in database %s. File %s could be corrupted." > > > "\n\nDatabase error: \n%s"), > > > > > > I think a corrupt file would be the least probable error here, no reason > > > to make a guess like that, IMO. > > > > Yes, I have changed that to: > > > > _("Can't create tables in database %s. File %s is not correct, maybe a > > install problem." > > "\n\nDatabase error: \n%s"), > > Should probably be "Could not...". I still think we are trying to make > an impossible guess. We should check if the upgrade file exists and if > not we should say that the database is out of date but can't be upgraded > automatically from version foo to version bar. > Ok, a more general message. I was trying to show the user a way in order to find some support ... > If the file exists and the upgrade doesn't work, it's probably not an > installation problem, but more likely a bug in the upgrade file or the C > code or the way that the database is set up. Since we have no idea which > it is, we should just say that the upgrade failed and show the error > message, something like: > > The database upgrade failed:\n\n%s > Ok, I have modified the message to: _("Could not create tables in database %s. File %s is not correct." "\n\nDatabase error: \n%s"), I think it is important to show the filename in order the user could get some support from its distribution or from us in the planner user list. > > > > Should set the main window as parent window for those dialogs (also > > > something we need to go through and fix in older code). > > > > Done! I will look to all planner code to solve other places with this > > problem. > > We could add a bug for that, sounds like a perfect way to get started on > planner ;) > Yes, good point! > > > > > > _("Tables in database %s doesn't exist. " > > > "Do you want to create them?"), > > > > > > Should be "do not exist"... (or a more friendly wording like "The > > > database is not setup for Planner. Do you want to do that?".) > > > > > > > Changed it two places to: > > > > _("The database is not setup for Planner. " > > "Do you want to do that?") > > Hm, a question: Couldn't we just go ahead and add create the tables? If > the user wants to use the database in the first place, why ask again? > I think that it is good that the user knows that something is happening first time. If everything is ok, only the first time she will see such dialogs. But if something goes wrong, she will receive more information and could get more support with the details. We can let the code as it is now and see what other people think and also, we can test it a bit more to find the best solution. I will let it be as it is for now, as I have talked with richard. So before commiting this patch: 1. We need to create a place in database to store the version for all the database data. A single data with one record seems to be a terrific waste of resources, but the direct solution. Maybe we can create a special property to store it ... 2. I need to implement the new dialog with Cancel, Upgrade buttons. I attach the new patch with corrected strings and style ;-) Cheers -- Alvaro > /Richard
Index: Makefile.am =================================================================== RCS file: /cvs/gnome/planner/Makefile.am,v retrieving revision 1.12 diff -u -b -B -p -r1.12 Makefile.am --- Makefile.am 4 Jul 2004 12:51:24 -0000 1.12 +++ Makefile.am 28 Jul 2004 21:26:14 -0000 @@ -13,7 +13,6 @@ SUBDIRS = \ src \ data \ docs \ - examples \ $(python_DIR) \ $(dotnet_DIR) Index: configure.in =================================================================== RCS file: /cvs/gnome/planner/configure.in,v retrieving revision 1.37 diff -u -b -B -p -r1.37 configure.in --- configure.in 19 Jul 2004 18:46:08 -0000 1.37 +++ configure.in 28 Jul 2004 21:26:15 -0000 @@ -270,7 +270,6 @@ docs/libplanner/Makefile docs/user-guide/Makefile docs/user-guide/C/Makefile docs/sql/Makefile -examples/Makefile po/Makefile.in data/Makefile data/images/Makefile Index: libplanner/Makefile.am =================================================================== RCS file: /cvs/gnome/planner/libplanner/Makefile.am,v retrieving revision 1.7 diff -u -b -B -p -r1.7 Makefile.am --- libplanner/Makefile.am 2 May 2004 13:30:16 -0000 1.7 +++ libplanner/Makefile.am 28 Jul 2004 21:26:16 -0000 @@ -2,7 +2,8 @@ INCLUDES = \ -I. -I$(top_srcdir) \ $(LIBPLANNER_CFLAGS) $(WARN_CFLAGS) \ -DMRP_STORAGEMODULEDIR=\""$(libdir)/planner/storage-modules"\" \ - -DMRP_FILE_MODULES_DIR=\""$(libdir)/planner/file-modules"\" + -DMRP_FILE_MODULES_DIR=\""$(libdir)/planner/file-modules"\" \ + -DDATADIR=\""$(datadir)"\" lib_LTLIBRARIES = libplanner-1.la Index: libplanner/mrp-project.c =================================================================== RCS file: /cvs/gnome/planner/libplanner/mrp-project.c,v retrieving revision 1.10 diff -u -b -B -p -r1.10 mrp-project.c Index: libplanner/mrp-sql.c =================================================================== RCS file: /cvs/gnome/planner/libplanner/mrp-sql.c,v retrieving revision 1.8 diff -u -b -B -p -r1.8 mrp-sql.c --- libplanner/mrp-sql.c 25 Jun 2004 09:59:35 -0000 1.8 +++ libplanner/mrp-sql.c 28 Jul 2004 21:26:27 -0000 @@ -37,7 +37,7 @@ #define REVISION "sql-storage-revision" /* Struct to keep calendar data before we can build the tree, create the - * calendars and insert the in the project. + * calendars and insert them in the project. */ typedef struct { gint id; @@ -206,7 +206,7 @@ sql_get_last_error (GdaConnection *conne error = (GdaError *) g_list_last (list)->data; - /* Poor user, she won't get localized messages */ + /* FIXME: Poor user, she won't get localized messages */ error_txt = gda_error_get_description (error); return error_txt; @@ -430,7 +430,7 @@ sql_read_project (SQLData *data, gint pr g_free (query); if (res == NULL) { - g_warning ("Couldn't get cursor for project %s.", + g_warning ("DECLARE CURSOR command failed (project) %s.", sql_get_last_error (data->con)); goto out; } @@ -604,7 +604,7 @@ sql_read_property_specs (SQLData *data) if (res == NULL) { - g_warning ("DECLARE CURSOR command failed (propecty_specs) %s.", + g_warning ("DECLARE CURSOR command failed (propecty_type) %s.", sql_get_last_error (data->con)); goto out; } @@ -612,7 +612,7 @@ sql_read_property_specs (SQLData *data) res = sql_execute_query (data->con, "FETCH ALL in mycursor"); if (res == NULL) { - g_warning ("FETCH ALL failed for property_specs %s.", + g_warning ("FETCH ALL failed for property_type %s.", sql_get_last_error (data->con)); goto out; } @@ -695,9 +695,10 @@ sql_read_property_specs (SQLData *data) TRUE /* FIXME: user_defined, should be read from the file */); - g_hash_table_insert (data->property_type_id_hash, GINT_TO_POINTER (property_type_id), property); + g_hash_table_insert (data->property_type_id_hash, + GINT_TO_POINTER (property_type_id), property); } else { - /* Properties that are already added (e.g. cost). */ + /* FIXME: Properties that are already added (e.g. cost). */ property = mrp_project_get_property (data->project, name, owner); g_hash_table_insert (data->property_type_id_hash, GINT_TO_POINTER (property_type_id), property); } @@ -2146,6 +2147,7 @@ mrp_sql_load_project (MrpStorageSQL *sto data = g_new0 (SQLData, 1); data->project_id = -1; + /* data->project_id = project_id; */ data->day_id_hash = g_hash_table_new (NULL, NULL); data->calendar_id_hash = g_hash_table_new (NULL, NULL); data->group_id_hash = g_hash_table_new (NULL, NULL); Index: libplanner/mrp-storage-sql.c =================================================================== RCS file: /cvs/gnome/planner/libplanner/mrp-storage-sql.c,v retrieving revision 1.2 diff -u -b -B -p -r1.2 mrp-storage-sql.c Index: src/Makefile.am =================================================================== RCS file: /cvs/gnome/planner/src/Makefile.am,v retrieving revision 1.16 diff -u -b -B -p -r1.16 Makefile.am --- src/Makefile.am 21 Jun 2004 20:57:05 -0000 1.16 +++ src/Makefile.am 28 Jul 2004 21:26:29 -0000 @@ -12,6 +12,8 @@ INCLUDES = \ -DGLADEDIR=\""$(datadir)/planner/glade"\" \ -DMRP_VIEWDIR=\""$(libdir)/planner/views"\" \ -DMRP_PLUGINDIR=\""$(libdir)/planner/plugins"\" \ + -DSQL_DIR=\""$(datadir)/planner/sql"\" \ + -DVERSION=\""$(VERSION)"\" \ $(GNOMEUI_UNSTABLE) if HAVE_PYTHON_PLUGIN Index: src/planner-sql-plugin.c =================================================================== RCS file: /cvs/gnome/planner/src/planner-sql-plugin.c,v retrieving revision 1.12 diff -u -b -B -p -r1.12 planner-sql-plugin.c --- src/planner-sql-plugin.c 25 Jun 2004 09:59:35 -0000 1.12 +++ src/planner-sql-plugin.c 28 Jul 2004 21:26:32 -0000 @@ -77,6 +77,10 @@ static void sql_plugin_save static GdaDataModel * sql_execute_query (GdaConnection *con, gchar *query); + +/* FIXME: The same in mrp-sql.c. Create a SQL API in libplanner? */ +static const gchar * sql_get_last_error (GdaConnection *connection); + void plugin_init (PlannerPlugin *plugin, PlannerWindow *main_window); void plugin_exit (void); @@ -112,6 +116,23 @@ sql_execute_query (GdaConnection *con, g return res; } +static const gchar * +sql_get_last_error (GdaConnection *connection) +{ + GList *list; + GdaError *error; + const gchar *error_txt; + + list = (GList *) gda_connection_get_errors (connection); + + error = (GdaError *) g_list_last (list)->data; + + /* FIXME: Poor user, she won't get localized messages */ + error_txt = gda_error_get_description (error); + + return error_txt; +} + /** * Helper to get an int. @@ -291,6 +312,347 @@ row_activated_cb (GtkWidget *tre gtk_widget_activate (ok_button); } +/* Planner versions: + 1.x is always lower than 2.x. + 0.6 is lower than 0.11 + If 0.11.90 we don't look ".90". +*/ +static gboolean +is_newer_version (const gchar *version_new_txt, + const gchar *version_old_txt) +{ + guint subversion_old, subversion_new; + guint version_old, version_new; + gchar **versionv_new, **versionv_old; + + g_return_val_if_fail (version_new_txt != NULL && + version_old_txt != NULL, FALSE); + + version_old = g_ascii_strtod (version_old_txt, NULL); + version_new = g_ascii_strtod (version_new_txt, NULL); + + if (version_new > version_old) { + return TRUE; + } + else if (version_old > version_new) { + return FALSE; + } + + /* Need to check subversion */ + versionv_old = g_strsplit (version_old_txt,".",-1); + versionv_new = g_strsplit (version_new_txt,".",-1); + + subversion_old = g_ascii_strtod (versionv_old[1], NULL); + subversion_new = g_ascii_strtod (versionv_new[1], NULL); + + g_strfreev (versionv_new); + g_strfreev (versionv_old); + + if (subversion_new > subversion_old) { + return TRUE; + } + return FALSE; +} + +static gboolean +check_database_tables (GdaConnection *conn, + PlannerPlugin *plugin) +{ + GtkWindow *window; + GdaDataModel *res; + GtkWidget *dialog; + gint result; + GDir* dir; + const gchar *name; + gboolean upgradable = FALSE; + gboolean create_tables; + gboolean can_create_tables = FALSE; + gchar *max_version_database; + gchar *max_version_upgrade; + gchar *upgrade_file = NULL; + gchar *database_file = NULL; + const gchar *database_name; + gboolean retval = FALSE; + + max_version_database = g_strdup ("0.0"); + max_version_upgrade = g_strdup ("0.0"); + database_name = gda_connection_get_database (conn); + + window = GTK_WINDOW (plugin->main_window); + + /* Check if tables exist */ + res = sql_execute_query (conn, "SELECT proj_id FROM project"); + if (res == NULL) { + create_tables = TRUE; + } else { + create_tables = FALSE; + g_free (res); + } + + /* Check for tables */ + dir = g_dir_open (SQL_DIR, 0, NULL); + while ((name = g_dir_read_name (dir)) != NULL) { + gchar **namev = NULL, **versionv = NULL; + gchar *version; + gchar *sql_file = g_build_filename (SQL_DIR, name, NULL); + + if (strncmp (name + strlen (name) - 4, ".sql", 4) != 0) { + g_warning ("Strange file in SQL data Planner directory: %s%s", + SQL_DIR, name); + continue; + } + + /* Find version between "-" and ".sql" */ + namev = g_strsplit (sql_file,"-",-1); + /* Upgrade: 2 versions in file */ + if (namev[1] && namev[2]) { + versionv = g_strsplit (namev[2],".sql",-1); + if (is_newer_version (versionv[0], namev[1])) { + if (!strcmp (namev[1], VERSION)) { + upgradable = TRUE; + if (is_newer_version (versionv[0], + max_version_upgrade)) { + if (upgrade_file) { + g_free (upgrade_file); + } + upgrade_file = g_strdup (sql_file); + g_free (max_version_upgrade); + max_version_upgrade = g_strdup (versionv[0]); + } + } + } else { + g_warning ("Incorrect upgrade file name: %s", sql_file); + } + } + /* Create tables */ + else if (namev[1]) { + versionv = g_strsplit (namev[1],".sql",-1); + if (is_newer_version (versionv[0], max_version_database)) { + if (database_file) { + g_free (database_file); + } + database_file = g_strdup (sql_file); + g_free (max_version_database); + max_version_database = g_strdup (versionv[0]); + } + + can_create_tables = TRUE; + version = g_strdup (versionv[0]); + g_free (version); + + } else { + if (!database_file) { + database_file = g_strdup (sql_file); + } + g_warning ("File with no version: %s", sql_file); + can_create_tables = TRUE; + } + if (versionv) { + g_strfreev (versionv); + } + if (namev) { + g_strfreev (namev); + } + g_free (sql_file); + } + + if (!upgradable && !create_tables) { + retval = TRUE; + } + else if (upgradable && !create_tables) { + gchar *contents; + + dialog = gtk_message_dialog_new (window, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + _("Database %s need to be upgraded to version: %s." + " Please backup the database before upgrading." + " Do you want to continue?"), + database_name, max_version_upgrade); + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + if (result == GTK_RESPONSE_YES) { + g_file_get_contents (upgrade_file, &contents, NULL, NULL); + res = sql_execute_query (conn, contents); + g_free (contents); + if (res == NULL) { + dialog = gtk_message_dialog_new (window, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_CLOSE, + _("Could not create tables in database %s. File %s is not correct." + "\n\nDatabase error: \n%s"), + database_name, upgrade_file, + sql_get_last_error (conn)); + + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + retval = FALSE; + } else { + retval = TRUE; + g_free (res); + } + } else { + retval = FALSE; + } + g_free (upgrade_file); + } + + else if (create_tables && !can_create_tables) { + g_warning ("Need to create tables but no database file"); + retval = FALSE; + } + + else if (create_tables && can_create_tables) { + gchar *contents; + + dialog = gtk_message_dialog_new (window, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + _("Database %s is not setup for Planner. " + "Do you want to do that?"), + database_name); + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + if (result == GTK_RESPONSE_YES) { + g_file_get_contents (database_file, &contents, NULL, NULL); + res = sql_execute_query (conn, contents); + g_free (contents); + if (res == NULL) { + dialog = gtk_message_dialog_new (window, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_CLOSE, + _("Can't create tables in database %s"), + database_name); + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + retval = FALSE; + } else { + g_free (res); + retval = TRUE; + } + } + g_free (database_file); + } + + g_free (max_version_upgrade); + g_free (max_version_database); + return retval; +} + +/* Try to create the database */ +static gboolean +create_database (const gchar *dsn_name, + const gchar *db_name, + PlannerPlugin *plugin) +{ + GtkWidget *dialog; + GtkWindow *window; + guint result; + gboolean retval; + GdaConnection *conn; + GdaClient *client; + GdaDataSourceInfo *dsn; + gchar *cnc_string_orig; + /* FIXME: In postgresql we use template1 as the connection database */ + gchar *init_database = "template1"; + gchar *query; + + dsn = gda_config_find_data_source (dsn_name); + cnc_string_orig = dsn->cnc_string; + retval = FALSE; + + window = GTK_WINDOW (plugin->main_window); + + /* Use same data but changing the database */ + dsn->cnc_string = g_strdup_printf ("DATABASE=%s", init_database); + gda_config_save_data_source_info (dsn); + + client = gda_client_new (); + conn = gda_client_open_connection (client, dsn_name, NULL, NULL, 0); + if (conn == NULL) { + g_warning ("Can't connect to database server in order to check/create the database: %s", cnc_string_orig); + } else { + dialog = gtk_message_dialog_new (window, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + _("Database %s is not setup for Planner. " + "Do you want to do that?"), + db_name); + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + if (result == GTK_RESPONSE_YES) { + query = g_strdup_printf ("CREATE DATABASE %s WITH ENCODING = 'UTF8'", + db_name); + sql_execute_query (conn, query); + g_free (query); + /* FIXME: Tables will need the group: dirty relation between + code and tables definitions in sql file.*/ + query = g_strdup_printf ("CREATE GROUP planner WITH USER %s", + gda_connection_get_username (conn)); + sql_execute_query (conn, query); + g_free (query); + retval = TRUE; + } else { + retval = FALSE; + } + gda_connection_close (conn); + g_object_unref (client); + } + g_free (dsn->cnc_string); + dsn->cnc_string = cnc_string_orig; + gda_config_save_data_source_info (dsn); + + return retval; +} + +/* Test database status: database exists, correct tables, correct version */ +static GdaConnection * +sql_get_tested_connection (const gchar *dsn_name, + const gchar *db_name, + GdaClient *client, + PlannerPlugin *plugin) +{ + GdaConnection *conn; + gchar *str; + + conn = gda_client_open_connection (client, dsn_name, NULL, NULL, 0); + + if (conn == NULL) { + if (!create_database (dsn_name, db_name, plugin)) { + str = g_strdup_printf (_("Connection to database '%s' failed."), + db_name); + show_error_dialog (plugin, str); + conn = NULL; + } else { + conn = gda_client_open_connection (client, dsn_name, NULL, NULL, 0); + } + } + + if (conn != NULL) { + if (!check_database_tables (conn, plugin)) { + str = g_strdup_printf (_("Test to tables in database '%s' failed."), db_name); + show_error_dialog (plugin, str); + g_free (str); + gda_connection_close (conn); + conn = NULL; + } + } + + /* g_object_unref (client); */ + return conn; +} + /** * Display a list with projects and let the user select one. Returns the project * id of the selected one. @@ -306,7 +668,6 @@ sql_plugin_retrieve_project_id (PlannerP GdaConnection *conn; GdaDataModel *res; GdaClient *client; - gchar *str; GladeXML *gui; GtkWidget *dialog; GtkWidget *treeview; @@ -331,13 +692,9 @@ sql_plugin_retrieve_project_id (PlannerP g_free (db_txt); client = gda_client_new (); + conn = sql_get_tested_connection (dsn_name, database, client, plugin); - conn = gda_client_open_connection (client, dsn_name, NULL, NULL, 0); - - if (!GDA_IS_CONNECTION (conn)) { - str = g_strdup_printf (_("Connection to database '%s' failed."), database); - show_error_dialog (plugin, str); - g_free (str); + if (conn == NULL) { return -1; } @@ -347,7 +704,6 @@ sql_plugin_retrieve_project_id (PlannerP return -1; } g_object_unref (res); - res = NULL; res = sql_execute_query (conn, "DECLARE mycursor CURSOR FOR SELECT proj_id, name," @@ -694,6 +1049,8 @@ sql_plugin_save (BonoboUIComponent *comp gpointer user_data, const gchar *cname) { + GdaClient *client; + GdaConnection *conn; PlannerPlugin *plugin = user_data; MrpProject *project; GObject *object; @@ -703,7 +1060,11 @@ sql_plugin_save (BonoboUIComponent *comp gchar *login = NULL; gchar *password = NULL; gchar *uri = NULL; + const gchar *uri_plan = NULL; GError *error = NULL; + gchar *db_txt; + const gchar *dsn_name = "planner-auto"; + const gchar *provider = "PostgreSQL"; project = planner_window_get_project (plugin->main_window); @@ -717,19 +1078,56 @@ sql_plugin_save (BonoboUIComponent *comp return; } + db_txt = g_strdup_printf ("DATABASE=%s",database); + gda_config_save_data_source (dsn_name, + provider, + db_txt, + "planner project", login, password); + g_free (db_txt); + client = gda_client_new (); + conn = sql_get_tested_connection (dsn_name, database, client, plugin); + if (conn == NULL) { + g_object_unref (client); + return; + } + gda_connection_close (conn); + g_object_unref (client); + /* This code is prepared for getting support for selecting a project to * save over. Needs finishing though. Pass project id -1 for now (always * create a new project). */ - uri = create_sql_uri (server, port, database, login, password, -1); + uri_plan = mrp_project_get_uri (project); + /* First time project */ + if (uri_plan == NULL) { + uri = create_sql_uri (server, port, database, login, password, -1); if (!mrp_project_save_as (project, uri, FALSE, &error)) { show_error_dialog (plugin, error->message); g_clear_error (&error); goto fail; } + g_free (uri); + } + /* Project was in database */ + else if (strncmp (uri_plan, "sql://", 6) == 0) { + if (!mrp_project_save (project, FALSE, &error)) { + show_error_dialog (plugin, error->message); + g_clear_error (&error); + goto fail; + } + } + /* Project wasn't in database */ + else { + uri = create_sql_uri (server, port, database, login, password, -1); + if (!mrp_project_save_as (project, uri, FALSE, &error)) { + show_error_dialog (plugin, error->message); + g_clear_error (&error); + goto fail; + } g_free (uri); + } object = G_OBJECT (plugin->main_window);
Attachment:
signature.asc
Description: Esta parte del mensaje =?ISO-8859-1?Q?est=E1?= firmada digitalmente