class Timer(): def __init__(self): self.time = QTime() self.time.start() self.cur_time = timedelta(milliseconds=self.time.elapsed()) # self.stop_time = self.time. # self.cur_time = self.stop_time - self.time def update_elapsed_time(self): self.cur_time = timedelta(milliseconds=self.time.elapsed())
def startPro(self): print("startPro") task_list = IM.getLocalTask(self) queue = Queue() for task in task_list: queue.put(task) self.pool.setMaxThreadCount(int(self.spinBoxProNum.value())) while True: if queue.empty(): print("备份队列为空") task = None else: print("取备份任务") bak_info = queue.get_nowait() task = Task() task.task_info = json.loads(bak_info.get("task_info")) task.user_info = json.loads(bak_info.get("user_info")) task.uids = json.loads( bak_info.get("uids")) if bak_info.get("uids") else None task.status = 1 othread = mThread() othread.transfer(task=task, communicate=self.communicate) def setStatus(items): self.model.item(items["index"], 4).setText(items["status"]) self.communicate.connect(setStatus) self.pool.start(othread) time = QTime() time.start() while time.elapsed() < 5000: QCoreApplication.processEvents()
def readUntil(self, expected=b"\n", size=None): r""" Public method to read data until an expected sequence is found (default: \n) or a specific size is exceeded. @param expected expected bytes sequence @type bytes @param size maximum data to be read @type int @return bytes read from the device including the expected sequence @rtype bytes """ data = bytearray() self.__timedOut = False t = QTime() t.start() while True: QCoreApplication.processEvents(QEventLoop.ExcludeUserInputEvents) c = bytes(self.read(1)) if c: data += c if data.endswith(expected): break if size is not None and len(data) >= size: break if t.elapsed() > self.__timeout: self.__timedOut = True break return bytes(data)
class Controller: def __init__(self): self.qt_app = QApplication(sys.argv) self.model = Model() self.view = View() self.view.button.clicked.connect(self.update_model) self.model.signal.connect(self.update_view) signal.signal(signal.SIGINT, self.keyboardInterruptHandler) self.time = QTime() timer = QTimer() timer.timeout.connect(lambda: None) timer.start(100) self.qt_app.exec() def update_model(self): self.time.start() self.model.setdata(self.view.getdata()) def update_view(self): print("--- DONE IN {}ms ---".format(self.time.elapsed())) self.time.restart() self.view.setdata(self.model.getdata()) def keyboardInterruptHandler(self, signal, frame): self.qt_app.exit()
class DigitalClock(QLCDNumber): def __init__(self): super(DigitalClock, self).__init__(8) self.setSegmentStyle(QLCDNumber.Filled) self.timer = QTimer() self.timer.timeout.connect(self.showTime) self.time = QTime(0, 0, 0) text = self.time.toString("hh:mm:ss") self.display(text) def start(self): self.time = QTime(0, 0, 0) self.time.start() self.timer.start(1000) def stop(self): self.timer.stop() @pyqtSlot() def showTime(self): # print(self.time.elapsed()) tt = QTime(0, 0, 0) tt = tt.addMSecs(self.time.elapsed()) text = tt.toString("hh:mm:ss") # print(text) self.display(text)
def on_btnProgress_clicked(self): labText = "正在复制文件..." #文字信息 btnText = "取消" #"取消"按钮的标题 minV = 0 maxV = 200 dlgProgress = QProgressDialog(labText, btnText, minV, maxV, self) dlgProgress.canceled.connect(self.do_progress_canceled) #canceled信号 dlgProgress.setWindowTitle("复制文件") dlgProgress.setWindowModality(Qt.WindowModal) #模态对话框 dlgProgress.setAutoReset( True) #calls reset() as soon as value() equals maximum() dlgProgress.setAutoClose( True) #whether the dialog gets hidden by reset() msCounter = QTime() #计时器 for i in range(minV, maxV + 1): dlgProgress.setValue(i) dlgProgress.setLabelText("正在复制文件,第 %d 个" % i) msCounter.start() #计时器重新开始 while (msCounter.elapsed() < 30): #延时 30ms None if (dlgProgress.wasCanceled()): #中途取消 break
class AutoSaver(QObject): """ Class implementing the auto saver. """ AUTOSAVE_IN = 1000 * 3 MAXWAIT = 1000 * 15 def __init__(self, parent, save): """ Constructor @param parent reference to the parent object (QObject) @param save slot to be called to perform the save operation @exception RuntimeError raised, if no parent is given """ super(AutoSaver, self).__init__(parent) if parent is None: raise RuntimeError("AutoSaver: parent must not be None.") self.__save = save self.__timer = QBasicTimer() self.__firstChange = QTime() def changeOccurred(self): """ Public slot handling a change. """ if self.__firstChange.isNull(): self.__firstChange.start() if self.__firstChange.elapsed() > self.MAXWAIT: self.saveIfNeccessary() else: self.__timer.start(self.AUTOSAVE_IN, self) def timerEvent(self, evt): """ Protected method handling timer events. @param evt reference to the timer event (QTimerEvent) """ if evt.timerId() == self.__timer.timerId(): self.saveIfNeccessary() else: super(AutoSaver, self).timerEvent(evt) def saveIfNeccessary(self): """ Public method to activate the save operation. """ if not self.__timer.isActive(): return self.__timer.stop() self.__firstChange = QTime() self.__save()
def _run_hid(self): runner_started_at = QTime() runner_started_at.start() auto_restart = False self._running = True try: h = self._hidapi.device() if self._hid_dev["path"]: Logger.log("d", "Trying to open %s", self._hid_dev["path"].decode("utf-8")) h.open_path(self._hid_dev["path"]) else: Logger.log("d", "Trying to open [%x,%x]", self._hid_dev["vendor_id"], self._hid_dev["product_id"]) h.open(self._hid_dev["vendor_id"], self._hid_dev["product_id"]) Logger.log("i", "Manufacturer: %s", h.get_manufacturer_string()) Logger.log("i", "Product: %s", h.get_product_string()) #Logger.log("i", "Serial No: %s", h.get_serial_number_string()) self._last_camera_update_at = QTime() self._last_camera_update_at.start() self._fast_view = False while self._running: if self._main_window: d = h.read(64, 50 if self._fast_view else 1000) if d: if self._main_window.isActive(): self._decoder(d) elif self._fast_view: self._controller.setActiveView("SimulationView") self._fast_view = False else: self._getComponents() time.sleep(0.1) h.close() except IOError as e: Logger.log("e", "IOError while reading HID events: %s", e) auto_restart = (sys.platform == "win32") except Exception as e: Logger.log("e", "Exception while reading HID events: %s", e) self._running = False if auto_restart: # throttle restarts to avoid hogging the CPU min_restart_seconds = 5 run_time = runner_started_at.elapsed() / 1000 if run_time < min_restart_seconds: Logger.log("d", "Delaying restart...") time.sleep(min_restart_seconds - run_time) if not self._running: self._runner = None self._restart() else: self._runner = None
def receive(self) -> str: time = QTime() time.start() data = "" while time.elapsed() <= self.long_timeout: if not self.waitForReadyRead(self.short_timeout): break line = str(bytes(self.readAll()).decode()) # if line == "": # break data += line return data
class QmyWidget(QWidget): def __init__(self, parent=None): super().__init__(parent) #调用父类构造函数,创建窗体 self.ui = Ui_Widget() #创建UI对象 self.ui.setupUi(self) #构造UI界面 self.timer = QTimer() #创建定时器 self.timer.stop() #停止 self.timer.setInterval(1000) #定时周期1000ms self.timer.timeout.connect(self.do_timer_timeout) self.counter = QTime() #创建计时器 ## =========由connectSlotsByName() 自动连接的槽函数============= def on_btnStart_clicked(self): ##“开始”按钮 self.timer.start() #开始定时 self.counter.start() #开始计时 self.ui.btnStart.setEnabled(False) self.ui.btnStop.setEnabled(True) self.ui.btnSetIntv.setEnabled(False) def on_btnSetIntv_clicked(self): ##设置定时器的周期 self.timer.setInterval(self.ui.spinBoxIntv.value()) def on_btnStop_clicked(self): ##“停止”按钮 self.timer.stop() #定时器停止 tmMs = self.counter.elapsed() #计时器流逝的毫秒数 ms = tmMs % 1000 #取余数,毫秒 sec = tmMs / 1000 #整秒 timeStr = "流逝的时间:%d 秒,%d 毫秒" % (sec, ms) self.ui.LabElapsedTime.setText(timeStr) self.ui.btnStart.setEnabled(True) self.ui.btnStop.setEnabled(False) self.ui.btnSetIntv.setEnabled(True) ## ==========自定义槽函数================================== def do_timer_timeout(self): ##定时中断响应 curTime = QTime.currentTime() #获取当前时间 self.ui.LCDHour.display(curTime.hour()) self.ui.LCDMin.display(curTime.minute()) self.ui.LCDSec.display(curTime.second())
class QmyWidget(QWidget): def __init__(self, parent=None): super().__init__(parent) #调用父类构造函数,创建窗体 self.ui = Ui_Widget() #创建Ui对象 self.ui.setupUi(self) #构造UI self.timer = QTimer() #创建定时器 self.timer.stop() self.timer.setInterval(100) #设定周期 self.timer.timeout.connect(self.do_timer_timeout) self.counter = QTime() ##==========自定义功能函数========== ##==========事件处理函数=========== ##==========由connectSlotsByName()自动关联的槽函数==== def on_btnStart_clicked(self): self.timer.start() self.counter.start() self.ui.btnStart.setEnabled(False) self.ui.btnStop.setEnabled(True) self.ui.btnSetIntv.setEnabled(False) def on_btnStop_clicked(self): self.timer.stop() tmMs = self.counter.elapsed() #计时器经过的时间 ms = tmMs % 1000 #毫秒 sec = tmMs / 1000 #秒 timeStr = "经过的时间:{}秒,{}毫秒".format(sec, ms) self.ui.LabElapsedTime.setText(timeStr) self.ui.btnStart.setEnabled(True) self.ui.btnStop.setEnabled(False) self.ui.btnSetIntv.setEnabled(True) def on_btnSetIntv_clicked(self): self.timer.setInterval(self.ui.spinBoxIntv.value()) ##=========自定义槽函数============ def do_timer_timeout(self, ): curTime = QTime.currentTime() self.ui.LCDHour.display(curTime.hour()) self.ui.LCDMin.display(curTime.minute()) self.ui.LCDSec.display(curTime.second())
def fill_polygon(win): t = QTime() pix = QPixmap() p = QPainter() t.start() xm = int(find_max_x(win.edges)) p.begin(win.image) for ed in win.edges: x1, y1 = ed[0], ed[1] x2, y2 = ed[2], ed[3] if y1 == y2: continue if y1 > y2: y1, y2 = y2, y1 x1, x2 = x2, x1 cur_y = y1 end_y = y2 dx = (x2 - x1) / (y2 - y1) start_x = x1 while cur_y < end_y: x = start_x while x < xm: activate_pixel(win, p, x, cur_y) p.drawPoint(x, cur_y) x += 1 start_x += dx cur_y += 1 if win.delay.isChecked(): delay(win, pix) pix.convertFromImage(win.image) win.scene.addPixmap(pix) p.end() displaytime(win, t.elapsed()) draw_edges(win.image, win.edges)
def on_qPushButton7_clicked(self): labText = "正在复制文件..." btnText = "取消" minV = 0 maxV = 200 dlgProgress = QProgressDialog(labText, btnText, minV, maxV, self) dlgProgress.canceled.connect(self.do_progress_cancled) dlgProgress.setWindowTitle("复制文件") dlgProgress.setWindowModality(Qt.WindowModal) dlgProgress.setAutoReset(True) dlgProgress.setAutoClose(True) msCounter = QTime() for i in range(minV, maxV + 1): dlgProgress.setValue(i) dlgProgress.setLabelText("正在复制文件,第 %d 个" % i) msCounter.start() while (msCounter.elapsed() < 30): None if (dlgProgress.wasCanceled()): break
def on_btn2_1_click(self): video = cv2.VideoCapture('D:/data/bgSub.mp4') if not video.isOpened(): print('video not found') return w = None subtractor = cv2.createBackgroundSubtractorMOG2()#detectShadows=False) t = QTime() t.start() while video.isOpened(): ret, frame = video.read() if ret: fg = subtractor.apply(frame) if w is None: w = MultiImageWindow( title='2.1 Background Subtraction', images=[frame, fg]) w.show() self.addWidget(w) else: w.setImage(frame, 0) w.setImage(fg, 1) w.update() t.restart() while t.elapsed() < 33: QApplication.processEvents() else: break video.release()
class QmyWidget(QWidget): def __init__(self, parent=None): super().__init__(parent=parent) self._ui = Ui_Widget() self._ui.setupUi(self) self._timer = QTimer() self._timer.stop() self._timer.setInterval(1000) self._timer.timeout.connect(self.my_timer_timeout) self._counter = QTime() def on_pushButton_Start_clicked(self): self._timer.start() self._counter.start() self._ui.pushButton_Start.setEnabled(False) self._ui.pushButton_Stop.setEnabled(True) self._ui.pushButton_SetTime.setEnabled(False) def on_pushButton_Stop_clicked(self): self._timer.stop() tms = self._counter.elapsed() ms = tms % 1000 sec = tms / 1000 timerstr = f'当前经过时间:{sec}s {ms}ms' self._ui.label_Reduce.setText(timerstr) self._ui.pushButton_Start.setEnabled(True) self._ui.pushButton_Stop.setEnabled(False) self._ui.pushButton_SetTime.setEnabled(True) def on_pushButton_SetTime_clicked(self): self._timer.setInterval(self._ui.timeEdit.value()) def my_timer_timeout(self): curTime = QTime.currentTime() self._ui.lcdNumber_Hour.display(curTime.hour()) self._ui.lcdNumber_Minute.display(curTime.minute()) self._ui.lcdNumber_Second.display(curTime.second())
class QmyWidget(QtWidgets.QWidget): def __init__(self, parent=None): super().__init__(parent) self.ui = Ui_Widget() self.ui.setupUi(self) self.timer = QTimer() self.timer.stop() self.timer.setInterval(1000) self.timer.timeout.connect(self.do_timer_timeout) self.count = QTime() def on_qPushButton1_clicked(self): self.timer.start() self.count.start() self.ui.qPushButton1.setEnabled(False) self.ui.qPushButton2.setEnabled(True) self.ui.qPushButton3.setEnabled(False) def on_qPushButton2_clicked(self): self.timer.stop() tm = self.count.elapsed() ms = tm % 1000 s = tm // 1000 self.ui.qLabel.setText("流逝的时间:%d秒 %d毫秒" % (s, ms)) self.ui.qPushButton1.setEnabled(True) self.ui.qPushButton2.setEnabled(False) self.ui.qPushButton3.setEnabled(True) def on_qPushButton3_clicked(self): self.timer.setInterval(self.ui.qSpinBox.value()) def do_timer_timeout(self): curTime = QTime.currentTime() self.ui.qLCDNumber1.display(curTime.hour()) self.ui.qLCDNumber2.display(curTime.minute()) self.ui.qLCDNumber3.display(curTime.second())
class MySimpleTimer(QtWidgets.QLabel): def __init__(self): super(MySimpleTimer, self).__init__() self.time = QTime( ) # we set the clock to 0; otherwise it'll copy the computer time # format = h, m, s, msec self.time.start() # starting up the clock! timer = QTimer(self) # when 1000 msec expires; to something & refresh timer.timeout.connect(self.update_seconds) timer.start(1000) self.update_seconds() #so things don't look fishy? def update_seconds(self): elapsed_seconds, _ = divmod(self.time.elapsed(), 1000) m, s = divmod(elapsed_seconds, 60) h, m = divmod(m, 60) to_print_str = (f'{m:02d}:{s:02d}') # Python 3.6+ if h > 0: to_print_str = (f'{h:02d}:{m:02d}:{s:02d}') # Python 3.6+ self.setText(to_print_str)
class TcpS(QDialog, Ui_TcpServer): """ 文件传输服务器 """ sendFileName = pyqtSignal(str) def __init__(self, parent=None): """ 一些初始设置 """ super(TcpS, self).__init__(parent) self.setupUi(self) self.payloadSize = 64 * 1024 # 读取数据64KB self.totalBytes = 0 # 总大小 self.bytesWritten = 0 # 保存的数据 self.bytesToWrite = 0 # 每次减少连接写的数据量大小 self.theFileName = "" # 文件名(不含路径) self.fileName = "" # 文件全名 self.localFile = QFile() self.outBlock = QByteArray() # QByteArray()的对象,即字节数组 self.time = QTime() self.initServer() def initServer(self): """ 网络设置初始化 """ self.tcpPort = 7788 # 指定了TCP端口为7788 self.tcpServer = QTcpServer(self) self.clientConnection = QTcpSocket(self) # 创建一个Tcp服务器和一个Tcp套接字 self.tcpServer.newConnection.connect(self.sendMessage) # 当有新的连接来的时候发出newConnection信号,我们连接到sendMessage()函数。 self.serverStatuslabel.setText("请选择要传送的文件") self.progressBar.reset() self.serverOpenBtn.setEnabled(True) self.serverSendBtn.setEnabled(False) self.tcpServer.close() # 显示我们开始创建的对话框,打开按钮是可用的,发送按钮是不可用的,进度条复位,先关闭服务器。 def refused(self): """ 对端拒绝接收文件,主程序会调用服务器的refused()函数,关闭服务器。 """ self.tcpServer.close() self.serverStatuslabel.setText("对方拒绝接收") def closeEvent(self, event): """ 关闭事件 """ self.on_serverCloseBtn_clicked() # 产生关闭事件,直接调用关闭窗口按钮函数。 def sendMessage(self): """ 发送文件 """ self.serverSendBtn.setEnabled(False) # 发送按钮不可用 self.clientConnection = self.tcpServer.nextPendingConnection() # self.clientConnection作为连接的QTcpSocket对象返回下一个挂起的连接。 self.clientConnection.bytesWritten.connect(self.updateClientProgress) # 当连接中每次将数据有效载荷写入设备的当前写通道时,都会发出此信号。在此有效负载中写入的数据量为字节数。 self.serverStatuslabel.setText("开始传送文件 {} !".format(self.theFileName)) self.localFile = QFile(self.fileName) if not (self.localFile.open(QFile.ReadOnly)): errorMsg = "无法读取文件 {}:\n {}".format(self.fileName, self.localFile.errorString()) QMessageBox.warning(self, "应用程序", errorMsg) return # 尝试打开文件,要是存在问题就报错。 self.serverCloseBtn.setText("取消") self.totalBytes = self.localFile.size() # 记录一下需要传输的文件大小。单位:字节 sendOut = QDataStream(self.outBlock, QIODevice.WriteOnly) # 这里的self.outBlock是QByteArray()的对象,即字节数组;QIODevice的模式为WriteOnly sendOut.setVersion(QDataStream.Qt_5_4) # 设定QDataStream的版本为Qt_5_4 self.time.start() # 开始计时 currentFile = self.fileName.split("/")[-1] # 传输的文件名 sendOut.writeInt64(0) sendOut.writeInt64(0) sendOut.writeQString(currentFile) self.totalBytes += self.outBlock.size() # 在sendOut中写入文件名以及文件名和文件的大小,大小都是以字节为单位的。 sendOut.device().seek(0) sendOut.writeInt64(self.totalBytes) sendOut.writeInt64(self.outBlock.size() - 2) # QIODevice读写位置移动到0。然后分别写入总的大小和文件名大小。 self.bytesToWrite = self.totalBytes - self.clientConnection.write( self.outBlock) # 待传输文件的大小。 self.outBlock.resize(0) # outBlock清零。 def updateClientProgress(self, numBytes): """ 发送进度显示 """ qApp.processEvents() # 长时间工作用,以免窗口假死 self.bytesWritten += numBytes if self.bytesWritten > 0: self.block = self.localFile.read( min(self.bytesToWrite, self.payloadSize)) self.bytesToWrite -= self.clientConnection.write(self.block) else: self.localFile.close() # 当我们待写入的字节数大于0时,我们每次读取的数据都是小于等于self.payloadSize的,这个self.payloadSize我们定义是64KB。 # self.bytesToWrite每次减少连接写的数据量大小。 # 要是待写入的字节数小于等于0,则关闭文件。 byteSent = self.bytesWritten / (1024 * 1024) # 已经写了多少文件 useTime = self.time.elapsed() / 1000 # 传输用了多长时间 speed = self.bytesWritten / useTime / (1024 * 1024) # 传输速度 total = self.totalBytes / (1024 * 1024) # 总大小 left = (total - byteSent) / speed # 表示剩余时间 if byteSent < 0.01: byteSent = self.bytesWritten / 1024 speed = self.bytesWritten / useTime / 1024 total = self.totalBytes / 1024 if left > 0: sendInfo = "已发送 {0:.2f}KB({1:.2f}KB/s)\n共{2:.2f}KB 已用时:{3:.1f}秒\n 估计剩余时间:{4:.1f}秒".format( byteSent, speed, total, useTime, left) else: sendInfo = "已发送 {0:.2f}KB({1:.2f}KB/s)\n共{2:.2f}KB 用时:{3:.1f}秒\n".format( byteSent, speed, total, useTime) else: if left > 0: sendInfo = "已发送 {0:.2f}MB({1:.2f}MB/s)\n共{2:.2f}MB 已用时:{3:.1f}秒\n 估计剩余时间:{4:.1f}秒".format( byteSent, speed, total, useTime, left) else: sendInfo = "已发送 {0:.2f}MB({1:.2f}MB/s)\n共{2:.2f}MB 用时:{3:.1f}秒\n".format( byteSent, speed, total, useTime) self.progressBar.setMaximum(total) self.progressBar.setValue(byteSent) if self.bytesWritten == self.totalBytes: self.serverCloseBtn.setText("关闭") # 进度条显示的方式,以及当传输的字节数等于总的字节数的时候,按钮就显示关闭。 self.serverStatuslabel.setText(sendInfo) @pyqtSlot() def on_serverOpenBtn_clicked(self): """ 打开文件准备发送 """ self.fileName = QFileDialog.getOpenFileName(self, '打开文件', './')[0] if self.fileName: self.theFileName = self.fileName.split("/")[-1] self.serverStatuslabel.setText("要传送的文件为:{}".format( self.theFileName)) self.serverSendBtn.setEnabled(True) self.serverOpenBtn.setEnabled(False) @pyqtSlot() def on_serverSendBtn_clicked(self): """ 发送文件,等待接收 """ if not (self.tcpServer.listen(QHostAddress.Any, self.tcpPort)): errorMsg = self.tcpServer.errorString() QMessageBox.warning(self, "错误", "发送失败:\n {}".format(errorMsg)) self.TcpServer.close() return self.serverStatuslabel.setText("等待对方接收... ...") self.serverSendBtn.setEnabled(False) self.sendFileName.emit(self.theFileName) @pyqtSlot() def on_serverCloseBtn_clicked(self): """ 取消或者关闭 """ if self.tcpServer.isListening(): self.tcpServer.close() if self.localFile.isOpen(): self.localFile.close() self.clientConnection.abort() if self.serverCloseBtn.text() == "取消": self.serverCloseBtn.setText("关闭") else: self.close() self.serverOpenBtn.setEnabled(True) self.serverSendBtn.setEnabled(False) self.progressBar.reset() self.totalBytes = 0 self.bytesWritten = 0 self.bytesToWrite = 0 self.serverStatuslabel.setText("请选择要传送的文件")
class Pricing_Validation_Main(QThread): """ Runs in thread. """ txtProgress = pyqtSignal(str) countProgress = pyqtSignal(int) currStatus = pyqtSignal(list) def __init__(self, src_folder, tgt_folder, keyword, templates, pt_model): super(Pricing_Validation_Main, self).__init__() self._src_folder = src_folder self._tgt_folder = tgt_folder self._keyword = keyword self._l_templates = templates self._pt_model = pt_model self._common_mod = Common_Model() self._pv_model = Pricing_Validation_Model(self._common_mod, self._pt_model) self.timer = QTime() self.elapsed_time = None self.is_running = True self._progress_count = 0 self._abort_flg = False self._cancel_flg = False self._main_dir = os.getcwd() self.preval_price_df = None def run(self): ''' Read source file to DataFrame and Excel file (for validation) Filter dataframe per Usage Type Perform Mappings Populate the validated dataframe to template ''' # Start timer self.timer.start() self.txtProgress.emit('Loading source file to dataframes.') success = False while not success: try: df_price_all = self._pv_model.read_source_to_DF( self._keyword, self._src_folder, 'Pricing') df_scales_all = self._pv_model.read_source_to_DF( self._keyword, self._src_folder, 'Scales') df_minf_all = self._pv_model.read_source_to_DF( self._keyword, self._src_folder, 'MINF') success = True except Exception as e: self.currStatus.emit([self._keyword, 'Load Source', str(e)]) response = None while response is None: response = self._pt_model.replyBtn time.sleep(1) if response == QMessageBox.Close: self._abort_flg = True self._pt_model.replyBtn = None success = True if not self._abort_flg: #Loop on the templates found for i in self._l_templates: usage_type = i[0] if self._cancel_flg: break status = self._pt_model.get_template_status(usage_type) if status == '': wb_name = 'OTC_{}_Pricing_Pre_Validation_Report_{}.xlsx'.format( usage_type, self._keyword.upper()) output_filenm = self._tgt_folder + "\\" + wb_name # Create a Pandas Excel writer using XlsxWriter as the engine. writer = pd.ExcelWriter( output_filenm, engine='xlsxwriter', options={'strings_to_numbers': False}) # Get the xlsxwriter workbook and worksheet objects. workbook = writer.book #Set workbook formats self._common_mod.set_workbook_formats(workbook) l_price_tabs = self._pv_model._config['PricingTabs'] success = False while not success: try: for d_tab in l_price_tabs: for k, v in d_tab.items(): tab = k template_sheet_name = v[ 'Template_Sheet_Name'] template_mapping_idx = v[ 'Template_Mapping_Index'] template_column_idx = v[ 'Template_Column_Index'] chart_sheet_name = v['Chart_Sheeet_Name'] details_sheet_name = v[ 'Details_Sheet_Name'] self.txtProgress.emit( 'Started: Processing {} - Initializing {} DataFrame.' .format(usage_type, tab)) #Filter dataframe if tab == 'Price': preval_df = df_price_all[ df_price_all['USAGE_TYPE_CD'] == usage_type] elif tab == 'Scale': preval_df = df_scales_all[ df_scales_all['USAGE_TYPE_CD'] == usage_type] else: preval_df = df_minf_all[ df_minf_all['USAGE_TYPE_CD'] == usage_type] #Initialize Pricing dataframe preval_df = self._pv_model.initialize_preval_df( preval_df, tab) self.txtProgress.emit( 'Finished: Processing {} - Initializing {} DataFrame.' .format(usage_type, tab)) time.sleep(3) #Read Template columns for mapping self.txtProgress.emit( 'Started: Processing {} - Get {} Template Column Mappings.' .format(usage_type, tab)) template_columns = self._pv_model.get_template_mappings( usage_type, template_sheet_name, template_mapping_idx) self.txtProgress.emit( 'Started: Processing {} - Get {} Template Column Mappings.' .format(usage_type, tab)) time.sleep(3) #Generate Price template DF self.txtProgress.emit( 'Started: Processing {} - Generating {} Template DataFrame.' .format(usage_type, tab)) if tab == 'Price': self.preval_price_df = preval_df.copy() template_df = self._pv_model.generate_template_df( usage_type, preval_df, template_sheet_name, template_columns, template_column_idx, tab) elif tab == 'Scale': merge_scale_price_df = self._pv_model.merge_scale_price_df( preval_df, self.preval_price_df) template_df = self._pv_model.generate_template_df( usage_type, merge_scale_price_df, template_sheet_name, template_columns, template_column_idx, tab, self.preval_price_df) else: merge_minf_price_df = self._pv_model.merge_minf_price_df( preval_df, self.preval_price_df) template_df = self._pv_model.generate_template_df( usage_type, merge_minf_price_df, template_sheet_name, template_columns, template_column_idx, tab, self.preval_price_df) self.txtProgress.emit( 'Finished: Processing {} - Generating {} Template DataFrame.' .format(usage_type, tab)) time.sleep(3) #Populate Summary Chart self.txtProgress.emit( 'Started: Processing {} - Populating {} Summary Chart.' .format(usage_type, tab)) print(template_df.columns.to_list()) self._pv_model.populate_summary_chart( usage_type, workbook, template_df, chart_sheet_name, template_column_idx) self.txtProgress.emit( 'Finished: Processing {} - Populating {} Summary Chart.' .format(usage_type, tab)) time.sleep(3) #Populate Details sheet self.txtProgress.emit( 'Started: Processing {} - Populating {} Details Sheet.' .format(usage_type, tab)) self._pv_model.populate_details_worksheet( writer, template_df, details_sheet_name, template_column_idx) self.txtProgress.emit( 'Finished: Processing {} - Populating {} Details Sheet.' .format(usage_type, tab)) time.sleep(3) #Generating Template Counts if not self._abort_flg: self.txtProgress.emit( 'Started: Processing {} - Generating Data Counts.' .format(usage_type)) data = { 'Source': 0, 'Template': preval_df.shape[0] } self._pt_model.append_template_logs( usage_type, 3, tab, data) self.txtProgress.emit( 'Finished: Processing {} - Generating Data Counts.' .format(usage_type)) success = True except Exception as e: self.currStatus.emit([ usage_type, 'Populate Worksheet', tab, str(e) ]) response = None while response is None: response = self._pt_model.replyBtn time.sleep(1) if response == QMessageBox.Abort: self._abort_flg = True self._pt_model.replyBtn = None success = True elif response == QMessageBox.Retry: self._pt_model.replyBtn = None workbook.close() elif response == QMessageBox.Ignore: self._pt_model.update_template_status( usage_type, 'i') self._pt_model.replyBtn = None success = True elif response == QMessageBox.Close: self._abort_flg = True self._pt_model.replyBtn = None success = True if self._cancel_flg: break #Save to workbook in output folder status = self._pt_model.get_template_status(usage_type) if status == '' and not self._abort_flg: success = False while not success: try: self.txtProgress.emit( 'Started: Processing {} - Saving Workbook to Output Folder.' .format(usage_type)) writer.save() self.txtProgress.emit( 'Finished: Processing {} - Saving Workbook to Output Folder.' .format(usage_type)) time.sleep(3) #Update Status self._pt_model.update_template_status( usage_type, 'c') success = True except Exception as e: self.currStatus.emit([ usage_type, 'Save Template', wb_name, str(e) ]) response = None while response is None: response = self._pt_model.replyBtn time.sleep(1) if response == QMessageBox.Abort: self._abort_flg = True self._pt_model.replyBtn = None success = True elif response == QMessageBox.Retry: self._pt_model.replyBtn = None elif response == QMessageBox.Ignore: self._pt_model.update_template_status( usage_type, 'i') self._pt_model.replyBtn = None success = True elif response == QMessageBox.Close: self._abort_flg = True self._pt_model.replyBtn = None success = True else: workbook.close() self._progress_count += 1 self.countProgress.emit(self._progress_count) ### Display Elapsed Time ### self.update_elapsed_time() self.txtProgress.emit('Finished') def update_elapsed_time(self): secs = self.timer.elapsed() / 1000 mins = (secs / 60) % 60 hours = (secs / 3600) seconds = secs % 60 self.elapsed_time = str(hours).split('.')[0] + ' Hours ' + str( mins).split('.')[0] + ' Minutes ' + str(seconds).split( '.')[0] + ' Seconds'
class QOpenGLControllerWidget(QOpenGLWidget): """Widget that sets up specific OpenGL version profile.""" def __init__(self, versionprofile=None, *args, **kwargs): """Initialize OpenGL version profile.""" super(QOpenGLControllerWidget, self).__init__(*args, **kwargs) self.versionprofile = versionprofile self.timer = QTimer() self.timer.setInterval(0) self.timer.start() self.timer.timeout.connect(self.update) self.frame_count = 0 self.fps_timer = QTime() def initializeGL(self): """Apply OpenGL version profile and initialize OpenGL functions.""" print('Opengl Version : ', glGetString(GL_VERSION)) self.rendering_program = shaders.compile_shaders( 'graph.v.glsl', 'graph.f.glsl') self.vertex_array_object = glGenVertexArrays(1) glBindVertexArray(self.vertex_array_object) def paintGL(self): self._update_fps() """Painting callback that uses the initialized OpenGL functions.""" now = time.time() * 5 color = np.array( [np.sin(now) * 0.5 + 0.5, np.cos(now) * 0.5 + 0.5, 0., 1.], dtype=np.float32) glClearBufferfv(GL_COLOR, 0, color) glUseProgram(self.rendering_program) offset = np.array( [np.sin(now) * 0.5, np.cos(now) * 0.6, 0., 0.], dtype=np.float32) color = np.array( [np.cos(now) * 0.5 + 0.5, np.sin(now) * 0.5 + 0.5, 0., 1.], dtype=np.float32) glVertexAttrib4fv(0, offset) glVertexAttrib4fv(1, color) glDrawArrays(GL_TRIANGLES, 0, 3) def resizeGL(self, w, h): """Resize viewport to match widget dimensions.""" glViewport(0, 0, w, h) def _update_fps(self): if self.frame_count == 0: self.fps_timer.start() else: fps = self.frame_count / self.fps_timer.elapsed() * 1000 self.parentWidget().setWindowTitle("FPS is {:.2f}".format(fps)) self.frame_count += 1
class TactileSurfaceArea(QTableWidget): signalRobotFinishWriting = pyqtSignal() def __init__(self, parent=None): QTableWidget.__init__(self, parent) self.myBrush = QBrush() self.myPen = QPen() self.pixmap = None self.pixmapHandwriting = None self.deviceDown = False self.time = QTime() self.lastPoints = [QPoint(), QPoint()] self.boxesToDraw = [] self.data = [] self.convert_pix_meter = 0.0001534 self.initPixmaps() self.setAutoFillBackground(True) self.setCursor(Qt.BlankCursor) self.time.start() def initPixmaps(self): width = 8000 height = 8000 self.pixmap = QPixmap(width, height) self.pixmap.fill(QColor(255, 255, 255)) self.pixmapHandwriting = QPixmap(width, height) self.pixmapHandwriting.fill(QColor(255, 255, 255)) self.viewport().update() def paintEvent(self, event): p = QPainter() p.begin(self.viewport()) p.drawPixmap(0, 0, self.pixmap) p.drawPixmap(0, 0, self.pixmapHandwriting) p.end() def tabletEvent(self, event): if event.type() == QTabletEvent.TabletPress: if self.deviceDown == False: self.deviceDown = True self.lastPoints[0] = event.pos() self.lastPoints[1] = event.pos() elif event.type() == QTabletEvent.TabletRelease: if self.deviceDown: self.deviceDown = False elif event.type() == QTabletEvent.TabletMove: self.lastPoints[1] = self.lastPoints[0] self.lastPoints[0] = event.pos() if self.deviceDown: self.updateBrush(event) painter = QPainter(self.pixmapHandwriting) self.paintPixmap(painter, event) self.data.append( Data(self.time.elapsed(), event.posF().x(), event.posF().y(), event.xTilt(), event.yTilt(), event.pressure())) def updateBrush(self, event): #hue, saturation, value, alpha; #myColor.getHsv(&hue, &saturation, &value, &alpha) myColor = QColor() vValue = int(((event.yTilt() + 60.0) / 120.0) * 255) hValue = int(((event.xTilt() + 60.0) / 120.0) * 255) alpha = int(event.pressure() * 255.0) # print vValue, hValue,alpha myColor.setHsv(0, vValue, hValue, alpha) #myColor.setAlpha(alpha) self.myPen.setWidthF(event.pressure() * 2 + 1) self.myBrush.setColor(myColor) self.myPen.setColor(myColor) def paintPixmap(self, painter, event): painter.setBrush(self.myBrush) painter.setPen(self.myPen) painter.drawLine(self.lastPoints[1], event.pos()) self.viewport().update() def erasePixmap(self): newPixmap = QPixmap(self.width(), self.height()) newPixmap.fill(QColor(255, 255, 255, 0)) self.pixmapHandwriting = newPixmap painter = QPainter(self.pixmap) painter.drawPixmap(0, 0, self.pixmapHandwriting) painter.end() # update drawing self.viewport().update() # erase data self.data = [] # restart timer self.time.start() def eraseRobotTrace(self): newPixmap = QPixmap(self.width(), self.height()) newPixmap.fill(QColor(255, 255, 255, 0)) self.pixmap = newPixmap painter = QPainter(self.pixmap) painter.drawPixmap(0, 0, self.pixmap) painter.end() # update drawing self.viewport().update() # erase data self.data = [] # restart timer self.time.start() def drawWord(self, path): # prepare drawing painter = QPainter(self.pixmap) myColor = QColor(0, 0, 0) self.myBrush.setColor(myColor) self.myPen.setColor(myColor) self.myPen.setWidthF(SIZE_ROBOT_WRITING) painter.setBrush(self.myBrush) painter.setPen(self.myPen) x = [] y = [] penUp = [] t = [] for i, pose in enumerate(path.poses): x.append(float(pose.pose.position.x) / self.convert_pix_meter) y.append(float(pose.pose.position.y) / self.convert_pix_meter) penUp.append(pose.header.seq) t.append(pose.header.stamp.nsecs) # put y in touch pad coordinate y = [-y_ + min(y) + max(y) for y_ in y] # put word in top of screen y = [y_ - min(y) + DISTANCE_ROBOT_WRITING_TO_TOP for y_ in y] # wait that robot move its arm up rospy.sleep(3.) # draw for i in range(len(x)): if i > 1: if penUp[i] == 0 and penUp[i - 1] == 0: painter.drawLine(QPoint(x[i - 1], y[i - 1]), QPoint(x[i], y[i])) self.viewport().update() waitingTime = (t[i] - t[i - 1]) / 1000000.0 rospy.sleep(TIME_BTW_POINTS) else: rospy.sleep(TIME_PEN_UP) # advert that drawing is done self.signalRobotFinishWriting.emit() def drawBoxes(self): # prepare drawing painter = QPainter(self.pixmap) myColor = QColor(0, 0, 0) self.myBrush.setColor(myColor) self.myPen.setColor(myColor) self.myPen.setWidthF(SIZE_BOXES) painter.setBrush(self.myBrush) painter.setPen(self.myPen) for data in self.boxesToDraw: x = data[0] / self.convert_pix_meter y = self.height() - data[1] / self.convert_pix_meter width = data[2] / self.convert_pix_meter - data[ 0] / self.convert_pix_meter height = -data[3] / self.convert_pix_meter + data[ 1] / self.convert_pix_meter painter.drawRect(x, y, width, height) self.viewport().update() def getData(self): return self.data
class GLWidget(QOpenGLWidget): """ OpenGL widget that shows a static 3D scene, allowing the observer to freely move and look around. """ background_color = gl_array([1, 1, 1]) * 0.6 ambient_color = gl_array([1, 1, 1]) * 0.1 diffuse_color = gl_array([1, 1, 1]) camera_speed = 1 # [m/s] zoom_speed = 1/10 # [1/deg] mouse_sensitivity = 1/100 # [rad/px] update_interval = 25 # [ms] shader_program = None update_timer = None def __init__(self, create_items, *args, **kwargs): """Create from a callable ``create_items: Camera -> [Object3D]``.""" super().__init__(*args, **kwargs) self._create_items = create_items self.items = [] self._key_state = {} self._update_time = QTime() self.resize(800, 600) self.camera = Camera() self.camera.updated.connect(self.update) # Enable multisampling (for antialiasing): # (must be set before initializeGL) surface_format = self.format() surface_format.setSamples(6) self.setFormat(surface_format) def free(self): """Free all items.""" for item in self.items: item.delete() self.items.clear() def closeEvent(self, event): """Free items.""" self.free() super().closeEvent(event) def showEvent(self, event): """Start scene updates (camera movement).""" super().showEvent(event) if self.update_timer is None: self.update_timer = QTimer(self) self.update_timer.setInterval(self.update_interval) self.update_timer.timeout.connect(self.update_event) self.update_timer.start() self._update_time.start() def hideEvent(self, event): """Stop scene updates (camera movement).""" super().hideEvent(event) if self.update_timer is not None: self.update_timer.timeout.disconnect(self.update_event) self.update_timer.stop() self.update_timer = None # def GL(self): # from PyQt5.QtGui import QOpenGLVersionProfile # version = QOpenGLVersionProfile() # version.setVersion(2, 0) # return self.context().versionFunctions(version) def initializeGL(self): """Called after first creating a valid OpenGL context. Creates shader program, sets up camera and creates an initial scene.""" self.create_shader_program() self.create_scene() # Activate wireframe: # GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE) camera = self.camera camera.look_from(camera.theta, camera.phi, camera.psi) def create_scene(self): """Fetch new items from the given callable.""" self.free() if self.shader_program is not None: self.items = self._create_items(self.camera) self.update() def paintGL(self): """Handle paint event by drawing the items returned by the creator function.""" program = self.shader_program projection = self.camera.projection(self.width(), self.height()) set_uniform_matrix(program, "view", self.camera.view_matrix) set_uniform_matrix(program, "projection", projection) set_uniform_vector(program, "ambient_color", self.ambient_color) set_uniform_vector(program, "diffuse_color", self.diffuse_color) set_uniform_vector(program, "diffuse_position", self.camera.position) GL.glClearColor(*self.background_color, 0) GL.glEnable(GL.GL_DEPTH_TEST) GL.glEnable(GL.GL_MULTISAMPLE) GL.glEnable(GL.GL_BLEND) GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) # Draw transparent items after opaque ones, and sorted by distance to # the observer (far to near). Note that this is only an approximation # that is correct only for point-like items; a 100% correct blending # order would have to be decided on the level of fragments (based on # the interpolated depth value). items = sorted(self.items, key=lambda item: ( item.opaque(), np.linalg.norm(self.camera.position - item.position()), ), reverse=True) for item in items: item.draw() def create_shader_program(self): """Create simple program with generic fragment/vertex shaders used to render objects with a simple ambient+diffuse lighting model.""" self.shader_program = create_shader_program([ load_shader(GL.GL_VERTEX_SHADER, 'shader_vertex.glsl'), load_shader(GL.GL_FRAGMENT_SHADER, 'shader_fragment.glsl'), ]) def minimumSizeHint(self): return QSize(50, 50) def sizeHint(self): return QSize(400, 400) def wheelEvent(self, event): """Handle mouse wheel as zoom.""" self.camera.zoom(self.zoom_speed * event.angleDelta().y()) def mousePressEvent(self, event): """Handle camera look around.""" self.last_mouse_position = event.pos() super().mousePressEvent(event) def mouseMoveEvent(self, event): """Handle camera look around.""" camera = self.camera delta = event.pos() - self.last_mouse_position if event.buttons() == Qt.RightButton: dx = delta.x() * self.mouse_sensitivity dy = delta.y() * self.mouse_sensitivity if event.modifiers() & Qt.ShiftModifier: camera.look_from(camera.theta + dx, camera.phi - dy, camera.psi) else: camera.look_toward(camera.theta + dx, camera.phi - dy, camera.psi) elif event.buttons() == Qt.RightButton | Qt.LeftButton: camera.zoom(-delta.y()) else: return super().mouseMoveEvent(event) self.last_mouse_position = event.pos() event.accept() def keyPressEvent(self, event): """Maintain a list of pressed keys for camera movement.""" key = event.key() if key in (Qt.Key_Escape, Qt.Key_Q): self.window().close() if not event.isAutoRepeat(): self._key_state[key] = True super().keyPressEvent(event) def keyReleaseEvent(self, event): """Maintain a list of pressed keys for camera movement.""" if not event.isAutoRepeat(): self._key_state[event.key()] = False def update_event(self): """Implement camera movement. Called regularly.""" pressed = lambda k: self._key_state.get(k, 0) upward = pressed(Qt.Key_Space) - pressed(Qt.Key_Control) forward = ((pressed(Qt.Key_Up) or pressed(Qt.Key_W)) - (pressed(Qt.Key_Down) or pressed(Qt.Key_S))) leftward = ((pressed(Qt.Key_Left) or pressed(Qt.Key_A)) - (pressed(Qt.Key_Right) or pressed(Qt.Key_D))) # we use this "update time" (a.k.a. "game time") to maintain a # somewhat framerate independent movement speed: ms_elapsed = self._update_time.elapsed() self._update_time.start() if forward or upward or leftward: direction = np.array([-leftward, upward, -forward]) direction = direction / np.linalg.norm(direction) translate = direction * self.camera_speed * (ms_elapsed/1000) self.camera.translate(*translate)
class VCProgressBar(QDialog): taskbarprogress = pyqtSignal(float, bool) def __init__(self, parent=None, flags=Qt.Dialog | Qt.FramelessWindowHint): super(VCProgressBar, self).__init__(parent, flags) self.parent = parent self.setWindowModality(Qt.ApplicationModal) self.setStyleSheet('QDialog { border: 2px solid #000; }') self._progress = QProgressBar(self) self._progress.setRange(0, 0) self._progress.setTextVisible(False) self._progress.setStyle(QStyleFactory.create('Fusion')) self._label = QLabel(self) self._label.setAlignment(Qt.AlignCenter) layout = QGridLayout() layout.addWidget(self._progress, 0, 0) layout.addWidget(self._label, 0, 0) self._timerprefix = QLabel('<b>Elapsed time:</b>', self) self._timerprefix.setObjectName('progresstimer') self._timervalue = QLabel(self) self._timervalue.setObjectName('progresstimer') timerlayout = QHBoxLayout() timerlayout.addWidget(self._timerprefix) timerlayout.addWidget(self._timervalue) self._timerwidget = QWidget(self) self._timerwidget.setLayout(timerlayout) self._timerwidget.hide() self._time = QTime() self._timer = QTimer(self) self._timer.timeout.connect(self.updateTimer) self.setLayout(layout) self.setFixedWidth(550) def reset(self, steps: int = 0, timer: bool = False) -> None: self.setValue(0) self.setRange(0, steps) self.setText('Analyzing video source') self.showTimer() if timer else self.hideTimer() def showTimer(self) -> None: self._timerwidget.show() # noinspection PyArgumentList self.layout().addWidget(self._timerwidget, 1, 0, Qt.AlignHCenter | Qt.AlignTop) self._time.start() self.updateTimer() self._timer.start(1000) def hideTimer(self) -> None: self._timerwidget.hide() self.layout().removeWidget(self._timerwidget) @pyqtSlot() def updateTimer(self) -> None: secs = self._time.elapsed() / 1000 mins = int(secs / 60) % 60 hrs = int(secs / 3600) secs = int(secs % 60) elapsed = '{hrs:02d}:{mins:02d}:{secs:02d}'.format(**locals()) self._timervalue.setText(elapsed) def value(self) -> int: return self._progress.value() def setStyle(self, style: QStyle) -> None: self._progress.setStyle(style) def setText(self, val: str) -> None: if '<b>' in val: css = '<style>b { font-family:"Noto Sans UI"; font-weight:bold; }</style>' val = '{0}{1}'.format(css, val) self._label.setText(val) def setMinimum(self, val: int) -> None: self._progress.setMinimum(val) def setMaximum(self, val: int) -> None: self._progress.setMaximum(val) @pyqtSlot(int, int) def setRange(self, minval: int, maxval: int) -> None: self._progress.setRange(minval, maxval) def setValue(self, val: int) -> None: if sys.platform.startswith('linux') and self._progress.maximum() != 0: self.taskbarprogress.emit(float(val / self._progress.maximum()), True) self._progress.setValue(val) if val >= self._progress.maximum() and self._timer.isActive(): self._timer.stop() @pyqtSlot(str) def updateProgress(self, text: str) -> None: self.setValue(self._progress.value() + 1) self.setText(text) qApp.processEvents() @pyqtSlot() def close(self) -> None: if sys.platform.startswith('linux'): self.taskbarprogress.emit(0.0, False) if self._timer.isActive(): self._timer.stop() super(VCProgressBar, self).close()
class MainWindow(QGraphicsView): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.updateTimer = QTimer(self) self.demoStartTime = QTime() self.fpsTime = QTime() self.background = QPixmap() self.scene = None self.mainSceneRoot = None self.frameTimeList = [] self.fpsHistory = [] self.currentFps = Colors.fps self.fpsMedian = -1 self.fpsLabel = None self.pausedLabel = None self.doneAdapt = False self.useTimer = False self.updateTimer.setSingleShot(True) self.companyLogo = None self.qtLogo = None self.setupWidget() self.setupScene() self.setupSceneItems() self.drawBackgroundToPixmap() def setupWidget(self): desktop = QApplication.desktop() screenRect = desktop.screenGeometry(desktop.primaryScreen()) windowRect = QRect(0, 0, 800, 600) if screenRect.width() < 800: windowRect.setWidth(screenRect.width()) if screenRect.height() < 600: windowRect.setHeight(screenRect.height()) windowRect.moveCenter(screenRect.center()) self.setGeometry(windowRect) self.setMinimumSize(80, 60) self.setWindowTitle("PyQt Examples") self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setFrameStyle(QFrame.NoFrame) self.setRenderingSystem() self.updateTimer.timeout.connect(self.tick) def setRenderingSystem(self): self.setCacheMode(QGraphicsView.CacheBackground) self.setViewport(QWidget()) def start(self): self.switchTimerOnOff(True) self.demoStartTime.restart() MenuManager.instance().itemSelected(MenuManager.ROOT, Colors.rootMenuName) Colors.debug("- starting demo") def enableMask(self, enable): if not enable or Colors.noWindowMask: self.clearMask() else: region = QPolygon([ # North side. 0, 0, 800, 0, # East side. # 800, 70, # 790, 90, # 790, 480, # 800, 500, 800, 600, # South side. 700, 600, 670, 590, 130, 590, 100, 600, 0, 600, # West side. # 0, 550, # 10, 530, # 10, 520, # 0, 520, 0, 0]) self.setMask(QRegion(region)) def setupScene(self): self.scene = QGraphicsScene(self) self.scene.setSceneRect(0, 0, 800, 600) self.setScene(self.scene) self.scene.setItemIndexMethod(QGraphicsScene.NoIndex) def switchTimerOnOff(self, on): ticker = MenuManager.instance().ticker if ticker and ticker.scene(): ticker.tickOnPaint = not on or Colors.noTimerUpdate if on and not Colors.noTimerUpdate: self.useTimer = True self.fpsTime = QTime.currentTime() self.updateTimer.start(int(1000 / Colors.fps)) update_mode = QGraphicsView.NoViewportUpdate else: self.useTimer = False self.updateTimer.stop() if Colors.noTicker: update_mode = QGraphicsView.MinimalViewportUpdate else: update_mode = QGraphicsView.SmartViewportUpdate self.setViewportUpdateMode(update_mode) def measureFps(self): # Calculate time difference. t = self.fpsTime.msecsTo(QTime.currentTime()) if t == 0: t = 0.01 self.currentFps = (1000.0 / t) self.fpsHistory.append(self.currentFps) self.fpsTime = QTime.currentTime() # Calculate median. size = len(self.fpsHistory) if size == 10: self.fpsHistory.sort() self.fpsMedian = self.fpsHistory[int(size / 2)] if self.fpsMedian == 0: self.fpsMedian = 0.01 self.fpsHistory = [] return True return False def forceFpsMedianCalculation(self): # Used for adaption in case things are so slow that no median has yet # been calculated. if self.fpsMedian != -1: return size = len(self.fpsHistory) if size == 0: self.fpsMedian = 0.01 return self.fpsHistory.sort() self.fpsMedian = self.fpsHistory[size // 2] if self.fpsMedian == 0: self.fpsMedian = 0.01 def tick(self): medianChanged = self.measureFps() self.checkAdapt() if medianChanged and self.fpsLabel and Colors.showFps: self.fpsLabel.setText("FPS: %d" % int(self.currentFps)) if MenuManager.instance().ticker: MenuManager.instance().ticker.tick() self.viewport().update() if self.useTimer: self.updateTimer.start(int(1000 / Colors.fps)) def setupSceneItems(self): if Colors.showFps: self.fpsLabel = DemoTextItem("FPS: --", Colors.buttonFont(), Qt.white, -1, None, DemoTextItem.DYNAMIC_TEXT) self.fpsLabel.setZValue(1000) self.fpsLabel.setPos(Colors.stageStartX, 600 - QFontMetricsF(Colors.buttonFont()).height() - 5) self.mainSceneRoot = QGraphicsWidget() self.scene.addItem(self.mainSceneRoot) self.companyLogo = ImageItem(QImage(':/images/trolltech-logo.png'), 1000, 1000, None, True, 0.5) self.qtLogo = ImageItem(QImage(':/images/qtlogo_small.png'), 1000, 1000, None, True, 0.5) self.companyLogo.setZValue(100) self.qtLogo.setZValue(100) self.pausedLabel = DemoTextItem("PAUSED", Colors.buttonFont(), Qt.white, -1, None) self.pausedLabel.setZValue(100) fm = QFontMetricsF(Colors.buttonFont()) self.pausedLabel.setPos(Colors.stageWidth - fm.width("PAUSED"), 590 - fm.height()) self.pausedLabel.setRecursiveVisible(False) def checkAdapt(self): if self.doneAdapt or Colors.noTimerUpdate or self.demoStartTime.elapsed() < 2000: return self.doneAdapt = True self.forceFpsMedianCalculation() Colors.benchmarkFps = self.fpsMedian Colors.debug("- benchmark: %d FPS" % int(Colors.benchmarkFps)) if Colors.noAdapt: return if self.fpsMedian < 30: ticker = MenuManager.instance().ticker if ticker and ticker.scene(): self.scene.removeItem(ticker) Colors.noTimerUpdate = True self.switchTimerOnOff(False) if self.fpsLabel: self.fpsLabel.setText("FPS: (%d)" % int(self.fpsMedian)) Colors.debug("- benchmark adaption: removed ticker (fps < 30)") if self.fpsMedian < 20: Colors.noAnimations = True Colors.debug("- benchmark adaption: animations switched off (fps < 20)") Colors.adapted = True def drawBackgroundToPixmap(self): r = self.scene.sceneRect() self.background = QPixmap(qRound(r.width()), qRound(r.height())) self.background.fill(Qt.black) painter = QPainter(self.background) bg = QImage(':/images/demobg.png') painter.drawImage(0, 0, bg) def drawBackground(self, painter, rect): painter.drawPixmap(QPoint(0, 0), self.background) def toggleFullscreen(self): if self.isFullScreen(): self.enableMask(True) self.showNormal() if MenuManager.instance().ticker: MenuManager.instance().ticker.pause(False) else: self.enableMask(False) self.showFullScreen() def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: QApplication.quit() elif event.key() == Qt.Key_F1: s = "" s += "\nAdapt: " s += ["on", "off"][Colors.noAdapt] s += "\nAdaption occured: " s += ["no", "yes"][Colors.adapted] w = QWidget() s += "\nColor bit depth: %d" % w.depth() s += "\nWanted FPS: %d" % Colors.fps s += "\nBenchmarked FPS: "; if Colors.benchmarkFps != -1: s += "%d" % Colors.benchmarkFps else: s += "not calculated" s += "\nAnimations: "; s += ["on", "off"][Colors.noAnimations] s += "\nBlending: "; s += ["on", "off"][Colors.useEightBitPalette] s += "\nTicker: "; s += ["on", "off"][Colors.noTicker] s += "\nPixmaps: "; s += ["off", "on"][Colors.usePixmaps] s += "\nRescale images on resize: "; s += ["on", "off"][Colors.noRescale] s += "\nTimer based updates: "; s += ["on", "off"][Colors.noTimerUpdate] s += "\nSeparate loop: "; s += ["no", "yes"][Colors.useLoop] s += "\nScreen sync: "; s += ["yes", "no"][Colors.noScreenSync] QMessageBox.information(None, "Current configuration", s) super(MainWindow, self).keyPressEvent(event) def focusInEvent(self, event): if not Colors.pause: return if MenuManager.instance().ticker: MenuManager.instance().ticker.pause(False) code = MenuManager.instance().currentMenuCode if code in (MenuManager.ROOT, MenuManager.MENU1): self.switchTimerOnOff(True) self.pausedLabel.setRecursiveVisible(False) def focusOutEvent(self, event): if not Colors.pause: return if MenuManager.instance().ticker: MenuManager.instance().ticker.pause(True) code = MenuManager.instance().currentMenuCode if code in (MenuManager.ROOT, MenuManager.MENU1): self.switchTimerOnOff(False) self.pausedLabel.setRecursiveVisible(True) def resizeEvent(self, event): self.resetTransform() self.scale(event.size().width() / 800.0, event.size().height() / 600.0) super(MainWindow, self).resizeEvent(event) DemoItem.setTransform(self.transform()) if self.companyLogo: r = self.scene.sceneRect() ttb = self.companyLogo.boundingRect() self.companyLogo.setPos(int((r.width() - ttb.width()) / 2), 595 - ttb.height()) qtb = self.qtLogo.boundingRect() self.qtLogo.setPos(802 - qtb.width(), 0) # Changing size will almost always hurt FPS during the change so ignore # it. self.fpsHistory = []
class BaseTestWidget(VisualWidget): def __init__(self, parent=None) -> None: """Base class for test widgets. This is not called directly, but contains methods which are inherited by all tests. These do much of the heavy lifting regarding running tests, storing data, and so on. """ super(BaseTestWidget, self).__init__(parent) logger.debug(f"initialised {type(self)} with parent={parent}") # timers self.block_time = QTime() self.block_timer = QTimer() self.block_timer.setSingleShot(True) self.block_timer.timeout.connect(self._block_timeout) self.trial_time = QTime() self.trial_timer = QTimer() self.trial_timer.setSingleShot(True) self.trial_timer.timeout.connect(self._trial_timeout) # override these if necessary self.silent_block = False self.skip_countdown = False self.block_deadline = None self.trial_deadline = None self.procedure = None self.current_trial = None self.delete_skipped = False # silent attributes self._performing_block = False self._performing_trial = False self._mouse_visible = True # set focus so we can accept keyboard events self.setFocusPolicy(Qt.StrongFocus) @property def performing_block(self) -> bool: return self._performing_block @performing_block.setter def performing_block(self, value) -> None: """Block timers will be silently and automatically started or restarted here.""" assert isinstance(value, bool), "performing_block must be a bool" self._performing_block = value time = self.block_time timer = self.block_timer deadline = self.block_deadline if timer.isActive(): logger.debug("stopping block timer") timer.stop() if value is True: logger.debug("performing_block set to True") logger.debug("starting the block time") time.start() if value is True and deadline: logger.debug("block deadline: %s" % str(self.block_deadline)) logger.debug("starting one-shot block timer") timer.start(deadline) @property def performing_trial(self) -> bool: return self._performing_trial @performing_trial.setter def performing_trial(self, value: bool) -> None: """Start of a trial defined from when the proband can start making responses. Trial timers will be silently and automatically started or restarted here. Args: value (bool): Are we performing a trial or not? """ assert isinstance(value, bool), "performing_trial must be a bool" self._performing_trial = value time = self.trial_time timer = self.trial_timer deadline = self.trial_deadline if timer.isActive(): logger.debug("stopping trial timer") timer.stop() if value is True: logger.debug("performing_trial set to True") logger.debug("starting the trial time") time.start() if value is True and deadline: logger.debug("trial deadline: %s" % str(self.trial_deadline)) logger.debug("starting one-shot trial timer") timer.start(deadline) @property def mouse_visible(self) -> bool: return self._mouse_visible @mouse_visible.setter def mouse_visible(self, value: bool) -> None: """Makes the mouse visible or invisible.""" assert isinstance(value, bool), "mouse_visible must be a bool" if value is False: self.setCursor(Qt.BlankCursor) else: self.setCursor(Qt.ArrowCursor) self._mouse_visible = value @property def _time_left_in_block(self) -> int: """Calculates difference between deadline and elapsed.""" if isinstance(self.block_deadline, int): return self.block_deadline - self.block_time.elapsed() else: return 0 @property def _block_time_up(self) -> bool: if isinstance(self._time_left_in_block, int): return self._time_left_in_block <= 0 else: return False @property def _time_left_in_trial(self) -> int: """Calculates difference between deadline and elapsed.""" if isinstance(self.trial_deadline, int): return self.trial_deadline - self.trial_time.elapsed() else: return 0 @property def _trial_time_up(self) -> int: if isinstance(self._time_left_in_trial, int): return self._time_left_in_trial <= 0 else: return 0 def begin(self) -> None: """Start the test. Public method called by the parent widget. Starts by initialising a procedure (currently only SimpleProcedure implemented), creates a new trial list if needed, and steps into the test. """ logger.debug("called begin()") if self.delete_skipped is True: self.kwds["delete_skipped"] = True self.procedure = SimpleProcedure(**self.kwds) started = self.procedure.data["test_started"] completed = self.procedure.data["test_completed"] if started is False and completed is False: logger.debug("generating new remaining_trials list") self.procedure.data["remaining_trials"] = self.make_trials() self.procedure.update() logger.debug( f"looks like {self.procedure.data['remaining_trials']}") self._step() def _step(self) -> None: """Step forward in the test. Private method. This could mean displaying instructions at the start of a block, starting the next trial, or continuing to the next test if all trials are done. """ logger.debug("called _step()") self.performing_trial = False try: self.current_trial = self.procedure.next(self.current_trial) logger.debug( f"successfully iterated, got this: {self.current_trial}") if self.current_trial.first_trial_in_block: logger.debug("first trial in new block") self._block() else: logger.debug("after first trial in new block") if self._block_stopping_rule(): logger.debug("stopping rule says to stop") self._stop_block() else: logger.debug("stopping rule says to go") self._trial() except StopIteration: logger.info("failed to iterate, end of test") self.safe_close() def _stop_block(self) -> None: """Stop the current block because stopping rule passed.""" logger.debug("called _block_stop") self.procedure.skip_block(self.current_trial.block_number, "stopping rule failed") self.current_trial.status = "skipped" self.current_trial.reason_skipped = "stopping rule failed" self._next_trial() def _block_stopping_rule(self) -> bool: """Apply block stopping rule. Private method and a wrapper around the public method of the same name. """ logger.debug("called _block_stopping_rule()") return False if self.current_trial is None else self.block_stopping_rule( ) def _block(self) -> None: """Runs at the start of a new block of trials. Private method. Typically blocks are used to delineate trials of a different condition, when new instructions or a break are often needed. """ logger.debug("called _block()") self.performing_block = False logger.debug("checking if this is a silent block") if self.silent_block: logger.debug("this is indeed a silent block") logger.debug("skipping the countdown") self.skip_countdown = True logger.debug("running _trial()") self._trial() else: logger.debug("this is a not a silent block") self.new_block.play() self.skip_countdown = False logger.debug("running block()") self.block() def _trial(self) -> None: """Runs at the start of a new trial. Private method. Displays the countdown if first in a new block, checks if very last trial, flags the fact that a trial is in progress, updates the results. """ logger.debug("called _trial()") self.silence.play() if self.current_trial.first_trial_in_block and not self.skip_countdown: logger.debug("countdown requested") self.display_countdown() self.repaint() if self.current_trial.first_trial_in_block is True: logger.debug("this is the first trial in a new block") self.performing_block = True self.performing_trial = True self.trial() def block_stopping_rule(self) -> bool: """Override this method.""" return False def make_trials(self) -> None: """Override this method.""" raise AssertionError("make_trials must be overridden") def safe_close(self) -> None: """Safely clean up and save the data.""" logger.debug("called safe_close()") # properly ended test if self.procedure.data["test_completed"] is True: logger.debug("summarising the results") self.procedure.data["summary"] = self.summarise() self.procedure.save() self.procedure.save_summary() # early quit else: logger.warning("quit early, need to save orphaned trial") rt = [t for t in self.procedure.data["remaining_trials"]] self.procedure.data["remaining_trials"] = [ dict(self.current_trial) ] + rt self.procedure.save() # end test logger.debug("all done, so switching the central widget") self.parent().switch_central_widget() def _block_timeout(self) -> None: """End a block early because it had timed out.""" logger.debug("called _block_timeout()") self.procedure.skip_block(self.current_trial.block_number, "timeout") self._trial_timeout() def _trial_timeout(self) -> None: """End a trial early because it had timed out.""" logger.debug("called _trial_timeout()") self.current_trial.status = "skipped" self.current_trial.reason_skipped = "timeout" self._next_trial() def _next_trial(self) -> None: """Moves on to the next trial.""" logger.debug("called _next_trial()") self._step() def next_trial(self) -> None: """Moves on to the next trial (public version).""" logger.debug("called next_trial()") self._next_trial() def mousePressEvent(self, event: QMouseEvent) -> None: """Overridden from `QtWidget`. Args: event (PyQt5.QtGui.QMouseEvent): """ logger.debug(f"called mousePressEvent() with event={event}") if self.performing_trial: self.mousePressEvent_(event) self._add_timing_details() if self.current_trial.status == "completed": logger.debug("current_trial was completed successfully") self._next_trial() def keyReleaseEvent(self, event: QKeyEvent) -> None: """Overridden from `QtWidget`.""" logger.debug(f"called keyReleaseEvent() with event={event}") if self.performing_trial: self.keyReleaseEvent_(event) self._add_timing_details() if self.current_trial.status == "completed": logger.debug("current_trial was completed successfully") self._next_trial() def _add_timing_details(self) -> None: """Gathers some details about the current state from the various timers.""" logger.debug("called _add_timing_details()") dic = { "block_time_elapsed_ms": self.block_time.elapsed(), "trial_time_elapsed_ms": self.trial_time.elapsed(), "block_time_left_ms": self._time_left_in_block, "trial_time_left_ms": self._time_left_in_trial, "block_time_up_ms": self._block_time_up, "trial_time_up_ms": self._trial_time_up, } self.current_trial.update(dic) def block(self) -> None: """Override this method.""" raise AssertionError("block must be overridden") def trial(self) -> None: """Override this method.""" raise AssertionError("trial must be overridden") def summarise(self) -> dict: """This method can be overridden.""" return basic_summary(self.procedure.data["completed_trials"]) def mousePressEvent_(self, event: QMouseEvent) -> None: """Override this method.""" pass def keyReleaseEvent_(self, event: QKeyEvent) -> None: """Override this method.""" pass def sleep(self, t: int) -> None: """Sleep for `t` ms. Use instead of `time.sleep()` or any other method of sleeping because (a) Qt handles it properly and (b) it prevents a `closeEvent` from quitting the test during this time. Args: t (int): Time to sleep in seconds. """ logger.debug(f"called sleep with t={t}") self.parent().ignore_close_event = True loop = QEventLoop() QTimer.singleShot(t, loop.quit) loop.exec_() self.parent().ignore_close_event = False
class Pricing_Template_Main(QThread): """ Runs in thread. """ txtProgress = pyqtSignal(str) countProgress = pyqtSignal(int) currStatus = pyqtSignal(list) def __init__(self, src_folder, tgt_folder, keyword, templates, pt_model): super(Pricing_Template_Main, self).__init__() self._src_folder = src_folder self._tgt_folder = tgt_folder self._keyword = keyword self._l_templates = templates self._pt_model = pt_model self.timer = QTime() self.elapsed_time = None self.is_running = True self._progress_count = 0 self._abort_flg = False self._cancel_flg = False self._main_dir = os.getcwd() self.src_price_cnt = 0 self.temp_price_cnt = 0 self.src_scales_cnt = 0 self.temp_scales_cnt = 0 self.src_minf_cnt = 0 self.temp_minf_cnt = 0 self.start_row = self._pt_model._config['StartRow'] def run(self): ''' Read source file to DataFrame and Excel file (for validation) Filter dataframe per Usage Type Perform Mappings Populate the validated dataframe to template ''' # Read source files and load to dataframe # Start timer self.timer.start() self.txtProgress.emit('Loading source files to dataframes.') success = False while not success: try: self.df_price_all = self._pt_model.read_source_to_DF( self._keyword, self._src_folder, 'Pricing') df_scales_all = self._pt_model.read_source_to_DF( self._keyword, self._src_folder, 'Scales') df_minf_all = self._pt_model.read_source_to_DF( self._keyword, self._src_folder, 'MINF') success = True except Exception as e: self.currStatus.emit([self._keyword, 'Load Source', str(e)]) response = None while response is None: response = self._pt_model.replyBtn time.sleep(1) if response == QMessageBox.Close: self._abort_flg = True self._pt_model.replyBtn = None success = True if not self._abort_flg: #Loop on the templates found for i in self._l_templates: usage_type = i[0] ''' Get current status c = Completed i = Ignored NULL = Not started (default) ''' if self._cancel_flg: break status = self._pt_model.get_template_status(usage_type) if status == '': self.txtProgress.emit('Processing ' + usage_type) # Get template worksheets template_file = self._pt_model.get_template_filename( usage_type) template_filename = template_file.split('\\')[-1] # Load Template Workbook self.txtProgress.emit( 'Loading Pricing Template to dataframe.') success = False while not success: try: temp_workbook = self._pt_model.load_workbook( template_file) temp_worksheets = self._pt_model.get_worksheets( temp_workbook) success = True except Exception as e: self.currStatus.emit( [usage_type, 'Load Template', str(e)]) response = None while response is None: response = self._pt_model.replyBtn time.sleep(1) if response == QMessageBox.Abort: self._abort_flg = True self._pt_model.replyBtn = None break elif response == QMessageBox.Retry: self._pt_model.replyBtn = None elif response == QMessageBox.Ignore: self._pt_model.update_template_status( usage_type, 'i') self._pt_model.replyBtn = None continue elif response == QMessageBox.Close: self._abort_flg = True self._pt_model.replyBtn = None break # Filter & Validate Usage type df_price = self._pt_model.filter_df( usage_type, self.df_price_all) df_scales = self._pt_model.filter_df( usage_type, df_scales_all) df_minf = self._pt_model.filter_df(usage_type, df_minf_all) # Prep Source data frame # Drop column fld_Contract_Type df_price.drop('fld_Contract_Type', axis=1, inplace=True) # Rename Column names in dataframe df_price.rename( columns={ 'Partner_Number': 'fld_Business_Partner', 'BillingMaterial_ID_ToBe': 'fld_OTC_Billing_Material_ID', 'fld_Requestor': 'fld_Requester', 'fld_Price': 'fld_Price_Amount', 'fld_Pricing_Bundle_ID': 'fld_Bundle_ID', 'fld_Pricing_Contract_Type': 'fld_Contract_Type', 'fld_Pricing_Contract_SubType': 'fld_Contract_Sub_Type', 'fld_SSCALE_ID': 'fld_Shared_Scale_ID', 'fld_SSCALE_BP': 'fld_Shared_Scale_BP', #'fld_Reach_Indicator': 'fld_Reach_Ind', 'fld_Flight_Range_Code': 'fld_Flight_Range' }, inplace=True) # Add columns to dataframe # Common Audit Fields df_price['fld_Created_By'] = '' df_price['fld_Last_Upd'] = '' df_price['fld_Last_Upd_By'] = 'DATA MIG' df_price['fld_Created'] = '' self.txtProgress.emit( 'Processing ' + usage_type + ' - Filtering and Validating dataframe.') #Loop on the template worksheet for sheet in temp_worksheets: success = False while not success: try: if ('price' in sheet.title.lower() and 'scale' not in sheet.title.lower() ) or ('minq' in sheet.title.lower() or 'caps' in sheet.title.lower() or 'flight' in sheet.title.lower()): self.src_price_cnt = df_price.shape[0] if not df_price.empty and not self._cancel_flg: # Mappings for CAP, Flight range and MINQ if 'minq' in sheet.title.lower( ) or 'caps' in sheet.title.lower( ) or 'flight' in sheet.title.lower(): self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Additional mappings for ' + sheet.title + '.') df_price['fld_Counter_ID'] = '*' df_price['fld_Frequency'] = '*' df_price[ 'fld_Type_of_Calendar'] = '*' df_price['fld_Min_Quantity'] = '*' df_price[ 'fld_Scale_Frequency'] = '*' df_price[ 'fld_Reference_Date'] = df_price[ 'fld_Start_Date'] df_price['fld_Range'] = '*' df_price['fld_Scale_Price'] = '*' df_price['fld_Unit_Price'] = '*' df_price['fld_CAP'] = '*' df_price[ 'fld_Billing_Material'] = df_price[ 'fld_OTC_Billing_Material_ID'] df_price['fld_ID'] = '*' df_price['fld_Lower_Bound'] = '*' df_price['fld_Upper_Bound'] = '*' df_price[ 'fld_Flight_Range_Label'] = '*' self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Additional mappings for ' + sheet.title + '.') time.sleep(3) # Get Mappings self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Getting mappings for ' + sheet.title + '.') l_mapping = self._pt_model.get_template_mappings( usage_type, sheet, df_price, 'Price') self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Getting mappings for ' + sheet.title + '.') time.sleep(3) if 'flight' in sheet.title.lower(): start_row = 3 else: start_row = self.start_row # Prepare the worksheet self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') #self._pt_model.prepare_worksheet(sheet, start_row, self.src_price_cnt) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') time.sleep(3) # Populate data from dataframe to worksheet self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Populating worksheet ' + sheet.title + '.') #self.temp_price_cnt = self._pt_model.populate_worksheet(sheet, df_price, l_mapping, start_row) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Populating worksheet ' + sheet.title + '.') time.sleep(3) # Format worksheet self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Formatting worksheet ' + sheet.title + '.') #self._pt_model.format_worksheet(sheet, start_row) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Formatting worksheet ' + sheet.title + '.') time.sleep(3) else: if 'flight' in sheet.title.lower(): start_row = 3 else: start_row = self.start_row # Prepare the worksheet self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') self._pt_model.prepare_worksheet( sheet, start_row, 0) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') time.sleep(3) #Insert empty mapping logs key_tab = 'Price' + '-' + sheet.title self._pt_model.append_template_logs( usage_type, 2, key_tab, []) if self._cancel_flg: return elif 'scale' in sheet.title.lower(): if not df_scales.empty and not self._cancel_flg: #Merge DataFrame with Price DataFrame self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Merging scales dataframe to Price.' ) merged_price_scale_df = self._pt_model.merge_scale_price_df( df_scales, df_price) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Merging scales dataframe to Price.' ) time.sleep(3) # Mapping logic for Type of calendar and reference_date self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Applying additional scales logic.' ) conditions = [ (merged_price_scale_df[ 'Condition_Type'] == 'ZCUY') | (merged_price_scale_df[ 'Condition_Type'] == 'ZCUA'), (merged_price_scale_df[ 'Condition_Type'] == 'ZCUM') | (merged_price_scale_df[ 'Condition_Type'] == 'ZCUX') ] choices = ['Yearly', 'Monthly'] merged_price_scale_df[ 'fld_Scale_Frequency'] = np.select( conditions, choices, default='*') merged_price_scale_df[ 'fld_Type_of_Calendar'] = merged_price_scale_df[ [ 'Condition_Type', 'fld_Start_Date' ]].apply(lambda x: 'Natural' if x['Condition_Type' ] == 'ZCUM' or x['Condition_Type' ] == 'ZCUM' else ('Natural' if (x['Condition_Type' ] == 'ZCUY' or x['Condition_Type' ] == 'ZCUA') and x['fld_Start_Date' ][:8][4:] == '0101' else 'Rolling'), axis=1) merged_price_scale_df[ 'fld_Reference_Date'] = merged_price_scale_df[ [ 'fld_Type_of_Calendar', 'fld_Start_Date' ]].apply(lambda x: x[ 'fld_Start_Date'] if x[ 'fld_Type_of_Calendar' ] == 'Rolling' else 'NA', axis=1) #Add/rename columns to dataframe merged_price_scale_df[ 'fld_Minimum_Fee'] = '*' merged_price_scale_df[ 'fld_Minimum_Fee_BM'] = '*' merged_price_scale_df.rename( columns={ 'MAPPING_TABLE': 'fld_Mapping_Table', 'RANGE': 'fld_Range', 'SCALE_PRICE': 'fld_Scale_Price', }, inplace=True) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Applying additional scales logic.' ) time.sleep(3) # Get Mappings self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Getting mappings for ' + sheet.title + '.') l_mapping = self._pt_model.get_template_mappings( usage_type, sheet, merged_price_scale_df, 'Scales') self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Getting mappings for ' + sheet.title + '.') time.sleep(3) # Prepare the worksheet self.src_scales_cnt = merged_price_scale_df.shape[ 0] self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') #self._pt_model.prepare_worksheet(sheet, self.start_row, self.src_scales_cnt) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') time.sleep(3) # Populate data from dataframe to worksheet self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Populating worksheet ' + sheet.title + '.') #self.temp_scales_cnt = self._pt_model.populate_worksheet(sheet, merged_price_scale_df, l_mapping, self.start_row) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Populating worksheet ' + sheet.title + '.') time.sleep(3) # Format worksheet self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Formatting worksheet ' + sheet.title + '.') #self._pt_model.format_worksheet(sheet, self.start_row) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Formatting worksheet ' + sheet.title + '.') time.sleep(3) else: # Prepare the worksheet self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') self._pt_model.prepare_worksheet( sheet, self.start_row, 0) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') time.sleep(3) #Insert empty mapping logs key_tab = 'Scales' + '-' + sheet.title self._pt_model.append_template_logs( usage_type, 2, key_tab, []) if self._cancel_flg: return elif 'minf' in sheet.title.lower(): if not df_minf.empty and not self._cancel_flg: self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Preparing MINQ dataframe ' + sheet.title + '.') # Drop not needed columns added on price dataframe df_price.drop([ 'fld_Counter_ID', 'fld_Frequency', 'fld_Type_of_Calendar', 'fld_Reference_Date', 'fld_Billing_Material' ], axis=1, inplace=True) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Preparing MINQ dataframe ' + sheet.title + '.') time.sleep(3) #Merge DataFrame with Price DataFrame self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Merging MINF dataframe to Price.' ) df_price_req = df_price[[ 'Short_Text_Key', 'fld_Business_Partner', 'HybrisProduct_ID', 'fld_OTC_Billing_Material_ID', 'fld_MF_Counter', 'fld_Discount', 'fld_Discount_Type', 'fld_Discount_Description', 'fld_Item_Category' ]] #Merge DataFrame with Price DataFrame merged_price_minf_df = self._pt_model.merge_minf_price_df( df_minf, df_price_req) #Rename columns merged_price_minf_df.rename( columns={ 'Start_Date': 'fld_Reference_Date', 'Frequency': 'fld_Frequency', 'Currency': 'fld_Currency', 'fld_OTC_Billing_Material_ID': 'fld_Billing_Material', 'Minimum_Fee': 'fld_Min_Fee', 'fld_MF_Counter': 'fld_Counter_ID', }, inplace=True) merged_price_minf_df[ 'fld_Type_of_Calendar'] = '*' self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Merging MINF dataframe to Price.' ) time.sleep(3) # Get Mappings self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Getting mappings for ' + sheet.title + '.') l_mapping = self._pt_model.get_template_mappings( usage_type, sheet, merged_price_minf_df, 'MINF') self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Getting mappings for ' + sheet.title + '.') time.sleep(3) # Prepare the worksheet self.src_minf_cnt = merged_price_minf_df.shape[ 0] self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') #self._pt_model.prepare_worksheet(sheet, self.start_row, self.src_minf_cnt) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') time.sleep(3) # Populate data from dataframe to worksheet self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Populating worksheet ' + sheet.title + '.') #self.temp_minf_cnt = self._pt_model.populate_worksheet(sheet, merged_price_minf_df, l_mapping, self.start_row) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Populating worksheet ' + sheet.title + '.') time.sleep(3) # Format worksheet self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') #self._pt_model.format_worksheet(sheet, self.start_row) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') time.sleep(3) else: # Prepare the worksheet self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') #self._pt_model.prepare_worksheet(sheet, self.start_row, 0) self.txtProgress.emit( 'Finished: Processing ' + usage_type + ' - Preparing worksheet ' + sheet.title + '.') time.sleep(3) #Insert empty mapping logs key_tab = 'MINF' + '-' + sheet.title self._pt_model.append_template_logs( usage_type, 2, key_tab, []) if self._cancel_flg: return success = True except Exception as e: self.currStatus.emit([ usage_type, 'Populate Worksheet', sheet.title, str(e) ]) response = None while response is None: response = self._pt_model.replyBtn time.sleep(1) if response == QMessageBox.Abort: self._abort_flg = True self._pt_model.replyBtn = None return elif response == QMessageBox.Retry: self._pt_model.replyBtn = None elif response == QMessageBox.Ignore: self._pt_model.update_template_status( usage_type, 'i') self._pt_model.replyBtn = None success = True elif response == QMessageBox.Close: self._abort_flg = True self._pt_model.replyBtn = None return if self._cancel_flg: break #Update Status self._pt_model.update_template_status(usage_type, 'c') #Price Counts self.txtProgress.emit('Started: Processing ' + usage_type + ' - Generating Data Counts.') if not df_price.empty and not self._abort_flg: data = { 'Source': self.src_price_cnt, 'Template': self.temp_price_cnt } self._pt_model.append_template_logs( usage_type, 3, 'Price', data) else: data = {'Source': 0, 'Template': 0} self._pt_model.append_template_logs( usage_type, 3, 'Price', data) #Scales Counts if not df_scales.empty and not self._abort_flg: data = { 'Source': self.src_scales_cnt, 'Template': self.temp_scales_cnt } self._pt_model.append_template_logs( usage_type, 3, 'Scales', data) else: data = {'Source': 0, 'Template': 0} self._pt_model.append_template_logs( usage_type, 3, 'Scales', data) #MinFee Counts if not df_minf.empty and not self._abort_flg: data = { 'Source': self.src_minf_cnt, 'Template': self.temp_minf_cnt } self._pt_model.append_template_logs( usage_type, 3, 'MINF', data) else: data = {'Source': 0, 'Template': 0} self._pt_model.append_template_logs( usage_type, 3, 'MINF', data) if self._cancel_flg: break self.txtProgress.emit('Finished: Processing ' + usage_type + ' - Generating Data Counts.') time.sleep(3) #Save to workbook in output folder status = self._pt_model.get_template_status(usage_type) if status == 'c': success = False while not success: try: self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Saving Workbook to Output Folder.') output_filename = self._tgt_folder + "\\" + template_filename temp_workbook.save(output_filename) self.txtProgress.emit( 'Started: Processing ' + usage_type + ' - Saving Workbook to Output Folder.') time.sleep(3) success = True except Exception as e: self.currStatus.emit([ usage_type, 'Save Template', output_filename, str(e) ]) response = None while response is None: response = self._pt_model.replyBtn time.sleep(1) if response == QMessageBox.Abort: self._abort_flg = True self._pt_model.replyBtn = None success = True elif response == QMessageBox.Retry: self._pt_model.replyBtn = None elif response == QMessageBox.Ignore: self._pt_model.update_template_status( usage_type, 'i') self._pt_model.replyBtn = None success = True elif response == QMessageBox.Close: self._abort_flg = True self._pt_model.replyBtn = None success = True self._progress_count += 1 self.countProgress.emit(self._progress_count) ####### Program End ######### ### Display Elapsed Time ### self.update_elapsed_time() self.txtProgress.emit('Finished') def stop(self): self.is_running = False def update_elapsed_time(self): secs = self.timer.elapsed() / 1000 mins = (secs / 60) % 60 hours = (secs / 3600) seconds = secs % 60 self.elapsed_time = str(hours).split('.')[0] + ' Hours ' + str( mins).split('.')[0] + ' Minutes ' + str(seconds).split( '.')[0] + ' Seconds' def get_all_usage_types(self): return list(self.df_price_all.USAGE_TYPE_CD.unique())[1:]
class DownloadItem(QWidget, Ui_DownloadItem): """ Class implementing a widget controlling a download. @signal statusChanged() emitted upon a status change of a download @signal downloadFinished() emitted when a download finished @signal progress(int, int) emitted to signal the download progress """ statusChanged = pyqtSignal() downloadFinished = pyqtSignal() progress = pyqtSignal(int, int) Downloading = 0 DownloadSuccessful = 1 DownloadCancelled = 2 def __init__(self, reply=None, requestFilename=False, webPage=None, download=False, parent=None, mainWindow=None): """ Constructor @keyparam reply reference to the network reply object (QNetworkReply) @keyparam requestFilename flag indicating to ask the user for a filename (boolean) @keyparam webPage reference to the web page object the download originated from (QWebPage) @keyparam download flag indicating a download operation (boolean) @keyparam parent reference to the parent widget (QWidget) @keyparam mainWindow reference to the main window (HelpWindow) """ super(DownloadItem, self).__init__(parent) self.setupUi(self) p = self.infoLabel.palette() p.setColor(QPalette.Text, Qt.darkGray) self.infoLabel.setPalette(p) self.progressBar.setMaximum(0) self.__isFtpDownload = reply is not None and \ reply.url().scheme() == "ftp" self.tryAgainButton.setIcon(UI.PixmapCache.getIcon("restart.png")) self.tryAgainButton.setEnabled(False) self.tryAgainButton.setVisible(False) self.stopButton.setIcon(UI.PixmapCache.getIcon("stopLoading.png")) self.pauseButton.setIcon(UI.PixmapCache.getIcon("pause.png")) self.openButton.setIcon(UI.PixmapCache.getIcon("open.png")) self.openButton.setEnabled(False) self.openButton.setVisible(False) if self.__isFtpDownload: self.stopButton.setEnabled(False) self.stopButton.setVisible(False) self.pauseButton.setEnabled(False) self.pauseButton.setVisible(False) self.__state = DownloadItem.Downloading icon = self.style().standardIcon(QStyle.SP_FileIcon) self.fileIcon.setPixmap(icon.pixmap(48, 48)) self.__mainWindow = mainWindow self.__reply = reply self.__requestFilename = requestFilename self.__page = webPage self.__pageUrl = webPage and webPage.mainFrame().url() or QUrl() self.__toDownload = download self.__bytesReceived = 0 self.__bytesTotal = -1 self.__downloadTime = QTime() self.__output = QFile() self.__fileName = "" self.__originalFileName = "" self.__startedSaving = False self.__finishedDownloading = False self.__gettingFileName = False self.__canceledFileSelect = False self.__autoOpen = False self.__sha1Hash = QCryptographicHash(QCryptographicHash.Sha1) self.__md5Hash = QCryptographicHash(QCryptographicHash.Md5) if not requestFilename: self.__requestFilename = \ Preferences.getUI("RequestDownloadFilename") self.__initialize() def __initialize(self, tryAgain=False): """ Private method to (re)initialize the widget. @param tryAgain flag indicating a retry (boolean) """ if self.__reply is None: return self.__startedSaving = False self.__finishedDownloading = False self.__bytesReceived = 0 self.__bytesTotal = -1 self.__sha1Hash.reset() self.__md5Hash.reset() # start timer for the download estimation self.__downloadTime.start() # attach to the reply object self.__url = self.__reply.url() self.__reply.setParent(self) self.__reply.setReadBufferSize(16 * 1024 * 1024) self.__reply.readyRead.connect(self.__readyRead) self.__reply.error.connect(self.__networkError) self.__reply.downloadProgress.connect(self.__downloadProgress) self.__reply.metaDataChanged.connect(self.__metaDataChanged) self.__reply.finished.connect(self.__finished) # reset info self.infoLabel.clear() self.progressBar.setValue(0) self.__getFileName() if self.__reply.error() != QNetworkReply.NoError: self.__networkError() self.__finished() def __getFileName(self): """ Private method to get the file name to save to from the user. """ if self.__gettingFileName: return import Helpviewer.HelpWindow downloadDirectory = Helpviewer.HelpWindow.HelpWindow\ .downloadManager().downloadDirectory() if self.__fileName: fileName = self.__fileName originalFileName = self.__originalFileName self.__toDownload = True ask = False else: defaultFileName, originalFileName = \ self.__saveFileName(downloadDirectory) fileName = defaultFileName self.__originalFileName = originalFileName ask = True self.__autoOpen = False if not self.__toDownload: from .DownloadAskActionDialog import DownloadAskActionDialog url = self.__reply.url() dlg = DownloadAskActionDialog( QFileInfo(originalFileName).fileName(), self.__reply.header(QNetworkRequest.ContentTypeHeader), "{0}://{1}".format(url.scheme(), url.authority()), self) if dlg.exec_() == QDialog.Rejected or dlg.getAction() == "cancel": self.progressBar.setVisible(False) self.__reply.close() self.on_stopButton_clicked() self.filenameLabel.setText( self.tr("Download canceled: {0}").format( QFileInfo(defaultFileName).fileName())) self.__canceledFileSelect = True return if dlg.getAction() == "scan": self.__mainWindow.requestVirusTotalScan(url) self.progressBar.setVisible(False) self.__reply.close() self.on_stopButton_clicked() self.filenameLabel.setText( self.tr("VirusTotal scan scheduled: {0}").format( QFileInfo(defaultFileName).fileName())) self.__canceledFileSelect = True return self.__autoOpen = dlg.getAction() == "open" if PYQT_VERSION_STR >= "5.0.0": from PyQt5.QtCore import QStandardPaths tempLocation = QStandardPaths.standardLocations( QStandardPaths.TempLocation)[0] else: from PyQt5.QtGui import QDesktopServices tempLocation = QDesktopServices.storageLocation( QDesktopServices.TempLocation) fileName = tempLocation + '/' + \ QFileInfo(fileName).completeBaseName() if ask and not self.__autoOpen and self.__requestFilename: self.__gettingFileName = True fileName = E5FileDialog.getSaveFileName( None, self.tr("Save File"), defaultFileName, "") self.__gettingFileName = False if not fileName: self.progressBar.setVisible(False) self.__reply.close() self.on_stopButton_clicked() self.filenameLabel.setText( self.tr("Download canceled: {0}") .format(QFileInfo(defaultFileName).fileName())) self.__canceledFileSelect = True return fileInfo = QFileInfo(fileName) Helpviewer.HelpWindow.HelpWindow.downloadManager()\ .setDownloadDirectory(fileInfo.absoluteDir().absolutePath()) self.filenameLabel.setText(fileInfo.fileName()) self.__output.setFileName(fileName + ".part") self.__fileName = fileName # check file path for saving saveDirPath = QFileInfo(self.__fileName).dir() if not saveDirPath.exists(): if not saveDirPath.mkpath(saveDirPath.absolutePath()): self.progressBar.setVisible(False) self.on_stopButton_clicked() self.infoLabel.setText(self.tr( "Download directory ({0}) couldn't be created.") .format(saveDirPath.absolutePath())) return self.filenameLabel.setText(QFileInfo(self.__fileName).fileName()) if self.__requestFilename: self.__readyRead() def __saveFileName(self, directory): """ Private method to calculate a name for the file to download. @param directory name of the directory to store the file into (string) @return proposed filename and original filename (string, string) """ path = parseContentDisposition(self.__reply) info = QFileInfo(path) baseName = info.completeBaseName() endName = info.suffix() origName = baseName if endName: origName += '.' + endName name = directory + baseName if endName: name += '.' + endName if not self.__requestFilename: # do not overwrite, if the user is not being asked i = 1 while QFile.exists(name): # file exists already, don't overwrite name = directory + baseName + ('-{0:d}'.format(i)) if endName: name += '.' + endName i += 1 return name, origName def __open(self): """ Private slot to open the downloaded file. """ info = QFileInfo(self.__output) url = QUrl.fromLocalFile(info.absoluteFilePath()) QDesktopServices.openUrl(url) @pyqtSlot() def on_tryAgainButton_clicked(self): """ Private slot to retry the download. """ self.retry() def retry(self): """ Public slot to retry the download. """ if not self.tryAgainButton.isEnabled(): return self.tryAgainButton.setEnabled(False) self.tryAgainButton.setVisible(False) self.openButton.setEnabled(False) self.openButton.setVisible(False) if not self.__isFtpDownload: self.stopButton.setEnabled(True) self.stopButton.setVisible(True) self.pauseButton.setEnabled(True) self.pauseButton.setVisible(True) self.progressBar.setVisible(True) if self.__page: nam = self.__page.networkAccessManager() else: import Helpviewer.HelpWindow nam = Helpviewer.HelpWindow.HelpWindow.networkAccessManager() reply = nam.get(QNetworkRequest(self.__url)) if self.__output.exists(): self.__output.remove() self.__output = QFile() self.__reply = reply self.__initialize(tryAgain=True) self.__state = DownloadItem.Downloading self.statusChanged.emit() @pyqtSlot(bool) def on_pauseButton_clicked(self, checked): """ Private slot to pause the download. @param checked flag indicating the state of the button (boolean) """ if checked: self.__reply.readyRead.disconnect(self.__readyRead) self.__reply.setReadBufferSize(16 * 1024) else: self.__reply.readyRead.connect(self.__readyRead) self.__reply.setReadBufferSize(16 * 1024 * 1024) self.__readyRead() @pyqtSlot() def on_stopButton_clicked(self): """ Private slot to stop the download. """ self.cancelDownload() def cancelDownload(self): """ Public slot to stop the download. """ self.setUpdatesEnabled(False) if not self.__isFtpDownload: self.stopButton.setEnabled(False) self.stopButton.setVisible(False) self.pauseButton.setEnabled(False) self.pauseButton.setVisible(False) self.tryAgainButton.setEnabled(True) self.tryAgainButton.setVisible(True) self.openButton.setEnabled(False) self.openButton.setVisible(False) self.setUpdatesEnabled(True) self.__state = DownloadItem.DownloadCancelled self.__reply.abort() self.downloadFinished.emit() @pyqtSlot() def on_openButton_clicked(self): """ Private slot to open the downloaded file. """ self.openFile() def openFile(self): """ Public slot to open the downloaded file. """ info = QFileInfo(self.__fileName) url = QUrl.fromLocalFile(info.absoluteFilePath()) QDesktopServices.openUrl(url) def openFolder(self): """ Public slot to open the folder containing the downloaded file. """ info = QFileInfo(self.__fileName) url = QUrl.fromLocalFile(info.absolutePath()) QDesktopServices.openUrl(url) def __readyRead(self): """ Private slot to read the available data. """ if self.__requestFilename and not self.__output.fileName(): return if not self.__output.isOpen(): # in case someone else has already put a file there if not self.__requestFilename: self.__getFileName() if not self.__output.open(QIODevice.WriteOnly): self.infoLabel.setText( self.tr("Error opening save file: {0}") .format(self.__output.errorString())) self.on_stopButton_clicked() self.statusChanged.emit() return self.statusChanged.emit() buffer = self.__reply.readAll() self.__sha1Hash.addData(buffer) self.__md5Hash.addData(buffer) bytesWritten = self.__output.write(buffer) if bytesWritten == -1: self.infoLabel.setText( self.tr("Error saving: {0}") .format(self.__output.errorString())) self.on_stopButton_clicked() else: self.__startedSaving = True if self.__finishedDownloading: self.__finished() def __networkError(self): """ Private slot to handle a network error. """ self.infoLabel.setText( self.tr("Network Error: {0}") .format(self.__reply.errorString())) self.tryAgainButton.setEnabled(True) self.tryAgainButton.setVisible(True) self.downloadFinished.emit() def __metaDataChanged(self): """ Private slot to handle a change of the meta data. """ locationHeader = self.__reply.header(QNetworkRequest.LocationHeader) if locationHeader and locationHeader.isValid(): self.__url = QUrl(locationHeader) import Helpviewer.HelpWindow self.__reply = Helpviewer.HelpWindow.HelpWindow\ .networkAccessManager().get(QNetworkRequest(self.__url)) self.__initialize() def __downloadProgress(self, bytesReceived, bytesTotal): """ Private method to show the download progress. @param bytesReceived number of bytes received (integer) @param bytesTotal number of total bytes (integer) """ self.__bytesReceived = bytesReceived self.__bytesTotal = bytesTotal currentValue = 0 totalValue = 0 if bytesTotal > 0: currentValue = bytesReceived * 100 / bytesTotal totalValue = 100 self.progressBar.setValue(currentValue) self.progressBar.setMaximum(totalValue) self.progress.emit(currentValue, totalValue) self.__updateInfoLabel() def bytesTotal(self): """ Public method to get the total number of bytes of the download. @return total number of bytes (integer) """ if self.__bytesTotal == -1: self.__bytesTotal = self.__reply.header( QNetworkRequest.ContentLengthHeader) if self.__bytesTotal is None: self.__bytesTotal = -1 return self.__bytesTotal def bytesReceived(self): """ Public method to get the number of bytes received. @return number of bytes received (integer) """ return self.__bytesReceived def remainingTime(self): """ Public method to get an estimation for the remaining time. @return estimation for the remaining time (float) """ if not self.downloading(): return -1.0 if self.bytesTotal() == -1: return -1.0 cSpeed = self.currentSpeed() if cSpeed != 0: timeRemaining = (self.bytesTotal() - self.bytesReceived()) / cSpeed else: timeRemaining = 1 # ETA should never be 0 if timeRemaining == 0: timeRemaining = 1 return timeRemaining def currentSpeed(self): """ Public method to get an estimation for the download speed. @return estimation for the download speed (float) """ if not self.downloading(): return -1.0 return self.__bytesReceived * 1000.0 / self.__downloadTime.elapsed() def __updateInfoLabel(self): """ Private method to update the info label. """ if self.__reply.error() != QNetworkReply.NoError: return bytesTotal = self.bytesTotal() running = not self.downloadedSuccessfully() speed = self.currentSpeed() timeRemaining = self.remainingTime() info = "" if running: remaining = "" if bytesTotal > 0: remaining = timeString(timeRemaining) info = self.tr("{0} of {1} ({2}/sec)\n{3}")\ .format( dataString(self.__bytesReceived), bytesTotal == -1 and self.tr("?") or dataString(bytesTotal), dataString(int(speed)), remaining) else: if self.__bytesReceived == bytesTotal or bytesTotal == -1: info = self.tr("{0} downloaded\nSHA1: {1}\nMD5: {2}")\ .format(dataString(self.__output.size()), str(self.__sha1Hash.result().toHex(), encoding="ascii"), str(self.__md5Hash.result().toHex(), encoding="ascii") ) else: info = self.tr("{0} of {1} - Stopped")\ .format(dataString(self.__bytesReceived), dataString(bytesTotal)) self.infoLabel.setText(info) def downloading(self): """ Public method to determine, if a download is in progress. @return flag indicating a download is in progress (boolean) """ return self.__state == DownloadItem.Downloading def downloadedSuccessfully(self): """ Public method to check for a successful download. @return flag indicating a successful download (boolean) """ return self.__state == DownloadItem.DownloadSuccessful def downloadCanceled(self): """ Public method to check, if the download was cancelled. @return flag indicating a canceled download (boolean) """ return self.__state == DownloadItem.DownloadCancelled def __finished(self): """ Private slot to handle the download finished. """ self.__finishedDownloading = True if not self.__startedSaving: return noError = self.__reply.error() == QNetworkReply.NoError self.progressBar.setVisible(False) if not self.__isFtpDownload: self.stopButton.setEnabled(False) self.stopButton.setVisible(False) self.pauseButton.setEnabled(False) self.pauseButton.setVisible(False) self.openButton.setEnabled(noError) self.openButton.setVisible(noError) self.__output.close() if QFile.exists(self.__fileName): QFile.remove(self.__fileName) self.__output.rename(self.__fileName) self.__updateInfoLabel() self.__state = DownloadItem.DownloadSuccessful self.statusChanged.emit() self.downloadFinished.emit() if self.__autoOpen: self.__open() def canceledFileSelect(self): """ Public method to check, if the user canceled the file selection. @return flag indicating cancellation (boolean) """ return self.__canceledFileSelect def setIcon(self, icon): """ Public method to set the download icon. @param icon reference to the icon to be set (QIcon) """ self.fileIcon.setPixmap(icon.pixmap(48, 48)) def fileName(self): """ Public method to get the name of the output file. @return name of the output file (string) """ return self.__fileName def absoluteFilePath(self): """ Public method to get the absolute path of the output file. @return absolute path of the output file (string) """ return QFileInfo(self.__fileName).absoluteFilePath() def getData(self): """ Public method to get the relevant download data. @return tuple of URL, save location, flag and the URL of the related web page (QUrl, string, boolean,QUrl) """ return (self.__url, QFileInfo(self.__fileName).filePath(), self.downloadedSuccessfully(), self.__pageUrl) def setData(self, data): """ Public method to set the relevant download data. @param data tuple of URL, save location, flag and the URL of the related web page (QUrl, string, boolean, QUrl) """ self.__url = data[0] self.__fileName = data[1] self.__pageUrl = data[3] self.__isFtpDownload = self.__url.scheme() == "ftp" self.filenameLabel.setText(QFileInfo(self.__fileName).fileName()) self.infoLabel.setText(self.__fileName) self.stopButton.setEnabled(False) self.stopButton.setVisible(False) self.pauseButton.setEnabled(False) self.pauseButton.setVisible(False) self.openButton.setEnabled(data[2]) self.openButton.setVisible(data[2]) self.tryAgainButton.setEnabled(not data[2]) self.tryAgainButton.setVisible(not data[2]) if data[2]: self.__state = DownloadItem.DownloadSuccessful else: self.__state = DownloadItem.DownloadCancelled self.progressBar.setVisible(False) def getInfoData(self): """ Public method to get the text of the info label. @return text of the info label (string) """ return self.infoLabel.text() def getPageUrl(self): """ Public method to get the URL of the download page. @return URL of the download page (QUrl) """ return self.__pageUrl
class CaptureThread(QThread): updateStatisticsInGUI = pyqtSignal(ThreadStatisticsData) end = pyqtSignal() def __init__(self, sharedImageBuffer, deviceUrl, dropFrameIfBufferFull, apiPreference, width, height, setting, parent=None): super(CaptureThread, self).__init__(parent) self.t = QTime() self.doStopMutex = QMutex() self.fps = Queue() # Save passed parameters self.sharedImageBuffer = sharedImageBuffer self.dropFrameIfBufferFull = dropFrameIfBufferFull self.deviceUrl = deviceUrl self._deviceUrl = int(deviceUrl) if deviceUrl.isdigit() else deviceUrl self.localVideo = True if os.path.exists(self._deviceUrl) else False self.apiPreference = apiPreference self.width = width self.height = height # Initialize variables(s) self.captureTime = 0 self.doStop = False self.sampleNumber = 0 self.fpsSum = 0.0 self.statsData = ThreadStatisticsData() self.defaultTime = 0 t = datetime.strptime(setting.skip_duration, '%H:%M:%S') self.skip_duration = timedelta(hours=t.hour, minutes=t.minute, seconds=t.second) self.video_date_time = datetime.strptime( "{} {}".format(setting.video_date, setting.video_time), '%d/%m/%Y %H:%M:%S') self.starting_time = self.video_date_time self.remain_video = None self.pause = False def update(self): current_frame = self.cap.get(1) process_time_second = round(current_frame / self.videofps, 0) self.video_date_time = self.starting_time + timedelta( seconds=process_time_second) if round(current_frame % self.videofps) == 0: self.remain_video = self.video_date_time - self.starting_time self.sharedImageBuffer.video_date_time = self.video_date_time self.sharedImageBuffer.remain_video = self.remain_video def run(self): pause = False while True: if self.pause: continue ################################ # Stop thread if doStop = TRUE # ################################ self.doStopMutex.lock() if self.doStop: self.doStop = False self.doStopMutex.unlock() break self.doStopMutex.unlock() ################################ ################################ # Synchronize with other streams (if enabled for this stream) self.sharedImageBuffer.sync(self.deviceUrl) # Capture frame ( if available) if not self.cap.grab(): if pause or not self.localVideo: continue # Video End pause = True self.end.emit() continue # Retrieve frame _, self.grabbedFrame = self.cap.retrieve() self.update() # Add frame to buffer self.sharedImageBuffer.getByDeviceUrl(self.deviceUrl).add( self.grabbedFrame, self.dropFrameIfBufferFull) self.statsData.nFramesProcessed += 1 # Inform GUI of updated statistics self.updateStatisticsInGUI.emit(self.statsData) # Limit fps delta = self.defaultTime - self.t.elapsed() # delta = self.defaultTime - self.captureTime if delta > 0: self.msleep(delta) # Save capture time self.captureTime = self.t.elapsed() # Update statistics self.updateFPS(self.captureTime) # Start timer (used to calculate capture rate) self.t.start() qDebug("Stopping capture thread...") def stop(self): with QMutexLocker(self.doStopMutex): self.doStop = True def connectToCamera(self): # Open camera self.cap = cv2.cudacodec.createVideoReader(self._deviceUrl, self.apiPreference) self.videofps = self.cap.get(5) if self.skip_duration: self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.videofps * self.skip_duration.total_seconds()) self.video_date_time = self.video_date_time + self.skip_duration # Set resolution if self.width != -1: self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, self.width) if self.height != -1: self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self.height) if camOpenResult: try: self.defaultTime = int(1000 / self.cap.get(cv2.CAP_PROP_FPS)) except: self.defaultTime = 40 # Return result return camOpenResult def disconnectCamera(self): # Camera is connected if self.cap.isOpened(): # Disconnect camera self.cap.release() return True # Camera is NOT connected else: return False def isCameraConnected(self): return self.cap.isOpened() def getInputSourceWidth(self): return self.cap.get(cv2.CAP_PROP_FRAME_WIDTH) def getInputSourceHeight(self): return self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT) def updateFPS(self, timeElapsed): # Add instantaneous FPS value to queue if timeElapsed > 0: self.fps.put(1000 / timeElapsed) # Increment sample Number self.sampleNumber += 1 # Maximum size of queue is DEFAULT_CAPTURE_FPS_STAT_QUEUE_LENGTH if self.fps.qsize() > CAPTURE_FPS_STAT_QUEUE_LENGTH: self.fps.get() # Update FPS value every DEFAULT_CAPTURE_FPS_STAT_QUEUE_LENGTH samples if self.fps.qsize( ) == CAPTURE_FPS_STAT_QUEUE_LENGTH and self.sampleNumber == CAPTURE_FPS_STAT_QUEUE_LENGTH: # Empty queue and store sum while not self.fps.empty(): self.fpsSum += self.fps.get() # Calculate average FPS self.statsData.averageFPS = self.fpsSum / CAPTURE_FPS_STAT_QUEUE_LENGTH # Reset sum self.fpsSum = 0.0 # Reset sample Number self.sampleNumber = 0
class Example(QMainWindow): def __init__(self, pipe): super().__init__() self.pipe = pipe self.gameConfig = GameConfig() self.playing = False self.game_over = [] self.all_die = 0 self.currentPlayer = 0 self.timer = QBasicTimer( ) # Used for controlling the game speed, and the canvas update self.speed = 100 self.timeCounter = 0 self.playtime = QTime() self.counter = [] self.rectangles_to_draw = [] self.playerLabels = [] self.scoreLabels = [] self.sec_counter = 1 self.special_food_border = False self.special_food = False self.score = [0, 0, 0, 0] self.initUI() # definise izgled glavnog prozora def initUI(self): self.setGeometry(200, 200, 900, 600) self.setWindowTitle("TurnSnakeGdxGame") self.setWindowIcon(QIcon('snake.png')) self.setStyleSheet("background-image : url(rsz_snake_background.png);") self.timerLabel = QLabel(self) self.timeElapsed = "Time Elapsed:" self.timerLabel.setText(str(self.timeElapsed)) self.timerLabel.resize(100, 50) self.timerLabel.move(600, 450) self.timerLabel.setStyleSheet("color: black;") self.timerCounterLabel = QLabel(self) self.timeCounter = 0 self.timerCounterLabel.setText(str(self.timeCounter)) self.timerCounterLabel.resize(50, 50) self.timerCounterLabel.move(700, 450) self.timerCounterLabel.setStyleSheet("color: black;") # next player button self.btn = QPushButton('Next Player', self) self.btn.setStyleSheet("background-color: purple; color: white;") self.btn.clicked.connect(self.next_player) self.btn.setGeometry(600, 520, 270, 50) menu = self.menuBar().addMenu("New game") self.menuBar().setStyleSheet("color: black;") self.hostAct = QAction("&Start Game", self) self.hostAct.triggered.connect(self.start) menu.addAction(self.hostAct) self.show() # metoda koja poziva metode za crtanje svih elemenata na terenu def paintEvent(self, e): qp = QPainter() qp.begin(self) self.draw_rectangles(qp) if self.playing is True: if self.special_food_border is False: if self.sec_counter % 17 == 0: self.draw_border() self.special_food_border = True qp.end() painter = QPainter(self) painter.setPen(QPen(Qt.darkGreen, 20, Qt.SolidLine)) painter.drawRect(20, 40, 520, 540) # iscrtava hranu i zmije def draw_rectangles(self, qp): col = QColor(0, 0, 0) col.setNamedColor('#d4d4d4') qp.setPen(col) for rect in self.rectangles_to_draw: qp.setBrush(rect['color']) qp.drawRect(rect['x'], rect['y'], rect['width'], rect['height']) ## crta granicu terena def draw_border(self): painter = QPainter(self) painter.setPen(QPen(Qt.darkGreen, 5, Qt.SolidLine)) painter.drawRect(450, 500, 60, 60) ## postavljanje labela za rezultat igraca def set_labels(self): for i in range(self.gameConfig.playerNumber): space = 15 + i * 50 self.playerLabels.append(QLabel(self)) self.player = "Player {}:".format(i + 1) self.playerLabels[i].setText(str(self.player)) self.playerLabels[i].setGeometry(600, space, 100, 50) self.playerLabels[i].setStyleSheet("color: black;") self.playerLabels[i].show() self.scoreLabels.append(QLabel(self)) self.score[i] = 0 self.scoreLabels[i].setText(str(self.score[3])) self.scoreLabels[i].setGeometry(660, space, 200, 50) self.scoreLabels[i].setStyleSheet("color: black;") self.scoreLabels[i].show() # sakrivanje labela ukoliko je broj igraca manji od 4 def hide_labels(self): for i in range(self.gameConfig.playerNumber): self.playerLabels[i].hide() self.scoreLabels[i].hide() # promena boje teksta u labelama kao indikator aktivnosti trenutnog igraca def change_label_color(self): for i in range(self.gameConfig.playerNumber): self.playerLabels[i].setStyleSheet("color: black;") if self.currentPlayer == 0: self.playerLabels[0].setStyleSheet("color: red;") elif self.currentPlayer == 1: self.playerLabels[1].setStyleSheet("color: green;") elif self.currentPlayer == 2: self.playerLabels[2].setStyleSheet("color: blue;") elif self.currentPlayer == 3: self.playerLabels[3].setStyleSheet("color: purple;") # signalizira izmenu igraca def next_player(self): if self.playing is True: self.pipe.send({ 'event_type': 'next_player', 'data': 'next_player' }) time.sleep(0.1) # registruje da je tipka pritisnuta i salje informaciju u pajp def keyPressEvent(self, e): if self.playing is True: self.pipe.send({'event_type': 'key_pressed', 'data': e.key()}) time.sleep(0.2) # thread def listen(self): while True: try: receive = self.pipe.recv() if receive['event_type'] == 'rectangles': self.rectangles_to_draw = receive['data'] self.update() elif receive['event_type'] == 'score': self.update_score(receive['data'], 1) elif receive['event_type'] == 'special_score': self.update_score(receive['data'], receive['score_type']) self.update_spec_food_value() elif receive['event_type'] == 'end_game': self.all_die += 1 self.set_game_over(receive['data']) elif receive['event_type'] == 'current_player': self.gameConfig.turnPlanTime = self.timeCounter self.timerCounterLabel.setText(str(self.timeCounter)) self.currentPlayer = receive['data'] self.change_label_color() except BrokenPipeError as e: print(e) print('Broken pipe error') break except EOFError as e: print(e) print('EOFError') break # resetuje brojac za specijalnu hranu def update_spec_food_value(self): self.special_food = False self.special_food_border = False self.sec_counter = 1 # slanje podataka u pajp i startovanje treda koji konstantno osluskuje da li ima pristiglih podataka def do_action(self, config: GameConfig): self.pipe.send({'event_type': 'start_game', 'data': config}) # start thread which listens on the child_connection t = Thread(target=self.listen) t.start() def start(self): dialog = StartDialog(self) dialog.exec() # pokrece tajmer def reset_value(self): for i in range(self.gameConfig.playerNumber): self.game_over.append(1) for i in range(self.gameConfig.playerNumber): self.counter.append(0) self.playing = True self.timeCounter = self.gameConfig.turnPlanTime self.speed = 100 self.playtime.start() self.timer.start(self.speed, Qt.PreciseTimer, self) # definise akciju posle pritisnutog start game dugmeta def start_game_pressed(self, gameConfig: GameConfig): self.menuBar().setDisabled(True) self.gameConfig = gameConfig if self.gameConfig.playerNumber > 4 or self.gameConfig.playerNumber < 2: dialog = ErrorDialog(self) dialog.exec() self.start() else: self.reset_value() self.set_labels() self.change_label_color() self.do_action(self.gameConfig) # prikazuje dijalog na ekranu def show_dialog(self, player: int): end_dialog = EndGameDialog(self, player) end_dialog.exec() # prikazuje specijalnu hranu def show_special_food(self): self.pipe.send({'event_type': 'special_food', 'data': 'next_player'}) time.sleep(0.1) self.special_food = True def timerEvent(self, event: QTimerEvent) -> None: """ In charge of, in this case, update the game and check the conditions to continue playing, grow, spawn food and special item """ if self.playtime.elapsed() > 1000: self.sec_counter += 1 self.gameConfig.turnPlanTime -= 1.0 self.timerCounterLabel.setText(str(self.gameConfig.turnPlanTime)) self.playtime.restart() if self.gameConfig.turnPlanTime == 0: self.next_player() self.gameConfig.turnPlanTime = self.timeCounter self.timerCounterLabel.setText(str(self.timeCounter)) if self.sec_counter % 17 == 0: self.update() if self.sec_counter % 19 == 0 and self.special_food is False: self.show_special_food() # Check if the event if from the self.timer if event.timerId() is self.timer.timerId(): if self.playing is True: if self.all_die == self.gameConfig.playerNumber - 1: winner = self.winner() self.playing = False self.show_dialog(winner) self.timer.stop() return else: super(Example, self).timerEvent(event) # odredjuje koji igrac je pobedio def winner(self): for i in range(len(self.game_over)): if self.game_over[i] == 1: return i + 1 # salje signal da je igra gotova u pajp def end_game(self, winner: int): self.pipe.send({'event_type': 'delete_all', 'data': winner}) self.hide_labels() # salje signal da je za odredjenog igraca igra gotova def set_game_over(self, player: int): for i in range(self.gameConfig.playerNumber): if player == i: self.score[i] = "Game over" self.scoreLabels[i].setText(str(self.score[i])) self.game_over[i] = 0 # menja rezultat u labelama za rezultat def update_score(self, player: int, points: int): for i in range(self.gameConfig.playerNumber): if player == i: self.score[i] = self.score[i] + points self.scoreLabels[i].setText(str(self.score[i])) def closeEvent(self, event): self.pipe.send({'event_type': 'close_app'})
class GLWidget(QOpenGLWidget): """ OpenGL widget that shows a static 3D scene, allowing the observer to freely move and look around. """ background_color = gl_array([1, 1, 1]) * 0.6 ambient_color = gl_array([1, 1, 1]) * 0.1 diffuse_color = gl_array([1, 1, 1]) camera_speed = 1 # [m/s] zoom_speed = 1 / 10 # [1/deg] mouse_sensitivity = 1 / 100 # [rad/px] update_interval = 25 # [ms] shader_program = None update_timer = None def __init__(self, create_items, *args, **kwargs): """Create from a callable ``create_items: Camera -> [Object3D]``.""" super().__init__(*args, **kwargs) self._create_items = create_items self.items = [] self._key_state = {} self._update_time = QTime() self.resize(800, 600) self.camera = Camera() self.camera.updated.connect(self.update) surface_format = self.format() # Enable multisampling (for antialiasing): # (must be set before initializeGL) surface_format.setSamples(6) # Technically, we require only 3.0, but we request 3.2 because that # allows enforcing CoreProfile. Note that there is no guarantee that # we get the requested version, but let's at least improve our chances: surface_format.setVersion(3, 2) surface_format.setProfile(QSurfaceFormat.CoreProfile) self.setFormat(surface_format) def free(self): """Free all items.""" for item in self.items: item.delete() self.items.clear() def closeEvent(self, event): """Free items.""" self.free() super().closeEvent(event) def showEvent(self, event): """Start scene updates (camera movement).""" super().showEvent(event) if self.update_timer is None: self.update_timer = QTimer(self) self.update_timer.setInterval(self.update_interval) self.update_timer.timeout.connect(self.update_event) self.update_timer.start() self._update_time.start() def hideEvent(self, event): """Stop scene updates (camera movement).""" super().hideEvent(event) if self.update_timer is not None: self.update_timer.timeout.disconnect(self.update_event) self.update_timer.stop() self.update_timer = None # def GL(self): # from PyQt5.QtGui import QOpenGLVersionProfile # version = QOpenGLVersionProfile() # version.setVersion(2, 0) # return self.context().versionFunctions(version) def initializeGL(self): """Called after first creating a valid OpenGL context. Creates shader program, sets up camera and creates an initial scene.""" logging.info('Initializing OpenGL') self.show_gl_info(GL.GL_VERSION, ' version: ') self.show_gl_info(GL.GL_VENDOR, ' vendor: ') self.show_gl_info(GL.GL_RENDERER, ' renderer: ') self.show_gl_info(GL.GL_SHADING_LANGUAGE_VERSION, ' shader: ') logging.info( ' context: {}.{}'.format(*self.context().format().version())) # We currently require modern OpenGL API for use of shaders etc. We # could ship a fallback implementation based on the deprecated API # (glBegin, etc) to be compatible with older devices, but that's # probably overkill. if not check_opengl_context(self.context(), (3, 0)): logging.error( "Cannot create shader with this version of OpenGL.\n" "This implementation uses the modern OpenGL API (>=3.0).") QTimer.singleShot(0, lambda: self.window().close()) return self.create_shader_program() self.create_scene() # Activate wireframe: # GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE) camera = self.camera camera.look_from(camera.theta, camera.phi, camera.psi) def show_gl_info(self, spec, text): """Show GL version info.""" try: string = GL.glGetString(spec).decode('utf-8') except GL.GLError: string = None if string: logging.info(text + string) else: logging.error(text + 'N/A') return string def create_scene(self): """Fetch new items from the given callable.""" self.free() if self.shader_program is not None: self.items = self._create_items(self.camera) self.update() def paintGL(self): """Handle paint event by drawing the items returned by the creator function.""" if not check_opengl_context(self.context(), (3, 0)): return program = self.shader_program projection = self.camera.projection(self.width(), self.height()) set_uniform_matrix(program, "view", self.camera.view_matrix) set_uniform_matrix(program, "projection", projection) set_uniform_vector(program, "ambient_color", self.ambient_color) set_uniform_vector(program, "diffuse_color", self.diffuse_color) set_uniform_vector(program, "diffuse_position", self.camera.position) GL.glClearColor(*self.background_color, 0) GL.glEnable(GL.GL_DEPTH_TEST) GL.glEnable(GL.GL_MULTISAMPLE) GL.glEnable(GL.GL_BLEND) GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) # Draw transparent items after opaque ones, and sorted by distance to # the observer (far to near). Note that this is only an approximation # that is correct only for point-like items; a 100% correct blending # order would have to be decided on the level of fragments (based on # the interpolated depth value). items = sorted( self.items, key=lambda item: ( item.opaque(), np.linalg.norm(self.camera.position - item.position()), ), reverse=True) for item in items: item.draw() def create_shader_program(self): """Create simple program with generic fragment/vertex shaders used to render objects with a simple ambient+diffuse lighting model.""" self.shader_program = create_shader_program([ load_shader(GL.GL_VERTEX_SHADER, 'shader_vertex.glsl'), load_shader(GL.GL_FRAGMENT_SHADER, 'shader_fragment.glsl'), ]) def minimumSizeHint(self): return QSize(50, 50) def sizeHint(self): return QSize(400, 400) def wheelEvent(self, event): """Handle mouse wheel as zoom.""" self.camera.zoom(self.zoom_speed * event.angleDelta().y()) def mousePressEvent(self, event): """Handle camera look around.""" self.last_mouse_position = event.pos() super().mousePressEvent(event) def mouseMoveEvent(self, event): """Handle camera look around.""" camera = self.camera delta = event.pos() - self.last_mouse_position if event.buttons() == Qt.RightButton: dx = delta.x() * self.mouse_sensitivity dy = delta.y() * self.mouse_sensitivity if event.modifiers() & Qt.ShiftModifier: camera.look_from(camera.theta + dx, camera.phi - dy, camera.psi) else: camera.look_toward(camera.theta + dx, camera.phi - dy, camera.psi) elif event.buttons() == Qt.RightButton | Qt.LeftButton: camera.zoom(-delta.y()) else: return super().mouseMoveEvent(event) self.last_mouse_position = event.pos() event.accept() def keyPressEvent(self, event): """Maintain a list of pressed keys for camera movement.""" key = event.key() if key in (Qt.Key_Escape, Qt.Key_Q): self.window().close() if not event.isAutoRepeat(): self._key_state[key] = True super().keyPressEvent(event) def keyReleaseEvent(self, event): """Maintain a list of pressed keys for camera movement.""" if not event.isAutoRepeat(): self._key_state[event.key()] = False def update_event(self): """Implement camera movement. Called regularly.""" pressed = lambda k: self._key_state.get(k, 0) upward = pressed(Qt.Key_Space) - pressed(Qt.Key_Control) forward = ((pressed(Qt.Key_Up) or pressed(Qt.Key_W)) - (pressed(Qt.Key_Down) or pressed(Qt.Key_S))) leftward = ((pressed(Qt.Key_Left) or pressed(Qt.Key_A)) - (pressed(Qt.Key_Right) or pressed(Qt.Key_D))) # we use this "update time" (a.k.a. "game time") to maintain a # somewhat framerate independent movement speed: ms_elapsed = self._update_time.elapsed() self._update_time.start() if forward or upward or leftward: direction = np.array([-leftward, upward, -forward]) direction = direction / np.linalg.norm(direction) translate = direction * self.camera_speed * (ms_elapsed / 1000) self.camera.translate(*translate)
class MainWindow(QMainWindow, Ui_MainWindow): """ Class documentation goes here. """ def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(MainWindow, self).__init__(parent) self.regdialog=DialogRegister() self.setupUi(self) self.arith=None self.preference=DialogPreference() self.timer=QTimer() self.timer.setInterval(10) self.caseIsOpen=False self.labelTotalMark.setText("") self.labelTime.setText("") self.createConnections() self.qtime=QTime() self.timeStart=0 self.timeElapsed=0 self.modeModel=None self.diffiModel=None def createConnections(self): # self.actionNew_Test.triggered.connect(self.on_btnNew_clicked) # self.actionSave.triggered.connect(self.on_actionSave_triggered) # self.btnSave.clicked.connect(self.on_btnSave_clicked) self.tableTestpaper.itemChanged.connect(self.on_tableTestPaper_itemChanged) self.cmbDifficulty.currentIndexChanged.connect(self.on_cmbDifficulty_currentIndexChanged) self.cmbMode.currentIndexChanged.connect(self.on_cmbMode_currentIndexChanged) return def setArith(self,arith): self.arith=arith self.answers=np.zeros(arith.getnTest())+self.arith.smallest self.setDifficulty() self.setMode() if arith.timerOn==False: self.labelTimeName.hide() self.labelTime.hide() self.preference.setArith(arith) return def setMode(self): # only called once for initialization of main window if self.modeModel is None: self.modeModel = QStringListModel() self.cmbMode.setModel(self.modeModel) self.modeModel.setStringList(self.arith.modeTexts[self.arith.diffiLevel]) self.cmbMode.setCurrentIndex(self.arith.mode) return def setDifficulty(self): if self.diffiModel is None: self.diffiModel=QStringListModel() self.cmbDifficulty.setModel(self.diffiModel) self.diffiModel.setStringList(self.arith.difficulties) self.cmbDifficulty.setCurrentIndex(self.arith.diffiLevel) return def on_cmbMode_currentIndexChanged(self): if self.arith: if self.cmbMode.currentIndex()>=0: self.arith.mode=self.cmbMode.currentIndex() else: if self.arith.mode>=len(self.arith.modeTexts[self.arith.diffiLevel]): self.arith.mode=0 self.cmbMode.setCurrentIndex(self.arith.mode) return def on_cmbDifficulty_currentIndexChanged(self): if self.arith: self.arith.diffiLevel=self.cmbDifficulty.currentIndex() if self.modeModel: self.modeModel.setStringList(self.arith.modeTexts[self.arith.diffiLevel]) return @pyqtSlot() def on_tableTestPaper_itemChanged(self): self.caseIsOpen=True return @pyqtSlot() def on_btnNew_clicked(self): """ Slot documentation goes here. """ self.arith.new() self.resetWidgets() return def resetWidgets(self): self.newTestTable() self.updateWindow() self.caseIsOpen=True if self.arith.timerOn: # self.timer.start() self.qtime.restart() return def newTestTable(self): self.tableTestpaper.clear() ncolumn=3*self.arith.nDataColumn self.tableTestpaper.setColumnCount(ncolumn) nTest=self.arith.getnTest() nrow=ceil(nTest/self.arith.nDataColumn) self.tableTestpaper.setRowCount(nrow) self.tableTestpaper.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding) headerLabels=[] for i in range(0,self.arith.nDataColumn): labels=['Expression', 'Answer','Y/N'] headerLabels+=labels self.tableTestpaper.setHorizontalHeaderLabels(headerLabels) self.tableTestpaper.resizeColumnsToContents() self.tableTestpaper.horizontalHeader().setStretchLastSection(True) self.tableTestpaper.horizontalHeader().resizeSections(QHeaderView.Stretch) for k in range(0,3,2): icol=0 for j in range(0,self.arith.nDataColumn): irow=0 for i in range(j,nTest,int(ncolumn/3)): item=QTableWidgetItem() flags=Qt.ItemIsSelectable | Qt.ItemIsEnabled item.setFlags(flags) self.tableTestpaper.setItem(irow,icol+k,item) irow+=1 icol+=3 k=1 icol=0 for j in range(0,self.arith.nDataColumn): irow=0 for i in range(j,nTest,int(ncolumn/3)): # item = QLineEdit() # item.setValidator(QIntValidator(item)) # self.tableTestpaper.setCellWidget(irow, icol+k, item) item=QTableWidgetItem() flags=Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled item.setFlags(flags) self.tableTestpaper.setItem(irow,icol+k,item) irow+=1 icol+=3 return def updateTestPaper(self): ncolumn=3*self.arith.nDataColumn nTest=self.arith.getnTest() icol=0 for j in range(0,self.arith.nDataColumn): irow=0 for i in range(j,nTest,int(ncolumn/3)): self.tableTestpaper.item(irow,icol).setText(self.arith.texts[i]) irow+=1 icol+=3 return def updateWindow(self): self.updateTestPaper() self.updateResultWindow() self.cmbDifficulty.setCurrentIndex(self.arith.diffiLevel) self.cmbMode.setCurrentIndex(self.arith.mode) return def updateResultWindow(self): # TODO: return def getAnswers(self): """ read answer from self.tableTestPaper """ ncolumn=3*self.arith.nDataColumn nTest=self.arith.getnTest() nrow=ceil(nTest/self.arith.nDataColumn) nsp=NumericStringParser() ok=False icol=1 for j in range(0,self.arith.nDataColumn): irow=0 for i in range(j,nTest,int(ncolumn/3)): text=self.tableTestpaper.item(irow,icol).text() # text=self.tableTestpaper.cellWidget(irow,icol).text() if not (text.strip()==str('')): itext=int(text.strip(),10) self.answers[i]=int(text.strip(),10) # goodanswers=nsp.eval(self.tableTestpaper.item(irow,icol-1).text()) # print("%d, %d: %d, %d\n" % (irow,icol,self.answers[i], goodanswers)) irow+=1 icol+=3 return def outputMarkReport(self): self.totalMarks=self.arith.getTotalMark() self.marks=self.arith.getMarks() self.labelTotalMark.setText(str(self.totalMarks)) ncolumn=3*self.arith.nDataColumn nTest=self.arith.getnTest() nrow=ceil(nTest/self.arith.nDataColumn) icol=2 for j in range(0,self.arith.nDataColumn): irow=0 for i in range(j,nTest,int(ncolumn/3)): text=self.tableTestpaper.item(irow,icol-1).text() if (text.strip()==str('')): mark='?' color=Qt.gray elif self.marks[i]==1: mark='Y' #'√' color=Qt.green elif self.marks[i]==0: mark='X' color=Qt.red # item=self.tableTestpaper.item(0,0).s # self.tableTestpaper.item(irow,icol).setBackgroundColor(color) # self.tableTestpaper.item(irow,icol).setBackground(QColor(100,100,150)) self.tableTestpaper.item(irow,icol).setBackground(color) self.tableTestpaper.item(irow,icol).setText(mark) # self.tableTestpaper.item(irow,icol).setWidth(80) irow+=1 icol+=3 if self.arith.timerOn: self.labelTimeName.show() self.labelTime.show() self.labelTime.setText(str(self.timeElapsed)+' sec') return def openFile(self): fname, _ = (QFileDialog.getOpenFileName(self, \ "Open File", "./", \ "CSV File (*.csv);;Text file (*.txt);;All Files (*)")) if not fname: # QMessageBox.information(self, "Unable to open file", # "There was an error opening \"%s\"" % fname) return with open(fname, 'rt',encoding='utf8') as stream: reader = csv.reader(stream,delimiter=',') i=0 for row in reader: if (i==1): self.arith.diffiLevel=int(row[1]) self.arith.mode=int(row[3]) if (i==2): ncol=len(row) self.arith.nDataColumn=int(ncol/3) i+=1 nrowfile=i nrow=i-2 stream.seek(0) i=0 for row in reader: if (i==nrowfile-1): ncol=int(len(row)/3) self.arith.nTest=(nrow-1)*self.arith.nDataColumn+ncol i+=1 self.arith.new() irow=0 i=0 stream.seek(0) for row in reader: if (irow>=2): if irow<nrowfile-1: ncol1=self.arith.nDataColumn else: ncol1=int(len(row)/3) icol=0 for j in range(icol,len(row),3): text=row[j] self.arith.texts[i]=text i+=1 irow+=1 self.arith.calcResults() self.resetWidgets() return def saveFile(self): fname, _ = (QFileDialog.getSaveFileName(self, \ "Save File As", "./", \ "CSV File (*.csv);;Text file (*.txt);;All Files (*)")) #??? if not fname: # QMessageBox.information(self, "Unable to open file", # "There was an error opening \"%s\"" % fname) return with open((fname), 'wt',encoding='utf8') as stream: writer = csv.writer(stream) writer.writerow(['Marks:', str(self.totalMarks), 'Elapsed time(sec): ', str(self.timeElapsed)]) writer.writerow(['Difficulty: ',self.arith.diffiLevel,'Mode: ', self.arith.mode]) for row in range(0,self.tableTestpaper.rowCount()): rowdata = [] for column in range(self.tableTestpaper.columnCount()): item = self.tableTestpaper.item(row, column) # item is not None or if item.text() is not str(''): rowdata.append( (item.text()))#.encode('utf8')) else: rowdata.append(str('N/A')) writer.writerow(rowdata) self.caseIsOpen=False return @pyqtSlot() def on_btnReset_clicked(self): """ Slot documentation goes here. """ self.arith.reset() self.updateWindow() return @pyqtSlot() def on_btnSave_clicked(self): """ Slot documentation goes here. """ if not self.arith.empty: self.saveFile() else: QMessageBox.information(self, "Unable to save file", "The test paper is still empty" ) return @pyqtSlot() def on_btnMark_clicked(self): """ Slot documentation goes here. """ if self.arith.timerOn: # self.timer.stop() self.timeElapsed=float(self.qtime.elapsed())/1000.0 self.getAnswers() self.arith.mark(self.answers) self.outputMarkReport() return @pyqtSlot() def on_btnStop_clicked(self): """ Slot documentation goes here. """ # TODO: not implemented yet self.timer.stop() return @pyqtSlot() def on_btnQuit_clicked(self): """ Slot documentation goes here. """ if(self.caseIsOpen==False): QCoreApplication.instance().quit() else: reply = QMessageBox.question(self, 'Warning', "Test not saved. Are you sure to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: QCoreApplication.instance().quit() # else: # event.ignore() return @pyqtSlot() def on_btnOpen_clicked(self): """ Slot documentation goes here. """ self.openFile() return @pyqtSlot() def on_actionOpen_triggered(self): """ Slot documentation goes here. """ self.openFile() return @pyqtSlot() def on_actionSave_triggered(self): """ Slot documentation goes here. """ if not self.arith.empty: self.saveFile() else: QMessageBox.information(self, "Unable to save file", "The test paper is still empty" ) return @pyqtSlot() def on_actionPreferences_triggered(self): """ Slot documentation goes here. """ self.preference.showArith() if self.preference.exec_()==QDialog.Accepted: self.answers=np.zeros(self.arith.getnTest())+self.arith.smallest if not self.arith.timerOn: self.labelTimeName.hide() self.labelTime.hide() else: self.labelTimeName.show() return @pyqtSlot() def on_actionAbout_triggered(self): """ Slot documentation goes here. """ QMessageBox.information(self, "About Arith", __arith_title__) return @pyqtSlot() def on_actionNew_Test_triggered(self): """ Slot documentation goes here. """ # TODO: not implemented yet self.on_btnNew_clicked() return @pyqtSlot() def on_actionQuit_triggered(self): """ Slot documentation goes here. """ QCoreApplication.instance().quit() return @pyqtSlot() def on_actionReset_triggered(self): """ Slot documentation goes here. """ self.arith.reset() self.updateWindow() return @pyqtSlot() def on_actionMark_triggered(self): """ Slot documentation goes here. """ self.on_btnMark_clicked() return @pyqtSlot() def on_actionRegister_triggered(self): if self.regdialog.exec_()==QDialog.Accepted: print('reg OK') # else: return
def artisticSleep(sleepTime): time = QTime() time.restart() while time.elapsed() < sleepTime: QApplication.processEvents(QEventLoop.AllEvents, 50)
class TrackWidget(QWidget): def __init__(self, track, scale, parent=None): super(TrackWidget, self).__init__(parent) self.antialiased = False self.frameNo = 0 self.setBackgroundRole(QPalette.Base) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.point_pen = QPen(QColor(0, 0, 0), 4) self.segment_pen = QPen(QColor(0, 0, 0), 2) self.base_poly_curve_pen = QPen(QColor(127, 127, 127), 1) self.current_point_pen = QPen(QColor(200, 0, 0), 5) self.tangent_line_pen = QPen(QColor(200, 0, 0), 1) self.time = QTime() self.time.start() def set_track(self, track): self.track = track def setAntialiased(self, antialiased): self.antialiased = antialiased self.update() def nextAnimationFrame(self): self.frameNo += 1 self.update() def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, self.antialiased) for i in range(len(self.track.points) - 1): painter.setPen(self.base_poly_curve_pen) painter.drawLine( QLineF(self.track.points[i].point.x * scale, self.track.points[i].point.y * scale, self.track.points[i + 1].point.x * scale, self.track.points[i + 1].point.y * scale)) for segment in self.track.segments: if type(segment) == LineSegment: painter.setPen(self.point_pen) painter.drawPoint( QPointF(segment.start.x * scale, segment.start.y * scale)) painter.drawPoint( QPointF(segment.finish.x * scale, segment.finish.y * scale)) painter.setPen(self.segment_pen) painter.drawLine(segment.start.x * scale, segment.start.y * scale, segment.finish.x * scale, segment.finish.y * scale) elif type(segment) == ArcSegment: painter.setPen(self.point_pen) painter.drawPoint( QPointF(segment.start.x * scale, segment.start.y * scale)) painter.drawPoint( QPointF(segment.finish.x * scale, segment.finish.y * scale)) painter.setPen(self.segment_pen) painter.drawEllipse( QPointF(segment.M.x * scale, segment.M.y * scale), segment.smooth_radius * scale, segment.smooth_radius * scale) current_time = self.time.elapsed() current_point = Track.get_track_point(track, current_time) painter.setPen(self.current_point_pen) painter.drawPoint( QPointF(current_point.x * scale, current_point.y * scale)) painter.setPen(self.tangent_line_pen) painter.drawLine( QLineF(current_point.x * scale, current_point.y * scale, current_point.x * scale + 20 * cos(current_point.angle), current_point.y * scale + 20 * sin(current_point.angle)))
class Example(QWidget): def __init__(self, vehicles_N, vehicles_W, vehicles_E, sendData_1, sendData_3): super().__init__() self.vehicles_N = vehicles_N self.vehicles_W = vehicles_W self.vehicles_E = vehicles_E self.sendData_1 = sendData_1 self.sendData_3 = sendData_3 self.my_result = 0 self.t_t = 0 self.initUI() self.timer = QTimer(self) self.timer.timeout.connect(self.update) self.timer.start(1000/60)#一秒間隔で更新 self.t = QTime() self.t.start() self.show() def initUI(self): self.setGeometry(300, 300, 600, 600) self.setWindowTitle("Koku's Simulation") self.ti = 0 self.beze_t = [] self.r = [] self.up_left_x = [] self.up_left_y = [] self.down_left_x = [] self.down_left_y = [] self.up_right_x = [] self.up_right_y = [] self.down_right_x = [] self.down_right_y = [] for i in range(10): self.beze_t.append(0) self.r.append(0) self.up_left_x.append(0) self.up_left_y.append(0) self.down_left_x.append(0) self.down_left_y.append(0) self.up_right_x.append(0) self.up_right_y.append(0) self.down_right_x.append(0) self.down_right_y.append(0) self.single_0_0 = True self.single_0_1 = True self.collision_check = [] self.collision_check_N = [] self.collision_check_S = [] self.collision_check_W = [] self.collision_check_E = [] self.grid = {} for i in range(270, 330, 10): for j in range(270, 330, 10): self.grid[(i, j)] = True def paintEvent(self, e): self.t_t += 1 qp = QPainter(self) self.drawLines(qp) #self.drawSignals_0(qp) self.drawVehicles(qp) def drawLines(self, qp): # print(self.t.elapsed()) pen = QPen(Qt.black, 2, Qt.SolidLine) pen_dash = QPen(Qt.black, 2, Qt.DotLine) # Vertical qp.setPen(pen) qp.drawLine(270, 0, 270, 600) # with grids ################## # qp.drawLine(280, 0, 280, 600) # qp.drawLine(290, 0, 290, 600) # qp.drawLine(300, 0, 300, 600) # qp.drawLine(310, 0, 310, 600) # qp.drawLine(320, 0, 320, 600) # with grids ################## qp.drawLine(330, 0, 330, 600) qp.drawLine(300, 0, 300, 270) qp.drawLine(300, 330, 300, 600) qp.setPen(pen_dash) qp.drawLine(280, 330, 280, 600) qp.drawLine(290, 330, 290, 600) qp.drawLine(310, 330, 310, 600) qp.drawLine(320, 330, 320, 600) qp.drawLine(280, 0, 280, 270) qp.drawLine(290, 0, 290, 270) qp.drawLine(310, 0, 310, 270) qp.drawLine(320, 0, 320, 270) # Tropical qp.setPen(pen) qp.drawLine(0, 270, 600, 270) # with grids ################## # qp.drawLine(0, 280, 600, 280) # qp.drawLine(0, 290, 600, 290) # qp.drawLine(0, 300, 600, 300) # qp.drawLine(0, 310, 600, 310) # qp.drawLine(0, 320, 600, 320) # with grids ################## qp.drawLine(0, 330, 600, 330) qp.drawLine(0, 300, 270, 300) qp.drawLine(330, 300, 600, 300) qp.setPen(pen_dash) qp.drawLine(0, 280, 270, 280) qp.drawLine(0, 290, 270, 290) qp.drawLine(0, 310, 270, 310) qp.drawLine(0, 320, 270, 320) qp.drawLine(330, 280, 600, 280) qp.drawLine(330, 290, 600, 290) qp.drawLine(330, 310, 600, 310) qp.drawLine(330, 320, 600, 320) def drawSignals_0(self, qp): #print(self.t.elapsed()) if 1000 < self.t.elapsed() < 2000: qp.setPen(Qt.black) qp.setBrush(Qt.red) qp.drawEllipse(272, 262, 6, 6) qp.drawEllipse(282, 262, 6, 6) qp.drawEllipse(292, 262, 6, 6) qp.setBrush(Qt.green) qp.drawEllipse(332, 272, 6, 6) qp.drawEllipse(332, 282, 6, 6) qp.drawEllipse(332, 292, 6, 6) qp.setBrush(Qt.red) qp.drawEllipse(302, 332, 6, 6) qp.drawEllipse(312, 332, 6, 6) qp.drawEllipse(322, 332, 6, 6) qp.setBrush(Qt.green) qp.drawEllipse(262, 302, 6, 6) qp.drawEllipse(262, 312, 6, 6) qp.drawEllipse(262, 322, 6, 6) self.single_0_0 = False self.single_0_1 = True else: qp.setPen(Qt.black) qp.setBrush(Qt.green) qp.drawEllipse(272, 262, 6, 6) qp.drawEllipse(282, 262, 6, 6) qp.drawEllipse(292, 262, 6, 6) qp.setBrush(Qt.red) qp.drawEllipse(332, 272, 6, 6) qp.drawEllipse(332, 282, 6, 6) qp.drawEllipse(332, 292, 6, 6) qp.setBrush(Qt.green) qp.drawEllipse(302, 332, 6, 6) qp.drawEllipse(312, 332, 6, 6) qp.drawEllipse(322, 332, 6, 6) qp.setBrush(Qt.red) qp.drawEllipse(262, 302, 6, 6) qp.drawEllipse(262, 312, 6, 6) qp.drawEllipse(262, 322, 6, 6) self.single_0_0 = True self.single_0_1 = False def coordinate_up_left_x(self, po_x, r): return po_x - 5 * math.cos(math.radians(r)) def coordinate_up_left_y(self, po_y): return po_y def coordinate_up_right_x(self, po_x, r): return po_x + 10 * math.cos(math.radians(r)) def coordinate_up_right_y(self, po_y): return po_y def coordinate_down_left_x(self, po_x, r): return po_x - 5 * math.cos(math.radians(r)) def coordinate_down_left_y(self, po_y, r): return po_y + 5 * math.sin(math.radians(r)) + 10 * math.cos(math.radians(r)) def coordinate_down_right_x(self, po_x, r): return po_x + 10 * math.cos(math.radians(r)) def coordinate_down_right_y(self, po_y, r): return po_y + 10 * math.sin(math.radians(r)) + 5 * math.cos(math.radians(r)) def propose_pattern_1(self, veh_id, current, origin, destination, speed, current_time, pattern): server_address = ('localhost', 6789) max_size = 4096 print('Starting the client at', datetime.now()) client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sendData_1["pattern"] = 3 #self.sendData_1["position"] = list(current) current_position = list(current) print('++++++++++++++++++++++++++++++++++++++') print(self.sendData_1) self.sendData_1["origin"] = list(origin) self.sendData_1["destination"] = list(destination) self.sendData_1["speed"] = speed #self.sendData_1["current_time"] = current_time # sendData_1: veh info and current Total_time #mes = bytes(json.dumps(dict({"time_step": self.t_t}, **self.sendData_1["vehicle"][veh_id])), encoding='utf-8') dictMerge = dict({"time_step": self.t_t}, **self.sendData_1["vehicle"][veh_id]) dictMerge = dict({"position": current_position}, **dictMerge) mes = bytes(json.dumps(dictMerge), encoding='utf-8') #print(mes) client.sendto(mes, server_address) data, server = client.recvfrom(max_size) data = data.decode('utf-8') recData = json.loads(data) print('At', datetime.now(), server, 'said', recData) client.close() #print('!!!!!!!', recData['result']) self.my_result = recData['result'] return self.my_result def propose_pattern_3(self, veh_id, current, origin, destination, speed, current_time): server_address = ('localhost', 6789) max_size = 4096 print('Starting the client at', datetime.now()) client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.sendData_3["pattern"] = 3 self.sendData_3["position"] = list(current) self.sendData_3["origin"] = list(origin) self.sendData_3["destination"] = list(destination) self.sendData_3["speed"] = speed self.sendData_3["current_time"] = current_time # sendData_3: veh info and current Total_time mes = bytes(json.dumps(dict({"time_step": self.t_t}, **self.sendData_3["vehicle"][veh_id])), encoding='utf-8') print(mes) client.sendto(mes, server_address) data, server = client.recvfrom(max_size) data = data.decode('utf-8') recData = json.loads(data) print('At', datetime.now(), server, 'said', recData) client.close() #print('!!!!!!!', recData['result']) self.my_result = recData['result'] return self.my_result def drawVehicles(self, qp): qp.setPen(Qt.black) qp.setBrush(Qt.green) #qp.drawRect(310, 310, 5, 10) #self.propose(1, [262, 273], [270, 273], [330, 330], 2) # for i in range(10): # if self.propose(i): # print('?????????????') # qp.drawRect(322, 330, 5, 10) # else: # print('!!!!!!!!!!!!!') # qp.drawRect(400, 400, 5, 10) # Vehicles from North # for i, veh in enumerate(vehicles_N): # if (veh.getPosition().x + veh.getSpeed().x, veh.getPosition().y + veh.getSpeed().y) in self.collision_check_N: # qp.drawRect(veh.getPosition().x, veh.getPosition().y, veh.getSize().x, veh.getSize().y) # for i in range(11): # self.collision_check_N.append((veh.getPosition().x, veh.getPosition().y - i)) # else: # if veh.getPosition().y + veh.getSpeed().y > 260 and veh.getPosition().y <= 260: # if self.single_0_1: # qp.drawRect(veh.getPosition().x, veh.getPosition().y, veh.getSize().x, veh.getSize().y) # for i in range(11): # self.collision_check_N.append((veh.getPosition().x, veh.getPosition().y - i)) # else: # if veh.getPosition().y <= 270: # if self.grid[((veh.getPosition().x + veh.getSpeed().x) // 10 * 10, # (veh.getPosition().y + veh.getSpeed().y + veh.getSize().y) // 10 * 10)] and \ # self.grid[((veh.getPosition().x + veh.getSpeed().x + veh.getSize().x) // 10 * 10, # (veh.getPosition().y + veh.getSpeed().y + veh.getSize().y) // 10 * 10)]: # # veh.getPosition().y += veh.getSpeed().y # qp.drawRect(veh.getPosition().x, veh.getPosition().y, 5, 10) # for i in range(11): # self.collision_check_N.append((veh.getPosition().x, veh.getPosition().y - i)) # self.grid[(veh.getPosition().x // 10 * 10, (veh.getPosition().y + veh.getSize().y) // 10 * 10)] = False # self.grid[((veh.getPosition().x + veh.getSize().x) // 10 * 10, (veh.getPosition().y + veh.getSize().y) // 10 * 10)] = False # else: # try: # if self.grid[((veh.getPosition().x + veh.getSpeed().x) // 10 * 10, # (veh.getPosition().y + veh.getSpeed().y) // 10 * 10)] and \ # self.grid[((veh.getPosition().x + veh.getSpeed().x + veh.getSize().x) // 10 * 10, # (veh.getPosition().y + veh.getSpeed().y) // 10 * 10)] and \ # self.grid[((veh.getPosition().x + veh.getSpeed().x) // 10 * 10, # (veh.getPosition().y + veh.getSpeed().y + veh.getSize().y) // 10 * 10)] and \ # self.grid[((veh.getPosition().x + veh.getSpeed().x + veh.getSize().x) // 10 * 10, # (veh.getPosition().y + veh.getSpeed().y + veh.getSize().y) // 10 * 10)]: # # self.vehicles_N[i].getPosition().y += veh.getSpeed().y # # self.grid[((veh.getPosition().x + veh.getSpeed().x) // 10 * 10, # (veh.getPosition().y + veh.getSpeed().y) // 10 * 10)] = False # self.grid[((veh.getPosition().x + veh.getSpeed().x + veh.getSize().x) // 10 * 10, # (veh.getPosition().y + veh.getSpeed().y) // 10 * 10)] = False # self.grid[((veh.getPosition().x + veh.getSpeed().x) // 10 * 10, # (veh.getPosition().y + veh.getSpeed().y + veh.getSize().y) // 10 * 10)] = False # self.grid[((veh.getPosition().x + veh.getSpeed().x + veh.getSize().x) // 10 * 10, # (veh.getPosition().y + veh.getSpeed().y + veh.getSize().y) // 10 * 10)] = False # # if self.vehicles_N[i].getPosition().y > 600: # self.vehicles_N[i].getPosition().y = 0 # qp.drawRect(veh.getPosition().x, veh.getPosition().y, 5, 10) # for i in range(11): # self.collision_check_N.append((veh.getPosition().x, veh.getPosition().y - i)) # # except KeyError: # self.vehicles_N[i].getPosition().y += veh.getSpeed().y # # if self.vehicles_N[i].getPosition().y > 600: # self.vehicles_N[i].getPosition().y = 0 # # qp.drawRect(self.vehicles_N[i].getPosition().x, self.vehicles_N[i].getPosition().y, 5, 10) # # else: # # print(self.single_0_1) # veh.getPosition().y += veh.getSpeed().y # if veh.getPosition().y > 600: # veh.getPosition().y = 0 # # print(self.t.elapsed()) # qp.drawRect(veh.getPosition().x, veh.getPosition().y, 5, 10) # for i in range(11): # self.collision_check_N.append((veh.getPosition().x, veh.getPosition().y - i)) #print(self.collision_check) # Vehicles from West for i, veh in enumerate(vehicles_W): # Check if there are vehicles ahead. If true, stop if (veh.getPosition().x + veh.getSpeed().x, veh.getPosition().y + veh.getSpeed().y) in self.collision_check_W: qp.drawRect(veh.getPosition().x, veh.getPosition().y, veh.getSize().x, veh.getSize().y) # Make the room not available for other vehicles for j in range(11): self.collision_check_W.append((veh.getPosition().x - j, veh.getPosition().y)) # Move forward else: # Just before the intersection if veh.getPosition().x + 10 + 2 > 270 and veh.getPosition().x <= 270 - 10: #+++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Check traffic signal. True, then stop before entering. #print(veh.getPosition()) if not self.propose_pattern_1(i, (veh.getPosition().x, veh.getPosition().y), (270, 273), (330, 330), veh.getSpeed().x, self.t_t, 1): # if True: qp.drawRect(veh.getPosition().x, veh.getPosition().y, 10, 5) for j in range(11): self.collision_check_W.append((veh.getPosition().x - j, veh.getPosition().y)) # Enter intersection else: veh.getPosition().x += 2 qp.drawRect(veh.getPosition().x, veh.getPosition().y, 10, 5) for j in range(11): self.collision_check_W.append((veh.getPosition().x - j, veh.getPosition().y)) # # Light up the grids in the intersection # # Up left # if (veh.getPosition().x // 10 * 10, veh.getPosition().y // 10 * 10) in self.grid: # self.grid[(veh.getPosition().x // 10 * 10, veh.getPosition().y // 10 * 10)] = False # #print('success, x:', veh.getPosition().x) # # # Up right # if ((veh.getPosition().x + 10) // 10 * 10, veh.getPosition().y // 10 * 10) in self.grid: # self.grid[((veh.getPosition().x + 10) // 10 * 10, veh.getPosition().y // 10 * 10)] = False # #print('success, x:', veh.getPosition().x) # # # Down left # if (veh.getPosition().x // 10 * 10, (veh.getPosition().y) // 10 * 10) in self.grid: # self.grid[(veh.getPosition().x // 10 * 10, (veh.getPosition().y + 5) // 10 * 10)] = False # #print('success, x:', veh.getPosition().x) # # # Down right # if ((veh.getPosition().x + 10) // 10 * 10, (veh.getPosition().y) // 10 * 10) in self.grid: # self.grid[((veh.getPosition().x + 10) // 10 * 10, (veh.getPosition().y + 5) // 10 * 10)] = False # #print('success, x:', veh.getPosition().x) # Already in the intersection else: if 270 < veh.getPosition().x < 328 and veh.getPosition().y < 330: qp.save() qp.translate(veh.getPosition().x, veh.getPosition().y) # Calculate rotation angle if (((veh.getPosition().x - 270 + 3) / 60) * 90 > 15): self.r[i] = ((veh.getPosition().x - 270 + 3) / 60) * 90 qp.rotate(self.r[i]) else: self.r[i] = 0 qp.rotate(self.r[i]) qp.translate(-veh.getPosition().x, -veh.getPosition().y) # Calculate trajectory by using Bezier Curve x = pow(1 - (self.beze_t[i] / 60), 2) * 273 + 2 * (self.beze_t[i] / 60) * ( 1 - self.beze_t[i] / 60) * 332 + pow( self.beze_t[i] / 60, 2) * 332 y = pow(1 - (self.beze_t[i] / 60), 2) * 273 + 2 * (self.beze_t[i] / 60) * ( 1 - self.beze_t[i] / 60) * 273 + pow( self.beze_t[i] / 60, 2) * 332 veh.setPosition(Position(x, y)) self.beze_t[i] += 2 qp.drawRect(veh.getPosition().x, veh.getPosition().y, 10, 5) for j in range(11): self.collision_check_W.append((veh.getPosition().x - j, veh.getPosition().y)) qp.restore() # Calculate the big Square's coordinate self.up_left_x[i] = self.coordinate_up_left_x(veh.getPosition().x, self.r[i]) self.up_left_y[i] = self.coordinate_up_left_y(veh.getPosition().y) self.down_left_x[i] = self.coordinate_down_left_x(veh.getPosition().x, self.r[i]) self.down_left_y[i] = self.coordinate_down_left_y(veh.getPosition().y, self.r[i]) self.up_right_x[i] = self.coordinate_up_right_x(veh.getPosition().x, self.r[i]) self.up_right_y[i] = self.coordinate_up_right_y(veh.getPosition().y) self.down_right_x[i] = self.coordinate_down_right_x(veh.getPosition().x, self.r[i]) self.down_right_y[i] = self.coordinate_down_right_y(veh.getPosition().y, self.r[i]) # # Up left # if (self.up_left_x[i] // 10 * 10, self.up_left_y[i] // 10 * 10) in self.grid: # self.grid[(self.up_left_x[i] // 10 * 10, self.up_left_y[i] // 10 * 10)] = False # # print('success') # # # Up right # if ((self.up_right_x[i]) // 10 * 10, self.up_right_y[i] // 10 * 10) in self.grid: # self.grid[((self.up_right_x[i]) // 10 * 10, self.up_right_y[i] // 10 * 10)] = False # # print('success') # # # Down left # if (self.down_left_x[i] // 10 * 10, (self.down_left_y[i]) // 10 * 10) in self.grid: # self.grid[(self.down_left_x[i] // 10 * 10, (self.down_left_y[i]) // 10 * 10)] = False # # print('success') # # # Down right # if ((self.down_right_x[i]) // 10 * 10, (self.down_right_y[i]) // 10 * 10) in self.grid: # self.grid[((self.down_right_x[i]) // 10 * 10, (self.down_right_y[i]) // 10 * 10)] = False # # print('success') # Already left intersection elif 328 <= veh.getPosition().x and veh.getPosition().y < 600: qp.save() qp.translate(veh.getPosition().x, veh.getPosition().y) qp.rotate(90) qp.translate(-veh.getPosition().x, -veh.getPosition().y) veh.getPosition().y += 2 qp.drawRect(veh.getPosition().x, veh.getPosition().y, 10, 5) for j in range(11): self.collision_check_W.append((veh.getPosition().x, veh.getPosition().y - j)) qp.restore() # Already left screen elif veh.getPosition().y >= 600: veh.getPosition().x = 0 veh.getPosition().y = 273 self.beze_t[i] = 0 qp.drawRect(veh.getPosition().x, veh.getPosition().y, 10, 5) for j in range(11): self.collision_check_W.append((veh.getPosition().x, veh.getPosition().y - j)) # Move horizontal direction(across X_axis) else: veh.getPosition().x += 2 qp.drawRect(veh.getPosition().x, veh.getPosition().y, 10, 5) for j in range(11): self.collision_check_W.append((veh.getPosition().x - j, veh.getPosition().y)) # Vehicle2 # if self.single_0_0: # qp.drawRect(self.vehicles_E[0].getPosition().x, self.vehicles_E[0].getPosition().y, 10, 5) # else: if 330 <= (vehicles_E[0].getPosition().x) and (vehicles_E[0].getPosition().x - vehicles_E[0].getSpeed().x) < 330: #if self.propose_pattern_3(0, (veh.getPosition().x, veh.getPosition().y), (330, 272), (260, 272), veh.getSpeed().x, self.t_t): if True: self.vehicles_E[0].getPosition().x -= self.vehicles_E[0].getSpeed().x if self.vehicles_E[0].getPosition().x < 0: self.vehicles_E[0].getPosition().x = 600 qp.drawPoint(self.vehicles_E[0].getPosition().x + 1, self.vehicles_E[0].getPosition().y - 1) qp.drawRect(self.vehicles_E[0].getPosition().x, self.vehicles_E[0].getPosition().y, 10, 5) else: qp.drawRect(self.vehicles_E[0].getPosition().x, self.vehicles_E[0].getPosition().y, 10, 5) else: self.vehicles_E[0].getPosition().x -= self.vehicles_E[0].getSpeed().x if self.vehicles_E[0].getPosition().x < 0: self.vehicles_E[0].getPosition().x = 600 qp.drawRect(self.vehicles_E[0].getPosition().x, self.vehicles_E[0].getPosition().y, 10, 5) ############################################################################################### # Just for seminar0920 # if 492 < self.t_t and self.t_t < 523: # qp.drawRect(self.vehicles_E[0].getPosition().x, self.vehicles_E[0].getPosition().y, 10, 5) # else: # self.vehicles_E[0].getPosition().x -= self.vehicles_E[0].getSpeed().x # qp.drawRect(self.vehicles_E[0].getPosition().x, self.vehicles_E[0].getPosition().y, 10, 5) # # if self.vehicles_E[0].getPosition().x < 0: # self.vehicles_E[0].getPosition().x = 600 ############################################################################################### # try: # if self.grid[((self.vehicles_E[0].getPosition().x - 5) // 10 * 10, self.vehicles_E[0].getPosition().y // 10 * 10)] and \ # self.grid[((self.vehicles_E[0].getPosition().x + 10 - 5) // 10 * 10, self.vehicles_E[0].getPosition().y // 10 * 10)] and \ # self.grid[((self.vehicles_E[0].getPosition().x - 5) // 10 * 10, (self.vehicles_E[0].getPosition().y + 5) // 10 * 10)] and \ # self.grid[((self.vehicles_E[0].getPosition().x + 10 - 5) // 10 * 10, (self.vehicles_E[0].getPosition().y + 5) // 10 * 10)]: # # self.vehicles_E[0].getPosition().x -= 3 # # if self.vehicles_E[0].getPosition().x < 0: # self.vehicles_E[0].getPosition().x = 600 # # qp.drawPoint(self.vehicles_E[0].getPosition().x + 1, self.vehicles_E[0].getPosition().y - 1) # qp.drawRect(self.vehicles_E[0].getPosition().x, self.vehicles_E[0].getPosition().y, 10, 5) # # else: # qp.drawPoint(self.vehicles_E[0].getPosition().x + 1, self.vehicles_E[0].getPosition().y - 1) # qp.drawRect(self.vehicles_E[0].getPosition().x, self.vehicles_E[0].getPosition().y, 10, 5) # # except KeyError: # self.vehicles_E[0].getPosition().x -= 3 # # if self.vehicles_E[0].getPosition().x < 0: # self.vehicles_E[0].getPosition().x = 600 # # qp.drawPoint(self.vehicles_E[0].getPosition().x + 1, self.vehicles_E[0].getPosition().y - 1) # qp.drawRect(self.vehicles_E[0].getPosition().x, self.vehicles_E[0].getPosition().y, 10, 5) self.collision_check = [] self.collision_check_N = [] self.collision_check_S = [] self.collision_check_W = [] self.collision_check_E = [] # # # for i in range(270, 330, 10): # for j in range(270, 330, 10): # self.grid[(i, j)] = True # # self.ti += 10 if self.ti > 700: self.ti = 0 # print(self.t.elapsed()) self.t.restart()
class Connection(QTcpSocket): """ Class representing a peer connection. @signal readyForUse() emitted when the connection is ready for use @signal newMessage(user, message) emitted after a new message has arrived (string, string) @signal getParticipants() emitted after a get participants message has arrived @signal participants(participants) emitted after the list of participants has arrived (list of strings of "host:port") """ WaitingForGreeting = 0 ReadingGreeting = 1 ReadyForUse = 2 PlainText = 0 Ping = 1 Pong = 2 Greeting = 3 GetParticipants = 4 Participants = 5 Editor = 6 Undefined = 99 ProtocolMessage = "MESSAGE" ProtocolPing = "PING" ProtocolPong = "PONG" ProtocolGreeting = "GREETING" ProtocolGetParticipants = "GET_PARTICIPANTS" ProtocolParticipants = "PARTICIPANTS" ProtocolEditor = "EDITOR" readyForUse = pyqtSignal() newMessage = pyqtSignal(str, str) getParticipants = pyqtSignal() participants = pyqtSignal(list) editorCommand = pyqtSignal(str, str, str) rejected = pyqtSignal(str) def __init__(self, parent=None): """ Constructor @param parent referenec to the parent object (QObject) """ super(Connection, self).__init__(parent) self.__greetingMessage = self.tr("undefined") self.__username = self.tr("unknown") self.__serverPort = 0 self.__state = Connection.WaitingForGreeting self.__currentDataType = Connection.Undefined self.__numBytesForCurrentDataType = -1 self.__transferTimerId = 0 self.__isGreetingMessageSent = False self.__pingTimer = QTimer(self) self.__pingTimer.setInterval(PingInterval) self.__pongTime = QTime() self.__buffer = QByteArray() self.__client = None self.readyRead.connect(self.__processReadyRead) self.disconnected.connect(self.__disconnected) self.__pingTimer.timeout.connect(self.__sendPing) self.connected.connect(self.__sendGreetingMessage) def name(self): """ Public method to get the connection name. @return connection name (string) """ return self.__username def serverPort(self): """ Public method to get the server port. @return server port (integer) """ return self.__serverPort def setClient(self, client): """ Public method to set the reference to the cooperation client. @param client reference to the cooperation client (CooperationClient) """ self.__client = client def setGreetingMessage(self, message, serverPort): """ Public method to set the greeting message. @param message greeting message (string) @param serverPort port number to include in the message (integer) """ self.__greetingMessage = "{0}:{1}".format(message, serverPort) def sendMessage(self, message): """ Public method to send a message. @param message message to be sent (string) @return flag indicating a successful send (boolean) """ if message == "": return False msg = QByteArray(message.encode("utf-8")) data = QByteArray("{0}{1}{2}{1}".format( Connection.ProtocolMessage, SeparatorToken, msg.size()) .encode("utf-8")) + msg return self.write(data) == data.size() def timerEvent(self, evt): """ Protected method to handle timer events. @param evt reference to the timer event (QTimerEvent) """ if evt.timerId() == self.__transferTimerId: self.abort() self.killTimer(self.__transferTimerId) self.__transferTimerId = 0 def __processReadyRead(self): """ Private slot to handle the readyRead signal. """ if self.__state == Connection.WaitingForGreeting: if not self.__readProtocolHeader(): return if self.__currentDataType != Connection.Greeting: self.abort() return self.__state = Connection.ReadingGreeting if self.__state == Connection.ReadingGreeting: if not self.__hasEnoughData(): return self.__buffer = QByteArray( self.read(self.__numBytesForCurrentDataType)) if self.__buffer.size() != self.__numBytesForCurrentDataType: self.abort() return try: user, serverPort = \ str(self.__buffer, encoding="utf-8").split(":") except ValueError: self.abort() return self.__serverPort = int(serverPort) hostInfo = QHostInfo.fromName(self.peerAddress().toString()) self.__username = "******".format( user, hostInfo.hostName(), self.peerPort() ) self.__currentDataType = Connection.Undefined self.__numBytesForCurrentDataType = 0 self.__buffer.clear() if not self.isValid(): self.abort() return bannedName = "{0}@{1}".format( user, hostInfo.hostName(), ) Preferences.syncPreferences() if bannedName in Preferences.getCooperation("BannedUsers"): self.rejected.emit(self.tr( "* Connection attempted by banned user '{0}'.") .format(bannedName)) self.abort() return if self.__serverPort != self.peerPort() and \ not Preferences.getCooperation("AutoAcceptConnections"): # don't ask for reverse connections or # if we shall accept automatically res = E5MessageBox.yesNo( None, self.tr("New Connection"), self.tr("""<p>Accept connection from """ """<strong>{0}@{1}</strong>?</p>""").format( user, hostInfo.hostName()), yesDefault=True) if not res: self.abort() return if self.__client is not None: chatWidget = self.__client.chatWidget() if chatWidget is not None and not chatWidget.isVisible(): e5App().getObject( "UserInterface").activateCooperationViewer() if not self.__isGreetingMessageSent: self.__sendGreetingMessage() self.__pingTimer.start() self.__pongTime.start() self.__state = Connection.ReadyForUse self.readyForUse.emit() while self.bytesAvailable(): if self.__currentDataType == Connection.Undefined: if not self.__readProtocolHeader(): return if not self.__hasEnoughData(): return self.__processData() def __sendPing(self): """ Private slot to send a ping message. """ if self.__pongTime.elapsed() > PongTimeout: self.abort() return self.write("{0}{1}1{1}p".format( Connection.ProtocolPing, SeparatorToken)) def __sendGreetingMessage(self): """ Private slot to send a greeting message. """ greeting = QByteArray(self.__greetingMessage.encode("utf-8")) data = QByteArray("{0}{1}{2}{1}".format( Connection.ProtocolGreeting, SeparatorToken, greeting.size()) .encode("utf-8")) + greeting if self.write(data) == data.size(): self.__isGreetingMessageSent = True def __readDataIntoBuffer(self, maxSize=MaxBufferSize): """ Private method to read some data into the buffer. @param maxSize maximum size of data to read (integer) @return size of data read (integer) """ if maxSize > MaxBufferSize: return 0 numBytesBeforeRead = self.__buffer.size() if numBytesBeforeRead == MaxBufferSize: self.abort() return 0 while self.bytesAvailable() and self.__buffer.size() < maxSize: self.__buffer.append(self.read(1)) if self.__buffer.endsWith(SeparatorToken): break return self.__buffer.size() - numBytesBeforeRead def __dataLengthForCurrentDataType(self): """ Private method to get the data length for the current data type. @return data length (integer) """ if self.bytesAvailable() <= 0 or \ self.__readDataIntoBuffer() <= 0 or \ not self.__buffer.endsWith(SeparatorToken): return 0 self.__buffer.chop(len(SeparatorToken)) number = self.__buffer.toInt()[0] self.__buffer.clear() return number def __readProtocolHeader(self): """ Private method to read the protocol header. @return flag indicating a successful read (boolean) """ if self.__transferTimerId: self.killTimer(self.__transferTimerId) self.__transferTimerId = 0 if self.__readDataIntoBuffer() <= 0: self.__transferTimerId = self.startTimer(TransferTimeout) return False self.__buffer.chop(len(SeparatorToken)) if self.__buffer == Connection.ProtocolPing: self.__currentDataType = Connection.Ping elif self.__buffer == Connection.ProtocolPong: self.__currentDataType = Connection.Pong elif self.__buffer == Connection.ProtocolMessage: self.__currentDataType = Connection.PlainText elif self.__buffer == Connection.ProtocolGreeting: self.__currentDataType = Connection.Greeting elif self.__buffer == Connection.ProtocolGetParticipants: self.__currentDataType = Connection.GetParticipants elif self.__buffer == Connection.ProtocolParticipants: self.__currentDataType = Connection.Participants elif self.__buffer == Connection.ProtocolEditor: self.__currentDataType = Connection.Editor else: self.__currentDataType = Connection.Undefined self.abort() return False self.__buffer.clear() self.__numBytesForCurrentDataType = \ self.__dataLengthForCurrentDataType() return True def __hasEnoughData(self): """ Private method to check, if enough data is available. @return flag indicating availability of enough data (boolean) """ if self.__transferTimerId: self.killTimer(self.__transferTimerId) self.__transferTimerId = 0 if self.__numBytesForCurrentDataType <= 0: self.__numBytesForCurrentDataType = \ self.__dataLengthForCurrentDataType() if self.bytesAvailable() < self.__numBytesForCurrentDataType or \ self.__numBytesForCurrentDataType <= 0: self.__transferTimerId = self.startTimer(TransferTimeout) return False return True def __processData(self): """ Private method to process the received data. """ self.__buffer = QByteArray( self.read(self.__numBytesForCurrentDataType)) if self.__buffer.size() != self.__numBytesForCurrentDataType: self.abort() return if self.__currentDataType == Connection.PlainText: self.newMessage.emit( self.__username, str(self.__buffer, encoding="utf-8")) elif self.__currentDataType == Connection.Ping: self.write("{0}{1}1{1}p".format( Connection.ProtocolPong, SeparatorToken)) elif self.__currentDataType == Connection.Pong: self.__pongTime.restart() elif self.__currentDataType == Connection.GetParticipants: self.getParticipants.emit() elif self.__currentDataType == Connection.Participants: msg = str(self.__buffer, encoding="utf-8") if msg == "<empty>": participantsList = [] else: participantsList = msg.split(SeparatorToken) self.participants.emit(participantsList[:]) elif self.__currentDataType == Connection.Editor: hash, fn, msg = \ str(self.__buffer, encoding="utf-8").split(SeparatorToken) self.editorCommand.emit(hash, fn, msg) self.__currentDataType = Connection.Undefined self.__numBytesForCurrentDataType = 0 self.__buffer.clear() def sendGetParticipants(self): """ Public method to request a list of participants. """ self.write( "{0}{1}1{1}l".format( Connection.ProtocolGetParticipants, SeparatorToken) ) def sendParticipants(self, participants): """ Public method to send the list of participants. @param participants list of participants (list of strings of "host:port") """ if participants: message = SeparatorToken.join(participants) else: message = "<empty>" msg = QByteArray(message.encode("utf-8")) data = QByteArray("{0}{1}{2}{1}".format( Connection.ProtocolParticipants, SeparatorToken, msg.size()) .encode("utf-8")) + msg self.write(data) def sendEditorCommand(self, projectHash, filename, message): """ Public method to send an editor command. @param projectHash hash of the project (string) @param filename project relative universal file name of the sending editor (string) @param message editor command to be sent (string) """ msg = QByteArray("{0}{1}{2}{1}{3}".format( projectHash, SeparatorToken, filename, message).encode("utf-8")) data = QByteArray("{0}{1}{2}{1}".format( Connection.ProtocolEditor, SeparatorToken, msg.size()) .encode("utf-8")) + msg self.write(data) def __disconnected(self): """ Private slot to handle the connection being dropped. """ self.__pingTimer.stop() if self.__state == Connection.WaitingForGreeting: self.rejected.emit(self.tr( "* Connection to {0}:{1} refused.").format( self.peerName(), self.peerPort()))