예제 #1
0
class OWKEGGPathwayBrowser(widget.OWWidget):
    name = "KEGG Pathways"
    description = "Browse KEGG pathways that include an input set of genes."
    icon = "../widgets/icons/KEGGPathways.svg"
    priority = 2030

    inputs = [("Examples", Orange.data.Table, "SetData", widget.Default),
              ("Reference", Orange.data.Table, "SetRefData")]
    outputs = [("Selected Examples", Orange.data.Table, widget.Default),
               ("Unselected Examples", Orange.data.Table)]

    settingsHandler = settings.DomainContextHandler()

    organismIndex = settings.ContextSetting(0)
    geneAttrIndex = settings.ContextSetting(0)
    useAttrNames = settings.ContextSetting(False)

    autoCommit = settings.Setting(False)
    autoResize = settings.Setting(True)
    useReference = settings.Setting(False)
    showOrthology = settings.Setting(True)

    Ready, Initializing, Running = 0, 1, 2

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

        self.organismCodes = []
        self._changedFlag = False
        self.__invalidated = False
        self.__runstate = OWKEGGPathwayBrowser.Initializing
        self.__in_setProgress = False

        self.controlArea.setMaximumWidth(250)
        box = gui.widgetBox(self.controlArea, "Info")
        self.infoLabel = gui.widgetLabel(box, "No data on input\n")

        # Organism selection.
        box = gui.widgetBox(self.controlArea, "Organism")
        self.organismComboBox = gui.comboBox(
            box, self, "organismIndex",
            items=[],
            callback=self.Update,
            addSpace=True,
            tooltip="Select the organism of the input genes")

        # Selection of genes attribute
        box = gui.widgetBox(self.controlArea, "Gene attribute")
        self.geneAttrCandidates = itemmodels.VariableListModel(parent=self)
        self.geneAttrCombo = gui.comboBox(
            box, self, "geneAttrIndex", callback=self.Update)
        self.geneAttrCombo.setModel(self.geneAttrCandidates)

        gui.checkBox(box, self, "useAttrNames",
                    "Use variable names", disables=[(-1, self.geneAttrCombo)],
                    callback=self.Update)

        self.geneAttrCombo.setDisabled(bool(self.useAttrNames))

        gui.separator(self.controlArea)

        gui.checkBox(self.controlArea, self, "useReference",
                    "From signal", box="Reference", callback=self.Update)

        gui.separator(self.controlArea)

        gui.checkBox(self.controlArea, self, "showOrthology",
                     "Show pathways in full orthology", box="Orthology",
                     callback=self.UpdateListView)

        gui.checkBox(self.controlArea, self, "autoResize",
                     "Resize to fit", box="Image",
                     callback=self.UpdatePathwayViewTransform)

        box = gui.widgetBox(self.controlArea, "Cache Control")

        gui.button(box, self, "Clear cache",
                     callback=self.ClearCache,
                     tooltip="Clear all locally cached KEGG data.")

        gui.separator(self.controlArea)

        gui.auto_commit(self.controlArea, self, "autoCommit", "Commit")

        gui.rubber(self.controlArea)

        spliter = QSplitter(Qt.Vertical, self.mainArea)
        self.pathwayView = PathwayView(self, spliter)
        self.pathwayView.scene().selectionChanged.connect(
            self._onSelectionChanged
        )
        self.mainArea.layout().addWidget(spliter)

        self.listView = QTreeWidget(
            allColumnsShowFocus=True,
            selectionMode=QTreeWidget.SingleSelection,
            sortingEnabled=True,
            maximumHeight=200)

        spliter.addWidget(self.listView)

        self.listView.setColumnCount(4)
        self.listView.setHeaderLabels(
            ["Pathway", "P value", "Genes", "Reference"])

        self.listView.itemSelectionChanged.connect(self.UpdatePathwayView)

        select = QAction(
            "Select All", self,
            shortcut=QKeySequence.SelectAll
        )
        select.triggered.connect(self.selectAll)
        self.addAction(select)

        self.data = None
        self.refData = None

        self._executor = concurrent.ThreadExecutor()
        self.setEnabled(False)
        self.setBlocking(True)
        progress = concurrent.methodinvoke(self, "setProgress", (float,))

        def get_genome():
            """Return a KEGGGenome with the common org entries precached."""
            genome = kegg.KEGGGenome()

            essential = genome.essential_organisms()
            common = genome.common_organisms()
            # Remove duplicates of essential from common.
            # (essential + common list as defined here will be used in the
            # GUI.)
            common = [c for c in common if c not in essential]

            # TODO: Add option to specify additional organisms not
            # in the common list.

            keys = list(map(genome.org_code_to_entry_key, essential + common))

            genome.pre_cache(keys, progress_callback=progress)
            return (keys, genome)

        self._genomeTask = task = concurrent.Task(function=get_genome)
        task.finished.connect(self.__initialize_finish)

        self.progressBarInit()
        self.infoLabel.setText("Fetching organism definitions\n")
        self._executor.submit(task)

    def __initialize_finish(self):
        if self.__runstate != OWKEGGPathwayBrowser.Initializing:
            return

        try:
            keys, genome = self._genomeTask.result()
        except Exception as err:
            self.error(0, str(err))
            raise

        self.progressBarFinished()
        self.setEnabled(True)
        self.setBlocking(False)

        entries = [genome[key] for key in keys]
        items = [entry.definition for entry in entries]
        codes = [entry.organism_code for entry in entries]

        self.organismCodes = codes
        self.organismComboBox.clear()
        self.organismComboBox.addItems(items)
        self.organismComboBox.setCurrentIndex(self.organismIndex)

        self.infoLabel.setText("No data on input\n")

    def Clear(self):
        """
        Clear the widget state.
        """
        self.queryGenes = []
        self.referenceGenes = []
        self.genes = {}
        self.uniqueGenesDict = {}
        self.revUniqueGenesDict = {}
        self.pathways = {}
        self.org = None
        self.geneAttrCandidates[:] = []

        self.infoLabel.setText("No data on input\n")
        self.listView.clear()
        self.pathwayView.SetPathway(None)

        self.send("Selected Examples", None)
        self.send("Unselected Examples", None)

    def SetData(self, data=None):
        if self.__runstate == OWKEGGPathwayBrowser.Initializing:
            self.__initialize_finish()

        self.closeContext()
        self.data = data
        self.warning(0)
        self.error(0)
        self.information(0)

        if data is not None:
            vars = data.domain.variables + data.domain.metas
            vars = [var for var in vars
                    if isinstance(var, Orange.data.StringVariable)]
            self.geneAttrCandidates[:] = vars

            # Try to guess the gene name variable
            names_lower = [v.name.lower() for v in vars]
            scores = [(name == "gene", "gene" in name)
                      for name in names_lower]
            imax, _ = max(enumerate(scores), key=itemgetter(1))
            self.geneAttrIndex = imax

            taxid = data_hints.get_hint(data, "taxid", None)
            if taxid:
                try:
                    code = kegg.from_taxid(taxid)
                    self.organismIndex = self.organismCodes.index(code)
                except Exception as ex:
                    print(ex, taxid)

            self.useAttrNames = data_hints.get_hint(data, "genesinrows",
                                                    self.useAttrNames)

            self.openContext(data)
        else:
            self.Clear()

        self.__invalidated = True

    def SetRefData(self, data=None):
        self.refData = data
        self.information(1)

        if data is not None and self.useReference:
            self.__invalidated = True

    def handleNewSignals(self):
        if self.__invalidated:
            self.Update()
            self.__invalidated = False

    def UpdateListView(self):
        self.bestPValueItem = None
        self.listView.clear()
        if not self.data:
            return

        allPathways = self.org.pathways()
        allRefPathways = kegg.pathways("map")

        items = []
        kegg_pathways = kegg.KEGGPathways()

        org_code = self.organismCodes[min(self.organismIndex,
                                          len(self.organismCodes) - 1)]

        if self.showOrthology:
            self.koOrthology = kegg.KEGGBrite("ko00001")
            self.listView.setRootIsDecorated(True)
            path_ids = set([s[-5:] for s in self.pathways.keys()])

            def _walkCollect(koEntry):
                num = koEntry.title[:5] if koEntry.title else None
                if num in path_ids:
                    return ([koEntry] +
                            reduce(lambda li, c: li + _walkCollect(c),
                                   [child for child in koEntry.entries],
                                   []))
                else:
                    c = reduce(lambda li, c: li + _walkCollect(c),
                               [child for child in koEntry.entries],
                               [])
                    return c + (c and [koEntry] or [])

            allClasses = reduce(lambda li1, li2: li1 + li2,
                                [_walkCollect(c) for c in self.koOrthology],
                                [])

            def _walkCreate(koEntry, lvItem):
                item = QTreeWidgetItem(lvItem)
                id = "path:" + org_code + koEntry.title[:5]

                if koEntry.title[:5] in path_ids:
                    p = kegg_pathways.get_entry(id)
                    if p is None:
                        # In case the genesets still have obsolete entries
                        name = koEntry.title
                    else:
                        name = p.name
                    genes, p_value, ref = self.pathways[id]
                    item.setText(0, name)
                    item.setText(1, "%.5f" % p_value)
                    item.setText(2, "%i of %i" % (len(genes), len(self.genes)))
                    item.setText(3, "%i of %i" % (ref, len(self.referenceGenes)))
                    item.pathway_id = id if p is not None else None
                else:
                    if id in allPathways:
                        text = kegg_pathways.get_entry(id).name
                    else:
                        text = koEntry.title
                    item.setText(0, text)

                    if id in allPathways:
                        item.pathway_id = id
                    elif "path:map" + koEntry.title[:5] in allRefPathways:
                        item.pathway_id = "path:map" + koEntry.title[:5]
                    else:
                        item.pathway_id = None

                for child in koEntry.entries:
                    if child in allClasses:
                        _walkCreate(child, item)

            for koEntry in self.koOrthology:
                if koEntry in allClasses:
                    _walkCreate(koEntry, self.listView)

            self.listView.update()
        else:
            self.listView.setRootIsDecorated(False)
            pathways = self.pathways.items()
            pathways = sorted(pathways, key=lambda item: item[1][1])

            for id, (genes, p_value, ref) in pathways:
                item = QTreeWidgetItem(self.listView)
                item.setText(0, kegg_pathways.get_entry(id).name)
                item.setText(1, "%.5f" % p_value)
                item.setText(2, "%i of %i" % (len(genes), len(self.genes)))
                item.setText(3, "%i of %i" % (ref, len(self.referenceGenes)))
                item.pathway_id = id
                items.append(item)

        self.bestPValueItem = items and items[0] or None
        self.listView.expandAll()
        for i in range(4):
            self.listView.resizeColumnToContents(i)

        if self.bestPValueItem:
            index = self.listView.indexFromItem(self.bestPValueItem)
            self.listView.selectionModel().select(
                index, QItemSelectionModel.ClearAndSelect
            )

    def UpdatePathwayView(self):
        items = self.listView.selectedItems()

        if len(items) > 0:
            item = items[0]
        else:
            item = None

        self.commit()
        item = item or self.bestPValueItem
        if not item or not item.pathway_id:
            self.pathwayView.SetPathway(None)
            return

        def get_kgml_and_image(pathway_id):
            """Return an initialized KEGGPathway with pre-cached data"""
            p = kegg.KEGGPathway(pathway_id)
            p._get_kgml()  # makes sure the kgml file is downloaded
            p._get_image_filename()  # makes sure the image is downloaded
            return (pathway_id, p)

        self.setEnabled(False)
        self._pathwayTask = concurrent.Task(
            function=lambda: get_kgml_and_image(item.pathway_id)
        )
        self._pathwayTask.finished.connect(self._onPathwayTaskFinshed)
        self._executor.submit(self._pathwayTask)

    def _onPathwayTaskFinshed(self):
        self.setEnabled(True)
        pathway_id, self.pathway = self._pathwayTask.result()
        self.pathwayView.SetPathway(
            self.pathway,
            self.pathways.get(pathway_id, [[]])[0]
        )

    def UpdatePathwayViewTransform(self):
        self.pathwayView.updateTransform()

    def Update(self):
        """
        Update (recompute enriched pathways) the widget state.
        """
        if not self.data:
            return

        self.error(0)
        self.information(0)

        # XXX: Check data in setData, do not even alow this to be executed if
        # data has no genes
        try:
            genes = self.GeneNamesFromData(self.data)
        except ValueError:
            self.error(0, "Cannot extract gene names from input.")
            genes = []

        if not self.useAttrNames and any("," in gene for gene in genes):
            genes = reduce(add, (split_and_strip(gene, ",")
                                 for gene in genes),
                           [])
            self.information(0,
                             "Separators detected in input gene names. "
                             "Assuming multiple genes per instance.")
        self.queryGenes = genes

        self.information(1)
        reference = None
        if self.useReference and self.refData:
            reference = self.GeneNamesFromData(self.refData)
            if not self.useAttrNames \
                    and any("," in gene for gene in reference):
                reference = reduce(add, (split_and_strip(gene, ",")
                                         for gene in reference),
                                   [])
                self.information(1,
                                 "Separators detected in reference gene "
                                 "names. Assuming multiple genes per "
                                 "instance.")

        org_code = self.SelectedOrganismCode()

        def run_enrichment(org_code, genes, reference=None, progress=None):
            org = kegg.KEGGOrganism(org_code)
            if reference is None:
                reference = org.get_genes()

            # Map 'genes' and 'reference' sets to unique KEGG identifiers
            unique_genes, _, _ = org.get_unique_gene_ids(set(genes))
            unique_ref_genes, _, _ = org.get_unique_gene_ids(set(reference))

            taxid = kegg.to_taxid(org.org_code)
            # Map the taxid back to standard 'common' taxids
            # (as used by 'geneset') if applicable
            r_tax_map = dict((v, k) for k, v in
                             kegg.KEGGGenome.TAXID_MAP.items())
            if taxid in r_tax_map:
                taxid = r_tax_map[taxid]

            # We use the kegg pathway gene sets provided by 'geneset' for
            # the enrichment calculation.

            # Ensure we are using the latest genesets
            # TODO: ?? Is updating the index enough?
            serverfiles.update(geneset.sfdomain, "index.pck")
            kegg_gs_collections = geneset.collections(
                (("KEGG", "pathways"), taxid)
            )

            pathways = pathway_enrichment(
                kegg_gs_collections, unique_genes.keys(),
                unique_ref_genes.keys(),
                callback=progress
            )
            # Ensure that pathway entries are pre-cached for later use in the
            # list/tree view
            kegg_pathways = kegg.KEGGPathways()
            kegg_pathways.pre_cache(
                pathways.keys(), progress_callback=progress
            )

            return pathways, org, unique_genes, unique_ref_genes

        self.progressBarInit()
        self.setEnabled(False)
        self.infoLabel.setText("Retrieving...\n")

        progress = concurrent.methodinvoke(self, "setProgress", (float,))
        self._enrichTask = concurrent.Task(
            function=lambda:
                run_enrichment(org_code, genes, reference, progress)
        )
        self._enrichTask.finished.connect(self._onEnrichTaskFinished)
        self._executor.submit(self._enrichTask)

    def _onEnrichTaskFinished(self):
        self.setEnabled(True)
        self.setBlocking(False)
        try:
            pathways, org, unique_genes, unique_ref_genes = \
                self._enrichTask.result()
        except Exception:
            raise

        self.progressBarFinished()

        self.org = org
        self.genes = unique_genes.keys()
        self.uniqueGenesDict = unique_genes
        self.revUniqueGenesDict = dict([(val, key) for key, val in
                                        self.uniqueGenesDict.items()])
        self.referenceGenes = unique_ref_genes.keys()
        self.pathways = pathways

        if not self.pathways:
            self.warning(0, "No enriched pathways found.")
        else:
            self.warning(0)

        count = len(set(self.queryGenes))
        self.infoLabel.setText(
            "%i unique gene names on input\n"
            "%i (%.1f%%) genes names matched" %
            (count, len(unique_genes),
             100.0 * len(unique_genes) / count if count else 0.0)
        )

        self.UpdateListView()

    @Slot(float)
    def setProgress(self, value):
        if self.__in_setProgress:
            return

        self.__in_setProgress = True
        self.progressBarSet(value)
        self.__in_setProgress = False

    def GeneNamesFromData(self, data):
        """
        Extract and return gene names from `data`.
        """
        if self.useAttrNames:
            genes = [str(v.name).strip() for v in data.domain.attributes]
        elif self.geneAttrCandidates:
            index = min(self.geneAttrIndex, len(self.geneAttrCandidates) - 1)
            geneAttr = self.geneAttrCandidates[index]
            genes = [str(e[geneAttr]) for e in data
                     if not numpy.isnan(e[geneAttr])]
        else:
            raise ValueError("No gene names in data.")
        return genes

    def SelectedOrganismCode(self):
        """
        Return the selected organism code.
        """
        return self.organismCodes[min(self.organismIndex,
                                      len(self.organismCodes) - 1)]

    def selectAll(self):
        """
        Select all items in the pathway view.
        """
        changed = False
        scene = self.pathwayView.scene()
        with disconnected(scene.selectionChanged, self._onSelectionChanged):
            for item in scene.items():
                if item.flags() & QGraphicsItem.ItemIsSelectable and \
                        not item.isSelected():
                    item.setSelected(True)
                    changed = True
        if changed:
            self._onSelectionChanged()

    def _onSelectionChanged(self):
        # Item selection in the pathwayView/scene has changed
        self.commit()

    def commit(self):
        if self.data:
            selectedItems = self.pathwayView.scene().selectedItems()
            selectedGenes = reduce(set.union, [item.marked_objects
                                               for item in selectedItems],
                                   set())

            if self.useAttrNames:
                selected = [self.data.domain[self.uniqueGenesDict[gene]]
                            for gene in selectedGenes]
#                 newDomain = Orange.data.Domain(selectedVars, 0)
                data = self.data[:, selected]
#                 data = Orange.data.Table(newDomain, self.data)
                self.send("Selected Examples", data)
            elif self.geneAttrCandidates:
                geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex,
                                                       len(self.geneAttrCandidates) - 1)]
                selectedIndices = []
                otherIndices = []
                for i, ex in enumerate(self.data):
                    names = [self.revUniqueGenesDict.get(name, None)
                             for name in split_and_strip(str(ex[geneAttr]), ",")]
                    if any(name and name in selectedGenes for name in names):
                        selectedIndices.append(i)
                    else:
                        otherIndices.append(i)

                if selectedIndices:
                    selected = self.data[selectedIndices]
                else:
                    selected = None

                if otherIndices:
                    other = self.data[otherIndices]
                else:
                    other = None

                self.send("Selected Examples", selected)
                self.send("Unselected Examples", other)
        else:
            self.send("Selected Examples", None)
            self.send("Unselected Examples", None)

    def ClearCache(self):
        kegg.caching.clear_cache()

    def onDeleteWidget(self):
        """
        Called before the widget is removed from the canvas.
        """
        super().onDeleteWidget()

        self.org = None
        self._executor.shutdown(wait=False)
        gc.collect()  # Force collection (WHY?)

    def sizeHint(self):
        return QSize(1024, 720)
예제 #2
0
class OWItemsets(widget.OWWidget):
    name = 'Frequent Itemsets'
    description = 'Explore sets of items that frequently appear together.'
    icon = 'icons/FrequentItemsets.svg'
    priority = 10

    inputs = [("Data", Table, 'set_data')]
    outputs = [(Output.DATA, Table)]

    minSupport = settings.Setting(30)
    maxItemsets = settings.Setting(10000)
    filterSearch = settings.Setting(True)
    autoFind = settings.Setting(False)
    autoSend = settings.Setting(True)
    filterKeywords = settings.Setting('')
    filterMinItems = settings.Setting(1)
    filterMaxItems = settings.Setting(10000)

    UserAdviceMessages = [
        widget.Message('Itemset are listed in item-sorted order, i.e. '
                       'an itemset containing A and B is only listed once, as '
                       'A > B (and not also B > A).',
                       'itemsets-order', widget.Message.Warning),
        widget.Message('To select all the itemsets that are descendants of '
                       '(include) some item X (i.e. the whole subtree), you '
                       'can fold the subtree at that item and then select it.',
                       'itemsets-order', widget.Message.Information)
    ]

    def __init__(self):
        self.tree = QTreeWidget(self.mainArea,
                                columnCount=2,
                                allColumnsShowFocus=True,
                                alternatingRowColors=True,
                                selectionMode=QTreeWidget.ExtendedSelection,
                                uniformRowHeights=True)
        self.tree.setHeaderLabels(["Itemsets", "Support", "%"])
        self.tree.header().setStretchLastSection(True)
        self.tree.itemSelectionChanged.connect(self.selectionChanged)
        self.mainArea.layout().addWidget(self.tree)

        box = gui.widgetBox(self.controlArea, "Info")
        self.nItemsets = self.nSelectedExamples = self.nSelectedItemsets = ''
        gui.label(box, self, "Number of itemsets: %(nItemsets)s")
        gui.label(box, self, "Selected itemsets: %(nSelectedItemsets)s")
        gui.label(box, self, "Selected examples: %(nSelectedExamples)s")
        hbox = gui.widgetBox(box, orientation='horizontal')
        gui.button(hbox, self, "Expand all", callback=self.tree.expandAll)
        gui.button(hbox, self, "Collapse all", callback=self.tree.collapseAll)

        box = gui.widgetBox(self.controlArea, 'Find itemsets')
        gui.hSlider(box, self, 'minSupport', minValue=1, maxValue=100,
                    label='Minimal support:', labelFormat="%d%%",
                    callback=lambda: self.find_itemsets())
        gui.hSlider(box, self, 'maxItemsets', minValue=10000, maxValue=100000, step=10000,
                    label='Max. number of itemsets:', labelFormat="%d",
                    callback=lambda: self.find_itemsets())
        gui.checkBox(box, self, 'filterSearch',
                     label='Apply below filters in search',
                     tooltip='If checked, the itemsets are filtered according '
                             'to below filter conditions already in the search '
                             'phase. \nIf unchecked, the only filters applied '
                             'during search are the ones above, '
                             'and the itemsets are \nfiltered afterwards only for '
                             'display, i.e. only the matching itemsets are shown.')
        self.button = gui.auto_commit(
            box, self, 'autoFind', 'Find itemsets', commit=self.find_itemsets)

        box = gui.widgetBox(self.controlArea, 'Filter itemsets')
        gui.lineEdit(box, self, 'filterKeywords', 'Contains:',
                     callback=self.filter_change, orientation='horizontal',
                     tooltip='A comma or space-separated list of regular '
                             'expressions.')
        hbox = gui.widgetBox(box, orientation='horizontal')
        gui.spin(hbox, self, 'filterMinItems', 1, 998, label='Min. items:',
                 callback=self.filter_change)
        gui.spin(hbox, self, 'filterMaxItems', 2, 999, label='Max. items:',
                 callback=self.filter_change)
        gui.rubber(hbox)

        gui.rubber(self.controlArea)
        gui.auto_commit(self.controlArea, self, 'autoSend', 'Send selection')

        self.filter_change()

    def sendReport(self):
        self.reportSettings("Itemset statistics",
                            [("Number of itemsets", self.nItemsets),
                             ("Selected itemsets", self.nSelectedItemsets),
                             ("Covered examples", self.nSelectedExamples),
                             ])
        self.reportSection("Itemsets")
        self.reportRaw(OWReport.reportTree(self.tree))

    ITEM_DATA_ROLE = Qt.UserRole + 1

    def selectionChanged(self):
        X = self.data.X
        mapping = self.onehot_mapping
        instances = set()
        where = np.where

        def whole_subtree(node):
            yield node
            for i in range(node.childCount()):
                yield from whole_subtree(node.child(i))

        def itemset(node):
            while node:
                yield node.data(0, self.ITEM_DATA_ROLE)
                node = node.parent()

        def selection_ranges(node):
            n_children = node.childCount()
            if n_children:
                yield (self.tree.indexFromItem(node.child(0)),
                       self.tree.indexFromItem(node.child(n_children - 1)))
            for i in range(n_children):
                yield from selection_ranges(node.child(i))

        nSelectedItemsets = 0
        item_selection = QItemSelection()
        for node in self.tree.selectedItems():
            nodes = (node,) if node.isExpanded() else whole_subtree(node)
            if not node.isExpanded():
                for srange in selection_ranges(node):
                    item_selection.select(*srange)
            for node in nodes:
                nSelectedItemsets += 1
                cols, vals = zip(*(mapping[i] for i in itemset(node)))
                instances.update(where((X[:, cols] == vals).all(axis=1))[0])
        self.tree.itemSelectionChanged.disconnect(self.selectionChanged)
        self.tree.selectionModel().select(item_selection,
                                          QItemSelectionModel.Select | QItemSelectionModel.Rows)
        self.tree.itemSelectionChanged.connect(self.selectionChanged)

        self.nSelectedExamples = len(instances)
        self.nSelectedItemsets = nSelectedItemsets
        self.output = self.data[sorted(instances)] or None
        self.commit()

    def commit(self):
        self.send(Output.DATA, self.output)

    def filter_change(self):
        isRegexMatch = self.isRegexMatch = re.compile(
            '|'.join(i.strip()
                     for i in re.split('(,|\s)+', self.filterKeywords.strip())
                     if i.strip())).search

        def hide(node, depth, has_kw):
            if not has_kw:
                has_kw = isRegexMatch(node.text(0))
            hidden = (sum(hide(node.child(i), depth + 1, has_kw)
                          for i in range(node.childCount())) == node.childCount()
                      if node.childCount() else
                      (not has_kw or
                       not self.filterMinItems <= depth <= self.filterMaxItems))
            node.setHidden(hidden)
            return hidden

        hide(self.tree.invisibleRootItem(), 0, False)

    class TreeWidgetItem(QTreeWidgetItem):
        def data(self, column, role):
            """Construct lazy tooltips"""
            if role != Qt.ToolTipRole:
                return super().data(column, role)
            tooltip = []
            while self:
                tooltip.append(self.text(0))
                self = self.parent()
            return ' '.join(reversed(tooltip))

    def find_itemsets(self):
        if self.data is None: return
        data = self.data
        self.tree.clear()
        self.tree.setUpdatesEnabled(False)
        self.tree.blockSignals(True)

        class ItemDict(dict):
            def __init__(self, item):
                self.item = item

        top = ItemDict(self.tree.invisibleRootItem())
        X, mapping = OneHot.encode(data)
        self.onehot_mapping = mapping
        names = {item: '{}={}'.format(var.name, val)
                 for item, var, val in OneHot.decode(mapping.keys(), data, mapping)}
        nItemsets = 0

        filterSearch = self.filterSearch
        filterMinItems, filterMaxItems = self.filterMinItems, self.filterMaxItems
        isRegexMatch = self.isRegexMatch

        # Find itemsets and populate the TreeView
        progress = gui.ProgressBar(self, self.maxItemsets + 1)
        for itemset, support in frequent_itemsets(X, self.minSupport / 100):

            if filterSearch and not filterMinItems <= len(itemset) <= filterMaxItems:
                continue

            parent = top
            first_new_item = None
            itemset_matches_filter = False

            for item in sorted(itemset):
                name = names[item]

                if filterSearch and not itemset_matches_filter:
                    itemset_matches_filter = isRegexMatch(name)

                child = parent.get(name)
                if child is None:
                    wi = self.TreeWidgetItem(parent.item, [name, str(support), '{:.1f}'.format(100 * support / len(data))])
                    wi.setData(0, self.ITEM_DATA_ROLE, item)
                    child = parent[name] = ItemDict(wi)

                    if first_new_item is None:
                        first_new_item = (parent, name)
                parent = child

            if filterSearch and not itemset_matches_filter:
                parent, name = first_new_item
                parent.item.removeChild(parent[name].item)
                del parent[name].item
                del parent[name]
            else:
                nItemsets += 1
                progress.advance()
            if nItemsets >= self.maxItemsets:
                break

        if not filterSearch:
            self.filter_change()
        self.nItemsets = nItemsets
        self.nSelectedItemsets = 0
        self.nSelectedExamples = 0
        self.tree.expandAll()
        for i in range(self.tree.columnCount()):
            self.tree.resizeColumnToContents(i)
        self.tree.setUpdatesEnabled(True)
        self.tree.blockSignals(False)
        progress.finish()

    def set_data(self, data):
        self.data = data
        if data is not None:
            self.warning(0, 'Data has continuous attributes which will be skipped.'
                            if data.domain.has_continuous_attributes() else None)
            self.error(1, 'Discrete features required but data has none.'
                          if not data.domain.has_discrete_attributes() else None)
            self.button.setDisabled(not data.domain.has_discrete_attributes())
        if self.autoFind:
            self.find_itemsets()
예제 #3
0
class Shortcuts(preferences.Page):
    def __init__(self, dialog):
        super(Shortcuts, self).__init__(dialog)

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

        self.scheme = SchemeSelector(self)
        layout.addWidget(self.scheme)
        self.tree = QTreeWidget(self)
        self.tree.setHeaderLabels([_("Command"), _("Shortcut")])
        self.tree.setRootIsDecorated(False)
        self.tree.setColumnCount(2)
        self.tree.setAllColumnsShowFocus(True)
        self.tree.setAnimated(True)
        layout.addWidget(self.tree)

        self.edit = QPushButton(
            icons.get("preferences-desktop-keyboard-shortcuts"), '')
        layout.addWidget(self.edit)

        # signals
        self.scheme.currentChanged.connect(self.slotSchemeChanged)
        self.scheme.changed.connect(self.changed)
        self.tree.currentItemChanged.connect(self.slotCurrentItemChanged)
        self.tree.itemDoubleClicked.connect(self.editCurrentItem)
        self.edit.clicked.connect(self.editCurrentItem)

        # make a dict of all actions with the actions as key and the names as
        # value, with the collection prepended (for loading/saving)
        win = dialog.parent()
        allactions = {}
        for collection in actioncollectionmanager.manager(
                win).actionCollections():
            for name, action in collection.actions().items():
                allactions[action] = (collection, name)

        # keep a list of actions not in the menu structure
        left = list(allactions.keys())

        def add_actions(menuitem, actions):
            """Add actions to a QTreeWidgetItem."""
            for a in actions:
                if a.menu():
                    item = build_menu_item(a)
                    if item.childCount():
                        menuitem.addChild(item)
                elif a in left:
                    left.remove(a)
                    menuitem.addChild(ShortcutItem(a, *allactions[a]))
            menuitem.setFlags(Qt.ItemIsEnabled)  # disable selection

        def build_menu_item(action):
            """Return a QTreeWidgetItem with children for all the actions in the submenu."""
            menuitem = QTreeWidgetItem()
            text = qutil.removeAccelerator(action.text())
            menuitem.setText(0, _("Menu {name}").format(name=text))
            add_actions(menuitem, action.menu().actions())
            return menuitem

        # present the actions nicely ordered as in the menus
        for a in win.menuBar().actions():
            menuitem = build_menu_item(a)
            if menuitem.childCount():
                self.tree.addTopLevelItem(menuitem)

        # sort leftover actions
        left.sort(key=lambda i: i.text())

        # show actions that are left, grouped by collection
        titlegroups = {}
        for a in left[:]:  # copy
            collection, name = allactions[a]
            if collection.title():
                titlegroups.setdefault(collection.title(), []).append(a)
                left.remove(a)
        for title in sorted(titlegroups):
            item = QTreeWidgetItem(["{0}:".format(title)])
            for a in titlegroups[title]:
                item.addChild(ShortcutItem(a, *allactions[a]))
            self.tree.addTopLevelItem(item)
            item.setFlags(Qt.ItemIsEnabled)  # disable selection

        # show other actions that were not in the menus
        item = QTreeWidgetItem([_("Other commands:")])
        for a in left:
            if a.text() and not a.menu():
                item.addChild(ShortcutItem(a, *allactions[a]))
        if item.childCount():
            self.tree.addTopLevelItem(item)
            item.setFlags(Qt.ItemIsEnabled)  # disable selection

        self.tree.expandAll()

        item = self.tree.topLevelItem(0).child(0)
        if _lastaction:
            # find the previously selected item
            for i in self.items():
                if i.name == _lastaction:
                    item = i
                    break
        self.tree.setCurrentItem(item)
        self.tree.resizeColumnToContents(0)

    def items(self):
        """Yield all the items in the actions tree."""
        def children(item):
            for i in range(item.childCount()):
                c = item.child(i)
                if c.childCount():
                    for c1 in children(c):
                        yield c1
                else:
                    yield c

        for c in children(self.tree.invisibleRootItem()):
            yield c

    def item(self, collection, name):
        for item in self.items():
            if item.collection.name == collection and item.name == name:
                return item

    def saveSettings(self):
        self.scheme.saveSettings("shortcut_scheme", "shortcut_schemes",
                                 "shortcuts")
        for item in self.items():
            for scheme in self.scheme.schemes():
                item.save(scheme)
            item.clearSettings()
            item.switchScheme(self.scheme.currentScheme())

    def loadSettings(self):
        self.scheme.loadSettings("shortcut_scheme", "shortcut_schemes")
        # clear the settings in all the items
        for item in self.items():
            item.clearSettings()
            item.switchScheme(self.scheme.currentScheme())

    def slotSchemeChanged(self):
        """Called when the Scheme combobox is changed by the user."""
        for item in self.items():
            item.switchScheme(self.scheme.currentScheme())

    def slotCurrentItemChanged(self, item):
        if isinstance(item, ShortcutItem):
            self.edit.setText(
                _("&Edit Shortcut for \"{name}\"").format(name=item.text(0)))
            self.edit.setEnabled(True)
            global _lastaction
            _lastaction = item.name
        else:
            self.edit.setText(_("(no shortcut)"))
            self.edit.setEnabled(False)

    def import_(self, filename):
        from . import import_export
        import_export.importShortcut(filename, self, self.scheme)

    def export(self, name, filename):
        from . import import_export
        try:
            import_export.exportShortcut(self, self.scheme.currentScheme(),
                                         name, filename)
        except (IOError, OSError) as e:
            QMessageBox.critical(
                self, _("Error"),
                _("Can't write to destination:\n\n{url}\n\n{error}").format(
                    url=filename, error=e.strerror))

    def findShortcutConflict(self, shortcut):
        """Find the possible shortcut conflict and return the conflict name."""
        if shortcut:
            item = self.tree.currentItem()
            if not isinstance(item, ShortcutItem):
                return None
            scheme = self.scheme.currentScheme()
            for i in self.items():
                a = i.action(scheme)
                if i != item and a.shortcuts():
                    for s1 in a.shortcuts():
                        if s1.matches(shortcut) or shortcut.matches(s1):
                            return qutil.removeAccelerator(a.text())
        return None

    def editCurrentItem(self):
        item = self.tree.currentItem()
        if not isinstance(item, ShortcutItem):
            return

        dlg = ShortcutEditDialog(self, self.findShortcutConflict)
        scheme = self.scheme.currentScheme()
        action = item.action(scheme)
        default = item.defaultShortcuts() or None
        if dlg.editAction(action, default):
            shortcuts = action.shortcuts()
            # check for conflicts
            conflicting = []
            for i in self.items():
                if i is not item:
                    for s1, s2 in itertools.product(i.shortcuts(scheme),
                                                    shortcuts):
                        if s1.matches(s2) or s2.matches(s1):
                            conflicting.append(i)
            if conflicting:
                for i in conflicting:
                    l = i.shortcuts(scheme)
                    for s1 in list(l):  # copy
                        for s2 in shortcuts:
                            if s1.matches(s2) or s2.matches(s1):
                                l.remove(s1)
                    i.setShortcuts(l, scheme)

            # store the shortcut
            item.setShortcuts(shortcuts, scheme)
            self.changed.emit()
예제 #4
0
class Shortcuts(preferences.Page):
    def __init__(self, dialog):
        super(Shortcuts, self).__init__(dialog)
        
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        
        self.scheme = SchemeSelector(self)
        layout.addWidget(self.scheme)
        self.tree = QTreeWidget(self)
        self.tree.setHeaderLabels([_("Command"), _("Shortcut")])
        self.tree.setRootIsDecorated(False)
        self.tree.setColumnCount(2)
        self.tree.setAllColumnsShowFocus(True)
        self.tree.setAnimated(True)
        layout.addWidget(self.tree)
        
        self.edit = QPushButton(icons.get("preferences-desktop-keyboard-shortcuts"), '')
        layout.addWidget(self.edit)
        
        # signals
        self.scheme.currentChanged.connect(self.slotSchemeChanged)
        self.scheme.changed.connect(self.changed)
        self.tree.currentItemChanged.connect(self.slotCurrentItemChanged)
        self.tree.itemDoubleClicked.connect(self.editCurrentItem)
        self.edit.clicked.connect(self.editCurrentItem)
        
        # make a dict of all actions with the actions as key and the names as
        # value, with the collection prepended (for loading/saving)
        win = dialog.parent()
        allactions = {}
        for collection in actioncollectionmanager.manager(win).actionCollections():
            for name, action in collection.actions().items():
                allactions[action] = (collection, name)
        
        # keep a list of actions not in the menu structure
        left = allactions.keys()
        
        def add_actions(menuitem, actions):
            """Add actions to a QTreeWidgetItem."""
            for a in actions:
                if a.menu():
                    item = build_menu_item(a)
                    if item.childCount():
                        menuitem.addChild(item)
                elif a in left:
                    left.remove(a)
                    menuitem.addChild(ShortcutItem(a, *allactions[a]))
            menuitem.setFlags(Qt.ItemIsEnabled) # disable selection
            
        def build_menu_item(action):
            """Return a QTreeWidgetItem with children for all the actions in the submenu."""
            menuitem = QTreeWidgetItem()
            text = qutil.removeAccelelator(action.text())
            menuitem.setText(0, _("Menu {name}").format(name=text))
            add_actions(menuitem, action.menu().actions())
            return menuitem
        
        # present the actions nicely ordered as in the menus
        for a in win.menuBar().actions():
            menuitem = build_menu_item(a)
            if menuitem.childCount():
                self.tree.addTopLevelItem(menuitem)
        
        # sort leftover actions
        left.sort(key=lambda i: i.text())
        
        # show actions that are left, grouped by collection
        titlegroups = {}
        for a in left[:]: # copy
            collection, name = allactions[a]
            if collection.title():
                titlegroups.setdefault(collection.title(), []).append(a)
                left.remove(a)
        for title in sorted(titlegroups):
            item = QTreeWidgetItem(["{0}:".format(title)])
            for a in titlegroups[title]:
                item.addChild(ShortcutItem(a, *allactions[a]))
            self.tree.addTopLevelItem(item)
            item.setFlags(Qt.ItemIsEnabled) # disable selection
            
        # show other actions that were not in the menus
        item = QTreeWidgetItem([_("Other commands:")])
        for a in left:
            if a.text() and not a.menu():
                item.addChild(ShortcutItem(a, *allactions[a]))
        if item.childCount():
            self.tree.addTopLevelItem(item)
            item.setFlags(Qt.ItemIsEnabled) # disable selection
        
        self.tree.expandAll()
        
        item = self.tree.topLevelItem(0).child(0)
        if _lastaction:
            # find the previously selected item
            for i in self.items():
                if i.name == _lastaction:
                    item = i
                    break
        self.tree.setCurrentItem(item)
        self.tree.resizeColumnToContents(0)
        
    def items(self):
        """Yield all the items in the actions tree."""
        def children(item):
            for i in range(item.childCount()):
                c = item.child(i)
                if c.childCount():
                    for c1 in children(c):
                        yield c1
                else:
                    yield c
        for c in children(self.tree.invisibleRootItem()):
            yield c
    
    def saveSettings(self):
        self.scheme.saveSettings("shortcut_scheme", "shortcut_schemes", "shortcuts")
        for item in self.items():
            for scheme in self.scheme.schemes():
                item.save(scheme)
            item.clearSettings()
            item.switchScheme(self.scheme.currentScheme())
        
    def loadSettings(self):
        self.scheme.loadSettings("shortcut_scheme", "shortcut_schemes")
        # clear the settings in all the items
        for item in self.items():
            item.clearSettings()
            item.switchScheme(self.scheme.currentScheme())
        
    def slotSchemeChanged(self):
        """Called when the Scheme combobox is changed by the user."""
        for item in self.items():
            item.switchScheme(self.scheme.currentScheme())
        
    def slotCurrentItemChanged(self, item):
        if isinstance(item, ShortcutItem):
            self.edit.setText(
                _("&Edit Shortcut for \"{name}\"").format(name=item.text(0)))
            self.edit.setEnabled(True)
            global _lastaction
            _lastaction = item.name
        else:
            self.edit.setText(_("(no shortcut)"))
            self.edit.setEnabled(False)
        
    def editCurrentItem(self):
        item = self.tree.currentItem()
        if not isinstance(item, ShortcutItem):
            return
        try:
            dlg = self._editdialog
        except AttributeError:
            dlg = self._editdialog = ShortcutEditDialog(self)
        scheme = self.scheme.currentScheme()
        action = item.action(scheme)
        default = item.defaultShortcuts()
        if dlg.editAction(action, default):
            shortcuts = action.shortcuts()
            # check for conflicts
            conflicting = []
            for i in self.items():
                if i is not item:
                    for s1, s2 in itertools.product(i.shortcuts(scheme), shortcuts):
                        if s1.matches(s2) or s2.matches(s1):
                            conflicting.append(i)
            if conflicting:
                # show a question dialog
                msg = [_("This shortcut conflicts with the following command:",
                        "This shortcut conflicts with the following commands:", len(conflicting))]
                msg.append('<br/>'.join(i.text(0) for i in conflicting))
                msg.append(_("Remove the shortcut from that command?",
                             "Remove the shortcut from those commands?", len(conflicting)))
                msg = '<p>{0}</p>'.format('</p><p>'.join(msg))
                res = QMessageBox.warning(self, _("Shortcut Conflict"), msg,
                        QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
                if res == QMessageBox.Yes:
                    # remove from conflicting
                    for i in conflicting:
                        l = i.shortcuts(scheme)
                        for s1 in list(l): # copy
                            for s2 in shortcuts:
                                if s1.matches(s2) or s2.matches(s1):
                                    l.remove(s1)
                        i.setShortcuts(l, scheme)
                elif res == QMessageBox.No:
                    # remove from ourselves
                    for i in conflicting:
                        for s1 in list(shortcuts): # copy
                            for s2 in i.shortcuts(scheme):
                                if s1.matches(s2) or s2.matches(s1):
                                    shortcuts.remove(s1)
                else:
                    return # cancelled
            # store the shortcut
            item.setShortcuts(shortcuts, scheme)
            self.changed.emit()
예제 #5
0
 def expandAll(self):
     self._treeDepth = 10000
     QTreeWidget.expandAll(self)
예제 #6
0
    def __init__(self, term, parent=None):
        super(FeeDialog, self).__init__(parent)
        
        self.term = term
        self.sid = term
        terms = self.pullOnes('terms', self.term)
        session = self.pullOnes('session', terms['sessionID'])
        self.termname = str(session['name'])+' '+terms['name']+' Term Report'
        self.pagetitle = self.termname 
        ko = 0
        
        
        Form1 = QFormLayout()
        Form2 = QFormLayout()
        
        #title
        self.title = QLabel("Set Fees")
        self.titleData = QComboBox()
        self.titleData.setObjectName("name")
        #self.titleData.setPlaceHolderText("e.g. 2019 FIRST TERM RESULT")
        
        tree = QTreeWidget()
        tree.setItemDelegate(Delegate())
        tree.setHeaderLabel("Which grading system will you be using?")
        
        tree1 = QTreeWidget()
        tree1.setHeaderLabel("Choose Assessments and Classes")
        
        tree2 = QTreeWidget()
        tree2.setHeaderLabel("Report Card Settings")
        
        self.ass_arr = {}
        parent = QTreeWidgetItem(tree1)
        parent.setText(0, "Select Assessments")
        parent.setFlags(parent.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
        arr = self.pullCas()
        if arr and len(arr) > 0:
            for val in arr:
                dt = self.pullOne(val['name'])
                child = QTreeWidgetItem(parent)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                child.setText(0, str(dt['name']).upper())
                self.ass_arr[val['name']] = child
                if (val['active'] == 0):
                    child.setCheckState(0, Qt.Unchecked)
                else:
                    child.setCheckState(0, Qt.Unchecked)
                ko += 1
        
        self.cla_arr ={}
        parent1 = QTreeWidgetItem(tree1)
        parent1.setText(0, "Select Class")
        parent1.setFlags(parent1.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
        arr = self.pullClass()
        if arr and len(arr) > 0:
            for val in arr:
                child = QTreeWidgetItem(parent1)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                child.setText(0, str(val['name']).upper())
                self.cla_arr[val['id']] = child
                if (val['active'] == 0):
                    child.setCheckState(0, Qt.Unchecked)
                else:
                    child.setCheckState(0, Qt.Unchecked)
                ko += 1

        self.gra_arr = {}
        parent2 = QTreeWidgetItem(tree)
        parent2.setText(0, "Select Grade")
        arr = self.pullGrade()
        if arr and len(arr) > 0:
            for val in arr:
                child = QTreeWidgetItem(parent2)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                child.setText(0, str(val['name']).upper())
                self.gra_arr[val['id']] = child
                if (val['active'] == 0):
                    child.setCheckState(0, Qt.Unchecked)
                else:
                    child.setCheckState(0, Qt.Unchecked)
                ko += 1
                
        self.set_arr= {}
        parent3 = QTreeWidgetItem(tree2)
        parent3.setText(0, "Include ...")
        parent3.setFlags(parent3.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
        arr ={
                1:'School Number',
                2:'Class Position',
                3:'Class Unit Position',
                4:'Total (100%)',
                5:'Total',
                6:'Grading',
                7:'Subject Average',
                8:'Ranking',
                9:'Ranking and Student Population',
                10:'Student Passport',
                11:'School Logo',
                12:'School Address',
                13:'Students Address',
                14:'Attendance',
                15:'Fees Owed',
                16:'Test/Assesments'
            }
        if arr and len(arr) > 0:
            for val in arr:
                child = QTreeWidgetItem(parent3)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                child.setText(0, str(arr[val]).upper())
                self.set_arr[val] = child
                child.setCheckState(0, Qt.Unchecked)
            
            child1 = QTreeWidgetItem(parent3)
            child1.setFlags(child1.flags() | Qt.ItemIsUserCheckable)
            child1.setText(0, 'AFFECTIVE DOMAIN REPORT')
            self.set_arr['aff'] = child1
            child1.setCheckState(0, Qt.Unchecked)
            
            child2 = QTreeWidgetItem(child1)
            child2.setFlags(child2.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
            child2.setText(0, 'TABLE')
            self.set_arr['afftable'] = child2
            child2.setCheckState(0, Qt.Unchecked)
            
            child3 = QTreeWidgetItem(child1)
            child3.setFlags(child3.flags() | Qt.ItemIsUserCheckable)
            child3.setText(0, 'GRAPH')
            self.set_arr['affgraph'] = child3
            child3.setCheckState(0, Qt.Unchecked)
            
            child4 = QTreeWidgetItem(parent3)
            child4.setFlags(child4.flags() | Qt.ItemIsTristate | Qt.ItemIsUserCheckable)
            child4.setText(0, 'PYSCHOMOTOR DOMAIN REPORT')
            self.set_arr['psy'] = child4
            child4.setCheckState(0, Qt.Unchecked)
            
            child5 = QTreeWidgetItem(child4)
            child5.setFlags(child5.flags() | Qt.ItemIsUserCheckable)
            child5.setText(0, 'TABLE')
            self.set_arr['psytable'] = child5
            child5.setCheckState(0, Qt.Unchecked)
            
            child6 = QTreeWidgetItem(child4)
            child6.setFlags(child6.flags() | Qt.ItemIsUserCheckable)
            child6.setText(0, 'GRAPH')
            self.set_arr['psygraph'] = child6
            child6.setCheckState(0, Qt.Unchecked)

        tree.expandAll()
        tree1.expandAll()
        tree2.expandAll()
        #tree.show()
     
        self.l5 = QLabel("Theme Color")
        self.pbc = QPushButton()
        self.pbc.setObjectName("Pickcolor")
        self.pbc.setText("Click to change")
        
        self.le5 = QLineEdit()
        self.le5.setObjectName("Showcolor")
        self.le5.setText("#000000")
        self.pbc.setStyleSheet("background-color: black; color: white")
        self.connect(self.pbc, SIGNAL("clicked()"), lambda: self.color_picker())
        
        self.l6 = QLabel("Pick Theme Font")
        self.pbf = QPushButton()
        self.pbf.setObjectName("Pickfont")
        self.pbf.setText("Click to Change")
        
        self.le6 = QLineEdit()
        self.le6.setObjectName("Showcolor")
        self.le6.setText("#000000")
        self.pbf.setStyleSheet("background-color: black; color: white")
        self.connect(self.pbf, SIGNAL("clicked()"), lambda: self.font_picker())
        
        self.lv_box = QHBoxLayout()
        self.lv_box.addWidget(self.pbc)
        self.lv_box.addWidget(self.le5)
        
        self.lv_box1 = QHBoxLayout()
        self.lv_box1.addWidget(self.pbf)
        self.lv_box1.addWidget(self.le6)
        
        Form1.addRow(self.title, self.titleData)
        Form2.addRow(self.l5, self.lv_box)
        Form2.addRow(self.l6, self.lv_box1)
        
        Gbo = QGridLayout()
        Gbo.addLayout(Form1, 0, 0, 1, 2)
        Gbo.addWidget(tree, 1, 0)
        Gbo.addWidget(tree1, 1, 1)
        Gbo.addWidget(tree2, 2, 0)
        Gbo.addLayout(Form2, 2, 1)
        
        groupBox1 = QGroupBox('Academic Report Setup')
        groupBox1.setLayout(Gbo)
        
        self.pb = QPushButton()
        self.pb.setObjectName("Add")
        self.pb.setText("Save")
        
        
        self.pb1 = QPushButton()
        self.pb1.setObjectName("Cancel")
        self.pb1.setText("Cancel")
        
        self.pb2 = QPushButton()
        self.pb2.setObjectName("Save")
        self.pb2.setText("Save and Keep Template")
        
        self.lTemplate = QLineEdit() 
        self.lTemplate.setPlaceholderText('Template Name')
        
        self.rTemplate = QLabel() 
        self.rTemplate.setText('')
        
        hbo = QHBoxLayout()
        hbo.addWidget(self.pb1)
        hbo.addStretch()
        hbo.addWidget(self.lTemplate)
        hbo.addWidget(self.pb2)
        hbo.addWidget(self.rTemplate)
        hbo.addStretch()
        hbo.addWidget(self.pb)
        
        groupBox2 = QGroupBox('')
        groupBox2.setLayout(hbo)
            
        grid = QGridLayout()
        grid.addWidget(groupBox1, 0, 0)
        grid.addWidget(groupBox2, 1, 0)
        
        self.setLayout(grid)
        self.connect(self.pb, SIGNAL("clicked()"), lambda: self.button_click(self))
        self.connect(self.pb2, SIGNAL("clicked()"), lambda: self.button_template(self))
        self.connect(self.pb1, SIGNAL("clicked()"), lambda: self.button_close(self))
       
        self.setWindowTitle(self.pagetitle)
예제 #7
0
class TreeSymbolsWidget(QDialog):
    """Class of Dialog for Tree Symbols"""

    def __init__(self, parent=None):
        super(TreeSymbolsWidget, self).__init__(parent,
            Qt.WindowStaysOnTopHint)
        vbox = QVBoxLayout(self)
        vbox.setContentsMargins(0, 0, 0, 0)
        vbox.setSpacing(0)
        self.tree = QTreeWidget()
        vbox.addWidget(self.tree)
        self.tree.header().setHidden(True)
        self.tree.setSelectionMode(self.tree.SingleSelection)
        self.tree.setAnimated(True)
        self.tree.header().setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self.tree.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self.tree.header().setStretchLastSection(False)
        self.actualSymbols = ('', {})
        self.docstrings = {}
        self.collapsedItems = {}

        self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem *, int)"),
            self._go_to_definition)
        self.connect(self, SIGNAL("itemActivated(QTreeWidgetItem *, int)"),
            self._go_to_definition)
        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connect(self,
            SIGNAL("customContextMenuRequested(const QPoint &)"),
            self._menu_context_tree)
        self.connect(self, SIGNAL("itemCollapsed(QTreeWidgetItem *)"),
            self._item_collapsed)
        self.connect(self, SIGNAL("itemExpanded(QTreeWidgetItem *)"),
            self._item_expanded)

        IDE.register_service('symbols_explorer', self)
        ExplorerContainer.register_tab(translations.TR_TAB_SYMBOLS, self)

    def install_tab(self):
        """Connect signals for goingdown"""
        ide = IDE.get_service('ide')
        self.connect(ide, SIGNAL("goingDown()"), self.close)

    def _menu_context_tree(self, point):
        """Context menu"""
        index = self.tree.indexAt(point)
        if not index.isValid():
            return

        menu = QMenu(self)
        f_all = menu.addAction(translations.TR_FOLD_ALL)
        u_all = menu.addAction(translations.TR_UNFOLD_ALL)
        menu.addSeparator()
        u_class = menu.addAction(translations.TR_UNFOLD_CLASSES)
        u_class_method = menu.addAction(
                         translations.TR_UNFOLD_CLASSES_AND_METHODS)
        u_class_attr = menu.addAction(
                       translations.TR_UNFOLD_CLASSES_AND_ATTRIBUTES)
        menu.addSeparator()
        #save_state = menu.addAction(self.tr("Save State"))

        self.connect(f_all, SIGNAL("triggered()"),
            lambda: self.tree.collapseAll())
        self.connect(u_all, SIGNAL("triggered()"),
            lambda: self.tree.expandAll())
        self.connect(u_class, SIGNAL("triggered()"), self._unfold_class)
        self.connect(u_class_method, SIGNAL("triggered()"),
            self._unfold_class_method)
        self.connect(u_class_attr, SIGNAL("triggered()"),
            self._unfold_class_attribute)
        #self.connect(save_state, SIGNAL("triggered()"),
            #self._save_symbols_state)

        menu.exec_(QCursor.pos())

    def _get_classes_root(self):
        """Return the root of classes"""
        class_root = None
        for i in range(self.tree.topLevelItemCount()):
            item = self.tree.topLevelItem(i)
            if item.isClass and not item.isClickable:
                class_root = item
                break
        return class_root

    def _unfold_class(self):
        """Method to Unfold Classes"""
        self.tree.collapseAll()
        classes_root = self._get_classes_root()
        if not classes_root:
            return

        classes_root.setExpanded(True)

    def _unfold_class_method(self):
        """Method to Unfold Methods"""
        self.tree.expandAll()
        classes_root = self._get_classes_root()
        if not classes_root:
            return
        #for each class!
        for i in range(classes_root.childCount()):
            class_item = classes_root.child(i)
            #for each attribute or functions
            for j in range(class_item.childCount()):
                item = class_item.child(j)
                #METHODS ROOT!!
                if not item.isMethod and not item.isClickable:
                    item.setExpanded(False)
                    break

    def _unfold_class_attribute(self):
        """Method to Unfold Attributes"""
        self.tree.expandAll()
        classes_root = self._get_classes_root()
        if not classes_root:
            return
        #for each class!
        for i in range(classes_root.childCount()):
            class_item = classes_root.child(i)
            #for each attribute or functions
            for j in range(class_item.childCount()):
                item = class_item.child(j)
                #ATTRIBUTES ROOT!!
                if not item.isAttribute and not item.isClickable:
                    item.setExpanded(False)
                    break

    def _save_symbols_state(self):
        """Method to Save a persistent Symbols state"""
        #filename = self.actualSymbols[0]
        #TODO: persist self.collapsedItems[filename] in QSettings
        pass

    def _get_expand(self, item):
        """
        Returns True or False to be used as setExpanded() with the items
        It method is based on the click that the user made in the tree
        """
        name = self._get_unique_name(item)
        filename = self.actualSymbols[0]
        collapsed_items = self.collapsedItems.get(filename, [])
        can_check = (not item.isClickable) or item.isClass or item.isMethod
        if can_check and name in collapsed_items:
            return False
        return True

    @staticmethod
    def _get_unique_name(item):
        """
        Returns a string used as unique name
        """
        # className_Attributes/className_Functions
        parent = item.parent()
        if parent:
            return "%s_%s" % (parent.text(0), item.text(0))
        return "_%s" % item.text(0)

    def update_symbols_tree(self, symbols, filename='', parent=None):
        """Method to Update the symbols on the Tree"""
        if not parent:
            if filename == self.actualSymbols[0] and \
                self.actualSymbols[1] and not symbols:
                    return

            if symbols == self.actualSymbols[1]:
                # Nothing new then return
                return

            # we have new symbols refresh it
            self.tree.clear()
            self.actualSymbols = (filename, symbols)
            self.docstrings = symbols.get('docstrings', {})
            parent = self.tree
        if 'attributes' in symbols:
            globalAttribute = ItemTree(parent, [translations.TR_ATTRIBUTES])
            globalAttribute.isClickable = False
            globalAttribute.isAttribute = True
            globalAttribute.setExpanded(self._get_expand(globalAttribute))
            for glob in sorted(symbols['attributes']):
                globItem = ItemTree(globalAttribute, [glob],
                    lineno=symbols['attributes'][glob])
                globItem.isAttribute = True
                globItem.setIcon(0, QIcon(":img/attribute"))
                globItem.setExpanded(self._get_expand(globItem))

        if 'functions' in symbols and symbols['functions']:
            functionsItem = ItemTree(parent, [translations.TR_FUNCTIONS])
            functionsItem.isClickable = False
            functionsItem.isMethod = True
            functionsItem.setExpanded(self._get_expand(functionsItem))
            for func in sorted(symbols['functions']):
                item = ItemTree(functionsItem, [func],
                    lineno=symbols['functions'][func]['lineno'])
                tooltip = self.create_tooltip(
                    func, symbols['functions'][func]['lineno'])
                item.isMethod = True
                item.setIcon(0, QIcon(":img/function"))
                item.setToolTip(0, tooltip)
                item.setExpanded(self._get_expand(item))
                self.update_symbols_tree(
                    symbols['functions'][func]['functions'], parent=item)
        if 'classes' in symbols and symbols['classes']:
            classItem = ItemTree(parent, [translations.TR_CLASSES])
            classItem.isClickable = False
            classItem.isClass = True
            classItem.setExpanded(self._get_expand(classItem))
            for claz in sorted(symbols['classes']):
                line_number = symbols['classes'][claz]['lineno']
                item = ItemTree(classItem, [claz], lineno=line_number)
                item.isClass = True
                tooltip = self.create_tooltip(claz, line_number)
                item.setToolTip(0, tooltip)
                item.setIcon(0, QIcon(":img/class"))
                item.setExpanded(self._get_expand(item))
                self.update_symbols_tree(symbols['classes'][claz]['members'],
                    parent=item)

    def _go_to_definition(self, item):
        """Takes and item object and goes to definition on the editor"""
        main_container = IDE.get_service('main_container')
        if item.isClickable and main_container:
            main_container.editor_go_to_line(item.lineno - 1)

    def create_tooltip(self, name, lineno):
        """Takes a name and line number and returns a tooltip"""
        doc = self.docstrings.get(lineno, None)
        if doc is None:
            doc = ''
        else:
            doc = '\n' + doc
        tooltip = name + doc
        return tooltip

    def _item_collapsed(self, item):
        """When item collapsed"""
        super(TreeSymbolsWidget, self).collapseItem(item)

        can_check = (not item.isClickable) or item.isClass or item.isMethod
        if can_check:
            n = self._get_unique_name(item)
            filename = self.actualSymbols[0]
            self.collapsedItems.setdefault(filename, [])
            if not n in self.collapsedItems[filename]:
                self.collapsedItems[filename].append(n)

    def _item_expanded(self, item):
        """When item expanded"""
        super(TreeSymbolsWidget, self).expandItem(item)

        n = self._get_unique_name(item)
        filename = self.actualSymbols[0]
        if n in self.collapsedItems.get(filename, []):
            self.collapsedItems[filename].remove(n)
            if not len(self.collapsedItems[filename]):
                # no more items, free space
                del self.collapsedItems[filename]

    def clean(self):
        """
        Reset the tree and reset attributes
        """
        self.tree.clear()
        self.collapsedItems = {}

    def reject(self):
        if self.parent() is None:
            self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self)

    def closeEvent(self, event):
        """On Close event handling"""
        self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self)
        event.ignore()
예제 #8
0
class BookmarksWindow(QDialog):
    """
    A simple UI for showing bookmarks and navigating to them.

    FIXME: For now, this window is tied to a particular lane.
           If your project has more than one lane, then each one
           will have it's own bookmark window, which is kinda dumb.
    """
    def __init__(self, parent, topLevelOperatorView):
        super(BookmarksWindow, self).__init__(parent)
        self.setWindowTitle("Bookmarks")
        self.topLevelOperatorView = topLevelOperatorView
        self.bookmark_tree = QTreeWidget(self)
        self.bookmark_tree.setHeaderLabels(["Location", "Notes"])
        self.bookmark_tree.setSizePolicy(QSizePolicy.Preferred,
                                         QSizePolicy.Preferred)
        self.bookmark_tree.setColumnWidth(0, 200)
        self.bookmark_tree.setColumnWidth(1, 300)

        self.note_edit = QLineEdit(self)
        self.add_bookmark_button = QPushButton("Add Bookmark",
                                               self,
                                               clicked=self.add_bookmark)

        geometry = self.geometry()
        geometry.setSize(QSize(520, 520))
        self.setGeometry(geometry)

        layout = QVBoxLayout()
        layout.addWidget(self.bookmark_tree)
        layout.addWidget(self.note_edit)
        layout.addWidget(self.add_bookmark_button)
        self.setLayout(layout)

        self._load_bookmarks()

        self.bookmark_tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.bookmark_tree.customContextMenuRequested.connect(
            self.showContextMenu)

        self.bookmark_tree.itemDoubleClicked.connect(self._handle_doubleclick)

    def _handle_doubleclick(self, item, col):
        """
        Navigate to the bookmark
        """
        data = item.data(0, Qt.UserRole).toPyObject()
        if data is None:
            return

        (coord, notes) = data
        axes = self.topLevelOperatorView.InputImages.meta.getAxisKeys()
        axes = axes[:-1]  # drop channel
        axes = sorted(axes)
        assert len(axes) == len(coord)
        tagged_coord = dict(zip(axes, coord))
        tagged_location = OrderedDict(zip('txyzc', (0, 0, 0, 0, 0)))
        tagged_location.update(tagged_coord)
        t = tagged_location.values()[0]
        coord3d = tagged_location.values()[1:4]

        self.parent().editor.posModel.time = t
        self.parent().editor.navCtrl.panSlicingViews(coord3d, [0, 1, 2])
        self.parent().editor.posModel.slicingPos = coord3d

    def showContextMenu(self, pos):
        item = self.bookmark_tree.itemAt(pos)
        data = item.data(0, Qt.UserRole).toPyObject()
        if data is None:
            return

        def delete_bookmark():
            (coord, notes) = data
            bookmarks = list(self.topLevelOperatorView.Bookmarks.value)
            i = bookmarks.index((coord, notes))
            bookmarks.pop(i)
            self.topLevelOperatorView.Bookmarks.setValue(bookmarks)
            self._load_bookmarks()

        menu = QMenu(parent=self)
        menu.addAction(QAction("Delete", menu, triggered=delete_bookmark))
        globalPos = self.bookmark_tree.viewport().mapToGlobal(pos)
        menu.exec_(globalPos)
        #selection = menu.exec_( globalPos )
        #if selection is removeLanesAction:
        #    self.removeLanesRequested.emit( self._selectedLanes )

    def add_bookmark(self):
        coord_txyzc = self.parent().editor.posModel.slicingPos5D
        tagged_coord_txyzc = dict(zip('txyzc', coord_txyzc))
        axes = self.topLevelOperatorView.InputImages.meta.getAxisKeys()
        axes = axes[:-1]  # drop channel
        axes = sorted(axes)
        coord = tuple(tagged_coord_txyzc[c] for c in axes)

        notes = str(self.note_edit.text())
        bookmarks = list(self.topLevelOperatorView.Bookmarks.value)
        bookmarks.append((coord, notes))
        self.topLevelOperatorView.Bookmarks.setValue(bookmarks)

        self._load_bookmarks()

    def _load_bookmarks(self):
        self.bookmark_tree.clear()
        lane_index = self.topLevelOperatorView.current_view_index()
        lane_nickname = self.topLevelOperatorView.InputImages.meta.nickname or "Lane {}".format(
            lane_index)
        bookmarks = self.topLevelOperatorView.Bookmarks.value
        group_item = QTreeWidgetItem(self.bookmark_tree,
                                     QStringList(lane_nickname))

        for coord, notes in bookmarks:
            item = QTreeWidgetItem(group_item, QStringList())
            item.setText(0, str(coord))
            item.setData(0, Qt.UserRole, (coord, notes))
            item.setText(1, notes)

        self.bookmark_tree.expandAll()
예제 #9
0
class Preferences(QDialog):

    configuration = {}
    weight = 0

    def __init__(self, parent=None):
        super(Preferences, self).__init__(parent, Qt.Dialog)
        self.setWindowTitle(translations.TR_PREFERENCES_TITLE)
        self.setMinimumSize(QSize(800, 600))
        self.setMaximumSize(QSize(0, 0))
        vbox = QVBoxLayout(self)
        hbox = QHBoxLayout()
        vbox.setContentsMargins(0, 0, 5, 5)
        hbox.setContentsMargins(0, 0, 0, 0)

        self.tree = QTreeWidget()
        self.tree.header().setHidden(True)
        self.tree.setSelectionMode(QTreeWidget.SingleSelection)
        self.tree.setAnimated(True)
        self.tree.header().setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self.tree.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self.tree.header().setStretchLastSection(False)
        self.tree.setFixedWidth(200)
        self.stacked = QStackedLayout()
        hbox.addWidget(self.tree)
        hbox.addLayout(self.stacked)
        vbox.addLayout(hbox)

        hbox_footer = QHBoxLayout()
        self._btnSave = QPushButton(translations.TR_SAVE)
        self._btnCancel = QPushButton(translations.TR_CANCEL)
        hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding))
        hbox_footer.addWidget(self._btnCancel)
        hbox_footer.addWidget(self._btnSave)
        vbox.addLayout(hbox_footer)

        self.connect(self.tree, SIGNAL("itemSelectionChanged()"),
                     self._change_current)
        self.connect(self._btnCancel, SIGNAL("clicked()"), self.close)
        self.connect(self._btnSave, SIGNAL("clicked()"),
                     self._save_preferences)

        self.load_ui()
        self.tree.setCurrentItem(self.tree.topLevelItem(0))

    def _save_preferences(self):
        self.emit(SIGNAL("savePreferences()"))
        self.close()

    def load_ui(self):
        sections = sorted(
            list(Preferences.configuration.keys()),
            key=lambda item: Preferences.configuration[item]['weight'])
        for section in sections:
            text = Preferences.configuration[section]['text']
            Widget = Preferences.configuration[section]['widget']
            widget = Widget(self)
            area = QScrollArea()
            area.setWidgetResizable(True)
            area.setWidget(widget)
            index = self.stacked.addWidget(area)
            item = QTreeWidgetItem([text])
            item.setData(0, Qt.UserRole, index)
            self.tree.addTopLevelItem(item)

            #Sort Item Children
            subcontent = Preferences.configuration[section].get(
                'subsections', {})
            subsections = sorted(list(subcontent.keys()),
                                 key=lambda item: subcontent[item]['weight'])
            for sub in subsections:
                text = subcontent[sub]['text']
                Widget = subcontent[sub]['widget']
                widget = Widget(self)
                area = QScrollArea()
                area.setWidgetResizable(True)
                area.setWidget(widget)
                index = self.stacked.addWidget(area)
                subitem = QTreeWidgetItem([text])
                subitem.setData(0, Qt.UserRole, index)
                item.addChild(subitem)

        self.tree.expandAll()

    def _change_current(self):
        item = self.tree.currentItem()
        index = item.data(0, Qt.UserRole)
        self.stacked.setCurrentIndex(index)

    @classmethod
    def register_configuration(cls,
                               section,
                               widget,
                               text,
                               weight=None,
                               subsection=None):
        if weight is None:
            Preferences.weight += 1
            weight = Preferences.weight
        if not subsection:
            Preferences.configuration[section] = {
                'widget': widget,
                'weight': weight,
                'text': text
            }
        else:
            config = Preferences.configuration.get(section, {})
            if not config:
                config[section] = {'widget': None, 'weight': 100}
            subconfig = config.get('subsections', {})
            subconfig[subsection] = {
                'widget': widget,
                'weight': weight,
                'text': text
            }
            config['subsections'] = subconfig
            Preferences.configuration[section] = config
class BookmarksWindow(QDialog):
    """
    A simple UI for showing bookmarks and navigating to them.

    FIXME: For now, this window is tied to a particular lane.
           If your project has more than one lane, then each one
           will have it's own bookmark window, which is kinda dumb.
    """
    def __init__(self, parent, topLevelOperatorView):
        super(BookmarksWindow, self).__init__(parent)
        self.setWindowTitle("Bookmarks")
        self.topLevelOperatorView = topLevelOperatorView
        self.bookmark_tree = QTreeWidget(self)
        self.bookmark_tree.setHeaderLabels( ["Location", "Notes"] )
        self.bookmark_tree.setSizePolicy( QSizePolicy.Preferred, QSizePolicy.Preferred )
        self.bookmark_tree.setColumnWidth(0, 200)
        self.bookmark_tree.setColumnWidth(1, 300)

        self.note_edit = QLineEdit(self)
        self.add_bookmark_button = QPushButton("Add Bookmark", self, clicked=self.add_bookmark)

        geometry = self.geometry()
        geometry.setSize( QSize(520, 520) )
        self.setGeometry(geometry)
        
        layout = QVBoxLayout()
        layout.addWidget(self.bookmark_tree)
        layout.addWidget(self.note_edit)
        layout.addWidget(self.add_bookmark_button)
        self.setLayout(layout)

        self._load_bookmarks()
        
        self.bookmark_tree.setContextMenuPolicy( Qt.CustomContextMenu )
        self.bookmark_tree.customContextMenuRequested.connect( self.showContextMenu )
        
        self.bookmark_tree.itemDoubleClicked.connect(self._handle_doubleclick)

    def _handle_doubleclick(self, item, col):
        """
        Navigate to the bookmark
        """
        data = item.data(0, Qt.UserRole).toPyObject()
        if data is None:
            return

        (coord, notes) = data
        axes = self.topLevelOperatorView.InputImages.meta.getAxisKeys()
        axes = axes[:-1] # drop channel
        axes = sorted(axes)
        assert len(axes) == len(coord)
        tagged_coord = dict(zip(axes, coord))
        tagged_location = OrderedDict(zip('txyzc', (0,0,0,0,0)))
        tagged_location.update(tagged_coord)
        t = tagged_location.values()[0]
        coord3d = tagged_location.values()[1:4]
        
        self.parent().editor.posModel.time = t
        self.parent().editor.navCtrl.panSlicingViews( coord3d, [0,1,2] )
        self.parent().editor.posModel.slicingPos = coord3d

    def showContextMenu(self, pos):
        item = self.bookmark_tree.itemAt(pos)
        data = item.data(0, Qt.UserRole).toPyObject()
        if data is None:
            return
        
        def delete_bookmark():
            (coord, notes) = data
            bookmarks = list(self.topLevelOperatorView.Bookmarks.value)
            i = bookmarks.index((coord, notes))
            bookmarks.pop(i)
            self.topLevelOperatorView.Bookmarks.setValue(bookmarks)
            self._load_bookmarks()

        menu = QMenu(parent=self)
        menu.addAction( QAction("Delete", menu, triggered=delete_bookmark) )
        globalPos = self.bookmark_tree.viewport().mapToGlobal( pos )
        menu.exec_( globalPos )
        #selection = menu.exec_( globalPos )
        #if selection is removeLanesAction:
        #    self.removeLanesRequested.emit( self._selectedLanes )

    def add_bookmark(self):
        coord_txyzc = self.parent().editor.posModel.slicingPos5D
        tagged_coord_txyzc = dict( zip('txyzc', coord_txyzc) )
        axes = self.topLevelOperatorView.InputImages.meta.getAxisKeys()
        axes = axes[:-1] # drop channel
        axes = sorted(axes)
        coord = tuple(tagged_coord_txyzc[c] for c in axes)

        notes = str(self.note_edit.text())
        bookmarks = list(self.topLevelOperatorView.Bookmarks.value)
        bookmarks.append((coord, notes))
        self.topLevelOperatorView.Bookmarks.setValue(bookmarks)
        
        self._load_bookmarks()
    
    def _load_bookmarks(self):
        self.bookmark_tree.clear()
        lane_index = self.topLevelOperatorView.current_view_index()
        lane_nickname = self.topLevelOperatorView.InputImages.meta.nickname or "Lane {}".format(lane_index)
        bookmarks = self.topLevelOperatorView.Bookmarks.value
        group_item = QTreeWidgetItem( self.bookmark_tree, QStringList(lane_nickname) )

        for coord, notes in bookmarks:
            item = QTreeWidgetItem( group_item, QStringList() )
            item.setText(0, str(coord))
            item.setData(0, Qt.UserRole, (coord, notes))
            item.setText(1, notes)

        self.bookmark_tree.expandAll()
예제 #11
0
class OWKEGGPathwayBrowser(widget.OWWidget):
    name = "KEGG Pathways"
    description = "Browse KEGG pathways that include an input set of genes."
    icon = "../widgets/icons/KEGGPathways.svg"
    priority = 2030

    inputs = [("Data", Orange.data.Table, "SetData", widget.Default),
              ("Reference", Orange.data.Table, "SetRefData")]
    outputs = [("Selected Data", Orange.data.Table, widget.Default),
               ("Unselected Data", Orange.data.Table)]

    settingsHandler = settings.DomainContextHandler()

    organismIndex = settings.ContextSetting(0)
    geneAttrIndex = settings.ContextSetting(0)
    useAttrNames = settings.ContextSetting(False)

    autoCommit = settings.Setting(False)
    autoResize = settings.Setting(True)
    useReference = settings.Setting(False)
    showOrthology = settings.Setting(True)

    Ready, Initializing, Running = 0, 1, 2

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

        self.organismCodes = []
        self._changedFlag = False
        self.__invalidated = False
        self.__runstate = OWKEGGPathwayBrowser.Initializing
        self.__in_setProgress = False

        self.controlArea.setMaximumWidth(250)
        box = gui.widgetBox(self.controlArea, "Info")
        self.infoLabel = gui.widgetLabel(box, "No data on input\n")

        # Organism selection.
        box = gui.widgetBox(self.controlArea, "Organism")
        self.organismComboBox = gui.comboBox(
            box,
            self,
            "organismIndex",
            items=[],
            callback=self.Update,
            addSpace=True,
            tooltip="Select the organism of the input genes")

        # Selection of genes attribute
        box = gui.widgetBox(self.controlArea, "Gene attribute")
        self.geneAttrCandidates = itemmodels.VariableListModel(parent=self)
        self.geneAttrCombo = gui.comboBox(box,
                                          self,
                                          "geneAttrIndex",
                                          callback=self.Update)
        self.geneAttrCombo.setModel(self.geneAttrCandidates)

        gui.checkBox(box,
                     self,
                     "useAttrNames",
                     "Use variable names",
                     disables=[(-1, self.geneAttrCombo)],
                     callback=self.Update)

        self.geneAttrCombo.setDisabled(bool(self.useAttrNames))

        gui.separator(self.controlArea)

        gui.checkBox(self.controlArea,
                     self,
                     "useReference",
                     "From signal",
                     box="Reference",
                     callback=self.Update)

        gui.separator(self.controlArea)

        gui.checkBox(self.controlArea,
                     self,
                     "showOrthology",
                     "Show pathways in full orthology",
                     box="Orthology",
                     callback=self.UpdateListView)

        gui.checkBox(self.controlArea,
                     self,
                     "autoResize",
                     "Resize to fit",
                     box="Image",
                     callback=self.UpdatePathwayViewTransform)

        box = gui.widgetBox(self.controlArea, "Cache Control")

        gui.button(box,
                   self,
                   "Clear cache",
                   callback=self.ClearCache,
                   tooltip="Clear all locally cached KEGG data.",
                   default=False,
                   autoDefault=False)

        gui.separator(self.controlArea)

        gui.auto_commit(self.controlArea, self, "autoCommit", "Commit")

        gui.rubber(self.controlArea)

        spliter = QSplitter(Qt.Vertical, self.mainArea)
        self.pathwayView = PathwayView(self, spliter)
        self.pathwayView.scene().selectionChanged.connect(
            self._onSelectionChanged)
        self.mainArea.layout().addWidget(spliter)

        self.listView = QTreeWidget(allColumnsShowFocus=True,
                                    selectionMode=QTreeWidget.SingleSelection,
                                    sortingEnabled=True,
                                    maximumHeight=200)

        spliter.addWidget(self.listView)

        self.listView.setColumnCount(4)
        self.listView.setHeaderLabels(
            ["Pathway", "P value", "Genes", "Reference"])

        self.listView.itemSelectionChanged.connect(self.UpdatePathwayView)

        select = QAction("Select All", self, shortcut=QKeySequence.SelectAll)
        select.triggered.connect(self.selectAll)
        self.addAction(select)

        self.data = None
        self.refData = None

        self._executor = concurrent.ThreadExecutor()
        self.setEnabled(False)
        self.setBlocking(True)
        progress = concurrent.methodinvoke(self, "setProgress", (float, ))

        def get_genome():
            """Return a KEGGGenome with the common org entries precached."""
            genome = kegg.KEGGGenome()

            essential = genome.essential_organisms()
            common = genome.common_organisms()
            # Remove duplicates of essential from common.
            # (essential + common list as defined here will be used in the
            # GUI.)
            common = [c for c in common if c not in essential]

            # TODO: Add option to specify additional organisms not
            # in the common list.

            keys = list(map(genome.org_code_to_entry_key, essential + common))

            genome.pre_cache(keys, progress_callback=progress)
            return (keys, genome)

        self._genomeTask = task = concurrent.Task(function=get_genome)
        task.finished.connect(self.__initialize_finish)

        self.progressBarInit()
        self.infoLabel.setText("Fetching organism definitions\n")
        self._executor.submit(task)

    def __initialize_finish(self):
        if self.__runstate != OWKEGGPathwayBrowser.Initializing:
            return

        try:
            keys, genome = self._genomeTask.result()
        except Exception as err:
            self.error(0, str(err))
            raise

        self.progressBarFinished()
        self.setEnabled(True)
        self.setBlocking(False)

        entries = [genome[key] for key in keys]
        items = [entry.definition for entry in entries]
        codes = [entry.organism_code for entry in entries]

        self.organismCodes = codes
        self.organismComboBox.clear()
        self.organismComboBox.addItems(items)
        self.organismComboBox.setCurrentIndex(self.organismIndex)

        self.infoLabel.setText("No data on input\n")

    def Clear(self):
        """
        Clear the widget state.
        """
        self.queryGenes = []
        self.referenceGenes = []
        self.genes = {}
        self.uniqueGenesDict = {}
        self.revUniqueGenesDict = {}
        self.pathways = {}
        self.org = None
        self.geneAttrCandidates[:] = []

        self.infoLabel.setText("No data on input\n")
        self.listView.clear()
        self.pathwayView.SetPathway(None)

        self.send("Selected Data", None)
        self.send("Unselected Data", None)

    def SetData(self, data=None):
        if self.__runstate == OWKEGGPathwayBrowser.Initializing:
            self.__initialize_finish()

        self.closeContext()
        self.data = data
        self.warning(0)
        self.error(0)
        self.information(0)

        if data is not None:
            vars = data.domain.variables + data.domain.metas
            vars = [
                var for var in vars
                if isinstance(var, Orange.data.StringVariable)
            ]
            self.geneAttrCandidates[:] = vars

            # Try to guess the gene name variable
            if vars:
                names_lower = [v.name.lower() for v in vars]
                scores = [(name == "gene", "gene" in name)
                          for name in names_lower]
                imax, _ = max(enumerate(scores), key=itemgetter(1))
            else:
                imax = -1

            self.geneAttrIndex = imax

            taxid = data_hints.get_hint(data, "taxid", None)
            if taxid:
                try:
                    code = kegg.from_taxid(taxid)
                    self.organismIndex = self.organismCodes.index(code)
                except Exception as ex:
                    print(ex, taxid)

            self.useAttrNames = data_hints.get_hint(data, "genesinrows",
                                                    self.useAttrNames)
            self.openContext(data)

            if len(self.geneAttrCandidates) == 0:
                self.useAttrNames = True
                self.geneAttrIndex = -1
            else:
                self.geneAttrIndex = min(self.geneAttrIndex,
                                         len(self.geneAttrCandidates) - 1)
        else:
            self.Clear()

        self.__invalidated = True

    def SetRefData(self, data=None):
        self.refData = data
        self.information(1)

        if data is not None and self.useReference:
            self.__invalidated = True

    def handleNewSignals(self):
        if self.__invalidated:
            self.Update()
            self.__invalidated = False

    def UpdateListView(self):
        self.bestPValueItem = None
        self.listView.clear()
        if not self.data:
            return

        allPathways = self.org.pathways()
        allRefPathways = kegg.pathways("map")

        items = []
        kegg_pathways = kegg.KEGGPathways()

        org_code = self.organismCodes[min(self.organismIndex,
                                          len(self.organismCodes) - 1)]

        if self.showOrthology:
            self.koOrthology = kegg.KEGGBrite("ko00001")
            self.listView.setRootIsDecorated(True)
            path_ids = set([s[-5:] for s in self.pathways.keys()])

            def _walkCollect(koEntry):
                num = koEntry.title[:5] if koEntry.title else None
                if num in path_ids:
                    return ([koEntry] +
                            reduce(lambda li, c: li + _walkCollect(c),
                                   [child for child in koEntry.entries], []))
                else:
                    c = reduce(lambda li, c: li + _walkCollect(c),
                               [child for child in koEntry.entries], [])
                    return c + (c and [koEntry] or [])

            allClasses = reduce(lambda li1, li2: li1 + li2,
                                [_walkCollect(c) for c in self.koOrthology],
                                [])

            def _walkCreate(koEntry, lvItem):
                item = QTreeWidgetItem(lvItem)
                id = "path:" + org_code + koEntry.title[:5]

                if koEntry.title[:5] in path_ids:
                    p = kegg_pathways.get_entry(id)
                    if p is None:
                        # In case the genesets still have obsolete entries
                        name = koEntry.title
                    else:
                        name = p.name
                    genes, p_value, ref = self.pathways[id]
                    item.setText(0, name)
                    item.setText(1, "%.5f" % p_value)
                    item.setText(2, "%i of %i" % (len(genes), len(self.genes)))
                    item.setText(3,
                                 "%i of %i" % (ref, len(self.referenceGenes)))
                    item.pathway_id = id if p is not None else None
                else:
                    if id in allPathways:
                        text = kegg_pathways.get_entry(id).name
                    else:
                        text = koEntry.title
                    item.setText(0, text)

                    if id in allPathways:
                        item.pathway_id = id
                    elif "path:map" + koEntry.title[:5] in allRefPathways:
                        item.pathway_id = "path:map" + koEntry.title[:5]
                    else:
                        item.pathway_id = None

                for child in koEntry.entries:
                    if child in allClasses:
                        _walkCreate(child, item)

            for koEntry in self.koOrthology:
                if koEntry in allClasses:
                    _walkCreate(koEntry, self.listView)

            self.listView.update()
        else:
            self.listView.setRootIsDecorated(False)
            pathways = self.pathways.items()
            pathways = sorted(pathways, key=lambda item: item[1][1])

            for id, (genes, p_value, ref) in pathways:
                item = QTreeWidgetItem(self.listView)
                item.setText(0, kegg_pathways.get_entry(id).name)
                item.setText(1, "%.5f" % p_value)
                item.setText(2, "%i of %i" % (len(genes), len(self.genes)))
                item.setText(3, "%i of %i" % (ref, len(self.referenceGenes)))
                item.pathway_id = id
                items.append(item)

        self.bestPValueItem = items and items[0] or None
        self.listView.expandAll()
        for i in range(4):
            self.listView.resizeColumnToContents(i)

        if self.bestPValueItem:
            index = self.listView.indexFromItem(self.bestPValueItem)
            self.listView.selectionModel().select(
                index, QItemSelectionModel.ClearAndSelect)

    def UpdatePathwayView(self):
        items = self.listView.selectedItems()

        if len(items) > 0:
            item = items[0]
        else:
            item = None

        self.commit()
        item = item or self.bestPValueItem
        if not item or not item.pathway_id:
            self.pathwayView.SetPathway(None)
            return

        def get_kgml_and_image(pathway_id):
            """Return an initialized KEGGPathway with pre-cached data"""
            p = kegg.KEGGPathway(pathway_id)
            p._get_kgml()  # makes sure the kgml file is downloaded
            p._get_image_filename()  # makes sure the image is downloaded
            return (pathway_id, p)

        self.setEnabled(False)
        self._pathwayTask = concurrent.Task(
            function=lambda: get_kgml_and_image(item.pathway_id))
        self._pathwayTask.finished.connect(self._onPathwayTaskFinshed)
        self._executor.submit(self._pathwayTask)

    def _onPathwayTaskFinshed(self):
        self.setEnabled(True)
        pathway_id, self.pathway = self._pathwayTask.result()
        self.pathwayView.SetPathway(self.pathway,
                                    self.pathways.get(pathway_id, [[]])[0])

    def UpdatePathwayViewTransform(self):
        self.pathwayView.updateTransform()

    def Update(self):
        """
        Update (recompute enriched pathways) the widget state.
        """
        if not self.data:
            return

        self.error(0)
        self.information(0)

        # XXX: Check data in setData, do not even alow this to be executed if
        # data has no genes
        try:
            genes = self.GeneNamesFromData(self.data)
        except ValueError:
            self.error(0, "Cannot extract gene names from input.")
            genes = []

        if not self.useAttrNames and any("," in gene for gene in genes):
            genes = reduce(add, (split_and_strip(gene, ",") for gene in genes),
                           [])
            self.information(
                0, "Separators detected in input gene names. "
                "Assuming multiple genes per instance.")
        self.queryGenes = genes

        self.information(1)
        reference = None
        if self.useReference and self.refData:
            reference = self.GeneNamesFromData(self.refData)
            if not self.useAttrNames \
                    and any("," in gene for gene in reference):
                reference = reduce(add, (split_and_strip(gene, ",")
                                         for gene in reference), [])
                self.information(
                    1, "Separators detected in reference gene "
                    "names. Assuming multiple genes per "
                    "instance.")

        org_code = self.SelectedOrganismCode()

        def run_enrichment(org_code, genes, reference=None, progress=None):
            org = kegg.KEGGOrganism(org_code)
            if reference is None:
                reference = org.get_genes()

            # Map 'genes' and 'reference' sets to unique KEGG identifiers
            unique_genes, _, _ = org.get_unique_gene_ids(set(genes))
            unique_ref_genes, _, _ = org.get_unique_gene_ids(set(reference))

            taxid = kegg.to_taxid(org.org_code)
            # Map the taxid back to standard 'common' taxids
            # (as used by 'geneset') if applicable
            r_tax_map = dict(
                (v, k) for k, v in kegg.KEGGGenome.TAXID_MAP.items())
            if taxid in r_tax_map:
                taxid = r_tax_map[taxid]

            # We use the kegg pathway gene sets provided by 'geneset' for
            # the enrichment calculation.

            # Ensure we are using the latest genesets
            # TODO: ?? Is updating the index enough?
            serverfiles.update(geneset.sfdomain, "index.pck")
            kegg_gs_collections = geneset.collections(
                (("KEGG", "pathways"), taxid))

            pathways = pathway_enrichment(kegg_gs_collections,
                                          unique_genes.keys(),
                                          unique_ref_genes.keys(),
                                          callback=progress)
            # Ensure that pathway entries are pre-cached for later use in the
            # list/tree view
            kegg_pathways = kegg.KEGGPathways()
            kegg_pathways.pre_cache(pathways.keys(),
                                    progress_callback=progress)

            return pathways, org, unique_genes, unique_ref_genes

        self.progressBarInit()
        self.setEnabled(False)
        self.infoLabel.setText("Retrieving...\n")

        progress = concurrent.methodinvoke(self, "setProgress", (float, ))
        self._enrichTask = concurrent.Task(function=lambda: run_enrichment(
            org_code, genes, reference, progress))
        self._enrichTask.finished.connect(self._onEnrichTaskFinished)
        self._executor.submit(self._enrichTask)

    def _onEnrichTaskFinished(self):
        self.setEnabled(True)
        self.setBlocking(False)
        try:
            pathways, org, unique_genes, unique_ref_genes = \
                self._enrichTask.result()
        except Exception:
            raise

        self.progressBarFinished()

        self.org = org
        self.genes = unique_genes.keys()
        self.uniqueGenesDict = unique_genes
        self.revUniqueGenesDict = dict([
            (val, key) for key, val in self.uniqueGenesDict.items()
        ])
        self.referenceGenes = unique_ref_genes.keys()
        self.pathways = pathways

        if not self.pathways:
            self.warning(0, "No enriched pathways found.")
        else:
            self.warning(0)

        count = len(set(self.queryGenes))
        self.infoLabel.setText("%i unique gene names on input\n"
                               "%i (%.1f%%) genes names matched" %
                               (count, len(unique_genes), 100.0 *
                                len(unique_genes) / count if count else 0.0))

        self.UpdateListView()

    @Slot(float)
    def setProgress(self, value):
        if self.__in_setProgress:
            return

        self.__in_setProgress = True
        self.progressBarSet(value)
        self.__in_setProgress = False

    def GeneNamesFromData(self, data):
        """
        Extract and return gene names from `data`.
        """
        if self.useAttrNames:
            genes = [str(v.name).strip() for v in data.domain.attributes]
        elif self.geneAttrCandidates:
            assert 0 <= self.geneAttrIndex < len(self.geneAttrCandidates)
            geneAttr = self.geneAttrCandidates[self.geneAttrIndex]
            genes = [
                str(e[geneAttr]) for e in data if not numpy.isnan(e[geneAttr])
            ]
        else:
            raise ValueError("No gene names in data.")
        return genes

    def SelectedOrganismCode(self):
        """
        Return the selected organism code.
        """
        return self.organismCodes[min(self.organismIndex,
                                      len(self.organismCodes) - 1)]

    def selectAll(self):
        """
        Select all items in the pathway view.
        """
        changed = False
        scene = self.pathwayView.scene()
        with disconnected(scene.selectionChanged, self._onSelectionChanged):
            for item in scene.items():
                if item.flags() & QGraphicsItem.ItemIsSelectable and \
                        not item.isSelected():
                    item.setSelected(True)
                    changed = True
        if changed:
            self._onSelectionChanged()

    def _onSelectionChanged(self):
        # Item selection in the pathwayView/scene has changed
        self.commit()

    def commit(self):
        if self.data:
            selectedItems = self.pathwayView.scene().selectedItems()
            selectedGenes = reduce(
                set.union, [item.marked_objects for item in selectedItems],
                set())

            if self.useAttrNames:
                selected = [
                    self.data.domain[self.uniqueGenesDict[gene]]
                    for gene in selectedGenes
                ]
                #                 newDomain = Orange.data.Domain(selectedVars, 0)
                data = self.data[:, selected]
                #                 data = Orange.data.Table(newDomain, self.data)
                self.send("Selected Data", data)
            elif self.geneAttrCandidates:
                assert 0 <= self.geneAttrIndex < len(self.geneAttrCandidates)
                geneAttr = self.geneAttrCandidates[self.geneAttrIndex]
                selectedIndices = []
                otherIndices = []
                for i, ex in enumerate(self.data):
                    names = [
                        self.revUniqueGenesDict.get(name, None)
                        for name in split_and_strip(str(ex[geneAttr]), ",")
                    ]
                    if any(name and name in selectedGenes for name in names):
                        selectedIndices.append(i)
                    else:
                        otherIndices.append(i)

                if selectedIndices:
                    selected = self.data[selectedIndices]
                else:
                    selected = None

                if otherIndices:
                    other = self.data[otherIndices]
                else:
                    other = None

                self.send("Selected Data", selected)
                self.send("Unselected Data", other)
        else:
            self.send("Selected Data", None)
            self.send("Unselected Data", None)

    def ClearCache(self):
        kegg.caching.clear_cache()

    def onDeleteWidget(self):
        """
        Called before the widget is removed from the canvas.
        """
        super().onDeleteWidget()

        self.org = None
        self._executor.shutdown(wait=False)
        gc.collect()  # Force collection (WHY?)

    def sizeHint(self):
        return QSize(1024, 720)
예제 #12
0
class OWKEGGPathwayBrowser(OWWidget):
    settingsList = ["organismIndex", "geneAttrIndex", "autoCommit",
                    "autoResize", "useReference", "useAttrNames",
                    "showOrthology"]

    contextHandlers = {
        "": DomainContextHandler(
            "",
            [ContextField("organismIndex",
                          DomainContextHandler.Required +
                          DomainContextHandler.IncludeMetaAttributes),
             ContextField("geneAttrIndex",
                          DomainContextHandler.Required +
                          DomainContextHandler.IncludeMetaAttributes),
             ContextField("useAttrNames",
                          DomainContextHandler.Required +
                          DomainContextHandler.IncludeMetaAttributes)]
        )
    }

    def __init__(self, parent=None, signalManager=None, name="KEGG Pathways"):
        OWWidget.__init__(self, parent, signalManager, name, wantGraph=True)
        self.inputs = [("Examples", Orange.data.Table, self.SetData),
                       ("Reference", Orange.data.Table, self.SetRefData)]
        self.outputs = [("Selected Examples", Orange.data.Table),
                        ("Unselected Examples", Orange.data.Table)]
        self.organismIndex = 0
        self.geneAttrIndex = 0
        self.autoCommit = False
        self.autoResize = True
        self.useReference = False
        self.useAttrNames = 0
        self.showOrthology = True

        self.loadSettings()

        self.organismCodes = []
        self._changedFlag = False

        self.controlArea.setMaximumWidth(250)
        box = OWGUI.widgetBox(self.controlArea, "Info")
        self.infoLabel = OWGUI.widgetLabel(box, "No data on input\n")

        # Organism selection.
        box = OWGUI.widgetBox(self.controlArea, "Organism")
        self.organismComboBox = OWGUI.comboBox(
            box, self, "organismIndex",
            items=[],
            callback=self.Update,
            addSpace=True,
            debuggingEnabled=0,
            tooltip="Select the organism of the input genes")

        # Selection of genes attribute
        box = OWGUI.widgetBox(self.controlArea, "Gene attribute")
        self.geneAttrCandidates = VariableListModel(parent=self)
        self.geneAttrCombo = OWGUI.comboBox(
            box, self, "geneAttrIndex", callback=self.Update)
        self.geneAttrCombo.setModel(self.geneAttrCandidates)

        OWGUI.checkBox(box, self, "useAttrNames",
                       "Use variable names",
                       disables=[(-1, self.geneAttrCombo)],
                       callback=self.Update)

        self.geneAttrCombo.setDisabled(bool(self.useAttrNames))

        OWGUI.separator(self.controlArea)

        OWGUI.checkBox(self.controlArea, self, "useReference",
                       "From signal",
                       box="Reference",
                       callback=self.Update)

        OWGUI.separator(self.controlArea)

        OWGUI.checkBox(self.controlArea, self, "showOrthology",
                       "Show pathways in full orthology",
                       box="Orthology",
                       callback=self.UpdateListView)

        OWGUI.checkBox(self.controlArea, self, "autoResize",
                       "Resize to fit",
                       box="Image",
                       callback=self.UpdatePathwayViewTransform)

        box = OWGUI.widgetBox(self.controlArea, "Cache Control")

        OWGUI.button(box, self, "Clear cache",
                     callback=self.ClearCache,
                     tooltip="Clear all locally cached KEGG data.")

        OWGUI.separator(self.controlArea)

        box = OWGUI.widgetBox(self.controlArea, "Selection")
        cb = OWGUI.checkBox(box, self, "autoCommit", "Commit on update")
        button = OWGUI.button(box, self, "Commit", callback=self.Commit,
                              default=True)
        OWGUI.setStopper(self, button, cb, "_changedFlag", self.Commit)

        OWGUI.rubber(self.controlArea)

        spliter = QSplitter(Qt.Vertical, self.mainArea)
        self.pathwayView = PathwayView(self, spliter)
        self.pathwayView.scene().selectionChanged.connect(
            self._onSelectionChanged
        )
        self.mainArea.layout().addWidget(spliter)

        self.listView = QTreeWidget(spliter)
        spliter.addWidget(self.listView)

        self.listView.setAllColumnsShowFocus(1)
        self.listView.setColumnCount(4)
        self.listView.setHeaderLabels(["Pathway", "P value",
                                       "Genes", "Reference"])

        self.listView.setSelectionMode(QTreeWidget.SingleSelection)

        self.listView.setSortingEnabled(True)

        self.listView.setMaximumHeight(200)

        self.connect(self.listView,
                     SIGNAL("itemSelectionChanged()"),
                     self.UpdatePathwayView)

        self.connect(self.graphButton,
                     SIGNAL("clicked()"),
                     self.saveGraph)

        select = QAction(
            "Select All", self,
            shortcut=QKeySequence.SelectAll
        )
        select.triggered.connect(self.selectAll)
        self.addAction(select)

        self.data = None
        self.refData = None

        self.resize(800, 600)

        self.connect(self,
                     SIGNAL("widgetStateChanged(QString, int, QString)"),
                     self.onStateChange)

        self.has_new_data = False
        self.has_new_reference_set = False

        self._executor = ThreadExecutor()
        self.setEnabled(False)
        self.setBlocking(True)
        QTimer.singleShot(0, self._initialize)
        self.infoLabel.setText("Fetching organism definitions\n")

    def _initialize(self):
        # First try to import slumber to see if we can even use the
        # kegg module.
        try:
            import slumber
        except ImportError:
            QMessageBox.warning(self,
                "'slumber' library required.",
                '<p>Please install '
                '<a href="http://pypi.python.org/pypi/slumber">slumber</a> '
                'library to use KEGG Pathways widget.</p>'
            )
            self.infoLabel.setText(
                '<p>Please install '
                '<a href="http://pypi.python.org/pypi/slumber">slumber</a> '
                'library to use KEGG Pathways widget.</p>'
            )
            self.error(0, "Missing slumber/requests library")
            return

        progress = methodinvoke(self, "setProgress", (float,))

        def get_genome():
            """Return a KEGGGenome with the common org entries precached."""
            genome = kegg.KEGGGenome()

            essential = genome.essential_organisms()
            common = genome.common_organisms()
            # Remove duplicates of essential from common.
            # (essential + common list as defined here will be used in the
            # GUI.)
            common = [c for c in common if c not in essential]

            # TODO: Add option to specify additional organisms not
            # in the common list.

            keys = map(genome.org_code_to_entry_key, essential + common)

            genome.pre_cache(keys, progress_callback=progress)
            return (keys, genome)

        self._genomeTask = task = Task(function=get_genome)
        task.finished.connect(self._initializeOrganisms)

        self.progressBarInit()
        self._executor.submit(task)

    def _initializeOrganisms(self):
        self.progressBarFinished()
        try:
            keys, genome = self._genomeTask.result()
        except Exception as err:
            self.error(0, str(err))
            return

        entries = [genome[key] for key in keys]
        items = [entry.definition for entry in entries]
        codes = [entry.organism_code for entry in entries]

        self.organismCodes = codes
        self.organismComboBox.clear()
        self.organismComboBox.addItems(items)
        self.organismComboBox.setCurrentIndex(self.organismIndex)

        self.setEnabled(True)
        self.setBlocking(False)
        self.infoLabel.setText("No data on input\n")

    def Clear(self):
        """
        Clear the widget state.
        """
        self.queryGenes = []
        self.referenceGenes = []
        self.genes = {}
        self.uniqueGenesDict = {}
        self.revUniqueGenesDict = {}
        self.pathways = {}
        self.org = None
        self.geneAttrCandidates[:] = []

        self.infoLabel.setText("No data on input\n")
        self.listView.clear()
        self.pathwayView.SetPathway(None)

        self.send("Selected Examples", None)
        self.send("Unselected Examples", None)

    def SetData(self, data=None):
        self.closeContext()
        self.data = data
        self.warning(0)
        self.error(0)
        self.information(0)

        if data is not None:
            vars = data.domain.variables + data.domain.getmetas().values()
            vars = [var for var in vars
                    if isinstance(var, (Orange.feature.String,
                                        Orange.feature.Discrete))]
            self.geneAttrCandidates[:] = vars

            # Try to guess the gene name variable
            names_lower = [v.name.lower() for v in vars]
            scores = [(name == "gene", "gene" in name)
                      for name in names_lower]
            imax, _ = max(enumerate(scores), key=itemgetter(1))
            self.geneAttrIndex = imax

            taxid = data_hints.get_hint(data, "taxid", None)
            if taxid:
                try:
                    code = kegg.from_taxid(taxid)
                    self.organismIndex = self.organismCodes.index(code)
                except Exception as ex:
                    print ex, taxid

            self.useAttrNames = data_hints.get_hint(data, "genesinrows",
                                                    self.useAttrNames)

            self.openContext("", data)
        else:
            self.Clear()

        self.has_new_data = True

    def SetRefData(self, data=None):
        self.refData = data
        self.information(1)

        self.has_new_reference_set = True

    def handleNewSignals(self):
        if self.has_new_data or (self.has_new_reference_set and \
                                 self.useReference):
            self.Update()

            self.has_new_data = False
            self.has_new_reference_set = False

    def UpdateListView(self):
        self.bestPValueItem = None
        self.listView.clear()
        if not self.data:
            return

        allPathways = self.org.pathways()
        allRefPathways = kegg.pathways("map")

        items = []
        kegg_pathways = kegg.KEGGPathways()

        org_code = self.organismCodes[min(self.organismIndex,
                                          len(self.organismCodes) - 1)]

        if self.showOrthology:
            self.koOrthology = kegg.KEGGBrite("ko00001")
            self.listView.setRootIsDecorated(True)
            path_ids = set([s[-5:] for s in self.pathways.keys()])

            def _walkCollect(koEntry):
                num = koEntry.title[:5] if koEntry.title else None
                if num in path_ids:
                    return ([koEntry] +
                            reduce(lambda li, c: li + _walkCollect(c),
                                   [child for child in koEntry.entries],
                                   []))
                else:
                    c = reduce(lambda li, c: li + _walkCollect(c),
                               [child for child in koEntry.entries],
                               [])
                    return c + (c and [koEntry] or [])

            allClasses = reduce(lambda li1, li2: li1 + li2,
                                [_walkCollect(c) for c in self.koOrthology],
                                [])

            def _walkCreate(koEntry, lvItem):
                item = QTreeWidgetItem(lvItem)
                id = "path:" + org_code + koEntry.title[:5]

                if koEntry.title[:5] in path_ids:
                    p = kegg_pathways.get_entry(id)
                    if p is None:
                        # In case the genesets still have obsolete entries
                        name = koEntry.title
                    else:
                        name = p.name
                    genes, p_value, ref = self.pathways[id]
                    item.setText(0, name)
                    item.setText(1, "%.5f" % p_value)
                    item.setText(2, "%i of %i" % (len(genes), len(self.genes)))
                    item.setText(3, "%i of %i" % (ref, len(self.referenceGenes)))
                    item.pathway_id = id if p is not None else None
                else:
                    if id in allPathways:
                        text = kegg_pathways.get_entry(id).name
                    else:
                        text = koEntry.title
                    item.setText(0, text)

                    if id in allPathways:
                        item.pathway_id = id
                    elif "path:map" + koEntry.title[:5] in allRefPathways:
                        item.pathway_id = "path:map" + koEntry.title[:5]
                    else:
                        item.pathway_id = None

                for child in koEntry.entries:
                    if child in allClasses:
                        _walkCreate(child, item)

            for koEntry in self.koOrthology:
                if koEntry in allClasses:
                    _walkCreate(koEntry, self.listView)

            self.listView.update()
        else:
            self.listView.setRootIsDecorated(False)
            pathways = self.pathways.items()
            pathways.sort(lambda a, b: cmp(a[1][1], b[1][1]))

            for id, (genes, p_value, ref) in pathways:
                item = QTreeWidgetItem(self.listView)
                item.setText(0, kegg_pathways.get_entry(id).name)
                item.setText(1, "%.5f" % p_value)
                item.setText(2, "%i of %i" % (len(genes), len(self.genes)))
                item.setText(3, "%i of %i" % (ref, len(self.referenceGenes)))
                item.pathway_id = id
                items.append(item)

        self.bestPValueItem = items and items[0] or None
        self.listView.expandAll()
        for i in range(4):
            self.listView.resizeColumnToContents(i)

        if self.bestPValueItem:
            index = self.listView.indexFromItem(self.bestPValueItem)
            self.listView.selectionModel().select(
                index, QItemSelectionModel.ClearAndSelect
            )

    def UpdatePathwayView(self):
        items = self.listView.selectedItems()

        if len(items) > 0:
            item = items[0]
        else:
            item = None

        self.Commit()
        item = item or self.bestPValueItem
        if not item or not item.pathway_id:
            self.pathwayView.SetPathway(None)
            return

        def get_kgml_and_image(pathway_id):
            """Return an initialized KEGGPathway with pre-cached data"""
            p = kegg.KEGGPathway(pathway_id)
            p._get_kgml()  # makes sure the kgml file is downloaded
            p._get_image_filename()  # makes sure the image is downloaded
            return (pathway_id, p)

        self.setEnabled(False)
        self._pathwayTask = Task(
            function=lambda: get_kgml_and_image(item.pathway_id)
        )
        self._pathwayTask.finished.connect(self._onPathwayTaskFinshed)
        self._executor.submit(self._pathwayTask)

    def _onPathwayTaskFinshed(self):
        self.setEnabled(True)
        pathway_id, self.pathway = self._pathwayTask.result()
        self.pathwayView.SetPathway(
            self.pathway,
            self.pathways.get(pathway_id, [[]])[0]
        )

    def UpdatePathwayViewTransform(self):
        self.pathwayView.updateTransform()

    def Update(self):
        """
        Update (recompute enriched pathways) the widget state.
        """
        if not self.data:
            return

        self.error(0)
        self.information(0)

        # XXX: Check data in setData, do not even alow this to be executed if
        # data has no genes
        try:
            genes = self.GeneNamesFromData(self.data)
        except ValueError:
            self.error(0, "Cannot extract gene names from input.")
            genes = []

        if not self.useAttrNames and any("," in gene for gene in genes):
            genes = reduce(add, (split_and_strip(gene, ",")
                                 for gene in genes),
                           [])
            self.information(0,
                             "Separators detected in input gene names. "
                             "Assuming multiple genes per instance.")
        self.queryGenes = genes

        self.information(1)
        reference = None
        if self.useReference and self.refData:
            reference = self.GeneNamesFromData(self.refData)
            if not self.useAttrNames \
                    and any("," in gene for gene in reference):
                reference = reduce(add, (split_and_strip(gene, ",")
                                         for gene in reference),
                                   [])
                self.information(1,
                                 "Separators detected in reference gene "
                                 "names. Assuming multiple genes per "
                                 "instance.")

        org_code = self.SelectedOrganismCode()

        def run_enrichment(org_code, genes, reference=None, progress=None):
            org = kegg.KEGGOrganism(org_code)
            if reference is None:
                reference = org.get_genes()

            # Map 'genes' and 'reference' sets to unique KEGG identifiers
            unique_genes, _, _ = org.get_unique_gene_ids(set(genes))
            unique_ref_genes, _, _ = org.get_unique_gene_ids(set(reference))

            taxid = kegg.to_taxid(org.org_code)
            # Map the taxid back to standard 'common' taxids
            # (as used by 'geneset') if applicable
            r_tax_map = dict((v, k) for k, v in
                             kegg.KEGGGenome.TAXID_MAP.items())
            if taxid in r_tax_map:
                taxid = r_tax_map[taxid]

            # We use the kegg pathway gene sets provided by 'geneset' for
            # the enrichment calculation.

            # Ensure we are using the latest genesets
            # TODO: ?? Is updating the index enough?
            serverfiles.update(geneset.sfdomain, "index.pck")
            kegg_gs_collections = geneset.collections(
                (("KEGG", "pathways"), taxid)
            )

            pathways = pathway_enrichment(
                kegg_gs_collections, unique_genes.keys(),
                unique_ref_genes.keys(),
                callback=progress
            )
            # Ensure that pathway entries are pre-cached for later use in the
            # list/tree view
            kegg_pathways = kegg.KEGGPathways()
            kegg_pathways.pre_cache(
                pathways.keys(), progress_callback=progress
            )

            return pathways, org, unique_genes, unique_ref_genes

        self.progressBarInit()
        self.setEnabled(False)
        self.infoLabel.setText("Retrieving...\n")

        progress = methodinvoke(self, "setProgress", (float,))
        self._enrichTask = Task(
            function=lambda:
                run_enrichment(org_code, genes, reference, progress)
        )
        self._enrichTask.finished.connect(self._onEnrichTaskFinished)
        self._executor.submit(self._enrichTask)

    def _onEnrichTaskFinished(self):
        self.setEnabled(True)
        self.setBlocking(False)

        self.progressBarFinished()
        try:
            pathways, org, unique_genes, unique_ref_genes = \
                self._enrichTask.result()
        except Exception:
            raise

        self.org = org
        self.genes = unique_genes.keys()
        self.uniqueGenesDict = unique_genes
        self.revUniqueGenesDict = dict([(val, key) for key, val in
                                        self.uniqueGenesDict.items()])
        self.referenceGenes = unique_ref_genes.keys()
        self.pathways = pathways

        if not self.pathways:
            self.warning(0, "No enriched pathways found.")
        else:
            self.warning(0)

        count = len(set(self.queryGenes))
        self.infoLabel.setText(
            "%i unique gene names on input\n"
            "%i (%.1f%%) genes names matched" %
            (count, len(unique_genes),
             100.0 * len(unique_genes) / count if count else 0.0)
        )

        self.UpdateListView()

    @pyqtSlot(float)
    def setProgress(self, value):
        self.progressBarValue = value

    def GeneNamesFromData(self, data):
        """
        Extract and return gene names from `data`.
        """
        if self.useAttrNames:
            genes = [str(v.name).strip() for v in data.domain.attributes]
        elif self.geneAttrCandidates:
            index = min(self.geneAttrIndex, len(self.geneAttrCandidates) - 1)
            geneAttr = self.geneAttrCandidates[index]
            genes = [str(e[geneAttr]) for e in data
                     if not e[geneAttr].isSpecial()]
        else:
            raise ValueError("No gene names in data.")
        return genes

    def SelectedOrganismCode(self):
        """
        Return the selected organism code.
        """
        return self.organismCodes[min(self.organismIndex,
                                      len(self.organismCodes) - 1)]

    def selectAll(self):
        """
        Select all items in the pathway view.
        """
        changed = False
        scene = self.pathwayView.scene()
        with disconnected(scene.selectionChanged, self._onSelectionChanged):
            for item in scene.items():
                if item.flags() & QGraphicsItem.ItemIsSelectable and \
                        not item.isSelected():
                    item.setSelected(True)
                    changed = True
        if changed:
            self._onSelectionChanged()

    def _onSelectionChanged(self):
        # Item selection in the pathwayView/scene has changed
        if self.autoCommit:
            self.Commit()
        else:
            self._changedFlag = True

    def Commit(self):
        if self.data:
            selectedItems = self.pathwayView.scene().selectedItems()
            selectedGenes = reduce(set.union, [item.marked_objects
                                               for item in selectedItems],
                                   set())

            if self.useAttrNames:
                selectedVars = [self.data.domain[self.uniqueGenesDict[gene]]
                                for gene in selectedGenes]
                newDomain = Orange.data.Domain(selectedVars, 0)
                data = Orange.data.Table(newDomain, self.data)
                self.send("Selected Examples", data)
            elif self.geneAttrCandidates:
                geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex,
                                                       len(self.geneAttrCandidates) - 1)]
                selectedExamples = []
                otherExamples = []
                for ex in self.data:
                    names = [self.revUniqueGenesDict.get(name, None)
                             for name in split_and_strip(str(ex[geneAttr]), ",")]
                    if any(name and name in selectedGenes for name in names):
                        selectedExamples.append(ex)
                    else:
                        otherExamples.append(ex)

                if selectedExamples:
                    selectedExamples = Orange.data.Table(selectedExamples)
                else:
                    selectedExamples = None

                if otherExamples:
                    otherExamples = Orange.data.Table(otherExamples)
                else:
                    otherExamples = None

                self.send("Selected Examples", selectedExamples)
                self.send("Unselected Examples", otherExamples)
        else:
            self.send("Selected Examples", None)
            self.send("Unselected Examples", None)

    def ClearCache(self):
        from ..kegg import caching
        try:
            caching.clear_cache()
        except Exception, ex:
            QMessageBox.warning(self, "Cache clear", ex.args[0])
예제 #13
0
class mainwindow(QtGui.QMainWindow):
    '''主窗体'''
    def __init__(self):
        super(mainwindow, self).__init__()
        self.setWindowTitle('组件设计工具')
        self.setWindowIcon(QIcon(':/image/组件设计工具.png'))

        self.setMinimumWidth(1024)
        self.setMinimumHeight(800)

        self.showMaximized()
        self.menuBar().show()
        self.createMenus()

        #self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)

        labelSizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        editSizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)

        cwVLayout = QVBoxLayout()
        cwHLayout = QHBoxLayout()

        lLayout = QVBoxLayout()
        rLayout = QVBoxLayout()
        self.lw = QListWidget()
        self.lw.setSelectionMode(QAbstractItemView.SingleSelection)

        lLayout.addWidget(self.lw)
        self.lw.itemSelectionChanged.connect(self.on_select)

        lGroup = QGroupBox('项目列表')
        lGroup.setLayout(lLayout)
        cwHLayout.addWidget(lGroup, 2)
        lGroup.setContentsMargins(0, 12, 0, 22)

        tLayout = QVBoxLayout()
        bLayout = QHBoxLayout()

        self.tGroup = QGroupBox('配置信息')
        self.bGroup = QGroupBox('生成代码')
        self.tGroup.setLayout(tLayout)
        self.tGroup.setEnabled(False)
        self.bGroup.setLayout(bLayout)
        self.bGroup.setEnabled(False)

        cwHLayout.addWidget(self.tGroup, 8)
        cwVLayout.addLayout(cwHLayout)
        cwVLayout.addWidget(self.bGroup)

        self.tw_config = QTreeWidget()
        headerLabels = QStringList()
        headerLabels.append('       项目')
        headerLabels.append('       值')
        self.tw_config.setHeaderLabels(headerLabels)
        self.tw_config.setColumnWidth(0, 312)
        self.tw_config.setColumnWidth(1, 660)
        thLayout = QHBoxLayout()
        thLayout.setContentsMargins(0, 6, 0, 0)
        thLayout.addSpacing(10)
        modify_btn = QPushButton('')  #修改
        modify_btn.setObjectName('modify_btn')
        modify_btn.clicked.connect(self.on_modify)
        del_btn = QPushButton('')  #删除
        del_btn.setObjectName('del_btn')
        del_btn.clicked.connect(self.on_del)
        thLayout.addWidget(modify_btn)
        thLayout.addWidget(del_btn)
        thLayout.addStretch(0)

        tLayout.addLayout(thLayout)
        tLayout.addWidget(self.tw_config)

        bhLayout = QHBoxLayout()

        lable1 = QLabel('工程名称:')
        lable1.setSizePolicy(labelSizePolicy)
        self.et_project_name = QLineEdit()
        self.et_project_name.setSizePolicy(editSizePolicy)
        bhLayout.addWidget(lable1)
        bhLayout.addWidget(self.et_project_name)
        bhLayout.addSpacing(16)

        lable2 = QLabel('工程位置:')
        lable2.setSizePolicy(labelSizePolicy)
        self.et_project_location = QLineEdit()
        self.et_project_location.setReadOnly(True)
        self.et_project_location.setSizePolicy(editSizePolicy)
        btn_location = QPushButton('')  #打开
        btn_location.setObjectName('btn_location')
        btn_location.setSizePolicy(labelSizePolicy)
        btn_location.clicked.connect(self.getProjectLocation)
        bhLayout.addWidget(lable2)
        bhLayout.addWidget(self.et_project_location)
        bhLayout.addSpacing(10)
        bhLayout.addWidget(btn_location)

        #bhLayout.addStretch(0)
        gen_btn = QPushButton('')  # 生成
        gen_btn.setObjectName('gen_btn')
        gen_btn.setSizePolicy(labelSizePolicy)
        gen_btn.clicked.connect(self.on_gen)
        bhLayout.addSpacing(45)
        bhLayout.addWidget(gen_btn)

        bLayout.addLayout(bhLayout)
        bLayout.setContentsMargins(10, 24, 22, 34)

        statusBar = self.statusBar()
        sBH = QHBoxLayout()
        copyright = QLabel('')
        copyright.setAlignment(QtCore.Qt.AlignCenter)
        copyright.setStyleSheet("color:#acacac")
        statusBar.setMinimumHeight(30)
        statusBar.addWidget(copyright, 10)

        cw = QWidget()
        cw.setLayout(cwVLayout)
        self.setCentralWidget(cw)
        self._initByConfig()
        self.setMinimumSize(400, 200)

    def _initByConfig(self):
        '''初始化'''
        pass

    def createMenus(self):
        '''创建菜单'''
        self.ToolBar = self.addToolBar('')

        self.ToolBar.setMinimumHeight(54)

        newBtn = QToolButton()
        newBtn.setText('创建项目')
        newBtn.setIcon(QIcon(':/image/创建项目.png'))
        newBtn.setToolButtonStyle(3)
        newBtn.setFixedWidth(99)

        OpenBtn = QToolButton()
        OpenBtn.setText('打开项目')
        OpenBtn.setIcon(QIcon(':/image/打开.png'))
        OpenBtn.setToolButtonStyle(3)
        OpenBtn.setFixedWidth(99)

        AboutBtn = QToolButton()
        AboutBtn.setText('关于')
        AboutBtn.setIcon(QIcon(':/image/关于.png'))
        AboutBtn.setToolButtonStyle(3)
        AboutBtn.setFixedWidth(99)

        HelpBtn = QToolButton()
        HelpBtn.setText('帮助')
        HelpBtn.setIcon(QIcon(':/image/帮助.png'))
        HelpBtn.setToolButtonStyle(3)
        HelpBtn.setFixedWidth(99)

        newBtn.clicked.connect(self.on_new)
        OpenBtn.clicked.connect(self.on_open)
        AboutBtn.clicked.connect(self.on_about)
        HelpBtn.clicked.connect(self.on_help)

        self.ToolBar.addWidget(newBtn)
        self.ToolBar.addWidget(OpenBtn)
        self.ToolBar.addWidget(AboutBtn)
        self.ToolBar.addWidget(HelpBtn)
        self.ToolBar.setMovable(False)
        self.ToolBar.setVisible(True)

    def on_help(self):
        app.g_pwd = os.getcwd()
        if not (QtGui.QDesktopServices.openUrl(
                QUrl.fromLocalFile(app.g_pwd + os.sep + 'image' + os.sep +
                                   'help.pdf'))):
            print app.g_pwd + os.sep + '/image/help.pdf'
            QMessageBox.critical(None, "Failure", "Cannot open help manual")

    def on_about(self):
        abt = AboutDlg()
        abt.exec_()

    def on_new(self):
        '''新建向导'''
        app.g_configurations = Configuration()  # 用来渲染的配置数据
        dlg = wizard.MyWizard()
        if dlg.exec_():
            app.g_configurations.initialized = True
            app.g_projects.append(app.g_configurations)
            content = app.g_configurations.toJson()
            self.path = QFileDialog.getSaveFileName(
                self, "选择模板保存的路径",
                app.g_pwd + os.sep + "configurations" + os.sep +
                app.g_configurations.project_name.encode('utf-8') + ".json",
                "Config (*.json)")
            fileInfo = QFileInfo(self.path)
            if not self.path.isEmpty():
                path = app.QString2str(self.path)
                with open(path, 'w+') as f:
                    f.write(content)
                self.addConfig(fileInfo.baseName(), fileInfo.filePath(),
                               content)
                #self.lw.addItem(app.g_configurations.project_name)

    def getProjectLocation(self):
        '''获取项目路径'''
        path = QFileDialog.getExistingDirectory()
        path = QDir.fromNativeSeparators(path)
        self.et_project_location.setText(path)

    def on_open(self):
        '''打开现有配置'''
        fileName = QFileDialog.getOpenFileName(
            self, "选择现有模板", app.g_pwd + os.sep + "configurations",
            "Config (*.json)")
        if fileName.isEmpty():
            return
        self.path = fileName
        with open(app.QString2str(fileName), 'r') as f:
            content = f.read()

        fileInfo = QFileInfo(fileName)
        if not fileInfo.exists():
            return
        config = Configuration()
        config.fromJson(content)
        config.allone_dir = os.getenv('ALLONEDIR', '../..').replace('\\', '/')
        self.addConfig(fileInfo.baseName(), fileInfo.filePath(), content)
        self.on_select()

    def on_del(self):
        self.tw_config.clear()
        self.bGroup.setEnabled(False)
        self.tGroup.setEnabled(False)
        index = self.lw.currentRow()
        self.lw.takeItem(index)

    def on_select(self):
        '''选取配置'''
        item = self.lw.currentItem()
        if item != None:
            content = item.data(QtCore.Qt.UserRole).toString()
            config = Configuration()
            config.fromJson(app.QString2str(content))
            self.currentConfig = config
            self.showConfigInfo(self.currentConfig)
            self.bGroup.setEnabled(True)
            self.path = item.data(QtCore.Qt.UserRole + 1).toString()

        # index = self.lw.currentRow()
        # if index < len(app.g_projects):
        #     self.currentConfig = app.g_projects[index]
        #     self.showConfigInfo(self.currentConfig)
        #     self.bGroup.setEnabled(True)

    def addConfig(self, fileName, filePath, config):
        item = QListWidgetItem(fileName)
        item.setData(QtCore.Qt.UserRole, config)
        item.setData(QtCore.Qt.UserRole + 1, filePath)
        self.lw.addItem(item)
        self.lw.setCurrentRow(0)

    def showConfigInfo(self, cf):
        '''显示配置信息'''
        self.tw_config.clear()
        self.et_project_name.setText(cf.project_name)
        self.et_project_location.setText(cf.project_location)
        sr = QStringList()
        sr.append('信息')
        root1 = QTreeWidgetItem(sr)
        sr = QStringList()
        sr.append('Qt库')
        root2 = QTreeWidgetItem(sr)
        sr = QStringList()
        sr.append('模块')
        root3a = QTreeWidgetItem(sr)
        sr = QStringList()
        sr.append('第三方库')
        root3b = QTreeWidgetItem(sr)
        sr = QStringList()
        sr.append('接口')
        root4 = QTreeWidgetItem(sr)

        self.tw_config.addTopLevelItem(root1)
        self.tw_config.addTopLevelItem(root2)
        self.tw_config.addTopLevelItem(root3a)
        self.tw_config.addTopLevelItem(root3b)
        self.tw_config.addTopLevelItem(root4)

        sr1c00 = QStringList()
        sr1c00.append("项目名称")
        sr1c00.append(cf.project_name)
        r1c00 = QTreeWidgetItem(sr1c00)
        root1.addChild(r1c00)

        # sr1c0 = QStringList()
        # sr1c0.append("项目位置")
        # sr1c0.append(cf.project_location)
        # r1c0 = QTreeWidgetItem(sr1c0)
        # root1.addChild(r1c0)

        sr1c1 = QStringList()
        sr1c1.append("组件类型")
        sr1c1.append(cf.component_type)
        r1c1 = QTreeWidgetItem(sr1c1)
        root1.addChild(r1c1)

        sr1c2 = QStringList()
        sr1c2.append("源模板")
        sr1c2.append(cf.template_source)
        r1c2 = QTreeWidgetItem(sr1c2)
        root1.addChild(r1c2)

        sr1c3 = QStringList()
        sr1c3.append("平台类型")
        tmp_pt = ""
        if cf.platform_type & configuration.PT_WIN32:
            tmp_pt += "win32;"
        if cf.platform_type & configuration.PT_LINUX:
            tmp_pt += "linux"

        sr1c3.append(tmp_pt)
        r1c3 = QTreeWidgetItem(sr1c3)
        root1.addChild(r1c3)

        sr1c4 = QStringList()
        sr1c4.append("平台级别")
        sr1c4.append(cf.platform_version)
        r1c4 = QTreeWidgetItem(sr1c4)
        root1.addChild(r1c4)

        sr1c5 = QStringList()
        sr1c5.append("资源文件")
        if cf.resourcesFile == "True":
            sr1c5.append("添加")
        else:
            sr1c5.append("未添加")
        r1c5 = QTreeWidgetItem(sr1c5)
        root1.addChild(r1c5)

        sr1c6 = QStringList()
        sr1c6.append("翻译文件")
        if cf.translateFile == "True":
            sr1c6.append("添加")
        else:
            sr1c6.append("未添加")
        r1c6 = QTreeWidgetItem(sr1c6)
        root1.addChild(r1c6)

        for qt in cf.qt_libs:
            sr2 = QStringList()
            sr2.append(qt['name'])
            sr2.append(qt['qt'])
            r2 = QTreeWidgetItem(sr2)
            root2.addChild(r2)

        for module in cf.modules:
            sr3a = QStringList()
            sr3a.append(module['name'])
            sr3a.append(module['description'])
            r3a = QTreeWidgetItem(sr3a)
            root3a.addChild(r3a)

        # sr3b = QStringList()
        # sr3b.append('ALLONE_DIR')
        # sr3b.append(os.getenv('ALLONEDIR','../..')) # 第二个参数是默认值
        # r3b = QTreeWidgetItem(sr3b)
        # root3b.addChild(r3b)
        for info in cf.thirdpart_lib:
            sr3b = QStringList()
            sr3b.append(info['libname'])
            sr3b.append(info['libpath'])
            r3b = QTreeWidgetItem(sr3b)
            root3b.addChild(r3b)

        for key in cf.interfaces.keys():
            sr4 = QStringList()
            sr4.append(key)
            if cf.interfaces[key]:
                sr4.append('实现')
            else:
                sr4.append('未实现')
            r4 = QTreeWidgetItem(sr4)
            root4.addChild(r4)
        self.tw_config.expandAll()
        self.tw_config.header().resizeSection(0, 300)
        self.tGroup.setEnabled(True)

    def on_modify(self):
        '''修改配置'''
        if self.currentConfig:
            app.g_configurations = copy.copy(self.currentConfig)
            dlg = wizard.MyWizard()
            if dlg.exec_():
                item = self.lw.currentItem()
                if item != None:
                    content = app.g_configurations.toJson()
                    item.setData(QtCore.Qt.UserRole, content)
                    path = item.data(QtCore.Qt.UserRole + 1).toString()
                    if not path.isEmpty():
                        path = app.QString2str(path)
                        with open(path, 'w+') as f:
                            f.write(content)
                    self.on_select()

    def on_gen(self):
        '''生成工程'''
        if not self.currentConfig:
            return

        #获取工程名及有效路径
        project_name = self.et_project_name.text()
        project_location = self.et_project_location.text()
        qdir = QDir(project_location)
        if not qdir.exists():
            if not qdir.mkpath(project_location):
                QMessageBox.warning(self, '警告', '路径无效!')
                return
        project_location = qdir.absolutePath()
        if not project_location.endsWith(
                '/') and not project_location.endsWith('\\'):
            project_location += os.sep
            project_location.replace('\\', '/')
        if project_name.isEmpty() or project_location.isEmpty():
            QMessageBox.warning(self, '警告', '项目名称或路径不能为空!')
            return

        self.currentConfig.project_name = app.QString2str(project_name)
        self.currentConfig.project_location = app.QString2str(project_location)

        content = self.currentConfig.toJson()
        fileInfo = QFileInfo(self.path)
        if not self.path.isEmpty():
            path = app.QString2str(self.path)
            with open(path, 'w+') as f:
                f.write(content)
        item = self.lw.currentItem()
        item.setData(QtCore.Qt.UserRole, content)

        template_name = self.currentConfig.template_source
        template_dir = app.g_pwd + os.sep + 'templates' + os.sep + template_name.encode(
            'utf-8')
        with open(template_dir + os.sep + 'config.json', 'r') as f:
            self.currentConfig.config_content = f.read()
        ret_json = app.render(self.currentConfig.config_content,
                              config=self.currentConfig)
        self.currentConfig.config = json.loads(ret_json)
        for file in self.currentConfig.config['files']:
            sourcepath = template_dir + os.sep + file['source'].encode('utf-8')
            targetdir = self.currentConfig.project_location + self.currentConfig.project_name
            targetpath = targetdir + os.sep + file['target']
            fi = QFileInfo(targetpath)
            qdir = fi.absoluteDir()
            if not qdir.exists():
                qdir.mkpath(fi.absolutePath())
            with open(sourcepath, 'r') as f:
                content = f.read()
                content = app.render(content, config=self.currentConfig)  #渲染文件
            with open(targetpath, 'w+') as f:
                f.write(content.encode('utf-8'))
        QMessageBox.information(self, '提示', '生成成功!')
예제 #14
0
class mainwindow(QtGui.QMainWindow):
    '''主窗体'''

    def __init__(self):
        super(mainwindow,self).__init__()
        self.setWindowTitle('组件设计工具')
        self.showMaximized()
        self.menuBar().show()
        self.createMenus()

        cwHLayout = QHBoxLayout()
        lLayout = QVBoxLayout()
        rLayout = QVBoxLayout()
        self.lw = QListWidget()
        self.lw.setSelectionMode(QAbstractItemView.SingleSelection )

        lLayout.addWidget(self.lw)
        self.lw.itemSelectionChanged.connect(self.on_select)

        lGroup = QGroupBox('项目列表')
        lGroup.setLayout(lLayout)
        cwHLayout.addWidget(lGroup,2)
        cwHLayout.addLayout(rLayout,8)

        tLayout = QVBoxLayout()
        bLayout = QVBoxLayout()

        tGroup = QGroupBox('配置信息')
        self.bGroup = QGroupBox('生成代码')
        tGroup.setLayout(tLayout)
        self.bGroup.setLayout(bLayout)
        self.bGroup.setEnabled(False)

        rLayout.addWidget(tGroup)
        rLayout.addWidget(self.bGroup)

        self.tw_config = QTreeWidget()
        headerLabels = QStringList()
        headerLabels.append('项目')
        headerLabels.append('值')
        self.tw_config.setHeaderLabels(headerLabels)
        thLayout = QHBoxLayout()
        thLayout.addStretch(0)
        modify_btn = QPushButton('修改')
        modify_btn.clicked.connect(self.on_modify)
        del_btn = QPushButton('删除')
        del_btn.clicked.connect(self.on_del)
        thLayout.addWidget(modify_btn)
        thLayout.addWidget(del_btn)

        tLayout.addWidget(self.tw_config)
        tLayout.addLayout(thLayout)

        bhLayout = QHBoxLayout()
        bhLayout.addStretch(0)
        gen_btn = QPushButton('生成')
        gen_btn.clicked.connect(self.on_gen)
        bhLayout.addWidget(gen_btn)

        row1 = QHBoxLayout()
        lable1 = QLabel('工程名称:')
        self.et_project_name = QLineEdit()
        row1.addSpacing(10)
        row1.addWidget(lable1)
        row1.addWidget(self.et_project_name)
        row1.addStretch(0)

        row2 = QHBoxLayout()
        lable2 = QLabel('工程位置:')
        self.et_project_location = QLineEdit()
        self.et_project_location.setReadOnly(True)
        btn_location = QPushButton('...')
        btn_location.setFixedWidth(50)
        btn_location.clicked.connect(self.getProjectLocation)
        row2.addSpacing(10)
        row2.addWidget(lable2)
        row2.addWidget(self.et_project_location)
        row2.addWidget(btn_location)
        row2.addStretch(0)

        bLayout.addLayout(row1)
        bLayout.addLayout(row2)
        bLayout.addLayout(bhLayout)

        cw = QWidget()
        cw.setLayout(cwHLayout)
        self.setCentralWidget(cw)
        self._initByConfig()
        self.setMinimumSize(400,200)

    def _initByConfig(self):
        '''初始化'''
        pass

    def createMenus(self):
        '''创建菜单'''
        menueBar = self.menuBar()
        menuSys = menueBar.addMenu('系统')
        actNew = menuSys.addAction('新建工程')
        actOpen = menuSys.addAction('打开工程')
        actNew.triggered.connect(self.on_new)
        actOpen.triggered.connect(self.on_open)
        menueBar.addMenu(menuSys)

    def on_new(self):
        '''新建向导'''
        app.g_configurations = Configuration()  # 用来渲染的配置数据
        dlg = wizard.MyWizard()
        if dlg.exec_():
            app.g_configurations.initialized = True
            app.g_projects.append(app.g_configurations)
            content = app.g_configurations.toJson()
            path = QFileDialog.getSaveFileName(self,"选择模板保存的路径",
                                               app.g_pwd + os.sep + "configurations" + os.sep + app.g_configurations.project_name + ".json"
                                               ,"Config (*.json)")
            if not path.isEmpty():
                path = app.QString2str(path)
                with open(path,'w+') as f:
                    f.write(content)
                self.lw.addItem(app.g_configurations.project_name)

    def getProjectLocation(self):
        '''获取项目路径'''
        path = QFileDialog.getExistingDirectory()
        path = QDir.fromNativeSeparators(path)
        self.et_project_location.setText(path)

    def on_open(self):
        '''打开现有配置'''
        fileName = QFileDialog.getOpenFileName(self,"选择现有模板",app.g_pwd + os.sep + "configurations","Config (*.json)")
        if fileName.isEmpty():
            return
        with open(app.QString2str(fileName), 'r') as f:
            content = f.read()

        config = Configuration()
        config.fromJson(content)
        app.g_projects.append(config)
        self.lw.addItem(config.project_name)

    def on_del(self):
        index = self.lw.currentRow()
        if index < app.g_projects:
            self.bGroup.setEnabled(False)
            self.lw.takeItem(index)
            config = app.g_projects[index]
            app.g_projects.remove(config)
            self.tw_config.clear()
        return


    def on_select(self):
        '''选取配置'''
        index = self.lw.currentRow()
        if index < app.g_projects:
            self.bGroup.setEnabled(True)
            self.currentConfig = app.g_projects[index]
            self.showConfigInfo(self.currentConfig)

    def showConfigInfo(self,cf):
        '''显示配置信息'''
        self.tw_config.clear()
        self.et_project_name.setText(cf.project_name)
        self.et_project_location.setText(cf.project_location)
        sr = QStringList()
        sr.append('信息')
        root1 = QTreeWidgetItem(sr)
        sr = QStringList()
        sr.append('Qt库')
        root2 = QTreeWidgetItem(sr)
        sr = QStringList()
        sr.append('模块')
        root3 = QTreeWidgetItem(sr)
        sr = QStringList()
        sr.append('接口')
        root4 = QTreeWidgetItem(sr)

        self.tw_config.addTopLevelItem(root1)
        self.tw_config.addTopLevelItem(root2)
        self.tw_config.addTopLevelItem(root3)
        self.tw_config.addTopLevelItem(root4)

        sr1c00 = QStringList()
        sr1c00.append("项目名称")
        sr1c00.append(cf.project_name)
        r1c00 = QTreeWidgetItem(sr1c00)
        root1.addChild(r1c00)

        # sr1c0 = QStringList()
        # sr1c0.append("项目位置")
        # sr1c0.append(cf.project_location)
        # r1c0 = QTreeWidgetItem(sr1c0)
        # root1.addChild(r1c0)

        sr1c1 = QStringList()
        sr1c1.append("组件类型")
        sr1c1.append(cf.component_type)
        r1c1 = QTreeWidgetItem(sr1c1)
        root1.addChild(r1c1)

        sr1c2 = QStringList()
        sr1c2.append("源模板")
        sr1c2.append(cf.template_source)
        r1c2 = QTreeWidgetItem(sr1c2)
        root1.addChild(r1c2)

        sr1c3 = QStringList()
        sr1c3.append("平台类型")
        tmp_pt = ""
        if cf.platform_type & configuration.PT_WIN32:
            tmp_pt += "win32;"
        if cf.platform_type & configuration.PT_LINUX:
            tmp_pt += "linux"

        sr1c3.append(tmp_pt)
        r1c3 = QTreeWidgetItem(sr1c3)
        root1.addChild(r1c3)

        sr1c4 = QStringList()
        sr1c4.append("平台级别")
        sr1c4.append(cf.platform_version)
        r1c4 = QTreeWidgetItem(sr1c4)
        root1.addChild(r1c4)

        for qt in cf.qt_libs:
            sr2 = QStringList()
            sr2.append(qt['name'])
            sr2.append(qt['qt'])
            r2 = QTreeWidgetItem(sr2)
            root2.addChild(r2)

        for module in cf.modules:
            sr3 = QStringList()
            sr3.append(module['name'])
            sr3.append(module['description'])
            r3 = QTreeWidgetItem(sr3)
            root3.addChild(r3)

        for key in cf.interfaces.keys():
            sr4 = QStringList()
            sr4.append(key)
            if cf.interfaces[key]:
                sr4.append('实现')
            else:
                sr4.append('未实现')
            r4 = QTreeWidgetItem(sr4)
            root4.addChild(r4)
        self.tw_config.expandAll()
        self.tw_config.header().resizeSection(0,300)

    def on_modify(self):
        '''修改配置'''
        if self.currentConfig:
            app.g_configurations = copy.copy(self.currentConfig)
            dlg = wizard.MyWizard()
            if dlg.exec_():
                index = self.lw.currentRow()
                if index < app.g_projects:
                    self.currentConfig = app.g_configurations
                    app.g_projects[index] = self.currentConfig
                    self.showConfigInfo(self.currentConfig)

    def on_gen(self):
        '''生成工程'''
        if not self.currentConfig:
            return

        #获取工程名及有效路径
        project_name = self.et_project_name.text()
        project_location = self.et_project_location.text()
        qdir = QDir(project_location)
        if not qdir.exists():
            if not qdir.mkpath(project_location):
                QMessageBox.warning(self, '警告', '路径无效!')
                return
        project_location = qdir.absolutePath()
        if not project_location.endsWith('/') and not project_location.endsWith('\\'):
            project_location += os.sep
        if project_name.isEmpty() or project_location.isEmpty():
            QMessageBox.warning(self, '警告', '项目名称或路径不能为空!')
            return

        self.currentConfig.project_name = app.QString2str(project_name)
        self.currentConfig.project_location = app.QString2str(project_location)
        template_name = self.currentConfig.template_source
        template_dir = app.g_pwd + os.sep + 'templates' + os.sep + template_name
        with open(template_dir + os.sep + 'config.json', 'r') as f:
            self.currentConfig.config_content = f.read()
        ret_json = app.render(self.currentConfig.config_content, config=self.currentConfig)
        self.currentConfig.config = json.loads(ret_json)
        for file in self.currentConfig.config['files']:
            sourcepath = template_dir + os.sep + file['source']
            targetdir = self.currentConfig.project_location + self.currentConfig.project_name
            targetpath = targetdir + os.sep + file['target']
            fi = QFileInfo(targetpath)
            qdir = fi.absoluteDir()
            if not qdir.exists():
                qdir.mkpath(fi.absolutePath())
            with open(sourcepath, 'r') as f:
                content = f.read()
                content = app.render(content, config=self.currentConfig) #渲染文件
            with open(targetpath, 'w+') as f:
                f.write(content.encode('utf-8'))
        QMessageBox.information(self,'提示','生成成功!')
예제 #15
0
class OWItemsets(widget.OWWidget):
    name = 'Frequent Itemsets'
    description = 'Explore sets of items that frequently appear together.'
    icon = 'icons/FrequentItemsets.svg'
    priority = 10

    inputs = [("Data", Table, 'set_data')]
    outputs = [(Output.DATA, Table)]

    minSupport = settings.Setting(30)
    maxItemsets = settings.Setting(10000)
    filterSearch = settings.Setting(True)
    autoFind = settings.Setting(False)
    autoSend = settings.Setting(True)
    filterKeywords = settings.Setting('')
    filterMinItems = settings.Setting(1)
    filterMaxItems = settings.Setting(10000)

    UserAdviceMessages = [
        widget.Message(
            'Itemset are listed in item-sorted order, i.e. '
            'an itemset containing A and B is only listed once, as '
            'A > B (and not also B > A).', 'itemsets-order',
            widget.Message.Warning),
        widget.Message(
            'To select all the itemsets that are descendants of '
            '(include) some item X (i.e. the whole subtree), you '
            'can fold the subtree at that item and then select it.',
            'itemsets-order', widget.Message.Information)
    ]

    def __init__(self):
        self._is_running = False
        self.isRegexMatch = lambda x: True
        self.tree = QTreeWidget(self.mainArea,
                                columnCount=2,
                                allColumnsShowFocus=True,
                                alternatingRowColors=True,
                                selectionMode=QTreeWidget.ExtendedSelection,
                                uniformRowHeights=True)
        self.tree.setHeaderLabels(["Itemsets", "Support", "%"])
        self.tree.header().setStretchLastSection(True)
        self.tree.itemSelectionChanged.connect(self.selectionChanged)
        self.mainArea.layout().addWidget(self.tree)

        box = gui.widgetBox(self.controlArea, "Info")
        self.nItemsets = self.nSelectedExamples = self.nSelectedItemsets = ''
        gui.label(box, self, "Number of itemsets: %(nItemsets)s")
        gui.label(box, self, "Selected itemsets: %(nSelectedItemsets)s")
        gui.label(box, self, "Selected examples: %(nSelectedExamples)s")
        hbox = gui.widgetBox(box, orientation='horizontal')
        gui.button(hbox, self, "Expand all", callback=self.tree.expandAll)
        gui.button(hbox, self, "Collapse all", callback=self.tree.collapseAll)

        box = gui.widgetBox(self.controlArea, 'Find itemsets')
        gui.valueSlider(box,
                        self,
                        'minSupport',
                        values=[.0001, .0005, .001, .005, .01, .05, .1, .5] +
                        list(range(1, 101)),
                        label='Minimal support:',
                        labelFormat="%g%%",
                        callback=lambda: self.find_itemsets())
        gui.hSlider(box,
                    self,
                    'maxItemsets',
                    minValue=10000,
                    maxValue=100000,
                    step=10000,
                    label='Max. number of itemsets:',
                    labelFormat="%d",
                    callback=lambda: self.find_itemsets())
        self.button = gui.auto_commit(box,
                                      self,
                                      'autoFind',
                                      'Find itemsets',
                                      commit=self.find_itemsets)

        box = gui.widgetBox(self.controlArea, 'Filter itemsets')
        gui.lineEdit(box,
                     self,
                     'filterKeywords',
                     'Contains:',
                     callback=self.filter_change,
                     orientation='horizontal',
                     tooltip='A comma or space-separated list of regular '
                     'expressions.')
        hbox = gui.widgetBox(box, orientation='horizontal')
        gui.spin(hbox,
                 self,
                 'filterMinItems',
                 1,
                 998,
                 label='Min. items:',
                 callback=self.filter_change)
        gui.spin(hbox,
                 self,
                 'filterMaxItems',
                 2,
                 999,
                 label='Max. items:',
                 callback=self.filter_change)
        gui.checkBox(box,
                     self,
                     'filterSearch',
                     label='Apply these filters in search',
                     tooltip='If checked, the itemsets are filtered according '
                     'to these filter conditions already in the search '
                     'phase. \nIf unchecked, the only filters applied '
                     'during search are the ones above, '
                     'and the itemsets are \nfiltered afterwards only for '
                     'display, i.e. only the matching itemsets are shown.')

        gui.rubber(hbox)

        gui.rubber(self.controlArea)
        gui.auto_commit(self.controlArea, self, 'autoSend', 'Send selection')

        self.filter_change()

    ITEM_DATA_ROLE = Qt.UserRole + 1

    def selectionChanged(self):
        X = self.X
        mapping = self.onehot_mapping
        instances = set()
        where = np.where

        def whole_subtree(node):
            yield node
            for i in range(node.childCount()):
                yield from whole_subtree(node.child(i))

        def itemset(node):
            while node:
                yield node.data(0, self.ITEM_DATA_ROLE)
                node = node.parent()

        def selection_ranges(node):
            n_children = node.childCount()
            if n_children:
                yield (self.tree.indexFromItem(node.child(0)),
                       self.tree.indexFromItem(node.child(n_children - 1)))
            for i in range(n_children):
                yield from selection_ranges(node.child(i))

        nSelectedItemsets = 0
        item_selection = QItemSelection()
        for node in self.tree.selectedItems():
            nodes = (node, ) if node.isExpanded() else whole_subtree(node)
            if not node.isExpanded():
                for srange in selection_ranges(node):
                    item_selection.select(*srange)
            for node in nodes:
                nSelectedItemsets += 1
                cols, vals = zip(*(mapping[i] for i in itemset(node)))
                if issparse(X):
                    rows = (len(cols) == np.bincount(
                        (X[:, cols] != 0).indices,
                        minlength=X.shape[0])).nonzero()[0]
                else:
                    rows = where((X[:, cols] == vals).all(axis=1))[0]
                instances.update(rows)
        self.tree.itemSelectionChanged.disconnect(self.selectionChanged)
        self.tree.selectionModel().select(
            item_selection,
            QItemSelectionModel.Select | QItemSelectionModel.Rows)
        self.tree.itemSelectionChanged.connect(self.selectionChanged)

        self.nSelectedExamples = len(instances)
        self.nSelectedItemsets = nSelectedItemsets
        self.output = self.data[sorted(instances)] or None
        self.commit()

    def commit(self):
        self.send(Output.DATA, self.output)

    def filter_change(self):
        self.warning(9)
        try:
            isRegexMatch = self.isRegexMatch = re.compile(
                '|'.join(
                    i.strip()
                    for i in re.split('(,|\s)+', self.filterKeywords.strip())
                    if i.strip()), re.IGNORECASE).search
        except Exception as e:
            self.warning(9,
                         'Error in regular expression: {}'.format(e.args[0]))
            isRegexMatch = self.isRegexMatch = lambda x: True

        def hide(node, depth, has_kw):
            if not has_kw:
                has_kw = isRegexMatch(node.text(0))
            hidden = (
                sum(
                    hide(node.child(i), depth + 1, has_kw)
                    for i in range(node.childCount())) == node.childCount()
                if node.childCount() else
                (not has_kw
                 or not self.filterMinItems <= depth <= self.filterMaxItems))
            node.setHidden(hidden)
            return hidden

        hide(self.tree.invisibleRootItem(), 0, False)

    class TreeWidgetItem(QTreeWidgetItem):
        def data(self, column, role):
            """Construct lazy tooltips"""
            if role != Qt.ToolTipRole:
                return super().data(column, role)
            tooltip = []
            while self:
                tooltip.append(self.text(0))
                self = self.parent()
            return ' '.join(reversed(tooltip))

    def find_itemsets(self):
        if self.data is None:
            return
        if self._is_running:
            return
        self._is_running = True

        data = self.data
        self.tree.clear()
        self.tree.setUpdatesEnabled(False)
        self.tree.blockSignals(True)

        class ItemDict(dict):
            def __init__(self, item):
                self.item = item

        top = ItemDict(self.tree.invisibleRootItem())
        X, mapping = OneHot.encode(data)
        self.onehot_mapping = mapping
        ITEM_FMT = '{}' if issparse(data.X) else '{}={}'
        names = {
            item: ITEM_FMT.format(var.name, val)
            for item, var, val in OneHot.decode(mapping.keys(), data, mapping)
        }
        nItemsets = 0

        filterSearch = self.filterSearch
        filterMinItems, filterMaxItems = self.filterMinItems, self.filterMaxItems
        isRegexMatch = self.isRegexMatch

        # Find itemsets and populate the TreeView
        with self.progressBar(self.maxItemsets + 1) as progress:
            for itemset, support in frequent_itemsets(X,
                                                      self.minSupport / 100):

                if filterSearch and not filterMinItems <= len(
                        itemset) <= filterMaxItems:
                    continue

                parent = top
                first_new_item = None
                itemset_matches_filter = False

                for item in sorted(itemset):
                    name = names[item]

                    if filterSearch and not itemset_matches_filter:
                        itemset_matches_filter = isRegexMatch(name)

                    child = parent.get(name)
                    if child is None:
                        try:
                            wi = self.TreeWidgetItem(parent.item, [
                                name,
                                str(support), '{:.4g}'.format(
                                    100 * support / len(data))
                            ])
                        except RuntimeError:
                            # FIXME: When autoFind was in effect and the support
                            # slider was moved, this line excepted with:
                            #     RuntimeError: wrapped C/C++ object of type
                            #                   TreeWidgetItem has been deleted
                            return
                        wi.setData(0, self.ITEM_DATA_ROLE, item)
                        child = parent[name] = ItemDict(wi)

                        if first_new_item is None:
                            first_new_item = (parent, name)
                    parent = child

                if filterSearch and not itemset_matches_filter:
                    parent, name = first_new_item
                    parent.item.removeChild(parent[name].item)
                    del parent[name].item
                    del parent[name]
                else:
                    nItemsets += 1
                    progress.advance()
                if nItemsets >= self.maxItemsets:
                    break

        if not filterSearch:
            self.filter_change()
        self.nItemsets = nItemsets
        self.nSelectedItemsets = 0
        self.nSelectedExamples = 0
        self.tree.expandAll()
        for i in range(self.tree.columnCount()):
            self.tree.resizeColumnToContents(i)
        self.tree.setUpdatesEnabled(True)
        self.tree.blockSignals(False)
        self._is_running = False

    def set_data(self, data):
        self.data = data
        is_error = False
        if data is not None:
            self.warning(0)
            self.error(1)
            self.button.setDisabled(False)
            self.X = data.X
            if issparse(data.X):
                self.X = data.X.tocsc()
            else:
                if not data.domain.has_discrete_attributes():
                    self.error(
                        1, 'Discrete features required but data has none.')
                    is_error = True
                    self.button.setDisabled(True)
                elif data.domain.has_continuous_attributes():
                    self.warning(
                        0,
                        'Data has continuous attributes which will be skipped.'
                    )
        else:
            self.output = None
            self.commit()
        if self.autoFind and not is_error:
            self.find_itemsets()
예제 #16
0
파일: GmGui.py 프로젝트: hftsai/gulon-soft
class GmApp(QMainWindow):
    def __init__(self):
        super(QMainWindow, self).__init__() 

        self.setWindowTitle("GuloMail by GulonSoft")
        self.setWindowIcon(QIcon("g-square.png"))

        self.createActions()
        self.createStatusBar()
        self.createMenus()
        self.createToolbars()
        self.createWidgets()
        self.createLayouts()

    def createActions(self):
        self.newAction=QAction("&New", self, shortcut=QKeySequence.New, statusTip="New")
        self.sendReceiveAction=QAction("Send / &Receive", self, shortcut="F9", statusTip="Send / Receive")
        self.printAction=QAction("&Print...", self, shortcut="Ctrl+P", statusTip="Print")
        self.quitAction=QAction("&Quit", self, shortcut="Ctrl+Q", statusTip="Quit", triggered=self.close) 

        self.copyAction=QAction("&Copy", self, statusTip="Copy", shortcut=QKeySequence.Copy)
        self.deleteAction=QAction("&Delete", self, statusTip="Delete Message")

        self.nextAction=QAction("Next &Unread Message", self, shortcut="Ctrl+]", statusTip="Next unread message")
        self.previousAction=QAction("P&revious Unread Message", self, shortcut="Ctrl+[", statusTip="Previous unread message")
        self.replyAction=QAction("&Reply", self, shortcut="Ctrl+R", statusTip="Reply to sender", triggered=self.reply)
        self.replyToAllAction=QAction("Reply to &All", self, shortcut="Ctrl+Shift+R", statusTip="Reply to all", triggered=self.replyToAll)
        self.forwardAction=QAction("&Forward", self, shortcut="Ctrl+F", statusTip="Forward")
        self.junkAction=QAction("Junk", self, shortcut="Ctrl+J", statusTip="Mark as Junk")
        self.notJunkAction=QAction("Not junk", self, shortcut="Shift+Ctrl+J", statusTip="Mark as Not Junk")

        self.contentsAction=QAction("&Contents", self, statusTip="Help Contents", shortcut="F1", triggered=self.helpContents)
        self.aboutAction=QAction("&About", self, statusTip="About GuloMail", triggered=self.about)

        self.cancelAction=QAction("&Cancel", self, statusTip="Cancel")

    def createStatusBar(self):
        self.statusBar()
        
    def createMenus(self):
        self.fileMenu=self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.newAction)
        self.fileMenu.addAction(self.sendReceiveAction)
        self.fileMenu.addAction(self.printAction)
        self.fileMenu.addAction(self.quitAction)

        self.editMenu=self.menuBar().addMenu("&Edit")
        self.editMenu.addAction(self.copyAction)
        self.editMenu.addAction(self.deleteAction)

        self.viewMenu=self.menuBar().addMenu("&View")
        self.folderMenu=self.menuBar().addMenu("F&older")

        self.messageMenu=self.menuBar().addMenu("&Message")
        self.goToMenu=self.messageMenu.addMenu("&Go To")
        self.goToMenu.addAction(self.nextAction)
        self.goToMenu.addAction(self.previousAction)
        self.messageMenu.addAction(self.replyAction)
        self.messageMenu.addAction(self.replyToAllAction)
        self.messageMenu.addAction(self.forwardAction)
        self.markAsMenu=self.messageMenu.addMenu("Mar&k as...")
        self.markAsMenu.addAction(self.junkAction)
        self.markAsMenu.addAction(self.notJunkAction)

        self.searchMenu=self.menuBar().addMenu("&Search")
        
        self.helpMenu=self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.contentsAction)
        self.helpMenu.addAction(self.aboutAction)

    def createToolbars(self):
        self.toolbar=self.addToolBar('Main Toolbar')
        self.toolbar.setMovable(False)
        self.toolbar.addAction(self.newAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.sendReceiveAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.replyAction)
        self.toolbar.addAction(self.replyToAllAction)
        self.toolbar.addAction(self.forwardAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.printAction)
        self.toolbar.addAction(self.deleteAction)
        self.toolbar.addAction(self.junkAction)
        self.toolbar.addAction(self.notJunkAction)
        self.toolbar.addAction(self.cancelAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.previousAction)
        self.toolbar.addAction(self.nextAction)

    def createWidgets(self):
        ## Message Table
        self.table=QTableView()
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setGridStyle(Qt.NoPen)
        
        self.model = QStandardItemModel(8, 3, self)
        self.model.setHeaderData(0, Qt.Horizontal, "From")
        self.model.setHeaderData(1, Qt.Horizontal, "Subject")
        self.model.setHeaderData(2, Qt.Horizontal, "Received")
        
        self.table.setModel(self.model)
        self.selectionModel = QItemSelectionModel(self.model)
        self.selectionModel.SelectionFlag=0x0020
        self.table.setSelectionModel(self.selectionModel)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.verticalHeader().setVisible(False)
        self.table.setSortingEnabled(True)
        self.table.setAlternatingRowColors(True) 
        
        ## Folder Tree View
        self.folderTree=QTreeWidget()
        self.folderTree.setColumnCount(1)
        self.folderTree.setHeaderLabel(QString('Folders'))

        self.treeItem=QTreeWidgetItem()
        self.treeItem.setText(0, 'Folders')

        self.inbox=QTreeWidgetItem()
        self.inbox.setText(0, 'Inbox')

        self.deletedItems=QTreeWidgetItem()
        self.deletedItems.setText(0, 'Deleted Items')

        self.drafts=QTreeWidgetItem()
        self.drafts.setText(0, 'Drafts')

        self.junk=QTreeWidgetItem()
        self.junk.setText(0, 'Junk')

        self.outbox=QTreeWidgetItem()
        self.outbox.setText(0, 'Outbox')

        self.sent=QTreeWidgetItem()
        self.sent.setText(0, 'Sent')
        
        self.treeItem.addChild(self.inbox)
        self.treeItem.addChild(self.deletedItems)
        self.treeItem.addChild(self.drafts)
        self.treeItem.addChild(self.junk)
        self.treeItem.addChild(self.outbox)
        self.treeItem.addChild(self.sent)

        self.folderTree.addTopLevelItem(self.treeItem)
        self.folderTree.expandAll()
        self.folderTree.setAnimated(True)

        self.folderTree.setMaximumWidth(150)

        ## Temp. placeholders 
        self.textEdit=QTextEdit()
        self.textEdit2=QTextEdit()
        
    def createLayouts(self):
        self.mainSplitter=QSplitter()
        self.setCentralWidget(self.mainSplitter)

        self.mainSplitter.addWidget(self.folderTree)

        self.messageSplitter=QSplitter(Qt.Vertical)
        self.messageSplitter.addWidget(self.table)
        self.messageSplitter.addWidget(self.textEdit2)

        self.mainSplitter.addWidget(self.messageSplitter)
        
    def helpContents(self):
        print "Help"

    def reply(self):
        print "Reply"

    def replyToAll(self):
        print "Reply To All"

    def about(self):
        text=QString("GuloMail v0.1\n\n")
        text.append("GuloMail is a freeware email client written in Python using PyQt4 (Python bindings for Nokia's Qt)\n\n")
        text.append(QChar(0x00A9))
        text.append("GulonSoft 2010\nhttp://www.gulon.co.uk/")
        QMessageBox.about(self, "About GuloMail", text)
예제 #17
0
class OWGEODatasets(OWWidget):
    name = "GEO Data Sets"
    description = DESCRIPTION
    icon = "../widgets/icons/GEODataSets.svg"
    priority = PRIORITY

    inputs = []
    outputs = [("Expression Data", Orange.data.Table)]

    settingsList = ["outputRows", "mergeSpots", "gdsSelectionStates",
                    "splitterSettings", "currentGds", "autoCommit",
                    "datasetNames"]

    outputRows = Setting(False)
    mergeSpots = Setting(True)
    gdsSelectionStates = Setting({})
    currentGds = Setting(None)
    datasetNames = Setting({})
    splitterSettings = Setting(
        (b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xea\x00\x00\x00\xd7\x01\x00\x00\x00\x07\x01\x00\x00\x00\x02',
         b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xb5\x00\x00\x02\x10\x01\x00\x00\x00\x07\x01\x00\x00\x00\x01')
    )

    autoCommit = Setting(True)

    def __init__(self, parent=None, signalManager=None, name=" GEO Data Sets"):
        OWWidget.__init__(self, parent, signalManager, name)

        self.selectionChanged = False
        self.filterString = ""
        self.datasetName = ""
        ## GUI
        box = gui.widgetBox(self.controlArea, "Info", addSpace=True)
        self.infoBox = gui.widgetLabel(box, "Initializing\n\n")

        box = gui.widgetBox(self.controlArea, "Output", addSpace=True)
        gui.radioButtonsInBox(box, self, "outputRows",
                              ["Genes or spots", "Samples"], "Rows",
                              callback=self.commitIf)

        gui.checkBox(box, self, "mergeSpots", "Merge spots of same gene",
                     callback=self.commitIf)

        gui.separator(box)
        self.nameEdit = gui.lineEdit(
            box, self, "datasetName", "Data set name",
            tooltip="Override the default output data set name",
            callback=self.onNameEdited
        )
        self.nameEdit.setPlaceholderText("")

        if sys.version_info < (3, ):
            box = gui.widgetBox(self.controlArea, "Commit", addSpace=True)
            self.commitButton = gui.button(
                box, self, "Commit", callback=self.commit)
            cb = gui.checkBox(box, self, "autoCommit", "Commit on any change")
            gui.setStopper(self, self.commitButton, cb, "selectionChanged",
                           self.commit)
        else:
            gui.auto_commit(self.controlArea, self, "autoCommit", "Commit",
                            box="Commit")

        gui.rubber(self.controlArea)

#         self.filterLineEdit = OWGUIEx.lineEditHint(
#             self.mainArea, self, "filterString", "Filter",
#             caseSensitive=False, matchAnywhere=True,
#             callback=self.filter,  delimiters=" ")

        gui.widgetLabel(self.mainArea, "Filter")
        self.filterLineEdit = QLineEdit(
            textChanged=self.filter
        )
        self.completer = QCompleter(
            caseSensitivity=Qt.CaseInsensitive
        )
        self.completer.setModel(QStringListModel(self))
        self.filterLineEdit.setCompleter(self.completer)

        self.mainArea.layout().addWidget(self.filterLineEdit)

        splitter = QSplitter(Qt.Vertical, self.mainArea)
        self.mainArea.layout().addWidget(splitter)
        self.treeWidget = QTreeView(splitter)

        self.treeWidget.setSelectionMode(QTreeView.SingleSelection)
        self.treeWidget.setRootIsDecorated(False)
        self.treeWidget.setSortingEnabled(True)
        self.treeWidget.setAlternatingRowColors(True)
        self.treeWidget.setUniformRowHeights(True)
        self.treeWidget.setEditTriggers(QTreeView.NoEditTriggers)

        linkdelegate = LinkStyledItemDelegate(self.treeWidget)
        self.treeWidget.setItemDelegateForColumn(1, linkdelegate)
        self.treeWidget.setItemDelegateForColumn(8, linkdelegate)
        self.treeWidget.setItemDelegateForColumn(
            0, gui.IndicatorItemDelegate(self.treeWidget,
                                         role=Qt.DisplayRole))

        proxyModel = MySortFilterProxyModel(self.treeWidget)
        self.treeWidget.setModel(proxyModel)
        self.treeWidget.selectionModel().selectionChanged.connect(
            self.updateSelection
        )
        self.treeWidget.viewport().setMouseTracking(True)

        splitterH = QSplitter(Qt.Horizontal, splitter)

        box = gui.widgetBox(splitterH, "Description")
        self.infoGDS = gui.widgetLabel(box, "")
        self.infoGDS.setWordWrap(True)
        gui.rubber(box)

        box = gui.widgetBox(splitterH, "Sample Annotations")
        self.annotationsTree = QTreeWidget(box)
        self.annotationsTree.setHeaderLabels(
            ["Type (Sample annotations)", "Sample count"]
        )
        self.annotationsTree.setRootIsDecorated(True)
        box.layout().addWidget(self.annotationsTree)
        self.annotationsTree.itemChanged.connect(
            self.annotationSelectionChanged
        )
        self._annotationsUpdating = False
        self.splitters = splitter, splitterH

        for sp, setting in zip(self.splitters, self.splitterSettings):
            sp.splitterMoved.connect(self.splitterMoved)
            sp.restoreState(setting)

        self.searchKeys = ["dataset_id", "title", "platform_organism",
                           "description"]

        self.gds = []
        self.gds_info = None

        self.resize(1000, 600)

        self.setBlocking(True)
        self.setEnabled(False)
        self.progressBarInit()

        self._executor = ThreadExecutor()

        func = partial(get_gds_model,
                       methodinvoke(self, "_setProgress", (float,)))
        self._inittask = Task(function=func)
        self._inittask.finished.connect(self._initializemodel)
        self._executor.submit(self._inittask)

        self._datatask = None

    @Slot(float)
    def _setProgress(self, value):
        self.progressBarValue = value

    def _initializemodel(self):
        assert self.thread() is QThread.currentThread()
        model, self.gds_info, self.gds = self._inittask.result()
        model.setParent(self)

        proxy = self.treeWidget.model()
        proxy.setFilterKeyColumn(0)
        proxy.setFilterRole(TextFilterRole)
        proxy.setFilterCaseSensitivity(False)
        proxy.setFilterFixedString(self.filterString)

        proxy.setSourceModel(model)
        proxy.sort(0, Qt.DescendingOrder)

        self.progressBarFinished()
        self.setBlocking(False)
        self.setEnabled(True)

        filter_items = " ".join(
            gds[key] for gds in self.gds for key in self.searchKeys
        )
        tr_chars = ",.:;!?(){}[]_-+\\|/%#@$^&*<>~`"
        tr_table = str.maketrans(tr_chars, " " * len(tr_chars))
        filter_items = filter_items.translate(tr_table)

        filter_items = sorted(set(filter_items.split(" ")))
        filter_items = [item for item in filter_items if len(item) > 3]

        self.completer.model().setStringList(filter_items)
#         self.filterLineEdit.setItems(filter_items)

        if self.currentGds:
            current_id = self.currentGds["dataset_id"]
            gdss = [(i, qunpack(proxy.data(proxy.index(i, 1), Qt.DisplayRole)))
                    for i in range(proxy.rowCount())]
            current = [i for i, data in gdss if data and data == current_id]
            if current:
                current_index = proxy.index(current[0], 0)
                self.treeWidget.selectionModel().select(
                    current_index,
                    QItemSelectionModel.Select | QItemSelectionModel.Rows
                )
                self.treeWidget.scrollTo(
                    current_index, QTreeView.PositionAtCenter)

        for i in range(8):
            self.treeWidget.resizeColumnToContents(i)

        self.treeWidget.setColumnWidth(
            1, min(self.treeWidget.columnWidth(1), 300))
        self.treeWidget.setColumnWidth(
            2, min(self.treeWidget.columnWidth(2), 200))

        self.updateInfo()

    def updateInfo(self):
        gds_info = self.gds_info
        text = ("%i datasets\n%i datasets cached\n" %
                (len(gds_info),
                 len(glob.glob(serverfiles.localpath("GEO") + "/GDS*"))))
        filtered = self.treeWidget.model().rowCount()
        if len(self.gds) != filtered:
            text += ("%i after filtering") % filtered
        self.infoBox.setText(text)

    def updateSelection(self, *args):
        current = self.treeWidget.selectedIndexes()
        mapToSource = self.treeWidget.model().mapToSource
        current = [mapToSource(index).row() for index in current]
        if current:
            self.currentGds = self.gds[current[0]]
            self.setAnnotations(self.currentGds)
            self.infoGDS.setText(self.currentGds.get("description", ""))
            self.nameEdit.setPlaceholderText(self.currentGds["title"])
            self.datasetName = \
                self.datasetNames.get(self.currentGds["dataset_id"], "")
        else:
            self.currentGds = None
            self.nameEdit.setPlaceholderText("")
            self.datasetName = ""

        self.commitIf()

    def setAnnotations(self, gds):
        self._annotationsUpdating = True
        self.annotationsTree.clear()

        annotations = defaultdict(set)
        subsetscount = {}
        for desc in gds["subsets"]:
            annotations[desc["type"]].add(desc["description"])
            subsetscount[desc["description"]] = str(len(desc["sample_id"]))

        for type, subsets in annotations.items():
            key = (gds["dataset_id"], type)
            subsetItem = QTreeWidgetItem(self.annotationsTree, [type])
            subsetItem.setFlags(subsetItem.flags() | Qt.ItemIsUserCheckable |
                                Qt.ItemIsTristate)
            subsetItem.setCheckState(
                0, self.gdsSelectionStates.get(key, Qt.Checked)
            )
            subsetItem.key = key
            for subset in subsets:
                key = (gds["dataset_id"], type, subset)
                item = QTreeWidgetItem(
                    subsetItem, [subset, subsetscount.get(subset, "")]
                )
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
                item.setCheckState(
                    0, self.gdsSelectionStates.get(key, Qt.Checked)
                )
                item.key = key
        self._annotationsUpdating = False
        self.annotationsTree.expandAll()
        for i in range(self.annotationsTree.columnCount()):
            self.annotationsTree.resizeColumnToContents(i)

    def annotationSelectionChanged(self, item, column):
        if self._annotationsUpdating:
            return
        for i in range(self.annotationsTree.topLevelItemCount()):
            item = self.annotationsTree.topLevelItem(i)
            self.gdsSelectionStates[item.key] = item.checkState(0)
            for j in range(item.childCount()):
                child = item.child(j)
                self.gdsSelectionStates[child.key] = child.checkState(0)

    def filter(self):
        filter_string = unicode(self.filterLineEdit.text())
        proxyModel = self.treeWidget.model()
        if proxyModel:
            strings = filter_string.lower().strip().split()
            proxyModel.setFilterFixedStrings(strings)
            self.updateInfo()

    def selectedSamples(self):
        """
        Return the currently selected sample annotations.

        The return value is a list of selected (sample type, sample value)
        tuples.

        .. note:: if some Sample annotation type has no selected values.
                  this method will return all values for it.

        """
        samples = []
        unused_types = []
        used_types = []
        for stype in childiter(self.annotationsTree.invisibleRootItem()):
            selected_values = []
            all_values = []
            for sval in childiter(stype):
                value = (str(stype.text(0)), str(sval.text(0)))
                if self.gdsSelectionStates.get(sval.key, True):
                    selected_values.append(value)
                all_values.append(value)
            if selected_values:
                samples.extend(selected_values)
                used_types.append(str(stype.text(0)))
            else:
                # If no sample of sample type is selected we don't filter
                # on it.
                samples.extend(all_values)
                unused_types.append(str(stype.text(0)))

        return samples, used_types

    def commitIf(self):
        if self.autoCommit:
            self.commit()
        else:
            self.selectionChanged = True

    def commit(self):
        if self.currentGds:
            self.error(0)
            sample_type = None
            self.progressBarInit()
            self.progressBarSet(10)

            _, groups = self.selectedSamples()
            if len(groups) == 1 and self.outputRows:
                sample_type = groups[0]

            self.setEnabled(False)
            self.setBlocking(True)

            def get_data(gds_id, report_genes, transpose, sample_type, title):
                gds = geo.GDS(gds_id)
                data = gds.getdata(
                    report_genes=report_genes, transpose=transpose,
                    sample_type=sample_type
                )
                data.name = title
                return data

            get_data = partial(
                get_data, self.currentGds["dataset_id"],
                report_genes=self.mergeSpots,
                transpose=self.outputRows,
                sample_type=sample_type,
                title=self.datasetName or self.currentGds["title"]
            )
            self._datatask = Task(function=get_data)
            self._datatask.finished.connect(self._on_dataready)
            self._executor.submit(self._datatask)

    def _on_dataready(self):
        self.setEnabled(True)
        self.setBlocking(False)

        self.progressBarSet(50)

        try:
            data = self._datatask.result()
        except urlrequest.URLError as error:
            self.error(0, "Error while connecting to the NCBI ftp server! %r" %
                       error)
            self._datatask = None
            self.progressBarFinished()
            return

        self._datatask = None

        data_name = data.name
        samples, _ = self.selectedSamples()

        self.warning(0)
        message = None
        if self.outputRows:
            def samplesinst(ex):
                out = []
                for meta in data.domain.metas:
                    out.append((meta.name, ex[meta].value))

                if data.domain.class_var.name != 'class':
                    out.append((data.domain.class_var.name,
                                ex[data.domain.class_var].value))

                return out
            samples = set(samples)
            mask = [samples.issuperset(samplesinst(ex)) for ex in data]
            data = data[numpy.array(mask, dtype=bool)]
            if len(data) == 0:
                message = "No samples with selected sample annotations."
        else:
            samples = set(samples)
            domain = Orange.data.Domain(
                [attr for attr in data.domain.attributes
                 if samples.issuperset(attr.attributes.items())],
                data.domain.class_var,
                data.domain.metas
            )
#             domain.addmetas(data.domain.getmetas())

            if len(domain.attributes) == 0:
                message = "No samples with selected sample annotations."
            stypes = set(s[0] for s in samples)
            for attr in domain.attributes:
                attr.attributes = dict(
                    (key, value) for key, value in attr.attributes.items()
                    if key in stypes
                )
            data = Orange.data.Table(domain, data)

        if message is not None:
            self.warning(0, message)

        data_hints.set_hint(data, "taxid", self.currentGds.get("taxid", ""),
                            10.0)
        data_hints.set_hint(data, "genesinrows", self.outputRows, 10.0)

        self.progressBarFinished()
        data.name = data_name
        self.send("Expression Data", data)

        model = self.treeWidget.model().sourceModel()
        row = self.gds.index(self.currentGds)

        model.setData(model.index(row, 0),  " ", Qt.DisplayRole)

        self.updateInfo()
        self.selectionChanged = False

    def splitterMoved(self, *args):
        self.splitterSettings = [str(sp.saveState()) for sp in self.splitters]

    def onDeleteWidget(self):
        if self._inittask:
            self._inittask.future().cancel()
            self._inittask.finished.disconnect(self._initializemodel)
        if self._datatask:
            self._datatask.future().cancel()
            self._datatask.finished.disconnect(self._on_dataready)
        self._executor.shutdown(wait=False)

        super(OWGEODatasets, self).onDeleteWidget()

    def onNameEdited(self):
        if self.currentGds:
            gds_id = self.currentGds["dataset_id"]
            self.datasetNames[gds_id] = unicode(self.nameEdit.text())
            self.commitIf()
예제 #18
0
class Preferences(QDialog):

    configuration = {}
    weight = 0

    def __init__(self, parent=None):
        super(Preferences, self).__init__(parent, Qt.Dialog)
        self.setWindowTitle(translations.TR_PREFERENCES_TITLE)
        self.setMinimumSize(QSize(800, 600))
        self.setMaximumSize(QSize(0, 0))
        vbox = QVBoxLayout(self)
        hbox = QHBoxLayout()
        vbox.setContentsMargins(0, 0, 5, 5)
        hbox.setContentsMargins(0, 0, 0, 0)

        self.tree = QTreeWidget()
        self.tree.header().setHidden(True)
        self.tree.setSelectionMode(QTreeWidget.SingleSelection)
        self.tree.setAnimated(True)
        self.tree.header().setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self.tree.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self.tree.header().setStretchLastSection(False)
        self.tree.setFixedWidth(200)
        self.stacked = QStackedLayout()
        hbox.addWidget(self.tree)
        hbox.addLayout(self.stacked)
        vbox.addLayout(hbox)

        hbox_footer = QHBoxLayout()
        self._btnSave = QPushButton(translations.TR_SAVE)
        self._btnCancel = QPushButton(translations.TR_CANCEL)
        hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding))
        hbox_footer.addWidget(self._btnCancel)
        hbox_footer.addWidget(self._btnSave)
        vbox.addLayout(hbox_footer)

        self.connect(self.tree, SIGNAL("itemSelectionChanged()"),
            self._change_current)
        self.connect(self._btnCancel, SIGNAL("clicked()"), self.close)
        self.connect(self._btnSave, SIGNAL("clicked()"),
            self._save_preferences)

        self.load_ui()
        self.tree.setCurrentItem(self.tree.topLevelItem(0))

    def _save_preferences(self):
        self.emit(SIGNAL("savePreferences()"))
        self.close()

    def load_ui(self):
        sections = sorted(list(Preferences.configuration.keys()),
            key=lambda item: Preferences.configuration[item]['weight'])
        for section in sections:
            text = Preferences.configuration[section]['text']
            Widget = Preferences.configuration[section]['widget']
            widget = Widget(self)
            area = QScrollArea()
            area.setWidgetResizable(True)
            area.setWidget(widget)
            index = self.stacked.addWidget(area)
            item = QTreeWidgetItem([text])
            item.setData(0, Qt.UserRole, index)
            self.tree.addTopLevelItem(item)

            #Sort Item Children
            subcontent = Preferences.configuration[section].get(
                'subsections', {})
            subsections = sorted(list(subcontent.keys()),
                key=lambda item: subcontent[item]['weight'])
            for sub in subsections:
                text = subcontent[sub]['text']
                Widget = subcontent[sub]['widget']
                widget = Widget(self)
                area = QScrollArea()
                area.setWidgetResizable(True)
                area.setWidget(widget)
                index = self.stacked.addWidget(area)
                subitem = QTreeWidgetItem([text])
                subitem.setData(0, Qt.UserRole, index)
                item.addChild(subitem)

        self.tree.expandAll()

    def _change_current(self):
        item = self.tree.currentItem()
        index = item.data(0, Qt.UserRole)
        self.stacked.setCurrentIndex(index)

    @classmethod
    def register_configuration(cls, section, widget, text, weight=None,
            subsection=None):
        if weight is None:
            Preferences.weight += 1
            weight = Preferences.weight
        if not subsection:
            Preferences.configuration[section] = {'widget': widget,
                'weight': weight, 'text': text}
        else:
            config = Preferences.configuration.get(section, {})
            if not config:
                config[section] = {'widget': None, 'weight': 100}
            subconfig = config.get('subsections', {})
            subconfig[subsection] = {'widget': widget, 'weight': weight,
                'text': text}
            config['subsections'] = subconfig
            Preferences.configuration[section] = config
예제 #19
0
    def __init__(self, term, row, parent=None):
        super(EditReportDialog, self).__init__(parent)

        self.term = term
        self.sid = term
        self.row = row
        terms = self.pullOnes('terms', self.term)
        datas = self.pullOnes('datas', self.row)
        session = self.pullOnes('session', terms['sessionID'])
        self.termname = str(
            session['name']) + ' ' + terms['name'] + ' Term Report'
        self.pagetitle = self.termname
        ko = 0

        #prepare data
        d = datas['description']
        d = d.split(':::')
        _title = d[0]
        _theme = d[1]
        _font = d[2]
        _ass = d[3]
        _gra = d[4]
        _set = d[5]

        _ass_list = _ass.split('::')
        _gra_list = _gra.split('::')
        _set_list = _set.split('::')

        _cla_list = _set.split('::')
        layout1 = QGridLayout()
        Form1 = QFormLayout()
        Form2 = QFormLayout()

        #title
        self.title = QLabel("Report Title")
        self.titleData = QLineEdit()
        self.titleData.setObjectName("name")
        self.titleData.setText(_title)

        tree = QTreeWidget()
        tree.setItemDelegate(Delegate())
        tree.setHeaderLabel("Which grading system will you be using?")

        tree1 = QTreeWidget()
        tree1.setHeaderLabel("Choose Assessments and classes")

        tree2 = QTreeWidget()
        tree2.setHeaderLabel("Report Card Settings")

        self.ass_arr = {}
        parent = QTreeWidgetItem(tree1)
        parent.setText(0, "Select Assessments")
        parent.setFlags(parent.flags() | Qt.ItemIsTristate
                        | Qt.ItemIsUserCheckable)
        arr = self.pullCas()
        if arr and len(arr) > 0:
            for val in arr:
                dt = self.pullOne(val['name'])
                child = QTreeWidgetItem(parent)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                child.setText(0, str(dt['name']).upper())
                self.ass_arr[val['id']] = child
                if str(val['id']) in _ass_list:
                    child.setCheckState(0, Qt.Checked)
                else:
                    child.setCheckState(0, Qt.Unchecked)
                ko += 1

        self.cla_arr = {}
        parent1 = QTreeWidgetItem(tree1)
        parent1.setText(0, "Select Class")
        parent1.setFlags(parent1.flags() | Qt.ItemIsTristate
                         | Qt.ItemIsUserCheckable)
        arr = self.pullClass()
        if arr and len(arr) > 0:
            for val in arr:
                child = QTreeWidgetItem(parent1)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                child.setText(0, str(val['name']).upper())
                self.cla_arr[val['id']] = child
                va = str(val['id'])
                if (va in _cla_list):
                    child.setCheckState(0, Qt.Checked)
                else:
                    child.setCheckState(0, Qt.Unchecked)
                ko += 1

        self.gra_arr = {}
        parent2 = QTreeWidgetItem(tree)
        parent2.setText(0, "Select Grade")
        arr = self.pullGrade()
        if arr and len(arr) > 0:
            for val in arr:
                child = QTreeWidgetItem(parent2)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                child.setText(0, str(val['name']).upper())
                self.gra_arr[val['id']] = child
                if str(val['id']) in _gra_list:
                    child.setCheckState(0, Qt.Checked)
                else:
                    child.setCheckState(0, Qt.Unchecked)
                ko += 1

        self.set_arr = {}
        parent3 = QTreeWidgetItem(tree2)
        parent3.setText(0, "Include ...")
        parent3.setFlags(parent3.flags() | Qt.ItemIsTristate
                         | Qt.ItemIsUserCheckable)
        arr = {
            1: 'School Number',
            2: 'Class Position',
            3: 'Class Unit Position',
            4: 'Total (100%)',
            5: 'Total',
            6: 'Grading',
            7: 'Subject Average',
            8: 'Ranking',
            9: 'Ranking and Student Population',
            10: 'Student Passport',
            11: 'School Logo',
            12: 'School Address',
            13: 'Students Address',
            14: 'Attendance',
            15: 'Fees Owed',
            16: 'Test/Assesments'
        }
        if arr and len(arr) > 0:
            for val in arr:

                child = QTreeWidgetItem(parent3)
                child.setFlags(child.flags() | Qt.ItemIsUserCheckable)
                child.setText(0, str(arr[val]).upper())
                self.set_arr[val] = child

                if str(val) in _set_list:

                    child.setCheckState(0, Qt.Checked)
                else:
                    child.setCheckState(0, Qt.Unchecked)

            child1 = QTreeWidgetItem(parent3)
            child1.setFlags(child1.flags() | Qt.ItemIsUserCheckable)
            child1.setText(0, 'AFFECTIVE DOMAIN REPORT')
            self.set_arr['aff'] = child1
            if 'aff' in _set_list:
                child1.setCheckState(0, Qt.Checked)
            else:
                child1.setCheckState(0, Qt.Unchecked)

            child2 = QTreeWidgetItem(child1)
            child2.setFlags(child2.flags() | Qt.ItemIsTristate
                            | Qt.ItemIsUserCheckable)
            child2.setText(0, 'TABLE')
            self.set_arr['afftable'] = child2
            if 'afftable' in _set_list:
                child2.setCheckState(0, Qt.Checked)
            else:
                child2.setCheckState(0, Qt.Unchecked)

            child3 = QTreeWidgetItem(child1)
            child3.setFlags(child3.flags() | Qt.ItemIsUserCheckable)
            child3.setText(0, 'GRAPH')
            self.set_arr['affgraph'] = child3
            if 'affgraph' in _set_list:
                child3.setCheckState(0, Qt.Checked)
            else:
                child3.setCheckState(0, Qt.Unchecked)

            child4 = QTreeWidgetItem(parent3)
            child4.setFlags(child4.flags() | Qt.ItemIsTristate
                            | Qt.ItemIsUserCheckable)
            child4.setText(0, 'PYSCHOMOTOR DOMAIN REPORT')
            self.set_arr['psy'] = child4
            if 'psy' in _set_list:
                child4.setCheckState(0, Qt.Checked)
            else:
                child4.setCheckState(0, Qt.Unchecked)

            child5 = QTreeWidgetItem(child4)
            child5.setFlags(child5.flags() | Qt.ItemIsUserCheckable)
            child5.setText(0, 'TABLE')
            self.set_arr['psytable'] = child5
            if 'psytable' in _set_list:
                child5.setCheckState(0, Qt.Checked)
            else:
                child5.setCheckState(0, Qt.Unchecked)

            child6 = QTreeWidgetItem(child4)
            child6.setFlags(child6.flags() | Qt.ItemIsUserCheckable)
            child6.setText(0, 'GRAPH')
            self.set_arr['psygraph'] = child6
            if 'psygraph' in _set_list:
                child6.setCheckState(0, Qt.Checked)
            else:
                child6.setCheckState(0, Qt.Unchecked)

        tree.expandAll()
        tree1.expandAll()
        tree2.expandAll()
        #tree.show()

        self.l5 = QLabel("Theme Color")
        self.pbc = QPushButton()
        self.pbc.setObjectName("Pickcolor")
        self.pbc.setText("Click to change")

        self.le5 = QLineEdit()
        self.le5.setObjectName("Showcolor")
        self.le5.setText(_theme)
        self.pbc.setStyleSheet("background-color: " + _theme +
                               "; color: white")
        self.connect(self.pbc, SIGNAL("clicked()"),
                     lambda: self.color_picker())

        self.l6 = QLabel("Pick Theme Font")
        self.pbf = QPushButton()
        self.pbf.setObjectName("Pickfont")
        self.pbf.setText(_font)

        self.le6 = QLineEdit()
        self.le6.setObjectName("Showcolor")
        self.le6.setText("#000000")
        self.pbf.setStyleSheet("color: black")
        self.connect(self.pbf, SIGNAL("clicked()"), lambda: self.font_picker())

        self.lv_box = QHBoxLayout()
        self.lv_box.addWidget(self.pbc)
        self.lv_box.addWidget(self.le5)

        self.lv_box1 = QHBoxLayout()
        self.lv_box1.addWidget(self.pbf)
        self.lv_box1.addWidget(self.le6)

        Form1.addRow(self.title, self.titleData)
        Form2.addRow(self.l5, self.lv_box)
        Form2.addRow(self.l6, self.lv_box1)

        Gbo = QGridLayout()
        Gbo.addLayout(Form1, 0, 0, 1, 2)
        Gbo.addWidget(tree, 1, 0)
        Gbo.addWidget(tree1, 1, 1)
        Gbo.addWidget(tree2, 2, 0)
        Gbo.addLayout(Form2, 2, 1)

        groupBox1 = QGroupBox('Academic Report Setup')
        groupBox1.setLayout(Gbo)

        self.pb = QPushButton()
        self.pb.setObjectName("Add")
        self.pb.setText("Add Assessment")

        self.pb1 = QPushButton()
        self.pb1.setObjectName("Cancel")
        self.pb1.setText("Cancel")

        hbo = QHBoxLayout()
        hbo.addWidget(self.pb1)
        hbo.addStretch()
        hbo.addWidget(self.pb)

        groupBox2 = QGroupBox('')
        groupBox2.setLayout(hbo)

        grid = QGridLayout()
        grid.addWidget(groupBox1, 0, 0)
        grid.addWidget(groupBox2, 1, 0)

        self.setLayout(grid)
        self.connect(self.pb, SIGNAL("clicked()"),
                     lambda: self.button_click(self))
        self.connect(self.pb1, SIGNAL("clicked()"),
                     lambda: self.button_close(self))

        self.setWindowTitle(self.pagetitle)
예제 #20
0
class OWItemsets(widget.OWWidget):
    name = "Frequent Itemsets"
    description = "Explore sets of items that frequently appear together."
    icon = "icons/FrequentItemsets.svg"
    priority = 10

    inputs = [("Data", Table, "set_data")]
    outputs = [(Output.DATA, Table)]

    minSupport = settings.Setting(30)
    maxItemsets = settings.Setting(10000)
    filterSearch = settings.Setting(True)
    autoFind = settings.Setting(False)
    autoSend = settings.Setting(True)
    filterKeywords = settings.Setting("")
    filterMinItems = settings.Setting(1)
    filterMaxItems = settings.Setting(10000)

    UserAdviceMessages = [
        widget.Message(
            "Itemset are listed in item-sorted order, i.e. "
            "an itemset containing A and B is only listed once, as "
            "A > B (and not also B > A).",
            "itemsets-order",
            widget.Message.Warning,
        ),
        widget.Message(
            "To select all the itemsets that are descendants of "
            "(include) some item X (i.e. the whole subtree), you "
            "can fold the subtree at that item and then select it.",
            "itemsets-order",
            widget.Message.Information,
        ),
    ]

    def __init__(self):
        self._is_running = False
        self.isRegexMatch = lambda x: True
        self.tree = QTreeWidget(
            self.mainArea,
            columnCount=2,
            allColumnsShowFocus=True,
            alternatingRowColors=True,
            selectionMode=QTreeWidget.ExtendedSelection,
            uniformRowHeights=True,
        )
        self.tree.setHeaderLabels(["Itemsets", "Support", "%"])
        self.tree.header().setStretchLastSection(True)
        self.tree.itemSelectionChanged.connect(self.selectionChanged)
        self.mainArea.layout().addWidget(self.tree)

        box = gui.widgetBox(self.controlArea, "Info")
        self.nItemsets = self.nSelectedExamples = self.nSelectedItemsets = ""
        gui.label(box, self, "Number of itemsets: %(nItemsets)s")
        gui.label(box, self, "Selected itemsets: %(nSelectedItemsets)s")
        gui.label(box, self, "Selected examples: %(nSelectedExamples)s")
        hbox = gui.widgetBox(box, orientation="horizontal")
        gui.button(hbox, self, "Expand all", callback=self.tree.expandAll)
        gui.button(hbox, self, "Collapse all", callback=self.tree.collapseAll)

        box = gui.widgetBox(self.controlArea, "Find itemsets")
        gui.valueSlider(
            box,
            self,
            "minSupport",
            values=[0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5] + list(range(1, 101)),
            label="Minimal support:",
            labelFormat="%g%%",
            callback=lambda: self.find_itemsets(),
        )
        gui.hSlider(
            box,
            self,
            "maxItemsets",
            minValue=10000,
            maxValue=100000,
            step=10000,
            label="Max. number of itemsets:",
            labelFormat="%d",
            callback=lambda: self.find_itemsets(),
        )
        self.button = gui.auto_commit(box, self, "autoFind", "Find itemsets", commit=self.find_itemsets)

        box = gui.widgetBox(self.controlArea, "Filter itemsets")
        gui.lineEdit(
            box,
            self,
            "filterKeywords",
            "Contains:",
            callback=self.filter_change,
            orientation="horizontal",
            tooltip="A comma or space-separated list of regular " "expressions.",
        )
        hbox = gui.widgetBox(box, orientation="horizontal")
        gui.spin(hbox, self, "filterMinItems", 1, 998, label="Min. items:", callback=self.filter_change)
        gui.spin(hbox, self, "filterMaxItems", 2, 999, label="Max. items:", callback=self.filter_change)
        gui.checkBox(
            box,
            self,
            "filterSearch",
            label="Apply these filters in search",
            tooltip="If checked, the itemsets are filtered according "
            "to these filter conditions already in the search "
            "phase. \nIf unchecked, the only filters applied "
            "during search are the ones above, "
            "and the itemsets are \nfiltered afterwards only for "
            "display, i.e. only the matching itemsets are shown.",
        )

        gui.rubber(hbox)

        gui.rubber(self.controlArea)
        gui.auto_commit(self.controlArea, self, "autoSend", "Send selection")

        self.filter_change()

    ITEM_DATA_ROLE = Qt.UserRole + 1

    def selectionChanged(self):
        X = self.X
        mapping = self.onehot_mapping
        instances = set()
        where = np.where

        def whole_subtree(node):
            yield node
            for i in range(node.childCount()):
                yield from whole_subtree(node.child(i))

        def itemset(node):
            while node:
                yield node.data(0, self.ITEM_DATA_ROLE)
                node = node.parent()

        def selection_ranges(node):
            n_children = node.childCount()
            if n_children:
                yield (self.tree.indexFromItem(node.child(0)), self.tree.indexFromItem(node.child(n_children - 1)))
            for i in range(n_children):
                yield from selection_ranges(node.child(i))

        nSelectedItemsets = 0
        item_selection = QItemSelection()
        for node in self.tree.selectedItems():
            nodes = (node,) if node.isExpanded() else whole_subtree(node)
            if not node.isExpanded():
                for srange in selection_ranges(node):
                    item_selection.select(*srange)
            for node in nodes:
                nSelectedItemsets += 1
                cols, vals = zip(*(mapping[i] for i in itemset(node)))
                if issparse(X):
                    rows = (len(cols) == np.bincount((X[:, cols] != 0).indices, minlength=X.shape[0])).nonzero()[0]
                else:
                    rows = where((X[:, cols] == vals).all(axis=1))[0]
                instances.update(rows)
        self.tree.itemSelectionChanged.disconnect(self.selectionChanged)
        self.tree.selectionModel().select(item_selection, QItemSelectionModel.Select | QItemSelectionModel.Rows)
        self.tree.itemSelectionChanged.connect(self.selectionChanged)

        self.nSelectedExamples = len(instances)
        self.nSelectedItemsets = nSelectedItemsets
        self.output = self.data[sorted(instances)] or None
        self.commit()

    def commit(self):
        self.send(Output.DATA, self.output)

    def filter_change(self):
        self.warning(9)
        try:
            isRegexMatch = self.isRegexMatch = re.compile(
                "|".join(i.strip() for i in re.split("(,|\s)+", self.filterKeywords.strip()) if i.strip()),
                re.IGNORECASE,
            ).search
        except Exception as e:
            self.warning(9, "Error in regular expression: {}".format(e.args[0]))
            isRegexMatch = self.isRegexMatch = lambda x: True

        def hide(node, depth, has_kw):
            if not has_kw:
                has_kw = isRegexMatch(node.text(0))
            hidden = (
                sum(hide(node.child(i), depth + 1, has_kw) for i in range(node.childCount())) == node.childCount()
                if node.childCount()
                else (not has_kw or not self.filterMinItems <= depth <= self.filterMaxItems)
            )
            node.setHidden(hidden)
            return hidden

        hide(self.tree.invisibleRootItem(), 0, False)

    class TreeWidgetItem(QTreeWidgetItem):
        def data(self, column, role):
            """Construct lazy tooltips"""
            if role != Qt.ToolTipRole:
                return super().data(column, role)
            tooltip = []
            while self:
                tooltip.append(self.text(0))
                self = self.parent()
            return " ".join(reversed(tooltip))

    def find_itemsets(self):
        if self.data is None:
            return
        if self._is_running:
            return
        self._is_running = True

        data = self.data
        self.tree.clear()
        self.tree.setUpdatesEnabled(False)
        self.tree.blockSignals(True)

        class ItemDict(dict):
            def __init__(self, item):
                self.item = item

        top = ItemDict(self.tree.invisibleRootItem())
        X, mapping = OneHot.encode(data)
        self.onehot_mapping = mapping
        ITEM_FMT = "{}" if issparse(data.X) else "{}={}"
        names = {
            item: ITEM_FMT.format(var.name, val) for item, var, val in OneHot.decode(mapping.keys(), data, mapping)
        }
        nItemsets = 0

        filterSearch = self.filterSearch
        filterMinItems, filterMaxItems = self.filterMinItems, self.filterMaxItems
        isRegexMatch = self.isRegexMatch

        # Find itemsets and populate the TreeView
        with self.progressBar(self.maxItemsets + 1) as progress:
            for itemset, support in frequent_itemsets(X, self.minSupport / 100):

                if filterSearch and not filterMinItems <= len(itemset) <= filterMaxItems:
                    continue

                parent = top
                first_new_item = None
                itemset_matches_filter = False

                for item in sorted(itemset):
                    name = names[item]

                    if filterSearch and not itemset_matches_filter:
                        itemset_matches_filter = isRegexMatch(name)

                    child = parent.get(name)
                    if child is None:
                        try:
                            wi = self.TreeWidgetItem(
                                parent.item, [name, str(support), "{:.4g}".format(100 * support / len(data))]
                            )
                        except RuntimeError:
                            # FIXME: When autoFind was in effect and the support
                            # slider was moved, this line excepted with:
                            #     RuntimeError: wrapped C/C++ object of type
                            #                   TreeWidgetItem has been deleted
                            return
                        wi.setData(0, self.ITEM_DATA_ROLE, item)
                        child = parent[name] = ItemDict(wi)

                        if first_new_item is None:
                            first_new_item = (parent, name)
                    parent = child

                if filterSearch and not itemset_matches_filter:
                    parent, name = first_new_item
                    parent.item.removeChild(parent[name].item)
                    del parent[name].item
                    del parent[name]
                else:
                    nItemsets += 1
                    progress.advance()
                if nItemsets >= self.maxItemsets:
                    break

        if not filterSearch:
            self.filter_change()
        self.nItemsets = nItemsets
        self.nSelectedItemsets = 0
        self.nSelectedExamples = 0
        self.tree.expandAll()
        for i in range(self.tree.columnCount()):
            self.tree.resizeColumnToContents(i)
        self.tree.setUpdatesEnabled(True)
        self.tree.blockSignals(False)
        self._is_running = False

    def set_data(self, data):
        self.data = data
        is_error = False
        if data is not None:
            self.warning(0)
            self.error(1)
            self.button.setDisabled(False)
            self.X = data.X
            if issparse(data.X):
                self.X = data.X.tocsc()
            else:
                if not data.domain.has_discrete_attributes():
                    self.error(1, "Discrete features required but data has none.")
                    is_error = True
                    self.button.setDisabled(True)
                elif data.domain.has_continuous_attributes():
                    self.warning(0, "Data has continuous attributes which will be skipped.")
        else:
            self.output = None
            self.commit()
        if self.autoFind and not is_error:
            self.find_itemsets()
예제 #21
0
class OWGEODatasets(OWWidget):
    name = "GEO Data Sets"
    description = DESCRIPTION
    icon = "../widgets/icons/GEODataSets.svg"
    priority = PRIORITY

    inputs = []
    outputs = [("Expression Data", Orange.data.Table)]

    settingsList = [
        "outputRows", "mergeSpots", "gdsSelectionStates", "splitterSettings",
        "currentGds", "autoCommit", "datasetNames"
    ]

    outputRows = Setting(True)
    mergeSpots = Setting(True)
    gdsSelectionStates = Setting({})
    currentGds = Setting(None)
    datasetNames = Setting({})
    splitterSettings = Setting((
        b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xea\x00\x00\x00\xd7\x01\x00\x00\x00\x07\x01\x00\x00\x00\x02',
        b'\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xb5\x00\x00\x02\x10\x01\x00\x00\x00\x07\x01\x00\x00\x00\x01'
    ))

    autoCommit = Setting(False)

    def __init__(self, parent=None, signalManager=None, name=" GEO Data Sets"):
        OWWidget.__init__(self, parent, signalManager, name)

        self.selectionChanged = False
        self.filterString = ""
        self.datasetName = ""

        ## GUI
        box = gui.widgetBox(self.controlArea, "Info", addSpace=True)
        self.infoBox = gui.widgetLabel(box, "Initializing\n\n")

        box = gui.widgetBox(self.controlArea, "Output", addSpace=True)
        gui.radioButtonsInBox(box,
                              self,
                              "outputRows",
                              ["Genes in rows", "Samples in rows"],
                              "Rows",
                              callback=self.commitIf)

        gui.checkBox(box,
                     self,
                     "mergeSpots",
                     "Merge spots of same gene",
                     callback=self.commitIf)

        gui.separator(box)
        self.nameEdit = gui.lineEdit(
            box,
            self,
            "datasetName",
            "Data set name",
            tooltip="Override the default output data set name",
            callback=self.onNameEdited)
        self.nameEdit.setPlaceholderText("")

        if sys.version_info < (3, ):
            box = gui.widgetBox(self.controlArea, "Commit", addSpace=True)
            self.commitButton = gui.button(box,
                                           self,
                                           "Commit",
                                           callback=self.commit)
            cb = gui.checkBox(box, self, "autoCommit", "Commit on any change")
            gui.setStopper(self, self.commitButton, cb, "selectionChanged",
                           self.commit)
        else:
            gui.auto_commit(self.controlArea,
                            self,
                            "autoCommit",
                            "Commit",
                            box="Commit")
            self.commitIf = self.commit

        gui.rubber(self.controlArea)

        gui.widgetLabel(self.mainArea, "Filter")
        self.filterLineEdit = QLineEdit(textChanged=self.filter)
        self.completer = TokenListCompleter(self,
                                            caseSensitivity=Qt.CaseInsensitive)
        self.filterLineEdit.setCompleter(self.completer)

        self.mainArea.layout().addWidget(self.filterLineEdit)

        splitter = QSplitter(Qt.Vertical, self.mainArea)
        self.mainArea.layout().addWidget(splitter)
        self.treeWidget = QTreeView(splitter)

        self.treeWidget.setSelectionMode(QTreeView.SingleSelection)
        self.treeWidget.setRootIsDecorated(False)
        self.treeWidget.setSortingEnabled(True)
        self.treeWidget.setAlternatingRowColors(True)
        self.treeWidget.setUniformRowHeights(True)
        self.treeWidget.setEditTriggers(QTreeView.NoEditTriggers)

        linkdelegate = LinkStyledItemDelegate(self.treeWidget)
        self.treeWidget.setItemDelegateForColumn(1, linkdelegate)
        self.treeWidget.setItemDelegateForColumn(8, linkdelegate)
        self.treeWidget.setItemDelegateForColumn(
            0, gui.IndicatorItemDelegate(self.treeWidget, role=Qt.DisplayRole))

        proxyModel = MySortFilterProxyModel(self.treeWidget)
        self.treeWidget.setModel(proxyModel)
        self.treeWidget.selectionModel().selectionChanged.connect(
            self.updateSelection)
        self.treeWidget.viewport().setMouseTracking(True)

        splitterH = QSplitter(Qt.Horizontal, splitter)

        box = gui.widgetBox(splitterH, "Description")
        self.infoGDS = gui.widgetLabel(box, "")
        self.infoGDS.setWordWrap(True)
        gui.rubber(box)

        box = gui.widgetBox(splitterH, "Sample Annotations")
        self.annotationsTree = QTreeWidget(box)
        self.annotationsTree.setHeaderLabels(
            ["Type (Sample annotations)", "Sample count"])
        self.annotationsTree.setRootIsDecorated(True)
        box.layout().addWidget(self.annotationsTree)
        self.annotationsTree.itemChanged.connect(
            self.annotationSelectionChanged)
        self._annotationsUpdating = False
        self.splitters = splitter, splitterH

        for sp, setting in zip(self.splitters, self.splitterSettings):
            sp.splitterMoved.connect(self.splitterMoved)
            sp.restoreState(setting)

        self.searchKeys = [
            "dataset_id", "title", "platform_organism", "description"
        ]

        self.gds = []
        self.gds_info = None

        self.resize(1000, 600)

        self.setBlocking(True)
        self.setEnabled(False)
        self.progressBarInit()

        self._executor = ThreadExecutor()

        func = partial(get_gds_model,
                       methodinvoke(self, "_setProgress", (float, )))
        self._inittask = Task(function=func)
        self._inittask.finished.connect(self._initializemodel)
        self._executor.submit(self._inittask)

        self._datatask = None

    @Slot(float)
    def _setProgress(self, value):
        self.progressBarValue = value

    def _initializemodel(self):
        assert self.thread() is QThread.currentThread()
        model, self.gds_info, self.gds = self._inittask.result()
        model.setParent(self)

        proxy = self.treeWidget.model()
        proxy.setFilterKeyColumn(0)
        proxy.setFilterRole(TextFilterRole)
        proxy.setFilterCaseSensitivity(False)
        proxy.setFilterFixedString(self.filterString)

        proxy.setSourceModel(model)
        proxy.sort(0, Qt.DescendingOrder)

        self.progressBarFinished()
        self.setBlocking(False)
        self.setEnabled(True)

        filter_items = " ".join(gds[key] for gds in self.gds
                                for key in self.searchKeys)
        tr_chars = ",.:;!?(){}[]_-+\\|/%#@$^&*<>~`"
        tr_table = str.maketrans(tr_chars, " " * len(tr_chars))
        filter_items = filter_items.translate(tr_table)

        filter_items = sorted(set(filter_items.split(" ")))
        filter_items = [item for item in filter_items if len(item) > 3]

        self.completer.setTokenList(filter_items)

        if self.currentGds:
            current_id = self.currentGds["dataset_id"]
            gdss = [(i, qunpack(proxy.data(proxy.index(i, 1), Qt.DisplayRole)))
                    for i in range(proxy.rowCount())]
            current = [i for i, data in gdss if data and data == current_id]
            if current:
                current_index = proxy.index(current[0], 0)
                self.treeWidget.selectionModel().select(
                    current_index,
                    QItemSelectionModel.Select | QItemSelectionModel.Rows)
                self.treeWidget.scrollTo(current_index,
                                         QTreeView.PositionAtCenter)

        for i in range(8):
            self.treeWidget.resizeColumnToContents(i)

        self.treeWidget.setColumnWidth(
            1, min(self.treeWidget.columnWidth(1), 300))
        self.treeWidget.setColumnWidth(
            2, min(self.treeWidget.columnWidth(2), 200))

        self.updateInfo()

    def updateInfo(self):
        gds_info = self.gds_info
        text = ("%i datasets\n%i datasets cached\n" %
                (len(gds_info),
                 len(glob.glob(serverfiles.localpath("GEO") + "/GDS*"))))
        filtered = self.treeWidget.model().rowCount()
        if len(self.gds) != filtered:
            text += ("%i after filtering") % filtered
        self.infoBox.setText(text)

    def updateSelection(self, *args):
        current = self.treeWidget.selectedIndexes()
        mapToSource = self.treeWidget.model().mapToSource
        current = [mapToSource(index).row() for index in current]
        if current:
            self.currentGds = self.gds[current[0]]
            self.setAnnotations(self.currentGds)
            self.infoGDS.setText(self.currentGds.get("description", ""))
            self.nameEdit.setPlaceholderText(self.currentGds["title"])
            self.datasetName = \
                self.datasetNames.get(self.currentGds["dataset_id"], "")
        else:
            self.currentGds = None
            self.nameEdit.setPlaceholderText("")
            self.datasetName = ""

        self.commitIf()

    def setAnnotations(self, gds):
        self._annotationsUpdating = True
        self.annotationsTree.clear()

        annotations = defaultdict(set)
        subsetscount = {}
        for desc in gds["subsets"]:
            annotations[desc["type"]].add(desc["description"])
            subsetscount[desc["description"]] = str(len(desc["sample_id"]))

        for type, subsets in annotations.items():
            key = (gds["dataset_id"], type)
            subsetItem = QTreeWidgetItem(self.annotationsTree, [type])
            subsetItem.setFlags(subsetItem.flags() | Qt.ItemIsUserCheckable
                                | Qt.ItemIsTristate)
            subsetItem.setCheckState(
                0, self.gdsSelectionStates.get(key, Qt.Checked))
            subsetItem.key = key
            for subset in subsets:
                key = (gds["dataset_id"], type, subset)
                item = QTreeWidgetItem(
                    subsetItem, [subset, subsetscount.get(subset, "")])
                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
                item.setCheckState(
                    0, self.gdsSelectionStates.get(key, Qt.Checked))
                item.key = key
        self._annotationsUpdating = False
        self.annotationsTree.expandAll()
        for i in range(self.annotationsTree.columnCount()):
            self.annotationsTree.resizeColumnToContents(i)

    def annotationSelectionChanged(self, item, column):
        if self._annotationsUpdating:
            return
        for i in range(self.annotationsTree.topLevelItemCount()):
            item = self.annotationsTree.topLevelItem(i)
            self.gdsSelectionStates[item.key] = item.checkState(0)
            for j in range(item.childCount()):
                child = item.child(j)
                self.gdsSelectionStates[child.key] = child.checkState(0)

    def filter(self):
        filter_string = unicode(self.filterLineEdit.text())
        proxyModel = self.treeWidget.model()
        if proxyModel:
            strings = filter_string.lower().strip().split()
            proxyModel.setFilterFixedStrings(strings)
            self.updateInfo()

    def selectedSamples(self):
        """
        Return the currently selected sample annotations.

        The return value is a list of selected (sample type, sample value)
        tuples.

        .. note:: if some Sample annotation type has no selected values.
                  this method will return all values for it.

        """
        samples = []
        unused_types = []
        used_types = []
        for stype in childiter(self.annotationsTree.invisibleRootItem()):
            selected_values = []
            all_values = []
            for sval in childiter(stype):
                value = (str(stype.text(0)), str(sval.text(0)))
                if self.gdsSelectionStates.get(sval.key, True):
                    selected_values.append(value)
                all_values.append(value)
            if selected_values:
                samples.extend(selected_values)
                used_types.append(str(stype.text(0)))
            else:
                # If no sample of sample type is selected we don't filter
                # on it.
                samples.extend(all_values)
                unused_types.append(str(stype.text(0)))

        return samples, used_types

    def commitIf(self):
        if self.autoCommit:
            self.commit()
        else:
            self.selectionChanged = True

    @Slot(int, int)
    def progressCompleted(self, value, total):
        if total > 0:
            self.progressBarSet(100. * value / total, processEvents=False)
        else:
            pass
            # TODO: report 'indeterminate progress'

    def commit(self):
        if self.currentGds:
            self.error(0)
            sample_type = None
            self.progressBarInit(processEvents=None)

            _, groups = self.selectedSamples()
            if len(groups) == 1 and self.outputRows:
                sample_type = groups[0]

            self.setEnabled(False)
            self.setBlocking(True)

            progress = methodinvoke(self, "progressCompleted", (int, int))

            def get_data(gds_id, report_genes, transpose, sample_type, title):
                gds_ensure_downloaded(gds_id, progress)
                gds = geo.GDS(gds_id)
                data = gds.getdata(report_genes=report_genes,
                                   transpose=transpose,
                                   sample_type=sample_type)
                data.name = title
                return data

            get_data = partial(get_data,
                               self.currentGds["dataset_id"],
                               report_genes=self.mergeSpots,
                               transpose=self.outputRows,
                               sample_type=sample_type,
                               title=self.datasetName
                               or self.currentGds["title"])
            self._datatask = Task(function=get_data)
            self._datatask.finished.connect(self._on_dataready)
            self._executor.submit(self._datatask)

    def _on_dataready(self):
        self.setEnabled(True)
        self.setBlocking(False)
        self.progressBarFinished(processEvents=False)

        try:
            data = self._datatask.result()
        except urlrequest.URLError as error:
            self.error(0, ("Error while connecting to the NCBI ftp server! "
                           "'%s'" % error))
            sys.excepthook(type(error), error, getattr(error, "__traceback__"))
            return
        finally:
            self._datatask = None

        data_name = data.name
        samples, _ = self.selectedSamples()

        self.warning(0)
        message = None
        if self.outputRows:

            def samplesinst(ex):
                out = []
                for meta in data.domain.metas:
                    out.append((meta.name, ex[meta].value))

                if data.domain.class_var.name != 'class':
                    out.append((data.domain.class_var.name,
                                ex[data.domain.class_var].value))

                return out

            samples = set(samples)
            mask = [samples.issuperset(samplesinst(ex)) for ex in data]
            data = data[numpy.array(mask, dtype=bool)]
            if len(data) == 0:
                message = "No samples with selected sample annotations."
        else:
            samples = set(samples)
            domain = Orange.data.Domain([
                attr for attr in data.domain.attributes
                if samples.issuperset(attr.attributes.items())
            ], data.domain.class_var, data.domain.metas)
            #             domain.addmetas(data.domain.getmetas())

            if len(domain.attributes) == 0:
                message = "No samples with selected sample annotations."
            stypes = set(s[0] for s in samples)
            for attr in domain.attributes:
                attr.attributes = dict(
                    (key, value) for key, value in attr.attributes.items()
                    if key in stypes)
            data = Orange.data.Table(domain, data)

        if message is not None:
            self.warning(0, message)

        data_hints.set_hint(data, "taxid", self.currentGds.get("taxid", ""),
                            10.0)
        data_hints.set_hint(data, "genesinrows", self.outputRows, 10.0)

        data.name = data_name
        self.send("Expression Data", data)

        model = self.treeWidget.model().sourceModel()
        row = self.gds.index(self.currentGds)

        model.setData(model.index(row, 0), " ", Qt.DisplayRole)

        self.updateInfo()
        self.selectionChanged = False

    def splitterMoved(self, *args):
        self.splitterSettings = [
            bytes(sp.saveState()) for sp in self.splitters
        ]

    def send_report(self):
        self.report_items("GEO Dataset",
                          [("ID", self.currentGds['dataset_id']),
                           ("Title", self.currentGds['title']),
                           ("Organism", self.currentGds['sample_organism'])])
        self.report_items("Data",
                          [("Samples", self.currentGds['sample_count']),
                           ("Features", self.currentGds['feature_count']),
                           ("Genes", self.currentGds['gene_count'])])
        self.report_name("Sample annotations")
        subsets = defaultdict(list)
        for subset in self.currentGds['subsets']:
            subsets[subset['type']].append(
                (subset['description'], len(subset['sample_id'])))
        self.report_html += "<ul>"
        for type in subsets:
            self.report_html += "<b>" + type + ":</b></br>"
            for desc, count in subsets[type]:
                self.report_html += 9 * "&nbsp" + "<b>{}:</b> {}</br>".format(
                    desc, count)
        self.report_html += "</ul>"

    def onDeleteWidget(self):
        if self._inittask:
            self._inittask.future().cancel()
            self._inittask.finished.disconnect(self._initializemodel)
        if self._datatask:
            self._datatask.future().cancel()
            self._datatask.finished.disconnect(self._on_dataready)
        self._executor.shutdown(wait=False)

        super(OWGEODatasets, self).onDeleteWidget()

    def onNameEdited(self):
        if self.currentGds:
            gds_id = self.currentGds["dataset_id"]
            self.datasetNames[gds_id] = unicode(self.nameEdit.text())
            self.commitIf()
예제 #22
0
 def expandAll(self):
     self._treeDepth=10000
     QTreeWidget.expandAll(self)
예제 #23
0
class TreeSymbolsWidget(QDialog):
    """Class of Dialog for Tree Symbols"""
    def __init__(self, parent=None):
        super(TreeSymbolsWidget, self).__init__(parent,
                                                Qt.WindowStaysOnTopHint)
        vbox = QVBoxLayout(self)
        vbox.setContentsMargins(0, 0, 0, 0)
        vbox.setSpacing(0)
        self.tree = QTreeWidget()
        vbox.addWidget(self.tree)
        self.tree.header().setHidden(True)
        self.tree.setSelectionMode(self.tree.SingleSelection)
        self.tree.setAnimated(True)
        self.tree.header().setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self.tree.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self.tree.header().setStretchLastSection(False)
        self.actualSymbols = ('', {})
        self.docstrings = {}
        self.collapsedItems = {}

        self.connect(self, SIGNAL("itemClicked(QTreeWidgetItem *, int)"),
                     self._go_to_definition)
        self.connect(self, SIGNAL("itemActivated(QTreeWidgetItem *, int)"),
                     self._go_to_definition)
        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connect(self,
                     SIGNAL("customContextMenuRequested(const QPoint &)"),
                     self._menu_context_tree)
        self.connect(self, SIGNAL("itemCollapsed(QTreeWidgetItem *)"),
                     self._item_collapsed)
        self.connect(self, SIGNAL("itemExpanded(QTreeWidgetItem *)"),
                     self._item_expanded)

        IDE.register_service('symbols_explorer', self)
        ExplorerContainer.register_tab(translations.TR_TAB_SYMBOLS, self)

    def install_tab(self):
        """Connect signals for goingdown"""
        ide = IDE.get_service('ide')
        self.connect(ide, SIGNAL("goingDown()"), self.close)

    def _menu_context_tree(self, point):
        """Context menu"""
        index = self.tree.indexAt(point)
        if not index.isValid():
            return

        menu = QMenu(self)
        f_all = menu.addAction(translations.TR_FOLD_ALL)
        u_all = menu.addAction(translations.TR_UNFOLD_ALL)
        menu.addSeparator()
        u_class = menu.addAction(translations.TR_UNFOLD_CLASSES)
        u_class_method = menu.addAction(
            translations.TR_UNFOLD_CLASSES_AND_METHODS)
        u_class_attr = menu.addAction(
            translations.TR_UNFOLD_CLASSES_AND_ATTRIBUTES)
        menu.addSeparator()
        #save_state = menu.addAction(self.tr("Save State"))

        self.connect(f_all, SIGNAL("triggered()"),
                     lambda: self.tree.collapseAll())
        self.connect(u_all, SIGNAL("triggered()"),
                     lambda: self.tree.expandAll())
        self.connect(u_class, SIGNAL("triggered()"), self._unfold_class)
        self.connect(u_class_method, SIGNAL("triggered()"),
                     self._unfold_class_method)
        self.connect(u_class_attr, SIGNAL("triggered()"),
                     self._unfold_class_attribute)
        #self.connect(save_state, SIGNAL("triggered()"),
        #self._save_symbols_state)

        menu.exec_(QCursor.pos())

    def _get_classes_root(self):
        """Return the root of classes"""
        class_root = None
        for i in range(self.tree.topLevelItemCount()):
            item = self.tree.topLevelItem(i)
            if item.isClass and not item.isClickable:
                class_root = item
                break
        return class_root

    def _unfold_class(self):
        """Method to Unfold Classes"""
        self.tree.collapseAll()
        classes_root = self._get_classes_root()
        if not classes_root:
            return

        classes_root.setExpanded(True)

    def _unfold_class_method(self):
        """Method to Unfold Methods"""
        self.tree.expandAll()
        classes_root = self._get_classes_root()
        if not classes_root:
            return
        #for each class!
        for i in range(classes_root.childCount()):
            class_item = classes_root.child(i)
            #for each attribute or functions
            for j in range(class_item.childCount()):
                item = class_item.child(j)
                #METHODS ROOT!!
                if not item.isMethod and not item.isClickable:
                    item.setExpanded(False)
                    break

    def _unfold_class_attribute(self):
        """Method to Unfold Attributes"""
        self.tree.expandAll()
        classes_root = self._get_classes_root()
        if not classes_root:
            return
        #for each class!
        for i in range(classes_root.childCount()):
            class_item = classes_root.child(i)
            #for each attribute or functions
            for j in range(class_item.childCount()):
                item = class_item.child(j)
                #ATTRIBUTES ROOT!!
                if not item.isAttribute and not item.isClickable:
                    item.setExpanded(False)
                    break

    def _save_symbols_state(self):
        """Method to Save a persistent Symbols state"""
        #filename = self.actualSymbols[0]
        #TODO: persist self.collapsedItems[filename] in QSettings
        pass

    def _get_expand(self, item):
        """
        Returns True or False to be used as setExpanded() with the items
        It method is based on the click that the user made in the tree
        """
        name = self._get_unique_name(item)
        filename = self.actualSymbols[0]
        collapsed_items = self.collapsedItems.get(filename, [])
        can_check = (not item.isClickable) or item.isClass or item.isMethod
        if can_check and name in collapsed_items:
            return False
        return True

    @staticmethod
    def _get_unique_name(item):
        """
        Returns a string used as unique name
        """
        # className_Attributes/className_Functions
        parent = item.parent()
        if parent:
            return "%s_%s" % (parent.text(0), item.text(0))
        return "_%s" % item.text(0)

    def update_symbols_tree(self, symbols, filename='', parent=None):
        """Method to Update the symbols on the Tree"""
        if not parent:
            if filename == self.actualSymbols[0] and \
                self.actualSymbols[1] and not symbols:
                return

            if symbols == self.actualSymbols[1]:
                # Nothing new then return
                return

            # we have new symbols refresh it
            self.tree.clear()
            self.actualSymbols = (filename, symbols)
            self.docstrings = symbols.get('docstrings', {})
            parent = self.tree
        if 'attributes' in symbols:
            globalAttribute = ItemTree(parent, [translations.TR_ATTRIBUTES])
            globalAttribute.isClickable = False
            globalAttribute.isAttribute = True
            globalAttribute.setExpanded(self._get_expand(globalAttribute))
            for glob in sorted(symbols['attributes']):
                globItem = ItemTree(globalAttribute, [glob],
                                    lineno=symbols['attributes'][glob])
                globItem.isAttribute = True
                globItem.setIcon(0, QIcon(":img/attribute"))
                globItem.setExpanded(self._get_expand(globItem))

        if 'functions' in symbols and symbols['functions']:
            functionsItem = ItemTree(parent, [translations.TR_FUNCTIONS])
            functionsItem.isClickable = False
            functionsItem.isMethod = True
            functionsItem.setExpanded(self._get_expand(functionsItem))
            for func in sorted(symbols['functions']):
                item = ItemTree(functionsItem, [func],
                                lineno=symbols['functions'][func]['lineno'])
                tooltip = self.create_tooltip(
                    func, symbols['functions'][func]['lineno'])
                item.isMethod = True
                item.setIcon(0, QIcon(":img/function"))
                item.setToolTip(0, tooltip)
                item.setExpanded(self._get_expand(item))
                self.update_symbols_tree(
                    symbols['functions'][func]['functions'], parent=item)
        if 'classes' in symbols and symbols['classes']:
            classItem = ItemTree(parent, [translations.TR_CLASSES])
            classItem.isClickable = False
            classItem.isClass = True
            classItem.setExpanded(self._get_expand(classItem))
            for claz in sorted(symbols['classes']):
                line_number = symbols['classes'][claz]['lineno']
                item = ItemTree(classItem, [claz], lineno=line_number)
                item.isClass = True
                tooltip = self.create_tooltip(claz, line_number)
                item.setToolTip(0, tooltip)
                item.setIcon(0, QIcon(":img/class"))
                item.setExpanded(self._get_expand(item))
                self.update_symbols_tree(symbols['classes'][claz]['members'],
                                         parent=item)

    def _go_to_definition(self, item):
        """Takes and item object and goes to definition on the editor"""
        main_container = IDE.get_service('main_container')
        if item.isClickable and main_container:
            main_container.editor_go_to_line(item.lineno - 1)

    def create_tooltip(self, name, lineno):
        """Takes a name and line number and returns a tooltip"""
        doc = self.docstrings.get(lineno, None)
        if doc is None:
            doc = ''
        else:
            doc = '\n' + doc
        tooltip = name + doc
        return tooltip

    def _item_collapsed(self, item):
        """When item collapsed"""
        super(TreeSymbolsWidget, self).collapseItem(item)

        can_check = (not item.isClickable) or item.isClass or item.isMethod
        if can_check:
            n = self._get_unique_name(item)
            filename = self.actualSymbols[0]
            self.collapsedItems.setdefault(filename, [])
            if not n in self.collapsedItems[filename]:
                self.collapsedItems[filename].append(n)

    def _item_expanded(self, item):
        """When item expanded"""
        super(TreeSymbolsWidget, self).expandItem(item)

        n = self._get_unique_name(item)
        filename = self.actualSymbols[0]
        if n in self.collapsedItems.get(filename, []):
            self.collapsedItems[filename].remove(n)
            if not len(self.collapsedItems[filename]):
                # no more items, free space
                del self.collapsedItems[filename]

    def clean(self):
        """
        Reset the tree and reset attributes
        """
        self.tree.clear()
        self.collapsedItems = {}

    def reject(self):
        if self.parent() is None:
            self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self)

    def closeEvent(self, event):
        """On Close event handling"""
        self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self)
        event.ignore()
예제 #24
0
파일: GmGui.py 프로젝트: hftsai/gulon-soft
class GmApp(QMainWindow):
    def __init__(self):
        super(QMainWindow, self).__init__()

        self.setWindowTitle("GuloMail by GulonSoft")
        self.setWindowIcon(QIcon("g-square.png"))

        self.createActions()
        self.createStatusBar()
        self.createMenus()
        self.createToolbars()
        self.createWidgets()
        self.createLayouts()

    def createActions(self):
        self.newAction = QAction("&New",
                                 self,
                                 shortcut=QKeySequence.New,
                                 statusTip="New")
        self.sendReceiveAction = QAction("Send / &Receive",
                                         self,
                                         shortcut="F9",
                                         statusTip="Send / Receive")
        self.printAction = QAction("&Print...",
                                   self,
                                   shortcut="Ctrl+P",
                                   statusTip="Print")
        self.quitAction = QAction("&Quit",
                                  self,
                                  shortcut="Ctrl+Q",
                                  statusTip="Quit",
                                  triggered=self.close)

        self.copyAction = QAction("&Copy",
                                  self,
                                  statusTip="Copy",
                                  shortcut=QKeySequence.Copy)
        self.deleteAction = QAction("&Delete",
                                    self,
                                    statusTip="Delete Message")

        self.nextAction = QAction("Next &Unread Message",
                                  self,
                                  shortcut="Ctrl+]",
                                  statusTip="Next unread message")
        self.previousAction = QAction("P&revious Unread Message",
                                      self,
                                      shortcut="Ctrl+[",
                                      statusTip="Previous unread message")
        self.replyAction = QAction("&Reply",
                                   self,
                                   shortcut="Ctrl+R",
                                   statusTip="Reply to sender",
                                   triggered=self.reply)
        self.replyToAllAction = QAction("Reply to &All",
                                        self,
                                        shortcut="Ctrl+Shift+R",
                                        statusTip="Reply to all",
                                        triggered=self.replyToAll)
        self.forwardAction = QAction("&Forward",
                                     self,
                                     shortcut="Ctrl+F",
                                     statusTip="Forward")
        self.junkAction = QAction("Junk",
                                  self,
                                  shortcut="Ctrl+J",
                                  statusTip="Mark as Junk")
        self.notJunkAction = QAction("Not junk",
                                     self,
                                     shortcut="Shift+Ctrl+J",
                                     statusTip="Mark as Not Junk")

        self.contentsAction = QAction("&Contents",
                                      self,
                                      statusTip="Help Contents",
                                      shortcut="F1",
                                      triggered=self.helpContents)
        self.aboutAction = QAction("&About",
                                   self,
                                   statusTip="About GuloMail",
                                   triggered=self.about)

        self.cancelAction = QAction("&Cancel", self, statusTip="Cancel")

    def createStatusBar(self):
        self.statusBar()

    def createMenus(self):
        self.fileMenu = self.menuBar().addMenu("&File")
        self.fileMenu.addAction(self.newAction)
        self.fileMenu.addAction(self.sendReceiveAction)
        self.fileMenu.addAction(self.printAction)
        self.fileMenu.addAction(self.quitAction)

        self.editMenu = self.menuBar().addMenu("&Edit")
        self.editMenu.addAction(self.copyAction)
        self.editMenu.addAction(self.deleteAction)

        self.viewMenu = self.menuBar().addMenu("&View")
        self.folderMenu = self.menuBar().addMenu("F&older")

        self.messageMenu = self.menuBar().addMenu("&Message")
        self.goToMenu = self.messageMenu.addMenu("&Go To")
        self.goToMenu.addAction(self.nextAction)
        self.goToMenu.addAction(self.previousAction)
        self.messageMenu.addAction(self.replyAction)
        self.messageMenu.addAction(self.replyToAllAction)
        self.messageMenu.addAction(self.forwardAction)
        self.markAsMenu = self.messageMenu.addMenu("Mar&k as...")
        self.markAsMenu.addAction(self.junkAction)
        self.markAsMenu.addAction(self.notJunkAction)

        self.searchMenu = self.menuBar().addMenu("&Search")

        self.helpMenu = self.menuBar().addMenu("&Help")
        self.helpMenu.addAction(self.contentsAction)
        self.helpMenu.addAction(self.aboutAction)

    def createToolbars(self):
        self.toolbar = self.addToolBar('Main Toolbar')
        self.toolbar.setMovable(False)
        self.toolbar.addAction(self.newAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.sendReceiveAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.replyAction)
        self.toolbar.addAction(self.replyToAllAction)
        self.toolbar.addAction(self.forwardAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.printAction)
        self.toolbar.addAction(self.deleteAction)
        self.toolbar.addAction(self.junkAction)
        self.toolbar.addAction(self.notJunkAction)
        self.toolbar.addAction(self.cancelAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.previousAction)
        self.toolbar.addAction(self.nextAction)

    def createWidgets(self):
        ## Message Table
        self.table = QTableView()
        self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setGridStyle(Qt.NoPen)

        self.model = QStandardItemModel(8, 3, self)
        self.model.setHeaderData(0, Qt.Horizontal, "From")
        self.model.setHeaderData(1, Qt.Horizontal, "Subject")
        self.model.setHeaderData(2, Qt.Horizontal, "Received")

        self.table.setModel(self.model)
        self.selectionModel = QItemSelectionModel(self.model)
        self.selectionModel.SelectionFlag = 0x0020
        self.table.setSelectionModel(self.selectionModel)
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.verticalHeader().setVisible(False)
        self.table.setSortingEnabled(True)
        self.table.setAlternatingRowColors(True)

        ## Folder Tree View
        self.folderTree = QTreeWidget()
        self.folderTree.setColumnCount(1)
        self.folderTree.setHeaderLabel(QString('Folders'))

        self.treeItem = QTreeWidgetItem()
        self.treeItem.setText(0, 'Folders')

        self.inbox = QTreeWidgetItem()
        self.inbox.setText(0, 'Inbox')

        self.deletedItems = QTreeWidgetItem()
        self.deletedItems.setText(0, 'Deleted Items')

        self.drafts = QTreeWidgetItem()
        self.drafts.setText(0, 'Drafts')

        self.junk = QTreeWidgetItem()
        self.junk.setText(0, 'Junk')

        self.outbox = QTreeWidgetItem()
        self.outbox.setText(0, 'Outbox')

        self.sent = QTreeWidgetItem()
        self.sent.setText(0, 'Sent')

        self.treeItem.addChild(self.inbox)
        self.treeItem.addChild(self.deletedItems)
        self.treeItem.addChild(self.drafts)
        self.treeItem.addChild(self.junk)
        self.treeItem.addChild(self.outbox)
        self.treeItem.addChild(self.sent)

        self.folderTree.addTopLevelItem(self.treeItem)
        self.folderTree.expandAll()
        self.folderTree.setAnimated(True)

        self.folderTree.setMaximumWidth(150)

        ## Temp. placeholders
        self.textEdit = QTextEdit()
        self.textEdit2 = QTextEdit()

    def createLayouts(self):
        self.mainSplitter = QSplitter()
        self.setCentralWidget(self.mainSplitter)

        self.mainSplitter.addWidget(self.folderTree)

        self.messageSplitter = QSplitter(Qt.Vertical)
        self.messageSplitter.addWidget(self.table)
        self.messageSplitter.addWidget(self.textEdit2)

        self.mainSplitter.addWidget(self.messageSplitter)

    def helpContents(self):
        print "Help"

    def reply(self):
        print "Reply"

    def replyToAll(self):
        print "Reply To All"

    def about(self):
        text = QString("GuloMail v0.1\n\n")
        text.append(
            "GuloMail is a freeware email client written in Python using PyQt4 (Python bindings for Nokia's Qt)\n\n"
        )
        text.append(QChar(0x00A9))
        text.append("GulonSoft 2010\nhttp://www.gulon.co.uk/")
        QMessageBox.about(self, "About GuloMail", text)