Ejemplo n.º 1
0
    def initializePage(self):
        model = QStandardItemModel()

        # using a document model, we can obtain all the documents to list inside this view...
        all_docs = DocumentStorage.documents()
        for doc_filename in all_docs:
            # find out the last scan date, number of files, etc
            document = PersistentScanningState(doc_filename)
            logger.debug("found info: {0}".format(document.info))
            creation_date_str = str(document.info.date_created)
            last_date = str(document.info.date_last_scanned)
            num_scanned = "{0:,}".format(document.info.files_scanned)
            num_merged = "{0:,}".format(document.info.files_merged)
            is_merged = document.info.merge_complete
            if not is_merged:
                last_date_str = ""
            else:
                last_date_str = last_date

            doc = os.path.split(doc_filename)[1][:-len('.sqlite')]
            items = [
                QStandardItem(doc),
                QStandardItem(str(num_scanned)),
                QStandardItem(creation_date_str),
                QStandardItem(str(num_merged)),
                QStandardItem(last_date_str),
            ]

            items[1].setData(Qt.AlignRight, Qt.TextAlignmentRole)
            items[3].setData(Qt.AlignRight, Qt.TextAlignmentRole)

            model.invisibleRootItem().appendRow(items)

        self.ui.treeView.setModel(model)

        header = self.ui.treeView.header()

        model.setHeaderData(0, Qt.Horizontal, "Name")
        model.setHeaderData(1, Qt.Horizontal, "# First Scan")
        model.setHeaderData(2, Qt.Horizontal, "Date Created")
        model.setHeaderData(3, Qt.Horizontal, "# Second Scan")
        model.setHeaderData(4, Qt.Horizontal, "Date Scanned")

        header.setResizeMode(0, QHeaderView.ResizeToContents)
        header.setResizeMode(1, QHeaderView.ResizeToContents)
        header.setResizeMode(2, QHeaderView.ResizeToContents)
        header.setResizeMode(3, QHeaderView.ResizeToContents)
        header.setResizeMode(4, QHeaderView.ResizeToContents)

        self.ui.treeView.selectionModel().currentRowChanged.connect(
            self.__onSelectionChanged)
Ejemplo n.º 2
0
    def initializePage(self):
        model = QStandardItemModel()

        # using a document model, we can obtain all the documents to list inside this view...
        all_docs = DocumentStorage.documents()
        for doc_filename in all_docs:
            # find out the last scan date, number of files, etc
            document = PersistentScanningState(doc_filename)
            logger.debug("found info: {0}".format(document.info))
            creation_date_str = str(document.info.date_created)
            last_date = str(document.info.date_last_scanned)
            num_scanned = "{0:,}".format(document.info.files_scanned)
            num_merged = "{0:,}".format(document.info.files_merged)
            is_merged = document.info.merge_complete
            if not is_merged:
                last_date_str = ""
            else:
                last_date_str = last_date

            doc = os.path.split(doc_filename)[1][:-len('.sqlite')]
            items = [
                QStandardItem(doc),
                QStandardItem(str(num_scanned)),
                QStandardItem(creation_date_str),
                QStandardItem(str(num_merged)),
                QStandardItem(last_date_str),
            ]

            items[1].setData(Qt.AlignRight, Qt.TextAlignmentRole)
            items[3].setData(Qt.AlignRight, Qt.TextAlignmentRole)

            model.invisibleRootItem().appendRow(items)

        self.ui.treeView.setModel(model)

        header = self.ui.treeView.header()

        model.setHeaderData(0, Qt.Horizontal, "Name")
        model.setHeaderData(1, Qt.Horizontal, "# First Scan")
        model.setHeaderData(2, Qt.Horizontal, "Date Created")
        model.setHeaderData(3, Qt.Horizontal, "# Second Scan")
        model.setHeaderData(4, Qt.Horizontal, "Date Scanned")

        header.setResizeMode(0, QHeaderView.ResizeToContents)
        header.setResizeMode(1, QHeaderView.ResizeToContents)
        header.setResizeMode(2, QHeaderView.ResizeToContents)
        header.setResizeMode(3, QHeaderView.ResizeToContents)
        header.setResizeMode(4, QHeaderView.ResizeToContents)

        self.ui.treeView.selectionModel().currentRowChanged.connect(self.__onSelectionChanged)
Ejemplo n.º 3
0
    def on_ions_updated(self, new_ions):
        qmodel = QStandardItemModel()
        qmodel.setColumnCount(2)
        qmodel.setHorizontalHeaderItem(0, QStandardItem('Ion'))
        qmodel.setHorizontalHeaderItem(1, QStandardItem('Abundance (%)'))

        root = qmodel.invisibleRootItem()

        element_keyfunc = lambda x: x.isotope.element
        sorted_ions = sorted(new_ions, key=element_keyfunc)

        for element, ions in itertools.groupby(sorted_ions, key=element_keyfunc):
            element_item = QStandardItem(element)
            element_item.setCheckable(True)
            element_item.setCheckState(2)
            root.appendRow(element_item)

            for ion in ions:
                ion_name = QStandardItem(ion.name)
                ion_name.setData(ion,32)
                ion_name.emitDataChanged()
                ion_abundance = QStandardItem(str(ion.isotope.abundance))
                element_item.appendRow([ion_name, ion_abundance])

        self.ionlistTree.setModel(qmodel)
        self.ionlistTree.expandAll()
        self.addionsButton.setEnabled(True)
        self._qmodel=qmodel
Ejemplo n.º 4
0
    def on_analyses_viewmodel_updated(self, view_model):
        qmodel = QStandardItemModel()
        qmodel.itemChanged.connect(self.on_qmodel_itemChanged)
        qmodel.setColumnCount(5)
        qmodel.setHorizontalHeaderItem(0, QStandardItem('Ion'))
        qmodel.setHorizontalHeaderItem(1, QStandardItem('Method'))
        qmodel.setHorizontalHeaderItem(2, QStandardItem('Start'))
        qmodel.setHorizontalHeaderItem(3, QStandardItem('End'))
        qmodel.setHorizontalHeaderItem(4, QStandardItem('Reason'))

        root = qmodel.invisibleRootItem()

        for ion, analysis in view_model.analyses.items():
            ion_name = QStandardItem(ion.name)
            ion_name.setData(ion, Qt.UserRole)
            method = QStandardItem(analysis.method)
            start = QStandardItem(str(round(analysis.range.start,2)))
            end = QStandardItem(str(round(analysis.range.end,2)))
            reason = QStandardItem(analysis.reason)

            root.appendRow([ion_name, method, start, end, reason])

        self.rangedTable.setModel(qmodel)
        self.rangedTable.setItemDelegateForColumn(1, MethodsComboDelegate(view_model.methods, self.rangedTable))
        for row in range(0, qmodel.rowCount()):
            self.rangedTable.openPersistentEditor(qmodel.index(row, 1))
        self.rangedTable.setColumnWidth(1, 95)
        self.rangedTable.setContextMenuPolicy(3)
        self.rangedTable.customContextMenuRequested.connect(self._context_menu_requested)
        shortcut = QShortcut(QKeySequence('Del'), self.rangedTable, self._delete_ion,self._delete_ion, context=0)
Ejemplo n.º 5
0
class BreakpointsViewer(QTreeView):
    """ showing bps  """
    def __init__(self, parent):
        super(QTreeView, self).__init__(parent)
        self.setAutoScroll(True)
        self.source_files = {}
        self.focus_signal = None
        self.header().setResizeMode(QHeaderView.ResizeToContents)
        self._show_args = None
        self.bp_data = QStandardItemModel()
        self.setModel(self.bp_data)
        self.setAlternatingRowColors(True)

    def set_focus_signal(self, signal):
        """ set callback to focus source file line"""
        self.focus_signal = signal

    def clear(self):
        """ clear the widget"""
        self.bp_data.clear()
        self.bp_data.setHorizontalHeaderLabels(['ID', 'Hits', 'Ignore Count', 'Condition'])

    def update_bp_info(self, target):
        """ update breakpoint info """
        self.clear()
        root = self.bp_data.invisibleRootItem()
        for breakpoint in target.breakpoint_iter():
            if not breakpoint.IsValid() or breakpoint.IsInternal():
                continue
            bp_item = QStandardItem(str(breakpoint.id))
            bp_row =[bp_item, QStandardItem(str(breakpoint.GetHitCount())), 
                       QStandardItem(str(breakpoint.GetIgnoreCount())), QStandardItem(str(breakpoint.GetCondition()))]
            for loc in breakpoint:
                loc_row = [QStandardItem(str(loc.GetID())), QStandardItem(str(loc.GetAddress().GetLineEntry()))]
                bp_item.appendRow(loc_row)
            root.appendRow(bp_row)
        self.expandToDepth(1)

    def mousePressEvent(self, event):
        """ overrided """
        idx = self.indexAt(event.pos())
        if idx.isValid() and self.focus_signal:
            model = idx.model()
            idx = idx.sibling(idx.row(), 0)
            if idx.isValid():
                item = model.itemFromIndex(idx)
                if item and item.isSelectable():
                    if item in self.source_files:
                        file_info = self.source_files[item]
                        if self.focus_signal:
                            self.focus_signal.emit(file_info.GetFileSpec().fullpath,
                                                   file_info.GetLine())
                        self.frame_changed.emit(self.frames[item])

                    else:
                        logging.error('frame cannot find associated source file')

        QTreeView.mousePressEvent(self, event)
 def update_commands(self,meas_prog_list_byname):
     global Regexprogramfile
     Regexprogramfile="("+"|".join(meas_prog_list_byname)+")"
     self.valid_list_of_commands = self.get_list_of_commands()
     #initiate syntax highlighting for the macro editor
     self.highlighter = MacroHighlighter(self.ui.macro_textbox.document(),self.valid_list_of_commands)
     #update the list of available macro commands in the user interface
     model=QStandardItemModel()
     parentItem = model.invisibleRootItem()
     for command in self.valid_list_of_commands:
         parentItem.appendRow(QStandardItem(command.label))
     self.ui.macrocommandtree.setModel(model)
Ejemplo n.º 7
0
 def update_commands(self, meas_prog_list_byname):
     global Regexprogramfile
     Regexprogramfile = "(" + "|".join(meas_prog_list_byname) + ")"
     self.valid_list_of_commands = self.get_list_of_commands()
     #initiate syntax highlighting for the macro editor
     self.highlighter = MacroHighlighter(self.ui.macro_textbox.document(),
                                         self.valid_list_of_commands)
     #update the list of available macro commands in the user interface
     model = QStandardItemModel()
     parentItem = model.invisibleRootItem()
     for command in self.valid_list_of_commands:
         parentItem.appendRow(QStandardItem(command.label))
     self.ui.macrocommandtree.setModel(model)
Ejemplo n.º 8
0
class Menu(TreeViewTela):
    def __init__(self, altura, parent=None):
        super().__init__(altura, parent)

        self._model = QStandardItemModel(0, 1)
        self._model.setHorizontalHeaderItem(0, QStandardItem("Menu"))

        self._itemsFuncoes = []

    def setMenu(self, menu):
        self._adicionarSubMenu(menu, self._model.invisibleRootItem())
        self.setSelecionado(self._model.index(0,0))

    def getMenuSelecionado(self):
        sel = self.getSelecionado()
        s = ''
        while sel.isValid():
            s = '/' + sel.data() + s
            sel = sel.parent()
        return s

    def getFuncaoItem(self, item):
        for i in self._itemsFuncoes:
            if i.item == item.data():
                return i.funcao

    def getFuncaoItemSelecionado(self):
        return self.getFuncaoItem(self.getSelecionado())
        
    def _adicionarSubMenu(self, subMenu, pai):
        if isinstance(subMenu, ItemFuncao):
            item = QStandardItem(subMenu.item)
            self._itemsFuncoes.append(subMenu)
            pai.appendRow(item)
        elif isinstance(subMenu, str):
            pai.appendRow(QStandardItem(subMenu))
        elif isinstance(subMenu, (tuple, list)):
            for i in subMenu:
                self._adicionarSubMenu(i, pai)
        else:
            for key, value in subMenu.items():
                p = QStandardItem(key)
                pai.appendRow(p)
                self._adicionarSubMenu(value, p)
Ejemplo n.º 9
0
class ConfigDialog(BASE, WIDGET):

    def __init__(self, toolbox):
        super(ConfigDialog, self).__init__(None)
        self.setupUi(self)

        self.toolbox = toolbox
        self.groupIcon = QIcon()
        self.groupIcon.addPixmap(self.style().standardPixmap(
            QStyle.SP_DirClosedIcon), QIcon.Normal, QIcon.Off)
        self.groupIcon.addPixmap(self.style().standardPixmap(
            QStyle.SP_DirOpenIcon), QIcon.Normal, QIcon.On)

        if hasattr(self.searchBox, 'setPlaceholderText'):
            self.searchBox.setPlaceholderText(self.tr('Search...'))

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

        self.delegate = SettingDelegate()
        self.tree.setItemDelegateForColumn(1, self.delegate)

        self.searchBox.textChanged.connect(self.fillTree)

        self.fillTree()

        self.tree.expanded.connect(self.adjustColumns)

    def fillTree(self):
        self.items = {}
        self.model.clear()
        self.model.setHorizontalHeaderLabels([self.tr('Setting'),
                                              self.tr('Value')])

        text = unicode(self.searchBox.text())
        settings = ProcessingConfig.getSettings()

        rootItem = self.model.invisibleRootItem()
        priorityKeys = [self.tr('General'), self.tr('Models'), self.tr('Scripts')]
        for group in priorityKeys:
            groupItem = QStandardItem(group)
            icon = ProcessingConfig.getGroupIcon(group)
            groupItem.setIcon(icon)
            groupItem.setEditable(False)
            emptyItem = QStandardItem()
            emptyItem.setEditable(False)
            rootItem.insertRow(0, [groupItem, emptyItem])
            for setting in settings[group]:
                if setting.hidden or setting.name.startswith("MENU_"):
                    continue

                if text == '' or text.lower() in setting.description.lower():
                    labelItem = QStandardItem(setting.description)
                    labelItem.setIcon(icon)
                    labelItem.setEditable(False)
                    self.items[setting] = SettingItem(setting)
                    groupItem.insertRow(0, [labelItem, self.items[setting]])

            if text != '':
                self.tree.expand(groupItem.index())

        providersItem = QStandardItem(self.tr('Providers'))
        icon = QIcon(os.path.join(pluginPath, 'images', 'alg.png'))
        providersItem.setIcon(icon)
        providersItem.setEditable(False)
        emptyItem = QStandardItem()
        emptyItem.setEditable(False)
        rootItem.insertRow(0, [providersItem, emptyItem])
        for group in settings.keys():
            if group in priorityKeys or group == menusSettingsGroup:
                continue

            groupItem = QStandardItem(group)
            icon = ProcessingConfig.getGroupIcon(group)
            groupItem.setIcon(icon)
            groupItem.setEditable(False)
            for setting in settings[group]:
                if setting.hidden:
                    continue

                if text == '' or text.lower() in setting.description.lower():
                    labelItem = QStandardItem(setting.description)
                    labelItem.setIcon(icon)
                    labelItem.setEditable(False)
                    self.items[setting] = SettingItem(setting)
                    groupItem.insertRow(0, [labelItem, self.items[setting]])

            emptyItem = QStandardItem()
            emptyItem.setEditable(False)
            providersItem.appendRow([groupItem, emptyItem])

        menusItem = QStandardItem(self.tr('Menus (requires restart)'))
        icon = QIcon(os.path.join(pluginPath, 'images', 'menu.png'))
        menusItem.setIcon(icon)
        menusItem.setEditable(False)
        emptyItem = QStandardItem()
        emptyItem.setEditable(False)
        rootItem.insertRow(0, [menusItem, emptyItem])
        providers = Processing.providers
        for provider in providers:
            groupItem = QStandardItem(provider.getDescription())
            icon = provider.getIcon()
            groupItem.setIcon(icon)
            groupItem.setEditable(False)
            for alg in provider.algs:
                labelItem = QStandardItem(alg.name)
                labelItem.setIcon(icon)
                labelItem.setEditable(False)
                try:
                    setting = ProcessingConfig.settings["MENU_" + alg.commandLineName()]
                except:
                    continue
                self.items[setting] = SettingItem(setting)
                groupItem.insertRow(0, [labelItem, self.items[setting]])
            emptyItem = QStandardItem()
            emptyItem.setEditable(False)
            menusItem.appendRow([groupItem, emptyItem])

        self.tree.sortByColumn(0, Qt.AscendingOrder)
        self.adjustColumns()

    def accept(self):
        for setting in self.items.keys():
            if isinstance(setting.value, bool):
                setting.setValue(self.items[setting].checkState() == Qt.Checked)
            else:
                try:
                    setting.setValue(unicode(self.items[setting].text()))
                except ValueError as e:
                    QMessageBox.warning(self, self.tr('Wrong value'),
                                        self.tr('Wrong value for parameter "%s":\n\n%s' % (setting.description, unicode(e))))
                    return
            setting.save()
        Processing.updateAlgsList()
        updateMenus()

        QDialog.accept(self)

    def adjustColumns(self):
        self.tree.resizeColumnToContents(0)
        self.tree.resizeColumnToContents(1)
Ejemplo n.º 10
0
class SubPowerWidget(QWidget):
    """
	@brief Zeigt alle Unterkräfte in einer Baumstruktur an.
	"""
    def __init__(self, template, character, parent=None):
        super(SubPowerWidget, self).__init__(parent)

        self.__storage = template
        self.__character = character

        self.__model = QStandardItemModel()
        # Das ungenutzte Model dient dazu, alle Unterkräfte aufzunehmen, die ich nicht darstellen möchte. Ist einfacher, als diese im View zu verstecken.
        self.__modelUnused = QStandardItemModel()

        self._layout = QVBoxLayout()
        self.setLayout(self._layout)

        self.__view = QTreeView()
        self.__view.setHeaderHidden(True)
        self.__view.setModel(self.__model)

        self._layout.addWidget(self.__view)

        self._typ = "Subpower"
        categories = self.__storage.categories(self._typ)

        self.__items = {}

        self.__rootItem = QStandardItem()
        self.__rootItem = self.__model.invisibleRootItem()

        self.__rootItemUnused = QStandardItem()
        self.__rootItemUnused = self.__modelUnused.invisibleRootItem()

        for item in categories:
            categoryItem = QStandardItem(item)
            self.__rootItem.appendRow(categoryItem)

            ## Ich benötige diese Items auch im ungenutzten Model.
            categoryItemUnused = QStandardItem(item)
            self.__rootItemUnused.appendRow(categoryItemUnused)

            traitList = list(self.__character.traits[self._typ][item].items())
            traitList.sort()
            for trait in traitList:
                traitItem = QStandardItem(trait[1].name)
                traitItem.setCheckable(True)
                ## Unhashable Type
                self.__items[trait[1]] = traitItem
                categoryItem.appendRow(traitItem)

                ## Funktioniert mit PySide nicht:
                #trait[1].availableChanged.connect(traitItem.setEnabled)
                ## Funktioniert auch mit PySide:
                trait[1].availableChanged.connect(
                    lambda enable, item=traitItem: item.setEnabled(enable))
                trait[1].valueChanged.connect(lambda val, trait=trait[
                    1], item=traitItem: self.__setItemValue(trait, item))

        self.__model.itemChanged.connect(self.__getItemValue)
        self.__character.speciesChanged.connect(self.hideOrShowToolPage)
        self.__character.breedChanged.connect(self.hideOrShowToolPage)
        self.__character.factionChanged.connect(self.hideOrShowToolPage)

    def __setItemValue(self, trait, item):
        """
		Setzt den Wert der Angezeigten Items.
		"""

        if trait.value == 0:
            item.setCheckState(Qt.Unchecked)
        elif trait.value == 1:
            item.setCheckState(Qt.PartiallyChecked)
        else:
            item.setCheckState(Qt.Checked)

    def __getItemValue(self, item):
        """
		Setzt den Wert der Eigenschaft im Speicher.
		"""

        for trait in self.__items.items():
            if id(trait[1]) == id(item):
                trait[0].value = item.checkState()
                break

    def hideOrShowToolPage(self, res):
        """
		Alle Eigenschaften, die nicht zur Verfügung stehen, werden verborgen, indem sie in ein anderes Model verschoben werden.

		\bug Möglicher Fehler in PySide: Der Aufruf von QStandardItem.model() führt beim Beenden des Programms zu einem Segmentation Fault.
		"""

        # Versteckt alle Unterkräfte, die zu gewähltem Charakter nicht passen.
        for item in self.__items.items():
            if ((item[0].species
                 and item[0].species != self.__character.species) or
                (item[0].only and self.__character.breed not in item[0].only
                 and self.__character.faction not in item[0].only)):
                #self.__view.setRowHidden(item[1].index().row(), item[1].parent().index(), True)
                #Debug.debug(item[1].model())
                ## Hier wird beispielsweise besagter Aufruf getätigt, der zu einem segfault führt.
                if item[1].model() == self.__model:
                    parent = item[1].parent()
                    itemUnused = parent.takeRow(item[1].index().row())
                    parentUnused = self.__modelUnused.findItems(
                        parent.text())[0]
                    parentUnused.appendRow(itemUnused)
            else:
                #self.__view.setRowHidden(item[1].index().row(), item[1].parent().index(), False)
                if item[1].model() == self.__modelUnused:
                    parent = item[1].parent()
                    itemUsed = parent.takeRow(item[1].index().row())
                    parentUsed = self.__model.findItems(parent.text())[0]
                    parentUsed.appendRow(itemUsed)

        ## Versteckt alle Elternzeilen, wenn sie keine Kinder enthalten.
        for i in range(self.__model.rowCount()):
            categoryItem = self.__model.item(i)
            if categoryItem.hasChildren():
                self.__view.setRowHidden(categoryItem.index().row(),
                                         self.__rootItem.index(), False)
            else:
                self.__view.setRowHidden(categoryItem.index().row(),
                                         self.__rootItem.index(), True)
Ejemplo n.º 11
0
class ConfigManagerDialog(ui_configmanager.Ui_ProjectInstallerDialog, QDialog):
    def __init__(self, roamapp, parent=None):
        super(ConfigManagerDialog, self).__init__(parent)
        self.setupUi(self)
        self.bar = roam.messagebaritems.MessageBar(self)

        self.roamapp = roamapp

        # Nope!
        self.projectwidget.roamapp = roamapp
        self.projectwidget.bar = self.bar

        self.treemodel = QStandardItemModel()
        self.projectList.setModel(self.treemodel)
        self.projectList.setHeaderHidden(True)

        self.projectList.selectionModel().currentChanged.connect(
            self.nodeselected)

        self.projectwidget.adjustSize()
        self.setWindowFlags(Qt.Window)

        self.projectwidget.projectupdated.connect(self.projectupdated)

        self.projectwidget.setaboutinfo()
        self.projectwidget.projects_page.projectlocationchanged.connect(
            self.loadprojects)
        self.setuprootitems()

        ConfigEvents.deleteForm.connect(self.delete_form)

    def raiseerror(self, *exinfo):
        self.bar.pushError(*exinfo)
        import roam.errors
        roam.errors.send_exception(exinfo)

    def setuprootitems(self):
        rootitem = self.treemodel.invisibleRootItem()
        self.roamnode = RoamNode()
        rootitem.appendRow(self.roamnode)

        self.projectsnode = ProjectsNode(folder=None)
        rootitem.appendRow(self.projectsnode)

        self.pluginsnode = PluginsNode()
        pluginpath = os.path.join(self.roamapp.apppath, "plugins")
        rootitem.appendRow(self.pluginsnode)
        self.pluginsnode.add_plugin_paths([pluginpath])

    def delete_form(self):
        index = self.projectList.currentIndex()
        node = index.data(Qt.UserRole)
        if not node.type() == Treenode.FormNode:
            return

        title, removemessage = node.removemessage
        delete = node.canremove
        if node.canremove and removemessage:
            button = QMessageBox.warning(self, title, removemessage,
                                         QMessageBox.Yes | QMessageBox.No)
            delete = button == QMessageBox.Yes

        print "Delete"
        if delete:
            parentindex = index.parent()
            newindex = self.treemodel.index(index.row(), 0, parentindex)
            if parentindex.isValid():
                parent = parentindex.data(Qt.UserRole)
                parent.delete(index.row())

            print parentindex
            self.projectList.setCurrentIndex(parentindex)

    def delete_project(self):
        index = self.projectList.currentIndex()
        node = index.data(Qt.UserRole)
        if node.type() == Treenode.ProjectNode:
            self.projectwidget._closeqgisproject()

        title, removemessage = node.removemessage
        delete = node.canremove
        if node.canremove and removemessage:
            button = QMessageBox.warning(self, title, removemessage,
                                         QMessageBox.Yes | QMessageBox.No)
            delete = button == QMessageBox.Yes

        if delete:
            parentindex = index.parent()
            newindex = self.treemodel.index(index.row(), 0, parentindex)
            if parentindex.isValid():
                parent = parentindex.data(Qt.UserRole)
                parent.delete(index.row())

            self.projectList.setCurrentIndex(newindex)

    def addprojectfolders(self, folders):
        self.projectwidget.projects_page.setprojectfolders(folders)

    def loadprojects(self, projectpath):
        projects = roam.project.getProjects([projectpath])
        self.projectsnode.loadprojects(projects, projectsbase=projectpath)

        index = self.treemodel.indexFromItem(self.projectsnode)
        self.projectList.setCurrentIndex(index)
        self.projectList.expand(index)

    def nodeselected(self, index, _):
        node = index.data(Qt.UserRole)
        if node is None:
            return

        project = node.project
        if project and not self.projectwidget.project == project:
            # Only load the project if it's different the current one.
            self.projectwidget.setproject(project)
            node.create_children()

            validateresults = list(project.validate())
            if validateresults:
                text = "Here are some reasons we found: \n\n"
                for message in validateresults:
                    text += "- {} \n".format(message)

                self.projectwidget.reasons_label.setText(text)

        if node.nodetype == Treenode.RoamNode:
            self.projectwidget.projectlabel.setText(
                "IntraMaps Roam Config Manager")

        if node.nodetype == Treenode.AddNew:
            try:
                item = node.additem()
            except ValueError:
                return
            newindex = self.treemodel.indexFromItem(item)
            self.projectList.setCurrentIndex(newindex)
            return

        self.projectwidget.projectbuttonframe.setVisible(not project is None)
        self.projectwidget.setpage(node.page, node)

    def projectupdated(self):
        index = self.projectList.currentIndex()
        node = find_node(index)
        node.refresh()
Ejemplo n.º 12
0
class FileTypes(base2, form2):
    def __init__(self, parent=None):
        super(base2, self).__init__(parent)
        self.setupUi(self)

        self.model = QStandardItemModel()
        self.model.itemChanged.connect(self.on_item_changed)
        self.model.setHorizontalHeaderItem(0, QStandardItem(""))
        self.model_init()

        self.saveButton.clicked.connect(self.save)
        self.okCancelBox.accepted.connect(self.accept)
        self.okCancelBox.rejected.connect(self.reject)
        self.treeView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.treeView.customContextMenuRequested.connect(self.openMenu)
        self.treeView.setToolTip(
            'Here you can select file types that you want to find. Also you can\nadd new category or file type. Click right button on it.'
        )

    def model_init(self):
        categories = {}
        if not categories:
            with open('categories.json') as f:
                categories = load(f)

        for element in categories:
            catItem = QStandardItem(element.keys()[0])
            catItem.setCheckable(True)
            catItem.setCheckState(element[element.keys()[0]])
            for type_name, check_state in element["Types"].items():
                typeItem = QStandardItem(type_name)
                typeItem.setCheckable(True)
                typeItem.setCheckState(check_state)
                catItem.appendRow(typeItem)
            self.model.appendRow(catItem)
        self.treeView.setModel(self.model)
        self.submit_file_types()

    def quit(self):
        self.close()

    def on_item_changed(self, item):
        if item.checkState() == Qt.Checked:
            if item.hasChildren():
                for row in range(item.rowCount()):
                    item.child(row).setCheckState(Qt.Checked)
            else:
                item.parent().setCheckState(Qt.PartiallyChecked)

        elif item.checkState() == Qt.Unchecked:
            if item.hasChildren():
                for row in range(item.rowCount()):
                    item.child(row).setCheckState(Qt.Unchecked)
            else:
                children = range(item.parent().rowCount())
                children.pop(item.index().row())
                for row in children:
                    if item.parent().child(row).checkState():
                        return
                item.parent().setCheckState(Qt.Unchecked)

    def submit_file_types(self):
        categories = []
        root = self.model.invisibleRootItem()

        for num_cat in range(root.rowCount()):
            category = root.child(num_cat, 0)
            categories.append({
                str(category.text()): category.checkState(),
                "Types": {}
            })
            for num_type in range(category.rowCount()):
                type = category.child(num_type, 0)
                categories[-1]["Types"].update(
                    {str(type.text()): type.checkState()})
        return categories

    def openMenu(self, position):
        level = 0
        index = self.treeView.selectedIndexes()[0]
        while index.parent().isValid():
            index = index.parent()
            level += 1

        menu = QMenu()
        if level == 0:
            menu.addAction(self.tr("Add category"), self.add_category)
            menu.addAction(self.tr("Add type"), self.add_type)
            menu.addAction(self.tr("Remove"), self.remove)
        elif level == 1:
            menu.addAction(self.tr("Add type"), self.add_type)
            menu.addAction(self.tr("Remove"), self.remove)

        menu.exec_(self.treeView.viewport().mapToGlobal(position))

    def add_category(self):
        text, ok = QInputDialog.getText(self, 'Create new category',
                                        'Category name:')
        if ok:
            catItem = QStandardItem(text)
            catItem.setCheckable(True)
            self.model.appendRow(catItem)
            #self.label.setText(unicode(text))

    def add_type(self):
        text, ok = QInputDialog.getText(self, 'Add new type', 'Postfix:')
        if ok:
            catType = QStandardItem(text)
            catType.setCheckable(True)
            index = self.treeView.selectedIndexes()[0]
            if self.model.itemFromIndex(index).hasChildren():
                self.model.itemFromIndex(index).appendRow(catType)
            else:
                self.model.itemFromIndex(index).parent().appendRow(catType)

    def save(self):
        with open('categories.json', 'w') as f:
            dump(self.submit_file_types(), f)

    def remove(self):
        index = self.treeView.selectedIndexes()[0]
        parent = self.model.itemFromIndex(index).parent()
        if parent:
            self.model.removeRow(index.row(), parent.index())
        else:
            parent = self.model.invisibleRootItem()
            self.model.removeRow(index.row(), parent.index())

    @staticmethod
    def call():
        dialog = FileTypes()
        result = dialog.exec_()
        categories = dialog.submit_file_types()
        return categories, result == QDialog.Accepted
Ejemplo n.º 13
0
class TreeviewWidgetSelectProve(QMainWindow):

    def __init__(self):
        super(TreeviewWidgetSelectProve, self).__init__()
        # self.uiw = loadUi("~/link/ROS/groovy_quantal/catkin_ws/src/rqt_prove/resource/treeview.ui")
        # self.uiw = loadUi("/resource/treeview.ui")
        self.uiw = loadUi("/home/n130s/link/ROS/groovy_quantal/catkin_ws/src/rqt_prove/resource/treeview.ui")

#        self._treeview = QTreeView(self)
#        self._treeview.SelectionMode = QAbstractItemView.ContiguousSelection

#        rp = rospkg.RosPack()
#        ui_file = os.path.join(rp.get_path('rqt_prove'),
#                               'resource', 'treeview.ui')
#        loadUi(ui_file, self)

        self._std_model = QStandardItemModel()
        self._rootitem = self._std_model.invisibleRootItem()

        item_r_1 = QStandardItem("r1")
        # item_r_2 = QStandardItem("r2")
        # item_r_3 = QStandardItem("r3")
        # self.item_r_3_1 = QStandardItem("r3-1")
        # self.item_r_3_1_1 = QStandardItem("child_c")
        # item_r_3.appendRow(self.item_r_3_1)
        # self.item_r_3_1.appendRow(self.item_r_3_1_1)
        # item_r_4 = QStandardItem("r4")
        # item_r_5 = QStandardItem("r5")
#        item_r_1 = TreenodeQstdItem("/a/rowrowrowrow1")
#        item_r_2 = TreenodeQstdItem("/b/rowrowrowrow2")
#        item_r_3 = TreenodeQstdItem("/c/rowrow3")
#        self.item_r_3_1 = TreenodeQstdItem("/c/rowrow3/child")
#        item_r_3.appendRow(self.item_r_3_1)
#        item_r_4 = TreenodeQstdItem("/d/row4")

        self._rootitem.appendRow(item_r_1)
        # self._rootitem.appendRow(item_r_2)
#        self._rootitem.appendRow(item_r_3)
#        self._rootitem.appendRow(item_r_4)
#        self._rootitem.appendRow(item_r_5)
        print('_rootitem index={}'.format(self._rootitem.index()))

        self.uiw._treeview.setModel(self._std_model)
        self.selectionModel = self.uiw._treeview.selectionModel()
        self.selectionModel.selectionChanged.connect(
                                                 self._selection_changed_slot)

        # print('del/sel?\tde/sel index\tde/sel.row\tde/sel.dat\tsel.item\tsel.item.name\tparent.de/sel\tparent.sel.dat\tinternal id')
        print('del/sel?\tde/sel index\tde/sel.row\tde/sel.dat\tparent\tinternal id')

        self.uiw.show()

    def _selection_changed_slot(self, selected, deselected):
        """
        Receives args from signal QItemSelectionModel.selectionChanged.

        :type selected: QItemSelection
        :type deselected: QItemSelection
        """
        self._test_sel_index(selected, deselected)

    def _test_sel_index(self, selected, deselected):
        src_model = self._std_model
        index_current = None
        index_deselected = None
        index_parent_sel = None
        index_parent_desel = None
        curr_qstd_item = None
        indexes = selected.indexes()
        del_or_sel = 'Sel'
        index_internalid = -1

        if len(indexes) > 0:
            index_internalid = selected.indexes()[0].internalId()

            # # Trying many approaches to get the right qindex
            # # Approach-1
            index_current = selected.indexes()[0]

            # # Approach-2

            # index_current_from_indexes = selected.indexes()[0]
            # index_current = src_model.index(index_current_from_indexes.row(),
                                            # 0, QModelIndex())
                                            # 0, index_current_from_indexes)
            # index_current = self.selectionModel.currentIndex()

            index_parent_sel = index_current.parent()
            curr_qstd_item = src_model.itemFromIndex(# index_parent)
                                                 index_current)
        elif len(deselected.indexes()) > 0:
            index_internalid = deselected.indexes()[0].internalId()

            del_or_sel = 'Desel'
            index_deselected = self.selectionModel.currentIndex()
            index_parent_desel = index_deselected.parent()
            curr_qstd_item = src_model.itemFromIndex(index_deselected)

        tabular_format = '{}\t{}\t{}\t{}\t{}\t{}'
        if len(indexes) > 0:
            print(tabular_format.format(
                              del_or_sel,
                              index_current,
                              index_current.row(),
                              index_current.data(Qt.DisplayRole).toString(),
                                  # curr_qstd_item,
                                  # curr_qstd_item.data(Qt.DisplayRole),
                              index_parent_sel,
                                  # index_parent_sel.data(Qt.DisplayRole),
                              index_internalid))
        elif len(deselected.indexes()) > 0:
            print(tabular_format.format(
                              del_or_sel,
                              index_deselected,
                              index_deselected.row(),
                              index_deselected.data(Qt.DisplayRole).toString(),
                              # curr_qstd_item,
                              #    curr_qstd_item.data(),
                                  index_parent_desel,
                              #  index_parent_desel.data(Qt.DisplayRole),
                                  index_internalid))
            self.selectionModel.select(index_deselected,
                                       QItemSelectionModel.Deselect)
Ejemplo n.º 14
0
class ConfigManagerDialog(ui_configmanager.Ui_ProjectInstallerDialog, QDialog):
    def __init__(self, roamapp, parent=None):
        super(ConfigManagerDialog, self).__init__(parent)
        self.setupUi(self)
        self.bar = roam.messagebaritems.MessageBar(self)

        self.roamapp = roamapp
        self.reloadingProject = False
        self.loadedProject = None

        # Nope!
        self.projectwidget.roamapp = roamapp
        self.projectwidget.bar = self.bar

        self.treemodel = QStandardItemModel()
        self.projectList.setModel(self.treemodel)
        self.projectList.setHeaderHidden(True)

        self.projectList.selectionModel().currentChanged.connect(self.nodeselected)

        self.projectwidget.adjustSize()
        self.setWindowFlags(Qt.Window)

        self.projectwidget.projectupdated.connect(self.projectupdated)
        self.projectwidget.projectloaded.connect(self.projectLoaded)

        self.projectwidget.setaboutinfo()
        self.projectwidget.projects_page.projectlocationchanged.connect(self.loadprojects)
        self.setuprootitems()

        ConfigEvents.deleteForm.connect(self.delete_form)

        # ## If all the layers are gone we need to reset back to the top state to get the widgets
        # ## back into sync.
        # QgsMapLayerRegistry.instance().removeAll.connect(self.reset_project)

    # def reset_project(self):
    #     print(QgsProject.instance().fileName())
    #     print("ALL REMOVED")
    #     node = self.projectsnode.find_by_filename(QgsProject.instance().fileName())

    def raiseerror(self, *exinfo):
        self.bar.pushError(*exinfo)
        import roam.errors
        roam.errors.send_exception(exinfo)

    def setuprootitems(self):
        rootitem = self.treemodel.invisibleRootItem()
        self.roamnode = RoamNode()
        rootitem.appendRow(self.roamnode)

        self.projectsnode = ProjectsNode(folder=None)
        rootitem.appendRow(self.projectsnode)

        self.pluginsnode = PluginsNode()
        pluginpath = os.path.join(self.roamapp.apppath, "plugins")
        rootitem.appendRow(self.pluginsnode)
        self.pluginsnode.add_plugin_paths([pluginpath])

    def delete_form(self):
        index = self.projectList.currentIndex()
        node = index.data(Qt.UserRole)
        if not node.type() == Treenode.FormNode:
            return

        title, removemessage = node.removemessage
        delete = node.canremove
        if node.canremove and removemessage:
            button = QMessageBox.warning(self, title, removemessage, QMessageBox.Yes | QMessageBox.No)
            delete = button == QMessageBox.Yes

        print "Delete"
        if delete:
            parentindex = index.parent()
            newindex = self.treemodel.index(index.row(), 0, parentindex)
            if parentindex.isValid():
                parent = parentindex.data(Qt.UserRole)
                parent.delete(index.row())

            print parentindex
            self.projectList.setCurrentIndex(parentindex)

    def delete_project(self):
        index = self.projectList.currentIndex()
        node = index.data(Qt.UserRole)
        if node.type() == Treenode.ProjectNode:
            self.projectwidget._closeqgisproject()

        title, removemessage = node.removemessage
        delete = node.canremove
        if node.canremove and removemessage:
            button = QMessageBox.warning(self, title, removemessage, QMessageBox.Yes | QMessageBox.No)
            delete = button == QMessageBox.Yes

        if delete:
            parentindex = index.parent()
            newindex = self.treemodel.index(index.row(), 0, parentindex)
            if parentindex.isValid():
                parent = parentindex.data(Qt.UserRole)
                parent.delete(index.row())

            self.projectList.setCurrentIndex(newindex)

    def addprojectfolders(self, folders):
        self.projectwidget.projects_page.setprojectfolders(folders)

    def loadprojects(self, projectpath):
        projects = roam.project.getProjects([projectpath])
        self.projectsnode.loadprojects(projects, projectsbase=projectpath)

        index = self.treemodel.indexFromItem(self.projectsnode)
        self.projectList.setCurrentIndex(index)
        self.projectList.expand(index)

    def projectLoaded(self, project):
        roam.utils.info("Project loaded: {}".format(project.name))
        node = self.projectsnode.find_by_name(project.name)
        node.create_children()
        self.projectwidget.setpage(node.page, node, refreshingProject=True)
        self.reloadingProject = False
        self.loadedProject = project
        self.projectList.setExpanded(node.index(), True )

    def nodeselected(self, index, last, reloadProject=False):
        node = index.data(Qt.UserRole)
        if node is None:
            return

        project = node.project

        if project:
            validateresults = list(project.validate())
            if validateresults:
                text = "Here are some reasons we found: \n\n"
                for message in validateresults:
                    text += "- {} \n".format(message)

                self.projectwidget.reasons_label.setText(text)
                return

        if node.nodetype == Treenode.ProjectNode and reloadProject:
            self.reloadingProject = True
            self.projectwidget.setproject(project)
            return

        if project and self.loadedProject != project:
            # Only load the project if it's different the current one.
            roam.utils.info("Swapping to project: {}".format(project.name))
            if self.loadedProject:
                lastnode = self.projectsnode.find_by_name(self.loadedProject.name)
                self.projectList.setExpanded(lastnode.index(), False )
            ## We are closing the open project at this point. Watch for null ref after this.
            self.projectwidget.setproject(project)
            return
        else:
            roam.utils.debug("Setting page")
            self.projectwidget.setpage(node.page, node)

        if node.nodetype == Treenode.RoamNode:
            self.projectwidget.projectlabel.setText("IntraMaps Roam Config Manager")

        if node.nodetype == Treenode.AddNew:
            try:
                item = node.additem()
            except ValueError:
                return
            newindex = self.treemodel.indexFromItem(item)
            self.projectList.setCurrentIndex(newindex)
            return

        self.projectwidget.projectbuttonframe.setVisible(not project is None)


    def projectupdated(self, project):
        # index = self.projectList.currentIndex()
        # node = find_node(index)
        # node.refresh()
        print "PROJECT UPDATED"
        node = self.projectsnode.find_by_name(project.name)
        self.projectList.selectionModel().select(node.index(), QItemSelectionModel.ClearAndSelect)
        self.nodeselected(node.index(), None, reloadProject=True)
Ejemplo n.º 15
0
class PersistendIndexProve(QMainWindow):

    def __init__(self):
        super(PersistendIndexProve, self).__init__()
        self.uiw = loadUi("/u/isaito/data/Dropbox/ROS/groovy_quantal/catkin_ws/src/rqt_prove/resource/treeview.ui")

        self._std_model = QStandardItemModel()
        self._rootitem = self._std_model.invisibleRootItem()

        item_r_1 = QStandardItem("r1")
        item_r_2 = QStandardItem("r2")
        print 'index before {}'.format(item_r_1.index())

        qindex_persistent = QPersistentModelIndex(item_r_1.index())

        self._std_model.beginInsertRows(self._rootitem.index(), 0, 0)
        self._rootitem.appendRow(item_r_1)
        self._rootitem.appendRow(item_r_2)
        self._std_model.endInsertRows()
        print 'index after {}'.format(item_r_1.index())
        print 'index after 2 {}'.format(self._std_model.index(0, 0,
                                                              QModelIndex()))

        print '_rootitem index={} persistent list={}'.format(
                                         self._rootitem.index(),
                                         self._std_model.persistentIndexList())

        self.uiw._treeview.setModel(self._std_model)
        self.selectionModel = self.uiw._treeview.selectionModel()
        self.selectionModel.selectionChanged.connect(
                                                 self._selection_changed_slot)
        self.selectionModel.currentChanged.connect(
                                                 self._current_changed_slot)

        print('del/sel?\tde/sel index\tde/sel.row\tde/sel.dat\tparent\tinternal id')

        self.uiw.show()

    def _current_changed_slot(self, current, previous):
        print 'changed slot current={} prev={}'.format(
                                      current.data(Qt.DisplayRole).toString(),
                                      previous.data(Qt.DisplayRole).toString())

    def _selection_changed_slot(self, selected, deselected):
        """
        Receives args from signal QItemSelectionModel.selectionChanged.

        :type selected: QItemSelection
        :type deselected: QItemSelection
        """
        # self._test_sel_index(selected, deselected)
        self._sel_index_2(selected, deselected)

    def _sel_index_2(self, selected, deselected):
        # index_list = self.selectionModel.selectedIndexes()
        for index in self.selectionModel.selectedIndexes():
            print 'indices selected={} len selected={} deseled={}'.format(
                                               str(index.data(Qt.DisplayRole)),
                                               len(selected), len(deselected))

    def _test_sel_index(self, selected, deselected):
        src_model = self._std_model
        index_current = None
        index_deselected = None
        index_parent_sel = None
        index_parent_desel = None
        curr_qstd_item = None
        indexes = selected.indexes()
        del_or_sel = 'Sel'
        index_internalid = -1

        if len(indexes) > 0:
            index_internalid = selected.indexes()[0].internalId()

            # # Trying many approaches to get the right qindex
            # # Approach-1
            index_current = selected.indexes()[0]

            # # Approach-2

            # index_current_from_indexes = selected.indexes()[0]
            # index_current = src_model.index(index_current_from_indexes.row(),
                                            # 0, QModelIndex())
                                            # 0, index_current_from_indexes)
            # index_current = self.selectionModel.currentIndex()

            index_parent_sel = index_current.parent()
            curr_qstd_item = src_model.itemFromIndex(# index_parent)
                                                 index_current)
        elif len(deselected.indexes()) > 0:
            index_internalid = deselected.indexes()[0].internalId()

            del_or_sel = 'Desel'
            index_deselected = self.selectionModel.currentIndex()
            index_parent_desel = index_deselected.parent()
            curr_qstd_item = src_model.itemFromIndex(index_deselected)

        tabular_format = '{}\t{}\t{}\t{}\t{}\t{}'
        if len(indexes) > 0:
            print(tabular_format.format(
                              del_or_sel,
                              index_current,
                              index_current.row(),
                              index_current.data(Qt.DisplayRole).toString(),
                                  # curr_qstd_item,
                                  # curr_qstd_item.data(Qt.DisplayRole),
                              index_parent_sel,
                                  # index_parent_sel.data(Qt.DisplayRole),
                              index_internalid))
        elif len(deselected.indexes()) > 0:
            print(tabular_format.format(
                              del_or_sel,
                              index_deselected,
                              index_deselected.row(),
                              index_deselected.data(Qt.DisplayRole).toString(),
                              # curr_qstd_item,
                              #    curr_qstd_item.data(),
                                  index_parent_desel,
                              #  index_parent_desel.data(Qt.DisplayRole),
                                  index_internalid))
            self.selectionModel.select(index_deselected,
                                       QItemSelectionModel.Deselect)
Ejemplo n.º 16
0
class OWConfusionMatrix(widget.OWWidget):
    """Confusion matrix widget"""

    name = "Confusion Matrix"
    description = "Display a confusion matrix constructed from " \
                  "the results of classifier evaluations."
    icon = "icons/ConfusionMatrix.svg"
    priority = 1001

    inputs = [("Evaluation Results", Orange.evaluation.Results, "set_results")]
    outputs = [("Selected Data", Orange.data.Table)]

    quantities = [
        "Number of instances", "Proportion of predicted",
        "Proportion of actual"
    ]

    settingsHandler = settings.ClassValuesContextHandler()

    selected_learner = settings.Setting([0], schema_only=True)
    selection = settings.ContextSetting(set())
    selected_quantity = settings.Setting(0)
    append_predictions = settings.Setting(True)
    append_probabilities = settings.Setting(False)
    autocommit = settings.Setting(True)

    UserAdviceMessages = [
        widget.Message(
            "Clicking on cells or in headers outputs the corresponding "
            "data instances", "click_cell")
    ]

    def __init__(self):
        super().__init__()

        self.data = None
        self.results = None
        self.learners = []
        self.headers = []

        box = gui.vBox(self.controlArea, "Learners")

        self.learners_box = gui.listBox(box,
                                        self,
                                        "selected_learner",
                                        "learners",
                                        callback=self._learner_changed)
        box = gui.vBox(self.controlArea, "Show")

        gui.comboBox(box,
                     self,
                     "selected_quantity",
                     items=self.quantities,
                     callback=self._update)

        box = gui.vBox(self.controlArea, "Select")

        gui.button(box,
                   self,
                   "Select Correct",
                   callback=self.select_correct,
                   autoDefault=False)
        gui.button(box,
                   self,
                   "Select Misclassified",
                   callback=self.select_wrong,
                   autoDefault=False)
        gui.button(box,
                   self,
                   "Clear Selection",
                   callback=self.select_none,
                   autoDefault=False)

        self.outputbox = box = gui.vBox(self.controlArea, "Output")
        gui.checkBox(box,
                     self,
                     "append_predictions",
                     "Predictions",
                     callback=self._invalidate)
        gui.checkBox(box,
                     self,
                     "append_probabilities",
                     "Probabilities",
                     callback=self._invalidate)

        gui.auto_commit(self.controlArea, self, "autocommit", "Send Selected",
                        "Send Automatically")

        grid = QGridLayout()

        self.tablemodel = QStandardItemModel(self)
        view = self.tableview = QTableView(
            editTriggers=QTableView.NoEditTriggers)
        view.setModel(self.tablemodel)
        view.horizontalHeader().hide()
        view.verticalHeader().hide()
        view.horizontalHeader().setMinimumSectionSize(60)
        view.selectionModel().selectionChanged.connect(self._invalidate)
        view.setShowGrid(False)
        view.setItemDelegate(BorderedItemDelegate(Qt.white))
        view.clicked.connect(self.cell_clicked)
        grid.addWidget(view, 0, 0)
        self.mainArea.layout().addLayout(grid)

    def sizeHint(self):
        """Initial size"""
        return QSize(750, 490)

    def _item(self, i, j):
        return self.tablemodel.item(i, j) or QStandardItem()

    def _set_item(self, i, j, item):
        self.tablemodel.setItem(i, j, item)

    def _init_table(self, nclasses):
        item = self._item(0, 2)
        item.setData("Predicted", Qt.DisplayRole)
        item.setTextAlignment(Qt.AlignCenter)
        item.setFlags(Qt.NoItemFlags)

        self._set_item(0, 2, item)
        item = self._item(2, 0)
        item.setData("Actual", Qt.DisplayRole)
        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignBottom)
        item.setFlags(Qt.NoItemFlags)
        self.tableview.setItemDelegateForColumn(0, gui.VerticalItemDelegate())
        self._set_item(2, 0, item)
        self.tableview.setSpan(0, 2, 1, nclasses)
        self.tableview.setSpan(2, 0, nclasses, 1)

        font = self.tablemodel.invisibleRootItem().font()
        bold_font = QFont(font)
        bold_font.setBold(True)

        for i in (0, 1):
            for j in (0, 1):
                item = self._item(i, j)
                item.setFlags(Qt.NoItemFlags)
                self._set_item(i, j, item)

        for p, label in enumerate(self.headers):
            for i, j in ((1, p + 2), (p + 2, 1)):
                item = self._item(i, j)
                item.setData(label, Qt.DisplayRole)
                item.setFont(bold_font)
                item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                item.setFlags(Qt.ItemIsEnabled)
                if p < len(self.headers) - 1:
                    item.setData("br"[j == 1], BorderRole)
                    item.setData(QColor(192, 192, 192), BorderColorRole)
                self._set_item(i, j, item)

        hor_header = self.tableview.horizontalHeader()
        if len(' '.join(self.headers)) < 120:
            hor_header.setResizeMode(QHeaderView.ResizeToContents)
        else:
            hor_header.setDefaultSectionSize(60)
        self.tablemodel.setRowCount(nclasses + 3)
        self.tablemodel.setColumnCount(nclasses + 3)

    def set_results(self, results):
        """Set the input results."""

        prev_sel_learner = self.selected_learner.copy()
        self.clear()
        self.warning()
        self.closeContext()

        data = None
        if results is not None and results.data is not None:
            data = results.data

        if data is not None and not data.domain.has_discrete_class:
            self.warning("Confusion Matrix cannot show regression results.")

        self.results = results
        self.data = data

        if data is not None:
            class_values = data.domain.class_var.values
        elif results is not None:
            raise NotImplementedError

        if results is None:
            self.report_button.setDisabled(True)
        else:
            self.report_button.setDisabled(False)

            nmodels = results.predicted.shape[0]
            self.headers = class_values + \
                           [unicodedata.lookup("N-ARY SUMMATION")]

            # NOTE: The 'learner_names' is set in 'Test Learners' widget.
            if hasattr(results, "learner_names"):
                self.learners = results.learner_names
            else:
                self.learners = [
                    "Learner #{}".format(i + 1) for i in range(nmodels)
                ]

            self._init_table(len(class_values))
            self.openContext(data.domain.class_var)
            if not prev_sel_learner or prev_sel_learner[0] >= len(
                    self.learners):
                self.selected_learner[:] = [0]
            else:
                self.selected_learner[:] = prev_sel_learner
            self._update()
            self._set_selection()
            self.unconditional_commit()

    def clear(self):
        """Reset the widget, clear controls"""
        self.results = None
        self.data = None
        self.tablemodel.clear()
        self.headers = []
        # Clear learners last. This action will invoke `_learner_changed`
        self.learners = []

    def select_correct(self):
        """Select the diagonal elements of the matrix"""
        selection = QItemSelection()
        n = self.tablemodel.rowCount()
        for i in range(2, n):
            index = self.tablemodel.index(i, i)
            selection.select(index, index)
        self.tableview.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect)

    def select_wrong(self):
        """Select the off-diagonal elements of the matrix"""
        selection = QItemSelection()
        n = self.tablemodel.rowCount()
        for i in range(2, n):
            for j in range(i + 1, n):
                index = self.tablemodel.index(i, j)
                selection.select(index, index)
                index = self.tablemodel.index(j, i)
                selection.select(index, index)
        self.tableview.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect)

    def select_none(self):
        """Reset selection"""
        self.tableview.selectionModel().clear()

    def cell_clicked(self, model_index):
        """Handle cell click event"""
        i, j = model_index.row(), model_index.column()
        if not i or not j:
            return
        n = self.tablemodel.rowCount()
        index = self.tablemodel.index
        selection = None
        if i == j == 1 or i == j == n - 1:
            selection = QItemSelection(index(2, 2), index(n - 1, n - 1))
        elif i in (1, n - 1):
            selection = QItemSelection(index(2, j), index(n - 1, j))
        elif j in (1, n - 1):
            selection = QItemSelection(index(i, 2), index(i, n - 1))

        if selection is not None:
            self.tableview.selectionModel().select(
                selection, QItemSelectionModel.ClearAndSelect)

    def commit(self):
        """Output data instances corresponding to selected cells"""
        if self.results is not None and self.data is not None \
                and self.selected_learner:
            indices = self.tableview.selectedIndexes()
            indices = {(ind.row() - 2, ind.column() - 2) for ind in indices}
            actual = self.results.actual
            learner_name = self.learners[self.selected_learner[0]]
            predicted = self.results.predicted[self.selected_learner[0]]
            selected = [
                i for i, t in enumerate(zip(actual, predicted)) if t in indices
            ]
            row_indices = self.results.row_indices[selected]

            extra = []
            class_var = self.data.domain.class_var
            metas = self.data.domain.metas

            if self.append_predictions:
                predicted = numpy.array(predicted[selected], dtype=object)
                extra.append(predicted.reshape(-1, 1))
                var = Orange.data.DiscreteVariable(
                    "{}({})".format(class_var.name, learner_name),
                    class_var.values)
                metas = metas + (var, )

            if self.append_probabilities and \
                    self.results.probabilities is not None:
                probs = self.results.probabilities[self.selected_learner[0],
                                                   selected]
                extra.append(numpy.array(probs, dtype=object))
                pvars = [
                    Orange.data.ContinuousVariable("p({})".format(value))
                    for value in class_var.values
                ]
                metas = metas + tuple(pvars)

            X = self.data.X[row_indices]
            Y = self.data.Y[row_indices]
            M = self.data.metas[row_indices]
            row_ids = self.data.ids[row_indices]

            M = numpy.hstack((M, ) + tuple(extra))
            domain = Orange.data.Domain(self.data.domain.attributes,
                                        self.data.domain.class_vars, metas)
            data = Orange.data.Table.from_numpy(domain, X, Y, M)
            data.ids = row_ids
            data.name = learner_name

        else:
            data = None

        self.send("Selected Data", data)

    def _invalidate(self):
        indices = self.tableview.selectedIndexes()
        self.selection = {(ind.row() - 2, ind.column() - 2) for ind in indices}
        self.commit()

    def _set_selection(self):
        selection = QItemSelection()
        index = self.tableview.model().index
        for row, col in self.selection:
            sel = index(row + 2, col + 2)
            selection.select(sel, sel)
        self.tableview.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect)

    def _learner_changed(self):
        self._update()
        self._set_selection()
        self.commit()

    def _update(self):
        def _isinvalid(x):
            return isnan(x) or isinf(x)

        # Update the displayed confusion matrix
        if self.results is not None and self.selected_learner:
            cmatrix = confusion_matrix(self.results, self.selected_learner[0])
            colsum = cmatrix.sum(axis=0)
            rowsum = cmatrix.sum(axis=1)
            n = len(cmatrix)
            diag = numpy.diag_indices(n)

            colors = cmatrix.astype(numpy.double)
            colors[diag] = 0
            if self.selected_quantity == 0:
                normalized = cmatrix.astype(numpy.int)
                formatstr = "{}"
                div = numpy.array([colors.max()])
            else:
                if self.selected_quantity == 1:
                    normalized = 100 * cmatrix / colsum
                    div = colors.max(axis=0)
                else:
                    normalized = 100 * cmatrix / rowsum[:, numpy.newaxis]
                    div = colors.max(axis=1)[:, numpy.newaxis]
                formatstr = "{:2.1f} %"
            div[div == 0] = 1
            colors /= div
            colors[diag] = normalized[diag] / normalized[diag].max()

            for i in range(n):
                for j in range(n):
                    val = normalized[i, j]
                    col_val = colors[i, j]
                    item = self._item(i + 2, j + 2)
                    item.setData(
                        "NA" if _isinvalid(val) else formatstr.format(val),
                        Qt.DisplayRole)
                    bkcolor = QColor.fromHsl(
                        [0, 240][i == j], 160,
                        255 if _isinvalid(col_val) else int(255 -
                                                            30 * col_val))
                    item.setData(QBrush(bkcolor), Qt.BackgroundRole)
                    item.setData("trbl", BorderRole)
                    item.setToolTip("actual: {}\npredicted: {}".format(
                        self.headers[i], self.headers[j]))
                    item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                    item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
                    self._set_item(i + 2, j + 2, item)

            bold_font = self.tablemodel.invisibleRootItem().font()
            bold_font.setBold(True)

            def _sum_item(value, border=""):
                item = QStandardItem()
                item.setData(value, Qt.DisplayRole)
                item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                item.setFlags(Qt.ItemIsEnabled)
                item.setFont(bold_font)
                item.setData(border, BorderRole)
                item.setData(QColor(192, 192, 192), BorderColorRole)
                return item

            for i in range(n):
                self._set_item(n + 2, i + 2, _sum_item(int(colsum[i]), "t"))
                self._set_item(i + 2, n + 2, _sum_item(int(rowsum[i]), "l"))
            self._set_item(n + 2, n + 2, _sum_item(int(rowsum.sum())))

    def send_report(self):
        """Send report"""
        if self.results is not None and self.selected_learner:
            self.report_table(
                "Confusion matrix for {} (showing {})".format(
                    self.learners[self.selected_learner[0]],
                    self.quantities[self.selected_quantity].lower()),
                self.tableview)
Ejemplo n.º 17
0
if __name__ == "__main__":
    app = QApplication(sys.argv)

    view = QTreeView()

    # 1.  模型
    '''
    PyQt使用Model时,如果Model创建时未设置parent,则运行完退出时会报错:
    QObject::startTimer: QTimer can only be used with threads started with QThread

    '''
    # model = QStandardItemModel()         # 创建标准项模型
    model = QStandardItemModel(view)  # 创建标准项模型
    # 获取模型的根项(Root Item),根项是不可见的
    parentItem = model.invisibleRootItem()

    # 创建标准项item0,并设置显示文本,图标和工具提示
    item0 = QStandardItem()
    item0.setText("A")
    pixmap0 = QPixmap(50, 50)
    pixmap0.fill(QColor("red"))
    # pixmap0.fill(Qt.red)
    item0.setIcon(QIcon(pixmap0))
    item0.setToolTip("indexA")

    parentItem.appendRow(item0)  # 将item0  作为根项的子项

    # 将创建的标准项作为新的父项
    parentItem = item0
    # 创建新的标准项,它将作为item0的子项
Ejemplo n.º 18
0
class SubPowerWidget(QWidget):
	"""
	@brief Zeigt alle Unterkräfte in einer Baumstruktur an.
	"""


	def __init__(self, template, character, parent=None):
		super(SubPowerWidget, self).__init__(parent)

		self.__storage = template
		self.__character = character

		self.__model = QStandardItemModel()
		# Das ungenutzte Model dient dazu, alle Unterkräfte aufzunehmen, die ich nicht darstellen möchte. Ist einfacher, als diese im View zu verstecken.
		self.__modelUnused = QStandardItemModel()

		self._layout = QVBoxLayout()
		self.setLayout( self._layout )

		self.__view = QTreeView()
		self.__view.setHeaderHidden(True)
		self.__view.setModel( self.__model)

		self._layout.addWidget(self.__view)

		self._typ = "Subpower"
		categories = self.__storage.categories(self._typ)

		self.__items = {}

		self.__rootItem = QStandardItem()
		self.__rootItem = self.__model.invisibleRootItem()

		self.__rootItemUnused = QStandardItem()
		self.__rootItemUnused = self.__modelUnused.invisibleRootItem()

		for item in categories:
			categoryItem = QStandardItem(item)
			self.__rootItem.appendRow(categoryItem)

			## Ich benötige diese Items auch im ungenutzten Model.
			categoryItemUnused = QStandardItem(item)
			self.__rootItemUnused.appendRow(categoryItemUnused)
			
			traitList = list( self.__character.traits[self._typ][item].items() )
			traitList.sort()
			for trait in traitList:
				traitItem = QStandardItem(trait[1].name)
				traitItem.setCheckable(True)
				## Unhashable Type
				self.__items[trait[1]] = traitItem
				categoryItem.appendRow(traitItem)

				## Funktioniert mit PySide nicht:
				#trait[1].availableChanged.connect(traitItem.setEnabled)
				## Funktioniert auch mit PySide:
				trait[1].availableChanged.connect(
					lambda enable, item=traitItem: item.setEnabled(enable)
				)
				trait[1].valueChanged.connect(
					lambda val, trait=trait[1], item=traitItem: self.__setItemValue(trait, item)
				)

		self.__model.itemChanged.connect(self.__getItemValue)
		self.__character.speciesChanged.connect(self.hideOrShowToolPage)
		self.__character.breedChanged.connect(self.hideOrShowToolPage)
		self.__character.factionChanged.connect(self.hideOrShowToolPage)


	def __setItemValue(self, trait, item):
		"""
		Setzt den Wert der Angezeigten Items.
		"""

		if trait.value == 0:
			item.setCheckState(Qt.Unchecked)
		elif trait.value == 1:
			item.setCheckState(Qt.PartiallyChecked)
		else:
			item.setCheckState(Qt.Checked)


	def __getItemValue(self, item):
		"""
		Setzt den Wert der Eigenschaft im Speicher.
		"""

		for trait in self.__items.items():
			if id(trait[1]) == id(item):
				trait[0].value = item.checkState()
				break


	def hideOrShowToolPage(self, res):
		"""
		Alle Eigenschaften, die nicht zur Verfügung stehen, werden verborgen, indem sie in ein anderes Model verschoben werden.

		\bug Möglicher Fehler in PySide: Der Aufruf von QStandardItem.model() führt beim Beenden des Programms zu einem Segmentation Fault.
		"""

		# Versteckt alle Unterkräfte, die zu gewähltem Charakter nicht passen.
		for item in self.__items.items():
			if (
				(
					item[0].species and
					item[0].species != self.__character.species
				) or (
					item[0].only and
					self.__character.breed not in item[0].only and
					self.__character.faction not in item[0].only
				)
			):
				#self.__view.setRowHidden(item[1].index().row(), item[1].parent().index(), True)
				#Debug.debug(item[1].model())
				## Hier wird beispielsweise besagter Aufruf getätigt, der zu einem segfault führt.
				if item[1].model() == self.__model:
					parent = item[1].parent()
					itemUnused = parent.takeRow(item[1].index().row())
					parentUnused = self.__modelUnused.findItems(parent.text())[0]
					parentUnused.appendRow(itemUnused)
			else:
				#self.__view.setRowHidden(item[1].index().row(), item[1].parent().index(), False)
				if item[1].model() == self.__modelUnused:
					parent = item[1].parent()
					itemUsed = parent.takeRow(item[1].index().row())
					parentUsed = self.__model.findItems(parent.text())[0]
					parentUsed.appendRow(itemUsed)

		## Versteckt alle Elternzeilen, wenn sie keine Kinder enthalten.
		for i in range(self.__model.rowCount()):
			categoryItem = self.__model.item(i)
			if categoryItem.hasChildren():
				self.__view.setRowHidden(categoryItem.index().row(), self.__rootItem.index(), False)
			else:
				self.__view.setRowHidden(categoryItem.index().row(), self.__rootItem.index(), True)
Ejemplo n.º 19
0
class ConfigManagerDialog(ui_configmanager.Ui_ProjectInstallerDialog, QDialog):
    def __init__(self, roamapp, parent=None):
        super(ConfigManagerDialog, self).__init__(parent)
        self.setupUi(self)
        self.bar = roam.messagebaritems.MessageBar(self)

        self.roamapp = roamapp

        # Nope!
        self.projectwidget.roamapp = roamapp
        self.projectwidget.bar = self.bar

        self.treemodel = QStandardItemModel()
        self.projectList.setModel(self.treemodel)
        self.projectList.setHeaderHidden(True)

        self.projectList.selectionModel().currentChanged.connect(self.nodeselected)

        self.projectwidget.adjustSize()
        self.setWindowFlags(Qt.Window)

        self.projectwidget.projectupdated.connect(self.projectupdated)

        self.projectwidget.setaboutinfo()
        self.projectwidget.projects_page.projectlocationchanged.connect(self.loadprojects)
        self.setuprootitems()

    def raiseerror(self, *exinfo):
        self.bar.pushError(*exinfo)
        import roam.errors
        roam.errors.send_exception(exinfo)

    def setuprootitems(self):
        rootitem = self.treemodel.invisibleRootItem()
        self.roamnode = RoamNode()
        rootitem.appendRow(self.roamnode)

        self.projectsnode = ProjectsNode(folder=None)
        rootitem.appendRow(self.projectsnode)

        self.pluginsnode = PluginsNode()
        pluginpath = os.path.join(self.roamapp.apppath, "plugins")
        rootitem.appendRow(self.pluginsnode)
        self.pluginsnode.add_plugin_paths([pluginpath])



    def delete_project(self):
        index = self.projectList.currentIndex()
        node = index.data(Qt.UserRole)
        if node.type() == Treenode.ProjectNode:
            self.projectwidget._closeqgisproject()

        title, removemessage = node.removemessage
        delete = node.canremove
        if node.canremove and removemessage:
            button = QMessageBox.warning(self, title, removemessage, QMessageBox.Yes | QMessageBox.No)
            delete = button == QMessageBox.Yes

        if delete:
            parentindex = index.parent()
            newindex = self.treemodel.index(index.row(), 0, parentindex)
            if parentindex.isValid():
                parent = parentindex.data(Qt.UserRole)
                parent.delete(index.row())

            self.projectList.setCurrentIndex(newindex)

    def addprojectfolders(self, folders):
        self.projectwidget.projects_page.setprojectfolders(folders)

    def loadprojects(self, projectpath):
        projects = roam.project.getProjects([projectpath])
        self.projectsnode.loadprojects(projects, projectsbase=projectpath)

        index = self.treemodel.indexFromItem(self.projectsnode)
        self.projectList.setCurrentIndex(index)
        self.projectList.expand(index)

    def nodeselected(self, index, _):
        node = index.data(Qt.UserRole)
        if node is None:
            return

        project = node.project
        if project and not self.projectwidget.project == project:
            # Only load the project if it's different the current one.
            self.projectwidget.setproject(project)
            node.create_children()

            validateresults = list(project.validate())
            if validateresults:
                text = "Here are some reasons we found: \n\n"
                for message in validateresults:
                    text += "- {} \n".format(message)

                self.projectwidget.reasons_label.setText(text)

        if node.nodetype == Treenode.RoamNode:
            self.projectwidget.projectlabel.setText("IntraMaps Roam Config Manager")

        if node.nodetype == Treenode.AddNew:
            try:
                item = node.additem()
            except ValueError:
                return
            newindex = self.treemodel.indexFromItem(item)
            self.projectList.setCurrentIndex(newindex)
            return

        self.projectwidget.projectbuttonframe.setVisible(not project is None)
        self.projectwidget.setpage(node.page, node)

    def projectupdated(self):
        index = self.projectList.currentIndex()
        node = find_node(index)
        node.refresh()
Ejemplo n.º 20
0
class AddLayerDialog(QDialog):
  def __init__(self, plugin):
    QDialog.__init__(self, plugin.iface.mainWindow())
    self.plugin = plugin

    # set up the user interface
    self.ui = Ui_Dialog()
    self.ui.setupUi(self)
    self.ui.pushButton_Add.clicked.connect(self.accept)
    self.ui.pushButton_Close.clicked.connect(self.reject)
    self.ui.pushButton_Settings.clicked.connect(self.settingsClicked)
    self.ui.treeView.doubleClicked.connect(self.treeItemDoubleClicked)
    self.setupTreeView()

  def setupTreeView(self):

    # tree view header labels
    headers = [self.tr("Title"), self.tr("Attribution"), self.tr("Url"), self.tr("Zoom"), self.tr("Extent"), self.tr("yOrigin")] + ["index"]
    self.indexColumn = len(headers) - 1

    self.model = QStandardItemModel(0, len(headers))
    self.model.setHorizontalHeaderLabels(headers)

    self.serviceInfoList = []
    # import layer definitions from external layer definition directory, and append it into the tree
    extDir = QSettings().value("/TileLayerPlugin/extDir", "", type=unicode)
    if extDir:
      self.importFromDirectory(extDir)

    # import layer definitions from TileLayerPlugin/layers directory, and append it into the tree
    pluginDir = os.path.dirname(QFile.decodeName(__file__))
    self.importFromDirectory(os.path.join(pluginDir, "layers"))

    # model and style settings
    self.ui.treeView.setModel(self.model)
    self.ui.treeView.header().setResizeMode(QHeaderView.ResizeToContents)
    self.ui.treeView.expandAll()

  def importFromDirectory(self, path):
    d = QDir(path)
    d.setFilter(QDir.Files | QDir.Hidden)
    #d.setSorting(QDir.Size | QDir.Reversed)

    for fileInfo in d.entryInfoList():
      if debug_mode == 0 and fileInfo.fileName() == "debug.tsv":
        continue
      if fileInfo.suffix().lower() == "tsv":
        self.importFromTsv(fileInfo.filePath())

  # Line Format is:
  # title attribution url [yOriginTop [zmin zmax [xmin ymin xmax ymax ]]]
  def importFromTsv(self, filename):
    # append file item
    rootItem = self.model.invisibleRootItem()
    basename = os.path.basename(filename)
    parent = QStandardItem(os.path.splitext(basename)[0])
    rootItem.appendRow([parent])

    # load service info from tsv file
    try:
      with codecs.open(filename, "r", "utf-8") as f:
        lines = f.readlines()
    except Exception as e:
      QgsMessageLog.logMessage(self.tr("Fail to read {0}: {1}").format(basename, unicode(e)), self.tr("TileLayerPlugin"))
      return False

    for i, line in enumerate(lines):
      if line.startswith("#"):
        continue
      vals = line.rstrip().split("\t")
      nvals = len(vals)
      try:
        if nvals < 3:
          raise
        title, attribution, url = vals[0:3]
        if not url:
          raise
        if nvals < 4:
          serviceInfo = TileLayerDefinition(title, attribution, url)
        else:
          yOriginTop = int(vals[3])
          if nvals < 6:
            serviceInfo = TileLayerDefinition(title, attribution, url, yOriginTop)
          else:
            zmin, zmax = map(int, vals[4:6])
            if nvals < 10:
              serviceInfo = TileLayerDefinition(title, attribution, url, yOriginTop, zmin, zmax)
            else:
              bbox = BoundingBox.fromString(",".join(vals[6:10]))
              serviceInfo = TileLayerDefinition(title, attribution, url, yOriginTop, zmin, zmax, bbox)
      except:
        QgsMessageLog.logMessage(self.tr("Invalid line format: {} line {}").format(basename, i + 1), self.tr("TileLayerPlugin"))
        continue

      # append the service info into the tree
      vals = serviceInfo.toArrayForTreeView() + [len(self.serviceInfoList)]
      rowItems = map(QStandardItem, map(unicode, vals))
      parent.appendRow(rowItems)
      self.serviceInfoList.append(serviceInfo)
    return True

  def selectedLayerDefinitions(self):
    list = []
    for idx in self.ui.treeView.selectionModel().selection().indexes():
      if idx.column() == self.indexColumn and idx.data() is not None:
        list.append(self.serviceInfoList[int(idx.data())])
    return list

  def settingsClicked(self):
    if self.plugin.settings():
      self.setupTreeView()

  def treeItemDoubleClicked(self, index):
    if len(self.selectedLayerDefinitions()) > 0:
      self.accept()
Ejemplo n.º 21
0
class NodeLibrary ( QtCore.QObject ) : # QtCore.QObject
  #
  # __init__
  #
  def __init__ ( self, dirName ) :
    #
    self.dirName = dirName
    self.libdir = QDir ( dirName );
    self.model = 	QStandardItemModel ()
    self.parentItem = self.model.invisibleRootItem ()
    
    print '>> NodeLibrary: libdir = %s' % dirName 
    
    self.liblevel = ''
    self.scanLibDir ()
  #    
  # scanLibDir
  #
  def scanLibDir ( self ) :
    # process directories
    sortFlags = QDir.Name
    filterFlags = ( QDir.AllDirs | QDir.NoDotAndDotDot )
    fileList = self.libdir.entryInfoList ( filterFlags, sortFlags ) 
    
    for f in fileList :
      item = QStandardItem ( f.fileName () )
      item.setEditable ( False )
      item.setDragEnabled ( False )
      
      # set bold font for folders
      font = item.font()
      font.setBold ( True )
      item.setFont ( font )
      
      item.setWhatsThis ( 'folder' )
      
      currparent = self.parentItem
      self.parentItem.appendRow ( item )
      self.parentItem = item
      
      currlevel = self.liblevel # store current level
      self.liblevel = self.liblevel + f.fileName () + '/' 
      self.libdir.cd ( f.fileName () )
      
      self.scanLibDir () # recurcive call itself
      
      self.liblevel = currlevel # restore current level
      self.libdir.cdUp ()
      
      self.parentItem = currparent
        
    # process XML files
    filterFlags = QDir.Files    
    fileList = self.libdir.entryInfoList ( [ '*.xml' ], filterFlags, sortFlags ) 
    for f in fileList :
      self.scanXmlNodes ( f.fileName () )
  #
  # scanXmlNodes
  #
  def scanXmlNodes ( self, filename ) :      
    #
    dom = QtXml.QDomDocument ( '' )
    nodeFilename = self.dirName + '/' + self.liblevel + filename
    
    file = QFile ( self.libdir.filePath ( filename )  )
    
    if file.open ( QtCore.QIODevice.ReadOnly ) :
      if dom.setContent ( file ) :
        node = dom.documentElement () 
        if node.nodeName () == 'nodenet' or node.nodeName () == 'node' :
          nodeName   = node.attributes ().namedItem ( 'name' ).nodeValue ()
          nodeType   = node.attributes ().namedItem ( 'type' ).nodeValue ()
          nodeAuthor = node.attributes ().namedItem ( 'author' ).nodeValue ()
          nodeIcon   = node.attributes ().namedItem ( 'icon' ).nodeValue ()
          nodeHelp   = ''
          help_tag   = node.namedItem ('help')
          
          if not help_tag.isNull() : nodeHelp = help_tag.toElement ().text ()
          
          item = QStandardItem ( nodeName )
          item.setEditable ( False )
          
          item.setData ( QVariant ( nodeAuthor ),   QtCore.Qt.UserRole + 1 )
          item.setData ( QVariant ( nodeType ),     QtCore.Qt.UserRole + 2 )
          item.setData ( QVariant ( nodeHelp ),     QtCore.Qt.UserRole + 3 )
          item.setData ( QVariant ( nodeFilename ), QtCore.Qt.UserRole + 4 )
          item.setData ( QVariant ( nodeIcon ),     QtCore.Qt.UserRole + 5 )
          
          if node.nodeName () == 'nodenet' :
            # set Blue color for nodenet items
            brush = QtGui.QBrush ()
            brush.setColor ( QtCore.Qt.blue )
            item.setForeground ( brush )
            item.setWhatsThis ( 'nodenet' )
          else:
            item.setWhatsThis ( 'node' )
          
          self.parentItem.appendRow ( item )
    file.close ()
class PatternEditorWindow(QtGui.QMainWindow):
    
    # My custom signals
    changedPattern = QtCore.pyqtSignal(str)

    def __init__(self, databaseFile, lastMathML, parent=None):
        QtGui.QWidget.__init__(self, parent)
        
        self.ui = Ui_PatternEditorWindow()
        self.ui.setupUi(self)
        
        # Make the fonts bigger
        font = QFont()
        font.setPointSize(12)
        font.setFamily('Consolas')
        font.setFixedPitch(True)
        self.ui.databaseEditor.setFont(font)
        self.ui.mathmlEditor.setFont(font)
        
        self.currentFile = databaseFile.strip()
        
        # If I actually got something, then let's load the file in
        if len(self.currentFile) > 0:
            try:
                f = open(self.currentFile, 'r')
                contents = f.read()
                f.close()
                self.ui.databaseEditor.setText(contents)
            except IOError:
                print 'Database file doesn\'t exist! Resetting to nothing...'
                self.currentFile = ''
        
        try:
            self.mathTTS = MathTTS(databaseFile)
        except Exception:
            self.mathTTS = None
        
        self.stagesModel = QStandardItemModel()
        self.stageTrees = []
        self.updateStagesModel()
        
        self.ui.mathmlEditor.setText(unicode(lastMathML))
        
        self.connect_signals()
        
    def connect_signals(self):
        self.ui.speakButton.clicked.connect(self.speakButton_clicked)
        self.ui.expandAllButton.clicked.connect(self.expandButton_clicked)
        self.ui.collapseAllButton.clicked.connect(self.collapseButton_clicked)
        
        self.ui.actionNew.triggered.connect(self.actionNew_triggered)
        self.ui.actionOpen.triggered.connect(self.actionOpen_triggered)
        self.ui.actionOpen_MathML.triggered.connect(self.actionOpen_MathML_triggered)
        self.ui.actionSave.triggered.connect(self.actionSave_triggered)
        self.ui.actionSave_As.triggered.connect(self.actionSaveAs_triggered)
        self.ui.actionQuit.triggered.connect(self.actionQuit_triggered)
        
    def speakButton_clicked(self):
        print 'Speak button pressed!'
        self.stageTrees = []
        stuff = self.mathTTS.parse(unicode(self.ui.mathmlEditor.text()), stageSink=self.stageTrees)
        
        # Output what the text was
        self.ui.outputText.setPlainText(stuff)
        
        # Turn my stages into a tree model with extra happy!
        self.updateStagesModel()
        
    def expandButton_clicked(self):
        self.ui.stagesTreeView.expandAll()
    
    def collapseButton_clicked(self):
        self.ui.stagesTreeView.collapseAll()
        
    def updateStagesModel(self):
        '''
        Used to update the tree model for the Stages tree
        '''
        self.stagesModel.clear()
        parent = self.stagesModel.invisibleRootItem();
        
        i = 0
        for stage in self.stageTrees:
            i += 1
            stageItem = QStandardItem(stage.replaceVariable)
            stageItem.setEditable(False)
            
            item = QStandardItem(self._buildTreeStringLabel(stage))
            item.setEditable(False)
            self._addChildrenToParent(stage, item)
            
            stageItem.appendRow(item)
            parent.appendRow(stageItem)
            
        self.ui.stagesTreeView.setModel(self.stagesModel)
        
    def _addChildrenToParent(self, replaceParentNode, standardItemParent):
        if len(replaceParentNode.expressions) > 0:
            for e in replaceParentNode.expressions:
                if isinstance(e, list):
                    listItem = QStandardItem('+')
                    listItem.setEditable(False)
                    for e2 in e:
                        item = QStandardItem(self._buildTreeStringLabel(e2))
                        item.setEditable(False)
                        self._addChildrenToParent(e2, item)
                        listItem.appendRow(item)
                    standardItemParent.appendRow(listItem)
                    
                else:
                    item = QStandardItem(self._buildTreeStringLabel(e))
                    item.setEditable(False)
                    self._addChildrenToParent(e, item)
                    standardItemParent.appendRow(item)
                
        if len(replaceParentNode.children) > 0:
            for c in replaceParentNode.children:
                item = QStandardItem(self._buildTreeStringLabel(c))
                item.setEditable(False)
                self._addChildrenToParent(c, item)
                standardItemParent.appendRow(item)
                
    def _buildTreeStringLabel(self, replaceTree):
        '''
        Builds the label for the stages tree based on the replace tree given
        '''
        myString = replaceTree.value + '   (' + replaceTree._getTypeString() + ')'
        if replaceTree.parent != None:
            myString += '    -> Parent: '
            myString += replaceTree.parent.value + ' (' + replaceTree.parent._getTypeString() + ')'
        return myString
        
    def actionNew_triggered(self):
        print 'New was triggered!'
        self.ui.databaseEditor.clear()
        self.currentFile = ''
        self.changedPattern.emit(self.currentFile)
        self.mathTTS.setPatternDatabase(self.currentFile)
        
    def actionOpen_triggered(self):
        print 'Open was triggered!'
        
        newFile = QtGui.QFileDialog.getOpenFileName(self, 'Open pattern database file...')
        
        if len(newFile) > 0:
            self.currentFile = newFile
            f = open(self.currentFile, 'r')
            contents = f.read()
            f.close()
            self.ui.databaseEditor.setText(contents)
            
            self.changedPattern.emit(self.currentFile)
            self.mathTTS.setPatternDatabase(self.currentFile)
            
    def actionOpen_MathML_triggered(self):
        print 'Open MathML was triggered!'
        
        newFile = QtGui.QFileDialog.getOpenFileName(self, 'Open MathML file...')
        
        if len(newFile) > 0:
            f = open(newFile, 'r')
            contents = f.read()
            f.close()
            self.ui.mathmlEditor.setText(contents)
        
    def actionSave_triggered(self):
        print 'Save was triggered!'
        
        if len(self.currentFile) == 0:
            # Perform a Save As instead
            self.actionSaveAs_triggered()
        else:
            f = open(self.currentFile, 'w')
            f.write(unicode(self.ui.databaseEditor.text()))
            f.close()
            
            self.changedPattern.emit(self.currentFile)
            
            if self.mathTTS == None:
                try:
                    self.mathTTS = MathTTS(self.currentFile)
                except Exception:
                    pass
            else:
                self.mathTTS.setPatternDatabase(self.currentFile)
        
    def actionSaveAs_triggered(self):
        print 'Save As was triggered!'
        newFileName = QtGui.QFileDialog.getSaveFileName(self, 'Save pattern database file...')
        if len(newFileName) > 0:
            self.currentFile = newFileName
            f = open(self.currentFile, 'w')
            f.write(unicode(self.ui.databaseEditor.text()))
            f.close()
            
            self.changedPattern.emit(self.currentFile)
            self.mathTTS.setPatternDatabase(self.currentFile)
        
    def actionQuit_triggered(self):
        print 'Quit was triggered!'
Ejemplo n.º 23
0
class ProgramInfoFiles(QWidget, Ui_ProgramInfoFiles):
    def __init__(self, context, update_main_ui_state, set_widget_enabled, is_alive, show_upload_files_wizard, show_download_wizard):
        QWidget.__init__(self)

        self.setupUi(self)

        self.session                 = context.session
        self.script_manager          = context.script_manager
        self.program                 = context.program
        self.update_main_ui_state    = update_main_ui_state
        self.set_widget_enabled      = set_widget_enabled
        self.is_alive                = is_alive
        self.show_download_wizard    = show_download_wizard
        self.bin_directory           = posixpath.join(self.program.root_directory, 'bin')
        self.refresh_in_progress     = False
        self.any_refresh_in_progress = False # set from ProgramInfoMain.update_ui_state
        self.available_files         = []
        self.available_directories   = []
        self.folder_icon             = QIcon(load_pixmap('folder-icon.png'))
        self.file_icon               = QIcon(load_pixmap('file-icon.png'))
        self.tree_files_model        = QStandardItemModel(self)
        self.tree_files_model_header = ['Name', 'Size', 'Last Modified']
        self.tree_files_proxy_model  = FilesProxyModel(self)
        self.last_download_directory = get_home_path()

        self.tree_files_model.setHorizontalHeaderLabels(self.tree_files_model_header)
        self.tree_files_proxy_model.setSourceModel(self.tree_files_model)
        self.tree_files.setModel(self.tree_files_model)
        self.tree_files.setModel(self.tree_files_proxy_model)
        self.tree_files.setColumnWidth(0, 210)
        self.tree_files.setColumnWidth(1, 85)

        self.tree_files.selectionModel().selectionChanged.connect(self.update_ui_state)
        self.tree_files.activated.connect(self.rename_activated_file)
        self.button_upload_files.clicked.connect(show_upload_files_wizard)
        self.button_download_files.clicked.connect(self.download_selected_files)
        self.button_rename_file.clicked.connect(self.rename_selected_file)
        self.button_change_file_permissions.clicked.connect(self.change_permissions_of_selected_file)
        self.button_delete_files.clicked.connect(self.delete_selected_files)

        self.label_error.setVisible(False)

    def update_ui_state(self):
        selection_count = len(self.tree_files.selectionModel().selectedRows())

        self.set_widget_enabled(self.button_upload_files, not self.any_refresh_in_progress)
        self.set_widget_enabled(self.button_download_files, not self.any_refresh_in_progress and selection_count > 0)
        self.set_widget_enabled(self.button_rename_file, not self.any_refresh_in_progress and selection_count == 1)
        self.set_widget_enabled(self.button_change_file_permissions, not self.any_refresh_in_progress and selection_count == 1)
        self.set_widget_enabled(self.button_delete_files, not self.any_refresh_in_progress and selection_count > 0)

    def close_all_dialogs(self):
        pass

    def refresh_files_done(self):
        self.refresh_in_progress = False
        self.update_main_ui_state()

    def refresh_files(self):
        def cb_walk(result):
            okay, message = check_script_result(result, decode_stderr=True)

            if not okay:
                self.label_error.setText('<b>Error:</b> ' + Qt.escape(message))
                self.label_error.setVisible(True)
                self.refresh_files_done()
                return

            self.label_error.setVisible(False)

            def expand_async(data):
                try:
                    walk = json.loads(zlib.decompress(buffer(data)).decode('utf-8'))
                except:
                    walk = None

                if walk == None or not isinstance(walk, dict):
                    available_files       = []
                    available_directories = []
                    walk                  = None
                else:
                    available_files, available_directories = expand_walk_to_lists(walk)

                return walk, available_files, available_directories

            def cb_expand_success(result):
                walk, available_files, available_directories = result

                self.available_files       = available_files
                self.available_directories = available_directories

                if walk != None:
                    expand_walk_to_model(walk, self.tree_files_model, self.folder_icon, self.file_icon)
                else:
                    self.label_error.setText('<b>Error:</b> Received invalid data')
                    self.label_error.setVisible(True)

                self.tree_files.header().setSortIndicator(0, Qt.AscendingOrder)
                self.refresh_files_done()

            def cb_expand_error():
                self.label_error.setText('<b>Error:</b> Internal async error')
                self.label_error.setVisible(True)
                self.refresh_files_done()

            async_call(expand_async, result.stdout, cb_expand_success, cb_expand_error)

        self.refresh_in_progress = True
        self.update_main_ui_state()

        width1 = self.tree_files.columnWidth(0)
        width2 = self.tree_files.columnWidth(1)

        self.tree_files_model.clear()
        self.tree_files_model.setHorizontalHeaderLabels(self.tree_files_model_header)
        self.tree_files.setColumnWidth(0, width1)
        self.tree_files.setColumnWidth(1, width2)

        self.script_manager.execute_script('walk', cb_walk,
                                           [self.bin_directory], max_length=1024*1024,
                                           decode_output_as_utf8=False)

    def get_directly_selected_name_items(self):
        selected_indexes    = self.tree_files.selectedIndexes()
        selected_name_items = []

        for selected_index in selected_indexes:
            if selected_index.column() == 0:
                mapped_index = self.tree_files_proxy_model.mapToSource(selected_index)
                selected_name_items.append(self.tree_files_model.itemFromIndex(mapped_index))

        return selected_name_items

    def download_selected_files(self):
        selected_name_items = self.get_directly_selected_name_items()

        if len(selected_name_items) == 0:
            return

        downloads = []

        def expand(name_item):
            item_type = name_item.data(USER_ROLE_ITEM_TYPE)

            if item_type == ITEM_TYPE_DIRECTORY:
                for i in range(name_item.rowCount()):
                    expand(name_item.child(i, 0))
            elif item_type == ITEM_TYPE_FILE:
                filename = get_full_item_path(name_item)

                downloads.append(Download(filename, QDir.toNativeSeparators(filename)))

        for selected_name_item in selected_name_items:
            expand(selected_name_item)

        if len(downloads) == 0:
            return

        download_directory = get_existing_directory(get_main_window(), 'Download Files',
                                                    self.last_download_directory)

        if len(download_directory) == 0:
            return

        self.last_download_directory = download_directory

        self.show_download_wizard('files', download_directory, downloads)

    def rename_activated_file(self, index):
        if index.column() == 0 and not self.any_refresh_in_progress:
            mapped_index = self.tree_files_proxy_model.mapToSource(index)
            name_item    = self.tree_files_model.itemFromIndex(mapped_index)
            item_type    = name_item.data(USER_ROLE_ITEM_TYPE)

            # only rename files via activation, because directories are expanded
            if item_type == ITEM_TYPE_FILE:
                self.rename_item(name_item)

    def rename_selected_file(self):
        selection_count = len(self.tree_files.selectionModel().selectedRows())

        if selection_count != 1:
            return

        selected_name_items = self.get_directly_selected_name_items()

        if len(selected_name_items) != 1:
            return

        self.rename_item(selected_name_items[0])

    def rename_item(self, name_item):
        item_type = name_item.data(USER_ROLE_ITEM_TYPE)

        if item_type == ITEM_TYPE_FILE:
            title     = 'Rename File'
            type_name = 'file'
        else:
            title     = 'Rename Directory'
            type_name = 'directory'

        old_name = name_item.text()

        # get new name
        dialog = ExpandingInputDialog(get_main_window())
        dialog.setModal(True)
        dialog.setWindowTitle(title)
        dialog.setLabelText('Enter new {0} name:'.format(type_name))
        dialog.setInputMode(QInputDialog.TextInput)
        dialog.setTextValue(old_name)
        dialog.setOkButtonText('Rename')

        if dialog.exec_() != QDialog.Accepted:
            return

        new_name = dialog.textValue()

        if new_name == old_name:
            return

        # check that new name is valid
        if len(new_name) == 0 or new_name == '.' or new_name == '..' or '/' in new_name:
            QMessageBox.critical(get_main_window(), title + ' Error',
                                 'A {0} name cannot be empty, cannot be one dot [.], cannot be two dots [..] and cannot contain a forward slash [/].'
                                 .format(type_name))
            return

        # check that new name is not already in use
        name_item_parent = name_item.parent()

        if name_item_parent == None:
            name_item_parent = self.tree_files_model.invisibleRootItem()

        for i in range(name_item_parent.rowCount()):
            if new_name == name_item_parent.child(i).text():
                QMessageBox.critical(get_main_window(), title + ' Error',
                                     'The new {0} name is already in use.'.format(type_name))
                return

        absolute_old_name = posixpath.join(self.bin_directory, get_full_item_path(name_item))
        absolute_new_name = posixpath.join(posixpath.split(absolute_old_name)[0], new_name)

        def cb_rename(result):
            if not report_script_result(result, title + ' Error', u'Could not rename {0}'.format(type_name)):
                return

            name_item.setText(new_name)

            if self.tree_files.header().sortIndicatorSection() == 0:
                self.tree_files.header().setSortIndicator(0, self.tree_files.header().sortIndicatorOrder())

        self.script_manager.execute_script('rename', cb_rename,
                                           [absolute_old_name, absolute_new_name])

    def change_permissions_of_selected_file(self):
        selection_count = len(self.tree_files.selectionModel().selectedRows())

        if selection_count != 1:
            return

        selected_name_items = self.get_directly_selected_name_items()

        if len(selected_name_items) != 1:
            return

        name_item = selected_name_items[0]
        item_type = name_item.data(USER_ROLE_ITEM_TYPE)
        old_permissions = name_item.data(USER_ROLE_PERMISSIONS)

        if item_type == ITEM_TYPE_FILE:
            title     = 'Change File Permissions'
            type_name = 'file'
        else:
            title     = 'Change Directory Permissions'
            type_name = 'directory'

        dialog = ProgramInfoFilesPermissions(get_main_window(), title, old_permissions)

        if dialog.exec_() != QDialog.Accepted:
            return

        new_permissions = dialog.get_permissions()

        if new_permissions == (old_permissions & 0o777):
            return

        absolute_name = posixpath.join(self.bin_directory, get_full_item_path(name_item))

        def cb_change_permissions(result):
            if not report_script_result(result, title + ' Error', u'Could change {0} permissions'.format(type_name)):
                return

            name_item.setData(new_permissions, USER_ROLE_PERMISSIONS)

        self.script_manager.execute_script('change_permissions', cb_change_permissions,
                                           [absolute_name, str(new_permissions)])

    def delete_selected_files(self):
        button = QMessageBox.question(get_main_window(), 'Delete Files',
                                      'Irreversibly deleting selected files and directories.',
                                      QMessageBox.Ok, QMessageBox.Cancel)

        if not self.is_alive() or button != QMessageBox.Ok:
            return

        selected_name_items = set(self.get_directly_selected_name_items())

        if len(selected_name_items) == 0:
            return

        script_instance_ref = [None]

        def progress_canceled():
            script_instance = script_instance_ref[0]

            if script_instance == None:
                return

            self.script_manager.abort_script(script_instance)

        progress = ExpandingProgressDialog(self)
        progress.set_progress_text_visible(False)
        progress.setModal(True)
        progress.setWindowTitle('Delete Files')
        progress.setLabelText('Collecting files and directories to delete')
        progress.setRange(0, 0)
        progress.canceled.connect(progress_canceled)
        progress.show()

        files_to_delete = []
        dirs_to_delete  = []
        all_done        = False

        while not all_done:
            all_done = True

            for selected_name_item in list(selected_name_items):
                item_done = False
                parent = selected_name_item.parent()

                while not item_done and parent != None:
                    if parent in selected_name_items:
                        selected_name_items.remove(selected_name_item)
                        item_done = True
                    else:
                        parent = parent.parent()

                if item_done:
                    all_done = False
                    break

        for selected_name_item in selected_name_items:
            path      = get_full_item_path(selected_name_item)
            item_type = selected_name_item.data(USER_ROLE_ITEM_TYPE)

            if item_type == ITEM_TYPE_DIRECTORY:
                dirs_to_delete.append(posixpath.join(self.bin_directory, path))
            else:
                files_to_delete.append(posixpath.join(self.bin_directory, path))

        message = 'Deleting '

        if len(files_to_delete) == 1:
            message += '1 file '
        elif len(files_to_delete) > 1:
            message += '{0} files '.format(len(files_to_delete))

        if len(dirs_to_delete) == 1:
            if len(files_to_delete) > 0:
                message += 'and '

            message += '1 directory'
        elif len(dirs_to_delete) > 1:
            if len(files_to_delete) > 0:
                message += 'and '

            message += '{0} directories'.format(len(dirs_to_delete))

        progress.setLabelText(message)

        def cb_delete(result):
            script_instance = script_instance_ref[0]

            if script_instance != None:
                aborted = script_instance.abort
            else:
                aborted = False

            script_instance_ref[0] = None

            progress.cancel()
            self.refresh_files()

            if aborted:
                QMessageBox.information(get_main_window(), 'Delete Files',
                                        u'Delete operation was aborted.')
                return

            report_script_result(result, 'Delete Files Error', 'Could not delete selected files/directories:')

        script_instance_ref[0] = self.script_manager.execute_script('delete', cb_delete,
                                                                    [json.dumps(files_to_delete), json.dumps(dirs_to_delete)],
                                                                    execute_as_user=True)
Ejemplo n.º 24
0
class ConfigManagerDialog(ui_configmanager.Ui_ProjectInstallerDialog, QDialog):
    def __init__(self, roamapp, parent=None):
        super(ConfigManagerDialog, self).__init__(parent)
        self.setupUi(self)
        self.bar = roam.messagebaritems.MessageBar(self)

        self.roamapp = roamapp
        self.reloadingProject = False
        self.loadedProject = None
        self.projectpath = None

        # Nope!
        self.projectwidget.roamapp = roamapp
        self.projectwidget.bar = self.bar

        self.treemodel = QStandardItemModel()
        self.projectList.setModel(self.treemodel)
        self.projectList.setHeaderHidden(True)

        self.projectList.selectionModel().currentChanged.connect(
            self.nodeselected)

        self.projectwidget.adjustSize()
        self.setWindowFlags(Qt.Window)

        self.projectwidget.projectupdated.connect(self.projectupdated)
        self.projectwidget.projectloaded.connect(self.projectLoaded)

        self.projectwidget.setaboutinfo()
        self.projectwidget.projects_page.projectlocationchanged.connect(
            self.loadprojects)
        self.setuprootitems()

        ConfigEvents.deleteForm.connect(self.delete_form)

    def closeEvent(self, closeevent):
        self.save_page_config()
        closeevent.accept()

    def raiseerror(self, *exinfo):
        self.bar.pushError(*exinfo)
        import roam.errors
        roam.errors.send_exception(exinfo)

    def setuprootitems(self):
        rootitem = self.treemodel.invisibleRootItem()
        self.roamnode = RoamNode()
        rootitem.appendRow(self.roamnode)

        self.datanode = DataNode(folder=None)
        rootitem.appendRow(self.datanode)
        self.projectsnode = ProjectsNode(folder=None)
        rootitem.appendRow(self.projectsnode)
        self.publishnode = PublishNode(folder=None)
        rootitem.appendRow(self.publishnode)

        self.pluginsnode = PluginsNode()
        pluginpath = os.path.join(self.roamapp.apppath, "plugins")
        rootitem.appendRow(self.pluginsnode)
        self.pluginsnode.add_plugin_paths([pluginpath])

    def delete_form(self):
        index = self.projectList.currentIndex()
        node = index.data(Qt.UserRole)
        if not node.type() == Treenode.FormNode:
            return

        title, removemessage = node.removemessage
        delete = node.canremove
        if node.canremove and removemessage:
            button = QMessageBox.warning(self, title, removemessage,
                                         QMessageBox.Yes | QMessageBox.No)
            delete = button == QMessageBox.Yes

        print "Delete"
        if delete:
            parentindex = index.parent()
            newindex = self.treemodel.index(index.row(), 0, parentindex)
            if parentindex.isValid():
                parent = parentindex.data(Qt.UserRole)
                parent.delete(index.row())

            print parentindex
            self.projectList.setCurrentIndex(parentindex)

    def delete_project(self):
        index = self.projectList.currentIndex()
        node = index.data(Qt.UserRole)
        if node.type() == Treenode.ProjectNode:
            self.projectwidget._closeqgisproject()

        title, removemessage = node.removemessage
        delete = node.canremove
        if node.canremove and removemessage:
            button = QMessageBox.warning(self, title, removemessage,
                                         QMessageBox.Yes | QMessageBox.No)
            delete = button == QMessageBox.Yes

        if delete:
            parentindex = index.parent()
            newindex = self.treemodel.index(index.row(), 0, parentindex)
            if parentindex.isValid():
                parent = parentindex.data(Qt.UserRole)
                parent.delete(index.row())

            self.projectList.setCurrentIndex(newindex)

    def addprojectfolders(self, folders):
        self.projectwidget.projects_page.setprojectfolders(folders)

    @property
    def active_project_folder(self):
        return self.projectpath

    @active_project_folder.setter
    def active_project_folder(self, value):
        self.projectpath = value
        pass

    def loadprojects(self, projectpath):
        self.active_project_folder = projectpath

        projects = roam.project.getProjects([projectpath])
        self.projectsnode.loadprojects(projects, projectsbase=projectpath)

        index = self.treemodel.indexFromItem(self.projectsnode)
        self.projectList.setCurrentIndex(index)
        self.projectList.expand(index)

    def projectLoaded(self, project):
        roam.utils.info("Project loaded: {}".format(project.name))
        node = self.projectsnode.find_by_name(project.name)
        node.create_children()
        self.projectwidget.setpage(node.page, node, refreshingProject=True)
        self.reloadingProject = False
        self.loadedProject = project
        self.projectList.setExpanded(node.index(), True)

    def nodeselected(self, index, last, reloadProject=False):
        node = index.data(Qt.UserRole)
        if node is None:
            return

        project = node.project

        if project:
            validateresults = list(project.validate())
            if validateresults:
                text = "Here are some reasons we found: \n\n"
                for message in validateresults:
                    text += "- {} \n".format(message)

                self.projectwidget.reasons_label.setText(text)
                return

        if node.nodetype == Treenode.ProjectNode and reloadProject:
            self.reloadingProject = True
            self.projectwidget.setproject(project)
            return

        if project and self.loadedProject != project:
            # Only load the project if it's different the current one.
            if self.loadedProject:
                lastnode = self.projectsnode.find_by_name(
                    self.loadedProject.name)
                self.projectList.setExpanded(lastnode.index(), False)
            ## We are closing the open project at this point. Watch for null ref after this.
            self.projectwidget.setproject(project)
            self.projectwidget.setpage(node.page, node)
            return
        else:
            self.projectwidget.setpage(node.page, node)

        if node.nodetype == Treenode.AddNew:
            try:
                item = node.additem()
            except ValueError:
                return
            newindex = self.treemodel.indexFromItem(item)
            self.projectList.setCurrentIndex(newindex)
            return

    def save_page_config(self):
        """
        Save the current page config
        """
        self.projectwidget.savePage(closing=True)

    def projectupdated(self, project):
        print "PROJECT UPDATED"
        node = self.projectsnode.find_by_name(project.name)
        self.projectList.selectionModel().select(
            node.index(), QItemSelectionModel.ClearAndSelect)
        self.nodeselected(node.index(), None, reloadProject=True)
Ejemplo n.º 25
0
class SetupDialog(QDialog, Ui_SetupDialog):
    """
        Function and Event handling class for the Ui_SetupDialog.
    """

    def __init__(self, parent):
        QDialog.__init__(self, parent)

        self._gui_logger = GUILogger("GUILogger", logging.INFO)
        self._gui_job = None
        EventLogger.add_logger(self._gui_logger)

        # FIXME better way to find interval and uids in tree_widget?!
        self.__tree_interval_tooltip = "Update interval in seconds"
        self.__tree_uid_tooltip = "UID cannot be empty"
        self.data_logger_thread = None
        self.tab_debug_warning = False

        self.device_dialog = None

        self.host_infos = None
        self.last_host = None
        self.host_index_changing = None

        self.setupUi(self)

        self.model_data = QStandardItemModel(self)
        self.model_data.setHorizontalHeaderLabels(['Time', 'Name', 'UID', 'Var', 'Raw', 'Unit'])
        self.table_data.setModel(self.model_data)
        self.table_data.setColumnWidth(0, 160)
        self.table_data.setColumnWidth(1, 170)
        self.table_data.setColumnWidth(2, 50)
        self.table_data.setColumnWidth(3, 110)
        self.table_data.setColumnWidth(4, 70)
        self.table_data.setColumnWidth(5, 100)

        self.model_devices = QStandardItemModel(self)
        self.model_devices.setHorizontalHeaderLabels(['Device', 'Value'])
        self.tree_devices.setModel(self.model_devices)
        self.tree_devices.setColumnWidth(0, 300)

        self.widget_initialization()

        self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/start-icon.png')))

        timestamp = int(time.time())
        self.edit_csv_file_name.setText(os.path.join(get_home_path(), 'logger_data_{0}.csv'.format(timestamp)))
        self.edit_log_file_name.setText(os.path.join(get_home_path(), 'logger_debug_{0}.log'.format(timestamp)))

        self.combo_data_time_format.addItem(utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de')
        self.combo_data_time_format.addItem(utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us')
        self.combo_data_time_format.addItem(utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso')
        self.combo_data_time_format.addItem(utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix')

        self.combo_debug_time_format.addItem(utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de')
        self.combo_debug_time_format.addItem(utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us')
        self.combo_debug_time_format.addItem(utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso')
        self.combo_debug_time_format.addItem(utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix')

        self.combo_log_level.addItem('Debug', 'debug')
        self.combo_log_level.addItem('Info', 'info')
        self.combo_log_level.addItem('Warning', 'warning')
        self.combo_log_level.addItem('Error', 'error')
        self.combo_log_level.addItem('Critical', 'critical')
        self.combo_log_level.setCurrentIndex(0) # debug

        self.combo_debug_level.addItem('Debug', logging.DEBUG)
        self.combo_debug_level.addItem('Info', logging.INFO)
        self.combo_debug_level.addItem('Warning', logging.WARNING)
        self.combo_debug_level.addItem('Error', logging.ERROR)
        self.combo_debug_level.addItem('Critical', logging.CRITICAL)
        self.combo_debug_level.setCurrentIndex(1) # info

        self.update_ui_state()

    def update_ui_state(self):
        data_to_csv_file = self.check_data_to_csv_file.isChecked()
        debug_to_log_file = self.check_debug_to_log_file.isChecked()

        self.label_csv_file_name.setVisible(data_to_csv_file)
        self.edit_csv_file_name.setVisible(data_to_csv_file)
        self.btn_browse_csv_file_name.setVisible(data_to_csv_file)

        self.label_log_file_name.setVisible(debug_to_log_file)
        self.edit_log_file_name.setVisible(debug_to_log_file)
        self.btn_browse_log_file_name.setVisible(debug_to_log_file)
        self.label_log_level.setVisible(debug_to_log_file)
        self.combo_log_level.setVisible(debug_to_log_file)

    def widget_initialization(self):
        """
            Sets default values for some widgets
        """
        # Login data
        self.host_info_initialization()

        self.signal_initialization()

    def signal_initialization(self):
        """
            Init of all important Signals and connections.
        """
        # Buttons
        self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked)
        self.btn_save_config.clicked.connect(self.btn_save_config_clicked)
        self.btn_load_config.clicked.connect(self.btn_load_config_clicked)
        self.check_data_to_csv_file.stateChanged.connect(self.update_ui_state)
        self.check_debug_to_log_file.stateChanged.connect(self.update_ui_state)
        self.btn_browse_csv_file_name.clicked.connect(self.btn_browse_csv_file_name_clicked)
        self.btn_browse_log_file_name.clicked.connect(self.btn_browse_log_file_name_clicked)
        self.btn_clear_debug.clicked.connect(self.btn_clear_debug_clicked)
        self.combo_debug_level.currentIndexChanged.connect(self.combo_debug_level_changed)
        self.btn_add_device.clicked.connect(self.btn_add_device_clicked)
        self.btn_remove_device.clicked.connect(self.btn_remove_device_clicked)
        self.btn_remove_all_devices.clicked.connect(self.btn_remove_all_devices_clicked)

        self.tab_widget.currentChanged.connect(self.tab_reset_warning)
        self.btn_clear_data.clicked.connect(self.btn_clear_data_clicked)

        self.connect(self._gui_logger, QtCore.SIGNAL(GUILogger.SIGNAL_NEW_MESSAGE), self.add_debug_message)
        self.connect(self._gui_logger, QtCore.SIGNAL(GUILogger.SIGNAL_NEW_MESSAGE_TAB_HIGHLIGHT),
                     self.highlight_debug_tab)

        self.combo_host.currentIndexChanged.connect(self._host_index_changed)
        self.spin_port.valueChanged.connect(self._port_changed)

    def host_info_initialization(self):
        """
            initialize host by getting information out of brickv.config
        """
        self.host_infos = config.get_host_infos(config.HOST_INFO_COUNT)
        self.host_index_changing = True

        for host_info in self.host_infos:
            self.combo_host.addItem(host_info.host)

        self.last_host = None
        self.combo_host.setCurrentIndex(0)
        self.spin_port.setValue(self.host_infos[0].port)
        self.host_index_changing = False

    def btn_start_logging_clicked(self):
        """
            Start/Stop of the logging process
        """
        if (self.data_logger_thread is not None) and (not self.data_logger_thread.stopped):
            self.btn_start_logging.clicked.disconnect()

            self.data_logger_thread.stop()
            self._reset_stop()

        elif self.data_logger_thread is None:
            from brickv.data_logger import main

            self._gui_job = GuiDataJob(name="GuiData-Writer")
            self.connect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row)

            self.data_logger_thread = main.main(None, GuiConfigHandler.create_config(self), self._gui_job)

            if self.data_logger_thread is not None:
                self.btn_start_logging.setText("Stop Logging")
                self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/stop-icon.png')))
                self.tab_devices.setEnabled(False)
                self.tab_setup.setEnabled(False)
                self.tab_widget.setCurrentIndex(self.tab_widget.indexOf(self.tab_data))
                self.tab_reset_warning()

    def _reset_stop(self):
        self.tab_devices.setEnabled(True)
        self.tab_setup.setEnabled(True)
        self.btn_start_logging.setText("Start Logging")
        self.btn_start_logging.setIcon(QIcon(load_pixmap('data_logger/start-icon.png')))

        self.disconnect(self._gui_job, QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA), self.table_add_row)
        self.data_logger_thread = None
        self._gui_job = None

        self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked)

    def btn_save_config_clicked(self):
        filename = get_save_file_name(get_main_window(), 'Save Config',
                                      get_home_path(), 'JSON Files (*.json)')

        if len(filename) == 0:
            return

        if not filename.lower().endswith('.json'):
            filename += '.json'

        config = GuiConfigHandler.create_config(self)

        if not save_config(config, filename):
            QMessageBox.warning(get_main_window(), 'Save Config',
                                'Could not save config to file! See Debug tab for details.',
                                QMessageBox.Ok)

    def btn_load_config_clicked(self):
        filename = get_open_file_name(get_main_window(), 'Load Config',
                                      get_home_path(), 'JSON Files (*.json)')

        if len(filename) == 0:
            return

        config = load_and_validate_config(filename)

        if config == None:
            QMessageBox.warning(get_main_window(), 'Load Config',
                                'Could not load config from file! See Debug tab for details.',
                                QMessageBox.Ok)
            return

        self.update_setup_tab(config)
        self.update_devices_tab(config)

    def btn_browse_csv_file_name_clicked(self):
        if len(self.edit_csv_file_name.text()) > 0:
            last_dir = os.path.dirname(os.path.realpath(self.edit_csv_file_name.text()))
        else:
            last_dir = get_home_path()

        filename = get_save_file_name(get_main_window(), 'Choose CSV File',
                                      last_dir, "CSV Files (*.csv)")

        if len(filename) > 0:
            if not filename.lower().endswith('.csv'):
                filename += '.csv'

            self.edit_csv_file_name.setText(filename)

    def btn_browse_log_file_name_clicked(self):
        if len(self.edit_log_file_name.text()) > 0:
            last_dir = os.path.dirname(os.path.realpath(self.edit_log_file_name.text()))
        else:
            last_dir = get_home_path()

        filename = get_save_file_name(get_main_window(), 'Choose Log File',
                                      last_dir, "Log Files (*.log)")

        if len(filename) > 0:
            if not filename.lower().endswith('.log'):
                filename += '.log'

            self.edit_log_file_name.setText(filename)

    def btn_add_device_clicked(self):
        """
            Opens the DeviceDialog in Add-Mode.
        """
        if self.device_dialog is None:
            self.device_dialog = DeviceDialog(self)

        self.device_dialog.btn_refresh_clicked()
        self.device_dialog.show()

    def btn_remove_device_clicked(self):
        selection = self.tree_devices.selectionModel().selectedIndexes()

        while len(selection) > 0:
            index = selection[0]

            while index.parent() != self.model_devices.invisibleRootItem().index():
                index = index.parent()

            self.model_devices.removeRows(index.row(), 1)

            # get new selection, because row removal might invalid indices
            selection = self.tree_devices.selectionModel().selectedIndexes()

    def btn_remove_all_devices_clicked(self):
        self.model_devices.removeRows(0, self.model_devices.rowCount())

    def btn_clear_data_clicked(self):
        self.model_data.removeRows(0, self.model_data.rowCount())

    def tab_reset_warning(self):
        """
            Resets the Warning @ the debug tab.
        """
        if not self.tab_debug_warning or self.tab_widget.currentWidget().objectName() != self.tab_debug.objectName():
            return

        self.tab_debug_warning = False

        self.tab_set(self.tab_widget.indexOf(self.tab_debug), self.palette().color(QPalette.WindowText), None)

    def combo_debug_level_changed(self):
        """
            Changes the log level dynamically.
        """
        self._gui_logger.level = self.combo_debug_level.itemData(self.combo_debug_level.currentIndex())

    def tab_set(self, tab_index, color, icon=None):
        """
            Sets the font Color and an icon, if given, at a specific tab.
        """
        from PyQt4.QtGui import QIcon

        self.tab_widget.tabBar().setTabTextColor(tab_index, color)
        if icon is not None:
            self.tab_widget.setTabIcon(tab_index, QIcon(icon))
        else:
            self.tab_widget.setTabIcon(tab_index, QIcon())

    def _host_index_changed(self, i):
        """
            Persists host information changes like in brickv.mainwindow
            Changes port if the host was changed
        """
        if i < 0:
            return

        self.host_index_changing = True
        self.spin_port.setValue(self.host_infos[i].port)
        self.host_index_changing = False

    def _port_changed(self, value):
        """
            Persists host information changes like in brickv.mainwindow
        """
        if self.host_index_changing:
            return

        i = self.combo_host.currentIndex()
        if i < 0:
            return

        self.host_infos[i].port = self.spin_port.value()

    def update_setup_tab(self, config):
        EventLogger.debug('Updating setup tab from config')

        self.combo_host.setEditText(config['hosts']['default']['name'])
        self.spin_port.setValue(config['hosts']['default']['port'])

        self.combo_data_time_format.setCurrentIndex(max(self.combo_data_time_format.findData(config['data']['time_format']), 0))
        self.check_data_to_csv_file.setChecked(config['data']['csv']['enabled'])
        self.edit_csv_file_name.setText(config['data']['csv']['file_name'].decode('utf-8'))

        self.combo_debug_time_format.setCurrentIndex(max(self.combo_debug_time_format.findData(config['debug']['time_format']), 0))
        self.check_debug_to_log_file.setChecked(config['debug']['log']['enabled'])
        self.edit_log_file_name.setText(config['debug']['log']['file_name'].decode('utf-8'))
        self.combo_log_level.setCurrentIndex(max(self.combo_debug_time_format.findData(config['debug']['log']['level']), 0))

    def update_devices_tab(self, config):
        EventLogger.debug('Updating devices tab from config')

        self.model_devices.removeRows(0, self.model_data.rowCount())

        for device in config['devices']:
            self.add_device_to_tree(device)

    def add_device_to_tree(self, device):
        # check if device is already added
        if len(device['uid']) > 0:
            for row in range(self.model_devices.rowCount()):
                existing_name = self.model_devices.item(row, 0).text()
                exisitng_uid = self.tree_devices.indexWidget(self.model_devices.item(row, 1).index()).text()

                if device['name'] == existing_name and device['uid'] == exisitng_uid:
                    EventLogger.info('Ignoring duplicate device "{0}" with UID "{1}"'
                                     .format(device['name'], device['uid']))
                    return

        # add device
        name_item = QStandardItem(device['name'])
        uid_item = QStandardItem('')

        self.model_devices.appendRow([name_item, uid_item])

        edit_uid = QLineEdit()
        edit_uid.setPlaceholderText('Enter UID')
        edit_uid.setValidator(QRegExpValidator(QRegExp('^[{0}]{{1,6}}$'.format(BASE58)))) # FIXME: use stricter logic
        edit_uid.setText(device['uid'])

        self.tree_devices.setIndexWidget(uid_item.index(), edit_uid)

        value_specs = device_specs[device['name']]['values']
        parent_item = QStandardItem('Values')

        name_item.appendRow([parent_item, QStandardItem('')])
        self.tree_devices.expand(parent_item.index())

        # add values
        for value_spec in value_specs:
            value_name_item = QStandardItem(value_spec['name'])
            value_interval_item = QStandardItem('')

            parent_item.appendRow([value_name_item, value_interval_item])

            spinbox_interval = QSpinBox()
            spinbox_interval.setRange(0, (1 << 31) - 1)
            spinbox_interval.setSingleStep(1)
            spinbox_interval.setValue(device['values'][value_spec['name']]['interval'])
            spinbox_interval.setSuffix(' seconds')

            self.tree_devices.setIndexWidget(value_interval_item.index(), spinbox_interval)

            if value_spec['subvalues'] != None:
                for subvalue_name in value_spec['subvalues']:
                    subvalue_name_item = QStandardItem(subvalue_name)
                    subvalue_check_item = QStandardItem('')

                    value_name_item.appendRow([subvalue_name_item, subvalue_check_item])

                    check_subvalue = QCheckBox()
                    check_subvalue.setChecked(device['values'][value_spec['name']]['subvalues'][subvalue_name])

                    self.tree_devices.setIndexWidget(subvalue_check_item.index(), check_subvalue)

        self.tree_devices.expand(name_item.index())

        # add options
        option_specs = device_specs[device['name']]['options']

        if option_specs != None:
            parent_item = QStandardItem('Options')

            name_item.appendRow([parent_item, QStandardItem('')])

            for option_spec in option_specs:
                option_name_item = QStandardItem(option_spec['name'])
                option_widget_item = QStandardItem('')

                parent_item.appendRow([option_name_item, option_widget_item])

                if option_spec['type'] == 'choice':
                    widget_option_value = QComboBox()

                    for option_value_spec in option_spec['values']:
                        widget_option_value.addItem(option_value_spec[0].decode('utf-8'), option_value_spec[1])

                    widget_option_value.setCurrentIndex(widget_option_value.findText(device['options'][option_spec['name']]['value'].decode('utf-8')))
                elif option_spec['type'] == 'int':
                    widget_option_value = QSpinBox()
                    widget_option_value.setRange(option_spec['minimum'], option_spec['maximum'])
                    widget_option_value.setSuffix(option_spec['suffix'])
                    widget_option_value.setValue(device['options'][option_spec['name']]['value'])
                elif option_spec['type'] == 'bool':
                    widget_option_value = QCheckBox()
                    widget_option_value.setChecked(device['options'][option_spec['name']]['value'])

                self.tree_devices.setIndexWidget(option_widget_item.index(), widget_option_value)

    def add_debug_message(self, message):
        self.text_debug.append(message)

        while self.text_debug.document().blockCount() > 1000:
            cursor = QTextCursor(self.text_debug.document().begin())
            cursor.select(QTextCursor.BlockUnderCursor)
            cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)
            cursor.removeSelectedText()

        if self.checkbox_debug_auto_scroll.isChecked():
            self.text_debug.verticalScrollBar().setValue(self.text_debug.verticalScrollBar().maximum())

    def btn_clear_debug_clicked(self):
        self.text_debug.clear()

    def highlight_debug_tab(self):
        """
            SIGNAL function:
            Highlight the debug tab when an error occurs.
        """
        if not self.tab_debug_warning and self.tab_widget.currentWidget().objectName() != self.tab_debug.objectName():
            self.tab_debug_warning = True
            self.tab_set(self.tab_widget.indexOf(self.tab_debug), QColor(255, 0, 0),
                         os.path.join(get_resources_path(), "warning-icon.png"))

    def table_add_row(self, csv_data):
        """
            SIGNAL function:
            Adds new CSV Data into the Table.
        """
        rows = self.model_data.rowCount()

        while rows >= 1000:
            self.model_data.removeRow(0)
            rows = self.model_data.rowCount()

        row_number = None

        if rows > 0:
            try:
                row_number = int(self.model_data.headerData(rows - 1, Qt.Vertical))
            except ValueError:
                pass

        self.model_data.appendRow([QStandardItem(csv_data.timestamp),
                                   QStandardItem(csv_data.name),
                                   QStandardItem(csv_data.uid),
                                   QStandardItem(csv_data.var_name),
                                   QStandardItem(str(csv_data.raw_data)),
                                   QStandardItem(csv_data.var_unit.decode('utf-8'))])

        if row_number != None:
            self.model_data.setHeaderData(rows, Qt.Vertical, str(row_number + 1))

        if self.checkbox_data_auto_scroll.isChecked():
            self.table_data.scrollToBottom()
Ejemplo n.º 26
0
class Model:
    """
    class model
    """

    def __init__(self, view, config, parent=None):
        """
		Constructor for class model
		@param view:
		@param config:
		"""
        self.parent = parent
        self.view = view
        self.config = config
        self.pageModel = QStandardItemModel()
        self.view.listView.setModel(self.pageModel)

    def createConnector(self):
        self.view.statusBar().showMessage('connecting...')
        self.c = Connector(self.view.serverLineEdit.text(), self.view.userLineEdit.text(),
                            self.view.passwdLineEdit.text(), '')
        
        print (self.c.getWikiVersion())
        self.allPages = self.c.getAllPages()
        if (self.allPages != None):
            self.view.statusBar().showMessage('connected.')
            parentItem = self.pageModel.invisibleRootItem()
            for i in self.allPages:
                parentItem.appendRow(QStandardItem(i['id']))
            self.connected = True
        else:
            self.view.statusBar().showMessage("Couldn't get pages.")
            print ("Couldn't get pages.")
    
    def copySettings(self):
        self.config.settings['app_x'] = self.view.pos().x()
        self.config.settings['app_y'] = self.view.pos().y()
        self.config.settings['app_w'] = self.view.size().width()
        self.config.settings['app_h'] = self.view.size().height()
        self.config.settings['user'] = str(self.view.userLineEdit.text())
        self.config.settings['serverAddress'] = str(self.view.serverLineEdit.text())
        self.config.writeConfig()
    
    def readyToSave(self):
        if (self.connected):
            self.view.save.setDisabled(False)

    def displayPage(self, newSelection, oldSelection):
        self.pageIndex = self.view.listView.selectionModel().selectedIndexes()
        if (self.pageIndex != None):
            self.pageName = self.pageIndex[0].data().toString()
            if (self.pageName != None):
                print ('Selected item: ' + self.pageName)
                self.view.statusBar().showMessage('Loading page ' + str(self.pageName))
                self.view.textEdit.setText(self.c.getPageText(self.pageName))
        
    def saveCurrentPage(self):
        attr = QVariant()
        if (self.pageName != None):
            self.c.setPageText(self.pageName, self.view.textEdit.document().toPlainText(), attr)
            self.view.statusBar().showMessage('Page ' + str(self.pageName) + ' saved.')
        
    def insertBoldText(self):
        print ('insert bold text or change text to bold')
        self.textCursor = self.view.textEdit.textCursor()
        self.view.textEdit.insertPlainText('**' + str(self.textCursor.selectedText()) + '**')
        # self.textCursor.setPosition(self.textCursor.position() - 2)
        # print self.textCursor.movePosition(QTextCursor.Left, 2)

    def insertItalicText(self):
        print ('insert italic text or change text to bold')
        textCursor = self.view.textEdit.textCursor()
        self.view.textEdit.insertPlainText('//' + str(textCursor.selectedText()) + '//')
        
    def insertH1Text(self):
        print ('insert H1 text or change text to H1')
        textCursor = self.view.textEdit.textCursor()
        self.view.textEdit.insertPlainText('======' + str(textCursor.selectedText()) + '======')
        
    def insertH2Text(self):
        print ('insert H2 text or change text to H2')
        textCursor = self.view.textEdit.textCursor()
        self.view.textEdit.insertPlainText('=====' + str(textCursor.selectedText()) + '=====')
        
    def insertH3Text(self):
        print ('insert H3 text or change text to H3')
        textCursor = self.view.textEdit.textCursor()
        self.view.textEdit.insertPlainText('====' + str(textCursor.selectedText()) + '====')
        
    def insertH4Text(self):
        print ('insert H4 text or change text to H4')
        textCursor = self.view.textEdit.textCursor()
        self.view.textEdit.insertPlainText('===' + str(textCursor.selectedText()) + '===')
        
    def insertH5Text(self):
        print ('insert H5 text or change text to H5')
        textCursor = self.view.textEdit.textCursor()
        self.view.textEdit.insertPlainText('==' + str(textCursor.selectedText()) + '==')
        
    def searchFor(self):
        print ('TODO: search for pages')
Ejemplo n.º 27
0
class OWConfusionMatrix(widget.OWWidget):
    """Confusion matrix widget"""

    name = "Confusion Matrix"
    description = "Display a confusion matrix constructed from " \
                  "the results of classifier evaluations."
    icon = "icons/ConfusionMatrix.svg"
    priority = 1001

    inputs = [("Evaluation Results", Orange.evaluation.Results, "set_results")]
    outputs = [("Selected Data", Orange.data.Table)]

    quantities = ["Number of instances",
                  "Proportion of predicted",
                  "Proportion of actual"]

    settingsHandler = settings.ClassValuesContextHandler()

    selected_learner = settings.Setting([0], schema_only=True)
    selection = settings.ContextSetting(set())
    selected_quantity = settings.Setting(0)
    append_predictions = settings.Setting(True)
    append_probabilities = settings.Setting(False)
    autocommit = settings.Setting(True)

    UserAdviceMessages = [
        widget.Message(
            "Clicking on cells or in headers outputs the corresponding "
            "data instances",
            "click_cell")]

    def __init__(self):
        super().__init__()

        self.data = None
        self.results = None
        self.learners = []
        self.headers = []

        box = gui.vBox(self.controlArea, "Learners")

        self.learners_box = gui.listBox(
            box, self, "selected_learner", "learners",
            callback=self._learner_changed
        )
        box = gui.vBox(self.controlArea, "Show")

        gui.comboBox(box, self, "selected_quantity", items=self.quantities,
                     callback=self._update)

        box = gui.vBox(self.controlArea, "Select")

        gui.button(box, self, "Select Correct",
                   callback=self.select_correct, autoDefault=False)
        gui.button(box, self, "Select Misclassified",
                   callback=self.select_wrong, autoDefault=False)
        gui.button(box, self, "Clear Selection",
                   callback=self.select_none, autoDefault=False)

        self.outputbox = box = gui.vBox(self.controlArea, "Output")
        gui.checkBox(box, self, "append_predictions",
                     "Predictions", callback=self._invalidate)
        gui.checkBox(box, self, "append_probabilities",
                     "Probabilities",
                     callback=self._invalidate)

        gui.auto_commit(self.controlArea, self, "autocommit",
                        "Send Selected", "Send Automatically")

        grid = QGridLayout()

        self.tablemodel = QStandardItemModel(self)
        view = self.tableview = QTableView(
            editTriggers=QTableView.NoEditTriggers)
        view.setModel(self.tablemodel)
        view.horizontalHeader().hide()
        view.verticalHeader().hide()
        view.horizontalHeader().setMinimumSectionSize(60)
        view.selectionModel().selectionChanged.connect(self._invalidate)
        view.setShowGrid(False)
        view.setItemDelegate(BorderedItemDelegate(Qt.white))
        view.clicked.connect(self.cell_clicked)
        grid.addWidget(view, 0, 0)
        self.mainArea.layout().addLayout(grid)

    def sizeHint(self):
        """Initial size"""
        return QSize(750, 490)

    def _item(self, i, j):
        return self.tablemodel.item(i, j) or QStandardItem()

    def _set_item(self, i, j, item):
        self.tablemodel.setItem(i, j, item)

    def _init_table(self, nclasses):
        item = self._item(0, 2)
        item.setData("Predicted", Qt.DisplayRole)
        item.setTextAlignment(Qt.AlignCenter)
        item.setFlags(Qt.NoItemFlags)

        self._set_item(0, 2, item)
        item = self._item(2, 0)
        item.setData("Actual", Qt.DisplayRole)
        item.setTextAlignment(Qt.AlignHCenter | Qt.AlignBottom)
        item.setFlags(Qt.NoItemFlags)
        self.tableview.setItemDelegateForColumn(0, gui.VerticalItemDelegate())
        self._set_item(2, 0, item)
        self.tableview.setSpan(0, 2, 1, nclasses)
        self.tableview.setSpan(2, 0, nclasses, 1)

        font = self.tablemodel.invisibleRootItem().font()
        bold_font = QFont(font)
        bold_font.setBold(True)

        for i in (0, 1):
            for j in (0, 1):
                item = self._item(i, j)
                item.setFlags(Qt.NoItemFlags)
                self._set_item(i, j, item)

        for p, label in enumerate(self.headers):
            for i, j in ((1, p + 2), (p + 2, 1)):
                item = self._item(i, j)
                item.setData(label, Qt.DisplayRole)
                item.setFont(bold_font)
                item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                item.setFlags(Qt.ItemIsEnabled)
                if p < len(self.headers) - 1:
                    item.setData("br"[j == 1], BorderRole)
                    item.setData(QColor(192, 192, 192), BorderColorRole)
                self._set_item(i, j, item)

        hor_header = self.tableview.horizontalHeader()
        if len(' '.join(self.headers)) < 120:
            hor_header.setResizeMode(QHeaderView.ResizeToContents)
        else:
            hor_header.setDefaultSectionSize(60)
        self.tablemodel.setRowCount(nclasses + 3)
        self.tablemodel.setColumnCount(nclasses + 3)

    def set_results(self, results):
        """Set the input results."""

        prev_sel_learner = self.selected_learner.copy()
        self.clear()
        self.warning()
        self.closeContext()

        data = None
        if results is not None and results.data is not None:
            data = results.data

        if data is not None and not data.domain.has_discrete_class:
            self.warning("Confusion Matrix cannot show regression results.")

        self.results = results
        self.data = data

        if data is not None:
            class_values = data.domain.class_var.values
        elif results is not None:
            raise NotImplementedError

        if results is None:
            self.report_button.setDisabled(True)
        else:
            self.report_button.setDisabled(False)

            nmodels = results.predicted.shape[0]
            self.headers = class_values + \
                           [unicodedata.lookup("N-ARY SUMMATION")]

            # NOTE: The 'learner_names' is set in 'Test Learners' widget.
            if hasattr(results, "learner_names"):
                self.learners = results.learner_names
            else:
                self.learners = ["Learner #{}".format(i + 1)
                                 for i in range(nmodels)]

            self._init_table(len(class_values))
            self.openContext(data.domain.class_var)
            if not prev_sel_learner or prev_sel_learner[0] >= len(self.learners):
                self.selected_learner[:] = [0]
            else:
                self.selected_learner[:] = prev_sel_learner
            self._update()
            self._set_selection()
            self.unconditional_commit()

    def clear(self):
        """Reset the widget, clear controls"""
        self.results = None
        self.data = None
        self.tablemodel.clear()
        self.headers = []
        # Clear learners last. This action will invoke `_learner_changed`
        self.learners = []

    def select_correct(self):
        """Select the diagonal elements of the matrix"""
        selection = QItemSelection()
        n = self.tablemodel.rowCount()
        for i in range(2, n):
            index = self.tablemodel.index(i, i)
            selection.select(index, index)
        self.tableview.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect)

    def select_wrong(self):
        """Select the off-diagonal elements of the matrix"""
        selection = QItemSelection()
        n = self.tablemodel.rowCount()
        for i in range(2, n):
            for j in range(i + 1, n):
                index = self.tablemodel.index(i, j)
                selection.select(index, index)
                index = self.tablemodel.index(j, i)
                selection.select(index, index)
        self.tableview.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect)

    def select_none(self):
        """Reset selection"""
        self.tableview.selectionModel().clear()

    def cell_clicked(self, model_index):
        """Handle cell click event"""
        i, j = model_index.row(), model_index.column()
        if not i or not j:
            return
        n = self.tablemodel.rowCount()
        index = self.tablemodel.index
        selection = None
        if i == j == 1 or i == j == n - 1:
            selection = QItemSelection(index(2, 2), index(n - 1, n - 1))
        elif i in (1, n - 1):
            selection = QItemSelection(index(2, j), index(n - 1, j))
        elif j in (1, n - 1):
            selection = QItemSelection(index(i, 2), index(i, n - 1))

        if selection is not None:
            self.tableview.selectionModel().select(
                selection, QItemSelectionModel.ClearAndSelect)

    def commit(self):
        """Output data instances corresponding to selected cells"""
        if self.results is not None and self.data is not None \
                and self.selected_learner:
            indices = self.tableview.selectedIndexes()
            indices = {(ind.row() - 2, ind.column() - 2) for ind in indices}
            actual = self.results.actual
            learner_name = self.learners[self.selected_learner[0]]
            predicted = self.results.predicted[self.selected_learner[0]]
            selected = [i for i, t in enumerate(zip(actual, predicted))
                        if t in indices]
            row_indices = self.results.row_indices[selected]

            extra = []
            class_var = self.data.domain.class_var
            metas = self.data.domain.metas

            if self.append_predictions:
                predicted = numpy.array(predicted[selected], dtype=object)
                extra.append(predicted.reshape(-1, 1))
                var = Orange.data.DiscreteVariable(
                    "{}({})".format(class_var.name, learner_name),
                    class_var.values
                )
                metas = metas + (var,)

            if self.append_probabilities and \
                    self.results.probabilities is not None:
                probs = self.results.probabilities[self.selected_learner[0],
                                                   selected]
                extra.append(numpy.array(probs, dtype=object))
                pvars = [Orange.data.ContinuousVariable("p({})".format(value))
                         for value in class_var.values]
                metas = metas + tuple(pvars)

            X = self.data.X[row_indices]
            Y = self.data.Y[row_indices]
            M = self.data.metas[row_indices]
            row_ids = self.data.ids[row_indices]

            M = numpy.hstack((M,) + tuple(extra))
            domain = Orange.data.Domain(
                self.data.domain.attributes,
                self.data.domain.class_vars,
                metas
            )
            data = Orange.data.Table.from_numpy(domain, X, Y, M)
            data.ids = row_ids
            data.name = learner_name

        else:
            data = None

        self.send("Selected Data", data)

    def _invalidate(self):
        indices = self.tableview.selectedIndexes()
        self.selection = {(ind.row() - 2, ind.column() - 2) for ind in indices}
        self.commit()

    def _set_selection(self):
        selection = QItemSelection()
        index = self.tableview.model().index
        for row, col in self.selection:
            sel = index(row + 2, col + 2)
            selection.select(sel, sel)
        self.tableview.selectionModel().select(
            selection, QItemSelectionModel.ClearAndSelect)

    def _learner_changed(self):
        self._update()
        self._set_selection()
        self.commit()

    def _update(self):
        def _isinvalid(x):
            return isnan(x) or isinf(x)

        # Update the displayed confusion matrix
        if self.results is not None and self.selected_learner:
            cmatrix = confusion_matrix(self.results, self.selected_learner[0])
            colsum = cmatrix.sum(axis=0)
            rowsum = cmatrix.sum(axis=1)
            n = len(cmatrix)
            diag = numpy.diag_indices(n)

            colors = cmatrix.astype(numpy.double)
            colors[diag] = 0
            if self.selected_quantity == 0:
                normalized = cmatrix.astype(numpy.int)
                formatstr = "{}"
                div = numpy.array([colors.max()])
            else:
                if self.selected_quantity == 1:
                    normalized = 100 * cmatrix / colsum
                    div = colors.max(axis=0)
                else:
                    normalized = 100 * cmatrix / rowsum[:, numpy.newaxis]
                    div = colors.max(axis=1)[:, numpy.newaxis]
                formatstr = "{:2.1f} %"
            div[div == 0] = 1
            colors /= div
            colors[diag] = normalized[diag] / normalized[diag].max()

            for i in range(n):
                for j in range(n):
                    val = normalized[i, j]
                    col_val = colors[i, j]
                    item = self._item(i + 2, j + 2)
                    item.setData(
                        "NA" if _isinvalid(val) else formatstr.format(val),
                        Qt.DisplayRole)
                    bkcolor = QColor.fromHsl(
                        [0, 240][i == j], 160,
                        255 if _isinvalid(col_val) else int(255 - 30 * col_val))
                    item.setData(QBrush(bkcolor), Qt.BackgroundRole)
                    item.setData("trbl", BorderRole)
                    item.setToolTip("actual: {}\npredicted: {}".format(
                        self.headers[i], self.headers[j]))
                    item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                    item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
                    self._set_item(i + 2, j + 2, item)

            bold_font = self.tablemodel.invisibleRootItem().font()
            bold_font.setBold(True)

            def _sum_item(value, border=""):
                item = QStandardItem()
                item.setData(value, Qt.DisplayRole)
                item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
                item.setFlags(Qt.ItemIsEnabled)
                item.setFont(bold_font)
                item.setData(border, BorderRole)
                item.setData(QColor(192, 192, 192), BorderColorRole)
                return item

            for i in range(n):
                self._set_item(n + 2, i + 2, _sum_item(int(colsum[i]), "t"))
                self._set_item(i + 2, n + 2, _sum_item(int(rowsum[i]), "l"))
            self._set_item(n + 2, n + 2, _sum_item(int(rowsum.sum())))

    def send_report(self):
        """Send report"""
        if self.results is not None and self.selected_learner:
            self.report_table(
                "Confusion matrix for {} (showing {})".
                format(self.learners[self.selected_learner[0]],
                       self.quantities[self.selected_quantity].lower()),
                self.tableview)
Ejemplo n.º 28
0
class ProgramInfoFiles(QWidget, Ui_ProgramInfoFiles):
    def __init__(self, context, update_main_ui_state, set_widget_enabled,
                 is_alive, show_upload_files_wizard, show_download_wizard):
        QWidget.__init__(self)

        self.setupUi(self)

        self.session = context.session
        self.script_manager = context.script_manager
        self.program = context.program
        self.update_main_ui_state = update_main_ui_state
        self.set_widget_enabled = set_widget_enabled
        self.is_alive = is_alive
        self.show_download_wizard = show_download_wizard
        self.bin_directory = posixpath.join(self.program.root_directory, 'bin')
        self.refresh_in_progress = False
        self.any_refresh_in_progress = False  # set from ProgramInfoMain.update_ui_state
        self.available_files = []
        self.available_directories = []
        self.folder_icon = QIcon(load_pixmap('folder-icon.png'))
        self.file_icon = QIcon(load_pixmap('file-icon.png'))
        self.tree_files_model = QStandardItemModel(self)
        self.tree_files_model_header = ['Name', 'Size', 'Last Modified']
        self.tree_files_proxy_model = FilesProxyModel(self)
        self.last_download_directory = get_home_path()

        self.tree_files_model.setHorizontalHeaderLabels(
            self.tree_files_model_header)
        self.tree_files_proxy_model.setSourceModel(self.tree_files_model)
        self.tree_files.setModel(self.tree_files_model)
        self.tree_files.setModel(self.tree_files_proxy_model)
        self.tree_files.setColumnWidth(0, 210)
        self.tree_files.setColumnWidth(1, 85)

        self.tree_files.selectionModel().selectionChanged.connect(
            self.update_ui_state)
        self.tree_files.activated.connect(self.rename_activated_file)
        self.button_upload_files.clicked.connect(show_upload_files_wizard)
        self.button_download_files.clicked.connect(
            self.download_selected_files)
        self.button_rename_file.clicked.connect(self.rename_selected_file)
        self.button_delete_files.clicked.connect(self.delete_selected_files)

        self.label_error.setVisible(False)

    def update_ui_state(self):
        selection_count = len(self.tree_files.selectionModel().selectedRows())

        self.set_widget_enabled(self.button_upload_files,
                                not self.any_refresh_in_progress)
        self.set_widget_enabled(
            self.button_download_files, not self.any_refresh_in_progress
            and selection_count > 0)
        self.set_widget_enabled(
            self.button_rename_file, not self.any_refresh_in_progress
            and selection_count == 1)
        self.set_widget_enabled(
            self.button_delete_files, not self.any_refresh_in_progress
            and selection_count > 0)

    def close_all_dialogs(self):
        pass

    def refresh_files_done(self):
        self.refresh_in_progress = False
        self.update_main_ui_state()

    def refresh_files(self):
        def cb_walk(result):
            okay, message = check_script_result(result, decode_stderr=True)

            if not okay:
                self.label_error.setText('<b>Error:</b> ' + Qt.escape(message))
                self.label_error.setVisible(True)
                self.refresh_files_done()
                return

            self.label_error.setVisible(False)

            def expand_async(data):
                try:
                    walk = json.loads(
                        zlib.decompress(buffer(data)).decode('utf-8'))
                except:
                    walk = None

                if walk == None or not isinstance(walk, dict):
                    available_files = []
                    available_directories = []
                    walk = None
                else:
                    available_files, available_directories = expand_walk_to_lists(
                        walk)

                return walk, available_files, available_directories

            def cb_expand_success(result):
                walk, available_files, available_directories = result

                self.available_files = available_files
                self.available_directories = available_directories

                if walk != None:
                    expand_walk_to_model(walk, self.tree_files_model,
                                         self.folder_icon, self.file_icon)
                else:
                    self.label_error.setText(
                        '<b>Error:</b> Received invalid data')
                    self.label_error.setVisible(True)

                self.tree_files.header().setSortIndicator(0, Qt.AscendingOrder)
                self.refresh_files_done()

            def cb_expand_error():
                self.label_error.setText('<b>Error:</b> Internal async error')
                self.label_error.setVisible(True)
                self.refresh_files_done()

            async_call(expand_async, result.stdout, cb_expand_success,
                       cb_expand_error)

        self.refresh_in_progress = True
        self.update_main_ui_state()

        width1 = self.tree_files.columnWidth(0)
        width2 = self.tree_files.columnWidth(1)

        self.tree_files_model.clear()
        self.tree_files_model.setHorizontalHeaderLabels(
            self.tree_files_model_header)
        self.tree_files.setColumnWidth(0, width1)
        self.tree_files.setColumnWidth(1, width2)

        self.script_manager.execute_script('walk',
                                           cb_walk, [self.bin_directory],
                                           max_length=1024 * 1024,
                                           decode_output_as_utf8=False)

    def get_directly_selected_name_items(self):
        selected_indexes = self.tree_files.selectedIndexes()
        selected_name_items = []

        for selected_index in selected_indexes:
            if selected_index.column() == 0:
                mapped_index = self.tree_files_proxy_model.mapToSource(
                    selected_index)
                selected_name_items.append(
                    self.tree_files_model.itemFromIndex(mapped_index))

        return selected_name_items

    def download_selected_files(self):
        selected_name_items = self.get_directly_selected_name_items()

        if len(selected_name_items) == 0:
            return

        downloads = []

        def expand(name_item):
            item_type = name_item.data(USER_ROLE_ITEM_TYPE)

            if item_type == ITEM_TYPE_DIRECTORY:
                for i in range(name_item.rowCount()):
                    expand(name_item.child(i, 0))
            elif item_type == ITEM_TYPE_FILE:
                filename = get_full_item_path(name_item)

                downloads.append(
                    Download(filename, QDir.toNativeSeparators(filename)))

        for selected_name_item in selected_name_items:
            expand(selected_name_item)

        if len(downloads) == 0:
            return

        download_directory = get_existing_directory(
            get_main_window(), 'Download Files', self.last_download_directory)

        if len(download_directory) == 0:
            return

        self.last_download_directory = download_directory

        self.show_download_wizard('files', download_directory, downloads)

    def rename_activated_file(self, index):
        if index.column() == 0 and not self.any_refresh_in_progress:
            mapped_index = self.tree_files_proxy_model.mapToSource(index)
            name_item = self.tree_files_model.itemFromIndex(mapped_index)
            item_type = name_item.data(USER_ROLE_ITEM_TYPE)

            # only rename files via activation, because directories are expanded
            if item_type == ITEM_TYPE_FILE:
                self.rename_item(name_item)

    def rename_selected_file(self):
        selection_count = len(self.tree_files.selectionModel().selectedRows())

        if selection_count != 1:
            return

        selected_name_items = self.get_directly_selected_name_items()

        if len(selected_name_items) != 1:
            return

        self.rename_item(selected_name_items[0])

    def rename_item(self, name_item):
        item_type = name_item.data(USER_ROLE_ITEM_TYPE)

        if item_type == ITEM_TYPE_FILE:
            title = 'Rename File'
            type_name = 'file'
        else:
            title = 'Rename Directory'
            type_name = 'directory'

        old_name = name_item.text()

        # get new name
        dialog = ExpandingInputDialog(get_main_window())
        dialog.setModal(True)
        dialog.setWindowTitle(title)
        dialog.setLabelText('Enter new {0} name:'.format(type_name))
        dialog.setInputMode(QInputDialog.TextInput)
        dialog.setTextValue(old_name)
        dialog.setOkButtonText('Rename')

        if dialog.exec_() != QDialog.Accepted:
            return

        new_name = dialog.textValue()

        if new_name == old_name:
            return

        # check that new name is valid
        if len(
                new_name
        ) == 0 or new_name == '.' or new_name == '..' or '/' in new_name:
            QMessageBox.critical(
                get_main_window(), title + ' Error',
                'A {0} name cannot be empty, cannot be one dot [.], cannot be two dots [..] and cannot contain a forward slash [/].'
                .format(type_name))
            return

        # check that new name is not already in use
        name_item_parent = name_item.parent()

        if name_item_parent == None:
            name_item_parent = self.tree_files_model.invisibleRootItem()

        for i in range(name_item_parent.rowCount()):
            if new_name == name_item_parent.child(i).text():
                QMessageBox.critical(
                    get_main_window(), title + ' Error',
                    'The new {0} name is already in use.'.format(type_name))
                return

        absolute_old_name = posixpath.join(self.bin_directory,
                                           get_full_item_path(name_item))
        absolute_new_name = posixpath.join(
            posixpath.split(absolute_old_name)[0], new_name)

        def cb_rename(result):
            if not report_script_result(
                    result, title + ' Error',
                    u'Could not rename {0}'.format(type_name)):
                return

            name_item.setText(new_name)

            if self.tree_files.header().sortIndicatorSection() == 0:
                self.tree_files.header().setSortIndicator(
                    0,
                    self.tree_files.header().sortIndicatorOrder())

        self.script_manager.execute_script(
            'rename', cb_rename, [absolute_old_name, absolute_new_name])

    def delete_selected_files(self):
        button = QMessageBox.question(
            get_main_window(), 'Delete Files',
            'Irreversibly deleting selected files and directories.',
            QMessageBox.Ok, QMessageBox.Cancel)

        if not self.is_alive() or button != QMessageBox.Ok:
            return

        selected_name_items = set(self.get_directly_selected_name_items())

        if len(selected_name_items) == 0:
            return

        script_instance_ref = [None]

        def progress_canceled():
            script_instance = script_instance_ref[0]

            if script_instance == None:
                return

            self.script_manager.abort_script(script_instance)

        progress = ExpandingProgressDialog(self)
        progress.set_progress_text_visible(False)
        progress.setModal(True)
        progress.setWindowTitle('Delete Files')
        progress.setLabelText('Collecting files and directories to delete')
        progress.setRange(0, 0)
        progress.canceled.connect(progress_canceled)
        progress.show()

        files_to_delete = []
        dirs_to_delete = []
        all_done = False

        while not all_done:
            all_done = True

            for selected_name_item in list(selected_name_items):
                item_done = False
                parent = selected_name_item.parent()

                while not item_done and parent != None:
                    if parent in selected_name_items:
                        selected_name_items.remove(selected_name_item)
                        item_done = True
                    else:
                        parent = parent.parent()

                if item_done:
                    all_done = False
                    break

        for selected_name_item in selected_name_items:
            path = get_full_item_path(selected_name_item)
            item_type = selected_name_item.data(USER_ROLE_ITEM_TYPE)

            if item_type == ITEM_TYPE_DIRECTORY:
                dirs_to_delete.append(posixpath.join(self.bin_directory, path))
            else:
                files_to_delete.append(posixpath.join(self.bin_directory,
                                                      path))

        message = 'Deleting '

        if len(files_to_delete) == 1:
            message += '1 file '
        elif len(files_to_delete) > 1:
            message += '{0} files '.format(len(files_to_delete))

        if len(dirs_to_delete) == 1:
            if len(files_to_delete) > 0:
                message += 'and '

            message += '1 directory'
        elif len(dirs_to_delete) > 1:
            if len(files_to_delete) > 0:
                message += 'and '

            message += '{0} directories'.format(len(dirs_to_delete))

        progress.setLabelText(message)

        def cb_delete(result):
            script_instance = script_instance_ref[0]

            if script_instance != None:
                aborted = script_instance.abort
            else:
                aborted = False

            script_instance_ref[0] = None

            progress.cancel()
            self.refresh_files()

            if aborted:
                QMessageBox.information(get_main_window(), 'Delete Files',
                                        u'Delete operation was aborted.')
                return

            report_script_result(
                result, 'Delete Files Error',
                'Could not delete selected files/directories:')

        script_instance_ref[0] = self.script_manager.execute_script(
            'delete',
            cb_delete,
            [json.dumps(files_to_delete),
             json.dumps(dirs_to_delete)],
            execute_as_user=True)
Ejemplo n.º 29
0
class ConfigManagerDialog(ui_configmanager.Ui_ProjectInstallerDialog, QDialog):
    def __init__(self, parent=None):
        super(ConfigManagerDialog, self).__init__(parent)
        self.setupUi(self)
        self.bar = roam.messagebaritems.MessageBar(self)
        self.projectwidget.bar = self.bar

        self.treemodel = QStandardItemModel()
        self.projectList.setModel(self.treemodel)
        self.projectList.setHeaderHidden(True)

        self.projectList.selectionModel().currentChanged.connect(self.nodeselected)

        self.projectwidget.adjustSize()
        self.setWindowFlags(Qt.Window)

        self.newProjectButton.pressed.connect(self.newproject)
        self.removeProjectButton.pressed.connect(self.deletebuttonpressed)
        self.projectwidget.projectupdated.connect(self.projectupdated)
        self.projectwidget.projectsaved.connect(self.projectupdated)
        self.projectwidget.projectloaded.connect(self.updateformsnode)
        self.projectwidget.selectlayersupdated.connect(self.updateformsnode)

        self.projectwidget.setaboutinfo()
        self.projectwidget.projects_page.newproject.connect(self.newproject)
        self.projectwidget.projects_page.projectlocationchanged.connect(self.loadprojects)
        self.setuprootitems()

    def updateformsnode(self, *args):
        haslayers = self.projectwidget.checkcapturelayers()
        index = self.projectList.currentIndex()
        node = index.data(Qt.UserRole)
        if node.nodetype == Treenode.FormsNode:
            self.newProjectButton.setEnabled(haslayers)

    def raiseerror(self, *exinfo):
        info = traceback.format_exception(*exinfo)
        self.bar.pushError('Seems something has gone wrong. Press for more details',
                                  info)

    def setuprootitems(self):
        rootitem = self.treemodel.invisibleRootItem()
        self.roamnode = RoamNode()
        rootitem.appendRow(self.roamnode)

        self.projectsnode = ProjectsNode(folder=None)
        rootitem.appendRow(self.projectsnode)

    def newproject(self):
        index = self.projectList.currentIndex()
        node = index.data(Qt.UserRole)
        if node and node.canadd:
            try:
                item = node.additem()
            except ValueError:
                return
            newindex = self.treemodel.indexFromItem(item)
            self.projectList.setCurrentIndex(newindex)

    def deletebuttonpressed(self):
        index = self.projectList.currentIndex()
        node = index.data(Qt.UserRole)
        if node.type() == Treenode.ProjectNode:
            self.projectwidget._closeqgisproject()

        title, removemessage = node.removemessage
        delete = node.canremove
        if node.canremove and removemessage:
            button = QMessageBox.warning(self, title, removemessage, QMessageBox.Yes | QMessageBox.No)
            delete = button == QMessageBox.Yes

        if delete:
            parentindex = index.parent()
            newindex = self.treemodel.index(index.row(), 0, parentindex)
            if parentindex.isValid():
                parent = parentindex.data(Qt.UserRole)
                parent.delete(index.row())

            self.projectList.setCurrentIndex(newindex)

    def addprojectfolders(self, folders):
        self.projectwidget.projects_page.setprojectfolders(folders)

    def loadprojects(self, projectpath):
        projects = roam.project.getProjects([projectpath])
        self.projectsnode.loadprojects(projects, projectsbase=projectpath)

        index = self.treemodel.indexFromItem(self.projectsnode)
        self.projectList.setCurrentIndex(index)
        self.projectList.expand(index)

    def nodeselected(self, index, _):
        node = index.data(Qt.UserRole)
        if node is None:
            return

        self.projectwidget.setpage(node.page)
        self.removeProjectButton.setEnabled(node.canremove)
        self.newProjectButton.setEnabled(node.canadd)
        #self.newProjectButton.setText(node.addtext)
        #self.removeProjectButton.setText(node.removetext)

        project = node.project
        if project and not self.projectwidget.project == project:
            # Only load the project if it's different the current one.
            self.projectwidget.setproject(project)

            validateresults = list(project.validate())
            if validateresults:
                text = "Here are some reasons we found: \n\n"
                for message in validateresults:
                    text += "- {} \n".format(message)

                self.projectwidget.reasons_label.setText(text)

        if node.nodetype == Treenode.FormNode:
            self.projectwidget.setform(node.form)
        elif node.nodetype == Treenode.RoamNode:
            self.projectwidget.projectlabel.setText("IntraMaps Roam Config Manager")
        elif node.nodetype == Treenode.MapNode:
            self.projectwidget.loadmap()
        elif node.nodetype == Treenode.FormsNode:
            haslayers = self.projectwidget.checkcapturelayers()
            self.newProjectButton.setEnabled(haslayers)


        self.projectwidget.projectbuttonframe.setVisible(not project is None)

    def projectupdated(self):
        index = self.projectList.currentIndex()
        self.treemodel.dataChanged.emit(index, index)
Ejemplo n.º 30
0
class SetupDialog(QDialog, Ui_SetupDialog):
    """
        Function and Event handling class for the Ui_SetupDialog.
    """
    def __init__(self, parent):
        QDialog.__init__(self, parent)

        self._gui_logger = GUILogger("GUILogger", logging.INFO)
        self._gui_job = None
        EventLogger.add_logger(self._gui_logger)

        # FIXME better way to find interval and uids in tree_widget?!
        self.__tree_interval_tooltip = "Update interval in seconds"
        self.__tree_uid_tooltip = "UID cannot be empty"
        self.data_logger_thread = None
        self.tab_debug_warning = False

        self.device_dialog = None

        self.host_infos = None
        self.last_host = None
        self.host_index_changing = None

        self.setupUi(self)

        self.model_data = QStandardItemModel(self)
        self.model_data.setHorizontalHeaderLabels(
            ['Time', 'Name', 'UID', 'Var', 'Raw', 'Unit'])
        self.table_data.setModel(self.model_data)
        self.table_data.setColumnWidth(0, 160)
        self.table_data.setColumnWidth(1, 170)
        self.table_data.setColumnWidth(2, 50)
        self.table_data.setColumnWidth(3, 110)
        self.table_data.setColumnWidth(4, 70)
        self.table_data.setColumnWidth(5, 100)

        self.model_devices = QStandardItemModel(self)
        self.model_devices.setHorizontalHeaderLabels(['Device', 'Value'])
        self.tree_devices.setModel(self.model_devices)
        self.tree_devices.setColumnWidth(0, 300)

        self.widget_initialization()

        self.btn_start_logging.setIcon(
            QIcon(load_pixmap('data_logger/start-icon.png')))

        timestamp = int(time.time())
        self.edit_csv_file_name.setText(
            os.path.join(get_home_path(),
                         'logger_data_{0}.csv'.format(timestamp)))
        self.edit_log_file_name.setText(
            os.path.join(get_home_path(),
                         'logger_debug_{0}.log'.format(timestamp)))

        self.combo_data_time_format.addItem(
            utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de')
        self.combo_data_time_format.addItem(
            utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us')
        self.combo_data_time_format.addItem(
            utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso')
        self.combo_data_time_format.addItem(
            utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix')

        self.combo_debug_time_format.addItem(
            utils.timestamp_to_de(timestamp) + ' (DD.MM.YYYY HH:MM:SS)', 'de')
        self.combo_debug_time_format.addItem(
            utils.timestamp_to_us(timestamp) + ' (MM/DD/YYYY HH:MM:SS)', 'us')
        self.combo_debug_time_format.addItem(
            utils.timestamp_to_iso(timestamp) + ' (ISO 8601)', 'iso')
        self.combo_debug_time_format.addItem(
            utils.timestamp_to_unix(timestamp) + ' (Unix)', 'unix')

        self.combo_log_level.addItem('Debug', 'debug')
        self.combo_log_level.addItem('Info', 'info')
        self.combo_log_level.addItem('Warning', 'warning')
        self.combo_log_level.addItem('Error', 'error')
        self.combo_log_level.addItem('Critical', 'critical')
        self.combo_log_level.setCurrentIndex(0)  # debug

        self.combo_debug_level.addItem('Debug', logging.DEBUG)
        self.combo_debug_level.addItem('Info', logging.INFO)
        self.combo_debug_level.addItem('Warning', logging.WARNING)
        self.combo_debug_level.addItem('Error', logging.ERROR)
        self.combo_debug_level.addItem('Critical', logging.CRITICAL)
        self.combo_debug_level.setCurrentIndex(1)  # info

        self.update_ui_state()

    def update_ui_state(self):
        data_to_csv_file = self.check_data_to_csv_file.isChecked()
        debug_to_log_file = self.check_debug_to_log_file.isChecked()

        self.label_csv_file_name.setVisible(data_to_csv_file)
        self.edit_csv_file_name.setVisible(data_to_csv_file)
        self.btn_browse_csv_file_name.setVisible(data_to_csv_file)

        self.label_log_file_name.setVisible(debug_to_log_file)
        self.edit_log_file_name.setVisible(debug_to_log_file)
        self.btn_browse_log_file_name.setVisible(debug_to_log_file)
        self.label_log_level.setVisible(debug_to_log_file)
        self.combo_log_level.setVisible(debug_to_log_file)

    def widget_initialization(self):
        """
            Sets default values for some widgets
        """
        # Login data
        self.host_info_initialization()

        self.signal_initialization()

    def signal_initialization(self):
        """
            Init of all important Signals and connections.
        """
        # Buttons
        self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked)
        self.btn_save_config.clicked.connect(self.btn_save_config_clicked)
        self.btn_load_config.clicked.connect(self.btn_load_config_clicked)
        self.check_data_to_csv_file.stateChanged.connect(self.update_ui_state)
        self.check_debug_to_log_file.stateChanged.connect(self.update_ui_state)
        self.btn_browse_csv_file_name.clicked.connect(
            self.btn_browse_csv_file_name_clicked)
        self.btn_browse_log_file_name.clicked.connect(
            self.btn_browse_log_file_name_clicked)
        self.btn_clear_debug.clicked.connect(self.btn_clear_debug_clicked)
        self.combo_debug_level.currentIndexChanged.connect(
            self.combo_debug_level_changed)
        self.btn_add_device.clicked.connect(self.btn_add_device_clicked)
        self.btn_remove_device.clicked.connect(self.btn_remove_device_clicked)
        self.btn_remove_all_devices.clicked.connect(
            self.btn_remove_all_devices_clicked)

        self.tab_widget.currentChanged.connect(self.tab_reset_warning)
        self.btn_clear_data.clicked.connect(self.btn_clear_data_clicked)

        self.connect(self._gui_logger,
                     QtCore.SIGNAL(GUILogger.SIGNAL_NEW_MESSAGE),
                     self.add_debug_message)
        self.connect(self._gui_logger,
                     QtCore.SIGNAL(GUILogger.SIGNAL_NEW_MESSAGE_TAB_HIGHLIGHT),
                     self.highlight_debug_tab)

        self.combo_host.currentIndexChanged.connect(self._host_index_changed)
        self.spin_port.valueChanged.connect(self._port_changed)

    def host_info_initialization(self):
        """
            initialize host by getting information out of brickv.config
        """
        self.host_infos = config.get_host_infos(config.HOST_INFO_COUNT)
        self.host_index_changing = True

        for host_info in self.host_infos:
            self.combo_host.addItem(host_info.host)

        self.last_host = None
        self.combo_host.setCurrentIndex(0)
        self.spin_port.setValue(self.host_infos[0].port)
        self.host_index_changing = False

    def btn_start_logging_clicked(self):
        """
            Start/Stop of the logging process
        """
        if (self.data_logger_thread
                is not None) and (not self.data_logger_thread.stopped):
            self.btn_start_logging.clicked.disconnect()

            self.data_logger_thread.stop()
            self._reset_stop()

        elif self.data_logger_thread is None:
            from brickv.data_logger import main

            self._gui_job = GuiDataJob(name="GuiData-Writer")
            self.connect(self._gui_job,
                         QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA),
                         self.table_add_row)

            self.data_logger_thread = main.main(
                None, GuiConfigHandler.create_config(self), self._gui_job)

            if self.data_logger_thread is not None:
                self.btn_start_logging.setText("Stop Logging")
                self.btn_start_logging.setIcon(
                    QIcon(load_pixmap('data_logger/stop-icon.png')))
                self.tab_devices.setEnabled(False)
                self.tab_setup.setEnabled(False)
                self.tab_widget.setCurrentIndex(
                    self.tab_widget.indexOf(self.tab_data))
                self.tab_reset_warning()

    def _reset_stop(self):
        self.tab_devices.setEnabled(True)
        self.tab_setup.setEnabled(True)
        self.btn_start_logging.setText("Start Logging")
        self.btn_start_logging.setIcon(
            QIcon(load_pixmap('data_logger/start-icon.png')))

        self.disconnect(self._gui_job,
                        QtCore.SIGNAL(GuiDataJob.SIGNAL_NEW_DATA),
                        self.table_add_row)
        self.data_logger_thread = None
        self._gui_job = None

        self.btn_start_logging.clicked.connect(self.btn_start_logging_clicked)

    def btn_save_config_clicked(self):
        filename = get_save_file_name(get_main_window(), 'Save Config',
                                      get_home_path(), 'JSON Files (*.json)')

        if len(filename) == 0:
            return

        if not filename.lower().endswith('.json'):
            filename += '.json'

        config = GuiConfigHandler.create_config(self)

        if not save_config(config, filename):
            QMessageBox.warning(
                get_main_window(), 'Save Config',
                'Could not save config to file! See Debug tab for details.',
                QMessageBox.Ok)

    def btn_load_config_clicked(self):
        filename = get_open_file_name(get_main_window(), 'Load Config',
                                      get_home_path(), 'JSON Files (*.json)')

        if len(filename) == 0:
            return

        config = load_and_validate_config(filename)

        if config == None:
            QMessageBox.warning(
                get_main_window(), 'Load Config',
                'Could not load config from file! See Debug tab for details.',
                QMessageBox.Ok)
            return

        self.update_setup_tab(config)
        self.update_devices_tab(config)

    def btn_browse_csv_file_name_clicked(self):
        if len(self.edit_csv_file_name.text()) > 0:
            last_dir = os.path.dirname(
                os.path.realpath(self.edit_csv_file_name.text()))
        else:
            last_dir = get_home_path()

        filename = get_save_file_name(get_main_window(), 'Choose CSV File',
                                      last_dir, "CSV Files (*.csv)")

        if len(filename) > 0:
            if not filename.lower().endswith('.csv'):
                filename += '.csv'

            self.edit_csv_file_name.setText(filename)

    def btn_browse_log_file_name_clicked(self):
        if len(self.edit_log_file_name.text()) > 0:
            last_dir = os.path.dirname(
                os.path.realpath(self.edit_log_file_name.text()))
        else:
            last_dir = get_home_path()

        filename = get_save_file_name(get_main_window(), 'Choose Log File',
                                      last_dir, "Log Files (*.log)")

        if len(filename) > 0:
            if not filename.lower().endswith('.log'):
                filename += '.log'

            self.edit_log_file_name.setText(filename)

    def btn_add_device_clicked(self):
        """
            Opens the DeviceDialog in Add-Mode.
        """
        if self.device_dialog is None:
            self.device_dialog = DeviceDialog(self)

        self.device_dialog.btn_refresh_clicked()
        self.device_dialog.show()

    def btn_remove_device_clicked(self):
        selection = self.tree_devices.selectionModel().selectedIndexes()

        while len(selection) > 0:
            index = selection[0]

            while index.parent() != self.model_devices.invisibleRootItem(
            ).index():
                index = index.parent()

            self.model_devices.removeRows(index.row(), 1)

            # get new selection, because row removal might invalid indices
            selection = self.tree_devices.selectionModel().selectedIndexes()

    def btn_remove_all_devices_clicked(self):
        self.model_devices.removeRows(0, self.model_devices.rowCount())

    def btn_clear_data_clicked(self):
        self.model_data.removeRows(0, self.model_data.rowCount())

    def tab_reset_warning(self):
        """
            Resets the Warning @ the debug tab.
        """
        if not self.tab_debug_warning or self.tab_widget.currentWidget(
        ).objectName() != self.tab_debug.objectName():
            return

        self.tab_debug_warning = False

        self.tab_set(self.tab_widget.indexOf(self.tab_debug),
                     self.palette().color(QPalette.WindowText), None)

    def combo_debug_level_changed(self):
        """
            Changes the log level dynamically.
        """
        self._gui_logger.level = self.combo_debug_level.itemData(
            self.combo_debug_level.currentIndex())

    def tab_set(self, tab_index, color, icon=None):
        """
            Sets the font Color and an icon, if given, at a specific tab.
        """
        from PyQt4.QtGui import QIcon

        self.tab_widget.tabBar().setTabTextColor(tab_index, color)
        if icon is not None:
            self.tab_widget.setTabIcon(tab_index, QIcon(icon))
        else:
            self.tab_widget.setTabIcon(tab_index, QIcon())

    def _host_index_changed(self, i):
        """
            Persists host information changes like in brickv.mainwindow
            Changes port if the host was changed
        """
        if i < 0:
            return

        self.host_index_changing = True
        self.spin_port.setValue(self.host_infos[i].port)
        self.host_index_changing = False

    def _port_changed(self, value):
        """
            Persists host information changes like in brickv.mainwindow
        """
        if self.host_index_changing:
            return

        i = self.combo_host.currentIndex()
        if i < 0:
            return

        self.host_infos[i].port = self.spin_port.value()

    def update_setup_tab(self, config):
        EventLogger.debug('Updating setup tab from config')

        self.combo_host.setEditText(config['hosts']['default']['name'])
        self.spin_port.setValue(config['hosts']['default']['port'])

        self.combo_data_time_format.setCurrentIndex(
            max(
                self.combo_data_time_format.findData(
                    config['data']['time_format']), 0))
        self.check_data_to_csv_file.setChecked(
            config['data']['csv']['enabled'])
        self.edit_csv_file_name.setText(
            config['data']['csv']['file_name'].decode('utf-8'))

        self.combo_debug_time_format.setCurrentIndex(
            max(
                self.combo_debug_time_format.findData(
                    config['debug']['time_format']), 0))
        self.check_debug_to_log_file.setChecked(
            config['debug']['log']['enabled'])
        self.edit_log_file_name.setText(
            config['debug']['log']['file_name'].decode('utf-8'))
        self.combo_log_level.setCurrentIndex(
            max(
                self.combo_debug_time_format.findData(
                    config['debug']['log']['level']), 0))

    def update_devices_tab(self, config):
        EventLogger.debug('Updating devices tab from config')

        self.model_devices.removeRows(0, self.model_data.rowCount())

        for device in config['devices']:
            self.add_device_to_tree(device)

    def add_device_to_tree(self, device):
        # check if device is already added
        if len(device['uid']) > 0:
            for row in range(self.model_devices.rowCount()):
                existing_name = self.model_devices.item(row, 0).text()
                exisitng_uid = self.tree_devices.indexWidget(
                    self.model_devices.item(row, 1).index()).text()

                if device['name'] == existing_name and device[
                        'uid'] == exisitng_uid:
                    EventLogger.info(
                        'Ignoring duplicate device "{0}" with UID "{1}"'.
                        format(device['name'], device['uid']))
                    return

        # add device
        name_item = QStandardItem(device['name'])
        uid_item = QStandardItem('')

        self.model_devices.appendRow([name_item, uid_item])

        edit_uid = QLineEdit()
        edit_uid.setPlaceholderText('Enter UID')
        edit_uid.setValidator(
            QRegExpValidator(QRegExp(
                '^[{0}]{{1,6}}$'.format(BASE58))))  # FIXME: use stricter logic
        edit_uid.setText(device['uid'])

        self.tree_devices.setIndexWidget(uid_item.index(), edit_uid)

        value_specs = device_specs[device['name']]['values']
        parent_item = QStandardItem('Values')

        name_item.appendRow([parent_item, QStandardItem('')])
        self.tree_devices.expand(parent_item.index())

        # add values
        for value_spec in value_specs:
            value_name_item = QStandardItem(value_spec['name'])
            value_interval_item = QStandardItem('')

            parent_item.appendRow([value_name_item, value_interval_item])

            spinbox_interval = QSpinBox()
            spinbox_interval.setRange(0, (1 << 31) - 1)
            spinbox_interval.setSingleStep(1)
            spinbox_interval.setValue(
                device['values'][value_spec['name']]['interval'])
            spinbox_interval.setSuffix(' seconds')

            self.tree_devices.setIndexWidget(value_interval_item.index(),
                                             spinbox_interval)

            if value_spec['subvalues'] != None:
                for subvalue_name in value_spec['subvalues']:
                    subvalue_name_item = QStandardItem(subvalue_name)
                    subvalue_check_item = QStandardItem('')

                    value_name_item.appendRow(
                        [subvalue_name_item, subvalue_check_item])

                    check_subvalue = QCheckBox()
                    check_subvalue.setChecked(device['values'][
                        value_spec['name']]['subvalues'][subvalue_name])

                    self.tree_devices.setIndexWidget(
                        subvalue_check_item.index(), check_subvalue)

        self.tree_devices.expand(name_item.index())

        # add options
        option_specs = device_specs[device['name']]['options']

        if option_specs != None:
            parent_item = QStandardItem('Options')

            name_item.appendRow([parent_item, QStandardItem('')])

            for option_spec in option_specs:
                option_name_item = QStandardItem(option_spec['name'])
                option_widget_item = QStandardItem('')

                parent_item.appendRow([option_name_item, option_widget_item])

                if option_spec['type'] == 'choice':
                    widget_option_value = QComboBox()

                    for option_value_spec in option_spec['values']:
                        widget_option_value.addItem(
                            option_value_spec[0].decode('utf-8'),
                            option_value_spec[1])

                    widget_option_value.setCurrentIndex(
                        widget_option_value.findText(device['options'][
                            option_spec['name']]['value'].decode('utf-8')))
                elif option_spec['type'] == 'int':
                    widget_option_value = QSpinBox()
                    widget_option_value.setRange(option_spec['minimum'],
                                                 option_spec['maximum'])
                    widget_option_value.setSuffix(option_spec['suffix'])
                    widget_option_value.setValue(
                        device['options'][option_spec['name']]['value'])
                elif option_spec['type'] == 'bool':
                    widget_option_value = QCheckBox()
                    widget_option_value.setChecked(
                        device['options'][option_spec['name']]['value'])

                self.tree_devices.setIndexWidget(option_widget_item.index(),
                                                 widget_option_value)

    def add_debug_message(self, message):
        self.text_debug.append(message)

        while self.text_debug.document().blockCount() > 1000:
            cursor = QTextCursor(self.text_debug.document().begin())
            cursor.select(QTextCursor.BlockUnderCursor)
            cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)
            cursor.removeSelectedText()

        if self.checkbox_debug_auto_scroll.isChecked():
            self.text_debug.verticalScrollBar().setValue(
                self.text_debug.verticalScrollBar().maximum())

    def btn_clear_debug_clicked(self):
        self.text_debug.clear()

    def highlight_debug_tab(self):
        """
            SIGNAL function:
            Highlight the debug tab when an error occurs.
        """
        if not self.tab_debug_warning and self.tab_widget.currentWidget(
        ).objectName() != self.tab_debug.objectName():
            self.tab_debug_warning = True
            self.tab_set(
                self.tab_widget.indexOf(self.tab_debug), QColor(255, 0, 0),
                os.path.join(get_resources_path(), "warning-icon.png"))

    def table_add_row(self, csv_data):
        """
            SIGNAL function:
            Adds new CSV Data into the Table.
        """
        rows = self.model_data.rowCount()

        while rows >= 1000:
            self.model_data.removeRow(0)
            rows = self.model_data.rowCount()

        row_number = None

        if rows > 0:
            try:
                row_number = int(
                    self.model_data.headerData(rows - 1, Qt.Vertical))
            except ValueError:
                pass

        self.model_data.appendRow([
            QStandardItem(csv_data.timestamp),
            QStandardItem(csv_data.name),
            QStandardItem(csv_data.uid),
            QStandardItem(csv_data.var_name),
            QStandardItem(str(csv_data.raw_data)),
            QStandardItem(csv_data.var_unit.decode('utf-8'))
        ])

        if row_number != None:
            self.model_data.setHeaderData(rows, Qt.Vertical,
                                          str(row_number + 1))

        if self.checkbox_data_auto_scroll.isChecked():
            self.table_data.scrollToBottom()
Ejemplo n.º 31
0
class ConfigDialog(BASE, WIDGET):

    def __init__(self, toolbox):
        super(ConfigDialog, self).__init__(None)
        self.setupUi(self)

        self.toolbox = toolbox
        self.groupIcon = QIcon()
        self.groupIcon.addPixmap(self.style().standardPixmap(
            QStyle.SP_DirClosedIcon), QIcon.Normal, QIcon.Off)
        self.groupIcon.addPixmap(self.style().standardPixmap(
            QStyle.SP_DirOpenIcon), QIcon.Normal, QIcon.On)

        if hasattr(self.searchBox, 'setPlaceholderText'):
            self.searchBox.setPlaceholderText(self.tr('Search...'))

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

        self.delegate = SettingDelegate()
        self.tree.setItemDelegateForColumn(1, self.delegate)

        self.searchBox.textChanged.connect(self.fillTree)

        self.fillTree()

        self.tree.expanded.connect(self.adjustColumns)

    def fillTree(self):
        self.items = {}
        self.model.clear()
        self.model.setHorizontalHeaderLabels([self.tr('Setting'),
                                              self.tr('Value')])

        text = unicode(self.searchBox.text())
        settings = ProcessingConfig.getSettings()

        rootItem = self.model.invisibleRootItem()
        priorityKeys = [self.tr('General'), self.tr('Models'), self.tr('Scripts')]
        for group in priorityKeys:
            groupItem = QStandardItem(group)
            icon = ProcessingConfig.getGroupIcon(group)
            groupItem.setIcon(icon)
            groupItem.setEditable(False)
            emptyItem = QStandardItem()
            emptyItem.setEditable(False)
            rootItem.insertRow(0, [groupItem, emptyItem])
            for setting in settings[group]:
                if setting.hidden:
                    continue

                if text == '' or text.lower() in setting.description.lower():
                    labelItem = QStandardItem(setting.description)
                    labelItem.setIcon(icon)
                    labelItem.setEditable(False)
                    self.items[setting] = SettingItem(setting)
                    groupItem.insertRow(0, [labelItem, self.items[setting]])

            if text != '':
                self.tree.expand(groupItem.index())

        providersItem = QStandardItem(self.tr('Providers'))
        icon = QIcon(os.path.join(pluginPath, 'images', 'alg.png'))
        providersItem.setIcon(icon)
        providersItem.setEditable(False)
        emptyItem = QStandardItem()
        emptyItem.setEditable(False)
        rootItem.insertRow(0, [providersItem, emptyItem])
        for group in settings.keys():
            if group in priorityKeys:
                continue

            groupItem = QStandardItem(group)
            icon = ProcessingConfig.getGroupIcon(group)
            groupItem.setIcon(icon)
            groupItem.setEditable(False)
            for setting in settings[group]:
                if setting.hidden:
                    continue

                if text == '' or text.lower() in setting.description.lower():
                    labelItem = QStandardItem(setting.description)
                    labelItem.setIcon(icon)
                    labelItem.setEditable(False)
                    self.items[setting] = SettingItem(setting)
                    groupItem.insertRow(0, [labelItem, self.items[setting]])

            emptyItem = QStandardItem()
            emptyItem.setEditable(False)
            providersItem.appendRow([groupItem, emptyItem])

        self.tree.sortByColumn(0, Qt.AscendingOrder)
        self.adjustColumns()

    def accept(self):
        for setting in self.items.keys():
            if isinstance(setting.value, bool):
                setting.value = self.items[setting].checkState() == Qt.Checked
            elif isinstance(setting.value, (float, int, long)):
                value = unicode(self.items[setting].text())
                try:
                    value = float(value)
                    setting.value = value
                except ValueError:
                    QMessageBox.critical(self, self.tr('Wrong value'),
                                         self.tr('Wrong parameter value:\n%1') % value)
                    return
            else:
                setting.value = unicode(self.items[setting].text())
            setting.save()
        Processing.updateAlgsList()

        QDialog.accept(self)

    def adjustColumns(self):
        self.tree.resizeColumnToContents(0)
        self.tree.resizeColumnToContents(1)
Ejemplo n.º 32
0
class FrameInfoViewer(QTreeView):
    """ Main tree for frame info  """
    frame_changed = pyqtSignal(SBFrame)
    def __init__(self, parent):
        super(QTreeView, self).__init__(parent)
        self.setAutoScroll(True)
        self.source_files = {}
        self.focus_signal = None
        self.header().setResizeMode(QHeaderView.ResizeToContents)
        self._show_args = None
        self.frame_data = QStandardItemModel()
        self.setModel(self.frame_data)
        self.setAlternatingRowColors(True)
        self.top_frame = None
        self.frames = {}

    def set_focus_signal(self, signal):
        """ set callback to focus source file line"""
        self.focus_signal = signal

    def clear(self):
        """ clear the widget"""
        self.frame_data.clear()
        self.frame_data.setColumnCount(2)
        self.frame_data.setHorizontalHeaderLabels(['', ''])

    def show_frame_info(self, process):
        """ show the frame info """
        if not self.isVisible:
            return
        #TODO: no update if top frame is the same
        self.clear()
        root = self.frame_data.invisibleRootItem()
        self.source_files.clear()
        self.frames.clear()

        if process is None or not process.is_alive:
            return

        #if process.num_of_threads == 1:
        for thread in process:
            thread_name = thread.GetName()
            if not thread_name:
                thread_name = '[No Thread]'
            thread_row = QStandardItem(thread_name)
            thread_row.setEditable(False)
            thread_row.setSelectable(False)
            dummy = QStandardItem('')
            dummy.setEditable(False)
            dummy.setSelectable(False)
            root.appendRow([thread_row, dummy])
            if len(thread.frames):
                self.top_frame = thread.frames[0]
                self.frame_changed.emit(self.top_frame)
            for frame in thread.frames:
                # first show the frame on the top of call stack.
                frame_idx = '#%d: ' % frame.idx
                frame_info = ''
                selectable = False
                if frame.name:
                    frame_idx += frame.name
                    if self._show_args.isChecked():
                        args = ','.join([str(x) for x in frame.args])
                        frame_info += ' (%s)' % args
                line = frame.line_entry
                if line:
                    file_info = ' at %s:%d' % (str(line.GetFileSpec()), line.GetLine())
                    frame_info += file_info
                    selectable = True
                else:
                    frame_info += str(frame.module.GetFileSpec())
                if frame.is_inlined:
                    frame_info += ' (inlined)'
                col_idx = QStandardItem(frame_idx)
                self.source_files[col_idx] = line
                self.frames[col_idx] = frame
                col_idx.setEditable(False)
                col_idx.setSelectable(selectable)

                col_info = QStandardItem(frame_info)
                col_info.setEditable(False)
                col_info.setSelectable(selectable)

                thread_row.appendRow([col_idx, col_info])

        self.expandToDepth(1)

    def frame_up(self):
        """ set frame to one level up """
        pass

    def frame_down(self):
        """ set frame to one level down """
        pass

    def set_show_args(self, widget):
        """ set the checkbox of showing func args"""
        self._show_args = widget

    def mousePressEvent(self, event):
        """ overrided """
        idx = self.indexAt(event.pos())
        if idx.isValid() and self.focus_signal:
            model = idx.model()
            idx = idx.sibling(idx.row(), 0)
            if idx.isValid():
                item = model.itemFromIndex(idx)
                if item and item.isSelectable():
                    if item in self.source_files:
                        file_info = self.source_files[item]
                        if self.focus_signal:
                            self.focus_signal.emit(file_info.GetFileSpec().fullpath,
                                                   file_info.GetLine())
                        self.frame_changed.emit(self.frames[item])

                    else:
                        logging.error('frame cannot find associated source file')

        QTreeView.mousePressEvent(self, event)