Пример #1
0
class EditorWorker(QObject):

    file_change_sig = pyqtSignal(bool)  # is_zim

    def __init__(self,
                 command,
                 old_text,
                 is_zim,
                 zim_folder=None,
                 docid=None,
                 zim_file=None,
                 parent=None):
        '''Observe the write/save states of a txt file to edit notes

        Args:
            command (list): command string list to pass into Popen.
            old_text (str): existing note text to paste into editor.
            is_zim (bool): if True, try open the associated zim note file.
                           if False, open a temp file to edit.
        Kwargs:
            zim_folder (str or None): if not None, the path to the zim note
                                      folder, used to search for zim notes.
            docid (int or None): if not None, id of current doc.
            parent (QWidget or None): parent widget.
        '''
        super(EditorWorker, self).__init__(parent)

        self.is_zim = is_zim
        self.zim_folder = zim_folder
        self.docid = docid
        self.logger = logging.getLogger(__name__)

        if not self.is_zim:
            self._temp_file = QTemporaryFile(self)
        else:
            if zim_file is not None:
                # use given zim file
                if os.path.exists(zim_file) and os.path.islink(zim_file):
                    self._temp_file = QFile(zim_file, self)
                    self.logger.debug('Got given zim file %s' % zim_file)
                else:
                    try:
                        zim_file = locateZimNote(self.zim_folder, self.docid)
                        self._temp_file = QFile(zim_file, self)
                        self.logger.exception(
                            'Failed to open given zim file. Get the id one.')
                    except:
                        self.logger.exception('Failed to find zim file.')
                        self._temp_file = QTemporaryFile(self)
                        self.is_zim = False
            else:
                # no given zim file, get the one in all_notes
                try:
                    zim_file = locateZimNote(self.zim_folder, self.docid)
                    self._temp_file = QFile(zim_file, self)
                    self.logger.debug('Got zim file %s' % zim_file)
                except:
                    self.logger.exception('Failed to find zim file.')
                    self._temp_file = QTemporaryFile(self)
                    self.is_zim = False

        self._process = QProcess(self)
        self._text = ""
        self._watcher = QFileSystemWatcher(self)
        self._watcher.fileChanged.connect(self.onFileChange)

        # write existing lines if temp file
        if not self.is_zim and self._temp_file.open():
            self._temp_file.write(old_text.encode('utf-8'))
            self._temp_file.close()

        # open() on temp file assumes QIODevice.ReadWrite as well.
        if self._temp_file.open(QIODevice.ReadWrite):
            self._file_path = self._temp_file.fileName()
            self._watcher.addPath(self._file_path)
            self.logger.debug('_file_path = %s' % self._file_path)

            program = command[0]
            arguments = command[1:]
            self._process.start(program,
                                arguments + [self._temp_file.fileName()])

    @pyqtSlot()
    def onFileChange(self):
        if self._temp_file.isOpen():

            #self._temp_file.seek(0)
            #self._text = self._temp_file.readAll().data().decode()

            # has to use with open and read(), the above doesn't work for
            # some editors, like xed

            # For some reason, if watching the zim file, and open in gvim
            # it reports file not found unless I wait for a while.
            wtf = os.path.exists(self._temp_file.fileName())
            while not wtf:
                wtf = os.path.exists(self._temp_file.fileName())

            with open(self._temp_file.fileName()) as tmp:
                self._text = tmp.read()

            # Re-add watch file, again for xed.
            self._watcher.removePath(self._file_path)
            self._watcher.addPath(self._file_path)

            self.file_change_sig.emit(self.is_zim)

    @property
    def text(self):
        return self._text

    def __del__(self):
        self._process.kill()