diff --git a/share/tryton/tryton.glade b/share/tryton/tryton.glade
index e3c4caf1bc..11b77ffed2 100644
--- a/share/tryton/tryton.glade
+++ b/share/tryton/tryton.glade
@@ -1746,216 +1746,6 @@ Latin1
-
- Choose a Database...
- GTK_WIN_POS_CENTER_ON_PARENT
- GDK_WINDOW_TYPE_HINT_DIALOG
-
-
- True
-
-
- True
- 3
- 3
-
-
- True
- 0
- <b>Backup a Database</b>
- True
-
-
- False
- False
-
-
-
-
- True
-
-
- False
- False
- 1
-
-
-
-
- True
- 2
- 3
- 3
- 3
- 3
-
-
- True
- 1
- 3
- 3
- Tryton Server Password:
- GTK_JUSTIFY_RIGHT
-
-
- 1
- 2
- GTK_FILL
-
-
-
-
-
- True
- 1
- Database:
-
-
- 2
- 3
- GTK_FILL
-
-
-
-
-
- True
-
-
- True
-
-
-
-
- True
- 0
- True
-
-
- False
- False
- 1
-
-
-
-
- 1
- 3
- 2
- 3
- GTK_FILL
- GTK_FILL
-
-
-
-
- True
- True
- True
- False
- True
- 16
-
-
- 1
- 3
- 1
- 2
-
-
-
-
-
- 117
- True
- 1
- 3
- 3
- Server:
-
-
- GTK_FILL
-
-
-
-
-
- True
- True
- Change
- 0
-
-
-
- 2
- 3
- GTK_FILL
-
-
-
-
-
- True
- False
- False
- True
- 16
- http://localhost:8069
-
-
- 1
- 2
-
-
-
-
-
- False
- False
- 2
-
-
-
-
- 2
-
-
-
-
- True
- GTK_BUTTONBOX_END
-
-
- True
- True
- True
- gtk-cancel
- True
- -6
-
-
-
-
- True
- True
- True
- gtk-ok
- True
- -5
-
-
- 1
-
-
-
-
- False
- GTK_PACK_END
-
-
-
-
-
Restore a Database
GTK_WIN_POS_CENTER_ON_PARENT
diff --git a/tryton/gui/main.py b/tryton/gui/main.py
index 53614c2171..57de322a36 100644
--- a/tryton/gui/main.py
+++ b/tryton/gui/main.py
@@ -14,6 +14,7 @@ from tryton.gui.window.preference import Preference
from tryton.gui.window import FilesActions
from tryton.gui.window.dblogin import DBLogin
from tryton.gui.window.dbcreate import DBCreate
+from tryton.gui.window.dbdumpdrop import DBBackupDrop
from tryton.gui.window.tips import Tips
from tryton.gui.window.about import About
from tryton.gui.window.shortcuts import Shortcuts
@@ -1273,24 +1274,35 @@ class Main(object):
def sig_db_drop(self, widget):
if not self.sig_logout(widget):
return False
- url, dbname, passwd = self._choose_db_select(_('Delete a database'))
+ dialog = DBBackupDrop(self.window, function='drop')
+ url, dbname, passwd = dialog.run(self.window)
if not dbname:
rpc.logout()
Main.get_main().refresh_ssl()
return
host, port = url.rsplit(':', 1)
-
+ sure = common.sur_3b(_("You are going to delete a Tryton " \
+ "database.\nAre you really sure to proceed?"), self.window)
+ if sure == "ko" or sure == "cancel":
+ return
try:
rpc.db_exec(host, int(port), 'drop', passwd, dbname)
except Exception, exception:
self.refresh_ssl()
- common.warning(_('Database drop failed with '\
- 'error message:\n') + str(exception[0]), self.window,
- _('Database drop failed!'))
+ if exception[0] == "AccessDenied":
+ common.warning(_("The Tryton Server Password you provided " \
+ "is different to the stored password in the " \
+ "configuration.\n\nPlease try again."), \
+ self.window, _('Access denied!'))
+ self.sig_db_drop(self.window)
+ else:
+ common.warning(_('Database drop failed with ' \
+ 'error message:\n') + str(exception[0]), \
+ self.window, _('Database drop failed!'))
return
self.refresh_ssl()
- common.message(_("Database dropped successfully!"),
+ common.message(_("Database dropped successfully!"), \
parent=self.window)
def sig_db_restore(self, widget):
@@ -1374,8 +1386,10 @@ class Main(object):
win.destroy()
def sig_db_dump(self, widget):
- url, dbname, passwd = self._choose_db_select(_('Backup a database'))
- if not dbname:
+ dialog = DBBackupDrop(self.window, function='backup')
+ url, dbname, passwd = dialog.run(self.window)
+
+ if not (dbname and url and passwd):
rpc.logout()
Main.get_main().refresh_ssl()
return
@@ -1384,105 +1398,45 @@ class Main(object):
try:
dump_b64 = rpc.db_exec(host, int(port), 'dump', passwd, dbname)
except Exception, exception:
+ if exception[0] == "Couldn't dump database with password":
+ common.warning(_("It is impossible to dump a password " \
+ "protected Database.\nBackground: \n" \
+ "The Postgres database backup and restore " \
+ "functions 'pg_dump' and 'pg_restore' did not " \
+ "support passwords at all. Backup and restore " \
+ "needed to be proceed manual."), \
+ self.window, _('Database is password protected!'))
+ elif exception[0] == "AccessDenied":
+ common.warning(_("The Tryton Server Password you provided " \
+ "is different to the stored password in the " \
+ "configuration.\n\nPlease try again."), \
+ self.window, _('Access denied!'))
+ self.sig_db_dump(self.window)
+ else:
+ common.warning(_('Database dump failed with ' \
+ 'error message:\n') + str(exception[0]), \
+ self.window, _('Database dump failed!'))
rpc.logout()
Main.get_main().refresh_ssl()
- common.warning(_('Database dump failed with error message:\n') + \
- str(exception[0]), self.window, _('Database dump failed!'))
return
+
self.refresh_ssl()
dump = base64.decodestring(dump_b64)
- filename = common.file_selection(_('Save As...'),
- action=gtk.FILE_CHOOSER_ACTION_SAVE, parent=self.window,
+ filename = common.file_selection(_('Save As...'), \
+ action=gtk.FILE_CHOOSER_ACTION_SAVE, parent=self.window, \
preview=False)
if filename:
file_ = file(filename, 'wb')
file_.write(dump)
file_.close()
- common.message(_("Database backuped successfully!"),
+ common.message(_("Database backuped successfully!"), \
parent=self.window)
else:
rpc.logout()
Main.get_main().refresh_ssl()
- def _choose_db_select(self, title=_("Backup a database")):
- def refreshlist(widget, db_widget, label, host, port):
- res = common.refresh_dblist(db_widget, host, port)
- if res is None or res == -1:
- if res is None:
- label.set_label('' + _('Could not connect to server!') +\
- '')
- else:
- label.set_label('' + \
- _('Incompatible version of the server!') + '')
- db_widget.hide()
- label.show()
- elif res == 0:
- label.set_label('' + \
- _('No database found, you must create one!') + '')
- db_widget.hide()
- label.show()
- else:
- label.hide()
- db_widget.show()
- return res
-
- def refreshlist_ask(widget, server_widget, db_widget, label,
- parent=None):
- res = common.request_server(server_widget, parent)
- if not res:
- return None
- host, port = res
- refreshlist(widget, db_widget, label, host, port)
- return (host, port)
-
- dialog = glade.XML(GLADE, "win_db_select",
- gettext.textdomain())
- win = dialog.get_widget('win_db_select')
- win.set_icon(TRYTON_ICON)
- win.set_default_response(gtk.RESPONSE_OK)
- win.set_transient_for(self.window)
- win.show_all()
-
- pass_widget = dialog.get_widget('ent_passwd_select')
- server_widget = dialog.get_widget('ent_server_select')
- db_widget = dialog.get_widget('combo_db_select')
- label = dialog.get_widget('label_db_select')
-
-
- dialog.get_widget('db_select_label').set_markup(''+title+'')
-
- host = CONFIG['login.server']
- port = int(CONFIG['login.port'])
- url = '%s:%d' % (host, port)
- server_widget.set_text(url)
-
- liststore = gtk.ListStore(str)
- db_widget.set_model(liststore)
-
- refreshlist(None, db_widget, label, host, port)
- change_button = dialog.get_widget('but_server_select')
- change_button.connect_after('clicked', refreshlist_ask,
- server_widget, db_widget, label, win)
-
- cell = gtk.CellRendererText()
- db_widget.pack_start(cell, True)
- db_widget.add_attribute(cell, 'text', 0)
-
- res = win.run()
-
- database = False
- url = False
- passwd = False
- if res == gtk.RESPONSE_OK:
- database = db_widget.get_active_text()
- url = server_widget.get_text()
- passwd = pass_widget.get_text()
- self.window.present()
- win.destroy()
- return (url, database, passwd)
-
def _choose_db_ent(self):
dialog = glade.XML(GLADE, "win_db_ent",
gettext.textdomain())
diff --git a/tryton/gui/window/dbdumpdrop.py b/tryton/gui/window/dbdumpdrop.py
new file mode 100644
index 0000000000..8d15576d8a
--- /dev/null
+++ b/tryton/gui/window/dbdumpdrop.py
@@ -0,0 +1,225 @@
+# This file is part of Tryton. The COPYRIGHT file at the top level of this
+# repository contains the full copyright notices and license terms.
+import gtk
+import gettext
+import tryton.common as common
+from tryton.config import CONFIG, TRYTON_ICON
+import tryton.rpc as rpc
+
+_ = gettext.gettext
+
+class DBBackupDrop(object):
+ """
+ Widget for database backup and drop.
+ """
+ @staticmethod
+ def refreshlist(widget, db_widget, label, host, port):
+ res = common.refresh_dblist(db_widget, host, port)
+ if res is None or res == -1:
+ if res is None:
+ label.set_label('' + \
+ _('Could not connect to server!') + '')
+ else:
+ label.set_label('' + \
+ _('Incompatible version of the server!') + '')
+ db_widget.hide()
+ label.show()
+ elif res == 0:
+ label.set_label('' + \
+ _('No database found, you must create one!') + '')
+ db_widget.hide()
+ label.show()
+ else:
+ label.hide()
+ db_widget.show()
+ return res
+
+ @staticmethod
+ def refreshlist_ask(widget, server_widget, db_widget, label, parent=None):
+ res = common.request_server(server_widget, parent)
+ if not res:
+ return None
+ host, port = res
+ DBBackupDrop.refreshlist(widget, db_widget, label, host, port)
+ return (host, port)
+
+ def event_show_button_ok(self, widget, event, data=None):
+ """
+ This event method decide by rules if the Create button will be
+ sensitive or insensitive. The general rule is, all given fields
+ must be filled, then the Create button is set to sensitive. This
+ event method doesn't check the valid of single entrys.
+ """
+ if self.entry_server_connection.get_text() != "" \
+ and self.combo_database.get_active() != -1 \
+ and self.entry_serverpasswd.get_text() != "":
+ widget.unset_flags(gtk.HAS_DEFAULT)
+ self.button_ok.set_sensitive(True)
+ self.button_ok.set_flags(gtk.CAN_DEFAULT)
+ self.button_ok.set_flags(gtk.HAS_DEFAULT)
+ self.button_ok.set_flags(gtk.CAN_FOCUS)
+ self.button_ok.set_flags(gtk.RECEIVES_DEFAULT)
+ self.button_ok.grab_default()
+ else:
+ self.button_ok.set_sensitive(False)
+
+ def __init__(self, parent, function=None):
+ # This widget is used for creating and droping a database!
+ if function =="backup":
+ dialog_title = _("Backup a database")
+ button_ok_text = _("Backup")
+ button_ok_tooltip = _("Backup the choosen database.")
+ button_ok_icon = "tryton-save-as"
+ label_subtitle_text = _("Choose a Tryton database to backup:")
+ elif function == "drop":
+ dialog_title = _("Delete a database")
+ button_ok_text = _("Delete")
+ button_ok_tooltip = _("Delete the choosen database.")
+ button_ok_icon = "tryton-delete"
+ label_subtitle_text = _("Choose a Tryton database to delete:")
+ else:
+ return None
+
+ self.dialog = gtk.Dialog( \
+ title = dialog_title, \
+ parent = parent, \
+ flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT \
+ | gtk.WIN_POS_CENTER_ON_PARENT,)
+ self.dialog.set_has_separator(True)
+ self.dialog.set_size_request(500, 201)
+ self.dialog.set_icon(TRYTON_ICON)
+ self.dialog.connect("key-press-event", self.event_show_button_ok)
+ self.tooltips = gtk.Tooltips()
+ self.dialog.add_button("gtk-cancel", \
+ gtk.RESPONSE_CANCEL)
+ self.button_ok = gtk.Button(button_ok_text)
+ self.button_ok.set_flags(gtk.CAN_DEFAULT)
+ self.button_ok.set_flags(gtk.HAS_DEFAULT)
+ self.button_ok.set_sensitive(False)
+ img_connect = gtk.Image()
+ img_connect.set_from_stock(button_ok_icon, gtk.ICON_SIZE_BUTTON)
+ self.button_ok.set_image(img_connect)
+ self.tooltips.set_tip(self.button_ok, button_ok_tooltip)
+ self.dialog.add_action_widget(self.button_ok, gtk.RESPONSE_OK)
+ self.dialog.set_default_response(gtk.RESPONSE_OK)
+ self.dialog_vbox = gtk.VBox()
+
+ table = gtk.Table(5, 3, False)
+ table.set_border_width(10)
+ table.set_row_spacings(3)
+ table.set_col_spacings(3)
+ self.dialog_vbox.pack_start(table, True, True,0)
+
+ label_subtitle = gtk.Label()
+ label_subtitle.set_markup(""+ label_subtitle_text + "")
+ label_subtitle.set_justify(gtk.JUSTIFY_LEFT)
+ label_subtitle.set_alignment(0, 1)
+ label_subtitle.set_padding( 9, 5)
+ table.attach(label_subtitle, 0, 3, 0, 1, xoptions=gtk.FILL)
+
+ hseparator = gtk.HSeparator()
+ table.attach(hseparator, 0, 3, 1, 2)
+
+ label_server = gtk.Label(_("Server Connection:"))
+ label_server.set_alignment(1, 0.5)
+ label_server.set_padding(3, 3)
+ table.attach(label_server, 0, 1, 2, 3, xoptions=gtk.FILL)
+
+ self.entry_server_connection = gtk.Entry()
+ self.entry_server_connection.set_sensitive(False)
+ self.entry_server_connection.unset_flags(gtk.CAN_FOCUS)
+ self.entry_server_connection.set_editable(False)
+ self.entry_server_connection.set_text("http://localhost:8070")
+ self.tooltips.set_tip(self.entry_server_connection, _("This is the " \
+ "URL of the server. Use server 'localhost' and port '8070' " \
+ "if the server is installed on this computer. " \
+ "Click on 'Change' to change the address."), None)
+ table.attach(self.entry_server_connection, 1, 2, 2, 3)
+
+ self.button_server_change = gtk.Button(_("C_hange"), stock=None, \
+ use_underline=True)
+ img_button_server_change = gtk.Image()
+ img_button_server_change.set_from_stock('tryton-preferences-system', \
+ gtk.ICON_SIZE_BUTTON)
+ self.button_server_change.set_image(img_button_server_change)
+ table.attach(self.button_server_change, 2, 3, 2, 3, yoptions=False, \
+ xoptions=gtk.FILL)
+
+ self.label_database = gtk.Label()
+ self.label_database.set_text(_("Database:"))
+ self.label_database.set_alignment(1, 0.5)
+ self.label_database.set_padding(3, 3)
+ table.attach(self.label_database, 0, 1, 3, 4, xoptions=gtk.FILL)
+
+ vbox_combo = gtk.VBox()
+ self.combo_database = gtk.ComboBox()
+ self.combo_database_label = gtk.Label()
+ self.combo_database_label.set_use_markup(True)
+ self.combo_database_label.set_alignment(0, 1)
+ vbox_combo.pack_start(self.combo_database, True, True, 0)
+ vbox_combo.pack_start(self.combo_database_label, False, False, 0)
+ table.attach(vbox_combo, 1, 2, 3, 4)
+
+ label_serverpasswd = gtk.Label(_("Tryton Server Password:"))
+ label_serverpasswd.set_justify(gtk.JUSTIFY_RIGHT)
+ label_serverpasswd.set_alignment(1, 0.5)
+ label_serverpasswd.set_padding( 3, 3)
+ table.attach(label_serverpasswd, 0, 1, 4, 5, xoptions=gtk.FILL)
+
+ self.entry_serverpasswd = gtk.Entry()
+ self.entry_serverpasswd.set_visibility(False)
+ self.entry_serverpasswd.set_activates_default(True)
+ self.tooltips.set_tip(self.entry_serverpasswd, _("This is the " \
+ "password of the Tryton server. It doesn't belong to a " \
+ "real user. This password is usually defined in the trytond " \
+ "configuration."), None)
+ table.attach(self.entry_serverpasswd, 1, 2, 4, 5)
+
+ self.entry_serverpasswd.grab_focus()
+ self.dialog.vbox.pack_start(self.dialog_vbox)
+
+ def run(self, parent):
+ self.dialog.set_default_response(gtk.RESPONSE_OK)
+ self.dialog.set_transient_for(parent)
+ self.dialog.show_all()
+
+ pass_widget = self.entry_serverpasswd
+ server_widget = self.entry_server_connection
+ db_widget = self.combo_database
+ label = self.combo_database_label
+
+ host = CONFIG['login.server']
+ port = int(CONFIG['login.port'])
+ url = '%s:%d' % (host, port)
+ server_widget.set_text(url)
+
+ liststore = gtk.ListStore(str)
+ db_widget.set_model(liststore)
+ cell = gtk.CellRendererText()
+ db_widget.pack_start(cell, True)
+ db_widget.add_attribute(cell, 'text', 0)
+ res = self.refreshlist(None, db_widget, label, host, port)
+
+ change_button = self.button_server_change
+ change_button.connect_after('clicked', DBBackupDrop.refreshlist_ask, \
+ server_widget, db_widget, label, self.dialog)
+
+ while True:
+ database = False
+ url = False
+ passwd = False
+ res = self.dialog.run()
+ if res == gtk.RESPONSE_OK:
+ database = db_widget.get_active_text()
+ url = server_widget.get_text()
+ passwd = pass_widget.get_text()
+ break
+ if res != gtk.RESPONSE_OK:
+ self.dialog.destroy()
+ rpc.logout()
+ break
+ parent.present()
+ self.dialog.destroy()
+
+ return (url, database, passwd)
+