def start(self, path): """ Public slot to populate the data. @param path directory name to show change lists for (string) """ self.changeListsDict = {} self.cancelled = False self.filesLabel.setText(self.tr("Files (relative to {0}):").format(path)) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() locker = QMutexLocker(self.vcs.vcsExecutionMutex) try: entries = self.client.get_changelist(path, depth=pysvn.depth.infinity) for entry in entries: file = entry[0] changelist = entry[1] if sys.version_info[0] == 2: file = file.decode("utf-8") changelist = changelist.decode("utf-8") if changelist not in self.changeListsDict: self.changeListsDict[changelist] = [] filename = file.replace(path + os.sep, "") if filename not in self.changeListsDict[changelist]: self.changeListsDict[changelist].append(filename) except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0]) self.__finish()
def start(self, fn): """ Public slot to start the svn blame command. @param fn filename to show the blame for (string) """ self.blameList.clear() self.errorGroup.hide() self.activateWindow() dname, fname = self.vcs.splitPath(fn) locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: annotations = self.client.annotate(fname) locker.unlock() for annotation in annotations: author = annotation["author"] line = annotation["line"] if sys.version_info[0] == 2: author = author.decode('utf-8') line = line.decode('utf-8') self.__generateItem( annotation["revision"].number, author, annotation["number"] + 1, line) except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0] + '\n') self.__finish() os.chdir(cwd)
def start(self, fn, recursive=False): """ Public slot to start the svn status command. @param fn filename(s) (string or list of strings) @param recursive flag indicating a recursive list is requested """ self.errorGroup.hide() self.propsList.clear() self.__args = fn self.__recursive = recursive self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self.refreshButton.setEnabled(False) QApplication.processEvents() self.propsFound = False if isinstance(fn, list): dname, fnames = self.vcs.splitPathList(fn) else: dname, fname = self.vcs.splitPath(fn) fnames = [fname] locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: for name in fnames: proplist = self.client.proplist(name, recurse=recursive) counter = 0 for path, prop in proplist: if sys.version_info[0] == 2: path = path.decode('utf-8') for propName, propVal in list(prop.items()): if sys.version_info[0] == 2: propName = propName.decode('utf-8') propVal = propVal.decode('utf-8') self.__generateItem(path, propName, propVal) self.propsFound = True counter += 1 if counter == 30: # check for cancel every 30 items counter = 0 if self._clientCancelCallback(): break if self._clientCancelCallback(): break except pysvn.ClientError as e: self.__showError(e.args[0]) locker.unlock() self.__finish() os.chdir(cwd)
def stopRecording(self): with QMutexLocker(self.Mutex): command = struct.pack('>BB', 0x12, 0) self.Connection.write(command) if self.binfile is not None: self.binfile.close() self.binfile = None
def setLogsText(self, textJACK, textA2J, textLASH, textLADISH): QMutexLocker(self.fTextLock) self.fTextJACK = textJACK self.fTextA2J = textA2J self.fTextLASH = textLASH self.fTextLADISH = textLADISH
def updateImage(self): locker = QMutexLocker(self.mutex) if not self.isRunning(): self.start(QThread.LowPriority) else: self.restart = True self.condition.wakeOne()
def receiveSignalHandle(self, state): if state == self.Register_FINISHSINGAL: if len(self.registerlist) > 0: with QMutexLocker(self._Mlock): self.face_thread.database.insertRow( self.registerlist, self.ACCOUNT_INFO) # 删除默认密码 self.face_thread.database.loadDataBase(self.ACCOUNT_INFO) if len(self.face_thread.database.keyid) == 0: self.face_thread.database.insertRow( ['123', '1234', '-1'], self.ACCOUNT_INFO) elif (len(self.face_thread.database.keyid) > 1 and '123' in self.face_thread.database.account_num): self.face_thread.database.deleteRow( '123', self.ACCOUNT_INFO) self.face_thread.database.loadDataBase(self.ACCOUNT_INFO) self.faceCapSignal.emit(False) self.Register_Button.setEnabled(True) self.videoLabel.setPixmap(QPixmap.fromImage(self.videoPicture)) if state == self.Register_FAILED: QMessageBox.critical(self, '注册失败', '人脸已经存在或没有识别到人脸,请靠近摄像头') self.faceCapSignal.emit(False) self.Register_Button.setEnabled(True) self.videoLabel.setPixmap(QPixmap.fromImage(self.videoPicture)) pass
def getView(self, dis): # 管理员数据字典 with QMutexLocker(self._Mlock): self.accoutDatabase = { self.face_thread.database.account_num[i]: self.face_thread.database.password[i] for i in range(len(self.face_thread.database.account_num)) } account, ok = QInputDialog.getText(self, 'Account Input', 'Please enter the account number:') secret, bingo = QInputDialog.getText( self, 'secret Input', 'Please enter the secret number:') if ok and bingo: if account in self.accoutDatabase.keys(): if secret == self.accoutDatabase.get(account): if dis: if self.pushButton_2.isEnabled( ) and self.Register_Button.isEnabled(): self.logicalDisplaySignal.emit( self.signal_OpenEvent) else: pass return True else: return "账号或者密码不正确" else: return "账号或者密码不正确" pass else: return False
def slot_updateLogs(self): QMutexLocker(self.fTextLock) if self.fFirstRun: self.ui.pte_jack.clear() self.ui.pte_a2j.clear() self.ui.pte_lash.clear() self.ui.pte_ladish.clear() if self.LOG_FILE_JACK and self.fTextJACK: self.ui.pte_jack.appendPlainText(self.fTextJACK) if self.LOG_FILE_A2J and self.fTextA2J: self.ui.pte_a2j.appendPlainText(self.fTextA2J) if self.LOG_FILE_LASH and self.fTextLASH: self.ui.pte_lash.appendPlainText(self.fTextLASH) if self.LOG_FILE_LADISH and self.fTextLADISH: self.ui.pte_ladish.appendPlainText(self.fTextLADISH) if self.fFirstRun: self.ui.pte_jack.horizontalScrollBar().setValue(0) self.ui.pte_jack.verticalScrollBar().setValue(self.ui.pte_jack.verticalScrollBar().maximum()) self.ui.pte_a2j.horizontalScrollBar().setValue(0) self.ui.pte_a2j.verticalScrollBar().setValue(self.ui.pte_a2j.verticalScrollBar().maximum()) self.ui.pte_lash.horizontalScrollBar().setValue(0) self.ui.pte_lash.verticalScrollBar().setValue(self.ui.pte_lash.verticalScrollBar().maximum()) self.ui.pte_ladish.horizontalScrollBar().setValue(0) self.ui.pte_ladish.verticalScrollBar().setValue(self.ui.pte_ladish.verticalScrollBar().maximum()) self.fFirstRun = False
def is_stopped(self): """ 线程状态是否是停止 :return: """ with QMutexLocker(self.mutex): return self.stopped
def readData(self): """SLOT: readData Reads data from the serial port when it's available Expects: none Connects to: QSerialPort.readyRead Emits: newDataAvailable """ with QMutexLocker(self.lock): bytesIn = self.serialPort.readAll() for b in bytesIn: if b == b'\n': # This translates to the \n character which means the message is complete msg = self.buffer.decode().strip() self.displayRXMessage.emit(msg) if msg == "ready": self.ready.emit() else: self.newDataAvailable.emit(float(msg)) self.printStatus.emit("Serial read complete") self.buffer = bytearray() # Clear buffer elif b != b'\r': # Ignore '\r' character too self.buffer = self.buffer + b
def add(self, deviceUrl, imageBuffer, sync=False): # Device stream is to be synchronized if sync: with QMutexLocker(self.mutex): self.syncSet.add(deviceUrl) # Add image buffer to map self.imageBufferDict[deviceUrl] = imageBuffer
def on_ignore_clicked(self, file_name): """ Stop watching a single file until next save """ #print(f'on_ignore_clicked {file_name} in', QThread.currentThread().objectName()) with QMutexLocker(self._mutex): self.blacklist.add(file_name)
def startNewRecording(self, countchannel, triggerchannel, binwidth, roistart, roistop, filename=None): logger = logging.getLogger(__name__) with QMutexLocker(self.Mutex): command = struct.pack('>BB', 0x12, 0) self.Connection.write(command) self.channel = countchannel self.triggerchannel = triggerchannel self.binwidth = binwidth self.roistart = roistart self.roistop = roistop self.numberOfBins = (roistop - roistart) / binwidth + 1 self.histogram = numpy.zeros(self.numberOfBins) logger.info("command {0:x}".format(0xff & (1 << self.channel | 1 << self.triggerchannel))) self.clearStatus() command = struct.pack( '>BB', 0x12, 0xff & (1 << self.channel | 1 << self.triggerchannel)) self.Connection.write(command) if self.filename != filename: if self.binfile is not None: self.binfile.close() if filename is not None: self.binfile = open(filename, 'wb') else: self.binfile = None self.filename = filename
def run(self): self._abort = False while True: with QMutexLocker(self._mutex): if self._abort: break frame = self.frame self.frame = None pixel_format = frame.pixelFormat() image_format = QVideoFrame.imageFormatFromPixelFormat(pixel_format) if image_format == QImage.Format_Invalid: qDebug("WARNING: Could not convert video frame to image!") return if not frame.map(QAbstractVideoBuffer.ReadOnly): qDebug("WARNING: Could not map video frame!") return width = frame.width() height = frame.height() bytes_per_line = frame.bytesPerLine() image = QImage(frame.bits(), width, height, bytes_per_line, image_format) image = image.convertToFormat(QImage.Format_RGB32) frame.unmap() # fix upside-down data for windows if platform.system() == "Windows": image = image.mirrored(vertical=True) # now convert QImage to ndarray pointer = image.constBits() pointer.setsize(image.byteCount()) array = np.array(pointer).reshape(image.height(), image.width(), 4) # get rid of the transparency channel and organize the colors as rgb # NB: it would be safer to figure out the image format first, and where the transparency channel is # stored... array = array[:, :, 0:3:][:, :, ::-1] self.ndarray_available.emit(array) # see if new data is available, go to sleep if not with QMutexLocker(self._mutex): if self.frame is None: self._condition.wait(self._mutex)
def updateImageProcessingFlags(self, imgProcFlags): with QMutexLocker(self.processingMutex): self.imgProcFlags.grayscaleOn = imgProcFlags.grayscaleOn self.imgProcFlags.smoothOn = imgProcFlags.smoothOn self.imgProcFlags.dilateOn = imgProcFlags.dilateOn self.imgProcFlags.erodeOn = imgProcFlags.erodeOn self.imgProcFlags.flipOn = imgProcFlags.flipOn self.imgProcFlags.cannyOn = imgProcFlags.cannyOn
def start(self, fn, recursive=False): """ Public slot to start the svn status command. @param fn filename(s) (string or list of strings) @param recursive flag indicating a recursive list is requested """ self.errorGroup.hide() QApplication.processEvents() self.propsFound = False if isinstance(fn, list): dname, fnames = self.vcs.splitPathList(fn) else: dname, fname = self.vcs.splitPath(fn) fnames = [fname] locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: for name in fnames: proplist = self.client.proplist(name, recurse=recursive) counter = 0 for path, prop in proplist: if sys.version_info[0] == 2: path = path.decode('utf-8') for propName, propVal in list(prop.items()): if sys.version_info[0] == 2: propName = propName.decode('utf-8') propVal = propVal.decode('utf-8') self.__generateItem(path, propName, propVal) self.propsFound = True counter += 1 if counter == 30: # check for cancel every 30 items counter = 0 if self._clientCancelCallback(): break if self._clientCancelCallback(): break except pysvn.ClientError as e: self.__showError(e.args[0]) locker.unlock() self.__finish() os.chdir(cwd)
def process_frame(self, frame: QVideoFrame): with QMutexLocker(self._mutex): self.frame = frame if not self.isRunning(): self.start() else: self._condition.wakeOne()
def stop(self): """ 线程停止 :return: """ # 互斥锁 with QMutexLocker(self.mutex): self.stopped = True
def run(self): with QMutexLocker(self.mutex): self.stopped = False while True: if self.stopped: return self.timeSignal.signal.emit("1") time.sleep(1 / self.frequent)
def requestNewFortune(self, hostname, port): locker = QMutexLocker(self.mutex) self.hostName = hostname self.port = port if not self.isRunning(): self.start() else: self.cond.wakeOne()
def bind_thread(self, thread): with QMutexLocker(self.mutex): self.sync_devices.add(thread.device_id) shape = project_shapes[thread.camera_model.camera_name] self.current_frames[thread.device_id] = np.zeros( shape[::-1] + (3, ), np.uint8) thread.proc_buffer_manager = self
def bytesAvailable(self): """ Public method to get the number of available bytes. @return number of available bytes @rtype int """ lock = QMutexLocker(self.__mutex) # __IGNORE_WARNING__ return self.__buffer.bytesAvailable()
def consume(self): # when this goes out of scope the lock is opened locker = QMutexLocker(QdImageLoader._mutex) if self._index == len(self._paths): return None path = self._paths[self._index] self._index += 1 return path
def readData(self, maxlen): """ Public method to retrieve data from the reply object. @param maxlen maximum number of bytes to read (integer) @return string containing the data (bytes) """ lock = QMutexLocker(self.__mutex) # __IGNORE_WARNING__ return self.__buffer.read(maxlen)
def onFinishRegister(self): if self.flag_registed == True: dir = self.PATH_FACE + self.name for file in os.listdir(dir): os.remove(dir + "/" + file) print("已删除已录入人脸的图片", dir + "/" + file) os.rmdir(self.PATH_FACE + self.name) print("已删除已录入人脸的姓名文件夹", dir) self.initData() return if self.pic_num > 0: pics = os.listdir(self.PATH_FACE + self.name) feature_list = [] feature_average = [] for i in range(len(pics)): pic_path = self.PATH_FACE + self.name + "/" + pics[i] print("正在读的人脸图像:", pic_path) img = iio.imread(pic_path) img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) dets = self.detector(img_gray, 1) if len(dets) != 0: shape = self.predictor(img_gray, dets[0]) face_descriptor = self.facerec.compute_face_descriptor( img_gray, shape) feature_list.append(face_descriptor) else: face_dssaescriptor = 0 print("未在照片中识别到人脸") if len(feature_list) > 0: for j in range(128): # 防止越界 feature_average.append(0) for i in range(len(feature_list)): feature_average[j] += feature_list[i][j] feature_average[j] = ( feature_average[j]) / len(feature_list) # 数据库写入 with QMutexLocker(self._mutex): self.database.insertRow( [self.id, self.name, feature_average], self.WORKER_INFO) print("写入数据库成功") # 删除处理图片的缓存 if True: dir = self.PATH_FACE + self.name for file in os.listdir(dir): os.remove(dir + "/" + file) print("已删除已录入人脸的图片", dir + "/" + file) os.rmdir(self.PATH_FACE + self.name) print("已删除已录入人脸的姓名文件夹", dir) self.initData() return pass else: os.rmdir(self.PATH_FACE + self.name) print("已删除空文件夹", self.PATH_FACE + self.name) self.initData()
def input(self): message = self.lineEdit.text() self.lineEdit.clear() self.plainTextEdit.verticalScrollBar().setValue( self.plainTextEdit.verticalScrollBar().maximum()) self.plainTextEdit.insertPlainText("<You> " + message + '\n') with QMutexLocker(io_lock): server.send(message.encode())
def __init__(self, myqueue=None, protocol_factory=None, file=None, parent=None): super(Application, self).__init__(parent=parent) # 界面初始化 self.setupUi(self) self.file = file # 界面显示的好看图片 self.videoPicture = QImage("data/2/Beatiful/2-2.png") self.loadingPicture = QImage("data/2/Loading/loading_2.png") # 加载数据锁 self._Mlock = QMutex() # 人脸识别线程 self.face_thread = FaceLearning(self.file) # 管理员数据字典 with QMutexLocker(self._Mlock): self.accoutDatabase = { self.face_thread.database.account_num[i]: self.face_thread.database.password[i] for i in range(len(self.face_thread.database.account_num)) } # 日志显示线程 self.logic = LogicalTable(self.tableView, self.logicShow, self.face_thread.database) self.logicalTableInit() # 摄像头显示线程 self.capLabel = LabelThread(self.face_thread.cap) # 用户删除槽连接 self.accountBoxInit() self.ser = None self.myqueue = myqueue self.protocol_factory = protocol_factory # 串口接收线程 self.read_threads = None # 串口接收数 self.receive_Num = 0 # 串口丢包数 self.receive_Lost = 0 # 实例化一个定时器 self.timer = QTimer(self) self.lcdDisplay(10.10, 10.10) self.serialinit() # 人脸识别线程开启 self.signalFaceConnect() try: # 摄像头显示线程开启 self.capLabel.start() except: print(print_exc()) self.face_thread.start() # 日志显示线程开启 self.logic.start() # 加载好看的图片 self.videoLabel.setPixmap(QPixmap.fromImage(self.videoPicture)) self.logicShow.setPixmap(QPixmap.fromImage(self.loadingPicture))
def on_file_saved(self, file_name): """ Remove file from blacklist, update mtime """ #print(f'on_file_saved {file_name} in', QThread.currentThread().objectName()) with QMutexLocker(self._mutex): self.blacklist = set([f for f in self.blacklist if f != file_name]) self.on_file_open(file_name)
def removeByDeviceUrl(self, deviceUrl): # Remove buffer for device from imageBufferDict self.imageBufferDict.pop(deviceUrl) # Also remove from syncSet (if present) with QMutexLocker(self.mutex): if self.syncSet.__contains__(deviceUrl): self.syncSet.remove(deviceUrl) self.wc.wakeAll()
def execute(self, function, *args, **kwargs): locker = QMutexLocker(self.mutex) self.function = function self.args = args self.kwargs = kwargs self.done = False self.start()
def logicDisplay(self): self.label.close() self.displaywidget.show() self.model.clear() self.row = None self.cloumn = None mylist = ["ID", "访问名称", "访问日期", "访问时间"] with QMutexLocker(self._lock): self.displaydatabase.loadDataBase(2) self.textitemlist = [ self.displaydatabase.logcat_id, self.displaydatabase.logcat_name, self.displaydatabase.logcat_datetime, self.displaydatabase.logcat_late ] self.row = len(self.displaydatabase.logcat_id) self.cloumn = self.MAXCLOSIZE self.model.setRowCount(self.MAXROWSIZE) self.model.setColumnCount(self.cloumn) # 显示标题 self.item_list = [ QStandardItem('{}'.format(datatext)) for datatext in mylist ] # 往每个项目插入对应数据 for clo in range(self.MAXCLOSIZE): self.model.setItem(0, clo, self.item_list[clo]) if self.row <= self.MAXROWSIZE: y = list(range(self.row)) y.reverse() rowx = 0 for row in y: self.item_list = [ QStandardItem('{}'.format(datatext[row])) for datatext in self.textitemlist ] # 往每个项目插入对应数据 for clo in range(self.MAXCLOSIZE): self.model.setItem(rowx + 1, clo, self.item_list[clo]) rowx += 1 else: y = list(range((self.row - self.MAXROWSIZE), self.row)) y.reverse() rowx = 0 for row in y: self.item_list = [ QStandardItem('{}'.format(datatext[row])) for datatext in self.textitemlist ] # 往每个项目插入对应数据 for clo in range(self.MAXCLOSIZE): self.model.setItem(rowx + 1, clo, self.item_list[clo]) rowx += 1 pass self.displaywidget.setEditTriggers( QAbstractItemView.NoEditTriggers) # 无法编辑 self.displaywidget.horizontalHeader().setStretchLastSection( True) # 自动调整补充窗口 pass
def run(self): '''重写QThread类的run函数,若线程启动,则会被执行''' with QMutexLocker(self.mutex): self.stopped = False while True: if self.stopped: return self.time_signal.signal.emit("1") time.sleep(1 / self.frequent)
def start(self, projectPath, fn): """ Public slot to start the svn info command. @param projectPath path name of the project (string) @param fn file or directory name relative to the project (string) """ locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(projectPath) try: entries = self.client.info2(fn, recurse=False) infoStr = "<table>" for path, info in entries: if sys.version_info[0] == 2: path = path.decode('utf-8') infoStr += self.tr( "<tr><td><b>Path (relative to project):</b></td>" "<td>{0}</td></tr>").format(path) if info['URL']: infoStr += self.tr( "<tr><td><b>Url:</b></td><td>{0}</td></tr>")\ .format(info['URL']) if info['rev']: infoStr += self.tr( "<tr><td><b>Revision:</b></td><td>{0}</td></tr>")\ .format(info['rev'].number) if info['repos_root_URL']: infoStr += self.tr( "<tr><td><b>Repository root URL:</b></td>" "<td>{0}</td></tr>").format(info['repos_root_URL']) if info['repos_UUID']: infoStr += self.tr( "<tr><td><b>Repository UUID:</b></td>" "<td>{0}</td></tr>").format(info['repos_UUID']) if info['last_changed_author']: infoStr += self.tr( "<tr><td><b>Last changed author:</b></td>" "<td>{0}</td></tr>")\ .format(info['last_changed_author']) if info['last_changed_date']: infoStr += self.tr( "<tr><td><b>Last Changed Date:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(info['last_changed_date'])) if info['last_changed_rev'] and \ info['last_changed_rev'].kind == \ pysvn.opt_revision_kind.number: infoStr += self.tr( "<tr><td><b>Last changed revision:</b></td>" "<td>{0}</td></tr>")\ .format(info['last_changed_rev'].number) if info['kind']: if info['kind'] == pysvn.node_kind.file: nodeKind = self.tr("file") elif info['kind'] == pysvn.node_kind.dir: nodeKind = self.tr("directory") elif info['kind'] == pysvn.node_kind.none: nodeKind = self.tr("none") else: nodeKind = self.tr("unknown") infoStr += self.tr( "<tr><td><b>Node kind:</b></td><td>{0}</td></tr>")\ .format(nodeKind) if info['lock']: lockInfo = info['lock'] infoStr += self.tr( "<tr><td><b>Lock Owner:</b></td><td>{0}</td></tr>")\ .format(lockInfo['owner']) infoStr += self.tr( "<tr><td><b>Lock Creation Date:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(lockInfo['creation_date'])) if lockInfo['expiration_date'] is not None: infoStr += self.tr( "<tr><td><b>Lock Expiration Date:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(lockInfo['expiration_date'])) infoStr += self.tr( "<tr><td><b>Lock Token:</b></td><td>{0}</td></tr>")\ .format(lockInfo['token']) infoStr += self.tr( "<tr><td><b>Lock Comment:</b></td><td>{0}</td></tr>")\ .format(lockInfo['comment']) if info['wc_info']: wcInfo = info['wc_info'] if wcInfo['schedule']: if wcInfo['schedule'] == pysvn.wc_schedule.normal: schedule = self.tr("normal") elif wcInfo['schedule'] == pysvn.wc_schedule.add: schedule = self.tr("add") elif wcInfo['schedule'] == pysvn.wc_schedule.delete: schedule = self.tr("delete") elif wcInfo['schedule'] == pysvn.wc_schedule.replace: schedule = self.tr("replace") infoStr += self.tr( "<tr><td><b>Schedule:</b></td><td>{0}</td></tr>")\ .format(schedule) if wcInfo['copyfrom_url']: infoStr += self.tr( "<tr><td><b>Copied From URL:</b></td>" "<td>{0}</td></tr>")\ .format(wcInfo['copyfrom_url']) infoStr += self.tr( "<tr><td><b>Copied From Rev:</b></td>" "<td>{0}</td></tr>")\ .format(wcInfo['copyfrom_rev'].number) if wcInfo['text_time']: infoStr += self.tr( "<tr><td><b>Text Last Updated:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(wcInfo['text_time'])) if wcInfo['prop_time']: infoStr += self.tr( "<tr><td><b>Properties Last Updated:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(wcInfo['prop_time'])) if wcInfo['checksum']: infoStr += self.tr( "<tr><td><b>Checksum:</b></td><td>{0}</td></tr>")\ .format(wcInfo['checksum']) infoStr += "</table>" self.infoBrowser.setHtml(infoStr) except pysvn.ClientError as e: self.__showError(e.args[0]) locker.unlock() os.chdir(cwd)
def start(self, fn): """ Public slot to start the svn status command. @param fn filename(s)/directoryname(s) to show the status of (string or list of strings) """ self.errorGroup.hide() for act in self.menuactions: act.setEnabled(False) self.addButton.setEnabled(False) self.commitButton.setEnabled(False) self.diffButton.setEnabled(False) self.sbsDiffButton.setEnabled(False) self.revertButton.setEnabled(False) self.restoreButton.setEnabled(False) self.statusFilterCombo.clear() self.__statusFilters = [] QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.args = fn self.setWindowTitle(self.tr('Subversion Status')) self.activateWindow() self.raise_() if isinstance(fn, list): self.dname, fnames = self.vcs.splitPathList(fn) else: self.dname, fname = self.vcs.splitPath(fn) fnames = [fname] opts = self.vcs.options['global'] + self.vcs.options['status'] verbose = "--verbose" in opts recurse = "--non-recursive" not in opts update = "--show-updates" in opts hideChangelistColumn = True hidePropertyStatusColumn = True hideLockColumns = True hideUpToDateColumn = True hideHistoryColumn = True hideSwitchedColumn = True locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(self.dname) try: for name in fnames: # step 1: determine changelists and their files changelistsDict = {} if hasattr(self.client, 'get_changelist'): if recurse: depth = pysvn.depth.infinity else: depth = pysvn.depth.immediate changelists = self.client.get_changelist(name, depth=depth) for fpath, changelist in changelists: if sys.version_info[0] == 2: fpath = fpath.decode('utf-8') changelist = changelist.decode('utf-8') fpath = Utilities.normcasepath(fpath) changelistsDict[fpath] = changelist hideChangelistColumn = hideChangelistColumn and \ len(changelistsDict) == 0 # step 2: determine status of files allFiles = self.client.status(name, recurse=recurse, get_all=verbose, ignore=True, update=update) counter = 0 for file in allFiles: uptodate = True if file.repos_text_status != pysvn.wc_status_kind.none: uptodate = uptodate and \ file.repos_text_status != \ pysvn.wc_status_kind.modified if file.repos_prop_status != pysvn.wc_status_kind.none: uptodate = uptodate and \ file.repos_prop_status != \ pysvn.wc_status_kind.modified lockState = " " if file.entry is not None and \ hasattr(file.entry, 'lock_token') and \ file.entry.lock_token is not None: lockState = "L" if hasattr(file, 'repos_lock') and update: if lockState == "L" and file.repos_lock is None: lockState = "B" elif lockState == " " and file.repos_lock is not None: lockState = "O" elif lockState == "L" and \ file.repos_lock is not None and \ file.entry.lock_token != \ file.repos_lock["token"]: lockState = "S" fpath = Utilities.normcasepath( os.path.join(self.dname, file.path)) if fpath in changelistsDict: changelist = changelistsDict[fpath] else: changelist = "" hidePropertyStatusColumn = hidePropertyStatusColumn and \ file.prop_status in [ pysvn.wc_status_kind.none, pysvn.wc_status_kind.normal ] hideLockColumns = hideLockColumns and \ not file.is_locked and lockState == " " hideUpToDateColumn = hideUpToDateColumn and uptodate hideHistoryColumn = hideHistoryColumn and \ not file.is_copied hideSwitchedColumn = hideSwitchedColumn and \ not file.is_switched self.__generateItem( changelist, file.text_status, file.prop_status, file.is_locked, file.is_copied, file.is_switched, lockState, uptodate, file.entry and file.entry.revision.number or "", file.entry and file.entry.commit_revision.number or "", file.entry and file.entry.commit_author or "", file.path ) counter += 1 if counter == 30: # check for cancel every 30 items counter = 0 if self._clientCancelCallback(): break if self._clientCancelCallback(): break except pysvn.ClientError as e: self.__showError(e.args[0] + '\n') self.statusList.setColumnHidden(self.__propStatusColumn, hidePropertyStatusColumn) self.statusList.setColumnHidden(self.__lockedColumn, hideLockColumns) self.statusList.setColumnHidden(self.__lockinfoColumn, hideLockColumns) self.statusList.setColumnHidden(self.__upToDateColumn, hideUpToDateColumn) self.statusList.setColumnHidden(self.__historyColumn, hideHistoryColumn) self.statusList.setColumnHidden(self.__switchedColumn, hideSwitchedColumn) self.statusList.setColumnHidden(self.__changelistColumn, hideChangelistColumn) locker.unlock() self.__finish() os.chdir(cwd)
def __getLogEntries(self, startRev=None): """ Private method to retrieve log entries from the repository. @param startRev revision number to start from (integer, string) """ fetchLimit = 10 self._reset() QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() limit = self.limitSpinBox.value() if startRev is None: start = pysvn.Revision(pysvn.opt_revision_kind.head) else: try: start = pysvn.Revision(pysvn.opt_revision_kind.number, int(startRev)) except TypeError: start = pysvn.Revision(pysvn.opt_revision_kind.head) locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(self.dname) try: nextRev = 0 fetched = 0 logs = [] while fetched < limit: flimit = min(fetchLimit, limit - fetched) if fetched == 0: revstart = start else: revstart = pysvn.Revision( pysvn.opt_revision_kind.number, nextRev) allLogs = self.client.log( self.fname, revision_start=revstart, discover_changed_paths=True, limit=flimit + 1, strict_node_history=self.stopCheckBox.isChecked()) if len(allLogs) <= flimit or self._clientCancelCallback(): logs.extend(allLogs) break else: logs.extend(allLogs[:-1]) nextRev = allLogs[-1]["revision"].number fetched += fetchLimit locker.unlock() for log in logs: author = log["author"] message = log["message"] if sys.version_info[0] == 2: author = author.decode('utf-8') message = message.decode('utf-8') self.__generateLogItem( author, log["date"], message, log["revision"], log['changed_paths']) dt = dateFromTime_t(log["date"]) if not self.__maxDate.isValid() and \ not self.__minDate.isValid(): self.__maxDate = dt self.__minDate = dt else: if self.__maxDate < dt: self.__maxDate = dt if self.__minDate > dt: self.__minDate = dt if len(logs) < limit and not self.cancelled: self.nextButton.setEnabled(False) self.limitSpinBox.setEnabled(False) self.__filterLogsEnabled = False self.fromDate.setMinimumDate(self.__minDate) self.fromDate.setMaximumDate(self.__maxDate) self.fromDate.setDate(self.__minDate) self.toDate.setMinimumDate(self.__minDate) self.toDate.setMaximumDate(self.__maxDate) self.toDate.setDate(self.__maxDate) self.__filterLogsEnabled = True self.__resizeColumnsLog() self.__resortLog() self.__filterLogs() except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0]) os.chdir(cwd) self.__finish()
def start(self, path, tags=True): """ Public slot to start the svn status command. @param path name of directory to be listed (string) @param tags flag indicating a list of tags is requested (False = branches, True = tags) @return flag indicating success (boolean) """ self.errorGroup.hide() self.tagList.clear() if not tags: self.setWindowTitle(self.tr("Subversion Branches List")) self.activateWindow() QApplication.processEvents() dname, fname = self.vcs.splitPath(path) reposURL = self.vcs.svnGetReposName(dname) if reposURL is None: E5MessageBox.critical( self, self.tr("Subversion Error"), self.tr( """The URL of the project repository could not be""" """ retrieved from the working copy. The list operation""" """ will be aborted""")) self.close() return False if self.vcs.otherData["standardLayout"]: # determine the base path of the project in the repository rx_base = QRegExp('(.+)/(trunk|tags|branches).*') if not rx_base.exactMatch(reposURL): E5MessageBox.critical( self, self.tr("Subversion Error"), self.tr( """The URL of the project repository has an""" """ invalid format. The list operation will""" """ be aborted""")) return False reposRoot = rx_base.cap(1) if tags: path = "{0}/tags".format(reposRoot) else: path = "{0}/branches".format(reposRoot) else: reposPath, ok = QInputDialog.getText( self, self.tr("Subversion List"), self.tr("Enter the repository URL containing the" " tags or branches"), QLineEdit.Normal, self.vcs.svnNormalizeURL(reposURL)) if not ok: self.close() return False if not reposPath: E5MessageBox.critical( self, self.tr("Subversion List"), self.tr( """The repository URL is empty. Aborting...""")) self.close() return False path = reposPath locker = QMutexLocker(self.vcs.vcsExecutionMutex) self.tagsList = [] cwd = os.getcwd() os.chdir(dname) try: entries = self.client.list(path, recurse=False) # dirent, lock already unicode in Python 2 for dirent, lock in entries: if dirent["path"] != path: name = dirent["path"].replace(path + '/', "") self.__generateItem(dirent["created_rev"].number, dirent["last_author"], formatTime(dirent["time"]), name) if self.vcs.otherData["standardLayout"]: self.tagsList.append(name) else: self.tagsList.append(path + '/' + name) if self._clientCancelCallback(): break res = True except pysvn.ClientError as e: self.__showError(e.args[0]) res = False except AttributeError: self.__showError( self.tr("The installed version of PySvn should be" " 1.4.0 or better.")) res = False locker.unlock() self.__finish() os.chdir(cwd) return res
def start(self, fn, versions=None, urls=None, summary=False, pegRev=None): """ Public slot to start the svn diff command. @param fn filename to be diffed (string) @param versions list of versions to be diffed (list of up to 2 integer or None) @keyparam urls list of repository URLs (list of 2 strings) @keyparam summary flag indicating a summarizing diff (only valid for URL diffs) (boolean) @keyparam pegRev revision number the filename is valid (integer) """ self.buttonBox.button(QDialogButtonBox.Save).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self._reset() self.errorGroup.hide() QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.filename = fn self.contents.clear() self.paras = 0 self.filesCombo.clear() self.__oldFile = "" self.__oldFileLine = -1 self.__fileSeparators = [] if Utilities.hasEnvironmentEntry('TEMP'): tmpdir = Utilities.getEnvironmentEntry('TEMP') elif Utilities.hasEnvironmentEntry('TMPDIR'): tmpdir = Utilities.getEnvironmentEntry('TMPDIR') elif Utilities.hasEnvironmentEntry('TMP'): tmpdir = Utilities.getEnvironmentEntry('TMP') elif os.path.exists('/var/tmp'): tmpdir = '/var/tmp' elif os.path.exists('/usr/tmp'): tmpdir = '/usr/tmp' elif os.path.exists('/tmp'): tmpdir = '/tmp' else: E5MessageBox.critical( self, self.tr("Subversion Diff"), self.tr("""There is no temporary directory available.""")) return tmpdir = os.path.join(tmpdir, 'svn_tmp') if not os.path.exists(tmpdir): os.mkdir(tmpdir) opts = self.vcs.options['global'] + self.vcs.options['diff'] recurse = "--non-recursive" not in opts if versions is not None: self.raise_() self.activateWindow() rev1 = self.__getVersionArg(versions[0]) if len(versions) == 1: rev2 = self.__getVersionArg("WORKING") else: rev2 = self.__getVersionArg(versions[1]) else: rev1 = self.__getVersionArg("BASE") rev2 = self.__getVersionArg("WORKING") if urls is not None: rev1 = self.__getVersionArg("HEAD") rev2 = self.__getVersionArg("HEAD") if isinstance(fn, list): dname, fnames = self.vcs.splitPathList(fn) else: dname, fname = self.vcs.splitPath(fn) fnames = [fname] locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: dname = e5App().getObject('Project').getRelativePath(dname) if dname: dname += "/" for name in fnames: self.__showError( self.tr("Processing file '{0}'...\n").format(name)) if urls is not None: url1 = "{0}/{1}{2}".format(urls[0], dname, name) url2 = "{0}/{1}{2}".format(urls[1], dname, name) if summary: diff_summary = self.client.diff_summarize( url1, revision1=rev1, url_or_path2=url2, revision2=rev2, recurse=recurse) diff_list = [] for diff_sum in diff_summary: path = diff_sum['path'] if sys.version_info[0] == 2: path = path.decode('utf-8') diff_list.append("{0} {1}".format( self.__getDiffSummaryKind( diff_sum['summarize_kind']), path)) diffText = os.linesep.join(diff_list) else: diffText = self.client.diff( tmpdir, url1, revision1=rev1, url_or_path2=url2, revision2=rev2, recurse=recurse) if sys.version_info[0] == 2: diffText = diffText.decode('utf-8') else: if pegRev is not None: diffText = self.client.diff_peg( tmpdir, name, peg_revision=self.__getVersionArg(pegRev), revision_start=rev1, revision_end=rev2, recurse=recurse) else: diffText = self.client.diff( tmpdir, name, revision1=rev1, revision2=rev2, recurse=recurse) if sys.version_info[0] == 2: diffText = diffText.decode('utf-8') counter = 0 for line in diffText.splitlines(): if line.startswith("--- ") or \ line.startswith("+++ "): self.__processFileLine(line) self.__appendText("{0}{1}".format(line, os.linesep)) counter += 1 if counter == 30: # check for cancel every 30 lines counter = 0 if self._clientCancelCallback(): break if self._clientCancelCallback(): break except pysvn.ClientError as e: self.__showError(e.args[0]) locker.unlock() os.chdir(cwd) self.__finish() if self.paras == 0: self.contents.setCurrentCharFormat(self.cNormalFormat) self.contents.setPlainText( self.tr('There is no difference.')) self.buttonBox.button(QDialogButtonBox.Save).setEnabled(self.paras > 0)
def __listRepo(self, url, parent=None): """ Private method to perform the svn list command. @param url the repository URL to browser (string) @param parent reference to the item, the data should be appended to (QTreeWidget or QTreeWidgetItem) """ QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() if parent is None: parent = self.repoTree locker = QMutexLocker(self.vcs.vcsExecutionMutex) try: try: entries = self.client.list(url, recurse=False) firstTime = parent == self.repoTree # dirent elements are all unicode in Python 2 for dirent, lock in entries: if (firstTime and dirent["path"] != url) or \ (parent != self.repoTree and dirent["path"] == url): continue if firstTime: if dirent["repos_path"] != "/": repoUrl = dirent["path"].replace( dirent["repos_path"], "") else: repoUrl = dirent["path"] if repoUrl != url: self.__ignoreExpand = True itm = self.__generateItem( parent, "/", "", "", 0, "", pysvn.node_kind.dir, repoUrl) itm.setExpanded(True) parent = itm urlPart = repoUrl for element in \ dirent["repos_path"].split("/")[:-1]: if element: urlPart = "{0}/{1}".format(urlPart, element) itm = self.__generateItem( parent, element, "", "", 0, "", pysvn.node_kind.dir, urlPart) itm.setExpanded(True) parent = itm self.__ignoreExpand = False itm = self.__generateItem( parent, dirent["repos_path"], dirent["created_rev"], dirent["last_author"], dirent["size"], dirent["time"], dirent["kind"], dirent["path"]) self.__resort() self.__resizeColumns() except pysvn.ClientError as e: self.__showError(e.args[0]) except AttributeError: self.__showError( self.tr("The installed version of PySvn should be " "1.4.0 or better.")) finally: locker.unlock() QApplication.restoreOverrideCursor()
def start(self, fn, noEntries=0): """ Public slot to start the svn log command. @param fn filename to show the log for (string) @param noEntries number of entries to show (integer) """ self.errorGroup.hide() fetchLimit = 10 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.filename = fn dname, fname = self.vcs.splitPath(fn) opts = self.vcs.options["global"] + self.vcs.options["log"] verbose = "--verbose" in opts self.activateWindow() self.raise_() locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: nextRev = 0 fetched = 0 logs = [] limit = noEntries or 9999999 while fetched < limit: flimit = min(fetchLimit, limit - fetched) if fetched == 0: revstart = pysvn.Revision(pysvn.opt_revision_kind.head) else: revstart = pysvn.Revision(pysvn.opt_revision_kind.number, nextRev) allLogs = self.client.log( fname, revision_start=revstart, discover_changed_paths=verbose, limit=flimit + 1, strict_node_history=False, ) if len(allLogs) <= flimit or self._clientCancelCallback(): logs.extend(allLogs) break else: logs.extend(allLogs[:-1]) nextRev = allLogs[-1]["revision"].number fetched += fetchLimit locker.unlock() self.contents.clear() self.__pegRev = None for log in logs: ver = "{0:d}".format(log["revision"].number) dstr = "<b>{0} {1}</b>".format(self.revString, ver) if self.__pegRev is None: self.__pegRev = int(ver) try: lv = "{0:d}".format(logs[logs.index(log) + 1]["revision"].number) url = QUrl() url.setScheme("file") url.setPath(self.filename) query = lv + "_" + ver url.setQuery(query) dstr += ' [<a href="{0}" name="{1}">{2}</a>]'.format( url.toString(), query, self.tr("diff to {0}").format(lv) ) except IndexError: pass dstr += "<br />\n" self.contents.insertHtml(dstr) author = log["author"] message = log["message"] if sys.version_info[0] == 2: author = author.decode("utf-8") message = message.decode("utf-8") dstr = self.tr("<i>author: {0}</i><br />\n").format(author) self.contents.insertHtml(dstr) dstr = self.tr("<i>date: {0}</i><br />\n").format(formatTime(log["date"])) self.contents.insertHtml(dstr) self.contents.insertHtml("<br />\n") for line in message.splitlines(): self.contents.insertHtml(Utilities.html_encode(line)) self.contents.insertHtml("<br />\n") if len(log["changed_paths"]) > 0: self.contents.insertHtml("<br />\n") for changeInfo in log["changed_paths"]: action = changeInfo["action"] path = changeInfo["path"] if sys.version_info[0] == 2: action = action.decode("utf-8") path = path.decode("utf-8") dstr = "{0} {1}".format(self.flags[action], path) if changeInfo["copyfrom_path"] is not None: copyfrom_path = changeInfo["copyfrom_path"] if sys.version_info[0] == 2: copyfrom_path = copyfrom_path.decode("utf-8") dstr += self.tr(" (copied from {0}, revision {1})").format( copyfrom_path, changeInfo["copyfrom_revision"].number ) dstr += "<br />\n" self.contents.insertHtml(dstr) self.contents.insertHtml("<hr /><br />\n") except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0]) os.chdir(cwd) self.__finish()