#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import os import gettext import logging from collections import OrderedDict from pathlib import Path from PyQt5.QtWidgets import (QDialogButtonBox, QPushButton, QLineEdit, QHBoxLayout, QDialog, QFrame, QLabel, QVBoxLayout, QStyle,) from PyQt5.QtGui import QPixmap, QFont from PyQt5.QtCore import Qt from app.commons import connection from app.commons import common from app.commons.config import Params from app.commons.dialogs import QuickDialog from app.commons.forms import GridForm from ..version import __version__ # from app.css.flat_button_small import * _ = gettext.gettext __all__ = ['Login', 'xconnection'] pkg_dir = str(Path(os.path.dirname(__file__)).parents[0]) path_logo = os.path.join(pkg_dir, 'share', 'login.png') file_base_css = os.path.join(pkg_dir, 'css', 'base.css') file_tablet_css = os.path.join(pkg_dir, 'css', 'tablet.css') class Login(QDialog): def __init__(self, parent=None, file_config=''): super(Login, self).__init__(parent) logging.info(' Start login Neox system X...') self.connection = None self.mode_conn = 'online' params = Params(file_config) self.params = params.params self.setObjectName('dialog_login') if self.params.get('tablet_mode') == 'True': self.tablet_mode = eval(self.params['tablet_mode']) self.set_style([file_tablet_css]) else: if self.params.get('theme'): file_theme_css = os.path.join( pkg_dir, 'css', self.params['theme'] + '.css') self.set_style([file_theme_css]) else: self.set_style([file_base_css]) self.tablet_mode = None self.init_UI() def set_style(self, style_files): styles = [] for style in style_files: with open(style, 'r') as infile: styles.append(infile.read()) self.setStyleSheet(''.join(styles)) def init_UI(self): hbox_logo = QHBoxLayout() label_logo = QLabel() label_logo.setObjectName('label_logo') hbox_logo.addWidget(label_logo, 0) pixmap_logo = QPixmap(path_logo) label_logo.setPixmap(pixmap_logo) hbox_logo.setAlignment(label_logo, Qt.AlignHCenter) values = OrderedDict([ ('host', {'name': 'SERVIDOR', 'readonly': True}), ('database', {'name': 'BASE DE DATOS', 'readonly': True}), ('user', {'name': 'USUARIO'}), ('password', {'name': 'CONTRASEÑA'}), ]) formLayout = GridForm(self, values=values, col=1) self.field_password.setEchoMode(QLineEdit.Password) self.field_password.textChanged.connect(self.clear_message) box_buttons = QDialogButtonBox() if self.params.get('option_offline') == 'True': pushButtonOffline = QPushButton("ONLINE") pushButtonOffline.setObjectName('button_offline') pushButtonOffline.setIcon( self.style().standardIcon(getattr(QStyle, 'SP_DriveNetIcon'))) box_buttons.addButton( pushButtonOffline, QDialogButtonBox.ActionRole) pushButtonCancel = QPushButton("C&ANCELAR") pushButtonCancel.setObjectName('button_cancel') box_buttons.addButton(pushButtonCancel, QDialogButtonBox.RejectRole) pushButtonOk = QPushButton("&CONNECTAR") pushButtonOk.setAutoDefault(True) pushButtonOk.setDefault(False) pushButtonOk.setObjectName('button_ok') box_buttons.addButton(pushButtonOk, QDialogButtonBox.AcceptRole) hbox_buttons = QHBoxLayout() hbox_buttons.addWidget(box_buttons) line = QFrame() line.setFrameShape(line.HLine) line.setFrameShadow(line.Sunken) hbox_line = QHBoxLayout() hbox_line.addWidget(line) hbox_msg = QHBoxLayout() self.error_msg = QLabel('Error: usuario o contraseña invalida...!') self.error_msg.setObjectName('login_msg_error') self.error_msg.setAlignment(Qt.AlignCenter) hbox_msg.addWidget(self.error_msg) hbox_version = QHBoxLayout() label_version = QLabel('VERSION: ' + __version__) label_version.setMargin(20) font_version = QFont('Times') label_version.setFont(font_version) hbox_version.addWidget(label_version) hbox_version.setAlignment(Qt.AlignCenter) vbox_layout = QVBoxLayout() vbox_layout.addLayout(hbox_logo) vbox_layout.addLayout(formLayout) vbox_layout.addLayout(hbox_msg) vbox_layout.addLayout(hbox_line) vbox_layout.addLayout(hbox_buttons) vbox_layout.addLayout(hbox_version) self.setLayout(vbox_layout) self.setWindowTitle('Login Presik System') self.clear_message() self.field_password.setFocus() box_buttons.accepted.connect(self.accept) box_buttons.rejected.connect(self.reject) box_buttons.clicked.connect(self.clicked) def clear_message(self): self.error_msg.hide() def run(self, profile=None): self.api_url = self.params['api_url'] if self.params['database']: self.field_database.setText(self.params['database']) if self.params['user']: self.field_user.setText(self.params['user']) if self.params['server']: self.field_host.setText(self.params['server']) if self.mode_conn == 'offline': self.api_url = self.params['api_url_offline'] if self.params['database_offline']: self.field_database.setText(self.params['database_offline']) if self.params['user']: self.field_user.setText(self.params['user']) if self.params['server']: self.field_host.setText(self.params['server_offline']) def accept(self): self.validate_access() super(Login, self).accept() def clicked(self, event): state = event.text() if state == 'ONLINE': event.setText('OFFLINE') event.setStyleSheet("background-color: rgb(255, 115, 0);") self.mode_conn = 'offline' self.error_msg.setText('Modo de facturacion offline activado...!') self.error_message() self.run() elif state == 'OFFLINE': event.setText('ONLINE') event.setStyleSheet("background-color: rgb(170, 175, 183);") self.mode_conn = 'online' self.clear_message() self.run() def reject(self): sys.exit() def validate_access(self): user = self.field_user.text() password = self.field_password.text() server = self.field_host.text() database = self.field_database.text() self.connection = xconnection(self.params['mode'], user, password, server, self.params['port'], database, self.params['protocol'] ) if not self.connection: self.field_password.setText('') self.field_password.setFocus() self.run() self.error_msg.setText('Error: usuario o contraseña invalida...!') self.error_message() self.params['user'] = user self.params['password'] = password def error_message(self): self.error_msg.show() def xconnection(mode, user, password, host, port, database, protocol): # Get user_id and session try: url = '%s://%s:%s@%s:%s/%s/' % ( mode, user, password, host, port, database) try: if not common.test_server_version(host, int(port)): print(u'Incompatible version of the server') return except: pass if protocol == 'json': conn = connection.set_jsonrpc(url[:-1]) elif protocol == 'local': conn = connection.set_trytond( database=database, user=user, ) elif protocol == 'xml': conn = connection.set_xmlrpc(url) else: print("Protocol error...!") return None return conn except Exception as e: print('LOG: Data connection invalid!', e) return None def safe_reconnect(main): field_password = QLineEdit() field_password.setEchoMode(QLineEdit.Password) field_password.cursorPosition() field_password.cursor() dialog_password = QuickDialog(main, 'question', info=main.tr('Enter your password:'), widgets=[field_password], buttons=['ok'], response=True ) field_password.setFocus() password = field_password.text() if not password or password == '': safe_reconnect(main) main.conn = xconnection( main.user, str(password), main.server, main.port, main.database, main.protocol, ) if main.conn: field_password.setText('') dialog_password.hide() main.global_timer = 0 else: safe_reconnect(main)