#!/usr/bin/python #-*- coding: utf-8 -*- # Copyright 2012 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 import urllib2 from calculate.core.client.function import switch from more import get_sid, ClientServiceThread, show_msg, ErrorWgt, ResultLayout from more import LabelWordWrap as Label class LabelWordWrap(Label): def __init__(self, name, parent = None): Label.__init__(self, name, parent) # set text selectable self.setTextInteractionFlags(self.textInteractionFlags() | \ QtCore.Qt.TextSelectableByMouse) class TaskWidget(QtGui.QWidget): def __init__(self, taskNumber = 1, parent = None): QtGui.QWidget.__init__(self) layout = QtGui.QGridLayout(self) self.text_lbl = LabelWordWrap('', self) layout.addWidget(self.text_lbl, 0, 0) layout.setContentsMargins(0,4,0,4) layout.setSpacing(10) self.image_lbl = QtGui.QLabel(self) self.image_lbl.setFixedSize(16,16) layout.addWidget(self.image_lbl, 0, 1) self.progressbar = QtGui.QProgressBar(self) layout.addWidget(self.progressbar, 1, 0, 1, 2) self.set_status = False self.task_number = taskNumber self.coef_for_one_part = 1 / float(taskNumber) self.coef_perc = 1 self.completed_parts = 0 self.completed_perc = 0 self.part_current_task = 1 def set_ok(self): if not self.set_status: i_path = '/usr/share/icons/Calculate/16x16/client-gui/console_ok' icon = QtGui.QIcon(i_path) self.image_lbl.setPixmap(icon.pixmap(16)) self.set_status = True def set_error(self): if not self.set_status: i_path = '/usr/share/icons/Calculate/16x16/client-gui/'\ 'console_cancel' icon = QtGui.QIcon(i_path) self.image_lbl.setPixmap(icon.pixmap(16)) self.set_status = True def setText(self, text): self.text_lbl.setText(text) def setProgress(self, perc): if perc > 100: perc = 100 elif perc < 0: perc = 0 - perc cur_perc = self.completed_perc + self.coef_perc * perc self.progressbar.setValue(cur_perc) def endCurrentTask(self): self.completed_parts += self.part_current_task self.completed_perc = 100*self.completed_parts/float(self.task_number) if self.completed_parts >= self.task_number: self.progressbar.hide() self.set_ok() def setCurrentCount(self, count): if count > (self.task_number - self.completed_parts): count = self.task_number - self.completed_parts self.part_current_task = count # calculate coef for this task self.coef_perc = count * self.coef_for_one_part class ShortFrameRes(QtGui.QWidget): valSignal = QtCore.Signal() def __init__(self, parent, ClientObj, method_name, meth_result): # super(ShortFrameRes, self).__init__(self, parent) QtGui.QWidget.__init__(self, 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 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.valSignal.connect(ClientObj.MainWidget.setScrollBarVal) self.progress_list = [] self.task_list = [] self._parent.methodname_wgt.show() self._parent.control_button.show() self._parent.control_button.del_button() if self.ClientObj.method_names.has_key(self.method_name): 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: #E4E1E0;}") self.setObjectName('Frame_Res') self.setStyleSheet("#Frame_Res {background-color: transparent;}") def initUI(self): self.updateGeometry() ################# API FUNCTION ############################### def show_view(self, view): pass def show_normal(self, message): # add normal message label if hasattr (self, 'taskWidget'): self.taskWidget.setText(message) else: if message: # add normal message label lbl_temp = LabelWordWrap(message, self) lbl_temp.setMinimumHeight(lbl_temp.sizeHint().height()) self.work_layout._addWidget(lbl_temp) self.initUI() def show_error(self, message): # add error message label # if self.progress_list: # self.progress_list[len(self.progress_list)-1].hide() lbl_temp = ErrorWgt(message, self) lbl_temp.set_error() lbl_temp.setMinimumHeight(lbl_temp.sizeHint().height()) self.work_layout._addWidget(lbl_temp) if hasattr (self, 'taskWidget'): self.taskWidget.set_error() self.initUI() def show_warning(self, item): # add warning message label lbl_temp = ErrorWgt(item.message, self) lbl_temp.set_warning() self.work_layout._addWidget(lbl_temp) self.initUI() def show_group(self, item): 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 startTask(self, item): if not hasattr (self, 'taskWidget'): self.taskWidget = TaskWidget(1, self) self.work_layout._addWidget(self.taskWidget) self.taskWidget.setText(item.message) self.taskWidget.setCurrentCount(item.id) self.initUI() def setTaskNumber(self, number): self.taskWidget = TaskWidget(int(number), self) self.work_layout._addWidget(self.taskWidget) self.initUI() def endTask(self, item): 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,"taskWidget"): self.taskWidget.endCurrentTask() if item.message: self.taskWidget.setText(item.message) self.initUI() def beginFrame(self, item): pass def endFrame(self, item): self.work_layout.hide_kill_button() self.close_all_thread() if hasattr (self, 'taskWidget'): self.taskWidget.endCurrentTask() if item.message: self.taskWidget.setText(item.message) self._parent.control_button.add_clear_cache_button(self.cur_pid) self.initUI() # 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: # show_msg (_('Error clear process cache on server')) # else: # self._parent.back() def startGroup(self, item): pass def endGroup(self, item): pass def callView(self, item, sid): return 0 def kill_process(self, pid): def wrapper(): sid = int(self.ClientObj.sid) # 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 self.cur_pid != pid: return 1 except: return 1 """ get one message by its type """ for case in switch(item.type): if case('normal'): self.show_normal(item.message) 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'): return 1 if case('group'): self.show_group(sid, pid, item) return 1 if case('question'): self.send_Message(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.setTaskNumber(item.message) return 1 if case('endTask'): self.endTask(item) return 1 if case('beginFrame'): self.beginFrame(item) return 1 if case('endFrame'): self.endFrame(item) return 0 if case('startGroup'): self.startGroup(item) return 1 if case('endGroup'): self.endGroup(item) return 1 if case('briefParams'): self.callView(item, sid) 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 """ 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, 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_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') return 1 sid, pid = through_object if current_frame in [None, [], ""]: try: if self.cur_pid != pid: return 1 except: return 1 else: 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() self.get_Frame_thread = ClientServiceThread(self.ClientObj,\ 'get_frame', sid, pid, return_except = True, \ sleeptime = int(self.ClientObj.client.frame_period),\ 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) 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 urllib2.URLError, e: 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) 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 get_Progress(self, sid, pid, id): if not hasattr (self, 'taskWidget'): self.taskWidget = TaskWidget(1, self) self.work_layout._addWidget(self.taskWidget) self.initUI() """ get progress for the current job """ 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)) self.get_Progress_thread.signal_extended.connect(self.get_Progress_cycle) self.get_Progress_thread.start() def get_Progress_cycle(self, returnProgr, through_object): 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') return 1 sid, pid, id, temp_progress = through_object ######################################## percent = returnProgr.percent if percent <= 100 and percent >= 0: if temp_progress != percent: if percent: # progressBar.setProperty("value", 100) if not hasattr (self, 'taskWidget'): return 1 self.taskWidget.setProgress(percent) if returnProgr.long_message: self.show_normal(returnProgr.long_message) elif returnProgr.short_message: self.show_normal(returnProgr.short_message) if percent == 100: return 0 self.initUI() temp_progress = percent try: if self.cur_pid != pid: return 1 except: return 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,\ sleeptime = 1, through_object = \ (sid, pid, id, temp_progress)) self.get_Progress_thread.signal_extended.connect \ (self.get_Progress_cycle) self.get_Progress_thread.start() if percent < 0: returnProgr.percent = 0 - percent if not hasattr (self, 'taskWidget'): return 1 self.taskWidget.setProgress(percent) self.ClientObj.app.processEvents() self.initUI() def send_Message(self, sid, pid, item): """ send answer to the question """ self.message = MessageDialog(self, item, sid, pid) 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 closeEvent(self, event): self.cur_pid = 'no' self.close_all_thread() self._parent.methodname_wgt._hide() self._parent.control_button._hide() event.accept() class MessageDialog(QtGui.QWidget): # answer to the server question def __init__(self, parent, item, sid, pid, isPassword = False): super(MessageDialog, self).__init__() self._parent = parent # self.item = item self.sid = sid self.pid = pid self.layout = QtGui.QGridLayout(self) self.label = LabelWordWrap(item.message, self) self.pass_edit = QtGui.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: self.pass_edit2 = QtGui.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) self.pass_edit2.textChanged.connect(self.check_passwd) self.send_button = QtGui.QPushButton(_('Send'), self) self.send_button.setShortcut(QtGui.QKeySequence(QtCore.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 (QtCore.Qt.WindowMinimizeButtonHint) # self.setAttribute(QtCore.Qt.WA_ShowModal) def send_password(self): answer = self.pass_edit.text() if 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)