def end(self, combo, progressbar, callback, dbname): if not self.updated.isSet(): progressbar.show() progressbar.pulse() return True progressbar.hide() dbs, createdb = self.db_info if dbs is None: dbs, createdb = None, False elif dbs == -1: dbs, createdb = -1, False else: from tryton.gui.main import Main Main.get_main().refresh_ssl() 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, createdb) return False
def _read(self): to_remove = set() while self.running: for filename in os.listdir(self.tmpdir): path = os.path.join(self.tmpdir, filename) if not os.path.isfile(path): continue if path in to_remove: continue try: data = open(path, 'r').readline() except IOError: pass if data and data[-1] != '\n': continue to_remove.add(path) if data: from tryton.gui.main import Main Main.get_main().open_url(data[:-1]) if not os.path.exists(self.config): self.setup() for path in to_remove.copy(): try: os.remove(path) except OSError: continue to_remove.remove(path) time.sleep(1)
def register(self): from tryton.gui.main import Main main = Main.get_main() self.page = main.get_page() if not self.page: self.page = main self.page.dialogs.append(self) self.sensible_widget.props.sensitive = False
def get_sensible_widget(window): from tryton.gui.main import Main main = Main.get_main() if main and window == main.window: focus_widget = window.get_focus() page = main.get_page() if page and focus_widget and focus_widget.is_ancestor(page.widget): return page.widget return window
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 [] 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 _read(self): fifo = os.fdopen(os.open(self.filename, os.O_RDONLY | os.O_NONBLOCK)) data = '' while self.running: try: rlist, _, _ = select.select([fifo], [], [], 1) except select.error: continue if rlist: try: data += fifo.readline() except IOError: pass if data and data[-1] != '\n': continue if data: from tryton.gui.main import Main Main.get_main().open_url(data.strip()) data = '' if not os.path.lexists(self.config): os.symlink(self.filename, self.config)
def process_exception(exception, *args, **kwargs): rpc_execute = kwargs.get('rpc_execute', rpc.execute) if isinstance(exception, TrytonError): if exception.faultCode == 'BadFingerprint': warning( _('The server fingerprint has changed since last connection!\n' 'The application will stop connecting to this server ' 'until its fingerprint is fixed.'), _('Security risk!')) from tryton.gui.main import Main Main.sig_quit() sys.exit() elif exception.faultCode == 'NotLogged': if rpc.CONNECTION is None: message(_('Connection error!\n' 'Unable to connect to the server!')) return False elif isinstance(exception, TrytonServerError): if exception.faultCode == 'UserWarning': name, msg, description = exception.args res = userwarning(description, msg) if res in ('always', 'ok'): args2, = ('model', 'res.user.warning', 'create', [{ 'user': rpc._USER, 'name': name, 'always': (res == 'always'), }], rpc.CONTEXT) try: rpc_execute(*args2) except TrytonServerError, exception: process_exception(exception, *args2) if args: try: return rpc_execute(*args) except TrytonServerError, exception: return process_exception(exception, *args, rpc_execute=rpc_execute) return True return False
if args: try: return rpc_execute(*args) except TrytonServerError, exception: return process_exception(exception, *args, rpc_execute=rpc_execute) return if not PLOCK.acquire(False): return False hostname = rpc._HOST port = rpc._PORT try: while True: password = ask(_('Password:'******'Connection error!\n' 'Unable to connect to the server!')) return False if res < 0: continue if args: try: return rpc_execute(*args) except TrytonServerError, exception: return process_exception(exception, *args,
def search_box(self, button): def key_press(window, event): if event.keyval == gtk.keysyms.Escape: button.set_active(False) window.hide() def search(): button.set_active(False) self.search_window.hide() text = '' for label, entry in self.search_table.fields: if isinstance(entry, gtk.ComboBox): value = entry.get_active_text() else: value = entry.get_text() if value: text += label + ' ' + quote(value) + ' ' self.set_text(text) self.do_search() def date_activate(entry): entry._focus_out(entry, None) search() if not self.search_window: self.search_window = gtk.Window() self.search_window.set_transient_for(button.get_toplevel()) self.search_window.set_type_hint( gtk.gdk.WINDOW_TYPE_HINT_POPUP_MENU) self.search_window.set_destroy_with_parent(True) self.search_window.set_title('Tryton') self.search_window.set_icon(TRYTON_ICON) self.search_window.set_decorated(False) if hasattr(self.search_window, 'set_deletable'): self.search_window.set_deletable(False) self.search_window.connect('key-press-event', key_press) vbox = gtk.VBox() fields = [f for f in self.screen.domain_parser.fields.itervalues() if f.get('searchable', True)] fields.sort(key=operator.itemgetter('string')) self.search_table = gtk.Table(rows=len(fields), columns=2) self.search_table.set_border_width(5) self.search_table.set_row_spacings(2) self.search_table.set_col_spacings(2) # Fill table with fields self.search_table.fields = [] for i, field in enumerate(fields): label = gtk.Label(field['string']) label.set_alignment(0.0, 0.5) self.search_table.attach(label, 0, 1, i, i + 1) if field['type'] in ('boolean', 'selection'): if hasattr(gtk, 'ComboBoxText'): entry = gtk.ComboBoxText() else: entry = gtk.combo_box_new_text() entry.append_text('') if field['type'] == 'boolean': selections = (_('True'), _('False')) else: selections = tuple(x[1] for x in field['selection']) for selection in selections: entry.append_text(selection) widget = entry elif field['type'] in ('date', 'datetime', 'time'): if field['type'] == 'date': format_ = date_format() elif field['type'] == 'datetime': format_ = date_format() + ' ' + common.HM_FORMAT elif field['type'] == 'time': format_ = common.HM_FORMAT widget = common.date_widget.ComplexEntry(format_, spacing=0) entry = widget.widget entry.connect('activate', date_activate) else: entry = gtk.Entry() widget = entry entry.connect('activate', lambda *a: search()) self.search_table.attach(widget, 1, 2, i, i + 1) self.search_table.fields.append((field['string'] + ':', entry)) scrolled = gtk.ScrolledWindow() scrolled.add_with_viewport(self.search_table) scrolled.set_shadow_type(gtk.SHADOW_NONE) vbox.pack_start(scrolled, expand=True, fill=True) find_button = gtk.Button(_('Find')) find_button.connect('clicked', lambda *a: search()) find_img = gtk.Image() find_img.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) find_button.set_image(find_img) hbuttonbox = gtk.HButtonBox() hbuttonbox.set_spacing(5) hbuttonbox.pack_start(find_button) hbuttonbox.set_layout(gtk.BUTTONBOX_END) vbox.pack_start(hbuttonbox, expand=False, fill=True) self.search_window.add(vbox) vbox.show_all() # Disable scrolling: scrolled.set_policy(gtk.POLICY_NEVER, gtk.POLICY_NEVER) # See what changed: new_size = self.search_window.size_request() # Reenable scrolling: scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.search_window.set_default_size(*new_size) parent = button.get_toplevel() button_x, button_y = button.translate_coordinates(parent, *parent.window.get_origin()) button_allocation = button.get_allocation() # Resize the window to not be out of the screen width, height = self.search_window.get_default_size() screen = self.search_window.get_screen() screen_width = screen.get_width() screen_height = screen.get_height() delta_width = screen_width - (button_x + width) delta_height = screen_height - (button_y + button_allocation.height + height) if delta_width < 0: width += delta_width if delta_height < 0: height += delta_height self.search_window.resize(width, height) # Move the window under the button self.search_window.move(button_x, button_y + button_allocation.height) from tryton.gui.main import Main page = Main.get_main().get_page() if button.get_active(): if self.search_window not in page.dialogs: page.dialogs.append(self.search_window) self.search_window.show() else: self.search_window.hide() if self.search_window in page.dialogs: page.dialogs.remove(self.search_window)
def get_toplevel_window(): for window in gtk.window_list_toplevels(): if window.is_active(): return window from tryton.gui.main import Main return Main.get_main().window
def search_box(self, button): def key_press(window, event): if event.keyval == gtk.keysyms.Escape: button.set_active(False) window.hide() def search(): button.set_active(False) self.search_window.hide() text = '' for label, entry in self.search_table.fields: if isinstance(entry, gtk.ComboBox): value = quote(entry.get_active_text()) or None elif isinstance(entry, (Dates, Selection)): value = entry.get_value() else: value = quote(entry.get_text()) or None if value is not None: text += quote(label) + ': ' + value + ' ' self.set_text(text) self.do_search() # Store text after doing the search # because domain parser could simplify the text self.last_search_text = self.get_text() if not self.search_window: self.search_window = gtk.Window() self.search_window.set_transient_for(button.get_toplevel()) self.search_window.set_type_hint( gtk.gdk.WINDOW_TYPE_HINT_POPUP_MENU) self.search_window.set_destroy_with_parent(True) self.search_window.set_title('coog') self.search_window.set_icon(TRYTON_ICON) self.search_window.set_decorated(False) # set_deletable is False on tryton master repo # But this is not working on each graphical environnement # Further more, setting theses windows deletable does not seems # to bring any trouble. self.search_window.set_deletable(True) self.search_window.connect('delete-event', lambda *a: True) self.search_window.connect('key-press-event', key_press) vbox = gtk.VBox() fields = [f for f in self.screen.domain_parser.fields.itervalues() if f.get('searchable', True)] self.search_table = gtk.Table(rows=len(fields), columns=2) self.search_table.set_homogeneous(False) self.search_table.set_border_width(5) self.search_table.set_row_spacings(2) self.search_table.set_col_spacings(2) # Fill table with fields self.search_table.fields = [] for i, field in enumerate(fields): label = gtk.Label(field['string']) label.set_alignment(0.0, 0.0) self.search_table.attach(label, 0, 1, i, i + 1, yoptions=gtk.FILL) yoptions = False if field['type'] == 'boolean': if hasattr(gtk, 'ComboBoxText'): entry = gtk.ComboBoxText() else: entry = gtk.combo_box_new_text() entry.append_text('') selections = (_('True'), _('False')) for selection in selections: entry.append_text(selection) elif field['type'] == 'selection': selections = tuple(x[1] for x in field['selection']) entry = Selection(selections) yoptions = gtk.FILL | gtk.EXPAND elif field['type'] in ('date', 'datetime', 'time'): date_format = self.screen.context.get('date_format', '%x') if field['type'] == 'date': entry = Dates(date_format) elif field['type'] in ('datetime', 'time'): time_format = PYSONDecoder({}).decode(field['format']) if field['type'] == 'time': entry = Times(time_format) elif field['type'] == 'datetime': entry = DateTimes(date_format, time_format) entry.connect_activate(lambda *a: search()) else: entry = gtk.Entry() entry.connect('activate', lambda *a: search()) label.set_mnemonic_widget(entry) self.search_table.attach(entry, 1, 2, i, i + 1, yoptions=yoptions) self.search_table.fields.append((field['string'], entry)) scrolled = gtk.ScrolledWindow() scrolled.add_with_viewport(self.search_table) scrolled.set_shadow_type(gtk.SHADOW_NONE) scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) vbox.pack_start(scrolled, expand=True, fill=True) find_button = gtk.Button(_('Find')) find_button.connect('clicked', lambda *a: search()) find_img = gtk.Image() find_img.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) find_button.set_image(find_img) hbuttonbox = gtk.HButtonBox() hbuttonbox.set_spacing(5) hbuttonbox.pack_start(find_button) hbuttonbox.set_layout(gtk.BUTTONBOX_END) vbox.pack_start(hbuttonbox, expand=False, fill=True) self.search_window.add(vbox) vbox.show_all() new_size = map(sum, zip(self.search_table.size_request(), scrolled.size_request())) self.search_window.set_default_size(*new_size) parent = button.get_toplevel() button_x, button_y = button.translate_coordinates(parent, 0, 0) button_allocation = button.get_allocation() # Resize the window to not be out of the parent width, height = self.search_window.get_default_size() allocation = parent.get_allocation() delta_width = allocation.width - (button_x + width) delta_height = allocation.height - (button_y + button_allocation.height + height) if delta_width < 0: width += delta_width if delta_height < 0: height += delta_height self.search_window.resize(width, height) # Move the window under the button x, y = button.window.get_origin() self.search_window.move( x + button_allocation.x, y + button_allocation.y + button_allocation.height) from tryton.gui.main import Main page = Main.get_main().get_page() if button.get_active(): if page and self.search_window not in page.dialogs: page.dialogs.append(self.search_window) self.search_window.show() if self.last_search_text.strip() != self.get_text().strip(): for label, entry in self.search_table.fields: if isinstance(entry, gtk.ComboBox): entry.set_active(-1) elif isinstance(entry, Dates): entry.set_values(None, None) elif isinstance(entry, Selection): entry.treeview.get_selection().unselect_all() else: entry.set_text('') if self.search_table.fields: self.search_table.fields[0][1].grab_focus() else: self.search_window.hide() if page and self.search_window in page.dialogs: page.dialogs.remove(self.search_window)
def get_toplevel_window(): for window in gtk.window_list_toplevels(): if window.is_active() and window.props.type == gtk.WINDOW_TOPLEVEL: return window from tryton.gui.main import Main return Main.get_main().window
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: res = self.dialog.run() dbname = self.entry_dbname.get_text() url = self.entry_server_connection.get_text() url_m = re.match('^([\w.\-]+):(\d{1,5})', \ url or '') 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 (not dbname) \ or (not re.match('^[a-zA-Z0-9_]+$', dbname)): common.warning(_('The database name is restricted to ' \ 'alpha-nummerical characters and "_" (underscore). ' \ 'Avoid all accents, space ' \ 'and any other special characters.'), _('Wrong characters in database name!')) continue elif 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 elif not admin_passwd.get_text(): common.warning(_("Admin password and confirmation are " \ "required to create a new database."), \ _('Missing admin password!')) continue elif url_m.group(1) \ and int(url_m.group(2)) \ and dbname \ and langreal \ and passwd \ and admin_passwd.get_text(): try: exist = rpc.db_exec(url_m.group(1), int(url_m.group(2)), '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 host = url_m.group(1) port = url_m.group(2) try: rpcprogress = common.RPCProgress('db_exec', (host, int(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() from tryton.gui.main import Main Main.get_main().refresh_ssl() break from tryton.gui.main import Main Main.get_main().refresh_ssl() parent.present() self.dialog.destroy() if self.sig_login: CONFIG['login.server'] = host CONFIG['login.port'] = port CONFIG['login.db'] = dbname CONFIG['login.login'] = '******' self.sig_login() break
def search_box(self, button): def key_press(window, event): if event.keyval == gtk.keysyms.Escape: button.set_active(False) window.hide() def search(): button.set_active(False) self.search_window.hide() text = '' for label, entry in self.search_table.fields: if isinstance(entry, gtk.ComboBox): value = quote(entry.get_active_text()) or None elif isinstance(entry, (Dates, Selection)): value = entry.get_value() else: value = quote(entry.get_text()) or None if value is not None: text += quote(label) + ': ' + value + ' ' self.set_text(text) self.do_search() # Store text after doing the search # because domain parser could simplify the text self.last_search_text = self.get_text() if not self.search_window: self.search_window = gtk.Window() self.search_window.set_transient_for(button.get_toplevel()) self.search_window.set_type_hint( gtk.gdk.WINDOW_TYPE_HINT_POPUP_MENU) self.search_window.set_destroy_with_parent(True) self.search_window.set_title('Tryton') self.search_window.set_icon(TRYTON_ICON) self.search_window.set_decorated(False) self.search_window.set_deletable(False) self.search_window.connect('delete-event', lambda *a: True) self.search_window.connect('key-press-event', key_press) vbox = gtk.VBox() fields = [ f for f in self.screen.domain_parser.fields.itervalues() if f.get('searchable', True) ] self.search_table = gtk.Table(rows=len(fields), columns=2) self.search_table.set_homogeneous(False) self.search_table.set_border_width(5) self.search_table.set_row_spacings(2) self.search_table.set_col_spacings(2) # Fill table with fields self.search_table.fields = [] for i, field in enumerate(fields): label = gtk.Label(field['string']) label.set_alignment(0.0, 0.0) self.search_table.attach(label, 0, 1, i, i + 1, yoptions=gtk.FILL) yoptions = False if field['type'] == 'boolean': if hasattr(gtk, 'ComboBoxText'): entry = gtk.ComboBoxText() else: entry = gtk.combo_box_new_text() entry.append_text('') selections = (_('True'), _('False')) for selection in selections: entry.append_text(selection) elif field['type'] == 'selection': selections = tuple(x[1] for x in field['selection']) entry = Selection(selections) yoptions = gtk.FILL | gtk.EXPAND elif field['type'] in ('date', 'datetime', 'time'): date_format = self.screen.context.get('date_format', '%x') if field['type'] == 'date': entry = Dates(date_format) elif field['type'] in ('datetime', 'time'): time_format = PYSONDecoder({}).decode(field['format']) if field['type'] == 'time': entry = Times(time_format) elif field['type'] == 'datetime': entry = DateTimes(date_format, time_format) entry.connect_activate(lambda *a: search()) else: entry = gtk.Entry() entry.connect('activate', lambda *a: search()) label.set_mnemonic_widget(entry) self.search_table.attach(entry, 1, 2, i, i + 1, yoptions=yoptions) self.search_table.fields.append((field['string'], entry)) scrolled = gtk.ScrolledWindow() scrolled.add_with_viewport(self.search_table) scrolled.set_shadow_type(gtk.SHADOW_NONE) scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) vbox.pack_start(scrolled, expand=True, fill=True) find_button = gtk.Button(_('Find')) find_button.connect('clicked', lambda *a: search()) find_img = gtk.Image() find_img.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) find_button.set_image(find_img) hbuttonbox = gtk.HButtonBox() hbuttonbox.set_spacing(5) hbuttonbox.pack_start(find_button) hbuttonbox.set_layout(gtk.BUTTONBOX_END) vbox.pack_start(hbuttonbox, expand=False, fill=True) self.search_window.add(vbox) vbox.show_all() new_size = map( sum, zip(self.search_table.size_request(), scrolled.size_request())) self.search_window.set_default_size(*new_size) parent = button.get_toplevel() button_x, button_y = button.translate_coordinates(parent, 0, 0) button_allocation = button.get_allocation() # Resize the window to not be out of the parent width, height = self.search_window.get_default_size() allocation = parent.get_allocation() delta_width = allocation.width - (button_x + width) delta_height = allocation.height - (button_y + button_allocation.height + height) if delta_width < 0: width += delta_width if delta_height < 0: height += delta_height self.search_window.resize(width, height) # Move the window under the button x, y = button.window.get_origin() self.search_window.move( x + button_allocation.x, y + button_allocation.y + button_allocation.height) from tryton.gui.main import Main page = Main.get_main().get_page() if button.get_active(): if page and self.search_window not in page.dialogs: page.dialogs.append(self.search_window) self.search_window.show() if self.last_search_text.strip() != self.get_text().strip(): for label, entry in self.search_table.fields: if isinstance(entry, gtk.ComboBox): entry.set_active(-1) elif isinstance(entry, Dates): entry.set_values(None, None) elif isinstance(entry, Selection): entry.treeview.get_selection().unselect_all() else: entry.set_text('') if self.search_table.fields: self.search_table.fields[0][1].grab_focus() else: self.search_window.hide() if page and self.search_window in page.dialogs: page.dialogs.remove(self.search_window)
def get_toplevel_window(): from tryton.gui.main import Main return Main().get_active_window()
def request_set(self): if self.model_name == 'res.request': from tryton.gui.main import Main Main.get_main().request_set()
else: message(_('Concurrency Exception'), msg_type=gtk.MESSAGE_ERROR) elif (exception.faultCode.startswith('403') or exception.faultCode.startswith('401')): from tryton.gui.main import Main if not PLOCK.acquire(False): return language = CONFIG['client.lang'] func = lambda parameters: rpc.login( rpc._HOST, rpc._PORT, rpc._DATABASE, rpc._USERNAME, parameters, language) try: Login(func) except TrytonError, exception: if exception.faultCode == 'QueryCanceled': Main.get_main().sig_quit() raise finally: PLOCK.release() if args: try: return rpc_execute(*args) except TrytonServerError, exception: return process_exception(exception, *args, rpc_execute=rpc_execute) else: error(exception.faultCode, exception.faultString) else: error(str(exception), traceback.format_exc()) raise RPCException(exception)