示例#1
0
    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()
示例#2
0
 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)
示例#3
0
 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)
示例#4
0
 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
示例#5
0
    def setLogsText(self, textJACK, textA2J, textLASH, textLADISH):
        QMutexLocker(self.fTextLock)

        self.fTextJACK   = textJACK
        self.fTextA2J    = textA2J
        self.fTextLASH   = textLASH
        self.fTextLADISH = textLADISH
示例#6
0
 def updateImage(self):
     locker = QMutexLocker(self.mutex)
     if not self.isRunning():
         self.start(QThread.LowPriority)
     else:
         self.restart = True
         self.condition.wakeOne()
示例#7
0
    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
示例#8
0
 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
示例#9
0
    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
示例#10
0
 def is_stopped(self):
     """
     线程状态是否是停止
     :return:
     """
     with QMutexLocker(self.mutex):
         return self.stopped
示例#11
0
 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
示例#13
0
 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)
示例#14
0
 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
示例#15
0
            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
示例#17
0
    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)
示例#18
0
            def process_frame(self, frame: QVideoFrame):
                with QMutexLocker(self._mutex):
                    self.frame = frame

                if not self.isRunning():
                    self.start()
                else:
                    self._condition.wakeOne()
示例#19
0
 def stop(self):
     """
     线程停止
     :return:
     """
     # 互斥锁
     with QMutexLocker(self.mutex):
         self.stopped = True
示例#20
0
 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()
示例#22
0
    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
示例#23
0
 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()
示例#24
0
    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
示例#25
0
 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)
示例#26
0
 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()
示例#27
0
    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())
示例#28
0
 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))
示例#29
0
    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()
示例#31
0
    def execute(self, function, *args, **kwargs):
        locker = QMutexLocker(self.mutex)

        self.function = function
        self.args = args
        self.kwargs = kwargs
        self.done = False

        self.start()
示例#32
0
    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
示例#33
0
    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)
示例#34
0
 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)
示例#35
0
    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)
示例#36
0
 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()
示例#37
0
 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
示例#38
0
 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)
示例#39
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()
示例#40
0
    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()