예제 #1
1
class FilenamePrompt(_BasePrompt):

    """A prompt for a filename."""

    def __init__(self, question, parent=None):
        super().__init__(question, parent)
        self._init_texts(question)
        self._init_fileview()
        self._set_fileview_root(question.default)

        self._lineedit = LineEdit(self)
        if question.default:
            self._lineedit.setText(question.default)
        self._lineedit.textEdited.connect(self._set_fileview_root)
        self._vbox.addWidget(self._lineedit)

        self.setFocusProxy(self._lineedit)
        self._init_key_label()

        if config.get('ui', 'prompt-filebrowser'):
            self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

    @pyqtSlot(str)
    def _set_fileview_root(self, path, *, tabbed=False):
        """Set the root path for the file display."""
        separators = os.sep
        if os.altsep is not None:
            separators += os.altsep

        dirname = os.path.dirname(path)

        try:
            if not path:
                pass
            elif path in separators and os.path.isdir(path):
                # Input "/" -> don't strip anything
                pass
            elif path[-1] in separators and os.path.isdir(path):
                # Input like /foo/bar/ -> show /foo/bar/ contents
                path = path.rstrip(separators)
            elif os.path.isdir(dirname) and not tabbed:
                # Input like /foo/ba -> show /foo contents
                path = dirname
            else:
                return
        except OSError:
            log.prompt.exception("Failed to get directory information")
            return

        root = self._file_model.setRootPath(path)
        self._file_view.setRootIndex(root)

    @pyqtSlot(QModelIndex)
    def _insert_path(self, index, *, clicked=True):
        """Handle an element selection.

        Args:
            index: The QModelIndex of the selected element.
            clicked: Whether the element was clicked.
        """
        path = os.path.normpath(self._file_model.filePath(index))
        if clicked:
            path += os.sep
        else:
            # On Windows, when we have C:\foo and tab over .., we get C:\
            path = path.rstrip(os.sep)

        log.prompt.debug('Inserting path {}'.format(path))
        self._lineedit.setText(path)
        self._lineedit.setFocus()
        self._set_fileview_root(path, tabbed=True)
        if clicked:
            # Avoid having a ..-subtree highlighted
            self._file_view.setCurrentIndex(QModelIndex())

    def _init_fileview(self):
        self._file_view = QTreeView(self)
        self._file_model = QFileSystemModel(self)
        self._file_view.setModel(self._file_model)
        self._file_view.clicked.connect(self._insert_path)

        if config.get('ui', 'prompt-filebrowser'):
            self._vbox.addWidget(self._file_view)
        else:
            self._file_view.hide()

        # Only show name
        self._file_view.setHeaderHidden(True)
        for col in range(1, 4):
            self._file_view.setColumnHidden(col, True)
        # Nothing selected initially
        self._file_view.setCurrentIndex(QModelIndex())
        # The model needs to be sorted so we get the correct first/last index
        self._file_model.directoryLoaded.connect(
            lambda: self._file_model.sort(0))

    def accept(self, value=None):
        text = value if value is not None else self._lineedit.text()
        text = downloads.transform_path(text)
        if text is None:
            message.error("Invalid filename")
            return False
        self.question.answer = text
        return True

    def item_focus(self, which):
        # This duplicates some completion code, but I don't see a nicer way...
        assert which in ['prev', 'next'], which
        selmodel = self._file_view.selectionModel()

        parent = self._file_view.rootIndex()
        first_index = self._file_model.index(0, 0, parent)
        row = self._file_model.rowCount(parent) - 1
        last_index = self._file_model.index(row, 0, parent)

        if not first_index.isValid():
            # No entries
            return

        assert last_index.isValid()

        idx = selmodel.currentIndex()
        if not idx.isValid():
            # No item selected yet
            idx = last_index if which == 'prev' else first_index
        elif which == 'prev':
            idx = self._file_view.indexAbove(idx)
        else:
            assert which == 'next', which
            idx = self._file_view.indexBelow(idx)

        # wrap around if we arrived at beginning/end
        if not idx.isValid():
            idx = last_index if which == 'prev' else first_index

        selmodel.setCurrentIndex(
            idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
        self._insert_path(idx, clicked=False)

    def _allowed_commands(self):
        return [('prompt-accept', 'Accept'), ('leave-mode', 'Abort')]
예제 #2
0
class FilenamePrompt(_BasePrompt):
    """A prompt for a filename."""
    def __init__(self, question, parent=None):
        super().__init__(question, parent)
        self._init_texts(question)
        self._init_key_label()

        self._lineedit = LineEdit(self)
        if question.default:
            self._lineedit.setText(question.default)
        self._lineedit.textEdited.connect(self._set_fileview_root)
        self._vbox.addWidget(self._lineedit)

        self.setFocusProxy(self._lineedit)

        self._init_fileview()
        self._set_fileview_root(question.default)

        if config.val.prompt.filebrowser:
            self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

        self._to_complete = ''

    @pyqtSlot(str)
    def _set_fileview_root(self, path, *, tabbed=False):
        """Set the root path for the file display."""
        separators = os.sep
        if os.altsep is not None:
            separators += os.altsep

        dirname = os.path.dirname(path)
        basename = os.path.basename(path)
        if not tabbed:
            self._to_complete = ''

        try:
            if not path:
                pass
            elif path in separators and os.path.isdir(path):
                # Input "/" -> don't strip anything
                pass
            elif path[-1] in separators and os.path.isdir(path):
                # Input like /foo/bar/ -> show /foo/bar/ contents
                path = path.rstrip(separators)
            elif os.path.isdir(dirname) and not tabbed:
                # Input like /foo/ba -> show /foo contents
                path = dirname
                self._to_complete = basename
            else:
                return
        except OSError:
            log.prompt.exception("Failed to get directory information")
            return

        root = self._file_model.setRootPath(path)
        self._file_view.setRootIndex(root)

    @pyqtSlot(QModelIndex)
    def _insert_path(self, index, *, clicked=True):
        """Handle an element selection.

        Args:
            index: The QModelIndex of the selected element.
            clicked: Whether the element was clicked.
        """
        if index == QModelIndex():
            path = os.path.join(self._file_model.rootPath(), self._to_complete)
        else:
            path = os.path.normpath(self._file_model.filePath(index))

        if clicked:
            path += os.sep
        else:
            # On Windows, when we have C:\foo and tab over .., we get C:\
            path = path.rstrip(os.sep)

        log.prompt.debug('Inserting path {}'.format(path))
        self._lineedit.setText(path)
        self._lineedit.setFocus()
        self._set_fileview_root(path, tabbed=True)
        if clicked:
            # Avoid having a ..-subtree highlighted
            self._file_view.setCurrentIndex(QModelIndex())

    def _init_fileview(self):
        self._file_view = QTreeView(self)
        self._file_model = QFileSystemModel(self)
        self._file_view.setModel(self._file_model)
        self._file_view.clicked.connect(self._insert_path)

        if config.val.prompt.filebrowser:
            self._vbox.addWidget(self._file_view)
        else:
            self._file_view.hide()

        # Only show name
        self._file_view.setHeaderHidden(True)
        for col in range(1, 4):
            self._file_view.setColumnHidden(col, True)
        # Nothing selected initially
        self._file_view.setCurrentIndex(QModelIndex())
        # The model needs to be sorted so we get the correct first/last index
        self._file_model.directoryLoaded.connect(
            lambda: self._file_model.sort(0))

    def accept(self, value=None, save=False):
        self._check_save_support(save)
        text = value if value is not None else self._lineedit.text()
        text = downloads.transform_path(text)
        if text is None:
            message.error("Invalid filename")
            return False
        self.question.answer = text
        return True

    def item_focus(self, which):
        # This duplicates some completion code, but I don't see a nicer way...
        assert which in ['prev', 'next'], which
        selmodel = self._file_view.selectionModel()

        parent = self._file_view.rootIndex()
        first_index = self._file_model.index(0, 0, parent)
        row = self._file_model.rowCount(parent) - 1
        last_index = self._file_model.index(row, 0, parent)

        if not first_index.isValid():
            # No entries
            return

        assert last_index.isValid()

        idx = selmodel.currentIndex()

        if not idx.isValid():
            # No item selected yet
            idx = last_index if which == 'prev' else first_index
        elif which == 'prev':
            idx = self._file_view.indexAbove(idx)
        else:
            assert which == 'next', which
            idx = self._file_view.indexBelow(idx)

        # wrap around if we arrived at beginning/end
        if not idx.isValid():
            idx = last_index if which == 'prev' else first_index

        idx = self._do_completion(idx, which)

        selmodel.setCurrentIndex(
            idx, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows)
        self._insert_path(idx, clicked=False)

    def _do_completion(self, idx, which):
        filename = self._file_model.fileName(idx)
        while not filename.startswith(self._to_complete) and idx.isValid():
            if which == 'prev':
                idx = self._file_view.indexAbove(idx)
            else:
                assert which == 'next', which
                idx = self._file_view.indexBelow(idx)
            filename = self._file_model.fileName(idx)

        return idx

    def _allowed_commands(self):
        return [('prompt-accept', 'Accept'), ('leave-mode', 'Abort')]
예제 #3
0
파일: navigation.py 프로젝트: lheido/Mojuru
class Navigation(QWidget):
    """
    Navigation class definition.
    
    Provide a combobox to switch on each opened directories and display it into
    a tree view
    
    Provide 2 useful function (to use in alter module):
      - add_action(name, shortcut, callback)
         - callback take 2 arguments : file_info and parent
      - add_separator()
    
    """
    
    SETTINGS_DIRECTORIES = 'navigation_dirs'
    SETTINGS_CURRENT_DIR = 'navigation_current_dir'
    
    onFileItemActivated = pyqtSignal(QFileInfo, name="onFileItemActivated")
    onDirItemActivated = pyqtSignal(QFileInfo, name="onDirItemActivated")
    
    def __init__(self, parent=None):
        super(Navigation, self).__init__(parent)
        self.setObjectName("Navigation")
        
        self.layout = QVBoxLayout(self)
        self.layout.setSpacing(0)
        self.layout.setContentsMargins(0,0,0,0)
        
        self.menu_button = QPushButton('Select directory', self)
        self.menu_button.setFlat(True)
#        self.menu_button.clicked.connect(self.on_menu_button_clicked)
        self.menu = QMenu(self)
        self.menu_button.setMenu(self.menu)
        self.menu_directories = QMenu(self)
        self.menu_directories.setTitle('Directories')
        self.menu_add_action(
            'Open directory', self.open_directory, None, QKeySequence.Open)
        self.menu_add_separator()
        self.menu_add_action('Refresh', self.reset, None, QKeySequence.Refresh)
        # @TODO invoke_all
        self.menu_add_separator()
        self.menu.addMenu(self.menu_directories)
        
        self.tree = QTreeView(self)
        self.model = FileSystemModel(self)
        self.tree.setModel(self.model)
        self.tree.setColumnHidden(1, True)
        self.tree.setColumnHidden(2, True)
        self.tree.setColumnHidden(3, True)
        self.tree.setHeaderHidden(True)
        # only to expand directory or activated with one click
        self.tree.clicked.connect(self.on_item_clicked)
        # else, for file use activated signal
        self.tree.activated.connect(self.on_item_activated)
        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree.customContextMenuRequested.connect(self.on_context_menu)
        
        self.widgets = collections.OrderedDict()
        self.widgets['menu_button'] = self.menu_button
        self.widgets['tree'] = self.tree
        
        # @ToDo: Alter.invoke_all('add_widget', self.widgets)
        
        for name, widget in self.widgets.items():
            if name == 'menu_button':
                self.layout.addWidget(widget, 0, Qt.AlignLeft)
            else:
                self.layout.addWidget(widget)
        
        self.context_menu = QMenu(self)
        self.add_action('New file', QKeySequence.New, 
                        FileSystemHelper.new_file)
        self.add_action('New Directory', '', 
                        FileSystemHelper.new_directory)
        self.add_separator()
        self.add_action('Rename', '', FileSystemHelper.rename)
        self.add_action('Copy', QKeySequence.Copy, FileSystemHelper.copy)
        self.add_action('Cut', QKeySequence.Cut, FileSystemHelper.cut)
        self.add_action('Paste', QKeySequence.Paste, FileSystemHelper.paste)
        self.add_separator()
        self.add_action('Delete', QKeySequence.Delete, 
                        FileSystemHelper.delete)
        
        # @ToDo Alter.invoke_all('navigation_add_action', self)
        
        #restore previous session and data
        dirs = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_DIRECTORIES, None, True)
        for directory_path in dirs:
            name = os.path.basename(directory_path)
            self.menu_add_directory(name, directory_path)
        current_dir = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_CURRENT_DIR, '')
        if current_dir:
            for action in self.menu_directories.actions():
                if action.data() == current_dir:
                    action.trigger()
        
        self.menu_button.setFocusPolicy(Qt.NoFocus)
        self.menu_button.setFocusProxy(self.tree)
    
    def reset(self, file_info):
        self.model.beginResetModel()
        current_dir = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_CURRENT_DIR, '')
        if current_dir:
            for action in self.menu_directories.actions():
                if action.data() == current_dir:
                    action.trigger()
    
    def on_menu_button_clicked(self):
        pos = self.mapToGlobal(self.menu_button.pos())
        menu_width = self.menu.sizeHint().width()
        pos.setY(pos.y() + self.menu_button.height())
#        pos.setX(pos.x() + self.menu_button.width() - menu_width)
        if len(self.menu.actions()) > 0:
            self.menu.exec(pos)
    
    def menu_add_action(self, name, callback, data=None, shortcut=None, icon=None):
        action = QAction(name, self)
        if icon:
            action.setIcon(icon)
        if shortcut:
            action.setShortcut(shortcut)
            action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        if data:
            action.setData(data)
        action.triggered.connect(callback)
        self.addAction(action)
        self.menu.addAction(action)
    
    def menu_add_directory(self, name, data):
        action = QAction(name, self)
        action.setData(data)
        action.triggered.connect(self.on_menu_action_triggered)
        self.menu_directories.addAction(action)
        return action
    
    def menu_add_separator(self):
        self.menu.addSeparator()
    
    def add_action(self, name, shortcut, callback, icon = None):
        """
        Ajoute une action au context menu et au widget navigation lui même.
        Créer une fonction à la volé pour fournir des arguments aux fonctions
        associé aux actions.
        """
        action = QAction(name, self)
        if icon:
            action.setIcon(icon)
        action.setShortcut(shortcut)
        action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        action.triggered.connect(self.__wrapper(callback))
        self.addAction(action)
        self.context_menu.addAction(action)
    
    def add_separator(self):
        """Simple abstraction of self.context_menu.addSeparator()"""
        self.context_menu.addSeparator()
    
    def __wrapper(self, callback):
        def __new_function():
            """
            __new_function représente la forme de tous les callbacks connecté
            à une action pour pouvoir utiliser les raccourcis en même temps que
            le menu contextuel.
            """
            action = self.sender()
            file_info = action.data()
            if not file_info:
                indexes = self.tree.selectedIndexes()
                if indexes:
                    model_index = indexes[0]
                    file_info = self.model.fileInfo(model_index)
                    callback(file_info, self)
                elif action.shortcut() == QKeySequence.New:
                    file_info = self.model.fileInfo(self.tree.rootIndex())
                    callback(file_info, self)
            else:
                callback(file_info, self)
                action.setData(None)
        return __new_function
    
    def question(self, text, informative_text = None):
        message_box = QMessageBox(self)
        message_box.setText(text)
        if informative_text:
            message_box.setInformativeText(informative_text)
        message_box.setStandardButtons(
            QMessageBox.No | QMessageBox.Yes)
        message_box.setDefaultButton(QMessageBox.No)
        return message_box.exec()
    
    def on_context_menu(self, point):
        model_index = self.tree.indexAt(point)
        file_info = self.model.fileInfo(model_index)
        # pour chaque action on met a jour les data (file_info)
        # puis on altère les actions (ex enabled)
        for action in self.context_menu.actions():
            if not action.isSeparator():
                action.setData(file_info)
                action.setEnabled(model_index.isValid())
                if action.shortcut() == QKeySequence.New:
                    action.setEnabled(True)
                    if not model_index.isValid():
                        file_info = self.model.fileInfo(self.tree.rootIndex())
                        action.setData(file_info)
                if action.shortcut() == QKeySequence.Paste:
                    enable = FileSystemHelper.ready() and model_index.isValid()
                    action.setEnabled(enable)
                if action.shortcut() == QKeySequence.Delete:
                    # remove directory only if is an empty directory
                    if model_index.isValid() and file_info.isDir():
                        path = file_info.absoluteFilePath()
                        # QDir(path).count() always contains '.' and '..'
                        action.setEnabled(QDir(path).count() == 2)
                # @ToDo 
                #Alter.invoke_all(
                #    'navigation_on_menu_action', 
                #    model_index, file_info, action, self)
        if len(self.context_menu.actions()) > 0:
            self.context_menu.exec(self.tree.mapToGlobal(point))
        # reset action data, sinon y a des problèmes dans _new_function
        for action in self.context_menu.actions():
            action.setData(None)
    
    def on_item_activated(self, index):
        qFileInfo = self.model.fileInfo(index)
        if qFileInfo.isDir():
            self.onDirItemActivated.emit(qFileInfo)
        else:
            self.onFileItemActivated.emit(qFileInfo)
    
    def on_item_clicked(self, index):
        qFileInfo = self.model.fileInfo(index)
        if qFileInfo.isDir():
            self.onDirItemActivated.emit(qFileInfo)
            self.tree.setExpanded(index, not self.tree.isExpanded(index))
        else:
            self.onFileItemActivated.emit(qFileInfo)
    
    def open_directory(self):
        project = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_CURRENT_DIR, '')
        path = QFileDialog.getExistingDirectory(self, "Open Directory", project)
        if path:
            name = os.path.basename(path)
            action = self.menu_add_directory(name, path)
            self.save_directories_path()
            action.trigger()
    
    def on_menu_action_triggered(self):
        action = self.sender()
        path = action.data()
        if path:
            self.model.setRootPath(path)
            self.tree.setRootIndex(self.model.index(path))
            self.menu_button.setText(os.path.basename(path))
            self.save_current_dir(path)
    
    def save_directories_path(self):
        ModuleManager.core['settings'].Settings.set_value(
            self.SETTINGS_DIRECTORIES,
            [action.data() for action in self.menu_directories.actions()]    
        )
    
    def save_current_dir(self, path):
        ModuleManager.core['settings'].Settings.set_value(
            self.SETTINGS_CURRENT_DIR,
            path
        )
예제 #4
0
class Navigation(QWidget):
    """
    Navigation class definition.
    
    Provide a combobox to switch on each opened directories and display it into
    a tree view
    
    Provide 2 useful function (to use in alter module):
      - add_action(name, shortcut, callback)
         - callback take 2 arguments : file_info and parent
      - add_separator()
    
    """

    SETTINGS_DIRECTORIES = 'navigation_dirs'
    SETTINGS_CURRENT_DIR = 'navigation_current_dir'

    onFileItemActivated = pyqtSignal(QFileInfo, name="onFileItemActivated")
    onDirItemActivated = pyqtSignal(QFileInfo, name="onDirItemActivated")

    def __init__(self, parent=None):
        super(Navigation, self).__init__(parent)
        self.setObjectName("Navigation")

        self.layout = QVBoxLayout(self)
        self.layout.setSpacing(0)
        self.layout.setContentsMargins(0, 0, 0, 0)

        self.menu_button = QPushButton('Select directory', self)
        self.menu_button.setFlat(True)
        #        self.menu_button.clicked.connect(self.on_menu_button_clicked)
        self.menu = QMenu(self)
        self.menu_button.setMenu(self.menu)
        self.menu_directories = QMenu(self)
        self.menu_directories.setTitle('Directories')
        self.menu_add_action('Open directory', self.open_directory, None,
                             QKeySequence.Open)
        self.menu_add_separator()
        self.menu_add_action('Refresh', self.reset, None, QKeySequence.Refresh)
        # @TODO invoke_all
        self.menu_add_separator()
        self.menu.addMenu(self.menu_directories)

        self.tree = QTreeView(self)
        self.model = FileSystemModel(self)
        self.tree.setModel(self.model)
        self.tree.setColumnHidden(1, True)
        self.tree.setColumnHidden(2, True)
        self.tree.setColumnHidden(3, True)
        self.tree.setHeaderHidden(True)
        # only to expand directory or activated with one click
        self.tree.clicked.connect(self.on_item_clicked)
        # else, for file use activated signal
        self.tree.activated.connect(self.on_item_activated)
        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree.customContextMenuRequested.connect(self.on_context_menu)

        self.widgets = collections.OrderedDict()
        self.widgets['menu_button'] = self.menu_button
        self.widgets['tree'] = self.tree

        # @ToDo: Alter.invoke_all('add_widget', self.widgets)

        for name, widget in self.widgets.items():
            if name == 'menu_button':
                self.layout.addWidget(widget, 0, Qt.AlignLeft)
            else:
                self.layout.addWidget(widget)

        self.context_menu = QMenu(self)
        self.add_action('New file', QKeySequence.New,
                        FileSystemHelper.new_file)
        self.add_separator()
        self.add_action('Copy', QKeySequence.Copy, FileSystemHelper.copy)
        self.add_action('Cut', QKeySequence.Cut, FileSystemHelper.cut)
        self.add_action('Paste', QKeySequence.Paste, FileSystemHelper.paste)
        self.add_separator()
        self.add_action('Delete', QKeySequence.Delete, FileSystemHelper.delete)

        # @ToDo Alter.invoke_all('navigation_add_action', self)

        #restore previous session and data
        dirs = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_DIRECTORIES, None, True)
        for directory_path in dirs:
            name = os.path.basename(directory_path)
            self.menu_add_directory(name, directory_path)
        current_dir = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_CURRENT_DIR, '')
        if current_dir:
            for action in self.menu_directories.actions():
                if action.data() == current_dir:
                    action.trigger()

        self.menu_button.setFocusPolicy(Qt.NoFocus)
        self.menu_button.setFocusProxy(self.tree)

    def reset(self, file_info):
        self.model.beginResetModel()
        current_dir = ModuleManager.core['settings'].Settings.value(
            self.SETTINGS_CURRENT_DIR, '')
        if current_dir:
            for action in self.menu_directories.actions():
                if action.data() == current_dir:
                    action.trigger()

    def on_menu_button_clicked(self):
        pos = self.mapToGlobal(self.menu_button.pos())
        menu_width = self.menu.sizeHint().width()
        pos.setY(pos.y() + self.menu_button.height())
        #        pos.setX(pos.x() + self.menu_button.width() - menu_width)
        if len(self.menu.actions()) > 0:
            self.menu.exec(pos)

    def menu_add_action(self,
                        name,
                        callback,
                        data=None,
                        shortcut=None,
                        icon=None):
        action = QAction(name, self)
        if icon:
            action.setIcon(icon)
        if shortcut:
            action.setShortcut(shortcut)
            action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        if data:
            action.setData(data)
        action.triggered.connect(callback)
        self.addAction(action)
        self.menu.addAction(action)

    def menu_add_directory(self, name, data):
        action = QAction(name, self)
        action.setData(data)
        action.triggered.connect(self.on_menu_action_triggered)
        self.menu_directories.addAction(action)
        return action

    def menu_add_separator(self):
        self.menu.addSeparator()

    def add_action(self, name, shortcut, callback, icon=None):
        """
        Ajoute une action au context menu et au widget navigation lui même.
        Créer une fonction à la volé pour fournir des arguments aux fonctions
        associé aux actions.
        """
        action = QAction(name, self)
        if icon:
            action.setIcon(icon)
        action.setShortcut(shortcut)
        action.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        action.triggered.connect(self.__wrapper(callback))
        self.addAction(action)
        self.context_menu.addAction(action)

    def add_separator(self):
        """Simple abstraction of self.context_menu.addSeparator()"""
        self.context_menu.addSeparator()

    def __wrapper(self, callback):
        def __new_function():
            """
            __new_function représente la forme de tous les callbacks connecté
            à une action pour pouvoir utiliser les raccourcis en même temps que
            le menu contextuel.
            """
            action = self.sender()
            file_info = action.data()
            if not file_info:
                indexes = self.tree.selectedIndexes()
                if indexes:
                    model_index = indexes[0]
                    file_info = self.model.fileInfo(model_index)
                    callback(file_info, self)
                elif action.shortcut() == QKeySequence.New:
                    file_info = self.model.fileInfo(self.tree.rootIndex())
                    callback(file_info, self)
            else:
                callback(file_info, self)
                action.setData(None)

        return __new_function

    def question(self, text, informative_text=None):
        message_box = QMessageBox(self)
        message_box.setText(text)
        if informative_text:
            message_box.setInformativeText(informative_text)
        message_box.setStandardButtons(QMessageBox.No | QMessageBox.Yes)
        message_box.setDefaultButton(QMessageBox.No)
        return message_box.exec()

    def on_context_menu(self, point):
        model_index = self.tree.indexAt(point)
        file_info = self.model.fileInfo(model_index)
        # pour chaque action on met a jour les data (file_info)
        # puis on altère les actions (ex enabled)
        for action in self.context_menu.actions():
            if not action.isSeparator():
                action.setData(file_info)
                action.setEnabled(model_index.isValid())
                if action.shortcut() == QKeySequence.New:
                    action.setEnabled(True)
                    if not model_index.isValid():
                        file_info = self.model.fileInfo(self.tree.rootIndex())
                        action.setData(file_info)
                if action.shortcut() == QKeySequence.Paste:
                    enable = FileSystemHelper.ready() and model_index.isValid()
                    action.setEnabled(enable)
                if action.shortcut() == QKeySequence.Delete:
                    # remove directory only if is an empty directory
                    if model_index.isValid() and file_info.isDir():
                        path = file_info.absoluteFilePath()
                        # QDir(path).count() always contains '.' and '..'
                        action.setEnabled(QDir(path).count() == 2)
                # @ToDo
                #Alter.invoke_all(
                #    'navigation_on_menu_action',
                #    model_index, file_info, action, self)
        if len(self.context_menu.actions()) > 0:
            self.context_menu.exec(self.tree.mapToGlobal(point))
        # reset action data, sinon y a des problèmes dans _new_function
        for action in self.context_menu.actions():
            action.setData(None)

    def on_item_activated(self, index):
        qFileInfo = self.model.fileInfo(index)
        if qFileInfo.isDir():
            self.onDirItemActivated.emit(qFileInfo)
        else:
            self.onFileItemActivated.emit(qFileInfo)

    def on_item_clicked(self, index):
        qFileInfo = self.model.fileInfo(index)
        if qFileInfo.isDir():
            self.onDirItemActivated.emit(qFileInfo)
            self.tree.setExpanded(index, not self.tree.isExpanded(index))
        else:
            self.onFileItemActivated.emit(qFileInfo)

    def open_directory(self):
        path = QFileDialog.getExistingDirectory(self, "Open Directory", ".")
        if path:
            name = os.path.basename(path)
            action = self.menu_add_directory(name, path)
            self.save_directories_path()
            action.trigger()

    def on_menu_action_triggered(self):
        action = self.sender()
        path = action.data()
        if path:
            self.model.setRootPath(path)
            self.tree.setRootIndex(self.model.index(path))
            self.menu_button.setText(os.path.basename(path))
            self.save_current_dir(path)

    def save_directories_path(self):
        ModuleManager.core['settings'].Settings.set_value(
            self.SETTINGS_DIRECTORIES,
            [action.data() for action in self.menu_directories.actions()])

    def save_current_dir(self, path):
        ModuleManager.core['settings'].Settings.set_value(
            self.SETTINGS_CURRENT_DIR, path)
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'logextracter-gui'
        self.left = 10
        self.top = 10
        self.width = 1024
        self.height = 400
        self.initUI()

    def initUI(self):

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        openSrcFolderAction = QAction(QIcon('opensrcfolder.png'), 'SRC Folder',
                                      self)
        openSrcFolderAction.setShortcut('Ctrl+S')
        openSrcFolderAction.setStatusTip('Open the source folder')
        openSrcFolderAction.triggered.connect(self.browseSrcFolder)

        openDestFolderAction = QAction(QIcon('opendestfolder.png'),
                                       'DEST Folder', self)
        openDestFolderAction.setShortcut('Ctrl+D')
        openDestFolderAction.setStatusTip('Open the destination folder')
        openDestFolderAction.triggered.connect(self.browseDestFolder)

        exitAction = QAction(QIcon('exit.png'), 'Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(self.close)

        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')
        fileMenu.addAction(openSrcFolderAction)
        fileMenu.addAction(openDestFolderAction)
        fileMenu.addAction(exitAction)
        helpMenu = menuBar.addMenu('&Help')

        self.srcModel = QFileSystemModel()
        self.srcModel.setRootPath(QDir.currentPath())
        self.srcTree = QTreeView()
        self.srcTree.setModel(self.srcModel)
        self.srcTree.setRootIndex(self.srcModel.index(QDir.currentPath()))
        self.srcTree.setAnimated(False)
        self.srcTree.setIndentation(20)
        self.srcTree.setSortingEnabled(True)
        self.srcTree.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.destModel = QFileSystemModel()
        self.destModel.setRootPath(QDir.currentPath())
        self.destTree = QTreeView()
        self.destTree.setModel(self.destModel)
        self.destTree.setRootIndex(self.destModel.index(QDir.currentPath()))
        self.destTree.setAnimated(False)
        self.destTree.setIndentation(20)
        self.destTree.setSortingEnabled(True)

        self.extractButton = QPushButton()
        self.extractButton.setText('====>')
        self.extractButton.clicked.connect(self.extract)
        mainLayout = QHBoxLayout()
        mainLayout.addWidget(self.srcTree)
        mainLayout.addWidget(self.extractButton)
        mainLayout.addWidget(self.destTree)
        self.centralWidget = QWidget()
        self.centralWidget.setLayout(mainLayout)
        self.setCentralWidget(self.centralWidget)

        self.show()

    def browseSrcFolder(self):

        directory = QFileDialog.getExistingDirectory(self,
                                                     'Open the source folder',
                                                     QDir.currentPath())

        if directory:
            self.srcTree.setRootIndex(self.srcModel.index(directory))

    def browseDestFolder(self):

        directory = QFileDialog.getExistingDirectory(self,
                                                     'Open the source folder',
                                                     QDir.currentPath())

        if directory:
            self.destTree.setRootIndex(self.destModel.index(directory))

    def extract(self):

        selectionModel = self.srcTree.selectionModel()
        indexes = selectionModel.selectedRows(0)
        logFilenameList = []
        excelFilenameList = []
        for index in indexes:
            logFilename = self.srcModel.filePath(index)
            excelFilename = QDir(
                self.destModel.filePath(
                    self.destTree.rootIndex())).absoluteFilePath(
                        self.srcModel.fileName(index).replace('.log', '.xlsx'))
            logFilenameList.append(logFilename)
            excelFilenameList.append(excelFilename)
        self.extractThread = ExtractThread()
        self.extractThread.setLogFilenameList(logFilenameList)
        self.extractThread.setExcelFilenameList(excelFilenameList)
        self.extractThread.completed.connect(self.updateStatusBar)
        self.extractThread.start()

        # for index in indexes:
        #     logFilename = self.srcModel.filePath(index)
        #     excelFilename = QDir(self.destModel.filePath(self.destTree.rootIndex())).absoluteFilePath(self.srcModel.fileName(index).replace('.log', '.xlsx'))
        #     data = parseFile(logFilename)
        #     saveToExcel(excelFilename, data)

    def updateStatusBar(self, message):
        self.statusBar().showMessage(message)
예제 #6
0
class FileWidget(QWidget):
    def __init__(self):
        super().__init__()
        # QWidget部件是PyQt5所有用户界面对象的基类。他为QWidget提供默认构造函数。默认构造函数没有父类。
        # 创建一个文件系统模型
        self.file_model = QFileSystemModel()
        # 设置目录为当前工作目录
        self.file_model.setRootPath(QDir.currentPath())
        # 创建树视图,构建文件目录视图
        self.treeview = QTreeView()
        # 绑定此文件模型
        self.treeview.setModel(self.file_model)
        '''
        设置当前勾结点索引为当前工作目录
        如果想从整个文件系统根节点开始浏览视图,
        简单删掉此行即可
        '''
        self.treeview.setRootIndex(self.file_model.index(QDir.currentPath()))
        # 头部显示排序戳
        self.treeview.header().setSortIndicatorShown(True)

        # 创建右键菜单
        self.treeview.setContextMenuPolicy(Qt.CustomContextMenu)
        # point = self.treeview.pos()
        self.treeview.customContextMenuRequested.connect(self.generateMenu)
        '''
        # 底部按钮布局
        self.mkdirButton = QPushButton("Make Directory...")
        self.rmButton = QPushButton("Remove")
        buttonLayout = QHBoxLayout()
        buttonLayout.addWidget(self.mkdirButton)
        buttonLayout.addWidget(self.rmButton)
        '''
        # 文件管理界面布局
        layout = QVBoxLayout()
        layout.addWidget(self.treeview)
        # layout.addLayout(buttonLayout)

        # resize()方法调整窗口的大小。600px宽300px高
        self.resize(600, 300)
        # move()方法移动窗口在屏幕上的位置到x = 300,y = 300坐标。
        self.move(300, 300)
        # 设置窗口的标题
        self.setWindowTitle('File Manage')
        # 设置窗口的图标
        self.setWindowIcon(QIcon('File-Explorer.png'))
        self.setLayout(layout)

    # 生成右键菜单
    def generateMenu(self, position):
        # 索引默认值
        row_num = -1
        # 遍历确定行号
        for i in self.treeview.selectionModel().selection().indexes():
            row_num = i.row()
        # 保证选中有效项
        if row_num != -1:
            # 创建右键菜单
            menu = QMenu()
            # 提供删除和创建文件/文件夹选项
            item1 = menu.addAction("Delete")
            item2 = menu.addAction("NewDirectory")
            # 在光标处显示执行菜单
            action = menu.exec_(self.treeview.mapToGlobal(position))
            if action == item1:
                #弹出消息框确认此次删除操作
                res = self.msgbox()
                if res:
                    self.delete()
                else:
                    return
            elif action == item2:
                self.mkdirectory()
            else:
                return
        else:
            return

    # 删除选定文件/文件夹
    def delete(self):
        index = self.treeview.currentIndex()
        if index.isValid():
            fileInfo = self.file_model.fileInfo(index)
            if fileInfo.isDir():
                self.file_model.rmdir(index)
            else:
                self.file_model.remove(index)

    # 确认框
    def msgbox(self):
        msgBox = QMessageBox()
        msgBox.setWindowTitle("Warning")
        msgBox.setText("Delete the file/dir you selected?")
        msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        msgBox.setDefaultButton(QMessageBox.No)
        # button = QMessageBox.question("Warning", "delete the file/dir?",
        #                               QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        button = msgBox.exec_()
        if button == QMessageBox.No:
            return False
        elif button == QMessageBox.Yes:
            return True

    # 创建文件夹
    def mkdirectory(self):
        index = self.treeview.rootIndex()
        if index.isValid():
            # 弹出输入框录入文件名
            dirname, ok = QInputDialog.getText(self, "File Name",
                                               "Input an unique dir name:")
            if ok:
                self.file_model.mkdir(index, dirname)
            else:
                return

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_F3:
            self.close()