#-*- coding: utf-8 -*- # Copyright 2012-2013 Calculate Ltd. 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 PySide import QtGui, QtCore from more import ButtonMenu, FlowLayout, get_sid, ClientServiceThread, \ get_view_params, show_msg from collections import namedtuple class DisplayMethod(QtGui.QWidget): def __init__(self, parent, ClientObj): super(DisplayMethod, self).__init__(parent) self.ClientObj = ClientObj self._parent = parent self.setAttribute(QtCore.Qt.WA_DeleteOnClose) ClientObj.back_step_list = [] def initUI(self, results): self.lable_list = [] self.button_list = {} self.layout = QtGui.QVBoxLayout() self.groupbox_dict = {} self.layout_dict = {} # set new Title self.ClientObj._parent.setWindowTitle(self.ClientObj.Name) background_color = 'rgb(255,255,255)' self._parent.main_frame.viewport().setStyleSheet(\ "background-color: %s ; " %background_color ) self.setStyleSheet(self.styleSheet() + \ 'QWidget { background: transparent;}' 'QGroupBox {font-weight: bold;' 'border: 1px solid gray;' 'border-left-color: qlineargradient( x1: 0, y1: 0, x2: 0, y2: 1,' 'stop: 0 gray, stop: 1 transparent);' 'border-top-color: qlineargradient( x1: 0, y1: 0, x2: 1, y2: 0,' 'stop: 0 gray, stop: 1 transparent);' 'border-right: 0px; border-bottom: 0px;' 'border-top-left-radius: 2px;' 'background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1,' 'stop: 0 rgb(230, 230, 230), stop: 0.5 transparent,' 'stop: 1 transparent);' 'padding-top: 18px; padding-bottom: 18px;}' 'QGroupBox::title {background-color: transparent;' 'color: #555; subcontrol-position: top left;' 'margin-top: 6px; margin-left: 8px;}') # transform a list into the dictionary {'group': [methods], ...} guiMethods = {} if type(results) == int: # self.layout.addWidget(LabelWordWrap(_('No Methods!'),self)) self.setLayout(self.layout) self.show() return 1 for method_info in results: groups_name = method_info.category if groups_name in [None,'None']: self.ClientObj.method_names[method_info.name] = method_info.title continue if not groups_name in guiMethods.keys(): guiMethods[groups_name] = [] self.ClientObj.method_names[method_info.name] = method_info.title guiMethods[groups_name].append(method_info) # display all groups and methods for group in guiMethods: if len (group.split('.')) > 1: group_name = group.split('.')[0].encode('utf-8') sub_group = group.split('.')[1].encode('utf-8') if not self.groupbox_dict.has_key(group_name): self.groupbox_dict[group_name] = \ QtGui.QGroupBox(group_name.decode('utf-8'), self) self.groupbox_dict[group_name].setAlignment \ (QtCore.Qt.AlignLeft) if not self.layout_dict.has_key(group_name): self.layout_dict[group_name] = \ FlowLayout(self.groupbox_dict[group_name]) attrubute_list = [] sub_group_list = [] if self.button_list.has_key(sub_group): attrubute_list = self.button_list[sub_group][0] sub_group_list = self.button_list[sub_group][1] self.button_list[sub_group] = [] self.button_list[sub_group].append \ (attrubute_list + guiMethods[group]) sub_group_list.append(group.split('.',1)[1].encode('utf-8')) self.button_list[sub_group].append \ (sub_group_list) Button = ButtonMenu(sub_group, sub_group, \ 'folder-documents,folder', parent=self) Button.clicked.connect(self.groupActivated \ (self.button_list[sub_group][0], \ self.button_list[sub_group][1])) # try: # Button.setStatusTip(sub_group.decode('utf-8')) # except (UnicodeDecodeError, UnicodeEncodeError): # Button.setStatusTip(sub_group) self.button_list[sub_group].append(Button) continue if not self.groupbox_dict.has_key(group): self.groupbox_dict[group] = \ QtGui.QGroupBox(group, self) self.groupbox_dict[group].setAlignment(QtCore.Qt.AlignLeft) if not self.layout_dict.has_key(group): self.layout_dict[group] = FlowLayout(self.groupbox_dict[group]) for method_info in sorted(guiMethods[group], key=lambda x:x.title): #print method_info.status Button = ButtonMenu(method_info.name, method_info.title, method_info.icon, emblem=method_info.status, parent=self) Button.clicked.connect(self.onActivated) # try: # Button.setStatusTip(sub_group.decode('utf-8')) # except (UnicodeDecodeError, UnicodeEncodeError): # Button.setStatusTip(sub_group) if not self.button_list.has_key(group): self.button_list[group] = [] self.button_list[group].append(Button) self.layout_dict[group].addWidget \ (self.button_list[group]\ [len(self.button_list[group]) - 1]) self.layout_dict[group].setAlignment(QtCore.Qt.AlignLeft | \ QtCore.Qt.AlignTop) self.groupbox_dict[group].setLayout(self.layout_dict[group]) keys_sort = guiMethods.keys() keys_sort.sort() for group in keys_sort: if len (group.split('.')) > 1: group_name = group.split('.')[0].encode('utf-8') sub_group = group.split('.')[1].encode('utf-8') # for i in range (20): # self.layout_dict[group_name].addWidget(ButtonMenu \ # ('gggggggg',\ # 'qqqqww wwwww', \ # 'code-block', \ # self)) self.layout_dict[group_name].addWidget \ (self.button_list[sub_group]\ [len(self.button_list[sub_group]) - 1]) self.layout_dict[group_name].setAlignment(QtCore.Qt.AlignLeft) if self.groupbox_dict[group_name]: self.groupbox_dict[group_name].setLayout \ (self.layout_dict[group_name]) if self.groupbox_dict[group_name]: self.layout.addWidget(self.groupbox_dict[group_name]) self.groupbox_dict[group_name] = None continue elif self.groupbox_dict[group]: self.layout.addWidget(self.groupbox_dict[group]) self.groupbox_dict[group] = None self.layout.setAlignment(QtCore.Qt.AlignTop) self.setLayout(self.layout) self.resize(self.layout.sizeHint()) def refresh(self): results = self.ClientObj.methods_list self.initUI(results) self.ClientObj.app.processEvents() self.ClientObj.MainWidget.left_frame.cur_palette = \ self._parent.main_frame.viewport().palette() self.ClientObj._parent.setWindowTitle(_("Calculate Console")) def onActivated(self): # Call server method if hasattr (self, 'onActivated_thread'): if self.onActivated_thread.isRunning(): return 1 self.setDisabled(True) method_name = self.sender().objectName() # view_method_name = self.sender().text() step = 0 brief = False self.ClientObj.method_name = method_name self.ClientObj.sid = get_sid(self.ClientObj.client) if self.ClientObj.param_objects.has_key(method_name): self.ClientObj.param_objects[method_name]['step'] = 0 view_params = get_view_params(self.ClientObj.client, \ str(method_name + '_view'), step = step, brief = brief) self.onActivated_thread = ClientServiceThread(self.ClientObj, \ str(method_name + '_view'), int(self.ClientObj.sid), \ view_params, return_except = True) self.onActivated_thread.signal.connect(self.onActivated_after) self.onActivated_thread.start() def onActivated_after(self, view): self.setDisabled(False) #self.con_lost_lbl.hide() 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__() show_msg(msg) return 1 method_name = self.ClientObj.method_name self._parent.main_frame.viewport().setStyleSheet('') # set new Title if self.ClientObj.method_names.has_key(method_name): view_method = self.ClientObj.method_names[method_name] else: view_method = method_name self.ClientObj._parent.setWindowTitle \ (view_method + ' - ' + self.ClientObj._parent.windowTitle()) self.ClientObj.MainWidget.main_frame_view(view, method_name) def groupActivated(self, groups, sub_group, back = False): def wrapper(): self._parent.main_frame.viewport().setStyleSheet('') self.ClientObj.MainWidget.delete_MainFrameWgt() self.ClientObj.MainWidget.MainFrameWgt = \ QtGui.QWidget(self.ClientObj.MainWidget) if not back: # save data for a step back self.ClientObj.back_step_list.append ([groups, sub_group, \ self.ClientObj._parent.windowTitle()]) hlayout = QtGui.QHBoxLayout() hlayout.addItem(QtGui.QSpacerItem( 0, 0, \ QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)) self.ClientObj.MainWidget.MainFrameWgt.setLayout(hlayout) self.ClientObj.MainWidget.main_frame.setWidget \ (self.ClientObj.MainWidget.MainFrameWgt) self.ClientObj.MainWidget.main_frame.setWidgetResizable(True) self.ClientObj.MainWidget.left_frame.update() self.ClientObj.MainWidget.left_frame.show() try: new_title = sub_group[0].split('.')[0].decode('utf-8') except (UnicodeDecodeError, UnicodeEncodeError): pass if self.ClientObj.MainWidget.left_frame.old_title: self.ClientObj._parent.setWindowTitle(new_title +' - '+ \ self.ClientObj.MainWidget.left_frame.old_title) else: self.ClientObj._parent.setWindowTitle(new_title + ' - ' + \ self.ClientObj._parent.windowTitle()) self.ClientObj.MainWidget.left_frame.create_menu \ (self, groups, sub_group, self.ClientObj) return wrapper def closeEvent(self, event): self._parent.main_frame.viewport().setStyleSheet ('') if hasattr (self, 'onActivated_thread'): if self.onActivated_thread.isRunning(): self.onActivated_thread.close() self.onActivated_thread.wait() event.accept() class StartWidget(QtGui.QWidget): def __init__(self, parent): super(StartWidget, self).__init__(parent) self.setAttribute(QtCore.Qt.WA_DeleteOnClose) class ConnectLostLabel (QtGui.QWidget): def __init__(self, text, parent, reconnect = False): QtGui.QWidget.__init__(self, parent.layout_wgt) self._parent = parent if parent.main_frame.isEnabled(): parent.left_frame.setDisabled(True) parent.main_frame.setDisabled(True) parent.control_button.setDisabled(True) white_layout = QtGui.QVBoxLayout(self) lbl = QtGui.QLabel(text + '\n\n', self) white_layout.addWidget(lbl) self.setStyleSheet ('background-color: rgba(250,250,250,200);' 'border-radius: 2px;') if reconnect: self.reconnect_button = QtGui.QPushButton(_('Reconnect'), self) self.reconnect_button.setIcon(QtGui.QIcon.fromTheme('view-refresh')) self.reconnect_button.setStyleSheet(''' QPushButton { border: 2px solid #8f8f91; border-radius: 6px; background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #f6f7fa, stop: 1 #dadbde); min-width: 80px; } QPushButton:pressed { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #dadbde, stop: 1 #f6f7fa);} QPushButton:flat {border: none;} QPushButton:default {border-color: navy;} ''') self.reconnect_button.clicked.connect \ (self._parent.reconnect_to_host) self.reconnect_button.move(parent.layout_wgt.size().width()/2 - \ self.reconnect_button.sizeHint().width()/2,\ parent.layout_wgt.size().height()/2 + \ self.reconnect_button.sizeHint().height()) self.reconnect_button.resize(self.reconnect_button.sizeHint() + \ QtCore.QSize(5,5)) self.reconnect_button.show() self.reconnect_button.setEnabled(True) lbl.setAlignment(QtCore.Qt.AlignCenter) self.move(-10,-10) self.resize(parent.layout_wgt.size() + QtCore.QSize(20,20)) self.setEnabled(True) def resize_widget(self): cur_size = self._parent.size() self.resize(cur_size + QtCore.QSize(20,20)) if hasattr (self, 'reconnect_button'): self.reconnect_button.move(cur_size.width()/2 - \ self.reconnect_button.sizeHint().width()/2,\ cur_size.height()/2 + \ self.reconnect_button.sizeHint().height())