コード例 #1
1
 def clear(self):
     """ Deletes all items in the TreeView
     """
     #logging.debug(__name__ + ": clear")
     self._itemDict = {}
     self._firstItem = None
     QTreeWidget.clear(self)
コード例 #2
0
ファイル: results.py プロジェクト: ntcong/ninja-ide
class Results(QWidget):
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self._parent = parent
        vbox = QVBoxLayout(self)
        self._tree = QTreeWidget()
        self._tree.setHeaderLabels((self.tr("Content"), self.tr("File"), self.tr("Line")))
        self._tree.header().setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
        self._tree.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self._tree.header().setResizeMode(1, QHeaderView.ResizeToContents)
        self._tree.header().setResizeMode(2, QHeaderView.ResizeToContents)
        self._tree.header().setStretchLastSection(True)
        self._tree.sortByColumn(1, Qt.AscendingOrder)

        vbox.addWidget(self._tree)

        # Signals
        self.connect(self._tree, SIGNAL("itemClicked(QTreeWidgetItem*, int)"), self._open_result)

    def _open_result(self, item, col):
        filename = unicode(item.toolTip(1))
        line = int(item.text(2)) - 1
        main_container.MainContainer().open_file(fileName=filename, cursorPosition=line, positionIsLineNumber=True)
        self._parent.hide()

    def update_result(self, items):
        self._tree.clear()
        for i in items:
            item = QTreeWidgetItem(self._tree, (i[3], i[0], QString.number(i[2] + 1)))
            item.setToolTip(1, i[1])
コード例 #3
0
ファイル: TreeView.py プロジェクト: Andrej-CMS/cmssw
 def clear(self):
     """ Deletes all items in the TreeView
     """
     #logging.debug(__name__ + ": clear")
     self._itemDict = {}
     self._firstItem = None
     QTreeWidget.clear(self)
コード例 #4
0
    def clear( self ):
        " Resets everything "
        self.resortEnabled = True
        self.openItems = []
        self.framenr = 0

        QTreeWidget.clear( self )
        return
コード例 #5
0
    def clear(self):
        " Resets everything "
        self.resortEnabled = True
        self.openItems = []
        self.framenr = 0

        QTreeWidget.clear(self)
        return
コード例 #6
0
ファイル: widgets.py プロジェクト: darvin/StructurEd
class DictWidget(QWidget, NodeWidget):
    data_type = "Dict"
    two_rows = True
    data_class = StructuredNode
    def __init__(self, name, data, scheme, parent=None):
        QWidget.__init__(self, parent)
        NodeWidget.__init__(self, name, data, scheme)
        self.layout = QVBoxLayout(self)
        self.layout.setMargin(0)
        self.layout.setContentsMargins(0,0,0,0)
        self._listwidget = QTreeWidget(self)
        self._listwidget.setColumnCount(2)
        self._listwidget.setHeaderLabels(("Key","Value"))
        self.layout.addWidget(self._listwidget)
        hlayout = QHBoxLayout()
        self.layout.addLayout(hlayout)

        self._plus_minus_widget = PlusMinusWidget(self.create_item, self.delete_item, self)
        hlayout.addWidget(self._plus_minus_widget)


        self.new_data = None
        hlayout.addStretch(1)
        self.add_widget =  WidgetSelector(self)
        hlayout.addWidget(self.add_widget)

    def delete_item(self):
        current_item = self._listwidget.currentItem()
        if current_item:
            key = current_item.data(1)
            new_data = self.data.get()
            del new_data[key]
            self.data.set(new_data)

    def create_item(self):
        new_data = self.data.get()
        new_item = self.add_widget.get_item()
        new_data[new_item["key"]] = Node.create_node(new_item["value"].get())
        self.data.set(new_data)

    def __createItem(self, itemname, itemvalue):
        item = QTreeWidgetItem(self._listwidget, [unicode(itemname), unicode(itemvalue)])
#        item.setFlags (Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled )


    def dump(self):
        pass

    def load(self):
        self._listwidget.clear()
        for key, value in self.data.iteritems():
            self.__createItem(key, value)


    @classmethod
    def _get_default_data(cls, scheme, data):
        return StructuredNode({})
コード例 #7
0
class MemUsageDialog(QDialog):
    def __init__(self, parent=None, update=True):
        QDialog.__init__(self, parent=parent)
        layout = QVBoxLayout()
        self.tree = QTreeWidget()
        layout.addWidget(self.tree)
        self.setLayout(layout)

        self._mgr = CacheMemoryManager()

        self._tracked_caches = {}

        # tree setup code
        self.tree.setHeaderLabels(
            ["cache", "memory", "roi", "dtype", "type", "info", "id"])
        self._idIndex = self.tree.columnCount() - 1
        self.tree.setColumnHidden(self._idIndex, True)
        self.tree.setSortingEnabled(True)
        self.tree.clear()

        self._root = TreeNode()

        # refresh every x seconds (see showEvent())
        self.timer = QTimer(self)
        if update:
            self.timer.timeout.connect(self._updateReport)

    def _updateReport(self):
        # we keep track of dirty reports so we just have to update the tree
        # instead of reconstructing it
        reports = []
        for c in self._mgr.getFirstClassCaches():
            r = MemInfoNode()
            c.generateReport(r)
            reports.append(r)
        self._root.handleChildrenReports(reports,
                                         root=self.tree.invisibleRootItem())

    def hideEvent(self, event):
        self.timer.stop()

    def showEvent(self, show):
        # update once so we don't have to wait for initial report
        self._updateReport()
        # update every 5 sec.
        self.timer.start(5 * 1000)
コード例 #8
0
ファイル: results.py プロジェクト: Hmaal/ninja-ide
class Results(QWidget):

    """Show results of occurrences in files inside the tools dock."""

    def __init__(self, parent):
        super(Results, self).__init__(parent)
        self._parent = parent
        vbox = QVBoxLayout(self)
        self._tree = QTreeWidget()
        self._tree.setHeaderLabels((self.tr("Content"),
            self.tr('File'), self.tr('Line')))
        self._tree.header().setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self._tree.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self._tree.header().setResizeMode(1, QHeaderView.ResizeToContents)
        self._tree.header().setResizeMode(2, QHeaderView.ResizeToContents)
        self._tree.header().setStretchLastSection(True)
        self._tree.sortByColumn(1, Qt.AscendingOrder)

        vbox.addWidget(self._tree)

        #Signals
        self.connect(self._tree,
            SIGNAL("itemActivated(QTreeWidgetItem*, int)"),
            self._open_result)
        self.connect(self._tree, SIGNAL("itemClicked(QTreeWidgetItem*, int)"),
            self._open_result)

    def _open_result(self, item, col):
        """Get the data of the selected item and open the file."""
        filename = item.toolTip(1)
        line = int(item.text(2)) - 1
        main_container = IDE.get_service('main_container')
        if main_container:
            main_container.open_file(
                filename=filename,
                cursorPosition=line,
                positionIsLineNumber=True)
        self._parent.hide()

    def update_result(self, items):
        """Update the result tree with the new items."""
        self._tree.clear()
        for i in items:
            item = QTreeWidgetItem(self._tree, (i[3], i[0], str(i[2] + 1)))
            item.setToolTip(1, i[1])
コード例 #9
0
class MemUsageDialog(QDialog):
    def __init__(self, parent=None, update=True):
        QDialog.__init__(self, parent=parent)
        layout = QVBoxLayout()
        self.tree = QTreeWidget()
        layout.addWidget(self.tree)
        self.setLayout(layout)

        self._mgr = CacheMemoryManager()

        self._tracked_caches = {}

        # tree setup code
        self.tree.setHeaderLabels(
            ["cache", "memory", "roi", "dtype", "type", "info", "id"])
        self._idIndex = self.tree.columnCount() - 1
        self.tree.setColumnHidden(self._idIndex, True)
        self.tree.setSortingEnabled(True)
        self.tree.clear()

        self._root = TreeNode()

        # refresh every x seconds (see showEvent())
        self.timer = QTimer(self)
        if update:
            self.timer.timeout.connect(self._updateReport)

    def _updateReport(self):
        # we keep track of dirty reports so we just have to update the tree
        # instead of reconstructing it
        reports = []
        for c in self._mgr.getFirstClassCaches():
            r = MemInfoNode()
            c.generateReport(r)
            reports.append(r)
        self._root.handleChildrenReports(
            reports, root=self.tree.invisibleRootItem())

    def hideEvent(self, event):
        self.timer.stop()

    def showEvent(self, show):
        # update once so we don't have to wait for initial report
        self._updateReport()
        # update every 5 sec.
        self.timer.start(5*1000)
コード例 #10
0
class Results(QWidget):
    """Show results of occurrences in files inside the tools dock."""
    def __init__(self, parent):
        super(Results, self).__init__(parent)
        self._parent = parent
        vbox = QVBoxLayout(self)
        self._tree = QTreeWidget()
        self._tree.setHeaderLabels(
            (translations.TR_CONTENT, translations.TR_FILE,
             translations.TR_LINE))
        self._tree.header().setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self._tree.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self._tree.header().setResizeMode(1, QHeaderView.ResizeToContents)
        self._tree.header().setResizeMode(2, QHeaderView.ResizeToContents)
        self._tree.header().setStretchLastSection(True)
        self._tree.sortByColumn(1, Qt.AscendingOrder)

        vbox.addWidget(self._tree)

        #Signals
        self.connect(self._tree,
                     SIGNAL("itemActivated(QTreeWidgetItem*, int)"),
                     self._open_result)
        self.connect(self._tree, SIGNAL("itemClicked(QTreeWidgetItem*, int)"),
                     self._open_result)

    def _open_result(self, item, col):
        """Get the data of the selected item and open the file."""
        filename = item.toolTip(1)
        line = int(item.text(2)) - 1
        main_container = IDE.get_service('main_container')
        if main_container:
            main_container.open_file(filename=filename,
                                     cursorPosition=line,
                                     positionIsLineNumber=True)
        self._parent.hide()

    def update_result(self, items):
        """Update the result tree with the new items."""
        self._tree.clear()
        for i in items:
            item = QTreeWidgetItem(self._tree, (i[3], i[0], str(i[2] + 1)))
            item.setToolTip(1, i[1])
コード例 #11
0
ファイル: results.py プロジェクト: ktosiu/ninja-ide
class Results(QWidget):
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        self._parent = parent
        vbox = QVBoxLayout(self)
        self._tree = QTreeWidget()
        self._tree.setHeaderLabels(
            (self.tr("Content"), self.tr('File'), self.tr('Line')))
        self._tree.header().setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self._tree.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self._tree.header().setResizeMode(1, QHeaderView.ResizeToContents)
        self._tree.header().setResizeMode(2, QHeaderView.ResizeToContents)
        self._tree.header().setStretchLastSection(True)
        self._tree.sortByColumn(1, Qt.AscendingOrder)

        vbox.addWidget(self._tree)

        #Signals
        self.connect(self._tree,
                     SIGNAL("itemActivated(QTreeWidgetItem*, int)"),
                     self._open_result)
        self.connect(self._tree, SIGNAL("itemClicked(QTreeWidgetItem*, int)"),
                     self._open_result)

    def _open_result(self, item, col):
        filename = unicode(item.toolTip(1))
        line = int(item.text(2)) - 1
        main_container.MainContainer().open_file(filename=filename,
                                                 cursorPosition=line,
                                                 positionIsLineNumber=True)
        self._parent.hide()

    def update_result(self, items):
        self._tree.clear()
        for i in items:
            item = QTreeWidgetItem(self._tree,
                                   (i[3], i[0], QString.number(i[2] + 1)))
            item.setToolTip(1, i[1])
コード例 #12
0
class Window(QMainWindow):
    def __init__(self):
        self.a = 0
        QMainWindow.__init__(self)
        self.setWindowTitle("Explorador de archivos y carpetas")

        self.back_history = []
        self.forward_history = []

        self.back_button = QPushButton(self)
        self.back_button.setIcon(QIcon("images/back.png"))
        self.back_button.clicked.connect(self.back_clicked)
        self.back_button.setEnabled(False)

        self.forward_button = QPushButton(self)
        self.forward_button.setIcon(QIcon("images/forward.png"))
        self.forward_button.clicked.connect(self.forward_clicked)
        self.forward_button.setEnabled(False)

        self.up_button = QPushButton(self)
        self.up_button.setIcon(QIcon("images/up.png"))
        self.up_button.clicked.connect(self.up_button_clicked)

        self.address_edit = QLineEdit(self)

        self.refresh_button = QPushButton(self)
        self.refresh_button.setIcon(QIcon("images/update.png"))
        self.refresh_button.clicked.connect(self.refresh_button_clicked)

        self.toplayout = QHBoxLayout()
        self.toplayout.addWidget(self.back_button)
        self.toplayout.addWidget(self.forward_button)
        self.toplayout.addWidget(self.up_button)
        self.toplayout.addWidget(self.address_edit)
        self.toplayout.addWidget(self.refresh_button)

        self.main_tree = QTreeWidget(self)
        self.main_tree.setRootIsDecorated(False)
        self.main_tree.setHeaderLabels(
            ("Nombre", u"Fecha de modificación", u"Tamaño"))
        self.main_tree.itemDoubleClicked.connect(self.item_double_clicked)

        self.layout = QVBoxLayout()
        self.layout.addLayout(self.toplayout)
        self.layout.addWidget(self.main_tree)

        self.central_widget = QWidget(self)
        self.central_widget.setLayout(self.layout)
        self.setCentralWidget(self.central_widget)

        self.resize(800, 600)
        # Iniciar en el directorio actual.
        self.load_path(getcwd())

    def back_clicked(self, checked):
        if self.back_history and len(self.back_history) > 1:
            # Obtener el último elemento.
            path = self.back_history[-2]
            self.forward_history.append(self.back_history[-1])
            # Remover el directorio actual.
            del self.back_history[-1]
            self.load_path(path, False)

    def forward_clicked(self, checked):
        if self.forward_history:
            path = self.forward_history[-1]
            self.back_history.append(path)
            del self.forward_history[-1]
            self.load_path(path, False)

    def item_double_clicked(self, item, column):
        filepath = join(self.current_path, unicode(item.text(0)))
        if isdir(filepath):
            self.load_path(filepath)
        else:
            # Iniciar archivo con el programa predeterminado.
            #startfile(filepath)

            a = filepath
            parcial.ponfoto(a)
            #print self.a

    def up_button_clicked(self, checked):
        parent = dirname(self.current_path)
        if parent != self.current_path:
            self.load_path(parent)

    def load_path(self, path, use_history=True):
        # Obtener archivos y carpetas.
        items = listdir(unicode(path))
        # Eliminar el contenido anterior.
        self.main_tree.clear()

        for i in items:
            # Omitir archivos ocultos.
            if i.startswith("."):
                continue
            filepath = join(path, i)
            # Obtener informacion del archivo.
            stats = stat(filepath)
            # Crear el control ítem.
            item_widget = QTreeWidgetItem(
                (i, strftime("%c", localtime(stats.st_mtime)).decode("utf-8"),
                 size(stats.st_size) if isfile(filepath) else ""))
            # Establecer el ícono correspondiente.
            item_widget.setIcon(
                0,
                QIcon("images/%s.png" %
                      ("file" if isfile(filepath) else "folder")))
            # Añadir elemento.
            self.main_tree.addTopLevelItem(item_widget)

        # Ajustar el tamaño de las columnas.
        for i in range(3):
            self.main_tree.resizeColumnToContents(i)

        self.current_path = path
        self.address_edit.setText(self.current_path)

        # Añadir al historial.
        if use_history:
            self.back_history.append(self.current_path)

        # Habilitar / dehabilitar botones del historial.
        if self.back_history and len(self.back_history) > 1:
            if not self.back_button.isEnabled():
                self.back_button.setEnabled(True)
        else:
            if self.back_button.isEnabled():
                self.forward_history = []
                self.back_button.setEnabled(False)

        if self.forward_history:
            if not self.forward_button.isEnabled():
                self.forward_button.setEnabled(True)
        else:
            if self.forward_button.isEnabled():
                self.forward_button.setEnabled(False)

    def refresh_button_clicked(self, checked):
        self.load_path(self.current_path)
コード例 #13
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)
コード例 #14
0
ファイル: OWDatabasesUpdate.py プロジェクト: grst/orange-bio
class OWDatabasesUpdate(OWWidget):

    name = "Databases Update"
    description = "Update local systems biology databases."
    icon = "../widgets/icons/Databases.svg"
    priority = 10

    inputs = []
    outputs = []

    want_main_area = False

    def __init__(self, parent=None, signalManager=None,
                 name="Databases update", domains=None):
        OWWidget.__init__(self, parent, signalManager, name,
                          wantMainArea=False)

        self.searchString = ""
        self.accessCode = ""
        self.domains = domains or DOMAINS
        self.serverFiles = serverfiles.ServerFiles()

        fbox = gui.widgetBox(self.controlArea, "Filter")
        self.completer = TokenListCompleter(
            self, caseSensitivity=Qt.CaseInsensitive)
        self.lineEditFilter = QLineEdit(textChanged=self.SearchUpdate)
        self.lineEditFilter.setCompleter(self.completer)

        fbox.layout().addWidget(self.lineEditFilter)

        box = gui.widgetBox(self.controlArea, "Files")

        self.filesView = QTreeWidget(self)
        self.filesView.setHeaderLabels(
            ["", "Data Source", "Update", "Last Updated", "Size"])

        self.filesView.setRootIsDecorated(False)
        self.filesView.setUniformRowHeights(True)
        self.filesView.setSelectionMode(QAbstractItemView.NoSelection)
        self.filesView.setSortingEnabled(True)
        self.filesView.sortItems(1, Qt.AscendingOrder)
        self.filesView.setItemDelegateForColumn(
            0, UpdateOptionsItemDelegate(self.filesView))

        self.filesView.model().layoutChanged.connect(self.SearchUpdate)

        box.layout().addWidget(self.filesView)

        box = gui.widgetBox(self.controlArea, orientation="horizontal")
        self.updateButton = gui.button(
            box, self, "Update all",
            callback=self.UpdateAll,
            tooltip="Update all updatable files",
         )

        self.downloadButton = gui.button(
            box, self, "Download all",
            callback=self.DownloadFiltered,
            tooltip="Download all filtered files shown"
        )

        self.cancelButton = gui.button(
            box, self, "Cancel", callback=self.Cancel,
            tooltip="Cancel scheduled downloads/updates."
        )

        self.retryButton = gui.button(
            box, self, "Reconnect", callback=self.RetrieveFilesList
        )
        self.retryButton.hide()

        gui.rubber(box)

        gui.lineEdit(box, self, "accessCode", "Access Code",
                     orientation="horizontal",
                     callback=self.RetrieveFilesList)

        self.warning(0)

        box = gui.widgetBox(self.controlArea, orientation="horizontal")
        gui.rubber(box)

        self.infoLabel = QLabel()
        self.infoLabel.setAlignment(Qt.AlignCenter)

        self.controlArea.layout().addWidget(self.infoLabel)
        self.infoLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        self.updateItems = []

        self.resize(800, 600)

        self.progress = ProgressState(self, maximum=3)
        self.progress.valueChanged.connect(self._updateProgress)
        self.progress.rangeChanged.connect(self._updateProgress)
        self.executor = ThreadExecutor(
            threadPool=QThreadPool(maxThreadCount=2)
        )

        task = Task(self, function=self.RetrieveFilesList)
        task.exceptionReady.connect(self.HandleError)
        task.start()

        self._tasks = []
        self._haveProgress = False

    def RetrieveFilesList(self):
        self.retryButton.hide()
        self.warning(0)
        self.progress.setRange(0, 3)
        self.serverFiles = serverfiles.ServerFiles(access_code=self.accessCode)

        task = Task(function=partial(retrieveFilesList, self.serverFiles,
                                     self.domains,
                                     methodinvoke(self.progress, "advance")))

        task.resultReady.connect(self.SetFilesList)
        task.exceptionReady.connect(self.HandleError)

        self.executor.submit(task)

        self.setEnabled(False)

    def SetFilesList(self, serverInfo):
        """
        Set the files to show.
        """
        self.setEnabled(True)

        domains = serverInfo.keys()
        if not domains:
            if self.domains:
                domains = self.domains
            else:
                domains = serverfiles.listdomains()

        localInfo = dict([(dom, serverfiles.allinfo(dom)) for dom in domains])

        all_tags = set()

        self.filesView.clear()
        self.updateItems = []

        for item in join_info_dict(localInfo, serverInfo):
            tree_item = UpdateTreeWidgetItem(item)
            options_widget = UpdateOptionsWidget(item.state)
            options_widget.item = item

            options_widget.installClicked.connect(
                partial(self.SubmitDownloadTask, item.domain, item.filename)
            )
            options_widget.removeClicked.connect(
                partial(self.SubmitRemoveTask, item.domain, item.filename)
            )

            self.updateItems.append((item, tree_item, options_widget))
            all_tags.update(item.tags)

        self.filesView.addTopLevelItems(
            [tree_item for _, tree_item, _ in self.updateItems]
        )

        for item, tree_item, options_widget in self.updateItems:
            self.filesView.setItemWidget(tree_item, 0, options_widget)

            # Add an update button if the file is updateable
            if item.state == OUTDATED:
                button = QToolButton(
                    None, text="Update",
                    maximumWidth=120,
                    minimumHeight=20,
                    maximumHeight=20
                )

                if sys.platform == "darwin":
                    button.setAttribute(Qt.WA_MacSmallSize)

                button.clicked.connect(
                    partial(self.SubmitDownloadTask, item.domain,
                            item.filename)
                )

                self.filesView.setItemWidget(tree_item, 2, button)

        self.progress.advance()

        self.filesView.setColumnWidth(0, self.filesView.sizeHintForColumn(0))

        for column in range(1, 4):
            contents_hint = self.filesView.sizeHintForColumn(column)
            header_hint = self.filesView.header().sectionSizeHint(column)
            width = max(min(contents_hint, 400), header_hint)
            self.filesView.setColumnWidth(column, width)

        hints = [hint for hint in sorted(all_tags) if not hint.startswith("#")]
        self.completer.setTokenList(hints)
        self.SearchUpdate()
        self.UpdateInfoLabel()
        self.toggleButtons()
        self.cancelButton.setEnabled(False)

        self.progress.setRange(0, 0)

    def buttonCheck(self, selected_items, state, button):
        for item in selected_items:
            if item.state != state:
                button.setEnabled(False)
            else:
                button.setEnabled(True)
                break

    def toggleButtons(self):
        selected_items = [item for item, tree_item, _ in self.updateItems if not tree_item.isHidden()]
        self.buttonCheck(selected_items, OUTDATED, self.updateButton)
        self.buttonCheck(selected_items, AVAILABLE, self.downloadButton)

    def HandleError(self, exception):
        if isinstance(exception, ConnectionError):
            self.warning(0,
                       "Could not connect to server! Check your connection "
                       "and try to reconnect.")
            self.SetFilesList({})
            self.retryButton.show()
        else:
            sys.excepthook(type(exception), exception.args, None)
            self.progress.setRange(0, 0)
            self.setEnabled(True)

    def UpdateInfoLabel(self):
        local = [item for item, tree_item, _ in self.updateItems
                 if item.state != AVAILABLE and not tree_item.isHidden()]
        size = sum(float(item.size) for item in local)

        onServer = [item for item, tree_item, _ in self.updateItems if not tree_item.isHidden()]
        sizeOnServer = sum(float(item.size) for item in onServer)

        text = ("%i items, %s (on server: %i items, %s)" %
                (len(local),
                 sizeof_fmt(size),
                 len(onServer),
                 sizeof_fmt(sizeOnServer)))

        self.infoLabel.setText(text)

    def UpdateAll(self):
        self.warning(0)
        for item, tree_item, _ in self.updateItems:
            if item.state == OUTDATED and not tree_item.isHidden():
                self.SubmitDownloadTask(item.domain, item.filename)

    def DownloadFiltered(self):
        # TODO: submit items in the order shown.
        for item, tree_item, _ in self.updateItems:
            if not tree_item.isHidden() and item.state in \
                    [AVAILABLE, OUTDATED]:
                self.SubmitDownloadTask(item.domain, item.filename)

    def SearchUpdate(self, searchString=None):
        strings = str(self.lineEditFilter.text()).split()
        for item, tree_item, _ in self.updateItems:
            hide = not all(UpdateItem_match(item, string)
                           for string in strings)
            tree_item.setHidden(hide)
        self.UpdateInfoLabel()
        self.toggleButtons()

    def SubmitDownloadTask(self, domain, filename):
        """
        Submit the (domain, filename) to be downloaded/updated.
        """
        self.cancelButton.setEnabled(True)

        index = self.updateItemIndex(domain, filename)
        _, tree_item, opt_widget = self.updateItems[index]

        if self.accessCode:
            sf = serverfiles.ServerFiles(access_code=self.accessCode)
        else:
            sf = serverfiles.ServerFiles()

        task = DownloadTask(domain, filename, sf)

        self.progress.adjustRange(0, 100)

        pb = ItemProgressBar(self.filesView)
        pb.setRange(0, 100)
        pb.setTextVisible(False)

        task.advanced.connect(pb.advance)
        task.advanced.connect(self.progress.advance)
        task.finished.connect(pb.hide)
        task.finished.connect(self.onDownloadFinished, Qt.QueuedConnection)
        task.exception.connect(self.onDownloadError, Qt.QueuedConnection)

        self.filesView.setItemWidget(tree_item, 2, pb)

        # Clear the text so it does not show behind the progress bar.
        tree_item.setData(2, Qt.DisplayRole, "")
        pb.show()

        # Disable the options widget
        opt_widget.setEnabled(False)
        self._tasks.append(task)

        self.executor.submit(task)

    def EndDownloadTask(self, task):
        future = task.future()
        index = self.updateItemIndex(task.domain, task.filename)
        item, tree_item, opt_widget = self.updateItems[index]

        self.filesView.removeItemWidget(tree_item, 2)
        opt_widget.setEnabled(True)

        if future.cancelled():
            # Restore the previous state
            tree_item.setUpdateItem(item)
            opt_widget.setState(item.state)

        elif future.exception():
            tree_item.setUpdateItem(item)
            opt_widget.setState(item.state)

            # Show the exception string in the size column.
            self.warning(0, "Error while downloading. Check your connection "
                            "and retry.")

            # recreate button for download
            button = QToolButton(
                None, text="Retry",
                maximumWidth=120,
                minimumHeight=20,
                maximumHeight=20
            )

            if sys.platform == "darwin":
                button.setAttribute(Qt.WA_MacSmallSize)

            button.clicked.connect(
                partial(self.SubmitDownloadTask, item.domain,
                        item.filename)
            )

            self.filesView.setItemWidget(tree_item, 2, button)

        else:
            # get the new updated info dict and replace the the old item
            self.warning(0)
            info = serverfiles.info(item.domain, item.filename)
            new_item = update_item_from_info(item.domain, item.filename,
                                             info, info)

            self.updateItems[index] = (new_item, tree_item, opt_widget)

            tree_item.setUpdateItem(new_item)
            opt_widget.setState(new_item.state)

            self.UpdateInfoLabel()

    def SubmitRemoveTask(self, domain, filename):
        serverfiles.remove(domain, filename)
        index = self.updateItemIndex(domain, filename)
        item, tree_item, opt_widget = self.updateItems[index]

        if item.info_server:
            new_item = item._replace(state=AVAILABLE, local=None,
                                      info_local=None)
        else:
            new_item = item._replace(local=None, info_local=None)
            # Disable the options widget. No more actions can be performed
            # for the item.
            opt_widget.setEnabled(False)

        tree_item.setUpdateItem(new_item)
        opt_widget.setState(new_item.state)
        self.updateItems[index] = (new_item, tree_item, opt_widget)

        self.UpdateInfoLabel()

    def Cancel(self):
        """
        Cancel all pending update/download tasks (that have not yet started).
        """
        for task in self._tasks:
            task.future().cancel()

    def onDeleteWidget(self):
        self.Cancel()
        self.executor.shutdown(wait=False)
        OWWidget.onDeleteWidget(self)

    def onDownloadFinished(self):
        # on download completed/canceled/error
        assert QThread.currentThread() is self.thread()
        for task in list(self._tasks):
            future = task.future()
            if future.done():
                self.EndDownloadTask(task)
                self._tasks.remove(task)

        if not self._tasks:
            # Clear/reset the overall progress
            self.progress.setRange(0, 0)
            self.cancelButton.setEnabled(False)

    def onDownloadError(self, exc_info):
        sys.excepthook(*exc_info)
        self.warning(0, "Error while downloading. Check your connection and "
                        "retry.")

    def updateItemIndex(self, domain, filename):
        for i, (item, _, _) in enumerate(self.updateItems):
            if item.domain == domain and item.filename == filename:
                return i
        raise ValueError("%r, %r not in update list" % (domain, filename))

    def _updateProgress(self, *args):
        rmin, rmax = self.progress.range()
        if rmin != rmax:
            if not self._haveProgress:
                self._haveProgress = True
                self.progressBarInit()

            self.progressBarSet(self.progress.ratioCompleted() * 100,
                                processEvents=None)
        if rmin == rmax:
            self._haveProgress = False
            self.progressBarFinished()
コード例 #15
0
class RecentProjectsViewer( QWidget ):
    " Recent projects viewer implementation "

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

        self.__projectContextItem = None
        self.__fileContextItem = None

        self.upper = self.__createRecentFilesLayout()
        self.lower = self.__createRecentProjectsLayout()
        self.__createProjectPopupMenu()
        self.__createFilePopupMenu()

        layout = QVBoxLayout()
        layout.setContentsMargins( 1, 1, 1, 1 )
        splitter = QSplitter( Qt.Vertical )
        splitter.addWidget( self.upper )
        splitter.addWidget( self.lower )
        splitter.setCollapsible( 0, False )
        splitter.setCollapsible( 1, False )

        layout.addWidget( splitter )
        self.setLayout( layout )

        self.__populateProjects()
        self.__populateFiles()
        self.__updateProjectToolbarButtons()
        self.__updateFileToolbarButtons()

        # Debugging mode support
        self.__debugMode = False
        parent.debugModeChanged.connect( self.__onDebugMode )
        return

    def setTooltips( self, switchOn ):
        " Switches the tooltips mode "
        for index in xrange( 0, self.recentFilesView.topLevelItemCount() ):
            self.recentFilesView.topLevelItem( index ).updateIconAndTooltip()
        for index in xrange( 0, self.projectsView.topLevelItemCount() ):
            self.projectsView.topLevelItem( index ).updateTooltip()
        return

    def __createFilePopupMenu( self ):
        " create the recent files popup menu "
        self.__fileMenu = QMenu( self.recentFilesView )
        self.__openMenuItem = self.__fileMenu.addAction( \
                                PixmapCache().getIcon( 'openitem.png' ),
                                'Open', self.__openFile )
        self.__copyPathFileMenuItem = self.__fileMenu.addAction( \
                        PixmapCache().getIcon( 'copytoclipboard.png' ),
                        'Copy path to clipboard', self.__filePathToClipboard )
        self.__fileMenu.addSeparator()
        self.__delFileMenuItem = self.__fileMenu.addAction( \
                                PixmapCache().getIcon( 'trash.png' ),
                                'Delete from recent',
                                self.__deleteFile )
        self.recentFilesView.setContextMenuPolicy( Qt.CustomContextMenu )
        self.connect( self.recentFilesView,
                      SIGNAL( "customContextMenuRequested(const QPoint &)" ),
                      self.__handleShowFileContextMenu )

        self.connect( GlobalData().project, SIGNAL( 'recentFilesChanged' ),
                      self.__populateFiles )
        return


    def __createProjectPopupMenu( self ):
        " Creates the recent project popup menu "
        self.__projectMenu = QMenu( self.projectsView )
        self.__prjLoadMenuItem = self.__projectMenu.addAction( \
                                PixmapCache().getIcon( 'load.png' ),
                                'Load',
                                self.__loadProject )
        self.__projectMenu.addSeparator()
        self.__propsMenuItem = self.__projectMenu.addAction( \
                                PixmapCache().getIcon( 'smalli.png' ),
                                'Properties',
                                self.__viewProperties )
        self.__prjCopyPathMenuItem = self.__projectMenu.addAction( \
                                PixmapCache().getIcon( 'copytoclipboard.png' ),
                                'Copy path to clipboard',
                                self.__prjPathToClipboard )
        self.__projectMenu.addSeparator()
        self.__delPrjMenuItem = self.__projectMenu.addAction( \
                                PixmapCache().getIcon( 'trash.png' ),
                                'Delete from recent',
                                self.__deleteProject )
        self.projectsView.setContextMenuPolicy( Qt.CustomContextMenu )
        self.connect( self.projectsView,
                      SIGNAL( "customContextMenuRequested(const QPoint &)" ),
                      self.__handleShowPrjContextMenu )

        self.connect( Settings().iInstance, SIGNAL( 'recentListChanged' ),
                      self.__populateProjects )
        GlobalData().project.projectChanged.connect( self.__projectChanged )
        return

    def __createRecentFilesLayout( self ):
        " Creates the upper part - recent files "
        headerFrame = QFrame()
        headerFrame.setFrameStyle( QFrame.StyledPanel )
        headerFrame.setAutoFillBackground( True )
        headerPalette = headerFrame.palette()
        headerBackground = headerPalette.color( QPalette.Background )
        headerBackground.setRgb( min( headerBackground.red() + 30, 255 ),
                                 min( headerBackground.green() + 30, 255 ),
                                 min( headerBackground.blue() + 30, 255 ) )
        headerPalette.setColor( QPalette.Background, headerBackground )
        headerFrame.setPalette( headerPalette )
        headerFrame.setFixedHeight( 24 )

        recentFilesLabel = QLabel()
        recentFilesLabel.setText( "Recent files" )

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins( 3, 0, 0, 0 )
        headerLayout.addWidget( recentFilesLabel )
        headerFrame.setLayout( headerLayout )

        self.recentFilesView = QTreeWidget()
        self.recentFilesView.setAlternatingRowColors( True )
        self.recentFilesView.setRootIsDecorated( False )
        self.recentFilesView.setItemsExpandable( False )
        self.recentFilesView.setSortingEnabled( True )
        self.recentFilesView.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.recentFilesView.setUniformRowHeights( True )

        self.__filesHeaderItem = QTreeWidgetItem( [ "", "File",
                                                    "Absolute path" ] )
        self.recentFilesView.setHeaderItem( self.__filesHeaderItem )
        self.recentFilesView.header().setSortIndicator( 1, Qt.AscendingOrder )

        self.connect( self.recentFilesView,
                      SIGNAL( "itemSelectionChanged()" ),
                      self.__fileSelectionChanged )
        self.connect( self.recentFilesView,
                      SIGNAL( "itemActivated(QTreeWidgetItem *, int)" ),
                      self.__fileActivated )

        # Toolbar part - buttons
        self.openFileButton = QAction( PixmapCache().getIcon( 'openitem.png' ),
                                       'Open the highlighted file', self )
        self.connect( self.openFileButton, SIGNAL( "triggered()" ),
                      self.__openFile )
        self.copyFilePathButton = QAction( \
                        PixmapCache().getIcon( 'copytoclipboard.png' ),
                        'Copy path to clipboard', self )
        self.connect( self.copyFilePathButton, SIGNAL( "triggered()" ),
                      self.__filePathToClipboard )
        spacer = QWidget()
        spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding )
        self.trashFileButton = QAction( PixmapCache().getIcon( 'delitem.png' ),
                                        'Remove selected (not from the disk)',
                                        self )
        self.connect( self.trashFileButton, SIGNAL( "triggered()" ),
                      self.__deleteFile )

        self.upperToolbar = QToolBar()
        self.upperToolbar.setMovable( False )
        self.upperToolbar.setAllowedAreas( Qt.TopToolBarArea )
        self.upperToolbar.setIconSize( QSize( 16, 16 ) )
        self.upperToolbar.setFixedHeight( 28 )
        self.upperToolbar.setContentsMargins( 0, 0, 0, 0 )
        self.upperToolbar.addAction( self.openFileButton )
        self.upperToolbar.addAction( self.copyFilePathButton )
        self.upperToolbar.addWidget( spacer )
        self.upperToolbar.addAction( self.trashFileButton )

        recentFilesLayout = QVBoxLayout()
        recentFilesLayout.setContentsMargins( 0, 0, 0, 0 )
        recentFilesLayout.setSpacing( 0 )
        recentFilesLayout.addWidget( headerFrame )
        recentFilesLayout.addWidget( self.upperToolbar )
        recentFilesLayout.addWidget( self.recentFilesView )

        upperContainer = QWidget()
        upperContainer.setContentsMargins( 0, 0, 0, 0 )
        upperContainer.setLayout( recentFilesLayout )
        return upperContainer

    def getRecentFilesToolbar( self ):
        " Provides a reference to the recent files toolbar "
        return self.upperToolbar

    def __createRecentProjectsLayout( self ):
        " Creates the bottom layout "
        self.headerFrame = QFrame()
        self.headerFrame.setFrameStyle( QFrame.StyledPanel )
        self.headerFrame.setAutoFillBackground( True )
        headerPalette = self.headerFrame.palette()
        headerBackground = headerPalette.color( QPalette.Background )
        headerBackground.setRgb( min( headerBackground.red() + 30, 255 ),
                                 min( headerBackground.green() + 30, 255 ),
                                 min( headerBackground.blue() + 30, 255 ) )
        headerPalette.setColor( QPalette.Background, headerBackground )
        self.headerFrame.setPalette( headerPalette )
        self.headerFrame.setFixedHeight( 24 )

        recentProjectsLabel = QLabel()
        recentProjectsLabel.setText( "Recent projects" )

        expandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )

        self.__showHideButton = QToolButton()
        self.__showHideButton.setAutoRaise( True )
        self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
        self.__showHideButton.setFixedSize( 20, 20 )
        self.__showHideButton.setToolTip( "Hide recent projects list" )
        self.__showHideButton.setFocusPolicy( Qt.NoFocus )
        self.connect( self.__showHideButton, SIGNAL( 'clicked()' ),
                      self.__onShowHide )

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins( 3, 0, 0, 0 )
        headerLayout.addWidget( recentProjectsLabel )
        headerLayout.addSpacerItem( expandingSpacer )
        headerLayout.addWidget( self.__showHideButton )
        self.headerFrame.setLayout( headerLayout )

        # Toolbar part - buttons
        self.loadButton = QAction( PixmapCache().getIcon( 'load.png' ),
                                   'Load the highlighted project', self )
        self.connect( self.loadButton, SIGNAL( "triggered()" ),
                      self.__loadProject )
        self.propertiesButton = QAction( PixmapCache().getIcon( 'smalli.png' ),
                                         'Show the highlighted project ' \
                                         'properties', self )
        self.connect( self.propertiesButton, SIGNAL( "triggered()" ),
                      self.__viewProperties )
        self.copyPrjPathButton = QAction( \
                        PixmapCache().getIcon( 'copytoclipboard.png' ),
                        'Copy path to clipboard', self )
        self.connect( self.copyPrjPathButton, SIGNAL( "triggered()" ),
                      self.__prjPathToClipboard )
        spacer = QWidget()
        spacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding )
        self.trashButton = QAction( PixmapCache().getIcon( 'delitem.png' ),
                                    'Remove selected (not from the disk)',
                                    self )
        self.connect( self.trashButton, SIGNAL( "triggered()" ),
                      self.__deleteProject )

        self.lowerToolbar = QToolBar()
        self.lowerToolbar.setMovable( False )
        self.lowerToolbar.setAllowedAreas( Qt.TopToolBarArea )
        self.lowerToolbar.setIconSize( QSize( 16, 16 ) )
        self.lowerToolbar.setFixedHeight( 28 )
        self.lowerToolbar.setContentsMargins( 0, 0, 0, 0 )
        self.lowerToolbar.addAction( self.loadButton )
        self.lowerToolbar.addAction( self.propertiesButton )
        self.lowerToolbar.addAction( self.copyPrjPathButton )
        self.lowerToolbar.addWidget( spacer )
        self.lowerToolbar.addAction( self.trashButton )

        self.projectsView = QTreeWidget()
        self.projectsView.setAlternatingRowColors( True )
        self.projectsView.setRootIsDecorated( False )
        self.projectsView.setItemsExpandable( False )
        self.projectsView.setSortingEnabled( True )
        self.projectsView.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.projectsView.setUniformRowHeights( True )

        self.__projectsHeaderItem = QTreeWidgetItem( [ "", "Project",
                                                       "Absolute path" ] )
        self.projectsView.setHeaderItem( self.__projectsHeaderItem )

        self.projectsView.header().setSortIndicator( 1, Qt.AscendingOrder )
        self.connect( self.projectsView,
                      SIGNAL( "itemActivated(QTreeWidgetItem *, int)" ),
                      self.__projectActivated )
        self.connect( self.projectsView,
                      SIGNAL( "itemSelectionChanged()" ),
                      self.__projectSelectionChanged )

        recentProjectsLayout = QVBoxLayout()
        recentProjectsLayout.setContentsMargins( 0, 0, 0, 0 )
        recentProjectsLayout.setSpacing( 0 )
        recentProjectsLayout.addWidget( self.headerFrame )
        recentProjectsLayout.addWidget( self.lowerToolbar )
        recentProjectsLayout.addWidget( self.projectsView )

        lowerContainer = QWidget()
        lowerContainer.setContentsMargins( 0, 0, 0, 0 )
        lowerContainer.setLayout( recentProjectsLayout )
        return lowerContainer

    def getRecentProjectsToolbar( self ):
        " Provides a reference to the projects toolbar "
        return self.lowerToolbar

    def __projectSelectionChanged( self ):
        " Handles the projects changed selection "
        selected = list( self.projectsView.selectedItems() )

        if selected:
            self.__projectContextItem = selected[ 0 ]
        else:
            self.__projectContextItem = None

        self.__updateProjectToolbarButtons()
        return

    def __fileSelectionChanged( self ):
        " Handles the files changed selection "
        selected = list( self.recentFilesView.selectedItems() )

        if selected:
            self.__fileContextItem = selected[ 0 ]
        else:
            self.__fileContextItem = None
        self.__updateFileToolbarButtons()
        return

    def __updateProjectToolbarButtons( self ):
        " Updates the toolbar buttons depending on the __projectContextItem "
        if self.__projectContextItem is None:
            self.loadButton.setEnabled( False )
            self.propertiesButton.setEnabled( False )
            self.copyPrjPathButton.setEnabled( False )
            self.trashButton.setEnabled( False )
        else:
            enabled = self.__projectContextItem.isValid()
            isCurrentProject = self.__projectContextItem.isCurrent()

            self.propertiesButton.setEnabled( enabled )
            self.copyPrjPathButton.setEnabled( True )
            self.loadButton.setEnabled( enabled and
                                        not isCurrentProject and
                                        not self.__debugMode )
            self.trashButton.setEnabled( not isCurrentProject )
        return

    def __updateFileToolbarButtons( self ):
        " Updates the toolbar buttons depending on the __fileContextItem "
        enabled = self.__fileContextItem is not None
        self.openFileButton.setEnabled( enabled )
        self.copyFilePathButton.setEnabled( enabled )
        self.trashFileButton.setEnabled( enabled )
        return

    def __handleShowPrjContextMenu( self, coord ):
        " Show the project item context menu "
        self.__projectContextItem = self.projectsView.itemAt( coord )
        if self.__projectContextItem is None:
            return

        enabled = self.__projectContextItem.isValid()
        isCurrentProject = self.__projectContextItem.isCurrent()

        self.__propsMenuItem.setEnabled( enabled )
        self.__delPrjMenuItem.setEnabled( not isCurrentProject )
#        fName = self.__projectContextItem.getFilename()
        self.__prjLoadMenuItem.setEnabled( enabled and \
                                           not isCurrentProject and \
                                           not self.__debugMode )

        self.__projectMenu.popup( QCursor.pos() )
        return

    def __sortProjects( self ):
        " Sort the project items "
        self.projectsView.sortItems( \
                self.projectsView.sortColumn(),
                self.projectsView.header().sortIndicatorOrder() )
        return

    def __sortFiles( self ):
        " Sort the file items "
        self.recentFilesView.sortItems( \
                self.recentFilesView.sortColumn(),
                self.recentFilesView.header().sortIndicatorOrder() )
        return

    def __resizeProjectColumns( self ):
        """ Resize the projects list columns """
        self.projectsView.header().setStretchLastSection( True )
        self.projectsView.header().resizeSections( \
                                    QHeaderView.ResizeToContents )
        self.projectsView.header().resizeSection( 0, 22 )
        self.projectsView.header().setResizeMode( 0, QHeaderView.Fixed )
        return

    def __resizeFileColumns( self ):
        " Resize the files list columns "
        self.recentFilesView.header().setStretchLastSection( True )
        self.recentFilesView.header().resizeSections( \
                                    QHeaderView.ResizeToContents )
        self.recentFilesView.header().resizeSection( 0, 22 )
        self.recentFilesView.header().setResizeMode( 0, QHeaderView.Fixed )
        return

    def __projectActivated( self, item, column ):
        " Handles the double click (or Enter) on the item "
        self.__projectContextItem = item
        self.__loadProject()
        return

    def __fileActivated( self, item, column ):
        " Handles the double click (or Enter) on a file item "
        self.__fileContextItem = item
        self.__openFile()
        return

    def __viewProperties( self ):
        " Handles the 'view properties' context menu item "
        if self.__projectContextItem is None:
            return
        if not self.__projectContextItem.isValid():
            return

        if self.__projectContextItem.isCurrent():
            # This is the current project - it can be edited
            project = GlobalData().project
            dialog = ProjectPropertiesDialog( project )
            if dialog.exec_() == QDialog.Accepted:
                importDirs = []
                for index in xrange( dialog.importDirList.count() ):
                    importDirs.append( dialog.importDirList.item( index ).text() )

                scriptName = dialog.scriptEdit.text().strip()
                relativePath = relpath( scriptName, project.getProjectDir() )
                if not relativePath.startswith( '..' ):
                    scriptName = relativePath

                project.updateProperties(
                    scriptName, importDirs,
                    dialog.creationDateEdit.text().strip(),
                    dialog.authorEdit.text().strip(),
                    dialog.licenseEdit.text().strip(),
                    dialog.copyrightEdit.text().strip(),
                    dialog.versionEdit.text().strip(),
                    dialog.emailEdit.text().strip(),
                    dialog.descriptionEdit.toPlainText().strip() )
        else:
            # This is not the current project - it can be viewed
            fName = self.__projectContextItem.getFilename()
            dialog = ProjectPropertiesDialog( fName )
            dialog.exec_()
        return

    def __deleteProject( self ):
        " Handles the 'delete from recent' context menu item "
        if self.__projectContextItem is None:
            return

        # Removal from the visible list is done via a signal which comes back
        # from settings
        fName = self.__projectContextItem.getFilename()
        Settings().deleteRecentProject( fName )
        return

    def __loadProject( self ):
        " handles 'Load' context menu item "
        if self.__projectContextItem is None:
            return
        if not self.__projectContextItem.isValid():
            return
        if self.__debugMode:
            return

        projectFileName = self.__projectContextItem.getFilename()

        if self.__projectContextItem.isCurrent():
            GlobalData().mainWindow.openFile( projectFileName, -1 )
            return  # This is the current project, open for text editing

        QApplication.processEvents()
        QApplication.setOverrideCursor( QCursor( Qt.WaitCursor ) )
        if os.path.exists( projectFileName ):
            mainWin = GlobalData().mainWindow
            editorsManager = mainWin.editorsManagerWidget.editorsManager
            if editorsManager.closeRequest():
                prj = GlobalData().project
                prj.setTabsStatus( editorsManager.getTabsStatus() )
                editorsManager.closeAll()
                prj.loadProject( projectFileName )
                mainWin.activateProjectTab()
        else:
            logging.error( "The project " + \
                           os.path.basename( projectFileName ) + \
                           " disappeared from the file system." )
            self.__populateProjects()
        QApplication.restoreOverrideCursor()
        return

    def __populateProjects( self ):
        " Populates the recent projects "
        self.projectsView.clear()
        for item in Settings().recentProjects:
            self.projectsView.addTopLevelItem( RecentProjectViewItem( item ) )

        self.__sortProjects()
        self.__resizeProjectColumns()
        self.__updateProjectToolbarButtons()
        return

    def __populateFiles( self ):
        " Populates the recent files "
        self.recentFilesView.clear()
        for path in GlobalData().project.recentFiles:
            self.recentFilesView.addTopLevelItem( RecentFileViewItem( path ) )

        self.__sortFiles()
        self.__resizeFileColumns()
        self.__updateFileToolbarButtons()
        return

    def __projectChanged( self, what ):
        " Triggered when the current project is changed "
        if what == CodimensionProject.CompleteProject:
            self.__populateProjects()
            self.__populateFiles()
            return

        if what == CodimensionProject.Properties:
            # Update the corresponding tooltip
            items = self.projectsView.findItems( GlobalData().project.fileName,
                                                 Qt.MatchExactly, 2 )
            if len( items ) != 1:
                logging.error( "Unexpected number of matched projects: " + \
                               str( len( items ) ) )
                return

            items[ 0 ].updateTooltip()
            return

    def __openFile( self ):
        " Handles 'open' file menu item "
        self.__fileContextItem.updateIconAndTooltip()
        fName = self.__fileContextItem.getFilename()

        if not self.__fileContextItem.isValid():
            logging.warning( "Cannot open " + fName )
            return

        fileType = detectFileType( fName )
        if fileType == PixmapFileType:
            GlobalData().mainWindow.openPixmapFile( fName )
            return

        GlobalData().mainWindow.openFile( fName, -1 )
        return

    def __deleteFile( self ):
        " Handles 'delete from recent' file menu item "
        self.removeRecentFile( self.__fileContextItem.getFilename() )
        return

    def __handleShowFileContextMenu( self, coord ):
        " File context menu "
        self.__fileContextItem = self.recentFilesView.itemAt( coord )
        if self.__fileContextItem is not None:
            self.__fileMenu.popup( QCursor.pos() )
        return

    def __filePathToClipboard( self ):
        " Copies the file item path to the clipboard "
        if self.__fileContextItem is not None:
            QApplication.clipboard().setText( \
                    self.__fileContextItem.getFilename() )
        return

    def __prjPathToClipboard( self ):
        " Copies the project item path to the clipboard "
        if self.__projectContextItem is not None:
            QApplication.clipboard().setText( \
                    self.__projectContextItem.getFilename() )
        return

    def onFileUpdated( self, fileName, uuid ):
        " Triggered when the file is updated: python or project "
        realPath = os.path.realpath( fileName )

        count = self.recentFilesView.topLevelItemCount()
        for index in xrange( 0, count ):
            item = self.recentFilesView.topLevelItem( index )

            itemRealPath = os.path.realpath( item.getFilename() )
            if realPath == itemRealPath:
                item.updateIconAndTooltip()
                break

        for index in xrange( 0, self.projectsView.topLevelItemCount() ):
            item = self.projectsView.topLevelItem( index )

            itemRealPath = os.path.realpath( item.getFilename() )
            if realPath == itemRealPath:
                item.updateTooltip()
                break
        return

    def __onShowHide( self ):
        " Triggered when show/hide button is clicked "
        if self.projectsView.isVisible():
            self.projectsView.setVisible( False )
            self.lowerToolbar.setVisible( False )
            self.__showHideButton.setIcon( PixmapCache().getIcon( 'more.png' ) )
            self.__showHideButton.setToolTip( "Show recent projects list" )

            self.__minH = self.lower.minimumHeight()
            self.__maxH = self.lower.maximumHeight()

            self.lower.setMinimumHeight( self.headerFrame.height() )
            self.lower.setMaximumHeight( self.headerFrame.height() )
        else:
            self.projectsView.setVisible( True )
            self.lowerToolbar.setVisible( True )
            self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
            self.__showHideButton.setToolTip( "Hide recent projects list" )

            self.lower.setMinimumHeight( self.__minH )
            self.lower.setMaximumHeight( self.__maxH )
        return

    def __onDebugMode( self, newState ):
        " Triggered when debug mode has changed "
        self.__debugMode = newState

        # Disable the load project button
        self.__updateProjectToolbarButtons()
        return

    def removeRecentFile( self, fName ):
        " Removes a single file from the recent files list "
        GlobalData().project.removeRecentFile( fName )

        for index in xrange( self.recentFilesView.topLevelItemCount() ):
            candidate = self.recentFilesView.topLevelItem( index )
            if candidate.getFilename() == fName:
                self.recentFilesView.takeTopLevelItem( index )
                return
        return
コード例 #16
0
class MemUsageDialog(QDialog):
    def __init__(self, parent=None, update=True):
        QDialog.__init__(self, parent=parent)
        layout = QVBoxLayout()
        self.tree = QTreeWidget()
        self.tree.setHeaderLabels(["cache", "memory", "roi", "dtype", "type"])
        layout.addWidget(self.tree)
        self.setLayout(layout)
        
        self.memMgr = ArrayCacheMemoryMgr.instance
        
        self.timer = QTimer(self)
        if update:
            self.timer.timeout.connect(self._updateReport)
            self._updateReport()
       
    def _updateReport(self):
        reports = []
        for c in self.memMgr.namedCaches:
            r = MemInfoNode()
            try:
                c.generateReport(r)
                reports.append(r)
            except NotImplementedError:
                warnings.warn('cache operator {} does not implement generateReport()'.format(c))
        self._showReports(reports)
        
        '''
        import pickle
        f = open("/tmp/reports.pickle",'w')
        pickle.dump(reports, f)
        f.close()
        print "... saved MEM reports to file ..."
        '''
        
    def _showReports(self, reports):
        self.tree.clear()
        root = self.tree.invisibleRootItem()
        for r in reports:
            self._showReportsImpl(r, root, 0)
       
    def _makeTreeWidgetItem(self, node):
        l = []
        l.append("%r" % node.name)
        l.append("%1.1f MB" % (node.usedMemory/1024**2.0))
        if node.roi is not None:
            l.append("%r\n%r" % (list(node.roi[0]), list(node.roi[1])))
        else:
            l.append("")
        if node.dtype is not None:
            if node.dtype == numpy.float32:
                l.append("float32")
            elif node.dtype == numpy.uint8:
                l.append("uint8")
            elif node.dtype == numpy.uint32:
                l.append("uint32")
            elif node.dtype == numpy.float64:
                l.append("float64")
            else:
                l.append(str(node.dtype))
                
        else:
            l.append("")
        
        t = str(node.type)
        t = t[len("<type '")+1:-len("'>")]
        t = t.split(".")[-1]
        l.append(t)
        return QTreeWidgetItem(l)
    
    def _showReportsImpl(self, node, itm, level):
        #print "  "*level,
        #print "node", node.name
        
        root = self._makeTreeWidgetItem(node)
        itm.addChild(root)
        root.setExpanded(True)
        
        for c in node.children:
            self._showReportsImpl(c, root, level+1)
            
    def hideEvent(self, event):
        self.timer.stop()
        
    def showEvent(self, show):
        self.timer.start(5*1000) #update every 5 sec.
コード例 #17
0
ファイル: OWPIPAx.py プロジェクト: nagyistoce/orange-bio
class OWPIPAx(widget.OWWidget):
    name = "PIPAx"
    description = "Access data from PIPA RNA-Seq database."
    icon = "../widgets/icons/PIPA.svg"
    priority = 35

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

    username = settings.Setting("")
    password = settings.Setting("")

    log2 = settings.Setting(False)
    rtypei = settings.Setting(5)  # hardcoded rpkm mapability polya
    excludeconstant = settings.Setting(False)
    joinreplicates = settings.Setting(False)
    #: The stored current selection (in experiments view)
    #: SelectionByKey | None
    currentSelection = settings.Setting(None)
    #: Stored selections (presets)
    #: list of SelectionByKey
    storedSelections = settings.Setting([])
    #: Stored column sort keys (from Sort view)
    #: list of strings
    storedSortingOrder = settings.Setting(
        ["Strain", "Experiment", "Genotype", "Timepoint"])

    experimentsHeaderState = settings.Setting(
        {name: False for _, name in HEADER[:ID_INDEX + 1]}
    )

    def __init__(self, parent=None, signalManager=None, name="PIPAx"):
        super().__init__(parent)

        self.selectedExperiments = []
        self.buffer = dicty.CacheSQLite(bufferfile)

        self.searchString = ""

        self.result_types = []
        self.mappings = {}

        self.controlArea.setMaximumWidth(250)
        self.controlArea.setMinimumWidth(250)

        gui.button(self.controlArea, self, "Reload",
                     callback=self.Reload)
        gui.button(self.controlArea, self, "Clear cache",
                     callback=self.clear_cache)

        b = gui.widgetBox(self.controlArea, "Experiment Sets")
        self.selectionSetsWidget = SelectionSetsWidget(self)
        self.selectionSetsWidget.setSizePolicy(
            QSizePolicy.Preferred, QSizePolicy.Maximum)

        def store_selections(modified):
            if not modified:
                self.storedSelections = self.selectionSetsWidget.selections

        self.selectionSetsWidget.selectionModified.connect(store_selections)
        b.layout().addWidget(self.selectionSetsWidget)

        gui.separator(self.controlArea)

        b = gui.widgetBox(self.controlArea, "Sort output columns")
        self.columnsSortingWidget = SortedListWidget(self)
        self.columnsSortingWidget.setSizePolicy(
            QSizePolicy.Preferred, QSizePolicy.Maximum)

        def store_sort_order():
            self.storedSortingOrder = self.columnsSortingWidget.sortingOrder
        self.columnsSortingWidget.sortingOrderChanged.connect(store_sort_order)
        b.layout().addWidget(self.columnsSortingWidget)
        sorting_model = QStringListModel(SORTING_MODEL_LIST)
        self.columnsSortingWidget.setModel(sorting_model)

        gui.separator(self.controlArea)

        box = gui.widgetBox(self.controlArea, 'Expression Type')
        self.expressionTypesCB = gui.comboBox(
            box, self, "rtypei", items=[], callback=self.UpdateResultsList)

        gui.checkBox(self.controlArea, self, "excludeconstant",
                     "Exclude labels with constant values")

        gui.checkBox(self.controlArea, self, "joinreplicates",
                     "Average replicates (use median)")

        gui.checkBox(self.controlArea, self, "log2",
                     "Logarithmic (base 2) transformation")

        self.commit_button = gui.button(self.controlArea, self, "&Commit",
                                        callback=self.Commit)
        self.commit_button.setDisabled(True)

        gui.rubber(self.controlArea)

        box = gui.widgetBox(self.controlArea, "Authentication")

        gui.lineEdit(box, self, "username", "Username:"******"password", "Password:"******"searchString", "Search",
                     callbackOnType=True,
                     callback=self.SearchUpdate)

        self.headerLabels = [t[1] for t in HEADER]

        self.experimentsWidget = QTreeWidget()
        self.experimentsWidget.setHeaderLabels(self.headerLabels)
        self.experimentsWidget.setSelectionMode(QTreeWidget.ExtendedSelection)
        self.experimentsWidget.setRootIsDecorated(False)
        self.experimentsWidget.setSortingEnabled(True)

        contextEventFilter = gui.VisibleHeaderSectionContextEventFilter(
            self.experimentsWidget, self.experimentsWidget
        )

        self.experimentsWidget.header().installEventFilter(contextEventFilter)
        self.experimentsWidget.setItemDelegateForColumn(
            0, gui.IndicatorItemDelegate(self, role=Qt.DisplayRole))

        self.experimentsWidget.setAlternatingRowColors(True)

        self.experimentsWidget.selectionModel().selectionChanged.connect(
            self.onSelectionChanged)

        self.selectionSetsWidget.setSelectionModel(
            self.experimentsWidget.selectionModel()
        )

        self.mainArea.layout().addWidget(self.experimentsWidget)

        # Restore the selection states from the stored settings
        self.selectionSetsWidget.selections = self.storedSelections
        self.columnsSortingWidget.sortingOrder = self.storedSortingOrder

        self.restoreHeaderState()

        self.experimentsWidget.header().geometriesChanged.connect(
            self.saveHeaderState)

        self.dbc = None

        self.AuthSet()

        QTimer.singleShot(100, self.UpdateExperiments)

    def sizeHint(self):
        return QSize(800, 600)

    def AuthSet(self):
        if len(self.username):
            self.passf.setDisabled(False)
        else:
            self.passf.setDisabled(True)

    def AuthChanged(self):
        self.AuthSet()
        self.ConnectAndUpdate()

    def ConnectAndUpdate(self):
        self.Connect()
        self.UpdateExperiments(reload=True)

    def Connect(self):
        self.error(1)
        self.warning(1)

        def en(x):
            return x if len(x) else None

        self.dbc = dicty.PIPAx(cache=self.buffer,
                               username=en(self.username),
                               password=self.password)

        # check password
        if en(self.username) != None:
            try:
                self.dbc.mappings(reload=True)
            except dicty.AuthenticationError:
                self.error(1, "Wrong username or password")
                self.dbc = None
            except Exception as ex:
                print("Error when contacting the PIPA database", ex)
                sys.excepthook(*sys.exc_info())
                try:  # maybe cached?
                    self.dbc.mappings()
                    self.warning(1, "Can not access database - using cached data.")
                except Exception as ex:
                    self.dbc = None
                    self.error(1, "Can not access database.")

    def Reload(self):
        self.UpdateExperiments(reload=True)

    def clear_cache(self):
        self.buffer.clear()
        self.Reload()

    def rtype(self):
        """Return selected result template type """
        if self.result_types:
            return self.result_types[self.rtypei][0]
        else:
            return "-1"

    def UpdateExperimentTypes(self):
        self.expressionTypesCB.clear()
        items = [desc for _, desc in self.result_types]
        self.expressionTypesCB.addItems(items)
        self.rtypei = max(0, min(self.rtypei, len(self.result_types) - 1))

    def UpdateExperiments(self, reload=False):
        self.experimentsWidget.clear()
        self.items = []

        self.progressBarInit()

        if not self.dbc:
            self.Connect()

        mappings = {}
        result_types = []
        sucind = False  # success indicator for database index

        try:
            mappings = self.dbc.mappings(reload=reload)
            result_types = self.dbc.result_types(reload=reload)
            sucind = True
        except Exception as ex:
            try:
                mappings = self.dbc.mappings()
                result_types = self.dbc.result_types()
                self.warning(0, "Can not access database - using cached data.")
                sucind = True
            except Exception as ex:
                self.error(0, "Can not access database.")

        if sucind:
            self.warning(0)
            self.error(0)

        self.mappings = mappings
        self.result_types = result_types

        self.UpdateExperimentTypes()
        self.UpdateResultsList(reload=reload)

        self.progressBarFinished()

        if self.currentSelection:
            self.currentSelection.select(
                self.experimentsWidget.selectionModel())

        self.handle_commit_button()

    def UpdateResultsList(self, reload=False):

        results_list = {}
        try:
            results_list = self.dbc.results_list(self.rtype(), reload=reload)
        except Exception as ex:
            try:
                results_list = self.dbc.results_list(self.rtype())
            except Exception as ex:
                self.error(0, "Can not access database.")

        self.results_list = results_list
        mappings_key_dict = dict(((m["data_id"], m["id"]), key) \
                                 for key, m in self.mappings.items())

        def mapping_unique_id(annot):
            """Map annotations dict from results_list to unique
            `mappings` ids.
            """
            data_id, mappings_id = annot["data_id"], annot["mappings_id"]
            return mappings_key_dict[data_id, mappings_id]

        elements = []

        # softly change the view so that the selection stays the same

        items_shown = {}
        for i, item in enumerate(self.items):
            c = str(item.text(10))
            items_shown[c] = i

        items_to_show = dict((mapping_unique_id(annot), annot)
                             for annot in self.results_list.values())

        add_items = set(items_to_show) - set(items_shown)
        delete_items = set(items_shown) - set(items_to_show)

        i = 0
        while i < self.experimentsWidget.topLevelItemCount():
            it = self.experimentsWidget.topLevelItem(i)
            if str(it.text(10)) in delete_items:
                self.experimentsWidget.takeTopLevelItem(i)
            else:
                i += 1

        delete_ind = set([items_shown[i] for i in delete_items])
        self.items = [it for i, it in enumerate(self.items) if i not in delete_ind]

        for r_annot in [items_to_show[i] for i in add_items]:
            d = defaultdict(lambda: "?", r_annot)
            row_items = [""] + [d.get(key, "?") for key, _ in HEADER[1:]]
            try:
                time_dict = literal_eval(row_items[DATE_INDEX])
                date_rna = date(time_dict["fullYearUTC"],
                                time_dict["monthUTC"] + 1,  # Why is month 0 based?
                                time_dict["dateUTC"])
                row_items[DATE_INDEX] = date_rna.strftime("%x")
            except Exception:
                row_items[DATE_INDEX] = ''

            row_items[ID_INDEX] = mapping_unique_id(r_annot)
            elements.append(row_items)

            ci = MyTreeWidgetItem(self.experimentsWidget, row_items)

            self.items.append(ci)

        for i in range(len(self.headerLabels)):
            self.experimentsWidget.resizeColumnToContents(i)

        # which is the ok buffer version
        # FIXME: what attribute to use for version?
        self.wantbufver = \
            lambda x, ad=self.results_list: \
            defaultdict(lambda: "?", ad[x])["date"]

        self.wantbufver = lambda x: "0"

        self.UpdateCached()

    def UpdateCached(self):
        if self.wantbufver and self.dbc:
            fn = self.dbc.download_key_function()
            result_id_key = dict(((m["data_id"], m["mappings_id"]), key) \
                                 for key, m in self.results_list.items())

            for item in self.items:
                c = str(item.text(10))
                mapping = self.mappings[c]
                data_id, mappings_id = mapping["data_id"], mapping["id"]
                r_id = result_id_key[data_id, mappings_id]
                # Get the buffered version
                buffered = self.dbc.inBuffer(fn(r_id))
                value = " " if buffered == self.wantbufver(r_id) else ""
                item.setData(0, Qt.DisplayRole, value)

    def SearchUpdate(self, string=""):
        for item in self.items:
            item.setHidden(not all(s in item \
                                   for s in self.searchString.split())
                           )

    def Commit(self):
        if not self.dbc:
            self.Connect()

        pb = gui.ProgressBar(self, iterations=100)

        table = None

        ids = []
        for item in self.experimentsWidget.selectedItems():
            unique_id = str(item.text(10))
            annots = self.mappings[unique_id]
            ids.append((annots["data_id"], annots["id"]))

        transfn = None
        if self.log2:
            transfn = lambda x: math.log(x + 1.0, 2)

        reverse_header_dict = dict((name, key) for key, name in HEADER)

        hview = self.experimentsWidget.header()
        shownHeaders = [label for i, label in \
                        list(enumerate(self.headerLabels))[1:] \
                        if not hview.isSectionHidden(i)
                        ]

        allowed_labels = [reverse_header_dict.get(label, label) \
                          for label in shownHeaders]

        if self.joinreplicates and "id" not in allowed_labels:
            # need 'id' labels in join_replicates for attribute names
            allowed_labels.append("id")

        if len(ids):
            table = self.dbc.get_data(ids=ids, result_type=self.rtype(),
                                      callback=pb.advance,
                                      exclude_constant_labels=self.excludeconstant,
                                      #                          bufver=self.wantbufver,
                                      transform=transfn,
                                      allowed_labels=allowed_labels)

            if self.joinreplicates:
                table = dicty.join_replicates(table,
                                              ignorenames=["replicate", "data_id", "mappings_id",
                                                           "data_name", "id", "unique_id"],
                                              namefn=None,
                                              avg=dicty.median
                                              )

            # Sort attributes
            sortOrder = self.columnsSortingWidget.sortingOrder

            all_values = defaultdict(set)
            for at in table.domain.attributes:
                atts = at.attributes
                for name in sortOrder:
                    all_values[name].add(atts.get(reverse_header_dict[name], ""))

            isnum = {}
            for at, vals in all_values.items():
                vals = filter(None, vals)
                try:
                    for a in vals:
                        float(a)
                    isnum[at] = True
                except:
                    isnum[at] = False

            def optfloat(x, at):
                if x == "":
                    return ""
                else:
                    return float(x) if isnum[at] else x

            def sorting_key(attr):
                atts = attr.attributes
                return tuple([optfloat(atts.get(reverse_header_dict[name], ""), name) \
                              for name in sortOrder])

            attributes = sorted(table.domain.attributes,
                                key=sorting_key)

            domain = Orange.data.Domain(
                attributes, table.domain.class_var, table.domain.metas)
            table = table.from_table(domain, table)

            data_hints.set_hint(table, "taxid", "352472")
            data_hints.set_hint(table, "genesinrows", False)

            self.send("Data", table)

            self.UpdateCached()

        pb.finish()

    def onSelectionChanged(self, selected, deselected):
        self.handle_commit_button()

    def handle_commit_button(self):
        self.currentSelection = \
            SelectionByKey(self.experimentsWidget.selectionModel().selection(),
                           key=(1, 2, 3, 10))
        self.commit_button.setDisabled(not len(self.currentSelection))

    def saveHeaderState(self):
        hview = self.experimentsWidget.header()
        for i, label in enumerate(self.headerLabels):
            self.experimentsHeaderState[label] = hview.isSectionHidden(i)

    def restoreHeaderState(self):
        hview = self.experimentsWidget.header()
        state = self.experimentsHeaderState
        for i, label in enumerate(self.headerLabels):
            hview.setSectionHidden(i, state.get(label, True))
            self.experimentsWidget.resizeColumnToContents(i)
コード例 #18
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()
コード例 #19
0
class OWPIPAx(widget.OWWidget):
    name = "PIPAx"
    description = "Access data from PIPA RNA-Seq database."
    icon = "../widgets/icons/PIPA.svg"
    priority = 35

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

    username = settings.Setting("")
    password = settings.Setting("")

    log2 = settings.Setting(False)
    rtypei = settings.Setting(5)  # hardcoded rpkm mapability polya
    excludeconstant = settings.Setting(False)
    joinreplicates = settings.Setting(False)
    #: The stored current selection (in experiments view)
    #: SelectionByKey | None
    currentSelection = settings.Setting(None)
    #: Stored selections (presets)
    #: list of SelectionByKey
    storedSelections = settings.Setting([])
    #: Stored column sort keys (from Sort view)
    #: list of strings
    storedSortingOrder = settings.Setting(
        ["Strain", "Experiment", "Genotype", "Timepoint"])

    experimentsHeaderState = settings.Setting(
        {name: False
         for _, name in HEADER[:ID_INDEX + 1]})

    def __init__(self, parent=None, signalManager=None, name="PIPAx"):
        super().__init__(parent)

        self.selectedExperiments = []
        self.buffer = dicty.CacheSQLite(bufferfile)

        self.searchString = ""

        self.result_types = []
        self.mappings = {}

        self.controlArea.setMaximumWidth(250)
        self.controlArea.setMinimumWidth(250)

        gui.button(self.controlArea, self, "Reload", callback=self.Reload)
        gui.button(self.controlArea,
                   self,
                   "Clear cache",
                   callback=self.clear_cache)

        b = gui.widgetBox(self.controlArea, "Experiment Sets")
        self.selectionSetsWidget = SelectionSetsWidget(self)
        self.selectionSetsWidget.setSizePolicy(QSizePolicy.Preferred,
                                               QSizePolicy.Maximum)

        def store_selections(modified):
            if not modified:
                self.storedSelections = self.selectionSetsWidget.selections

        self.selectionSetsWidget.selectionModified.connect(store_selections)
        b.layout().addWidget(self.selectionSetsWidget)

        gui.separator(self.controlArea)

        b = gui.widgetBox(self.controlArea, "Sort output columns")
        self.columnsSortingWidget = SortedListWidget(self)
        self.columnsSortingWidget.setSizePolicy(QSizePolicy.Preferred,
                                                QSizePolicy.Maximum)

        def store_sort_order():
            self.storedSortingOrder = self.columnsSortingWidget.sortingOrder

        self.columnsSortingWidget.sortingOrderChanged.connect(store_sort_order)
        b.layout().addWidget(self.columnsSortingWidget)
        sorting_model = QStringListModel(SORTING_MODEL_LIST)
        self.columnsSortingWidget.setModel(sorting_model)

        gui.separator(self.controlArea)

        box = gui.widgetBox(self.controlArea, 'Expression Type')
        self.expressionTypesCB = gui.comboBox(box,
                                              self,
                                              "rtypei",
                                              items=[],
                                              callback=self.UpdateResultsList)

        gui.checkBox(self.controlArea, self, "excludeconstant",
                     "Exclude labels with constant values")

        gui.checkBox(self.controlArea, self, "joinreplicates",
                     "Average replicates (use median)")

        gui.checkBox(self.controlArea, self, "log2",
                     "Logarithmic (base 2) transformation")

        self.commit_button = gui.button(self.controlArea,
                                        self,
                                        "&Commit",
                                        callback=self.Commit)
        self.commit_button.setDisabled(True)

        gui.rubber(self.controlArea)

        box = gui.widgetBox(self.controlArea, "Authentication")

        gui.lineEdit(box,
                     self,
                     "username",
                     "Username:"******"password",
                                  "Password:"******"searchString",
                     "Search",
                     callbackOnType=True,
                     callback=self.SearchUpdate)

        self.headerLabels = [t[1] for t in HEADER]

        self.experimentsWidget = QTreeWidget()
        self.experimentsWidget.setHeaderLabels(self.headerLabels)
        self.experimentsWidget.setSelectionMode(QTreeWidget.ExtendedSelection)
        self.experimentsWidget.setRootIsDecorated(False)
        self.experimentsWidget.setSortingEnabled(True)

        contextEventFilter = gui.VisibleHeaderSectionContextEventFilter(
            self.experimentsWidget, self.experimentsWidget)

        self.experimentsWidget.header().installEventFilter(contextEventFilter)
        self.experimentsWidget.setItemDelegateForColumn(
            0, gui.IndicatorItemDelegate(self, role=Qt.DisplayRole))

        self.experimentsWidget.setAlternatingRowColors(True)

        self.experimentsWidget.selectionModel().selectionChanged.connect(
            self.onSelectionChanged)

        self.selectionSetsWidget.setSelectionModel(
            self.experimentsWidget.selectionModel())

        self.mainArea.layout().addWidget(self.experimentsWidget)

        # Restore the selection states from the stored settings
        self.selectionSetsWidget.selections = self.storedSelections
        self.columnsSortingWidget.sortingOrder = self.storedSortingOrder

        self.restoreHeaderState()

        self.experimentsWidget.header().geometriesChanged.connect(
            self.saveHeaderState)

        self.dbc = None

        self.AuthSet()

        QTimer.singleShot(100, self.UpdateExperiments)

    def sizeHint(self):
        return QSize(800, 600)

    def AuthSet(self):
        if len(self.username):
            self.passf.setDisabled(False)
        else:
            self.passf.setDisabled(True)

    def AuthChanged(self):
        self.AuthSet()
        self.ConnectAndUpdate()

    def ConnectAndUpdate(self):
        self.Connect()
        self.UpdateExperiments(reload=True)

    def Connect(self):
        self.error(1)
        self.warning(1)

        def en(x):
            return x if len(x) else None

        self.dbc = dicty.PIPAx(cache=self.buffer,
                               username=en(self.username),
                               password=self.password)

        # check password
        if en(self.username) != None:
            try:
                self.dbc.mappings(reload=True)
            except dicty.AuthenticationError:
                self.error(1, "Wrong username or password")
                self.dbc = None
            except Exception as ex:
                print("Error when contacting the PIPA database", ex)
                sys.excepthook(*sys.exc_info())
                try:  # maybe cached?
                    self.dbc.mappings()
                    self.warning(
                        1, "Can not access database - using cached data.")
                except Exception as ex:
                    self.dbc = None
                    self.error(1, "Can not access database.")

    def Reload(self):
        self.UpdateExperiments(reload=True)

    def clear_cache(self):
        self.buffer.clear()
        self.Reload()

    def rtype(self):
        """Return selected result template type """
        if self.result_types:
            return self.result_types[self.rtypei][0]
        else:
            return "-1"

    def UpdateExperimentTypes(self):
        self.expressionTypesCB.clear()
        items = [desc for _, desc in self.result_types]
        self.expressionTypesCB.addItems(items)
        self.rtypei = max(0, min(self.rtypei, len(self.result_types) - 1))

    def UpdateExperiments(self, reload=False):
        self.experimentsWidget.clear()
        self.items = []

        self.progressBarInit()

        if not self.dbc:
            self.Connect()

        mappings = {}
        result_types = []
        sucind = False  # success indicator for database index

        try:
            mappings = self.dbc.mappings(reload=reload)
            result_types = self.dbc.result_types(reload=reload)
            sucind = True
        except Exception as ex:
            try:
                mappings = self.dbc.mappings()
                result_types = self.dbc.result_types()
                self.warning(0, "Can not access database - using cached data.")
                sucind = True
            except Exception as ex:
                self.error(0, "Can not access database.")

        if sucind:
            self.warning(0)
            self.error(0)

        self.mappings = mappings
        self.result_types = result_types

        self.UpdateExperimentTypes()
        self.UpdateResultsList(reload=reload)

        self.progressBarFinished()

        if self.currentSelection:
            self.currentSelection.select(
                self.experimentsWidget.selectionModel())

        self.handle_commit_button()

    def UpdateResultsList(self, reload=False):

        results_list = {}
        try:
            results_list = self.dbc.results_list(self.rtype(), reload=reload)
        except Exception as ex:
            try:
                results_list = self.dbc.results_list(self.rtype())
            except Exception as ex:
                self.error(0, "Can not access database.")

        self.results_list = results_list
        mappings_key_dict = dict(((m["data_id"], m["id"]), key) \
                                 for key, m in self.mappings.items())

        def mapping_unique_id(annot):
            """Map annotations dict from results_list to unique
            `mappings` ids.
            """
            data_id, mappings_id = annot["data_id"], annot["mappings_id"]
            return mappings_key_dict[data_id, mappings_id]

        elements = []

        # softly change the view so that the selection stays the same

        items_shown = {}
        for i, item in enumerate(self.items):
            c = str(item.text(10))
            items_shown[c] = i

        items_to_show = dict((mapping_unique_id(annot), annot)
                             for annot in self.results_list.values())

        add_items = set(items_to_show) - set(items_shown)
        delete_items = set(items_shown) - set(items_to_show)

        i = 0
        while i < self.experimentsWidget.topLevelItemCount():
            it = self.experimentsWidget.topLevelItem(i)
            if str(it.text(10)) in delete_items:
                self.experimentsWidget.takeTopLevelItem(i)
            else:
                i += 1

        delete_ind = set([items_shown[i] for i in delete_items])
        self.items = [
            it for i, it in enumerate(self.items) if i not in delete_ind
        ]

        for r_annot in [items_to_show[i] for i in add_items]:
            d = defaultdict(lambda: "?", r_annot)
            row_items = [""] + [d.get(key, "?") for key, _ in HEADER[1:]]
            try:
                time_dict = literal_eval(row_items[DATE_INDEX])
                date_rna = date(
                    time_dict["fullYearUTC"],
                    time_dict["monthUTC"] + 1,  # Why is month 0 based?
                    time_dict["dateUTC"])
                row_items[DATE_INDEX] = date_rna.strftime("%x")
            except Exception:
                row_items[DATE_INDEX] = ''

            row_items[ID_INDEX] = mapping_unique_id(r_annot)
            elements.append(row_items)

            ci = MyTreeWidgetItem(self.experimentsWidget, row_items)

            self.items.append(ci)

        for i in range(len(self.headerLabels)):
            self.experimentsWidget.resizeColumnToContents(i)

        # which is the ok buffer version
        # FIXME: what attribute to use for version?
        self.wantbufver = \
            lambda x, ad=self.results_list: \
            defaultdict(lambda: "?", ad[x])["date"]

        self.wantbufver = lambda x: "0"

        self.UpdateCached()

    def UpdateCached(self):
        if self.wantbufver and self.dbc:
            fn = self.dbc.download_key_function()
            result_id_key = dict(((m["data_id"], m["mappings_id"]), key) \
                                 for key, m in self.results_list.items())

            for item in self.items:
                c = str(item.text(10))
                mapping = self.mappings[c]
                data_id, mappings_id = mapping["data_id"], mapping["id"]
                r_id = result_id_key[data_id, mappings_id]
                # Get the buffered version
                buffered = self.dbc.inBuffer(fn(r_id))
                value = " " if buffered == self.wantbufver(r_id) else ""
                item.setData(0, Qt.DisplayRole, value)

    def SearchUpdate(self, string=""):
        for item in self.items:
            item.setHidden(not all(s in item \
                                   for s in self.searchString.split())
                           )

    def Commit(self):
        if not self.dbc:
            self.Connect()

        pb = gui.ProgressBar(self, iterations=100)

        table = None

        ids = []
        for item in self.experimentsWidget.selectedItems():
            unique_id = str(item.text(10))
            annots = self.mappings[unique_id]
            ids.append((annots["data_id"], annots["id"]))

        transfn = None
        if self.log2:
            transfn = lambda x: math.log(x + 1.0, 2)

        reverse_header_dict = dict((name, key) for key, name in HEADER)

        hview = self.experimentsWidget.header()
        shownHeaders = [label for i, label in \
                        list(enumerate(self.headerLabels))[1:] \
                        if not hview.isSectionHidden(i)
                        ]

        allowed_labels = [reverse_header_dict.get(label, label) \
                          for label in shownHeaders]

        if self.joinreplicates and "id" not in allowed_labels:
            # need 'id' labels in join_replicates for attribute names
            allowed_labels.append("id")

        if len(ids):
            table = self.dbc.get_data(
                ids=ids,
                result_type=self.rtype(),
                callback=pb.advance,
                exclude_constant_labels=self.excludeconstant,
                #                          bufver=self.wantbufver,
                transform=transfn,
                allowed_labels=allowed_labels)

            if self.joinreplicates:
                table = dicty.join_replicates(table,
                                              ignorenames=[
                                                  "replicate", "data_id",
                                                  "mappings_id", "data_name",
                                                  "id", "unique_id"
                                              ],
                                              namefn=None,
                                              avg=dicty.median)

            # Sort attributes
            sortOrder = self.columnsSortingWidget.sortingOrder

            all_values = defaultdict(set)
            for at in table.domain.attributes:
                atts = at.attributes
                for name in sortOrder:
                    all_values[name].add(
                        atts.get(reverse_header_dict[name], ""))

            isnum = {}
            for at, vals in all_values.items():
                vals = filter(None, vals)
                try:
                    for a in vals:
                        float(a)
                    isnum[at] = True
                except:
                    isnum[at] = False

            def optfloat(x, at):
                if x == "":
                    return ""
                else:
                    return float(x) if isnum[at] else x

            def sorting_key(attr):
                atts = attr.attributes
                return tuple([optfloat(atts.get(reverse_header_dict[name], ""), name) \
                              for name in sortOrder])

            attributes = sorted(table.domain.attributes, key=sorting_key)

            domain = Orange.data.Domain(attributes, table.domain.class_var,
                                        table.domain.metas)
            table = table.from_table(domain, table)

            data_hints.set_hint(table, "taxid", "352472")
            data_hints.set_hint(table, "genesinrows", False)

            self.send("Data", table)

            self.UpdateCached()

        pb.finish()

    def onSelectionChanged(self, selected, deselected):
        self.handle_commit_button()

    def handle_commit_button(self):
        self.currentSelection = \
            SelectionByKey(self.experimentsWidget.selectionModel().selection(),
                           key=(1, 2, 3, 10))
        self.commit_button.setDisabled(not len(self.currentSelection))

    def saveHeaderState(self):
        hview = self.experimentsWidget.header()
        for i, label in enumerate(self.headerLabels):
            self.experimentsHeaderState[label] = hview.isSectionHidden(i)

    def restoreHeaderState(self):
        hview = self.experimentsWidget.header()
        state = self.experimentsHeaderState
        for i, label in enumerate(self.headerLabels):
            hview.setSectionHidden(i, state.get(label, True))
            self.experimentsWidget.resizeColumnToContents(i)
コード例 #20
0
class PluginsDialog( QDialog ):
    " Codimension plugins dialog "

    def __init__( self, pluginManager, parent = None ):
        QDialog.__init__( self, parent )
        self.setWindowTitle( "Plugin Manager" )

        self.__pluginManager = pluginManager
        self.__configFuncs = {} # int -> callable

        self.__createLayout()
        self.__populate()

        self.__pluginsView.setFocus()
        self.__inItemChange = False
        return

    def __createLayout( self ):
        " Creates the dialog layout "
        self.resize( 640, 480 )
        self.setSizeGripEnabled( True )

        layout = QVBoxLayout()

        # Plugins list
        self.__pluginsView = QTreeWidget()
        self.__pluginsView.setAlternatingRowColors( True )
        self.__pluginsView.setRootIsDecorated( False )
        self.__pluginsView.setItemsExpandable( False )
        self.__pluginsView.setSortingEnabled( True )
        self.__pluginsView.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.__pluginsView.setUniformRowHeights( True )

        # Alert | system/user | Enable | Name | Version
        self.__pluginsHeader = QTreeWidgetItem( [ "", "", "", "Name", "Version", "" ] )
        self.__pluginsView.setHeaderItem( self.__pluginsHeader )
        self.__pluginsView.header().setSortIndicator( NAME_COL, Qt.AscendingOrder )
        self.connect( self.__pluginsView,
                      SIGNAL( "itemSelectionChanged()" ),
                      self.__pluginSelectionChanged )
        self.connect( self.__pluginsView,
                      SIGNAL( "itemChanged(QTreeWidgetItem*,int)" ),
                      self.__onItemChanged )

        layout.addWidget( self.__pluginsView )

        # Detailed information
        detailsLabel = QLabel( "Detailed information" )
        layout.addWidget( detailsLabel )
        self.__details = QTreeWidget()
        self.__details.setAlternatingRowColors( False )
        self.__details.setRootIsDecorated( False )
        self.__details.setItemsExpandable( False )
        self.__details.setSortingEnabled( False )
        self.__details.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.__details.setUniformRowHeights( True )

        detailsHeader = QTreeWidgetItem( [ "", "" ] )
        self.__details.setHeaderItem( detailsHeader )
        self.__details.setHeaderHidden( True )

        metrics = QFontMetrics( self.__details.font() )
        rect = metrics.boundingRect( "X" )
        self.__details.setFixedHeight( rect.height() * 6 + 5 )
        layout.addWidget( self.__details )

        # Errors/warnings
        errorsLabel = QLabel( "Errors / warnings" )
        layout.addWidget( errorsLabel )
        self.__errorsText = QTextEdit()
        self.__errorsText.setReadOnly( True )
        self.__errorsText.setAcceptRichText( False )
        metrics = QFontMetrics( self.__errorsText.font() )
        rect = metrics.boundingRect( "X" )
        self.__errorsText.setFixedHeight( rect.height() * 4 + 5 )
        layout.addWidget( self.__errorsText )

        # Buttons box
        buttonBox = QDialogButtonBox( self )
        buttonBox.setOrientation( Qt.Horizontal )
        buttonBox.setStandardButtons( QDialogButtonBox.Ok )
        self.__OKButton = buttonBox.button( QDialogButtonBox.Ok )
        self.__OKButton.setDefault( True )
        self.connect( buttonBox, SIGNAL( "accepted()" ), self.close )
        self.connect( buttonBox, SIGNAL( "rejected()" ), self.close )
        layout.addWidget( buttonBox )

        self.setLayout( layout )
        return

    def __createConfigButton( self ):
        " Creates a configure button for a plugin "
        button = SettingsButton()
        self.connect( button, SIGNAL( 'CustomClick' ), self.onPluginSettings )
        return button

    def __populate( self ):
        " Populates the list with the plugins "
        index = 0

        for category in self.__pluginManager.activePlugins:
            for cdmPlugin in self.__pluginManager.activePlugins[ category ]:
                newItem = PluginItem( self.__pluginManager, cdmPlugin, True, category )
                self.__pluginsView.addTopLevelItem( newItem )
                settingsButton = self.__createConfigButton()

                try:
                    configFunction = cdmPlugin.getObject().getConfigFunction()
                    if configFunction is None:
                        settingsButton.setToolTip( "Plugin does not need configuring" )
                        settingsButton.setEnabled( False )
                    else:
                        settingsButton.setToolTip( "Click to configure" )
                        settingsButton.setEnabled( True )
                        self.__configFuncs[ index ] = configFunction
                        settingsButton.index = index
                        index += 1
                except Exception:
                    settingsButton.setToolTip( "Bad plugin interface. No "
                                               "configuration function received." )
                    settingsButton.setEnabled( False )

                self.__pluginsView.setItemWidget( newItem, SETTINGS_COL, settingsButton )

        for category in self.__pluginManager.inactivePlugins:
            for cdmPlugin in self.__pluginManager.inactivePlugins[ category ]:
                newItem = PluginItem( self.__pluginManager, cdmPlugin, False, category )
                self.__pluginsView.addTopLevelItem( newItem )
                settingsButton = self.__createConfigButton()

                try:
                    configFunction = cdmPlugin.getObject().getConfigFunction()
                    if configFunction is None:
                        settingsButton.setToolTip( "Plugin does not need configuring" )
                        settingsButton.setEnabled( False )
                    else:
                        settingsButton.setToolTip( "Enable plugin and then click to configure" )
                        settingsButton.setEnabled( False )
                        self.__configFuncs[ index ] = configFunction
                        settingsButton.index = index
                        index += 1
                except:
                    settingsButton.setToolTip( "Bad plugin interface. No "
                                               "configuration function received." )
                    settingsButton.setEnabled( False )

                self.__pluginsView.setItemWidget( newItem, SETTINGS_COL, settingsButton )

        for cdmPlugin in self.__pluginManager.unknownPlugins:
            newItem = PluginItem( self.__pluginManager, cdmPlugin, False, None )
            self.__pluginsView.addTopLevelItem( newItem )
            settingsButton = self.__createConfigButton()
            settingsButton.setToolTip( "Unknown plugins are not configurable" )
            settingsButton.setEnabled( False )
            self.__pluginsView.setItemWidget( newItem, SETTINGS_COL, settingsButton )

        self.__sortPlugins()
        self.__resizePlugins()
        return


    def __sortPlugins( self ):
        " Sorts the plugins table "
        self.__pluginsView.sortItems(
                    self.__pluginsView.sortColumn(),
                    self.__pluginsView.header().sortIndicatorOrder() )
        return

    def __resizePlugins( self ):
        " Resizes the plugins table "
        self.__pluginsView.header().setStretchLastSection( False )
        self.__pluginsView.header().resizeSections(
                                        QHeaderView.ResizeToContents )
        self.__pluginsView.header().resizeSection( STATE_COL, 28 )
        self.__pluginsView.header().setResizeMode( STATE_COL, QHeaderView.Fixed )
        self.__pluginsView.header().resizeSection( CONFLICT_COL, 28 )
        self.__pluginsView.header().setResizeMode( CONFLICT_COL, QHeaderView.Fixed )
        self.__pluginsView.header().resizeSection( TYPE_COL, 28 )
        self.__pluginsView.header().setResizeMode( TYPE_COL, QHeaderView.Fixed )

        self.__pluginsView.header().setResizeMode( VERSION_COL, QHeaderView.Stretch )
        self.__pluginsView.header().resizeSection( SETTINGS_COL, 24 )
        self.__pluginsView.header().setResizeMode( SETTINGS_COL, QHeaderView.Fixed )
        return

    def __pluginSelectionChanged( self ):
        " Triggered when an item is selected "
        selected = list( self.__pluginsView.selectedItems() )
        if selected:
            self.__updateDetails( selected[ 0 ] )
        else:
            self.__updateDetails( None )
        return

    def __updateDetails( self, item ):
        " Updates the content of the details and the error boxes "
        self.__details.clear()
        self.__errorsText.setText( "" )

        if item is None:
            return

        self.__details.addTopLevelItem(
                    QTreeWidgetItem( [ "Author", item.plugin.getAuthor() ] ) )
        self.__details.addTopLevelItem(
                    QTreeWidgetItem( [ "Path", os.path.normpath( item.plugin.getPath() ) ] ) )
        self.__details.addTopLevelItem(
                    QTreeWidgetItem( [ "Description", item.plugin.getDescription() ] ) )
        self.__details.addTopLevelItem(
                    QTreeWidgetItem( [ "Web site", item.plugin.getWebsite() ] ) )

        copyright = item.plugin.getCopyright()
        if copyright is not None:
            if copyright.lower() != "unknown":
                self.__details.addTopLevelItem(
                    QTreeWidgetItem( [ "Copyright", copyright ] ) )

        for name in item.plugin.getDetails():
            value = item.plugin.getDetails()[ name ]
            self.__details.addTopLevelItem( QTreeWidgetItem( [ name, value ] ) )

        self.__errorsText.setText( item.plugin.conflictMessage )
        return

    def __onItemChanged( self, item, column ):
        " Triggered when an item is changed "

        if self.__inItemChange:
            return

        if item.active:
            self.__inItemChange = True
            item.plugin.disable()
            item.active = False

            settingsButton = self.__pluginsView.itemWidget( item, SETTINGS_COL )
            settingsButton.setEnabled( False )
            if settingsButton.index != -1:
                settingsButton.setToolTip( "Enable plugin and then click to configure" )

            if item.category in self.__pluginManager.inactivePlugins:
                self.__pluginManager.inactivePlugins[ item.category ].append( item.plugin )
            else:
                self.__pluginManager.inactivePlugins[ item.category ] = [ item.plugin ]
            self.__pluginManager.activePlugins[ item.category ].remove( item.plugin )
            self.__pluginManager.saveDisabledPlugins()
            self.__inItemChange = False
            self.__pluginManager.sendPluginDeactivated( item.plugin )
            return

        self.__inItemChange = True
        message = self.__pluginManager.checkConflict( item.plugin )
        if message is not None:
            item.setCheckState( STATE_COL, Qt.Unchecked )
            self.__errorsText.setText( message )
            self.__inItemChange = False
            return

        try:
            item.plugin.enable()
            item.active = True
            if item.category in self.__pluginManager.activePlugins:
                self.__pluginManager.activePlugins[ item.category ].append( item.plugin )
            else:
                self.__pluginManager.activePlugins[ item.category ] = [ item.plugin ]
            self.__pluginManager.inactivePlugins[ item.category ].remove( item.plugin )
            self.__pluginManager.saveDisabledPlugins()
            self.__errorsText.setText( "" )
            item.setIcon( CONFLICT_COL, PixmapCache().getIcon( 'empty.png' ) )
            item.setToolTip( CONFLICT_COL, "" )

            settingsButton = self.__pluginsView.itemWidget( item, SETTINGS_COL )
            if settingsButton.index != -1:
                settingsButton.setToolTip( "Click to configure" )
                settingsButton.setEnabled( True )
            self.__pluginManager.sendPluginActivated( item.plugin )
        except:
            item.setCheckState( STATE_COL, Qt.Unchecked )
            self.__errorsText.setText( "Error activating the plugin - exception is generated" )

        self.__inItemChange = False
        return

    def onPluginSettings( self, index ):
        " Triggered when a configuring function is called "
        if index not in self.__configFuncs:
            return

        try:
            self.__configFuncs[ index ]()
        except Exception, exc:
            logging.error( "Error calling the plugin configuration function. "
                           "Message: " + str( exc ) )
        return
コード例 #21
0
class DBDatabasesWidget(QWidget):
    """Displays a list of Databases"""

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

        self.debug = False
        
        self.db = None
        
        self.setWindowTitle("Databases")
        #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)

        
        self.mainLayout = QVBoxLayout()
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self.setLayout(self.mainLayout)

        #=============================================
        ## Top Toolbar
        topBar = QToolBar()
        topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.mainLayout.addWidget(topBar)
        
        ## Add the action buttons
        topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add)
        self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit), "Edit", self.on_server_edit)
        self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete), "Delete", self.on_server_delete)
        
        #=============================================
        ## Tree
        self.tree = QTreeWidget()
        self.mainLayout.addWidget(self.tree)
        self.tree.setHeaderLabels(["Server", "User", ""])
        self.tree.setUniformRowHeights(True)
        self.tree.setRootIsDecorated(False)
        self.tree.setColumnWidth(C.widget, 20)
        
        
        self.connect( self.tree, SIGNAL( 'itemSelectionChanged()' ), self.on_tree_selection_changed )
        self.connect( self.tree, SIGNAL( 'itemDoubleClicked (QTreeWidgetItem *,int)' ), self.on_tree_double_clicked )
    
        self.buttGroup = QButtonGroup(self)
        self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"), self.on_open_server)
    
        self.on_tree_selection_changed()
    
    
        self.load_servers()
        
    #=======================================
    ##== Tree Events
    def on_tree_selection_changed(self):
        
        disabled = self.tree.selectionModel().hasSelection() == False
        self.actionServerEdit.setDisabled(disabled)
        self.actionServerDelete.setDisabled(disabled)
        
    def on_tree_double_clicked(self):
        self.actionServerEdit.trigger()


    
    #=======================================
    ## Server Actions
    def on_server_add(self):
        self.show_server_dialog(None)
        
    def on_server_edit(self):
        item = self.tree.currentItem()
        if item == None:
            return
        server = str(item.text(C.server))
        self.show_server_dialog(server)
    
    def show_server_dialog(self, server=None):
        d = DBServerDialog.DBServerDialog(self, server)
        if d.exec_():
            self.load_servers()
       
       
    def on_open_server(self, butt):
        self.emit(SIGNAL("open_server"), butt.property("server").toString())
              
             
    
    def load_servers(self):
        """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """
        
        self.tree.clear()
        
        for butt in self.buttGroup.buttons():
            self.buttGroup.removeButton(butt)
        
        for srv in G.settings.get_servers_list():
            
            item = QTreeWidgetItem()
            item.setText(C.server, srv['server'])
            item.setText(C.user, srv['user'])
            self.tree.addTopLevelItem(item)
            
            butt = QToolButton()
            butt.setIcon(Ico.icon(Ico.Connect))
            butt.setProperty("server", srv['server'])
            self.tree.setItemWidget(item, C.widget, butt)
            self.buttGroup.addButton(butt)
        
        
    def on_server_delete(self):
        item = self.tree.currentItem()
        if item == None:
            return
        srv = str(item.text(C.server))
        G.settings.delete_server(srv)
        self.load_servers()
        
コード例 #22
0
ファイル: OWGenExpress.py プロジェクト: r0b1n1983liu/o3env
class OWGenExpress(widget.OWWidget):
    name = "GenExpress"
    description = "Expression data from GenExpress."
    icon = "../widgets/icons/GenCloud.svg"
    priority = 36

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

    username = settings.Setting("anonymous")
    password = settings.Setting("")
    log2 = settings.Setting(False)
    transpose = settings.Setting(False)
    rtypei = settings.Setting(0)
    projecti = settings.Setting(0)
    serveri = settings.Setting(0)
    exnamei = settings.Setting(6)

    excludeconstant = settings.Setting(False)
    joinreplicates = settings.Setting(False)
    currentSelection = settings.Setting(None)

    experimentsHeaderState = settings.Setting({
        name: False for _, name in HEADER[:ID_INDEX + 1]}
    )

    storedSortOrder = settings.Setting([])
    storedSelections = settings.Setting([])

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

        self.servers = [
            ('https://dictyexpress.research.bcm.edu/', 'dictyExpress'),
            ('https://cloud.genialis.com/', 'Genialis'),
        ]

        self.selectedExperiments = []
        self.buffer = dicty.CacheSQLite(bufferfile)

        self.searchString = ""

        self.items = []

        self.result_types = []

        self.controlArea.setMaximumWidth(250)
        self.controlArea.setMinimumWidth(250)

        box = gui.widgetBox(self.controlArea, 'Project')
        self.projectCB = gui.comboBox(
            box, self, "projecti", items=[], callback=self.ProjectChosen)

        self.projects = []

        b = gui.widgetBox(self.controlArea, "Selection bookmarks")
        self.selectionSetsWidget = SelectionSetsWidget(self)
        self.selectionSetsWidget.setSizePolicy(
            QSizePolicy.Preferred, QSizePolicy.Maximum)

        def store_selections(modified):
            if not modified:
                self.storedSelections = self.selectionSetsWidget.selections
        self.selectionSetsWidget.selectionModified.connect(store_selections)

        b.layout().addWidget(self.selectionSetsWidget)

        gui.separator(self.controlArea)

        b = gui.widgetBox(self.controlArea, "Sort output columns")
        self.columnsSortingWidget = SortedListWidget(self)
        self.columnsSortingWidget.setSizePolicy(
            QSizePolicy.Preferred, QSizePolicy.Maximum)

        box = gui.widgetBox(self.controlArea, 'Experiment name')
        self.experimentNameCB = gui.comboBox(
            box, self, "exnamei", items=SORTING_MODEL_LIST)

        b.layout().addWidget(self.columnsSortingWidget)
        sorting_model = QStringListModel(SORTING_MODEL_LIST)
        self.columnsSortingWidget.setModel(sorting_model)
        self.columnsSortingWidget.sortingOrder = self.storedSortOrder

        def store_sort_order():
            self.storedSortOrder = self.columnsSortingWidget.sortingOrder
        self.columnsSortingWidget.sortingOrderChanged.connect(store_sort_order)

        gui.separator(self.controlArea)


        box = gui.widgetBox(self.controlArea, 'Expression Type')
        self.expressionTypesCB = gui.comboBox(
            box, self, "rtypei", items=[], callback=self.UpdateResultsList)

        gui.checkBox(self.controlArea, self, "excludeconstant",
                     "Exclude labels with constant values")

        gui.checkBox(self.controlArea, self, "joinreplicates",
                     "Average replicates (use median)")

        gui.checkBox(self.controlArea, self, "log2",
                     "Logarithmic (base 2) transformation")

        gui.checkBox(self.controlArea, self, "transpose",
                     "Genes as attributes")

        self.commit_button = gui.button(self.controlArea, self, "&Commit",
                                        callback=self.Commit)
        self.commit_button.setDisabled(True)

        gui.rubber(self.controlArea)

        box = gui.widgetBox(self.controlArea, 'Server')
        gui.comboBox(box, self, "serveri",
                     items=[title for url, title in self.servers],
                     callback=self.ServerChosen)

        gui.lineEdit(box, self, "username", "Username:"******"password", "Password:"******"Clear cache",
                   callback=self.clear_cache)

        gui.lineEdit(self.mainArea, self, "searchString", "Search",
                     callbackOnType=True,
                     callback=self.SearchUpdate)

        self.headerLabels = [t[1] for t in HEADER]

        self.experimentsWidget = QTreeWidget()
        self.experimentsWidget.setHeaderLabels(self.headerLabels)
        self.experimentsWidget.setSelectionMode(QTreeWidget.ExtendedSelection)
        self.experimentsWidget.setRootIsDecorated(False)
        self.experimentsWidget.setSortingEnabled(True)

        contextEventFilter = gui.VisibleHeaderSectionContextEventFilter(
            self.experimentsWidget, self.experimentsWidget)

        self.experimentsWidget.header().installEventFilter(contextEventFilter)
        self.experimentsWidget.setItemDelegateForColumn(
            0, gui.IndicatorItemDelegate(self, role=Qt.DisplayRole))

        self.experimentsWidget.setAlternatingRowColors(True)

        self.experimentsWidget.selectionModel().selectionChanged.connect(
            self.onSelectionChanged)

        self.selectionSetsWidget.setSelectionModel(
            self.experimentsWidget.selectionModel())
        self.selectionSetsWidget.setSelections(self.storedSelections)

        self.mainArea.layout().addWidget(self.experimentsWidget)

        self.restoreHeaderState()

        self.experimentsWidget.header().geometriesChanged.connect(
            self.saveHeaderState)

        self.dbc = None

        self.AuthSet()

        QTimer.singleShot(100, self.ConnectAndUpdate)

    def sizeHint(self):
        return QSize(800, 600)

    def AuthSet(self):
        if len(self.username):
            self.passf.setDisabled(False)
        else:
            self.passf.setDisabled(True)

    def AuthChanged(self):
        self.AuthSet()
        self.ConnectAndUpdate()

    def ConnectAndUpdate(self):
        self.Connect()
        if self.dbc:
            def get_data_count(project_id):
                # XXX: is there a better way?
                # Note: limit 0 would return all objects
                return self.dbc.gen.api.data.get(case_ids__contains=project_id,
                                                 type__startswith='data:expression:',
                                                 limit=1)['meta']['total_count']

            self.projects = sorted([p for p in self.dbc.projects().items() if
                                    get_data_count(p[0]) > 0], key=lambda x: x[1])
            self.UpdateProjects()
            self.ProjectChosen()
            self.UpdateExperimentTypes()

    def Connect(self):
        self.error(1)
        self.warning(1)

        username = '******'
        password = '******'
        url = self.servers[self.serveri][0]

        if self.username:
            username = self.username
            password = self.password

        if username.lower() in ['*****@*****.**', 'anonymous']:
            username = '******'
            password = '******'

        self.dbc = None
        self.projects = []
        self.result_types = []

        try:
            self.dbc = Genesis(
                address=url, username=username, password=password,
                cache=self.buffer)
        except requests.exceptions.ConnectionError:
            self.dbc = Genesis(
                address=url, username=username, password=password,
                connect=False, cache=self.buffer)
            self.warning(1, "Could not connect to server, working from cache.")
        except Exception:
            self.error(1, "Wrong username or password.")

        self.UpdateProjects()
        self.UpdateExperimentTypes()  # clear lists

    def Reload(self):
        self.UpdateExperiments(reload=True)

    def clear_cache(self):
        self.buffer.clear()
        self.Reload()

    def rtype(self):
        """Return selected result template type """
        if self.result_types:
            return self.result_types[self.rtypei]
        else:
            return None

    def UpdateExperimentTypes(self):
        self.expressionTypesCB.clear()
        items = [self.result_types_labels[desc] for desc in self.result_types]
        self.expressionTypesCB.addItems(items)
        #do not update anything if the list is empty
        if len(self.result_types):
            self.rtypei = max(0, min(self.rtypei, len(self.result_types) - 1))

    def UpdateProjects(self):
        self.projectCB.clear()
        items = [desc for pid, desc in self.projects]
        self.projectCB.addItems(items)
        #do not update anything if the list if empty
        if len(self.projects) > 0:
            self.projecti = max(0, min(self.projecti, len(self.projects) - 1))

    def UpdateExperiments(self, reload=False):

        self.experimentsWidget.clear()

        if not self.dbc or not self.dbc.projectid:  # the connection did not succeed
            return

        self.items = []

        self.progressBarInit()

        result_types = []
        result_types_labels = []

        sucind = False  # success indicator for database index

        try:
            result_types, result_types_labels = self.dbc.result_types(reload=reload)
            sucind = True
        except Exception:
            try:
                result_types, result_types_labels = self.dbc.result_types()
                self.warning(0, "Can not access database - using cached data.")
                sucind = True
            except Exception:
                self.error(0, "Can not access database.")

        if sucind:
            self.warning(0)
            self.error(0)

        self.result_types = result_types
        self.result_types_labels = result_types_labels

        self.UpdateExperimentTypes()
        self.UpdateResultsList(reload=reload)

        self.progressBarFinished()

        if self.currentSelection:
            self.currentSelection.select(self.experimentsWidget.selectionModel())

        self.handle_commit_button()

    def ProjectChosen(self, reload=False):
        if self.projects:
            self.dbc.projectid = self.projects[self.projecti][0]
        else:
            self.dbc.projectid = None

        self.UpdateExperiments(reload=reload)

    def ServerChosen(self):
        self.ConnectAndUpdate()

    def UpdateResultsList(self, reload=False):
        results_list = self.dbc.results_list(self.rtype(), reload=reload)
        try:
            results_list = self.dbc.results_list(self.rtype(), reload=reload)
        except Exception:
            try:
                results_list = self.dbc.results_list(self.rtype())
            except Exception:
                self.error(0, "Can not access database.")

        self.results_list = results_list

        #softly change the view so that the selection stays the same

        items_shown = {}
        for i, item in enumerate(self.items):
            c = str(item.text(ID_INDEX))
            items_shown[c] = i

        items_to_show = set(id_ for id_ in self.results_list)

        add_items = set(items_to_show) - set(items_shown)
        delete_items = set(items_shown) - set(items_to_show)

        i = 0
        while i < self.experimentsWidget.topLevelItemCount():
            it = self.experimentsWidget.topLevelItem(i)
            if str(it.text(ID_INDEX)) in delete_items:
                self.experimentsWidget.takeTopLevelItem(i)
            else:
                i += 1

        delete_ind = set([items_shown[i] for i in delete_items])
        self.items = [it for i, it in enumerate(self.items)
                      if i not in delete_ind]

        for r_annot in add_items:
            d = defaultdict(lambda: "?", self.results_list[r_annot])
            row_items = [""] + [to_text(d.get(key, "?"))
                                for key, _ in HEADER[1:]]
            row_items[ID_INDEX] = r_annot

            ci = MyTreeWidgetItem(self.experimentsWidget, row_items)
            self.items.append(ci)

        for i in range(len(self.headerLabels)):
            self.experimentsWidget.resizeColumnToContents(i)

        self.wantbufver = lambda x: self.results_list[x]["date_modified"]

        self.UpdateCached()

    def UpdateCached(self):
        if self.wantbufver and self.dbc:

            for item in self.items:
                id = str(item.text(ID_INDEX))
                version = self.dbc._in_buffer(id + "|||" + self.rtype())
                value = " " if version == self.wantbufver(id) else ""
                item.setData(0, Qt.DisplayRole, value)

    def SearchUpdate(self, string=""):
        for item in self.items:
            item.setHidden(
                not all(s in item for s in self.searchString.split()))

    def Commit(self):

        pb = gui.ProgressBar(self, iterations=100)

        table = None

        ids = []
        for item in self.experimentsWidget.selectedItems():
            unique_id = str(item.text(ID_INDEX))
            ids.append(unique_id)

        transfn = None
        if self.log2:
            transfn = lambda x: math.log(x + 1.0, 2)

        reverse_header_dict = {name: name for key, name in HEADER}
        reverse_header_dict["ID"] = "id"

        allowed_labels = None

        def namefn(a):
            name = SORTING_MODEL_LIST[self.exnamei]
            name = reverse_header_dict.get(name, "id")
            return dict(a)[name]

        if len(ids):
            table = self.dbc.get_data(
                ids=ids, result_type=self.rtype(),
                callback=pb.advance,
                exclude_constant_labels=self.excludeconstant,
                bufver=self.wantbufver,
                transform=transfn,
                allowed_labels=allowed_labels,
                namefn=namefn)

            if self.joinreplicates:
                table = dicty.join_replicates(table,
                    ignorenames=self.dbc.IGNORE_REPLICATE,
                    namefn="name",
                    avg=dicty.median,
                    fnshow=lambda x: " | ".join(map(str, x)))

            # Sort attributes
            sortOrder = self.columnsSortingWidget.sortingOrder

            all_values = defaultdict(set)
            for at in table.domain.attributes:
                atts = at.attributes
                for name in sortOrder:
                    all_values[name].add(atts.get(reverse_header_dict[name], ""))

            isnum = {}
            for at, vals in all_values.items():
                vals = filter(None, vals)
                try:
                    for a in vals:
                        float(a)
                    isnum[at] = True
                except ValueError:
                    isnum[at] = False

            def optfloat(x, at):
                if x == "":
                    return ""
                else:
                    return float(x) if isnum[at] else x

            def sorting_key(attr):
                atts = attr.attributes
                return tuple([optfloat(atts.get(reverse_header_dict[name], ""), name)
                              for name in sortOrder])

            attributes = sorted(table.domain.attributes, key=sorting_key)

            domain = Orange.data.Domain(
                attributes, table.domain.class_vars, table.domain.metas)

            table = Orange.data.Table.from_table(domain, table)
            table = Orange.data.Table(domain, table)

            if self.transpose:
                experiments = [at for at in table.domain.variables]
                attr = [compat.ContinuousVariable.make(ex['DDB'].value) for ex in table]
                metavars = sorted(table.domain.variables[0].attributes.keys())
                metavars = [compat.StringVariable.make(name) for name in metavars]
                domain = compat.create_domain(attr, None, metavars)
                metavars = compat.get_metas(domain)
                metas = [[exp.attributes[var.name] for var in metavars] for exp in experiments]
                table = compat.create_table(domain, table.X.transpose(), None, metas)

            data_hints.set_hint(table, "taxid", "352472")
            data_hints.set_hint(table, "genesinrows", False)

            self.send("Data", table)

            self.UpdateCached()

        pb.finish()

    def onSelectionChanged(self, selected, deselected):
        self.handle_commit_button()

    def handle_commit_button(self):
        self.currentSelection = \
            SelectionByKey(self.experimentsWidget.selectionModel().selection(),
                           key=(ID_INDEX,))
        self.commit_button.setDisabled(not len(self.currentSelection))

    def saveHeaderState(self):
        hview = self.experimentsWidget.header()
        for i, label in enumerate(self.headerLabels):
            self.experimentsHeaderState[label] = hview.isSectionHidden(i)

    def restoreHeaderState(self):
        hview = self.experimentsWidget.header()
        state = self.experimentsHeaderState
        for i, label in enumerate(self.headerLabels):
            hview.setSectionHidden(i, state.get(label, True))
            self.experimentsWidget.resizeColumnToContents(i)
コード例 #23
0
ファイル: yarascanTreeView.py プロジェクト: ulisesrc/yavol
class yarascanTreeView():

    def __init__(self, data):
        self.treeWidget = QTreeWidget()
        self.data = data
        self.detections = DetectionContainer()
        self.initialLoad()


    def initialLoad(self):
        for detection in self.generateDetections():
            self.detections.addDetection(detection)
        self.populateTree()


    def populateTree(self, selectedDetection=None):
        selected = None
        self.treeWidget.clear()
        self.treeWidget.setColumnCount(3)
        self.treeWidget.setHeaderLabels(["Rule/Process", "Pid", "Text"])
        self.treeWidget.setItemsExpandable(True)
        parentRule = {}
        parentRuleProcess = {}
        for detection in self.detections:
            ancestor = parentRule.get(detection.rule_name)
            if ancestor is None:
                ancestor = QTreeWidgetItem(self.treeWidget, [detection.rule_name])
                parentRule[detection.rule_name] = ancestor
            process = detection.process
            parent = parentRuleProcess.get(process)
            if parent is None:
                parent = QTreeWidgetItem(ancestor, [process, QString("%L1").arg(detection.pid)])
                parentRuleProcess[process] = parent
                item = QTreeWidgetItem(parent, ['','', detection.text])
                item.setTextAlignment(3, Qt.AlignRight|Qt.AlignVCenter)
            if selectedDetection is not None and selectedDetection == id(detection):
                selected = item
            #self.treeWidget.expandItem(parent)
            self.treeWidget.expandItem(ancestor)
        self.treeWidget.resizeColumnToContents(0)
        self.treeWidget.resizeColumnToContents(1)
        if selected is not None:
            selected.setSelected(True)
            self.treeWidget.setCurrentItem(selected)


    def generateDetections(self):

        for x in range(len(self.data)):
            line = self.data["Owner"][x]
            matchObj = re.match(r'(.*):\s{1,}\(pid\s(\d{1,})', line, re.I)
            #if matchObj:
            #    print "matchObj.group() :", matchObj.group()
            process = matchObj.group(1)
            pid = matchObj.group(2)

            bindata = self.data["Data"][x]
            textB = ''
            for i in range(0, len(bindata), 2):
                if not i%32:
                    textB+="\n"
                else:
                    textB+=chr(int(bindata[i:i+2], 16))

            yield Detection(self.data["Rule"][x], process, pid, textB)
コード例 #24
0
class RecentProjectsViewer(QWidget):
    " Recent projects viewer implementation "

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

        self.__projectContextItem = None
        self.__fileContextItem = None

        self.upper = self.__createRecentFilesLayout()
        self.lower = self.__createRecentProjectsLayout()
        self.__createProjectPopupMenu()
        self.__createFilePopupMenu()

        layout = QVBoxLayout()
        layout.setContentsMargins(1, 1, 1, 1)
        splitter = QSplitter(Qt.Vertical)
        splitter.addWidget(self.upper)
        splitter.addWidget(self.lower)
        splitter.setCollapsible(0, False)
        splitter.setCollapsible(1, False)

        layout.addWidget(splitter)
        self.setLayout(layout)

        self.__populateProjects()
        self.__populateFiles()
        self.__updateProjectToolbarButtons()
        self.__updateFileToolbarButtons()

        # Debugging mode support
        self.__debugMode = False
        parent.debugModeChanged.connect(self.__onDebugMode)
        return

    def setTooltips(self, switchOn):
        " Switches the tooltips mode "
        for index in xrange(0, self.recentFilesView.topLevelItemCount()):
            self.recentFilesView.topLevelItem(index).updateIconAndTooltip()
        for index in xrange(0, self.projectsView.topLevelItemCount()):
            self.projectsView.topLevelItem(index).updateTooltip()
        return

    def __createFilePopupMenu(self):
        " create the recent files popup menu "
        self.__fileMenu = QMenu(self.recentFilesView)
        self.__openMenuItem = self.__fileMenu.addAction(
            getIcon('openitem.png'), 'Open', self.__openFile)
        self.__copyPathFileMenuItem = self.__fileMenu.addAction(
            getIcon('copytoclipboard.png'), 'Copy path to clipboard',
            self.__filePathToClipboard)
        self.__fileMenu.addSeparator()
        self.__delFileMenuItem = self.__fileMenu.addAction(
            getIcon('trash.png'), 'Delete from recent', self.__deleteFile)
        self.recentFilesView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connect(self.recentFilesView,
                     SIGNAL("customContextMenuRequested(const QPoint &)"),
                     self.__handleShowFileContextMenu)

        self.connect(GlobalData().project, SIGNAL('recentFilesChanged'),
                     self.__populateFiles)
        return

    def __createProjectPopupMenu(self):
        " Creates the recent project popup menu "
        self.__projectMenu = QMenu(self.projectsView)
        self.__prjLoadMenuItem = self.__projectMenu.addAction(
            getIcon('load.png'), 'Load', self.__loadProject)
        self.__projectMenu.addSeparator()
        self.__propsMenuItem = self.__projectMenu.addAction(
            getIcon('smalli.png'), 'Properties', self.__viewProperties)
        self.__prjCopyPathMenuItem = self.__projectMenu.addAction(
            getIcon('copytoclipboard.png'), 'Copy path to clipboard',
            self.__prjPathToClipboard)
        self.__projectMenu.addSeparator()
        self.__delPrjMenuItem = self.__projectMenu.addAction(
            getIcon('trash.png'), 'Delete from recent', self.__deleteProject)
        self.projectsView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.connect(self.projectsView,
                     SIGNAL("customContextMenuRequested(const QPoint &)"),
                     self.__handleShowPrjContextMenu)

        Settings().recentListChanged.connect(self.__populateProjects)
        GlobalData().project.projectChanged.connect(self.__projectChanged)
        return

    def __createRecentFilesLayout(self):
        " Creates the upper part - recent files "
        headerFrame = QFrame()
        headerFrame.setFrameStyle(QFrame.StyledPanel)
        headerFrame.setAutoFillBackground(True)
        headerPalette = headerFrame.palette()
        headerBackground = headerPalette.color(QPalette.Background)
        headerBackground.setRgb(min(headerBackground.red() + 30, 255),
                                min(headerBackground.green() + 30, 255),
                                min(headerBackground.blue() + 30, 255))
        headerPalette.setColor(QPalette.Background, headerBackground)
        headerFrame.setPalette(headerPalette)
        headerFrame.setFixedHeight(24)

        recentFilesLabel = QLabel()
        recentFilesLabel.setText("Recent files")

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(3, 0, 0, 0)
        headerLayout.addWidget(recentFilesLabel)
        headerFrame.setLayout(headerLayout)

        self.recentFilesView = QTreeWidget()
        self.recentFilesView.setAlternatingRowColors(True)
        self.recentFilesView.setRootIsDecorated(False)
        self.recentFilesView.setItemsExpandable(False)
        self.recentFilesView.setSortingEnabled(True)
        self.recentFilesView.setItemDelegate(NoOutlineHeightDelegate(4))
        self.recentFilesView.setUniformRowHeights(True)

        self.__filesHeaderItem = QTreeWidgetItem(["", "File", "Absolute path"])
        self.recentFilesView.setHeaderItem(self.__filesHeaderItem)
        self.recentFilesView.header().setSortIndicator(1, Qt.AscendingOrder)

        self.connect(self.recentFilesView, SIGNAL("itemSelectionChanged()"),
                     self.__fileSelectionChanged)
        self.connect(self.recentFilesView,
                     SIGNAL("itemActivated(QTreeWidgetItem *, int)"),
                     self.__fileActivated)

        # Toolbar part - buttons
        self.openFileButton = QAction(getIcon('openitem.png'),
                                      'Open the highlighted file', self)
        self.connect(self.openFileButton, SIGNAL("triggered()"),
                     self.__openFile)
        self.copyFilePathButton = QAction(getIcon('copytoclipboard.png'),
                                          'Copy path to clipboard', self)
        self.connect(self.copyFilePathButton, SIGNAL("triggered()"),
                     self.__filePathToClipboard)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.trashFileButton = QAction(getIcon('delitem.png'),
                                       'Remove selected (not from the disk)',
                                       self)
        self.connect(self.trashFileButton, SIGNAL("triggered()"),
                     self.__deleteFile)

        self.upperToolbar = QToolBar()
        self.upperToolbar.setMovable(False)
        self.upperToolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.upperToolbar.setIconSize(QSize(16, 16))
        self.upperToolbar.setFixedHeight(28)
        self.upperToolbar.setContentsMargins(0, 0, 0, 0)
        self.upperToolbar.addAction(self.openFileButton)
        self.upperToolbar.addAction(self.copyFilePathButton)
        self.upperToolbar.addWidget(spacer)
        self.upperToolbar.addAction(self.trashFileButton)

        recentFilesLayout = QVBoxLayout()
        recentFilesLayout.setContentsMargins(0, 0, 0, 0)
        recentFilesLayout.setSpacing(0)
        recentFilesLayout.addWidget(headerFrame)
        recentFilesLayout.addWidget(self.upperToolbar)
        recentFilesLayout.addWidget(self.recentFilesView)

        upperContainer = QWidget()
        upperContainer.setContentsMargins(0, 0, 0, 0)
        upperContainer.setLayout(recentFilesLayout)
        return upperContainer

    def getRecentFilesToolbar(self):
        " Provides a reference to the recent files toolbar "
        return self.upperToolbar

    def __createRecentProjectsLayout(self):
        " Creates the bottom layout "
        self.headerFrame = QFrame()
        self.headerFrame.setFrameStyle(QFrame.StyledPanel)
        self.headerFrame.setAutoFillBackground(True)
        headerPalette = self.headerFrame.palette()
        headerBackground = headerPalette.color(QPalette.Background)
        headerBackground.setRgb(min(headerBackground.red() + 30, 255),
                                min(headerBackground.green() + 30, 255),
                                min(headerBackground.blue() + 30, 255))
        headerPalette.setColor(QPalette.Background, headerBackground)
        self.headerFrame.setPalette(headerPalette)
        self.headerFrame.setFixedHeight(24)

        recentProjectsLabel = QLabel()
        recentProjectsLabel.setText("Recent projects")

        expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)

        self.__showHideButton = QToolButton()
        self.__showHideButton.setAutoRaise(True)
        self.__showHideButton.setIcon(getIcon('less.png'))
        self.__showHideButton.setFixedSize(20, 20)
        self.__showHideButton.setToolTip("Hide recent projects list")
        self.__showHideButton.setFocusPolicy(Qt.NoFocus)
        self.connect(self.__showHideButton, SIGNAL('clicked()'),
                     self.__onShowHide)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(3, 0, 0, 0)
        headerLayout.addWidget(recentProjectsLabel)
        headerLayout.addSpacerItem(expandingSpacer)
        headerLayout.addWidget(self.__showHideButton)
        self.headerFrame.setLayout(headerLayout)

        # Toolbar part - buttons
        self.loadButton = QAction(getIcon('load.png'),
                                  'Load the highlighted project', self)
        self.connect(self.loadButton, SIGNAL("triggered()"),
                     self.__loadProject)
        self.propertiesButton = QAction(
            getIcon('smalli.png'), 'Show the highlighted project '
            'properties', self)
        self.connect(self.propertiesButton, SIGNAL("triggered()"),
                     self.__viewProperties)
        self.copyPrjPathButton = QAction(getIcon('copytoclipboard.png'),
                                         'Copy path to clipboard', self)
        self.connect(self.copyPrjPathButton, SIGNAL("triggered()"),
                     self.__prjPathToClipboard)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.trashButton = QAction(getIcon('delitem.png'),
                                   'Remove selected (not from the disk)', self)
        self.connect(self.trashButton, SIGNAL("triggered()"),
                     self.__deleteProject)

        self.lowerToolbar = QToolBar()
        self.lowerToolbar.setMovable(False)
        self.lowerToolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.lowerToolbar.setIconSize(QSize(16, 16))
        self.lowerToolbar.setFixedHeight(28)
        self.lowerToolbar.setContentsMargins(0, 0, 0, 0)
        self.lowerToolbar.addAction(self.loadButton)
        self.lowerToolbar.addAction(self.propertiesButton)
        self.lowerToolbar.addAction(self.copyPrjPathButton)
        self.lowerToolbar.addWidget(spacer)
        self.lowerToolbar.addAction(self.trashButton)

        self.projectsView = QTreeWidget()
        self.projectsView.setAlternatingRowColors(True)
        self.projectsView.setRootIsDecorated(False)
        self.projectsView.setItemsExpandable(False)
        self.projectsView.setSortingEnabled(True)
        self.projectsView.setItemDelegate(NoOutlineHeightDelegate(4))
        self.projectsView.setUniformRowHeights(True)

        self.__projectsHeaderItem = QTreeWidgetItem(
            ["", "Project", "Absolute path"])
        self.projectsView.setHeaderItem(self.__projectsHeaderItem)

        self.projectsView.header().setSortIndicator(1, Qt.AscendingOrder)
        self.connect(self.projectsView,
                     SIGNAL("itemActivated(QTreeWidgetItem *, int)"),
                     self.__projectActivated)
        self.connect(self.projectsView, SIGNAL("itemSelectionChanged()"),
                     self.__projectSelectionChanged)

        recentProjectsLayout = QVBoxLayout()
        recentProjectsLayout.setContentsMargins(0, 0, 0, 0)
        recentProjectsLayout.setSpacing(0)
        recentProjectsLayout.addWidget(self.headerFrame)
        recentProjectsLayout.addWidget(self.lowerToolbar)
        recentProjectsLayout.addWidget(self.projectsView)

        lowerContainer = QWidget()
        lowerContainer.setContentsMargins(0, 0, 0, 0)
        lowerContainer.setLayout(recentProjectsLayout)
        return lowerContainer

    def getRecentProjectsToolbar(self):
        " Provides a reference to the projects toolbar "
        return self.lowerToolbar

    def __projectSelectionChanged(self):
        " Handles the projects changed selection "
        selected = list(self.projectsView.selectedItems())

        if selected:
            self.__projectContextItem = selected[0]
        else:
            self.__projectContextItem = None

        self.__updateProjectToolbarButtons()
        return

    def __fileSelectionChanged(self):
        " Handles the files changed selection "
        selected = list(self.recentFilesView.selectedItems())

        if selected:
            self.__fileContextItem = selected[0]
        else:
            self.__fileContextItem = None
        self.__updateFileToolbarButtons()
        return

    def __updateProjectToolbarButtons(self):
        " Updates the toolbar buttons depending on the __projectContextItem "
        if self.__projectContextItem is None:
            self.loadButton.setEnabled(False)
            self.propertiesButton.setEnabled(False)
            self.copyPrjPathButton.setEnabled(False)
            self.trashButton.setEnabled(False)
        else:
            enabled = self.__projectContextItem.isValid()
            isCurrentProject = self.__projectContextItem.isCurrent()

            self.propertiesButton.setEnabled(enabled)
            self.copyPrjPathButton.setEnabled(True)
            self.loadButton.setEnabled(enabled and not isCurrentProject
                                       and not self.__debugMode)
            self.trashButton.setEnabled(not isCurrentProject)
        return

    def __updateFileToolbarButtons(self):
        " Updates the toolbar buttons depending on the __fileContextItem "
        enabled = self.__fileContextItem is not None
        self.openFileButton.setEnabled(enabled)
        self.copyFilePathButton.setEnabled(enabled)
        self.trashFileButton.setEnabled(enabled)
        return

    def __handleShowPrjContextMenu(self, coord):
        " Show the project item context menu "
        self.__projectContextItem = self.projectsView.itemAt(coord)
        if self.__projectContextItem is None:
            return

        enabled = self.__projectContextItem.isValid()
        isCurrentProject = self.__projectContextItem.isCurrent()

        self.__propsMenuItem.setEnabled(enabled)
        self.__delPrjMenuItem.setEnabled(not isCurrentProject)
        #        fName = self.__projectContextItem.getFilename()
        self.__prjLoadMenuItem.setEnabled(enabled and not isCurrentProject
                                          and not self.__debugMode)

        self.__projectMenu.popup(QCursor.pos())
        return

    def __sortProjects(self):
        " Sort the project items "
        self.projectsView.sortItems( \
                self.projectsView.sortColumn(),
                self.projectsView.header().sortIndicatorOrder() )
        return

    def __sortFiles(self):
        " Sort the file items "
        self.recentFilesView.sortItems(
            self.recentFilesView.sortColumn(),
            self.recentFilesView.header().sortIndicatorOrder())
        return

    def __resizeProjectColumns(self):
        """ Resize the projects list columns """
        self.projectsView.header().setStretchLastSection(True)
        self.projectsView.header().resizeSections(QHeaderView.ResizeToContents)
        self.projectsView.header().resizeSection(0, 22)
        self.projectsView.header().setResizeMode(0, QHeaderView.Fixed)
        return

    def __resizeFileColumns(self):
        " Resize the files list columns "
        self.recentFilesView.header().setStretchLastSection(True)
        self.recentFilesView.header().resizeSections(
            QHeaderView.ResizeToContents)
        self.recentFilesView.header().resizeSection(0, 22)
        self.recentFilesView.header().setResizeMode(0, QHeaderView.Fixed)
        return

    def __projectActivated(self, item, column):
        " Handles the double click (or Enter) on the item "
        self.__projectContextItem = item
        self.__loadProject()
        return

    def __fileActivated(self, item, column):
        " Handles the double click (or Enter) on a file item "
        self.__fileContextItem = item
        self.__openFile()
        return

    def __viewProperties(self):
        " Handles the 'view properties' context menu item "
        if self.__projectContextItem is None:
            return
        if not self.__projectContextItem.isValid():
            return

        if self.__projectContextItem.isCurrent():
            # This is the current project - it can be edited
            project = GlobalData().project
            dialog = ProjectPropertiesDialog(project, self)
            if dialog.exec_() == QDialog.Accepted:
                importDirs = []
                for index in xrange(dialog.importDirList.count()):
                    importDirs.append(dialog.importDirList.item(index).text())

                scriptName = dialog.scriptEdit.text().strip()
                relativePath = relpath(scriptName, project.getProjectDir())
                if not relativePath.startswith('..'):
                    scriptName = relativePath

                project.updateProperties(
                    scriptName, importDirs,
                    dialog.creationDateEdit.text().strip(),
                    dialog.authorEdit.text().strip(),
                    dialog.licenseEdit.text().strip(),
                    dialog.copyrightEdit.text().strip(),
                    dialog.versionEdit.text().strip(),
                    dialog.emailEdit.text().strip(),
                    dialog.descriptionEdit.toPlainText().strip())
        else:
            # This is not the current project - it can be viewed
            fName = self.__projectContextItem.getFilename()
            dialog = ProjectPropertiesDialog(fName, self)
            dialog.exec_()
        return

    def __deleteProject(self):
        " Handles the 'delete from recent' context menu item "
        if self.__projectContextItem is None:
            return

        # Removal from the visible list is done via a signal which comes back
        # from settings
        fName = self.__projectContextItem.getFilename()
        Settings().deleteRecentProject(fName)
        return

    def __loadProject(self):
        " handles 'Load' context menu item "
        if self.__projectContextItem is None:
            return
        if not self.__projectContextItem.isValid():
            return
        if self.__debugMode:
            return

        projectFileName = self.__projectContextItem.getFilename()

        if self.__projectContextItem.isCurrent():
            GlobalData().mainWindow.openFile(projectFileName, -1)
            return  # This is the current project, open for text editing

        QApplication.processEvents()
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        if os.path.exists(projectFileName):
            mainWin = GlobalData().mainWindow
            editorsManager = mainWin.editorsManagerWidget.editorsManager
            if editorsManager.closeRequest():
                prj = GlobalData().project
                prj.setTabsStatus(editorsManager.getTabsStatus())
                editorsManager.closeAll()
                prj.loadProject(projectFileName)
                mainWin.activateProjectTab()
        else:
            logging.error("The project " + os.path.basename(projectFileName) +
                          " disappeared from the file system.")
            self.__populateProjects()
        QApplication.restoreOverrideCursor()
        return

    def __populateProjects(self):
        " Populates the recent projects "
        self.projectsView.clear()
        for item in Settings().recentProjects:
            self.projectsView.addTopLevelItem(RecentProjectViewItem(item))

        self.__sortProjects()
        self.__resizeProjectColumns()
        self.__updateProjectToolbarButtons()
        return

    def __populateFiles(self):
        " Populates the recent files "
        self.recentFilesView.clear()
        for path in GlobalData().project.recentFiles:
            self.recentFilesView.addTopLevelItem(RecentFileViewItem(path))

        self.__sortFiles()
        self.__resizeFileColumns()
        self.__updateFileToolbarButtons()
        return

    def __projectChanged(self, what):
        " Triggered when the current project is changed "
        if what == CodimensionProject.CompleteProject:
            self.__populateProjects()
            self.__populateFiles()
            return

        if what == CodimensionProject.Properties:
            # Update the corresponding tooltip
            items = self.projectsView.findItems(GlobalData().project.fileName,
                                                Qt.MatchExactly, 2)
            if len(items) != 1:
                logging.error("Unexpected number of matched projects: " +
                              str(len(items)))
                return

            items[0].updateTooltip()
            return

    def __openFile(self):
        " Handles 'open' file menu item "
        self.__fileContextItem.updateIconAndTooltip()
        fName = self.__fileContextItem.getFilename()

        if not self.__fileContextItem.isValid():
            logging.warning("Cannot open " + fName)
            return

        fileType = detectFileType(fName)
        if fileType == PixmapFileType:
            GlobalData().mainWindow.openPixmapFile(fName)
            return

        GlobalData().mainWindow.openFile(fName, -1)
        return

    def __deleteFile(self):
        " Handles 'delete from recent' file menu item "
        self.removeRecentFile(self.__fileContextItem.getFilename())
        return

    def __handleShowFileContextMenu(self, coord):
        " File context menu "
        self.__fileContextItem = self.recentFilesView.itemAt(coord)
        if self.__fileContextItem is not None:
            self.__fileMenu.popup(QCursor.pos())
        return

    def __filePathToClipboard(self):
        " Copies the file item path to the clipboard "
        if self.__fileContextItem is not None:
            QApplication.clipboard().setText(
                self.__fileContextItem.getFilename())
        return

    def __prjPathToClipboard(self):
        " Copies the project item path to the clipboard "
        if self.__projectContextItem is not None:
            QApplication.clipboard().setText(
                self.__projectContextItem.getFilename())
        return

    def onFileUpdated(self, fileName, uuid):
        " Triggered when the file is updated: python or project "
        realPath = os.path.realpath(fileName)

        count = self.recentFilesView.topLevelItemCount()
        for index in xrange(0, count):
            item = self.recentFilesView.topLevelItem(index)

            itemRealPath = os.path.realpath(item.getFilename())
            if realPath == itemRealPath:
                item.updateIconAndTooltip()
                break

        for index in xrange(0, self.projectsView.topLevelItemCount()):
            item = self.projectsView.topLevelItem(index)

            itemRealPath = os.path.realpath(item.getFilename())
            if realPath == itemRealPath:
                item.updateTooltip()
                break
        return

    def __onShowHide(self):
        " Triggered when show/hide button is clicked "
        if self.projectsView.isVisible():
            self.projectsView.setVisible(False)
            self.lowerToolbar.setVisible(False)
            self.__showHideButton.setIcon(getIcon('more.png'))
            self.__showHideButton.setToolTip("Show recent projects list")

            self.__minH = self.lower.minimumHeight()
            self.__maxH = self.lower.maximumHeight()

            self.lower.setMinimumHeight(self.headerFrame.height())
            self.lower.setMaximumHeight(self.headerFrame.height())
        else:
            self.projectsView.setVisible(True)
            self.lowerToolbar.setVisible(True)
            self.__showHideButton.setIcon(getIcon('less.png'))
            self.__showHideButton.setToolTip("Hide recent projects list")

            self.lower.setMinimumHeight(self.__minH)
            self.lower.setMaximumHeight(self.__maxH)
        return

    def __onDebugMode(self, newState):
        " Triggered when debug mode has changed "
        self.__debugMode = newState

        # Disable the load project button
        self.__updateProjectToolbarButtons()
        return

    def removeRecentFile(self, fName):
        " Removes a single file from the recent files list "
        GlobalData().project.removeRecentFile(fName)

        for index in xrange(self.recentFilesView.topLevelItemCount()):
            candidate = self.recentFilesView.topLevelItem(index)
            if candidate.getFilename() == fName:
                self.recentFilesView.takeTopLevelItem(index)
                return
        return
コード例 #25
0
class Main(plugin.Plugin):
    " Main Class "

    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.scriptPath, self.scriptArgs = "", []
        self.profilerPath, self.tempPath = profilerPath, tempPath
        self.output = " ERROR: FAIL: No output ! "

        self.process = QProcess()
        self.process.finished.connect(self.on_process_finished)
        self.process.error.connect(self.on_process_error)

        self.tabWidget, self.stat = QTabWidget(), QWidget()
        self.tabWidget.tabCloseRequested.connect(
            lambda: self.tabWidget.setTabPosition(1) if self.tabWidget.
            tabPosition() == 0 else self.tabWidget.setTabPosition(0))
        self.tabWidget.setStyleSheet('QTabBar{font-weight:bold;}')
        self.tabWidget.setMovable(True)
        self.tabWidget.setTabsClosable(True)
        self.vboxlayout1 = QVBoxLayout(self.stat)
        self.hboxlayout1 = QHBoxLayout()
        self.filterTableLabel = QLabel("<b>Type to Search : </b>", self.stat)
        self.hboxlayout1.addWidget(self.filterTableLabel)
        self.filterTableLineEdit = QLineEdit(self.stat)
        self.filterTableLineEdit.setPlaceholderText(' Type to Search . . . ')
        self.hboxlayout1.addWidget(self.filterTableLineEdit)
        self.filterHintTableLabel = QLabel(" ? ", self.stat)
        self.hboxlayout1.addWidget(self.filterHintTableLabel)
        self.vboxlayout1.addLayout(self.hboxlayout1)
        self.tableWidget = QTableWidget(self.stat)
        self.tableWidget.setAlternatingRowColors(True)
        self.tableWidget.setColumnCount(8)
        self.tableWidget.setRowCount(2)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(2, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(3, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(4, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(5, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(6, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(7, item)
        self.tableWidget.itemDoubleClicked.connect(
            self.on_tableWidget_itemDoubleClicked)
        self.vboxlayout1.addWidget(self.tableWidget)
        self.tabWidget.addTab(self.stat, " ? ")

        self.source = QWidget()
        self.gridlayout = QGridLayout(self.source)
        self.scintillaWarningLabel = QLabel(
            "QScintilla is not installed!. Falling back to basic text edit!.",
            self.source)
        self.gridlayout.addWidget(self.scintillaWarningLabel, 1, 0, 1, 2)
        self.sourceTreeWidget = QTreeWidget(self.source)
        self.sourceTreeWidget.setAlternatingRowColors(True)
        self.sourceTreeWidget.itemActivated.connect(
            self.on_sourceTreeWidget_itemActivated)
        self.sourceTreeWidget.itemClicked.connect(
            self.on_sourceTreeWidget_itemClicked)
        self.sourceTreeWidget.itemDoubleClicked.connect(
            self.on_sourceTreeWidget_itemClicked)

        self.gridlayout.addWidget(self.sourceTreeWidget, 0, 0, 1, 1)
        self.sourceTextEdit = QTextEdit(self.source)
        self.sourceTextEdit.setReadOnly(True)
        self.gridlayout.addWidget(self.sourceTextEdit, 0, 1, 1, 1)
        self.tabWidget.addTab(self.source, " ? ")

        self.result = QWidget()
        self.vlayout = QVBoxLayout(self.result)
        self.globalStatGroupBox = QGroupBox(self.result)
        self.hboxlayout = QHBoxLayout(self.globalStatGroupBox)
        self.totalTimeLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.totalTimeLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.totalTimeLcdNumber.setNumDigits(7)
        self.totalTimeLcdNumber.display(1000000)
        self.totalTimeLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.totalTimeLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                              QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.totalTimeLcdNumber)
        self.tTimeLabel = QLabel("<b>Total Time (Sec)</b>",
                                 self.globalStatGroupBox)
        self.tTimeLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.tTimeLabel)
        self.numCallLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.numCallLcdNumber.setNumDigits(7)
        self.numCallLcdNumber.display(1000000)
        self.numCallLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.numCallLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.numCallLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.numCallLcdNumber)
        self.numCallLabel = QLabel("<b>Number of calls</b>",
                                   self.globalStatGroupBox)
        self.numCallLabel.setSizePolicy(QSizePolicy.Minimum,
                                        QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.numCallLabel)
        self.primCallLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.primCallLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.primCallLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.primCallLcdNumber.setNumDigits(7)
        self.primCallLcdNumber.display(1000000)
        self.primCallLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.primCallLcdNumber)
        self.primCallLabel = QLabel("<b>Primitive calls (%)</b>",
                                    self.globalStatGroupBox)
        self.primCallLabel.setSizePolicy(QSizePolicy.Minimum,
                                         QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.primCallLabel)
        self.vlayout.addWidget(self.globalStatGroupBox)
        try:
            from PyKDE4.kdeui import KRatingWidget
            self.rating = KRatingWidget(self.globalStatGroupBox)
            self.rating.setToolTip('Profiling Performance Rating')
        except ImportError:
            pass
        self.tabWidget.addTab(self.result, " Get Results ! ")

        self.resgraph = QWidget()
        self.vlayout2 = QVBoxLayout(self.result)
        self.graphz = QGroupBox(self.resgraph)
        self.hboxlayout2 = QHBoxLayout(self.graphz)
        try:
            from PyKDE4.kdeui import KLed
            KLed(self.graphz)
        except ImportError:
            pass
        self.hboxlayout2.addWidget(
            QLabel('''
            Work in Progress  :)  Not Ready Yet'''))
        self.vlayout2.addWidget(self.graphz)
        self.tabWidget.addTab(self.resgraph, " Graphs and Charts ")

        self.pathz = QWidget()
        self.vlayout3 = QVBoxLayout(self.pathz)
        self.patz = QGroupBox(self.pathz)
        self.hboxlayout3 = QVBoxLayout(self.patz)
        self.profilepath = QLineEdit(profilerPath)
        self.getprofile = QPushButton(QIcon.fromTheme("document-open"), 'Open')
        self.getprofile.setToolTip(
            'Dont touch if you dont know what are doing')
        self.getprofile.clicked.connect(lambda: self.profilepath.setText(
            str(
                QFileDialog.getOpenFileName(
                    self.patz, ' Open the profile.py file ',
                    path.expanduser("~"), ';;(profile.py)'))))
        self.hboxlayout3.addWidget(
            QLabel(
                '<center><b>Profile.py Python Library Full Path:</b></center>')
        )
        self.hboxlayout3.addWidget(self.profilepath)
        self.hboxlayout3.addWidget(self.getprofile)

        self.argGroupBox = QGroupBox(self.pathz)
        self.hbxlayout = QHBoxLayout(self.argGroupBox)
        self.argLineEdit = QLineEdit(self.argGroupBox)
        self.argLineEdit.setToolTip(
            'Not touch if you dont know what are doing')
        self.argLineEdit.setPlaceholderText(
            'Dont touch if you dont know what are doing')
        self.hbxlayout.addWidget(
            QLabel('<b>Additional Profile Arguments:</b>'))
        self.hbxlayout.addWidget(self.argLineEdit)
        self.hboxlayout3.addWidget(self.argGroupBox)

        self.vlayout3.addWidget(self.patz)
        self.tabWidget.addTab(self.pathz, " Paths and Configs ")

        self.outp = QWidget()
        self.vlayout4 = QVBoxLayout(self.outp)
        self.outgro = QGroupBox(self.outp)
        self.outgro.setTitle(" MultiProcessing Output Logs ")
        self.hboxlayout4 = QVBoxLayout(self.outgro)
        self.outputlog = QTextEdit()
        self.outputlog.setText('''
        I do not fear computers, I fear the lack of them.   -Isaac Asimov ''')
        self.hboxlayout4.addWidget(self.outputlog)
        self.vlayout4.addWidget(self.outgro)
        self.tabWidget.addTab(self.outp, " Logs ")

        self.actionNew_profiling = QAction(QIcon.fromTheme("document-new"),
                                           'New Profiling', self)
        self.actionLoad_profile = QAction(QIcon.fromTheme("document-open"),
                                          'Open Profiling', self)
        self.actionClean = QAction(QIcon.fromTheme("edit-clear"), 'Clean',
                                   self)
        self.actionClean.triggered.connect(lambda: self.clearContent)
        self.actionAbout = QAction(QIcon.fromTheme("help-about"), 'About',
                                   self)
        self.actionAbout.triggered.connect(lambda: QMessageBox.about(
            self.dock, __doc__, ', '.join(
                (__doc__, __license__, __author__, __email__))))
        self.actionSave_profile = QAction(QIcon.fromTheme("document-save"),
                                          'Save Profiling', self)
        self.actionManual = QAction(QIcon.fromTheme("help-contents"), 'Help',
                                    self)
        self.actionManual.triggered.connect(lambda: open_new_tab(
            'http://docs.python.org/library/profile.html'))

        self.tabWidget.setCurrentIndex(2)

        self.globalStatGroupBox.setTitle("Global Statistics")
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText("Number of Calls")
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText("Total Time")
        item = self.tableWidget.horizontalHeaderItem(2)
        item.setText("Per Call")
        item = self.tableWidget.horizontalHeaderItem(3)
        item.setText("Cumulative Time")
        item = self.tableWidget.horizontalHeaderItem(4)
        item.setText("Per Call")
        item = self.tableWidget.horizontalHeaderItem(5)
        item.setText("Filename")
        item = self.tableWidget.horizontalHeaderItem(6)
        item.setText("Line")
        item = self.tableWidget.horizontalHeaderItem(7)
        item.setText("Function")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.stat),
                                  "Statistics per Function")

        self.sourceTreeWidget.headerItem().setText(0, "Source files")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.source),
                                  "Sources Navigator")
        #######################################################################

        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(self.tabWidget)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        QToolBar(self.dock).addActions(
            (self.actionNew_profiling, self.actionClean,
             self.actionSave_profile, self.actionLoad_profile,
             self.actionManual, self.actionAbout))

        self.actionNew_profiling.triggered.connect(
            self.on_actionNew_profiling_triggered)
        self.actionLoad_profile.triggered.connect(
            self.on_actionLoad_profile_triggered)
        self.actionSave_profile.triggered.connect(
            self.on_actionSave_profile_triggered)

        self.locator.get_service('misc').add_widget(
            self.dock, QIcon.fromTheme("document-open-recent"), __doc__)

        if QSCI:
            # Scintilla source editor management
            self.scintillaWarningLabel.setText(' QScintilla is Ready ! ')
            layout = self.source.layout()
            layout.removeWidget(self.sourceTextEdit)
            self.sourceTextEdit = Qsci.QsciScintilla(self.source)
            layout.addWidget(self.sourceTextEdit, 0, 1)
            doc = self.sourceTextEdit
            doc.setLexer(Qsci.QsciLexerPython(self.sourceTextEdit))
            doc.setReadOnly(True)
            doc.setEdgeMode(Qsci.QsciScintilla.EdgeLine)
            doc.setEdgeColumn(80)
            doc.setEdgeColor(QColor("#FF0000"))
            doc.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle)
            doc.setBraceMatching(Qsci.QsciScintilla.SloppyBraceMatch)
            doc.setCaretLineVisible(True)
            doc.setMarginLineNumbers(1, True)
            doc.setMarginWidth(1, 25)
            doc.setTabWidth(4)
            doc.setEolMode(Qsci.QsciScintilla.EolUnix)
            self.marker = {}
            for color in COLORS:
                mnr = doc.markerDefine(Qsci.QsciScintilla.Background)
                doc.setMarkerBackgroundColor(color, mnr)
                self.marker[color] = mnr
        self.currentSourcePath = None

        # Connect table and tree filter edit signal to unique slot
        self.filterTableLineEdit.textEdited.connect(
            self.on_filterLineEdit_textEdited)

        # Timer to display filter hint message
        self.filterHintTimer = QTimer(self)
        self.filterHintTimer.setSingleShot(True)
        self.filterHintTimer.timeout.connect(self.on_filterHintTimer_timeout)

        # Timer to start search
        self.filterSearchTimer = QTimer(self)
        self.filterSearchTimer.setSingleShot(True)
        self.filterSearchTimer.timeout.connect(
            self.on_filterSearchTimer_timeout)

        self.tabLoaded = {}
        for i in range(10):
            self.tabLoaded[i] = False
        self.backgroundTreeMatchedItems = {}
        self.resizeWidgetToContent(self.tableWidget)

    def on_actionNew_profiling_triggered(self):
        self.clearContent()
        self.scriptPath = str(
            QFileDialog.getOpenFileName(self.dock,
                                        "Choose your script to profile",
                                        path.expanduser("~"),
                                        "Python (*.py *.pyw)"))
        commandLine = [
            self.profilerPath, "-o", self.tempPath, self.scriptPath
        ] + self.scriptArgs
        commandLine = " ".join(commandLine)
        ##if self.termCheckBox.checkState() == Qt.Checked:
        #termList = ["xterm", "aterm"]
        #for term in termList:
        #termPath = which(term)
        #if termPath:
        #break
        #commandLine = """%s -e "%s ; echo 'Press ENTER Exit' ; read" """ \
        #% (termPath, commandLine)
        self.process.start(commandLine)
        if not self.process.waitForStarted():
            print((" ERROR: {} failed!".format(commandLine)))
            return

    def on_process_finished(self, exitStatus):
        ' whan the process end '
        print((" INFO: OK: QProcess is %s" % self.process.exitCode()))
        self.output = self.process.readAll().data()
        if not self.output:
            self.output = " ERROR: FAIL: No output ! "
        self.outputlog.setText(self.output + str(self.process.exitCode()))
        if path.exists(self.tempPath):
            self.setStat(self.tempPath)
            remove(self.tempPath)
        else:
            self.outputlog.setText(" ERROR: QProcess FAIL: Profiling failed.")
        self.tabWidget.setCurrentIndex(2)

    def on_process_error(self, error):
        ' when the process fail, I hope you never see this '
        print(" ERROR: QProcess FAIL: Profiler Dead, wheres your God now ? ")
        if error == QProcess.FailedToStart:
            self.outputlog.setText(" ERROR: FAIL: Profiler execution failed ")
        elif error == QProcess.Crashed:
            self.outputlog.setText(" ERROR: FAIL: Profiler execution crashed ")
        else:
            self.outputlog.setText(" ERROR: FAIL: Profiler unknown error ")

    def on_actionLoad_profile_triggered(self):
        """Load a previous profile sessions"""
        statPath = str(
            QFileDialog.getOpenFileName(self.dock, "Open profile dump",
                                        path.expanduser("~"),
                                        "Profile file (*)"))
        if statPath:
            self.clearContent()
            print(' INFO: OK: Loading profiling from ' + statPath)
            self.setStat(statPath)

    def on_actionSave_profile_triggered(self):
        """Save a profile sessions"""
        statPath = str(
            QFileDialog.getSaveFileName(self.dock, "Save profile dump",
                                        path.expanduser("~"),
                                        "Profile file (*)"))
        if statPath:
            #TODO: handle error case and give feelback to user
            print(' INFO: OK: Saving profiling to ' + statPath)
            self.stat.save(statPath)

    #=======================================================================#
    # Common parts                                                          #
    #=======================================================================#

    def on_tabWidget_currentChanged(self, index):
        """slot for tab change"""
        # Kill search and hint timer if running to avoid cross effect
        for timer in (self.filterHintTimer, self.filterSearchTimer):
            if timer.isActive():
                timer.stop()
        if not self.stat:
            #No stat loaded, nothing to do
            return
        self.populateTable()
        self.populateSource()

    def on_filterLineEdit_textEdited(self, text):
        """slot for filter change (table or tree"""
        if self.filterSearchTimer.isActive():
            # Already runnning, stop it
            self.filterSearchTimer.stop()
        # Start timer
        self.filterSearchTimer.start(300)

    def on_filterHintTimer_timeout(self):
        """Timeout to warn user about text length"""
        print("timeout")
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            label = self.filterHintTableLabel
        label.setText("Type > 2 characters to search")

    def on_filterSearchTimer_timeout(self):
        """timeout to start search"""
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            text = self.filterTableLineEdit.text()
            label = self.filterHintTableLabel
            edit = self.filterTableLineEdit
            widget = self.tableWidget
        else:
            print("Unknow tab for filterSearch timeout !")

        print(("do search for %s" % text))
        if not len(text):
            # Empty keyword, just clean all
            if self.filterHintTimer.isActive():
                self.filterHintTimer.stop()
            label.setText(" ? ")
            self.warnUSer(True, edit)
            self.clearSearch()
            return
        if len(text) < 2:
            # Don't filter if text is too short and tell it to user
            self.filterHintTimer.start(600)
            return
        else:
            if self.filterHintTimer.isActive():
                self.filterHintTimer.stop()
            label.setText(" ? ")

        # Search
        self.clearSearch()
        matchedItems = []
        if tab == TAB_FUNCTIONSTAT:
            # Find items
            matchedItems = widget.findItems(text, Qt.MatchContains)
            widget.setSortingEnabled(False)
            matchedRows = [item.row() for item in matchedItems]
            # Hide matched items
            header = widget.verticalHeader()
            for row in range(widget.rowCount()):
                if row not in matchedRows:
                    header.hideSection(row)
            widget.setSortingEnabled(True)
        else:
            print(" Unknow tab for filterSearch timeout ! ")

        print(("got %s members" % len(matchedItems)))
        self.warnUSer(matchedItems, edit)
        self.resizeWidgetToContent(widget)

    def resizeWidgetToContent(self, widget):
        """Resize all columns according to content"""
        for i in range(widget.columnCount()):
            widget.resizeColumnToContents(i)

    def clearSearch(self):
        """Clean search result
        For table, show all items
        For tree, remove colored items"""
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            header = self.tableWidget.verticalHeader()
            if header.hiddenSectionCount():
                for i in range(header.count()):
                    if header.isSectionHidden(i):
                        header.showSection(i)

    def clearContent(self):
        # Clear tabs
        self.tableWidget.clearContents()
        self.sourceTreeWidget.clear()
        # Reset LCD numbers
        for lcdNumber in (self.totalTimeLcdNumber, self.numCallLcdNumber,
                          self.primCallLcdNumber):
            lcdNumber.display(1000000)
        # Reset stat
        self.pstat = None
        # Disable save as menu
        self.actionSave_profile.setEnabled(False)
        # Mark all tabs as unloaded
        for i in range(10):
            self.tabLoaded[i] = False

    def warnUSer(self, result, inputWidget):
        palette = inputWidget.palette()
        if result:
            palette.setColor(QPalette.Normal, QPalette.Base,
                             QColor(255, 255, 255))
        else:
            palette.setColor(QPalette.Normal, QPalette.Base,
                             QColor(255, 136, 138))
        inputWidget.setPalette(palette)
        inputWidget.update()

    def setStat(self, statPath):
        self.stat = Stat(path=statPath)
        # Global stat update
        self.totalTimeLcdNumber.display(self.stat.getTotalTime())
        self.numCallLcdNumber.display(self.stat.getCallNumber())
        self.primCallLcdNumber.display(self.stat.getPrimitiveCallRatio())
        # Refresh current tab
        self.on_tabWidget_currentChanged(self.tabWidget.currentIndex())
        # Activate save as menu
        self.actionSave_profile.setEnabled(True)
        try:
            self.rating.setMaxRating(10)
            self.rating.setRating(
                int(self.stat.getPrimitiveCallRatio()) / 10 - 1)
        except:
            pass

    #========================================================================#
    # Statistics table                                                      #
    #=======================================================================#

    def populateTable(self):
        row = 0
        rowCount = self.stat.getStatNumber()
        progress = QProgressDialog("Populating statistics table...", "Abort",
                                   0, 2 * rowCount)
        self.tableWidget.setSortingEnabled(False)
        self.tableWidget.setRowCount(rowCount)

        progress.setWindowModality(Qt.WindowModal)
        for (key, value) in self.stat.getStatItems():
            #ncalls
            item = StatTableWidgetItem(str(value[0]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_NCALLS, item)
            colorTableItem(item, self.stat.getCallNumber(), value[0])
            #total time
            item = StatTableWidgetItem(str(value[2]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_TTIME, item)
            colorTableItem(item, self.stat.getTotalTime(), value[2])
            #per call (total time)
            if value[0] != 0:
                tPerCall = str(value[2] / value[0])
                cPerCall = str(value[3] / value[0])
            else:
                tPerCall = ""
                cPerCall = ""
            item = StatTableWidgetItem(tPerCall)
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_TPERCALL, item)
            colorTableItem(
                item,
                100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(),
                tPerCall)
            #per call (cumulative time)
            item = StatTableWidgetItem(cPerCall)
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_CPERCALL, item)
            colorTableItem(
                item,
                100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(),
                cPerCall)
            #cumulative time
            item = StatTableWidgetItem(str(value[3]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_CTIME, item)
            colorTableItem(item, self.stat.getTotalTime(), value[3])
            #Filename
            self.tableWidget.setItem(row, STAT_FILENAME,
                                     StatTableWidgetItem(str(key[0])))
            #Line
            item = StatTableWidgetItem(str(key[1]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_LINE, item)
            #Function name
            self.tableWidget.setItem(row, STAT_FUNCTION,
                                     StatTableWidgetItem(str(key[2])))
            row += 1
            # Store it in stat hash array
            self.stat.setStatLink(item, key, TAB_FUNCTIONSTAT)
            progress.setValue(row)
            if progress.wasCanceled():
                return

        for i in range(self.tableWidget.rowCount()):
            progress.setValue(row + i)
            for j in range(self.tableWidget.columnCount()):
                item = self.tableWidget.item(i, j)
                if item:
                    item.setFlags(Qt.ItemIsEnabled)

        self.tableWidget.setSortingEnabled(True)
        self.resizeWidgetToContent(self.tableWidget)
        progress.setValue(2 * rowCount)

    def on_tableWidget_itemDoubleClicked(self, item):
        matchedItems = []
        filename = str(self.tableWidget.item(item.row(), STAT_FILENAME).text())
        if not filename or filename.startswith("<"):
            # No source code associated, return immediatly
            return
        function = self.tableWidget.item(item.row(), STAT_FUNCTION).text()
        line = self.tableWidget.item(item.row(), STAT_LINE).text()

        self.on_tabWidget_currentChanged(TAB_SOURCE)  # load source tab
        function = "%s (%s)" % (function, line)
        fathers = self.sourceTreeWidget.findItems(filename, Qt.MatchContains,
                                                  SOURCE_FILENAME)
        print(("find %s father" % len(fathers)))
        for father in fathers:
            findItems(father, function, SOURCE_FILENAME, matchedItems)
        print(("find %s items" % len(matchedItems)))

        if matchedItems:
            self.tabWidget.setCurrentIndex(TAB_SOURCE)
            self.sourceTreeWidget.scrollToItem(matchedItems[0])
            self.on_sourceTreeWidget_itemClicked(matchedItems[0],
                                                 SOURCE_FILENAME)
            matchedItems[0].setSelected(True)
        else:
            print("oups, item found but cannot scroll to it !")

    #=======================================================================#
    # Source explorer                                                      #
    #=====================================================================#

    def populateSource(self):
        items = {}
        for stat in self.stat.getStatKeys():
            source = stat[0]
            function = "%s (%s)" % (stat[2], stat[1])
            if source in ("", "profile") or source.startswith("<"):
                continue
            # Create the function child
            child = QTreeWidgetItem([function])
            # Store it in stat hash array
            self.stat.setStatLink(child, stat, TAB_SOURCE)
            if source in items:
                father = items[source]
            else:
                # Create the father
                father = QTreeWidgetItem([source])
                items[source] = father
            father.addChild(child)
        self.sourceTreeWidget.setSortingEnabled(False)
        for value in list(items.values()):
            self.sourceTreeWidget.addTopLevelItem(value)
        self.sourceTreeWidget.setSortingEnabled(True)

    def on_sourceTreeWidget_itemActivated(self, item, column):
        self.on_sourceTreeWidget_itemClicked(item, column)

    def on_sourceTreeWidget_itemClicked(self, item, column):
        line = 0
        parent = item.parent()
        if QSCI:
            doc = self.sourceTextEdit
        if parent:
            pathz = parent.text(column)
            result = match("(.*) \(([0-9]+)\)", item.text(column))
            if result:
                try:
                    function = str(result.group(1))
                    line = int(result.group(2))
                except ValueError:
                    # We got garbage... falling back to line 0
                    pass
        else:
            pathz = item.text(column)
        pathz = path.abspath(str(pathz))
        if self.currentSourcePath != pathz:
            # Need to load source
            self.currentSourcePath == pathz
            try:
                if QSCI:
                    doc.clear()
                    doc.insert(file(pathz).read())
                else:
                    self.sourceTextEdit.setPlainText(file(pathz).read())
            except IOError:
                QMessageBox.warning(self, "Error",
                                    "Source file could not be found",
                                    QMessageBox.Ok)
                return

            if QSCI:
                for function, line in [(i[2], i[1])
                                       for i in self.stat.getStatKeys()
                                       if i[0] == pathz]:
                    # expr, regexp, case sensitive, whole word, wrap, forward
                    doc.findFirst("def", False, True, True, False, True, line,
                                  0, True)
                    end, foo = doc.getCursorPosition()
                    time = self.stat.getStatTotalTime((pathz, line, function))
                    colorSource(doc, self.stat.getTotalTime(), time, line, end,
                                self.marker)
        if QSCI:
            doc.ensureLineVisible(line)
コード例 #26
0
class explorador(QDialog):
    def __init__(self):
        self.a = 0
        super(explorador, self).__init__(None)
        self.setWindowTitle("Explorador de archivos y carpetas")
        self.resize(610, 450)

        self.back_history = []
        self.forward_history = []

        self.back = QPushButton('<-', self)
        self.back.clicked.connect(self.back_click)
        self.back.setGeometry(10, 10, 30, 20)
        self.back.setEnabled(False)

        self.forward = QPushButton('->', self)
        self.forward.clicked.connect(self.forward_click)
        self.forward.setGeometry(50, 10, 30, 20)
        self.forward.setEnabled(False)

        self.up = QPushButton('^', self)
        self.up.clicked.connect(self.up_button_click)
        self.up.setGeometry(90, 10, 30, 20)

        self.address = QLineEdit(self)
        self.address.setGeometry(130, 10, 420, 20)

        self.refresh = QPushButton('@', self)
        self.refresh.clicked.connect(self.refresh_click)
        self.refresh.setGeometry(560, 10, 30, 20)

        self.items = QTreeWidget(self)
        self.items.setRootIsDecorated(False)
        self.items.setHeaderLabels(
            ("Nombre", u"Fecha de modificación", u"Tamaño"))
        self.items.itemDoubleClicked.connect(self.item_double_clicked)
        self.items.setGeometry(5, 40, 600, 400)

        # Iniciar en el directorio actual.
        self.load_path(getcwd())

    def back_click(self, checked):
        if self.back_history and len(self.back_history) > 1:
            # Obtener el último elemento.
            path = self.back_history[-2]
            self.forward_history.append(self.back_history[-1])
            # Remover el directorio actual.
            del self.back_history[-1]
            self.load_path(path, False)

    def forward_click(self, checked):
        if self.forward_history:
            path = self.forward_history[-1]
            self.back_history.append(path)
            del self.forward_history[-1]
            self.load_path(path, False)

    def item_double_clicked(self, item, column):
        filepath = join(self.current_path, unicode(item.text(0)))
        if isdir(filepath):
            self.load_path(filepath)
        else:
            # Iniciar archivo con el programa predeterminado.
            #startfile(filepath)

            a = filepath
            #print a
            e = entrar()
            e.ponfoto(a)
            #parcial.ponfoto(a)
            #print self.a

    def up_button_click(self, checked):
        parent = dirname(self.current_path)
        if parent != self.current_path:
            self.load_path(parent)

    def load_path(self, path, use_history=True):
        # Obtener archivos y carpetas.
        items = listdir(unicode(path))
        # Eliminar el contenido anterior.
        self.items.clear()

        for i in items:
            # Omitir archivos ocultos.
            if i.startswith("."):
                continue
            filepath = join(path, i)
            # Obtener informacion del archivo.
            stats = stat(filepath)
            # Crear el control ítem.
            item_widget = QTreeWidgetItem(
                (i, strftime("%c", localtime(stats.st_mtime)).decode("utf-8"),
                 size(stats.st_size) if isfile(filepath) else ""))
            # Establecer el ícono correspondiente.
            item_widget.setIcon(
                0,
                QIcon("images/%s.png" %
                      ("file" if isfile(filepath) else "folder")))
            # Añadir elemento.
            self.items.addTopLevelItem(item_widget)

        # Ajustar el tamaño de las columnas.
        for i in range(3):
            self.items.resizeColumnToContents(i)

        self.current_path = path
        self.address.setText(self.current_path)

        # Añadir al historial.
        if use_history:
            self.back_history.append(self.current_path)

        # Habilitar / dehabilitar botones del historial.
        if self.back_history and len(self.back_history) > 1:
            if not self.back.isEnabled():
                self.back.setEnabled(True)
        else:
            if self.back.isEnabled():
                self.forward_history = []
                self.back.setEnabled(False)

        if self.forward_history:
            if not self.forward.isEnabled():
                self.forward.setEnabled(True)
        else:
            if self.forward.isEnabled():
                self.forward.setEnabled(False)

    def refresh_click(self, checked):
        self.load_path(self.current_path)
コード例 #27
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()
コード例 #28
0
ファイル: info.py プロジェクト: palaniyappanBala/dff
class Info(QDockWidget):
    def __init__(self, mainWindow):
        super(Info, self).__init__()
        self.__mainWindow = mainWindow
        self.loader = loader.loader()
        self.env = env.env()
        self.tm = TaskManager()
        self.addAction()
        self.configure()
        self.g_display()
        self.initCallback()
        self.Load()

    def configure(self):
        self.setAllowedAreas(Qt.AllDockWidgetAreas)
        self.setObjectName("dockWidgetBrowser")
        self.setWindowTitle(
            QApplication.translate("Info", "Info", None,
                                   QApplication.UnicodeUTF8))

    def addAction(self):
        self.__action = QAction(self)
        self.__action.setCheckable(True)
        self.__action.setChecked(True)
        self.__action.setObjectName("actionCoreInformations")
        self.__action.setText(
            QApplication.translate("MainWindow", "Info", None,
                                   QApplication.UnicodeUTF8))
        self.__mainWindow.menuWindow.addAction(self.__action)
        self.connect(self.__action, SIGNAL("triggered()"),
                     self.changeVisibleInformations)

    def changeVisibleInformations(self):
        if not self.isVisible():
            self.setVisible(True)
            self.__action.setChecked(True)
        else:
            self.setVisible(False)
            self.__action.setChecked(False)

    def g_display(self):
        self.Info = QWidget(self)
        self.layout = QHBoxLayout(self.Info)
        self.Info.setLayout(self.layout)
        self.tabWidget = QTabWidget(self)
        self.tabWidget.setElideMode(Qt.ElideRight)
        self.initTreeProcess()
        self.initTreeModule()
        self.initTreeEnv()
        self.layout.addWidget(self.tabWidget)
        self.setWidget(self.Info)

    def initCallback(self):
        self.connect(self, SIGNAL("visibilityChanged(bool)"),
                     self.visibilityChanged)
        self.timer = QTimer(self)
        self.connect(self.timer, SIGNAL("timeout()"), self.refresh)
        self.timer.start(2000)

    def visibilityChanged(self, bool):
        if not self.isVisible():
            self.__action.setChecked(False)
        else:
            self.__action.setChecked(True)

    def Load(self):
        self.LoadInfoProcess()
        self.LoadInfoModules()
        self.LoadInfoEnv()
        pass

    def refresh(self):
        self.LoadInfoProcess()
        self.LoadInfoModules()
        self.LoadInfoEnv()
        pass

    def deleteInfos(self):
        self.deleteInfoProcess()
        self.deleteInfoModule()
        self.deleteInfoEnv()

#MODULES

    def initTreeModule(self):
        self.treeModule = QTreeWidget(self)
        self.treeModule.setColumnCount(3)
        headerLabel = [
            QApplication.translate("Info", "Name", None,
                                   QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Key", None,
                                   QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Value", None,
                                   QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Info", None,
                                   QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Type", None,
                                   QApplication.UnicodeUTF8)
        ]
        self.treeModule.setHeaderLabels(headerLabel)
        self.treeModule.setAlternatingRowColors(True)
        self.tabWidget.addTab(self.treeModule, "Modules")
        self.itemModuleDic = dict()
        self.itemListArgDic = dict()
        self.itemArgDic = dict()
        self.itemListResDic = dict()
        self.itemResDic = dict()

    def LoadInfoModules(self):
        modules = self.loader.modules
        for mod in modules:
            try:
                itemModule = self.itemModuleDic[mod]
            except KeyError:
                itemModule = QTreeWidgetItem(self.treeModule)
                self.itemModuleDic[mod] = itemModule
                itemModule.setText(0, str(mod))
                itemConfig = QTreeWidgetItem(itemModule)
                itemConfig.setText(0, "Config")
                cdesc = modules[mod].conf.descr_l
                for key in cdesc:
                    itemConfKey = QTreeWidgetItem(itemConfig)
                    itemConfKey.setText(0, "var")
                    itemConfKey.setText(1, key.name)
                    itemConfKey.setText(4, key.type)
                    if len(key.description):
                        itemConfKey.setText(3, key.description)
                for type, name, val, _from in self.env.get_val_list(
                        modules[mod].conf.val_l):
                    itemConfKey = QTreeWidgetItem(itemConfig)
                    itemConfKey.setText(0, "const")
                    itemConfKey.setText(1, name)
                    itemConfKey.setText(2, val)
                    itemConfKey.setText(4, type)
            for proc in self.tm.lprocessus:
                if proc.mod.name == mod:
                    try:
                        itemListArg = self.itemListArgDic[mod]
                    except KeyError:
                        itemListArg = QTreeWidgetItem(itemModule)
                        self.itemListArgDic[mod] = itemListArg
                        itemListArg.setText(0, "Arg")
                    for type, name, val in self.env.get_val_map(
                            proc.args.val_m):
                        try:
                            itemArgKey = self.itemArgDic[(type, name, val)]
                        except KeyError:
                            itemArgKey = QTreeWidgetItem(itemListArg)
                            self.itemArgDic[(type, name, val)] = itemArgKey
                            itemArgKey.setText(1, name)
                            itemArgKey.setText(2, val)
                            itemArgKey.setText(4, type)
                    try:
                        itemListRes = self.itemListResDic[mod]
                    except KeyError:
                        itemListRes = QTreeWidgetItem(itemModule)
                        self.itemListResDic[mod] = itemListRes
                        itemListRes.setText(0, "Results")
                    if proc.res:
                        for type, name, val in self.env.get_val_map(
                                proc.res.val_m):
                            try:
                                itemResKey = self.itemResDic[(type, name, val)]
                            except KeyError:
                                itemResKey = QTreeWidgetItem(itemListRes)
                                self.itemResDic[(type, name, val)] = itemResKey
                                itemResKey.setText(1, name)
                                itemResKey.setText(2, val)
                                itemResKey.setText(4, type)

    def deleteInfoModule(self):
        self.treeModule.clear()

#ENV

    def initTreeEnv(self):
        self.treeEnv = QTreeWidget(self)
        self.treeEnv.setColumnCount(3)
        headerLabel = [
            QApplication.translate("Info", "Key", None,
                                   QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Type", None,
                                   QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Value", None,
                                   QApplication.UnicodeUTF8),
            QApplication.translate("Info", "From", None,
                                   QApplication.UnicodeUTF8)
        ]
        self.treeEnv.setHeaderLabels(headerLabel)
        self.treeEnv.setAlternatingRowColors(True)
        self.tabWidget.addTab(self.treeEnv, "Environment")
        self.envItemDic = dict()
        self.envConfKeyDic = dict()
        self.envValKeyDic = dict()

    def LoadInfoEnv(self):
        db = self.env.vars_db
        for key in db:
            try:
                (itemEnv, itemVar, itemValues) = self.envItemDic[key]
            except KeyError:
                itemEnv = QTreeWidgetItem(self.treeEnv)
                itemEnv.setText(0, key)
                itemVar = QTreeWidgetItem(itemEnv)
                itemVar.setText(0, "var")
                itemValues = QTreeWidgetItem(itemEnv)
                self.envItemDic[key] = (itemEnv, itemVar, itemValues)
            cdesc = db[key].descr_l
            for vk in cdesc:
                try:
                    itemConfKey = self.envConfKeyDic[(vk.type, vk._from)]
                except KeyError:
                    itemConfKey = QTreeWidgetItem(itemVar)
                    self.envConfKeyDic[(vk.type, vk._from)] = itemConfKey
                    itemConfKey.setText(1, vk.type)
                    itemConfKey.setText(3, vk._from)
            itemValues.setText(0, "values")
            for type, name, val, _from in self.env.get_val_list(db[key].val_l):
                try:
                    itemValKey = self.envValKeyDic[(type, _from, val)]
                except:
                    itemValKey = QTreeWidgetItem(itemValues)
                    self.envValKeyDic[(type, _from, val)] = itemValKey
                    itemValKey.setText(1, type)
                    itemValKey.setText(2, val)
                    itemValKey.setText(3, _from)

    def deleteInfoEnv(self):
        self.treeEnv.clear()


#PROCESSUS

    def initTreeProcess(self):
        self.treeProcess = QTreeWidget(self)
        self.treeProcess.setColumnCount(3)
        headerLabel = [
            QApplication.translate("Info", "PID", None,
                                   QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Name", None,
                                   QApplication.UnicodeUTF8),
            QApplication.translate("Info", "State", None,
                                   QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Info", None,
                                   QApplication.UnicodeUTF8)
        ]
        self.treeProcess.setHeaderLabels(headerLabel)
        self.treeProcess.setAlternatingRowColors(True)
        self.tabWidget.addTab(self.treeProcess, "Task Manager")
        self.connect(self.treeProcess,
                     SIGNAL("itemDoubleClicked(QTreeWidgetItem*,int)"),
                     self.procClicked)
        self.procItemDic = dict()
        self.procChildItemDic = dict()

    def procClicked(self, item, column):
        dial = procMB(self, item.text(0))
        dial.exec_()

    def LoadInfoProcess(self):
        lproc = self.tm.lprocessus
        for proc in lproc:
            try:
                item = self.procItemDic[proc]
            except KeyError:
                item = QTreeWidgetItem(self.treeProcess)
                self.procItemDic[proc] = item
                item.setText(0, str(proc.pid))
                item.setText(1, str(proc.name))
            if item.text(2) != str(proc.state):
                item.setText(2, str(proc.state))
            if item.text(3) != str(proc.stateinfo):
                item.setText(3, str(proc.stateinfo))

    def deleteInfoProcess(self):
        self.treeProcess.clear()
コード例 #29
0
class IgnoredExceptionsViewer(QWidget):
    " Implements the client exceptions viewer for a debugger "

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

        self.__createPopupMenu()
        self.__createLayout()
        self.__ignored = []
        self.__currentItem = None

        GlobalData().project.projectChanged.connect(self.__onProjectChanged)

        if Settings().showIgnoredExcViewer == False:
            self.__onShowHide(True)
        return

    def __createPopupMenu(self):
        " Creates the popup menu "
        self.__excptMenu = QMenu()
        self.__removeMenuItem = self.__excptMenu.addAction(
            PixmapCache().getIcon('ignexcptdel.png'),
            "Remove from ignore list", self.__onRemoveFromIgnore)
        return

    def __createLayout(self):
        " Creates the widget layout "

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

        self.headerFrame = QFrame()
        self.headerFrame.setFrameStyle(QFrame.StyledPanel)
        self.headerFrame.setAutoFillBackground(True)
        headerPalette = self.headerFrame.palette()
        headerBackground = headerPalette.color(QPalette.Background)
        headerBackground.setRgb(min(headerBackground.red() + 30, 255),
                                min(headerBackground.green() + 30, 255),
                                min(headerBackground.blue() + 30, 255))
        headerPalette.setColor(QPalette.Background, headerBackground)
        self.headerFrame.setPalette(headerPalette)
        self.headerFrame.setFixedHeight(24)

        self.__excptLabel = QLabel("Ignored exception types")

        expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)
        fixedSpacer = QSpacerItem(3, 3)

        self.__showHideButton = QToolButton()
        self.__showHideButton.setAutoRaise(True)
        self.__showHideButton.setIcon(PixmapCache().getIcon('less.png'))
        self.__showHideButton.setFixedSize(20, 20)
        self.__showHideButton.setToolTip("Hide ignored exceptions list")
        self.__showHideButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideButton.clicked.connect(self.__onShowHide)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(1, 1, 1, 1)
        headerLayout.addSpacerItem(fixedSpacer)
        headerLayout.addWidget(self.__excptLabel)
        headerLayout.addSpacerItem(expandingSpacer)
        headerLayout.addWidget(self.__showHideButton)
        self.headerFrame.setLayout(headerLayout)

        self.exceptionsList = QTreeWidget(self)
        self.exceptionsList.setSortingEnabled(False)
        self.exceptionsList.setAlternatingRowColors(True)
        self.exceptionsList.setRootIsDecorated(False)
        self.exceptionsList.setItemsExpandable(True)
        self.exceptionsList.setUniformRowHeights(True)
        self.exceptionsList.setSelectionMode(QAbstractItemView.SingleSelection)
        self.exceptionsList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.exceptionsList.setItemDelegate(NoOutlineHeightDelegate(4))
        self.exceptionsList.setContextMenuPolicy(Qt.CustomContextMenu)

        self.exceptionsList.customContextMenuRequested.connect(
            self.__showContextMenu)
        self.exceptionsList.itemSelectionChanged.connect(
            self.__onSelectionChanged)
        self.exceptionsList.setHeaderLabels(["Exception type"])

        self.__excTypeEdit = QLineEdit()
        self.__excTypeEdit.setFixedHeight(26)
        self.__excTypeEdit.textChanged.connect(self.__onNewFilterChanged)
        self.__excTypeEdit.returnPressed.connect(self.__onAddExceptionFilter)
        self.__addButton = QPushButton("Add")
        # self.__addButton.setFocusPolicy( Qt.NoFocus )
        self.__addButton.setEnabled(False)
        self.__addButton.clicked.connect(self.__onAddExceptionFilter)

        expandingSpacer2 = QWidget()
        expandingSpacer2.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)

        self.__removeButton = QAction(PixmapCache().getIcon('delitem.png'),
                                      "Remove selected exception type", self)
        self.__removeButton.triggered.connect(self.__onRemoveFromIgnore)
        self.__removeButton.setEnabled(False)

        fixedSpacer1 = QWidget()
        fixedSpacer1.setFixedWidth(5)

        self.__removeAllButton = QAction(
            PixmapCache().getIcon('ignexcptdelall.png'),
            "Remove all the exception types", self)
        self.__removeAllButton.triggered.connect(self.__onRemoveAllFromIgnore)
        self.__removeAllButton.setEnabled(False)

        self.toolbar = QToolBar()
        self.toolbar.setOrientation(Qt.Horizontal)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.TopToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedHeight(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)
        self.toolbar.addWidget(expandingSpacer2)
        self.toolbar.addAction(self.__removeButton)
        self.toolbar.addWidget(fixedSpacer1)
        self.toolbar.addAction(self.__removeAllButton)

        addLayout = QHBoxLayout()
        addLayout.setContentsMargins(1, 1, 1, 1)
        addLayout.setSpacing(1)
        addLayout.addWidget(self.__excTypeEdit)
        addLayout.addWidget(self.__addButton)

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.toolbar)
        verticalLayout.addWidget(self.exceptionsList)
        verticalLayout.addLayout(addLayout)
        return

    def clear(self):
        " Clears the content "
        self.exceptionsList.clear()
        self.__excTypeEdit.clear()
        self.__addButton.setEnabled(False)
        self.__ignored = []
        self.__currentItem = None
        self.__updateTitle()
        return

    def __onShowHide(self, startup=False):
        " Triggered when show/hide button is clicked "
        if startup or self.exceptionsList.isVisible():
            self.exceptionsList.setVisible(False)
            self.__excTypeEdit.setVisible(False)
            self.__addButton.setVisible(False)
            self.__removeButton.setVisible(False)
            self.__removeAllButton.setVisible(False)
            self.__showHideButton.setIcon(PixmapCache().getIcon('more.png'))
            self.__showHideButton.setToolTip("Show ignored exceptions list")

            self.__minH = self.minimumHeight()
            self.__maxH = self.maximumHeight()

            self.setMinimumHeight(self.headerFrame.height())
            self.setMaximumHeight(self.headerFrame.height())

            Settings().showIgnoredExcViewer = False
        else:
            self.exceptionsList.setVisible(True)
            self.__excTypeEdit.setVisible(True)
            self.__addButton.setVisible(True)
            self.__removeButton.setVisible(True)
            self.__removeAllButton.setVisible(True)
            self.__showHideButton.setIcon(PixmapCache().getIcon('less.png'))
            self.__showHideButton.setToolTip("Hide ignored exceptions list")

            self.setMinimumHeight(self.__minH)
            self.setMaximumHeight(self.__maxH)

            Settings().showIgnoredExcViewer = True
        return

    def __onSelectionChanged(self):
        " Triggered when the current item is changed "
        selected = list(self.exceptionsList.selectedItems())
        if selected:
            self.__currentItem = selected[0]
            self.__removeButton.setEnabled(True)
        else:
            self.__currentItem = None
            self.__removeButton.setEnabled(False)
        return

    def __showContextMenu(self, coord):
        " Shows the frames list context menu "
        contextItem = self.exceptionsList.itemAt(coord)
        if contextItem is not None:
            self.__currentItem = contextItem
            self.__excptMenu.popup(QCursor.pos())
        return

    def __updateTitle(self):
        " Updates the section title "
        count = self.exceptionsList.topLevelItemCount()
        if count == 0:
            self.__excptLabel.setText("Ignored exception types")
        else:
            self.__excptLabel.setText("Ignored exception types (total: " +
                                      str(count) + ")")
        self.__removeAllButton.setEnabled(count != 0)
        return

    def __onProjectChanged(self, what):
        " Triggered when a project is changed "
        if what != CodimensionProject.CompleteProject:
            return

        self.clear()
        project = GlobalData().project
        if project.isLoaded():
            self.__ignored = list(project.ignoredExcpt)
        else:
            self.__ignored = list(Settings().ignoredExceptions)

        for exceptionType in self.__ignored:
            item = QTreeWidgetItem(self.exceptionsList)
            item.setText(0, exceptionType)
        self.__updateTitle()
        return

    def __onNewFilterChanged(self, text):
        " Triggered when the text is changed "
        text = str(text).strip()
        if text == "":
            self.__addButton.setEnabled(False)
            return
        if " " in text:
            self.__addButton.setEnabled(False)
            return

        if text in self.__ignored:
            self.__addButton.setEnabled(False)
            return

        self.__addButton.setEnabled(True)
        return

    def __onAddExceptionFilter(self):
        " Adds an item into the ignored exceptions list "
        text = self.__excTypeEdit.text().strip()
        self.addExceptionFilter(text)

    def addExceptionFilter(self, excType):
        " Adds a new item into the ignored exceptions list "
        if excType == "":
            return
        if " " in excType:
            return
        if excType in self.__ignored:
            return

        item = QTreeWidgetItem(self.exceptionsList)
        item.setText(0, excType)

        project = GlobalData().project
        if project.isLoaded():
            project.addExceptionFilter(excType)
        else:
            Settings().addExceptionFilter(excType)
        self.__ignored.append(excType)
        self.__updateTitle()
        return

    def __onRemoveFromIgnore(self):
        " Removes an item from the ignored exception types list "
        if self.__currentItem is None:
            return

        text = self.__currentItem.text(0)

        # Find the item index and remove it
        index = 0
        while True:
            if self.exceptionsList.topLevelItem(index).text(0) == text:
                self.exceptionsList.takeTopLevelItem(index)
                break
            index += 1

        project = GlobalData().project
        if project.isLoaded():
            project.deleteExceptionFilter(text)
        else:
            Settings().deleteExceptionFilter(text)
        self.__ignored.remove(text)
        self.__updateTitle()
        return

    def __onRemoveAllFromIgnore(self):
        " Triggered when all the ignored exceptions should be deleted "
        self.clear()

        project = GlobalData().project
        if project.isLoaded():
            project.setExceptionFilters([])
        else:
            Settings().setExceptionFilters([])
        return

    def isIgnored(self, exceptionType):
        " Returns True if this exception type should be ignored "
        return exceptionType in self.__ignored
コード例 #30
0
ファイル: nPhoto.py プロジェクト: g3rg/nPhoto
class NPhotoMainWindow(QMainWindow):
    rootAlbum = None
    currentPage = 0
    
    def __init__(self, parent=None):
        super(NPhotoMainWindow, self).__init__(parent)

        self.image = None 
        self.status = self.statusBar()
        self.status.setSizeGripEnabled(False)

        fileMenu = self.menuBar().addMenu("&File")
        fileEditAction = createAction(self, "&Edit", self.doEdit, "Ctrl-E", "fileedit", "Edit photo details")
        fileDeleteAction = createAction(self, "&Delete", self.doDelete, "Ctrl-D", "filedelete", "Delete selected file(s)")
        fileImportAction = createAction(self, "&Import", self.doImport, "Ctrl-I", "fileimport", "Import photos into your library")
        fileRescanLibraryAction = createAction(self, "&Rescan", self.doRescan, "Ctrl-R", "filerescan", "Rescan library folder and update sidecar files, and thumbnails")
        fileBackupAction = createAction(self, "&Backup", self.doBackup, "Ctrl-B", "filebkup", "Backup your library")
        fileSettingsAction = createAction(self, "&Settings", self.doSettings, "Ctrl-S", "filesettings", "Settings")
        fileQuitAction = createAction(self, "&Quit", self.close, "Ctrl+Q", "filequit", "Close the application")

        helpMenu = self.menuBar().addMenu("&Help")
        helpAboutAction = createAction(self, "&About", self.doAbout, None, "helpabout", "About nPhoto")
        
        addActions(fileMenu, (fileEditAction, fileDeleteAction, None, fileImportAction, fileRescanLibraryAction,
                              fileBackupAction, fileSettingsAction, None, fileQuitAction))
        addActions(helpMenu, (helpAboutAction,))
    
        size = getSettingQVar("MainWindow/Size", QSize(600,500)).toSize()
        self.resize(size)
        position = getSettingQVar("MainWindow/Position", QPoint(0,0)).toPoint()
        self.move(position)
        self.restoreState(getSettingQVar("MainWindow/State").toByteArray())
        self.setWindowTitle("nPhoto")

        self.controlFrame = QFrame()
        self.controlLayout = QBoxLayout(QBoxLayout.TopToBottom)

        #TODO Make this a combo box that populates the tree by date or by folder
        self.viewByCombo = QLabel("PLACEHOLDER")
        
        self.tree = QTreeWidget()

        self.tree.setColumnCount(1)
        self.tree.setHeaderLabels(["Album"])
        self.tree.setItemsExpandable(True)

        self.connect(self.tree, SIGNAL("itemSelectionChanged()"), self.treeSelection)

        self.controlLayout.addWidget(self.viewByCombo)
        self.controlLayout.addWidget(self.tree)

        self.controlFrame.setLayout(self.controlLayout)

        self.browserFrame = QFrame()

        self.browserGrid = QGridLayout()

        self.imageLabels = []
        for row in range(0,BROWSER_GRID_HEIGHT):
            self.imageLabels.append([])
            for col in range(0,BROWSER_GRID_WIDTH):
                self.imageLabels[row].append(QLabel())
                self.imageLabels[row][col].setBackgroundRole(QPalette.Base)
                self.imageLabels[row][col].setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
                self.imageLabels[row][col].setScaledContents = True
                self.imageLabels[row][col].setAlignment(Qt.AlignCenter)
                self.imageLabels[row][col].setStyleSheet("border:2px solid #000")

                dbl = functools.partial(self.imgDoubleClick, row, col)
                click = functools.partial(self.imgMouseRelease, row, col)
                
                self.imageLabels[row][col].mouseDoubleClickEvent = dbl
                self.imageLabels[row][col].mouseReleaseEvent = click
                self.browserGrid.addWidget(self.imageLabels[row][col],row,col)

        self.prevPage = QPushButton("Prev")
        self.pageInfoLabel = QLabel("Page 0 of 0")
        self.pageInfoLabel.setAlignment(Qt.AlignCenter)
        self.nextPage = QPushButton("Next")

        self.prevPage.clicked.connect(self.goPreviousPage)
        self.nextPage.clicked.connect(self.goNextPage)
        
        self.browserGrid.addWidget(self.prevPage, row+1, 0)
        self.browserGrid.addWidget(self.pageInfoLabel, row+1, 1)
        self.browserGrid.addWidget(self.nextPage, row+1, 2)

        self.browserFrame.setLayout(self.browserGrid)

        self.mainSplitter = QSplitter(Qt.Horizontal)
        self.mainSplitter.addWidget(self.controlFrame)
        self.mainSplitter.addWidget(self.browserFrame)
        self.mainSplitter.setStretchFactor(1,4)
        
        self.setCentralWidget(self.mainSplitter)

        self.mainSplitter.restoreState(getSettingQVar("MainWindow/Splitter").toByteArray())

        if getSettingStr("Paths/Library") not in (None, ''):
            QTimer.singleShot(0, self.loadLibrary)
        else:
            self.status.showMessage("No Library Path in settings", 10000)

    def getPhotoByBrowserLocation(self, row, col):
        idx = ((self.currentPage - 1) * BROWSER_THUMBS_PER_PAGE) + (row * BROWSER_GRID_WIDTH) + col
        if idx < len(self.currentAlbum.photos):
            return self.currentAlbum.photos[idx]
        else:
            return None

    def imgDoubleClick(self, row, col, event):

        if event.button() == Qt.LeftButton:
            if event.modifiers() & Qt.ControlModifier or event.modifiers() & Qt.AltModifier \
                    or event.modifiers() & Qt.ShiftModifier:
                pass
            else:
                curr = self.getPhotoByBrowserLocation(row,col)
                if curr:
                    self.currentSelection = [curr,]
                    self.highlightSelected()
                    self.doEdit()        

    def imgMouseRelease(self, row, col, event):
        if event.button() == Qt.LeftButton:
            if event.modifiers() & Qt.ControlModifier or event.modifiers() & Qt.AltModifier \
                or event.modifiers() & Qt.ShiftModifier:
                pass
            else:
                curr = self.getPhotoByBrowserLocation(row,col)
                if curr:
                    if not hasattr(self, "currentSelection"):
                        self.currentSelection = []

                    if curr in self.currentSelection:
                        self.currentSelection.remove(curr)
                    else:
                        self.currentSelection.append(curr)

        self.highlightSelected()

    def highlightSelected(self):
        if hasattr(self, "currentSelection"):
            for x in range(0, BROWSER_GRID_HEIGHT):
                for y in range(0, BROWSER_GRID_WIDTH):
                    ph = self.getPhotoByBrowserLocation(x,y)
                    if ph:
                        if ph in self.currentSelection:
                            self.imageLabels[x][y].setStyleSheet("border:2px solid #FFF")
                        else:
                            self.imageLabels[x][y].setStyleSheet("border:2px solid #000")



    def regenAlbumThumbnails(self, album):
        for al in album.albums:
            self.regenAlbumThumbnails(al)

        for ph in album.photos:
            createThumbnail(ph.path, True)
        
    def doRescan(self):
        #TODO Rebuild sidecar files!

        self.regenAlbumThumbnails(self.rootAlbum)
        self.reloadLibrary()

        

    def treeSelection(self):
        curr = self.tree.currentItem()
        path = curr.data(0,0).toString()
        tmp = curr
        while tmp.parent() is not None:
            tmp = tmp.parent()
            path = tmp.data(0,0).toString() + "." + path

        album = self.getAlbum(path)
        if hasattr(self, 'currentAlbum'):
            if self.currentAlbum != album:
                self.currentAlbum = album
        else:
            self.currentAlbum = album
        self.changeAlbums()

    def changeAlbums(self):
        if len(self.currentAlbum.photos) == 0:
            self.currentPage = 0
        else:
            self.currentPage = 1
        
        for row in range(0, BROWSER_GRID_HEIGHT):
            for col in range(0, BROWSER_GRID_WIDTH):
                if len(self.currentAlbum.photos)<= (row*BROWSER_GRID_WIDTH + col):
                    self.imageLabels[row][col].setPixmap(QPixmap())
                else:
                    self.imageLabels[row][col].setPixmap(loadQPixMap(self.image, self.currentAlbum.photos[
                            (BROWSER_THUMBS_PER_PAGE * (self.currentPage - 1)) + row*BROWSER_GRID_WIDTH+col]
                                                                          .path, self.imageLabels[0][0].width(), self.imageLabels[0][0].height(), True))
                    self.imageLabels[row][col].adjustSize()

        self.updatePageInfo()

    def loadPageThumbs(self):
        for row in range(0, BROWSER_GRID_HEIGHT):
            for col in range(0, BROWSER_GRID_WIDTH):
                if len(self.currentAlbum.photos)<= (
                            (BROWSER_THUMBS_PER_PAGE * (self.currentPage - 1)) + row*BROWSER_GRID_WIDTH + col):
                    self.imageLabels[row][col].setPixmap(QPixmap())
                else:
                    self.imageLabels[row][col].setPixmap(loadQPixMap(self.image, self.currentAlbum.photos[
                            (BROWSER_THUMBS_PER_PAGE * (self.currentPage - 1)) + row*BROWSER_GRID_WIDTH+col]
                                                                          .path, self.imageLabels[0][0].width(), self.imageLabels[0][0].height(), True))
                    self.imageLabels[row][col].adjustSize()


    def goPreviousPage(self):
        if self.currentPage > 1:
            self.currentPage -= 1
            self.loadPageThumbs()
            self.updatePageInfo()

    def goNextPage(self):
        if self.currentPage < self.getMaxPage():
            self.currentPage += 1
            self.loadPageThumbs()
            self.updatePageInfo()

    def getMaxPage(self):
        totalPages = len(self.currentAlbum.photos) / BROWSER_THUMBS_PER_PAGE
        if (len(self.currentAlbum.photos) % BROWSER_THUMBS_PER_PAGE) != 0:
            totalPages += 1
        return totalPages
        

    def updatePageInfo(self):
        if self.currentPage == 0:
            self.pageInfoLabel.setText("Page 0 of 0")
        else:
            self.pageInfoLabel.setText("Page %d of %d" % (self.currentPage, self.getMaxPage()))
                                                   
    def getAlbum(self, path):
        nodes = path.split(".")
        if nodes[0] != 'Library':
            print "WTF?!?!?!"
        else:
            album = self.rootAlbum
            for albumName in nodes[1:]:
                album = album.albums[unicode(albumName)]

            return album
        
    def doBackup(self):
        libDir = getSettingStr("Paths/Library")
        bkupPaths = getSettingStr("Paths/Backup")
        
        if libDir in (None,  ''):
            QMessageBox.warning(self, "Backup Failed", "You need to specify a library directory in your settings")
            return
        if not os.path.exists(libDir) or os.path.isfile(libDir):
            QMessageBox.warning(self, "Backup Failed", "The library directory in your settings either doesn't exist, or its not a directory")
            return        
        
        if bkupPaths in (None,  ''):
            QMessageBox.warning(self, "Backup Failed",  "You need to specify at least one backup directory in your settings")
            return

        dt = datetime.date.today()
        bkupDirName = str(dt.year) + str(dt.month) + str(dt.day)

        for path in bkupPaths.split(","):
            if not os.path.exists(path.strip()) or os.path.isfile(path.strip()):
                QMessageBox.warning(self, "Backup Failed", "The backup directory <%s> in your settings either doesn't exist, or its not a directory" % (path))
                return
        
            if os.path.exists(path.strip() + os.sep + bkupDirName):
                QMessageBox.warning(self, "Backup Failed", "There is already a backup for today in a backup directory <%s>" % (path.strip()))
                return
        
        for path in bkupPaths.split(","):
            shutil.copytree(libDir, path.strip() + os.sep + bkupDirName)
        
        QMessageBox.information(self, "Backup", "Backup completed!")

    def doDelete(self):
        if hasattr(self, "currentSelection"):
            if len(self.currentSelection) > 0:
                msg = "Are you sure you want to delete the selected image?"
                if len(self.currentSelection) > 1:
                    msg = "Are you sure you want to delete the %s selected images?" % len(self.currentSelection)
                    
                if QMessageBox.warning(self, "Delete Image(s)", msg,
                                             QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes:
                    for ph in self.currentSelection:
                        msg = ph.delete()
                        if msg not in (None, ''):
                            QMessageBox.warning(self, "Error while deleting", msg)
                            break

                    self.reloadLibrary()
                    

    def reloadLibrary(self):
        self.currentSelection = []
        self.highlightSelected()
        
        currPage = self.currentPage

        self.loadLibrary()
        if currPage > self.getMaxPage():
            #Assumes you can't delete more than one page worth of photos at a time
            currPage = self.getMaxPage()

        self.currentPage = currPage
        self.loadPageThumbs()
        self.updatePageInfo()


    def doEdit(self):
        if hasattr(self, "currentSelection"):
            if len(self.currentSelection) == 1:
                ph = self.currentSelection[0]
                comment = ph.comment
                keywords = (" ".join(ph.keywords)).strip()
                dialog = EditPhotoDialog(self, ph.path, comment, keywords)
                if dialog.exec_():
                    ph.comment = unicode(dialog.commentEdit.text()).strip()
                    ph.keywords = unicode(dialog.keywordEdit.text()).strip().split(" ")
                    ph.save(ph.path)

    def doSettings(self):
        libPath = getSettingStr("Paths/Library", "")
        backupPaths = getSettingStr("Paths/Backup", "")
        fileExt = getSettingStr("FileExtensions", "jpg, CR2")
        fileExtOther = getSettingStr("FileExtensionsOther", "mov, avi")
        
        
        dialog = SettingsDialog(self, libPath, backupPaths, fileExt, fileExtOther)
        if dialog.exec_():
            saveSetting("Paths/Library", dialog.libPathEdit.text())
            saveSetting("Paths/Backup", dialog.backupPathsEdit.text())
            saveSetting("FileExtensions", dialog.fileExtensionEdit.text())
            saveSetting("FileExtensionsOther", dialog.fileExtensionOtherEdit.text())
            
            self.status.showMessage("Settings updated", 5000)
            

    def buildTree(self, parentNode, parentAlbum):
        for name in parentAlbum.albums:
            childNode = QTreeWidgetItem(parentNode, [name])
            childAlbum = parentAlbum.albums[name]
            if childAlbum.albums != None and len(childAlbum.albums) > 0:
                self.buildTree(childNode, childAlbum)

    def loadLibrary(self):
        self.status.showMessage("Loading Photo Library")

        self.rootAlbum = self.loadAlbum(getSettingStr("Paths/Library"), "Library")

        if self.rootAlbum == None:
            self.rootAlbum = Album(name="Library")

        self.refreshTree()
        
        self.status.showMessage("Library successfully loaded", 5000)

    def refreshTree(self):
        self.tree.clear()
        node = QTreeWidgetItem(self.tree, ["Library"])
        self.buildTree(node, self.rootAlbum)
        self.tree.setCurrentItem(node)

    def loadAlbum(self, path, title = None):
        album = Album()
        if title not in (None, ''):
            album.name = title
        else:
            album.name = path[path.rfind(os.sep)+1:]
            
        album.albums = {}
        album.photos = []
        album.path = path

        files = os.listdir(path)
        files.sort()

        tmpPhotos = []
        for fl in files:
            if not os.path.isfile(path + os.sep + fl):
                album.albums[fl] = self.loadAlbum(path + os.sep + fl)
            else:
                if self.isImageFile(path + os.sep + fl):
                    ph = None
                    if os.path.exists(path + os.sep + fl + ".sidecar"):
                        ph = Photo.load(path + os.sep + fl + ".sidecar")
                    else:
                        ph = Photo()
                        ph.comment = ""
                        ph.keywords = {}
                        ph.srcPath = None
                        ph.path = path + os.sep + fl
                        exif = loadExif(path + os.sep + fl, EXIF_TAGS)
                        ph.setExif(exif)
                        ph.save(path + os.sep + fl)

                    ph.path = path + os.sep + fl
                    tmpPhotos.append(ph)

        album.photos = sorted(tmpPhotos, key = lambda photo: photo.date)
        return album

    def doImport(self):
        libPath = getSettingStr("Paths/Library")
        fileExt = getSettingStr("FileExtensions")
        
        if libPath in (None,  ''):
            QMessageBox.warning(self, "Import Failed",  "You need to specify a library directory in your settings")
            return
        
        if not os.path.exists(libPath) or os.path.isfile(libPath):
            QMessageBox.warning(self, "Import Failed", "The library directory in your settings either doesn't exist, or its not a directory")
            return
            
        if not fileExt or fileExt in (None, ''):
            QMessageBox.warning(self, "Import Failed", "You need to specify file extensions to manage in your settings")
            return

        lastImport = getSettingStr("Paths/LastImport")

        importFrom = QFileDialog.getExistingDirectory(self, "Choose a Path to Import From", lastImport)
        
        if importFrom in (None,  ''):
            return
        
        if not os.path.exists(importFrom) or os.path.isfile(importFrom):
            QMessageBox.warning(self, "Import Failed", "The import directory either doesn't exist, or is not a directory")
            return

        if importFrom == libPath:
            QMessageBox.warning(self, "Import Failed", "Your import directory and library directory can not be the same")
            return

        imd = ImportMetadataDialog(self)

        if imd.exec_():
            album = imd.albumEdit.text()
            comments = imd.commentsEdit.text()
            keywords = imd.keywordsEdit.text()
            
            if album and album not in (None, ''):
                albumpath = album + os.sep
            else:
                album = None
                albumpath = ""
            
            if not keywords or keywords in (None, ''):
                keywords = ""

            if not comments or comments in (None, ''):
                comments = ""

            paths = self.buildFileList(importFrom)
            numTotal = len(paths)
            
            nonDupes = self.removeDuplicates(paths, importFrom, albumpath)
            numDuplicates = numTotal - len(nonDupes)
            
            if QMessageBox.question(self, "Import", "Out of %d files found, %d look to be duplicates. Continue with import?"
                                    % (numTotal,  numDuplicates), QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes:
                
                saveSetting("Paths/LastImport", importFrom)
                
                for path in nonDupes:
                    dest = self.buildLibPath(importFrom, path, albumpath)
                    copyFileIncludingDirectories(path, dest)
                    # TODO Handle copy failure exceptions!
                    
                    if not os.path.exists(dest):
                        QMessageBox.warming(self, "Import Failed", "The file <%s> was not imported properly, aborting import" % (path))
                        return
                    if self.isImageFile(path):
                        exif = loadExif(unicode(path), EXIF_TAGS)
                        ph = Photo()
                        ph.path = dest
                        ph.srcPath = path
                        ph.comment = comments
                        ph.keywords = keywords
                        ph.setExif(exif)
                        ph.save(dest)

                        #Create Thumbnail
                        createThumbnail(unicode(ph.path))
                        
                QMessageBox.information(self, "Import", "Import completed")

                self.loadLibrary()
            
    def buildLibPath(self, importFrom, path, albumpath):
        relPath = path[len(importFrom):]
        libPath = getSettingStr("Paths/Library") + os.sep + albumpath + relPath
        
        return libPath

        
    def isImageFile(self, filepath):
        extensionList = unicode(getSettingStr("FileExtensions")).split(",")
        for extension in extensionList:
            if unicode(filepath).upper().endswith(unicode(extension).upper()):
                return True
        return False

    def isOtherManagedFile(self, filepath):
        #TODO Implement list of other files to import into lib folders and to backup
        extensionList = unicode(getSettingStr("FileExtensionsOther")).split(",")
        for extension in extensionList:
            if unicode(filepath).upper().endswith(unicode(extension).upper()):
                return True
        return False
    

        
    def removeDuplicates(self, paths, importFrom, albumpath):
        nonDupes = []
        
        for path in paths:
            libPath = self.buildLibPath(importFrom, path, albumpath)
            if not os.path.exists(libPath):
                nonDupes.append(path)
        
        return nonDupes

    def buildFileList(self, importFrom):
        #TODO Can probably be done with Glob or whatever it is?
        paths = []
        for f in os.listdir(importFrom):
            fullpath = importFrom + os.sep + f
            
            if not os.path.isfile(fullpath):
                paths.extend(self.buildFileList(fullpath))
            else:
                if self.isImageFile(fullpath):
                    paths.append(fullpath)
                elif self.isOtherManagedFile(fullpath):
                    paths.append(fullpath)
                    
        return paths

    def closeEvent(self, event):
        saveSetting("MainWindow/Size", self.size())
        saveSetting("MainWindow/Position", self.pos())
        saveSetting("MainWindow/State", self.saveState())
        saveSetting("MainWindow/Splitter", self.mainSplitter.saveState())

    def doAbout(self):
        QMessageBox.about(self, "About nPhoto",
                "<p>nPhoto allows simple reviewing, commenting, and keywording of images, useful for running"
                                " on a netbook while travelling, to then import into programs such as Lightroom"
                                " on return from your holiday</p>")
コード例 #31
0
ファイル: DBBrowser.py プロジェクト: pedromorgan/PyQtDb
class DBBrowser(QMainWindow):


    def __init__(self, parent, server):
        QMainWindow.__init__(self, parent)

        self.debug = False
        self.server = server
        
        self.db = None
        
        self.setWindowTitle("Database Browser")
        #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)


        topBar = QToolBar()
        
        self.addToolBar(Qt.TopToolBarArea, topBar)
        
        

        self.cenWid = QWidget()
        self.setCentralWidget(self.cenWid)
        
        self.mainLayout = QHBoxLayout()
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self.cenWid.setLayout( self.mainLayout )

        
        
        self.treeTables = QTreeWidget()
        self.mainLayout.addWidget(self.treeTables, 1)
        self.treeTables.setHeaderLabels(["Table"])
        self.treeTables.setSelectionBehavior( QAbstractItemView.SelectRows )
        self.treeTables.setSelectionMode( QTreeView.SingleSelection )
        self.connect( self.treeTables, SIGNAL( 'itemSelectionChanged()' ), self.on_table )
        
        
        self.treeColumns = QTreeWidget()
        self.mainLayout.addWidget(self.treeColumns, 4)
        self.treeColumns.setHeaderLabels(["Column", "Type", "Nullable"])
        
        self.db_connect()
        
        #self.fetch()
        
    def on_table(self):
        item = self.treeTables.currentItem()
        if item == None:
            return
        self.fetch( table = str(item.text(0)) )
        
    def db_connect(self):
        #print "db_connect", self.server
        self.db = QSqlDatabase.addDatabase("QMYSQL")
        self.db.setHostName(self.server['server'])
        self.db.setUserName(self.server['user'])
        self.db.setPassword(self.server['passwd'])
        
        ok = self.db.open()
        print "open", ok
        #self.db.setHostName(self.server['server'])
        
        
    def load_data(self, data):
        
        
        if "tables" in data:
            
            self.treeTables.clear()
            for t in data['tables']:
                item = QTreeWidgetItem()
                item.setText(0, t['table'])
                self.treeTables.addTopLevelItem(item)

        else:
            self.treeColumns.clear()
            for t in data['columns']:
                item = QTreeWidgetItem()
                item.setText(0, t['column'])
                item.setText(1, t['type'])
                item.setText(2, "Yes" if t['nullable'] else "-")
                self.treeColumns.addTopLevelItem(item)
コード例 #32
0
ファイル: arbol_simbolos.py プロジェクト: ekimdev/edis
class ArbolDeSimbolos(custom_dock.CustomDock):

    _ir_a_linea = pyqtSignal(int, name='irALinea')

    iconos = {
        'clase': paths.ICONOS['class'],
        'funcion': paths.ICONOS['funcion'],
        'struct': paths.ICONOS['struct'],
        'miembro': paths.ICONOS['miembro'],
        'global': paths.ICONOS['variable'],
        'enumerator': paths.ICONOS['enumerator'],
        'enums': paths.ICONOS['enums']
        }

    def __init__(self):
        custom_dock.CustomDock.__init__(self)
        self.tree = QTreeWidget()
        self.setWidget(self.tree)
        self.tree.setObjectName("simbolos")
        self.tree.header().setHidden(True)
        self.tree.setSelectionMode(self.tree.SingleSelection)
        self.tree.setAnimated(True)
        self.tree.header().setStretchLastSection(False)
        self.tree.header().setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self.tree.header().setResizeMode(0, QHeaderView.ResizeToContents)

        # Conexión
        self.tree.itemClicked[QTreeWidgetItem, int].connect(self.ir_a_linea)
        self.tree.itemActivated[QTreeWidgetItem, int].connect(self.ir_a_linea)

        EDIS.cargar_lateral("simbolos", self)

    def actualizar_simbolos(self, archivo):
        #FIXME: mover esto
        self.ctags = ectags.Ctags()
        tag = self.ctags.run_ctags(archivo)
        simbolos = self.ctags.parser(tag)
        self._actualizar_simbolos(simbolos)

    def _actualizar_simbolos(self, simbolos):
        #FIXME:
        # Limpiar
        self.tree.clear()
        if simbolos is None:
            no_ctags = Item(self.tree, [self.tr('Ctags no está instalado.')])
            no_ctags.clickeable = False
            return

        if 'variable' in simbolos:
            variables = Item(self.tree, [self.tr('Variables')])
            variables.clickeable = False
            for v in simbolos['variable']:
                variable = Item(variables, [v.get('nombre')])
                linea = v['linea']
                variable.linea = linea
                variable.setIcon(0, QIcon(self.iconos['global']))
            variables.setExpanded(True)

        if 'function' in simbolos:
            funciones = Item(self.tree, [self.tr('Funciones')])
            funciones.clickeable = False
            for f in simbolos['function']:
                funcion = Item(funciones, [f.get('nombre')])
                linea = f['linea']
                funcion.linea = linea
                funcion.setIcon(0, QIcon(self.iconos['funcion']))
            funciones.setExpanded(True)

        if 'struct' in simbolos:
            structs = Item(self.tree, [self.tr('Estructuras')])
            structs.clickeable = False
            for s in simbolos['struct']:
                struct = Item(structs, [s.get('nombre')])
                linea = s['linea']
                struct.linea = linea
                struct.setIcon(0, QIcon(self.iconos['struct']))
            structs.setExpanded(True)

        if 'member' in simbolos:
            miembros = Item(self.tree, [self.tr('Miembros')])
            miembros.clickeable = False
            for m in simbolos['member']:
                nombre = m['nombre'] + ' [' + m['padre'] + ']'
                miembro = Item(miembros, [nombre])
                miembro.setIcon(0, QIcon(self.iconos['miembro']))
                linea = m['linea']
                miembro.linea = linea

            miembros.setExpanded(True)

    def ir_a_linea(self, item):
        if item.clickeable:
            self._ir_a_linea.emit(int(item.linea) - 1)
コード例 #33
0
ファイル: info.py プロジェクト: johnjohnsp1/dff
class Info(QDockWidget):
    def __init__(self, mainWindow):
        super(Info, self).__init__()
        self.__mainWindow = mainWindow
        self.loader = loader.loader()
        self.env = env.env()
        self.tm = TaskManager()
        self.addAction()
        self.configure()
        self.g_display()
        self.initCallback()
        self.Load()

    def configure(self):
        self.setAllowedAreas(Qt.AllDockWidgetAreas)
        self.setObjectName("dockWidgetBrowser")
        self.setWindowTitle(QApplication.translate("Info", "Info", None, QApplication.UnicodeUTF8))

    def addAction(self):
        self.__action = QAction(self)
        self.__action.setCheckable(True)
        self.__action.setChecked(True)
        self.__action.setObjectName("actionCoreInformations")
        self.__action.setText(QApplication.translate("MainWindow", "Info", None, QApplication.UnicodeUTF8))
        self.__mainWindow.menuWindow.addAction(self.__action)
        self.connect(self.__action, SIGNAL("triggered()"), self.changeVisibleInformations)

    def changeVisibleInformations(self):
        if not self.isVisible():
            self.setVisible(True)
            self.__action.setChecked(True)
        else:
            self.setVisible(False)
            self.__action.setChecked(False)

    def g_display(self):
        self.Info = QWidget(self)
        self.layout = QHBoxLayout(self.Info)
        self.Info.setLayout(self.layout)
        self.tabWidget = QTabWidget(self)
        self.tabWidget.setElideMode(Qt.ElideRight)
        self.initTreeProcess()
        self.initTreeModule()
        self.initTreeEnv()
        self.layout.addWidget(self.tabWidget)
        self.setWidget(self.Info)

    def initCallback(self):
        self.connect(self, SIGNAL("visibilityChanged(bool)"), self.visibilityChanged)
        self.timer = QTimer(self)
        self.connect(self.timer, SIGNAL("timeout()"), self.refresh)
        self.timer.start(2000)

    def visibilityChanged(self, bool):
        if not self.isVisible():
            self.__action.setChecked(False)
        else:
            self.__action.setChecked(True)

    def Load(self):
        self.LoadInfoProcess()
        self.LoadInfoModules()
        self.LoadInfoEnv()
        pass

    def refresh(self):
        self.LoadInfoProcess()
        self.LoadInfoModules()
        self.LoadInfoEnv()
        pass

    def deleteInfos(self):
        self.deleteInfoProcess()
        self.deleteInfoModule()
        self.deleteInfoEnv()

    # MODULES

    def initTreeModule(self):
        self.treeModule = QTreeWidget(self)
        self.treeModule.setColumnCount(3)
        headerLabel = [
            QApplication.translate("Info", "Name", None, QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Key", None, QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Value", None, QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Info", None, QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Type", None, QApplication.UnicodeUTF8),
        ]
        self.treeModule.setHeaderLabels(headerLabel)
        self.treeModule.setAlternatingRowColors(True)
        self.tabWidget.addTab(self.treeModule, "Modules")
        self.itemModuleDic = dict()
        self.itemListArgDic = dict()
        self.itemArgDic = dict()
        self.itemListResDic = dict()
        self.itemResDic = dict()

    def LoadInfoModules(self):
        modules = self.loader.modules
        for mod in modules:
            try:
                itemModule = self.itemModuleDic[mod]
            except KeyError:
                itemModule = QTreeWidgetItem(self.treeModule)
                self.itemModuleDic[mod] = itemModule
                itemModule.setText(0, str(mod))
                itemConfig = QTreeWidgetItem(itemModule)
                itemConfig.setText(0, "Config")
                cdesc = modules[mod].conf.descr_l
                for key in cdesc:
                    itemConfKey = QTreeWidgetItem(itemConfig)
                    itemConfKey.setText(0, "var")
                    itemConfKey.setText(1, key.name)
                    itemConfKey.setText(4, key.type)
                    if len(key.description):
                        itemConfKey.setText(3, key.description)
                for type, name, val, _from in self.env.get_val_list(modules[mod].conf.val_l):
                    itemConfKey = QTreeWidgetItem(itemConfig)
                    itemConfKey.setText(0, "const")
                    itemConfKey.setText(1, name)
                    itemConfKey.setText(2, val)
                    itemConfKey.setText(4, type)
            for proc in self.tm.lprocessus:
                if proc.mod.name == mod:
                    try:
                        itemListArg = self.itemListArgDic[mod]
                    except KeyError:
                        itemListArg = QTreeWidgetItem(itemModule)
                        self.itemListArgDic[mod] = itemListArg
                        itemListArg.setText(0, "Arg")
                    for type, name, val in self.env.get_val_map(proc.args.val_m):
                        try:
                            itemArgKey = self.itemArgDic[(type, name, val)]
                        except KeyError:
                            itemArgKey = QTreeWidgetItem(itemListArg)
                            self.itemArgDic[(type, name, val)] = itemArgKey
                            itemArgKey.setText(1, name)
                            itemArgKey.setText(2, val)
                            itemArgKey.setText(4, type)
                    try:
                        itemListRes = self.itemListResDic[mod]
                    except KeyError:
                        itemListRes = QTreeWidgetItem(itemModule)
                        self.itemListResDic[mod] = itemListRes
                        itemListRes.setText(0, "Results")
                    if proc.res:
                        for type, name, val in self.env.get_val_map(proc.res.val_m):
                            try:
                                itemResKey = self.itemResDic[(type, name, val)]
                            except KeyError:
                                itemResKey = QTreeWidgetItem(itemListRes)
                                self.itemResDic[(type, name, val)] = itemResKey
                                itemResKey.setText(1, name)
                                itemResKey.setText(2, val)
                                itemResKey.setText(4, type)

    def deleteInfoModule(self):
        self.treeModule.clear()

    # ENV
    def initTreeEnv(self):
        self.treeEnv = QTreeWidget(self)
        self.treeEnv.setColumnCount(3)
        headerLabel = [
            QApplication.translate("Info", "Key", None, QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Type", None, QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Value", None, QApplication.UnicodeUTF8),
            QApplication.translate("Info", "From", None, QApplication.UnicodeUTF8),
        ]
        self.treeEnv.setHeaderLabels(headerLabel)
        self.treeEnv.setAlternatingRowColors(True)
        self.tabWidget.addTab(self.treeEnv, "Environment")
        self.envItemDic = dict()
        self.envConfKeyDic = dict()
        self.envValKeyDic = dict()

    def LoadInfoEnv(self):
        db = self.env.vars_db
        for key in db:
            try:
                (itemEnv, itemVar, itemValues) = self.envItemDic[key]
            except KeyError:
                itemEnv = QTreeWidgetItem(self.treeEnv)
                itemEnv.setText(0, key)
                itemVar = QTreeWidgetItem(itemEnv)
                itemVar.setText(0, "var")
                itemValues = QTreeWidgetItem(itemEnv)
                self.envItemDic[key] = (itemEnv, itemVar, itemValues)
            cdesc = db[key].descr_l
            for vk in cdesc:
                try:
                    itemConfKey = self.envConfKeyDic[(vk.type, vk._from)]
                except KeyError:
                    itemConfKey = QTreeWidgetItem(itemVar)
                    self.envConfKeyDic[(vk.type, vk._from)] = itemConfKey
                    itemConfKey.setText(1, vk.type)
                    itemConfKey.setText(3, vk._from)
            itemValues.setText(0, "values")
            for type, name, val, _from in self.env.get_val_list(db[key].val_l):
                try:
                    itemValKey = self.envValKeyDic[(type, _from, val)]
                except:
                    itemValKey = QTreeWidgetItem(itemValues)
                    self.envValKeyDic[(type, _from, val)] = itemValKey
                    itemValKey.setText(1, type)
                    itemValKey.setText(2, val)
                    itemValKey.setText(3, _from)

    def deleteInfoEnv(self):
        self.treeEnv.clear()

    # PROCESSUS

    def initTreeProcess(self):
        self.treeProcess = QTreeWidget(self)
        self.treeProcess.setColumnCount(3)
        headerLabel = [
            QApplication.translate("Info", "PID", None, QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Name", None, QApplication.UnicodeUTF8),
            QApplication.translate("Info", "State", None, QApplication.UnicodeUTF8),
            QApplication.translate("Info", "Info", None, QApplication.UnicodeUTF8),
        ]
        self.treeProcess.setHeaderLabels(headerLabel)
        self.treeProcess.setAlternatingRowColors(True)
        self.tabWidget.addTab(self.treeProcess, "Task Manager")
        self.connect(self.treeProcess, SIGNAL("itemDoubleClicked(QTreeWidgetItem*,int)"), self.procClicked)
        self.procItemDic = dict()
        self.procChildItemDic = dict()

    def procClicked(self, item, column):
        dial = procMB(self, item.text(0))
        dial.exec_()

    def LoadInfoProcess(self):
        lproc = self.tm.lprocessus
        for proc in lproc:
            try:
                item = self.procItemDic[proc]
            except KeyError:
                item = QTreeWidgetItem(self.treeProcess)
                self.procItemDic[proc] = item
                item.setText(0, str(proc.pid))
                item.setText(1, str(proc.name))
            if item.text(2) != str(proc.state):
                item.setText(2, str(proc.state))
            if item.text(3) != str(proc.stateinfo):
                item.setText(3, str(proc.stateinfo))

    def deleteInfoProcess(self):
        self.treeProcess.clear()
コード例 #34
0
class ThreadsViewer(QWidget):
    " Implements the threads viewer for a debugger "

    def __init__(self, debugger, parent=None):
        QWidget.__init__(self, parent)

        self.__debugger = debugger
        self.__createLayout()

        if Settings().showThreadViewer == False:
            self.__onShowHide(True)
        return

    def __createLayout(self):
        " Creates the widget layout "

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

        self.headerFrame = QFrame()
        self.headerFrame.setFrameStyle(QFrame.StyledPanel)
        self.headerFrame.setAutoFillBackground(True)
        headerPalette = self.headerFrame.palette()
        headerBackground = headerPalette.color(QPalette.Background)
        headerBackground.setRgb(min(headerBackground.red() + 30, 255),
                                min(headerBackground.green() + 30, 255),
                                min(headerBackground.blue() + 30, 255))
        headerPalette.setColor(QPalette.Background, headerBackground)
        self.headerFrame.setPalette(headerPalette)
        self.headerFrame.setFixedHeight(24)

        self.__threadsLabel = QLabel("Threads")

        expandingSpacer = QSpacerItem(10, 10, QSizePolicy.Expanding)
        fixedSpacer = QSpacerItem(3, 3)

        self.__showHideButton = QToolButton()
        self.__showHideButton.setAutoRaise(True)
        self.__showHideButton.setIcon(PixmapCache().getIcon('less.png'))
        self.__showHideButton.setFixedSize(20, 20)
        self.__showHideButton.setToolTip("Hide threads list")
        self.__showHideButton.setFocusPolicy(Qt.NoFocus)
        self.__showHideButton.clicked.connect(self.__onShowHide)

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins(0, 0, 0, 0)
        headerLayout.addSpacerItem(fixedSpacer)
        headerLayout.addWidget(self.__threadsLabel)
        headerLayout.addSpacerItem(expandingSpacer)
        headerLayout.addWidget(self.__showHideButton)
        self.headerFrame.setLayout(headerLayout)

        self.__threadsList = QTreeWidget()
        self.__threadsList.setSortingEnabled(False)
        # I might not need that because of two reasons:
        # - the window has no focus
        # - the window has custom current indicator
        # self.__threadsList.setAlternatingRowColors( True )
        self.__threadsList.setRootIsDecorated(False)
        self.__threadsList.setItemsExpandable(False)
        self.__threadsList.setUniformRowHeights(True)
        self.__threadsList.setSelectionMode(QAbstractItemView.NoSelection)
        self.__threadsList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.__threadsList.setItemDelegate(NoOutlineHeightDelegate(4))
        self.__threadsList.setFocusPolicy(Qt.NoFocus)

        self.__threadsList.itemClicked.connect(self.__onThreadClicked)
        self.__threadsList.setHeaderLabels(["", "Name", "State", "TID"])

        verticalLayout.addWidget(self.headerFrame)
        verticalLayout.addWidget(self.__threadsList)
        return

    def __onShowHide(self, startup=False):
        " Triggered when show/hide button is clicked "
        if startup or self.__threadsList.isVisible():
            self.__threadsList.setVisible(False)
            self.__showHideButton.setIcon(PixmapCache().getIcon('more.png'))
            self.__showHideButton.setToolTip("Show threads list")

            self.__minH = self.minimumHeight()
            self.__maxH = self.maximumHeight()

            self.setMinimumHeight(self.headerFrame.height())
            self.setMaximumHeight(self.headerFrame.height())

            Settings().showThreadViewer = False
        else:
            self.__threadsList.setVisible(True)
            self.__showHideButton.setIcon(PixmapCache().getIcon('less.png'))
            self.__showHideButton.setToolTip("Hide threads list")

            self.setMinimumHeight(self.__minH)
            self.setMaximumHeight(self.__maxH)

            Settings().showThreadViewer = True
        return

    def __resizeColumns(self):
        " Resize the files list columns "
        self.__threadsList.header().setStretchLastSection(True)
        self.__threadsList.header().resizeSections(
            QHeaderView.ResizeToContents)
        self.__threadsList.header().resizeSection(0, 22)
        self.__threadsList.header().setResizeMode(0, QHeaderView.Fixed)
        return

    def clear(self):
        " Clears the content "
        self.__threadsList.clear()
        self.__threadsLabel.setText("Threads")
        return

    def populate(self, currentThreadID, threadList):
        " Populates the thread list from the client "
        self.clear()
        for thread in threadList:
            if thread['broken']:
                state = "Waiting at breakpoint"
            else:
                state = "Running"
            item = ThreadItem(thread['id'], thread['name'], state)
            if thread['id'] == currentThreadID:
                item.setCurrent(True)
            self.__threadsList.addTopLevelItem(item)

        self.__resizeColumns()
        self.__threadsLabel.setText("Threads (total: " + str(len(threadList)) +
                                    ")")
        return

    def switchControl(self, isInIDE):
        " Switches the UI depending where the control flow is "
        self.__threadsList.setEnabled(isInIDE)
        return

    def __onThreadClicked(self, item, column):
        " Triggered when a thread is clicked "
        if item.isCurrent():
            return

        for index in xrange(self.__threadsList.topLevelItemCount()):
            listItem = self.__threadsList.topLevelItem(index)
            if listItem.isCurrent():
                listItem.setCurrent(False)
                break
        item.setCurrent(True)

        self.__debugger.remoteSetThread(item.getTID())
        return
コード例 #35
0
ファイル: main.py プロジェクト: birkenfeld/marche
 def clear(self):
     self._client.stopPoller()
     self._items.clear()
     QTreeWidget.clear(self)
コード例 #36
0
class ChooseSectionsPage(QIWizardPage):
    """
    page to choose the sections that should be compared in the table
    """

    def __init__(self, parent=None):
        super(ChooseSectionsPage, self).__init__(parent)
        self.selected_sections = []  # sections in the right tree
        self.sections = []  # all sections without the selected
        self.filtered_sections = []  # filtered sections without the selected
        self.initUI()

    def initUI(self):

        mainlayout = QVBoxLayout()

        # layout containing the treewidgets
        sectionlistlayout = QHBoxLayout()

        # layout for filter form
        filterbox = QGroupBox("Filter")

        self.LEsecname = QLineEdit()
        self.LEsectype = QLineEdit()
        self.LEpropname = QLineEdit()

        filterlayout = QGridLayout()
        filterlayout.addWidget(QLabel("Section Name"), 1, 0)
        filterlayout.addWidget(QLabel("Section Type"), 2, 0)
        filterlayout.addWidget(QLabel("Property Name"), 3, 0)
        filterlayout.addWidget(self.LEsecname, 1, 1)
        filterlayout.addWidget(self.LEsectype, 2, 1)
        filterlayout.addWidget(self.LEpropname, 3, 1)
        filterbox.setLayout(filterlayout)

        self.LEsecname.textChanged.connect(self.filterSections)
        self.LEsectype.textChanged.connect(self.filterSections)
        self.LEpropname.textChanged.connect(self.filterSections)

        # define layout for the trre-widgets containing the sections
        self.section_tree = QTreeWidget()
        self.section_tree.setColumnCount(2)
        self.section_tree.setHeaderLabels(["Name", "Path"])
        self.section_tree.itemDoubleClicked.connect(self.toright)

        self.selection_tree = QTreeWidget()
        self.selection_tree.setColumnCount(2)
        self.selection_tree.setHeaderLabels(["Name", "Path"])
        self.selection_tree.itemDoubleClicked.connect(self.toleft)

        self.selection_tree.setSelectionMode(3)
        self.section_tree.setSelectionMode(3)

        self.settings.register("selected_secs", self.selected_sections)

        # buttons to move items of the tree-widgets
        movebuttonlayout = QVBoxLayout()
        btn_right = QToolButton()
        btn_right.setArrowType(Qt.RightArrow)
        btn_right.clicked.connect(self.toright)
        btn_left = QToolButton()
        btn_left.setArrowType(Qt.LeftArrow)
        btn_left.clicked.connect(self.toleft)

        movebuttonlayout.addStretch(1)
        movebuttonlayout.addWidget(btn_right)
        movebuttonlayout.addSpacing(1)
        movebuttonlayout.addWidget(btn_left)
        movebuttonlayout.addStretch(1)

        sectionlistlayout.addWidget(self.section_tree)
        sectionlistlayout.addSpacing(1)
        sectionlistlayout.addLayout(movebuttonlayout)
        sectionlistlayout.addSpacing(1)
        sectionlistlayout.addWidget(self.selection_tree)

        mainlayout.addLayout(sectionlistlayout)
        self.selectallcb = QCheckBox('select all (Ctrl+A)')
        self.selectallcb.stateChanged.connect(self.selectall)
        mainlayout.addWidget(self.selectallcb)
        mainlayout.addWidget(filterbox)

        self.setTitle("Select Sections")
        self.setLayout(mainlayout)
        self.adjustSize()

    def initializePage(self):

        # load sections and properties from the selected file
        odmldoc = odml.tools.xmlparser.load(self.settings.get_object(
                "inputfilename"))
        for section in odmldoc.itersections():
            self.sections.append([section.name,
                                  section.get_path(),
                                  [p.name for p in section.properties],
                                  section.type])

        # fill tree widget with sections and properties
        for line in self.sections:
            parent = QTreeWidgetItem([line[0], line[1]])
            for p in line[2]:
                QTreeWidgetItem(parent, [str(p)])
            self.section_tree.addTopLevelItem(parent)

        self.filtered_sections = list(self.sections)
        self.setTitle("Choose Sections")
        self.setSubTitle("Choose the sections you want to compare")

    def _get_selected_rows(self, tree):
        """
        function to determine the selected rows in a specified QTreeWidget
        """

        rows = []
        for index in tree.selectedIndexes():
            if index.parent().row() is -1:
                rows.append(index.row())
            else:
                # if a property is selected, the whole section containing this
                # property shall be moved
                rows.append(index.parent().row())

        # sort rownumbers in descending order to prevent shifting when moving
        # the items
        return sorted(list(set(rows)), reverse=True)

    def toright(self):
        """
        function to shift items from the left TreeWidget to the right
        """

        rows = self._get_selected_rows(self.section_tree)
        for row in rows:
            self.selection_tree.addTopLevelItem(
                    self.section_tree.takeTopLevelItem(row))
            self.selected_sections.append(self.sections.pop(
                    self.sections.index(self.filtered_sections[row])))
            self.filtered_sections.pop(row)

    def toleft(self):
        """
        function to shift items from the right TreeWidget to the left
        """

        rows = self._get_selected_rows(self.selection_tree)
        for row in rows:
            self.section_tree.addTopLevelItem(
                    self.selection_tree.takeTopLevelItem(row))
            item = self.selected_sections.pop(row)
            self.sections.append(item)
            self.filtered_sections.append(item)

    def filterSections(self):

        # find sections that match the filter
        self.filtered_sections = [s for s in self.sections
                                  if str(self.LEsecname.text()) in s[0]
                                  and str(self.LEsectype.text()) in s[3]
                                  and any([str(self.LEpropname.text())
                                           in p for p in s[2]])]
        # clear left treewidget
        self.section_tree.clear()

        # fill left treewidget with the filtered sections
        for line in self.filtered_sections:
            parent = QTreeWidgetItem([line[0], line[1]])
            for p in line[2]:
                QTreeWidgetItem(parent, [p])
            self.section_tree.addTopLevelItem(parent)

    def selectall(self):
        if self.selectallcb.isChecked():
            self.section_tree.selectAll()
        else:
            self.section_tree.clearSelection()

    def validatePage(self):
        if not self.settings.get_object("selected_secs"):
            QMessageBox.warning(self, 'No sections chosen',
                                'You should choose at least two sections to be '
                                'compared in the table.')
            return 0
        return 1
コード例 #37
0
ファイル: Probes.py プロジェクト: jfillatre/extensivetesting
class WProbes(QWidget, Logger.ClassLogger):
    """
    Widget for probes
    """
    def __init__(self, parent):
        """
        Constructs WProbes widget

        @param parent: 
        @type parent:
        """
        QWidget.__init__(self, parent)
        self.parent = parent
        self.name = self.tr("Probes")
        self.itemCurrentRunning = None
        self.itemCurrentInstalled = None
        self.itemCurrentDefault = None
        self.probes = {}

        self.nbPrbs = 0
        # self.prbsInstalled = None

        self.createWidgets()
        self.createConnections()
        self.createActions()
        self.createToolbar()
        self.deactivate()

    def createWidgets (self):
        """
        QtWidgets creation

        QTreeWidget (Name, Running on address, Type, Sched at, Version, Description)
         _______________
        |               |
        |---------------|
        |               |
        |               |
        |_______________|
        """
        layout = QHBoxLayout()

        self.deployBox = QGroupBox("Default probes")
        self.probesAvailable = QTreeWidget(self)
        self.probesAvailable.setIndentation(10)
        self.labelsAvail = [ self.tr("Installed") ]
        self.probesAvailable.setHeaderLabels(self.labelsAvail)

        self.runningBox = QGroupBox("Running")
        self.probesRegistered = QTreeWidget(self)
        self.probesRegistered.setIndentation(10)
        self.runningDockToolbar = QToolBar(self)
        self.runningDockToolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.availDockToolbar = QToolBar(self)
        self.availDockToolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)

        self.labels = [ self.tr("Name"), self.tr("Running on address"), self.tr("Started at"), 
                        self.tr("Type"), self.tr("Auto Startup"), self.tr("Description") ]        
        self.probesRegistered.setHeaderLabels(self.labels)
        self.probesRegistered.setColumnWidth(0, 180)
        self.probesRegistered.setColumnWidth(1, 120)
        self.probesRegistered.setColumnWidth(2, 150)
        self.probesRegistered.setColumnWidth(3, 70)
        self.probesRegistered.setContextMenuPolicy(Qt.CustomContextMenu)

        self.probesDefault = QTreeWidget(self)
        self.probesDefault.setIndentation(10)
        self.labelsDefault = [ self.tr("Enabled"), self.tr("Name"), self.tr("Type"), self.tr("Description") ]
        self.probesDefault.setHeaderLabels(self.labelsDefault)
        self.probesDefault.setContextMenuPolicy(Qt.CustomContextMenu)
        self.probesDefault.setColumnWidth(1, 180)


        layoutRunning = QVBoxLayout()
        layoutRunning.addWidget(self.runningDockToolbar)
        layoutRunning.addWidget(self.probesRegistered)
        self.runningBox.setLayout(layoutRunning)

        self.probeNameEdit = QLineEdit('')
        self.probeNameEdit.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Fixed )

        self.probeDescEdit = QLineEdit('')
        self.probeDescEdit.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Fixed )

        self.probeTypeEdit = QLineEdit('')
        self.probeTypeEdit.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Fixed )
        self.probeTypeEdit.setEnabled(False)
        
        self.probeDescrInstalledEdit = QTextEdit('')
        self.probeDescrInstalledEdit.setEnabled(False)
        
        self.checkAutoStartOption = QCheckBox()
        self.checkStartNowOption = QCheckBox()

        paramLayout = QGridLayout()
        paramLayout.addWidget(QLabel("Type:"), 0, 0, Qt.AlignRight)
        paramLayout.addWidget(self.probeTypeEdit, 0, 1)
        paramLayout.addWidget(QLabel("Name:"), 1, 0, Qt.AlignRight)
        paramLayout.addWidget(self.probeNameEdit, 1, 1)
        paramLayout.addWidget(QLabel("Description:"), 2, 0, Qt.AlignRight)
        paramLayout.addWidget(self.probeDescEdit, 2, 1)
        paramLayout.addWidget(QLabel("Startup on boot:"), 3, 0, Qt.AlignRight)
        paramLayout.addWidget(self.checkAutoStartOption, 3, 1)
        paramLayout.addWidget(QLabel("Start now:"), 4, 0, Qt.AlignRight)
        paramLayout.addWidget(self.checkStartNowOption, 4, 1)
      
        layoutLeft = QVBoxLayout()

        layoutAvail = QHBoxLayout()
        layoutAvail.addWidget(self.probesAvailable)
        layoutAvail.addWidget(self.probeDescrInstalledEdit)
        
        layoutLeft.addLayout(layoutAvail)
        layoutLeft.addWidget(self.runningBox)

        layoutDeploy = QVBoxLayout()
        layoutDeploy.addWidget(self.availDockToolbar)
        layoutDeploy.addLayout(paramLayout)
        layoutDeploy.addWidget(self.probesDefault)
        self.deployBox.setLayout(layoutDeploy)

        layoutRight = QVBoxLayout()
        layoutRight.addWidget(self.deployBox)   

        layout.addLayout(layoutLeft)
        layout.addLayout(layoutRight)
        self.setLayout(layout)

    def createConnections (self):
        """
        Create Qt Connections
        """
        self.probesRegistered.customContextMenuRequested.connect(self.onPopupMenu)
        self.probesRegistered.currentItemChanged.connect(self.currentItemChanged)
        self.probesRegistered.itemClicked.connect(self.itemClicked)

        self.probesAvailable.currentItemChanged.connect(self.currentItemChanged)

        self.probesDefault.currentItemChanged.connect(self.currentItemChanged)
        self.probesDefault.customContextMenuRequested.connect(self.onPopupMenuDefault)

    def createActions (self):
        """
        Actions defined:
         * stop probe
         * start probe
         * delete one probe
         * clear fields
         * refresh running probes
         * refresh default probes
        """
        self.stopAction = QtHelper.createAction(self, "&Stop", self.stopProbe, tip = 'Stop probe', 
                                        icon = QIcon(":/act-stop.png"))
        self.startAction = QtHelper.createAction(self, "&Add / Start", self.startProbe, tip = 'Add default probe', 
                                        icon = QIcon(":/probe-add.png"))
        self.delProbeAction = QtHelper.createAction(self, "&Delete", self.delProbe, tip = 'Delete default probe', 
                                        icon = QIcon(":/probe-del.png"))
        self.cancelAction = QtHelper.createAction(self, "&Clear", self.resetProbe, tip = 'Clear fields', 
                                        icon = QIcon(":/clear.png") )
        self.refreshRunningAction = QtHelper.createAction(self, "&Refresh", 
                                        self.refreshRunningProbe, tip = 'Refresh running probes', 
                                        icon = QIcon(":/act-refresh.png") )
        self.refreshDefaultAction = QtHelper.createAction(self, "&Refresh", 
                                        self.refreshDefaultProbe, tip = 'Refresh default probes', 
                                        icon = QIcon(":/act-refresh.png") )

    def createToolbar(self):
        """
        Toolbar creation
            
        ||-------||
        || Empty ||
        ||-------||
        """
        self.runningDockToolbar.setObjectName("Registered Probe toolbar")
        self.runningDockToolbar.addAction(self.refreshRunningAction)
        self.runningDockToolbar.addSeparator()
        self.runningDockToolbar.addAction(self.stopAction)
        self.runningDockToolbar.addSeparator()
        self.runningDockToolbar.setIconSize(QSize(16, 16))

        self.availDockToolbar.setObjectName("Installed Probe toolbar")
        self.availDockToolbar.addAction(self.refreshDefaultAction)
        self.availDockToolbar.addSeparator()
        self.availDockToolbar.addAction(self.startAction)
        self.availDockToolbar.addAction(self.delProbeAction)
        self.availDockToolbar.addSeparator()
        self.availDockToolbar.addAction(self.cancelAction)
        self.availDockToolbar.addSeparator()
        self.availDockToolbar.setIconSize(QSize(16, 16))

    def itemClicked(self, currentItem):
        """
        On item clicked

        @param currentItem: 
        @type currentItem:  
        """
        if currentItem is not None:
            if isinstance( currentItem, ProbeItem ):
                self.itemCurrentRunning = currentItem
                self.stopAction.setEnabled(True)

    def currentItemChanged(self, currentItem, previousItem):
        """
        On current item changed

        @param currentItem: 
        @type currentItem:  

        @param previousItem: 
        @type previousItem: 
        """
        if currentItem is not None:
            if isinstance( currentItem, ProbeInstalledItem ):
                self.itemCurrentInstalled = currentItem
                if 'description' in currentItem.dataProbe:
                    self.probeDescrInstalledEdit.setText( currentItem.dataProbe['description'] )
                    self.probeTypeEdit.setText( currentItem.dataProbe['type'] )
                else:
                    self.probeDescrInstalledEdit.setText( '' )
            elif isinstance( currentItem, ProbeItem ):
                self.itemCurrentRunning = currentItem
                self.stopAction.setEnabled(True)
            elif isinstance( currentItem, ProbeDefaultItem ):
                self.itemCurrentDefault = currentItem
                self.delProbeAction.setEnabled(True)
            else:
                self.stopAction.setEnabled(False)
                self.delProbeAction.setEnabled(False)
                self.probeDescrInstalledEdit.setText( '' )

    def onPopupMenu(self, pos):
        """
        Display menu on right click

        @param pos: 
        @type pos:
        """
        self.menu = QMenu()
        item = self.probesRegistered.itemAt(pos)
        if item:
            self.itemCurrentRunning = item
            self.menu.addAction( "Stop...", self.stopProbe)
            self.menu.popup(self.probesRegistered.mapToGlobal(pos))

    def onPopupMenuDefault(self, pos):
        """
        Display menu on right click

        @param pos: 
        @type pos:
        """
        self.menu = QMenu()
        item = self.probesDefault.itemAt(pos)
        if item:
            self.itemCurrentDefault = item
            self.menu.addAction( "Delete...", self.delProbe)
            self.menu.popup(self.probesDefault.mapToGlobal(pos))


    def refreshDefaultProbe(self):
        """
        Refresh the default list of probes
        """
        RCI.instance().defaultProbes()
        
    def refreshRunningProbe(self):
        """
        Refresh the running list of probes
        """
        RCI.instance().runningProbes()
        
    def delProbe(self):
        """
        Delete probe
        """
        if self.itemCurrentDefault is not None:
            reply = QMessageBox.question(self, "Stop probe", "Are you sure ?",
                QMessageBox.Yes | QMessageBox.No )
            if reply == QMessageBox.Yes:
                probeName = self.itemCurrentDefault.dataProbe['name']
                self.delProbeAction.setEnabled(False)
                
                # rest call
                RCI.instance().removeProbe(probeName=probeName)
                
    def stopProbe(self):
        """
        Stop the selected probe
        """
        if self.itemCurrentRunning is not None:
            reply = QMessageBox.question(self, "Stop probe", "Are you sure ?",
                QMessageBox.Yes | QMessageBox.No )
            if reply == QMessageBox.Yes:
                probeName = self.itemCurrentRunning.dataProbe['id']
                self.itemCurrentRunning = None
                self.stopAction.setEnabled(False)
                
                # rest call
                RCI.instance().disconnectProbe(probeName=probeName)
                
    def startProbe(self):
        """
        Start a new probe
        """
        # some checks before
        if self.probeTypeEdit.text() == '':
            QMessageBox.information(self, "Add Default Probe" , "Please select the probe type.")
            return
        if self.probeNameEdit.text() == '':
            QMessageBox.information(self, "Add Default Probe" , "Probe name is mandatory.")
            return
        if not self.checkAutoStartOption.isChecked() and not self.checkStartNowOption.isChecked():
            QMessageBox.information(self, "Add Default Probe" , "Select startup option.")
            return
            
        # call web services
        probeType = str( self.probeTypeEdit.text() )
        probeName = str( self.probeNameEdit.text() )
        probeDescription =  str( self.probeDescEdit.text() )
        probeAutoStart = self.checkAutoStartOption.isChecked()

        if not self.checkStartNowOption.isChecked():
            RCI.instance().addProbe(probeName=probeName, probeType=probeType, 
                                    probeDescription=probeDescription)
        else:
            RCI.instance().connectProbe(probeName=probeName, probeType=probeType, 
                                        probeDescription=probeDescription, 
                                        probeBoot=probeAutoStart)
                                        
    def resetProbe(self):
        """
        Clear probe field
        """
        self.probeDescrInstalledEdit.setText( '' )
        self.probeDescEdit.setText( '' )
        self.probeNameEdit.setText( '' )
        self.probeTypeEdit.setText( '' )
        
        # clear selection
        itms = self.probesAvailable.selectedItems()
        for i in itms:
            if i.isSelected():
                i.setSelected(False)
        self.itemCurrentInstalled = None

    def active (self):
        """
        Enables QTreeWidget
        """
        self.probesRegistered.setEnabled(True)
        self.probesAvailable.setEnabled(True)
        self.deployBox.setEnabled(True)
        self.runningBox.setEnabled(True)

        self.refreshRunningAction.setEnabled(True)

    def deactivate (self):
        """
        Clears QTreeWidget and disables it
        """
        self.checkAutoStartOption.setCheckState(Qt.Unchecked) 
        self.checkStartNowOption.setCheckState(Qt.Unchecked) 

        self.probesAvailable.clear()
        self.probeDescrInstalledEdit.setText('')
        
        self.probesRegistered.clear()
        self.probesDefault.clear()
        self.probes = {}
        
        self.probesRegistered.setEnabled(False)
        self.probesAvailable.setEnabled(False)
        self.deployBox.setEnabled(False)
        self.runningBox.setEnabled(False)

        # actions
        self.stopAction.setEnabled(False)
        self.delProbeAction.setEnabled(False)
        
        self.itemCurrentRunning = None
        self.itemCurrentInstalled = None

        self.probeDescEdit.setText( '' )
        self.probeTypeEdit.setText( '' )
        self.probeNameEdit.setText( '' )

        self.resetNbProbes()

        self.refreshRunningAction.setEnabled(False)

    def getRunningProbes(self):
        """
        Get running probes 
        """
        if sys.version_info > (3,): # python3 support
            return list(self.probes.keys())
        else:
            return self.probes.keys()

    def getProbeTypeByName(self, name):
        """
        Get probe type by name

        @param name: 
        @type name:
        """
        if name in self.probes:
            return self.probes[name].getProbeType()
        else:
            return ''

    def loadDefault (self, data):
        """
        Loads default probes

        @param data: 
        @type data: dict
        """
        self.probesDefault.clear()

        for defProbe in data:
            defProbeItem = ProbeDefaultItem( probe = defProbe, parent= self.probesDefault)

    def loadData (self, data, dataInstalled=None):
        """
        Loads probes

        @param data: 
        @type data: dict

        @param dataInstalled: 
        @type dataInstalled:
        """
        if isinstance(data, dict):
            data = [ data ]

        self.probesRegistered.clear()

        for probe in data:
            probeItem = ProbeItem( probe = probe, parent= self.probesRegistered)
            self.probes[probe['id']] = probeItem

        # load tests stats
        if dataInstalled is not None:
            if len(dataInstalled) == 0:
                self.deployBox.setEnabled(False)
                self.probesAvailable.setEnabled(False)

    def resetNbProbes(self, data=None):
        """
        Reset the number of probes
        """
        pass

    def refreshData (self, data, action):
        """
        Refresh probes

        @param data: 
        @type data: dict

        @param action: expected values in 'del' and 'add'
        @type action: string
        """
        if action == 'del':
            self.probesRegistered.clear()
            self.probes = {}
            self.resetNbProbes(data=data)
            self.loadData( data = data )
        elif action == 'add':
            self.resetNbProbes(data=data)
            self.loadData( data = data )        
        else:
            self.error( 'action unknown: %s' % str(action) )
    
    def refreshDataDefault(self, data, action):
        """
        Refresh probes

        @param data: 
        @type data: dict

        @param action: expected values in 'del' and 'add'
        @type action: string
        """
        if action == 'del':
            self.probesDefault.clear()
            self.loadDefault( data = data )
        elif action == 'add':
            self.probesDefault.clear()
            self.loadDefault( data = data )     
        else:
            self.error( 'action unknown: %s' % str(action) )
コード例 #38
0
ファイル: stackviewer.py プロジェクト: eaglexmw/codimension
class StackViewer( QWidget ):
    " Implements the stack viewer for a debugger "

    def __init__( self, debugger, parent = None ):
        QWidget.__init__( self, parent )

        self.__debugger = debugger
        self.currentStack = None
        self.currentFrame = 0
        self.__createPopupMenu()
        self.__createLayout()

        if Settings().showStackViewer == False:
            self.__onShowHide( True )
        return

    def __createPopupMenu( self ):
        " Creates the popup menu "
        self.__framesMenu = QMenu()
        self.__setCurrentMenuItem = self.__framesMenu.addAction(
                    "Set current (single click)", self.__onSetCurrent )
        self.__jumpMenuItem = self.__framesMenu.addAction(
                    "Set current and jump to the source (double click)",
                    self.__onSetCurrentAndJump )
        return

    def __createLayout( self ):
        " Creates the widget layout "

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

        self.headerFrame = QFrame()
        self.headerFrame.setFrameStyle( QFrame.StyledPanel )
        self.headerFrame.setAutoFillBackground( True )
        headerPalette = self.headerFrame.palette()
        headerBackground = headerPalette.color( QPalette.Background )
        headerBackground.setRgb( min( headerBackground.red() + 30, 255 ),
                                 min( headerBackground.green() + 30, 255 ),
                                 min( headerBackground.blue() + 30, 255 ) )
        headerPalette.setColor( QPalette.Background, headerBackground )
        self.headerFrame.setPalette( headerPalette )
        self.headerFrame.setFixedHeight( 24 )

        self.__stackLabel = QLabel( "Stack" )

        expandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )
        fixedSpacer = QSpacerItem( 3, 3 )

        self.__showHideButton = QToolButton()
        self.__showHideButton.setAutoRaise( True )
        self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
        self.__showHideButton.setFixedSize( 20, 20 )
        self.__showHideButton.setToolTip( "Hide frames list" )
        self.__showHideButton.setFocusPolicy( Qt.NoFocus )
        self.__showHideButton.clicked.connect( self.__onShowHide )

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins( 0, 0, 0, 0 )
        headerLayout.addSpacerItem( fixedSpacer )
        headerLayout.addWidget( self.__stackLabel )
        headerLayout.addSpacerItem( expandingSpacer )
        headerLayout.addWidget( self.__showHideButton )
        self.headerFrame.setLayout( headerLayout )

        self.__framesList = QTreeWidget( self )
        self.__framesList.setSortingEnabled( False )
        # I might not need that because of two reasons:
        # - the window has no focus
        # - the window has custom current indicator
        # self.__framesList.setAlternatingRowColors( True )
        self.__framesList.setRootIsDecorated( False )
        self.__framesList.setItemsExpandable( False )
        self.__framesList.setUniformRowHeights( True )
        self.__framesList.setSelectionMode( QAbstractItemView.NoSelection )
        self.__framesList.setSelectionBehavior( QAbstractItemView.SelectRows )
        self.__framesList.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.__framesList.setFocusPolicy( Qt.NoFocus )
        self.__framesList.setContextMenuPolicy( Qt.CustomContextMenu )

        self.__framesList.itemClicked.connect( self.__onFrameClicked )
        self.__framesList.itemDoubleClicked.connect( self.__onFrameDoubleClicked )
        self.__framesList.customContextMenuRequested.connect( self.__showContextMenu )

        self.__framesList.setHeaderLabels( [ "", "File:line", "Function",
                                             "Full path" ] )

        verticalLayout.addWidget( self.headerFrame )
        verticalLayout.addWidget( self.__framesList )
        return

    def __onShowHide( self, startup = False ):
        " Triggered when show/hide button is clicked "
        if startup or self.__framesList.isVisible():
            self.__framesList.setVisible( False )
            self.__showHideButton.setIcon( PixmapCache().getIcon( 'more.png' ) )
            self.__showHideButton.setToolTip( "Show frames list" )

            self.__minH = self.minimumHeight()
            self.__maxH = self.maximumHeight()

            self.setMinimumHeight( self.headerFrame.height() )
            self.setMaximumHeight( self.headerFrame.height() )

            Settings().showStackViewer = False
        else:
            self.__framesList.setVisible( True )
            self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
            self.__showHideButton.setToolTip( "Hide frames list" )

            self.setMinimumHeight( self.__minH )
            self.setMaximumHeight( self.__maxH )

            Settings().showStackViewer = True
        return

    def clear( self ):
        " Clears the content "
        self.__framesList.clear()
        self.currentStack = None
        self.__stackLabel.setText( "Stack" )
        return

    def __resizeColumns( self ):
        " Resize the files list columns "
        self.__framesList.header().setStretchLastSection( True )
        self.__framesList.header().resizeSections(
                                    QHeaderView.ResizeToContents )
        self.__framesList.header().resizeSection( 0, 22 )
        self.__framesList.header().setResizeMode( 0, QHeaderView.Fixed )
        return


    def populate( self, stack ):
        " Sets the new call stack and selects the first item in it "
        self.clear()

        self.currentStack = stack
        self.currentFrame = 0
        frameNumber = 0
        for s in stack:
            if len( s ) == 2:
                # This is when an exception comes
                funcName = ""
            else:
                funcName = s[ 2 ]
            item = StackFrameItem( s[ 0 ], s[ 1 ], funcName, frameNumber )
            self.__framesList.addTopLevelItem( item )
            frameNumber += 1
        self.__resizeColumns()
        self.__framesList.topLevelItem( 0 ).setCurrent( True )
        self.__stackLabel.setText( "Stack (total: " +
                                   str( len( stack ) ) + ")" )
        return

    def getFrameNumber( self ):
        " Provides the current frame number "
        return self.currentFrame

    def __onFrameClicked( self, item, column ):
        " Triggered when a frame is clicked "
        if item.isCurrent():
            return

        # Hide the current indicator
        self.__framesList.topLevelItem( self.currentFrame ).setCurrent( False )

        # Show the new indicator
        self.currentFrame = item.getFrameNumber()
        for index in xrange( self.__framesList.topLevelItemCount() ):
            item = self.__framesList.topLevelItem( index )
            if item.getFrameNumber() == self.currentFrame:
                item.setCurrent( True )
        self.__debugger.remoteClientVariables( 1, self.currentFrame )  # globals
        self.__debugger.remoteClientVariables( 0, self.currentFrame )  # locals
        return

    def __onFrameDoubleClicked( self, item, column ):
        " Triggered when a frame is double clicked "
        # The frame has been switched already because the double click
        # signal always comes after the single click one
        fileName = item.getFilename()
        lineNumber = item.getLineNumber()

        editorsManager = GlobalData().mainWindow.editorsManager()
        editorsManager.openFile( fileName, lineNumber )
        editor = editorsManager.currentWidget().getEditor()
        editor.gotoLine( lineNumber )
        editorsManager.currentWidget().setFocus()
        return

    def __showContextMenu( self, coord ):
        " Shows the frames list context menu "
        self.__contextItem = self.__framesList.itemAt( coord )
        if self.__contextItem is not None:
            self.__setCurrentMenuItem.setEnabled(
                                not self.__contextItem.isCurrent() )
            self.__framesMenu.popup( QCursor.pos() )
        return

    def __onSetCurrent( self ):
        " Context menu item handler "
        self.__onFrameClicked( self.__contextItem, 0 )
        return

    def __onSetCurrentAndJump( self ):
        " Context menu item handler "
        self.__onFrameClicked( self.__contextItem, 0 )
        self.__onFrameDoubleClicked( self.__contextItem, 0 )
        return

    def switchControl( self, isInIDE ):
        " Switches the UI depending where the control flow is "
        self.__framesList.setEnabled( isInIDE )
        return
コード例 #39
0
class PymetricsViewer(QWidget):
    " Pymetrics tab widget "

    # Limits to colorize the McCabe score
    LittleRiskLimit = 10
    ModerateRiskLimit = 20
    HighRiskLimit = 50

    # Options of providing a report
    SingleFile = 0
    DirectoryFiles = 1
    ProjectFiles = 2
    SingleBuffer = 3

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

        self.__reportUUID = ""
        self.__reportFileName = ""
        self.__reportOption = -1
        self.__reportShown = False
        self.__report = None

        # Prepare members for reuse
        self.__noneLabel = QLabel("\nNo results available")

        self.__noneLabel.setFrameShape(QFrame.StyledPanel)
        self.__noneLabel.setAlignment(Qt.AlignHCenter)
        self.__headerFont = self.__noneLabel.font()
        self.__headerFont.setPointSize(self.__headerFont.pointSize() + 4)
        self.__noneLabel.setFont(self.__headerFont)
        self.__noneLabel.setAutoFillBackground(True)
        noneLabelPalette = self.__noneLabel.palette()
        noneLabelPalette.setColor(QPalette.Background,
                                  GlobalData().skin.nolexerPaper)
        self.__noneLabel.setPalette(noneLabelPalette)

        self.__createLayout(parent)

        self.__updateButtonsStatus()
        return

    def __createLayout(self, parent):
        " Creates the toolbar and layout "

        # Buttons
        self.__mcCabeButton = QAction(PixmapCache().getIcon('tableview.png'),
                                      'Switch to McCabe only table view', self)
        self.__mcCabeButton.setCheckable(True)
        self.connect(self.__mcCabeButton, SIGNAL('toggled(bool)'),
                     self.__onMcCabe)

        self.printButton = QAction(PixmapCache().getIcon('printer.png'),
                                   'Print', self)
        #printButton.setShortcut( 'Ctrl+' )
        self.connect(self.printButton, SIGNAL('triggered()'), self.__onPrint)
        self.printButton.setVisible(False)

        self.printPreviewButton = QAction(
            PixmapCache().getIcon('printpreview.png'), 'Print preview', self)
        #printPreviewButton.setShortcut( 'Ctrl+' )
        self.connect(self.printPreviewButton, SIGNAL('triggered()'),
                     self.__onPrintPreview)
        self.printPreviewButton.setVisible(False)

        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.clearButton = QAction(PixmapCache().getIcon('trash.png'), 'Clear',
                                   self)
        self.connect(self.clearButton, SIGNAL('triggered()'), self.__clear)

        # The toolbar
        self.toolbar = QToolBar(self)
        self.toolbar.setOrientation(Qt.Vertical)
        self.toolbar.setMovable(False)
        self.toolbar.setAllowedAreas(Qt.RightToolBarArea)
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.setFixedWidth(28)
        self.toolbar.setContentsMargins(0, 0, 0, 0)

        self.toolbar.addAction(self.__mcCabeButton)
        self.toolbar.addAction(self.printPreviewButton)
        self.toolbar.addAction(self.printButton)
        self.toolbar.addWidget(spacer)
        self.toolbar.addAction(self.clearButton)

        self.__totalResultsTree = QTreeWidget()
        self.__totalResultsTree.setAlternatingRowColors(True)
        self.__totalResultsTree.setRootIsDecorated(True)
        self.__totalResultsTree.setItemsExpandable(True)
        self.__totalResultsTree.setUniformRowHeights(True)
        self.__totalResultsTree.setItemDelegate(NoOutlineHeightDelegate(4))
        headerLabels = ["Path / name", "Value", ""]
        self.__totalResultsTree.setHeaderLabels(headerLabels)
        self.connect(self.__totalResultsTree,
                     SIGNAL("itemActivated(QTreeWidgetItem *, int)"),
                     self.__allItemActivated)
        self.connect(self.__totalResultsTree,
                     SIGNAL("itemExpanded(QTreeWidgetItem *)"),
                     self.__onResultsExpanded)
        self.__totalResultsTree.setColumnHidden(2, True)
        self.__totalResultsTree.hide()

        self.__mcCabeTable = QTreeWidget()
        self.__mcCabeTable.setAlternatingRowColors(True)
        self.__mcCabeTable.setRootIsDecorated(False)
        self.__mcCabeTable.setItemsExpandable(False)
        self.__mcCabeTable.setSortingEnabled(True)
        self.__mcCabeTable.setItemDelegate(NoOutlineHeightDelegate(4))
        self.__mcCabeTable.setUniformRowHeights(True)
        headerLabels = ["", "File name", "Object", "McCabe Complexity"]
        self.__mcCabeTable.setHeaderLabels(headerLabels)
        self.connect(self.__mcCabeTable,
                     SIGNAL("itemActivated(QTreeWidgetItem *, int)"),
                     self.__mcCabeActivated)
        self.__mcCabeTable.hide()

        self.__hLayout = QHBoxLayout()
        self.__hLayout.setContentsMargins(0, 0, 0, 0)
        self.__hLayout.setSpacing(0)
        self.__hLayout.addWidget(self.toolbar)
        self.__hLayout.addWidget(self.__noneLabel)
        self.__hLayout.addWidget(self.__totalResultsTree)
        self.__hLayout.addWidget(self.__mcCabeTable)

        self.setLayout(self.__hLayout)
        return

    def getTotalResultsWidget(self):
        " Provides a reference to the total results widget "
        return self.__totalResultsTree

    def getMcCabeResultsWidget(self):
        " Provides a reference to the McCabe results widget "
        return self.__mcCabeTable

    def __updateButtonsStatus(self):
        " Updates the buttons status "
        self.__mcCabeButton.setEnabled(self.__reportShown)
        self.printButton.setEnabled(self.__reportShown)
        self.printPreviewButton.setEnabled(self.__reportShown)
        self.clearButton.setEnabled(self.__reportShown)
        return

    def __onResultsExpanded(self, item):
        " An item has been expanded, so the column width should be adjusted "
        self.__totalResultsTree.header().resizeSections(
            QHeaderView.ResizeToContents)
        return

    def __onPrint(self):
        " Triggered when the print button is pressed "
        pass

    def __onPrintPreview(self):
        " triggered when the print preview button is pressed "
        pass

    def __onMcCabe(self, state):
        " Triggered when the metrics view is switched "

        if not self.__reportShown:
            return

        if state:
            self.__totalResultsTree.hide()
            self.__mcCabeTable.show()
            self.__mcCabeButton.setIcon(PixmapCache().getIcon('treeview.png'))
            self.__mcCabeButton.setToolTip("Switch to complete "
                                           "results tree view")
        else:
            self.__mcCabeTable.hide()
            self.__totalResultsTree.show()
            self.__mcCabeButton.setIcon(PixmapCache().getIcon('tableview.png'))
            self.__mcCabeButton.setToolTip("Switch to McCabe only table view")
        return

    def setFocus(self):
        " Overridden setFocus "
        self.__hLayout.setFocus()
        return

    def __clear(self):
        " Clears the content of the vertical layout "
        if not self.__reportShown:
            return

        self.__totalResultsTree.clear()
        self.__totalResultsTree.hide()
        self.__mcCabeTable.clear()
        self.__mcCabeTable.hide()
        self.__noneLabel.show()

        self.__report = None
        self.__reportShown = False
        self.__updateButtonsStatus()
        #        self.resizeEvent()
        self.__mcCabeButton.setIcon(PixmapCache().getIcon('tableview.png'))
        self.__mcCabeButton.setToolTip("Switch to McCabe only table view")
        self.__mcCabeButton.setChecked(False)

        self.__updateTooltip()
        return

    def __updateTooltip(self):
        " Generates a signal with appropriate string message "
        if not self.__reportShown:
            tooltip = "No metrics available"
        elif self.__reportOption == self.DirectoryFiles:
            tooltip = "Metrics generated for directory: " + \
                      self.__reportFileName
        elif self.__reportOption == self.ProjectFiles:
            tooltip = "Metrics generated for the whole project"
        elif self.__reportOption == self.SingleFile:
            tooltip = "Metrics generated for file: " + self.__reportFileName
        elif self.__reportOption == self.SingleBuffer:
            tooltip = "Metrics generated for unsaved file: " + \
                      self.__reportFileName
        else:
            tooltip = ""
        self.emit(SIGNAL('updatePymetricsTooltip'), tooltip)
        return

    @staticmethod
    def __shouldShowFileName(table, column):
        " Checks if the file name is the same "

        size = table.topLevelItemCount()
        if size == 0:
            return False

        index = size - 1
        firstName = table.topLevelItem(index).text(column)
        index -= 1
        while index >= 0:
            if table.topLevelItem(index).text(column) != firstName:
                return True
            index -= 1
        return False

    def showReport(self, metrics, reportOption, fileName, uuid):
        " Shows the pymetrics results "
        self.__clear()
        self.__noneLabel.hide()

        self.__report = metrics
        self.__reportUUID = uuid
        self.__reportFileName = fileName
        self.__reportOption = reportOption

        if len(metrics.report) > 1:
            accumulatedBasic = self.__accumulateBasicMetrics()
            accItem = QTreeWidgetItem(["Cumulative basic metrics"])
            self.__totalResultsTree.addTopLevelItem(accItem)
            for key in accumulatedBasic:
                bmItem = [
                    BasicMetrics.metricsOfInterest[key],
                    splitThousands(str(accumulatedBasic[key]))
                ]
                basicMetric = QTreeWidgetItem(bmItem)
                accItem.addChild(basicMetric)

        # Add the complete information
        for fileName in metrics.report:
            if reportOption == self.SingleBuffer:
                fileItem = QTreeWidgetItem(["Editor buffer"])
            else:
                fileItem = QTreeWidgetItem([fileName])
                info = GlobalData().briefModinfoCache.get(fileName)
                if info.docstring is not None:
                    fileItem.setToolTip(0, info.docstring.text)
                else:
                    fileItem.setToolTip(0, "")
            self.__totalResultsTree.addTopLevelItem(fileItem)

            # Messages part
            messages = metrics.report[fileName].messages
            if len(messages) > 0:
                messagesItem = QTreeWidgetItem(["Messages"])
                fileItem.addChild(messagesItem)
                for message in messages:
                    mItem = [message, "", "E"]
                    messagesItem.addChild(QTreeWidgetItem(mItem))

            # Basic metrics part
            basicItem = QTreeWidgetItem(["Basic metrics"])
            fileItem.addChild(basicItem)
            basic = metrics.report[fileName].basicMetrics
            for key in basic.metrics:
                bmItem = [
                    BasicMetrics.metricsOfInterest[key],
                    str(basic.metrics[key])
                ]
                basicMetric = QTreeWidgetItem(bmItem)
                basicItem.addChild(basicMetric)

            # McCabe part
            mccabeItem = QTreeWidgetItem(["McCabe metrics"])
            fileItem.addChild(mccabeItem)
            mccabe = metrics.report[fileName].mcCabeMetrics.metrics
            for objName in mccabe:
                objItem = [objName, str(mccabe[objName]), "M"]
                mccabeMetric = QTreeWidgetItem(objItem)
                mccabeItem.addChild(mccabeMetric)

            # COCOMO 2 part
            cocomo = [
                "COCOMO 2",
                str(metrics.report[fileName].cocomo2Metrics.value)
            ]
            cocomoItem = QTreeWidgetItem(cocomo)
            fileItem.addChild(cocomoItem)

        # Resizing the table
        self.__totalResultsTree.header().resizeSections(
            QHeaderView.ResizeToContents)

        # Add McCabe complexity information
        for fileName in metrics.report:
            mccabe = metrics.report[fileName].mcCabeMetrics.metrics
            for objName in mccabe:
                values = ["", fileName, objName, str(mccabe[objName])]
                self.__mcCabeTable.addTopLevelItem(McCabeTableItem(values))

        if not self.__shouldShowFileName(self.__mcCabeTable, 1):
            self.__mcCabeTable.setColumnHidden(1, True)

        # Resizing and sorting the table
        self.__mcCabeTable.header().setSortIndicator(3, Qt.DescendingOrder)
        self.__mcCabeTable.sortItems(
            3,
            self.__mcCabeTable.header().sortIndicatorOrder())
        self.__mcCabeTable.header().resizeSections(
            QHeaderView.ResizeToContents)

        # Show the complete information
        self.__mcCabeTable.hide()
        self.__totalResultsTree.show()

        self.__reportShown = True
        self.__updateButtonsStatus()
        self.__updateTooltip()

        # It helps, but why do I have flickering?
        QApplication.processEvents()
        return

    def __accumulateBasicMetrics(self):
        " Accumulates basic metrics for all the processed files "
        basic = {}
        for fileName in self.__report.report:
            singleBasic = self.__report.report[fileName].basicMetrics.metrics
            for key in singleBasic:
                if not key.startswith('num'):
                    continue
                if key in basic:
                    basic[key] += int(singleBasic[key])
                else:
                    basic[key] = int(singleBasic[key])
        return basic

    def __mcCabeActivated(self, item, column):
        " Handles the double click (or Enter) on the mccabe table item "

        objName = str(item.text(2))
        if self.__reportOption == self.SingleBuffer:
            if os.path.isabs(self.__reportFileName):
                fileName = self.__reportFileName
            else:
                fileName = ""
        else:
            fileName = str(item.text(1))
        self.__onMcCabeObject(objName, fileName)
        return

    def __allItemActivated(self, item, column):
        " Handles the double click (or Enter) in the total results tree "

        # We process only the error messages and McCabe items
        hiddenColumnText = str(item.text(2))
        if not hiddenColumnText in ["M", "E"]:
            return

        fileName = self.__getTreeItemFileName(item)
        lineNumber = 0
        if hiddenColumnText == "M":
            # This is McCabe item
            objName = str(item.text(0))
            self.__onMcCabeObject(objName, fileName)
            return
        elif hiddenColumnText == "E":
            # This is an error message
            message = str(item.text(0))
            pos = message.find("at line")
            if pos == -1:
                logging.error("Unknown format of the message. "
                              "Please inform the developers.")
                return
            parts = message[pos:].split()
            try:
                lineNumber = int(parts[2].replace(',', ''))
            except:
                logging.error("Unknown format of the message. "
                              "Please inform the developers.")
                return

            if fileName == "":
                # This is an unsaved buffer, try to find the editor by UUID
                mainWindow = GlobalData().mainWindow
                widget = mainWindow.getWidgetByUUID(self.__reportUUID)
                if widget is None:
                    logging.error("The unsaved buffer has been closed")
                    return
                # The widget was found, so jump to the required
                editor = widget.getEditor()
                editor.gotoLine(lineNumber)
                editor.setFocus()
                return

        GlobalData().mainWindow.openFile(fileName, lineNumber)
        return

    def __getTreeItemFileName(self, item):
        " Identifies the tree view item file name "
        if self.__reportOption == self.SingleBuffer:
            if os.path.isabs(self.__reportFileName):
                return self.__reportFileName
            return ""

        # The file name is always two levels up
        fileItem = item.parent().parent()
        return str(fileItem.text(0))

    def __onMcCabeObject(self, objName, fileName):
        " Called when the user activated McCabe item "

        info = None

        mainWindow = GlobalData().mainWindow
        widget = mainWindow.getWidgetByUUID(self.__reportUUID)
        if widget is None:
            if fileName == "":
                logging.error("The unsaved buffer has been closed")
                return
            # No widget, but we know the file name
            info = getBriefModuleInfoFromFile(fileName)
        else:
            # The widget was found
            editor = widget.getEditor()
            # The editor content has been modified, so re-parse the buffer
            info = getBriefModuleInfoFromMemory(editor.text())

        parts = objName.split('.')
        currentIndex = 0
        functionsContainer = info.functions
        classesContainer = info.classes
        line = -1

        if objName == "__main__" and len(parts) == 1:
            # Special case - global file scope
            line = 1
            currentIndex = 1

        while currentIndex < len(parts):
            found = False
            for func in functionsContainer:
                if func.name == parts[currentIndex]:
                    if currentIndex == len(parts) - 1:
                        # Found, jump to the line
                        line = func.line
                        break
                    functionsContainer = func.functions
                    classesContainer = func.classes
                    found = True
                    break
            if line != -1:
                break
            if found:
                currentIndex += 1
                continue
            for klass in classesContainer:
                if klass.name == parts[currentIndex]:
                    if currentIndex == len(parts) - 1:
                        # Found, jump to the line
                        line = klass.line
                        break
                    functionsContainer = klass.functions
                    classesContainer = klass.classes
                    found = True
            if line != -1:
                break
            if found:
                currentIndex += 1
                continue

            # Not found
            logging.error("Cannot find the " + objName)
            return

        # Here we have the line number
        if widget is None:
            GlobalData().mainWindow.openFile(fileName, line)
        else:
            editor = widget.getEditor()
            editor.gotoLine(line)
            editor.setFocus()
        return

    def onFileUpdated(self, fileName, uuid):
        " Called when a buffer is saved or saved as "

        if not self.__reportShown:
            return
        if self.__reportUUID != uuid:
            return

        # Currently shown report is for the saved buffer
        # File name is expected being absolute
        self.__reportFileName = fileName
        self.emit(SIGNAL('updatePymetricsTooltip'),
                  "Metrics generated for buffer saved as " + fileName)
        return
コード例 #40
0
class MembersWidget(QWidget):
    def __init__(self, parent, logger):
        super(MembersWidget, self).__init__(parent)

        self.logger = logger
        layout = QVBoxLayout(self)
        layout.setSpacing(0)

        self.dropdown_members_dict = {}
        self.dropdown_members_model = DropdownModel(get_peers(), self.logger)
        self.dropdown_members = QComboBox(self)
        self.dropdown_members.setModel(self.dropdown_members_model)

        topLayout = QHBoxLayout()
        topLayout.setSpacing(10)
        topLayout.addWidget(self.dropdown_members, 1)
        self.requestLogsButton = QPushButton("Request Logfiles", self)
        topLayout.addWidget(self.requestLogsButton)
        layout.addLayout(topLayout)

        layout.addWidget(QLabel("Member Information:", self))
        self.memberInformationTable = QTreeWidget(self)
        self.memberInformationTable.setMaximumHeight(65)
        self.memberInformationTable.setSelectionMode(QTreeWidget.NoSelection)
        layout.addWidget(self.memberInformationTable, 0)

        layout.addWidget(QLabel("Send Message:", self))

        sendMessageLayout = QHBoxLayout()
        sendMessageLayout.setSpacing(10)
        messageInput = HistoryLineEdit(self, "Enter a message")
        self.sendMessageButton = QPushButton("Send", self)
        sendMessageLayout.addWidget(messageInput, 1)
        sendMessageLayout.addWidget(self.sendMessageButton)
        layout.addLayout(sendMessageLayout)

        layout.addWidget(QLabel("Log files:", self))
        logSplitter = QSplitter(Qt.Horizontal, self)

        logListWidget = QWidget(self)
        logListLayout = QVBoxLayout(logListWidget)
        logListLayout.setContentsMargins(0, 0, 0, 0)

        self.log_tree_view = QTreeWidget(logSplitter)
        self.log_tree_view.setAlternatingRowColors(True)
        self.log_tree_view.setColumnCount(1)
        self.log_tree_view.setHeaderHidden(True)
        self.log_tree_view.setItemsExpandable(False)
        self.log_tree_view.setIndentation(0)

        logListLayout.addWidget(self.log_tree_view, 1)

        logListBottomLayout = QHBoxLayout()
        self.logSizeLabel = QLabel(logListWidget)
        logListBottomLayout.addWidget(self.logSizeLabel, 1)

        self.clearLogsButton = QPushButton("Clear", logListWidget)
        self.clearLogsButton.setEnabled(False)
        self.clearLogsButton.clicked.connect(self.clearLogs)
        logListBottomLayout.addWidget(self.clearLogsButton, 0)

        logListLayout.addLayout(logListBottomLayout)

        logSplitter.addWidget(logListWidget)

        self.log_area = QTextEdit(logListWidget)
        self.log_area.setLineWrapMode(QTextEdit.WidgetWidth)
        self.log_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.log_area.setReadOnly(True)
        logSplitter.addWidget(self.log_area)

        logSplitter.setStretchFactor(0, 0)
        logSplitter.setStretchFactor(1, 1)

        layout.addWidget(logSplitter, 1)

        self.memberSelectionChanged()
        self.log_tree_view.selectionModel().selectionChanged.connect(self.displaySelectedLogfile)
        self.dropdown_members.currentIndexChanged.connect(self.memberSelectionChanged)
        self.requestLogsButton.clicked.connect(self.requestLogClicked)
        self.sendMessageButton.clicked.connect(partial(self.sendMessageToMember, messageInput))
        messageInput.returnPressed.connect(partial(self.sendMessageToMember, messageInput))

        get_notification_center().connectPeerAppended(self.dropdown_members_model.externalRowAppended)
        get_notification_center().connectPeerUpdated(self.dropdown_members_model.externalRowUpdated)
        get_notification_center().connectPeerRemoved(self.dropdown_members_model.externalRowRemoved)
        get_notification_center().connectPeerUpdated(self.updateMemberInformation)

    def destroy_widget(self):
        get_notification_center().disconnectPeerAppended(self.dropdown_members_model.externalRowAppended)
        get_notification_center().disconnectPeerUpdated(self.dropdown_members_model.externalRowUpdated)
        get_notification_center().disconnectPeerRemoved(self.dropdown_members_model.externalRowRemoved)
        get_notification_center().disconnectPeerUpdated(self.updateMemberInformation)

    def listLogfiles(self, basePath, sort=None):
        if sort is None:
            sort = lambda aFile: -self.getLogNumber(aFile)
        logList = [
            os.path.join(basePath, aFile)
            for aFile in os.listdir(basePath)
            if aFile.endswith(".log") and not os.path.isdir(os.path.join(basePath, aFile))
        ]
        return sorted(logList, key=sort)

    def getNumLogsToKeep(self, oldLogFiles, newLogFiles, logOffset):
        oldestNew = None
        for aLogFile in newLogFiles:
            oldestNew, _ = self.getLogDates(aLogFile)
            if oldestNew != None:
                break

        if oldestNew == None:
            # new new log file contains timestamps (they are probably all empty)
            return len(oldLogFiles)

        numToKeep = 0
        while numToKeep < len(oldLogFiles) - logOffset:
            curTime, _ = self.getLogDates(oldLogFiles[numToKeep])
            if curTime == None or curTime < oldestNew:
                # keep empty log files
                numToKeep = numToKeep + 1
            else:
                break
        return numToKeep

    def getLogDates(self, aLogFile):
        with codecs.open(aLogFile, "rb", "utf-8") as logContent:
            logLines = logContent.readlines()
            firstDate = None
            for aLine in logLines:
                firstDate = getLogLineTime(aLine)
                if firstDate != None:
                    break

            lastDate = None
            for aLine in reversed(logLines):
                lastDate = getLogLineTime(aLine)
                if lastDate != None:
                    break

            return firstDate, lastDate

    def getLogNumber(self, aLogFile):
        aLogFile = os.path.basename(aLogFile)
        try:
            return int(aLogFile[: aLogFile.rfind(".")])
        except:
            return -1

    def shiftLogFiles(self, oldLogFiles, numToKeep, shift, logOffset):
        renamedLogfiles = []
        for index, aFile in enumerate(oldLogFiles):
            logNum = self.getLogNumber(aFile)
            if logNum < logOffset:
                # don't touch up-to-date logs
                break
            if index < numToKeep:
                newName = os.path.join(os.path.dirname(aFile), "%d.log" % (logNum + shift))
                renamedLogfiles.append((len(oldLogFiles) - index - 1, aFile, newName))
                os.rename(aFile, newName)
            else:
                os.remove(aFile)
        return renamedLogfiles

    def handleNewLogFiles(self, basePath, tmpPath, logOffset=0):
        oldLogFiles = self.listLogfiles(basePath)
        newLogFiles = self.listLogfiles(tmpPath)

        # check how many log files are actually new
        numToKeep = self.getNumLogsToKeep(oldLogFiles, newLogFiles, logOffset)

        # rename / remove old log files to make room for the new ones
        numNew = len(newLogFiles) - (len(oldLogFiles) - logOffset - numToKeep)
        renamedLogfiles = self.shiftLogFiles(oldLogFiles, numToKeep, numNew, logOffset)

        # move new log files
        addedLogfiles = []
        for index, aLogFile in enumerate(reversed(newLogFiles)):
            shutil.move(aLogFile, basePath)
            if index < numNew:
                addedLogfiles.append((index + logOffset, os.path.join(basePath, os.path.basename(aLogFile))))
        shutil.rmtree(tmpPath, True)

        return numNew, addedLogfiles, renamedLogfiles

    def requestFinished(self):
        self.requestLogsButton.setEnabled(True)
        self.dropdown_members.setEnabled(True)

    @loggingSlot(QThread, object)
    def cb_log_transfer_success(self, thread, path):
        path = convert_string(path)

        basePath = os.path.dirname(path)
        tmpPath = os.path.join(basePath, "tmp")
        if not os.path.exists(tmpPath):
            os.makedirs(tmpPath)

        logsAdded = []
        if path.endswith(".tgz"):
            # extract received log files
            with contextlib.closing(tarfile.open(path, "r:gz")) as tarContent:
                tarContent.extractall(tmpPath)
            _, logsAdded, logsRenamed = self.handleNewLogFiles(basePath, tmpPath)
            self.requestFinished()
        else:
            # log comes from old version
            logNum = 0
            if thread.sender in self.logRequests:
                logNum, requestTime = self.logRequests[thread.sender]
                now = datetime.now()
                td = now - requestTime
                tdSeconds = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 ** 6) / 10 ** 6
                if tdSeconds > self.LOG_REQUEST_TIMEOUT:
                    # request timed out or was finished already
                    logNum = 0

            shutil.move(path, os.path.join(tmpPath, "%d.log" % logNum))

            numNew, logsAdded, logsRenamed = self.handleNewLogFiles(basePath, tmpPath, logNum)
            if numNew > 0 and logNum < 9:
                # there might be more new ones
                self.logRequests[thread.sender] = (logNum + 1, datetime.now())
                self.logger.debug("log seems to be new, another!!!")
                logsAdded.append((logNum + 1, None))
                self.request_log(thread.sender, logNum + 1)
            elif thread.sender in self.logRequests:
                # request finished
                del self.logRequests[thread.sender]
                self.requestFinished()
            else:
                self.requestFinished()

        if len(logsAdded) > 0 or len(logsRenamed) > 0:
            self.updateLogList(logsAdded, logsRenamed)

    @loggingSlot(QThread, object)
    def cb_log_transfer_error(self, _thread, message):
        if not self.isVisible():
            return False
        self.log_area.setText("Error while getting log (%s)" % message)
        self.requestFinished()

    def get_selected_log_member(self):
        member = convert_string(self.dropdown_members.currentText())
        if not member:
            return None

        if "(" in member:
            # member contains name, extract ID
            member = member[member.rfind("(") + 1 : member.rfind(")")]

        return member

    def request_log(self, member=None, logNum=0):
        if member == None:
            member = self.get_selected_log_member()
        if member != None:
            self.logger.debug("Requesting log %d from %s", logNum, member)
            get_server().call(
                "HELO_REQUEST_LOGFILE %s %d" % (DataReceiverThread.getOpenPort(category="log%s" % member), logNum),
                set([member]),
            )
        else:
            self.log_area.setText("No Member selected!")

    @loggingSlot()
    def requestLogClicked(self):
        self.requestLogsButton.setEnabled(False)
        self.dropdown_members.setEnabled(False)
        self.updateLogList([(0, None)])
        self.request_log()

    def listLogFilesForMember(self, member):
        if member is None:
            return []
        logDir = os.path.join(get_settings().get_main_config_dir(), "logs", member)
        if not os.path.exists(logDir):
            return []
        return self.listLogfiles(logDir)

    def numLogFilesForMember(self, member):
        return len(self.listLogFilesForMember(member))

    def requestTimedOut(self, item):
        if not sip.isdeleted(item) and item != None and item.data(0, Qt.UserRole) == None:
            self.log_tree_view.takeTopLevelItem(self.log_tree_view.indexFromItem(item).row())
            self.requestFinished()

    def formatFileSize(self, num):
        for x in ["Bytes", "KB", "MB", "GB", "TB"]:
            if num < 1024.0:
                return "%3.1f %s" % (num, x)
            num /= 1024.0

    def initializeLogItem(self, item, logFile):
        firstDate, lastDate = self.getLogDates(logFile)
        text = None
        tooltip = None
        if firstDate != None:
            text = firstDate.strftime("%Y-%m-%d %H:%M:%S")
            tooltip = u"File: %s\nFirst entry: %s\nLast entry: %s" % (
                logFile,
                firstDate.strftime("%Y-%m-%d %H:%M:%S"),
                lastDate.strftime("%Y-%m-%d %H:%M:%S"),
            )
        else:
            timestamp = datetime.fromtimestamp(os.path.getmtime(logFile)).strftime("%Y-%m-%d %H:%M:%S")
            text = u"%s" % os.path.basename(logFile)
            tooltip = u"File:%s\nModification Date: %s" % (logFile, timestamp)
        text = text + "\n%s" % self.formatFileSize(os.path.getsize(logFile))
        if tooltip != None:
            item.setData(0, Qt.ToolTipRole, QVariant(tooltip))
        item.setData(0, Qt.UserRole, logFile)
        item.setData(0, Qt.DisplayRole, QVariant(text))

    @loggingSlot()
    def clearLogs(self):
        for aLogFile in self.listLogFilesForMember(self.get_selected_log_member()):
            os.remove(aLogFile)
        self.updateLogList()

    def updateLogList(self, logsAdded=None, logsRenamed=None):
        selectedMember = self.get_selected_log_member()

        if logsAdded == None:
            self.log_tree_view.clear()
            logsAdded = []
            for index, logFile in enumerate(reversed(self.listLogFilesForMember(selectedMember))):
                logsAdded.append((index, logFile))
            if len(logsAdded) == 0:
                self.log_tree_view.clear()
                self.log_tree_view.addTopLevelItem(
                    QTreeWidgetItem(self.log_tree_view, QStringList("No logs available."))
                )
                self.log_tree_view.setSelectionMode(QTreeWidget.NoSelection)
                self.logSizeLabel.setText("No logs")
                self.clearLogsButton.setEnabled(False)
                return

        if logsRenamed != None:
            for index, oldName, newName in logsRenamed:
                # index + 1 because of the "requesting" item
                item = self.log_tree_view.topLevelItem(index + 1)
                if item != None:
                    itemLogFile = convert_string(item.data(0, Qt.UserRole).toString())
                    if itemLogFile != oldName:
                        self.logger.warning(
                            "index does not correspond to item in list:\n\t%s\n\t%s", itemLogFile, oldName
                        )
                    self.initializeLogItem(item, newName)

        if len(logsAdded) == 0:
            self.log_tree_view.takeTopLevelItem(0)
        else:
            for index, logFile in logsAdded:
                oldItem = self.log_tree_view.topLevelItem(index)
                item = None
                if oldItem != None and oldItem.data(0, Qt.UserRole) == None:
                    # requested item has been received
                    item = oldItem
                else:
                    item = QTreeWidgetItem()
                    oldItem = None

                if logFile == None:
                    item.setData(0, Qt.DisplayRole, QVariant("Requesting..."))
                    QTimer.singleShot(6000, partial(self.requestTimedOut, item))
                else:
                    self.initializeLogItem(item, logFile)

                if oldItem == None:
                    # else, the old item is being modified
                    self.log_tree_view.insertTopLevelItem(index, item)
                self.log_tree_view.setSelectionMode(QTreeWidget.SingleSelection)

        totalSize = 0
        for aLogFile in self.listLogFilesForMember(selectedMember):
            totalSize += os.path.getsize(aLogFile)

        self.logSizeLabel.setText("%s consumed" % self.formatFileSize(totalSize))
        self.clearLogsButton.setEnabled(True)
        # self.displaySelectedLogfile()

    def getSelectedLogContent(self):
        member = self.get_selected_log_member()
        if member == None:
            return "No Log selected."
        selection = self.log_tree_view.selectedIndexes()
        if len(selection) is 0:
            return "No Log selected."

        logPath = convert_string(selection[0].data(Qt.UserRole).toString())
        if logPath == None:
            return "ERROR: path is None"
        if not os.path.exists(logPath):
            return "File not found: " + logPath

        fcontent = ""
        try:
            with codecs.open(logPath, "r", "utf8") as fhandler:
                fcontent = fhandler.read()
        except Exception as e:
            self.logger.exception("Error reading file")
            fcontent = "Error reading file: %s" % str(e)
        return fcontent

    @loggingSlot(QItemSelection, QItemSelection)
    def displaySelectedLogfile(self, _new, _old):
        self.log_area.setText(self.getSelectedLogContent())

    @loggingSlot(int)
    def memberSelectionChanged(self, _new=None):
        self.updateLogList()
        isMemberSelected = self.get_selected_log_member() != None
        self.sendMessageButton.setEnabled(isMemberSelected)
        self.requestLogsButton.setEnabled(isMemberSelected)
        self.updateMemberInformation()

    @loggingSlot(object)
    def sendMessageToMember(self, lineEdit):
        selectedMember = self.get_selected_log_member()
        if selectedMember != None:
            get_server().call(convert_string(lineEdit.text()), set([selectedMember]))
            lineEdit.clear()

    @loggingSlot(object, object)
    def updateMemberInformation(self, peerID=None, peerInfo=None):
        if peerID != None and peerID != self.get_selected_log_member():
            # only update if selected member updated
            return

        self.memberInformationTable.clear()

        if self.get_selected_log_member() == None:
            self.memberInformationTable.setColumnCount(0)
            self.memberInformationTable.setHeaderLabel("No member selected.")
            return

        if peerInfo == None:
            peerInfo = get_peers().getPeerInfo(pID=self.get_selected_log_member())

        if peerInfo == None:
            self.memberInformationTable.setColumnCount(0)
            self.memberInformationTable.setHeaderLabel("No member information available.")
            return

        self.memberInformationTable.setColumnCount(len(peerInfo))
        headers = sorted(peerInfo.keys(), key=lambda s: s.lower())
        self.memberInformationTable.setHeaderLabels(QStringList(headers))
        item = QTreeWidgetItem(self.memberInformationTable)
        for col, header in enumerate(headers):
            item.setData(col, Qt.DisplayRole, QVariant(peerInfo[header]))
        for col in range(self.memberInformationTable.columnCount()):
            self.memberInformationTable.resizeColumnToContents(col)
コード例 #41
0
class WServerReleaseNote(QWidget, Logger.ClassLogger):
    """
    Widget for display all release notes
    """
    def __init__(self, parent = None):
        """
        Constructs WServerReleaseNote widget 

        @param parent: 
        @type parent:
        """
        QWidget.__init__(self, parent)
        self.parent = parent
        self.name = self.tr("Release Notes")
        self.createWidgets()
        self.deactivate()

    def createWidgets(self):
        """
        QtWidgets creation
        """
        self.mainTab = QTabWidget()
        mainLayout = QVBoxLayout()
    
        self.toRead = QLabel( "%s" % "Release notes are specific to each version of the server, SUT adapters, libraries and toolbox. More details on each HISTORY files."  )

        mainLayout.addWidget(self.toRead)
        mainLayout.addWidget(self.mainTab)

        palette = QPalette()
        brush = QBrush(QColor(240, 240, 240))
        brush.setStyle(Qt.SolidPattern)
        palette.setBrush(QPalette.Active, QPalette.Base, brush)

        # treewidget for server rn
        self.rn = QTreeWidget(self)
        self.rn.setHeaderHidden(True)
        self.rn.setFrameShape(QFrame.NoFrame)
        self.rn.setSelectionMode(QAbstractItemView.NoSelection)
        self.rn.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.rn.setRootIsDecorated(False)
        self.rn.setPalette(palette)

        # treewidget for adapter rn
        self.rnAdp = QTreeWidget(self)
        self.rnAdp.setHeaderHidden(True)
        self.rnAdp.setFrameShape(QFrame.NoFrame)
        self.rnAdp.setSelectionMode(QAbstractItemView.NoSelection)
        self.rnAdp.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.rnAdp.setRootIsDecorated(False)
        self.rnAdp.setPalette(palette)

        # treewidget for library rn
        self.rnLibAdp = QTreeWidget(self)
        self.rnLibAdp.setHeaderHidden(True)
        self.rnLibAdp.setFrameShape(QFrame.NoFrame)
        self.rnLibAdp.setSelectionMode(QAbstractItemView.NoSelection)
        self.rnLibAdp.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.rnLibAdp.setRootIsDecorated(False)
        self.rnLibAdp.setPalette(palette)
        
        # treewidget for agent rn
        self.rnToolbox = QTreeWidget(self)
        self.rnToolbox.setHeaderHidden(True)
        self.rnToolbox.setFrameShape(QFrame.NoFrame)
        self.rnToolbox.setSelectionMode(QAbstractItemView.NoSelection)
        self.rnToolbox.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.rnToolbox.setRootIsDecorated(False)
        self.rnToolbox.setPalette(palette)

        self.mainTab.addTab( self.rn, Settings.instance().readValue( key = 'Common/acronym-server' )  )
        self.mainTab.addTab( self.rnAdp, "Sut Adapters" )
        self.mainTab.addTab( self.rnLibAdp, "Sut Librairies" )
        self.mainTab.addTab( self.rnToolbox, "Toolbox" )

        self.setLayout(mainLayout)

    def active (self):
        """
        Enables QTreeWidget
        Active all qwidget
        """
        self.rn.setEnabled(True)
        self.rnAdp.setEnabled(True)
        self.rnLibAdp.setEnabled(True)
        self.rnToolbox.setEnabled(True)

    def deactivate (self):
        """
        Clears QTreeWidget and disables it
        """
        self.rn.clear()
        self.rn.setEnabled(False)
        
        self.rnAdp.clear()
        self.rnAdp.setEnabled(False)

        self.rnLibAdp.clear()
        self.rnLibAdp.setEnabled(False)
        
        self.rnToolbox.clear()
        self.rnToolbox.setEnabled(False)

    def loadData (self, data, dataAdp, dataLibAdp, dataToolbox):
        """
        Dispatch data between tas tab and adapter tab

        @param data: 
        @type data:

        @param dataAdp: 
        @type dataAdp:

        @param dataProbes: 
        @type dataProbes:
        """
        # load server rn
        self.constructItem(parent=self.rn, data= data )

        # load adapters rn
        if not len(dataAdp): # dataAdp is false then adapters are not installed on the server
            emptyItem = KeyItem( key = b"", parent = self.rnAdp, type = 0)
            notInstalledItem = KeyItem( key = b"   Package adapters not installed on server", 
                                        parent = self.rnAdp, type = 1)
        else:
            try:
                self.constructItem(parent=self.rnAdp, data=dataAdp )
            except Exception as e:
                self.error( e )

        # load libraries rn
        if not len(dataLibAdp): # dataLibAdp is false then libraries are not installed on the server
            emptyItem = KeyItem( key = b"", parent = self.rnLibAdp, type = 0)
            notInstalledItem = KeyItem( key = b"   Package libraries not installed on server", 
                                        parent = self.rnLibAdp, type = 1)
        else:
            try:
                self.constructItem(parent=self.rnLibAdp, data=dataLibAdp )
            except Exception as e:
                self.error( e )
                
        # load toolbox rn
        if not len(dataToolbox): # dataToolbox is false then toolbox are not installed on the server
            emptyItem = KeyItem( key = b"", parent = self.rnToolbox, type = 0)
            notInstalledItem = KeyItem( key = b"   Package toolbox not installed on server", 
                                        parent = self.rnToolbox, type = 1)
        else:
            try:
                self.constructItem(parent=self.rnToolbox, data=dataToolbox )
            except Exception as e:
                self.error( e )

    def constructItem (self, parent, data):
        """
        Add items to tree widget

        @param data: 
        @type data:

        @param parent: 
        @type parent:
        """
        rootItem = None
        subItem = None
        for line in data.splitlines():
            if sys.version_info > (3,):
                line = bytes(line, 'utf8')
            if not line.startswith(b'\t'): # wrap to bytes for python 3 support
                rootItem = KeyItem( key = line, parent = parent, type = 0)
                rootItem.setExpanded(True)

            elif line.startswith(b'\t\t'): # wrap to bytes for python 3 support
                KeyItem( key = line[2:], parent = subItem, type = 2)

            elif line.startswith(b'\t'): # wrap to bytes for python 3 support
                subItem = KeyItem( key = line[1:], parent = rootItem, type = 1)
                subItem.setExpanded(True)
コード例 #42
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()
コード例 #43
0
ファイル: rumor.py プロジェクト: Alwnikrotikz/lilykde
class RumorSettings(KDialog):
    """
    Dialog with more Rumor settings.
    """
    def __init__(self, mainwin):
        KDialog.__init__(self, mainwin)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setCaption(i18n("Rumor Settings"))
        self.setButtons(KDialog.ButtonCode(
            KDialog.Ok | KDialog.Cancel | KDialog.Help))
        self.setHelp("rumor")

        layout = QGridLayout(self.mainWidget())
        # MIDI input and output.
        # Get the list of available OSS and ALSA devices
        oslist = [('oss:{0}'.format(i), i18n("OSS device %1", i))
            for i in range(getOSSnrMIDIs())]
        i = oslist + parseAconnect('i') + [("keyboard", i18n("Keyboard"))]
        o = oslist + parseAconnect('o')
        self.ilist, ititles = map(list, zip(*i))
        self.olist, otitles = map(list, zip(*o))

        # input
        l = QLabel(i18n("MIDI input:"))
        layout.addWidget(l, 1, 0)
        self.ibut = QComboBox()
        self.ibut.addItems(ititles)
        self.ibut.setToolTip(i18n("MIDI input to use. Choose 'Keyboard' if "
            "you want to play on the keyboard of your computer."))
        layout.addWidget(self.ibut, 1, 1)
        l.setBuddy(self.ibut)
        
        # output
        l = QLabel(i18n("MIDI output:"))
        layout.addWidget(l, 2, 0)
        self.obut = QComboBox()
        self.obut.addItems(otitles)
        self.obut.setToolTip(i18n("MIDI output to use."))
        layout.addWidget(self.obut, 2, 1)
        l.setBuddy(self.obut)
        
        # Language
        l = QLabel(i18n("Language:"))
        layout.addWidget(l, 3, 0)
        self.lang = QComboBox()
        self.lang.addItems((
            AUTO(), 'ne', 'en', 'en-short', 'de', 'no', 'sv', 'it', 'ca', 'es'))
        self.lang.setToolTip(i18n("The LilyPond language you want Rumor to "
            "output the pitches in."))
        layout.addWidget(self.lang, 3, 1)
        l.setBuddy(self.lang)

        hb = QHBoxLayout()
        layout.addLayout(hb, 4, 0, 1, 2)
        # explicit durations
        self.explDur = QCheckBox(i18n("Explicit durations"))
        self.explDur.setToolTip(i18n(
            "Add a duration after every note, even if it is the same as the "
            "preceding note."))
        hb.addWidget(self.explDur)

        # absolute pitches
        self.absPitches = QCheckBox(i18n("Absolute pitch"))
        self.absPitches.setToolTip(i18n(
            "Use absolute pitches instead of relative."))
        hb.addWidget(self.absPitches)

        hb = QHBoxLayout()
        layout.addLayout(hb, 5, 0, 1, 2)
        # No Barlines
        self.noBar = QCheckBox(i18n("No barlines"))
        self.noBar.setToolTip(i18n(
            "Filter the barlines out of Rumor's output."))
        hb.addWidget(self.noBar)

        # No dots
        self.noDots = QCheckBox(i18n("No dots"))
        self.noDots.setToolTip(i18n(
            "Do not use dotted notes, but ties instead."))
        hb.addWidget(self.noDots)

        # Legato
        self.legato = QCheckBox(i18n("Legato"))
        self.legato.setToolTip(i18n("Do not use rests, but give all notes "
            "the maximum length."))
        hb.addWidget(self.legato)

        # Strip rests
        self.stripRests = QCheckBox(i18n("Strip rests"))
        self.stripRests.setToolTip(i18n(
            "Strip leading and trialing rests from output."))
        hb.addWidget(self.stripRests)

        layout.addWidget(QLabel(i18n(
            "Guile scripts to load:")), 6, 0, 1, 2)

        # Guile scripts listview
        self.scripts = QTreeWidget()
        self.scripts.setRootIsDecorated(False)
        self.scripts.setHeaderLabels((i18n("Name"), i18n("Description")))
        self.scripts.setToolTip(i18n(
            "Here you can select which Guile scripts you want Rumor to load. "
            "Check \"What's this\" for more information."))
        localRumorDir = "~/.kde/share/apps/frescobaldi/rumor/"
        self.scripts.setWhatsThis(i18n(
            "Here you can select which Guile scripts you want Rumor to load. "
            "You can add your own scripts by putting them in %1. "
            "If the first line of your script starts with a semicolon (;) "
            "that line will be shown as description.", localRumorDir))
        layout.addWidget(self.scripts, 7, 0, 1, 2)
        
        self.loadSettings()

    def done(self, result):
        if result:
            self.saveSettings()
        KDialog.done(self, result)

    def loadSettings(self):
        """ Load the settings """
        conf = config("rumor")
        if 'oss:1' in self.ilist:
            idefault = odefault = 'oss:1'
        else:
            idefault = 'kbd'
            odefault = self.olist and self.olist[-1] or ""
        i = conf.readEntry("midi in", idefault)
        o = conf.readEntry("midi out", odefault)
        if i in self.ilist:
            self.ibut.setCurrentIndex(self.ilist.index(i))
        if o in self.olist:
            self.obut.setCurrentIndex(self.olist.index(o))
        setComboBox(self.lang, unautofy(conf.readEntry("language", "auto")))
        self.absPitches.setChecked(conf.readEntry("absolute pitches", False))
        self.explDur.setChecked(conf.readEntry("explicit durations", False))
        self.noBar.setChecked(conf.readEntry("no barlines", False))
        self.noDots.setChecked(conf.readEntry("no dots", False))
        self.legato.setChecked(conf.readEntry("legato", False))
        self.stripRests.setChecked(conf.readEntry("strip rests", False))
        # Guile scripts
        self.scripts.clear()
        scripts = conf.readEntry("scripts", [])
        for path in rumorScripts():
            name = os.path.basename(path)
            try:
                desc = open(path).readline().strip()
                item = QTreeWidgetItem(self.scripts)
                item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
                item.setCheckState(0, (name in scripts) and Qt.Checked or Qt.Unchecked)
                item.setText(0, name)
                if desc.startswith(';'):
                    item.setText(1, desc.strip(";"))
            except IOError:
                pass
        for col in 0, 1:
            self.scripts.resizeColumnToContents(col)

    def saveSettings(self):
        """ Save the settings """
        conf = config("rumor")
        conf.writeEntry("midi in", self.ilist[self.ibut.currentIndex()])
        conf.writeEntry("midi out", self.olist[self.obut.currentIndex()])
        conf.writeEntry("language", autofy(self.lang.currentText()))
        conf.writeEntry("absolute pitches", self.absPitches.isChecked())
        conf.writeEntry("explicit durations", self.explDur.isChecked())
        conf.writeEntry("no barlines", self.noBar.isChecked())
        conf.writeEntry("no dots", self.noDots.isChecked())
        conf.writeEntry("legato", self.legato.isChecked())
        conf.writeEntry("strip rests", self.stripRests.isChecked())
        # Read script treeview
        names = []
        for row in range(self.scripts.topLevelItemCount()):
            item = self.scripts.topLevelItem(row)
            if item.checkState(0) == Qt.Checked:
                names.append(item.text(0))
        conf.writeEntry("scripts", names)
コード例 #44
0
class MemUsageDialog(QDialog):
    def __init__(self, parent=None, update=True):
        QDialog.__init__(self, parent=parent)
        layout = QVBoxLayout()
        self.tree = QTreeWidget()
        self.tree.setHeaderLabels(["cache", "memory", "roi", "dtype", "type"])
        layout.addWidget(self.tree)
        self.setLayout(layout)

        self.memMgr = ArrayCacheMemoryMgr.instance

        self.timer = QTimer(self)
        if update:
            self.timer.timeout.connect(self._updateReport)
            self._updateReport()

    def _updateReport(self):
        reports = []
        for c in self.memMgr.namedCaches:
            r = MemInfoNode()
            try:
                c.generateReport(r)
                reports.append(r)
            except NotImplementedError:
                warnings.warn("cache operator {} does not implement generateReport()".format(c))
        self._showReports(reports)

        """
        import pickle
        f = open("/tmp/reports.pickle",'w')
        pickle.dump(reports, f)
        f.close()
        print "... saved MEM reports to file ..."
        """

    def _showReports(self, reports):
        self.tree.clear()
        root = self.tree.invisibleRootItem()
        for r in reports:
            self._showReportsImpl(r, root, 0)

    def _makeTreeWidgetItem(self, node):
        l = []
        l.append("%r" % node.name)
        l.append("%1.1f MB" % (node.usedMemory / 1024 ** 2.0))
        if node.roi is not None:
            l.append("%r\n%r" % (list(node.roi[0]), list(node.roi[1])))
        else:
            l.append("")
        if node.dtype is not None:
            if node.dtype == numpy.float32:
                l.append("float32")
            elif node.dtype == numpy.uint8:
                l.append("uint8")
            elif node.dtype == numpy.uint32:
                l.append("uint32")
            elif node.dtype == numpy.float64:
                l.append("float64")
            else:
                l.append(str(node.dtype))

        else:
            l.append("")

        t = str(node.type)
        t = t[len("<type '") + 1 : -len("'>")]
        t = t.split(".")[-1]
        l.append(t)
        return QTreeWidgetItem(l)

    def _showReportsImpl(self, node, itm, level):
        # print "  "*level,
        # print "node", node.name

        root = self._makeTreeWidgetItem(node)
        itm.addChild(root)
        root.setExpanded(True)

        for c in node.children:
            self._showReportsImpl(c, root, level + 1)

    def hideEvent(self, event):
        self.timer.stop()

    def showEvent(self, show):
        self.timer.start(5 * 1000)  # update every 5 sec.
コード例 #45
0
ファイル: OWGEODatasets.py プロジェクト: nikicc/orange-bio
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()
コード例 #46
0
class DBServersWidget(QWidget):
    """Displays a list of servers"""
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.debug = False

        self.connections = {}

        self.setWindowTitle("Servers")
        #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)

        self.mainLayout = QVBoxLayout()
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self.setLayout(self.mainLayout)

        #=============================================
        ## Top Toolbar
        topBar = QToolBar()
        topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.mainLayout.addWidget(topBar)

        ## Add the action buttons
        topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add)
        self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit),
                                                 "Edit", self.on_server_edit)
        self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete),
                                                   "Delete",
                                                   self.on_server_delete)

        #=============================================
        ## Tree
        self.tree = QTreeWidget()
        self.mainLayout.addWidget(self.tree)
        self.tree.setUniformRowHeights(True)
        self.tree.setRootIsDecorated(True)

        self.tree.setHeaderLabels(["Server",
                                   "Butt"])  # set header, but hide anyway
        self.tree.header().hide()
        self.tree.header().setResizeMode(C.node, QHeaderView.Stretch)
        self.tree.setColumnWidth(C.butt, 20)

        self.connect(self.tree, SIGNAL('itemSelectionChanged()'),
                     self.on_tree_selection_changed)
        self.connect(self.tree,
                     SIGNAL('itemDoubleClicked (QTreeWidgetItem *,int)'),
                     self.on_tree_double_clicked)

        self.buttGroup = QButtonGroup(self)
        self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"),
                     self.on_open_server)

        self.on_tree_selection_changed()

        self.load_servers()

    #=======================================
    ##== Tree Events
    def on_tree_selection_changed(self):

        disabled = self.tree.selectionModel().hasSelection() == False
        self.actionServerEdit.setDisabled(disabled)
        self.actionServerDelete.setDisabled(disabled)

    def on_tree_double_clicked(self):
        self.actionServerEdit.trigger()

    #=======================================
    ## Server Actions
    def on_server_add(self):
        self.show_server_dialog(None)

    def on_server_edit(self):
        item = self.tree.currentItem()
        if item == None:
            return
        server = str(item.text(C.server))
        self.show_server_dialog(server)

    def show_server_dialog(self, server=None):
        d = DBServerDialog.DBServerDialog(self, server)
        if d.exec_():
            self.load_servers()

    def load_servers(self):
        """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """

        self.tree.clear()

        for butt in self.buttGroup.buttons():
            self.buttGroup.removeButton(butt)

        for srv in G.settings.get_servers_list():

            item = QTreeWidgetItem()
            item.setText(C.node, srv['server'])
            #item.setText(C.user, srv['user'])
            self.tree.addTopLevelItem(item)

            butt = QToolButton()
            butt.setIcon(Ico.icon(Ico.Connect))
            butt.setProperty("server", srv['server'])
            self.tree.setItemWidget(item, C.butt, butt)
            self.buttGroup.addButton(butt)

    def on_server_delete(self):
        item = self.tree.currentItem()
        if item == None:
            return
        srv = str(item.text(C.server))
        G.settings.delete_server(srv)
        self.load_servers()

    def on_open_server(self, butt):

        # self.emit(SIGNAL("open_server"), butt.property("server").toString())
        srv_ki = str(butt.property("server").toString())
        server = G.settings.get_server(srv_ki)
        db = QSqlDatabase.addDatabase("QMYSQL", srv_ki)
        db.setHostName(server['server'])
        db.setUserName(server['user'])
        db.setPassword(server['passwd'])

        ok = db.open()
        if ok:
            #self.connections[srv_ki] =
            self.load_databases(srv_ki)
            print "open", ok

    def load_databases(self, srv_ki):
        """Load databases into tree node for server;  executes 'show databases;' or aslike """

        sql = "show databases;"
        query = QSqlQuery(QSqlDatabase.database(srv_ki))
        ok = query.exec_(sql)
        print ok, sql, query.result()

        # Get the parent node, ie the server node
        pItem = self.tree.findItems(srv_ki, Qt.MatchExactly, C.node)[0]

        ## Assumed value(0) is the table.. we need the defs (ie mysql case)
        while query.next():
            table_name = query.value(0).toString()
            nuItem = QTreeWidgetItem(pItem)
            nuItem.setText(C.node, table_name)
            #print table_name

        self.tree.setItemExpanded(pItem, True)
コード例 #47
0
class WServerInformation(QWidget, Logger.ClassLogger):
    """
    Widget for the global server information
    """
    def __init__(self, parent=None):
        """
        Constructs WServerInformation widget 

        @param parent: 
        @type parent:
        """
        QWidget.__init__(self, parent)
        self.parent = parent
        self.name = self.tr("Miscellaneous")
        self.createWidgets()
        self.createActions()
        self.createToolbar()
        self.deactivate()

    def createWidgets(self):
        """
        QtWidgets creation
        """
        self.dockToolbar = QToolBar(self)
        self.dockToolbar.setStyleSheet(
            "QToolBar { border: 0px }")  # remove 3D border
        self.dockToolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)

        self.dockToolbarReset = QToolBar(self)
        self.dockToolbarReset.setStyleSheet(
            "QToolBar { border: 0px }")  # remove 3D border
        self.dockToolbarReset.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)

        self.dockToolbarGen = QToolBar(self)
        self.dockToolbarGen.setStyleSheet(
            "QToolBar { border: 0px }")  # remove 3D border
        self.dockToolbarGen.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)

        self.refreshBox = QGroupBox("Refresh")
        self.refreshBox.setStyleSheet("""
                                           QGroupBox { font: normal; border: 1px solid silver; border-radius: 2px; } 
                                           QGroupBox { padding-bottom: 10px; background-color: #FAFAFA; } 
                                           QGroupBox::title { subcontrol-position: bottom center;}
                                       """)
        layoutRefreshBox = QHBoxLayout()
        layoutRefreshBox.addWidget(self.dockToolbar)
        layoutRefreshBox.setContentsMargins(0, 0, 0, 0)
        self.refreshBox.setLayout(layoutRefreshBox)

        self.resetBox = QGroupBox("Reset")
        self.resetBox.setStyleSheet("""
                                           QGroupBox { font: normal; border: 1px solid silver; border-radius: 2px; } 
                                           QGroupBox { padding-bottom: 10px; background-color: #FAFAFA; } 
                                           QGroupBox::title { subcontrol-position: bottom center;}
                                       """)
        layoutResetBox = QHBoxLayout()
        layoutResetBox.addWidget(self.dockToolbarReset)
        layoutResetBox.setContentsMargins(0, 0, 0, 0)
        self.resetBox.setLayout(layoutResetBox)

        self.genBox = QGroupBox("Prepare")
        self.genBox.setStyleSheet("""
                                           QGroupBox { font: normal; border: 1px solid silver; border-radius: 2px; } 
                                           QGroupBox { padding-bottom: 10px; background-color: #FAFAFA; } 
                                           QGroupBox::title { subcontrol-position: bottom center;}
                                       """)
        layoutGenBox = QHBoxLayout()
        layoutGenBox.addWidget(self.dockToolbarGen)
        layoutGenBox.setContentsMargins(0, 0, 0, 0)
        self.genBox.setLayout(layoutGenBox)

        layoutToolbars = QHBoxLayout()
        layoutToolbars.addWidget(self.refreshBox)
        layoutToolbars.addWidget(self.genBox)
        layoutToolbars.addWidget(self.resetBox)
        layoutToolbars.addStretch(1)

        layoutFinal = QHBoxLayout()
        layoutLeft = QVBoxLayout()

        layoutRight = QVBoxLayout()
        layoutRight.addLayout(layoutToolbars)

        self.diskUsageBox = QGroupBox("Disk Usage")
        self.nbSizeLogsOnDiskLabel = QLabel("0")
        self.nbSizeTmpOnDiskLabel = QLabel("0")
        self.nbSizeArchivesOnDiskLabel = QLabel("0")
        self.nbSizeAdpOnDiskLabel = QLabel("0")
        self.nbSizeLibOnDiskLabel = QLabel("0")
        self.nbSizeBakOnDiskLabel = QLabel("0")
        self.nbSizeTestsOnDiskLabel = QLabel("0")
        layout2 = QFormLayout()
        layout2.addRow(QLabel("Logs"), self.nbSizeLogsOnDiskLabel)
        layout2.addRow(QLabel("Tmp"), self.nbSizeTmpOnDiskLabel)
        layout2.addRow(QLabel("Archives"), self.nbSizeArchivesOnDiskLabel)
        layout2.addRow(QLabel("Tests"), self.nbSizeTestsOnDiskLabel)
        layout2.addRow(QLabel("Adapters"), self.nbSizeAdpOnDiskLabel)
        layout2.addRow(QLabel("Libraries"), self.nbSizeLibOnDiskLabel)
        layout2.addRow(QLabel("Backups"), self.nbSizeBakOnDiskLabel)
        self.diskUsageBox.setLayout(layout2)

        layoutGrid = QGridLayout()
        layoutGrid.addWidget(self.diskUsageBox, 0, 0)
        layoutRight.addLayout(layoutGrid)
        layoutRight.addStretch(1)

        self.informations = QTreeWidget(self)
        self.informations.setVerticalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self.informations.setIndentation(10)
        self.labels = [self.tr("Key"), self.tr("Value")]
        self.informations.setHeaderLabels(self.labels)

        layoutLeft.addWidget(self.informations)
        layoutFinal.addLayout(layoutLeft)
        layoutFinal.addLayout(layoutRight)

        self.setLayout(layoutFinal)

    def createActions(self):
        """
        Actions defined:
         * generate the cache for the documentation
         * generate all packages
         * refresh statistics
         * refresh the context of the server
         * check the syntax of adapters
         * reset statistics
        """
        self.genCacheHelpAction = QtHelper.createAction(
            self,
            "&Generate\nDocumentations",
            self.genCacheHelp,
            tip='Generate the cache for the documentation',
            icon=QIcon(":/generate-doc.png"))
        self.genTarAdaptersAction = QtHelper.createAction(
            self,
            "&Package\nAdapters",
            self.genPackageAdapters,
            tip='Generate adapters packages',
            icon=QIcon(":/generate-tar.png"))
        self.genTarLibrariesAction = QtHelper.createAction(
            self,
            "&Package\nLibraries",
            self.genPackageLibraries,
            tip='Generate libraries packages',
            icon=QIcon(":/generate-tar.png"))
        self.genTarSamplesAction = QtHelper.createAction(
            self,
            "&Package\nSamples",
            self.genPackageSamples,
            tip='Generate samples packages',
            icon=QIcon(":/generate-tar.png"))

        self.refreshAction = QtHelper.createAction(
            self,
            "&Usages",
            self.refreshUsages,
            tip='Refresh Usages',
            tooltip='Refresh usages',
            icon=QIcon(":/refresh-statistics.png"))
        self.refreshCtxAction = QtHelper.createAction(
            self,
            "&Session",
            self.refreshCtx,
            tip='Refresh server context',
            tooltip='Refresh server context',
            icon=QIcon(":/act-refresh.png"))

        self.resetAction = QtHelper.createAction(
            self,
            "&Reset\nStatistics",
            self.resetStats,
            tip='Reset all statistics',
            icon=QIcon(":/reset-counter.png"))
        self.unlockAllTestsAction = QtHelper.createAction(
            self,
            "&Unlock\nTests",
            self.unlockTests,
            tip='Unlock all files',
            icon=QIcon(":/unlock.png"))

        self.unlockAllAdaptersAction = QtHelper.createAction(
            self,
            "&Unlock\nAdapters",
            self.unlockAdapters,
            tip='Unlock all files',
            icon=QIcon(":/unlock.png"))

        self.unlockAllLibrariesAction = QtHelper.createAction(
            self,
            "&Unlock\nLibraries",
            self.unlockLibraries,
            tip='Unlock all files',
            icon=QIcon(":/unlock.png"))

    def createToolbar(self):
        """
        Toolbar creation
        """
        self.dockToolbar.setObjectName("Misc toolbar")
        self.dockToolbar.addAction(self.refreshCtxAction)
        self.dockToolbar.addAction(self.refreshAction)
        self.dockToolbar.setIconSize(QSize(16, 16))

        self.dockToolbarGen.setObjectName("Generate toolbar")
        self.dockToolbarGen.addAction(self.genCacheHelpAction)
        self.dockToolbarGen.addAction(self.genTarAdaptersAction)
        self.dockToolbarGen.addAction(self.genTarLibrariesAction)
        self.dockToolbarGen.addAction(self.genTarSamplesAction)
        self.dockToolbarGen.setIconSize(QSize(16, 16))

        self.dockToolbarReset.setObjectName("Reset toolbar")
        self.dockToolbarReset.addAction(self.resetAction)
        self.dockToolbarReset.addAction(self.unlockAllTestsAction)
        self.dockToolbarReset.addAction(self.unlockAllAdaptersAction)
        self.dockToolbarReset.addAction(self.unlockAllLibrariesAction)
        self.dockToolbarReset.setIconSize(QSize(16, 16))

    def unlockTests(self):
        """
        Unlock all files
        """
        RCI.instance().unlockTests()

    def unlockAdapters(self):
        """
        Unlock all files
        """
        RCI.instance().unlockAdapters()

    def unlockLibraries(self):
        """
        Unlock all files
        """
        RCI.instance().unlockLibraries()

    def genPackageAdapters(self):
        """
        Generate all tar packages
        """
        RCI.instance().buildAdapters()

    def genPackageLibraries(self):
        """
        Generate all tar packages
        """
        RCI.instance().buildLibraries()

    def genPackageSamples(self):
        """
        Generate all tar packages
        """
        RCI.instance().buildSamples()

    def resetStats(self):
        """
        Reset statistic manually
        """
        reply = QMessageBox.question(self, "Reset statistics",
                                     "Are you sure ?",
                                     QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            RCI.instance().resetTestsMetrics()

    def refreshCtx(self):
        """
        Call the server to refresh context of the server
        """
        RCI.instance().sessionContext()

    def refreshUsages(self):
        """
        Call the server to refresh statistics of the server
        """
        RCI.instance().systemUsages()

    def genCacheHelp(self):
        """
        Call the server to generate the cache documentation
        """
        reply = QMessageBox.question(self, "Generate cache", "Are you sure ?",
                                     QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            RCI.instance().buildDocumentations()

    def active(self):
        """
        Enables QTreeWidget
        """
        self.diskUsageBox.setEnabled(True)
        self.informations.setEnabled(True)
        self.genCacheHelpAction.setEnabled(True)
        self.resetAction.setEnabled(True)
        self.unlockAllTestsAction.setEnabled(True)
        self.unlockAllAdaptersAction.setEnabled(True)
        self.unlockAllLibrariesAction.setEnabled(True)

    def deactivate(self):
        """
        Clears QTreeWidget and disables it
        """
        self.diskUsageBox.setEnabled(False)

        self.informations.clear()
        self.informations.setEnabled(False)
        self.genCacheHelpAction.setEnabled(False)
        self.resetAction.setEnabled(False)
        self.unlockAllTestsAction.setEnabled(False)
        self.unlockAllAdaptersAction.setEnabled(False)
        self.unlockAllLibrariesAction.setEnabled(False)

        self.nbSizeLogsOnDiskLabel.setText("0")
        self.nbSizeTmpOnDiskLabel.setText("0")
        self.nbSizeArchivesOnDiskLabel.setText("0")
        self.nbSizeAdpOnDiskLabel.setText("0")
        self.nbSizeLibOnDiskLabel.setText("0")
        self.nbSizeBakOnDiskLabel.setText("0")
        self.nbSizeTestsOnDiskLabel.setText("0")

    def cleanContext(self):
        """
        Clear the context
        Removes all items
        """
        self.informations.clear()

    def loadStats(self, data):
        """
        Load statistics
        """

        self.nbSizeLogsOnDiskLabel.setText(
            str(QtHelper.bytes2human(data['disk-usage-logs'])))
        self.nbSizeTmpOnDiskLabel.setText(
            str(QtHelper.bytes2human(data['disk-usage-tmp'])))

        self.nbSizeArchivesOnDiskLabel.setText(
            str(QtHelper.bytes2human(data['disk-usage-testresults'])))
        self.nbSizeAdpOnDiskLabel.setText(
            str(QtHelper.bytes2human(data['disk-usage-adapters'])))
        self.nbSizeLibOnDiskLabel.setText(
            str(QtHelper.bytes2human(data['disk-usage-libraries'])))
        self.nbSizeBakOnDiskLabel.setText(
            str(QtHelper.bytes2human(data['disk-usage-backups'])))
        self.nbSizeTestsOnDiskLabel.setText(
            str(QtHelper.bytes2human(data['disk-usage-tests'])))

    def loadData(self, data):
        """
        Load all config keys

        @param data: 
        @type data:
        """
        if isinstance(data, dict):
            data = [data]
        for param in data:
            probeItem = ParamItem(param=param, parent=self.informations)

        # resize columns
        for i in xrange(len(self.labels) - 1):
            self.informations.resizeColumnToContents(i)
コード例 #48
0
ファイル: threadsviewer.py プロジェクト: eaglexmw/codimension
class ThreadsViewer( QWidget ):
    " Implements the threads viewer for a debugger "

    def __init__( self, debugger, parent = None ):
        QWidget.__init__( self, parent )

        self.__debugger = debugger
        self.__createLayout()

        if Settings().showThreadViewer == False:
            self.__onShowHide( True )
        return

    def __createLayout( self ):
        " Creates the widget layout "

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

        self.headerFrame = QFrame()
        self.headerFrame.setFrameStyle( QFrame.StyledPanel )
        self.headerFrame.setAutoFillBackground( True )
        headerPalette = self.headerFrame.palette()
        headerBackground = headerPalette.color( QPalette.Background )
        headerBackground.setRgb( min( headerBackground.red() + 30, 255 ),
                                 min( headerBackground.green() + 30, 255 ),
                                 min( headerBackground.blue() + 30, 255 ) )
        headerPalette.setColor( QPalette.Background, headerBackground )
        self.headerFrame.setPalette( headerPalette )
        self.headerFrame.setFixedHeight( 24 )

        self.__threadsLabel = QLabel( "Threads" )

        expandingSpacer = QSpacerItem( 10, 10, QSizePolicy.Expanding )
        fixedSpacer = QSpacerItem( 3, 3 )

        self.__showHideButton = QToolButton()
        self.__showHideButton.setAutoRaise( True )
        self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
        self.__showHideButton.setFixedSize( 20, 20 )
        self.__showHideButton.setToolTip( "Hide threads list" )
        self.__showHideButton.setFocusPolicy( Qt.NoFocus )
        self.__showHideButton.clicked.connect( self.__onShowHide )

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins( 0, 0, 0, 0 )
        headerLayout.addSpacerItem( fixedSpacer )
        headerLayout.addWidget( self.__threadsLabel )
        headerLayout.addSpacerItem( expandingSpacer )
        headerLayout.addWidget( self.__showHideButton )
        self.headerFrame.setLayout( headerLayout )

        self.__threadsList = QTreeWidget()
        self.__threadsList.setSortingEnabled( False )
        # I might not need that because of two reasons:
        # - the window has no focus
        # - the window has custom current indicator
        # self.__threadsList.setAlternatingRowColors( True )
        self.__threadsList.setRootIsDecorated( False )
        self.__threadsList.setItemsExpandable( False )
        self.__threadsList.setUniformRowHeights( True )
        self.__threadsList.setSelectionMode( QAbstractItemView.NoSelection )
        self.__threadsList.setSelectionBehavior( QAbstractItemView.SelectRows )
        self.__threadsList.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.__threadsList.setFocusPolicy( Qt.NoFocus )

        self.__threadsList.itemClicked.connect( self.__onThreadClicked )
        self.__threadsList.setHeaderLabels( [ "", "Name", "State", "TID" ] )

        verticalLayout.addWidget( self.headerFrame )
        verticalLayout.addWidget( self.__threadsList )
        return

    def __onShowHide( self, startup = False ):
        " Triggered when show/hide button is clicked "
        if startup or self.__threadsList.isVisible():
            self.__threadsList.setVisible( False )
            self.__showHideButton.setIcon( PixmapCache().getIcon( 'more.png' ) )
            self.__showHideButton.setToolTip( "Show threads list" )

            self.__minH = self.minimumHeight()
            self.__maxH = self.maximumHeight()

            self.setMinimumHeight( self.headerFrame.height() )
            self.setMaximumHeight( self.headerFrame.height() )

            Settings().showThreadViewer = False
        else:
            self.__threadsList.setVisible( True )
            self.__showHideButton.setIcon( PixmapCache().getIcon( 'less.png' ) )
            self.__showHideButton.setToolTip( "Hide threads list" )

            self.setMinimumHeight( self.__minH )
            self.setMaximumHeight( self.__maxH )

            Settings().showThreadViewer = True
        return

    def __resizeColumns( self ):
        " Resize the files list columns "
        self.__threadsList.header().setStretchLastSection( True )
        self.__threadsList.header().resizeSections(
                                    QHeaderView.ResizeToContents )
        self.__threadsList.header().resizeSection( 0, 22 )
        self.__threadsList.header().setResizeMode( 0, QHeaderView.Fixed )
        return

    def clear( self ):
        " Clears the content "
        self.__threadsList.clear()
        self.__threadsLabel.setText( "Threads" )
        return

    def populate( self, currentThreadID, threadList ):
        " Populates the thread list from the client "
        self.clear()
        for thread in threadList:
            if thread[ 'broken' ]:
                state = "Waiting at breakpoint"
            else:
                state = "Running"
            item = ThreadItem( thread[ 'id' ], thread[ 'name' ], state )
            if thread[ 'id' ] == currentThreadID:
                item.setCurrent( True )
            self.__threadsList.addTopLevelItem( item )

        self.__resizeColumns()
        self.__threadsLabel.setText( "Threads (total: " +
                                     str( len( threadList ) ) + ")" )
        return

    def switchControl( self, isInIDE ):
        " Switches the UI depending where the control flow is "
        self.__threadsList.setEnabled( isInIDE )
        return

    def __onThreadClicked( self, item, column ):
        " Triggered when a thread is clicked "
        if item.isCurrent():
            return

        for index in xrange( self.__threadsList.topLevelItemCount() ):
            listItem = self.__threadsList.topLevelItem( index )
            if listItem.isCurrent():
                listItem.setCurrent( False )
                break
        item.setCurrent( True )

        self.__debugger.remoteSetThread( item.getTID() )
        return
コード例 #49
0
ファイル: DBBrowser.py プロジェクト: actuarial-tools/PyQtDb
class DBBrowser(QMainWindow):
    def __init__(self, parent, server):
        QMainWindow.__init__(self, parent)

        self.debug = False
        self.server = server

        self.db = None

        self.setWindowTitle("Database Browser")
        #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)

        topBar = QToolBar()

        self.addToolBar(Qt.TopToolBarArea, topBar)

        self.cenWid = QWidget()
        self.setCentralWidget(self.cenWid)

        self.mainLayout = QHBoxLayout()
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self.cenWid.setLayout(self.mainLayout)

        self.treeTables = QTreeWidget()
        self.mainLayout.addWidget(self.treeTables, 1)
        self.treeTables.setHeaderLabels(["Table"])
        self.treeTables.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.treeTables.setSelectionMode(QTreeView.SingleSelection)
        self.connect(self.treeTables, SIGNAL('itemSelectionChanged()'),
                     self.on_table)

        self.treeColumns = QTreeWidget()
        self.mainLayout.addWidget(self.treeColumns, 4)
        self.treeColumns.setHeaderLabels(["Column", "Type", "Nullable"])

        self.db_connect()

        #self.fetch()

    def on_table(self):
        item = self.treeTables.currentItem()
        if item == None:
            return
        self.fetch(table=str(item.text(0)))

    def db_connect(self):
        #print "db_connect", self.server
        self.db = QSqlDatabase.addDatabase("QMYSQL")
        self.db.setHostName(self.server['server'])
        self.db.setUserName(self.server['user'])
        self.db.setPassword(self.server['passwd'])

        ok = self.db.open()
        print "open", ok
        #self.db.setHostName(self.server['server'])

    def load_data(self, data):

        if "tables" in data:

            self.treeTables.clear()
            for t in data['tables']:
                item = QTreeWidgetItem()
                item.setText(0, t['table'])
                self.treeTables.addTopLevelItem(item)

        else:
            self.treeColumns.clear()
            for t in data['columns']:
                item = QTreeWidgetItem()
                item.setText(0, t['column'])
                item.setText(1, t['type'])
                item.setText(2, "Yes" if t['nullable'] else "-")
                self.treeColumns.addTopLevelItem(item)
コード例 #50
0
class VersionSelectDialog( QDialog ):
    def __init__( self, parent ):
        # initialize the super class
        super( VersionSelectDialog, self ).__init__( parent )
        
        # create the tree
        self.uiVersionsTREE = QTreeWidget(self)
        self.uiVersionsTREE.setAlternatingRowColors(True)
        self.uiVersionsTREE.setRootIsDecorated(False)
        self.uiVersionsTREE.setSelectionMode( self.uiVersionsTREE.NoSelection )
        
        header = self.uiVersionsTREE.header()
        header.setVisible(False)
        
        # create the layout
        layout = QVBoxLayout()
        layout.addWidget(self.uiVersionsTREE)
        layout.setContentsMargins(0,0,0,0)
        
        # inherit the highlight palette
        palette = self.palette()
        palette.setColor(palette.Highlight,parent.palette().color(palette.Highlight))
        self.setPalette(palette)
        
        # set dialog information
        self.setLayout(layout)
        self.setWindowFlags( Qt.Popup )
        self.resize(500,250)
        
        # create connections
        self.uiVersionsTREE.itemClicked.connect( self.acceptItem )
    
    def closeEvent( self, event ):
        # update all the items for this
        for i in range( self.uiVersionsTREE.topLevelItemCount() ):
            item    = self.uiVersionsTREE.topLevelItem(i)
            widget  = item.versionWidget()
            version = widget.version()
            
            # match the active state
            version.setActive(widget.isActive())
        
        super(VersionSelectDialog,self).closeEvent(event)
    
    def acceptItem( self, item ):
        # handle version change information
        widget = item.versionWidget()
        widget.toggleActive()
        
        # accept the dialog
        self.close()
    
    def popup( self, versions ):
        self.uiVersionsTREE.setUpdatesEnabled(False)
        self.uiVersionsTREE.blockSignals(True)
        
        self.uiVersionsTREE.clear()
        for version in versions:
            item = VersionItem(self.uiVersionsTREE, version)
            self.uiVersionsTREE.addTopLevelItem( item )
            self.uiVersionsTREE.setItemWidget( item, 0, item.versionWidget() )
        
        # reset the scrolling
        self.uiVersionsTREE.verticalScrollBar().setValue(0)
        
        self.uiVersionsTREE.setUpdatesEnabled(True)
        self.uiVersionsTREE.blockSignals(False)
        
        return self.exec_()
コード例 #51
0
class OWGenExpress(widget.OWWidget):
    name = "GenExpress"
    description = "Expression data from GenExpress."
    icon = "../widgets/icons/GenCloud.svg"
    priority = 36

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

    username = settings.Setting("anonymous")
    password = settings.Setting("")
    log2 = settings.Setting(False)
    transpose = settings.Setting(False)
    rtypei = settings.Setting(0)
    projecti = settings.Setting(0)
    serveri = settings.Setting(0)
    exnamei = settings.Setting(6)

    excludeconstant = settings.Setting(False)
    joinreplicates = settings.Setting(False)
    currentSelection = settings.Setting(None)

    experimentsHeaderState = settings.Setting(
        {name: False
         for _, name in HEADER[:ID_INDEX + 1]})

    storedSortOrder = settings.Setting([])
    storedSelections = settings.Setting([])

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

        self.servers = [
            ('https://dictyexpress.research.bcm.edu/', 'dictyExpress'),
            ('https://cloud.genialis.com/', 'Genialis'),
        ]

        self.selectedExperiments = []
        self.buffer = dicty.CacheSQLite(bufferfile)

        self.searchString = ""

        self.items = []

        self.result_types = []

        self.controlArea.setMaximumWidth(250)
        self.controlArea.setMinimumWidth(250)

        box = gui.widgetBox(self.controlArea, 'Project')
        self.projectCB = gui.comboBox(box,
                                      self,
                                      "projecti",
                                      items=[],
                                      callback=self.ProjectChosen)

        self.projects = []

        b = gui.widgetBox(self.controlArea, "Selection bookmarks")
        self.selectionSetsWidget = SelectionSetsWidget(self)
        self.selectionSetsWidget.setSizePolicy(QSizePolicy.Preferred,
                                               QSizePolicy.Maximum)

        def store_selections(modified):
            if not modified:
                self.storedSelections = self.selectionSetsWidget.selections

        self.selectionSetsWidget.selectionModified.connect(store_selections)

        b.layout().addWidget(self.selectionSetsWidget)

        gui.separator(self.controlArea)

        b = gui.widgetBox(self.controlArea, "Sort output columns")
        self.columnsSortingWidget = SortedListWidget(self)
        self.columnsSortingWidget.setSizePolicy(QSizePolicy.Preferred,
                                                QSizePolicy.Maximum)

        box = gui.widgetBox(self.controlArea, 'Experiment name')
        self.experimentNameCB = gui.comboBox(box,
                                             self,
                                             "exnamei",
                                             items=SORTING_MODEL_LIST)

        b.layout().addWidget(self.columnsSortingWidget)
        sorting_model = QStringListModel(SORTING_MODEL_LIST)
        self.columnsSortingWidget.setModel(sorting_model)
        self.columnsSortingWidget.sortingOrder = self.storedSortOrder

        def store_sort_order():
            self.storedSortOrder = self.columnsSortingWidget.sortingOrder

        self.columnsSortingWidget.sortingOrderChanged.connect(store_sort_order)

        gui.separator(self.controlArea)

        box = gui.widgetBox(self.controlArea, 'Expression Type')
        self.expressionTypesCB = gui.comboBox(box,
                                              self,
                                              "rtypei",
                                              items=[],
                                              callback=self.UpdateResultsList)

        gui.checkBox(self.controlArea, self, "excludeconstant",
                     "Exclude labels with constant values")

        gui.checkBox(self.controlArea, self, "joinreplicates",
                     "Average replicates (use median)")

        gui.checkBox(self.controlArea, self, "log2",
                     "Logarithmic (base 2) transformation")

        gui.checkBox(self.controlArea, self, "transpose", "Genes as columns")

        self.commit_button = gui.button(self.controlArea,
                                        self,
                                        "&Commit",
                                        callback=self.Commit)
        self.commit_button.setDisabled(True)

        gui.rubber(self.controlArea)

        box = gui.widgetBox(self.controlArea, 'Server')
        gui.comboBox(box,
                     self,
                     "serveri",
                     items=[title for url, title in self.servers],
                     callback=self.ServerChosen)

        gui.lineEdit(box,
                     self,
                     "username",
                     "Username:"******"password",
                                  "Password:"******"Clear cache",
                   callback=self.clear_cache)

        gui.lineEdit(self.mainArea,
                     self,
                     "searchString",
                     "Search",
                     callbackOnType=True,
                     callback=self.SearchUpdate)

        self.headerLabels = [t[1] for t in HEADER]

        self.experimentsWidget = QTreeWidget()
        self.experimentsWidget.setHeaderLabels(self.headerLabels)
        self.experimentsWidget.setSelectionMode(QTreeWidget.ExtendedSelection)
        self.experimentsWidget.setRootIsDecorated(False)
        self.experimentsWidget.setSortingEnabled(True)

        contextEventFilter = gui.VisibleHeaderSectionContextEventFilter(
            self.experimentsWidget, self.experimentsWidget)

        self.experimentsWidget.header().installEventFilter(contextEventFilter)
        self.experimentsWidget.setItemDelegateForColumn(
            0, gui.IndicatorItemDelegate(self, role=Qt.DisplayRole))

        self.experimentsWidget.setAlternatingRowColors(True)

        self.experimentsWidget.selectionModel().selectionChanged.connect(
            self.onSelectionChanged)

        self.selectionSetsWidget.setSelectionModel(
            self.experimentsWidget.selectionModel())
        self.selectionSetsWidget.setSelections(self.storedSelections)

        self.mainArea.layout().addWidget(self.experimentsWidget)

        self.restoreHeaderState()

        self.experimentsWidget.header().geometriesChanged.connect(
            self.saveHeaderState)

        self.dbc = None

        self.AuthSet()

        QTimer.singleShot(100, self.ConnectAndUpdate)

    def sizeHint(self):
        return QSize(800, 600)

    def AuthSet(self):
        if len(self.username):
            self.passf.setDisabled(False)
        else:
            self.passf.setDisabled(True)

    def AuthChanged(self):
        self.AuthSet()
        self.ConnectAndUpdate()

    def ConnectAndUpdate(self):
        self.Connect()
        if self.dbc:

            def get_data_count(project_id):
                # XXX: is there a better way?
                # Note: limit 0 would return all objects
                return self.dbc.gen.api.data.get(
                    case_ids__contains=project_id,
                    type__startswith='data:expression:',
                    limit=1)['meta']['total_count']

            self.projects = sorted([
                p for p in self.dbc.projects().items()
                if get_data_count(p[0]) > 0
            ],
                                   key=lambda x: x[1])
            self.UpdateProjects()
            self.ProjectChosen()
            self.UpdateExperimentTypes()

    def Connect(self):
        self.error(1)
        self.warning(1)

        username = '******'
        password = '******'
        url = self.servers[self.serveri][0]

        if self.username:
            username = self.username
            password = self.password

        if username.lower() in ['*****@*****.**', 'anonymous']:
            username = '******'
            password = '******'

        self.dbc = None
        self.projects = []
        self.result_types = []

        try:
            self.dbc = Genesis(address=url,
                               username=username,
                               password=password,
                               cache=self.buffer)
        except requests.exceptions.ConnectionError:
            self.dbc = Genesis(address=url,
                               username=username,
                               password=password,
                               connect=False,
                               cache=self.buffer)
            self.warning(1, "Could not connect to server, working from cache.")
        except Exception:
            self.error(1, "Wrong username or password.")

        self.UpdateProjects()
        self.UpdateExperimentTypes()  # clear lists

    def Reload(self):
        self.UpdateExperiments(reload=True)

    def clear_cache(self):
        self.buffer.clear()
        self.Reload()

    def rtype(self):
        """Return selected result template type """
        if self.result_types:
            return self.result_types[self.rtypei]
        else:
            return None

    def UpdateExperimentTypes(self):
        self.expressionTypesCB.clear()
        items = [self.result_types_labels[desc] for desc in self.result_types]
        self.expressionTypesCB.addItems(items)
        #do not update anything if the list is empty
        if len(self.result_types):
            self.rtypei = max(0, min(self.rtypei, len(self.result_types) - 1))

    def UpdateProjects(self):
        self.projectCB.clear()
        items = [desc for pid, desc in self.projects]
        self.projectCB.addItems(items)
        #do not update anything if the list if empty
        if len(self.projects) > 0:
            self.projecti = max(0, min(self.projecti, len(self.projects) - 1))

    def UpdateExperiments(self, reload=False):

        self.experimentsWidget.clear()

        if not self.dbc or not self.dbc.projectid:  # the connection did not succeed
            return

        self.items = []

        self.progressBarInit()

        result_types = []
        result_types_labels = []

        sucind = False  # success indicator for database index

        try:
            result_types, result_types_labels = self.dbc.result_types(
                reload=reload)
            sucind = True
        except Exception:
            try:
                result_types, result_types_labels = self.dbc.result_types()
                self.warning(0, "Can not access database - using cached data.")
                sucind = True
            except Exception:
                self.error(0, "Can not access database.")

        if sucind:
            self.warning(0)
            self.error(0)

        self.result_types = result_types
        self.result_types_labels = result_types_labels

        self.UpdateExperimentTypes()
        self.UpdateResultsList(reload=reload)

        self.progressBarFinished()

        if self.currentSelection:
            self.currentSelection.select(
                self.experimentsWidget.selectionModel())

        self.handle_commit_button()

    def ProjectChosen(self, reload=False):
        if self.projects:
            self.dbc.projectid = self.projects[self.projecti][0]
        else:
            self.dbc.projectid = None

        self.UpdateExperiments(reload=reload)

    def ServerChosen(self):
        self.ConnectAndUpdate()

    def UpdateResultsList(self, reload=False):
        results_list = self.dbc.results_list(self.rtype(), reload=reload)
        try:
            results_list = self.dbc.results_list(self.rtype(), reload=reload)
        except Exception:
            try:
                results_list = self.dbc.results_list(self.rtype())
            except Exception:
                self.error(0, "Can not access database.")

        self.results_list = results_list

        #softly change the view so that the selection stays the same

        items_shown = {}
        for i, item in enumerate(self.items):
            c = str(item.text(ID_INDEX))
            items_shown[c] = i

        items_to_show = set(id_ for id_ in self.results_list)

        add_items = set(items_to_show) - set(items_shown)
        delete_items = set(items_shown) - set(items_to_show)

        i = 0
        while i < self.experimentsWidget.topLevelItemCount():
            it = self.experimentsWidget.topLevelItem(i)
            if str(it.text(ID_INDEX)) in delete_items:
                self.experimentsWidget.takeTopLevelItem(i)
            else:
                i += 1

        delete_ind = set([items_shown[i] for i in delete_items])
        self.items = [
            it for i, it in enumerate(self.items) if i not in delete_ind
        ]

        for r_annot in add_items:
            d = defaultdict(lambda: "?", self.results_list[r_annot])
            row_items = [""] + [
                to_text(d.get(key, "?")) for key, _ in HEADER[1:]
            ]
            row_items[ID_INDEX] = r_annot

            ci = MyTreeWidgetItem(self.experimentsWidget, row_items)
            self.items.append(ci)

        for i in range(len(self.headerLabels)):
            self.experimentsWidget.resizeColumnToContents(i)

        self.wantbufver = lambda x: self.results_list[x]["date_modified"]

        self.UpdateCached()

    def UpdateCached(self):
        if self.wantbufver and self.dbc:

            for item in self.items:
                id = str(item.text(ID_INDEX))
                version = self.dbc._in_buffer(id + "|||" + self.rtype())
                value = " " if version == self.wantbufver(id) else ""
                item.setData(0, Qt.DisplayRole, value)

    def SearchUpdate(self, string=""):
        for item in self.items:
            item.setHidden(not all(s in item
                                   for s in self.searchString.split()))

    def Commit(self):

        pb = gui.ProgressBar(self, iterations=100)

        table = None

        ids = []
        for item in self.experimentsWidget.selectedItems():
            unique_id = str(item.text(ID_INDEX))
            ids.append(unique_id)

        transfn = None
        if self.log2:
            transfn = lambda x: math.log(x + 1.0, 2)

        reverse_header_dict = {name: name for key, name in HEADER}
        reverse_header_dict["ID"] = "id"

        allowed_labels = None

        def namefn(a):
            name = SORTING_MODEL_LIST[self.exnamei]
            name = reverse_header_dict.get(name, "id")
            return dict(a)[name]

        if len(ids):
            table = self.dbc.get_data(
                ids=ids,
                result_type=self.rtype(),
                callback=pb.advance,
                exclude_constant_labels=self.excludeconstant,
                bufver=self.wantbufver,
                transform=transfn,
                allowed_labels=allowed_labels,
                namefn=namefn)

            if self.joinreplicates:
                table = dicty.join_replicates(
                    table,
                    ignorenames=self.dbc.IGNORE_REPLICATE,
                    namefn="name",
                    avg=dicty.median,
                    fnshow=lambda x: " | ".join(map(str, x)))

            # Sort attributes
            sortOrder = self.columnsSortingWidget.sortingOrder

            all_values = defaultdict(set)
            for at in table.domain.attributes:
                atts = at.attributes
                for name in sortOrder:
                    all_values[name].add(
                        atts.get(reverse_header_dict[name], ""))

            isnum = {}
            for at, vals in all_values.items():
                vals = filter(None, vals)
                try:
                    for a in vals:
                        float(a)
                    isnum[at] = True
                except ValueError:
                    isnum[at] = False

            def optfloat(x, at):
                if x == "":
                    return ""
                else:
                    return float(x) if isnum[at] else x

            def sorting_key(attr):
                atts = attr.attributes
                return tuple([
                    optfloat(atts.get(reverse_header_dict[name], ""), name)
                    for name in sortOrder
                ])

            attributes = sorted(table.domain.attributes, key=sorting_key)

            domain = Orange.data.Domain(attributes, table.domain.class_vars,
                                        table.domain.metas)

            table = Orange.data.Table.from_table(domain, table)
            table = Orange.data.Table(domain, table)

            if self.transpose:
                experiments = [at for at in table.domain.variables]
                attr = [
                    compat.ContinuousVariable.make(ex['DDB'].value)
                    for ex in table
                ]
                metavars = sorted(table.domain.variables[0].attributes.keys())
                metavars = [
                    compat.StringVariable.make(name) for name in metavars
                ]
                domain = compat.create_domain(attr, None, metavars)
                metavars = compat.get_metas(domain)
                metas = [[exp.attributes[var.name] for var in metavars]
                         for exp in experiments]
                table = compat.create_table(domain, table.X.transpose(), None,
                                            metas)

            data_hints.set_hint(table, "taxid", "352472")
            data_hints.set_hint(table, "genesinrows", False)

            self.send("Data", table)

            self.UpdateCached()

        pb.finish()

    def onSelectionChanged(self, selected, deselected):
        self.handle_commit_button()

    def handle_commit_button(self):
        self.currentSelection = \
            SelectionByKey(self.experimentsWidget.selectionModel().selection(),
                           key=(ID_INDEX,))
        self.commit_button.setDisabled(not len(self.currentSelection))

    def saveHeaderState(self):
        hview = self.experimentsWidget.header()
        for i, label in enumerate(self.headerLabels):
            self.experimentsHeaderState[label] = hview.isSectionHidden(i)

    def restoreHeaderState(self):
        hview = self.experimentsWidget.header()
        state = self.experimentsHeaderState
        for i, label in enumerate(self.headerLabels):
            hview.setSectionHidden(i, state.get(label, True))
            self.experimentsWidget.resizeColumnToContents(i)
コード例 #52
0
ファイル: owitemsets.py プロジェクト: r0b1n1983liu/o3env
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()
コード例 #53
0
class RunsDialog(QtHelper.EnhancedQDialog):
    """
    Runs several dialog
    """
    RefreshRepository = pyqtSignal(str)
    def __init__(self, dialogName, parent = None, iRepo=None, lRepo=None, rRepo=None):
        """
        Constructor
        """
        QtHelper.EnhancedQDialog.__init__(self, parent)

        self.name = self.tr("Prepare a group of runs")
        self.projectReady = False
        self.iRepo = iRepo
        self.lRepo = lRepo
        self.rRepo = rRepo

        self.createDialog()
        self.createConnections()

    def createDialog(self):
        """
        Create qt dialog
        """
        self.setWindowTitle( self.name )

        mainLayout = QHBoxLayout()
        layoutTests = QHBoxLayout()
        layoutRepoTest = QVBoxLayout()

        self.prjCombo = QComboBox(self)
        self.prjCombo.setEnabled(False)

        self.repoTests = QTreeWidget(self)
        self.repoTests.setFrameShape(QFrame.NoFrame)
        if USE_PYQT5:
            self.repoTests.header().setSectionResizeMode(QHeaderView.Stretch)
        else:
            self.repoTests.header().setResizeMode(QHeaderView.Stretch)
        self.repoTests.setHeaderHidden(True)
        self.repoTests.setContextMenuPolicy(Qt.CustomContextMenu)
        self.repoTests.setIndentation(10)

        layoutRepoTest.addWidget(self.prjCombo)
        layoutRepoTest.addWidget(self.repoTests)

        self.testsList = QListWidget(self)

        layoutTests.addLayout( layoutRepoTest )
        layoutTests.addWidget( self.testsList )
        mainLayout.addLayout( layoutTests )

        buttonLayout = QVBoxLayout()

        self.okButton = QPushButton(self.tr("Execute All"), self)
        self.okButton.setEnabled(False)
        self.cancelButton = QPushButton(self.tr("Cancel"), self)
        self.upButton = QPushButton(self.tr("UP"), self)
        self.upButton.setEnabled(False)
        self.downButton = QPushButton(self.tr("DOWN"), self)
        self.downButton.setEnabled(False)
        self.clearButton = QPushButton(self.tr("Remove All"), self)
        self.delButton = QPushButton(self.tr("Remove"), self)
        self.delButton.setEnabled(False)

        self.runSimultaneous = QCheckBox(self.tr("Simultaneous Run"))
        
        self.schedImmed = QRadioButton(self.tr("Run Immediately"))
        self.schedImmed.setChecked(True)
        self.schedAt = QRadioButton(self.tr("Run At:"))
        self.schedAtDateTimeEdit = QDateTimeEdit(QDateTime.currentDateTime())
        self.schedAtDateTimeEdit.setEnabled(False)

        buttonLayout.addWidget(self.okButton)
        buttonLayout.addWidget(self.runSimultaneous)
        buttonLayout.addWidget(self.schedImmed)
        buttonLayout.addWidget(self.schedAt)
        buttonLayout.addWidget(self.schedAtDateTimeEdit)

        
        buttonLayout.addWidget( self.upButton )
        buttonLayout.addWidget( self.downButton )
        buttonLayout.addWidget( self.delButton )
        buttonLayout.addWidget( self.clearButton )

        buttonLayout.addWidget(self.cancelButton)

        mainLayout.addLayout(buttonLayout)

        self.setMinimumHeight(400)
        self.setMinimumWidth(750)
        self.setLayout(mainLayout)

    def initProjects(self, projects=[], defaultProject=1):
        """
        Initialize projects
        """
        # init date and time
        self.schedAtDateTimeEdit.setDateTime(QDateTime.currentDateTime()) 

        self.projectReady = False

        self.repoTests.clear()
        self.prjCombo.clear()
        self.testsList.clear()

        self.prjCombo.setEnabled(True)
        
        # insert data
        pname = ''
        for p in projects:
            self.prjCombo.addItem ( p['name']  )
            if defaultProject == p['project_id']:
                pname = p['name']
        
        for i in xrange(self.prjCombo.count()):
            item_text = self.prjCombo.itemText(i)
            if str(pname) == str(item_text):
                self.prjCombo.setCurrentIndex(i)

        self.projectReady = True
        self.RefreshRepository.emit(pname)

    def initializeTests(self, listing):
        """
        Initialize tests
        """
        self.repoTests.clear()
        self.testRoot = self.rRepo.Item(repo = self.iRepo.remote(), 
                                        parent = self.repoTests, txt = "Root", 
                                        type = QTreeWidgetItem.UserType+10, 
                                        isRoot = True )
        self.testRoot.setSelected(True)
        self.createRepository(listing=listing, parent=self.testRoot,fileincluded=True)
        self.repoTests.sortItems(0, Qt.AscendingOrder)

        self.hideItems(hideTsx=False, hideTpx=False, hideTcx=True, hideTdx=True, hideTxt=True, hidePy=True,
                                hideTux=False, hidePng=True, hideTgx=False, hideTax=False)

    def createRepository(self, listing, parent, fileincluded=True):
        """
        Create repository

        @param listing: 
        @type listing: list

        @param parent: 
        @type parent:

        @param fileincluded: 
        @type fileincluded: boolean
        """
        try:
            for dct in  listing:
                if dct["type"] == "folder":
                    item = self.rRepo.Item(repo = self.iRepo.remote(), parent = parent, 
                                           txt = dct["name"], propertiesFile=dct )
                    self.createRepository(  dct["content"] , item, fileincluded )
                else:
                    if fileincluded:
                        if dct["type"] == "file":
                            pname = self.iRepo.remote().getProjectName(dct["project"])
                            # {'modification': 1342259500, 'type': 'file', 'name': '__init__.py', 'size': '562 }
                            item = self.rRepo.Item(repo = self.iRepo.remote(), parent = parent, txt = dct["name"] ,
                                                   propertiesFile=dct, type = QTreeWidgetItem.UserType+0, 
                                                   projectId=dct["project"], projectName=pname )

        except Exception as e:
            self.error( "unable to create tree for runs: %s" % e )

    def onProjectChanged(self, projectItem):
        """
        Called when the project changed on the combo box
        """
        if self.projectReady:
            item_text = self.prjCombo.itemText(projectItem)
            self.RefreshRepository.emit(item_text)

    def createConnections (self):
        """
        create qt connections
         * ok
         * cancel
        """
        self.prjCombo.currentIndexChanged.connect(self.onProjectChanged)
        self.okButton.clicked.connect( self.acceptClicked )
        self.cancelButton.clicked.connect( self.reject )
        self.upButton.clicked.connect(self.upTest)
        self.downButton.clicked.connect(self.downTest)
        self.clearButton.clicked.connect(self.clearList)
        self.delButton.clicked.connect(self.delTest)

        self.testsList.itemClicked.connect(self.onItemSelected)
        self.testsList.itemSelectionChanged.connect(self.onItemSelectionChanged)

        self.schedAt.toggled.connect(self.onSchedAtActivated)

        self.repoTests.itemDoubleClicked.connect( self.onTestDoucleClicked )

    def onSchedAtActivated(self, toggled):
        """
        On sched at button activated
        """
        if toggled:
            self.schedAtDateTimeEdit.setEnabled(True)
        else:
            self.schedAtDateTimeEdit.setEnabled(False)

    def onItemSelectionChanged(self):
        """
        Called on item selection changed
        """
        self.onItemSelected(itm=None)

    def onItemSelected(self, itm):
        """
        Call on item selected
        """
        selectedItems = self.testsList.selectedItems()
        if len(selectedItems):
            self.delButton.setEnabled(True)
            self.upButton.setEnabled(True)
            self.downButton.setEnabled(True)
        else:
            self.delButton.setEnabled(False)
            self.upButton.setEnabled(False)
            self.downButton.setEnabled(False)

        if not self.testsList.count():
            self.okButton.setEnabled(False)

    def upTest(self):
        """
        Up test
        """
        currentRow = self.testsList.currentRow()
        currentItem = self.testsList.takeItem(currentRow)
        self.testsList.insertItem(currentRow - 1, currentItem)

    def downTest(self):
        """
        Down test
        """
        currentRow = self.testsList.currentRow()
        currentItem = self.testsList.takeItem(currentRow)
        self.testsList.insertItem(currentRow + 1, currentItem)


    def delTest(self):
        """
        Del test
        """
        currentRow = self.testsList.currentRow()
        currentItem = self.testsList.takeItem(currentRow)

    def clearList(self):
        """
        Clear test
        """
        self.testsList.clear()
        self.delButton.setEnabled(False)
        self.upButton.setEnabled(False)
        self.downButton.setEnabled(False)

        self.okButton.setEnabled(False)

    def iterateTree(self, item, hideTsx, hideTpx, hideTcx, hideTdx, hideTxt, 
                          hidePy, hideTux, hidePng, hideTgx, hideTax):
        """
        Iterate tree
        """
        child_count = item.childCount()
        for i in range(child_count):
            subitem = item.child(i)
            subchild_count = subitem.childCount()
            if subchild_count > 0:
                self.iterateTree(item=subitem, hideTsx=hideTsx, 
                                 hideTpx=hideTpx, hideTcx=hideTcx, 
                                 hideTdx=hideTdx, hideTxt=hideTxt,
                                 hidePy=hidePy, hideTux=hideTux, 
                                 hidePng=hidePng, hideTgx=hideTgx, hideTax=hideTax)
            else:
                if hideTux and subitem.getExtension() == self.rRepo.EXTENSION_TUX:
                    subitem.setHidden (True)
                elif hideTpx and subitem.getExtension() == self.rRepo.EXTENSION_TPX:
                    subitem.setHidden (True)
                elif hideTgx and subitem.getExtension() == self.rRepo.EXTENSION_TGX:
                    subitem.setHidden (True)
                elif hideTcx and subitem.getExtension() == self.rRepo.EXTENSION_TCX:
                    subitem.setHidden (True)
                elif hideTsx and  subitem.getExtension() == self.rRepo.EXTENSION_TSX:
                    subitem.setHidden (True)
                elif hideTdx and  subitem.getExtension() == self.rRepo.EXTENSION_TDX:
                    subitem.setHidden (True)
                elif hideTxt and  subitem.getExtension() == self.rRepo.EXTENSION_TXT:
                    subitem.setHidden (True)
                elif hidePy and  subitem.getExtension() == self.rRepo.EXTENSION_PY:
                    subitem.setHidden (True)
                elif hidePng and  subitem.getExtension() == self.rRepo.EXTENSION_PNG:
                    subitem.setHidden (True)
                elif hideTax and  subitem.getExtension() == self.rRepo.EXTENSION_TAx:
                    subitem.setHidden (True)
                else:
                    subitem.setHidden(False)

    def hideItems(self, hideTsx=False, hideTpx=False, hideTcx=False, hideTdx=False, hideTxt=False, hidePy=False, 
                        hideTux=False, hidePng=False, hideTgx=False, hideTax=False):
        """
        Hide items
        """
        root = self.repoTests.invisibleRootItem()
        self.iterateTree(item=root, hideTsx=hideTsx, hideTpx=hideTpx, hideTcx=hideTcx, 
                         hideTdx=hideTdx, hideTxt=hideTxt, hidePy=hidePy,
                         hideTux=hideTux, hidePng=hidePng, hideTgx=hideTgx, hideTax=hideTax)

    def onTestDoucleClicked(self, testItem):
        """
        On tests double clicked
        """
        if testItem.type() != QTreeWidgetItem.UserType+0:
            return

        self.okButton.setEnabled(True)

        currentProject = self.prjCombo.currentText()

        testName = "%s:%s" % (str(currentProject),testItem.getPath(withFileName = True))
        testItem = QListWidgetItem(testName )

        if testName.endswith(self.rRepo.EXTENSION_TUX):
            testItem.setIcon(QIcon(":/tux.png"))
        if testName.endswith(self.rRepo.EXTENSION_TSX):
            testItem.setIcon(QIcon(":/tsx.png"))
        if testName.endswith(self.rRepo.EXTENSION_TPX):
            testItem.setIcon(QIcon(":/tpx.png"))
        if testName.endswith(self.rRepo.EXTENSION_TGX):
            testItem.setIcon(QIcon(":/tgx.png"))
        if testName.endswith(self.rRepo.EXTENSION_TAX):
            testItem.setIcon(QIcon(":/tax.png"))
            
        self.testsList.addItem( testItem )

    def acceptClicked (self):
        """
        Called on accept button
        """
        self.accept()
    
    def getTests(self):
        """
        Returns all tests in the list
        """
        tests = []
        for i in xrange(self.testsList.count()):
            testItem = self.testsList.item(i)
            tests.append( str(testItem.text()) )

        runSimultaneous = False
        if self.runSimultaneous.isChecked(): runSimultaneous = True
        
        if self.schedImmed.isChecked():
            runAt = (0,0,0,0,0,0)
            return (tests, False, runAt, runSimultaneous)
        else:
            pydt = self.schedAtDateTimeEdit.dateTime().toPyDateTime()
            runAt = (pydt.year, pydt.month, pydt.day, pydt.hour, pydt.minute, pydt.second)
            return (tests, True, runAt, runSimultaneous)
コード例 #54
0
class ClientExceptionsViewer( QWidget ):
    " Implements the client exceptions viewer for a debugger "

    def __init__( self, parent, ignoredExceptionsViewer ):
        QWidget.__init__( self, parent )

        self.__ignoredExceptionsViewer = ignoredExceptionsViewer
        self.__currentItem = None

        self.__createPopupMenu()
        self.__createLayout()

        GlobalData().project.projectChanged.connect( self.__onProjectChanged )
        return

    def setFocus( self ):
        " Sets the widget focus "
        self.exceptionsList.setFocus()
        return

    def __createPopupMenu( self ):
        " Creates the popup menu "
        self.__excptMenu = QMenu()
        self.__addToIgnoreMenuItem = self.__excptMenu.addAction(
                    "Add to ignore list", self.__onAddToIgnore )
        self.__jumpToCodeMenuItem = self.__excptMenu.addAction(
                    "Jump to code", self.__onJumpToCode )
        return

    def __createLayout( self ):
        " Creates the widget layout "

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

        self.headerFrame = QFrame()
        self.headerFrame.setFrameStyle( QFrame.StyledPanel )
        self.headerFrame.setAutoFillBackground( True )
        headerPalette = self.headerFrame.palette()
        headerBackground = headerPalette.color( QPalette.Background )
        headerBackground.setRgb( min( headerBackground.red() + 30, 255 ),
                                 min( headerBackground.green() + 30, 255 ),
                                 min( headerBackground.blue() + 30, 255 ) )
        headerPalette.setColor( QPalette.Background, headerBackground )
        self.headerFrame.setPalette( headerPalette )
        self.headerFrame.setFixedHeight( 24 )

        self.__excptLabel = QLabel( "Exceptions" )

        fixedSpacer = QSpacerItem( 3, 3 )

        headerLayout = QHBoxLayout()
        headerLayout.setContentsMargins( 0, 0, 0, 0 )
        headerLayout.addSpacerItem( fixedSpacer )
        headerLayout.addWidget( self.__excptLabel )
        self.headerFrame.setLayout( headerLayout )

        self.exceptionsList = QTreeWidget( self )
        self.exceptionsList.setSortingEnabled( False )
        self.exceptionsList.setAlternatingRowColors( True )
        self.exceptionsList.setRootIsDecorated( True )
        self.exceptionsList.setItemsExpandable( True )
        self.exceptionsList.setUniformRowHeights( True )
        self.exceptionsList.setSelectionMode( QAbstractItemView.SingleSelection )
        self.exceptionsList.setSelectionBehavior( QAbstractItemView.SelectRows )
        self.exceptionsList.setItemDelegate( NoOutlineHeightDelegate( 4 ) )
        self.exceptionsList.setContextMenuPolicy( Qt.CustomContextMenu )

        self.__addToIgnoreButton = QAction(
            PixmapCache().getIcon( 'add.png' ),
            "Add exception to the list of ignored", self )
        self.__addToIgnoreButton.triggered.connect( self.__onAddToIgnore )
        self.__addToIgnoreButton.setEnabled( False )


        expandingSpacer = QWidget()
        expandingSpacer.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding )

        self.__jumpToCodeButton = QAction(
            PixmapCache().getIcon( 'gotoline.png' ),
            "Jump to the code", self )
        self.__jumpToCodeButton.triggered.connect( self.__onJumpToCode )
        self.__jumpToCodeButton.setEnabled( False )

        self.__delAllButton = QAction(
            PixmapCache().getIcon( 'trash.png' ),
            "Delete all the client exceptions", self )
        self.__delAllButton.triggered.connect( self.__onDelAll )
        self.__delAllButton.setEnabled( False )

        self.toolbar = QToolBar()
        self.toolbar.setOrientation( Qt.Horizontal )
        self.toolbar.setMovable( False )
        self.toolbar.setAllowedAreas( Qt.TopToolBarArea )
        self.toolbar.setIconSize( QSize( 16, 16 ) )
        self.toolbar.setFixedHeight( 28 )
        self.toolbar.setContentsMargins( 0, 0, 0, 0 )
        self.toolbar.addAction( self.__addToIgnoreButton )
        self.toolbar.addAction( self.__jumpToCodeButton )
        self.toolbar.addWidget( expandingSpacer )
        self.toolbar.addAction( self.__delAllButton )

        self.exceptionsList.itemDoubleClicked.connect(
                                            self.__onExceptionDoubleClicked )
        self.exceptionsList.customContextMenuRequested.connect(
                                            self.__showContextMenu )
        self.exceptionsList.itemSelectionChanged.connect(
                                            self.__onSelectionChanged )


        self.exceptionsList.setHeaderLabels( [ "Exception" ] )

        verticalLayout.addWidget( self.headerFrame )
        verticalLayout.addWidget( self.toolbar )
        verticalLayout.addWidget( self.exceptionsList )
        return

    def clear( self ):
        " Clears the content "
        self.exceptionsList.clear()
        self.__updateExceptionsLabel()
        self.__addToIgnoreButton.setEnabled( False )
        self.__jumpToCodeButton.setEnabled( False )
        self.__delAllButton.setEnabled( False )
        self.__currentItem = None
        self.emit( SIGNAL( 'ClientExceptionsCleared' ) )
        return

    def __onExceptionDoubleClicked( self, item, column ):
        " Triggered when an exception is double clicked "
        if self.__currentItem is not None:
            if self.__currentItem.getType() == STACK_FRAME_ITEM:
                self.__onJumpToCode()
                return

            # This is an exception item itself.
            # Open a separate dialog window with th detailed info.

        return

    def __showContextMenu( self, coord ):
        " Shows the frames list context menu "
        self.__contextItem = self.exceptionsList.itemAt( coord )

        self.__addToIgnoreMenuItem.setEnabled( self.__addToIgnoreButton.isEnabled() )
        self.__jumpToCodeMenuItem.setEnabled( self.__jumpToCodeButton.isEnabled() )

        if self.__contextItem is not None:
            self.__excptMenu.popup( QCursor.pos() )
        return

    def __onAddToIgnore( self ):
        " Adds an exception into the ignore list "
        if self.__currentItem is not None:
            self.__ignoredExceptionsViewer.addExceptionFilter(
                        str( self.__currentItem.getExceptionType() ) )
            self.__addToIgnoreButton.setEnabled( False )
        return

    def __onJumpToCode( self ):
        " Jumps to the corresponding source code line "
        if self.__currentItem is not None:
            if self.__currentItem.getType() == STACK_FRAME_ITEM:
                fileName = self.__currentItem.getFileName()
                if '<' not in fileName and '>' not in fileName:
                    lineNumber = self.__currentItem.getLineNumber()

                    editorsManager = GlobalData().mainWindow.editorsManager()
                    editorsManager.openFile( fileName, lineNumber )
                    editor = editorsManager.currentWidget().getEditor()
                    editor.gotoLine( lineNumber )
                    editorsManager.currentWidget().setFocus()
        return

    def __onDelAll( self ):
        " Triggered when all the exceptions should be deleted "
        self.clear()
        return

    def addException( self, exceptionType, exceptionMessage,
                            stackTrace ):
        " Adds the exception to the view "
        for index in xrange( self.exceptionsList.topLevelItemCount() ):
            item = self.exceptionsList.topLevelItem( index )
            if item.equal( exceptionType, exceptionMessage, stackTrace ):
                item.incrementCounter()
                self.exceptionsList.clearSelection()
                self.exceptionsList.setCurrentItem( item )
                self.__updateExceptionsLabel()
                return

        item = ExceptionItem( self.exceptionsList, exceptionType,
                              exceptionMessage, stackTrace )
        self.exceptionsList.clearSelection()
        self.exceptionsList.setCurrentItem( item )
        self.__updateExceptionsLabel()
        self.__delAllButton.setEnabled( True )
        return

    def __updateExceptionsLabel( self ):
        " Updates the exceptions header label "
        total = self.getTotalCount()
        if total > 0:
            self.__excptLabel.setText( "Exceptions (total: " +
                                       str( total ) + ")" )
        else:
            self.__excptLabel.setText( "Exceptions" )
        return

    def getTotalCount( self ):
        " Provides the total number of exceptions "
        count = 0
        for index in xrange( self.exceptionsList.topLevelItemCount() ):
            count += self.exceptionsList.topLevelItem( index ).getCount()
        return count

    def __onProjectChanged( self, what ):
        " Triggered when a project is changed "
        if what == CodimensionProject.CompleteProject:
            self.clear()
        return

    def __onSelectionChanged( self ):
        " Triggered when the current item is changed "
        selected = list( self.exceptionsList.selectedItems() )
        if selected:
            self.__currentItem = selected[ 0 ]
            if self.__currentItem.getType() == STACK_FRAME_ITEM:
                fileName = self.__currentItem.getFileName()
                if '<' in fileName or '>' in fileName:
                    self.__jumpToCodeButton.setEnabled( False )
                else:
                    self.__jumpToCodeButton.setEnabled( True )
                self.__addToIgnoreButton.setEnabled( False )
            else:
                self.__jumpToCodeButton.setEnabled( False )
                excType = str( self.__currentItem.getExceptionType() )
                if self.__ignoredExceptionsViewer.isIgnored( excType ) or \
                   " " in excType or excType.startswith( "unhandled" ):
                    self.__addToIgnoreButton.setEnabled( False )
                else:
                    self.__addToIgnoreButton.setEnabled( True )
        else:
            self.__currentItem = None
            self.__addToIgnoreButton.setEnabled( False )
            self.__jumpToCodeButton.setEnabled( False )
        return
コード例 #55
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()
コード例 #56
0
class WTestManager(QWidget, Logger.ClassLogger):
    """
    Widget to display all tests in the scheduler
    """
    def __init__(self, parent):
        """
        Constructs WTestManager widget

        @param parent: 
        @type parent:
        """
        QWidget.__init__(self, parent)
        self.parent = parent
        self.name = self.tr("Task Manager")
        self.ascendingOrder = False
        self.ascendingOrderHistory = False
        self.ascendingOrderWaiting = False
        
        self.itemCurrent = None
        self.projects = []
        self.createWidgets()
        self.createActions()
        self.createConnections()
        self.createActions()
        self.createToolbar()
        self.deactivate()

    def createWidgets (self):
        """
        QtWidgets creation
        
        QTreeWidget (Id, Name, Init at, Sched at, Start at, Stop at, User, Duration)
         _______________
        |    QToolBar   |
        |---------------|
         _______________
        |               |
        |---------------|
        |               |
        |               |
        |_______________|
        """

        #self.mainTab = QTabWidget()


        layout = QVBoxLayout()

        topLayout = QHBoxLayout()

        # waiting tree widget
        self.tabWaiting = QTabWidget()

        #self.waitingBox = QGroupBox("Waiting")
        self.waitingBox = QFrame(self)
        self.testWaiting = QTreeWidget(self)
        self.testWaiting.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.waitingToolbar = QToolBar(self)
        self.labelsWaiting = [ self.tr("No.") , self.tr("Group"), self.tr("Schedulation Type"),
                              self.tr("Project"), self.tr("Name") , self.tr("Next run"), 
                              self.tr("Repeat"), self.tr("Probes"), self.tr("Notifications") , 
                              self.tr("Tests result"), self.tr("Author")  ]
        self.testWaiting.setHeaderLabels(self.labelsWaiting)
        self.testWaiting.setIndentation(10)
        self.testWaiting.setContextMenuPolicy(Qt.CustomContextMenu)
        layoutWaiting = QVBoxLayout()
        layoutWaiting.addWidget(self.waitingToolbar)
        layoutWaiting.addWidget(self.testWaiting)
        self.waitingBox.setLayout(layoutWaiting)

        self.tabWaiting.addTab( self.waitingBox, "Scheduled" )

        self.enqueuedBox = QFrame(self)
        layoutEnqueued = QVBoxLayout()

        self.testEnqueued = QTreeWidget(self)
        self.labelsEnqueued = [ self.tr("Group of tests")  ] 
        self.testEnqueued.setHeaderLabels(self.labelsEnqueued)
        self.testEnqueued.setIndentation(10)

        layoutEnqueued.addWidget(self.testEnqueued)
        self.enqueuedBox.setLayout(layoutEnqueued)
        self.tabWaiting.addTab( self.enqueuedBox, "Waiting" )


        # current tree widget
        self.currentBox = QGroupBox("Running")
        self.testManager = QTreeWidget(self)
        self.testManager.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.dockToolbar = QToolBar(self)
        self.labels  = [ self.tr("No."), self.tr("Project"), self.tr("Name"), self.tr("Started at"),
                         self.tr("Author"), self.tr("Recursive") ]
        self.testManager.setHeaderLabels(self.labels)
        self.testManager.setIndentation(10)
        self.testManager.setContextMenuPolicy(Qt.CustomContextMenu)
        layoutCurrent = QVBoxLayout()
        layoutCurrent.addWidget(self.dockToolbar)
        layoutCurrent.addWidget(self.testManager)
        self.currentBox.setLayout(layoutCurrent)
        
        v_splitter = QSplitter(self)      
        v_splitter.addWidget( self.tabWaiting )
        v_splitter.addWidget( self.currentBox ) 
        topLayout.addWidget(v_splitter)

        # history tree widget
        self.historyBox = QGroupBox("History")
        self.testHistory = QTreeWidget(self)
        self.historyToolbar = QToolBar(self)
        self.labels2 = [ self.tr("Id"),  self.tr("Schedulation Type"),  self.tr("Project") , self.tr("Name"), 
                         self.tr("Sched at"), self.tr("Run start"), self.tr("Run end"), self.tr("Author"), 
                         self.tr("Duration (in sec.)"), self.tr("Run Result") ]
        self.testHistory.setHeaderLabels(self.labels2)
        
        self.statsBox = QGroupBox("Summary")
        self.nbRunningLabel = QLabel("0")
        self.nbWaitingLabel = QLabel("0")
        self.nbHistoryLabel = QLabel("0")
        self.nbCompleteHistoryLabel = QLabel("0")
        self.nbErrorHistoryLabel = QLabel("0")
        self.nbKilledHistoryLabel = QLabel("0")
        self.nbCancelledHistoryLabel = QLabel("0")
        layout2 = QFormLayout()
        layout2.addRow(QLabel("Running"), self.nbRunningLabel )
        layout2.addRow(QLabel("Waiting"), self.nbWaitingLabel )
        layout2.addRow( QLabel(""), QLabel("") )
        layout2.addRow(QLabel("History"), self.nbHistoryLabel )
        layout2.addRow(QLabel(" - COMPLETE"), self.nbCompleteHistoryLabel )
        layout2.addRow(QLabel(" - ERROR"), self.nbErrorHistoryLabel )
        layout2.addRow(QLabel(" - KILLED"), self.nbKilledHistoryLabel )
        layout2.addRow(QLabel(" - CANCELLED"), self.nbCancelledHistoryLabel )
        self.statsBox.setLayout(layout2)

        layoutHistory = QVBoxLayout()
        layoutHistory.addWidget(self.historyToolbar)
        layoutHistory.addWidget(self.testHistory)
        self.historyBox.setLayout(layoutHistory)
        
        subLayout = QHBoxLayout()
        subLayout.addWidget(self.historyBox)
        subLayout.addWidget(self.statsBox)

        frame_left = QFrame(self)
        frame_left.setFrameShape(QFrame.NoFrame)
        frame_left.setLayout(topLayout)

        frame_right = QFrame(self)
        frame_right.setFrameShape(QFrame.NoFrame)
        frame_right.setLayout(subLayout)

        topLayout.setContentsMargins(0,0,0,0)
        subLayout.setContentsMargins(0,0,0,0)

        splitter1 = QSplitter(Qt.Vertical)
        splitter1.addWidget(frame_left)
        splitter1.addWidget(frame_right)

        layout.addWidget(splitter1)
        self.setLayout(layout)

    def createConnections(self):
        """
        Create Qt Connections
        """
        self.testWaiting.customContextMenuRequested.connect(self.onPopupMenuWaiting)
        self.testWaiting.currentItemChanged.connect(self.onCurrentWaitingItemChanged)

        self.testManager.customContextMenuRequested.connect(self.onPopupMenu)
        self.testManager.currentItemChanged.connect(self.onCurrentItemChanged)

        self.testWaiting.itemDoubleClicked.connect(self.onItemDoubleClicked)

    def createActions (self):
        """
        Actions defined:
         * sort running task
         * sort waiting task
         * sort history task
         * kill one task
         * kill all tasks
         * cancel one task
         * cancel all task
         * clear the history
         * edit a waiting task
         * refresh waiting tasks
         * refresh running tasks
         * partial refresh of the history
         * complete refresh of the history
         * disable a waiting task
         * enable a waiting task
        """
        self.sortAction = QtHelper.createAction(self, "Ascending Order", self.toggleSort, toggled = True, 
                                icon = QIcon(":/ascending.png") )
        self.sortHistoryAction = QtHelper.createAction(self, "Ascending Order", self.toggleSortHistory, toggled = True, 
                                icon = QIcon(":/ascending.png") )
        self.sortWaitingAction = QtHelper.createAction(self, "Ascending Order", self.toggleSortWaiting, toggled = True, 
                                icon = QIcon(":/ascending.png") )
        self.killAction = QtHelper.createAction(self, "&Kill", self.killTask, tip = 'Kill selected test', 
                                icon = QIcon(":/process-kill.png") )
        self.killAllAction = QtHelper.createAction(self, "&Kill All", self.killAllTasks, tip = 'Kill all running tests', 
                                icon = QIcon(":/process-killall.png") )
        self.cancelAction = QtHelper.createAction(self, "&Cancel", self.cancelTask, tip = 'Cancel selected test', 
                                icon = QIcon(":/process-cancel.png") )
        self.cancelAllAction = QtHelper.createAction(self, "&Cancel All", self.cancelAllTasks, tip = 'Cancel all waiting tests', 
                                icon = QIcon(":/processes-cancelall.png") )
        
        self.clearHistoryAction = QtHelper.createAction(self, "&Clear history", self.clearHistory, tip = 'Clear history', 
                                icon = QIcon(":/trash.png"))
        self.editWaitingAction = QtHelper.createAction(self, "&Edit", self.editWaiting, tip = 'Edit the selected task', 
                                icon = QIcon(":/reschedule.png"))

        self.refreshWaitingAction = QtHelper.createAction(self, "Waiting tasks", self.refreshWaitingList, 
                                icon = QIcon(":/act-refresh.png"), tip="Refresh waiting tasks" )
        self.refreshRunningAction = QtHelper.createAction(self, "Running tasks", self.refreshRunningList, 
                                icon = QIcon(":/act-refresh.png"), tip="Refresh running tasks" )
        self.partialRefreshHistoryAction = QtHelper.createAction(self, "Partial history", self.partialRefreshHistoryList, 
                                icon = QIcon(":/act-half-refresh.png"), tip="Refresh partial history" )
        self.refreshHistoryAction = QtHelper.createAction(self, "Full history", self.refreshHistoryList, 
                                icon = QIcon(":/act-refresh.png"), tip="Refresh full history" )

        self.disableAction = QtHelper.createAction(self, "&Disable", self.disableTask, tip = 'Disable task', 
                                icon = QIcon(":/process-pause-icon.png") )
        self.enableAction = QtHelper.createAction(self, "&Enable", self.enableTask, tip = 'Enable task', 
                                icon = None)

    def createToolbar(self):
        """
        Toolbar creation
            
        ||----------||
        || Kill all ||
        ||----------||
        """
        self.dockToolbar.setObjectName("Test Manager toolbar")
        self.dockToolbar.addAction(self.sortAction)
        self.dockToolbar.addAction(self.refreshRunningAction)
        self.dockToolbar.addSeparator()
        self.dockToolbar.addAction(self.killAction)
        self.dockToolbar.addAction(self.killAllAction)
        self.dockToolbar.addSeparator()
        self.dockToolbar.setIconSize(QSize(16, 16))
        #
        self.historyToolbar.setObjectName("Test Manager History toolbar")
        self.historyToolbar.addAction(self.sortHistoryAction)
        self.historyToolbar.addAction(self.partialRefreshHistoryAction)
        self.historyToolbar.addAction(self.refreshHistoryAction)
        self.historyToolbar.addSeparator()
        self.historyToolbar.addAction(self.clearHistoryAction)
        self.historyToolbar.setIconSize(QSize(16, 16))
        #
        self.waitingToolbar.setObjectName("Test Manager Waiting toolbar")
        self.waitingToolbar.addAction(self.sortWaitingAction)
        self.waitingToolbar.addAction(self.refreshWaitingAction)
        self.waitingToolbar.addSeparator()
        self.waitingToolbar.addAction(self.editWaitingAction)
        self.waitingToolbar.addAction(self.disableAction)
        self.waitingToolbar.addAction(self.cancelAction)
        self.waitingToolbar.addAction(self.cancelAllAction)
        self.waitingToolbar.addSeparator()
        self.waitingToolbar.setIconSize(QSize(16, 16))

    def onItemDoubleClicked(self, item):
        """
        On item double clicked in waiting task
        """
        if item.taskEventType in [ UCI.SCHED_QUEUE_AT, UCI.SCHED_QUEUE ]:
            pass
        else:
            self.editWaiting()
        
    def getProjectName(self, prjId):
        """
        Return the project name
        """
        pname = "UNKNOWN"
        
        if prjId == 0:
            return "UNDEFINED"

        for p in self.projects:
            if int(p['project_id']) == int(prjId):
                pname = p['name']
                break

        return pname

    def refreshWaitingList(self):
        """
        Refresh the waiting task list
        """
        RCI.instance().waitingTasks()
        
    def refreshRunningList(self):
        """
        Refresh the running task list
        """
        RCI.instance().runningTasks()
        
    def partialRefreshHistoryList(self):
        """
        Partial refresh of the history task list
        """
        RCI.instance().historyTasks()
        
    def refreshHistoryList(self):
        """
        Refresh the history task list
        """
        RCI.instance().historyTasksAll()
        
    def onCurrentItemChanged(self, witem1, witem2):
        """
        On current item changed 

        @param witem1: 
        @type witem1:

        @param witem2: 
        @type witem2:
        """
        # kill task available just for admin and tester
        if UCI.RIGHTS_ADMIN in RCI.instance().userRights  or UCI.RIGHTS_TESTER in RCI.instance().userRights :
            if witem1 is not None:
                if witem1.taskState == STATE_RUNNING :
                    self.itemCurrent = witem1
                    self.killAction.setEnabled(True)
                else:
                    self.killAction.setEnabled(False)

    def onCurrentWaitingItemChanged(self, witem1, witem2):
        """
        On current waiting task item changed

        @param witem1: 
        @type witem1:

        @param witem2: 
        @type witem2:
        """
        # kill task available just for admin and tester
        if UCI.RIGHTS_ADMIN in RCI.instance().userRights or UCI.RIGHTS_TESTER in RCI.instance().userRights :
            if witem1 is not None:
                self.itemCurrent = witem1
                self.cancelAction.setEnabled(True)
                self.editWaitingAction.setEnabled(True)
                self.disableAction.setEnabled(True)
            else:
                self.cancelAction.setEnabled(False)
                self.editWaitingAction.setEnabled(False)
                self.disableAction.setEnabled(False)

    def disableTask(self):
        """
        Disable a waiting task
        """
        # if self.itemCurrent is not None:
        for currentItem in self.testWaiting.selectedItems():
            RCI.instance().rescheduleTask(taskId=currentItem.taskId, taskEnabled=False, 
                                            scheduleType=currentItem.taskEventType,
                                            scheduleAt=currentItem.taskEventArgs, 
                                            scheduleRepeat=currentItem.taskEventNb, 
                                            probesEnabled=currentItem.taskWithoutProbes, 
                                            notificationsEnabled=currentItem.taskWithoutNotif, 
                                            debugEnabled=False, logsEnabled=currentItem.taskNoKeepTr, 
                                            fromTime=currentItem.taskEventFrom, toTime=currentItem.taskEventTo )
                                            
    def enableTask(self):
        """
        Enable a waiting task
        """
        # if self.itemCurrent is not None:
        for currentItem in self.testWaiting.selectedItems():
            RCI.instance().rescheduleTask(taskId=currentItem.taskId, taskEnabled=True, 
                                            scheduleType=currentItem.taskEventType,
                                            scheduleAt=currentItem.taskEventArgs, 
                                            scheduleRepeat=currentItem.taskEventNb, 
                                            probesEnabled=currentItem.taskWithoutProbes, 
                                            notificationsEnabled=currentItem.taskWithoutNotif, 
                                            debugEnabled=False, logsEnabled=currentItem.taskNoKeepTr, 
                                            fromTime=currentItem.taskEventFrom, toTime=currentItem.taskEventTo )
    
    def editWaiting(self):
        """
        Edit a waiting task
        """
        if self.itemCurrent is not None:
            if self.itemCurrent.taskEventType in [ UCI.SCHED_QUEUE_AT, UCI.SCHED_QUEUE ]:
                pass
            else:
                dSched = ScheduleDialog.SchedDialog( self )
                dSched.fillFields( schedType=self.itemCurrent.taskEventType, schedArgs=self.itemCurrent.taskEventArgs,
                                    taskName=self.itemCurrent.taskEventName, taskId=self.itemCurrent.taskId, 
                                    schedNb=self.itemCurrent.taskEventNb, withoutProbes=self.itemCurrent.taskWithoutProbes,
                                    enabled=self.itemCurrent.taskEventEnabled,
                                    withoutNotifs=self.itemCurrent.taskWithoutNotif, noKeepTr=self.itemCurrent.taskNoKeepTr,
                                    schedFrom=self.itemCurrent.taskEventFrom, schedTo=self.itemCurrent.taskEventTo )
                if dSched.exec_() == QDialog.Accepted:
                    runAt, runType, runNb, withoutProbes, runEnabled, noTr, withoutNotifs, runFrom, runTo = dSched.getSchedtime()

                    RCI.instance().rescheduleTask(taskId=self.itemCurrent.taskId, taskEnabled=runEnabled, scheduleType=runType,
                                                    scheduleAt=runAt, scheduleRepeat=runNb, 
                                                    probesEnabled=withoutProbes, notificationsEnabled=withoutNotifs, 
                                                    debugEnabled=False, logsEnabled=noTr, 
                                                    fromTime=runFrom, toTime=runTo )
    def clearHistory(self):
        """
        Call the server to clear the history
        """
        reply = QMessageBox.question(self, "Clear tasks history", "Are you sure ?",
                        QMessageBox.Yes | QMessageBox.No )
        if reply == QMessageBox.Yes:
            RCI.instance().clearHistory()
            
    def testKilled(self):
        """
        Test kiled
        """
        self.itemCurrent = None
        self.killAction.setEnabled(False)

    def testCancelled(self):
        """
        Test cancelled
        """
        self.itemCurrent = None
        self.cancelAction.setEnabled(False)

    def active (self):
        """
        Enables QTreeWidget 
        """
        self.waitingBox.setEnabled(True)
        self.currentBox.setEnabled(True)
        self.historyBox.setEnabled(True)
        self.statsBox.setEnabled(True)
        #
        self.testManager.setEnabled(True)
        self.testHistory.setEnabled(True)
        self.testWaiting.setEnabled(True)
        #
        self.sortAction.setEnabled(True)
        self.sortHistoryAction.setEnabled(True)
        self.sortWaitingAction.setEnabled(True)
        
        self.refreshWaitingAction.setEnabled(True)
        self.refreshRunningAction.setEnabled(True)
        self.refreshHistoryAction.setEnabled(True)
        self.partialRefreshHistoryAction.setEnabled(True)

        self.killAction.setEnabled(False)
        self.cancelAction.setEnabled(False)
        self.editWaitingAction.setEnabled(False)
        if UCI.RIGHTS_ADMIN in RCI.instance().userRights:
            self.killAllAction.setEnabled(True)
            self.cancelAllAction.setEnabled(True)
            self.clearHistoryAction.setEnabled(True)

        self.disableAction.setEnabled(False)
        self.enableAction.setEnabled(True)

    def deactivate (self):
        """
        Clears QTreeWidget and disables it
        """
        self.waitingBox.setEnabled(False)
        self.currentBox.setEnabled(False)
        self.historyBox.setEnabled(False)
        self.statsBox.setEnabled(False)
        
        self.testWaiting.clear()
        self.testWaiting.setEnabled(False)
        self.testManager.clear()
        self.testManager.setEnabled(False)
        self.testHistory.clear()
        self.testHistory.setEnabled(False)
        self.testEnqueued.clear()
        self.testHistory.setEnabled(False)

        self.nbRunningLabel.setText("0")
        self.nbWaitingLabel.setText("0")
        self.nbHistoryLabel.setText("0")
        self.nbCompleteHistoryLabel.setText("0")
        self.nbErrorHistoryLabel.setText("0")
        self.nbKilledHistoryLabel.setText("0")
        self.nbCancelledHistoryLabel.setText("0")
        self.itemCurrent = None
        
        self.setDefaultActionsValues()
    
    def setDefaultActionsValues (self):
        """
        Set default values for qt actions
        """
        self.sortAction.setEnabled(False)
        self.sortHistoryAction.setEnabled(False)
        self.sortWaitingAction.setEnabled(False)

        self.killAction.setEnabled(False)
        self.killAllAction.setEnabled(False)

        self.cancelAction.setEnabled(False)
        self.cancelAllAction.setEnabled(False)
        self.editWaitingAction.setEnabled(False)
        self.clearHistoryAction.setEnabled(False)

        self.refreshWaitingAction.setEnabled(False)
        self.refreshRunningAction.setEnabled(False)
        self.refreshHistoryAction.setEnabled(False)
        self.partialRefreshHistoryAction.setEnabled(False)

        self.disableAction.setEnabled(False)
        self.enableAction.setEnabled(False)

    def loadProjects(self, data):
        """
        Load all projects
        """
        self.projects = data

    def loadRunning (self, data):
        """
        Loads running tasks

        @param data: 
        @type data: dict
        """
        self.nbRunningLabel.setText( str( len(data) ) )
        for task in data:
            if self.getProjectName(task['project-id']) == "UNKNOWN":
                continue
            taskItem = TaskRunningItem(  task = task, parent= self.testManager )
        
        # resize cols
        for i in xrange(len(self.labels2) - 1):
            self.testManager.resizeColumnToContents(i)
        
        # change sort order
        if self.ascendingOrder:
            self.testWaiting.sortItems(2, Qt.AscendingOrder)     # sort by sched time
        self.testManager.sortItems(2, Qt.DescendingOrder)

    def updateRunning(self, data):
        """
        Update running tasks

        @param data: 
        @type data: 
        """
        self.testManager.clear()
        self.loadRunning( data=data )

    def loadWaiting (self, data):
        """
        Loads waiting tasks

        @param data: 
        @type data: dict
        """
        self.nbWaitingLabel.setText( str(len(data)) )
        for task in data:
            eventid, eventtype, eventargs, eventtime, eventname, author, realruntime, duration, result, eventnb, \
            eventnbcur, eventenabled, withoutprobes, withoutnotif, nokeeptr, userid, projectid, eventfrom, eventto, groupid  = task
            if self.getProjectName(projectid) == "UNKNOWN":
                continue
            taskItem = TaskWaitingItem(  task = task, parent= self.testWaiting )
        
        # resize cols
        for i in xrange(len(self.labels2) - 1):
            self.testWaiting.resizeColumnToContents(i)
        
        # change sort order
        if self.ascendingOrderHistory:
            self.testWaiting.sortItems(3, Qt.AscendingOrder)     
        self.testWaiting.sortItems(3, Qt.DescendingOrder)

    def updateWaiting(self, data):
        """
        Update waiting tasks

        @param data: 
        @type data: 
        """
        self.testWaiting.clear()
        self.loadWaiting( data=data )

    def loadEnqueued (self, data):
        """
        Loads enqueued tasks

        @param data: 
        @type data: dict
        """
        for (groupId, groupData) in data.items():
            groupName, groupsTests = groupData

            pluriel = ''
            if len(groupsTests) > 1:
                pluriel = ''
            groupTask = TaskEnqueuedItem( parent=self.testEnqueued, text="%s - %s - (%s test%s)" % (groupId, groupName, len(groupsTests), pluriel) )
            groupTask.setExpanded(True)
            for gTest in groupsTests:
                tDict = eval(gTest)
                tst = "%s:%s.%s" % ( self.getProjectName(tDict['prj-id']), tDict['test-path'], tDict['test-extension'])
                
                # set the icon according to the type of test
                if tDict['test-extension'] == 'tux':
                    testIcon = QIcon(":/tux.png")
                if tDict['test-extension'] == 'tax':
                    testIcon = QIcon(":/tax.png")
                if tDict['test-extension'] == 'tsx':
                    testIcon = QIcon(":/tsx.png")
                if tDict['test-extension'] == 'tpx':
                    testIcon = QIcon(":/tpx.png")
                if tDict['test-extension'] == 'tgx':
                    testIcon = QIcon(":/tgx.png")
                subTask = TaskEnqueuedItem(parent=groupTask, text=tst, icon=testIcon)

    def updateEnqueued(self, data):
        """
        Update enqueued tasks

        @param data: 
        @type data: 
        """
        self.testEnqueued.clear()
        self.loadEnqueued( data=data )

    def loadHistory (self, data):
        """
        Loads history tasks

        @param data: 
        @type data: dict
        """
        # Init counters
        nbComplete = int(self.nbCompleteHistoryLabel.text())
        nbError = int(self.nbErrorHistoryLabel.text())
        nbKilled = int(self.nbKilledHistoryLabel.text())
        nbCancelled = int(self.nbCancelledHistoryLabel.text())

        for task in data:
            dbid, eventtype, eventargs, eventtime, eventname, author, realruntime, duration, result, projectid  = task
            if self.getProjectName(projectid) == "UNKNOWN":
                continue
            taskItem = TaskHistoryItem(  task = task, parent= self.testHistory )
            if taskItem.taskEventResult == STATE_COMPLETE:
                nbComplete += 1
            if taskItem.taskEventResult == STATE_ERROR:
                nbError += 1
            if taskItem.taskEventResult == STATE_KILLED:
                nbKilled += 1
            if taskItem.taskEventResult == STATE_CANCELLED:
                nbCancelled += 1

        # resize cols
        for i in xrange(len(self.labels2) - 1):
            self.testHistory.resizeColumnToContents(i)
        
        # change sort order by sched at
        if self.ascendingOrderHistory:
            self.testHistory.sortItems(0, Qt.AscendingOrder)     
        self.testHistory.sortItems(0, Qt.DescendingOrder)
        
        # Update summary
        nbHistory = int(self.nbHistoryLabel.text())
        self.nbHistoryLabel.setText( str( len(data) + nbHistory ) )
        self.nbCompleteHistoryLabel.setText( str(nbComplete) )
        self.nbErrorHistoryLabel.setText( str(nbError) )
        self.nbKilledHistoryLabel.setText( str(nbKilled) )
        self.nbCancelledHistoryLabel.setText( str(nbCancelled) )

    def updateHistory(self, data):
        """
        Update history tasks

        @param data: 
        @type data: 
        """
        # reset counters
        self.nbHistoryLabel.setText("0")
        self.nbCompleteHistoryLabel.setText("0")
        self.nbErrorHistoryLabel.setText("0")
        self.nbKilledHistoryLabel.setText("0")
        self.nbCancelledHistoryLabel.setText("0")
        #
        self.testHistory.clear()
        self.loadHistory( data=data )
    
    def refreshRunningTask(self, data, action):
        """
        Refresh running task

        @param data: 
        @type data: 

        @param action: 
        @type action: 
        """
        if action == "add":
            self.loadRunning(data=data)
        elif action == "update":
            self.updateRunning(data=data)
        else:
            pass # error

    def refreshWaitingTask(self, data, action):
        """
        Refresh waiting task

        @param data: 
        @type data: 

        @param action: 
        @type action: 
        """
        if action == "update":
            self.updateWaiting(data=data)
        else:
            pass # error

    def refreshEnqueuedTask(self, data, action):
        """
        Refresh enqueued task

        @param data: 
        @type data: 

        @param action: 
        @type action: 
        """
        if action == "update":
            self.updateEnqueued(data=data)
        else:
            pass # error

    def refreshHistoryTask(self, data, action):
        """
        Refresh history task

        @param data: 
        @type data: 

        @param action: 
        @type action: 
        """
        if action == "add":
            self.loadHistory(data=data)
        elif action == "update":
            self.updateHistory(data=data)
        else:
            pass # error

    def onPopupMenu(self, pos):
        """
        Display menu on right click

        @param pos: 
        @type pos:
        """
        self.menu = QMenu()
        item = self.testManager.itemAt(pos)
        if item:
            self.itemCurrent = item
            # kill task available just for admin and tester
            if UCI.RIGHTS_ADMIN in RCI.instance().userRights or UCI.RIGHTS_TESTER in RCI.instance().userRights :
                if item.taskState == STATE_RUNNING :
                    self.menu.addAction( self.killAction )
                self.menu.popup(self.testManager.mapToGlobal(pos))

    def onPopupMenuWaiting(self, pos):
        """
        Display menu on right click

        @param pos: 
        @type pos:
        """
        self.menu = QMenu()
        item = self.testWaiting.itemAt(pos)
        if item:
            self.itemCurrent = item
            # kill task available just for admin and tester
            if UCI.RIGHTS_ADMIN in RCI.instance().userRights or UCI.RIGHTS_TESTER in RCI.instance().userRights :
                self.menu.addAction( self.editWaitingAction )
                self.menu.addAction( self.cancelAction )
                self.menu.addSeparator()
                self.menu.addAction( self.disableAction )
                self.menu.addAction( self.enableAction )
                self.menu.popup(self.testWaiting.mapToGlobal(pos))

    def cancelTask(self):
        """
        Cancel the selected task
        """
        items = self.testWaiting.selectedItems()
        taskIds = []
        for itm in items:
            taskIds.append( itm.taskId )
        
        reply = QMessageBox.question(self, "Cancel test(s)", "Are you sure ?",
                        QMessageBox.Yes | QMessageBox.No )
        if reply == QMessageBox.Yes:
            RCI.instance().cancelTasks(taskIds=taskIds)
            
    def cancelAllTasks(self):
        """
        Cancel all tasks
        """
        reply = QMessageBox.question(self, "Cancel all tests", "Are you sure ?",
                        QMessageBox.Yes | QMessageBox.No )
        if reply == QMessageBox.Yes:
            RCI.instance().cancelTasksAll()
            
    def killTask(self):
        """
        Kill the selected task
        """
        items = self.testManager.selectedItems()
        taskIds = []
        for itm in items:
            taskIds.append( itm.taskId )
            
        reply = QMessageBox.question(self, "Kill test", "Are you sure ?",
                        QMessageBox.Yes | QMessageBox.No )
        if reply == QMessageBox.Yes:
            RCI.instance().killTasks(taskIds=taskIds)
            
    def killAllTasks(self):
        """
        Kill all tasks
        """
        reply = QMessageBox.question(self, "Kill all tests", "Are you sure ?",
                        QMessageBox.Yes | QMessageBox.No )
        if reply == QMessageBox.Yes:
            RCI.instance().killTasksAll()
    
    def toggleSort(self):
        """
        Toggle sort of running task
        """
        if not self.ascendingOrder:
            self.testManager.sortItems(2, Qt.AscendingOrder)
            self.ascendingOrder = True
        else:
            self.testManager.sortItems(2, Qt.DescendingOrder)
            self.ascendingOrder = False

    def toggleSortHistory(self):
        """
        Toggle sort of the history
        """
        if not self.ascendingOrderHistory:
            self.testHistory.sortItems(0, Qt.AscendingOrder)
            self.ascendingOrderHistory = True
        else:
            self.testHistory.sortItems(0, Qt.DescendingOrder)
            self.ascendingOrderHistory = False

    def toggleSortWaiting(self):
        """
        Toggle sort of the waiting 
        """
        if not self.ascendingOrderWaiting:
            self.testWaiting.sortItems(3, Qt.AscendingOrder)
            self.ascendingOrderWaiting = True
        else:
            self.testWaiting.sortItems(3, Qt.DescendingOrder)
            self.ascendingOrderWaiting = False
コード例 #57
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()
コード例 #58
0
class OWDatabasesUpdate(OWWidget):

    name = "Databases update"
    description = "Update local system biology databases."
    icon = "../widgets/icons/Databases.svg"
    priority = 10

    inputs = []
    outputs = []

    want_main_area = False

    def __init__(self, parent=None, signalManager=None,
                 name="Databases update", domains=None):
        OWWidget.__init__(self, parent, signalManager, name,
                          wantMainArea=False)

        self.searchString = ""
        self.accessCode = ""
        self.domains = domains or DOMAINS
        self.serverFiles = serverfiles.ServerFiles()

        self.__in_progress_update = False

        fbox = gui.widgetBox(self.controlArea, "Filter")

        # The completer model token strings
        self.completertokens = []
        # A 'dynamic' completer item model will be updated with
        # 'prefix {token}' where prefix is current 'active' filter list
        # (the QCompleter only completes on one item in the model)
        self.completermodel = QStringListModel(self)
        self.completer = QCompleter(
            self.completermodel, self,
            caseSensitivity=Qt.CaseInsensitive
        )

        self.lineEditFilter = QLineEdit(textChanged=self.SearchUpdate)

        self.lineEditFilter.setCompleter(self.completer)

        fbox.layout().addWidget(self.lineEditFilter)

        box = gui.widgetBox(self.controlArea, "Files")

        self.filesView = QTreeWidget(self)
        self.filesView.setHeaderLabels(
            ["", "Data Source", "Update", "Last Updated", "Size"])

        self.filesView.setRootIsDecorated(False)
        self.filesView.setUniformRowHeights(True)
        self.filesView.setSelectionMode(QAbstractItemView.NoSelection)
        self.filesView.setSortingEnabled(True)
        self.filesView.sortItems(1, Qt.AscendingOrder)
        self.filesView.setItemDelegateForColumn(
            0, UpdateOptionsItemDelegate(self.filesView))

        self.filesView.model().layoutChanged.connect(self.SearchUpdate)

        box.layout().addWidget(self.filesView)

        box = gui.widgetBox(self.controlArea, orientation="horizontal")
        self.updateButton = gui.button(
            box, self, "Update all",
            callback=self.UpdateAll,
            tooltip="Update all updatable files",
         )

        self.downloadButton = gui.button(
            box, self, "Download all",
            callback=self.DownloadFiltered,
            tooltip="Download all filtered files shown"
        )

        self.cancelButton = gui.button(
            box, self, "Cancel", callback=self.Cancel,
            tooltip="Cancel scheduled downloads/updates."
        )
        gui.rubber(box)

        gui.lineEdit(box, self, "accessCode", "Access Code",
                     orientation="horizontal",
                     callback=self.RetrieveFilesList)

        self.retryButton = gui.button(
            box, self, "Retry", callback=self.RetrieveFilesList
        )
        self.retryButton.hide()

        box = gui.widgetBox(self.controlArea, orientation="horizontal")
        gui.rubber(box)

        self.infoLabel = QLabel()
        self.infoLabel.setAlignment(Qt.AlignCenter)

        self.controlArea.layout().addWidget(self.infoLabel)
        self.infoLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        self.updateItems = []

        self.resize(800, 600)

        self.progress = ProgressState(self, maximum=3)
        self.progress.valueChanged.connect(self._updateProgress)
        self.progress.rangeChanged.connect(self._updateProgress)
        self.executor = ThreadExecutor(
            threadPool=QThreadPool(maxThreadCount=2)
        )

        task = Task(self, function=self.RetrieveFilesList)
        task.exceptionReady.connect(self.HandleError)
        task.start()

        self._tasks = []
        self._haveProgress = False

    def RetrieveFilesList(self):
        self.progress.setRange(0, 3)
        self.serverFiles = serverfiles.ServerFiles(access_code=self.accessCode)

        task = Task(function=partial(retrieveFilesList, self.serverFiles,
                                     self.domains,
                                     methodinvoke(self.progress, "advance")))

        task.resultReady.connect(self.SetFilesList)
        task.exceptionReady.connect(self.HandleError)

        self.executor.submit(task)

        self.setEnabled(False)

    def SetFilesList(self, serverInfo):
        """
        Set the files to show.
        """
        self.setEnabled(True)

        domains = serverInfo.keys()
        if not domains:
            if self.domains:
                domains = self.domains
            else:
                domains = serverfiles.listdomains()

        localInfo = dict([(dom, serverfiles.allinfo(dom)) for dom in domains])

        all_tags = set()

        self.filesView.clear()
        self.updateItems = []

        for item in join_info_dict(localInfo, serverInfo):
            tree_item = UpdateTreeWidgetItem(item)
            options_widget = UpdateOptionsWidget(item.state)
            options_widget.item = item

            options_widget.installClicked.connect(
                partial(self.SubmitDownloadTask, item.domain, item.filename)
            )
            options_widget.removeClicked.connect(
                partial(self.SubmitRemoveTask, item.domain, item.filename)
            )

            self.updateItems.append((item, tree_item, options_widget))
            all_tags.update(item.tags)

        self.filesView.addTopLevelItems(
            [tree_item for _, tree_item, _ in self.updateItems]
        )

        for item, tree_item, options_widget in self.updateItems:
            self.filesView.setItemWidget(tree_item, 0, options_widget)

            # Add an update button if the file is updateable
            if item.state == OUTDATED:
                button = QToolButton(
                    None, text="Update",
                    maximumWidth=120,
                    maximumHeight=30
                )

                if sys.platform == "darwin":
                    button.setAttribute(Qt.WA_MacSmallSize)

                button.clicked.connect(
                    partial(self.SubmitDownloadTask, item.domain,
                            item.filename)
                )

                self.filesView.setItemWidget(tree_item, 2, button)

        self.progress.advance()

        self.filesView.setColumnWidth(0, self.filesView.sizeHintForColumn(0))

        for column in range(1, 4):
            contents_hint = self.filesView.sizeHintForColumn(column)
            header_hint = self.filesView.header().sectionSizeHint(column)
            width = max(min(contents_hint, 400), header_hint)
            self.filesView.setColumnWidth(column, width)

        hints = [hint for hint in sorted(all_tags) if not hint.startswith("#")]
        self.completertokens = hints
        self.completermodel.setStringList(hints)

        self.SearchUpdate()
        self.UpdateInfoLabel()
        self.toggleButtons()
        self.cancelButton.setEnabled(False)

        self.progress.setRange(0, 0)

    def buttonCheck(self, selected_items, state, button):
        for item in selected_items:
            if item.state != state:
                button.setEnabled(False)
            else:
                button.setEnabled(True)
                break

    def toggleButtons(self):
        selected_items = [item for item, tree_item, _ in self.updateItems if not tree_item.isHidden()]
        self.buttonCheck(selected_items, OUTDATED, self.updateButton)
        self.buttonCheck(selected_items, AVAILABLE, self.downloadButton)

    def HandleError(self, exception):
        if isinstance(exception, IOError):
            self.error(0,
                       "Could not connect to server! Press the Retry "
                       "button to try again.")
            self.SetFilesList({})
        else:
            sys.excepthook(type(exception), exception.args, None)
            self.progress.setRange(0, 0)
            self.setEnabled(True)

    def UpdateInfoLabel(self):
        local = [item for item, tree_item, _ in self.updateItems
                 if item.state != AVAILABLE and not tree_item.isHidden()]
        size = sum(float(item.size) for item in local)

        onServer = [item for item, tree_item, _ in self.updateItems if not tree_item.isHidden()]
        sizeOnServer = sum(float(item.size) for item in onServer)

        text = ("%i items, %s (on server: %i items, %s)" %
                (len(local),
                 sizeof_fmt(size),
                 len(onServer),
                 sizeof_fmt(sizeOnServer)))

        self.infoLabel.setText(text)

    def UpdateAll(self):
        for item, tree_item, _ in self.updateItems:
            if item.state == OUTDATED and not tree_item.isHidden():
                self.SubmitDownloadTask(item.domain, item.filename)

    def DownloadFiltered(self):
        # TODO: submit items in the order shown.
        for item, tree_item, _ in self.updateItems:
            if not tree_item.isHidden() and item.state in \
                    [AVAILABLE, OUTDATED]:
                self.SubmitDownloadTask(item.domain, item.filename)

    def _updateCompleterPrefix(self, prefix, seperator=" "):
        prefix = str(self.completer.completionPrefix())

        tokens = self.completertokens
        model = self.completer.model()

        if not prefix.endswith(seperator) and seperator in prefix:
            prefix, _ = prefix.rsplit(seperator, 1)
            items = [prefix + seperator + item for item in tokens]
        else:
            items = tokens
        old = set(str(item) for item in model.stringList())

        if old != set(items):
            model.setStringList(items)

    def SearchUpdate(self, searchString=None):
        self._updateCompleterPrefix(searchString)
        strings = str(self.lineEditFilter.text()).split()
        for item, tree_item, _ in self.updateItems:
            hide = not all(UpdateItem_match(item, string)
                           for string in strings)
            tree_item.setHidden(hide)
        self.UpdateInfoLabel()
        self.toggleButtons()

    def SubmitDownloadTask(self, domain, filename):
        """
        Submit the (domain, filename) to be downloaded/updated.
        """
        self.cancelButton.setEnabled(True)

        index = self.updateItemIndex(domain, filename)
        _, tree_item, opt_widget = self.updateItems[index]

        if self.accessCode:
            sf = serverfiles.ServerFiles(access_code=self.accessCode)
        else:
            sf = serverfiles.ServerFiles()

        task = DownloadTask(domain, filename, sf)

        self.executor.submit(task)

        self.progress.adjustRange(0, 100)

        pb = ItemProgressBar(self.filesView)
        pb.setRange(0, 100)
        pb.setTextVisible(False)

        task.advanced.connect(pb.advance)
        task.advanced.connect(self.progress.advance)
        task.finished.connect(pb.hide)
        task.finished.connect(self.onDownloadFinished, Qt.QueuedConnection)
        task.exception.connect(self.onDownloadError, Qt.QueuedConnection)

        self.filesView.setItemWidget(tree_item, 2, pb)

        # Clear the text so it does not show behind the progress bar.
        tree_item.setData(2, Qt.DisplayRole, "")
        pb.show()

        # Disable the options widget
        opt_widget.setEnabled(False)
        self._tasks.append(task)

    def EndDownloadTask(self, task):
        future = task.future()
        index = self.updateItemIndex(task.domain, task.filename)
        item, tree_item, opt_widget = self.updateItems[index]

        self.filesView.removeItemWidget(tree_item, 2)
        opt_widget.setEnabled(True)

        if future.cancelled():
            # Restore the previous state
            tree_item.setUpdateItem(item)
            opt_widget.setState(item.state)

        elif future.exception():
            tree_item.setUpdateItem(item)
            opt_widget.setState(item.state)

            # Show the exception string in the size column.
            tree_item.setData(
                2, Qt.DisplayRole,
                "Error occurred while downloading:" + str(future.exception())
            )

        else:
            # get the new updated info dict and replace the the old item
            info = serverfiles.info(item.domain, item.filename)
            new_item = update_item_from_info(item.domain, item.filename,
                                             info, info)

            self.updateItems[index] = (new_item, tree_item, opt_widget)

            tree_item.setUpdateItem(new_item)
            opt_widget.setState(new_item.state)

            self.UpdateInfoLabel()

    def SubmitRemoveTask(self, domain, filename):
        serverfiles.remove(domain, filename)
        index = self.updateItemIndex(domain, filename)
        item, tree_item, opt_widget = self.updateItems[index]

        if item.info_server:
            new_item = item._replace(state=AVAILABLE, local=None,
                                      info_local=None)
        else:
            new_item = item._replace(local=None, info_local=None)
            # Disable the options widget. No more actions can be performed
            # for the item.
            opt_widget.setEnabled(False)

        tree_item.setUpdateItem(new_item)
        opt_widget.setState(new_item.state)
        self.updateItems[index] = (new_item, tree_item, opt_widget)

        self.UpdateInfoLabel()

    def Cancel(self):
        """
        Cancel all pending update/download tasks (that have not yet started).
        """
        for task in self._tasks:
            task.future().cancel()

    def onDeleteWidget(self):
        self.Cancel()
        self.executor.shutdown(wait=False)
        OWWidget.onDeleteWidget(self)

    def onDownloadFinished(self):
        # on download completed/canceled/error
        assert QThread.currentThread() is self.thread()
        for task in list(self._tasks):
            future = task.future()
            if future.done():
                self.EndDownloadTask(task)
                self._tasks.remove(task)

        if not self._tasks:
            # Clear/reset the overall progress
            self.progress.setRange(0, 0)

            self.cancelButton.setEnabled(False)

    def onDownloadError(self, exc_info):
        sys.excepthook(*exc_info)

    def updateItemIndex(self, domain, filename):
        for i, (item, _, _) in enumerate(self.updateItems):
            if item.domain == domain and item.filename == filename:
                return i
        raise ValueError("%r, %r not in update list" % (domain, filename))

    def _updateProgress(self, *args):
        rmin, rmax = self.progress.range()
        if rmin != rmax:
            if not self._haveProgress:
                self._haveProgress = True
                self.progressBarInit()

            self.progressBarSet(self.progress.ratioCompleted() * 100)
#             self.progressBarSet(self.progress.ratioCompleted() * 100,
#                                 processEventsFlags=None)
        if rmin == rmax:
            self._haveProgress = False
            self.progressBarFinished()

    def progressBarSet(self, value):
        if not self.__in_progress_update:
            self.__in_progress_update = True
            try:
                OWWidget.progressBarSet(self, value)
            finally:
                self.__in_progress_update = False
コード例 #59
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()
コード例 #60
0
class DBDatabasesWidget(QWidget):
    """Displays a list of Databases"""
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.debug = False

        self.db = None

        self.setWindowTitle("Databases")
        #s#elf.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)

        self.mainLayout = QVBoxLayout()
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setSpacing(0)
        self.setLayout(self.mainLayout)

        #=============================================
        ## Top Toolbar
        topBar = QToolBar()
        topBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.mainLayout.addWidget(topBar)

        ## Add the action buttons
        topBar.addAction(Ico.icon(Ico.ServerAdd), "Add", self.on_server_add)
        self.actionServerEdit = topBar.addAction(Ico.icon(Ico.ServerEdit),
                                                 "Edit", self.on_server_edit)
        self.actionServerDelete = topBar.addAction(Ico.icon(Ico.ServerDelete),
                                                   "Delete",
                                                   self.on_server_delete)

        #=============================================
        ## Tree
        self.tree = QTreeWidget()
        self.mainLayout.addWidget(self.tree)
        self.tree.setHeaderLabels(["Server", "User", ""])
        self.tree.setUniformRowHeights(True)
        self.tree.setRootIsDecorated(False)
        self.tree.setColumnWidth(C.widget, 20)

        self.connect(self.tree, SIGNAL('itemSelectionChanged()'),
                     self.on_tree_selection_changed)
        self.connect(self.tree,
                     SIGNAL('itemDoubleClicked (QTreeWidgetItem *,int)'),
                     self.on_tree_double_clicked)

        self.buttGroup = QButtonGroup(self)
        self.connect(self.buttGroup, SIGNAL("buttonClicked(QAbstractButton*)"),
                     self.on_open_server)

        self.on_tree_selection_changed()

        self.load_servers()

    #=======================================
    ##== Tree Events
    def on_tree_selection_changed(self):

        disabled = self.tree.selectionModel().hasSelection() == False
        self.actionServerEdit.setDisabled(disabled)
        self.actionServerDelete.setDisabled(disabled)

    def on_tree_double_clicked(self):
        self.actionServerEdit.trigger()

    #=======================================
    ## Server Actions
    def on_server_add(self):
        self.show_server_dialog(None)

    def on_server_edit(self):
        item = self.tree.currentItem()
        if item == None:
            return
        server = str(item.text(C.server))
        self.show_server_dialog(server)

    def show_server_dialog(self, server=None):
        d = DBServerDialog.DBServerDialog(self, server)
        if d.exec_():
            self.load_servers()

    def on_open_server(self, butt):
        self.emit(SIGNAL("open_server"), butt.property("server").toString())

    def load_servers(self):
        """Load servers from :py:meth:`pyqtdb.XSettings.XSettings.get_servers` """

        self.tree.clear()

        for butt in self.buttGroup.buttons():
            self.buttGroup.removeButton(butt)

        for srv in G.settings.get_servers_list():

            item = QTreeWidgetItem()
            item.setText(C.server, srv['server'])
            item.setText(C.user, srv['user'])
            self.tree.addTopLevelItem(item)

            butt = QToolButton()
            butt.setIcon(Ico.icon(Ico.Connect))
            butt.setProperty("server", srv['server'])
            self.tree.setItemWidget(item, C.widget, butt)
            self.buttGroup.addButton(butt)

    def on_server_delete(self):
        item = self.tree.currentItem()
        if item == None:
            return
        srv = str(item.text(C.server))
        G.settings.delete_server(srv)
        self.load_servers()