Esempio n. 1
0
    def _copy_lib_file(cls, file_name, dir_name, dst_file_name=None):
        """ Copy a library file to a directory and return the full pathname of
        the copy.
        """

        # Note that we use the Qt file operations to support the possibility
        # that pyqtdeploy itself has been deployed as a single executable.

        if dst_file_name is None:
            dst_file_name = file_name
            s_file_name = cls._get_lib_file_name(file_name)
        else:
            s_file_name = file_name

        d_file_name = dir_name + '/' + dst_file_name

        # Make sure the destination doesn't exist.
        QFile.remove(d_file_name)

        if not QFile.copy(s_file_name, d_file_name):
            raise UserException("Unable to copy file {0}".format(file_name))

        # The file will be read-only if it was embedded.
        QFile.setPermissions(d_file_name,
                             QFileDevice.ReadOwner | QFileDevice.WriteOwner)

        return d_file_name
Esempio n. 2
0
    def _copy_lib_file(cls, file_name, dir_name, dst_file_name=None):
        """ Copy a library file to a directory and return the full pathname of
        the copy.
        """

        # Note that we use the Qt file operations to support the possibility
        # that pyqtdeploy itself has been deployed as a single executable.

        if dst_file_name is None:
            dst_file_name = file_name
            s_file_name = cls._get_lib_file_name(file_name)
        else:
            s_file_name = file_name

        d_file_name = dir_name + '/' +  dst_file_name

        # Make sure the destination doesn't exist.
        QFile.remove(d_file_name)

        if not QFile.copy(s_file_name, d_file_name):
            raise UserException("Unable to copy file {0}".format(file_name))

        # The file will be read-only if it was embedded.
        QFile.setPermissions(d_file_name,
                QFileDevice.ReadOwner|QFileDevice.WriteOwner)

        return d_file_name
Esempio n. 3
0
    def _copy_file(self, uid: str = "", source_path: str = "", dest_path: str = ""):
        self._current_uid = uid

        source_file = QFile(source_path)
        dest_file = QFile(dest_path)

        if not source_file.open(QFile.ReadOnly):
            self.copy_error.emit(uid, FileCopier.CannotOpenSourceFile)
            return

        dest_file_info = QFileInfo(dest_file)
        dest_dir = dest_file_info.absoluteDir()
        if not dest_dir.exists():
            if not dest_dir.mkpath(dest_dir.absolutePath()):
                self.copy_error.emit(uid, FileCopier.CannotCreateDestinationDirectory)
                return

        if not dest_file.open(QFile.WriteOnly):
            ic(dest_path, dest_file.errorString())
            self.copy_error.emit(uid, FileCopier.CannotOpenDestinationFile)
            return

        progress: int = 0
        total: int = source_file.size()
        error: int = FileCopier.NoError
        while True:
            if self._cancel_current:
                self._cancel_current = False
                self.copy_cancelled.emit(uid)
                break

            data: Union[bytes, int] = source_file.read(_COPY_BLOCK_SIZE)
            if isinstance(data, int):
                assert data == -1
                error = FileCopier.CannotReadSourceFile
                break

            data_len = len(data)
            if data_len == 0:
                self.copy_progress.emit(uid, progress, total)
                break

            if data_len != dest_file.write(data):
                error = FileCopier.CannotWriteDestinationFile
                break

            progress += data_len
            self.copy_progress.emit(uid, progress, total)

            qApp.processEvents()

        source_file.close()
        dest_file.close()
        if error != FileCopier.NoError:
            dest_file.remove()
            self.copy_error.emit(uid, error)
        else:
            dest_file.setPermissions(source_file.permissions())
            self.copy_complete.emit(uid)
Esempio n. 4
0
 def get_app_settings() -> QSettings:
     FixedSettings.config_path = QStandardPaths.writableLocation(
         QStandardPaths.AppConfigLocation)
     settings_ini = os.path.join(
         FixedSettings.config_path,
         '%s.ini' % FixedSettings.applicationName.lower())
     if not os.path.exists(settings_ini):
         os.makedirs(FixedSettings.config_path, exist_ok=True)
         QFile.copy(':%s.ini' % FixedSettings.applicationName.lower(),
                    settings_ini)
         QFile.setPermissions(settings_ini,
                              QFile.ReadOwner | QFile.WriteOwner)
     return QSettings(settings_ini, QSettings.IniFormat)
Esempio n. 5
0
class NSwapFile(QObject):
    """
    In case Ninja-IDE crash, this can be used to recover the lost data.

    When the user begins to edit an existing file on the disk, this object
    creates a swap file and activates a timer that will execute a function,
    that will update that swap file as soon as the timeout ends (by default,
    is 15 seconds).
    The swap file is deleted when the original file is saved or closed.
    When system or Ninja crash, the swap file exists on disk and Ninja will
    used to recover the lost data.
    """

    canBeRecovered = pyqtSignal()

    def __init__(self, neditable):
        QObject.__init__(self)
        self._neditable = neditable
        self.__swap_file = QFile()
        self.__stream = QTextStream()

        # Activate timer when user typing
        self.__timer = QTimer()
        self.__timer.setSingleShot(True)

        self.__timer.timeout.connect(self._finish_typing)
        self._neditable.fileLoaded.connect(self._file_loaded)
        self._neditable.fileSaved.connect(self._file_saved)

        self.init(tracking=True)

    def init(self, tracking):
        if tracking:
            self._neditable.editor.textChanged.connect(self._start_typing)
            self._neditable.fileClosing.connect(self._file_closed)
        else:
            self._neditable.editor.textChanged.disconnect(self._start_typing)
            self._neditable.fileClosing.disconnect(self._file_closed)

    def _file_closed(self):
        """Editor was closed normally, now remove swap file"""

        self.__remove()

    def _file_saved(self):
        """If file is saved, remove swap file"""

        # Remove old swap file and set the name for the new swap file
        self.__remove()
        self.__update_filename()

    def __remove(self):
        """Remove swap file"""

        if self.__swap_file.fileName() and self.__swap_file.exists():
            self.__stream.setDevice(None)
            self.__swap_file.close()
            self.__swap_file.remove()

    def _file_loaded(self):
        """This slot is executed when a file is loaded on the editor and
        look for swap file, if exists then can be recover"""

        self.__update_filename()
        if self.__swap_file.exists():
            # In recovery process can't edit
            self._neditable.editor.setReadOnly(True)
            # Ok, can be recover
            self.canBeRecovered.emit()

    def __update_filename(self):
        # First clear filename
        self.__swap_file.setFileName("")
        # Get new path
        filename = self.filename()
        self.__swap_file.setFileName(filename)

    def _start_typing(self):
        # Skip if editor is not modified
        if not self._neditable.editor.is_modified:
            return
        # No swap file, no work
        if not self.__swap_file.fileName():
            return
        # Create the file
        if not self.__swap_file.exists():
            self.__swap_file.open(QIODevice.WriteOnly)
            permissions = QFileDevice.ReadOwner | QFileDevice.WriteOwner
            self.__swap_file.setPermissions(permissions)
            self.__stream.setDevice(self.__swap_file)

        if self.__timer.isActive():
            self.__timer.stop()
        # Write swap file to the disk every 10 seconds by default
        self.__timer.start(settings.SWAP_FILE_INTERVAL * 1000)

    def _finish_typing(self):
        if not self.__swap_file.isOpen():
            return
        logger.debug("Now write the swap file...")
        text = self._neditable.editor.text
        self.__swap_file.write(text.encode())
        self.__swap_file.flush()

    def filename(self):
        """Returns the filename for swap file"""

        path, name = os.path.split(
            os.path.join(SWAP_PATH, self._neditable.nfile.file_name))
        filename = os.path.join(path, "%s.ninja-swap" % name)
        return filename

    def recover(self):
        self._neditable.editor.setReadOnly(False)
        # Disconnect signals
        self.init(tracking=False)

        self.__stream.setDevice(self.__swap_file)
        if not self.__swap_file.open(QIODevice.ReadOnly):
            logger.warning("Can't open swap file")
            return
        # Ok
        data = []
        append = data.append
        while not self.__stream.atEnd():
            line = self.__stream.readLine()
            append(line)

        # Set data in the editor
        self._neditable.editor.text = "\n".join(data)
        self._neditable.document.setModified(True)

        # Close swap file
        self.__stream.setDevice(None)
        self.__swap_file.close()
        # Reconnect signals
        self.init(tracking=True)

    def discard(self):
        self._neditable.editor.setReadOnly(False)
        # Remove swap file
        self.__remove()