#-*- 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 absolute_import from .. import qt from .more import ButtonMenu, icon_visible, LabelWordWrap, get_sid, show_msg, \ ClientServiceThread, show_question, get_view_params, _print, \ get_system_rgb, dpivalue class StepLabel(qt.QLabel): clicked = qt.Signal() def __init__(self, text, parent): super().__init__(parent) self.setWordWrap(True) self.setText(text) self.updateGeometry() self.setCursor(qt.Qt.PointingHandCursor) bg = get_system_rgb(parent._parent, qt.QPalette.Highlight) self.setStyleSheet("QLabel {margin-left: 0px; margin-right: 0px;}" "QLabel:hover {"#color: blue;" # "QLabel:hover {color: white;" "background-color: %s;}"%bg) self.setContentsMargins(26,0,26,0) self.adjustSize() self.setFixedHeight(dpivalue(self.height() + 18)) def mousePressEvent(self, event): self.clicked.emit() def setBold(self, bold): font = self.font() font.setBold(bold) self.setFont(font) class LeftMenu(qt.QScrollArea): def __init__(self, parent, ClientObj): super().__init__(parent) self._parent = parent self.ClientObj = ClientObj self.horizontalScrollBar().hide() self.old_title = None # self.setStyleSheet("QWidget { background-color: rgb (%s) ;}" \ # %ClientObj.method_background_color.replace(' ',',',2)) # Set style # self.setStyleSheet("QScrollArea {"# D6D2D0 ## "background-color: #EEEEEE;" # "background-color: qlineargradient(" # "x1: 0, y1: 0, x2: 0, y2: 1, " # "stop: 0 #EEEEEE, stop: 0.8 #EEEEEE, " # "stop: 1 #E4E1E0);" # ## "border: 4px solid red;" # "border-right: 1px solid qlineargradient(" # "x1: 0, y1: 0, x2: 0, y2: 1, " # "stop: 0 #A8A3A0, stop: 0.8 #A8A3A0, " # "stop: 0.95 transparent, stop: 1 transparent);" ## "border-bottom-color: qlineargradient(" ## "x1: 0, y1: 0, x2: 0, y2: 1, " ## "stop: 0 transparent, stop: 1 #888380);" ## "border-left-color: qlineargradient(" ## "x1: 1, y1: 0, x2: 0, y2: 0, " ## "stop: 0 transparent, stop: 1 #888380);" ## "border-top-color: qlineargradient(" ## "x1: 0, y1: 1, x2: 0, y2: 0, " ## "stop: 0 transparent, stop: 1 #888380);}") # "border-bottom: 0px;" # "border-left: 0px;" # "border-top: 0px;}") self.setFrameShape(qt.QFrame.NoFrame) self.setAttribute(qt.Qt.WA_DeleteOnClose) def create_menu(self, display_wgt, groups, sub_groups, ClientObj): self.display_wgt = display_wgt # create left subgroup menu self.old_title = self._parent.ClientObj._parent.windowTitle() # icon_visible(self._parent.ClientObj.MainWidget, 'Methods', True) icon_visible(self._parent.ClientObj.MainWidget, 'Back', True) self.widget = qt.QWidget (self) #self.cur_palette = display_wgt._parent.viewport().palette() #self.widget.setPalette(self.cur_palette) # self.widget.setStyleSheet("QWidget { background-color: rgb(%s) }" \ # %ClientObj.method_background_color.replace(' ',',',2)) #self.widget.setStyleSheet("QWidget { background-color: #EEEEEE;}") self.lable_list = [] self.button_list = {} self.layout = qt.QVBoxLayout(self.widget) self.layout.setAlignment(qt.Qt.AlignTop | qt.Qt.AlignHCenter) self.group_name = LabelWordWrap(sub_groups[0].split('.')[0], self) self.group_name.setStyleSheet( \ 'QLabel' '{' 'border-bottom: 2px outset black;' 'border-radius: 3px;' '}') self.group_name.setAlignment(qt.Qt.AlignHCenter) self.layout.addWidget(self.group_name) for num in range(len(sub_groups)): if len(sub_groups[num].split('.')) > 1: # try: sub_group = sub_groups[num].split('.')[1] # except (UnicodeDecodeError, UnicodeEncodeError): # pass attrubute_list = [] sub_group_list = [] if sub_group in self.button_list: attrubute_list = self.button_list[sub_group][0] sub_group_list = self.button_list[sub_group][1] self.button_list[sub_group] = [] param_list = [groups[num*3], groups[num*3 +1], groups[num*3 +2]] self.button_list[sub_group].append \ (attrubute_list + param_list) sub_group_list.append(sub_groups[num].split('.',1)[1]) self.button_list[sub_group].append \ (sub_group_list) Button = ButtonMenu(sub_group, sub_group, \ 'folder-documents,folder', self) Button.clicked.connect(display_wgt.groupActivated \ (self.button_list[sub_group][0],\ self.button_list[sub_group][1])) self.button_list[sub_group].append(Button) continue for i in range (0, len(groups), 3): try: if len(sub_groups[i/3].split('.')) > 1: continue except IndexError: pass Button = ButtonMenu(groups[i], groups[i + 1], groups[i + 2], self) Button.clicked.connect(self.onActivated) if sub_groups[num] not in self.button_list: self.button_list[sub_groups[num]] = [] self.button_list[sub_groups[num]].append(Button) for num in range(len(self.button_list)): # add subgroup if len(sub_groups[num].split('.')) > 1: sub_group = sub_groups[num].split('.')[1] self.layout.addWidget(self.button_list[sub_group] \ [len(self.button_list[sub_group]) - 1]) continue # add methos for button in self.button_list[sub_groups[num]]: self.layout.addWidget(button) self.setWidget(self.widget) self.setWidgetResizable(True) # self.setFixedWidth(self.sizeHint().width() + \ # self.verticalScrollBar().sizeHint().width()) self.setFixedWidth(self.sizeHint().width()) def groupActivated(self, groups, sub_group, title, ClientObj, back = False): ClientObj.MainWidget.delete_MainFrameWgt() ClientObj.MainWidget.MainFrameWgt = qt.QWidget(ClientObj.MainWidget) hlayout = qt.QHBoxLayout() hlayout.addItem(qt.QSpacerItem( 0, 0, \ qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding )) ClientObj.MainWidget.MainFrameWgt.setLayout(hlayout) ClientObj.MainWidget.main_frame.setWidget \ (ClientObj.MainWidget.MainFrameWgt) ClientObj.MainWidget.main_frame.setWidgetResizable(True) ClientObj.MainWidget.left_frame.update() ClientObj.MainWidget.left_frame.show() ClientObj._parent.setWindowTitle (title) self.old_title = title self.create_menu (self.display_wgt, groups, sub_group, ClientObj) def onActivated(self): method_name = self.sender().objectName() # set new Title new_title = self.sender().text() try: # new_title = new_title.decode('utf-8') new_title = new_title except (UnicodeDecodeError, UnicodeEncodeError): pass self._parent.ClientObj._parent.setWindowTitle \ (new_title + ' - ' + self.old_title) step = 0 self._parent.ClientObj.method_name = method_name self._parent.ClientObj.sid = \ get_sid(self._parent.ClientObj.client) # switch to the desired step if method_name in self._parent.ClientObj.param_objects: self._parent.ClientObj.param_objects[method_name]['step'] = step # Call server method if hasattr (self, 'onActivated_thread'): if self.onActivated_thread.isRunning(): return 1 view_params = get_view_params(self._parent.ClientObj.client, \ str(method_name + '_view'), step = step) self.onActivated_thread = ClientServiceThread(self._parent.ClientObj, \ str(method_name + '_view'), \ int(self._parent.ClientObj.sid), view_params, \ return_except = True) self.onActivated_thread.signal.connect(self.onActivated_after) self.onActivated_thread.start() def onActivated_after(self, view): if type(view) == Exception: # if hasattr (view.message, 'message'): # view = view.message # if type(view.message) == tuple: # if view.message[0] == 403: # msg = _('Permission denied') # else: # msg = ' '.join(map(lambda x: str(x), view.message)) # else: # msg = view.message.__str__() msg = str(view) show_msg(msg) return 1 self._parent.ClientObj.MainWidget.main_frame_view(view, \ self._parent.ClientObj.method_name) def create_steps (self, method_name, steps, icons = None): self.old_title = self._parent.ClientObj._parent.windowTitle() if not hasattr (self, 'step'): self.step = 0 # icon_visible(self._parent.ClientObj.MainWidget, 'Methods', True) icon_visible(self._parent.ClientObj.MainWidget, 'Back', True) self.widget = qt.QWidget (self) #--self.widget.setPalette(self.cur_palette) # self.widget.setStyleSheet("QWidget { background-color: rgb (%s) }" \ # %self._parent.ClientObj.method_background_color.\ # replace(' ',',',2)) self.setDisabled(False) self.widget.setObjectName('QQQ') self.widget.setStyleSheet("QWidget#QQQ { " "background-color: %s;}" % get_system_rgb(self, qt.QPalette.Base)) #self.setStyleSheet("QScrollArea { " # "background-color: qlineargradient(" # "x1: 0, y1: 0, x2: 0, y2: 1, " # "stop: 0 %(start)s, stop: 0.7 %(start)s, " # "stop: 0.9 %(end)s, stop: 1 %(end)s);}"% # {'start':get_system_rgb(self, qt.QPalette.Base), # 'end':get_system_rgb(self, qt.QPalette.Window), # }) self.button_list = [] self.layout = qt.QVBoxLayout(self.widget) self.layout.setAlignment(qt.Qt.AlignTop | qt.Qt.AlignHCenter) # self.layout.setContentsMargins(28,28,28,0) self.layout.setContentsMargins(2,28,2,0) self.layout.setSpacing(5) if not icons: icons = [] width_list = [] for num_step in range(len(steps)): self.button_list.append(StepLabel(steps[num_step], self)) # collect parameters object self.button_list[num_step].clicked.connect(self.collect_object \ (method_name, num_step)) # call function (or check parameters) self.button_list[num_step].clicked.connect(self.calling_method \ (method_name, num_step)) # self.button_list[num_step].clicked.connect \ # (self.check_step(method_name, num_step)) # calculate button width fmn = qt.QFontMetrics(qt.QFont('',-1,qt.QFont.Normal)) normal_width = fmn.width(self.button_list[num_step].text()) fmb = qt.QFontMetrics(qt.QFont('',-1,qt.QFont.Bold)) bold_width = fmb.width(self.button_list[num_step].text()) diff = bold_width - normal_width + 6 # self.button_list[num_step].setFixedWidth \ # (self.button_list[num_step].sizeHint().width() + diff) width_list.append(self.button_list[num_step].sizeHint().width() \ + diff) self.layout.addWidget(self.button_list[num_step]) if width_list: width_list.sort() max_width = width_list.pop() else: max_width = 0 for num_step in range(len(steps)): self.button_list[num_step].setFixedWidth(max_width) # set bold button self.changed_step(self._parent.ClientObj.param_objects \ [method_name]['step']) # self.layout.addItem(qt.QSpacerItem(100, 100, \ # qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)) self.setWidget(self.widget) self.setWidgetResizable(True) self.setFixedWidth(self.sizeHint().width())# + \ # self.verticalScrollBar().sizeHint().width()) if not self.isVisible(): self.show() # create helper signals collect = qt.Signal() calling = qt.Signal() def collect_object(self, method_name, set_step = None): def wrapper(): self.setDisabled(True) if hasattr (self, 'check_step_thread'): if self.check_step_thread.isRunning(): _print ('check_step_thread is running') self.setEnabled(True) return 1 change_step = set_step if set_step else 0 if self._parent.ClientObj.param_objects[method_name]['step'] > \ change_step: # self.setEnabled(True) return self.collect.connect(self._parent.ClientObj.MainWidget.\ MainFrameWgt.collect_object()) self.collect.emit() self.collect.disconnect() return wrapper def calling_method(self, method_name, set_step = None): def wrapper(): if hasattr (self, 'check_step_thread'): if self.check_step_thread.isRunning(): self.setEnabled(True) _print ('check_step_thread is running') return 1 change_step = set_step if set_step else 0 if self._parent.ClientObj.param_objects[method_name]['step'] > \ change_step: self.check_step(method_name, set_step) # self.setEnabled(True) return self.calling.connect(self._parent.ClientObj.MainWidget.\ MainFrameWgt.calling(True, from_left_frame = True)) self.calling.emit() self.calling.disconnect() self.check_step(method_name, set_step) return wrapper def check_step(self, method_name, set_step = None): # def wrapper(): # Call server method if hasattr (self, 'check_step_thread'): if self.check_step_thread.isRunning(): _print ('check_step_thread is running') self.setEnabled(True) return 1 self.step = set_step if set_step else 0 self._parent.ClientObj.method_name = method_name self._parent.ClientObj.sid = \ get_sid(self._parent.ClientObj.client) expert = None if self._parent.ClientObj.MainWidget.MainFrameWgt. \ isBrief(self.step): num = None brief = True expert = True else: brief = False num = self.step view_params = get_view_params(self._parent.ClientObj.client, \ str(method_name + '_view'), step = num, \ expert = expert, brief = brief) self.check_step_thread = ClientServiceThread( \ self._parent.ClientObj,\ str(method_name + '_view'), \ int(self._parent.ClientObj.sid), \ view_params) self.check_step_thread.signal.connect(self.check_step_after) self.check_step_thread.start() # return wrapper def check_step_after(self, view = None): method_name = self._parent.ClientObj.method_name if self._parent.ClientObj.param_objects[method_name]['error']: if self._parent.ClientObj.param_objects[method_name]['step'] < \ self.step: text = _('Error at this step.') informative_text = _('Do you want to continue?') reply = show_question(self._parent, text, informative_text, \ not_move = True, title = _('Calculate Console')) if reply == qt.QMessageBox.No: self.setEnabled(True) return if not view: self.setEnabled(True) return # set bold for current step self.changed_step(self.step) self._parent.ClientObj.param_objects[method_name]['step'] = self.step self._parent.ClientObj.MainWidget.main_frame_view(view, method_name) self.setEnabled(True) def changed_step(self, step): if not hasattr (self, 'button_list'): return 1 # set bold for current step for i in range(len(self.button_list)): if i == step: self.button_list[i].text() self.button_list[i].setBold(True) else: self.button_list[i].setBold(False) def hideEvent (self, event): if hasattr (self, 'onActivated_thread'): if self.onActivated_thread.isRunning(): self.onActivated_thread.close() self.onActivated_thread.wait() if hasattr (self, 'send_password_thread'): if self.check_step_thread.isRunning(): self.check_step_thread.close() self.check_step_thread.wait() event.accept()