#-*- coding: utf-8 -*- # Copyright 2012-2016 Mir Calculate. http://www.calculate-linux.org # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import print_function from __future__ import absolute_import from .. import qt DEBUG_LEVEL = 99999 def debug(level, *args): if level <= DEBUG_LEVEL: for s in args: print(s, end=' ') print() import calculate.contrib from urllib.error import URLError from suds import MethodNotFound import re from calculate.lib.utils.colortext.converter import XmlConverter from calculate.lib.utils.colortext.output import SpanCssOutput from calculate.lib.utils.tools import imap_regexp from .utils import switch, create_obj from .more import WorkPalette, ParameterWindow, get_system_rgb from .more import get_sid, ClientServiceThread, show_msg, TaskWidget, ErrorWgt,\ ResultLayout, get_view_params, get_icon, dpivalue from .more import LabelWordWrap as Label from .SelectTable import SelectedTableWidget class LabelWordWrap(Label): def __init__(self, name, parent=None, mono=False, margin_top=0): Label.__init__(self, name, parent, mono, margin_top) # set text selectable self.setTextInteractionFlags(self.textInteractionFlags() | \ qt.Qt.TextSelectableByMouse) class PlusButton(qt.QPushButton): def __init__(self, parent, ClientObj, method, disable_method=None): super().__init__(parent) icon = get_icon('list-add') if not icon.isNull(): self.setIcon(icon) else: self.setText('+') self._parent = parent self.ClientObj = ClientObj self.method = method self.setFixedSize(30, 30) if disable_method: self.clicked.connect(disable_method) self.clicked.connect(self.call_method) def call_method(self): # Call server method if hasattr (self, 'get_Frame_thread'): if self.get_Frame_thread.isRunning(): return 1 sid = int(self.ClientObj.sid) view_params = get_view_params(self.ClientObj.client, \ self.method + '_view') self.get_Frame_thread = ClientServiceThread(self.ClientObj,\ self.method + '_view', sid, view_params) self.get_Frame_thread.signal.connect(self.after_call) self.get_Frame_thread.start() def after_call(self, view): if self.method in self.ClientObj.method_names: view_method = self._parent.ClientObj.method_names[self.method] else: view_method = self.method self._parent.ClientObj._parent.setWindowTitle(view_method + ' - ' + self.ClientObj.Name) self._parent._parent.main_frame_view(view, self.method) class MainFrameRes(qt.QWidget): valSignal = qt.Signal() def __init__(self, parent, ClientObj, method_name, meth_result, change_offset=False): super().__init__(parent) self._parent = parent self.ClientObj = ClientObj self.method_name = method_name self.meth_result = meth_result self.client = ClientObj.client self.cur_pid = 0 self.change_offset = change_offset self.show_last = True self.max_val = None self.buttons = [] if self.meth_result.type == "pid": self.cur_pid = self.meth_result.message self.work_layout = ResultLayout(self) self.work_layout.kill_process_button.clicked.connect \ (self.kill_process(self.cur_pid)) self.progress_list = [] self.task_list = [] self._parent.methodname_wgt.show() self._parent.control_button.show() #DEBUG # self._parent.control_button.del_button() if self.method_name in self.ClientObj.method_names: self._parent.methodname_wgt.setMethodName \ (self.ClientObj.method_names[self.method_name]) else: self._parent.methodname_wgt.setMethodName(method_name) parent.main_frame.viewport().setObjectName('main_frame') #parent.main_frame.viewport().setStyleSheet("#main_frame " # "{background-color: #FFFFFF;}") # #"{background-color: #E4E1E0;}") #self.setObjectName("Frame_Res") #self.setStyleSheet("#Frame_Res {background-color: %s;}"% get_system_rgb(self, ParameterWindow)) #self.setStyleSheet("#Frame_Res {background-color: green;}") # "QWidget {border: 1px solid red;}") self.timer = qt.QTimer(self) self.timer.timeout.connect(self.show_bottom) self.timer.start(100) self.valSignal.connect(self.show_bottom) def initUI(self): #self.setSizePolicy(qt.QSizePolicy.Minimum,qt.QSizePolicy.Minimum) self.updateGeometry() def show_bottom(self): # debug(20, "SHOW BOTTOM PAGE") max_val = self._parent.main_frame.verticalScrollBar().maximum() current_val = \ self._parent.main_frame.verticalScrollBar().sliderPosition() if self.show_last: if current_val != max_val: if self.max_val != max_val: self._parent.main_frame.verticalScrollBar( ).setSliderPosition(max_val) else: self.show_last = False else: if current_val == max_val: self.show_last = True self.max_val = max_val ################# API FUNCTION ############################### def show_view(self, view): pass def show_table(self, table, item): # method to display tables add_offset_flag = False if not table.body: table.body = [[]] self.show_normal(item) self.mytable = None if self.method_name in self.ClientObj.param_objects: if len(table.body[0]) >= self.ClientObj.count_row_res_table or \ self.ClientObj.param_objects[self.method_name]['offset']: if table.onClick and table.records != "0": self.add_offset_buttons(len(table.body[0]), table.addAction, table.records) add_offset_flag = True if table.addAction and not add_offset_flag: plus_but = PlusButton(self, self.ClientObj, table.addAction, self.disable_buttons) self.buttons.append(plus_but) self.work_layout._addWidget(plus_but) if table.onClick and table.body[0]: self.mytable = SelectedTableWidget(len(table.body[0]), \ len(table.head[0]), self) if not self.mytable: if table.body: len_body = len(table.body[0]) else: len_body = 0 if table.head: len_head = len(table.head[0]) else: len_head = 1 if len_body: self.mytable = SelectedTableWidget(len_body, len_head, self, readonly=True) if self.mytable: list_head = table.head[0] self.mytable.setHorizontalHeaderLabels(list_head) for line in range(len(table.body[0])): for i in range(len(table.body[0][line][0])): tablewidgetitem = qt.QTableWidgetItem( table.body[0][line][0][i]) self.mytable.setItem(line, i, tablewidgetitem) # set writeonly self.mytable.setEditTriggers(qt.QAbstractItemView.NoEditTriggers) if table.onClick: self.mytable.itemClicked.connect(self.row_activate(table)) self.mytable.setColor() minimum = qt.QSizePolicy.Minimum self.mytable.setSizePolicy(minimum, minimum) self.mytable.horizontalHeader().resizeSections( qt.QHeaderView.ResizeToContents) self.work_layout._addWidget(self.mytable) self.ClientObj.app.processEvents() self.mytable.resizeRowsToContents() self.mytable.resizeColumnsToContents() self.initUI() def row_activate(self, table): def wrapper(item): param_object = create_obj(self.client, table.onClick) for field in table.fields.string: if field: if ":" in field: field, op, value = field.partition(":") else: value = None if hasattr (param_object, field): if value: param_object[field] = value else: param_object[field] = self.mytable.item(item.row(),0).\ text() #print param_object, table.step param_object.CheckOnly = True # Calling method sid = int(self.ClientObj.sid) self.client.service[0][table.onClick](sid, param_object) # Calling View try: self.client.service.clear_pid_cache(sid, self.cur_pid) except: pass try: view_params = get_view_params(self.client, table.onClick + '_view', step = 0) #int(table.step) if table.step else 0) view = self.client.service[0][table.onClick + '_view']( sid, view_params) except MethodNotFound as e: _print(e) return if table.onClick in self._parent.ClientObj.method_names: view_method = self._parent.ClientObj.method_names \ [table.onClick] else: view_method = table.onClick self._parent.ClientObj._parent.setWindowTitle(view_method + \ ' - ' + self.ClientObj.Name) #self.ClientObj.param_objects[self.method_name]['offset'] = 0 self._parent.main_frame_view( view, table.onClick, new_step=table.step if table.step else None) return wrapper def disable_buttons(self): debug(11, "DISABLE", self.buttons) for button in self.buttons: button.setDisabled(True) self.timer.stop() def add_offset_buttons(self, len_body, addAction, records): offset_buttons = qt.QWidget() layout = qt.QHBoxLayout(offset_buttons) layout.setAlignment(qt.Qt.AlignLeft) offset = self.ClientObj.param_objects[self.method_name]['offset'] count_records = int(self.ClientObj.count_row_res_table) debug(15, "DATA:", records, offset, count_records) records = int(records) or 0 if records: if offset + count_records >= records: last = True else: last = False else: if len_body < self.ClientObj.count_row_res_table: last = True else: last = False begin_offset = qt.QPushButton(offset_buttons) begin_offset.setIcon(get_icon('go-first')) begin_offset.setToolTip('First page') begin_offset.clicked.connect(self.disable_buttons) begin_offset.clicked.connect(self.call_method_with_offset(0, True)) begin_offset.setFixedSize(30, 30) self.buttons.append(begin_offset) layout.addWidget(begin_offset) minus_offset = qt.QPushButton(offset_buttons) minus_offset.setIcon(get_icon('go-previous')) minus_offset.setToolTip('Previous page') minus_offset.clicked.connect(self.disable_buttons) minus_offset.clicked.connect(self.call_method_with_offset( -count_records)) minus_offset.setFixedSize(30, 30) layout.addWidget(minus_offset) self.buttons.append(minus_offset) if not offset: minus_offset.setDisabled(True) begin_offset.setDisabled(True) plus_offset = qt.QPushButton(offset_buttons) plus_offset.setIcon(get_icon('go-next')) plus_offset.setToolTip('Next page') plus_offset.clicked.connect(self.disable_buttons) plus_offset.clicked.connect(self.call_method_with_offset( count_records)) plus_offset.setFixedSize(30, 30) layout.addWidget(plus_offset) self.buttons.append(plus_offset) last_offset = qt.QPushButton(offset_buttons) last_offset.setIcon(get_icon('go-last')) last_offset.setToolTip('Last page') last_offset.clicked.connect(self.disable_buttons) last_offset.clicked.connect(self.call_method_with_offset( 0, False, records - count_records)) last_offset.setFixedSize(30, 30) layout.addWidget(last_offset) self.buttons.append(last_offset) if last or not records: last_offset.setDisabled(True) if last: plus_offset.setDisabled(True) if addAction: plus_but = PlusButton(self, self.ClientObj, addAction, self.disable_buttons) self.buttons.append(plus_but) layout.addWidget(plus_but) self.work_layout._addWidget(offset_buttons) def call_method_with_offset(self, offset, begin=False, reset=None): def wrapper(): debug(10, "CHANGE OFFSET FOR %s to %d" % ( self.method_name, offset)) if begin: self.ClientObj.param_objects[self.method_name]['offset'] = 0 elif reset is not None: self.ClientObj.param_objects[self.method_name]['offset'] = \ reset else: self.ClientObj.param_objects[self.method_name]['offset'] += offset if self.ClientObj.param_objects[self.method_name]['offset'] < 0: self.ClientObj.param_objects[self.method_name]['offset'] = 0 # Calling View debug(10, "CALL VIEW", self.method_name) sid = int(self.ClientObj.sid) try: view_params = get_view_params(self.client, self.method_name + '_view', step = None) view = self.client.service[0][self.method_name + '_view'] \ (sid, view_params) except MethodNotFound: return #if self._parent.ClientObj.method_names.has_key(self.method_name): # view_method = self._parent.ClientObj.method_names \ # [self.method_name] #else: view_method = self.method_name self._parent.ClientObj._parent.setWindowTitle(view_method + \ ' - ' + self.ClientObj.Name) self._parent.main_frame_view(view, view_method, change_offset=True) return wrapper def show_message(self, message, mono=False, space=0): message = self.processTags(message) # add normal message label lbl_temp = LabelWordWrap(message, self, mono=mono, margin_top=space) if mono: lbl_temp.setMinimumHeight(lbl_temp.minimumSizeHint().height()) lbl_temp.setMaximumHeight(lbl_temp.sizeHint().height()) else: lbl_temp.setMinimumHeight(lbl_temp.minimumSizeHint().height()) lbl_temp.setMaximumHeight(lbl_temp.sizeHint().height()) self.work_layout._addWidget(lbl_temp) self.initUI() return lbl_temp #self._parent.main_frame.verticalScrollBar().setSliderPosition \ # (self._parent.main_frame.verticalScrollBar().maximum()) def show_normal(self, item, mono=False): if not hasattr(item, 'message'): return if item.message: self.show_message(item.message, mono) if not mono: if self.progress_list: self.progress_list[-1].hide() self.add_Progress() def show_error(self, message): # add error message label self.set_result_task(True) if self.progress_list: self.progress_list[len(self.progress_list)-1].hide() if message: message = self.processTags(message) lbl_temp = ErrorWgt(message, self) lbl_temp.set_error() lbl_temp.setMinimumHeight(lbl_temp.minimumSizeHint().height()) lbl_temp.setMaximumHeight(lbl_temp.minimumSizeHint().height()) #lbl_temp.setMinimumHeight(lbl_temp.sizeHint().height()) self.work_layout._addWidget(lbl_temp) self.initUI() def show_warning(self, item): # add warning message label if item.message: item.message = self.processTags(item.message) lbl_temp = ErrorWgt(item.message, self) lbl_temp.set_warning() lbl_temp.setMinimumHeight(lbl_temp.minimumSizeHint().height()) lbl_temp.setMaximumHeight(lbl_temp.minimumSizeHint().height()) self.work_layout._addWidget(lbl_temp) self.initUI() def show_group(self, item, *args): pass def show_result(self, result): # add normal message label lbl_temp = LabelWordWrap(result.message, self) lbl_temp.setMinimumHeight(lbl_temp.sizeHint().height()) self.work_layout._addWidget(lbl_temp) self.initUI() def processTags(self, s): xc = XmlConverter(SpanCssOutput(palette=WorkPalette())) return xc.transform(s) def cleanTags(self, s): xc = XmlConverter() return xc.transform(s) def startTask(self, item): if self.progress_list: self.progress_list[-1].hide() task_widget = TaskWidget(self.processTags(item.message), self, clean_text=self.cleanTags(item.message)) self.task_list.append(task_widget) self.work_layout._addWidget(task_widget) self.add_Progress() self.initUI() def endTask(self, item, set_res = True): if self.progress_list: self.progress_list[-1].hide() message = item.message if item.message else '' if set_res: if message == "skip": self.set_result_task(skip=True) elif hasattr(item,"result") and not item.result is None: self.set_result_task(not item.result) else: self.set_result_task() if message and message != "skip": message = self.processTags(message) lbl_temp = LabelWordWrap(message, self) lbl_temp.setMinimumHeight(lbl_temp.sizeHint().height()) self.work_layout._addWidget(lbl_temp) self.initUI() def set_result_task(self, error=False, skip=False): if not len(self.task_list): return if skip: self.task_list[len(self.task_list) - 1].set_skip() elif error: self.task_list[len(self.task_list) - 1].set_error() else: self.task_list[len(self.task_list) - 1].set_ok() def beginFrame(self, item): pass def endFrame(self, item): if self.progress_list: self.progress_list[len(self.progress_list)-1].hide() self.endTask(item) self.initUI() self.work_layout.hide_kill_button() self.closeDialogs() self.close_all_thread() if self.change_offset: self._parent.delete_MainFrameWgt() self._parent.MainFrameWgt = self self._parent.main_frame.setWidget (self._parent.MainFrameWgt) self._parent.main_frame.setWidgetResizable(True) self._parent.methodname_wgt.show() self._parent.control_button.show() #if hasattr (self, "mytable"): # if not self.mytable.readonly: # self.initUI() # return 0 #self._parent.control_button.add_clear_cache_button(self.cur_pid) #self.initUI() # TODO: возможно здесь не нужне return 1 self._parent.control_button.add_clear_cache_button(self.cur_pid) self.initUI() return 0 # def clear_pid_cache(self): # self.clear_proc_cache_button.setDisabled(True) # sid = int(self.ClientObj.sid) # res = self.client.service.clear_pid_cache(sid, self.cur_pid) # if res: # _print (_('Error closing the process')) # self._parent.back() def startGroup(self, item): if not hasattr(item, 'message'): return if item.message: item.message = self.processTags(item.message) # add normal message label lbl_temp = LabelWordWrap("%s"%item.message, self) lbl_temp.setMinimumHeight(lbl_temp.minimumSizeHint().height()) lbl_temp.setMaximumHeight(lbl_temp.sizeHint().height()) self.work_layout._addWidget(lbl_temp) self.initUI() #self._parent.main_frame.verticalScrollBar().setSliderPosition \ # (self._parent.main_frame.verticalScrollBar().maximum()) def endGroup(self, item): pass def kill_process(self, pid): def wrapper(): sid = int(self.ClientObj.sid) self.closeDialogs() # Call server method if hasattr (self, 'kill_process_thread'): if self.kill_process_thread.isRunning(): return 1 self.kill_process_thread = ClientServiceThread(self.ClientObj,\ 'pid_kill', pid, sid) self.kill_process_thread.signal.connect(self.kill_process_after) self.kill_process_thread.start() return wrapper def kill_process_after(self, result): if result in [0,2]: return 0 elif result == -1: msg = _("Certificate not found in the server!") elif result == -2: msg = _("Session not matching your certificate!") elif result == 1: msg = _("Failed to kill the process!") else: msg = 'error' show_msg(msg) ############################################################################### def analysis(self, meth_result): """ analysis of the bounced message method """ # for mess in meth_result: self.ClientObj.app.processEvents() mess = meth_result if mess.type == 'pid': self.get_messages(self.ClientObj.sid, mess.message) if mess.type == 'error': try: self.show_error(self, mess.message) except: pass if mess.type == 'warning': try: self.show_warning(self, mess) except: pass def get_message(self, item, sid, pid): try: if item.type == "error" and item.message == "403 Forbidden": return 0 if self.cur_pid != pid: return 1 except: return 1 """ get one message by its type """ if not hasattr(item,"type"): return 1 for case in switch(item.type): if case('normal'): self.show_normal(item) return 1 if case('pre'): self.show_normal(item,mono=True) return 1 if case('plain'): self.show_normal(item) return 1 if case('progress'): self.get_Progress(sid, pid, item.id) return 1 if case('error'): # for i in range(20): self.show_error(item.message) if item.message == "403 Forbidden": # show_msg(item.message, 'Access Denied') return 0 return 1 if case('warning'): self.show_warning(item) return 1 if case('table'): self.get_Table(sid, pid, item) return 1 if case('group'): self.show_group(item) return 1 if case('question'): self.send_Message(sid, pid, item) return 1 if case('confirm'): self.send_Confirm(sid, pid, item) return 1 if case('choice'): self.send_Choice(sid, pid, item) return 1 if case('password'): self.send_Password(sid, pid, item) return 1 if case('startTask'): self.startTask(item) return 1 if case('taskNumber'): # self.startTask(item) return 1 if case('endTask'): self.endTask(item) return 1 if case('beginFrame'): self.beginFrame(item) return 1 if case('endFrame'): self.endFrame(item) self.resize(self.sizeHint()) return 0 if case('startGroup'): self.startGroup(item) return 1 if case('endGroup'): self.endGroup(item) return 1 if case(): # default, could also just omit condition or 'if True' return 1 def get_messages(self, sid, pid): """ get frame in a separate thread """ #import threading #thread_messages = threading.Thread(target=self.get_Frame,\ # args = (sid, pid)) #thread_messages.start() self.get_Frame(sid, pid) def get_Frame(self, sid, pid, def_end_frame = 1): """ get all messages, until type is not endFrame (or Error) """ self.not_end_frame = def_end_frame if self.not_end_frame: # Call server method if hasattr (self, 'get_Frame_thread'): if self.get_Frame_thread.isRunning(): self.get_Frame_thread.wait() self.get_Frame_thread = ClientServiceThread(self.ClientObj,\ 'get_frame', sid, pid, "gui", return_except = True, \ through_object = (sid, pid)) self.get_Frame_thread.signal_extended.connect(self.get_Frame_cycle) self.get_Frame_thread.start() def get_errno(self, exception): """ Exception container with URLError """ from socket import error as socket_error try: if (exception.args and type(exception.args[0]) == URLError and exception.args[0].args and type(exception.args[0].args[0]) == socket_error): return exception.args[0].args[0].errno if (exception.args[0].args and type(exception.args[0].args[0]) == socket_error): return exception.args[0].errno except: return None return None def get_Frame_cycle(self, current_frame, through_object): if type(current_frame) == Exception: _print (_("Failed to get a frame from the server.")) #show_msg(_("Failed to get a frame from the server.") +'\n'+ \ # _('Try resfeshing this page later.'),'get frame error') sid, pid = through_object if current_frame in [None, [], ""]: try: if self.cur_pid != pid: return 1 except: return 1 elif not isinstance(current_frame,Exception): self.get_Frame_after(current_frame, sid, pid) if self.not_end_frame: # Call server method if hasattr (self, 'get_Frame_thread'): if self.get_Frame_thread.isRunning(): self.get_Frame_thread.wait() if self.ClientObj.host_name in ('localhost','127.0.0.1'): if self.get_errno(current_frame) == 111: sleeptime = 5 else: sleeptime = int(self.ClientObj.client.frame_period) else: sleeptime = int(self.ClientObj.client.frame_period) self.get_Frame_thread = ClientServiceThread(self.ClientObj, 'get_frame', sid, pid, "gui",return_except = True, sleeptime = sleeptime, through_object = (sid, pid)) self.get_Frame_thread.signal_extended.connect(self.get_Frame_cycle) self.get_Frame_thread.start() def get_Frame_after(self, current_frame, sid, pid): for item in range(len(current_frame[0])): self.not_end_frame = self.get_message(current_frame[0][item], sid, pid) self.valSignal.emit() try: if self.cur_pid != pid: return 1 except: return 1 if len (current_frame[0]) > 3: if not item % 10: self.ClientObj.app.processEvents() else: self.ClientObj.app.processEvents() self.valSignal.emit() def get_entire_frame(self, pid = None): """ get entire frame, from beginning (if client disconnected) """ self.ClientObj.app.processEvents() sid = get_sid(self.ClientObj.client) if not pid: try: list_pid = self.ClientObj.client.service.list_pid(sid = sid) except URLError as e: _print ('get_entire_frame in MainFrameResult Exception') show_msg (e, _("Not connected!")) return 1 else: list_pid = {} list_pid[0] = [pid] if list_pid[0] == [0]: return 0 pid = list_pid[0][0] # Call server method if hasattr (self, 'get_Frame_thread'): if self.get_Frame_thread.isRunning(): self.get_Frame_thread.wait() self.get_Frame_thread = ClientServiceThread(self.ClientObj,\ 'get_entire_frame', sid, pid, return_except = True, \ through_object = (sid, pid)) self.get_Frame_thread.signal_extended.connect \ (self.get_entire_frame_after) self.get_Frame_thread.start() def get_entire_frame_after(self, current_frame, through_object): if type(current_frame) == Exception: _print (_('Failed to get the complete frame from the server.')) # show_msg(_("Failed to get a frame from the server.") +'\n'+ \ # _('Try resfeshing this page later.'),'get frame error') return 1 sid, pid = through_object end_frame = 1 if not current_frame in [None, [], ""]: # for i in range (10): for item in range(len(current_frame[0])): end_frame = self.get_message(current_frame[0][item], sid, pid) self.valSignal.emit() try: if self.cur_pid != pid: return 1 except: return 1 if len (current_frame[0]) > 3: if not item % 10: self.ClientObj.app.processEvents() else: self.ClientObj.app.processEvents() self.get_Frame(sid, pid, def_end_frame = end_frame) def add_Progress(self): progressBar = qt.QProgressBar() progressBar.setMinimumHeight(progressBar.sizeHint().height()) progressBar.setTextVisible(True) self.progress_list.append(progressBar) self.work_layout._addWidget(progressBar) progressBar.setMinimum(0) progressBar.setMaximum(0) self.initUI() return progressBar def get_Progress(self, sid, pid, id): """ get progress for the current job """ #if self.progress_list and self.progress_list[-1].isVisible(): if self.progress_list: progressBar = self.progress_list[-1] else: progressBar = self.add_Progress() #else: # progressBar = self.add_Progress() #if self.progress_list: # self.progress_list[-1].hide() temp_progress = -1 # Call server method if hasattr (self, 'get_Progress_thread'): if self.get_Progress_thread.isRunning(): self.get_Progress_thread.wait() self.get_Progress_thread = ClientServiceThread(self.ClientObj,\ 'get_progress', sid, pid, id, return_except = True, \ through_object = (sid, pid, id, temp_progress, \ progressBar)) self.get_Progress_thread.signal_extended.connect \ (self.get_Progress_cycle) self.get_Progress_thread.start() def get_Progress_cycle(self, returnProgr, through_object): sid, pid, id, temp_progress, progressBar = through_object def nextProgress(): if hasattr (self, 'get_Progress_thread'): if self.get_Progress_thread.isRunning(): self.get_Progress_thread.wait() self.get_Progress_thread = ClientServiceThread(self.ClientObj,\ 'get_progress', sid, pid, id, return_except = True,\ sleeptime = 1, through_object = \ (sid, pid, id, temp_progress, progressBar)) self.get_Progress_thread.signal_extended.connect \ (self.get_Progress_cycle) self.get_Progress_thread.start() if type(returnProgr) == Exception: _print (_('Failed to get the progress status from the server')) # show_msg(_('Failed to get the progress status from the server') + \ # '\n'+ \ # _('Try resfeshing this page later.'),'get progress error') nextProgress() return 1 ######################################## try: percent = returnProgr.percent except AttributeError: if type(returnProgr) in [str,unicode]: _print ('Server return:', returnProgr) percent = temp_progress if percent <= 100 and percent >= 0 : if temp_progress != percent: if percent: # progressBar.setProperty("value", 100) progressBar.setMaximum(100) # progressBar.setValue(percent) self.set_progress_value(progressBar, returnProgr) if percent == 100: return 0 self.initUI() temp_progress = percent try: if self.cur_pid != pid: return 1 except: return 1 # Call server method nextProgress() if percent < 0: progressBar.setMaximum(100) returnProgr.percent = 0 - percent self.set_progress_value(progressBar, returnProgr) self.ClientObj.app.processEvents() self.initUI() def set_progress_value(self, progressBar, returnProgr): if returnProgr.long_message: if progressBar.fontMetrics().width(returnProgr.long_message) + \ progressBar.fontMetrics().width(' 000%') \ < progressBar.width(): progressBar.setFormat('%s %d%%' %(returnProgr.long_message, \ returnProgr.percent)) progressBar.setValue(returnProgr.percent) self.ClientObj.app.processEvents() return 0 if returnProgr.short_message: progressBar.setFormat('%s %d%%' %(returnProgr.short_message, \ returnProgr.percent)) progressBar.setValue(returnProgr.percent) self.ClientObj.app.processEvents() return 0 progressBar.setFormat('%d%%' %returnProgr.percent) progressBar.setValue(returnProgr.percent) self.ClientObj.app.processEvents() def get_Table(self, sid, pid, item): try: table = self.ClientObj.client.service.get_table(sid, pid, item.id) except URLError: self.show_error('Error get table from server') return 1 self.show_table(table, item) self.ClientObj.app.processEvents() # Resize table if self.mytable: h = self.mytable.horizontalHeader().height() + \ 2 * self.mytable.frameWidth() h += self.mytable.horizontalScrollBar().sizeHint().height() for row_in_table in range(self.mytable.rowCount()): h += self.mytable.rowHeight(row_in_table) self.mytable.setFixedHeight(h) def send_Confirm(self, sid, pid, item): """ send answer to the question """ if self.progress_list: self.progress_list[-1].hide() self.message = ConfirmDialog(self, item, sid, pid) self._parent.control_button.set_confirmation(self.message) self.message.show() def send_Choice(self, sid, pid, item): """ send answer to the question """ if self.progress_list: self.progress_list[-1].hide() self.message = ChoiceDialog(self, item, sid, pid) self._parent.control_button.set_confirmation(self.message) self.message.show() def send_Message(self, sid, pid, item): """ send answer to the question """ self.message = MessageDialog(self, item, sid, pid) debug(11, f"send message{item}") self.message.show() def send_Password(self, sid, pid, item): """ send password """ self.passwd = MessageDialog(self, item, sid, pid, True) self.passwd.show() def close_all_thread(self): if hasattr (self, 'get_Frame_thread'): if self.get_Frame_thread.isRunning(): self.get_Frame_thread.close() self.get_Frame_thread.wait() if hasattr (self, 'get_Progress_thread'): if self.get_Progress_thread.isRunning(): self.get_Progress_thread.close() self.get_Progress_thread.wait() if hasattr (self, 'send_password_thread'): if self.send_password_thread.isRunning(): self.send_password_thread.close() self.send_password_thread.wait() def closeDialogs(self): if hasattr(self, "message") and self.message: self.message.close() self.message = None if hasattr(self, "passwd") and self.passwd: self.passwd.close() self.passwd = None self._parent.control_button.close_confirmation() self._parent.control_button.close_break_button() def closeEvent(self, event): self.timer.stop() self.cur_pid = 'no' self.close_all_thread() self._parent.methodname_wgt._hide() self._parent.control_button._hide() self.closeDialogs() event.accept() class MessageDialog(qt.QWidget): # answer to the server question def __init__(self, parent, item, sid, pid, isPassword = False): super().__init__() self._parent = parent # self.item = item self.sid = sid self.pid = pid self.setWindowTitle(self._parent.ClientObj._parent.windowTitle()) self.layout = qt.QGridLayout(self) self.label = LabelWordWrap(item.message, self) self.pass_edit = qt.QLineEdit(self) self.layout.addWidget(self.label,0,0) self.layout.addWidget(self.pass_edit,0,1) x = 1 if isPassword: self.pass_edit.setEchoMode(self.pass_edit.Password) if item.id == 2: if hasattr(self,'pass_edit2'): self.pass_edit2 = qt.QLineEdit(self) self.pass_edit2.setEchoMode(self.pass_edit2.Password) self.layout.addWidget(LabelWordWrap(_('Repeat'), self), x, 0) self.layout.addWidget(self.pass_edit2, x, 1) x += 1 self.pass_edit.textChanged.connect(self.check_passwd) if hasattr(self,'pass_edit2'): self.pass_edit2.textChanged.connect(self.check_passwd) self.send_button = qt.QPushButton(_('Send'), self) self.send_button.setShortcut(qt.QKeySequence(qt.Qt.Key_Return)) self.send_button.clicked.connect(self.send_password) self.layout.addWidget(self.send_button,x,1) self.move(parent.ClientObj._parent.geometry().x() + \ parent.ClientObj._parent.geometry().width() / 2 \ - self.sizeHint().width() / 2, \ parent.ClientObj._parent.geometry().y() + \ parent.ClientObj._parent.geometry().height() / 2 \ - self.sizeHint().height() / 2) self.setWindowFlags (qt.Qt.WindowMinimizeButtonHint) def send_password(self): answer = self.pass_edit.text() if not hasattr(self,"pass_edit2") or \ answer == self.pass_edit2.text(): # Call server method if hasattr (self, 'send_password_thread'): if self.send_password_thread.isRunning(): return 1 self.send_password_thread = ClientServiceThread(\ self._parent.ClientObj, 'send_message', self.sid, \ self.pid, answer, return_except = True) self.send_password_thread.signal.connect(self.send_password_after) self.send_password_thread.start() else: self.send_button.setDisabled(True) def send_password_after(self, result): if type(result) == Exception: show_msg(_('Failed to send the message (password) to the server')) self.close() return 1 self._parent.show_result(result) self.close() def check_passwd(self): if self.pass_edit.text() != self.pass_edit2.text(): self.send_button.setDisabled(True) else: self.send_button.setEnabled(True) class ButtonDialog(qt.QWidget): button_size = 144 def __init__(self, parent, item, sid, pid): super().__init__() self._parent = parent self.sid = sid self.pid = pid self.layout = qt.QHBoxLayout(self) self.layout.setContentsMargins(0, 0, 4, 0) self.header_label = None minimum = qt.QSizePolicy.Fixed self.setSizePolicy(minimum, minimum) self.setFixedHeight(dpivalue(32)) self.init(item) def init(self, item): pass def createButton(self, label, answer, shortcut=None): """ Создать кнопку в диалоге """ button = qt.QPushButton(label, self) if type(shortcut) in (list, tuple): action = qt.QAction(self) action.setShortcuts([qt.QKeySequence(x) for x in shortcut]) action.triggered.connect(button.animateClick) button.addAction(action) elif shortcut: button.setShortcut(qt.QKeySequence(shortcut)) button.clicked.connect(self.send(answer, label)) button.setFixedWidth(self.button_size) button.setFixedHeight(dpivalue(32)) self.layout.addWidget(button) def send(self, answer, human_answer=None): # Call server method def wrapper(): self._parent._parent.control_button.close_confirmation() if human_answer and self.header_label: self.header_label.setText( self.header_label.text() + " " + human_answer) if hasattr(self, 'send_password_thread'): if self.send_password_thread.isRunning(): return 1 self.send_password_thread = ClientServiceThread( \ self._parent.ClientObj, 'send_message', self.sid, \ self.pid, answer, return_except=True) self.send_password_thread.signal.connect(self.send_after) self.send_password_thread.start() return wrapper def send_after(self, result): if type(result) == Exception: show_msg(_('Failed to send the message (password) to the server')) self.close() return 1 #self._parent.show_result(result) self.close() class ConfirmDialog(ButtonDialog): """ Диалог подтверждения действия """ def init(self, item): self._parent._parent.control_button.set_confirm_question( "%s" % item.message) self.createButton(_("Yes"), "yes", [qt.Qt.Key_Enter, qt.Qt.Key_Return]) self.createButton(_("No"), "no", qt.Qt.Key_Escape) class ChoiceDialog(ButtonDialog): """ Диалог выбора ответа из нескольких """ def init(self, item): message, answers = item.message.split('|') self._parent._parent.control_button.set_confirm_question( "%s" % message) reAnswer = re.compile("^(.*)\((.*)\)$") answers = imap_regexp(reAnswer, answers.split(',')) for answer, label in answers: self.createButton(label, answer)