diff --git a/tryton/common/common.py b/tryton/common/common.py
index 76491ea9b7..a9bba0d58a 100644
--- a/tryton/common/common.py
+++ b/tryton/common/common.py
@@ -4,6 +4,7 @@ from gtk import glade
import gobject
import gettext
import os
+import re
import logging
from tryton.config import CONFIG
from tryton.config import GLADE, TRYTON_ICON, PIXMAPS_DIR, DATA_DIR
@@ -14,9 +15,113 @@ import md5
import webbrowser
import traceback
import tryton.rpc as rpc
+import locale
_ = gettext.gettext
+def refresh_dblist(db_widget, host, port, dbtoload=None):
+ if not dbtoload:
+ dbtoload = CONFIG['login.db']
+ index = 0
+ liststore = db_widget.get_model()
+ liststore.clear()
+ result = rpc.db_list(host, port)
+ from tryton.gui.main import Main
+ Main.get_main().refresh_ssl()
+ if result is None:
+ return None
+ for db_num, dbname in enumerate(result):
+ liststore.append([dbname])
+ if dbname == dbtoload:
+ index = db_num
+ db_widget.set_active(index)
+ return len(liststore)
+
+def refresh_langlist(lang_widget, host, port):
+ liststore = lang_widget.get_model()
+ liststore.clear()
+ lang_list = rpc.db_exec(host, port, 'list_lang')
+ from tryton.gui.main import Main
+ Main.get_main().refresh_ssl()
+ index = -1
+ i = 0
+ lang = locale.getdefaultlocale()[0]
+ for key, val in lang_list:
+ liststore.insert(i, (val, key))
+ if key == lang:
+ index = i
+ if key == 'en_US' and index < 0 :
+ index = i
+ i += 1
+ lang_widget.set_active(index)
+ return lang_list
+
+def request_server(server_widget, parent):
+ result = False
+ dialog = gtk.Dialog(
+ title = _('Server'),
+ parent = parent,
+ flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT |
+ gtk.WIN_POS_CENTER_ON_PARENT |
+ gtk.gdk.WINDOW_TYPE_HINT_DIALOG,)
+ vbox = gtk.VBox()
+ label_connect = gtk.Label(_("Connect to a Tryton server"))
+ label_connect.set_use_markup(True)
+ label_connect.set_alignment(0, 0.5)
+ vbox.pack_start(label_connect, False, False, 0)
+ hseparator = gtk.HSeparator()
+ vbox.pack_start(hseparator, False, True, 0)
+ table = gtk.Table(2, 2, False)
+ table.set_border_width(12)
+ table.set_row_spacings(6)
+ vbox.pack_start(table, False, True, 0)
+ label_server = gtk.Label(_("Server:"))
+ label_server.set_alignment(1, 0)
+ label_server.set_padding(3, 0)
+ table.attach(label_server, 0, 1, 0, 1, yoptions=False,
+ xoptions=gtk.FILL)
+ entry_port = gtk.Entry()
+ entry_port.set_max_length(5)
+ entry_port.set_text("8069")
+ entry_port.set_activates_default(True)
+ entry_port.set_width_chars(16)
+ table.attach(entry_port, 1, 2, 1, 2, yoptions=False,
+ xoptions=gtk.FILL)
+ entry_server = gtk.Entry()
+ entry_server.set_text("localhost")
+ entry_server.set_activates_default(True)
+ entry_server.set_width_chars(16)
+ table.attach(entry_server, 1, 2, 0, 1,yoptions=False,
+ xoptions=gtk.FILL | gtk.EXPAND)
+ label_port = gtk.Label(_("Port:"))
+ label_port.set_alignment(1, 0.5)
+ label_port.set_padding(3, 3)
+ table.attach(label_port, 0, 1, 1, 2, yoptions=False,
+ xoptions=False)
+ dialog.add_button("gtk-cancel", gtk.RESPONSE_CANCEL | gtk.CAN_DEFAULT)
+ dialog.add_button("gtk-ok", gtk.RESPONSE_OK)
+ dialog.vbox.pack_start(vbox)
+ dialog.set_icon(TRYTON_ICON)
+ dialog.show_all()
+ dialog.set_default_response(gtk.RESPONSE_OK)
+
+ url_m = re.match('^([\w.-]+):(\d{1,5})$',
+ server_widget.get_text())
+ if url_m:
+ entry_server.set_text(url_m.group(1))
+ entry_port.set_text(url_m.group(2))
+
+ res = dialog.run()
+ if res == gtk.RESPONSE_OK:
+ host = entry_server.get_text()
+ port = int(entry_port.get_text())
+ url = '%s:%d' % (host, port)
+ server_widget.set_text(url)
+ result = (host, port)
+ parent.present()
+ dialog.destroy()
+ return result
+
def selection(title, values, parent, alwaysask=False):
if not values or len(values)==0:
diff --git a/tryton/gui/main.py b/tryton/gui/main.py
index a8321d8e1d..32e3b95e7a 100644
--- a/tryton/gui/main.py
+++ b/tryton/gui/main.py
@@ -13,526 +13,17 @@ from tryton.action import Action
from tryton.gui.window import Window
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.tips import Tips
+from tryton.gui.window.credits import Credits
import re
import base64
import tryton.translate as translate
import tryton.plugin
-import locale
_ = gettext.gettext
-def _refresh_dblist(db_widget, host, port, dbtoload=None):
- if not dbtoload:
- dbtoload = CONFIG['login.db']
- index = 0
- liststore = db_widget.get_model()
- liststore.clear()
- result = rpc.db_list(host, port)
- Main.get_main().refresh_ssl()
- if result is None:
- return None
- for db_num, dbname in enumerate(result):
- liststore.append([dbname])
- if dbname == dbtoload:
- index = db_num
- db_widget.set_active(index)
- return len(liststore)
-
-def _refresh_langlist(lang_widget, host, port):
- liststore = lang_widget.get_model()
- liststore.clear()
- lang_list = rpc.db_exec(host, port, 'list_lang')
- Main.get_main().refresh_ssl()
- index = -1
- i = 0
- lang = locale.getdefaultlocale()[0]
- for key, val in lang_list:
- liststore.insert(i, (val, key))
- if key == lang:
- index = i
- if key == 'en_US' and index < 0 :
- index = i
- i += 1
- lang_widget.set_active(index)
- return lang_list
-
-def _request_server(server_widget, parent):
- result = False
- dialog = gtk.Dialog(
- title = _('Server'),
- parent = parent,
- flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT |
- gtk.WIN_POS_CENTER_ON_PARENT |
- gtk.gdk.WINDOW_TYPE_HINT_DIALOG,)
- vbox = gtk.VBox()
- label_connect = gtk.Label(_("Connect to a Tryton server"))
- label_connect.set_use_markup(True)
- label_connect.set_alignment(0, 0.5)
- vbox.pack_start(label_connect, False, False, 0)
- hseparator = gtk.HSeparator()
- vbox.pack_start(hseparator, False, True, 0)
- table = gtk.Table(2, 2, False)
- table.set_border_width(12)
- table.set_row_spacings(6)
- vbox.pack_start(table, False, True, 0)
- label_server = gtk.Label(_("Server:"))
- label_server.set_alignment(1, 0)
- label_server.set_padding(3, 0)
- table.attach(label_server, 0, 1, 0, 1, yoptions=False,
- xoptions=gtk.FILL)
- entry_port = gtk.Entry()
- entry_port.set_max_length(5)
- entry_port.set_text("8069")
- entry_port.set_activates_default(True)
- entry_port.set_width_chars(16)
- table.attach(entry_port, 1, 2, 1, 2, yoptions=False,
- xoptions=gtk.FILL)
- entry_server = gtk.Entry()
- entry_server.set_text("localhost")
- entry_server.set_activates_default(True)
- entry_server.set_width_chars(16)
- table.attach(entry_server, 1, 2, 0, 1,yoptions=False,
- xoptions=gtk.FILL | gtk.EXPAND)
- label_port = gtk.Label(_("Port:"))
- label_port.set_alignment(1, 0.5)
- label_port.set_padding(3, 3)
- table.attach(label_port, 0, 1, 1, 2, yoptions=False,
- xoptions=False)
- dialog.add_button("gtk-cancel", gtk.RESPONSE_CANCEL | gtk.CAN_DEFAULT)
- dialog.add_button("gtk-ok", gtk.RESPONSE_OK)
- dialog.vbox.pack_start(vbox)
- dialog.set_icon(TRYTON_ICON)
- dialog.show_all()
- dialog.set_default_response(gtk.RESPONSE_OK)
-
- url_m = re.match('^([\w.-]+):(\d{1,5})$',
- server_widget.get_text())
- if url_m:
- entry_server.set_text(url_m.group(1))
- entry_port.set_text(url_m.group(2))
-
- res = dialog.run()
- if res == gtk.RESPONSE_OK:
- host = entry_server.get_text()
- port = int(entry_port.get_text())
- url = '%s:%d' % (host, port)
- server_widget.set_text(url)
- result = (host, port)
- parent.present()
- dialog.destroy()
- return result
-
-
-class DBLogin(object):
- def __init__(self, parent):
- self.dialog = gtk.Dialog(title=_('Login'), parent=parent,
- flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
- self.dialog.set_size_request(500, 301)
- self.dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
- self.dialog.set_has_separator(False)
- self.dialog.set_icon(TRYTON_ICON)
- self.dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CANCEL)
- self.button_connect = gtk.Button(_('C_onnect'))
- img_connect = gtk.Image()
- img_connect.set_from_stock('tryton-connect', gtk.ICON_SIZE_BUTTON)
- self.button_connect.set_image(img_connect)
- self.button_connect.set_flags(gtk.CAN_DEFAULT)
- self.dialog.add_action_widget(self.button_connect, gtk.RESPONSE_OK)
- self.dialog.set_default_response(gtk.RESPONSE_OK)
- dialog_vbox = gtk.VBox()
- vbox_image = gtk.VBox()
- image = gtk.Image()
- image.set_from_file(os.path.join(PIXMAPS_DIR, 'tryton.png'))
- image.set_size_request(500, 129)
- vbox_image.pack_start(image)
- dialog_vbox.pack_start(vbox_image)
- table_main = gtk.Table(4, 3, False)
- table_main.set_border_width(10)
- table_main.set_row_spacings(3)
- table_main.set_col_spacings(3)
- vbox_image.pack_start(table_main, True, True, 0)
- vbox_combo = gtk.VBox()
- self.combo_database = gtk.ComboBox()
- self.combo_label = gtk.Label()
- self.combo_label.set_use_markup(True)
- self.combo_label.set_alignment(0, 1)
- vbox_combo.pack_start(self.combo_database, True, True, 0)
- vbox_combo.pack_start(self.combo_label, False, False, 0)
- table_main.attach(vbox_combo, 1, 3, 1, 2)
- self.entry_password = gtk.Entry()
- self.entry_password.set_visibility(False)
- self.entry_password.set_activates_default(True)
- table_main.attach(self.entry_password, 1, 3, 3, 4)
- self.entry_login = gtk.Entry()
- self.entry_login.set_text("admin")
- self.entry_login.set_activates_default(True)
- table_main.attach(self.entry_login, 1, 3, 2, 3)
- label_server = gtk.Label()
- label_server.set_text(_("Server:"))
- label_server.set_alignment(1, 0.5)
- label_server.set_padding(3, 3)
- table_main.attach(label_server, 0, 1, 0, 1, xoptions=gtk.FILL)
- label_database = gtk.Label()
- label_database.set_text(_("Database:"))
- label_database.set_alignment(1, 0.5)
- label_database.set_padding(3, 3)
- table_main.attach(label_database, 0, 1, 1, 2, xoptions=gtk.FILL)
- self.entry_server = gtk.Entry()
- table_main.attach(self.entry_server, 1, 2, 0, 1)
- 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("localhost")
- self.entry_server.set_activates_default(True)
- self.entry_server.set_width_chars(16)
- self.button_server = gtk.Button(label=_("C_hange"), stock=None,
- use_underline=True)
- table_main.attach(self.button_server, 2, 3, 0, 1, xoptions=gtk.FILL)
- label_password = gtk.Label(str = _("Password:"))
- label_password.set_justify(gtk.JUSTIFY_RIGHT)
- label_password.set_alignment(1, 0.5)
- label_password.set_padding(3, 3)
- table_main.attach(label_password, 0, 1, 3, 4, xoptions=gtk.FILL)
- label_username = gtk.Label(str = _("User name:"))
- label_username.set_alignment(1, 0.5)
- label_username.set_padding(3, 3)
- table_main.attach(label_username, 0, 1, 2, 3, xoptions=gtk.FILL)
- self.entry_password.grab_focus()
- self.dialog.vbox.pack_start(dialog_vbox)
-
- @staticmethod
- def refreshlist(widget, db_widget, label, host, port, butconnect=None):
- res = _refresh_dblist(db_widget, host, port)
- if res is None:
- label.set_label(''+_('Could not connect to server!')+'')
- db_widget.hide()
- label.show()
- if butconnect:
- butconnect.set_sensitive(False)
- elif res==0:
- label.set_label('' + \
- _('No database found, you must create one!') + '')
- db_widget.hide()
- label.show()
- if butconnect:
- butconnect.set_sensitive(False)
- else:
- label.hide()
- db_widget.show()
- if butconnect:
- butconnect.set_sensitive(True)
- return res
-
- @staticmethod
- def refreshlist_ask(widget, server_widget, db_widget, label,
- butconnect=False, host=False, port=0, parent=None):
- host, port = _request_server(server_widget, parent) or (host, port)
- return DBLogin.refreshlist(widget, db_widget, label, host, port,
- butconnect)
-
- def run(self, dbname, parent):
- self.dialog.show_all()
- self.combo_label.hide()
-
- host = CONFIG['login.server']
- port = int(CONFIG['login.port'])
-
- url = '%s:%d' % (host, port)
- self.entry_server.set_text(url)
- self.entry_login.set_text(CONFIG['login.login'])
-
- # construct the list of available db and select the last one used
- liststore = gtk.ListStore(str)
- self.combo_database.set_model(liststore)
- cell = gtk.CellRendererText()
- self.combo_database.pack_start(cell, True)
- self.combo_database.add_attribute(cell, 'text', 0)
-
- res = self.refreshlist(None, self.combo_database, self.combo_label,
- host, port, self.button_connect)
-
- self.button_server.connect_after('clicked', DBLogin.refreshlist_ask,
- self.entry_server, self.combo_database, self.combo_label,
- self.button_connect, host, port, self.dialog)
- if dbname:
- i = liststore.get_iter_root()
- while i:
- if liststore.get_value(i, 0)==dbname:
- self.combo_database.set_active_iter(i)
- break
- i = liststore.iter_next(i)
-
- res = self.dialog.run()
- url_m = re.match('^([\w.:\-\d]+):(\d{1,5})$',
- self.entry_server.get_text() or '')
- if url_m:
- CONFIG['login.server'] = url_m.group(1)
- CONFIG['login.login'] = self.entry_login.get_text()
- CONFIG['login.port'] = url_m.group(2)
- CONFIG['login.db'] = self.combo_database.get_active_text()
- result = (self.entry_login.get_text(),
- self.entry_password.get_text(), url_m.group(1),
- int(url_m.group(2)), self.combo_database.get_active_text())
- else:
- parent.present()
- self.dialog.destroy()
- raise Exception('QueryCanceled')
- if res != gtk.RESPONSE_OK:
- parent.present()
- self.dialog.destroy()
- rpc.logout()
- Main.get_main().refresh_ssl()
- raise Exception('QueryCanceled')
- parent.present()
- self.dialog.destroy()
- return result
-
-class DBCreate(object):
- def set_sensitive(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)
- else:
- label = self.dialog.get_widget('db_label_info')
- label.set_markup('' + \
- _('Can not connect to server!') + '')
- self.dialog.get_widget('button_db_ok').set_sensitive(False)
- return sensitive
-
- def server_change(self, widget, parent):
- host, port = _request_server(self.server_widget, parent)
- try:
- if self.lang_widget and host and port:
- _refresh_langlist(self.lang_widget, host, port)
- self.set_sensitive(True)
- except:
- self.set_sensitive(False)
- return False
- return url
-
- def __init__(self, sig_login):
- self.dialog = glade.XML(GLADE, "win_createdb", gettext.textdomain())
- 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')
-
- change_button.connect_after('clicked', self.server_change, win)
- host = CONFIG['login.server']
- port = int(CONFIG['login.port'])
- url = '%s:%d' % (host, port)
-
- self.server_widget.set_text(url)
- liststore = gtk.ListStore(str, str)
- self.lang_widget.set_model(liststore)
- try:
- _refresh_langlist(self.lang_widget, host, port)
- except:
- self.set_sensitive(False)
-
- while True:
- res = win.run()
- dbname = self.db_widget.get_text()
- if (res==gtk.RESPONSE_OK) \
- and ((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!'))
-
- else:
- 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()
- 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()
-
- 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
- users = rpc.db_exec(host, int(port), 'create', passwd, dbname,
- langreal)
- Main.get_main().refresh_ssl()
- except Exception, exception:
- common.warning(_('The server crashed during installation.\n' \
- 'We suggest you to drop this database.\n' \
- 'Error message:\n') + str(exception[0]), parent,
- _("Error during database creation!"))
- return False
- dialog = glade.XML(GLADE, "dia_dbcreate_ok", gettext.textdomain())
- win = dialog.get_widget('dia_dbcreate_ok')
- win.set_transient_for(parent)
- win.show_all()
- buf = dialog.get_widget('dia_tv').get_buffer()
-
- buf.delete(buf.get_start_iter(), buf.get_end_iter())
- iter_start = buf.get_start_iter()
-
- pwdlst = '\n'.join([' - %s: %s / %s' % \
- (x['name'], x['login'], x['password']) for x in users])
-
- buf.insert(iter_start, _('The following users have been ' \
- 'installed on your database:') + '\n\n' + pwdlst + \
- '\n\n' + _('You can now connect to the database ' \
- 'as an administrator.'))
- res = win.run()
- parent.present()
- win.destroy()
-
- if res == gtk.RESPONSE_OK:
- url_m = re.match('^(http[s]?://|socket://)([\w.]+):(\d{1,5})$',
- url)
- res = ['admin', 'admin']
- if url_m:
- res.append(url_m.group(2))
- res.append(url_m.group(3))
- res.append(url_m.group(1))
- res.append(dbname)
-
- self.sig_login(dbname=dbname)
- return True
- else:
- rpc.logout()
- Main.get_main().refresh_ssl()
-
-
-class Tips(object):
-
- def __init__(self, parent):
- self.win = gtk.Dialog(_('Tips'), parent,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
- self.win.set_icon(TRYTON_ICON)
-
- self.win.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
-
- vbox = gtk.VBox()
- img = gtk.Image()
- img.set_from_file(os.path.join(PIXMAPS_DIR, 'tryton.png'))
- vbox.pack_start(img, False, False)
- self.label = gtk.Label()
- self.label.set_alignment(0, 0)
- vbox.pack_start(self.label, True, True)
- separator = gtk.HSeparator()
- vbox.pack_start(separator, False, False)
-
- hbox = gtk.HBox()
- self.check = gtk.CheckButton(_('_Display a new tip next time'), True)
- self.check.set_active(True)
- hbox.pack_start(self.check)
- but_previous = gtk.Button()
- hbox_previous = gtk.HBox()
- img_previous = gtk.Image()
- img_previous.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_BUTTON)
- hbox_previous.pack_start(img_previous)
- label_previous = gtk.Label(_('Previous'))
- hbox_previous.pack_start(label_previous)
- but_previous.add(hbox_previous)
- but_previous.set_relief(gtk.RELIEF_NONE)
- but_previous.connect('clicked', self.tip_previous)
- hbox.pack_start(but_previous)
- hbox_next = gtk.HBox()
- label_next = gtk.Label(_('Next'))
- hbox_next.pack_start(label_next)
- but_next = gtk.Button()
- img_next = gtk.Image()
- img_next.set_from_stock('tryton-go-next', gtk.ICON_SIZE_BUTTON)
- hbox_next.pack_start(img_next)
- but_next.add(hbox_next)
- but_next.set_relief(gtk.RELIEF_NONE)
- but_next.connect('clicked', self.tip_next)
- hbox.pack_start(but_next)
- vbox.pack_start(hbox, False, False)
- self.win.vbox.pack_start(vbox)
- self.win.show_all()
-
- try:
- self.number = int(CONFIG['tip.position'])
- except:
- self.number = 0
-
- self.tip_set()
-
- self.win.run()
- CONFIG['tip.autostart'] = self.check.get_active()
- CONFIG['tip.position'] = self.number + 1
- CONFIG.save()
- parent.present()
- self.win.destroy()
-
- def tip_set(self):
- lang = CONFIG['client.lang']
- tip_file = False
- if lang:
- tip_file = os.path.join(DATA_DIR, 'tipoftheday.'+lang+'.txt')
- if not os.path.isfile(tip_file):
- tip_file = os.path.join(DATA_DIR, 'tipoftheday.txt')
- if not os.path.isfile(tip_file):
- return
- tips = file(tip_file).read().split('---')
- tip = tips[self.number % len(tips)].lstrip()
- del tips
- self.label.set_text(tip)
- self.label.set_use_markup(True)
-
- def tip_next(self, widget):
- self.number += 1
- self.tip_set()
-
- def tip_previous(self, widget):
- self.number -= 1
- self.tip_set()
-
-
-class Credits(object):
-
- def __init__(self, parent):
- self.win = gtk.Dialog(_('Credits'), parent,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
- self.win.set_icon(TRYTON_ICON)
-
- self.win.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
-
- vbox = gtk.VBox()
- img = gtk.Image()
- img.set_from_file(os.path.join(PIXMAPS_DIR, 'tryton.png'))
- vbox.pack_start(img, False, False)
- self.label = gtk.Label()
- self.label.set_alignment(0.5, 0)
- contributors_file = os.path.join(DATA_DIR, 'contributors.txt')
- contributors = '\n' + _('Contributors:') + '\n\n'
- contributors += file(contributors_file).read()
- self.label.set_text(contributors)
- self.label.set_use_markup(True)
- vbox.pack_start(self.label, True, True)
- self.win.vbox.pack_start(vbox)
- self.win.show_all()
-
- self.win.run()
- parent.present()
- self.win.destroy()
_MAIN = []
@@ -1204,7 +695,7 @@ class Main(object):
new_pass2_widget = dialog.get_widget('new_passwd2')
change_button = dialog.get_widget('but_server_change')
change_button.connect_after('clicked', \
- lambda a,b: _request_server(b, win), server_widget)
+ lambda a,b: common.request_server(b, win), server_widget)
host = CONFIG['login.server']
port = int(CONFIG['login.port'])
@@ -1272,7 +763,7 @@ class Main(object):
def _choose_db_select(self, title=_("Backup a database")):
def refreshlist(widget, db_widget, label, host, port):
- res = _refresh_dblist(db_widget, host, port)
+ res = common.refresh_dblist(db_widget, host, port)
if res == -1:
label.set_label('' + \
_('Could not connect to server !') + '')
@@ -1290,7 +781,7 @@ class Main(object):
def refreshlist_ask(widget, server_widget, db_widget, label,
parent=None):
- host, port = _request_server(server_widget, parent)
+ host, port = common.request_server(server_widget, parent)
if not url:
return None
refreshlist(widget, db_widget, label, host, port)
@@ -1358,8 +849,8 @@ class Main(object):
widget_url.set_text(url)
change_button = dialog.get_widget('but_server_change')
- change_button.connect_after('clicked', lambda a, b: _request_server(b, win),
- widget_url)
+ change_button.connect_after('clicked',
+ lambda a, b: common.request_server(b, win), widget_url)
res = win.run()
diff --git a/tryton/gui/window/credits.py b/tryton/gui/window/credits.py
new file mode 100644
index 0000000000..0f11470693
--- /dev/null
+++ b/tryton/gui/window/credits.py
@@ -0,0 +1,36 @@
+#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 os
+from tryton.config import TRYTON_ICON, PIXMAPS_DIR, DATA_DIR
+
+_ = gettext.gettext
+
+
+class Credits(object):
+
+ def __init__(self, parent):
+ self.win = gtk.Dialog(_('Credits'), parent,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
+ self.win.set_icon(TRYTON_ICON)
+
+ self.win.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
+
+ vbox = gtk.VBox()
+ img = gtk.Image()
+ img.set_from_file(os.path.join(PIXMAPS_DIR, 'tryton.png'))
+ vbox.pack_start(img, False, False)
+ self.label = gtk.Label()
+ self.label.set_alignment(0.5, 0)
+ contributors_file = os.path.join(DATA_DIR, 'contributors.txt')
+ contributors = '\n' + _('Contributors:') + '\n\n'
+ contributors += file(contributors_file).read()
+ self.label.set_text(contributors)
+ self.label.set_use_markup(True)
+ vbox.pack_start(self.label, True, True)
+ self.win.vbox.pack_start(vbox)
+ self.win.show_all()
+
+ self.win.run()
+ parent.present()
+ self.win.destroy()
diff --git a/tryton/gui/window/dbcreate.py b/tryton/gui/window/dbcreate.py
new file mode 100644
index 0000000000..acf06ae5f2
--- /dev/null
+++ b/tryton/gui/window/dbcreate.py
@@ -0,0 +1,145 @@
+#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
+import gettext
+import re
+import tryton.common as common
+from tryton.config import CONFIG, GLADE, TRYTON_ICON, PIXMAPS_DIR
+import tryton.rpc as rpc
+
+_ = gettext.gettext
+
+
+class DBCreate(object):
+ def set_sensitive(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)
+ else:
+ label = self.dialog.get_widget('db_label_info')
+ label.set_markup('' + \
+ _('Can not connect to server!') + '')
+ self.dialog.get_widget('button_db_ok').set_sensitive(False)
+ return sensitive
+
+ def server_change(self, widget, parent):
+ host, port = common.request_server(self.server_widget, parent)
+ try:
+ if self.lang_widget and host and port:
+ common.refresh_langlist(self.lang_widget, host, port)
+ self.set_sensitive(True)
+ except:
+ self.set_sensitive(False)
+ return False
+ return url
+
+ def __init__(self, sig_login):
+ self.dialog = glade.XML(GLADE, "win_createdb", gettext.textdomain())
+ 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')
+
+ change_button.connect_after('clicked', self.server_change, win)
+ host = CONFIG['login.server']
+ port = int(CONFIG['login.port'])
+ url = '%s:%d' % (host, port)
+
+ self.server_widget.set_text(url)
+ liststore = gtk.ListStore(str, str)
+ self.lang_widget.set_model(liststore)
+ try:
+ common.refresh_langlist(self.lang_widget, host, port)
+ except:
+ self.set_sensitive(False)
+
+ while True:
+ res = win.run()
+ dbname = self.db_widget.get_text()
+ if (res==gtk.RESPONSE_OK) \
+ and ((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!'))
+
+ else:
+ 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()
+ 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()
+
+ 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
+ users = rpc.db_exec(host, int(port), 'create', passwd, dbname,
+ langreal)
+ from tryton.gui.main import Main
+ Main.get_main().refresh_ssl()
+ except Exception, exception:
+ common.warning(_('The server crashed during installation.\n' \
+ 'We suggest you to drop this database.\n' \
+ 'Error message:\n') + str(exception[0]), parent,
+ _("Error during database creation!"))
+ return False
+ dialog = glade.XML(GLADE, "dia_dbcreate_ok", gettext.textdomain())
+ win = dialog.get_widget('dia_dbcreate_ok')
+ win.set_transient_for(parent)
+ win.show_all()
+ buf = dialog.get_widget('dia_tv').get_buffer()
+
+ buf.delete(buf.get_start_iter(), buf.get_end_iter())
+ iter_start = buf.get_start_iter()
+
+ pwdlst = '\n'.join([' - %s: %s / %s' % \
+ (x['name'], x['login'], x['password']) for x in users])
+
+ buf.insert(iter_start, _('The following users have been ' \
+ 'installed on your database:') + '\n\n' + pwdlst + \
+ '\n\n' + _('You can now connect to the database ' \
+ 'as an administrator.'))
+ res = win.run()
+ parent.present()
+ win.destroy()
+
+ if res == gtk.RESPONSE_OK:
+ url_m = re.match('^(http[s]?://|socket://)([\w.]+):(\d{1,5})$',
+ url)
+ res = ['admin', 'admin']
+ if url_m:
+ res.append(url_m.group(2))
+ res.append(url_m.group(3))
+ res.append(url_m.group(1))
+ res.append(dbname)
+
+ self.sig_login(dbname=dbname)
+ return True
+ else:
+ rpc.logout()
+ from tryton.gui.main import Main
+ Main.get_main().refresh_ssl()
+
diff --git a/tryton/gui/window/dblogin.py b/tryton/gui/window/dblogin.py
new file mode 100644
index 0000000000..e541fa9685
--- /dev/null
+++ b/tryton/gui/window/dblogin.py
@@ -0,0 +1,177 @@
+#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 os
+import re
+import gettext
+import tryton.common as common
+from tryton.config import CONFIG, TRYTON_ICON, PIXMAPS_DIR
+import tryton.rpc as rpc
+
+_ = gettext.gettext
+
+
+class DBLogin(object):
+ def __init__(self, parent):
+ self.dialog = gtk.Dialog(title=_('Login'), parent=parent,
+ flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
+ self.dialog.set_size_request(500, 301)
+ self.dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
+ self.dialog.set_has_separator(False)
+ self.dialog.set_icon(TRYTON_ICON)
+ self.dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CANCEL)
+ self.button_connect = gtk.Button(_('C_onnect'))
+ img_connect = gtk.Image()
+ img_connect.set_from_stock('tryton-connect', gtk.ICON_SIZE_BUTTON)
+ self.button_connect.set_image(img_connect)
+ self.button_connect.set_flags(gtk.CAN_DEFAULT)
+ self.dialog.add_action_widget(self.button_connect, gtk.RESPONSE_OK)
+ self.dialog.set_default_response(gtk.RESPONSE_OK)
+ dialog_vbox = gtk.VBox()
+ vbox_image = gtk.VBox()
+ image = gtk.Image()
+ image.set_from_file(os.path.join(PIXMAPS_DIR, 'tryton.png'))
+ image.set_size_request(500, 129)
+ vbox_image.pack_start(image)
+ dialog_vbox.pack_start(vbox_image)
+ table_main = gtk.Table(4, 3, False)
+ table_main.set_border_width(10)
+ table_main.set_row_spacings(3)
+ table_main.set_col_spacings(3)
+ vbox_image.pack_start(table_main, True, True, 0)
+ vbox_combo = gtk.VBox()
+ self.combo_database = gtk.ComboBox()
+ self.combo_label = gtk.Label()
+ self.combo_label.set_use_markup(True)
+ self.combo_label.set_alignment(0, 1)
+ vbox_combo.pack_start(self.combo_database, True, True, 0)
+ vbox_combo.pack_start(self.combo_label, False, False, 0)
+ table_main.attach(vbox_combo, 1, 3, 1, 2)
+ self.entry_password = gtk.Entry()
+ self.entry_password.set_visibility(False)
+ self.entry_password.set_activates_default(True)
+ table_main.attach(self.entry_password, 1, 3, 3, 4)
+ self.entry_login = gtk.Entry()
+ self.entry_login.set_text("admin")
+ self.entry_login.set_activates_default(True)
+ table_main.attach(self.entry_login, 1, 3, 2, 3)
+ label_server = gtk.Label()
+ label_server.set_text(_("Server:"))
+ label_server.set_alignment(1, 0.5)
+ label_server.set_padding(3, 3)
+ table_main.attach(label_server, 0, 1, 0, 1, xoptions=gtk.FILL)
+ label_database = gtk.Label()
+ label_database.set_text(_("Database:"))
+ label_database.set_alignment(1, 0.5)
+ label_database.set_padding(3, 3)
+ table_main.attach(label_database, 0, 1, 1, 2, xoptions=gtk.FILL)
+ self.entry_server = gtk.Entry()
+ table_main.attach(self.entry_server, 1, 2, 0, 1)
+ 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("localhost")
+ self.entry_server.set_activates_default(True)
+ self.entry_server.set_width_chars(16)
+ self.button_server = gtk.Button(label=_("C_hange"), stock=None,
+ use_underline=True)
+ table_main.attach(self.button_server, 2, 3, 0, 1, xoptions=gtk.FILL)
+ label_password = gtk.Label(str = _("Password:"))
+ label_password.set_justify(gtk.JUSTIFY_RIGHT)
+ label_password.set_alignment(1, 0.5)
+ label_password.set_padding(3, 3)
+ table_main.attach(label_password, 0, 1, 3, 4, xoptions=gtk.FILL)
+ label_username = gtk.Label(str = _("User name:"))
+ label_username.set_alignment(1, 0.5)
+ label_username.set_padding(3, 3)
+ table_main.attach(label_username, 0, 1, 2, 3, xoptions=gtk.FILL)
+ self.entry_password.grab_focus()
+ self.dialog.vbox.pack_start(dialog_vbox)
+
+ @staticmethod
+ def refreshlist(widget, db_widget, label, host, port, butconnect=None):
+ res = common.refresh_dblist(db_widget, host, port)
+ if res is None:
+ label.set_label(''+_('Could not connect to server!')+'')
+ db_widget.hide()
+ label.show()
+ if butconnect:
+ butconnect.set_sensitive(False)
+ elif res==0:
+ label.set_label('' + \
+ _('No database found, you must create one!') + '')
+ db_widget.hide()
+ label.show()
+ if butconnect:
+ butconnect.set_sensitive(False)
+ else:
+ label.hide()
+ db_widget.show()
+ if butconnect:
+ butconnect.set_sensitive(True)
+ return res
+
+ @staticmethod
+ def refreshlist_ask(widget, server_widget, db_widget, label,
+ butconnect=False, host=False, port=0, parent=None):
+ host, port = common.request_server(server_widget, parent) or (host, port)
+ return DBLogin.refreshlist(widget, db_widget, label, host, port,
+ butconnect)
+
+ def run(self, dbname, parent):
+ self.dialog.show_all()
+ self.combo_label.hide()
+
+ host = CONFIG['login.server']
+ port = int(CONFIG['login.port'])
+
+ url = '%s:%d' % (host, port)
+ self.entry_server.set_text(url)
+ self.entry_login.set_text(CONFIG['login.login'])
+
+ # construct the list of available db and select the last one used
+ liststore = gtk.ListStore(str)
+ self.combo_database.set_model(liststore)
+ cell = gtk.CellRendererText()
+ self.combo_database.pack_start(cell, True)
+ self.combo_database.add_attribute(cell, 'text', 0)
+
+ res = self.refreshlist(None, self.combo_database, self.combo_label,
+ host, port, self.button_connect)
+
+ self.button_server.connect_after('clicked', DBLogin.refreshlist_ask,
+ self.entry_server, self.combo_database, self.combo_label,
+ self.button_connect, host, port, self.dialog)
+ if dbname:
+ i = liststore.get_iter_root()
+ while i:
+ if liststore.get_value(i, 0)==dbname:
+ self.combo_database.set_active_iter(i)
+ break
+ i = liststore.iter_next(i)
+
+ res = self.dialog.run()
+ url_m = re.match('^([\w.:\-\d]+):(\d{1,5})$',
+ self.entry_server.get_text() or '')
+ if url_m:
+ CONFIG['login.server'] = url_m.group(1)
+ CONFIG['login.login'] = self.entry_login.get_text()
+ CONFIG['login.port'] = url_m.group(2)
+ CONFIG['login.db'] = self.combo_database.get_active_text()
+ result = (self.entry_login.get_text(),
+ self.entry_password.get_text(), url_m.group(1),
+ int(url_m.group(2)), self.combo_database.get_active_text())
+ else:
+ parent.present()
+ self.dialog.destroy()
+ raise Exception('QueryCanceled')
+ if res != gtk.RESPONSE_OK:
+ parent.present()
+ self.dialog.destroy()
+ rpc.logout()
+ from tryton.gui.main import Main
+ Main.get_main().refresh_ssl()
+ raise Exception('QueryCanceled')
+ parent.present()
+ self.dialog.destroy()
+ return result
+
diff --git a/tryton/gui/window/tips.py b/tryton/gui/window/tips.py
new file mode 100644
index 0000000000..4a73601cf1
--- /dev/null
+++ b/tryton/gui/window/tips.py
@@ -0,0 +1,96 @@
+#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 os
+from tryton.config import CONFIG, TRYTON_ICON, PIXMAPS_DIR, DATA_DIR
+
+_ = gettext.gettext
+
+
+class Tips(object):
+
+ def __init__(self, parent):
+ self.win = gtk.Dialog(_('Tips'), parent,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
+ self.win.set_icon(TRYTON_ICON)
+
+ self.win.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
+
+ vbox = gtk.VBox()
+ img = gtk.Image()
+ img.set_from_file(os.path.join(PIXMAPS_DIR, 'tryton.png'))
+ vbox.pack_start(img, False, False)
+ self.label = gtk.Label()
+ self.label.set_alignment(0, 0)
+ vbox.pack_start(self.label, True, True)
+ separator = gtk.HSeparator()
+ vbox.pack_start(separator, False, False)
+
+ hbox = gtk.HBox()
+ self.check = gtk.CheckButton(_('_Display a new tip next time'), True)
+ self.check.set_active(True)
+ hbox.pack_start(self.check)
+ but_previous = gtk.Button()
+ hbox_previous = gtk.HBox()
+ img_previous = gtk.Image()
+ img_previous.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_BUTTON)
+ hbox_previous.pack_start(img_previous)
+ label_previous = gtk.Label(_('Previous'))
+ hbox_previous.pack_start(label_previous)
+ but_previous.add(hbox_previous)
+ but_previous.set_relief(gtk.RELIEF_NONE)
+ but_previous.connect('clicked', self.tip_previous)
+ hbox.pack_start(but_previous)
+ hbox_next = gtk.HBox()
+ label_next = gtk.Label(_('Next'))
+ hbox_next.pack_start(label_next)
+ but_next = gtk.Button()
+ img_next = gtk.Image()
+ img_next.set_from_stock('tryton-go-next', gtk.ICON_SIZE_BUTTON)
+ hbox_next.pack_start(img_next)
+ but_next.add(hbox_next)
+ but_next.set_relief(gtk.RELIEF_NONE)
+ but_next.connect('clicked', self.tip_next)
+ hbox.pack_start(but_next)
+ vbox.pack_start(hbox, False, False)
+ self.win.vbox.pack_start(vbox)
+ self.win.show_all()
+
+ try:
+ self.number = int(CONFIG['tip.position'])
+ except:
+ self.number = 0
+
+ self.tip_set()
+
+ self.win.run()
+ CONFIG['tip.autostart'] = self.check.get_active()
+ CONFIG['tip.position'] = self.number + 1
+ CONFIG.save()
+ parent.present()
+ self.win.destroy()
+
+ def tip_set(self):
+ lang = CONFIG['client.lang']
+ tip_file = False
+ if lang:
+ tip_file = os.path.join(DATA_DIR, 'tipoftheday.'+lang+'.txt')
+ if not os.path.isfile(tip_file):
+ tip_file = os.path.join(DATA_DIR, 'tipoftheday.txt')
+ if not os.path.isfile(tip_file):
+ return
+ tips = file(tip_file).read().split('---')
+ tip = tips[self.number % len(tips)].lstrip()
+ del tips
+ self.label.set_text(tip)
+ self.label.set_use_markup(True)
+
+ def tip_next(self, widget):
+ self.number += 1
+ self.tip_set()
+
+ def tip_previous(self, widget):
+ self.number -= 1
+ self.tip_set()
+
+