Rewrite the dbcreate from glade to pygtk with additional functions.
- Better tooltips for all widgets - While input validation for databasename - Restrict databasenames according to he following rules: - Allowed characters are alpha-nummeric [A-Za-z0-9] and underscore (_) - First character must be a letter - Length of databasename less equal 63 characters - Less popup windows on wrong entrys - Create button appears only if all required entrys compleated - Introduce another error message for AccessDenied: tryton server password is wrong! - All entryboxes listen to signal ctrl-u by clear the actual entrybox - Message "Can't connect to database" is appened in the same box where the connection is shown. No additional popup. (Needs fitting in the regex in common.py. See next commit.) - Renaming the variables to more meaningful names. - All buttons get icons.
This commit is contained in:
1 parent
770d8ee969
commit
7527f9aebe
1 file changed
+324
-81
+324
-81
@@ -1,6 +1,7 @@
|
||||
#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
|
||||
from gtk import glade
|
||||
#from gtk import glade
|
||||
import gobject
|
||||
import gettext
|
||||
import re
|
||||
import tryton.common as common
|
||||
@@ -9,125 +10,367 @@ import tryton.rpc as rpc
|
||||
|
||||
_ = gettext.gettext
|
||||
|
||||
# Some Postgres restrictions for the DB_Name
|
||||
def move_cursor(entry, pos):
|
||||
entry.set_position(pos)
|
||||
return False
|
||||
|
||||
def entry_insert_text(entry, new_text, new_text_length, position):
|
||||
if (new_text.isalnum() or new_text == '_' ):
|
||||
# _string = entry.get_chars(0, -1) + new_text
|
||||
_hid = entry.get_data('handlerid')
|
||||
entry.handler_block(_hid)
|
||||
_pos = entry.get_position()
|
||||
# _val = _string
|
||||
if _pos == 0 and not new_text.isalpha():
|
||||
new_text = ""
|
||||
|
||||
_pos = entry.insert_text(new_text, _pos)
|
||||
entry.handler_unblock(_hid)
|
||||
gobject.idle_add(move_cursor, entry, _pos)
|
||||
|
||||
entry.stop_emission("insert-text")
|
||||
|
||||
class DBCreate(object):
|
||||
def set_sensitive(self, sensitive):
|
||||
def server_connection_state(self, sensitive):
|
||||
if sensitive:
|
||||
label = self.dialog.get_widget('db_label_info')
|
||||
label.set_text(_('Do not use special characters!'))
|
||||
self.dialog.get_widget('button_db_ok').set_sensitive(True)
|
||||
self.entry_server.modify_text(gtk.STATE_INSENSITIVE, gtk.gdk.color_parse("#000000"))
|
||||
# self.button_db_ok.set_flags(gtk.CAN_FOCUS)
|
||||
# self.button_db_ok.grab_focus()
|
||||
self.button_db_ok.set_sensitive(True)
|
||||
self.button_db_ok.set_flags(gtk.CAN_DEFAULT)
|
||||
self.button_db_ok.unset_flags(gtk.HAS_DEFAULT)
|
||||
self.button_db_ok.grab_default()
|
||||
self.button_db_ok.set_flags(gtk.RECEIVES_DEFAULT)
|
||||
else:
|
||||
label = self.dialog.get_widget('db_label_info')
|
||||
label.set_markup('<b>' + \
|
||||
_('Can not connect to server!') + '</b>')
|
||||
self.dialog.get_widget('button_db_ok').set_sensitive(False)
|
||||
self.entry_server.set_editable(False)
|
||||
self.entry_server.set_sensitive(False)
|
||||
self.entry_server.set_text(self.entry_server.get_text() + " " + _('Can not connect to server!'))
|
||||
self.entry_server.modify_text(gtk.STATE_INSENSITIVE, gtk.gdk.color_parse("#ff0000"))
|
||||
self.button_db_ok.set_sensitive(False)
|
||||
self.button_db_ok.unset_flags(gtk.CAN_DEFAULT)
|
||||
self.button_db_ok.unset_flags(gtk.HAS_DEFAULT)
|
||||
return sensitive
|
||||
|
||||
def server_change(self, widget, parent):
|
||||
res = common.request_server(self.server_widget, parent)
|
||||
res = common.request_server(self.entry_server, parent)
|
||||
if not res:
|
||||
return False
|
||||
host, port = res
|
||||
try:
|
||||
if self.lang_widget and host and port:
|
||||
common.refresh_langlist(self.lang_widget, host, port)
|
||||
self.set_sensitive(True)
|
||||
if self.combo_default_lang and host and port:
|
||||
common.refresh_langlist(self.combo_default_lang, host, port)
|
||||
self.server_connection_state(True)
|
||||
except:
|
||||
self.set_sensitive(False)
|
||||
self.server_connection_state(False)
|
||||
return False
|
||||
return True
|
||||
|
||||
def event_passwd_clear( self, widget, event, data=None ):
|
||||
if event.keyval == gtk.keysyms.u:
|
||||
widget.set_text("")
|
||||
|
||||
def event_show_button_create( self, widget, event, data=None ):
|
||||
if self.entry_server.get_text() != _("") \
|
||||
and self.entry_password_new.get_text() != "" \
|
||||
and self.entry_new_db.get_text() != "" \
|
||||
and self.combo_default_lang.get_active() != -1 \
|
||||
and self.ent_password_admin.get_text() != "" \
|
||||
and self.ent_re_password_admin.get_text() != "":
|
||||
self.button_db_ok.set_sensitive(True)
|
||||
else:
|
||||
self.button_db_ok.set_sensitive(False)
|
||||
|
||||
def __init__(self, sig_login):
|
||||
self.dialog = glade.XML(GLADE, "win_createdb", gettext.textdomain())
|
||||
|
||||
self.dialog = gtk.Dialog(
|
||||
title = _("Create New Database"),
|
||||
parent = None,
|
||||
flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
|
||||
| gtk.WIN_POS_CENTER_ON_PARENT,
|
||||
)
|
||||
self.dialog.connect("key-press-event", self.event_show_button_create)
|
||||
self.dialog.connect("focus-in-event", self.event_show_button_create)
|
||||
self.dialog.connect("focus-out-event", self.event_show_button_create)
|
||||
|
||||
tooltips = gtk.Tooltips()
|
||||
|
||||
self.dialog.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
|
||||
self.dialog.set_has_separator(False)
|
||||
|
||||
dialog_vbox = gtk.VBox()
|
||||
|
||||
table_main = gtk.Table(9, 3, False)
|
||||
table_main.set_border_width(10)
|
||||
table_main.set_row_spacings(3)
|
||||
table_main.set_col_spacings(3)
|
||||
dialog_vbox.pack_start(table_main)
|
||||
|
||||
label_credentials = gtk.Label()
|
||||
label_credentials.set_markup("<b>" + _("Tryton Administration " \
|
||||
"Credentials") + "</b>")
|
||||
label_credentials.set_justify(gtk.JUSTIFY_LEFT)
|
||||
label_credentials.set_alignment(0, 1)
|
||||
label_credentials.set_padding( 9, 5)
|
||||
table_main.attach(label_credentials, 0, 3, 0, 1, xoptions=gtk.EXPAND \
|
||||
| gtk.FILL)
|
||||
|
||||
label_server = gtk.Label(_("Server:"))
|
||||
label_server.set_alignment(1, 0.5)
|
||||
label_server.set_padding(3, 3)
|
||||
table_main.attach(label_server, 0, 1, 1, 2, xoptions=gtk.FILL)
|
||||
|
||||
self.entry_server = gtk.Entry()
|
||||
self.entry_server.set_sensitive(False)
|
||||
|
||||
self.entry_server.unset_flags(gtk.CAN_FOCUS)
|
||||
self.entry_server.set_editable(False)
|
||||
self.entry_server.set_text(_("http://localhost:8070"))
|
||||
self.entry_server.set_width_chars(16)
|
||||
table_main.attach(self.entry_server, 1, 2, 1, 2)
|
||||
tooltips.set_tip(self.entry_server, _("This is the URL of the Tryton " \
|
||||
"server. Use 'localhost' if the server is installed on this " \
|
||||
"computer. Click on 'Change' to change the address."), None)
|
||||
|
||||
self.but_server_new = gtk.Button(_("C_hange"), stock=None,
|
||||
use_underline=True)
|
||||
img_but_server_new = gtk.Image()
|
||||
img_but_server_new.set_from_stock('tryton-preferences-system', \
|
||||
gtk.ICON_SIZE_BUTTON)
|
||||
self.but_server_new.set_image(img_but_server_new)
|
||||
table_main.attach(self.but_server_new, 2, 3, 1, 2, xoptions=gtk.FILL)
|
||||
tooltips.set_tip(self.but_server_new, _("Setup the Tryton server " \
|
||||
"connection..."), None)
|
||||
|
||||
label_server_password = gtk.Label(_("Server Password:"))
|
||||
label_server_password.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
label_server_password.set_alignment(1, 0.5)
|
||||
label_server_password.set_padding( 3, 3)
|
||||
table_main.attach(label_server_password, 0, 1, 2, 3)
|
||||
|
||||
self.entry_password_new = gtk.Entry()
|
||||
self.entry_password_new.set_max_length(16)
|
||||
self.entry_password_new.set_visibility(False)
|
||||
self.entry_password_new.set_activates_default(True)
|
||||
|
||||
self.entry_password_new.set_width_chars(16)
|
||||
table_main.attach(self.entry_password_new, 1, 3, 2, 3, yoptions=False,
|
||||
xoptions=gtk.EXPAND | gtk.FILL)
|
||||
tooltips.set_tip(self.entry_password_new, _("This is the Password " \
|
||||
"password for Tryton administration. It doesn't belong to a " \
|
||||
"Tryton user. This password is usually defined in the trytond" \
|
||||
"configuration."), None)
|
||||
self.entry_password_new.connect("key-press-event", self.event_passwd_clear)
|
||||
|
||||
hseparator = gtk.HSeparator()
|
||||
table_main.attach(hseparator, 0, 3, 3, 4, yoptions=False,
|
||||
xoptions=gtk.EXPAND | gtk.FILL)
|
||||
|
||||
label_new_db = gtk.Label()
|
||||
label_new_db.set_markup("<b>" + _("New Database Settings") \
|
||||
+ "</b>")
|
||||
label_new_db.set_justify(gtk.JUSTIFY_LEFT)
|
||||
label_new_db.set_alignment(0, 1)
|
||||
label_new_db.set_padding( 9, 5)
|
||||
table_main.attach(label_new_db, 0, 3, 4, 5, xoptions=gtk.EXPAND \
|
||||
| gtk.FILL)
|
||||
|
||||
label_new_db_name = gtk.Label(_("Name:"))
|
||||
label_new_db_name.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
label_new_db_name.set_padding( 3, 3)
|
||||
label_new_db_name.set_alignment(1, 0.5)
|
||||
table_main.attach(label_new_db_name, 0, 1, 5, 6, \
|
||||
xoptions=gtk.FILL)
|
||||
|
||||
self.entry_new_db = gtk.Entry()
|
||||
self.entry_new_db.set_max_length(63)
|
||||
self.entry_new_db.set_width_chars(63)
|
||||
table_main.attach(self.entry_new_db, 1, 3, 5, 6, yoptions=False,
|
||||
xoptions=gtk.EXPAND | gtk.FILL)
|
||||
tooltips.set_tip(self.entry_new_db, _("Choose the name of the new database.\n" \
|
||||
"Allowed characters are alphanumerical or _ (underscore)\n" \
|
||||
"You need to avoid all accents, space or special characters! " \
|
||||
"Example: tryton"), None)
|
||||
handlerid = self.entry_new_db.connect("insert-text", entry_insert_text)
|
||||
self.entry_new_db.set_data('handlerid', handlerid)
|
||||
|
||||
label_default_lang = gtk.Label(_("Default Language:"))
|
||||
label_default_lang.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
label_default_lang.set_alignment(1, 0.5)
|
||||
label_default_lang.set_padding( 3, 3)
|
||||
table_main.attach(label_default_lang, 0, 1, 6, 7, xoptions=gtk.FILL)
|
||||
eventbox_default_lang = gtk.EventBox()
|
||||
|
||||
self.combo_default_lang = gtk.combo_box_new_text()
|
||||
eventbox_default_lang.add(self.combo_default_lang)
|
||||
table_main.attach(eventbox_default_lang, 1, 3, 6, 7, \
|
||||
xoptions=gtk.EXPAND | gtk.FILL)
|
||||
tooltips.set_tip(eventbox_default_lang, _("Choose the default language that " \
|
||||
"will be installed for this database. You will be able to " \
|
||||
"install new languages after installation through the " \
|
||||
"administration menu."), None)
|
||||
|
||||
label_admin_password = gtk.Label(_("Admin Password:"))
|
||||
label_admin_password.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
label_admin_password.set_padding( 3, 3)
|
||||
label_admin_password.set_alignment(1, 0.5)
|
||||
table_main.attach(label_admin_password, 0, 1, 7, 8, xoptions=gtk.FILL)
|
||||
|
||||
self.ent_password_admin = gtk.Entry()
|
||||
self.ent_password_admin.set_visibility(False)
|
||||
tooltips.set_tip(self.ent_password_admin, _("Choose a password for " \
|
||||
"the admin user of the new database. With these credentials you " \
|
||||
"are later able to login into the database:\n" \
|
||||
"login: admin\n" \
|
||||
"password: <The password you set here>"), None)
|
||||
table_main.attach(self.ent_password_admin, 1, 3, 7, 8, \
|
||||
xoptions=gtk.EXPAND | gtk.FILL)
|
||||
self.ent_password_admin.connect("key-press-event", self.event_passwd_clear)
|
||||
|
||||
label_admin_re_password = gtk.Label(_("Confirm Admin Password:"))
|
||||
label_admin_re_password.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
label_admin_re_password.set_padding( 3, 3)
|
||||
label_admin_re_password.set_alignment(1, 0.5)
|
||||
table_main.attach(label_admin_re_password, 0, 1, 8, 9, xoptions=gtk.FILL)
|
||||
|
||||
self.ent_re_password_admin = gtk.Entry()
|
||||
self.ent_re_password_admin.set_visibility(False)
|
||||
tooltips.set_tip(self.ent_re_password_admin, _("Type the Admin Password again"), None)
|
||||
table_main.attach(self.ent_re_password_admin, 1, 3, 8, 9, \
|
||||
xoptions=gtk.EXPAND | gtk.FILL)
|
||||
#self.ent_re_password_admin.connect("key-press-event", self.event_passwd_clear)
|
||||
|
||||
# self.label_connection_info = gtk.Label()
|
||||
# table_main.attach(self.label_connection_info, 1, 3, 9, 10)
|
||||
# self.label_connection_info.set_use_markup(True)
|
||||
# self.label_connection_info.set_alignment(0, 0.5)
|
||||
|
||||
self.dialog.add_button("gtk-cancel", \
|
||||
gtk.RESPONSE_CANCEL)
|
||||
|
||||
self.button_db_ok = gtk.Button(_('C_reate'))
|
||||
self.button_db_ok.set_sensitive(False)
|
||||
img_connect = gtk.Image()
|
||||
img_connect.set_from_stock('tryton-new', gtk.ICON_SIZE_BUTTON)
|
||||
self.button_db_ok.set_image(img_connect)
|
||||
self.button_db_ok.set_flags(gtk.CAN_DEFAULT)
|
||||
#self.button_db_ok.set_flags(gtk.HAS_DEFAULT)
|
||||
#self.button_db_ok.grab_default()
|
||||
tooltips.set_tip(self.button_db_ok, _('Create the new Tryton database.'))
|
||||
self.dialog.add_action_widget(self.button_db_ok, gtk.RESPONSE_OK)
|
||||
self.dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
|
||||
self.entry_password_new.grab_focus()
|
||||
self.dialog.vbox.pack_start(dialog_vbox)
|
||||
|
||||
self.sig_login = sig_login
|
||||
self.lang_widget = self.dialog.get_widget('db_create_combo')
|
||||
self.db_widget = self.dialog.get_widget('ent_db')
|
||||
self.server_widget = self.dialog.get_widget('ent_server_new')
|
||||
|
||||
def run(self, parent):
|
||||
win = self.dialog.get_widget('win_createdb')
|
||||
win.set_default_response(gtk.RESPONSE_OK)
|
||||
win.set_transient_for(parent)
|
||||
win.show_all()
|
||||
pass_widget = self.dialog.get_widget('ent_password_new')
|
||||
change_button = self.dialog.get_widget('but_server_new')
|
||||
admin_passwd = self.dialog.get_widget('ent_password_admin')
|
||||
admin_passwd2 = self.dialog.get_widget('ent_re_password_admin')
|
||||
self.dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
self.dialog.set_transient_for(parent)
|
||||
self.dialog.show_all()
|
||||
|
||||
pass_widget = self.entry_password_new
|
||||
change_button = self.but_server_new
|
||||
admin_passwd = self.ent_password_admin
|
||||
admin_passwd2 = self.ent_re_password_admin
|
||||
|
||||
change_button.connect_after('clicked', self.server_change, win)
|
||||
change_button.connect_after('clicked', self.server_change, self.dialog)
|
||||
host = CONFIG['login.server']
|
||||
port = int(CONFIG['login.port'])
|
||||
url = '%s:%d' % (host, port)
|
||||
self.entry_server.set_text(url)
|
||||
#print "URL: ",url
|
||||
|
||||
self.server_widget.set_text(url)
|
||||
liststore = gtk.ListStore(str, str)
|
||||
self.lang_widget.set_model(liststore)
|
||||
self.combo_default_lang.set_model(liststore)
|
||||
try:
|
||||
common.refresh_langlist(self.lang_widget, host, port)
|
||||
common.refresh_langlist(self.combo_default_lang, host, port)
|
||||
except:
|
||||
self.set_sensitive(False)
|
||||
self.button_db_ok.set_sensitive(False)
|
||||
|
||||
while True:
|
||||
res = win.run()
|
||||
dbname = self.db_widget.get_text()
|
||||
res = self.dialog.run()
|
||||
dbname = self.entry_new_db.get_text()
|
||||
url = self.entry_server.get_text()
|
||||
|
||||
url_m = re.match('^([\w.\-]+):(\d{1,5})$', \
|
||||
url or '')
|
||||
|
||||
langidx = self.combo_default_lang.get_active_iter()
|
||||
langreal = langidx \
|
||||
and self.combo_default_lang.get_model().get_value(langidx, 1)
|
||||
passwd = pass_widget.get_text()
|
||||
if res == gtk.RESPONSE_OK:
|
||||
if (not dbname) \
|
||||
or (not re.match('^[a-zA-Z][a-zA-Z0-9_]+$', dbname)):
|
||||
common.warning(_('The database name must contain ' \
|
||||
'only normal characters or "_".\n' \
|
||||
'You must avoid all accents, space ' \
|
||||
'or special characters.'), parent,
|
||||
_('Bad database name!'))
|
||||
common.warning(_('The database name is restricted to' \
|
||||
'alphanumerical characters and "_" (underscore).\n' \
|
||||
'Try to avoid all accents, space ' \
|
||||
'and any other special characters.'), parent, \
|
||||
_('Wrong characters in database name!'))
|
||||
continue
|
||||
elif admin_passwd.get_text() != admin_passwd2.get_text():
|
||||
common.warning(_('Admin password confirmation ' \
|
||||
'do not match password!'), parent,
|
||||
_('Wrong passwords!'))
|
||||
common.warning(_("The new admin password " \
|
||||
"doesn't match to the retyped password.\n" \
|
||||
"Try to type the same passwords in the " \
|
||||
"Admin Password and the Confirm Admin Password " \
|
||||
"fields again."), parent, \
|
||||
_("Passwords doesn't match!"))
|
||||
continue
|
||||
elif not admin_passwd.get_text():
|
||||
common.warning(_('Admin password is required!'),
|
||||
parent, _('Admin password!'))
|
||||
common.warning(_("Admin password and confirmation are " \
|
||||
"required to create a new Tryton database\n"), \
|
||||
parent, _('Missing admin password!'))
|
||||
continue
|
||||
|
||||
elif url_m.group(1) and int(url_m.group(2)) and dbname and langreal and passwd \
|
||||
and admin_passwd.get_text():
|
||||
try:
|
||||
if rpc.db_exec( url_m.group(1), int(url_m.group(2)), 'db_exist', dbname):
|
||||
common.warning(_('Try another database name.'), parent, \
|
||||
_('The Database already exists!'))
|
||||
self.entry_new_db.set_text("")
|
||||
self.entry_new_db.grab_focus()
|
||||
continue
|
||||
else: # Everything runs fine, break the block here
|
||||
if url_m:
|
||||
CONFIG['login.server'] = host = url_m.group(1)
|
||||
CONFIG['login.port'] = port = url_m.group(2)
|
||||
rpc.db_exec(host, int(port), 'create', passwd, dbname, \
|
||||
langreal, admin_passwd.get_text())
|
||||
from tryton.gui.main import Main
|
||||
Main.get_main().refresh_ssl()
|
||||
common.message(_('You can now connect to the new database\n' \
|
||||
'with the user: admin.'), parent)
|
||||
self.sig_login(dbname=dbname)
|
||||
return True
|
||||
break
|
||||
except Exception, exception:
|
||||
if str(exception[0]) == "AccessDenied":
|
||||
common.warning(_("The Tryton server password " \
|
||||
"is wrong. Please type again.") \
|
||||
, parent, _("Access denied!"))
|
||||
self.entry_password_new.set_text("")
|
||||
self.entry_password_new.grab_focus()
|
||||
continue
|
||||
else: # Unclassified error
|
||||
common.warning(_("Can't request if a database with " \
|
||||
"the given name already exists.\n" \
|
||||
"The connection to the PostgreSQL server seems " \
|
||||
"refused. \n" \
|
||||
"Error message:\n") + str(exception[0]), parent, \
|
||||
_("Error request database!"))
|
||||
parent.present()
|
||||
self.dialog.destroy()
|
||||
rpc.logout()
|
||||
from tryton.gui.main import Main
|
||||
Main.get_main().refresh_ssl()
|
||||
break
|
||||
break
|
||||
|
||||
langidx = self.lang_widget.get_active_iter()
|
||||
langreal = langidx \
|
||||
and self.lang_widget.get_model().get_value(langidx, 1)
|
||||
passwd = pass_widget.get_text()
|
||||
admin_passwd = admin_passwd.get_text()
|
||||
url = self.server_widget.get_text()
|
||||
url_m = re.match('^([\w.\-]+):(\d{1,5})$',
|
||||
url or '')
|
||||
if url_m:
|
||||
CONFIG['login.server'] = host = url_m.group(1)
|
||||
CONFIG['login.port'] = port = url_m.group(2)
|
||||
parent.present()
|
||||
win.destroy()
|
||||
self.dialog.destroy()
|
||||
|
||||
|
||||
|
||||
if res == gtk.RESPONSE_OK:
|
||||
try:
|
||||
if rpc.db_exec(host, int(port), 'db_exist', dbname):
|
||||
common.warning(_('Try with an other name.'), parent,
|
||||
_('The Database already exists!'))
|
||||
return False
|
||||
rpc.db_exec(host, int(port), 'create', passwd, dbname,
|
||||
langreal, admin_passwd)
|
||||
from tryton.gui.main import Main
|
||||
Main.get_main().refresh_ssl()
|
||||
except Exception, exception:
|
||||
common.warning(_('The database creation failed ' \
|
||||
'during installation.\n' \
|
||||
'We suggest you to drop this database.\n' \
|
||||
'Error message:\n') + str(exception[0]), parent,
|
||||
_("Error during database creation!"))
|
||||
return False
|
||||
common.message(_('You can now connect to the new database\n' \
|
||||
'with the user: admin.'), parent)
|
||||
self.sig_login(dbname=dbname)
|
||||
return True
|
||||
else:
|
||||
rpc.logout()
|
||||
from tryton.gui.main import Main
|
||||
Main.get_main().refresh_ssl()
|
||||
|
||||
Reference in new issue
Block a user