def on_copy(self):
        self.ds_model.sort(DSManagerModel.COLUMN_GROUP_DS)

        select_data_sources_dialog = QDialog(self)
        select_data_sources_dialog.setWindowTitle(self.tr("Choose source service"))
        layout = QVBoxLayout(select_data_sources_dialog)
        select_data_sources_dialog.setLayout(layout)

        list_view = QTreeView(self)
        layout.addWidget(list_view)
        list_view.setModel(self.ds_model)
        list_view.setColumnHidden(DSManagerModel.COLUMN_VISIBILITY, True)
        list_view.setAlternatingRowColors(True)
        list_view.header().setResizeMode(DSManagerModel.COLUMN_GROUP_DS, QHeaderView.ResizeToContents)
        list_view.clicked.connect(
            lambda index: select_data_sources_dialog.accept()
            if not self.ds_model.isGroup(index) and index.column() == DSManagerModel.COLUMN_GROUP_DS
            else None
        )

        if select_data_sources_dialog.exec_() == QDialog.Accepted:
            data_source = self.ds_model.data(list_view.currentIndex(), Qt.UserRole)
            data_source.id += "_copy"
            edit_dialog = DsEditDialog()
            edit_dialog.setWindowTitle(self.tr("Create service from existing"))
            edit_dialog.fill_ds_info(data_source)
            if edit_dialog.exec_() == QDialog.Accepted:
                self.feel_list()
                self.ds_model.resetModel()
    def on_copy(self):
        self.ds_model.sort(DSManagerModel.COLUMN_GROUP_DS)

        select_data_sources_dialog = QDialog(self)
        select_data_sources_dialog.resize(400, 400)
        select_data_sources_dialog.setWindowTitle(
            self.tr("Choose source service"))
        layout = QVBoxLayout(select_data_sources_dialog)
        select_data_sources_dialog.setLayout(layout)

        list_view = QTreeView(self)
        layout.addWidget(list_view)
        list_view.setModel(self.ds_model)
        #list_view.expandAll()
        list_view.setColumnHidden(DSManagerModel.COLUMN_VISIBILITY, True)
        list_view.setAlternatingRowColors(True)
        list_view.header().setResizeMode(DSManagerModel.COLUMN_GROUP_DS,
                                         QHeaderView.ResizeToContents)
        list_view.clicked.connect(
            lambda index: select_data_sources_dialog.accept() \
                if not self.ds_model.isGroup(index) and \
                    index.column() == DSManagerModel.COLUMN_GROUP_DS \
                else None
        )

        if select_data_sources_dialog.exec_() == QDialog.Accepted:
            data_source = self.ds_model.data(list_view.currentIndex(),
                                             Qt.UserRole)
            data_source.id += "_copy"
            edit_dialog = DsEditDialog()
            edit_dialog.setWindowTitle(self.tr('Create service from existing'))
            edit_dialog.fill_ds_info(data_source)
            if edit_dialog.exec_() == QDialog.Accepted:
                self.feel_list()
                self.ds_model.resetModel()
Beispiel #3
0
class AddToProject(QDialog):
    """Dialog to let the user choose one of the folders from the opened proj"""
    def __init__(self, projects, parent=None):
        super(AddToProject, self).__init__(parent)
        # pathProjects must be a list
        self._projects = projects
        self.setWindowTitle("XX")
        self.pathSelected = ''
        vbox = QVBoxLayout(self)

        hbox = QHBoxLayout()
        self._list = QListWidget()
        for project in self._projects:
            self._list.addItem(project['name'])

        # self._list.setCurrentRow(0)
        self._tree = QTreeView()
        # self._tree.header().setHidden(True)
        # self._tree.setSelectionMode(QTreeView.SingleSelection)
        # self._tree.setAnimated(True)
        self.load_tree(self._projects[0])
        hbox.addWidget(self._list)
        hbox.addWidget(self._tree)
        vbox.addLayout(hbox)

        hbox2 = QHBoxLayout()
        btnAdd = QPushButton("XX")
        btnCancel = QPushButton("XX")
        hbox2.addWidget(btnCancel)
        hbox2.addWidget(btnAdd)
        vbox.addLayout(hbox2)

        self.connect(btnCancel, SIGNAL("clicked()"), self.close)
        self.connect(btnAdd, SIGNAL("clicked()"), self._select_path)
        self.connect(
            self._list,
            SIGNAL("currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)"),
            self._project_changed)

    def _project_changed(self, item, previous):
        # FIXME, this is not being called, at least in osx
        for each_project in self._projects:
            if each_project.name == item.text():
                self.load_tree(each_project)

    def load_tree(self, project):
        """Load the tree view on the right based on the project selected."""
        qfsm = QFileSystemModel()
        qfsm.setRootPath(project['path'])
        load_index = qfsm.index(qfsm.rootPath())
        # qfsm.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
        # qfsm.setNameFilterDisables(False)
        # pext = ["*{0}".format(x) for x in project['extensions']]
        # qfsm.setNameFilters(pext)

        self._tree.setModel(qfsm)
        self._tree.setRootIndex(load_index)

        t_header = self._tree.header()
        # t_header.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
        # t_header.setResizeMode(0, QHeaderView.Stretch)
        # t_header.setStretchLastSection(False)
        # t_header.setClickable(True)
        #

        # self._tree.hideColumn(1)  # Size
        # self._tree.hideColumn(2)  # Type
        # self._tree.hideColumn(3)  # Modification date

        # FIXME: Changing the name column's title requires some magic
        # Please look at the project tree

    def _select_path(self):
        """Set pathSelected to the folder selected in the tree."""
        path = self._tree.model().filePath(self._tree.currentIndex())
        if path:
            self.pathSelected = path
            self.close()
Beispiel #4
0
class _LocatorDialog(QDialog):
    """Locator widget and implementation
    """
    def __init__(self, parent, commandClasses):
        QDialog.__init__(self, parent)
        self._terminated = False
        self._commandClasses = commandClasses

        self._createUi()

        self._loadingTimer = QTimer(self)
        self._loadingTimer.setSingleShot(True)
        self._loadingTimer.setInterval(200)
        self._loadingTimer.timeout.connect(self._applyLoadingCompleter)

        self._completerLoaderThread = _CompleterLoaderThread(self)

        self.finished.connect(self._terminate)

        self._command = None
        self._updateCurrentCommand()

    def _createUi(self):
        self.setWindowTitle(core.project().path() or 'Locator')

        self.setLayout(QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.layout().setSpacing(1)

        biggerFont = self.font()
        biggerFont.setPointSizeF(biggerFont.pointSizeF() * 2)
        self.setFont(biggerFont)

        self._edit = _CompletableLineEdit(self)
        self._edit.updateCurrentCommand.connect(self._updateCurrentCommand)
        self._edit.enterPressed.connect(self._onEnterPressed)
        self._edit.installEventFilter(self)  # catch Up, Down
        self.layout().addWidget(self._edit)
        self.setFocusProxy(self._edit)

        self._table = QTreeView(self)
        self._table.setFont(biggerFont)
        self._model = _CompleterModel()
        self._table.setModel(self._model)
        self._table.setItemDelegate(HTMLDelegate(self._table))
        self._table.setRootIsDecorated(False)
        self._table.setHeaderHidden(True)
        self._table.clicked.connect(self._onItemClicked)
        self._table.setAlternatingRowColors(True)
        self._table.installEventFilter(
            self)  # catch focus and give to the edit
        self.layout().addWidget(self._table)

        width = QFontMetrics(self.font()).width('x' *
                                                64)  # width of 64 'x' letters
        self.resize(width, width * 0.62)

    def _terminate(self):
        if not self._terminated:
            if self._command is not None:
                self._command.terminate()
                self._command = None

            self._edit.terminate()

            self._completerLoaderThread.terminate()
            core.workspace().focusCurrentDocument()
            self._terminated = True

    def _updateCurrentCommand(self):
        """Try to parse line edit text and set current command
        """
        if self._terminated:
            return

        newCommand = self._parseCurrentCommand()

        if newCommand is not self._command:
            if self._command is not None:
                self._command.updateCompleter.disconnect(
                    self._updateCompletion)
                self._command.terminate()

            self._command = newCommand
            if self._command is not None:
                self._command.updateCompleter.connect(self._updateCompletion)

        self._updateCompletion()

    def _updateCompletion(self):
        """User edited text or moved cursor. Update inline and TreeView completion
        """
        if self._command is not None:
            completer = self._command.completer()

            if completer is not None and completer.mustBeLoaded:
                self._loadingTimer.start()
                self._completerLoaderThread.loadCompleter(
                    self._command, completer)
            else:
                self._applyCompleter(self._command, completer)
        else:
            self._applyCompleter(None, _HelpCompleter(self._commandClasses))

    def _applyLoadingCompleter(self):
        """Set 'Loading...' message
        """
        self._applyCompleter(None, StatusCompleter('<i>Loading...</i>'))

    def onCompleterLoaded(self, command, completer):
        """The method called from _CompleterLoaderThread when the completer is ready
        This code works in the GUI thread
        """
        self._applyCompleter(command, completer)

    def _applyCompleter(self, command, completer):
        """Apply completer. Called by _updateCompletion or by thread function when Completer is constructed
        """
        self._loadingTimer.stop()

        if command is not None:
            command.onCompleterLoaded(completer)

        if completer is None:
            completer = _HelpCompleter([command])

        if self._edit.cursorPosition() == len(
                self._edit.text()):  # if cursor at the end of text
            self._edit.setInlineCompletion(completer.inline())

        self._model.setCompleter(completer)
        if completer.columnCount() > 1:
            self._table.resizeColumnToContents(0)
            self._table.setColumnWidth(0,
                                       self._table.columnWidth(0) +
                                       20)  # 20 px spacing between columns

        selItem = completer.autoSelectItem()
        if selItem:
            index = self._model.createIndex(selItem[0], selItem[1])
            self._table.setCurrentIndex(index)

    def _onItemClicked(self, index):
        """Item in the TreeView has been clicked.
        Open file, if user selected it
        """
        if self._command is not None:
            fullText = self._model.completer.getFullText(index.row())
            if fullText is not None:
                self._command.onItemClicked(fullText)
                if self._tryExecCurrentCommand():
                    self.accept()
                    return
                else:
                    self._edit.setText(self._command.lineEditText())
                    self._updateCurrentCommand()

        self._edit.setFocus()

    def _onEnterPressed(self):
        """User pressed Enter or clicked item. Execute command, if possible
        """
        if self._table.currentIndex().isValid():
            self._onItemClicked(self._table.currentIndex())
        else:
            self._tryExecCurrentCommand()

    def _tryExecCurrentCommand(self):
        if self._command is not None and self._command.isReadyToExecute():
            self._command.execute()
            self.accept()
            return True
        else:
            return False

    def _chooseCommand(self, words):
        for cmd in self._commandClasses:
            if cmd.command == words[0]:
                return cmd, words[1:]

        isPath = words and (words[0].startswith('/')
                            or words[0].startswith('./')
                            or words[0].startswith('../')
                            or words[0].startswith('~/')
                            or words[0][1:3] == ':\\' or words[0][1:3] == ':/')
        isNumber = len(words) == 1 and all([c.isdigit() for c in words[0]])

        def matches(cmd):
            if isPath:
                return cmd.isDefaultPathCommand
            elif isNumber:
                return cmd.isDefaultNumericCommand
            else:
                return cmd.isDefaultCommand

        for cmd in self._commandClasses:
            if matches(cmd):
                return cmd, words

    def _parseCurrentCommand(self):
        """ Parse text and try to get (command, completable word index)
        Return None if failed to parse
        """
        # Split line
        text = self._edit.commandText()
        words = splitLine(text)
        if not words:
            return None

        # Find command
        cmdClass, args = self._chooseCommand(words)

        if isinstance(self._command, cmdClass):
            command = self._command
        else:
            command = cmdClass()

        # Try to make command object
        try:
            command.setArgs(args)
        except InvalidCmdArgs:
            return None
        else:
            return command

    def eventFilter(self, obj, event):
        if obj is self._edit:
            if event.type() == QEvent.KeyPress and \
               event.key() in (Qt.Key_Up, Qt.Key_Down, Qt.Key_PageUp, Qt.Key_PageDown):
                return self._table.event(event)
        elif obj is self._table:
            if event.type() == QEvent.FocusIn:
                self._edit.setFocus()
                return True

        return False
class AddToProject(QDialog):
    """Dialog to let the user choose one of the folders from the opened proj"""

    def __init__(self, projects, parent=None):
        super(AddToProject, self).__init__(parent)
        #pathProjects must be a list
        self._projects = projects
        self.setWindowTitle(translations.TR_ADD_FILE_TO_PROJECT)
        self.pathSelected = ''
        vbox = QVBoxLayout(self)

        hbox = QHBoxLayout()
        self._list = QListWidget()
        for project in self._projects:
            self._list.addItem(project.name)
        self._list.setCurrentRow(0)
        self._tree = QTreeView()
        #self._tree.header().setHidden(True)
        self._tree.setSelectionMode(QTreeView.SingleSelection)
        self._tree.setAnimated(True)
        self.load_tree(self._projects[0])
        hbox.addWidget(self._list)
        hbox.addWidget(self._tree)
        vbox.addLayout(hbox)

        hbox2 = QHBoxLayout()
        btnAdd = QPushButton(translations.TR_ADD_HERE)
        btnCancel = QPushButton(translations.TR_CANCEL)
        hbox2.addWidget(btnCancel)
        hbox2.addWidget(btnAdd)
        vbox.addLayout(hbox2)

        self.connect(btnCancel, SIGNAL("clicked()"), self.close)
        self.connect(btnAdd, SIGNAL("clicked()"), self._select_path)

    def load_tree(self, project):
        """Load the tree view on the right based on the project selected."""
        qfsm = QFileSystemModel()
        #FIXME it's not loading the proper folder, just the root /
        qfsm.setRootPath(project.path)
        qfsm.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
        qfsm.setNameFilterDisables(False)
        pext = ["*{0}".format(x) for x in project.extensions]
        qfsm.setNameFilters(pext)
        self._tree.setModel(qfsm)

        t_header = self._tree.header()
        t_header.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
        t_header.setResizeMode(0, QHeaderView.Stretch)
        t_header.setStretchLastSection(False)
        t_header.setClickable(True)

        self._tree.hideColumn(1)  # Size
        self._tree.hideColumn(2)  # Type
        self._tree.hideColumn(3)  # Modification date

    def _select_path(self):
        """Set pathSelected to the folder selected in the tree."""
        path = self._tree.model().filePath(self._tree.currentIndex())
        if path:
            self.pathSelected = path
            self.close()
Beispiel #6
0
class NavigatorDock(DockWidget):
    def __init__(self):
        DockWidget.__init__(self, core.mainWindow(), '&Navigator',
                            QIcon(':/enkiicons/goto.png'), "Alt+N")

        self._tags = []

        self._tree = QTreeView(self)
        self._tree.installEventFilter(self)
        self._tree.setHeaderHidden(True)
        self.setFocusProxy(self._tree)

        self._filterEdit = LineEdit(self)
        self._filterEdit.setClearButtonVisible(True)
        self._filterEdit.textEdited.connect(self._applyFilter)
        self._filterEdit.clearButtonClicked.connect(self._applyFilter)
        self._filterEdit.clearButtonClicked.connect(self._tree.setFocus)
        self._filterEdit.clearButtonClicked.connect(self._hideFilter)
        self._filterEdit.installEventFilter(self)

        self._displayWidget = QWidget(self)
        layout = QVBoxLayout(self._displayWidget)
        layout.addWidget(self._tree)
        layout.addWidget(self._filterEdit)
        layout.setContentsMargins(0, 0, 0, 0)

        self.setWidget(self._displayWidget)

        self._tagModel = _TagModel(self._tree)
        self._tagModel.jumpToTagDone.connect(self._hideFilter)

        self._tree.setModel(self._tagModel)
        self._tree.activated.connect(self._tagModel.onActivated)
        self._tree.clicked.connect(self._tagModel.onActivated)
        self._tagModel.modelAboutToBeReset.connect(self._onModelAboutToBeReset)
        self._tagModel.modelReset.connect(self._onModelReset)
        self._currentTagPath = None

        self._errorLabel = None

        self._installed = False

    def install(self):
        if not self._installed:
            core.mainWindow().addDockWidget(Qt.RightDockWidgetArea, self)
            core.actionManager().addAction("mView/aNavigator",
                                           self.showAction())
            self._installed = True

    def remove(self):
        if self._installed:
            core.mainWindow().removeDockWidget(self)
            core.actionManager().removeAction("mView/aNavigator")
            self.hide()
            self._installed = False

    def setTags(self, tags):
        self._tags = tags
        self._setFilteredTags(tags)
        self._hideFilter()

        if self.widget() is not self._displayWidget:
            self.setWidget(self._displayWidget)
            self._displayWidget.show()
        if self._errorLabel is not None:
            self._errorLabel.hide()

    def _setFilteredTags(self, tags):
        self._tagModel.setTags(tags)

    def onError(self, error):
        self._displayWidget.hide()
        if self._errorLabel is None:
            self._errorLabel = QLabel(self)
            self._errorLabel.setWordWrap(True)

        self._errorLabel.setText(error)

        if not self.widget() is self._errorLabel:
            self.setWidget(self._errorLabel)
            self._errorLabel.show()
            self._displayWidget.hide()

    def _onModelAboutToBeReset(self):
        currIndex = self._tree.currentIndex()
        self._currentTagPath = self._tagModel.tagPathForIndex(
            currIndex) if currIndex.isValid() else None

    def _onModelReset(self):
        self._tree.expandAll()

        # restore current item
        if self._currentTagPath is not None:
            index = self._tagModel.indexForTagPath(self._currentTagPath)
            if index.isValid():
                self._tree.setCurrentIndex(index)

    def eventFilter(self, object_, event):
        if object_ is self._tree:
            if event.type() == QEvent.KeyPress:
                if event.key() == Qt.Key_Backspace:
                    if event.modifiers() == Qt.ControlModifier:
                        self._onTreeCtrlBackspace()
                    else:
                        self._onTreeBackspace()
                    return True
                elif event.text() and \
                     (event.text().isalnum() or event.text() == '_'):
                    self._onTreeTextTyped(event.text())
                    return True
        elif object_ is self._filterEdit:
            if event.type() == QEvent.KeyPress:
                if event.key() in (Qt.Key_Up, Qt.Key_Down):
                    self._tree.setFocus()
                    self._tree.event(event)
                    return True
                elif event.key() in (Qt.Key_Enter, Qt.Key_Return):
                    currIndex = self._tree.currentIndex()
                    if currIndex.isValid():
                        self._tagModel.onActivated(currIndex)

        return DockWidget.eventFilter(self, object_, event)

    def _hideFilter(self):
        hadText = self._filterEdit.text() != ''
        self._filterEdit.clear()
        self._filterEdit.hide()
        if hadText:
            self._applyFilter()

    def _applyFilter(self):
        text = self._filterEdit.text()
        if text:
            if not text.startswith('*'):
                text = '*' + text
            if not text.endswith('*'):
                text = text + '*'

            wildcard = text.lower()

            filteredTags = _filterTags(wildcard, self._tags)

            self._setFilteredTags(filteredTags)
            self._tree.expandAll()
            if filteredTags:
                firstMatchingTag = _findFirstMatching(wildcard, filteredTags)
                path = _tagPath(firstMatchingTag)
                index = self._tagModel.indexForTagPath(path)
                self._tree.setCurrentIndex(index)
        else:
            self._setFilteredTags(self._tags)

        if text:
            self._filterEdit.show()
        elif not self._filterEdit.hasFocus():
            self._hideFilter()

    def _onTreeTextTyped(self, text):
        self._filterEdit.setText(self._filterEdit.text() + text)
        self._applyFilter()

    def _onTreeBackspace(self):
        text = self._filterEdit.text()
        if text:
            self._filterEdit.setText(text[:-1])
            self._applyFilter()

    def _onTreeCtrlBackspace(self):
        self._hideFilter()
        self._applyFilter()
Beispiel #7
0
class EncryptDialog(QDialog):
    def __init__(self):
        self.techniquesClass = {
            'caesar cipher': caesarCipher,
            'mono alphabetic cipher': monoAlphabeticCipher,
            'vigenere cipher': vigenereCipher,
            'vernan cipher': vernanCipher,
            'one time pad': oneTimePad
        }

        self.rowsview = []
        self.filesview = []
        self.techniques = []

        QDialog.__init__(self)
        self.setWindowTitle("CryptoSystems")
        self.resize(1024, 600)
        self.setMinimumSize(QSize(1024, 600))
        self.setMaximumSize(QSize(1024, 600))

        self.checkBox_2 = QCheckBox(self)
        self.checkBox_2.setGeometry(QRect(620, 10, 130, 20))
        self.checkBox_2.setText('Select All')
        self.checkBox_2.clicked.connect(self.__selectAllFiles)

        self.treeView = QTreeView(self)
        self.treeView.setGeometry(QRect(10, 10, 230, 580))
        self.treeView.setObjectName("treeView")

        self.fileSystemModel = QFileSystemModel(self.treeView)
        self.fileSystemModel.setReadOnly(False)

        self.fileSystemModel.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
        root = self.fileSystemModel.setRootPath("/")
        self.treeView.setModel(self.fileSystemModel)
        self.treeView.setRootIndex(root)
        self.treeView.hideColumn(1)
        self.treeView.hideColumn(2)
        self.treeView.hideColumn(3)
        self.treeView.clicked.connect(self.__eventDirectoryChanged)

        self.mygroupbox = QGroupBox(self)
        self.mygroupbox.setGeometry(QRect(0, 0, 1000, 1000))
        self.myform = QFormLayout()
        for j in list(range(100)):
            horizontalLayout = QHBoxLayout()
            self.myform.addRow(horizontalLayout)
            self.rowsview.append(horizontalLayout)

        self.mygroupbox.setLayout(self.myform)
        scroll = QScrollArea(self)
        scroll.setWidget(self.mygroupbox)
        scroll.setWidgetResizable(True)
        scroll.setGeometry(QRect(250, 30, 500, 580))
        scroll.setWidgetResizable(True)

        self.label_4 = QLabel(self)
        self.label_4.setGeometry(QRect(780, 30, 31, 16))
        self.label_4.setPixmap(QPixmap("images/key.png"))
        self.label_4.setScaledContents(True)

        self.lineEdit = QLineEdit(self)
        self.lineEdit.setGeometry(QRect(820, 30, 180, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit.setPlaceholderText(_fromUtf8('write your password'))
        self.lineEdit.setEchoMode(QLineEdit.Password)

        self.techniquesGroup = QGroupBox(self)
        self.tecniquesform = QFormLayout()
        self.techniquesGroup.setLayout(self.tecniquesform)

        self.techniquesScroll = QScrollArea(self)
        self.techniquesScroll.setGeometry(QRect(770, 100, 230, 300))
        self.techniquesScroll.setWidget(self.techniquesGroup)
        self.techniquesScroll.setWidgetResizable(True)

        self.rowsTechiques = []
        for i in list(range(8)):
            horizontalLayout = QHBoxLayout()
            self.tecniquesform.addRow(horizontalLayout)
            self.rowsTechiques.append(horizontalLayout)

        techniquesCombo = QComboBox()
        techniquesCombo.setGeometry(QRect(10, 50, 171, 22))
        techniquesCombo.addItems(self.techniquesClass.keys())
        self.techniques.append(techniquesCombo)
        self.rowsTechiques[0].addWidget(techniquesCombo)
        self.techniquesNumber = 1

        self.addTechnique = QPushButton()
        self.addTechnique.setGeometry(QRect(90, 90, 31, 21))
        self.addTechnique.setFixedSize(31, 21)
        self.addTechnique.setText('+')
        self.connect(self.addTechnique, SIGNAL("clicked()"),
                     self.__eventAddTechnique)
        self.rowsTechiques[len(self.rowsTechiques) - 1].addWidget(
            self.addTechnique)

        self.okButton = QPushButton(self)
        self.okButton.setGeometry(QRect(920, 560, 80, 20))
        self.okButton.setText('Start...')
        self.connect(self.okButton, SIGNAL("clicked()"),
                     self.__eventInitEncryption)

    def __eventAddTechnique(self):
        techniquesCombo = QComboBox()
        techniquesCombo.setGeometry(QRect(10, 50, 171, 22))
        techniquesCombo.addItems(self.techniquesClass.keys())
        self.techniques.append(techniquesCombo)
        self.rowsTechiques[self.techniquesNumber].addWidget(techniquesCombo)
        self.techniquesNumber = self.techniquesNumber + 1
        if ((len(self.rowsTechiques) - 1) == self.techniquesNumber):
            self.addTechnique.setEnabled(False)

    def __eventDirectoryChanged(self):
        index = self.treeView.currentIndex()
        self.__changeDirectory(self.fileSystemModel.filePath(index))

    def __changeDirectory(self, path):
        for c in self.filesview:
            c.setParent(None)
            c.deleteLater()
        self.filesview = []
        self.checkBox_2.setChecked(False)

        self.progressBars = {}
        for f in self.__getFiles(path):
            try:
                group = QGroupBox(f, self)
                group.setGeometry(QRect(20, 20, 100, 150))
                group.setCheckable(True)
                group.setChecked(False)
                group.setFixedSize(100, 150)
                group.setFlat(True)
                group.setToolTip(f)

                label = QLabel(group)
                label.setScaledContents(True)
                label.setGeometry(QRect(5, 25, 90, 90))
                label.setToolTip(f)

                progressBar = QProgressBar(group)
                progressBar.setGeometry(QRect(0, 70, 111, 10))
                progressBar.setProperty("value", 0)
                progressBar.setTextVisible(False)
                progressBar.setToolTip('0%')
                progressBar.setVisible(False)
                self.progressBars[f] = progressBar

                self.filesview.append(group)
                from os.path import isfile
                if isfile(path + '/' + f):
                    ext = f.split('.')[-1]
                    if isfile('icons/' + ext.lower() + '.png'):
                        label.setPixmap(
                            QPixmap('icons/' + ext.lower() + '.png'))
                    else:
                        label.setPixmap(QPixmap('icons/default.png'))
                else:
                    label.setPixmap(QPixmap('icons/folder.png'))
                self.connect(group, SIGNAL("clicked()"), self.__deselectFile)
            except ValueError:
                pass

        i = 0
        for x in list(range(len(self.filesview))):
            if (x % 4) == 0:
                i = i + 1
            self.rowsview[i].addWidget(self.filesview[x])

    def __selectAllFiles(self):
        for o in self.filesview:
            o.setChecked(self.checkBox_2.isChecked())

    def __deselectFile(self):
        #print 'deselect'
        self.checkBox_2.setChecked(False)

    def __arrozconpollo(self):
        self.__obtainSelectedFIles()

    def __obtainSelectedFIles(self):
        files = []
        for o in self.filesview:
            if o.isChecked():
                files.append(str(o.title()))
                self.progressBars[str(o.title())].setVisible(True)
        return files

    def __getFiles(self, path):
        from os import listdir
        from os.path import isfile

        f = []

        for base in listdir(path):
            try:
                if isfile(path + '/' + base):
                    f.append(base)
            except ValueError:
                pass
        f.sort()
        return f

    def __eventInitEncryption(self):
        if len(self.__obtainSelectedFIles()) == 0:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("You must specify the files you want to encrypt")
            msg.setWindowTitle("CryptoSystems")
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()
            return

        if str(self.lineEdit.text()).strip() == '':
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("You must specify a key")
            msg.setWindowTitle("CryptoSystems")
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()
            return

        self.okButton.setEnabled(False)
        self.techniquesGroup.setEnabled(False)
        self.lineEdit.setEnabled(False)

        index = self.treeView.currentIndex()

        path = self.fileSystemModel.filePath(index)
        selectedFiles = self.__obtainSelectedFIles()

        from os.path import getsize
        blockSize = 4096

        from hashlib import md5
        Hash = md5()
        Hash.update(str(self.lineEdit.text()))
        key = Hash.hexdigest()

        for f in selectedFiles:

            f_in = open(path + '/' + f, 'rb')
            f_out = open(
                path + '/' + reduceMd5(checksum(path + '/' + f)) + '.cry',
                'wb')

            f_out.write('CRYOGENESIS' + unhexlify('00') + 'ARCHIVE' +
                        unhexlify('01'))

            header_list = ''
            techniquesObjects = []
            for t in self.techniques:
                header_list = header_list + t.currentText() + ':'
                techniquesObjects.append(self.techniquesClass[str(
                    t.currentText())](key))

            file_header = str('header|' + str(f_in.name.split('/')[-1]) + '|' +
                              str(header_list) + '|' +
                              str(checksum(path + '/' + f)))

            aes = AES(key)
            f_out.write(aes.encrypt(file_header))
            f_out.write(unhexlify('02'))

            in_size = getsize(path + '/' + f)
            in_progress = 0.0

            block = f_in.read(blockSize)
            while (block):
                block_c = block
                for t in techniquesObjects:
                    block_c = t.encrypt(block_c)
                f_out.write(block_c)
                in_progress = in_progress + blockSize

                progress = (in_progress / in_size) * 100
                #print progress
                self.progressBars[str(f)].setProperty("value", int(progress))
                self.progressBars[str(f)].setToolTip(str(progress) + '%')
                block = f_in.read(blockSize)

            f_in.close()
            f_out.close()

        msg = QMessageBox()

        msg.setIcon(QMessageBox.Information)

        msg.setText("Encryption has successfully concluded")
        msg.setWindowTitle("CryptoSystems")
        msg.setStandardButtons(QMessageBox.Ok)
        msg.exec_()

        self.hide()
Beispiel #8
0
class DecryptDialog(QDialog):
    def __init__(self):
        self.techniquesClass = {
            'caesar cipher': caesarCipher,
            'mono alphabetic cipher': monoAlphabeticCipher,
            'vigenere cipher': vigenereCipher,
            'vernan cipher': vernanCipher,
            'one time pad': oneTimePad
        }

        self.rowsview = []
        self.filesview = []
        #self.techniques = []

        QDialog.__init__(self)
        self.setWindowTitle("Desencriptador de Cryogenesis Systems.")
        self.resize(1024, 600)
        self.setMinimumSize(QSize(1024, 600))
        self.setMaximumSize(QSize(1024, 600))

        self.checkBox_2 = QCheckBox(self)
        self.checkBox_2.setGeometry(QRect(620, 10, 130, 20))
        self.checkBox_2.setText('seleccionar todos')
        self.checkBox_2.clicked.connect(self.__selectAllFiles)

        self.treeView = QTreeView(self)
        self.treeView.setGeometry(QRect(10, 10, 230, 580))
        self.treeView.setObjectName("treeView")

        self.fileSystemModel = QFileSystemModel(self.treeView)
        self.fileSystemModel.setReadOnly(False)

        self.fileSystemModel.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot)
        root = self.fileSystemModel.setRootPath("/")
        self.treeView.setModel(self.fileSystemModel)
        self.treeView.setRootIndex(root)
        self.treeView.hideColumn(1)
        self.treeView.hideColumn(2)
        self.treeView.hideColumn(3)
        self.treeView.clicked.connect(self.__eventDirectoryChanged)

        self.mygroupbox = QGroupBox(self)
        self.mygroupbox.setGeometry(QRect(0, 0, 1000, 1000))
        self.myform = QFormLayout()
        for j in list(range(100)):
            horizontalLayout = QHBoxLayout()
            self.myform.addRow(horizontalLayout)
            self.rowsview.append(horizontalLayout)

        self.mygroupbox.setLayout(self.myform)
        scroll = QScrollArea(self)
        scroll.setWidget(self.mygroupbox)
        scroll.setWidgetResizable(True)
        scroll.setGeometry(QRect(250, 30, 500, 580))
        scroll.setWidgetResizable(True)

        self.label_4 = QLabel(self)
        self.label_4.setGeometry(QRect(780, 30, 31, 16))
        self.label_4.setPixmap(QPixmap("images/key.png"))
        self.label_4.setScaledContents(True)

        self.lineEdit = QLineEdit(self)
        self.lineEdit.setGeometry(QRect(820, 30, 180, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit.setPlaceholderText(_fromUtf8('escriba su contraseña'))
        self.lineEdit.setEchoMode(QLineEdit.Password)

        self.okButton = QPushButton(self)
        self.okButton.setGeometry(QRect(920, 560, 80, 20))
        self.okButton.setText('Iniciar...')
        self.connect(self.okButton, SIGNAL("clicked()"),
                     self.__eventInitDecryption)

    def __eventDirectoryChanged(self):
        index = self.treeView.currentIndex()
        self.__changeDirectory(self.fileSystemModel.filePath(index))

    def __changeDirectory(self, path):
        for c in self.filesview:
            c.setParent(None)
            c.deleteLater()
        self.filesview = []
        self.checkBox_2.setChecked(False)

        self.progressBars = {}
        for f in self.__getFiles(path):
            try:
                group = QGroupBox(f, self)
                group.setGeometry(QRect(20, 20, 100, 150))
                group.setCheckable(True)
                group.setChecked(False)
                group.setFixedSize(100, 150)
                group.setFlat(True)
                group.setToolTip(f)

                label = QLabel(group)
                label.setScaledContents(True)
                label.setGeometry(QRect(5, 25, 90, 90))
                label.setToolTip(f)

                progressBar = QProgressBar(group)
                progressBar.setGeometry(QRect(0, 70, 111, 10))
                progressBar.setProperty("value", 0)
                progressBar.setTextVisible(False)
                progressBar.setToolTip('0%')
                progressBar.setVisible(False)
                self.progressBars[f] = progressBar

                self.filesview.append(group)
                from os.path import isfile
                if isfile(path + '/' + f):
                    ext = f.split('.')[-1]
                    if isfile('icons/' + ext.lower() + '.png'):
                        label.setPixmap(
                            QPixmap('icons/' + ext.lower() + '.png'))
                    else:
                        label.setPixmap(QPixmap('icons/default.png'))
                else:
                    label.setPixmap(QPixmap('icons/folder.png'))
                self.connect(group, SIGNAL("clicked()"), self.__deselectFile)
            except ValueError:
                pass

        i = 0
        for x in list(range(len(self.filesview))):
            if (x % 4) == 0:
                i = i + 1
            self.rowsview[i].addWidget(self.filesview[x])

    def __selectAllFiles(self):
        for o in self.filesview:
            o.setChecked(self.checkBox_2.isChecked())

    def __deselectFile(self):
        #print 'deselect'
        self.checkBox_2.setChecked(False)

    def __arrozconpollo(self):
        self.__obtainSelectedFIles()

    def __obtainSelectedFIles(self):
        files = []
        for o in self.filesview:
            if o.isChecked():
                files.append(str(o.title()))
                self.progressBars[str(o.title())].setVisible(True)
        return files

    def __getFiles(self, path):
        from os import listdir
        from os.path import isfile

        f = []

        for base in listdir(path):
            try:
                if isfile(path + '/' + base) and base.split('.')[-1] == 'cry':
                    f.append(base)
            except ValueError:
                pass
        f.sort()
        return f

    def __eventInitDecryption(self):
        if len(self.__obtainSelectedFIles()) == 0:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText(
                "Debes especificar los archivos que quieres desencriptar")
            msg.setWindowTitle("Cryosystems")
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()
            return

        if str(self.lineEdit.text()).strip() == '':
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setText("Debes especificar una clave")
            msg.setWindowTitle("Cryosystems")
            msg.setStandardButtons(QMessageBox.Ok)
            msg.exec_()
            return

        self.okButton.setEnabled(False)
        self.lineEdit.setEnabled(False)

        index = self.treeView.currentIndex()

        path = self.fileSystemModel.filePath(index)
        selectedFiles = self.__obtainSelectedFIles()

        from hashlib import md5
        Hash = md5()
        Hash.update(str(self.lineEdit.text()))
        key = Hash.hexdigest()

        errors = 0

        from os.path import getsize
        blockSize = 4096
        for f in selectedFiles:

            f_in = open(path + '/' + f, 'rb')
            print path + '/' + f

            header = ''
            if (f_in.read(20) == ('CRYOGENESIS' + unhexlify('00') + 'ARCHIVE' +
                                  unhexlify('01'))):
                while (True):
                    c = f_in.read(1)
                    if c == unhexlify('02'):
                        break
                    else:
                        header = header + c
            else:
                print 'esto no es un archivo cifradodo de Cryogenesis Systems'

            #print key
            aes = AES(key)
            #print aes.decrypt(header)
            header_sections = aes.decrypt(header).split('|')

            if header_sections[0] != 'header':
                msg = QMessageBox()
                msg.setIcon(QMessageBox.Critical)
                msg.setText("La clave no es correcta para el archivo:" + f)
                msg.setWindowTitle("Cryosystems")
                msg.setStandardButtons(QMessageBox.Ok)
                msg.exec_()
                errors = errors + 1
                continue

            f_out = open(path + '/' + header_sections[1], 'wb')

            techniques = header_sections[2].split(':')[:-1]

            techniquesObjects = []

            for t in techniques:
                techniquesObjects.append(self.techniquesClass[t](key))
            techniquesObjects.reverse()

            in_size = getsize(path + '/' + f)
            in_progress = 0.0

            block = f_in.read(blockSize)
            while (block):
                block_p = block
                for t in techniquesObjects:
                    block_p = t.decrypt(block_p)
                f_out.write(block_p)
                in_progress = in_progress + blockSize
                progress = (in_progress / in_size) * 100
                self.progressBars[str(f)].setProperty("value", int(progress))
                self.progressBars[str(f)].setToolTip(str(progress) + '%')
                block = f_in.read(blockSize)

            f_in.close()
            f_out.close()

            if (checksum(path + '/' + header_sections[1]) !=
                    header_sections[3]):
                msg = QMessageBox()
                msg.setIcon(QMessageBox.Critical)
                msg.setText("El archivo" + f + 'se ha corrompido')
                msg.setWindowTitle("Cryosystems")
                msg.setStandardButtons(QMessageBox.Ok)
                msg.exec_()
                errors = errors + 1
                from os import remove
                remove(header_sections[1])

        msg = QMessageBox()
        msg.setWindowTitle("Cryosystems")
        msg.setStandardButtons(QMessageBox.Ok)

        if (errors == 0):
            msg.setIcon(QMessageBox.Information)
            msg.setText("La desencriptacion ha concluido exitosamente")
        else:
            msg.setIcon(QMessageBox.Warning)
            msg.setText("La desencriptacion ha concluido con " + str(errors) +
                        ' error(es)')

        msg.exec_()
        self.hide()
Beispiel #9
0
class Widget(QWidget):
    def __init__(self, panel):
        super(Widget, self).__init__(panel)
        
        layout = QVBoxLayout()
        self.setLayout(layout)
        layout.setSpacing(0)
        
        self.searchEntry = SearchLineEdit()
        self.treeView = QTreeView(contextMenuPolicy=Qt.CustomContextMenu)
        self.textView = QTextBrowser()
        
        applyButton = QToolButton(autoRaise=True)
        editButton = QToolButton(autoRaise=True)
        addButton = QToolButton(autoRaise=True)
        self.menuButton = QPushButton(flat=True)
        menu = QMenu(self.menuButton)
        self.menuButton.setMenu(menu)
        
        splitter = QSplitter(Qt.Vertical)
        top = QHBoxLayout()
        layout.addLayout(top)
        splitter.addWidget(self.treeView)
        splitter.addWidget(self.textView)
        layout.addWidget(splitter)
        splitter.setSizes([200, 100])
        splitter.setCollapsible(0, False)
        
        top.addWidget(self.searchEntry)
        top.addWidget(applyButton)
        top.addSpacing(10)
        top.addWidget(addButton)
        top.addWidget(editButton)
        top.addWidget(self.menuButton)
        
        # action generator for actions added to search entry
        def act(slot, icon=None):
            a = QAction(self, triggered=slot)
            self.addAction(a)
            a.setShortcutContext(Qt.WidgetWithChildrenShortcut)
            icon and a.setIcon(icons.get(icon))
            return a
        
        # hide if ESC pressed in lineedit
        a = act(self.slotEscapePressed)
        a.setShortcut(QKeySequence(Qt.Key_Escape))
        
        # import action
        a = self.importAction = act(self.slotImport, 'document-open')
        menu.addAction(a)
        
        # export action
        a = self.exportAction = act(self.slotExport, 'document-save-as')
        menu.addAction(a)
        
        # apply button
        a = self.applyAction = act(self.slotApply, 'edit-paste')
        applyButton.setDefaultAction(a)
        menu.addSeparator()
        menu.addAction(a)
        
        # add button
        a = self.addAction_ = act(self.slotAdd, 'list-add')
        a.setShortcut(QKeySequence(Qt.Key_Insert))
        addButton.setDefaultAction(a)
        menu.addSeparator()
        menu.addAction(a)
        
        # edit button
        a = self.editAction = act(self.slotEdit, 'document-edit')
        a.setShortcut(QKeySequence(Qt.Key_F2))
        editButton.setDefaultAction(a)
        menu.addAction(a)
        
        # set shortcut action
        a = self.shortcutAction = act(self.slotShortcut, 'preferences-desktop-keyboard-shortcuts')
        menu.addAction(a)
        
        # delete action
        a = self.deleteAction = act(self.slotDelete, 'list-remove')
        a.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_Delete))
        menu.addAction(a)
        
        # restore action
        a = self.restoreAction = act(self.slotRestore)
        menu.addSeparator()
        menu.addAction(a)
        
        # help button
        a = self.helpAction = act(self.slotHelp, 'help-contents')
        menu.addSeparator()
        menu.addAction(a)
        
        self.treeView.setSelectionBehavior(QTreeView.SelectRows)
        self.treeView.setSelectionMode(QTreeView.ExtendedSelection)
        self.treeView.setRootIsDecorated(False)
        self.treeView.setAllColumnsShowFocus(True)
        self.treeView.setModel(model.model())
        self.treeView.setCurrentIndex(QModelIndex())
        
        # signals
        self.searchEntry.returnPressed.connect(self.slotReturnPressed)
        self.searchEntry.textChanged.connect(self.updateFilter)
        self.treeView.doubleClicked.connect(self.slotDoubleClicked)
        self.treeView.customContextMenuRequested.connect(self.showContextMenu)
        self.treeView.selectionModel().currentChanged.connect(self.updateText)
        self.treeView.model().dataChanged.connect(self.updateFilter)
        
        # highlight text
        self.highlighter = highlight.Highlighter(self.textView.document())
        
        # complete on snippet variables
        self.searchEntry.setCompleter(QCompleter([
            ':icon', ':indent', ':menu', ':name', ':python', ':selection',
            ':set', ':symbol', ':template', ':template-run'], self.searchEntry))
        self.readSettings()
        app.settingsChanged.connect(self.readSettings)
        app.translateUI(self)
        self.updateColumnSizes()
        self.setAcceptDrops(True)

    def dropEvent(self, ev):
        if not ev.source() and ev.mimeData().hasUrls():
            filename = ev.mimeData().urls()[0].toLocalFile()
            if filename:
                ev.accept()
                from . import import_export
                import_export.load(filename, self)
        
    def dragEnterEvent(self, ev):
        if not ev.source() and ev.mimeData().hasUrls():
            ev.accept()
        
    def translateUI(self):
        try:
            self.searchEntry.setPlaceholderText(_("Search..."))
        except AttributeError:
            pass # not in Qt 4.6
        shortcut = lambda a: a.shortcut().toString(QKeySequence.NativeText)
        self.menuButton.setText(_("&Menu"))
        self.addAction_.setText(_("&Add..."))
        self.addAction_.setToolTip(
            _("Add a new snippet. ({key})").format(key=shortcut(self.addAction_)))
        self.editAction.setText(_("&Edit..."))
        self.editAction.setToolTip(
            _("Edit the current snippet. ({key})").format(key=shortcut(self.editAction)))
        self.shortcutAction.setText(_("Configure Keyboard &Shortcut..."))
        self.deleteAction.setText(_("&Remove"))
        self.deleteAction.setToolTip(_("Remove the selected snippets."))
        self.applyAction.setText(_("A&pply"))
        self.applyAction.setToolTip(_("Apply the current snippet."))
        self.importAction.setText(_("&Import..."))
        self.importAction.setToolTip(_("Import snippets from a file."))
        self.exportAction.setText(_("E&xport..."))
        self.exportAction.setToolTip(_("Export snippets to a file."))
        self.restoreAction.setText(_("Restore &Built-in Snippets..."))
        self.restoreAction.setToolTip(
            _("Restore deleted or changed built-in snippets."))
        self.helpAction.setText(_("&Help"))
        self.searchEntry.setToolTip(_(
            "Enter text to search in the snippets list.\n"
            "See \"What's This\" for more information."))
        self.searchEntry.setWhatsThis(''.join(map("<p>{0}</p>\n".format, (
            _("Enter text to search in the snippets list, and "
              "press Enter to apply the currently selected snippet."),
            _("If the search text fully matches the value of the '{name}' variable "
              "of a snippet, that snippet is selected.").format(name="name"),
            _("If the search text starts with a colon ':', the rest of the "
              "search text filters snippets that define the given variable. "
              "After a space a value can also be entered, snippets will then "
              "match if the value of the given variable contains the text after "
              "the space."),
            _("E.g. entering {menu} will show all snippets that are displayed "
              "in the insert menu.").format(menu="<code>:menu</code>"),
            ))))
    
    def sizeHint(self):
        return self.parent().mainwindow().size() / 4
        
    def readSettings(self):
        data = textformats.formatData('editor')
        self.textView.setFont(data.font)
        self.textView.setPalette(data.palette())

    def showContextMenu(self, pos):
        """Called when the user right-clicks the tree view."""
        self.menuButton.menu().popup(self.treeView.viewport().mapToGlobal(pos))
    
    def slotReturnPressed(self):
        """Called when the user presses Return in the search entry. Applies current snippet."""
        name = self.currentSnippet()
        if name:
            view = self.parent().mainwindow().currentView()
            insert.insert(name, view)
            self.parent().hide() # make configurable?
            view.setFocus()

    def slotEscapePressed(self):
        """Called when the user presses ESC in the search entry. Hides the panel."""
        self.parent().hide()
        self.parent().mainwindow().currentView().setFocus()
    
    def slotDoubleClicked(self, index):
        name = self.treeView.model().name(index)
        view = self.parent().mainwindow().currentView()
        insert.insert(name, view)
        
    def slotAdd(self):
        """Called when the user wants to add a new snippet."""
        edit.Edit(self, None)
        
    def slotEdit(self):
        """Called when the user wants to edit a snippet."""
        name = self.currentSnippet()
        if name:
            edit.Edit(self, name)
        
    def slotShortcut(self):
        """Called when the user selects the Configure Shortcut action."""
        from widgets import shortcuteditdialog
        name = self.currentSnippet()
        if name:
            collection = self.parent().snippetActions
            action = actions.action(name, None, collection)
            default = collection.defaults().get(name)
            mgr = actioncollectionmanager.manager(self.parent().mainwindow())
            cb = mgr.findShortcutConflict
            dlg = shortcuteditdialog.ShortcutEditDialog(self, cb, (collection, name))
            
            if dlg.editAction(action, default):
                mgr.removeShortcuts(action.shortcuts())
                collection.setShortcuts(name, action.shortcuts())
                self.treeView.update()
            
    def slotDelete(self):
        """Called when the user wants to delete the selected rows."""
        rows = sorted(set(i.row() for i in self.treeView.selectedIndexes()), reverse=True)
        if rows:
            for row in rows:
                name = self.treeView.model().names()[row]
                self.parent().snippetActions.setShortcuts(name, [])
                self.treeView.model().removeRow(row)
            self.updateFilter()
    
    def slotApply(self):
        """Called when the user clicks the apply button. Applies current snippet."""
        name = self.currentSnippet()
        if name:
            view = self.parent().mainwindow().currentView()
            insert.insert(name, view)
    
    def slotImport(self):
        """Called when the user activates the import action."""
        filetypes = "{0} (*.xml);;{1} (*)".format(_("XML Files"), _("All Files"))
        caption = app.caption(_("dialog title", "Import Snippets"))
        filename = None
        filename = QFileDialog.getOpenFileName(self, caption, filename, filetypes)
        if filename:
            from . import import_export
            import_export.load(filename, self)
        
    def slotExport(self):
        """Called when the user activates the export action."""
        allrows = [row for row in range(model.model().rowCount())
                       if not self.treeView.isRowHidden(row, QModelIndex())]
        selectedrows = [i.row() for i in self.treeView.selectedIndexes()
                                if i.column() == 0 and i.row() in allrows]
        names = self.treeView.model().names()
        names = [names[row] for row in selectedrows or allrows]
        
        filetypes = "{0} (*.xml);;{1} (*)".format(_("XML Files"), _("All Files"))
        n = len(names)
        caption = app.caption(_("dialog title",
            "Export {num} Snippet", "Export {num} Snippets", n).format(num=n))
        filename = QFileDialog.getSaveFileName(self, caption, None, filetypes)
        if filename:
            from . import import_export
            try:
                import_export.save(names, filename)
            except (IOError, OSError) as e:
                QMessageBox.critical(self, _("Error"), _(
                    "Can't write to destination:\n\n{url}\n\n{error}").format(
                    url=filename, error=e.strerror))
        
    def slotRestore(self):
        """Called when the user activates the Restore action."""
        from . import restore
        dlg = restore.RestoreDialog(self)
        dlg.setWindowModality(Qt.WindowModal)
        dlg.populate()
        dlg.show()
        dlg.finished.connect(dlg.deleteLater)
        
    def slotHelp(self):
        """Called when the user clicks the small help button."""
        userguide.show("snippets")
        
    def currentSnippet(self):
        """Returns the name of the current snippet if it is visible."""
        row = self.treeView.currentIndex().row()
        if row != -1 and not self.treeView.isRowHidden(row, QModelIndex()):
            return self.treeView.model().names()[row]

    def updateFilter(self):
        """Called when the text in the entry changes, updates search results."""
        text = self.searchEntry.text()
        ltext = text.lower()
        filterVars = text.startswith(':')
        if filterVars:
            try:
                fvar, fval = text[1:].split(None, 1)
                fhide = lambda v: v.get(fvar) in (True, None) or fval not in v.get(fvar)
            except ValueError:
                fvar = text[1:].strip()
                fhide = lambda v: not v.get(fvar)
        for row in range(self.treeView.model().rowCount()):
            name = self.treeView.model().names()[row]
            nameid = snippets.get(name).variables.get('name', '')
            if filterVars:
                hide = fhide(snippets.get(name).variables)
            elif nameid == text:
                i = self.treeView.model().createIndex(row, 0)
                self.treeView.selectionModel().setCurrentIndex(i, QItemSelectionModel.SelectCurrent | QItemSelectionModel.Rows)
                hide = False
            elif nameid.lower().startswith(ltext):
                hide = False
            elif ltext in snippets.title(name).lower():
                hide = False
            else:
                hide = True
            self.treeView.setRowHidden(row, QModelIndex(), hide)
        self.updateText()
            
    def updateText(self):
        """Called when the current snippet changes."""
        name = self.currentSnippet()
        self.textView.clear()
        if name:
            s = snippets.get(name)
            self.highlighter.setPython('python' in s.variables)
            self.textView.setPlainText(s.text)
        
    def updateColumnSizes(self):
        self.treeView.resizeColumnToContents(0)
        self.treeView.resizeColumnToContents(1)