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()