Beispiel #1
0
    def refreshPropertiesDock(self):
        # TODO separate the toolbar with one bottom widget holding some informations and a upper part holding a layout specific to each node
        self.print('Dock properties')
        # get DataSubWindow
        if hasattr(self.mdiArea.activeSubWindow(), 'widget'):
            actSubWnd = self.mdiArea.activeSubWindow().widget()
            try:
                # reset layout
                itemsSelected = actSubWnd.scene.getSelectedItems()
                if len(itemsSelected) > 1:
                    self.propDock.setWidget(self.propDockLbl)
                    self.propDockLbl.setText('{} items selected'.format(len(itemsSelected)))

                elif len(itemsSelected) == 1:
                    itemSelected = itemsSelected[0]
                    if hasattr(itemSelected, 'node') and itemSelected.node.hasPropertiesWidget():
                        self.propDock.setWidget(itemSelected.node.propertiesWidget)

                    else:
                        self.propDockLbl.setText('{} items selected'.format(len(itemsSelected)))
                        self.propDock.setWidget(self.propDockLbl)

                else:
                    self.propDock.setWidget(self.propDockLbl)
                    self.propDockLbl.setText('No selection')

            except Exception as e:
                dumpException(e)
Beispiel #2
0
    def onDrop(self, event):
        if event.mimeData().hasFormat(LISTBOX_MIMETYPE):
            eventData = event.mimeData().data(LISTBOX_MIMETYPE)
            dataStream = QDataStream(eventData, QIODevice.ReadOnly)
            pixmap = QPixmap()
            dataStream >> pixmap
            op_code = dataStream.readInt()
            text = dataStream.readQString()

            mouse_position = event.pos()
            scene_position = self.scene.grScene.views()[0].mapToScene(
                mouse_position)

            if DEBUG:
                print("GOT DROP: [%d] '%s'" % (op_code, text), "mouse:",
                      mouse_position, "scene:", scene_position)

            try:
                node = get_class_from_opcode(op_code)(self.scene)
                node.setPos(scene_position.x(), scene_position.y())
                self.scene.history.storeHistory("Created node %s" %
                                                node.__class__.__name__)
            except Exception as e:
                dumpException(e)

            event.setDropAction(Qt.MoveAction)
            event.accept()
        else:
            # print(" ... drop ignored, not requested format '%s'" % LISTBOX_MIMETYPE)
            event.ignore()
Beispiel #3
0
    def __init__(self,
                 parent: 'DataTableView',
                 dataframe: Union[pd.DataFrame, pd.Series] = None):
        """Model handling values taken either from a DataFrame or a Series

        Parameters
        ----------
        parent

        Instance attributes
        -------------------
        _source_dataframe : pd.DataFrame
            Data source
        _dataframe : pd.DataFrame
            Data sorted or filtered
        filters : List[Filter]
            list of `Filter` to apply
        """
        try:
            super().__init__(parent=parent)
            # init attributes
            self._source_dataframe: Union[pd.DataFrame, pd.Series, None] = None
            self._dataframe: Union[pd.DataFrame, pd.Series, None] = None
            self.dataframe = dataframe
        except Exception as e:
            dumpException(e)
    def startDrag(self, *args, **kwargs):
        try:
            item = self.currentItem()
            op_code = item.data(Qt.UserRole + 1)

            pixmap = QPixmap(item.data(Qt.UserRole))


            itemData = QByteArray()
            dataStream = QDataStream(itemData, QIODevice.WriteOnly)
            dataStream << pixmap
            dataStream.writeInt(op_code)
            dataStream.writeQString(item.text())

            mimeData = QMimeData()
            mimeData.setData(LISTBOX_MIMETYPE, itemData)

            drag = QDrag(self)
            drag.setMimeData(mimeData)
            drag.setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2))
            drag.setPixmap(pixmap)

            drag.exec_(Qt.MoveAction)

        except Exception as e: dumpException(e)
 def setEditorData(self, editor, index):
     try:
         value = index.data(Qt.DisplayRole)
         num = self.options.index(value)
         editor.setCurrentIndex(num)
     except Exception as e:
         dumpException(e)
Beispiel #6
0
 def startDrag(self, supportedActions: Union[Qt.DropActions, Qt.DropAction]) -> None:
     try:
         item: SourceListWidgetItem = self.currentItem()
         drag = getDragObject(self, item)
         drag.exec_(Qt.MoveAction)
     except Exception as e:
         dumpException(e)
Beispiel #7
0
    def onFileOpen(self):
        """Open OpenFileDialog"""
        # OpenFile dialog
        fnames, filter = QFileDialog.getOpenFileNames(
            self, 'Open graph from file', self.getFileDialogDirectory(),
            self.getFileDialogFilter())

        try:
            for fname in fnames:
                if fname:
                    existing = self.findMdiChild(fname)
                    if existing:
                        self.mdiArea.setActiveSubWindow(existing)
                    else:
                        # do not use createMdiChild as a new node editor to call the fileLoad method
                        # Create new subwindow and open file
                        nodeeditor = CalculatorSubWindow()
                        if nodeeditor.fileLoad(fname):
                            self.statusBar().showMessage(
                                f'File {fname} loaded', 5000)
                            nodeeditor.setTitle()
                            subwnd = self.createMdiChild(nodeeditor)
                            subwnd.show()
                        else:
                            nodeeditor.close()
        except Exception as e:
            dumpException(e)
 def onFileNew(self):
     try:
         subwnd = self.createMdiChild()
         subwnd.widget().fileNew()
         subwnd.show()
     except Exception as e:
         dumpException(e)
Beispiel #9
0
    def onDrop(self, event: QDropEvent):
        if DEBUG:
            print('CalcSubWnd : onDrop')
            print(event.mimeData().text())
        if event.mimeData().hasFormat(LISTBOX_MIMETYPE):
            eventData = event.mimeData().data(LISTBOX_MIMETYPE)
            dataStream = QDataStream(eventData, QIODevice.ReadOnly)
            pixmap = QPixmap()
            dataStream >> pixmap
            op_code = dataStream.readQString()
            text = dataStream.readQString()

            mouse_pos = event.pos()
            scene_pos = self.scene.grScene.views()[0].mapToScene(mouse_pos)

            if DEBUG: print(f'DROP: {op_code} {text} at {scene_pos}')

            try:
                node = NodeFactory.from_op_code(op_code)(self.scene)
                node.setPos(scene_pos.x(), scene_pos.y())
                self.scene.history.storeHistory('Create node {}'.format(
                    node.__class__.__name__))

                event.setDropAction(Qt.MoveAction)
                event.accept()

            except Exception as e:
                dumpException(e)
        else:
            if DEBUG:
                print(' ... drop ignored, not requested format ',
                      LISTBOX_MIMETYPE)
            event.ignore()
Beispiel #10
0
    def filter(self):
        """Filter the underlying dataframe

        Parameters
        ----------
        header : QHeaderView
            reference to header holding the text for filtering

        """
        try:
            header = self.view.horizontalHeader()
            mask = None
            self.layoutAboutToBeChanged.emit()
            # Filter according to filter text in header
            # TODO handle in function of datatype
            for i in range(self.columnCount()):
                text = header.getFilterTextAtIndex(i)
                column = self._source_data.columns[i]
                if text != '':
                    if mask is not None:
                        mask &= self._source_data[column].str.contains(text, na=False)
                    else:
                        mask = self._source_data[column].str.contains(text, na=False)

            if mask is None:
                self._data = self._source_data
            else:
                self._data = self._source_data[mask]

            self.layoutChanged.emit()

        except Exception as e:
            dumpException(e)
Beispiel #11
0
    def startDrag(self, *args, **kwargs):
        try:
            # Retrieve the operational code
            item = self.currentItem()
            op_code = item.data(Qt.UserRole + 1)
            # name = item.text()

            # Define Mime data
            # Retrieve pixmap
            pixmap = QPixmap(item.data(Qt.UserRole))
            # Populate a QByteArray with datastream
            itemData = QByteArray()
            dataStream = QDataStream(itemData, QIODevice.WriteOnly)
            dataStream << pixmap
            dataStream.writeQString(op_code)
            dataStream.writeQString(item.text())

            mimeData = QMimeData()
            mimeData.setData(LISTBOX_MIMETYPE, itemData)

            drag = QDrag(self)
            drag.setMimeData(mimeData)
            drag.setPixmap(pixmap)  # set pixmap to drag
            drag.setHotSpot(QPoint(pixmap.width() // 2, pixmap.height() // 2))  # Hotspot in the middle of the drag

            drag.exec_(Qt.MoveAction)

        except Exception as e:
            dumpException(e)
    def data(self, index, role=Qt.DisplayRole):
        try:
            if index.isValid():
                if role == Qt.DisplayRole:
                    return self._data.iloc[index.row(), index.column()]
                # elif role == Qt.TextAlignmentRole:
                #     return _align(value)

        except Exception as e:
            dumpException(e)
Beispiel #13
0
 def loadFromFile(self, filename):
     with open(filename, "r") as file:
         raw_data = file.read()
         try:
             data = json.loads(raw_data, encoding='utf-8')
             self.deserialize(data)
         except json.JSONDecodeError:
             raise InvalidFile("%s is not a valid JSON file" %
                               os.path.basename(filename))
         except Exception as e:
             dumpException(e)
Beispiel #14
0
 def deserialize(self,
                 data: dict,
                 hashmap: dict = {},
                 restore_id: bool = True):
     res = super().deserialize(data, hashmap)
     try:
         value = data['value']
         self.edit.setText(value)
         return True & res
     except Exception as e:
         dumpException(e)
     return res
Beispiel #15
0
    def set_spans(self):
        """Adjust spans of the table to display multiheader like"""
        self.clearSpans()
        try:
            # Find spans for horizontal HeaderView
            if self.isHorizontal():
                self._adjust_spans(self.dataframe.columns)
            else:
                self._adjust_spans(self.dataframe.index)

        except Exception as e:
            dumpException(e)
Beispiel #16
0
 def changeHorizontalHeader(self, index):
     try:
         oldHeader = self.model().headerData(index, Qt.Horizontal, Qt.DisplayRole)
         value, valid = QInputDialog.getText(self,
                                             'Change header label for column %d' % index,
                                             'Header:',
                                             QLineEdit.Normal,
                                             str(oldHeader))
         if valid:
             self.model().setHeaderValue(index, Qt.Horizontal, value)
     except Exception as e:
         dumpException(e)
Beispiel #17
0
 def closeEvent(self, event: QCloseEvent) -> None:
     try:
         self.mdiArea.closeAllSubWindows()
         if self.mdiArea.currentSubWindow():
             event.ignore()
         else:
             self.writeSettings()
             event.accept()
             # In case of fixing the application closing
             # import sys
             # sys.exit(0)
     except Exception as e:
         dumpException(e)
Beispiel #18
0
 def debug(self):
     print('dropped')
     try:
         settings = dict()
         root = self.outputTree.invisibleRootItem()
         for n in range(root.childCount()):
             child = root.child(n)
             settings[child.text(0)] = list()
             if child.childCount() > 0:
                 for i in range(child.childCount()):
                     print(child.child(i).value)
     except Exception as e:
         dumpException(e)
Beispiel #19
0
    def onDoubleClicked(self, event):
        """Event handling double click on Graphics Node in `Scene`"""
        try:
            flags = Qt.WindowMaximizeButtonHint
            flags |= Qt.WindowCloseButtonHint
            # flags |= Qt.WindowMinimizeButtonHint

            wnd = QDialog(flags=flags)
            layout = QVBoxLayout()
            layout.addWidget(self.content.view.copy())
            wnd.setLayout(layout)
            wnd.exec_()
        except Exception as e:
            dumpException(e)
    def updateEditMenu(self):
        try:
            # print("update Edit Menu")
            active = self.getCurrentNodeEditorWidget()
            hasMdiChild = (active is not None)

            self.actPaste.setEnabled(hasMdiChild)

            self.actCut.setEnabled(hasMdiChild and active.hasSelectedItems())
            self.actCopy.setEnabled(hasMdiChild and active.hasSelectedItems())
            self.actDelete.setEnabled(hasMdiChild
                                      and active.hasSelectedItems())

            self.actUndo.setEnabled(hasMdiChild and active.canUndo())
            self.actRedo.setEnabled(hasMdiChild and active.canRedo())
        except Exception as e:
            dumpException(e)
Beispiel #21
0
    def sort(self, column: int, order: Qt.SortOrder = ...) -> None:
        """Sort the undelying dataframe

        Parameters
        ----------
        column : int
            Column along which to sort
        order : Qt.SortOrder
            Ascending or descending
        """
        try:
            self.layoutAboutToBeChanged.emit()
            self._data = self._data.sort_values(self._data.columns[column], ascending=not order)
            self.layoutChanged.emit()

        except Exception as e:
            dumpException(e)
Beispiel #22
0
    def eval(self):
        if not self.isDirty() and not self.isInvalid():
            print(
                f" _> return cached {self.__class__.__name__} value {self.value}"
            )
            return self.value

        try:
            val = self.evalImplementation()
            return val

        except ValueError as e:
            self.markInvalid()
            self.grNode.setToolTip(str(e))
            self.markDescendantDirty()
        except Exception as e:
            self.markInvalid()
            self.grNode.setToolTip(str(e))
            dumpException(e)
Beispiel #23
0
    def setDataFrame(self, dataframe: pd.DataFrame):
        """Define the dataframe through a new `DataTableModel`

        Parameters
        ----------
        dataframe : pd.DataFrame
            dataframe holding the data
        editable : bool
            flag setting the `DataTableModel` as editable
        """
        try:
            # dataframe_model_bak = DataTableModel(view=self, dataframe=dataframe, editable=editable)
            # self.header.setFilterBoxes(dataframe_model_bak.columnCount())
            self.model().dataframe = dataframe
            self.header.setFilterBoxes(dataframe.shape[1])
            # Connect filter from model to event in FilterHeader
            # super().setModel(dataframe_model_bak)
        except Exception as e:
            dumpException(e)
Beispiel #24
0
    def updateEditMenu(self):
        """Gray the properties of the editMenu in function of the active subwindow
        """
        if DEBUG: self.print('updateEditMenu')
        try:
            active = self.getCurrentNodeEditorWidget()
            hasMdiChild = (active is not None)
            hasSelectedItems = hasMdiChild and active.hasSelectedItems()

            self.actPaste.setEnabled(hasMdiChild)

            self.actCut.setEnabled(hasSelectedItems)
            self.actCopy.setEnabled(hasSelectedItems)
            self.actDelete.setEnabled(hasSelectedItems)

            self.actUndo.setEnabled(hasMdiChild and active.canUndo())
            self.actRedo.setEnabled(hasMdiChild and active.canRedo())
        except Exception as e:
            dumpException(e)
    def deserialize(self, data, hashmap={}, restore_id=True):
        try:
            if restore_id: self.id = data['id']
            hashmap[data['id']] = self

            self.setPos(data['pos_x'], data['pos_y'])
            self.title = data['title']

            data['inputs'].sort(key=lambda socket: socket['index'] + socket[
                'position'] * 10000)
            data['outputs'].sort(key=lambda socket: socket['index'] + socket[
                'position'] * 10000)
            num_inputs = len(data['inputs'])
            num_outputs = len(data['outputs'])

            self.inputs = []
            for socket_data in data['inputs']:
                new_socket = Socket(node=self,
                                    index=socket_data['index'],
                                    position=socket_data['position'],
                                    socket_type=socket_data['socket_type'],
                                    count_on_this_node_side=num_inputs,
                                    is_input=True)
                new_socket.deserialize(socket_data, hashmap, restore_id)
                self.inputs.append(new_socket)

            self.outputs = []
            for socket_data in data['outputs']:
                new_socket = Socket(node=self,
                                    index=socket_data['index'],
                                    position=socket_data['position'],
                                    socket_type=socket_data['socket_type'],
                                    count_on_this_node_side=num_outputs,
                                    is_input=False)
                new_socket.deserialize(socket_data, hashmap, restore_id)
                self.outputs.append(new_socket)
        except Exception as e:
            dumpException(e)

        # also deseralize the content of the node
        # res = self.content.deserialize(data['content'], hashmap)

        return True
    def dropEvent(self, event: QDropEvent) -> None:
        try:
            item = self.itemAt(event.pos())
            source = event.source()

            mime = event.mimeData()
            if mime.hasFormat(LISTBOX_W_VALUE_MIMETYPE):
                # Retrieve value from mime data
                value = getValueFromMime(mime)
                new_item = DraggableListItem(value)
                # find existing items with the same name and remove them
                # source is either self or the instance of DraggableListWidget
                source.removeItems(new_item.text())
                # Add new_item
                currentRow = self.row(item)
                self.insertItem(currentRow, new_item)
                self.itemDropped.emit()
                event.acceptProposedAction()
        except Exception as e:
            dumpException(e)
Beispiel #27
0
    def eval(self, force: bool = False) -> Any:
        """Evaluate this `Node`.

        Return cached value in case no change was detected. Evaluation can be forced by setting Force to ``True``.
        Otherwise, evaluate this `Node` by calling :py:meth:`~data_node_base.DataNode.evalImplementation`.
        In case of ValueError, set the node and their children as dirty.
        Any other error will set the node and their children as invalid
        Parameters
        ----------
        force: bool
            ``True`` Force evaluation of this `Node`.

        Returns
        -------
        Any

        """
        if not self.isDirty() and not self.isInvalid():
            self.print('Dirty : ', self.isDirty(), 'Invalid : ',
                       self.isInvalid())
            self.print(
                f" _> return cached {self.__class__.__name__} value {self.value}"
            )
            return self.value

        try:
            # By default, undirty and valid the node
            # self.markDirty(False)
            # self.markInvalid(False)
            val = self.evalImplementation(force=force)
            return val

        except ValueError as e:
            self.markDirty()
            self.setToolTip(str(e))
            self.markDescendantDirty()

        except Exception as e:
            self.markInvalid()
            self.setToolTip(str(e))
            dumpException(e)
Beispiel #28
0
    def contextMenuEvent(self, event: QContextMenuEvent) -> None:
        try:
            item = self.scene.getItemAt(event.pos())
            if DEBUG_CONTEXT: print(item)

            if type(item) == QGraphicsProxyWidget:
                item = item.widget()

            if hasattr(item, 'node') or hasattr(item, 'socket'):
                self.handleNodeContextMenu(event)

            elif hasattr(item, 'edge'):
                self.handleEdgeContextMenu(event)

            else:
                self.handleNewNodeContextMenu(event)

            return super().contextMenuEvent(event)

        except Exception as e:
            dumpException(e)
Beispiel #29
0
    def restoreHistoryStamp(self, history_stamp):
        if DEBUG: print("RHS: ", history_stamp['desc'])

        try:
            self.scene.deserialize(history_stamp['snapshot'])

            # restore selection
            for edge_id in history_stamp['selection']['edges']:
                for edge in self.scene.edges:
                    if edge.id == edge_id:
                        edge.grEdge.setSelected(True)
                        break

            for node_id in history_stamp['selection']['nodes']:
                for node in self.scene.nodes:
                    if node.id == node_id:
                        node.grNode.setSelected(True)
                        break

        except Exception as e:
            dumpException(e)
Beispiel #30
0
    def restoreStatus(self, data: dict) -> bool:
        """Restore the status of the widget.

        Restore the status of the widget using a dictionary with keys 'input', 'output' as returned by getStatus method.
        Parameters
        ----------
        data: dict
            dictionary as returned by the method getStatus

        Returns
        -------
        ``bool``
            True if successful
        """
        try:
            # restore inputs
            self.inputList.clear()
            if data['inputs'] is not None:
                for value in data['inputs']:
                    item = SourceListWidgetItem(value)
                    self.inputList.addItem(item)

            # restore outputs
            root = self.outputTree.invisibleRootItem()
            for n in range(root.childCount()):
                child = root.child(n)
                # remove current child items in case of any
                if child.childCount() > 0:
                    for i in range(child.childCount()):
                        child.removeChild(child.child(i))
                # add child items to the corresponding leaf
                key = child.text(0)
                for value in data['outputs'][key]:
                    item = DestTreeWidgetItem(value)
                    child.addChild(item)
            return True
        except Exception as e:
            dumpException(e)

        return False