예제 #1
0
class RouteTable(QWidget):
    NO1, FROM, NO2, TO, CLUSTER = range(5)

    def __init__(self):
        super().__init__()
        # Main layout
        main_layout = QVBoxLayout()

        # Sub layout
        self.cluster_combobox = QComboBox()
        self.table_container = QGroupBox("Result")

        # Route Table
        self.table = QTreeView()
        self.table.setRootIsDecorated(False)
        self.table.setAlternatingRowColors(True)

        self.model = QStandardItemModel(0, 5, self)
        self.model.setHeaderData(self.NO1, Qt.Horizontal, "No")
        self.model.setHeaderData(self.FROM, Qt.Horizontal, "From")
        self.model.setHeaderData(self.NO2, Qt.Horizontal, "No")
        self.model.setHeaderData(self.TO, Qt.Horizontal, "To")
        self.model.setHeaderData(self.CLUSTER, Qt.Horizontal, "Cluster number")

        self.table.setModel(self.model)
        table_header = self.table.header()
        table_header.resizeSection(0, 25)
        table_header.resizeSection(1, 190)
        table_header.resizeSection(2, 25)
        table_header.resizeSection(3, 190)

        table_container_layout = QHBoxLayout()
        table_container_layout.addWidget(self.table)
        self.table_container.setLayout(table_container_layout)

        # Add to main layout
        main_layout.addWidget(self.cluster_combobox)
        main_layout.addWidget(self.table_container)
        self.setLayout(main_layout)

    def addRoute(self, model, from_no, from_route, to_no, to_route,
                 cluster_number):
        root = self.table.model()
        n = root.rowCount()
        model.insertRow(n)
        model.setData(model.index(n, self.NO1), from_no)
        model.setData(model.index(n, self.FROM), from_route)
        model.setData(model.index(n, self.NO2), to_no)
        model.setData(model.index(n, self.TO), to_route)
        model.setData(model.index(n, self.CLUSTER), cluster_number)

    def clearAllRoute(self):
        root = self.table.model()
        root.removeRows(0, root.rowCount())
예제 #2
0
class ParameterWindow(QMainWindow):
    def __init__(self, dplugin, api, pl_win_name = '',parent = None):
        QMainWindow.__init__(self, parent)

        # Build the tree for the parameters
        self.parameterTree = QTreeView(self)
        self.parameterTree.setObjectName("parameterTree")
        # Add it as the central widget
        self.setCentralWidget(self.parameterTree)
        # Add the DParameterTreeModel to the parameter tree
        self.dparameterModel = DParameterTreeModel()
        self.dparameterModel.setHorizontalHeaderLabels(['Name',''])
        self.parameterTree.setModel(self.dparameterModel)
        self.parameterTree.setUniformRowHeights(True)
        # connect the callback function for value changes
        self.dparameterModel.dataChanged.connect(self.data_changed_parameter_model)

        self.dpluign_object = dplugin
        self.api = api

        self.setWindowTitle(pl_win_name+' Parameter')



    def show_paramters(self, para_list):
        """
        Shows the list of parameters and values in the parameter window
        :param para_list:
        :return:
        """
        for dparameter_name in sorted(para_list):
            dparameter = para_list[dparameter_name]
            dparameter_item = DParameterTreeItem(dparameter)
            self.dparameterModel.appendRow(dparameter_item)
            self.parameterTree.resizeColumnToContents(0)
            self.parameterTree.resizeColumnToContents(1)
        self.parameterTree.expandAll()

        fh = self.parameterTree.fontMetrics().height()

        if len(para_list.keys()) > 8:
            self.setFixedHeight(fh*9+fh+25)
        else:
             self.setFixedHeight(fh*len(para_list.keys())+fh+fh+25)




    def data_changed_parameter_model(self, index, n):
        """
        This function is called when a dparameter value is changed by editing the 'value'-column.

        :param index: Index of current changed dparameter
        :param n: None
        :return:
        """

        dparameter = self.parameterTree.model().data(index, Qt.UserRole)

        self.api.do_set_parameter(self.dpluign_object.id, dparameter.name, dparameter.value)
예제 #3
0
class DirectoryDockWidget(QWidget):
    def __init__(self, directory: Directory, filtered=False, parent=None):
        super().__init__(parent)
        layout = QVBoxLayout(self)
        layout.setContentsMargins(4, 4, 4, 4)
        self.setLayout(layout)
        self.path_label = QLineEdit()
        self.path_label.setReadOnly(True)
        layout.addWidget(self.path_label)
        self.tree_view = QTreeView()
        layout.addWidget(self.tree_view)
        self.directory = directory
        self.filtered = filtered
        self.tree_view.setModel(QFileSystemModel())
        for i in range(1, 4):
            self.tree_view.hideColumn(i)
        self.tree_view.setHeaderHidden(True)
        self.directory.changed.connect(self.handle_directory_path_changed)

    def handle_directory_path_changed(self, path):
        if not path:
            return
        self.path_label.setText(path)
        model = self.tree_view.model()
        model.setRootPath(path)
        self.tree_view.setRootIndex(model.index(path))
        if self.filtered:
            model.setNameFilters(plugin.pattern
                                 for plugin in FilePluginRegistry.plugins)
예제 #4
0
파일: ui.py 프로젝트: 5cr009e/voc_vis
class App(QWidget):
    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 file system view'
        self.left = 100
        self.top = 100
        self.width = 1140
        self.height = 480
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.model = QFileSystemModel()
        self.model.setRootPath(QDir.rootPath())
        self.tree = QTreeView()
        self.tree.setModel(self.model)
        self.tree.setRootIndex(self.model.index(config['rgb_img_path']))
        self.tree.setAnimated(False)
        self.tree.setIndentation(20)
        self.tree.setSortingEnabled(True)
        self.tree.setWindowTitle("Dir View")
        self.tree.resize(640, 480)
        self.tree.doubleClicked.connect(self.plot)
        windowLayout = QVBoxLayout()
        windowLayout.addWidget(self.tree)
        self.setLayout(windowLayout)
        self.m = PlotCanvas(self, width=5, height=4)
        self.m.move(640, 0)
        self.show()

    def plot(self, signal):
        file_path = self.tree.model().filePath(signal)
        sample_id = re.search(r'\d+', file_path.split('/')[-1]).group()
        self.m.plot(str(sample_id))
예제 #5
0
class QTreeSelection(QToolButton):
    currentIndexChanged = pyqtSignal(QModelIndex, QModelIndex)
    currentDataChanged = pyqtSignal(object)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setPopupMode(QToolButton.MenuButtonPopup)
        self.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)

        self.tree = QTreeView(self)
        self.tree.setMinimumWidth(640)
        self.tree.setSelectionMode(QTreeView.SingleSelection)
        self.tree.setSelectionBehavior(QTreeView.SelectRows)

        act = QWidgetAction(self)
        act.setDefaultWidget(self.tree)

        self.menu = QMenu(self)
        self.menu.addAction(act)
        self.setMenu(self.menu)
        self.clicked.connect(self.showMenu)

    def _currentIndexChanged(self, newindex, oldindex):
        self.menu.close()
        selected = newindex.sibling(newindex.row(), 0)

        display = selected.data(Qt.DisplayRole)
        icon = selected.data(Qt.DecorationRole)

        self.setText(display or "")
        self.setIcon(icon or QIcon())
        self.currentIndexChanged.emit(newindex, oldindex)
        self.currentDataChanged.emit(newindex.data(Qt.UserRole))

    def currentIndex(self):
        return self.tree.currentIndex()

    def currentData(self):
        return self.currentIndex().data(Qt.UserRole)

    def setCurrentIndex(self, index):
        return self.tree.setCurrentIndex(index)

    def model(self):
        return self.tree.model()

    def setModel(self, model):
        self.tree.setModel(model)
        self.tree.selectionModel().currentChanged.connect(
            self._currentIndexChanged)

    def keyPressEvent(self, event):
        if (event.key() in (Qt.Key_Up, Qt.Key_Down)
                and not (event.modifiers()
                         & (Qt.ShiftModifier | Qt.AltModifier
                            | Qt.ControlModifier))):
            self.tree.keyPressEvent(event)

        return super().keyPressEvent(event)
예제 #6
0
class FileListWidget(QGroupBox):

    FILENAME, PATH = range(2)

    def __init__(self, title="Files"):
        super(QGroupBox, self).__init__(title)

        self.layout = QVBoxLayout(self)

        self.dataView = QTreeView()
        self.dataView.setRootIsDecorated(False)
        self.dataView.setAlternatingRowColors(True)
        self.layout.addWidget(self.dataView)

        model = self.create_file_list_model(self)
        self.dataView.setModel(model)

        self.data_dir = None
        self.loaded_directory_label = QLabel(
            "Click 'Open' to select a directory.", self)
        self.layout.addWidget(self.loaded_directory_label)

        self.btnOpen = QPushButton("Open", self)
        self.btnOpen.clicked.connect(self.load_data_directory)
        self.layout.addWidget(self.btnOpen)

        self.setLayout(self.layout)

    def load_data_directory(self):
        d = QFileDialog.getExistingDirectory(self, "Select Directory")
        self.data_dir = d
        self.loaded_directory_label.setText(self.data_dir)

        # Load all encountered files
        files = []
        allowed_extensions = ["jpg", "jpeg", "png"]
        for ext in allowed_extensions:
            files.extend(glob.glob(os.path.join(d, "*." + ext)))

        # Add them all into the file list.
        for file in files:
            self.add_file_entry(self.dataView.model(), file)

        return d

    def create_file_list_model(self, parent):
        model = QStandardItemModel(0, 2, parent)
        model.setHeaderData(self.FILENAME, Qt.Horizontal, "Filename")
        model.setHeaderData(self.PATH, Qt.Horizontal, "Path")
        return model

    def add_file_entry(self, model, path):
        filename = os.path.basename(path)
        model.insertRow(0)
        model.setData(model.index(0, self.FILENAME), filename)
        model.setData(model.index(0, self.PATH), path)
예제 #7
0
def main(args):
    app = QApplication (args)
    view = QTreeView()
    view.setModel(StorageModel(view))
    view.resize(640, 480)
    view.setSelectionBehavior(QAbstractItemView.SelectRows)
    for column in range(view.model().columnCount()):
        view.resizeColumnToContents(column)
    view.show()
    return app.exec_()
예제 #8
0
class StandardLibraryPage(QSplitter):
    """ The GUI for the standard library page of a project. """

    # The page's label.
    label = "Standard Library"

    @property
    def project(self):
        """ The project property getter. """

        return self._project

    @project.setter
    def project(self, value):
        """ The project property setter. """

        if self._project != value:
            self._project = value

            self._update_page()

    def __init__(self):
        """ Initialise the page. """

        super().__init__()

        self._project = None

        # Create the page's GUI.
        stdlib_pane = QWidget()
        stdlib_layout = QVBoxLayout()

        self._stdlib_edit = QTreeWidget(
                whatsThis="This shows the packages and modules in the target "
                        "Python version's standard library. Check those "
                        "packages and modules that are explicitly imported by "
                        "the application. A module will be partially checked "
                        "(and automatically included) if another module "
                        "requires it.")
        self._stdlib_edit.setHeaderLabels(["Package"])
        self._stdlib_edit.itemChanged.connect(self._module_changed)

        stdlib_layout.addWidget(self._stdlib_edit)

        stdlib_pane.setLayout(stdlib_layout)
        self.addWidget(stdlib_pane)

        extlib_pane = QWidget()
        extlib_layout = QVBoxLayout()
        extlib_sublayout = QFormLayout()

        self._version_edit = QComboBox(
                whatsThis="Select the target Python version. This will cause "
                        "the standard library package hierarchy to be "
                        "updated.")
        self._version_edit.addItems(get_supported_python_versions())
        self._version_edit.currentIndexChanged.connect(self._version_changed)
        extlib_sublayout.addRow("Target Python version", self._version_edit)

        self._ssl_edit = QCheckBox(
                whatsThis="Enable SSL for the standard library modules "
                        "that have optional support for it.",
                stateChanged=self._ssl_changed)
        extlib_sublayout.addRow("Enable optional SSL support", self._ssl_edit)

        extlib_layout.addLayout(extlib_sublayout)

        plat_gb = QGroupBox("Use standard Python shared library")
        plat_gb_layout = QVBoxLayout()
        self._platform_buttons = []

        for scope, plat, subscopes in PLATFORM_SCOPES:
            plat_cb = QCheckBox(plat,
                    whatsThis="Enable the use of the standard Python shared "
                            "library on {0} rather than a statically compiled "
                            "library.".format(plat),
                    stateChanged=self._platforms_changed)
            plat_cb._scope = scope
            plat_gb_layout.addWidget(plat_cb)
            self._platform_buttons.append(plat_cb)

        plat_gb.setLayout(plat_gb_layout)
        extlib_layout.addWidget(plat_gb)

        self._extlib_edit = QTreeView(
                whatsThis="This is the list of external libraries that must "
                        "be linked with the application. A library will only "
                        "be enabled if a module in the standard library uses "
                        "it. Double-click in the <b>DEFINES</b>, "
                        "<b>INCLUDEPATH</b> and <b>LIBS</b> columns to modify "
                        "the corresponding <tt>qmake</tt> variable as "
                        "required. Values may be prefixed by a platform "
                        "specific <tt>qmake</tt> scope.")
        self._extlib_edit.setRootIsDecorated(False)
        self._extlib_edit.setEditTriggers(
                QTreeView.DoubleClicked|QTreeView.SelectedClicked|
                QTreeView.EditKeyPressed)

        model = QStandardItemModel(self._extlib_edit)
        model.setHorizontalHeaderLabels(
                ("External Library", 'DEFINES', 'INCLUDEPATH', 'LIBS'))
        model.itemChanged.connect(self._extlib_changed)

        for extlib in external_libraries_metadata:
            name_itm = QStandardItem(extlib.user_name)

            extlib._items = (name_itm, QStandardItem(), QStandardItem(),
                    QStandardItem())

            model.appendRow(extlib._items)

        self._extlib_edit.setModel(model)

        for col in range(3):
            self._extlib_edit.resizeColumnToContents(col)

        extlib_layout.addWidget(self._extlib_edit)

        self._ignore_extlib_changes = False

        extlib_pane.setLayout(extlib_layout)
        self.addWidget(extlib_pane)

    def _update_page(self):
        """ Update the page using the current project. """

        project = self.project

        blocked = self._version_edit.blockSignals(True)
        self._version_edit.setCurrentIndex(
                get_supported_python_version_index(
                        project.python_target_version))
        self._version_edit.blockSignals(blocked)

        blocked = self._ssl_edit.blockSignals(True)
        self._ssl_edit.setCheckState(
                Qt.Checked if project.python_ssl else Qt.Unchecked)
        self._ssl_edit.blockSignals(blocked)

        for plat in self._platform_buttons:
            blocked = plat.blockSignals(True)
            plat.setCheckState(
                    Qt.Checked if plat._scope in project.python_use_platform
                            else Qt.Unchecked)
            plat.blockSignals(blocked)

        self._update_extlib_editor()
        self._update_stdlib_editor()

    def _update_stdlib_editor(self):
        """ Update the standard library module editor. """

        project = self.project
        editor = self._stdlib_edit

        metadata = get_python_metadata(project.python_target_version)

        blocked = editor.blockSignals(True)

        editor.clear()

        def add_module(name, module, parent):
            itm = QTreeWidgetItem(parent, name.split('.')[-1:])
            itm.setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable)
            itm._name = name

            # Handle any sub-modules.
            if module.modules is not None:
                for submodule_name in module.modules:
                    # We assume that a missing sub-module is because it is not
                    # in the current version rather than bad meta-data.
                    submodule = metadata.get(submodule_name)
                    if submodule is not None:
                        add_module(submodule_name, submodule, itm)

        for name, module in metadata.items():
            if not module.internal and '.' not in name:
                add_module(name, module, editor)

        editor.sortItems(0, Qt.AscendingOrder)

        editor.blockSignals(blocked)

        self._set_dependencies()

    def _set_dependencies(self):
        """ Set the dependency information. """

        project = self.project
        editor = self._stdlib_edit

        required_modules, required_libraries = project.get_stdlib_requirements()

        blocked = editor.blockSignals(True)

        it = QTreeWidgetItemIterator(editor)
        itm = it.value()
        while itm is not None:
            external = required_modules.get(itm._name)
            expanded = False
            if external is None:
                state = Qt.Unchecked
            elif external:
                state = Qt.Checked
                expanded = True
            else:
                state = Qt.PartiallyChecked

            itm.setCheckState(0, state)

            # Make sure every explicitly checked item is visible.
            if expanded:
                parent = itm.parent()
                while parent is not None:
                    parent.setExpanded(True)
                    parent = parent.parent()

            it += 1
            itm = it.value()

        editor.blockSignals(blocked)

        model = self._extlib_edit.model()

        # Note that we can't simply block the model's signals as this would
        # interfere with the model/view interactions.
        self._ignore_extlib_changes = True

        for extlib in external_libraries_metadata:
            if extlib.name in required_libraries:
                for idx, itm in enumerate(extlib._items):
                    itm.setFlags(
                            Qt.ItemIsEnabled|Qt.ItemIsEditable if idx != 0
                                    else Qt.ItemIsEnabled)
            else:
                for itm in extlib._items:
                    itm.setFlags(Qt.NoItemFlags)

        self._ignore_extlib_changes = False

    def _update_extlib_editor(self):
        """ Update the external library editor. """

        project = self.project
        model = self._extlib_edit.model()

        blocked = model.blockSignals(True)

        for extlib in external_libraries_metadata:
            _, defs, incp, libs = extlib._items

            for prj_extlib in project.external_libraries:
                if prj_extlib.name == extlib.name:
                    defs.setText(prj_extlib.defines)
                    incp.setText(prj_extlib.includepath)
                    libs.setText(prj_extlib.libs)
                    break
            else:
                defs.setText('')
                incp.setText('')
                libs.setText(extlib.libs)

        model.blockSignals(blocked)

    def _version_changed(self, idx):
        """ Invoked when the target Python version changes. """

        project = self.project

        project.python_target_version = get_supported_python_version(idx)
        self._update_page()

        project.modified = True

    def _ssl_changed(self, state):
        """ Invoked when the SSL support changes. """

        project = self.project

        project.python_ssl = (state == Qt.Checked)
        self._set_dependencies()

        project.modified = True

    def _platforms_changed(self, state):
        """ Invoked when the platforms change. """

        project = self._project

        project.python_use_platform = []

        for plat in self._platform_buttons:
            if plat.checkState() == Qt.Checked:
                project.python_use_platform.append(plat._scope)

        project.modified = True

    def _module_changed(self, itm, col):
        """ Invoked when a standard library module has changed. """

        project = self._project
        name = itm._name

        if name in project.standard_library:
            project.standard_library.remove(name)
        else:
            project.standard_library.append(name)

        self._set_dependencies()

        project.modified = True

    def _extlib_changed(self, itm):
        """ Invoked when an external library has changed. """

        if self._ignore_extlib_changes:
            return

        self._ignore_extlib_changes = True

        project = self.project

        idx = self._extlib_edit.model().indexFromItem(itm)
        extlib = external_libraries_metadata[idx.row()]
        col = idx.column()

        # Get the project entry, creating it if necessary.
        for prj_extlib in project.external_libraries:
            if prj_extlib.name == extlib.name:
                break
        else:
            prj_extlib = ExternalLibrary(extlib.name, '', '', extlib.libs)
            project.external_libraries.append(prj_extlib)

        # Update the project.
        text = itm.text().strip()

        if col == 1:
            prj_extlib.defines = text
        elif col == 2:
            prj_extlib.includepath = text
        elif col == 3:
            if text == '':
                text = extlib.libs
                itm.setText(text)

            prj_extlib.libs = text

        # If the project entry corresponds to the default then remove it.
        if prj_extlib.defines == '' and prj_extlib.includepath == '' and prj_extlib.libs == extlib.libs:
            project.external_libraries.remove(prj_extlib)

        project.modified = True

        self._ignore_extlib_changes = False
예제 #9
0
class Installed(preferences.Group):
    """Overview of installed extensions.

    A QTreeView lists the metadata of all installed extensions.
    If the currently selected extension provides a configuration
    widget it is displayed in the bottom group of the page.

    With a checkbox individual extensions can be deactivated.
    Metadata is listed for all *installed* extensions, regardless
    of manual deactivation or load failure.
    """

    def __init__(self, page):
        super(Installed, self).__init__(page)

        layout = QVBoxLayout()
        self.setLayout(layout)

        # This must be called before self.populate() because
        # the data model relies on the labels
        app.translateUI(self)

        self.tree = QTreeView()
        self.name_items = {}
        self._selected_extension = ''
        self.tree.setModel(QStandardItemModel())
        self.tree.model().setColumnCount(2)
        self.tree.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.tree.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tree.setHeaderHidden(True)
        self.tree.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.tree.selectionModel().selectionChanged.connect(
            self.selection_changed)
        self.populate()
        layout.addWidget(self.tree)

    def translateUI(self):
        self.setTitle(_("Installed Extensions"))
        self.config_labels = {
            'extension-name': _("Name"),
            'maintainers': _("Maintainer(s)"),
            'version': _("Version"),
            'api-version': _("API version"),
            'license': _("License"),
            'short-description': _("Short Description"),
            'description': _("Description"),
            'repository': _("Repository"),
            'website': _("Website"),
            'dependencies': _("Dependencies")
        }

    def loadSettings(self):
        s = QSettings()
        self.setEnabled(self.page().active())
        s.beginGroup("extension-settings/installed")
        inactive = s.value("inactive", [], list)
        for ext in self.name_items.keys():
            self.name_items[ext].setCheckState(
                Qt.Checked if ext not in inactive else Qt.Unchecked)
        self.tree.model().dataChanged.connect(self.page().changed)

    def saveSettings(self):
        s = QSettings()
        s.beginGroup("extension-settings/installed")
        inactive = [ext for ext in self.name_items.keys()
            if self.name_items[ext].checkState() == Qt.Unchecked]
        s.setValue("inactive", inactive)

    def populate(self):
        """Populate the tree view with data from the installed extensions.
        """

        # TODO/Question:
        # Would it make sense to move this to a dedicated model class
        # complementing the FailedModel?

        root = self.tree.model().invisibleRootItem()
        extensions = app.extensions()
        for ext in extensions.installed_extensions():
            ext_infos = extensions.infos(ext)
            display_name = ext_infos.get(ext, ext) if ext_infos else ext.name()
            loaded_extension = extensions.get(ext)
            if loaded_extension:
                display_name += ' ({})'.format(loaded_extension.load_time())

            name_item = QStandardItem(display_name)
            name_item.extension_name = ext
            name_item.setCheckable(True)
            self.name_items[ext] = name_item
            icon = extensions.icon(ext)
            if icon:
                name_item.setIcon(icon)
            root.appendRow([name_item])
            for entry in [
                'extension-name',
                'short-description',
                'description',
                'version',
                'api-version',
                'dependencies',
                'maintainers',
                'repository',
                'website',
                'license'
            ]:
                label_item = QStandardItem('{}:'.format(
                    self.config_labels[entry]))
                label_item.setTextAlignment(Qt.AlignTop)
                bold = QFont()
                bold.setWeight(QFont.Bold)
                label_item.setFont(bold)
                details = ext_infos.get(entry, "") if ext_infos else ""
                if type(details) == list:
                    details = '\n'.join(details)
                details_item = QStandardItem(details)
                details_item.setTextAlignment(Qt.AlignTop)
                if entry == 'api-version':
                    # Check for correct(ly formatted) api-version entry
                    # and highlight it in case of mismatch
                    api_version = appinfo.extension_api
                    if not details:
                        details_item.setFont(bold)
                        details_item.setText(
                            _("Misformat: {api}").format(details))
                    elif not details == api_version:
                            details_item.setFont(bold)
                            details_item.setText('{} ({}: {})'.format(
                                details,
                                appinfo.appname,
                                api_version))
                name_item.appendRow([label_item, details_item])

    def selected_extension(self):
        """Return the (directory) name of the extension that
        is currently selected."""
        return self._selected_extension

    def selection_changed(self, new, old):
        """Show the configuration widget for the selected extension,
        if available."""
        config = self.siblingGroup(Config)
        if new.indexes():
            ext_item = self.tree.model().itemFromIndex(new.indexes()[0])
            # NOTE: This may have to be changed if there should be
            # more complexity in the tree model than now (a selected
            # row is either a top-level row or its immediate child)
            if not hasattr(ext_item, 'extension_name'):
                ext_item = ext_item.parent()
            name = ext_item.extension_name
            if name == self.selected_extension():
                return
        else:
            # If nothing is selected, show the "empty" widget
            name = ""

        config.hide_extension()
        self._selected_extension = name
        config.show_extension(name)
예제 #10
0
class bands_pairing2(QWidget):
    def __init__(self, dataview):
        super().__init__()
        """a tree widget to create a list of datasets and select bands from each dataset"""

        self.dataview = dataview
        self.firstband = QTreeView()
        self.secondband = QTreeView()
        self.firstband.setModel(self.dataview.model)
        self.secondband.setModel(self.dataview.model)
        self.pairs = treewidget()
        self.pairs.setColumnCount(2)
        self.pairs.setHeaderLabels(['first band', 'second band'])
        self.pairbutton = QPushButton('Pair')

        self.pairbutton.clicked.connect(self.add_pair)
        mainlayout = QVBoxLayout()
        sublayout = QHBoxLayout()
        sublayout.addWidget(self.firstband)
        sublayout.addWidget(self.secondband)
        firstsecondgroup = QGroupBox()
        firstsecondgroup.setLayout(sublayout)
        mainlayout.addWidget(firstsecondgroup)
        mainlayout.addWidget(self.pairbutton)
        mainlayout.addWidget(self.pairs)
        self.maingroup = QGroupBox()
        self.maingroup.setLayout(mainlayout)

    def additems(self):
        """when the widget is activated, a list of selected bands will be added"""
        dict = self.dataview.collect_user_input()
        for i in dict['bandsdict'].keys():
            name = os.path.basename(i)
            for j in dict['bandsdict'][name].keys():
                band = QListWidgetItem(j)
                band2 = QListWidgetItem(j)
                self.firstband.addItem(band)
                self.secondband.addItem(band2)

    def add_pair(self):
        """when pair button is pressed the paire will be add to the list"""
        # get selected index
        firstitem = self.firstband.selectedIndexes()
        # item text (example:band1)
        firstitemtext = self.firstband.model().itemData(firstitem[0])[0]
        # parent text (example: rastername.tif)
        firstparent = self.firstband.model().itemFromIndex(firstitem[0]).parent().data(0)
        #text to appear on the pairing widget
        firstpairtext = os.path.basename(firstparent) + ' - ' + firstitemtext

        # get selected index
        seconditem = self.secondband.selectedIndexes()
        # item text (example:band1)
        seconditemtext = self.secondband.model().itemData(seconditem[0])[0]
        # parent text (example: rastername.tif)
        secondparent = self.firstband.model().itemFromIndex(firstitem[0]).parent().data(0)
        # text to appear on the pairing widget
        secondpairtext = os.path.basename(secondparent) + ' - ' + seconditemtext

        print(firstitemtext)
        print(os.path.basename(firstparent))

        pairitem = QTreeWidgetItem()
        pairitem.setText(0, firstpairtext)
        pairitem.setText(1, secondpairtext)
        self.pairs.addTopLevelItem(pairitem)
        #self.get_pairs()

    def get_pairs(self):
        """returns  1. a dictionary of selected bands created with the datatreeview widget, 2. a list of featurebands,
         3. a list of texts from the items in the widgets (dataset and band number) """
        bandsdict = self.dataview.collectinput()[0]
        print (bandsdict)
        datasets = self.dataview.collectinput()[1]
        selectedbands = self.dataview.collectinput()[2]
        print(selectedbands)
        featurebands = []
        feturebandstext = []
        for i in range(self.pairs.topLevelItemCount()):
            item = self.pairs.topLevelItem(i)
            item1text = item.text(0)
            item2text = item.text(1)
            # get the list of the items from the widget
            feturebandstext += [[item1text, item2text]]
            band1 = bandsdict[item1text]
            band2 = bandsdict[item2text]
            # get the pair of bands by indexes
            pair = [selectedbands.index(band1), selectedbands.index(band2)]
            featurebands += [pair]
        print(selectedbands)
        print(featurebands)
        return [selectedbands, featurebands,feturebandstext]
예제 #11
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)[0]
        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)[0]
        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)
예제 #12
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Untitled")
        icon = os.path.join(BASE_DIR, 'ide/Icon.ico')
        self.setWindowIcon(QIcon(icon))
        self.saveLoad = SaveLoad()
        self.fileName = None
        self.setupUI()

    def setupUI(self):
        centralWidget = QWidget(self)
        layout = QHBoxLayout(centralWidget)
        self.fileSysView = QTreeView(centralWidget)
        self.setupFileSystemViewer()
        self.editor = QsciScintilla(centralWidget)
        self.setupEditor()
        layout.addWidget(self.fileSysView, 1)
        layout.addWidget(self.editor, 3)
        self.setCentralWidget(centralWidget)
        self.setMinimumSize(700, 500)
        self.defaultMenuBar = QMenuBar(self)
        self.setupMenus()
        self.setMenuBar(self.defaultMenuBar)
        self.show()

    def setupEditor(self):
        self.editor.setFont(QFont("Times New Roman", 12))
        self.editor.setMargins(2)
        self.editor.setMarginType(0, QsciScintilla.NumberMargin)
        self.editor.setMarginType(1, QsciScintilla.SymbolMargin)
        self.editor.setMarginWidth(0, "000")
        self.editor.setMarginWidth(1, "00")
        self.editor.markerDefine(QsciScintilla.RightTriangle, 1)
        if system() == "Windows":
            self.editor.setEolMode(QsciScintilla.EolWindows)
        elif system() == "Linux":
            self.editor.setEolMode(QsciScintilla.EolUnix)
        elif system() == "Mac":
            self.editor.setEolMode(QsciScintilla.EolMac)
        else:
            print("Using Windows EOL")
            self.editor.setEolMode(QsciScintilla.EolWindows)
        self.editor.setBraceMatching(QsciScintilla.SloppyBraceMatch)
        self.editor.setIndentationsUseTabs(True)
        self.editor.setTabWidth(4)
        self.editor.setIndentationGuides(True)
        self.editor.setTabIndents(True)
        self.editor.setAutoIndent(True)
        self.editor.setCaretForegroundColor(QColor("#ff11214b"))
        self.editor.setCaretLineVisible(True)
        self.editor.setCaretLineBackgroundColor(QColor("#1f0000ff"))
        self.editor.setUtf8(True)
        self.editor.setMarginSensitivity(1, True)
        self.editor.marginClicked.connect(self.margin_clicked)
        self.editor.marginRightClicked.connect(self.margin_right_clicked)
        self.lexer = QsciLexerPython()
        self.lexer.setFont(QFont("Times New Roman", 12))
        self.editor.setLexer(self.lexer)
        self.editor.textChanged.connect(self.fileChanged)

    def setupFileSystemViewer(self):
        model = QFileSystemModel()
        model.setRootPath("/")
        self.fileSysView.setModel(model)
        self.fileSysView.hideColumn(1)
        self.fileSysView.hideColumn(2)
        self.fileSysView.hideColumn(3)
        self.fileSysView.doubleClicked.connect(self.openFile)

    def setupMenus(self):
        fileMenu = QMenu(self.defaultMenuBar)
        fileMenu.setTitle("File")
        editMenu = QMenu(self.defaultMenuBar)
        editMenu.setTitle("Edit")
        viewMenu = QMenu(self.defaultMenuBar)
        viewMenu.setTitle("View")
        runMenu = QMenu(self.defaultMenuBar)
        runMenu.setTitle("Run")
        settingsMenu = QMenu(self.defaultMenuBar)
        settingsMenu.setTitle("Settings")
        self.actionNew = QAction(self)
        self.actionNew.setText("New")
        self.actionNew.setShortcut("Ctrl+N")
        self.actionOpen = QAction(self)
        self.actionOpen.setText("Open")
        self.actionOpen.setShortcut("Ctrl+O")
        self.actionSave = QAction(self)
        self.actionSave.setText("Save")
        self.actionSave.setShortcut("Ctrl+S")
        self.actionSaveAs = QAction(self)
        self.actionSaveAs.setText("Save As")
        self.actionSaveAs.setShortcut("Ctrl+Shift+S")
        self.actionExit = QAction(self)
        self.actionExit.setText("Exit")
        self.actionExit.setShortcut("Alt+X")
        self.actionUndo = QAction(self)
        self.actionUndo.setText("Undo")
        self.actionUndo.setShortcut("Ctrl+Z")
        self.actionRedo = QAction(self)
        self.actionRedo.setText("Redo")
        self.actionRedo.setShortcut("Ctrl+Shift+Z")
        self.actionSelectAll = QAction(self)
        self.actionSelectAll.setText("Select all")
        self.actionSelectAll.setShortcut("Ctrl+A")
        self.actionCut = QAction(self)
        self.actionCut.setText("Cut")
        self.actionCut.setShortcut("Ctrl+X")
        self.actionCopy = QAction(self)
        self.actionCopy.setText("Copy")
        self.actionCopy.setShortcut("Ctrl+C")
        self.actionPaste = QAction(self)
        self.actionPaste.setText("Paste")
        self.actionPaste.setShortcut("Ctrl+V")
        self.actionFind = QAction(self)
        self.actionFind.setText("Find")
        self.actionFind.setShortcut("Ctrl+F")
        self.actionReplace = QAction(self)
        self.actionReplace.setText("Replace")
        self.actionReplace.setShortcut("Ctrl+H")
        self.actionRun = QAction(self)
        self.actionRun.setText("Run")
        self.actionRun.setShortcut("F5")
        self.actionRunCustom = QAction(self)
        self.actionRunCustom.setText("Run Customized")
        self.actionRunCustom.setShortcut("Shift+F5")
        self.actionShell = QAction(self)
        self.actionShell.setText("Python shell")
        self.actionShell.setShortcut("Alt+S")
        self.actionFont = QAction(self)
        self.actionFont.setText("Font")
        self.actionEncoding = QAction(self)
        self.actionEncoding.setText("Encoding")
        fileMenu.addAction(self.actionNew)
        fileMenu.addAction(self.actionOpen)
        fileMenu.addAction(self.actionSave)
        fileMenu.addAction(self.actionSaveAs)
        fileMenu.addSeparator()
        fileMenu.addAction(self.actionExit)
        editMenu.addAction(self.actionUndo)
        editMenu.addAction(self.actionRedo)
        editMenu.addSeparator()
        editMenu.addAction(self.actionSelectAll)
        editMenu.addSeparator()
        editMenu.addAction(self.actionCut)
        editMenu.addAction(self.actionCopy)
        editMenu.addAction(self.actionPaste)
        viewMenu.addAction(self.actionFind)
        viewMenu.addAction(self.actionReplace)
        runMenu.addAction(self.actionRun)
        runMenu.addAction(self.actionRunCustom)
        runMenu.addAction(self.actionShell)
        settingsMenu.addAction(self.actionFont)
        settingsMenu.addAction(self.actionEncoding)
        self.defaultMenuBar.addAction(fileMenu.menuAction())
        self.defaultMenuBar.addAction(editMenu.menuAction())
        self.defaultMenuBar.addAction(viewMenu.menuAction())
        self.defaultMenuBar.addAction(runMenu.menuAction())
        self.defaultMenuBar.addAction(settingsMenu.menuAction())
        self.actionNew.triggered.connect(self.new)
        self.actionOpen.triggered.connect(self.open)
        self.actionSave.triggered.connect(self.save)
        self.actionSaveAs.triggered.connect(self.saveAs)
        self.actionExit.triggered.connect(self.close)
        self.actionUndo.triggered.connect(self.editor.undo)
        self.actionRedo.triggered.connect(self.editor.redo)
        self.actionSelectAll.triggered.connect(
            lambda: self.editor.selectAll(True))
        self.actionCut.triggered.connect(self.editor.cut)
        self.actionCopy.triggered.connect(self.editor.copy)
        self.actionPaste.triggered.connect(self.editor.paste)
        self.actionFind.triggered.connect(self.find)
        self.actionReplace.triggered.connect(self.replace)
        self.actionRun.triggered.connect(self.run)
        self.actionRunCustom.triggered.connect(self.runCustom)
        self.actionShell.triggered.connect(self.shell)
        self.actionFont.triggered.connect(self.Font)

    def margin_clicked(self, margin_nr, line_nr, state):
        self.editor.markerAdd(line_nr, margin_nr)

    def margin_right_clicked(self, margin_nr, line_nr, state):
        self.editor.markerDelete(line_nr, margin_nr)

    def new(self):
        if self.windowTitle().endswith("*"):
            if (Dialogs().Question(
                    self, "Do you want to save your file?") == "accept"):
                if self.filename is None:
                    self.saveAs()
                else:
                    self.save()
        self.editor.setText("")
        self.setWindowTitle("Untitled")

    def open(self):
        if self.windowTitle().endswith("*"):
            if (Dialogs().Question(
                    self, "Do you want to save your file?") == "accept"):
                if self.filename is None:
                    self.saveAs()
                else:
                    self.save()
        filename = self.saveLoad.OpenDialog()
        data = Open(filename)
        if data is not None:
            self.editor.setText(data)
            self.setWindowTitle(filename)
            self.filename = filename

    def save(self):
        if self.filename is None:
            self.saveAs()
        else:
            returnval = Save(self.editor.text(), self.filename)
            if (returnval):
                Dialogs().Message(self, "File saved successfully")
                self.setWindowTitle(self.filename)
            else:
                Dialogs().Error(self, "File could not be saved")

    def saveAs(self):
        self.filename = self.saveLoad.SaveDialog()
        returnval = Save(self.editor.text(), self.filename)
        if (returnval):
            Dialogs().Message(self, "File saved successfully")
            self.setWindowTitle(self.filename)
        else:
            Dialogs().Error(self, "File could not be saved")

    def run(self):
        if self.filename is None:
            self.saveAs()
        Runfile(self.filename)

    def runCustom(self):
        if self.filename is None:
            self.saveAs()
        if self.filename != "":
            print(len(self.filename))
            option, ok = QInputDialog().getText(
                self, "Customized run", "Enter parameters for sys.argv",
                QLineEdit.Normal, " ")
            if ok:
                Runfile(self.filename, option)

    def shell(self):
        Shell()

    def Font(self):
        font, ok = QFontDialog.getFont()
        if ok:
            self.editor.setFont(font)
            self.lexer.setFont(font)
            self.editor.setLexer(self.lexer)

    def openFile(self, signal):
        fileName = self.fileSysView.model().filePath(signal)
        if fileName.endswith("py") or fileName.endswith("pyw"):
            if self.windowTitle().endswith("*"):
                if Dialogs().Question(
                        self, "Do you want to save your file?") == "accept":
                    if self.filename is None:
                        self.saveAs()
                    else:
                        self.save()
            data = Open(fileName)
            if data is not None:
                self.editor.setText(data)
                self.setWindowTitle(fileName)
                self.filename = fileName

    def fileChanged(self):
        title = self.windowTitle()
        if not (title.endswith("*")):
            self.setWindowTitle(title + " *")

    def replace(self):
        replaceObj = replaceDialog(self, self.editor)

    def find(self):
        findObj = findDialog(self, self.editor)
class LogInspectorWindow(QMainWindow):
    def __init__(self, configFilePath, parent=None):
        super(LogInspectorWindow, self).__init__(parent)
        self.initMatPlotLib()
        self.configFilePath = configFilePath

        folder = os.path.dirname(self.configFilePath)
        if not os.path.exists(folder):
            os.makedirs(folder)

        if os.path.exists(self.configFilePath):
            # config.yaml found.  Read from file.
            file = open(self.configFilePath, 'r')
            self.config = yaml.safe_load(file)
            file.close()
        else:
            # config.yaml not found.  Create new file.
            self.config = {}
            self.config['logs_directory'] = os.path.join(
                os.path.expanduser("~"), "Documents", "Inertial_Sense", "Logs")
            self.config['directory'] = ""
            self.config['serials'] = ["ALL"]
            file = open(self.configFilePath, 'w')
            yaml.dump(self.config, file)
            file.close()

        self.currently_selected = 'posNEDMap'
        self.downsample = 5
        self.plotargs = None
        self.log = None
        self.plotter = None

    def initMatPlotLib(self):
        self.figure = plt.figure()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.figure.subplots_adjust(left=0.05,
                                    right=0.99,
                                    bottom=0.05,
                                    top=0.91,
                                    wspace=0.2,
                                    hspace=0.2)

    def addButton(self, name, function, multithreaded=True, layout=None):
        setattr(self, name + "button", QPushButton(name))
        # if multithreaded:
        # setattr(self, name+"buttonThread", Thread(target=function))
        # getattr(self, name+"button").pressed.connect(self.startLoadingIndicator)
        # getattr(self, name+"button").released.connect(getattr(self, name+"buttonThread").start)
        # else:
        getattr(self, name + "button").clicked.connect(function)
        # getattr(self, name + "button").setMinimumWidth(220)
        if layout is None:
            if self.buttonLayoutRightCol.count(
            ) < self.buttonLayoutMiddleCol.count():
                self.buttonLayoutRightCol.addWidget(
                    getattr(self, name + "button"))
            elif self.buttonLayoutMiddleCol.count(
            ) < self.buttonLayoutLeftCol.count():
                self.buttonLayoutMiddleCol.addWidget(
                    getattr(self, name + "button"))
            else:
                self.buttonLayoutLeftCol.addWidget(
                    getattr(self, name + "button"))
        else:
            layout.addWidget(getattr(self, name + "button"))

    def updatePlot(self):
        self.plot(self.currently_selected, self.plotargs)

    def updateWindowTitle(self):
        if np.shape(self.log.data[0, DID_DEV_INFO])[0] != 0:
            info = self.log.data[0, DID_DEV_INFO][0]
            infoStr = 'SN' + str(info[1]) + ', H:' + verArrayToString(
                info[2]) + ', F:' + verArrayToString(
                    info[3]) + ' build ' + str(
                        info[4]) + ', ' + dateTimeArrayToString(
                            info[8], info[9]) + ', ' + info[10].decode('UTF-8')
            self.setWindowTitle("LogInspector  -  " + infoStr)

    def choose_directory(self):
        log_dir = config['logs_directory']
        directory = QFileDialog.getExistingDirectory(
            parent=self, caption='Choose Log Directory', directory=log_dir)

        if directory != '':
            try:
                self.load(directory)
            except Exception as e:
                msg = QMessageBox()
                msg.setIcon(QMessageBox.Critical)
                msg.setText("Unable to load log: " + e.__str__())
                msg.setDetailedText(traceback.format_exc())
                msg.exec()

    def load(self, directory):
        print("loading files from " + directory)
        # if self.log is None:
        self.log = Log()
        self.log.load(directory)
        print("done loading")
        self.plotter = logPlot(False, False, 'svg', self.log)
        self.plotter.setDownSample(self.downsample)
        # str = ''
        # if self.log.navMode:
        #     str += 'NAV '
        # if self.log.rtk:
        #     str += 'RTK '
        # if self.log.compassing:
        #     str += 'Comp '
        # self.statusLabel.setText(str)
        self.updatePlot()
        self.updateWindowTitle()
        self.stopLoadingIndicator()

    def setupUi(self):
        self.setObjectName("LogInspector")
        self.setWindowTitle("LogInspector")
        self.resize(1280, 900)
        self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowSystemMenuHint
                            | QtCore.Qt.WindowMinMaxButtonsHint)
        self.setWindowIcon(QIcon("assets/Magnifying_glass_icon.png"))

        # MainWindow.showMaximized()

        self.createFileTree()
        self.createButtonColumn()
        self.formatButtonColumn()
        self.createBottomToolbar()

        self.figureLayout = QVBoxLayout()
        self.figureLayout.addWidget(self.canvas)
        self.figureLayout.addLayout(self.toolLayout)
        self.figureLayout.setStretchFactor(self.canvas, 1)

        layout = QHBoxLayout()
        layout.addLayout(self.controlLayout)
        layout.addLayout(self.figureLayout)
        layout.setStretch(1, 1)
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        # self.resize(1280, 900)
        self.resize(1450, 1000)
        self.setAcceptDrops(True)

    def createButtonColumn(self):
        self.controlLayout = QVBoxLayout()
        self.buttonLayoutLeftCol = QVBoxLayout()
        self.buttonLayoutMiddleCol = QVBoxLayout()
        self.buttonLayoutRightCol = QVBoxLayout()
        self.addButton('Pos NED Map', lambda: self.plot('posNEDMap'))
        self.addButton('Pos NED', lambda: self.plot('posNED'))
        self.addButton('Pos LLA', lambda: self.plot('posLLA'))
        self.addButton('GPS LLA', lambda: self.plot('llaGps'))
        self.addButton('Vel NED', lambda: self.plot('velNED'))
        self.addButton('Vel UVW', lambda: self.plot('velUVW'))
        self.addButton('Attitude', lambda: self.plot('attitude'))
        self.addButton('Heading', lambda: self.plot('heading'))
        self.addButton('INS Status', lambda: self.plot('insStatus'))
        self.addButton('HDW Status', lambda: self.plot('hdwStatus'))
        self.addButton('GPS 1 Stats', lambda: self.plot('gpsStats'))
        self.addButton('GPS 2 Stats', lambda: self.plot('gps2Stats'))
        self.addButton('RTK Pos Stats', lambda: self.plot('rtkPosStats'))
        self.addButton('RTK Cmp Stats', lambda: self.plot('rtkCmpStats'))
        self.addButton('Flash Config', lambda: self.showFlashConfig())
        self.addButton('Device Info', lambda: self.showDeviceInfo())
        self.addButton('IMU PQR', lambda: self.plot('imuPQR'))
        self.addButton('IMU Accel', lambda: self.plot('imuAcc'))
        self.addButton('PSD PQR', lambda: self.plot('gyroPSD'))
        self.addButton('PSD Accel', lambda: self.plot('accelPSD'))
        self.addButton('Magnetometer', lambda: self.plot('magnetometer'))
        self.addButton('Temp', lambda: self.plot('temp'))

    def formatButtonColumn(self):
        self.buttonLayoutLeftCol.setAlignment(QtCore.Qt.AlignTop)
        self.buttonLayoutMiddleCol.setAlignment(QtCore.Qt.AlignTop)
        self.buttonLayoutRightCol.setAlignment(QtCore.Qt.AlignTop)
        self.buttonColumnLayout = QHBoxLayout()
        self.buttonColumnLayout.addLayout(self.buttonLayoutLeftCol)
        self.buttonColumnLayout.addLayout(self.buttonLayoutMiddleCol)
        self.buttonColumnLayout.addLayout(self.buttonLayoutRightCol)
        self.controlLayout.addLayout(self.buttonColumnLayout)
        self.controlDirLayout = QHBoxLayout()
        self.controlDirLayout.addWidget(self.dirLineEdit)
        self.controlLayout.addLayout(self.controlDirLayout)
        self.controlLayout.addWidget(self.fileTree)
        # self.buttonLayout.addItem(QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding))
        # self.addButton('load', self.choose_directory, multithreaded=False)

    def createBottomToolbar(self):
        self.toolLayout = QHBoxLayout()
        self.toolLayout.addWidget(self.toolbar)

        self.loadingIndictator = QLabel()
        self.loadingMovie = QMovie('assets/loader.gif')
        self.emptyLoadingPicture = QPicture()
        self.emptyLoadingPicture.load('assets/empty_loader.png')
        self.stopLoadingIndicator()
        self.toolLayout.addWidget(self.loadingIndictator)

        self.toolLayout.addItem(
            QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding))
        # self.toolLayout.addWidget(QSpacerItem(150, 10, QSizePolicy.Expanding))

        self.copyImagePushButton = QPushButton()
        # self.copyImagePushButton.setText("Copy")
        # self.copyImagePushButton.setMinimumWidth(1)
        # self.copyImagePushButton.style().standardIcon(QStyle.SP_DialogOpenButton)
        self.copyImagePushButton.setIcon(self.style().standardIcon(
            QStyle.SP_DialogSaveButton))
        self.toolLayout.addWidget(self.copyImagePushButton)
        self.copyImagePushButton.clicked.connect(self.copyPlotToClipboard)

        downsampleLabel = QLabel()
        downsampleLabel.setText("DS")
        self.downSampleInput = QSpinBox()
        self.downSampleInput.setValue(self.downsample)
        self.toolLayout.addWidget(downsampleLabel)
        self.toolLayout.addWidget(self.downSampleInput)
        self.downSampleInput.valueChanged.connect(self.changeDownSample)

        self.statusLabel = QLabel()
        self.toolLayout.addWidget(self.statusLabel)

    def changeDownSample(self, val):
        self.downsample = val
        self.plotter.setDownSample(self.downsample)
        self.updatePlot()

    def copyPlotToClipboard(self):
        # pixmap = QPixmap.grabWidget(self.canvas)
        # QApplication.clipboard().setPixmap(pixmap)
        # pixmap.save('test.png')

        # store the image in a buffer using savefig(), this has the
        # advantage of applying all the default savefig parameters
        # such as background color; those would be ignored if you simply
        # grab the canvas using Qt
        buf = io.BytesIO()
        self.figure.savefig(buf)

        QApplication.clipboard().setImage(QImage.fromData(buf.getvalue()))
        buf.close()

    def startLoadingIndicator(self):
        self.loadingIndictator.setMovie(self.loadingMovie)
        self.loadingMovie.start()

    def dragEnterEvent(self, e):
        if (e.mimeData().hasUrls()):
            e.acceptProposedAction()

    def dropEvent(self, e):
        try:
            directory = e.mimeData().urls()[0].toLocalFile()
            self.load(directory)
        except Exception as e:
            self.showError(e)

    def showError(self, e):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Critical)
        msg.setText("Unable to load log: " + e.__str__())
        msg.setDetailedText(traceback.format_exc())
        msg.exec()

    def createFileTree(self):
        self.dirModel = QFileSystemModel()
        self.dirModel.setRootPath(self.config["logs_directory"])
        self.dirModel.setFilter(QtCore.QDir.Dirs | QtCore.QDir.NoDotAndDotDot)
        self.dirLineEdit = QLineEdit()
        self.dirLineEdit.setText(self.config["logs_directory"])
        self.dirLineEdit.setFixedHeight(25)
        self.dirLineEdit.returnPressed.connect(self.handleTreeDirChange)
        self.fileTree = QTreeView()
        self.fileTree.setModel(self.dirModel)
        self.fileTree.setRootIndex(
            self.dirModel.index(self.config['logs_directory']))
        self.fileTree.setColumnHidden(1, True)
        self.fileTree.setColumnHidden(2, True)
        self.fileTree.setColumnHidden(3, True)
        self.fileTree.setMinimumWidth(300)
        self.fileTree.clicked.connect(self.handleTreeViewClick)
        self.fileTree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.fileTree.setSelectionMode(QAbstractItemView.SingleSelection)
        self.fileTree.customContextMenuRequested.connect(
            self.handleTreeViewRightClick)
        # self.populateRMSCheck(self.config['logs_directory'])

    def updateFileTree(self):
        self.dirModel.setRootPath(self.config["logs_directory"])
        self.fileTree.setRootIndex(
            self.dirModel.index(self.config['logs_directory']))

    def populateRMSCheck(self, directory):
        for subdir in os.listdir(directory):
            path = os.path.join(directory, subdir)
            if os.path.isdir(path):
                self.populateRMSCheck(path)
            elif 'RMS' in subdir:
                f = open(path)
                rms_report = f.read()
                p = re.compile(r'(?<=^PASS/FAIL).*\n', re.M)
                line = re.search(p, rms_report).group()
                failed = True if "FAIL" in line else False
                if failed:
                    pass
                else:
                    pass

    def handleTreeDirChange(self):
        self.config["logs_directory"] = self.dirLineEdit.text()
        self.updateFileTree()

        file = open(self.configFilePath, 'w')
        yaml.dump(self.config, file)
        file.close()

    def handleTreeViewClick(self):
        selected_directory = self.fileTree.model().filePath(
            self.fileTree.selectedIndexes()[0])
        for fname in os.listdir(selected_directory):
            if fname.endswith('.dat'):
                try:
                    self.load(selected_directory)
                except Exception as e:
                    self.showError(e)
                break

    def handleTreeViewRightClick(self, event):
        selected_directory = os.path.normpath(self.fileTree.model().filePath(
            self.fileTree.selectedIndexes()[0]))
        menu = QMenu(self)
        copyAction = menu.addAction("Copy path")
        nppActionHot = menu.addAction("Run NPP, HOT start")
        nppActionCold = menu.addAction("Run NPP, COLD start")
        nppActionFactory = menu.addAction("Run NPP, FACTORY start")
        setDataInfoDirHotAction = menu.addAction(
            "Set dataInfo.json directory, HOT start")
        setDataInfoDirColdAction = menu.addAction(
            "Set dataInfo.json directory, COLD start")
        setDataInfoDirFactoryAction = menu.addAction(
            "Set dataInfo.json directory, FACTORY start")
        exploreAction = menu.addAction("Explore folder")
        cleanFolderAction = menu.addAction("Clean folder")
        deleteFolderAction = menu.addAction("Delete folder")
        action = menu.exec_(self.fileTree.viewport().mapToGlobal(event))
        if action == copyAction:
            cb = QApplication.clipboard()
            cb.clear(mode=cb.Clipboard)
            cb.setText(selected_directory, mode=cb.Clipboard)
        if action == nppActionHot:
            cleanFolder(selected_directory)
            setDataInformationDirectory(selected_directory,
                                        startMode=START_MODE_HOT)
            sys.path.insert(1, '../../../../python/src')
            from supernpp.supernpp import SuperNPP
            spp = SuperNPP(selected_directory, self.config['serials'])
            spp.run()
        if action == nppActionCold:
            cleanFolder(selected_directory)
            setDataInformationDirectory(selected_directory,
                                        startMode=START_MODE_COLD)
            sys.path.insert(1, '../../../../python/src')
            from supernpp.supernpp import SuperNPP
            spp = SuperNPP(selected_directory,
                           self.config['serials'],
                           startMode=START_MODE_COLD)
            spp.run()
        if action == nppActionFactory:
            cleanFolder(selected_directory)
            setDataInformationDirectory(selected_directory,
                                        startMode=START_MODE_FACTORY)
            sys.path.insert(1, '../../../../python/src')
            from supernpp.supernpp import SuperNPP
            spp = SuperNPP(selected_directory,
                           self.config['serials'],
                           startMode=START_MODE_FACTORY)
            spp.run()
        if action == setDataInfoDirHotAction:
            setDataInformationDirectory(selected_directory,
                                        startMode=START_MODE_HOT)
        if action == setDataInfoDirColdAction:
            setDataInformationDirectory(selected_directory,
                                        startMode=START_MODE_COLD)
        if action == setDataInfoDirFactoryAction:
            setDataInformationDirectory(selected_directory,
                                        startMode=START_MODE_FACTORY)
        if action == exploreAction:
            openFolderWithFileBrowser(selected_directory)
        if action == cleanFolderAction:
            cleanFolder(selected_directory)
        if action == deleteFolderAction:
            msg = QMessageBox(self)
            msg.setIcon(QMessageBox.Question)
            msg.setText("Are you sure you want to delete this folder?\n\n" +
                        selected_directory)
            msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            result = msg.exec()
            if result == QMessageBox.Yes:
                removeDirectory(selected_directory)

    def stopLoadingIndicator(self):
        self.loadingMovie.stop()
        self.loadingIndictator.clear()
        self.loadingIndictator.setPicture(self.emptyLoadingPicture)

    def showDeviceInfo(self):
        dlg = DeviceInfoDialog(self.log, self)
        dlg.show()
        dlg.exec_()

    def showFlashConfig(self):
        dlg = FlashConfigDialog(self.log, self)
        dlg.show()
        dlg.exec_()

    def plot(self, func, args=None):
        print("plotting " + func)
        self.currently_selected = func
        self.plotargs = args

        self.figure.clear()

        if hasattr(self, 'plotter'):
            if args is not None:
                getattr(self.plotter, func)(*args, self.figure)
            else:
                getattr(self.plotter, func)(self.figure)

        self.canvas.draw()
        self.stopLoadingIndicator()
        print("done plotting")
class DriveAnalysisWidget(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle('Drive Analysis Tool')
        # self.root_path = os.path.expanduser('~')  # BUG 2018-09-18: No permission to access certain files for os.stat
        self.root_path = os.path.expanduser('~\\Downloads')
        self.threadpool = QThreadPool()
        self.resize_mode = 'dynamic'

        select_btn = QPushButton('Select Folder', self)
        select_btn.setToolTip('Select <b>root folder</b> to simplify.')
        select_btn.clicked.connect(self.show_file_dialog)
        select_btn.resize(select_btn.sizeHint())

        test_btn = QPushButton('Test Scripts', self)
        test_btn.clicked.connect(self.run_tests)
        test_btn.resize(test_btn.sizeHint())

        self.folder_edit = QLabel()
        self.folder_edit.setText(self.root_path)

        self.status_label = QLabel()
        self.status_label.setText('')
        self.status_label.setStyleSheet("color: red;"
                                        "font: bold;")

        ogtree_label = QLabel()
        ogtree_label.setAlignment(Qt.AlignCenter)
        ogtree_label.setText('Original folders data')

        anontree_label = QLabel()
        anontree_label.setAlignment(Qt.AlignCenter)
        anontree_label.setText('Anonymized folders data used for research')

        self.ogtree = QTreeView(self)
        self.ogtree.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.ogmodel = QStandardItemModel()
        self.ogmodel.setHorizontalHeaderLabels(['Folder Name', 'Number of Files'])
        self.ogmodel.itemChanged.connect(self.on_item_change)

        self.anontree = QTreeView(self)
        self.anontree.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.anonmodel = QStandardItemModel()
        self.anonmodel.setHorizontalHeaderLabels(['Folder Name', 'Number of Files'])

        self.dir_dict, self.og_dir_dict = dict(), dict()
        self.build_tree_structure_threaded(self.root_path)

        grid = QGridLayout()
        grid.addWidget(select_btn, 0, 0, 1, 1)
        grid.addWidget(self.folder_edit, 0, 1, 1, 8)
        grid.addWidget(self.status_label, 1, 0, 1, 9)
        grid.addWidget(test_btn, 2, 0, 1, 1)
        grid.addWidget(ogtree_label, 3, 0, 1, 4)
        grid.addWidget(anontree_label, 3, 5, 1, 4)
        grid.addWidget(self.ogtree, 4, 0, 1, 4)
        grid.addWidget(self.anontree, 4, 5, 1, 4)

        self.setLayout(grid)
        self.resize(640, 480)
        self.show()

    def refresh_tree_header(self, tree, resize_mode='dynamic'):
        if resize_mode == 'dynamic':
            tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
            tree.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
            # tree.header().setSectionResizeMode(2, QHeaderView.ResizeToContents)
        elif resize_mode == 'static':
            tree.header().setSectionResizeMode(0, QHeaderView.Interactive)
            tree.header().setSectionResizeMode(1, QHeaderView.Interactive)
            # tree.header().setSectionResizeMode(2, QHeaderView.Interactive)

    def show_file_dialog(self):
        dirpath = QFileDialog.getExistingDirectory(self, 'Select Folder', self.root_path)
        if dirpath:
            self.root_path = os.path.abspath(dirpath)
            self.folder_edit.setText(self.root_path)
            self.build_tree_structure_threaded(self.root_path, self.prune_thold)

    def build_tree_structure_threaded(self, root_path):
        worker = Worker(self.build_tree_structure, root_path)
        worker.signals.started.connect(self.build_tree_started)
        worker.signals.result.connect(self.build_tree_finished)
        self.threadpool.start(worker)

    def anonymize_tree_structure_threaded(self, root_path, dir_dict, rename_dict, remove_dict):
        worker = Worker(self.anonymize_tree_structure, root_path, dir_dict, rename_dict, remove_dict)
        worker.signals.started.connect(self.anonymize_tree_started)
        worker.signals.result.connect(self.anonymize_tree_finished)
        self.threadpool.start(worker)

    def build_tree_structure(self, root_path):
        # self.slider.setDisabled(True)
        dir_dict = record_stat(root_path)
        og_dir_dict = deepcopy(dir_dict)
        # dir_dict = simplify_tree(root_path, 1, dir_dict, 0.95, self.scale_pruning(prune_thold), print_=False)
        # self.slider.setEnabled(True)
        return og_dir_dict, dir_dict

    def anonymize_tree_structure(self, dir_dict, rename_dict, remove_dict):
        # dir_dict = simplify_tree(root_path, 1, dir_dict, 0.95, self.scale_pruning(prune_thold), print_=False)
        dir_dict = anonymize_stat(dir_dict, rename_dict, remove_dict)
        return dir_dict

    def build_tree_started(self):
        self.status_label.setText('Building tree, please wait...')

    def build_tree_finished(self, result):
        self.og_dir_dict, self.dir_dict = result
        # print(self.og_dir_dict[1],self.og_dir_dict[2], self.og_dir_dict[3])

        self.refresh_treeview(self.ogmodel, self.ogtree, self.og_dir_dict)
        # #BUG 2018-09-18: crashes the interface because i am referring to non-existent dictionary keys
        # (see append_all_children, e.g., dir_dict[dirkey][0])
        # I've updated my dir_dict to use string names instead of integers so append_all_children
        # needs to be updated as well.

        # self.refresh_treeview(self.anonmodel, self.anontree, self.dir_dict)
        self.status_label.setText('')

    def anonymize_tree_started(self):
        self.status_label.setText('Anonymizing tree, please wait...')

    def anonymize_tree_finished(self, dir_dict):
        self.refresh_treeview(self.anonmodel, self.anontree, dir_dict)
        self.status_label.setText('')

    def refresh_treeview(self, model, tree, dir_dict):
        model.removeRow(0)
        parent = model.invisibleRootItem()
        self.append_all_children(1, dir_dict, parent)  # dir_dict key starts at 1 since 0==False
        tree.setModel(model)
        self.refresh_tree_header(tree, self.resize_mode)
        tree.expandToDepth(0)

    def append_all_children(self, dirkey, dir_dict, qitem):
        qitem.setData(dirkey, Qt.UserRole)  # PAUSING HERE FOR NOW 20180918-1254
        print(dirkey, dir_dict[dirkey]['dirname'])
        # print(qitem.data(Qt.UserRole))
        dirname = QStandardItem(dir_dict[dirkey]['dirname'])
        nfiles = QStandardItem(str(dir_dict[dirkey]['nfiles']))
        # dirname.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
        # dirname.setData(QVariant(Qt.Checked), Qt.CheckStateRole)
        dirname.setCheckable(True)
        dirname.setCheckState(Qt.Checked)  # Qt.Checked == 2
        # dirname.setData(QVariant(str(dirkey)), role=Qt.UserRole+1)  # doesn't work
        # qitem.appendRow([QStandardItem(dir_dict[dirkey]['dirname']),
        #                  QStandardItem(str(dir_dict[dirkey]['nfiles']))])
        qitem.appendRow([dirname, nfiles, QStandardItem(str(dirkey))])
        current_row = qitem.rowCount() - 1
        print('Current row: ', current_row)
        print('dirkey for root: ', self.ogmodel.item(0).data(Qt.UserRole), qitem.data(Qt.UserRole))
        children_keys = dir_dict[dirkey]['childkeys']
        children_names = [dir_dict[child]['dirname'].lower() for child in children_keys]
        for child_name, child_key in sorted(zip(children_names, children_keys)):
            self.append_all_children(child_key, dir_dict, qitem.child(current_row))

    def on_item_change(self, qitem):
        # print(type(qitem))
        dirkey = qitem.data(Qt.UserRole)
        print(dirkey)
        # print(qitem.row(), qitem.column())
        # print(qitem.rowCount(), qitem.columnCount())
        # print(qitem.hasChildren())
        # print(qitem.parent())
        # print(qitem.text())
        # if qitem.hasChildren():  # doesn't work
        #     for child_item in qitem.sortChildren():
        #         self.on_item_change(child_item)
        # qitem.index(1, 1).setCheckState(check_state)
        # current_row = qitem.rowCount() - 1
        # print(qitem.sortChildren(1))
        # print(current_row)
        # print(qitem.checkState())

    def run_tests(self):
        print(self.ogtree.model().rowCount())
        for row in range(self.ogmodel.rowCount()):
            print(self.ogmodel.item(row).text(), self.ogmodel.item(row).data(Qt.UserRole))
            print(self.ogmodel.item(row).hasChildren())
예제 #15
0
파일: __init__.py 프로젝트: Zubax/kucher
class RegisterViewWidget(WidgetBase):
    def __init__(self, parent: QWidget):
        super(RegisterViewWidget, self).__init__(parent)

        self._registers = []
        self._running_task: asyncio.Task = None

        self._visibility_selector = QComboBox(self)
        self._visibility_selector.addItem("Show all registers", lambda _: True)
        self._visibility_selector.addItem("Only configuration parameters",
                                          lambda r: r.mutable and r.persistent)

        # noinspection PyUnresolvedReferences
        self._visibility_selector.currentIndexChanged.connect(
            lambda _: self._on_visibility_changed())

        self._reset_selected_button = make_button(
            self,
            "Reset selected",
            icon_name="clear-symbol",
            tool_tip=f"Reset the currently selected registers to their default "
            f"values. The restored values will be committed "
            f"immediately. This function is available only if a "
            f"default value is defined. [{RESET_SELECTED_SHORTCUT}]",
            on_clicked=self._do_reset_selected,
        )

        self._reset_all_button = make_button(
            self,
            "Reset all",
            icon_name="skull-crossbones",
            tool_tip=f"Reset the all registers to their default "
            f"values. The restored values will be committed "
            f"immediately.",
            on_clicked=self._do_reset_all,
        )

        self._read_selected_button = make_button(
            self,
            "Read selected",
            icon_name="process",
            tool_tip=f"Read the currently selected registers only "
            f"[{READ_SELECTED_SHORTCUT}]",
            on_clicked=self._do_read_selected,
        )

        self._read_all_button = make_button(
            self,
            "Read all",
            icon_name="process-plus",
            tool_tip="Read all registers from the device",
            on_clicked=self._do_read_all,
        )

        self._export_button = make_button(
            self,
            "Export",
            icon_name="export",
            tool_tip="Export configuration parameters",
            on_clicked=self._do_export,
        )

        self._import_button = make_button(
            self,
            "Import",
            icon_name="import",
            tool_tip="Import configuration parameters",
            on_clicked=self._do_import,
        )

        self._expand_all_button = make_button(
            self,
            "",
            icon_name="expand-arrow",
            tool_tip="Expand all namespaces",
            on_clicked=lambda: self._tree.expandAll(),
        )

        self._collapse_all_button = make_button(
            self,
            "",
            icon_name="collapse-arrow",
            tool_tip="Collapse all namespaces",
            on_clicked=lambda: self._tree.collapseAll(),
        )

        self._status_display = QLabel(self)
        self._status_display.setWordWrap(True)

        self._reset_selected_button.setEnabled(False)
        self._reset_all_button.setEnabled(False)
        self._read_selected_button.setEnabled(False)
        self._read_all_button.setEnabled(False)
        self._export_button.setEnabled(False)
        self._import_button.setEnabled(False)

        self._tree = QTreeView(self)
        self._tree.setVerticalScrollMode(QTreeView.ScrollPerPixel)
        self._tree.setHorizontalScrollMode(QTreeView.ScrollPerPixel)
        self._tree.setAnimated(True)
        self._tree.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self._tree.setAlternatingRowColors(True)
        self._tree.setContextMenuPolicy(Qt.ActionsContextMenu)

        # Not sure about this one. This hardcoded value may look bad on some platforms.
        self._tree.setIndentation(20)

        def add_action(
            callback: typing.Callable[[], None],
            icon_name: str,
            name: str,
            shortcut: typing.Optional[str] = None,
        ):
            action = QAction(get_icon(icon_name), name, self)
            # noinspection PyUnresolvedReferences
            action.triggered.connect(callback)
            if shortcut:
                action.setShortcut(shortcut)
                action.setAutoRepeat(False)
                try:
                    action.setShortcutVisibleInContextMenu(True)
                except AttributeError:
                    pass  # This feature is not available in PyQt before 5.10

            self._tree.addAction(action)

        add_action(self._do_read_all, "process-plus", "Read all registers")
        add_action(
            self._do_read_selected,
            "process",
            "Read selected registers",
            READ_SELECTED_SHORTCUT,
        )
        add_action(
            self._do_reset_selected,
            "clear-symbol",
            "Reset selected to default",
            RESET_SELECTED_SHORTCUT,
        )

        self._tree.setItemDelegateForColumn(
            int(Model.ColumnIndices.VALUE),
            EditorDelegate(self._tree, self._display_status),
        )

        # It doesn't seem to be explicitly documented, but it seems to be necessary to select either top or bottom
        # decoration position in order to be able to use center alignment. Left or right positions do not work here.
        self._tree.setItemDelegateForColumn(
            int(Model.ColumnIndices.FLAGS),
            StyleOptionModifyingDelegate(
                self._tree,
                decoration_position=QStyleOptionViewItem.Top,  # Important
                decoration_alignment=Qt.AlignCenter,
            ),
        )

        header: QHeaderView = self._tree.header()
        header.setSectionResizeMode(QHeaderView.ResizeToContents)
        header.setStretchLastSection(
            False)  # Horizontal scroll bar doesn't work if this is enabled

        buttons_layout = QGridLayout()
        buttons_layout.addWidget(self._read_selected_button, 0, 0)
        buttons_layout.addWidget(self._reset_selected_button, 0, 2)
        buttons_layout.addWidget(self._read_all_button, 1, 0)
        buttons_layout.addWidget(self._reset_all_button, 1, 2)
        buttons_layout.addWidget(self._import_button, 2, 0)
        buttons_layout.addWidget(self._export_button, 2, 2)

        for col in range(3):
            buttons_layout.setColumnStretch(col, 1)

        layout = lay_out_vertically(
            (self._tree, 1),
            buttons_layout,
            lay_out_horizontally(
                self._visibility_selector,
                (None, 1),
                self._expand_all_button,
                self._collapse_all_button,
            ),
            self._status_display,
        )

        self.setLayout(layout)

    def reset(self):
        self.setup([])

    def setup(self, registers: typing.Iterable[Register]):
        self._registers = list(registers)
        self._on_visibility_changed()

    def _replace_model(
            self, register_visibility_predicate: typing.Callable[[Register],
                                                                 bool]):
        # Cancel all operations that might be pending on the old model
        self._cancel_task()

        old_model = self._tree.model()

        # Configure the new model
        filtered_registers = list(
            filter(register_visibility_predicate, self._registers))
        # It is important to set the Tree widget as the parent in order to let the widget take ownership
        new_model = Model(self._tree, filtered_registers)
        _logger.info("New model %r", new_model)
        self._tree.setModel(new_model)

        # The selection model is implicitly replaced when we replace the model, so it has to be reconfigured
        self._tree.selectionModel().selectionChanged.connect(
            lambda *_: self._on_selection_changed())

        # TODO: Something fishy is going on. Something keeps the old model alive when we're replacing it.
        #       We could call deleteLater() on it, but it seems dangerous, because if that something ever decided
        #       to refer to that dead model later for any reason, we'll get a rougue dangling pointer access on
        #       our hands. The horror!
        if old_model is not None:
            import gc

            model_referrers = gc.get_referrers(old_model)
            if len(model_referrers) > 1:
                _logger.warning(
                    "Extra references to the old model %r: %r",
                    old_model,
                    model_referrers,
                )

        # Update the widget - all root items are expanded by default
        for row in itertools.count():
            index = self._tree.model().index(row, 0)
            if not index.isValid():
                break

            self._tree.expand(index)

        self._reset_selected_button.setEnabled(False)
        self._read_selected_button.setEnabled(False)
        self._read_all_button.setEnabled(len(filtered_registers) > 0)
        self._reset_all_button.setEnabled(len(filtered_registers) > 0)
        self._export_button.setEnabled(len(filtered_registers) > 0)
        self._import_button.setEnabled(len(filtered_registers) > 0)

        self._display_status(f"{len(filtered_registers)} registers loaded")

    def _on_visibility_changed(self):
        self._replace_model(self._visibility_selector.currentData())

    def _on_selection_changed(self):
        selected = self._get_selected_registers()

        self._reset_selected_button.setEnabled(
            any(map(lambda r: r.has_default_value, selected)))
        self._read_selected_button.setEnabled(len(selected) > 0)

    def _do_read_selected(self):
        selected = self._get_selected_registers()
        if selected:
            self._read_specific(selected)
        else:
            self._display_status("No registers are selected, nothing to read")

    def _do_reset_selected(self):
        rv = {}
        for r in self._get_selected_registers():
            if r.has_default_value:
                rv[r] = r.default_value

        self._write_specific(rv)

    def _do_reset_all(self):
        rv = {}
        for r in self._registers:
            if r.has_default_value:
                rv[r] = r.default_value

        self._write_specific(rv)

    def _do_read_all(self):
        self._read_specific(self._tree.model().registers)

    def _do_import(self):
        import_registers(parent=self, registers=self._registers)

    def _do_export(self):
        export_registers(parent=self, registers=self._registers)

    def _read_specific(self, registers: typing.List[Register]):
        total_registers_read = None

        def progress_callback(register: Register, current_register_index: int,
                              total_registers: int):
            nonlocal total_registers_read
            total_registers_read = total_registers
            self._display_status(
                f"Reading {register.name!r} "
                f"({current_register_index + 1} of {total_registers})")

        async def executor():
            try:
                _logger.info("Reading registers: %r",
                             [r.name for r in registers])
                mod: Model = self._tree.model()
                await mod.read(registers=registers,
                               progress_callback=progress_callback)
            except asyncio.CancelledError:
                self._display_status(f"Read has been cancelled")
                raise
            except Exception as ex:
                _logger.exception("Register read failed")
                show_error("Read failed", "Could not read registers", repr(ex),
                           self)
                self._display_status(f"Could not read registers: {ex!r}")
            else:
                self._display_status(
                    f"{total_registers_read} registers have been read")

        self._cancel_task()
        self._running_task = asyncio.get_event_loop().create_task(executor())

    def _write_specific(self, register_value_mapping: typing.Dict[Register,
                                                                  typing.Any]):
        total_registers_assigned = None

        def progress_callback(register: Register, current_register_index: int,
                              total_registers: int):
            nonlocal total_registers_assigned
            total_registers_assigned = total_registers
            self._display_status(
                f"Writing {register.name!r} "
                f"({current_register_index + 1} of {total_registers})")

        async def executor():
            try:
                _logger.info(
                    "Writing registers: %r",
                    [r.name for r in register_value_mapping.keys()],
                )
                mod: Model = self._tree.model()
                await mod.write(
                    register_value_mapping=register_value_mapping,
                    progress_callback=progress_callback,
                )
            except asyncio.CancelledError:
                self._display_status(f"Write has been cancelled")
                raise
            except Exception as ex:
                _logger.exception("Register write failed")
                show_error("Write failed", "Could not read registers",
                           repr(ex), self)
                self._display_status(f"Could not write registers: {ex!r}")
            else:
                self._display_status(
                    f"{total_registers_assigned} registers have been written")

        self._cancel_task()
        self._running_task = asyncio.get_event_loop().create_task(executor())

    def _get_selected_registers(self) -> typing.List[Register]:
        selected_indexes: typing.List[
            QModelIndex] = self._tree.selectedIndexes()
        selected_registers = set()
        for si in selected_indexes:
            r = Model.get_register_from_index(si)
            if r is not None:
                selected_registers.add(r)
        # Beware that sets are not sorted, this may lead to weird user experience when watching the registers
        # read in a funny order.
        return list(sorted(selected_registers, key=lambda x: x.name))

    def _cancel_task(self):
        # noinspection PyBroadException
        try:
            self._running_task.cancel()
        except Exception:
            pass
        else:
            _logger.info("A running task had to be cancelled: %r",
                         self._running_task)
        finally:
            self._running_task = None

    def _display_status(self, text=None):
        self._status_display.setText(text)
예제 #16
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)
        # projects must be a list
        self._projects = projects
        self.setWindowTitle(translations.TR_ADD_FILE_TO_PROJECT)
        self.path_selected = ''
        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.setHeaderHidden(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()
        btn_add = QPushButton(translations.TR_ADD_HERE)
        btn_cancel = QPushButton(translations.TR_CANCEL)
        hbox2.addWidget(btn_cancel)
        hbox2.addWidget(btn_add)
        vbox.addLayout(hbox2)

        btn_add.clicked.connect(self._select_path)
        btn_cancel.clicked.connect(self.close)
        self._list.currentItemChanged.connect(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.setSectionResizeMode(0, QHeaderView.Stretch)
        t_header.setStretchLastSection(False)
        t_header.setSectionsClickable(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 path_selected to the folder selected in the tree."""
        path = self._tree.model().filePath(self._tree.currentIndex())
        if path:
            self.path_selected = path
            self.close()
예제 #17
0
class MyWindow(QMainWindow):  # QWidget
    def __init__(self):
        #super(MyWindow, self).__init__()
        super().__init__()
        global mainWindow
        mainWindow = self
        self.fileLabels = []
        self.model = None
        self.tree = None
        self.grpBox = None
        self.viewWindow = None
        self._drawIndex = -1
        self.thumbs = {}
        self.thumbFileName = None
        self.newImgFound = False  # if True, new image file non-referenced in .pythumbs file is found, need to update the .pythumbs file
        self.initUI()

    def initUI(self):
        self.resize(600, 800)

        bar = self.menuBar()
        makeMenu(bar, FILE_MENU, self)

        # #self.model = QDirModel([], QDir.Dirs, QDir.NoSort )
        # rootPath = 'C:/Users/azemero' # QDir.currentPath()
        # self.model = QFileSystemModel()
        # self.model.setRootPath(rootPath)
        # self.model.setFilter(QDir.AllDirs|QDir.NoDotAndDotDot)
        # #todo: filter or custom tree
        # proxyModel = QSortFilterProxyModel()
        # proxyModel.setSourceModel(self.model)
        # proxyModel.setFilterRegExp(r"^([^.]+)$")
        #
        # self.tree = QTreeView()
        # self.tree.setModel(proxyModel)
        # self.tree.setColumnHidden(1, True)
        # self.tree.setColumnHidden(2, True)
        # self.tree.setColumnHidden(3, True)
        # self.tree.doubleClicked.connect(self.onDirDblClick)
        # self.tree.selectionModel().selectionChanged.connect(self.onDirSelChange)
        #
        # self.tree.setSortingEnabled(True)
        # self.tree.sortByColumn(0, Qt.AscendingOrder)
        # idx = self.model.index(rootPath)
        # idx = proxyModel.mapFromSource(idx)
        # self.tree.setRootIndex(idx)
        #
        # self.tree.setAnimated(False)
        # self.tree.setIndentation(20)
        # self.tree.setSortingEnabled(True)
        #
        # self.tree.setWindowTitle("Dir View")
        # #self.tree.resize(640, 480)
        # self.tree.setMinimumWidth(200)

        self.model = QStandardItemModel()
        parentItem = self.model.invisibleRootItem()
        frstIdx = None
        for i in range(4):
            item = QStandardItem("Pictures %d" % i)
            item.setData('C:/Users/azemero/Pictures')
            #item.setIcon(QIcon(os.path.abspath(os.path.join(os.path.dirname(__file__),'..','icons','base','24.png'))))
            item.setIcon(QIcon(appctxt.get_resource('folder_png8773.ico')))
            parentItem.appendRow(item)
            if not frstIdx:
                frstIdx = item.index()
            #parentItem = item
        self.model.setHeaderData(0, Qt.Horizontal, "Directories")
        self.tree = QTreeView(self)
        self.tree.setModel(self.model)
        self.tree.clicked[QModelIndex].connect(self.onTreeClick)
        self.tree.setMinimumWidth(200)

        windowLayout = QHBoxLayout()
        windowLayout.setSpacing(0)  #windowLayout.setContentsMargins(0,0,0,0)
        windowLayout.addWidget(self.tree, alignment=Qt.AlignLeft)

        self.grpBox = QGroupBox('')
        self.grpBox.setLayout(
            FlowLayout())  #self.grpBox.setLayout(QGridLayout(self))
        self.grpBox.setMinimumWidth(400)
        windowLayout.addWidget(self.grpBox)  #, alignment=Qt.AlignLeft)

        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(self.tree)
        splitter.addWidget(self.grpBox)
        splitter.setSizes([200, 800])
        splitter.setStretchFactor(1, 1)

        windowLayout.addWidget(splitter)

        #~self.setLayout(windowLayout)
        center = QWidget()
        center.setLayout(windowLayout)
        self.setCentralWidget(center)

        self.viewWindow = ViewWindow()
        if frstIdx:
            self.onTreeClick(frstIdx)

    def onDirDblClick(self, signal):
        file_path = self.tree.model().filePath(signal)
        #print(file_path)
        if os.path.isdir(file_path):
            self.drawFiles(file_path)

    def onTreeClick(self, index):
        item = self.model.itemFromIndex(index)
        file_path = item.data()
        #print(file_path)
        if os.path.isdir(file_path):
            self.drawFiles(file_path)

    # def onDirSelChange(self, newitem, olditem):
    #     _ = olditem
    #     idx = newitem.indexes()[0]
    #     idx = self.tree.model().mapToSource(idx)
    #     file_path=self.model.filePath(idx)
    #     #print(file_path)
    #     if os.path.isdir(file_path):
    #         self.drawFiles(file_path)

    # def onFileDblClick(self):
    #     self.viewWindow.openImage('')
    #     self.viewWindow.show()

    # def eventFilter(self, obj, event):
    #     if event.type() == QEvent.MouseButtonPress:
    #         pass #здесь выполняем код
    #     return True

    def drawFiles(self, dname):
        row = col = 0
        for label in self.fileLabels:
            label.setParent(None)  # remove old image labels
        del self.fileLabels[:]
        QApplication.processEvents()

        self.thumbFileName = os.path.join(dname, '.pythumbs')
        self.newImgFound = False
        if os.path.isfile(self.thumbFileName):
            with open(self.thumbFileName, 'rb') as f:
                data = pickle.load(f)
                self.thumbs = deserializeDict(data)
        else:
            self.thumbs = {}

        fnames = imgFiles(dname)
        for fname in fnames:
            label = ClickableLabel(dname, fname)
            self.fileLabels.append(label)
            self.grpBox.layout().addWidget(label)
            col += 1
            if col % 6 == 0:
                row += 1
                col = 0
        #print('drawFiles.3')
        QApplication.processEvents()
        self._drawIndex = 0 if fnames else -1
        threading.Thread(target=self.drawFile).start()

    def drawFile(self):
        if self._drawIndex < len(self.fileLabels):
            self.fileLabels[self._drawIndex].showImage()
            QApplication.processEvents()
        self._drawIndex += 1
        if self._drawIndex >= len(self.fileLabels):
            self._drawIndex = -1
            if self.thumbFileName and self.newImgFound:
                print('update .pythumbs')
                array = serializeDict(self.thumbs)
                with open(self.thumbFileName, 'wb') as f:
                    pickle.dump(array, f)
        else:
            threading.Thread(target=self.drawFile).start()
예제 #18
0
파일: debug.py 프로젝트: wbsoft/parceqt
class DebugWindow(QMainWindow):
    """A main window to edit text and examine the generated token structure.

    Example::

        from PyQt5.Qt import *
        a=QApplication([])

        from parceqt.debug import DebugWindow
        w = DebugWindow()
        w.resize(1200,900)
        w.show()

        w.set_theme("default", True)

        from parce.lang.css import *
        w.set_root_lexicon(Css.root)
        w.set_text(open("path/to/parce/themes/default.css").read())

    In the debug window you can edit the text at the left and directly at the
    right examine the tree structure. Along the top of the window the path to
    the token at the current cursor position is displayed, from the root
    lexicon upto the token, from which the action is displayed.

    Clicking a button selects the associated range of the context or token in
    the text view. Clicking an item in the tree also selects that range in the
    text.

    Moving the cursor in the text updates the current item in the tree,
    and the displayed ancestor path.

    """

    show_updated_region_enabled = False

    def __init__(self, parent=None):
        super().__init__(parent, windowTitle="parceqt debugger")

        f = self._updated_format = QTextCharFormat()
        c = QColor("palegreen")
        c.setAlpha(64)
        f.setBackground(c)
        f = self._currentline_format = QTextCharFormat()
        f.setProperty(QTextCharFormat.FullWidthSelection, True)

        self._actions = Actions(self)
        self._actions.add_menus(self.menuBar())

        widget = QWidget(self)
        self.setCentralWidget(widget)
        layout = QVBoxLayout(margin=4, spacing=2)
        widget.setLayout(layout)

        top_layout = QHBoxLayout(margin=0, spacing=0)

        self.guessButton = QToolButton(self,
                                       clicked=self.guess_root_lexicon,
                                       toolTip="Guess Language",
                                       icon=self.style().standardIcon(
                                           QStyle.SP_BrowserReload))
        self.lexiconChooser = LexiconChooser(self)
        self.ancestorView = AncestorView(self)
        top_layout.addWidget(self.guessButton)
        top_layout.addWidget(self.lexiconChooser)
        top_layout.addWidget(self.ancestorView)
        top_layout.addStretch(10)
        layout.addLayout(top_layout)
        self.guessButton.setFixedHeight(
            self.lexiconChooser.sizeHint().height())

        splitter = QSplitter(self, orientation=Qt.Horizontal)
        layout.addWidget(splitter, 100)

        self.textEdit = QPlainTextEdit(lineWrapMode=QPlainTextEdit.NoWrap,
                                       cursorWidth=2)
        self.treeView = QTreeView()

        splitter.addWidget(self.textEdit)
        splitter.addWidget(self.treeView)
        splitter.setStretchFactor(0, 3)
        splitter.setStretchFactor(1, 2)

        self.extraSelectionManager = ExtraSelectionManager(self.textEdit)

        self.document = d = self.textEdit.document()
        self.textEdit.setDocument(self.document)

        self.worker = w = parceqt.worker(d)
        self.builder = b = w.builder()
        w.debugging = True

        self.setStatusBar(QStatusBar())
        self.create_model()

        # signal connections
        self.textEdit.viewport().installEventFilter(self)
        self.textEdit.installEventFilter(self)
        self.lexiconChooser.lexicon_changed.connect(
            self.slot_root_lexicon_changed)
        self.ancestorView.node_clicked.connect(self.slot_node_clicked)
        w.started.connect(self.slot_build_started)
        w.tree_updated.connect(self.slot_build_updated)
        self.textEdit.cursorPositionChanged.connect(
            self.slot_cursor_position_changed)
        self.treeView.clicked.connect(self.slot_item_clicked)

        self.textEdit.setFocus()
        self.set_theme()

        # somewhat larger font by default
        font = self.textEdit.font()
        font.setPointSizeF(11)
        self.textEdit.setFont(font)

    def create_model(self):
        """Instantiate a tree model for the tree view."""
        m = self.treeView.model()
        if not m:
            m = parceqt.treemodel.TreeModel(self.builder.root)
            m.connect_debugging_builder(self.builder)
            self.treeView.setModel(m)

    def delete_model(self):
        """Delete the model and remove it from the tree."""
        m = self.treeView.model()
        if m:
            m.disconnect_debugging_builder(self.builder)
            self.treeView.setModel(None)
            m.deleteLater()

    def set_text(self, text):
        """Set the text in the text edit."""
        self.document.setPlainText(text)

    def set_root_lexicon(self, lexicon):
        """Set the root lexicon to use."""
        self.lexiconChooser.set_root_lexicon(lexicon)

    def guess_root_lexicon(self):
        """Again choose the root lexicon based on the text."""
        text = self.document.toPlainText()
        if text:
            self.set_root_lexicon(parce.find(contents=text))

    def open_file(self, filename):
        """Read a file from disk and guess the language."""
        text = read_file(filename)
        root_lexicon = parce.find(filename=filename, contents=text)
        self.set_text(text)
        self.set_root_lexicon(root_lexicon)
        c = self.textEdit.textCursor()
        c.setPosition(0)
        self.textEdit.setTextCursor(c)

    def set_theme(self, theme="default", adjust_widget=True):
        """Set the theme to use for the text edit."""
        if isinstance(theme, str):
            theme = parce.theme_by_name(theme)
        formatter = parceqt.formatter.Formatter(theme) if theme else None
        if adjust_widget:
            if formatter:
                font = formatter.font(self)
                self.textEdit.setPalette(formatter.palette(self))
            else:
                font = QApplication.font(self)
                self.textEdit.setPalette(QApplication.palette(self))
            font.setPointSizeF(self.textEdit.font().pointSizeF())  # keep size
            self.textEdit.setFont(font)
            self.highlight_current_line()
        h = parceqt.highlighter.SyntaxHighlighter.instance(self.worker)
        h.set_formatter(formatter)

    def slot_build_started(self):
        """Called when the tree builder has started a build."""
        self.treeView.setCursor(Qt.BusyCursor)

    def slot_build_updated(self):
        """Called when the tree builder has finished a build."""
        self.treeView.unsetCursor()
        self.slot_cursor_position_changed()
        self.statusBar().showMessage(", ".join(
            lexicon_names(self.builder.lexicons)))
        tree = self.worker.get_root()
        self.lexiconChooser.setToolTip(
            parceqt.treemodel.TreeModel.node_tooltip(tree))
        if self.show_updated_region_enabled:
            self.show_updated_region()

    def slot_cursor_position_changed(self):
        """Called when the text cursor moved."""
        tree = self.worker.get_root()
        if tree:
            pos = self.textEdit.textCursor().position()
            doc = parceqt.document.Document(self.document)
            token = doc.token(pos)
            if token:
                self.ancestorView.set_token_path(token)
                model = self.treeView.model()
                if model:
                    index = model.get_model_index(token)
                    self.treeView.setCurrentIndex(index)
        elif tree is not None:
            self.ancestorView.clear()
        self.highlight_current_line()

    def slot_item_clicked(self, index):
        """Called when a node in the tree view is clicked."""
        tree = self.worker.get_root()
        if tree:
            model = self.treeView.model()
            if model:
                node = self.treeView.model().get_node(index)
                cursor = self.textEdit.textCursor()
                cursor.setPosition(node.end)
                cursor.setPosition(node.pos, QTextCursor.KeepAnchor)
                self.textEdit.setTextCursor(cursor)
        self.textEdit.setFocus()

    def slot_node_clicked(self, node):
        """Called when a button in the ancestor view is clicked."""
        tree = self.worker.get_root()
        if tree and node.root() is tree:
            cursor = self.textEdit.textCursor()
            cursor.setPosition(node.end)
            cursor.setPosition(node.pos, QTextCursor.KeepAnchor)
            self.textEdit.setTextCursor(cursor)
            self.textEdit.setFocus()
            model = self.treeView.model()
            if model:
                index = model.get_model_index(node)
                self.treeView.expand(index)
                self.treeView.setCurrentIndex(index)

    def slot_root_lexicon_changed(self, lexicon):
        """Called when the root lexicon is changed."""
        parceqt.set_root_lexicon(self.document, lexicon)

    def highlight_current_line(self):
        """Highlight the current line."""
        group = QPalette.Active if self.textEdit.hasFocus(
        ) else QPalette.Inactive
        p = self.textEdit.palette()
        color = p.color(group, QPalette.AlternateBase)
        self._currentline_format.setBackground(color)
        if color != p.color(group, QPalette.Base):
            c = self.textEdit.textCursor()
            c.clearSelection()
            self.extraSelectionManager.highlight(self._currentline_format, [c])
        else:
            self.extraSelectionManager.clear(self._currentline_format)

    def show_updated_region(self):
        """Highlight the updated region for 2 seconds."""
        end = self.builder.end
        if end >= self.document.characterCount() - 1:
            end = self.document.characterCount() - 1
            if self.builder.start == 0:
                return
        c = QTextCursor(self.document)
        c.setPosition(end)
        c.setPosition(self.builder.start, QTextCursor.KeepAnchor)
        self.extraSelectionManager.highlight(self._updated_format, [c],
                                             msec=2000)

    def clear_updated_region(self):
        self.extraSelectionManager.clear(self._updated_format)

    def eventFilter(self, obj, ev):
        """Implemented to support Ctrl+wheel zooming and keybfocus handling."""
        if obj == self.textEdit:
            if ev.type() in (QEvent.FocusIn, QEvent.FocusOut):
                self.highlight_current_line()
        else:  # viewport
            if ev.type() == QEvent.Wheel and ev.modifiers(
            ) == Qt.ControlModifier:
                if ev.angleDelta().y() > 0:
                    self.textEdit.zoomIn()
                elif ev.angleDelta().y() < 0:
                    self.textEdit.zoomOut()
                return True
        return False
예제 #19
0
class KerningWindow(QWidget):

    def __init__(self, font, parent=None):
        super().__init__(parent, Qt.Window)
        self._font = font
        self._font.kerning.addObserver(
            self, "_kerningChanged", "Kerning.Changed")
        self._font.info.addObserver(self, "_fontInfoChanged", "Info.Changed")
        self.kerningView = QTreeView(self)
        self.kerningView.setModel(
            KerningDictModel(font.kerning, self.kerningView))
        self.kerningView.expandAll()
        metrics = self.kerningView.fontMetrics()
        self.kerningView.setColumnWidth(1, 8 * metrics.width("0"))
        hdr = self.kerningView.header()
        hdr.setStretchLastSection(False)
        hdr.setSectionResizeMode(0, hdr.Stretch)
        hdr.hide()

        layout = QVBoxLayout(self)
        layout.addWidget(self.kerningView)
        layout.setContentsMargins(0, 0, 0, 0)

        self.updateWindowTitle(font=font)
        self.readSettings()

    def readSettings(self):
        geometry = settings.kerningWindowGeometry()
        if geometry:
            self.restoreGeometry(geometry)

    def writeSettings(self):
        settings.setKerningWindowGeometry(self.saveGeometry())

    def updateWindowTitle(self, title=None, font=None):
        if title is None:
            title = self.tr("Kerning")
        if font is not None:
            title = "%s – %s %s" % (
                title, font.info.familyName, font.info.styleName)
        self.setWindowTitle(title)

    # -------------
    # Notifications
    # -------------

    def _kerningChanged(self, notification):
        model = self.kerningView.model()
        model.setupModelData(self._font.kerning)

    def _fontInfoChanged(self, notification):
        self.updateWindowTitle(font=self._font)

    # ----------
    # Qt methods
    # ----------

    def sizeHint(self):
        return QSize(280, 460)

    def moveEvent(self, event):
        self.writeSettings()

    resizeEvent = moveEvent

    def closeEvent(self, event):
        super().closeEvent(event)
        if event.isAccepted():
            self._font.kerning.removeObserver(self, "Kerning.Changed")
            self._font.info.removeObserver(self, "Info.Changed")
예제 #20
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.resize(800, 600)
        MainWindow.setMinimumSize(600, 400)
        icon = QIcon()
        icon.addPixmap(QPixmap("icon.png"), QIcon.Normal, QIcon.Off)
        font = QFont()
        font.setFamily("MS Sans Serif")
        font.setBold(True)
        font.setWeight(75)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QWidget(MainWindow)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menuFiles = QMenu(self.menubar)
        self.menuMark = QMenu(self.menubar)
        self.menuCommands = QMenu(self.menubar)
        self.menuNet = QMenu(self.menubar)
        self.menuShow = QMenu(self.menubar)
        self.menuConfiguration = QMenu(self.menubar)
        self.menuStart = QMenu(self.menubar)
        MainWindow.setMenuBar(self.menubar)
        self.helpMenuBar = QMenuBar(self.menubar)
        self.menuHelp = QMenu(self.helpMenuBar)
        self.helpMenuBar.addMenu(self.menuHelp)
        self.menubar.setCornerWidget(self.helpMenuBar)
        self.toolBar = QToolBar(MainWindow)
        self.toolBar.setMovable(False)
        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
        self.toolBar_2 = QToolBar(MainWindow)

        font2 = QFont()
        font2.setFamily("MS Sans Serif")
        font2.setWeight(700)
        font2.setPixelSize(8)
        font2.setBold(True)

        self.model1 = QFileSystemModel()
        self.model1.setRootPath('C:\\Windows')
        self.tree1 = QTreeView()
        self.tree1.setModel(self.model1)
        self.tree1.setRootIndex(self.model1.index("C:\\Windows\\"))
        self.tree1.setAnimated(False)
        self.tree1.setFont(font2)
        self.tree1.setIndentation(20)
        self.tree1.setSortingEnabled(True)
        self.tree1.setItemsExpandable(False)
        self.tree1.setRootIsDecorated(False)
        self.tree1.sortByColumn(0, QtCore.Qt.AscendingOrder)
        self.tree1.resize(350, 480)

        self.model2 = QFileSystemModel()
        self.model2.setRootPath('C:\\Windows\\System32')
        self.tree2 = QTreeView()
        self.tree2.setModel(self.model2)
        self.tree2.setRootIndex(self.model2.index("C:\\Windows\\System32\\"))
        self.tree2.setAnimated(False)
        self.tree2.setFont(font2)
        self.tree2.setIndentation(20)
        self.tree2.setItemsExpandable(False)
        self.tree2.setRootIsDecorated(False)
        self.tree2.setSortingEnabled(True)
        self.tree2.resize(350, 480)

        for i in range(1, self.tree1.model().columnCount()):
            self.tree1.header().hideSection(i)

        for i in range(1, self.tree2.model().columnCount()):
            self.tree2.header().hideSection(i)

        self.centralHBox = QHBoxLayout()
        self.centralHBox.addWidget(self.tree1)
        self.centralHBox.addWidget(self.tree2)
        self.centralHBox.setContentsMargins(3, 3, 3, 3)
        self.centralwidget.setLayout(self.centralHBox)

        self.toolBar_2.setMovable(False)

        self.toolBar_3 = QToolBar(MainWindow)
        self.toolBar_3.setFixedHeight(30)
        self.toolBar_3.setContentsMargins(1, 1, 1, 1)
        self.dirLabel = QLabel()
        self.dirLabel.setText('c:\\Windows>')
        self.dirBox = QComboBox()
        self.dirBox.setEditable(True)
        self.dirBox.addItem('')
        self.dirBox.setFixedWidth(470)
        self.spacer = QWidget()
        self.spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        self.toolBar_3.addWidget(self.spacer)
        self.toolBar_3.addWidget(self.dirLabel)
        self.toolBar_3.addWidget(self.dirBox)
        self.toolBar_3.setFont(font)
        self.toolBar_3.setMovable(False)
        self.toolBar_3.setStyleSheet("QToolBar{spacing: 5px;}")

        MainWindow.addToolBar(QtCore.Qt.BottomToolBarArea, self.toolBar_2)
        MainWindow.addToolBar(QtCore.Qt.BottomToolBarArea, self.toolBar_3)
        MainWindow.insertToolBarBreak(self.toolBar_3)
        self.actionIndex = QAction(MainWindow)
        icon1 = QIcon()
        icon1.addPixmap(QPixmap("help.png"), QIcon.Normal, QIcon.Off)
        self.actionIndex.setIcon(icon1)
        self.actionKeyboard = QAction(MainWindow)
        self.actionRegistration_Info = QAction(MainWindow)
        self.actionVisit_Total_CMD_s_website = QAction(MainWindow)
        self.actionAbout_Total_Commander = QAction(MainWindow)
        self.actionOption_1 = QAction(MainWindow)
        self.actionOption_2 = QAction(MainWindow)
        self.actionOption_3 = QAction(MainWindow)
        self.actionOption_4 = QAction(MainWindow)
        self.actionOption_5 = QAction(MainWindow)
        self.actionOption_6 = QAction(MainWindow)
        self.actionOption_7 = QAction(MainWindow)
        self.actionOption_8 = QAction(MainWindow)
        self.actionOption_9 = QAction(MainWindow)
        self.actionOption_10 = QAction(MainWindow)
        self.actionOption_11 = QAction(MainWindow)
        self.actionOption_12 = QAction(MainWindow)
        self.actionOption_13 = QAction(MainWindow)
        self.actionOption_14 = QAction(MainWindow)
        self.Refresh = QAction(MainWindow)
        icon2 = QIcon()
        icon2.addPixmap(QPixmap("refresh.png"), QIcon.Normal, QIcon.Off)
        self.Refresh.setIcon(icon2)
        self.action_view1 = QAction(MainWindow)
        icon3 = QIcon()
        icon3.addPixmap(QPixmap("folder_structure_1.png"), QIcon.Normal,
                        QIcon.Off)
        self.view_group = QActionGroup(MainWindow)
        self.action_view1.setIcon(icon3)
        self.action_view1.setCheckable(True)
        self.action_view2 = QAction(MainWindow)
        self.action_view2.setCheckable(True)
        self.action_view2.setChecked(True)
        icon4 = QIcon()
        icon4.addPixmap(QPixmap("folder_structure_2.png"), QIcon.Normal,
                        QIcon.Off)
        self.action_view2.setIcon(icon4)
        self.view_group.addAction(self.action_view1)
        self.view_group.addAction(self.action_view2)
        self.view_group.setExclusive(True)
        self.actionF3_View = QToolButton(MainWindow)
        self.actionF3_View.setStyleSheet("QToolButton{border: none;}")
        self.actionF3_View.setFont(font)
        self.actionF4_Edit = QToolButton(MainWindow)
        self.actionF4_Edit.setStyleSheet("QToolButton{border: none;}")
        self.actionF4_Edit.setFont(font)
        self.actionF5_Copy = QToolButton(MainWindow)
        self.actionF5_Copy.setStyleSheet("QToolButton{border: none;}")
        self.actionF5_Copy.setFont(font)
        self.actionF6_Move = QToolButton(MainWindow)
        self.actionF6_Move.setStyleSheet("QToolButton{border: none;}")
        self.actionF6_Move.setFont(font)
        self.actionF5_NewFolder = QToolButton(MainWindow)
        self.actionF5_NewFolder.setStyleSheet("QToolButton{border: none;}")
        self.actionF5_NewFolder.setFont(font)
        self.actionF8_Delete = QToolButton(MainWindow)
        self.actionF8_Delete.setStyleSheet("QToolButton{border: none;}")
        self.actionF8_Delete.setFont(font)
        self.actionAlt_F4_Exit = QToolButton(MainWindow)
        self.actionAlt_F4_Exit.setStyleSheet("QToolButton{border: none;}")
        self.actionAlt_F4_Exit.setFont(font)
        self.menuFiles.addAction(self.actionOption_1)
        self.menuFiles.addAction(self.actionOption_2)
        self.menuMark.addAction(self.actionOption_3)
        self.menuMark.addAction(self.actionOption_4)
        self.menuCommands.addAction(self.actionOption_5)
        self.menuCommands.addAction(self.actionOption_6)
        self.menuNet.addAction(self.actionOption_7)
        self.menuNet.addAction(self.actionOption_8)
        self.menuShow.addAction(self.actionOption_9)
        self.menuShow.addAction(self.actionOption_10)
        self.menuConfiguration.addAction(self.actionOption_11)
        self.menuConfiguration.addAction(self.actionOption_12)
        self.menuStart.addAction(self.actionOption_13)
        self.menuStart.addAction(self.actionOption_14)
        self.menuHelp.addAction(self.actionIndex)
        self.menuHelp.addAction(self.actionKeyboard)
        self.menuHelp.addAction(self.actionRegistration_Info)
        self.menuHelp.addAction(self.actionVisit_Total_CMD_s_website)
        self.menuHelp.addSeparator()
        self.menuHelp.addAction(self.actionAbout_Total_Commander)
        self.menubar.addAction(self.menuFiles.menuAction())
        self.menubar.addAction(self.menuMark.menuAction())
        self.menubar.addAction(self.menuCommands.menuAction())
        self.menubar.addAction(self.menuNet.menuAction())
        self.menubar.addAction(self.menuShow.menuAction())
        self.menubar.addAction(self.menuConfiguration.menuAction())
        self.menubar.addAction(self.menuStart.menuAction())
        self.helpMenuBar.addAction(self.menuHelp.menuAction())
        self.toolBar.addAction(self.Refresh)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.action_view1)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.action_view2)

        self.separator1 = QFrame()
        self.separator1.setFrameShape(QFrame.VLine)
        self.separator1.setFrameShadow(QFrame.Sunken)
        self.separator2 = QFrame()
        self.separator2.setFrameShape(QFrame.VLine)
        self.separator2.setFrameShadow(QFrame.Sunken)
        self.separator3 = QFrame()
        self.separator3.setFrameShape(QFrame.VLine)
        self.separator3.setFrameShadow(QFrame.Sunken)
        self.separator4 = QFrame()
        self.separator4.setFrameShape(QFrame.VLine)
        self.separator4.setFrameShadow(QFrame.Sunken)
        self.separator5 = QFrame()
        self.separator5.setFrameShape(QFrame.VLine)
        self.separator5.setFrameShadow(QFrame.Sunken)
        self.separator6 = QFrame()
        self.separator6.setFrameShape(QFrame.VLine)
        self.separator6.setFrameShadow(QFrame.Sunken)

        self.toolbarHBoxWidget = QWidget()
        self.toolbarHBoxWidget.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Preferred)
        self.toolbarHBox = QGridLayout()
        self.toolbarHBoxWidget.setLayout(self.toolbarHBox)
        self.toolbarHBox.addWidget(self.actionF3_View, 0, 0)
        self.toolbarHBox.addWidget(self.separator1, 0, 1)
        self.toolbarHBox.addWidget(self.actionF4_Edit, 0, 2)
        self.toolbarHBox.addWidget(self.separator2, 0, 3)
        self.toolbarHBox.addWidget(self.actionF5_Copy, 0, 4)
        self.toolbarHBox.addWidget(self.separator3, 0, 5)
        self.toolbarHBox.addWidget(self.actionF6_Move, 0, 6)
        self.toolbarHBox.addWidget(self.separator4, 0, 7)
        self.toolbarHBox.addWidget(self.actionF5_NewFolder, 0, 8)
        self.toolbarHBox.addWidget(self.separator5, 0, 9)
        self.toolbarHBox.addWidget(self.actionF8_Delete, 0, 10)
        self.toolbarHBox.addWidget(self.separator6, 0, 11)
        self.toolbarHBox.addWidget(self.actionAlt_F4_Exit, 0, 12)
        self.toolBar_2.addWidget(self.toolbarHBoxWidget)
        self.toolBar_2.setFixedHeight(40)

        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(
            "Total Commander 7.50a - Politechnika Lodzka - Wydzial EEIA")
        self.menuFiles.setTitle("Files")
        self.menuMark.setTitle("Mark")
        self.menuCommands.setTitle("Commands")
        self.menuNet.setTitle("Net")
        self.menuShow.setTitle("Show")
        self.menuConfiguration.setTitle("Configuration")
        self.menuStart.setTitle("Start")
        self.menuHelp.setTitle("Help")
        self.toolBar.setWindowTitle("toolBar")
        self.toolBar_2.setWindowTitle("toolBar_2")
        self.actionIndex.setText("Index")
        self.actionIndex.setIconText("Index")
        self.actionIndex.setShortcut("F1")
        self.actionKeyboard.setText("Keyboard")
        self.actionRegistration_Info.setText("Registration Info")
        self.actionVisit_Total_CMD_s_website.setText(
            "Visit Totalcmd\'s Web Site")
        self.actionAbout_Total_Commander.setText("About Total Commander...")
        self.actionOption_1.setText("Option 1")
        self.actionOption_2.setText("Option 2")
        self.actionOption_3.setText("Option 1")
        self.actionOption_4.setText("Option 2")
        self.actionOption_5.setText("Option 1")
        self.actionOption_6.setText("Option 2")
        self.actionOption_7.setText("Option 1")
        self.actionOption_8.setText("Option 2")
        self.actionOption_9.setText("Option 1")
        self.actionOption_10.setText("Option 2")
        self.actionOption_11.setText("Option 1")
        self.actionOption_12.setText("Option 2")
        self.actionOption_13.setText("Option 1")
        self.actionOption_14.setText("Option 2")
        self.Refresh.setText("Refresh")
        self.action_view1.setText("View 1")
        self.action_view2.setText("View 2")
        self.actionF3_View.setText("F3 View")
        self.actionF3_View.setShortcut("F3")
        self.actionF4_Edit.setText("F4 Edit")
        self.actionF4_Edit.setShortcut("F4")
        self.actionF5_Copy.setText("F5 Copy")
        self.actionF5_Copy.setShortcut("F5")
        self.actionF6_Move.setText("F6 Move")
        self.actionF6_Move.setShortcut("F6")
        self.actionF5_NewFolder.setText("F7 NewFolder")
        self.actionF5_NewFolder.setShortcut("F7")
        self.actionF8_Delete.setText("F8 Delete")
        self.actionF8_Delete.setShortcut("F8")
        self.actionAlt_F4_Exit.setText("Alt+F4 Exit")
        self.actionAlt_F4_Exit.setShortcut("Ctrl+Alt+F4")
예제 #21
0
class VGExplorer(QWidget):
    def __init__(self, app, config):
        super().__init__()

        self.clipboard = app.clipboard()

        self.config = config
        self.setWindowTitle(config.server_name)

        rootPath = self.get_cwd()

        self.model = QFileSystemModel()
        index = self.model.setRootPath(rootPath)

        self.tree = QTreeView()
        self.tree.setModel(self.model)

        self.tree.setRootIndex(index)

        self.tree.setAnimated(False)
        self.tree.setIndentation(20)

        self.tree.hideColumn(1)
        self.tree.hideColumn(2)
        self.tree.hideColumn(3)
        self.tree.setHeaderHidden(True)

        self.tree.doubleClicked.connect(self.on_double_click)
        self.tree.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.tree.customContextMenuRequested.connect(self.show_menu)

        windowLayout = QVBoxLayout()
        windowLayout.addWidget(self.tree)
        self.setLayout(windowLayout)

        # Shortcut for hide
        self.shortcut = QShortcut(QKeySequence(config.toggle_key), self)
        self.shortcut.activated.connect(self.hide)

        if not config.hidden:
            self.show()

    def toggle_show(self):
        if self.isHidden():
            self.show()
        else:
            self.hide()

    def open_file(self, index):
        path = self.sender().model().filePath(index)
        if os.path.isfile(path):
            subprocess.call([
                self.config.vim, "--servername", self.config.server_name,
                "--remote", path
            ])

    def get_cwd(self):
        path = subprocess.check_output([
            self.config.vim, "--servername", self.config.server_name,
            "--remote-expr", "getcwd()"
        ])
        return path.decode("utf-8").strip()

    def on_double_click(self, index):
        self.open_file(index)

    def show_menu(self, clickPos):
        index = self.tree.indexAt(clickPos)
        selected_path = self.tree.model().filePath(index)
        enclosing_dir = self.find_enclosing_dir(selected_path)

        menu = QMenu(self)
        openAction = menu.addAction("Open")
        newFolderAction = menu.addAction("New Folder")
        newFileAction = menu.addAction("New File")
        copyAction = menu.addAction("Copy")
        pasteAction = menu.addAction("Paste")
        renameAction = menu.addAction("Rename")
        fileInfo = menu.addAction("Properties")

        menuPos = QPoint(clickPos.x() + 15, clickPos.y() + 15)
        action = menu.exec_(self.mapToGlobal(menuPos))

        if action == openAction:
            self.open_file(index)

        elif action == newFolderAction:
            path = self.get_dialog_str("New Folder",
                                       "Enter name for new folder:")
            if path:
                self.mkdir(os.path.join(enclosing_dir, path))

        elif action == newFileAction:
            path = self.get_dialog_str("New File", "Enter name for new file:")
            if path:
                self.touch(os.path.join(enclosing_dir, path))

        elif action == renameAction:
            path = self.get_dialog_str("Rename File", "Enter new name:")

            # Naive validation
            if "/" in path:
                msg = QMessageBox()
                msg.setIcon(QMessageBox.Critical)
                msg.setText("Filename cannot contain '/'")
                msg.setWindowTitle("Error")
                msg.exec_()
                return

            new_path = os.path.join(enclosing_dir, path)

            self.move(selected_path, new_path)

        elif action == copyAction:
            mime_data = QMimeData()

            # TODO: support multiple selections
            mime_data.setUrls([QUrl(Path(selected_path).as_uri())])
            self.clipboard.setMimeData(mime_data)

        elif action == pasteAction:
            mime_data = self.clipboard.mimeData()
            if not mime_data:
                return

            if mime_data.hasUrls():
                for src_url in mime_data.urls():
                    self.copy(src_url.path(), enclosing_dir)

    def get_dialog_str(self, title, message):
        text, confirm = QInputDialog.getText(self, title, message,
                                             QLineEdit.Normal, "")
        if confirm and text != '':
            return text
        return None

    '''
    Filesystem and OS Functions
    '''

    def copy(self, src_file, dest_dir):
        src_basename = os.path.basename(src_file)
        dest_file = os.path.join(dest_dir, src_basename)

        # First confirm file doesn't already exist
        if os.path.exists(dest_file):
            print(f"Destination path '{dest_file}' already exists, skipping")
            return

        print(f"Pasting {src_file} -> {dest_file}")
        shutil.copy2(src_file, dest_file)

    def move(self, old_path, new_path):
        os.rename(old_path, new_path)

    def mkdir(self, path):
        if not os.path.exists(path):
            os.mkdir(path)

    def touch(self, path):
        subprocess.run(["touch", path])

    def find_enclosing_dir(self, path):
        '''
        If path is file, return dir it is in
        If path is dir, return itself
        '''
        if os.path.isdir(path):
            return path

        if os.path.isfile(path):
            return str(Path(path).parent)
예제 #22
0
파일: TransCodaEditor.py 프로젝트: ag-sd/py
class EncoderSelector(QComboBox):
    __PATH_SEPARATOR__ = " → "
    _PATH_ROLE = 1
    _DETAILS_ROLE = 2

    class EncoderModel(QStandardItemModel):
        def __init__(self, json_file, disable_selections=False):
            super().__init__()
            self.disable_selections = disable_selections
            self.json_file = json_file
            self.json = None
            self.reload()

        def reload(self):
            with open(self.json_file) as config:
                self.json = json.load(config)
                self.beginResetModel()
                self.clear()
                self._build_descendents(self.invisibleRootItem(), self.json,
                                        self.disable_selections)
                self.endResetModel()

        def get_item(self, model_index):
            item = self.itemFromIndex(model_index)
            if item:
                return item.text()
            return None

        def del_item(self, media_type, encoder_group, name):
            del self.json[media_type][encoder_group][name]
            # Clean up ancestors if they dont have any children
            if len(self.json[media_type][encoder_group].keys()) == 0:
                del self.json[media_type][encoder_group]
            if len(self.json[media_type].keys()) == 0:
                del self.json[media_type]

        def add_item(self, media_type, group, name, extension, executable,
                     command):
            if media_type not in self.json:
                self.json[media_type] = {}
            if group not in self.json[media_type]:
                self.json[media_type][group] = {}
            self.json[media_type][group][name] = {
                "extension": extension,
                "executable": executable,
                "command": command
            }

        def backup_and_save(self):
            # Backup current config
            backup_config_file()
            # Save new config
            with open(self.json_file, "w") as config:
                json.dump(self.json, config, indent=4)
            self.reload()

        @staticmethod
        def _build_descendents(parent, _json, disable_selections):
            encoder_keys = {"extension", "executable", "command"}
            intersection = set(_json.keys()) & encoder_keys
            if not intersection:
                # add node and build further
                for key in _json:
                    section_root = QStandardItem(key)
                    parent.appendRow(section_root)
                    if disable_selections:
                        parent.setSelectable(False)
                    EncoderSelector.EncoderModel._build_descendents(
                        section_root, _json[key], disable_selections)
            else:
                if len(intersection) < 3:
                    raise SyntaxError(
                        f"Missing value(s) {encoder_keys - intersection} in node {parent.text()}"
                    )
                else:
                    path = ""
                    item = parent
                    while item.parent() is not None:
                        path = f"{EncoderSelector.__PATH_SEPARATOR__}{item.text()}" + path
                        item = item.parent()
                    path = f"{item.text()}" + path
                    parent.setData(path,
                                   Qt.UserRole + EncoderSelector._PATH_ROLE)
                    parent.setData(_json,
                                   Qt.UserRole + EncoderSelector._DETAILS_ROLE)

    encoder_changed = pyqtSignal('PyQt_PyObject', 'PyQt_PyObject')

    def __init__(self):
        super().__init__()
        self.tree_view = QTreeView(self)
        self.tree_view.setEditTriggers(QTreeView.NoEditTriggers)
        self.tree_view.setSelectionBehavior(QTreeView.SelectRows)
        self.tree_view.setWordWrap(True)
        self.tree_view.setHeaderHidden(True)
        self.setView(self.tree_view)
        self.encoder_model = EncoderSelector.EncoderModel(
            get_config_file(), disable_selections=True)
        self.setModel(self.encoder_model)
        self.refresh_encoders()
        self._selected_encoder = ""

    def paintEvent(self, event):
        style = QApplication.style()
        opt = QStyleOptionComboBox()
        opt.rect = self.rect()
        self.initStyleOption(opt)
        painter = QPainter(self)
        painter.save()
        style.drawComplexControl(QStyle.CC_ComboBox, opt, painter)
        opt.currentText = self._encoder_path()
        style.drawControl(QStyle.CE_ComboBoxLabel, opt, painter)
        painter.restore()

    def hidePopup(self):
        super(EncoderSelector, self).hidePopup()
        selected_index = self.tree_view.selectionModel().currentIndex()
        if selected_index:
            encoder = self.tree_view.model().get_item(selected_index)
            if encoder:
                self._selected_encoder = encoder
                self.encoder_changed.emit(self._encoder_path(),
                                          self._encoder_details())

    def get_encoder(self):
        return self._encoder_path(), self._encoder_details()

    def add_encoder(self, media_type, encoder_group, name, command, executable,
                    extension):
        self.encoder_model.add_item(media_type, encoder_group, name, extension,
                                    executable, command)
        self.encoder_model.backup_and_save()
        self.refresh_encoders()

    def del_encoder(self, media_type, encoder_group, name):
        self.encoder_model.del_item(media_type, encoder_group, name)
        self.encoder_model.backup_and_save()
        self.refresh_encoders()

    def update_encoder(self, media_type, encoder_group, name, command,
                       executable, extension):
        self.encoder_model.del_item(media_type, encoder_group, name)
        self.encoder_model.add_item(media_type, encoder_group, name, extension,
                                    executable, command)
        self.encoder_model.backup_and_save()
        self.refresh_encoders()

    def refresh_encoders(self):
        self.encoder_model.reload()
        self.tree_view.expandAll()

    def select_encoder(self, encoder_name):
        match = self._find_encoder(encoder_name)
        if match:
            self._selected_encoder = encoder_name
        self.encoder_changed.emit(self._encoder_path(),
                                  self._encoder_details())

    def _encoder_path(self):
        if self._selected_encoder:
            match = self._find_encoder(self._selected_encoder)
            if match:
                return match[0].data(Qt.UserRole + self._PATH_ROLE)
        return None

    def _encoder_details(self):
        if self._selected_encoder:
            match = self._find_encoder(self._selected_encoder)
            if match:
                return match[0].data(Qt.UserRole + self._DETAILS_ROLE)
        return None

    def _find_encoder(self, encoder_name):
        return self.model().match(self.model().index(0, 0),
                                  Qt.UserRole + self._PATH_ROLE, encoder_name,
                                  1, Qt.MatchEndsWith | Qt.MatchRecursive)
예제 #23
0
class CatalogMainWindow(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        # Структура главного окна
        # Создаем меню
        self.menu_bar = self.menuBar()

        # Создаем блоки меню
        # Блок меню 'Учет движения товаров'

        self.gma_menu = self.menu_bar.addMenu('Учет движения товаров')
        self.gma_menu.setEnabled(False)
        self.ro_open_btn = QAction(self)
        self.ro_open_btn.setText('Приходный ордер')
        self.wo_open_btn = QAction(self)
        self.wo_open_btn.setText('Расходный ордер')
        self.gma_menu.addAction(self.ro_open_btn)
        self.gma_menu.addAction(self.wo_open_btn)

        # Блок меню 'Отчеты'

        self.r_menu = self.menu_bar.addMenu('Отчеты')
        self.r_menu.setEnabled(False)
        self.tws_report_btn = QAction(self)
        self.tws_report_btn.setText('Операции с поставщиками')
        self.gis_report_btn = QAction(self)
        self.gis_report_btn.setText('Товары в наличии')
        self.r_menu.addAction(self.tws_report_btn)
        self.r_menu.addAction(self.gis_report_btn)

        # Блок меню 'Справочники'
        self.d_menu = self.menu_bar.addMenu('Справочники')
        self.d_menu.setEnabled(False)

        self.u_catalog_btn = QAction(self)
        self.u_catalog_btn.setText('Пользователи')

        self.r_catalog_btn = QAction(self)
        self.r_catalog_btn.setText('Права пользователей')

        self.c_catalog_btn = QAction(self)
        self.c_catalog_btn.setText('Категории')

        self.n_catalog_btn = QAction(self)
        self.n_catalog_btn.setText('Номенклатура товаров')

        self.un_catalog_btn = QAction(self)
        self.un_catalog_btn.setText('Единицы измерения')

        self.s_catalog_btn = QAction(self)
        self.s_catalog_btn.setText('Поставщики')

        self.p_catalog_btn = QAction(self)
        self.p_catalog_btn.setText('Должности')

        self.e_catalog_btn = QAction(self)
        self.e_catalog_btn.setText('Сотрудники')

        self.d_menu.addAction(self.u_catalog_btn)
        self.d_menu.addAction(self.r_catalog_btn)
        self.d_menu.addAction(self.c_catalog_btn)
        self.d_menu.addAction(self.n_catalog_btn)
        self.d_menu.addAction(self.un_catalog_btn)
        self.d_menu.addAction(self.s_catalog_btn)
        self.d_menu.addAction(self.p_catalog_btn)
        self.d_menu.addAction(self.e_catalog_btn)

        # Верхний виджет с полным путем до файла БД

        self.db_lbl = QLabel()
        self.db_lbl.setText('Путь до БД:')
        self.db_lbl.setStyleSheet("border-style: none;" "font-size: 10pt;")
        self.db_path_lbl = QLineEdit()
        self.db_path_lbl.setStyleSheet(
            "background-color: white;"
            "font-size: 10pt;"
            "color: green;")
        self.db_path_lbl.setFixedSize(700, 25)
        self.db_path_lbl.setEnabled(False)
        self.db_path_btn = QPushButton('...')
        self.db_path_btn.setFixedSize(25, 25)
        self.db_path_btn.setStyleSheet(
            "border-width: 1px;"
            "border-style: solid;"
            "border-color: dimgray;"
            "border-radius: 5px;"
            "background-color: gainsboro;")
        self.db_path_btn.clicked.connect(self.on_db_path_btn_clicked)

        self.tdw = QDockWidget()
        self.tdw.setFixedHeight(65)
        self.tdw.setFeatures(self.tdw.NoDockWidgetFeatures)
        self.tdw_grid = QGridLayout()
        self.tdw_grid.setColumnStretch(3, 1)
        self.tdw_grid.addWidget(self.db_lbl)
        self.tdw_grid.addWidget(self.db_path_lbl)
        self.tdw_grid.addWidget(self.db_path_btn)
        self.tdw_frame = QFrame()
        self.tdw_frame.setStyleSheet(
            "background-color: ghostwhite;"
            "border-width: 0.5px;"
            "border-style: solid;"
            "border-color: silver;")
        self.tdw_frame.setLayout(self.tdw_grid)
        self.tdw.setWidget(self.tdw_frame)
        self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.tdw)

        # Левый виджет с окном каталога продукции

        self.ldw = QDockWidget()
        self.ldw.setFixedSize(500, 570)
        self.ldw.setFeatures(self.ldw.NoDockWidgetFeatures)
        self.ldw_tree = QTreeView()
        self.ldw_tree.setFixedSize(500, 530)
        self.ldw_tree.setHeaderHidden(True)
        self.ldw_tree_model = QStandardItemModel()
        self.ldw_tree.setModel(self.ldw_tree_model)
        self.ldw_tree.clicked.connect(self.on_ldw_tree_clicked)
        self.outf_scroll = QScrollArea()
        self.outf_scroll.setWidget(self.ldw_tree)
        self.ldw.setWidget(self.outf_scroll)
        self.ldw.setWindowTitle("Каталог продукции")

        # Центральный виджет с карточкой товара

        self.cdw = QDockWidget()
        self.cdw.setFeatures(self.cdw.NoDockWidgetFeatures)
        #self.setCentralWidget(self.cdw)

        # Нижний виджет со служебными сообщениями

        self.smdw = QDockWidget()
        self.smdw.setFixedHeight(140)
        self.smdw.setFeatures(self.smdw.NoDockWidgetFeatures)
        self.sm_list_widget = QListWidget()
        self.smdw.setWidget(self.sm_list_widget)
        self.smdw.setWindowTitle("Служебные сообщения")

    # Функции главного окна
    # Функция выбора файла базы данных
    def on_db_path_btn_clicked(self):
        global db_path
        db_path, _filter = QFileDialog.getOpenFileName(
            None, "Open Data File", '.', "(*.sqlite)")
        self.db_path_lbl.setText(db_path)
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.ldw)
        self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.smdw)

        # Создаем все таблицы, которые нужны
        con = QtSql.QSqlDatabase.addDatabase('QSQLITE')
        con.setDatabaseName(db_path)
        con.open()

        if 'rules' not in con.tables():

            query = QtSql.QSqlQuery()
            query.exec(
                "CREATE TABLE rules(rule STRING UNIQUE, description STRING)")

            r1 = "admin"
            d1 = "Доступны все опции"
            query.exec(
                "INSERT INTO rules(rule, description) VALUES ('%s','%s')" %
                (r1, d1))

            r2 = "Кладовщик"
            d2 = "Доступны опции кладовщика"
            query.exec(
                "INSERT INTO rules(rule, description) VALUES ('%s','%s')" %
                (r2, d2))

        if 'nomenclature' not in con.tables():
            query = QtSql.QSqlQuery()
            query.exec(
                "CREATE TABLE nomenclature(item_numb INTEGER UNIQUE PRIMARY KEY NOT NULL, \
                item_name STRING NOT NULL, item_unit STRING REFERENCES units (unit) NOT NULL, \
                item_cat STRING REFERENCES categories (category) NOT NULL, item_img BLOB)")

        if 'units' not in con.tables():
            query = QtSql.QSqlQuery()
            query.exec("CREATE TABLE units(unit STRING PRIMARY KEY \
            UNIQUE NOT NULL)")

        if 'categories' not in con.tables():
            query = QtSql.QSqlQuery()
            query.exec(
                "CREATE TABLE categories(category STRING PRIMARY KEY UNIQUE \
                NOT NULL, description STRING NOT NULL)")

        # Создаем таблицу 'users', если не существует
        if 'users' not in con.tables():
            query = QtSql.QSqlQuery()
            query.exec(
                "CREATE TABLE users(id_user INTEGER PRIMARY KEY AUTOINCREMENT \
                unique NOT NULL, \
                login STRING UNIQUE NOT NULL, password STRING NOT NULL, \
                name TEXT NOT NULL, \
                rules STRING REFERENCES rules (rule) NOT NULL)")

        if 'suppliers' not in con.tables():
            query = QtSql.QSqlQuery()
            query.exec("CREATE TABLE suppliers( \
                id_supplier INTEGER UNIQUE PRIMARY KEY AUTOINCREMENT NOT NULL, \
                supplier STRING UNIQUE NOT NULL, \
                ownerchipform STRING NOT NULL, \
                address STRING NOT NULL, \
                phone STRING NOT NULL, \
                email STRING NOT NULL \
            )")

        if 'positions' not in con.tables():
            query = QtSql.QSqlQuery()
            query.exec(
                "CREATE TABLE positions(position STRING PRIMARY KEY UNIQUE \
                NOT NULL)")

        if 'employee' not in con.tables():
            query = QtSql.QSqlQuery()
            query.exec(
                "CREATE TABLE employee(employee_id INTEGER UNIQUE PRIMARY KEY AUTOINCREMENT, \
                fio STRING NOT NULL, \
                position STRING REFERENCES positions (position) NOT NULL)")

        con.close()



        con = sqlite3.connect(db_path)
        cur = con.cursor()
        sql_cats_select = """\
        SELECT DISTINCT item_cat FROM nomenclature
        """
        cur.execute(sql_cats_select)
        arr = cur.fetchall()
        #print(arr)

        for cat in arr:
            sql_items_select = "SELECT item_name FROM nomenclature \
            WHERE item_cat = ?"
            cur.execute(sql_items_select, [cat[0]])
            items = cur.fetchall()
            #print(items)
            parent_item = QStandardItem(cat[0])
            self.ldw_tree_model.appendRow(parent_item)

            j = 0

            for item in items:
                child_item = QStandardItem(item[0])
                parent_item.setChild(j, 0, child_item)
                j = j + 1


        cur.close()
        con.close()

        self.gma_menu.setEnabled(True)
        self.r_menu.setEnabled(True)
        self.d_menu.setEnabled(True)

        self.ro_open_btn.triggered.connect(
            lambda: documents_class.on_ro_doc_btn(
                self, db_path))
        self.wo_open_btn.triggered.connect(
            lambda: documents_class.on_wo_doc_btn(
                self, db_path))

        self.gis_report_btn.triggered.connect(
            lambda: gis_report_class.on_gis_report_btn(
                self, db_path))

        self.tws_report_btn.triggered.connect(
            lambda: tws_report_class.on_tws_report_btn(
                self, db_path))

        self.u_catalog_btn.triggered.connect(
            lambda: directories_class.on_u_catalog_btn(
                self, db_path))
        self.r_catalog_btn.triggered.connect(
            lambda: directories_class.on_r_catalog_btn(
                self, db_path))
        self.c_catalog_btn.triggered.connect(
            lambda: directories_class.on_c_catalog_btn(
                self, db_path))
        self.n_catalog_btn.triggered.connect(
            lambda: directories_class.on_n_catalog_btn(
                self, db_path))
        self.un_catalog_btn.triggered.connect(
            lambda: directories_class.on_un_catalog_btn(
                self, db_path))
        self.s_catalog_btn.triggered.connect(
            lambda: directories_class.on_s_catalog_btn(
                self, db_path))
        self.p_catalog_btn.triggered.connect(
            lambda: directories_class.on_p_catalog_btn(
                self, db_path))
        self.e_catalog_btn.triggered.connect(
            lambda: directories_class.on_e_catalog_btn(
                self, db_path))

    # Функция выбора товара из каталога-дерева
    def on_ldw_tree_clicked(self):
        #print('вах')


        try:
            current_index = self.ldw_tree.currentIndex()
            file_name = self.ldw_tree.model().data(current_index)
            con = sqlite3.connect(db_path)
            cur = con.cursor()
            sql_item_select = "SELECT item_name FROM nomenclature \
            WHERE item_name = ?"
            cur.execute(sql_item_select, [file_name])
            item = cur.fetchone()
            if item:
                self.setCentralWidget(self.cdw)
                self.cdw.setWindowTitle("Карточка товара")
                item_card = item_card_class(self, db_path, file_name)
                self.cdw.setWidget(item_card)
            cur.close()
            con.close()
        except Exception as e:
            print('Ошибка:\n', traceback.format_exc())
예제 #24
0
class TestDialog(QDialog):
    def __init__(self, data):

        super(TestDialog, self).__init__()

        self.data = copy.deepcopy(data)

        # Layout
        btOk = QPushButton("OK")
        btCancel = QPushButton("Cancel")
        self.tree = QTreeView()
        hbox = QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(btOk)
        hbox.addWidget(btCancel)
        vbox = QVBoxLayout()
        vbox.addLayout(hbox)
        vbox.addWidget(self.tree)
        self.setLayout(vbox)
        self.setGeometry(300, 300, 600, 400)

        # Button signals
        btCancel.clicked.connect(self.reject)
        btOk.clicked.connect(self.accept)

        # Tree view
        self.tree.setModel(QStandardItemModel())
        self.tree.setAlternatingRowColors(True)
        self.tree.setSortingEnabled(True)
        self.tree.setHeaderHidden(False)
        self.tree.setSelectionBehavior(QAbstractItemView.SelectItems)

        self.tree.model().setHorizontalHeaderLabels(['Parameter', 'Value'])

        for x in self.data:
            if not self.data[x]:
                continue
            parent = QStandardItem(x)
            parent.setFlags(QtCore.Qt.NoItemFlags)
            for y in self.data[x]:
                value = self.data[x][y]
                child0 = QStandardItem(y)
                child0.setFlags(QtCore.Qt.NoItemFlags
                                | QtCore.Qt.ItemIsEnabled)
                child1 = QStandardItem(repr(value))
                child1.setFlags(QtCore.Qt.ItemIsEnabled
                                | QtCore.Qt.ItemIsEditable
                                | ~QtCore.Qt.ItemIsSelectable)
                parent.appendRow([child0, child1])
            self.tree.model().appendRow(parent)

        self.tree.expandAll()
        self.tree.model().itemChanged.connect(self.handleItemChanged)

    def get_data(self):
        return self.data

    def handleItemChanged(self, item):
        parent = self.data[item.parent().text()]
        key = item.parent().child(item.row(), 0).text()
        parent[key] = eval(item.text())
예제 #25
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(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)

        btnCancel.connect(self.close)
        btnAdd.connect(self._select_path)
        self._list.currentItemChanged['QTreeWidgetItem*', 'QTreeWidgetItem*'].connect(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.setSectionResizeMode(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()
예제 #26
0
class CSearchWidget(QWidget):
    def __init__(self, bpID, parent=None):
        super(CSearchWidget, self).__init__(parent)
        self.m_BPID = bpID
        self.m_Status = define.FULL_MATCH
        self.m_Search = None
        self.m_CaseSensitively = None
        self.m_WholeWords = None
        self.m_Regular = None
        self.m_Tree = None
        self._InitUI()
        self._InitSignal()
        self.m_BtnMatch.click()

    def _InitUI(self):
        self.setWindowTitle("搜索")
        self.setWindowFlags(Qt.Popup | Qt.Sheet)
        vBox = QVBoxLayout(self)
        hBox = QHBoxLayout()
        self.m_Search = QLineEdit(self)
        self.m_Search.setFocusPolicy(Qt.ClickFocus)
        self.m_Search.setClearButtonEnabled(True)
        self.m_Search.setPlaceholderText("搜索节点或者槽名称")
        hBox.addWidget(self.m_Search)

        self.m_BtnMatch = QPushButton("全匹配", self)
        self.m_BtnMatch.setToolTip("点击切换全匹配/模糊匹配")
        hBox.addWidget(self.m_BtnMatch)

        vBox.addLayout(hBox)

        line = QFrame(self)
        line.setMinimumSize(QSize(0, 2))
        line.setMaximumSize(QSize(1234567, 2))
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)
        vBox.addWidget(line)

        self.m_Tree = QTreeView(self)
        self.m_Tree.setHeaderHidden(True)
        self.m_Tree.setModel(QStandardItemModel(self))
        self.m_Tree.setEditTriggers(QAbstractItemView.NoEditTriggers)
        vBox.addWidget(self.m_Tree)
        # self.setLayout(vBox)

    def _InitSignal(self):
        self.m_BtnMatch.clicked.connect(self.S_ChangeMatch)
        self.m_Search.returnPressed.connect(self.S_Search)
        self.m_Tree.doubleClicked.connect(self.S_FocusItem)
        GetSignal().UI_SHOW_BP_SEARCH.connect(self.S_ShowBPSearch)

    def S_ChangeMatch(self):
        self.m_Status ^= define.FUZZY_MATCH
        if self.m_Status & define.FUZZY_MATCH:
            self.m_BtnMatch.setText("模糊匹配")
        else:
            self.m_BtnMatch.setText("全匹配")

    def S_ShowBPSearch(self, bpID):
        if bpID == self.m_BPID:
            self.show()

    def S_Search(self):
        sText = self.m_Search.text()
        if not sText:
            return
        dInfo = interface.GetSearchInfo(self.m_BPID, sText,
                                        self.m_Status & define.FUZZY_MATCH)
        parentModel = self.m_Tree.model()
        parentModel.clear()
        for graphicID, dNode in dInfo.items():
            graphicName = interface.GetGraphicAttr(
                graphicID, eddefine.GraphicAttrName.NAME)
            tInfo = (define.SearchTreeItemType.GRAPHIC, graphicID)
            oGItem = CStandardItem(graphicName, tInfo)
            parentModel.appendRow(oGItem)
            for nodeID, lstPin in dNode.items():
                nodeName = interface.GetNodeAttr(
                    nodeID, bddefine.NodeAttrName.DISPLAYNAME)
                tInfo = (define.SearchTreeItemType.NODE, nodeID)
                oNItem = CStandardItem(nodeName, tInfo)
                oGItem.appendRow(oNItem)
                for pinID in lstPin:
                    pinName = interface.GetPinAttr(
                        pinID, bddefine.PinAttrName.DISPLAYNAME)
                    tInfo = (define.SearchTreeItemType.PIN, pinID)
                    oPItem = CStandardItem(pinName, tInfo)
                    oNItem.appendRow(oPItem)
        self.m_Tree.expandAll()

    def S_FocusItem(self, oModelIndex):
        """
        oModelIndex QModelIndex
        self.model() QStandardItemModel
        """
        item = self.m_Tree.model().itemFromIndex(oModelIndex)
        if not item:
            return
        iItemType, ID = item.GetInfo()
        if iItemType == define.SearchTreeItemType.GRAPHIC:
            GetSignal().UI_FOCUS_GRAPHIC.emit(self.m_BPID, ID)
        else:
            if iItemType == define.SearchTreeItemType.PIN:
                ID = interface.GetNodeIDByPinID(ID)
            graphicID = interface.GetGraphicIDByNodeID(ID)
            GetSignal().UI_FOCUS_NODE.emit(graphicID, ID)
class Broswer_Img(QMainWindow):
    """
    选择图片文件并且预览,自动匹配多图的情况和背景图片
    """
    Close_Signal = pyqtSignal(list)

    def __init__(self, *args, **kwargs):
        QMainWindow.__init__(self, *args, **kwargs)
        self.Current_Dir = QDir.home().absolutePath()
        #self.Current_Dir = Wk_Dir
        self.setWindowTitle("Select Imags")
        self.setWindowModality(Qt.ApplicationModal)
        self.Left_Dock_Code()
        self.Central_Frame_Code()
        self.Right_Dock_Code()
        self.connect_Signals()

        self.wb_nav_left.setEnabled(False)
        self.wb_nav_right.setEnabled(False)
        self.bkgd_nav_left.setEnabled(False)
        self.bkgd_nav_right.setEnabled(False)

        #self.setGeometry(200, 200, 1000, 600)
        #self.setMaximumSize(QSize(1000, 600))

    def Left_Dock_Code(self):
        self.Left_Frame = QFrame(self)
        self.Model = QFileSystemModel()
        self.Model.setNameFilterDisables(False)
        self.Model.setRootPath(self.Current_Dir)
        #self.Model.setSorting(QDir.DirsFirst | QDir.IgnoreCase | QDir.Name)
        self.Model.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs
                             | QDir.AllEntries)
        self.Model.setNameFilters(['*.tif'])
        self.Tree = QTreeView(self.Left_Frame)
        self.Tree.setModel(self.Model)
        self.Tree.setRootIndex(self.Model.index(self.Current_Dir))
        self.Tree.expandAll()
        self.Dir_Select = QPushButton("Select a Folder", self.Left_Frame)
        layout = QVBoxLayout()
        layout.addWidget(self.Tree)
        layout.addWidget(self.Dir_Select)
        self.Left_Frame.setLayout(layout)
        self.Left_Dock = QDockWidget('Broswer Images', self)
        self.Left_Dock.setWidget(self.Left_Frame)
        self.Left_Dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.Dir_Select.clicked.connect(self.dir_selection)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.Left_Dock)

    def Central_Frame_Code(self):
        self.Central_Frame = QFrame(self)
        layout = QGridLayout()
        self.wb_label = QLabel(self.Central_Frame)
        self.bkgd_label = QLabel(self.Central_Frame)
        #self.wb_label.setMaximumHeight(30)
        self.wb_label.setWordWrap(True)

        self.wb = QLabel(self.Central_Frame)
        self.wb.setScaledContents(True)
        self.bkgd = QLabel(self.Central_Frame)
        self.bkgd.setScaledContents(True)
        self.wb.setMaximumSize(QSize(300, 300))
        self.bkgd.setMaximumSize(QSize(300, 300))

        self.wb_navigator = QFrame(self.Central_Frame)
        self.wb_nav_left = QPushButton('<--', self.wb_navigator)
        self.wb_nav_right = QPushButton('-->', self.wb_navigator)
        nav_layout = QHBoxLayout()
        nav_layout.addWidget(self.wb_nav_left)
        nav_layout.addWidget(self.wb_nav_right)
        self.wb_navigator.setLayout(nav_layout)
        self.wb_navigator.setMaximumHeight(60)

        self.bkgd_navigator = QFrame(self.Central_Frame)
        self.bkgd_nav_left = QPushButton('<--', self.bkgd_navigator)
        self.bkgd_nav_right = QPushButton('-->', self.bkgd_navigator)
        nav_layout2 = QHBoxLayout()
        nav_layout2.addWidget(self.bkgd_nav_left)
        nav_layout2.addWidget(self.bkgd_nav_right)
        self.bkgd_navigator.setLayout(nav_layout2)
        self.bkgd_navigator.setMaximumHeight(60)

        self.btns = QFrame(self.Central_Frame)
        self.btns.setMaximumHeight(60)
        self.Btn_Add = QPushButton('Add', self.btns)
        self.Btn_Close = QPushButton('Close', self.btns)
        btn_layout = QHBoxLayout()
        btn_layout.addWidget(self.Btn_Add)
        btn_layout.addWidget(self.Btn_Close)
        self.btns.setLayout(btn_layout)

        # 根据具体的传入参数构建不同的视图
        layout.addWidget(self.wb_label, 0, 0)
        layout.addWidget(self.bkgd_label, 0, 1)

        layout.addWidget(self.wb, 1, 0)
        layout.addWidget(self.bkgd, 1, 1)

        layout.addWidget(self.wb_navigator, 2, 0)
        layout.addWidget(self.bkgd_navigator, 2, 1)

        layout.addWidget(self.btns, 3, 0, 2, 0)
        layouts = QVBoxLayout()
        layouts.addLayout(layout)
        self.Central_Frame.setLayout(layouts)
        self.setCentralWidget(self.Central_Frame)
        #self.setStyleSheet('border:1px solid red')

    def Right_Dock_Code(self):
        self.Added_Img_tree = Img_Tree([], self)
        self.Right_Dock = QDockWidget('Selected Images', self)
        self.Right_Dock.setWidget(self.Added_Img_tree)
        self.Right_Dock.setFeatures(QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(Qt.RightDockWidgetArea, self.Right_Dock)

    def connect_Signals(self):
        self.Tree.clicked.connect(self.Load_Img_to_Central_Frame)
        self.wb_nav_left.clicked.connect(self.change_img_index)
        self.wb_nav_right.clicked.connect(self.change_img_index)
        self.bkgd_nav_left.clicked.connect(self.change_img_index)
        self.bkgd_nav_right.clicked.connect(self.change_img_index)
        self.Btn_Add.clicked.connect(self.Add_Btn_Action)
        self.Btn_Close.clicked.connect(self.Close_Btn_Action)

    def Load_Img_to_Central_Frame(self, Index):
        select_file = self.Tree.model().filePath(Index)
        _, ext = os.path.splitext(select_file)
        if ext in ['.tif', '.jpeg', '.png', '.jpg']:
            self.Related_Imgs = BioRad_Imgs(select_file)
        self.set_Central_Frame()

    def set_Central_Frame(self):
        self.wb_nav_left.setEnabled(False)
        self.wb_nav_right.setEnabled(False)
        self.bkgd_nav_left.setEnabled(False)
        self.bkgd_nav_right.setEnabled(False)

        self.current_wb = self.Related_Imgs.WB_list[self.Related_Imgs.wb_index]
        self.current_bkgd = self.Related_Imgs.BKGD_list[
            self.Related_Imgs.bkgd_index]
        self.wb_label.setText(
            self.current_wb.replace(self.Related_Imgs.Dir, '.'))
        self.bkgd_label.setText(
            self.current_bkgd.replace(self.Related_Imgs.Dir, '.'))
        wb, _ = CV_Img_to_QImage(cv2.imread(self.current_wb))
        bkgd, _ = CV_Img_to_QImage(cv2.imread(self.current_bkgd))
        self.wb.setPixmap(wb)
        self.wb.setScaledContents(True)
        self.bkgd.setPixmap(bkgd)
        wb_len = len(self.Related_Imgs.WB_list)
        bkgd_len = len(self.Related_Imgs.BKGD_list)
        if self.Related_Imgs.wb_index > 0:
            self.wb_nav_left.setEnabled(True)
        if wb_len - self.Related_Imgs.wb_index > 1:
            self.wb_nav_right.setEnabled(True)

        if self.Related_Imgs.bkgd_index > 0:
            self.bkgd_nav_left.setEnabled(True)
        if bkgd_len - self.Related_Imgs.bkgd_index > 1:
            self.bkgd_nav_right.setEnabled(True)

    def change_img_index(self):
        sender = self.sender()
        if sender == self.wb_nav_left:
            self.Related_Imgs.wb_index = self.Related_Imgs.wb_index - 1
        if sender == self.wb_nav_right:
            self.Related_Imgs.wb_index = self.Related_Imgs.wb_index + 1
        if sender == self.bkgd_nav_left:
            self.Related_Imgs.bkgd_index = self.Related_Imgs.bkgd_index - 1
        if sender == self.bkgd_nav_right:
            self.Related_Imgs.bkgd_index = self.Related_Imgs.bkgd_index + 1
        self.set_Central_Frame()

    def Add_Btn_Action(self):
        list = [{'wb': self.current_wb, 'bkgd': self.current_bkgd}]
        self.Added_Img_tree.Add_top_Level_Item(list)
        print(self.Added_Img_tree.imgs)

    def Close_Btn_Action(self):
        self.close()

    def closeEvent(self, event):
        self.Close_Signal.emit(self.Added_Img_tree.imgs)

    def dir_selection(self):
        global Wk_Dir
        dir = QFileDialog.getExistingDirectory(self, "Choose a Directory",
                                               Wk_Dir)
        self.Current_Dir = dir
        Wk_Dir = dir
        self.Tree.setRootIndex(self.Model.index(self.Current_Dir))
        self.Left_Dock.setWindowTitle(dir)
class _PlatformGui(QWidget):
    """ The platform-specific GUI. """
    def __init__(self, platform_name):
        """ Initialise the object. """

        super().__init__()

        self._project = None
        self._platform_name = platform_name

        self._ignore_extlib_changes = False

        layout = QVBoxLayout()

        self._pyshlib_cb = QCheckBox(
            "Use standard Python shared library",
            whatsThis="Use the standard Python shared library rather than "
            "a statically compiled library.",
            stateChanged=self._pyshlib_changed)
        layout.addWidget(self._pyshlib_cb)

        self._extlib_edit = QTreeView(
            whatsThis="This is the list of external libraries that must "
            "be linked with the application for this platform. A "
            "library will only be enabled if a module in the "
            "standard library uses it. Double-click in the "
            "<b>DEFINES</b>, <b>INCLUDEPATH</b> and <b>LIBS</b> "
            "columns to modify the corresponding <tt>qmake</tt> "
            "variable as required.")
        self._extlib_edit.setRootIsDecorated(False)
        self._extlib_edit.setEditTriggers(QTreeView.DoubleClicked
                                          | QTreeView.SelectedClicked
                                          | QTreeView.EditKeyPressed)

        model = QStandardItemModel(self._extlib_edit)
        model.setHorizontalHeaderLabels(
            ("External Library", 'DEFINES', 'INCLUDEPATH', 'LIBS'))
        model.itemChanged.connect(self._extlib_changed)

        model._items = {}

        for extlib in external_libraries_metadata:
            name_itm = QStandardItem(extlib.user_name)

            items = (name_itm, QStandardItem(), QStandardItem(),
                     QStandardItem())

            model.appendRow(items)

            model._items[extlib.name] = items

        self._extlib_edit.setModel(model)

        for col in range(3):
            self._extlib_edit.resizeColumnToContents(col)

        layout.addWidget(self._extlib_edit)

        self.setLayout(layout)

    def update_from_project(self, project):
        """ Update the GUI to reflect the current state of the project. """

        self._project = project

        platform_name = self._platform_name

        # Update the shared library state.
        blocked = self._pyshlib_cb.blockSignals(True)
        self._pyshlib_cb.setCheckState(Qt.Checked if platform_name in project.
                                       python_use_platform else Qt.Unchecked)
        self._pyshlib_cb.blockSignals(blocked)

        # Update the external libraries.
        model = self._extlib_edit.model()

        blocked = model.blockSignals(True)

        external_libs = project.external_libraries.get(platform_name, [])

        for extlib in external_libraries_metadata:
            _, defs, incp, libs = model._items[extlib.name]

            for prj_extlib in external_libs:
                if prj_extlib.name == extlib.name:
                    defs.setText(prj_extlib.defines)
                    incp.setText(prj_extlib.includepath)
                    libs.setText(prj_extlib.libs)
                    break
            else:
                defs.setText(extlib.defines)
                incp.setText(extlib.includepath)
                libs.setText(extlib.get_libs(platform_name))

        model.blockSignals(blocked)

    def update_from_required_libraries(self, required_libraries):
        """ Update the GUI as the required external libraries changes. """

        items = self._extlib_edit.model()._items

        # Note that we can't simply block the model's signals as this would
        # interfere with the model/view interactions.
        self._ignore_extlib_changes = True

        for extlib in external_libraries_metadata:
            if extlib.name in required_libraries:
                for idx, itm in enumerate(items[extlib.name]):
                    itm.setFlags(
                        Qt.ItemIsEnabled
                        | Qt.ItemIsEditable if idx != 0 else Qt.ItemIsEnabled)
            else:
                for itm in items[extlib.name]:
                    itm.setFlags(Qt.NoItemFlags)

        self._ignore_extlib_changes = False

    def _pyshlib_changed(self, state):
        """ Invoked when the shared library state changes. """

        project = self._project
        platform_name = self._platform_name

        if state == Qt.Checked:
            project.python_use_platform.append(platform_name)
        else:
            project.python_use_platform.remove(platform_name)

        project.modified = True

    def _extlib_changed(self, itm):
        """ Invoked when an external library has changed. """

        if self._ignore_extlib_changes:
            return

        self._ignore_extlib_changes = True

        project = self._project
        platform_name = self._platform_name

        idx = self._extlib_edit.model().indexFromItem(itm)
        extlib = external_libraries_metadata[idx.row()]
        col = idx.column()

        # Get the project entry, creating it if necessary.
        external_libs = project.external_libraries.get(platform_name, [])

        for prj_extlib in external_libs:
            if prj_extlib.name == extlib.name:
                break
        else:
            prj_extlib = ExternalLibrary(extlib.name, '', '',
                                         extlib.get_libs(platform_name))
            external_libs.append(prj_extlib)
            project.external_libraries[platform_name] = external_libs

        # Update the project.
        text = itm.text().strip()

        if col == 1:
            prj_extlib.defines = text
        elif col == 2:
            prj_extlib.includepath = text
        elif col == 3:
            prj_extlib.libs = text

        # If the project entry corresponds to the default then remove it.
        if prj_extlib.defines == extlib.defines and prj_extlib.includepath == extlib.includepath and prj_extlib.libs == extlib.get_libs(
                platform_name):
            external_libs.remove(prj_extlib)
            if len(external_libs) == 0:
                del project.external_libraries[platform_name]

        project.modified = True

        self._ignore_extlib_changes = False
예제 #29
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)[0]
        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)[0]
        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)
예제 #30
0
class ImageViewer(QWidget):
    def __init__(self):

        super(ImageViewer, self).__init__()

        pal = QPalette()
        pal.setColor(QPalette.Background, Qt.lightGray)

        self.factor = 3.0

        self.config = Config()
        self.currentRep = ""

        self.createActions()
        self.createToolbarMenus()
        #self.createMenus()

        self.browserFile()
        self.imgqLabel()
        self.boxSliders()

        self.verticalLayout = QVBoxLayout(self)
        self.horizontalLayout = QHBoxLayout(self)

        self.textInfo = QTextEdit()

        self.textInfoTop = QTextEdit()
        self.textInfoTop.setEnabled(True)
        self.textInfoTop.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Ignored)
        self.textInfoTop.setFontPointSize(11)
        self.textInfoTop.setStyleSheet("background-color: lightgray")
        #self.textInfoTop.adjustSize()
        self.textInfoTop.setText('Welcome to IRMaGe')

        self.tableJson = QTableWidget()
        self.tableJson.setColumnCount(2)
        self.tableJson.setColumnWidth(0, 150)
        self.tableJson.setColumnWidth(1, 400)
        self.tableJson.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContents)

        self.tableJson.setHorizontalHeaderLabels(['Keys', 'Values'])
        #self.tableJson.setBackgroundRole(QPalette.Light)

        self.scrollText = QScrollArea()
        self.scrollText.setBackgroundRole(QPalette.Dark)
        self.scrollText.setWidget(self.textInfoTop)
        self.scrollText.setWidgetResizable(True)
        #=======================================================================
        # self.adjustScrollBar(self.scrollText.horizontalScrollBar(), 1.0)
        # self.adjustScrollBar(self.scrollText.verticalScrollBar(), 2.0)
        #=======================================================================
        self.scrollTable = QScrollArea()
        self.scrollTable.setBackgroundRole(QPalette.Dark)
        self.scrollTable.setWidget(self.tableJson)
        self.scrollTable.setWidgetResizable(True)
        #=======================================================================
        # self.adjustScrollBar(self.scrollTable.horizontalScrollBar(), 2.0)
        # self.adjustScrollBar(self.scrollTable.verticalScrollBar(), 2.0)
        #=======================================================================

        self.headerTabData = [
            'Data', 'PatientName', 'StudyName', 'DateCreation', 'PatientSex',
            'PatientWeight', 'ProtocolName', 'SequenceName'
        ]

        self.tableData = TableDataBrower(self)
        self.tableData.setColumnCount(8)
        self.tableData.setRowCount(10)
        self.tableData.setColumnWidth(0, 200)
        self.tableData.setHorizontalHeaderLabels(self.headerTabData)
        self.tableData.setBackgroundRole(QPalette.Light)
        self.tableData.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContents)
        self.tableData.verticalHeader().hide()

        self.scrollBrowser = QScrollArea()
        self.scrollBrowser.setBackgroundRole(QPalette.Dark)
        self.scrollBrowser.setWidget(self.tableData)
        self.scrollBrowser.setWidgetResizable(True)

        self.splitter0 = QSplitter(Qt.Vertical)
        self.splitter0.addWidget(self.scrollText)
        self.splitter0.addWidget(self.scrollTable)

        self.scrollArea = QScrollArea()
        self.scrollArea.setBackgroundRole(QPalette.Dark)
        self.scrollArea.setWidget(self.imageLabel)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setAlignment(Qt.AlignCenter)

        self.adjustScrollBar(self.scrollArea.horizontalScrollBar(), 0.8)
        self.adjustScrollBar(self.scrollArea.verticalScrollBar(), 1.0)

        self.splitter1 = QSplitter(Qt.Horizontal)
        self.splitter1.addWidget(self.splitter0)
        self.splitter1.addWidget(self.scrollArea)
        self.splitter1.addWidget(self.layoutSlide)

        self.splitter3 = QSplitter(Qt.Horizontal)
        self.splitter3.addWidget(self.browser)
        self.splitter3.addWidget(self.scrollBrowser)

        self.splitter2 = QSplitter(Qt.Vertical)
        self.splitter2.addWidget(self.splitter1)
        self.splitter2.addWidget(self.splitter3)
        self.splitter2.setHandleWidth(15)
        #=======================================================================
        # self.splitter2.
        #=======================================================================

        self.verticalLayout.addWidget(self.menuToolBar)
        self.verticalLayout.addWidget(self.splitter2)

        self.setWindowTitle("MRImage Viewer (IRMaGe)")
        self.resize(800, 600)

        self.setAutoFillBackground(True)
        self.setPalette(pal)

    def changeSel(self):
        print('Tab changed')

    def adjustScrollBar(self, scrollBar, factor):
        scrollBar.setValue(
            int(factor * scrollBar.value() +
                ((factor - 1) * scrollBar.pageStep() / 2)))

    def imgqLabel(self):
        QLabel.__init__(self)
        image = QImage('sources_images/LogoIRMaGe.png')
        self.scaleFactor = 1.0
        self.imageLabel = QLabel()
        self.imageLabel.setBackgroundRole(QPalette.Base)
        self.imageLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.imageLabel.setScaledContents(True)
        self.imageLabel.setPixmap(QPixmap.fromImage(image))
        self.scaleFactor *= self.factor
        self.imageLabel.adjustSize()
        self.imageLabel.resize(self.scaleFactor *
                               self.imageLabel.pixmap().size())

    def open(self, filePath):
        self.img = nib.load(filePath)
        self.textInfoTop.setText('File : ' + filePath + '\n')
        self.textInfoTop.append('Dim : ' + str(self.img.shape) + '\n')
        self.enableSliders()
        self.a1.setValue(0)
        self.a2.setValue(0)
        self.a3.setValue(0)
        self.c2.setMaximum(self.img.shape[0])
        self.c2.setMinimum(-self.img.shape[0])
        self.c3.setMaximum(self.img.shape[1])
        self.c3.setMinimum(-self.img.shape[1])
        self.navigImage()
        self.fitToWindowAct.setEnabled(True)
        self.fitToWindow()

    def openJson(self, pathJson, fileName):
        with open(pathJson, 'r') as stream:
            try:
                json_object = json.load(stream)
                data = json.dumps(json_object, indent=0, sort_keys=True)
                data = json.loads(data)
                rowPosition = 0
                self.tableJson.setRowCount(0)

                i = 0
                for keyd in self.headerTabData:
                    try:
                        val = str(data[keyd])
                        val = val.replace('[', '')
                        val = val.replace(']', '')
                    except:
                        val = ''
                    #===========================================================
                    # self.tableData.insertRow(i)
                    # self.tableData.setItem(0,i,QTableWidgetItem(val))
                    # i+=1
                    #===========================================================
                #===============================================================
                # self.tableData.setItem(0,0,QTableWidgetItem(fileName))
                # self.tableData.selectRow(0)
                #===============================================================
                for keys in data:
                    stringValue = str(data[keys])
                    stringValue = stringValue.replace('[', '')
                    stringValue = stringValue.replace(']', '')
                    self.tableJson.insertRow(rowPosition)
                    self.tableJson.setItem(rowPosition, 0,
                                           QTableWidgetItem(keys))
                    self.tableJson.setItem(rowPosition, 1,
                                           QTableWidgetItem(stringValue))
                    rowPosition += 1
                self.tableJson.resizeColumnsToContents()
            except json.JSONDecodeError as exc:
                itemError = 'Error Json format'
                self.tableJson.setRowCount(0)
                self.tableJson.insertRow(0)
                self.tableJson.setItem(0, 0, QTableWidgetItem(itemError))
                print(exc)

    def jsonParser(self, pathJson):
        with open(pathJson, 'r') as stream:
            try:
                json_object = json.load(stream)
                listTag = json.dumps(json_object, indent=0, sort_keys=True)
                listTag = json.loads(listTag)
            except json.JSONDecodeError as exc:
                itemError = 'Error Json format'
        return listTag

    def tableDataFill(self, pathRepertory):
        files = [f for f in fnmatch.filter(os.listdir(pathRepertory), '*.nii')]
        self.tableData.setRowCount(0)
        j = 0
        for f in files:
            base = os.path.splitext(f)[0]
            g = os.path.join(pathRepertory, base + ".json")
            self.tableData.insertRow(j)
            if os.path.isfile(g):
                data = self.jsonParser(g)
                i = 0
                for keyw in self.headerTabData:
                    try:
                        val = str(data[keyw])
                        val = val.replace('[', '')
                        val = val.replace(']', '')
                    except:
                        val = ''
                    self.tableData.setItem(j, i, QTableWidgetItem(val))
                    i += 1
            else:
                self.tableData.setItem(j, 1,
                                       QTableWidgetItem('No json file found'))
            self.tableData.setItem(j, 0, QTableWidgetItem(f))
            self.tableData.resizeColumnsToContents()
            j += 1

    def indexImage(self):
        sl1 = self.a1.value()
        sl2 = self.a2.value()
        sl3 = self.a3.value()
        if len(self.img.shape) == 3:
            x = self.img.get_data()[:, :, sl1].copy()
            self.a1.setMaximum(self.img.shape[2] - 1)
            self.a2.setMaximum(0)
            self.a3.setMaximum(0)
        if len(self.img.shape) == 4:
            x = self.img.get_data()[:, :, sl1, sl2].copy()
            self.a1.setMaximum(self.img.shape[2] - 1)
            self.a2.setMaximum(self.img.shape[3] - 1)
            self.a3.setMaximum(0)
        if len(self.img.shape) == 5:
            x = self.img.get_data()[:, :, sl1, sl2, sl3].copy()
            self.a1.setMaximum(self.img.shape[2] - 1)
            self.a2.setMaximum(self.img.shape[3] - 1)
            self.a3.setMaximum(self.img.shape[4] - 1)
        x = rotate(x, -90, reshape=False)
        x = np.uint8((x - x.min()) / x.ptp() * 255.0)
        self.x = x

############################ Slice controls  #########################################

    def boxSliders(self):
        self.k1 = QLabel('Slider 1    ')
        self.k2 = QLabel('Slider 2')
        self.k3 = QLabel('Slider 3')

        self.a1 = self.createSlider(0, 0, 0)
        self.a2 = self.createSlider(0, 0, 0)
        self.a3 = self.createSlider(0, 0, 0)

        self.a1.valueChanged.connect(self.changePosValue)
        self.a2.valueChanged.connect(self.changePosValue)
        self.a3.valueChanged.connect(self.changePosValue)

        self.txta1 = self.createFieldValue()
        self.txta2 = self.createFieldValue()
        self.txta3 = self.createFieldValue()

        self.controlsGroup = QGroupBox('Slice Controls')
        gridCtrl = QGridLayout()
        gridCtrl.addWidget(self.k1, 0, 0)
        gridCtrl.addWidget(self.a1, 0, 1)
        gridCtrl.addWidget(self.txta1, 0, 2)
        gridCtrl.addWidget(self.k2, 1, 0)
        gridCtrl.addWidget(self.a2, 1, 1)
        gridCtrl.addWidget(self.txta2, 1, 2)
        gridCtrl.addWidget(self.k3, 2, 0)
        gridCtrl.addWidget(self.a3, 2, 1)
        gridCtrl.addWidget(self.txta3, 2, 2)
        self.controlsGroup.setLayout(gridCtrl)

        ############################ brightness and contrast  ################################
        self.txtb1 = self.createFieldValue()
        self.txtb2 = self.createFieldValue()
        self.txtb3 = self.createFieldValue()
        self.txtb4 = self.createFieldValue()

        self.l1 = QLabel('Brightness    ')
        self.b1 = self.createSlider(101, 0, 50)
        self.l2 = QLabel('Contrast')
        self.b2 = self.createSlider(101, 0, 50)
        self.l3 = QLabel('Sharpness')
        self.b3 = self.createSlider(101, 0, 50)
        self.l4 = QLabel('Color')
        self.b4 = self.createSlider(101, 0, 50)

        self.b1.valueChanged.connect(self.changeContValue)
        self.b2.valueChanged.connect(self.changeContValue)
        self.b3.valueChanged.connect(self.changeContValue)
        self.b4.valueChanged.connect(self.changeContValue)

        self.txtb1.setText(str(0))
        self.txtb2.setText(str(0))
        self.txtb3.setText(str(0))
        self.txtb4.setText(str(0))

        self.buttonResetContrast = QPushButton('reset', self)
        self.buttonResetContrast.setToolTip('Reset all values')
        self.buttonResetContrast.setEnabled(False)
        self.buttonResetContrast.clicked.connect(self.resetValuesContrast)

        self.contrastGroup = QGroupBox('Brightness and Contrast')
        gridCont = QGridLayout()
        gridCont.addWidget(self.l1, 0, 0)
        gridCont.addWidget(self.b1, 0, 1)
        gridCont.addWidget(self.txtb1, 0, 2)
        gridCont.addWidget(self.l2, 1, 0)
        gridCont.addWidget(self.b2, 1, 1)
        gridCont.addWidget(self.txtb2, 1, 2)
        gridCont.addWidget(self.l3, 2, 0)
        gridCont.addWidget(self.b3, 2, 1)
        gridCont.addWidget(self.txtb3, 2, 2)
        gridCont.addWidget(self.l4, 3, 0)
        gridCont.addWidget(self.b4, 3, 1)
        gridCont.addWidget(self.txtb4, 3, 2)
        gridCont.addWidget(self.buttonResetContrast, 4, 2)
        self.contrastGroup.setLayout(gridCont)

        ############################ Transformation  #########################################
        self.txtc1 = self.createFieldValue()
        self.txtc2 = self.createFieldValue()
        self.txtc3 = self.createFieldValue()
        self.txtc4 = self.createFieldValue()

        self.m1 = QLabel('Rotation')
        self.c1 = self.createSlider(180, -180, 0)
        self.m2 = QLabel('Translate X    ')
        self.c2 = self.createSlider(1, -1, 0)
        self.m3 = QLabel('Translate Y    ')
        self.c3 = self.createSlider(1, -1, 0)
        self.m4 = QLabel('Resize')
        self.c4 = self.createSlider(10, 0, 0)

        self.c1.valueChanged.connect(self.changeTransValue)
        self.c2.valueChanged.connect(self.changeTransValue)
        self.c3.valueChanged.connect(self.changeTransValue)
        self.c4.valueChanged.connect(self.changeTransValue)

        self.txtc1.setText(str(0))
        self.txtc2.setText(str(0))
        self.txtc3.setText(str(0))
        self.txtc4.setText(str(0))

        self.buttonResetTransform = QPushButton('reset', self)
        self.buttonResetTransform.setToolTip('Reset all values')
        self.buttonResetTransform.setEnabled(False)
        self.buttonResetTransform.clicked.connect(self.resetValuesTransform)

        self.transformationGroup = QGroupBox('Transformations')
        gridTransf = QGridLayout()
        gridTransf.addWidget(self.m1, 0, 0)
        gridTransf.addWidget(self.c1, 0, 1)
        gridTransf.addWidget(self.txtc1, 0, 2)
        gridTransf.addWidget(self.m2, 1, 0)
        gridTransf.addWidget(self.c2, 1, 1)
        gridTransf.addWidget(self.txtc2, 1, 2)
        gridTransf.addWidget(self.m3, 2, 0)
        gridTransf.addWidget(self.c3, 2, 1)
        gridTransf.addWidget(self.txtc3, 2, 2)
        gridTransf.addWidget(self.m4, 3, 0)
        gridTransf.addWidget(self.c4, 3, 1)
        gridTransf.addWidget(self.txtc4, 3, 2)
        gridTransf.addWidget(self.buttonResetTransform, 4, 2)
        self.transformationGroup.setLayout(gridTransf)

        ####################################################################################
        self.layoutSliders = QVBoxLayout()
        self.layoutSliders.addWidget(self.controlsGroup)
        self.layoutSliders.addWidget(self.contrastGroup)
        self.layoutSliders.addWidget(self.transformationGroup)

        self.layoutSlide = QWidget()
        self.layoutSlide.setLayout(self.layoutSliders)

    def createSlider(self, maxm=0, minm=0, pos=0):
        slider = QSlider(Qt.Horizontal)
        slider.setFocusPolicy(Qt.StrongFocus)
        #slider.setTickPosition(QSlider.TicksBothSides)
        slider.setTickInterval(1)
        #slider.setSingleStep(1)
        slider.setMaximum(maxm)
        slider.setMinimum(minm)
        slider.setValue(pos)
        slider.setEnabled(False)
        return slider

    def createFieldValue(self):
        fieldValue = QLineEdit()
        fieldValue.setEnabled(False)
        fieldValue.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        return fieldValue

    def displayPosValue(self):
        self.txta1.setText(
            str(self.a1.value() + 1) + ' / ' + str(self.a1.maximum() + 1))
        self.txta2.setText(
            str(self.a2.value() + 1) + ' / ' + str(self.a2.maximum() + 1))
        self.txta3.setText(
            str(self.a3.value() + 1) + ' / ' + str(self.a3.maximum() + 1))

    def changePosValue(self):
        self.navigImage()

    def navigImage(self):
        self.indexImage()
        self.displayPosValue()
        w, h = self.x.shape
        image = QImage(self.x.data, w, h, QImage.Format_Indexed8)
        self.pixm = QPixmap.fromImage(image)
        self.imageLabel.setPixmap(self.pixm)
        self.imageLabel.adjustSize()
        self.imageLabel.resize(self.scaleFactor *
                               self.imageLabel.pixmap().size())
        self.filter()

    def changeContValue(self):
        self.txtb1.setText(str(self.b1.value() - 50))
        self.txtb2.setText(str(self.b2.value() - 50))
        self.txtb3.setText(str(self.b3.value() - 50))
        self.txtb4.setText(str(self.b4.value() - 50))
        self.filter()

    def changeTransValue(self):
        self.txtc1.setText(str(self.c1.value()))
        self.txtc2.setText(str(self.c2.value()))
        self.txtc3.setText(str(self.c3.value()))
        self.txtc4.setText(str(self.c4.value()))
        self.filter()

    def filter(self):
        img = Image.fromarray(self.x, 'L')

        brightness = ImageEnhance.Brightness(img)
        newImg = brightness.enhance(1.2 * (self.b1.value() + 1) / 50.0)

        contrast = ImageEnhance.Contrast(newImg)
        newImg = contrast.enhance((self.b2.value() + 1) / 50.0)

        sharpness = ImageEnhance.Sharpness(newImg)
        newImg = sharpness.enhance(2.0 * (self.b3.value() + 1) / 50.0)

        color = ImageEnhance.Color(newImg)
        newImg = color.enhance((self.b4.value() + 1) / 50.0)

        newImg = newImg.rotate(self.c1.value())

        newImg = newImg.transform(
            img.size, Image.AFFINE,
            (1, 0, self.c2.value(), 0, 1, self.c3.value()))

        size1 = int(img.size[0] * (self.c4.value() + 1))
        size2 = int(img.size[1] * (self.c4.value() + 1))

        newImg = newImg.resize((size1, size2), Image.ANTIALIAS)

        self.pixm = QPixmap.fromImage(newImg.toqimage())
        self.imageLabel.setPixmap(self.pixm)
        self.imageLabel.adjustSize()
        self.imageLabel.resize(self.scaleFactor *
                               self.imageLabel.pixmap().size())

    def resetValuesContrast(self):
        self.b1.setSliderPosition(50)
        self.b2.setSliderPosition(50)
        self.b3.setSliderPosition(50)
        self.b4.setSliderPosition(50)
        self.changeContValue()

    def resetValuesTransform(self):
        self.c1.setSliderPosition(0)
        self.c2.setSliderPosition(0)
        self.c3.setSliderPosition(0)
        self.c4.setSliderPosition(0)
        self.changeTransValue()

    def enableSliders(self):
        self.a1.setEnabled(True)
        self.a2.setEnabled(True)
        self.a3.setEnabled(True)
        self.b1.setEnabled(True)
        self.b2.setEnabled(True)
        self.b3.setEnabled(True)
        self.b4.setEnabled(True)
        self.c1.setEnabled(True)
        self.c2.setEnabled(True)
        self.c3.setEnabled(True)
        self.c4.setEnabled(True)
        self.buttonResetContrast.setEnabled(True)
        self.buttonResetTransform.setEnabled(True)

####################################################################################

    def browserFile(self):

        global Browser, Model

        self.browser = QTreeView()

        model = QFileSystemModel()
        model.setNameFilters(['*.nii'])
        model.setNameFilterDisables(False)
        model.setReadOnly(True)

        self.browser.setModel(model)
        self.browser.expandAll()
        self.browser.setColumnWidth(0, 400)

        self.browser.selectionModel().selectionChanged.connect(self.select)

        Browser = self.browser
        Model = model

        #=======================================================================
        # self.browser.doubleClicked.connect(self.selection)
        #self.browser.clicked.connect(self.selection)
        #=======================================================================

    def select(self, signal):
        file_path = self.browser.model().filePath(signal.indexes()[0])
        shortName, fileExt = os.path.splitext(file_path)
        filePath, fileName = os.path.split(file_path)
        self.textInfo.setText(filePath)
        blackColor = QColor(0, 0, 0)

        if os.path.isfile(file_path):
            if fileExt == ".nii":
                if self.currentRep != filePath:
                    self.tableDataFill(filePath)
                    self.currentRep = filePath
                self.open(file_path)
                self.tableData.selectRow(
                    self.tableData.findItems(fileName,
                                             Qt.MatchExactly)[0].row())
                if os.path.isfile(shortName + '.json'):
                    greenColor = QColor(50, 150, 100)
                    self.textInfoTop.setTextColor(greenColor)
                    self.textInfoTop.append('Json file exists ' + '\n')
                    self.openJson(shortName + '.json', fileName)
                else:
                    redColor = QColor(255, 0, 0)
                    self.textInfoTop.setTextColor(redColor)
                    self.textInfoTop.append('Json file doesn\'t exist' + '\n')
                    self.tableJson.setRowCount(0)
        else:
            self.tableData.setRowCount(0)
            self.currentRep = filePath

        self.textInfoTop.setTextColor(blackColor)
        self.scrollText.setWidgetResizable(True)


####################################################################################

    def createMenus(self):
        self.fileMenu = QMenu("&File", self)
        self.fileMenu.addAction(self.exitAct)

        self.viewMenu = QMenu("&View", self)
        self.viewMenu.addAction(self.zoomInAct)
        self.viewMenu.addAction(self.zoomOutAct)
        self.viewMenu.addAction(self.normalSizeAct)
        self.viewMenu.addSeparator()
        self.viewMenu.addAction(self.fitToWindowAct)
        self.viewMenu.addSeparator()

        self.helpMenu = QMenu("&Help", self)
        self.helpMenu.addAction(self.aboutAct)

        self.menuBar = QMenuBar()

        self.menuBar.addMenu(self.fileMenu)
        self.menuBar.addMenu(self.viewMenu)
        self.menuBar.addMenu(self.helpMenu)

    def createToolbarMenus(self):
        self.menuToolBar = QToolBar()

        viewMenu = QToolButton()
        viewMenu.setText('View')
        viewMenu.setPopupMode(QToolButton.MenuButtonPopup)
        aMenu = QMenu()
        aMenu.addAction(self.zoomInAct)
        aMenu.addAction(self.zoomOutAct)
        aMenu.addAction(self.normalSizeAct)
        aMenu.addSeparator()
        aMenu.addAction(self.fitToWindowAct)
        viewMenu.setMenu(aMenu)

        helpMenu = QToolButton()
        helpMenu.setText('Help')
        helpMenu.setPopupMode(QToolButton.MenuButtonPopup)
        bMenu = QMenu()
        helpMenu.setMenu(bMenu)

        self.menuToolBar.addWidget(viewMenu)
        self.menuToolBar.addWidget(helpMenu)

    def createActions(self):
        self.exitAct = QAction("Exit",
                               self,
                               shortcut="Ctrl+Q",
                               triggered=self.close)

        self.zoomInAct = QAction("Zoom In (25%)",
                                 self,
                                 shortcut="Ctrl++",
                                 enabled=False,
                                 triggered=self.zoomIn)

        self.zoomOutAct = QAction("Zoom Out (25%)",
                                  self,
                                  shortcut="Ctrl+-",
                                  enabled=False,
                                  triggered=self.zoomOut)

        self.normalSizeAct = QAction("Normal Size",
                                     self,
                                     shortcut="Ctrl+S",
                                     enabled=False,
                                     triggered=self.normalSize)

        self.fitToWindowAct = QAction("Fit to Window",
                                      self,
                                      enabled=False,
                                      checkable=True,
                                      shortcut="Ctrl+F",
                                      triggered=self.fitToWindow)

    def zoomIn(self):
        self.factor = 1.25
        self.scaleImage(self.factor)

    def zoomOut(self):
        self.factor = 0.8
        self.scaleImage(self.factor)

    def normalSize(self):
        self.imageLabel.adjustSize()
        self.scaleFactor = 1.0

    def fitToWindow(self):
        fitToWindow = self.fitToWindowAct.isChecked()
        self.scrollArea.setWidgetResizable(fitToWindow)
        self.scrollText.setWidgetResizable(fitToWindow)
        if not fitToWindow:
            self.normalSize()

        self.updateActions()

    def updateActions(self):
        self.zoomInAct.setEnabled(not self.fitToWindowAct.isChecked())
        self.zoomOutAct.setEnabled(not self.fitToWindowAct.isChecked())
        self.normalSizeAct.setEnabled(not self.fitToWindowAct.isChecked())

    def scaleImage(self, factor):
        self.scaleFactor *= factor
        self.imageLabel.resize(self.scaleFactor *
                               self.imageLabel.pixmap().size())

        self.adjustScrollBar(self.scrollArea.horizontalScrollBar(), factor)
        self.adjustScrollBar(self.scrollArea.verticalScrollBar(), factor)

        self.zoomInAct.setEnabled(self.scaleFactor < 5.0)
        self.zoomOutAct.setEnabled(self.scaleFactor > 0.333)

    def close(self):
        self.close()
예제 #31
0
class OperacaoLogistica(QDialog):
    #TODO: Acertar formatação na listagem de items por SIMAFIC
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowFlags(Qt.WindowMinMaxButtonsHint
                            | Qt.WindowCloseButtonHint)
        self.setWindowTitle('Operação Logística')
        self.setMinimumSize(QSize(h_size, v_size))
        self.setWindowIcon(QIcon(main_icon))

        verticalSpacer = QSpacerItem(40, 20, QSizePolicy.Minimum,
                                     QSizePolicy.Expanding)

        #Pedido Input Field
        self.proxy_list_result_id = QSortFilterProxyModel()
        self.numero_pedido = QLineEdit(self)
        self.numero_pedido.setPlaceholderText("Insira o Número do Pedido")
        self.numero_pedido.textChanged.connect(
            lambda wildcard: self.proxy_list_result_id.setFilterWildcard(
                wildcard))

        #Voltar Btn
        self.voltar_btn = QPushButton(self)
        #self.voltar_btn.setStyleSheet('background-color: rgb(0,0,255); color: #fff')
        self.voltar_btn.setText('Voltar')
        self.voltar_btn.clicked.connect(self.goMainWindow)
        self.close()

        #Adicionar Cores no StyleSheet
        colors = ['##393318', '  ##fff']
        self.pedidos = services.get_all_pedidos()
        self.item_result = None
        self.item_escolhido = None

        self.id_pedido_list = QListView()
        self.simafics_do_id = QListWidget()
        #self.simafics_do_id.setHidden(True)
        self.createPedidoIdList()

        self.id_pedido_list.clicked.connect(
            lambda id_pedido: self.createListaSimafics(id_pedido))
        self.simafics_do_id.itemDoubleClicked.connect(
            lambda pedido: self.simaficSelecionado(pedido))

        self.pedidos_label = QLabel()
        self.pedidos_label.setBuddy(self.id_pedido_list)
        self.simafic_label = QLabel()
        self.simafic_label.setBuddy(self.simafics_do_id)

        self.itensTree = PedidoItensTree()
        self.treeItensTV = QTreeView()
        self.treeItensTV.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.treeItensTV.setAlternatingRowColors(True)
        self.treeItensTV.setRootIsDecorated(True)
        self.treeItensTV.doubleClicked.connect(self.simaficSelecionado)
        self.treeItensTV.setColumnHidden(8, True)

        if len(self.pedidos) <= 0:
            self.pedidos_label.setText(
                "É necessário adicionar um pedido na tela de cadastro.")
            self.pedidos_label.setStyleSheet("QLabel { color: red; }")
        else:
            self.pedidos_label.setText("Listagem de Pedidos:")
            self.pedidos_label.setStyleSheet("QLabel { color: black; }")
            self.simafic_label.setText(
                "Selecione um pedido para ver a listagem de Itens por SIMAFIC:"
            )
            self.simafic_label.setStyleSheet("QLabel { color: red; }")

        layout = QGridLayout()
        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 4)
        layout.addWidget(self.numero_pedido, 0, 0)
        layout.addWidget(self.voltar_btn, 0, 1)
        layout.addWidget(self.pedidos_label, 1, 0)
        layout.addWidget(self.simafic_label, 1, 1)
        layout.addWidget(self.id_pedido_list, 2, 0)
        layout.addWidget(self.treeItensTV, 2, 1)
        #layout.addWidget(self.simafics_do_id, 2,1)
        self.setLayout(layout)

    def createPedidoIdList(self):
        print('def createPedidoIdList(self):')
        onlyids = set()
        pedidosbyid = []
        pedidosCompletos = []
        self.proxy_list_result_id = QSortFilterProxyModel()
        for obj in self.pedidos:
            if obj.id_pedido not in onlyids:
                pedidosbyid.append(obj)
                onlyids.add(obj.id_pedido)

        self.pedidoId_model = QStringListModel(onlyids, self)
        self.proxy_list_result_id.setSourceModel(self.pedidoId_model)
        self.id_pedido_list.setModel(self.proxy_list_result_id)
        self.id_pedido_list.setAlternatingRowColors(True)
        self.id_pedido_list.setEditTriggers(QAbstractItemView.NoEditTriggers)

    def createListaSimafics(self, id_pedido):

        pedido = id_pedido.data()
        self.pedidosModel = self.itensTree.createPedidosModel(self.itensTree)
        self.treeItensTV.setModel(self.pedidosModel)
        print('def listaSimafics(self, id_pedido): {id_pedido}'.format(
            id_pedido=pedido))
        self.item_result = None
        self.item_result = [x for x in self.pedidos if x.id_pedido == pedido]
        self.simafics_do_id.clear()
        self.pedidosModel.beginResetModel
        self.pedidosModel.modelReset
        self.pedidosModel.endResetModel

        for idx, item in enumerate(self.item_result):
            print(item)
            self.itensTree.addItens(
                self.pedidosModel, item.cod_simafic, item.desc,
                item.qty_scanneada, item.qty_total, item.nome_responsavel,
                item.id_caixa, item.time_updated.strftime("%d/%m/%y %H:%M:%S"),
                item.id_pedido, item)

        self.simafic_label.setText(
            "Listagem de Itens do pedido {} por SIMAFIC:".format(pedido))
        self.simafic_label.setStyleSheet("QLabel { color: black; }")

        #self.simafics_do_id.setHidden(False)

    def simaficSelecionado(self, item):
        print(item.column(), item.row())
        simafic_escolhido = self.treeItensTV.model().index(item.row(),
                                                           0).data()
        id_pedido = self.treeItensTV.model().index(item.row(), 7).data()
        self.item_escolhido = [
            x for x in self.item_result
            if x.cod_simafic == simafic_escolhido and x.id_pedido == id_pedido
        ]
        self.cams = ItemScanner(self.item_escolhido[0])
        self.cams.show()
        self.close()

    def goMainWindow(self):
        self.cams = mainView
        self.cams.show()
        self.close()

    def goScan(self):
        self.cams = ItemScanner("Eu sou o Pedido", "Eu sou o Simafic",
                                "Eu sou a Descrição", "300")
        self.cams.show()
        self.close()
예제 #32
0
class LeftSideBar(QWidget):

    treeViewSelectionChanged = pyqtSignal(QModelIndex, QModelIndex)
    treeViewDoubleClicked = pyqtSignal(QModelIndex)

    addPlaylistRequested = pyqtSignal()
    removePlaylistRequested = pyqtSignal(UUID)
    addToPlaylistRequested = pyqtSignal(UUID)

    playlistAdded = pyqtSignal(UUID)
    playlistRenamed = pyqtSignal(UUID, str)

    def __init__(self, tree_items, parent=None):
        super(LeftSideBar, self).__init__(parent)
        self._tree_items = tree_items
        self._restoreSettings()

        self._setTreeView()
        self._setAlbumCoverBox()

        self._renderUI()

        self.setMinimumWidth(FRONT_COVER_MIN_WIDTH)
        self.setMaximumWidth(FRONT_COVER_MAX_WIDTH)

    def _restoreSettings(self):
        pass

    def _setTreeView(self):
        self.treeModel = TreeModel()

        self.treeModel.addTopLevelItems(self._tree_items.keys())

        self.leftBarView = QTreeView()
        self.leftBarView.setModel(self.treeModel)
        self.leftBarView.setHeaderHidden(True)
        self.leftBarView.setRootIsDecorated(False)
        self.leftBarView.setItemsExpandable(False)
        self.leftBarView.setMouseTracking(True)
        self.leftBarView.expandAll()
        self.leftBarView.setFocusPolicy(Qt.NoFocus)
        self.leftBarView.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.leftBarView.setSelectionMode(QAbstractItemView.SingleSelection)
        self.leftBarView.setEditTriggers(QAbstractItemView.SelectedClicked)

        self.leftBarView.selectionModel().currentRowChanged.connect(
            lambda c, p: self.treeViewSelectionChanged.emit(c, p))

        self.leftBarView.selectionModel().setCurrentIndex(
            self.leftBarView.model().index(
                0, 0, self.leftBarView.model().index(0, 0)),
            QItemSelectionModel.Select)

        self.leftBarView.doubleClicked.connect(
            lambda i: self.treeViewDoubleClicked.emit(i))

        delegate = LeftSideBarDelegate(self.leftBarView)
        self.leftBarView.setItemDelegate(delegate)
        delegate.addPlaylistRequested.connect(
            lambda: self.addPlaylistRequested.emit())
        delegate.removePlaylistRequested.connect(
            lambda i: self.removePlaylistRequested.emit(
                self.__getUuidFromIndex(i)))
        delegate.addToPlaylistRequested.connect(
            lambda i:
            self.addToPlaylistRequested.emit(self.__getUuidFromIndex(i)))
        delegate.editingFinished.connect(self._onRenamed)

    def _onRenamed(self, index, text):
        self.playlistRenamed.emit(
            self.__getUuidFromIndex(index),
            text)

    @property
    def model(self):
        return self.treeModel

    def _setAlbumCoverBox(self):
        self.albumCoverBox = CoverArtBox()

    def _renderUI(self):
        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)
        self.layout.addWidget(self.leftBarView)
        self.layout.addWidget(self.albumCoverBox)
        self.setLayout(self.layout)

    @QtCore.pyqtSlot(str, str, bytes)
    def changeCoverArtBoxInformation(self, title, artist, cover):
        self.albumCoverBox.setCoverArtBox(title, artist, cover)

    @QtCore.pyqtSlot(UUID, str, int, int)
    def addPlaylistEntry(self, uuid, name, row=0, column=0):
        model = self.model
        parent = model.getTopLevelIndex('PLAYLISTS')
        if model.insertPlaylistEntry(row, name, uuid, parent):
            self.playlistAdded.emit(uuid)

        child = model.index(row, column, parent)
        self.leftBarView.selectionModel().setCurrentIndex(
            child, QItemSelectionModel.SelectCurrent)
        self.leftBarView.edit(child)

    @QtCore.pyqtSlot(UUID, int, int)
    def createDefaults(self, uuid, row=0, column=0):
        model = self.model
        parent = model.getTopLevelIndex('LIBRARY')
        model.insertPlaylistEntry(row, 'Songs', uuid, parent)

    def __getUuidFromIndex(self, index):
        model = self.model
        uuid = model.getItemUuid(index)
        return uuid

    def __getIndexFromUuid(self, uuid):
        model = self.model
        row = model.getIndexFromUuid(uuid)
        return row

    @QtCore.pyqtSlot(UUID)
    def removePlaylistEntry(self, uuid):
        model = self.model
        row = self.__getIndexFromUuid(uuid)
        parent = model.getTopLevelIndex('PLAYLISTS')

        if not model.removeRow(row, parent):
            return None
예제 #33
0
class PropertyWidget(QWidget):
    def __init__(self, itemView, parent=None):
        super(PropertyWidget, self).__init__(parent)
        self.itemView = itemView
        self.currentRow = None

        # labels
        nameLabel = QLabel("Title")
        fileLabel = QLabel("Source path")
        groupLabel = QLabel("Group")

        # line edit
        self.nameEdit = QLineEdit()
        self.pathEdit = QLineEdit()
        self.groupEdit = QLineEdit()
        self.noteEdit = QTextEdit()

        # buttons
        self.browseButton = QToolButton(self)
        self.browseButton.setToolButtonStyle(Qt.ToolButtonTextOnly)
        self.browseButton.setArrowType(Qt.DownArrow)
        self.browseButton.setPopupMode(QToolButton.MenuButtonPopup)
        self.browseButton.setText('Browse...')
        self.browseButton.setAutoRaise(True)
        menu = QMenu(self)
        menu.addAction('Browse Path', lambda: self.slot_browse(0))
        menu.addAction('Browse file', lambda: self.slot_browse(1))
        self.browseButton.setMenu(menu)

        # dir tree
        self.tree = QTreeView()
        self.tree.setAnimated(False)
        self.tree.setIndentation(20)
        self.tree.setSortingEnabled(True)

        model = QFileSystemModel()
        self.tree.setModel(model)
        self.tree.header().setSectionResizeMode(QHeaderView.ResizeToContents)

        # tree and comments tabs
        self.tabWidget = QTabWidget()
        self.tabWidget.addTab(self.tree, "Navigation")
        self.tabWidget.addTab(self.noteEdit, "Comments")

        # set layout
        mainLayout = QGridLayout()
        mainLayout.addWidget(nameLabel, 0, 0)  # title
        mainLayout.addWidget(self.nameEdit, 0, 1, 1, 2)
        mainLayout.addWidget(fileLabel, 1, 0)  # path
        mainLayout.addWidget(self.pathEdit, 1, 1)
        mainLayout.addWidget(self.browseButton, 1, 2)
        mainLayout.addWidget(groupLabel, 2, 0)  # group
        mainLayout.addWidget(self.groupEdit, 2, 1, 1, 2)
        mainLayout.addWidget(self.tabWidget, 3, 0, 1, 3)
        self.setLayout(mainLayout)

        # initial status
        self.tabWidget.setTabEnabled(0, False)
        self.pathEdit.setEnabled(False)
        self.groupEdit.setEnabled(False)

        # signals
        self.nameEdit.textChanged.connect(self.slot_saveItem)
        self.pathEdit.textChanged.connect(self.slot_saveItem)
        self.noteEdit.textChanged.connect(self.slot_saveItem)
        self.tree.doubleClicked.connect(self.slot_openSource)

    @staticmethod
    def setTextSafely(textEdit, value):
        textEdit.blockSignals(True)
        textEdit.setText(value)
        textEdit.blockSignals(False)

    def setEditorsEnbaled(self, enabled=True):
        self.nameEdit.setEnabled(enabled)
        self.noteEdit.setEnabled(enabled)
        self.browseButton.setEnabled(enabled)

    def setup(self, index, data):
        '''set data
           :param index: index of source model, so the following process should 
                    also apply on source model, rather than proxy model by default
        '''
        self.setEditorsEnbaled(True)

        self.currentRow = index.row() if index else None
        name, group, path, comments = data
        self.setTextSafely(self.nameEdit, name)
        self.setTextSafely(self.pathEdit, path)
        self.setTextSafely(self.groupEdit, group)
        self.setTextSafely(self.noteEdit, comments)
        self.updateTree(path)  # set dir tree status

    def slot_saveItem(self):
        '''save when changed'''
        editor = self.sender()

        if editor == self.nameEdit:
            value = self.nameEdit.text()
            col = ItemModel.NAME
        elif editor == self.pathEdit:
            value = self.pathEdit.text()
            col = ItemModel.PATH
        elif editor == self.noteEdit:
            value = self.noteEdit.toPlainText()
            col = ItemModel.NOTES
        else:
            return

        # update values
        model = self.itemView.model().sourceModel()
        index = model.index(self.currentRow, col)
        if index.isValid():
            model.setData(index, value)

        # update unreferenced status if path is updated:
        # move item to UNGROUPED if current group is UNREFERENCED
        if editor == self.pathEdit:
            group_index = model.index(self.currentRow, ItemModel.GROUP)
            if group_index.data() == GroupModel.UNREFERENCED:
                model.setData(group_index, GroupModel.UNGROUPED)

    def slot_openSource(self, index):
        '''open source file/folder from navigation tree'''
        path = self.tree.model().filePath(index)
        QDesktopServices.openUrl(QUrl.fromLocalFile(path))

    def slot_browse(self, path_type):
        if path_type == 0:
            path = QFileDialog.getExistingDirectory(self,
                                                    "Select directory...")
        else:
            path, _ = QFileDialog.getOpenFileName(self, "Select file...")
        if path:
            self.pathEdit.setText(path)
            if not self.nameEdit.text():
                self.nameEdit.setText(os.path.basename(path))

            # update dir tree
            self.updateTree(path)

    def updateTree(self, path):
        '''show dir tree if directory else set disabled'''
        if os.path.isdir(path):
            # set root path
            model = self.tree.model()
            model.setRootPath(path)
            self.tree.setRootIndex(model.index(path))
            # activate tree tab
            self.tabWidget.setTabEnabled(0, True)
            self.tabWidget.setCurrentIndex(0)
        else:
            self.tabWidget.setTabEnabled(0, False)