Remove database management
issue5384 review30261003
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Remove database management
|
||||
* Limit readonly state for xxx2Many
|
||||
* Show records names in relate window title
|
||||
* Add support for count on Action Window Domains
|
||||
|
||||
+11
-130
@@ -22,7 +22,7 @@ Synopsis
|
||||
After startup, there raises the `login dialog`__ and optionally a
|
||||
`tips dialog`__.
|
||||
|
||||
__ Menu-File-Connect_
|
||||
__ Menu-Connection_
|
||||
__ Menu-Help-Tips_
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ Figure: Tryton client application::
|
||||
Client Window ________________________________________________________________
|
||||
| Tryton _ o x|
|
||||
|----------------------------------------------------------------|
|
||||
Menu bar | File User Options Favorites Help |
|
||||
Menu bar | Connection User Options Favorites Help |
|
||||
|________________________________________________________________|
|
||||
| | ______ |
|
||||
Tabs | Menu | [Tab1] |[Tab2]| [Tab3]... |
|
||||
@@ -202,12 +202,12 @@ menu action. Most dialogs provide a *Cancel* button, used to stop the
|
||||
complete dialog process.
|
||||
|
||||
|
||||
File
|
||||
^^^^
|
||||
The file menu level provides functions about Tryton server login,
|
||||
Database maintenance and closing the client application.
|
||||
Connection
|
||||
^^^^^^^^^^
|
||||
The connection menu level provides functions about Tryton server login,
|
||||
logout and closing the client application.
|
||||
|
||||
.. _Menu-File-Connect:
|
||||
.. _Menu-Connection:
|
||||
|
||||
Connect...
|
||||
By choosing this menu entry the client will be connected to an available
|
||||
@@ -226,138 +226,19 @@ Connect...
|
||||
user may be logged out of the current session, and need to login again.
|
||||
Default timeout for inactivity logout is six minutes.
|
||||
|
||||
__ File-Server-Connection_
|
||||
__ Connection-Server-Connection_
|
||||
|
||||
|
||||
.. _Menu-File-Disconnect:
|
||||
.. _Menu-Connection-Disconnect:
|
||||
|
||||
Disconnect...
|
||||
Disconnects the client from an active server connection. In case of unsaved
|
||||
changes in an open tab, the Tryton client will request for saving the
|
||||
changes.
|
||||
|
||||
Database
|
||||
++++++++
|
||||
This menu level provides tools to maintain Tryton databases.
|
||||
For all database operations the user needs to know the Tryton server password.
|
||||
__ Connection-Server-Connection_
|
||||
|
||||
.. warning:: Consider not to use this server-site maintaining functions,
|
||||
if there are security concerns. Since there are always security
|
||||
concerns in a multiuser environment, better disclaim to provide
|
||||
these functions on database level.
|
||||
|
||||
.. note:: Database names are restricted by some rules:
|
||||
|
||||
* Allowed characters are alpha-nummeric [A-Za-z0-9] and
|
||||
underscore (_).
|
||||
* First character must be an alphabetic letter.
|
||||
* The maximum length of a database name is 64 characters.
|
||||
|
||||
Tryton automatically checks if the given database name follows
|
||||
the rules.
|
||||
|
||||
.. _Menu-File-New_Database:
|
||||
|
||||
New Database
|
||||
Opens a :term:`dialog` for creating a new Tryton database with an initial
|
||||
user called *admin*.
|
||||
|
||||
* Server Setup:
|
||||
|
||||
- `Server Connection`__
|
||||
- Tryton Server Password: The password given in the Tryton server
|
||||
configuration.
|
||||
|
||||
* New Database Setup:
|
||||
|
||||
- Database Name: The name of the new database.
|
||||
- Default Language: The default language of the new database.
|
||||
- Admin Password: The *admin*-user password of the new database.
|
||||
- Confirm Admin Password: Repeat the password of the new 'admin' user.
|
||||
|
||||
* Actions:
|
||||
|
||||
- Create: Creates the new database with initial user *admin* and the
|
||||
provided password.
|
||||
- Cancel
|
||||
|
||||
__ File-Server-Connection_
|
||||
|
||||
.. note:: The appropriate Tryton database user (defined in the Tryton server
|
||||
configuration) needs to be authorized to create databases for this step.
|
||||
|
||||
.. _Menu-File-Restore_Database:
|
||||
|
||||
Restore Database
|
||||
Opens a :term:`dialog` to restore a previously created database backup
|
||||
file.
|
||||
|
||||
* File choose menu dialog
|
||||
|
||||
- Choose a database backup file in the file system to be restored.
|
||||
- Actions:
|
||||
|
||||
+ Open: Open the chosen backup file.
|
||||
+ Cancel
|
||||
|
||||
* Restore Database dialog:
|
||||
|
||||
- `Server Connection`__
|
||||
- Tryton Server Password: The password given in the Tryton server
|
||||
configuration.
|
||||
- File to Restore: Show filename and path.
|
||||
- New Database Name: Enter a new name for the database to be restored
|
||||
- Actions:
|
||||
|
||||
+ Restore: Proceed database restore.
|
||||
+ Cancel
|
||||
|
||||
__ File-Server-Connection_
|
||||
|
||||
.. _Menu-File-Backup_Database:
|
||||
|
||||
Backup Database
|
||||
Open a :term:`dialog` to backup an existing database and save it as a file.
|
||||
|
||||
* `Backup a Database` dialog
|
||||
|
||||
- `Server connection`__
|
||||
- Database: Choose the Tryton database to backup.
|
||||
- Tryton Server Password: The password given in the Tryton server
|
||||
configuration.
|
||||
- Actions:
|
||||
|
||||
+ Backup: Proceed database backup.
|
||||
+ Cancel
|
||||
|
||||
* `Save Backup File` dialog
|
||||
|
||||
- Choose a filename and location for the created backup file.
|
||||
- Save the backup file.
|
||||
|
||||
__ File-Server-Connection_
|
||||
|
||||
.. _Menu-File-Drop_Database:
|
||||
|
||||
Drop Database
|
||||
Open a :term:`dialog` to delete an existing Tryton database.
|
||||
|
||||
* `Delete a Database` dialog
|
||||
|
||||
- `Server Connection`__
|
||||
- Database: Choose a database to delete.
|
||||
- Tryton Server Password: The password given in the Tryton server
|
||||
configuration.
|
||||
|
||||
* Confirmation Dialog
|
||||
|
||||
- Yes: Drop the database
|
||||
- No: Do not drop the database
|
||||
- Cancel
|
||||
|
||||
__ File-Server-Connection_
|
||||
|
||||
.. _File-Server-Connection:
|
||||
.. _Connection-Server-Connection:
|
||||
|
||||
Server (connection) dialog:
|
||||
This :term:`dialog` is widely used to setup a Tryton server connection.
|
||||
|
||||
@@ -24,11 +24,8 @@ except ImportError:
|
||||
import md5
|
||||
import webbrowser
|
||||
import traceback
|
||||
import threading
|
||||
import tryton.rpc as rpc
|
||||
import locale
|
||||
import socket
|
||||
from tryton import __version__
|
||||
import thread
|
||||
import urllib
|
||||
from string import Template
|
||||
@@ -227,46 +224,6 @@ def find_in_path(name):
|
||||
return name
|
||||
|
||||
|
||||
def test_server_version(host, port):
|
||||
version = rpc.server_version(host, port)
|
||||
if not version:
|
||||
return False
|
||||
return version.split('.')[:2] == __version__.split('.')[:2]
|
||||
|
||||
|
||||
def refresh_dblist(host, port):
|
||||
'''
|
||||
Return the number of database available
|
||||
or None if it is impossible to connect
|
||||
or -1 if the server version doesn't match the client version
|
||||
'''
|
||||
rpc.logout()
|
||||
if not test_server_version(host, port):
|
||||
return -1
|
||||
return rpc.db_list(host, port)
|
||||
|
||||
|
||||
def refresh_langlist(lang_widget, host, port):
|
||||
liststore = lang_widget.get_model()
|
||||
liststore.clear()
|
||||
try:
|
||||
lang_list = rpc.db_exec(host, port, 'list_lang')
|
||||
except socket.error:
|
||||
return []
|
||||
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):
|
||||
result = False
|
||||
parent = get_toplevel_window()
|
||||
@@ -1192,54 +1149,6 @@ def generateColorscheme(masterColor, keys, light=0.1):
|
||||
s, (v + light * i) % 1) for i, key in enumerate(keys)}
|
||||
|
||||
|
||||
class DBProgress(object):
|
||||
|
||||
def __init__(self, host, port):
|
||||
self.dbs = None, None
|
||||
self.host, self.port = host, port
|
||||
self.updated = threading.Event()
|
||||
|
||||
def start(self):
|
||||
dbs = None
|
||||
try:
|
||||
dbs = refresh_dblist(self.host, self.port)
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
self.dbs = dbs
|
||||
self.updated.set()
|
||||
|
||||
def update(self, combo, progressbar, callback, dbname=''):
|
||||
self.db_info = None
|
||||
threading.Thread(target=self.start).start()
|
||||
gobject.timeout_add(100, self.end, combo, progressbar, callback,
|
||||
dbname)
|
||||
|
||||
def end(self, combo, progressbar, callback, dbname):
|
||||
if not self.updated.isSet():
|
||||
progressbar.show()
|
||||
progressbar.pulse()
|
||||
return True
|
||||
progressbar.hide()
|
||||
dbs = self.dbs
|
||||
|
||||
if dbs is not None and dbs not in (-1, -2):
|
||||
liststore = combo.get_model()
|
||||
liststore.clear()
|
||||
index = -1
|
||||
for db_num, db_name in enumerate(dbs):
|
||||
liststore.append([db_name])
|
||||
if db_name == dbname:
|
||||
index = db_num
|
||||
if index == -1:
|
||||
index = 0
|
||||
combo.set_active(index)
|
||||
dbs = len(dbs)
|
||||
|
||||
callback(dbs)
|
||||
return False
|
||||
|
||||
|
||||
class RPCException(Exception):
|
||||
|
||||
def __init__(self, exception):
|
||||
|
||||
+18
-194
@@ -29,19 +29,15 @@ from tryton.gui.window.preference import Preference
|
||||
from tryton.gui.window import Limit
|
||||
from tryton.gui.window import Email
|
||||
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
|
||||
from tryton.gui.window.dbrestore import DBRestore
|
||||
from tryton.common.cellrendererclickablepixbuf import \
|
||||
CellRendererClickablePixbuf
|
||||
import tryton.translate as translate
|
||||
import tryton.plugins
|
||||
from tryton.common.placeholder_entry import PlaceholderEntry
|
||||
import pango
|
||||
import time
|
||||
if os.environ.get('GTKOSXAPPLICATION'):
|
||||
import gtkosx_application
|
||||
else:
|
||||
@@ -215,13 +211,13 @@ class Main(object):
|
||||
self.vbox.pack_start(menubar, False, True)
|
||||
self.vbox.reorder_child(menubar, 0)
|
||||
|
||||
menuitem_file = gtk.MenuItem(_('_File'))
|
||||
menubar.add(menuitem_file)
|
||||
menuitem_connection = gtk.MenuItem(_('_Connection'))
|
||||
menubar.add(menuitem_connection)
|
||||
|
||||
menu_file = self._set_menu_file()
|
||||
menuitem_file.set_submenu(menu_file)
|
||||
menu_file.set_accel_group(self.accel_group)
|
||||
menu_file.set_accel_path('<tryton>/File')
|
||||
menu_connection = self._set_menu_connection()
|
||||
menuitem_connection.set_submenu(menu_connection)
|
||||
menu_connection.set_accel_group(self.accel_group)
|
||||
menu_connection.set_accel_path('<tryton>/Connection')
|
||||
|
||||
menuitem_user = gtk.MenuItem(_('_User'))
|
||||
if self.menuitem_user:
|
||||
@@ -273,7 +269,7 @@ class Main(object):
|
||||
self.menubar.set_no_show_all(True)
|
||||
self.macapp.set_menu_bar(self.menubar)
|
||||
self.macapp.insert_app_menu_item(self.aboutitem, 0)
|
||||
menuitem_file.show_all()
|
||||
menuitem_connection.show_all()
|
||||
menuitem_user.show_all()
|
||||
menuitem_options.show_all()
|
||||
menuitem_favorite.show_all()
|
||||
@@ -389,8 +385,8 @@ class Main(object):
|
||||
title += ' - ' + value
|
||||
self.window.set_title(title)
|
||||
|
||||
def _set_menu_file(self):
|
||||
menu_file = gtk.Menu()
|
||||
def _set_menu_connection(self):
|
||||
menu_connection = gtk.Menu()
|
||||
|
||||
imagemenuitem_connect = gtk.ImageMenuItem(_('_Connect...'),
|
||||
self.accel_group)
|
||||
@@ -398,65 +394,17 @@ class Main(object):
|
||||
image.set_from_stock('tryton-connect', gtk.ICON_SIZE_MENU)
|
||||
imagemenuitem_connect.set_image(image)
|
||||
imagemenuitem_connect.connect('activate', self.sig_login)
|
||||
imagemenuitem_connect.set_accel_path('<tryton>/File/Connect')
|
||||
menu_file.add(imagemenuitem_connect)
|
||||
imagemenuitem_connect.set_accel_path('<tryton>/Connection/Connect')
|
||||
menu_connection.add(imagemenuitem_connect)
|
||||
|
||||
imagemenuitem_disconnect = gtk.ImageMenuItem(_('_Disconnect'))
|
||||
image = gtk.Image()
|
||||
image.set_from_stock('tryton-disconnect', gtk.ICON_SIZE_MENU)
|
||||
imagemenuitem_disconnect.set_image(image)
|
||||
imagemenuitem_disconnect.connect('activate', self.sig_logout)
|
||||
imagemenuitem_disconnect.set_accel_path('<tryton>/File/Disconnect')
|
||||
menu_file.add(imagemenuitem_disconnect)
|
||||
|
||||
menu_file.add(gtk.SeparatorMenuItem())
|
||||
|
||||
imagemenuitem_database = gtk.ImageMenuItem(_('Data_base'))
|
||||
image = gtk.Image()
|
||||
image.set_from_stock('tryton-system-file-manager', gtk.ICON_SIZE_MENU)
|
||||
imagemenuitem_database.set_image(image)
|
||||
menu_file.add(imagemenuitem_database)
|
||||
|
||||
menu_database = gtk.Menu()
|
||||
menu_database.set_accel_group(self.accel_group)
|
||||
menu_database.set_accel_path('<tryton>/File/Database')
|
||||
imagemenuitem_database.set_submenu(menu_database)
|
||||
|
||||
imagemenuitem_db_new = gtk.ImageMenuItem(_('_New Database...'))
|
||||
image = gtk.Image()
|
||||
image.set_from_stock('tryton-folder-new', gtk.ICON_SIZE_MENU)
|
||||
imagemenuitem_db_new.set_image(image)
|
||||
imagemenuitem_db_new.connect('activate', self.sig_db_new)
|
||||
imagemenuitem_db_new.set_accel_path(
|
||||
'<tryton>/File/Database/New Database')
|
||||
menu_database.add(imagemenuitem_db_new)
|
||||
|
||||
imagemenuitem_db_restore = gtk.ImageMenuItem(_('_Restore Database...'))
|
||||
image = gtk.Image()
|
||||
image.set_from_stock('tryton-folder-saved-search', gtk.ICON_SIZE_MENU)
|
||||
imagemenuitem_db_restore.set_image(image)
|
||||
imagemenuitem_db_restore.connect('activate', self.sig_db_restore)
|
||||
imagemenuitem_db_restore.set_accel_path(
|
||||
'<tryton>/File/Database/Restore Database')
|
||||
menu_database.add(imagemenuitem_db_restore)
|
||||
|
||||
imagemenuitem_db_dump = gtk.ImageMenuItem(_('_Backup Database...'))
|
||||
image = gtk.Image()
|
||||
image.set_from_stock('tryton-save-as', gtk.ICON_SIZE_MENU)
|
||||
imagemenuitem_db_dump.set_image(image)
|
||||
imagemenuitem_db_dump.connect('activate', self.sig_db_dump)
|
||||
imagemenuitem_db_dump.set_accel_path(
|
||||
'<tryton>/File/Database/Backup Database')
|
||||
menu_database.add(imagemenuitem_db_dump)
|
||||
|
||||
imagemenuitem_db_drop = gtk.ImageMenuItem(_('Dro_p Database...'))
|
||||
image = gtk.Image()
|
||||
image.set_from_stock('tryton-delete', gtk.ICON_SIZE_MENU)
|
||||
imagemenuitem_db_drop.set_image(image)
|
||||
imagemenuitem_db_drop.connect('activate', self.sig_db_drop)
|
||||
imagemenuitem_db_drop.set_accel_path(
|
||||
'<tryton>/File/Database/Drop Database')
|
||||
menu_database.add(imagemenuitem_db_drop)
|
||||
imagemenuitem_disconnect.set_accel_path(
|
||||
'<tryton>/Connection/Disconnect')
|
||||
menu_connection.add(imagemenuitem_disconnect)
|
||||
|
||||
imagemenuitem_close = gtk.ImageMenuItem(_('_Quit...'),
|
||||
self.accel_group)
|
||||
@@ -464,11 +412,11 @@ class Main(object):
|
||||
image.set_from_stock('tryton-log-out', gtk.ICON_SIZE_MENU)
|
||||
imagemenuitem_close.set_image(image)
|
||||
imagemenuitem_close.connect('activate', self.sig_close)
|
||||
imagemenuitem_close.set_accel_path('<tryton>/File/Quit')
|
||||
imagemenuitem_close.set_accel_path('<tryton>/Connection/Quit')
|
||||
if self.macapp is None:
|
||||
menu_file.add(gtk.SeparatorMenuItem())
|
||||
menu_file.add(imagemenuitem_close)
|
||||
return menu_file
|
||||
menu_connection.add(gtk.SeparatorMenuItem())
|
||||
menu_connection.add(imagemenuitem_close)
|
||||
return menu_connection
|
||||
|
||||
def _set_menu_user(self):
|
||||
menu_user = gtk.Menu()
|
||||
@@ -1270,130 +1218,6 @@ class Main(object):
|
||||
for dialog in current_form.dialogs:
|
||||
dialog.show()
|
||||
|
||||
def sig_db_new(self, widget):
|
||||
if not self.sig_logout(widget):
|
||||
return False
|
||||
dia = DBCreate(CONFIG['login.server'], int(CONFIG['login.port']),
|
||||
sig_login=self.sig_login)
|
||||
res = dia.run()
|
||||
if res:
|
||||
CONFIG.save()
|
||||
return res
|
||||
|
||||
def sig_db_drop(self, widget=None):
|
||||
if not self.sig_logout(widget):
|
||||
return False
|
||||
url, dbname, passwd = DBBackupDrop(function='drop').run()
|
||||
if not dbname:
|
||||
rpc.logout()
|
||||
return
|
||||
|
||||
host, port = url.rsplit(':', 1)
|
||||
sure = common.sur_3b(_("You are going to delete a Tryton "
|
||||
"database.\nAre you really sure to proceed?"))
|
||||
if sure == "ko" or sure == "cancel":
|
||||
return
|
||||
rpcprogress = common.RPCProgress('db_exec', (host, int(port), 'drop',
|
||||
dbname, passwd))
|
||||
try:
|
||||
rpcprogress.run(False)
|
||||
except TrytonServerError, exception:
|
||||
if exception.faultCode == "AccessDenied":
|
||||
common.warning(_("Wrong Tryton Server Password\n"
|
||||
"Please try again."),
|
||||
_('Access denied!'))
|
||||
self.sig_db_drop()
|
||||
else:
|
||||
common.warning(_('Database drop failed with error message:\n')
|
||||
+ str(exception.faultCode), _('Database drop failed!'))
|
||||
return
|
||||
common.message(_("Database dropped successfully!"))
|
||||
|
||||
def sig_db_restore(self, widget=None):
|
||||
if not self.sig_logout(widget):
|
||||
return False
|
||||
filename = common.file_selection(_('Open Backup File to Restore...'),
|
||||
preview=False)
|
||||
if not filename:
|
||||
return
|
||||
dialog = DBRestore(filename=filename)
|
||||
url, dbname, passwd, update = dialog.run()
|
||||
if dbname:
|
||||
with open(filename, 'rb') as file_p:
|
||||
data = file_p.read()
|
||||
host, port = url.rsplit(':', 1)
|
||||
cast = bytearray if bytes == str else bytes
|
||||
rpcprogress = common.RPCProgress('db_exec', (host, int(port),
|
||||
'restore', dbname, passwd, cast(data), update))
|
||||
try:
|
||||
res = rpcprogress.run(False)
|
||||
except TrytonServerError, exception:
|
||||
if exception.faultCode == \
|
||||
"Couldn't restore database with password":
|
||||
common.warning(_("It is not possible to restore a "
|
||||
"password protected database.\n"
|
||||
"Backup and restore needed to be proceed "
|
||||
"manual."),
|
||||
_('Database is password protected!'))
|
||||
elif exception.faultCode == "AccessDenied":
|
||||
common.warning(_("Wrong Tryton Server Password.\n"
|
||||
"Please try again."),
|
||||
_('Access denied!'))
|
||||
self.sig_db_restore()
|
||||
else:
|
||||
common.warning(_('Database restore failed with '
|
||||
'error message:\n') + str(exception.faultCode),
|
||||
_('Database restore failed!'))
|
||||
return
|
||||
if res:
|
||||
common.message(_("Database restored successfully!"))
|
||||
else:
|
||||
common.message(_('Database restore failed!'))
|
||||
|
||||
def sig_db_dump(self, widget=None):
|
||||
if not self.sig_logout(widget):
|
||||
return False
|
||||
dialog = DBBackupDrop(function='backup')
|
||||
url, dbname, passwd = dialog.run()
|
||||
|
||||
if not (dbname and url and passwd):
|
||||
rpc.logout()
|
||||
return
|
||||
|
||||
host, port = url.rsplit(':', 1)
|
||||
rpcprogress = common.RPCProgress('db_exec', (host, int(port), 'dump',
|
||||
dbname, passwd))
|
||||
try:
|
||||
dump = rpcprogress.run(False)
|
||||
except TrytonServerError, exception:
|
||||
if exception.faultCode == "Couldn't dump database with password":
|
||||
common.warning(_("It is not possible to dump a password "
|
||||
"protected Database.\nBackup and restore "
|
||||
"needed to be proceed manual."),
|
||||
_('Database is password protected!'))
|
||||
elif exception.faultCode == "AccessDenied":
|
||||
common.warning(_("Wrong Tryton Server Password.\n"
|
||||
"Please try again."),
|
||||
_('Access denied!'))
|
||||
self.sig_db_dump()
|
||||
else:
|
||||
common.warning(_('Database dump failed with '
|
||||
'error message:\n') + str(exception.faultCode),
|
||||
_('Database dump failed!'))
|
||||
rpc.logout()
|
||||
return
|
||||
|
||||
filename = common.file_selection(_('Save As...'),
|
||||
action=gtk.FILE_CHOOSER_ACTION_SAVE, preview=False,
|
||||
filename=dbname + '-' + time.strftime('%Y%m%d%H%M') + '.dump')
|
||||
|
||||
if filename:
|
||||
with open(filename, 'wb') as file_:
|
||||
file_.write(dump)
|
||||
common.message(_("Database backuped successfully!"))
|
||||
else:
|
||||
rpc.logout()
|
||||
|
||||
def _open_url(self, url):
|
||||
urlp = urlparse(url)
|
||||
if not urlp.scheme == 'tryton':
|
||||
|
||||
@@ -1,392 +0,0 @@
|
||||
# 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 gobject
|
||||
import gettext
|
||||
|
||||
import tryton.common as common
|
||||
from tryton.config import CONFIG, TRYTON_ICON
|
||||
from tryton.exceptions import TrytonServerError
|
||||
import tryton.rpc as rpc
|
||||
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class DBCreate(object):
|
||||
def server_connection_state(self, state):
|
||||
"""
|
||||
Method to set the server connection information depending on the
|
||||
connection state. If state is True, the connection string will shown.
|
||||
Otherwise the wrong connection string will be shown plus an additional
|
||||
errormessage. In this case, all entryboxes set insensitive
|
||||
"""
|
||||
if state:
|
||||
self.entry_serverpasswd.set_sensitive(True)
|
||||
self.entry_dbname.set_sensitive(True)
|
||||
self.entry_adminpasswd.set_sensitive(True)
|
||||
self.entry_adminpasswd2.set_sensitive(True)
|
||||
self.tooltips.set_tip(self.entry_server_connection,
|
||||
_("This is the URL of the Tryton server. Use server "
|
||||
"'localhost' and port '8000' if the server is installed "
|
||||
"on this computer. Click on 'Change' to change the "
|
||||
"address."))
|
||||
else:
|
||||
self.entry_serverpasswd.set_sensitive(False)
|
||||
self.entry_dbname.set_sensitive(False)
|
||||
self.entry_adminpasswd.set_sensitive(False)
|
||||
self.entry_adminpasswd2.set_sensitive(False)
|
||||
self.entry_server_connection.set_editable(False)
|
||||
self.entry_server_connection.set_sensitive(False)
|
||||
self.entry_server_connection.set_text(
|
||||
self.entry_server_connection.get_text()
|
||||
+ " " + _("No connection!"))
|
||||
self.tooltips.set_tip(self.entry_server_connection, _(
|
||||
"Can not connect to the server!\n"
|
||||
"1. Try to check if the server is running.\n"
|
||||
"2. Find out on which address and port it is listening.\n"
|
||||
"3. If there is a firewall between the server and this "
|
||||
"client, make sure that the server address and port "
|
||||
"(usually 8000) are not blocked.\n"
|
||||
"Click on 'Change' to change the address."))
|
||||
return state
|
||||
|
||||
def server_change(self, widget):
|
||||
"""
|
||||
This method checks the server connection via host and port. If the
|
||||
connection is successfull, it query the language list and pass true
|
||||
state to the GUI. Otherwise it pass false state to the GUI.
|
||||
"""
|
||||
res = common.request_server(self.entry_server_connection)
|
||||
if not res:
|
||||
return False
|
||||
host, port = res
|
||||
try:
|
||||
if self.combo_language and host and port:
|
||||
common.refresh_langlist(self.combo_language, host, port)
|
||||
self.server_connection_state(True)
|
||||
except TrytonServerError:
|
||||
self.server_connection_state(False)
|
||||
return False
|
||||
return True
|
||||
|
||||
def event_passwd_clear(self, widget, event, data=None):
|
||||
"""
|
||||
This event method clear the text in a widget if CTRL-u
|
||||
is pressed.
|
||||
"""
|
||||
if ((event.keyval == gtk.keysyms.u)
|
||||
and (event.state & gtk.gdk.CONTROL_MASK)):
|
||||
widget.set_text("")
|
||||
|
||||
def event_show_button_create(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.entry_serverpasswd.get_text() != ""
|
||||
and self.entry_dbname.get_text() != ""
|
||||
and self.combo_language.get_active() != -1
|
||||
and self.entry_adminpasswd.get_text() != ""
|
||||
and self.entry_adminpasswd2.get_text() != ""):
|
||||
widget.unset_flags(gtk.HAS_DEFAULT)
|
||||
self.button_create.set_sensitive(True)
|
||||
self.button_create.set_flags(gtk.CAN_DEFAULT)
|
||||
self.button_create.set_flags(gtk.HAS_DEFAULT)
|
||||
self.button_create.set_flags(gtk.CAN_FOCUS)
|
||||
self.button_create.set_flags(gtk.RECEIVES_DEFAULT)
|
||||
self.button_create.grab_default()
|
||||
|
||||
else:
|
||||
self.button_create.set_sensitive(False)
|
||||
|
||||
def entry_insert_text(self, entry, new_text, new_text_length, position):
|
||||
"""
|
||||
This event method checks each text input for the PostgreSQL
|
||||
database name. It allows the following rules:
|
||||
- Allowed characters are alpha-nummeric [A-Za-z0-9] and underscore (_)
|
||||
- First character must be a letter
|
||||
"""
|
||||
|
||||
if new_text.isalnum() or new_text == '_':
|
||||
_hid = entry.get_data('handlerid')
|
||||
entry.handler_block(_hid)
|
||||
_pos = entry.get_position()
|
||||
_pos = entry.insert_text(new_text, _pos)
|
||||
entry.handler_unblock(_hid)
|
||||
|
||||
def _move_cursor():
|
||||
if not entry.props.window:
|
||||
return
|
||||
with gtk.gdk.lock:
|
||||
entry.set_position(_pos)
|
||||
return False
|
||||
gobject.idle_add(_move_cursor)
|
||||
entry.stop_emission("insert-text")
|
||||
|
||||
def __init__(self, host=None, port=None, sig_login=None):
|
||||
self.host = host
|
||||
self.port = port
|
||||
|
||||
# GTK Stuffs
|
||||
self.dialog = gtk.Dialog(title=_("Create new database"),
|
||||
flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT |
|
||||
gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
self.dialog.set_has_separator(True)
|
||||
self.dialog.set_icon(TRYTON_ICON)
|
||||
# This event is needed for controlling the button_create
|
||||
self.dialog.connect("key-press-event", self.event_show_button_create)
|
||||
self.tooltips = common.Tooltips()
|
||||
self.dialog.add_button("gtk-cancel",
|
||||
gtk.RESPONSE_CANCEL)
|
||||
self.button_create = gtk.Button(_('C_reate'))
|
||||
self.button_create.set_flags(gtk.CAN_DEFAULT)
|
||||
self.button_create.set_flags(gtk.HAS_DEFAULT)
|
||||
self.button_create.set_sensitive(False)
|
||||
img_connect = gtk.Image()
|
||||
img_connect.set_from_stock('tryton-new', gtk.ICON_SIZE_BUTTON)
|
||||
self.button_create.set_image(img_connect)
|
||||
self.tooltips.set_tip(self.button_create,
|
||||
_('Create the new database.'))
|
||||
self.dialog.add_action_widget(self.button_create, gtk.RESPONSE_OK)
|
||||
self.dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
|
||||
dialog_vbox = gtk.VBox()
|
||||
table = gtk.Table(9, 3, False)
|
||||
table.set_border_width(10)
|
||||
table.set_row_spacings(3)
|
||||
table.set_col_spacings(3)
|
||||
|
||||
self.label_server_setup = gtk.Label()
|
||||
self.label_server_setup.set_markup("<b>" + _("Server Setup:") + "</b>")
|
||||
self.label_server_setup.set_justify(gtk.JUSTIFY_LEFT)
|
||||
self.label_server_setup.set_alignment(0, 1)
|
||||
self.label_server_setup.set_padding(9, 5)
|
||||
table.attach(self.label_server_setup, 0, 3, 0, 1, xoptions=gtk.FILL)
|
||||
self.label_server = gtk.Label(_("Server connection:"))
|
||||
self.label_server.set_alignment(1, 0.5)
|
||||
self.label_server.set_padding(3, 3)
|
||||
table.attach(self.label_server, 0, 1, 1, 2, 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.label_server.set_mnemonic_widget(self.entry_server_connection)
|
||||
self.tooltips.set_tip(self.entry_server_connection,
|
||||
_("This is the URL of the server. Use server 'localhost' and port "
|
||||
"'8000' if the server is installed on this computer. Click on "
|
||||
"'Change' to change the address."))
|
||||
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, 1, 2, yoptions=False,
|
||||
xoptions=gtk.FILL)
|
||||
self.tooltips.set_tip(self.button_server_change,
|
||||
_("Setup the server connection..."))
|
||||
|
||||
table.attach(self.entry_server_connection, 1, 2, 1, 2)
|
||||
self.label_serverpasswd = gtk.Label(_("Tryton Server Password:"))
|
||||
self.label_serverpasswd.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
self.label_serverpasswd.set_alignment(1, 0.5)
|
||||
self.label_serverpasswd.set_padding(3, 3)
|
||||
table.attach(self.label_serverpasswd, 0, 1, 2, 3, xoptions=gtk.FILL,
|
||||
yoptions=gtk.FILL)
|
||||
self.entry_serverpasswd = gtk.Entry()
|
||||
self.entry_serverpasswd.set_visibility(False)
|
||||
self.entry_serverpasswd.set_activates_default(True)
|
||||
self.label_serverpasswd.set_mnemonic_widget(self.entry_serverpasswd)
|
||||
table.attach(self.entry_serverpasswd, 1, 3, 2, 3, yoptions=gtk.FILL)
|
||||
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."))
|
||||
self.entry_serverpasswd.connect("key-press-event",
|
||||
self.event_passwd_clear)
|
||||
|
||||
self.hseparator = gtk.HSeparator()
|
||||
table.attach(self.hseparator, 0, 3, 3, 4, yoptions=gtk.FILL)
|
||||
|
||||
label_dbname = gtk.Label()
|
||||
label_dbname.set_markup("<b>" + _("New database setup:") + "</b>")
|
||||
label_dbname.set_justify(gtk.JUSTIFY_LEFT)
|
||||
label_dbname.set_alignment(0, 1)
|
||||
label_dbname.set_padding(9, 5)
|
||||
table.attach(label_dbname, 0, 3, 4, 5, xoptions=gtk.FILL,
|
||||
yoptions=gtk.FILL)
|
||||
label_dbname = gtk.Label(_("Database name:"))
|
||||
label_dbname.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
label_dbname.set_padding(3, 3)
|
||||
label_dbname.set_alignment(1, 0.5)
|
||||
table.attach(label_dbname, 0, 1, 5, 6, xoptions=gtk.FILL,
|
||||
yoptions=gtk.FILL)
|
||||
self.entry_dbname = gtk.Entry()
|
||||
self.entry_dbname.set_max_length(63)
|
||||
self.entry_dbname.set_width_chars(16)
|
||||
self.entry_dbname.set_activates_default(True)
|
||||
label_dbname.set_mnemonic_widget(self.entry_dbname)
|
||||
table.attach(self.entry_dbname, 1, 3, 5, 6, yoptions=gtk.FILL)
|
||||
self.tooltips.set_tip(self.entry_dbname,
|
||||
_("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"))
|
||||
handlerid = self.entry_dbname.connect("insert-text",
|
||||
self.entry_insert_text)
|
||||
self.entry_dbname.set_data('handlerid', handlerid)
|
||||
label_language = gtk.Label(_("Default language:"))
|
||||
label_language.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
label_language.set_alignment(1, 0.5)
|
||||
label_language.set_padding(3, 3)
|
||||
table.attach(label_language, 0, 1, 6, 7, xoptions=gtk.FILL,
|
||||
yoptions=gtk.FILL)
|
||||
eventbox_language = gtk.EventBox()
|
||||
self.combo_language = gtk.combo_box_new_text()
|
||||
eventbox_language.add(self.combo_language)
|
||||
table.attach(eventbox_language, 1, 3, 6, 7, yoptions=gtk.FILL)
|
||||
self.tooltips.set_tip(eventbox_language, _("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."))
|
||||
label_adminpasswd = gtk.Label(_("Admin password:"))
|
||||
label_adminpasswd.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
label_adminpasswd.set_padding(3, 3)
|
||||
label_adminpasswd.set_alignment(1, 0.5)
|
||||
table.attach(label_adminpasswd, 0, 1, 7, 8, xoptions=gtk.FILL,
|
||||
yoptions=gtk.FILL)
|
||||
self.entry_adminpasswd = gtk.Entry()
|
||||
self.entry_adminpasswd.set_visibility(False)
|
||||
self.entry_adminpasswd.set_activates_default(True)
|
||||
label_adminpasswd.set_mnemonic_widget(self.entry_adminpasswd)
|
||||
self.tooltips.set_tip(self.entry_adminpasswd,
|
||||
_("Choose a password for the admin user of the new database. "
|
||||
"With these credentials you will be later able to login into "
|
||||
"the database:\n"
|
||||
"User name: admin\n"
|
||||
"Password: <The password you set here>"))
|
||||
table.attach(self.entry_adminpasswd, 1, 3, 7, 8, yoptions=gtk.FILL)
|
||||
self.entry_adminpasswd.connect("key-press-event",
|
||||
self.event_passwd_clear)
|
||||
label_adminpasswd2 = gtk.Label(_("Confirm admin password:"))
|
||||
label_adminpasswd2.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
label_adminpasswd2.set_padding(3, 3)
|
||||
label_adminpasswd2.set_alignment(1, 0.5)
|
||||
table.attach(label_adminpasswd2, 0, 1, 8, 9, xoptions=gtk.FILL,
|
||||
yoptions=gtk.FILL)
|
||||
self.entry_adminpasswd2 = gtk.Entry()
|
||||
self.entry_adminpasswd2.set_visibility(False)
|
||||
self.entry_adminpasswd2.set_activates_default(True)
|
||||
label_adminpasswd2.set_mnemonic_widget(self.entry_adminpasswd2)
|
||||
self.tooltips.set_tip(self.entry_adminpasswd2, _("Type the Admin "
|
||||
"password again"))
|
||||
table.attach(self.entry_adminpasswd2, 1, 3, 8, 9, yoptions=gtk.FILL)
|
||||
self.entry_adminpasswd2.connect("key-press-event",
|
||||
self.event_passwd_clear)
|
||||
self.entry_serverpasswd.grab_focus()
|
||||
dialog_vbox.pack_start(table)
|
||||
self.dialog.vbox.pack_start(dialog_vbox)
|
||||
self.sig_login = sig_login
|
||||
|
||||
def run(self):
|
||||
parent = common.get_toplevel_window()
|
||||
self.dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
self.dialog.set_transient_for(parent)
|
||||
self.dialog.show_all()
|
||||
|
||||
pass_widget = self.entry_serverpasswd
|
||||
change_button = self.button_server_change
|
||||
admin_passwd = self.entry_adminpasswd
|
||||
admin_passwd2 = self.entry_adminpasswd2
|
||||
change_button.connect_after('clicked', self.server_change)
|
||||
|
||||
if self.host and self.port:
|
||||
url = '%s:%d' % (self.host, self.port)
|
||||
else:
|
||||
url = ''
|
||||
self.entry_server_connection.set_text(url)
|
||||
|
||||
liststore = gtk.ListStore(str, str)
|
||||
self.combo_language.set_model(liststore)
|
||||
try:
|
||||
common.refresh_langlist(self.combo_language, self.host, self.port)
|
||||
except TrytonServerError:
|
||||
self.button_create.set_sensitive(False)
|
||||
|
||||
while True:
|
||||
self.dialog.props.sensitive = True
|
||||
res = self.dialog.run()
|
||||
dbname = self.entry_dbname.get_text()
|
||||
netloc = self.entry_server_connection.get_text()
|
||||
host = common.get_hostname(netloc)
|
||||
port = common.get_port(netloc)
|
||||
langidx = self.combo_language.get_active_iter()
|
||||
langreal = langidx \
|
||||
and self.combo_language.get_model().get_value(langidx, 1)
|
||||
passwd = pass_widget.get_text()
|
||||
if res == gtk.RESPONSE_OK:
|
||||
if admin_passwd.get_text() != admin_passwd2.get_text():
|
||||
common.warning(
|
||||
_("The new admin password "
|
||||
"doesn't match the confirmation field.\n"),
|
||||
_("Passwords doesn't match!"))
|
||||
continue
|
||||
try:
|
||||
exist = rpc.db_exec(host, port, 'db_exist', dbname)
|
||||
except TrytonServerError, exception:
|
||||
common.process_exception(exception)
|
||||
continue
|
||||
if exist:
|
||||
common.warning(_("A database with the same name "
|
||||
"already exists.\n"
|
||||
"Try another database name."),
|
||||
_("This database name already exist!"))
|
||||
self.entry_dbname.set_text("")
|
||||
self.entry_dbname.grab_focus()
|
||||
continue
|
||||
else: # Everything runs fine, break the block here
|
||||
self.dialog.props.sensitive = False
|
||||
try:
|
||||
rpcprogress = common.RPCProgress('db_exec',
|
||||
(host, port, 'create', dbname, passwd, langreal,
|
||||
admin_passwd.get_text()))
|
||||
rpcprogress.run(False)
|
||||
except TrytonServerError, exception:
|
||||
if str(exception.faultCode) == "AccessDenied":
|
||||
common.warning(_("Sorry, wrong password for "
|
||||
"the Tryton server. "
|
||||
"Please try again."),
|
||||
_("Access denied!"))
|
||||
self.entry_serverpasswd.set_text("")
|
||||
self.entry_serverpasswd.grab_focus()
|
||||
continue
|
||||
else: # Unclassified error
|
||||
common.warning(_("Can't create the "
|
||||
"database, caused by an unknown reason.\n"
|
||||
"If there is a database created, it could "
|
||||
"be broken. Maybe drop this database! "
|
||||
"Please check the error message for "
|
||||
"possible informations.\n"
|
||||
"Error message:\n")
|
||||
+ str(exception.faultCode),
|
||||
_("Error creating database!"))
|
||||
parent.present()
|
||||
self.dialog.destroy()
|
||||
rpc.logout()
|
||||
break
|
||||
parent.present()
|
||||
self.dialog.destroy()
|
||||
if self.sig_login:
|
||||
CONFIG['login.server'] = host
|
||||
CONFIG['login.port'] = str(port)
|
||||
CONFIG['login.db'] = dbname
|
||||
CONFIG['login.login'] = 'admin'
|
||||
self.sig_login()
|
||||
break
|
||||
break
|
||||
parent.present()
|
||||
self.dialog.destroy()
|
||||
return dbname
|
||||
@@ -1,240 +0,0 @@
|
||||
# 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 gobject
|
||||
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.
|
||||
"""
|
||||
def refreshlist(self, host, port):
|
||||
self.combo_database.hide()
|
||||
self.combo_database_label.hide()
|
||||
self.combo_database_entry.hide()
|
||||
dbprogress = common.DBProgress(host, port)
|
||||
|
||||
def callback(dbs):
|
||||
if dbs is None:
|
||||
self.combo_database_label.set_label('<b>' +
|
||||
_('Could not connect to server!') + '</b>')
|
||||
self.combo_database_label.show()
|
||||
elif dbs == -1:
|
||||
self.combo_database_label.set_label('<b>' +
|
||||
_('This client version is not compatible '
|
||||
'with the server!')
|
||||
+ '</b>')
|
||||
self.combo_database_label.show()
|
||||
elif dbs == -2:
|
||||
self.combo_database_entry.show()
|
||||
self.combo_database_entry.grab_focus()
|
||||
elif dbs == 0:
|
||||
self.combo_database_label.set_label('<b>'
|
||||
+ _('No database found, you must create one!') + '</b>')
|
||||
self.combo_database_label.show()
|
||||
else:
|
||||
self.combo_database.show()
|
||||
dbprogress.update(self.combo_database, self.db_progressbar, callback)
|
||||
|
||||
def refreshlist_ask(self, widget=None):
|
||||
res = common.request_server(self.entry_server_connection)
|
||||
if not res:
|
||||
return None
|
||||
host, port = res
|
||||
self.refreshlist(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_text() != ""
|
||||
or self.combo_database_entry.get_text() != "")
|
||||
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, 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.parent = common.get_toplevel_window()
|
||||
self.dialog = gtk.Dialog(title=dialog_title, parent=self.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_icon(TRYTON_ICON)
|
||||
self.dialog.connect("key-press-event", self.event_show_button_ok)
|
||||
self.tooltips = common.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, False, 0)
|
||||
|
||||
label_subtitle = gtk.Label()
|
||||
label_subtitle.set_markup("<b>" + label_subtitle_text + "</b>")
|
||||
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, yoptions=False,
|
||||
xoptions=gtk.FILL)
|
||||
|
||||
hseparator = gtk.HSeparator()
|
||||
table.attach(hseparator, 0, 3, 1, 2, yoptions=False)
|
||||
|
||||
self.label_server = gtk.Label(_("Server Connection:"))
|
||||
self.label_server.set_alignment(1, 0.5)
|
||||
self.label_server.set_padding(3, 3)
|
||||
table.attach(self.label_server, 0, 1, 2, 3, yoptions=False,
|
||||
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.label_server.set_mnemonic_widget(self.entry_server_connection)
|
||||
self.tooltips.set_tip(self.entry_server_connection, _("This is the "
|
||||
"URL of the server. Use server 'localhost' and port '8000' "
|
||||
"if the server is installed on this computer. "
|
||||
"Click on 'Change' to change the address."))
|
||||
table.attach(self.entry_server_connection, 1, 2, 2, 3,
|
||||
yoptions=gtk.FILL)
|
||||
|
||||
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)
|
||||
|
||||
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, yoptions=False,
|
||||
xoptions=gtk.FILL)
|
||||
|
||||
vbox_combo = gtk.VBox(homogeneous=True)
|
||||
self.combo_database = gtk.ComboBox()
|
||||
dbstore = gtk.ListStore(gobject.TYPE_STRING)
|
||||
cell = gtk.CellRendererText()
|
||||
self.combo_database.pack_start(cell, True)
|
||||
self.combo_database.add_attribute(cell, 'text', 0)
|
||||
self.combo_database.set_model(dbstore)
|
||||
self.db_progressbar = gtk.ProgressBar()
|
||||
self.combo_database_label = gtk.Label()
|
||||
self.combo_database_label.set_use_markup(True)
|
||||
self.combo_database_label.set_alignment(0, 1)
|
||||
self.combo_database_entry = gtk.Entry()
|
||||
vbox_combo.pack_start(self.combo_database)
|
||||
vbox_combo.pack_start(self.combo_database_label)
|
||||
vbox_combo.pack_start(self.db_progressbar)
|
||||
vbox_combo.pack_start(self.combo_database_entry)
|
||||
width, height = 0, 0
|
||||
# Compute size_request of box in order to prevent "form jumping"
|
||||
for child in vbox_combo.get_children():
|
||||
cwidth, cheight = child.size_request()
|
||||
width, height = max(width, cwidth), max(height, cheight)
|
||||
vbox_combo.set_size_request(width, height)
|
||||
table.attach(vbox_combo, 1, 3, 3, 4, yoptions=False)
|
||||
|
||||
self.label_serverpasswd = gtk.Label(_("Tryton Server Password:"))
|
||||
self.label_serverpasswd.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
self.label_serverpasswd.set_alignment(1, 0.5)
|
||||
self.label_serverpasswd.set_padding(3, 3)
|
||||
table.attach(self.label_serverpasswd, 0, 1, 4, 5, yoptions=False,
|
||||
xoptions=gtk.FILL)
|
||||
|
||||
self.entry_serverpasswd = gtk.Entry()
|
||||
self.entry_serverpasswd.set_visibility(False)
|
||||
self.entry_serverpasswd.set_activates_default(True)
|
||||
self.label_serverpasswd.set_mnemonic_widget(self.entry_serverpasswd)
|
||||
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."))
|
||||
table.attach(self.entry_serverpasswd, 1, 3, 4, 5, yoptions=False)
|
||||
|
||||
self.entry_serverpasswd.grab_focus()
|
||||
self.dialog.vbox.pack_start(self.dialog_vbox)
|
||||
|
||||
def run(self):
|
||||
self.dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
self.dialog.show_all()
|
||||
|
||||
self.entry_server_connection.set_text(
|
||||
'%(login.server)s:%(login.port)s' % CONFIG)
|
||||
self.refreshlist(CONFIG['login.server'], CONFIG['login.port'])
|
||||
|
||||
self.button_server_change.connect_after('clicked',
|
||||
self.refreshlist_ask)
|
||||
|
||||
while True:
|
||||
database = False
|
||||
url = False
|
||||
passwd = False
|
||||
res = self.dialog.run()
|
||||
if res == gtk.RESPONSE_OK:
|
||||
if self.combo_database.get_visible():
|
||||
database = self.combo_database.get_active_text()
|
||||
elif self.combo_database_entry.get_visible():
|
||||
database = self.combo_database_entry.get_text()
|
||||
else:
|
||||
continue
|
||||
url = self.entry_server_connection.get_text()
|
||||
passwd = self.entry_serverpasswd.get_text()
|
||||
break
|
||||
if res != gtk.RESPONSE_OK:
|
||||
self.dialog.destroy()
|
||||
rpc.logout()
|
||||
break
|
||||
self.parent.present()
|
||||
self.dialog.destroy()
|
||||
|
||||
return (url, database, passwd)
|
||||
@@ -6,12 +6,12 @@ import gtk
|
||||
import gobject
|
||||
import os
|
||||
import gettext
|
||||
import threading
|
||||
|
||||
from tryton import __version__
|
||||
import tryton.common as common
|
||||
from tryton.config import CONFIG, TRYTON_ICON, PIXMAPS_DIR, get_config_dir
|
||||
import tryton.rpc as rpc
|
||||
from tryton.gui.window.dbcreate import DBCreate
|
||||
from tryton.exceptions import TrytonError
|
||||
|
||||
_ = gettext.gettext
|
||||
@@ -95,18 +95,14 @@ class DBListEditor(object):
|
||||
self.database_combo.add_attribute(cell, 'text', 0)
|
||||
self.database_combo.set_model(dbstore)
|
||||
self.database_combo.connect('changed', self.dbcombo_changed)
|
||||
self.database_button = gtk.Button(_(u'Create'))
|
||||
self.database_button.connect('clicked', self.db_create)
|
||||
self.database_progressbar = gtk.ProgressBar()
|
||||
self.database_progressbar.set_text(_(u'Fetching databases list'))
|
||||
image = gtk.Image()
|
||||
image.set_from_stock('tryton-new', gtk.ICON_SIZE_BUTTON)
|
||||
self.database_button.set_image(image)
|
||||
db_box = gtk.VBox(homogeneous=True)
|
||||
db_box.pack_start(self.database_entry)
|
||||
db_box.pack_start(self.database_combo)
|
||||
db_box.pack_start(self.database_label)
|
||||
db_box.pack_start(self.database_button)
|
||||
db_box.pack_start(self.database_progressbar)
|
||||
# Compute size_request of box in order to prevent "form jumping"
|
||||
width, height = 0, 0
|
||||
@@ -177,7 +173,6 @@ class DBListEditor(object):
|
||||
self.database_entry.hide()
|
||||
self.database_combo.hide()
|
||||
self.database_label.hide()
|
||||
self.database_button.hide()
|
||||
self.database_progressbar.hide()
|
||||
|
||||
def profile_create(self, button):
|
||||
@@ -219,7 +214,7 @@ class DBListEditor(object):
|
||||
if field == 'database':
|
||||
self.current_database = entry_value
|
||||
|
||||
self.display_dbwidget(None, None, self.current_database)
|
||||
self.display_dbwidget(None, None)
|
||||
|
||||
def edit_started(self, renderer, editable, path):
|
||||
if isinstance(editable, gtk.Entry):
|
||||
@@ -266,7 +261,74 @@ class DBListEditor(object):
|
||||
for option in ('host', 'database'))
|
||||
model[selection][1] = active
|
||||
|
||||
def display_dbwidget(self, entry, event, dbname=None):
|
||||
@classmethod
|
||||
def test_server_version(cls, host, port):
|
||||
'''
|
||||
Tests if the server version is compatible with the client version
|
||||
'''
|
||||
version = rpc.server_version(host, port)
|
||||
if not version:
|
||||
return False
|
||||
return version.split('.')[:2] == __version__.split('.')[:2]
|
||||
|
||||
def refresh_databases(self, host, port):
|
||||
self.dbs_updated = threading.Event()
|
||||
threading.Thread(target=self.refresh_databases_start,
|
||||
args=(host, port)).start()
|
||||
gobject.timeout_add(100, self.refresh_databases_end, host, port)
|
||||
|
||||
def refresh_databases_start(self, host, port):
|
||||
dbs = None
|
||||
try:
|
||||
dbs = rpc.db_list(host, port)
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
self.dbs = dbs
|
||||
self.dbs_updated.set()
|
||||
|
||||
def refresh_databases_end(self, host, port):
|
||||
if not self.dbs_updated.isSet():
|
||||
self.database_progressbar.show()
|
||||
self.database_progressbar.pulse()
|
||||
return True
|
||||
self.database_progressbar.hide()
|
||||
dbs = self.dbs
|
||||
|
||||
label = None
|
||||
if not self.test_server_version(host, port):
|
||||
label = _(u'Incompatible version of the server')
|
||||
elif dbs is None:
|
||||
label = _(u'Could not connect to the server')
|
||||
if label:
|
||||
self.database_label.set_label('<b>%s</b>' % label)
|
||||
self.database_label.show()
|
||||
else:
|
||||
liststore = self.database_combo.get_model()
|
||||
liststore.clear()
|
||||
index = -1
|
||||
for db_num, db_name in enumerate(dbs):
|
||||
liststore.append([db_name])
|
||||
if self.current_database and db_name == self.current_database:
|
||||
index = db_num
|
||||
if index == -1:
|
||||
index = 0
|
||||
self.database_combo.set_active(index)
|
||||
dbs = len(dbs)
|
||||
self.database_entry.set_text(self.current_database
|
||||
if self.current_database else '')
|
||||
self.database_combo.show()
|
||||
self.db_cache = (host, port, self.current_profile['name'])
|
||||
|
||||
self.add_button.set_sensitive(True)
|
||||
self.remove_button.set_sensitive(True)
|
||||
self.ok_button.set_sensitive(True)
|
||||
self.cell.set_property('editable', True)
|
||||
self.host_entry.set_sensitive(True)
|
||||
self.updating_db = False
|
||||
return False
|
||||
|
||||
def display_dbwidget(self, entry, event):
|
||||
netloc = self.host_entry.get_text()
|
||||
host = common.get_hostname(netloc)
|
||||
if not host:
|
||||
@@ -276,10 +338,7 @@ class DBListEditor(object):
|
||||
return
|
||||
if self.updating_db:
|
||||
return
|
||||
if dbname is None:
|
||||
dbname = self.current_database
|
||||
|
||||
dbprogress = common.DBProgress(host, port)
|
||||
self.hide_database_info()
|
||||
self.add_button.set_sensitive(False)
|
||||
self.remove_button.set_sensitive(False)
|
||||
@@ -287,46 +346,7 @@ class DBListEditor(object):
|
||||
self.cell.set_property('editable', False)
|
||||
self.host_entry.set_sensitive(False)
|
||||
self.updating_db = True
|
||||
|
||||
def callback(dbs):
|
||||
self.updating_db = False
|
||||
self.db_cache = (host, port, self.current_profile['name'])
|
||||
|
||||
if dbs is None or dbs == -1:
|
||||
if dbs is None:
|
||||
label = _(u'Could not connect to the server')
|
||||
else:
|
||||
label = _(u'Incompatible version of the server')
|
||||
self.database_label.set_label('<b>%s</b>' % label)
|
||||
self.database_label.show()
|
||||
elif dbs == 0:
|
||||
self.database_button.show()
|
||||
elif dbs == -2:
|
||||
self.database_entry.show()
|
||||
else:
|
||||
self.database_entry.set_text(dbname if dbname else '')
|
||||
self.database_combo.show()
|
||||
|
||||
self.add_button.set_sensitive(True)
|
||||
self.remove_button.set_sensitive(True)
|
||||
self.ok_button.set_sensitive(True)
|
||||
self.cell.set_property('editable', True)
|
||||
self.host_entry.set_sensitive(True)
|
||||
|
||||
dbprogress.update(self.database_combo,
|
||||
self.database_progressbar, callback, dbname)
|
||||
|
||||
def db_create(self, button):
|
||||
if not self.current_profile['name']:
|
||||
return
|
||||
netloc = self.host_entry.get_text()
|
||||
host = common.get_hostname(netloc)
|
||||
port = common.get_port(netloc)
|
||||
dia = DBCreate(host, port)
|
||||
dbname = dia.run()
|
||||
self.db_cache = None
|
||||
self.username_entry.set_text('admin')
|
||||
self.display_dbwidget(None, None, dbname)
|
||||
self.refresh_databases(host, port)
|
||||
|
||||
def dbcombo_changed(self, combobox):
|
||||
dbname = combobox.get_active_text()
|
||||
@@ -583,7 +603,7 @@ class DBLogin(object):
|
||||
host = common.get_hostname(netloc)
|
||||
port = common.get_port(netloc)
|
||||
try:
|
||||
if not common.test_server_version(host, port):
|
||||
if not DBListEditor.test_server_version(host, port):
|
||||
common.warning('',
|
||||
_(u'Incompatible version of the server'))
|
||||
continue
|
||||
|
||||
@@ -1,207 +0,0 @@
|
||||
# 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 gobject
|
||||
import gettext
|
||||
import tryton.common as common
|
||||
from tryton.config import CONFIG
|
||||
import tryton.rpc as rpc
|
||||
|
||||
_ = gettext.gettext
|
||||
|
||||
|
||||
class DBRestore(object):
|
||||
def event_show_button_restore(self, widget, event, data=None):
|
||||
"""
|
||||
This event method decide by rules if the restore button will be
|
||||
sensitive or insensitive. The general rule is, all given fields
|
||||
must be filled, then the restore button is set to sensitive. This
|
||||
event method doesn't check the valid of single entrys.
|
||||
"""
|
||||
if (self.entry_server_url.get_text() != ""
|
||||
and self.entry_server_password.get_text() != ""
|
||||
and self.entry_server_url.get_text() != ""
|
||||
and self.entry_db_name.get_text() != ""):
|
||||
widget.unset_flags(gtk.HAS_DEFAULT)
|
||||
self.button_restore.set_sensitive(True)
|
||||
self.button_restore.set_flags(gtk.CAN_DEFAULT)
|
||||
self.button_restore.set_flags(gtk.HAS_DEFAULT)
|
||||
self.button_restore.set_flags(gtk.CAN_FOCUS)
|
||||
self.button_restore.set_flags(gtk.RECEIVES_DEFAULT)
|
||||
self.button_restore.grab_default()
|
||||
else:
|
||||
self.button_restore.set_sensitive(False)
|
||||
|
||||
def entry_insert_text(self, entry, new_text, new_text_length, position):
|
||||
"""
|
||||
This event method checks each text input for the PostgreSQL
|
||||
database name. It allows the following rules:
|
||||
- Allowed characters are alpha-nummeric [A-Za-z0-9] and underscore (_)
|
||||
- First character must be a letter
|
||||
"""
|
||||
if new_text.isalnum() or new_text == '_':
|
||||
_hid = entry.get_data('handlerid')
|
||||
entry.handler_block(_hid)
|
||||
_pos = entry.get_position()
|
||||
if _pos == 0 and not new_text.isalpha():
|
||||
new_text = ""
|
||||
_pos = entry.insert_text(new_text, _pos)
|
||||
entry.handler_unblock(_hid)
|
||||
|
||||
def _move_cursor():
|
||||
if not entry.props.window:
|
||||
return
|
||||
with gtk.gdk.lock:
|
||||
entry.set_position(_pos)
|
||||
return False
|
||||
gobject.idle_add(_move_cursor)
|
||||
entry.stop_emission("insert-text")
|
||||
|
||||
def __init__(self, filename=None):
|
||||
"""
|
||||
Database restore widget
|
||||
"""
|
||||
self.parent = common.get_toplevel_window()
|
||||
self.dialog = gtk.Dialog(title=_("Restore Database"),
|
||||
parent=self.parent, flags=gtk.DIALOG_MODAL
|
||||
| gtk.WIN_POS_CENTER_ON_PARENT)
|
||||
vbox = gtk.VBox()
|
||||
self.dialog.vbox.pack_start(vbox)
|
||||
self.tooltips = common.Tooltips()
|
||||
table = gtk.Table(6, 3, False)
|
||||
table.set_border_width(9)
|
||||
table.set_row_spacings(3)
|
||||
table.set_col_spacings(3)
|
||||
vbox.pack_start(table)
|
||||
self.label_server_url = gtk.Label(_("Server Connection:"))
|
||||
self.label_server_url.set_size_request(117, -1)
|
||||
self.label_server_url.set_alignment(1, 0.5)
|
||||
self.label_server_url.set_padding(3, 3)
|
||||
table.attach(self.label_server_url, 0, 1, 0, 1, yoptions=gtk.FILL)
|
||||
self.entry_server_url = gtk.Entry()
|
||||
self.entry_server_url.set_sensitive(False)
|
||||
self.entry_server_url.unset_flags(gtk.CAN_FOCUS)
|
||||
self.entry_server_url.set_editable(False)
|
||||
self.entry_server_url.set_activates_default(True)
|
||||
self.entry_server_url.set_width_chars(16)
|
||||
self.label_server_url.set_mnemonic_widget(self.entry_server_url)
|
||||
self.tooltips.set_tip(self.entry_server_url, _("This is the URL of "
|
||||
"the server. Use server 'localhost' and port '8000' if "
|
||||
"the server is installed on this computer. Click on "
|
||||
"'Change' to change the address."))
|
||||
table.attach(self.entry_server_url, 1, 2, 0, 1, yoptions=gtk.FILL)
|
||||
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)
|
||||
self.tooltips.set_tip(self.button_server_change, _("Setup the "
|
||||
"server connection..."))
|
||||
table.attach(self.button_server_change, 2, 3, 0, 1, yoptions=gtk.FILL)
|
||||
self.label_server_password = gtk.Label(_("Tryton Server Password:"))
|
||||
self.label_server_password.set_justify(gtk.JUSTIFY_RIGHT)
|
||||
self.label_server_password.set_alignment(1, 0.5)
|
||||
self.label_server_password.set_padding(3, 3)
|
||||
table.attach(self.label_server_password, 0, 1, 1, 2, yoptions=gtk.FILL)
|
||||
self.entry_server_password = gtk.Entry()
|
||||
self.entry_server_password.set_visibility(False)
|
||||
self.entry_server_password.set_activates_default(True)
|
||||
self.entry_server_password.set_width_chars(16)
|
||||
self.label_server_password.set_mnemonic_widget(
|
||||
self.entry_server_password)
|
||||
self.tooltips.set_tip(self.entry_server_password, _("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."))
|
||||
table.attach(self.entry_server_password, 1, 3, 1, 2, yoptions=gtk.FILL)
|
||||
self.hseparator = gtk.HSeparator()
|
||||
table.attach(self.hseparator, 0, 3, 2, 3, yoptions=gtk.FILL)
|
||||
label_filename = gtk.Label()
|
||||
label_filename.set_markup(_("File to Restore:"))
|
||||
label_filename.set_alignment(1, 0.5)
|
||||
table.attach(label_filename, 0, 1, 3, 4, yoptions=gtk.FILL)
|
||||
entry_filename = gtk.Label()
|
||||
entry_filename.set_markup("<tt>" + filename + "</tt>")
|
||||
table.attach(entry_filename, 1, 3, 3, 4, yoptions=gtk.FILL)
|
||||
self.entry_db_name = gtk.Entry()
|
||||
self.entry_db_name.set_visibility(True)
|
||||
self.entry_db_name.set_activates_default(True)
|
||||
self.entry_db_name.set_width_chars(16)
|
||||
self.entry_db_name.set_max_length(63)
|
||||
handlerid = self.entry_db_name.connect("insert-text",
|
||||
self.entry_insert_text)
|
||||
self.entry_db_name.set_data('handlerid', handlerid)
|
||||
self.tooltips.set_tip(self.entry_db_name, _("Choose the name of "
|
||||
"the database to be restored.\n"
|
||||
"Allowed characters are alphanumerical or _ (underscore)\n"
|
||||
"You need to avoid all accents, space or special "
|
||||
"characters! \nExample: tryton"))
|
||||
table.attach(self.entry_db_name, 1, 3, 4, 5, yoptions=gtk.FILL)
|
||||
label_db_name = gtk.Label(_("New Database Name:"))
|
||||
label_db_name.set_alignment(1, 0.5)
|
||||
label_db_name.set_mnemonic_widget(self.entry_db_name)
|
||||
table.attach(label_db_name, 0, 1, 4, 5, yoptions=gtk.FILL)
|
||||
label_db_update = gtk.Label(_('Update Database:'))
|
||||
label_db_update.set_alignment(1, 0.5)
|
||||
table.attach(label_db_update, 0, 1, 5, 6, yoptions=gtk.FILL)
|
||||
self.check_update = gtk.CheckButton()
|
||||
label_db_update.set_mnemonic_widget(self.check_update)
|
||||
self.tooltips.set_tip(self.check_update, _('Check for an automatic '
|
||||
'database update after restoring a database from a previous '
|
||||
'Tryton version.'))
|
||||
self.check_update.set_active(True)
|
||||
table.attach(self.check_update, 1, 3, 5, 6, yoptions=gtk.FILL)
|
||||
# Buttons and events
|
||||
self.dialog.connect("key-press-event",
|
||||
self.event_show_button_restore)
|
||||
self.dialog.add_button("gtk-cancel",
|
||||
gtk.RESPONSE_CANCEL)
|
||||
self.button_restore = gtk.Button(_('Restore'))
|
||||
self.button_restore.set_flags(gtk.CAN_DEFAULT)
|
||||
self.button_restore.set_flags(gtk.HAS_DEFAULT)
|
||||
self.button_restore.set_sensitive(False)
|
||||
img_restore = gtk.Image()
|
||||
img_restore.set_from_stock('tryton-folder-saved-search',
|
||||
gtk.ICON_SIZE_BUTTON)
|
||||
self.button_restore.set_image(img_restore)
|
||||
self.tooltips.set_tip(self.button_restore,
|
||||
_('Restore the database from file.'))
|
||||
self.dialog.add_action_widget(self.button_restore, gtk.RESPONSE_OK)
|
||||
self.dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
|
||||
self.entry_server_password.grab_focus()
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Database Restore widget run part
|
||||
"""
|
||||
self.dialog.show_all()
|
||||
|
||||
self.entry_server_url.set_text('%(login.server)s:%(login.port)s' %
|
||||
CONFIG)
|
||||
while True:
|
||||
database = False
|
||||
passwd = False
|
||||
url = False
|
||||
update = False
|
||||
# TODO: This needs to be unified with the other widgets
|
||||
self.button_server_change.connect_after('clicked',
|
||||
lambda a, b: common.request_server(b),
|
||||
self.entry_server_url)
|
||||
res = self.dialog.run()
|
||||
if res == gtk.RESPONSE_OK:
|
||||
database = self.entry_db_name.get_text()
|
||||
url = self.entry_server_url.get_text()
|
||||
passwd = self.entry_server_password.get_text()
|
||||
update = self.check_update.get_active()
|
||||
break
|
||||
else:
|
||||
self.dialog.destroy()
|
||||
rpc.logout()
|
||||
break
|
||||
self.parent.present()
|
||||
self.dialog.destroy()
|
||||
|
||||
return url, database, passwd, update
|
||||
+2
-10
@@ -42,21 +42,13 @@ def db_list(host, port):
|
||||
return result
|
||||
except Fault, exception:
|
||||
if exception.faultCode == 'AccessDenied':
|
||||
logging.getLogger(__name__).debug(-2)
|
||||
return -2
|
||||
logging.getLogger(__name__).debug('AccessDenied')
|
||||
return None
|
||||
else:
|
||||
logging.getLogger(__name__).debug(repr(None))
|
||||
return None
|
||||
|
||||
|
||||
def db_exec(host, port, method, database='', *args):
|
||||
connection = ServerProxy(host, port, database=database)
|
||||
logging.getLogger(__name__).info('common.db.%s(%s)' % (method, args))
|
||||
result = getattr(connection.common.db, method)(*args)
|
||||
logging.getLogger(__name__).debug(repr(result))
|
||||
return result
|
||||
|
||||
|
||||
def server_version(host, port):
|
||||
try:
|
||||
connection = ServerProxy(host, port)
|
||||
|
||||
Reference in New Issue
Block a user