예제 #1
0
파일: Node.py 프로젝트: pedroCabrera/PyFlow
    def onUpdatePropertyView(self, formLayout):
        # name
        le_name = QLineEdit(self.getName())
        le_name.setReadOnly(True)
        if self.label().IsRenamable():
            le_name.setReadOnly(False)
            le_name.returnPressed.connect(lambda: self.setName(le_name.text()))
        formLayout.addRow("Name", le_name)

        # uid
        leUid = QLineEdit(str(self.uid))
        leUid.setReadOnly(True)
        #formLayout.addRow("Uuid", leUid)

        # type
        leType = QLineEdit(self.__class__.__name__)
        leType.setReadOnly(True)
        formLayout.addRow("Type", leType)

        # pos
        #le_pos = QLineEdit("{0} x {1}".format(self.pos().x(), self.pos().y()))
        #formLayout.addRow("Pos", le_pos)

        # inputs
        if len([i for i in self.inputs.values()]) != 0:
            for inp in self.inputs.values():
                dataSetter = inp.call if inp.dataType == DataTypes.Exec else inp.setData
                if not inp.hasConnections():
                    w = getInputWidget(inp.dataType, dataSetter,
                                       inp.defaultValue(), inp.getUserStruct())
                    if w:
                        w.setWidgetValue(inp.currentData())
                        w.setObjectName(inp.getName())
                        formLayout.addRow(inp.name, w)
                        if inp.hasConnections():
                            w.setEnabled(False)
                            w.hide()
        if self.asGraphSides:
            # outputs

            if len([i for i in self.outputs.values()]) != 0:
                for out in self.outputs.values():
                    dataSetter = out.call if out.dataType == DataTypes.Exec else out.setData
                    w = getInputWidget(out.dataType, dataSetter,
                                       out.defaultValue(), out.getUserStruct())
                    if w:
                        w.setWidgetValue(out.currentData())
                        w.setObjectName(out.getName())
                        formLayout.addRow(out.name, w)
                        if out.hasConnections():
                            w.setEnabled(True)

        doc_lb = QLabel()
        doc_lb.setStyleSheet("background-color: black;")
        doc_lb.setText("Description")
        #formLayout.addRow("", doc_lb)
        doc = QTextBrowser()
        doc.setOpenExternalLinks(True)
        doc.setHtml(self.description())
예제 #2
0
    def __init__(self, settings, parent=None, description=None, pstvOnly=True):
        super(ConfigDialog, self).__init__(parent)

        self.setWindowTitle("Configure source")

        self.layout = QGridLayout(self)
        row = 0
        self.widgets = {}
        self.settings = settings

        # Settings should be a dictionary
        for name, val in settings.items():

            label = QLabel(self)
            label.setText(str(name))
            self.layout.addWidget(label, row, 0, 1, 1)

            # Check the type of each setting, and create widgets accordingly
            if isinstance(val, str):
                # A string of some kind
                widget = QLineEdit(self)
                widget.setText(val)
            elif isinstance(val, list):
                # A list of alternative values, first is selected
                print("List: ", name)
                continue
            elif isinstance(val, bool):
                widget = QCheckBox(self)
                if val:
                    widget.setCheckState(Qt.CheckState.Checked)
                else:
                    widget.setCheckState(Qt.CheckState.Unchecked)
            elif isinstance(val, int):
                widget = QLineEdit(self)
                widget.setInputMask("9000000")
                widget.setText(str(val).strip())
            elif isinstance(val, float):
                widget = QLineEdit(self)
                if pstvOnly:
                    widget.setInputMask("0.000")
                widget.setText(str(val).strip())
            else:
                print("Ignoring: " + name)
                continue
            widget.config = name
            self.widgets[name] = widget
            self.layout.addWidget(widget, row, 1, 1, 1)
            row += 1
        # Add OK and Cancel buttons
        buttonbox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        buttonbox.accepted.connect(self.getValues)
        buttonbox.rejected.connect(self.reject)
        self.layout.addWidget(buttonbox, row, 1, 2, 1)
예제 #3
0
    def __init__(self, parent: QWidget = None):
        super().__init__(parent)

        self.setWindowFlags(self.windowFlags()
                            & ~Qt.WindowContextHelpButtonHint)

        self.server = QLocalServer(self)

        if not self.server.listen("fortune"):
            QMessageBox.critical(
                self,
                self.tr("Local Fortune Server"),
                self.tr("Unable to start the server: %s." %
                        (self.server.errorString())),
            )
            QTimer.singleShot(0, self.close)
            return

        statusLabel = QLabel()
        statusLabel.setWordWrap(True)
        statusLabel.setText(
            self.
            tr("The server is running.\nRun the Local Fortune Client example now."
               ))

        self.fortunes = (
            self.tr(
                "You've been leading a dog's life. Stay off the furniture."),
            self.tr("You've got to think about tomorrow."),
            self.tr("You will be surprised by a loud noise."),
            self.tr("You will feel hungry again in another hour."),
            self.tr("You might have mail."),
            self.tr("You cannot kill time without injuring eternity."),
            self.tr(
                "Computers are not intelligent. They only think they are."),
        )

        quitButton = QPushButton(self.tr("Quit"))
        quitButton.setAutoDefault(False)
        quitButton.clicked.connect(self.close)
        self.server.newConnection.connect(self.sendFortune)

        buttonLayout = QHBoxLayout()
        buttonLayout.addStretch(1)
        buttonLayout.addWidget(quitButton)
        buttonLayout.addStretch(1)

        mainLayout = QVBoxLayout(self)
        mainLayout.addWidget(statusLabel)
        mainLayout.addLayout(buttonLayout)

        self.setWindowTitle(QGuiApplication.applicationDisplayName())
예제 #4
0
class FrameProgressBar(QFrame, object):
    def __init__(self, *args, **kwargs):
        super(FrameProgressBar, self).__init__(*args, **kwargs)

        layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        self.setLayout(layout)

        self._label = QLabel('', self)
        self._label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        layout.addWidget(self._label)

        self._progress_bar = QProgressBar(self)
        self._progress_bar.setFormat('')
        self._progress_bar.setRange(0, 100)
        self._progress_bar.setSizePolicy(QSizePolicy.Preferred,
                                         QSizePolicy.Preferred)
        layout.addWidget(self._progress_bar)

    def reset(self):
        """
        Reset progress bar
        """

        self._progress_bar.reset()

    def set_text(self, text):
        """
        Set the text of the progress bar
        :param text: str
        """

        self._label.setText(text)

    def set_value(self, value):
        """
        Set the value of the progress bar
        :param value: int or float
        """

        self._progress_bar.setValue(value)

    def set_range(self, min_, max_):
        """
        Set the range of the progress bar
        :param min_: int
        :param max_: int
        """

        self._progress_bar.setRange(min_, max_)
예제 #5
0
    def update_sum(self):
        """updates the sum of energy and thermo corrections"""
        self.sum_table.setRowCount(0)

        if not self.sp_table.rowCount():
            return

        sp_nrg = float(self.sp_table.cellWidget(0, 1).text())

        for row in range(0, self.thermo_table.rowCount()):
            self.sum_table.insertRow(row)

            label = self.thermo_table.cellWidget(row, 0)
            tooltip = label.toolTip()
            text = label.text().replace("𝛿", "")
            sum_label = QLabel(text)
            if "href=" in text:
                sum_label = QLabel()
                sum_label.setText(text)
                sum_label.setTextFormat(Qt.RichText)
                sum_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
                sum_label.linkActivated.connect(self.open_link)

            sum_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
            sum_label.setToolTip(tooltip)

            self.sum_table.setCellWidget(row, 0, sum_label)

            thermo = float(self.thermo_table.cellWidget(row, 1).text())

            total = sp_nrg + thermo
            total_nrg = SmallLineEdit("%.6f" % total)
            total_nrg.setFrame(False)
            total_nrg.setReadOnly(True)
            total_nrg.setToolTip(tooltip)
            self.sum_table.setCellWidget(row, 1, total_nrg)

            unit_label = ReadOnlyTableItem()
            unit_label.setData(Qt.DisplayRole, "E\u2095")
            unit_label.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter)
            unit_label.setToolTip(tooltip)
            self.sum_table.setItem(row, 2, unit_label)

            self.sum_table.resizeRowToContents(row)

        self.sum_table.resizeColumnToContents(0)
        self.sum_table.resizeColumnToContents(1)
        self.sum_table.resizeColumnToContents(2)
예제 #6
0
class Widget(QTabWidget):
    def __init__(self):
        super(Widget, self).__init__()
        self.title = "Andrea <3"
        self.top = 100
        self.left = 300
        self.width = 200
        self.height = 480
        self.msg = "Nothing going on..."
        self.label = QLabel()
        self.label.setText(self.msg)
        self.build_button1()
        self.build_tab1()
        self.build_tab2()

        self.init_ui()

    def button1_clicked(self):
        self.msg = "Button 1 has been clicked."
        self.label.setText(self.msg)
        print(self.msg)

    def build_button1(self):
        self.button1 = QPushButton("Button1")
        self.button1.clicked.connect(self.button1_clicked)

    def build_tab1(self):
        self.tab1 = QWidget()
        self.tab1.layout = QVBoxLayout(self)
        self.tab1.layout.addWidget(self.button1)
        self.tab1.setLayout(self.tab1.layout)

    def build_tab2(self):
        self.tab2 = QWidget()
        self.tab2.layout = QVBoxLayout(self)
        self.tab2.layout.addWidget(self.label)
        self.tab2.setLayout(self.tab2.layout)

    def init_ui(self):
        self.setWindowTitle(self.title)
        self.addTab(self.tab1, "tab 1")
        self.addTab(self.tab2, "tab 2")
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.show()
예제 #7
0
    def _create_version(self, version, elements):

        version_widget = QWidget()
        version_layout = layouts.VerticalLayout(spacing=0,
                                                margins=(0, 0, 0, 0))
        version_layout.setContentsMargins(0, 0, 0, 0)
        version_layout.setSpacing(0)
        version_layout.setAlignment(Qt.AlignTop)
        version_widget.setLayout(version_layout)
        self.version_accordion.add_item(version,
                                        version_widget,
                                        collapsed=True)

        version_label = QLabel()
        version_layout.addWidget(version_label)
        version_text = ''
        for item in elements:
            version_text += '- {}\n'.format(item)
        version_label.setText(version_text)

        self.main_layout.addSpacing(5)
예제 #8
0
class HelpForm(QDialog):
    def __init__(self, page, parent=None):
        super(HelpForm, self).__init__(parent)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setAttribute(Qt.WA_GroupLeader)

        backAction = QAction(QIcon(":/back.png"), "&Back", self)
        backAction.setShortcut(QKeySequence.Back)
        homeAction = QAction(QIcon(":/home.png"), "&Home", self)
        homeAction.setShortcut("Home")
        self.pageLabel = QLabel()

        toolBar = QToolBar()
        toolBar.addAction(backAction)
        toolBar.addAction(homeAction)
        toolBar.addWidget(self.pageLabel)
        self.textBrowser = QTextBrowser()

        layout = QVBoxLayout()
        layout.addWidget(toolBar)
        layout.addWidget(self.textBrowser, 1)
        self.setLayout(layout)

        backAction.triggered.connect(self.tbackward)
        homeAction.triggered.connect(self.thome)
        self.textBrowser.sourceChanged.connect(self.updatePageTitle)

        self.textBrowser.setSearchPaths([":/help"])
        self.textBrowser.setSource(QUrl(page))
        self.resize(400, 600)
        self.setWindowTitle("{0} Help".format(QApplication.applicationName()))

    def updatePageTitle(self):
        self.pageLabel.setText(self.textBrowser.documentTitle())

    def tbackward(self):
        self.textBrowser.backward()

    def thome(self):
        self.textBrowser.home()
예제 #9
0
    def onUpdatePropertyView(self, formLayout):

        # name
        le_name = QLineEdit(self.getName())
        le_name.setReadOnly(True)
        if self.label().IsRenamable():
            le_name.setReadOnly(False)
            le_name.returnPressed.connect(lambda: self.setName(le_name.text()))
        formLayout.addRow("Name", le_name)

        # uid
        leUid = QLineEdit(str(self.uid))
        leUid.setReadOnly(True)
        formLayout.addRow("Uuid", leUid)

        # type
        leType = QLineEdit(self.__class__.__name__)
        leType.setReadOnly(True)
        formLayout.addRow("Type", leType)

        # pos
        le_pos = QLineEdit("{0} x {1}".format(self.pos().x(), self.pos().y()))
        formLayout.addRow("Pos", le_pos)

        pb = QPushButton("...")
        pb.clicked.connect(self.onChangeColor)
        formLayout.addRow("Color", pb)

        doc_lb = QLabel()
        doc_lb.setStyleSheet("background-color: black;")
        doc_lb.setText("Description")
        formLayout.addRow("", doc_lb)
        doc = QTextBrowser()
        doc.setOpenExternalLinks(True)
        doc.setHtml(self.description())
        formLayout.addRow("", doc)
예제 #10
0
class MayaShelf(abstract_shelf.AbstractShelf, object):

    def __init__(self, name='MayaShelf', label_background=(0, 0, 0, 0), label_color=(0.9, 0.9, 0.9),
                 category_icon=None, enable_labels=True):
        super(MayaShelf, self).__init__(name=name, label_background=label_background, label_color=label_color,
                                        category_icon=category_icon, enable_labels=enable_labels)

    @staticmethod
    def add_menu_item(parent, label, command='', icon=''):
        """
        Adds a menu item with the given attributes
        :param parent:
        :param label:
        :param command:
        :param icon:
        :return:
        """

        return maya.cmds.menuItem(parent=parent, label=label, command=command, image=icon or '')

    @staticmethod
    def add_sub_menu(parent, label, icon=None):
        """
        Adds a sub menu item with the given label and icon to the given parent popup menu
        :param parent:
        :param label:
        :param icon:
        :return:
        """

        return maya.cmds.menuItem(parent=parent, label=label, icon=icon or '', subMenu=True)

    def create(self, delete_if_exists=True):
        """
        Creates a new shelf
        """

        if delete_if_exists:
            if gui.shelf_exists(shelf_name=self._name):
                gui.delete_shelf(shelf_name=self._name)
        else:
            assert not gui.shelf_exists(self._name), 'Shelf with name {} already exists!'.format(self._name)

        self._name = gui.create_shelf(name=self._name)

        # ========================================================================================================

        self._category_btn = QPushButton('')
        if self._category_icon:
            self._category_btn.setIcon(self._category_icon)
        self._category_btn.setIconSize(QSize(18, 18))
        self._category_menu = QMenu(self._category_btn)
        self._category_btn.setStyleSheet(
            'QPushButton::menu-indicator {image: url(myindicator.png);'
            'subcontrol-position: right center;subcontrol-origin: padding;left: -2px;}')
        self._category_btn.setMenu(self._category_menu)
        self._category_lbl = QLabel('MAIN')
        self._category_lbl.setAlignment(Qt.AlignCenter)
        font = self._category_lbl.font()
        font.setPointSize(6)
        self._category_lbl.setFont(font)
        menu_ptr = maya.OpenMayaUI.MQtUtil.findControl(self._name)
        menu_widget = qtutils.wrapinstance(menu_ptr, QWidget)
        menu_widget.layout().addWidget(self._category_btn)
        menu_widget.layout().addWidget(self._category_lbl)

        self.add_separator()

    def set_as_active(self):
        """
        Sets this shelf as active shelf in current DCC session
        """

        main_shelf = maya.mel.eval("$_tempVar = $gShelfTopLevel")
        maya.cmds.tabLayout(main_shelf, edit=True, selectTab=self._name)

    def add_button(self, label, tooltip=None, icon='customIcon.png', command=None,
                   double_command=None, command_type='python'):
        """
        Adds a shelf button width the given parameters
        :param label:
        :param tooltip:
        :param icon:
        :param command:
        :param double_command:
        :param command_type:
        :return:
        """

        maya.cmds.setParent(self._name)
        command = command or ''
        double_command = double_command or ''

        if not self._enable_labels:
            label = ''

        return maya.cmds.shelfButton(width=37, height=37, image=icon or '', label=label, command=command,
                                     doubleClickCommand=double_command, annotation=tooltip or '',
                                     imageOverlayLabel=label, overlayLabelBackColor=self._label_background,
                                     overlayLabelColor=self._label_color, sourceType=command_type)

    def add_separator(self):
        """
        Adds a separator to shelf
        :param parent:
        :return:
        """

        maya.cmds.separator(
            parent=self._name, manage=True, visible=True, horizontal=False, style='shelf',
            enableBackground=False, preventOverride=False)

    def build_category(self, shelf_file, category_name):

        self._category_lbl.setText(category_name.upper())

        self.load_category(shelf_file, 'general', clear=True)
        if category_name != 'general':
            self.add_separator()
            self.load_category(shelf_file, category_name, clear=False)

    def build_categories(self, shelf_file, categories):
        """
        Builds all categories given
        :param categories: list<str>, list of categories to build
        """

        self._category_lbl.setText('ALL')

        self.load_category(shelf_file, 'general', clear=True)
        for cat in categories:
            if cat == 'general':
                continue
            self.add_separator()
            self.load_category(shelf_file, cat, clear=False)

    def load_category(self, shelf_file, category_name, clear=True):
        """
        Loads into a shelf all the items of given category name, if exists
        :param category_name: str, name of the category
        """

        if clear:
            self.clear_list()
            # self.add_separator()

        with open(shelf_file) as f:
            shelf_data = json.load(f, object_pairs_hook=OrderedDict)

            for item, item_data in shelf_data.items():
                if item != category_name:
                    continue

                for i in item_data:
                    icon = i.get('icon')
                    command = i.get('command')
                    annotation = i.get('annotation')
                    label = i.get('label')

                    if annotation == 'separator':
                        self.add_separator()
                    else:
                        self.add_button(label=label, command=command, icon=icon, tooltip=annotation)
                return

    def build(self, shelf_file):
        """
        Builds shelf from JSON file
        :param shelf_file: str
        """

        first_item = None

        all_categories = list()

        with open(shelf_file) as f:
            shelf_data = json.load(f, object_pairs_hook=OrderedDict)

            for i, item in enumerate(shelf_data.keys()):
                if i == 0:
                    first_item = item

                category_action = self._category_menu.addAction(item.title())
                category_action.triggered.connect(partial(self.build_category, shelf_file, item))
                all_categories.append(item)

            category_action = self._category_menu.addAction('All')
            category_action.triggered.connect(partial(self.build_categories, shelf_file, all_categories))

        if first_item:
            self.load_category(shelf_file, first_item, clear=False)

    def clear_list(self):
        """
        Clears all the elements of the shelf
        """

        if gui.shelf_exists(shelf_name=self._name):
            menu_items = maya.cmds.shelfLayout(self._name, query=True, childArray=True)
            for item in menu_items:
                try:
                    maya.cmds.deleteUI(item)
                except Exception:
                    pass
예제 #11
0
class DockTitleBar(QWidget, object):
    def __init__(self, dock_widget, renamable=False):
        super(DockTitleBar, self).__init__(dock_widget)

        self._renamable = renamable

        main_layout = QHBoxLayout()
        main_layout.setContentsMargins(0, 0, 0, 1)
        self.setLayout(main_layout)

        self._buttons_box = QGroupBox('')
        self._buttons_box.setObjectName('Docked')
        self._buttons_layout = QHBoxLayout()
        self._buttons_layout.setSpacing(1)
        self._buttons_layout.setMargin(2)
        self._buttons_box.setLayout(self._buttons_layout)
        main_layout.addWidget(self._buttons_box)

        self._title_label = QLabel(self)
        self._title_label.setStyleSheet('background: transparent')
        self._title_edit = QLineEdit(self)
        self._title_edit.setVisible(False)

        self._button_size = QSize(14, 14)

        self._dock_btn = QToolButton(self)
        self._dock_btn.setIcon(resources.icon('restore_window', theme='color'))
        self._dock_btn.setMaximumSize(self._button_size)
        self._dock_btn.setAutoRaise(True)
        self._close_btn = QToolButton(self)
        self._close_btn.setIcon(resources.icon('close_window', theme='color'))
        self._close_btn.setMaximumSize(self._button_size)
        self._close_btn.setAutoRaise(True)

        self._buttons_layout.addSpacing(2)
        self._buttons_layout.addWidget(self._title_label)
        self._buttons_layout.addWidget(self._title_edit)
        self._buttons_layout.addStretch()
        self._buttons_layout.addSpacing(5)
        self._buttons_layout.addWidget(self._dock_btn)
        self._buttons_layout.addWidget(self._close_btn)

        self._buttons_box.mouseDoubleClickEvent = self.mouseDoubleClickEvent
        self._buttons_box.mousePressEvent = self.mousePressEvent
        self._buttons_box.mouseMoveEvent = self.mouseMoveEvent
        self._buttons_box.mouseReleaseEvent = self.mouseReleaseEvent

        dock_widget.featuresChanged.connect(self._on_dock_features_changed)
        self._title_edit.editingFinished.connect(self._on_finish_edit)
        self._dock_btn.clicked.connect(self._on_dock_btn_clicked)
        self._close_btn.clicked.connect(self._on_close_btn_clicked)

        self._on_dock_features_changed(dock_widget.features())
        self.set_title(dock_widget.windowTitle())
        dock_widget.installEventFilter(self)
        dock_widget.topLevelChanged.connect(self._on_change_floating_style)

    @property
    def renamable(self):
        return self._renamable

    @renamable.setter
    def renamable(self, flag):
        self._renamable = flag

    def eventFilter(self, obj, event):
        if event.type() == QEvent.WindowTitleChange:
            self.set_title(obj.windowTitle())
        return super(DockTitleBar, self).eventFilter(obj, event)

    def mouseMoveEvent(self, event):
        event.ignore()

    def mousePressEvent(self, event):
        event.ignore()

    def mouseReleaseEvent(self, event):
        event.ignore()

    def mouseDoubleClickEvent(self, event):
        if event.pos().x() <= self._title_label.width() and self._renamable:
            self._start_edit()
        else:
            super(DockTitleBar, self).mouseDoubleClickEvent(event)

    def update(self, *args, **kwargs):
        self._on_change_floating_style(self.parent().isFloating())
        super(DockTitleBar, self).update(*args, **kwargs)

    def set_title(self, title):
        self._title_label.setText(title)
        self._title_edit.setText(title)

    def add_button(self, button):
        button.setAutoRaise(True)
        button.setMaximumSize(self._button_size)
        self._buttons_layout.insertWidget(5, button)

    def _start_edit(self):
        self._title_label.hide()
        self._title_edit.show()
        self._title_edit.setFocus()

    def _finish_edit(self):
        self._title_edit.hide()
        self._title_label.show()
        self.parent().setWindowTitle(self._title_edit.text())

    def _on_dock_features_changed(self, features):
        if not features & QDockWidget.DockWidgetVerticalTitleBar:
            self._close_btn.setVisible(features
                                       & QDockWidget.DockWidgetClosable)
            self._dock_btn.setVisible(features
                                      & QDockWidget.DockWidgetFloatable)
        else:
            raise ValueError('Vertical title bar is not supported!')

    def _on_finish_edit(self):
        self._finish_edit()

    def _on_dock_btn_clicked(self):
        self.parent().setFloating(not self.parent().isFloating())

    def _on_close_btn_clicked(self):
        self.parent().toggleViewAction().setChecked(False)
        self.parent().close()

    def _on_change_floating_style(self, state):
        pass
예제 #12
0
class Dialog(QDialog):
    def __init__(self, parent: QWidget = None) -> None:
        super().__init__(parent)

        self.tcpServer = QTcpServer()
        self.tcpClient = QTcpSocket()
        self.tcpServerConnection: QTcpSocket = None

        self.bytesToWrite = 0
        self.bytesWritten = 0
        self.bytesReceived = 0

        self.clientProgressBar = QProgressBar()
        self.clientStatusLabel = QLabel(self.tr("Client ready"))
        self.serverProgressBar = QProgressBar()
        self.serverStatusLabel = QLabel(self.tr("Server ready"))

        self.startButton = QPushButton(self.tr("&Start"))
        self.quitButton = QPushButton(self.tr("&Quit"))

        self.buttonBox = QDialogButtonBox()
        self.buttonBox.addButton(self.startButton, QDialogButtonBox.ActionRole)
        self.buttonBox.addButton(self.quitButton, QDialogButtonBox.RejectRole)

        self.startButton.clicked.connect(self.start)
        self.quitButton.clicked.connect(self.close)
        self.tcpServer.newConnection.connect(self.acceptConnection)
        self.tcpClient.connected.connect(self.startTransfer)
        self.tcpClient.bytesWritten.connect(self.updateClientProgress)
        self.tcpClient.error.connect(self.displayError)

        mainLayout = QVBoxLayout(self)
        mainLayout.addWidget(self.clientProgressBar)
        mainLayout.addWidget(self.clientStatusLabel)
        mainLayout.addWidget(self.serverProgressBar)
        mainLayout.addWidget(self.serverStatusLabel)
        mainLayout.addStretch(1)
        mainLayout.addSpacing(10)
        mainLayout.addWidget(self.buttonBox)

    @Slot()
    def start(self):
        self.startButton.setEnabled(False)

        QGuiApplication.setOverrideCursor(Qt.WaitCursor)

        self.bytesWritten = 0
        self.bytesReceived = 0

        while not self.tcpServer.isListening() and not self.tcpServer.listen():
            ret = QMessageBox.critical(
                self,
                self.tr("Loopback"),
                self.tr(
                    "Unable to start the test: %s" % (self.tcpServer.errorString())
                ),
                QMessageBox.Retry | QMessageBox.Cancel,
            )
            if ret == QMessageBox.Cancel:
                return

        self.serverStatusLabel.setText(self.tr("Listening"))
        self.clientStatusLabel.setText(self.tr("Connecting"))
        self.tcpClient.connectToHost(
            QHostAddress.LocalHost, self.tcpServer.serverPort()
        )

    @Slot()
    def acceptConnection(self):
        self.tcpServerConnection = self.tcpServer.nextPendingConnection()
        if not self.tcpServerConnection:
            self.serverStatusLabel.setText(
                self.tr("Error: got invalid pending connection!")
            )
            return

        self.tcpServerConnection.readyRead.connect(self.updateServerProgress)
        self.tcpServerConnection.error.connect(self.displayError)
        self.tcpServerConnection.disconnected.connect(
            self.tcpServerConnection.deleteLater
        )

        self.serverStatusLabel.setText(self.tr("Accepted connection"))
        self.tcpServer.close()

    @Slot()
    def startTransfer(self):
        # called when the TCP client connected to the loopback server
        self.bytesToWrite = TOTAL_BYTES - int(
            self.tcpClient.write(QByteArray(PAYLOAD_SIZE, "@"))
        )
        self.clientStatusLabel.setText(self.tr("Connected"))

    @Slot()
    def updateServerProgress(self):
        self.bytesReceived += int(self.tcpServerConnection.bytesAvailable())
        self.tcpServerConnection.readAll()

        self.serverProgressBar.setMaximum(TOTAL_BYTES)
        self.serverProgressBar.setValue(self.bytesReceived)
        self.serverStatusLabel.setText(
            self.tr("Received %dMB" % (self.bytesReceived / (1024 * 1024),))
        )

        if self.bytesReceived == TOTAL_BYTES:
            self.tcpServerConnection.close()
            self.startButton.setEnabled(True)

            QGuiApplication.restoreOverrideCursor()

    @Slot("qint64")
    def updateClientProgress(self, numBytes):
        self.bytesWritten += int(numBytes)

        if self.bytesToWrite > 0 and self.tcpClient.bytesToWrite() <= 4 * PAYLOAD_SIZE:
            self.bytesToWrite -= self.tcpClient.write(
                QByteArray(min(self.bytesToWrite, PAYLOAD_SIZE), "@")
            )

        self.clientProgressBar.setMaximum(TOTAL_BYTES)
        self.clientProgressBar.setValue(self.bytesWritten)
        self.clientStatusLabel.setText(
            self.tr("Sent %dMB" % (self.bytesWritten / (1024 * 1024),))
        )

    @Slot(QAbstractSocket.SocketError)
    def displayError(self, socketError):
        if socketError == QTcpSocket.RemoteHostClosedError:
            return

        QMessageBox.information(
            self,
            self.tr("Network error"),
            self.tr(
                "The following error occurred: {}.".format(self.tcpClient.errorString())
            ),
        )
        self.tcpClient.close()
        self.tcpServer.close()
        self.clientProgressBar.reset()
        self.serverProgressBar.reset()
        self.clientStatusLabel.setText(self.tr("Client ready"))
        self.serverStatusLabel.setText(self.tr("Server ready"))
        self.startButton.setEnabled(True)
        QGuiApplication.restoreOverrideCursor()
예제 #13
0
파일: libadd.py 프로젝트: QChASM/SEQCROW
    def _build_ui(self):
        layout = QGridLayout()

        library_tabs = QTabWidget()

        #ligand tab
        ligand_tab = QWidget()
        ligand_layout = QFormLayout(ligand_tab)

        self.ligand_name = QLineEdit()
        self.ligand_name.setText("")
        self.ligand_name.setPlaceholderText("leave blank to preview")
        self.ligand_name.setToolTip(
            "name of ligand you are adding to your ligand library\nleave blank to open a new model with just the ligand"
        )
        ligand_layout.addRow("ligand name:", self.ligand_name)

        ligand_key_atoms = QPushButton("set key atoms to current selection")
        ligand_key_atoms.clicked.connect(self.update_key_atoms)
        ligand_key_atoms.setToolTip(
            "the current selection will be the key atoms for the ligand\nleave blank to automatically determine key atoms"
        )
        ligand_layout.addRow(ligand_key_atoms)

        libadd_ligand = QPushButton("add current selection to library")
        libadd_ligand.clicked.connect(self.libadd_ligand)
        ligand_layout.addRow(libadd_ligand)

        #substituent tab
        sub_tab = QWidget()
        sub_layout = QFormLayout(sub_tab)

        self.sub_name = QLineEdit()
        self.sub_name.setText("")
        self.sub_name.setPlaceholderText("leave blank to preview")
        self.sub_name.setToolTip(
            "name of substituent you are adding to your substituent library\nleave blank to open a new model with just the substituent"
        )
        sub_layout.addRow("substituent name:", self.sub_name)

        self.sub_confs = QSpinBox()
        self.sub_confs.setMinimum(1)
        sub_layout.addRow("number of conformers:", self.sub_confs)

        self.sub_angle = QSpinBox()
        self.sub_angle.setRange(0, 180)
        self.sub_angle.setSingleStep(30)
        sub_layout.addRow("angle between conformers:", self.sub_angle)

        libadd_sub = QPushButton("add current selection to library")
        libadd_sub.clicked.connect(self.libadd_substituent)
        sub_layout.addRow(libadd_sub)

        #ring tab
        ring_tab = QWidget()
        ring_layout = QFormLayout(ring_tab)

        self.ring_name = QLineEdit()
        self.ring_name.setText("")
        self.ring_name.setPlaceholderText("leave blank to preview")
        self.ring_name.setToolTip(
            "name of ring you are adding to your ring library\nleave blank to open a new model with just the ring"
        )
        ring_layout.addRow("ring name:", self.ring_name)

        libadd_ring = QPushButton("add ring with selected walk to library")
        libadd_ring.clicked.connect(self.libadd_ring)
        ring_layout.addRow(libadd_ring)

        library_tabs.addTab(sub_tab, "substituent")
        library_tabs.addTab(ring_tab, "ring")
        library_tabs.addTab(ligand_tab, "ligand")
        self.library_tabs = library_tabs

        layout.addWidget(library_tabs)

        whats_this = QLabel()
        whats_this.setText(
            "<a href=\"req\" style=\"text-decoration: none;\">what's this?</a>"
        )
        whats_this.setTextFormat(Qt.RichText)
        whats_this.setTextInteractionFlags(Qt.TextBrowserInteraction)
        whats_this.linkActivated.connect(self.open_link)
        whats_this.setToolTip(
            "click for more information about AaronTools libraries")
        layout.addWidget(whats_this)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
예제 #14
0
    def set_thermo(self):
        """computes thermo corrections and sets thermo entries for when thermo model changes"""
        #index of combobox is -1 when combobox has no entries
        self.thermo_table.setRowCount(0)
        if self.thermo_selector.currentIndex() >= 0:
            fr = self.thermo_selector.currentData()
            if fr not in self.thermo_co:
                self.thermo_co[fr] = CompOutput(fr)
            co = self.thermo_co[fr]

            v0 = self.v0_edit.value()

            if v0 != self.settings.w0:
                self.settings.w0 = v0

            T = self.temperature_line.value()
            if not T:
                return

            dZPE = co.ZPVE
            #compute enthalpy and entropy at this temperature
            #AaronTools uses Grimme's Quasi-RRHO, but this is the same as RRHO when w0=0
            dE, dH, s = co.therm_corr(temperature=T, v0=0, method="RRHO")
            rrho_dg = dH - T * s
            #compute G with quasi entropy treatments
            qrrho_dg = co.calc_G_corr(v0=v0, temperature=T, method="QRRHO")
            qharm_dg = co.calc_G_corr(v0=v0, temperature=T, method="QHARM")

            items = [(
                "𝛿ZPE =",
                dZPE,
                None,
                "lowest energy the molecule can have\n"
                "no rotational or vibrational modes populated\n"
                "equal to enthalpy at 0 K",
            )]

            if fr.other["frequency"].anharm_data:
                dZPE_anh = co.calc_zpe(anharmonic=True)
                items.append((
                    "𝛿ZPE<sub>anh</sub> =",
                    dZPE_anh,
                    None,
                    "lowest energy the molecule can have\n"
                    "no rotational or vibrational modes populated\n"
                    "includes corrections for anharmonic vibrations",
                ))

            items.extend([
                (
                    "𝛿H<sub>RRHO</sub> =",
                    dH,
                    None,
                    "enthalpy of formation",
                ),
                (
                    "𝛿G<sub>RRHO</sub> =",
                    rrho_dg,
                    None,
                    "energy after taking into account the average\n"
                    "population of vibrational, rotational, and translational\n"
                    "degrees of freedom",
                ),
                (
                    "𝛿G<sub>Quasi-RRHO</sub> =",
                    qrrho_dg,
                    "Grimme's Quasi-RRHO",
                    "vibrational entropy of each real mode is damped and complemented\n"
                    "with rotational entropy, with the damping function being stronger for\n"
                    "frequencies < 𝜔\u2080\n"
                    "can mitigate error from inaccuracies in the harmonic oscillator\n"
                    "approximation for low-frequency vibrations",
                ),
                (
                    "𝛿G<sub>Quasi-Harmonic</sub> =",
                    qharm_dg,
                    "Truhlar's Quasi-Harmonic",
                    "real vibrational frequencies below 𝜔\u2080 are treated as 𝜔\u2080\n"
                    "can mitigate error from inaccuracies in the harmonic oscillator\n"
                    "approximation for low-frequency vibrations",
                ),
            ])

            for i, (label_text, val, link, tooltip) in enumerate(items):
                self.thermo_table.insertRow(i)

                label = QLabel(label_text)
                if link:
                    label = QLabel()
                    label.setText(
                        "<a href=\"%s\" style=\"text-decoration: none;\">%s</a>"
                        % (link, label_text))
                    label.setTextFormat(Qt.RichText)
                    label.setTextInteractionFlags(Qt.TextBrowserInteraction)
                    label.linkActivated.connect(self.open_link)

                label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
                label.setToolTip(tooltip)

                self.thermo_table.setCellWidget(i, 0, label)

                unit_label = ReadOnlyTableItem()
                unit_label.setData(Qt.DisplayRole, "E\u2095")
                unit_label.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter)
                unit_label.setToolTip(tooltip)
                self.thermo_table.setItem(i, 2, unit_label)

                d_nrg = SmallLineEdit("%.6f" % val)
                d_nrg.setReadOnly(True)
                d_nrg.setFrame(False)
                d_nrg.setToolTip(tooltip)
                self.thermo_table.setCellWidget(i, 1, d_nrg)

                self.thermo_table.resizeRowToContents(i)

            self.thermo_table.resizeColumnToContents(0)
            self.thermo_table.resizeColumnToContents(1)
            self.thermo_table.resizeColumnToContents(2)

        self.update_sum()
예제 #15
0
class Client(QDialog):
    def __init__(self, parent: QWidget = None):
        super().__init__(parent)

        self._in = QDataStream()
        self.blockSize = 0

        self.currentFortune = ""

        self.hostLineEdit = QLineEdit("fortune")
        self.getFortuneButton = QPushButton(self.tr("Get Fortune"))
        self.statusLabel = QLabel(
            self.tr(
                "This examples requires that you run the Local Fortune Server example as well."
            )
        )
        self.socket = QLocalSocket()

        self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
        hostLabel = QLabel(self.tr("&Server name:"))
        hostLabel.setBuddy(self.hostLineEdit)

        self.statusLabel.setWordWrap(True)

        self.getFortuneButton.setDefault(True)
        quitButton = QPushButton(self.tr("Quit"))

        buttonBox = QDialogButtonBox()
        buttonBox.addButton(self.getFortuneButton, QDialogButtonBox.ActionRole)
        buttonBox.addButton(quitButton, QDialogButtonBox.RejectRole)

        self._in.setDevice(self.socket)
        self._in.setVersion(QDataStream.Qt_5_10)

        self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton)

        self.getFortuneButton.clicked.connect(self.requestNewFortune)
        quitButton.clicked.connect(self.close)
        self.socket.readyRead.connect(self.readFortune)
        self.socket.errorOccurred.connect(self.displayError)

        mainLayout = QGridLayout(self)
        mainLayout.addWidget(hostLabel, 0, 0)
        mainLayout.addWidget(self.hostLineEdit, 0, 1)
        mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2)
        mainLayout.addWidget(buttonBox, 3, 0, 1, 2)

        self.setWindowTitle(QGuiApplication.applicationDisplayName())
        self.hostLineEdit.setFocus()

    @Slot()
    def requestNewFortune(self):
        self.getFortuneButton.setEnabled(False)
        self.blockSize = 0
        self.socket.abort()
        self.socket.connectToServer(self.hostLineEdit.text())

    @Slot()
    def readFortune(self):
        if self.blockSize == 0:
            # Relies on the fact that QDataStream serializes a quint32 into
            # sizeof(quint32) bytes
            if self.socket.bytesAvailable() < 4:  #  (int)sizeof(quint32))
                return
            self.blockSize = self._in.readUInt32()

        if self.socket.bytesAvailable() < self.blockSize or self._in.atEnd():
            return

        nextFortune = ""
        nextFortune = self._in.readQString()

        if nextFortune == self.currentFortune:
            QTimer.singleShot(0, self.requestNewFortune)
            return

        currentFortune = nextFortune
        self.statusLabel.setText(currentFortune)
        self.getFortuneButton.setEnabled(True)

    @Slot(QLocalSocket.LocalSocketError)
    def displayError(self, socketError):
        if socketError == QLocalSocket.ServerNotFoundError:

            QMessageBox.information(
                self,
                self.tr("Local Fortune Client"),
                self.tr(
                    "The host was not found. Please make sure "
                    "that the server is running and that the "
                    "server name is correct."
                ),
            )
        elif socketError == QLocalSocket.ConnectionRefusedError:
            QMessageBox.information(
                self,
                self.tr("Local Fortune Client"),
                self.tr(
                    "The connection was refused by the peer. "
                    "Make sure the fortune server is running, "
                    "and check that the server name is correct."
                ),
            )
        elif socketError == QLocalSocket.PeerClosedError:
            return
        else:
            QMessageBox.information(
                self,
                self.tr("Local Fortune Client"),
                self.tr(
                    "The following error occurred: %s." % (self.socket.errorString())
                ),
            )

        self.getFortuneButton.setEnabled(True)

    @Slot()
    def enableGetFortuneButton(self):
        self.getFortuneButton.setEnabled(bool(self.hostLineEdit.ext()))
예제 #16
0
class NotificationPopup(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.m_icon = QLabel()
        self.m_title = QLabel()
        self.m_message = QLabel()

        self.notification = None

        self.setWindowFlags(Qt.ToolTip)
        rootLayout = QHBoxLayout(self)

        rootLayout.addWidget(self.m_icon)

        bodyLayout = QVBoxLayout()
        rootLayout.addLayout(bodyLayout)

        titleLayout = QHBoxLayout()
        bodyLayout.addLayout(titleLayout)

        titleLayout.addWidget(self.m_title)
        titleLayout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding))

        close = QPushButton(self.tr("Close"))
        titleLayout.addWidget(close)
        close.clicked.connect(self.onClosed)

        bodyLayout.addWidget(self.m_message)
        self.adjustSize()

    def present(self, newNotification):
        if self.notification:
            self.notification.close()
            sip.delete(self.notification)
            self.notification = None

        self.notification = newNotification

        self.m_title.setText(f"<b>{self.notification.title()}</b>")
        self.m_message.setText(self.notification.message())
        self.m_icon.setPixmap(
            QPixmap.fromImage(self.notification.icon()).scaledToHeight(
                self.m_icon.height()))

        self.show()
        self.notification.show()

        self.notification.closed.connect(self.onClosed)
        QTimer.singleShot(
            10000, lambda: self.onClosed()
            if self.notification is not None else None)

        # position our popup in the right corner of its parent widget
        self.move(self.parentWidget().mapToGlobal(
            self.parentWidget().rect().bottomRight() -
            QPoint(self.width() + 10,
                   self.height() + 10)))

    @Slot()
    def onClosed(self):
        self.hide()
        self.notification.close()
        self.notification = None

    def mouseReleaseEvent(self, event):
        super().mouseReleaseEvent(event)
        if self.notification and event.button() == Qt.LeftButton:
            self.notification.click()
            self.onClosed()
예제 #17
0
class VariableBase(QWidget):
    ## executed when value been set
    valueChanged = QtCore.Signal()
    ## executed when name been changed
    nameChanged = QtCore.Signal(str)
    ## executed when variable been killed
    killed = QtCore.Signal()
    ## executed when variable data type been changed
    dataTypeChanged = QtCore.Signal(int)
    ## executed when variable access level been changed
    accessLevelChanged = QtCore.Signal(int)

    def __init__(self,
                 name,
                 value,
                 graph,
                 varsListWidget,
                 dataType=DataTypes.Bool,
                 uid=None):
        super(VariableBase, self).__init__()
        self._accessLevel = AccessLevel.public
        # ui
        self.horizontalLayout = QHBoxLayout(self)
        self.horizontalLayout.setSpacing(1)
        self.horizontalLayout.setContentsMargins(1, 1, 1, 1)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.widget = TypeWidget(Colors.Bool, self)
        self.widget.setObjectName("widget")
        self.horizontalLayout.addWidget(self.widget)
        self.labelName = QLabel(self)
        self.labelName.setObjectName("labelName")
        self.horizontalLayout.addWidget(self.labelName, 1)
        spacerItem = QSpacerItem(1, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)

        QtCore.QMetaObject.connectSlotsByName(self)
        # body
        self.varsListWidget = varsListWidget
        self.name = None
        self._value = value
        self.dataType = dataType
        self._uid = uid
        if self._uid is None:
            self._uid = uuid4()
        self.graph = graph
        self.setName(name)
        self.types = [
            v.name for v in list(DataTypes)
            if v not in [DataTypes.Reference, DataTypes.Exec, DataTypes.Enum]
        ]
        self.graph.vars[self.uid] = self

    @property
    def accessLevel(self):
        return self._accessLevel

    @accessLevel.setter
    def accessLevel(self, value):
        self._accessLevel = value
        self.accessLevelChanged.emit(value)

    @property
    def uid(self):
        return self._uid

    @uid.setter
    def uid(self, value):
        self._uid = value
        if self._uid in self.graph.vars:
            self.graph.vars.pop(self._uid)
            self.graph.vars[self._uid] = self

    @staticmethod
    def jsonTemplate():
        template = {'name': None, 'uuid': None, 'value': None, 'type': None}
        return template

    def serialize(self):
        template = VariableBase.jsonTemplate()
        template['name'] = self.name
        template['uuid'] = str(self.uid)
        template['value'] = self.value
        template['type'] = int(self.dataType)
        template['accessLevel'] = int(self.accessLevel)
        return template

    @staticmethod
    def deserialize(data, graph):
        var = graph.parent.variablesWidget.createVariable(
            uuid.UUID(data['uuid']))
        var.setName(data['name'])
        var.setDataType(data['type'])
        var.value = data['value']
        var.accessLevel = data['accessLevel']
        return var

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, data):
        self._value = data
        self.valueChanged.emit()

    ## Changes variable data type and updates [TypeWidget](@ref PyFlow.Core.Variable.TypeWidget) color
    # @bug in the end of this method we clear undo stack, but we should not. We do this because undo redo goes crazy
    def setDataType(self, dataType, _bJustSpawned=False):
        self.dataType = dataType
        #print self.dataType
        try:
            self.widget.color = Pins.findPinClassByType(self.dataType).color()

            self.value = Pins.findPinClassByType(
                self.dataType).pinDataTypeHint()[1]
        except:
            pass
        self.widget.update()
        if _bJustSpawned:
            return
        self.dataTypeChanged.emit(self.dataType)
        self.graph.undoStack.clear()
        self.graph.tryFillPropertiesView(self)

    def mousePressEvent(self, event):
        QWidget.mousePressEvent(self, event)
        self.graph.tryFillPropertiesView(self)

    def setName(self, name):
        self.labelName.setText(name)
        self.name = name
        self.nameChanged.emit(str(name))

    def onUpdatePropertyView(self, formLayout):
        # name
        le_name = QLineEdit(self.name)
        le_name.returnPressed.connect(lambda: self.setName(le_name.text()))
        formLayout.addRow("Name", le_name)

        # data type
        cbTypes = VarTypeComboBox(self)
        formLayout.addRow("Type", cbTypes)

        # current value
        def valSetter(x):
            self.value = x

        w = InputWidgets.getInputWidget(
            self.dataType, valSetter,
            Pins.getPinDefaultValueByType(self.dataType), None)
        if w:
            w.setWidgetValue(self.value)
            w.setObjectName(self.name)
            formLayout.addRow(self.name, w)
        # access level
        cb = QComboBox()
        cb.addItem('public', 0)
        cb.addItem('private', 1)
        cb.addItem('protected', 2)

        def accessLevelChanged(x):
            self.accessLevel = x

        cb.currentIndexChanged[int].connect(accessLevelChanged)
        cb.setCurrentIndex(self.accessLevel)
        formLayout.addRow('Access level', cb)
예제 #18
0
class UIVariable(QWidget, IPropertiesViewSupport):
    def __init__(self, rawVariable, variablesWidget, parent=None):
        super(UIVariable, self).__init__(parent)
        self._rawVariable = rawVariable
        self.variablesWidget = variablesWidget

        # ui
        self.horizontalLayout = QHBoxLayout(self)
        self.horizontalLayout.setSpacing(1)
        self.horizontalLayout.setContentsMargins(1, 1, 1, 1)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.widget = TypeWidget(
            findPinClassByType(self._rawVariable.dataType).color(), self)
        self.widget.setObjectName("widget")
        self.horizontalLayout.addWidget(self.widget)
        self.labelName = QLabel(self)
        self.labelName.setObjectName("labelName")
        self.horizontalLayout.addWidget(self.labelName)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        # find refs
        self.pbFindRefs = QPushButton("")
        self.pbFindRefs.setIcon(
            QtGui.QIcon(RESOURCES_DIR + "/searching-magnifying-glass.png"))
        self.pbFindRefs.setObjectName("pbFindRefs")
        self.horizontalLayout.addWidget(self.pbFindRefs)
        self.pbFindRefs.clicked.connect(self.onFindRefsClicked)
        #  kill variable
        self.pbKill = QPushButton("")
        self.pbKill.setIcon(QtGui.QIcon(RESOURCES_DIR + "/delete_icon.png"))
        self.pbKill.setObjectName("pbKill")
        self.horizontalLayout.addWidget(self.pbKill)
        self.pbKill.clicked.connect(self.onKillClicked)

        QtCore.QMetaObject.connectSlotsByName(self)
        self.setName(self._rawVariable.name)

    def createPropertiesWidget(self, propertiesWidget):
        baseCategory = CollapsibleFormWidget(headName="Base")
        # name
        le_name = QLineEdit(self._rawVariable.name)
        le_name.returnPressed.connect(lambda: self.setName(le_name.text()))
        baseCategory.addWidget("Name", le_name)

        # data type
        cbTypes = VarTypeComboBox(self)
        baseCategory.addWidget("Type", cbTypes)
        propertiesWidget.addWidget(baseCategory)

        valueCategory = CollapsibleFormWidget(headName="Value")

        # current value
        def valSetter(x):
            self._rawVariable.value = x

        w = createInputWidget(
            self._rawVariable.dataType, valSetter,
            getPinDefaultValueByType(self._rawVariable.dataType))
        if w:
            w.setWidgetValue(self._rawVariable.value)
            w.setObjectName(self._rawVariable.name)
            valueCategory.addWidget(self._rawVariable.name, w)

        # access level
        cb = QComboBox()
        cb.addItem('public', 0)
        cb.addItem('private', 1)
        cb.addItem('protected', 2)

        def accessLevelChanged(x):
            self._rawVariable.accessLevel = AccessLevel[x]

        cb.currentTextChanged.connect(accessLevelChanged)
        cb.setCurrentIndex(self._rawVariable.accessLevel)
        valueCategory.addWidget('Access level', cb)
        propertiesWidget.addWidget(valueCategory)

    def onFindRefsClicked(self):
        refs = self._rawVariable.findRefs()
        print(refs)

    def onKillClicked(self):
        # check refs and ask user what to do
        refs = self._rawVariable.findRefs()
        if len(refs) > 0:
            item, accepted = QInputDialog.getItem(
                None,
                'Decide!',
                'What to do with getters and setters in canvas?',
                ['kill', 'leave'],
                editable=False)
            if accepted:
                if item == 'kill':
                    self.variablesWidget.killVar(self)
                elif item == 'leave':
                    # mark node as invalid
                    # TODO: For future. Like in ue4, if variable is removed, it can be recreated from node (e.g. promote to variable)
                    print('leave')
        else:
            self.variablesWidget.killVar(self)

    @property
    def dataType(self):
        return self._rawVariable.dataType

    @dataType.setter
    def dataType(self, value):
        self._rawVariable.dataType = value

    @property
    def packageName(self):
        return self._rawVariable.packageName

    @property
    def accessLevel(self):
        return self._rawVariable.accessLevel

    @accessLevel.setter
    def accessLevel(self, value):
        self._rawVariable.accessLevel = value

    @property
    def uid(self):
        return self._rawVariable.uid

    @uid.setter
    def uid(self, value):
        self._rawVariable.uid = value
        if self._rawVariable.uid in self.graph.vars:
            self.graph.vars.pop(self._rawVariable.uid)
            self.graph.vars[self._rawVariable.uid] = self._rawVariable

    @staticmethod
    def jsonTemplate():
        template = {
            'name': None,
            'uuid': None,
            'value': None,
            'type': None,
            'package': None,
            'accessLevel': None
        }
        return template

    def serialize(self):
        pinClass = findPinClassByType(self._rawVariable.dataType)

        template = UIVariable.jsonTemplate()
        template['name'] = self._rawVariable.name
        template['uuid'] = str(self._rawVariable.uid)

        if self._rawVariable.dataType == "AnyPin":
            # don't save any variables
            # value will be calculated for this type of variables
            template['value'] = None
        else:
            template['value'] = json.dumps(self._rawVariable.value,
                                           cls=pinClass.jsonEncoderClass())

        template['type'] = self._rawVariable.dataType
        template['package'] = self._rawVariable.packageName
        template['accessLevel'] = self._rawVariable.accessLevel.value
        return template

    @staticmethod
    def deserialize(data, graph):
        pinClass = findPinClassByType(data['dataType'])

        varUid = uuid.UUID(data['uuid'])
        # TODO: this is probably bad. Too long call chain
        var = graph.parent.variablesWidget.createVariable(
            dataType=data['dataType'],
            accessLevel=AccessLevel(data['accessLevel']),
            uid=varUid)
        var.setName(data['name'])
        var.setDataType(data['dataType'])

        if data['dataType'] == 'AnyPin':
            var.value = getPinDefaultValueByType('AnyPin')
        else:
            var.value = json.loads(data['value'],
                                   cls=pinClass.jsonDecoderClass())

        return var

    @property
    def value(self):
        return self._rawVariable.value

    @value.setter
    def value(self, data):
        self._rawVariable.value = data

    # Changes variable data type and updates [TypeWidget](@ref PyFlow.Core.Variable.TypeWidget) color
    # @bug in the end of this method we clear undo stack, but we should not. We do this because undo redo goes crazy
    def setDataType(self, dataType, _bJustSpawned=False):
        self._rawVariable.dataType = dataType
        self.widget.color = findPinClassByType(self.dataType).color()
        self.widget.update()
        if _bJustSpawned:
            return
        self.variablesWidget.onUpdatePropertyView(self)

    def mousePressEvent(self, event):
        super(UIVariable, self).mousePressEvent(event)
        self.variablesWidget.onUpdatePropertyView(self)

    def setName(self, name):
        self._rawVariable.name = name
        self.labelName.setText(self._rawVariable.name)
예제 #19
0
class Second(QMainWindow):
    def __init__(self):
        super(Second, self).__init__()
        self.setWindowTitle("Add new device")

        self.nameLabel = QLabel(self)
        self.nameLabel.move(10, 10)
        self.nameLabel.setText("Device name")
        self.nameEntry = QLineEdit(self)
        self.nameEntry.move(10, 40)
        self.nameEntry.resize(100, 30)

        self.colorLabel = QLabel(self)
        self.colorLabel.move(120, 10)
        self.colorLabel.setText("Color cameras")
        self.colorEntry = QLineEdit(self)
        self.colorEntry.move(140, 40)
        self.colorEntry.resize(70, 30)
        self.colorEntry.setValidator(QtGui.QIntValidator())

        self.monoLabel = QLabel(self)
        self.monoLabel.move(230, 10)
        self.monoLabel.setText("Mono cameras")
        self.monoEntry = QLineEdit(self)
        self.monoEntry.move(250, 40)
        self.monoEntry.resize(70, 30)
        self.monoEntry.setValidator(QtGui.QIntValidator())

        self.depthPresent = QCheckBox("Include depth", self)
        self.depthPresent.move(10, 80)
        self.depthPresent.resize(150, 30)
        self.depthPresent.stateChanged.connect(self.toggle_depth)

        self.leftfovLabel = QLabel(self)
        self.leftfovLabel.move(10, 120)
        self.leftfovLabel.setText("Left FOV deg.")
        self.leftfovEntry = QLineEdit(self)
        self.leftfovEntry.move(180, 120)
        self.leftfovEntry.resize(140, 30)
        self.leftfovEntry.setValidator(QtGui.QDoubleValidator())

        self.rightfovLabel = QLabel(self)
        self.rightfovLabel.move(10, 160)
        self.rightfovLabel.setText("Right FOV deg.")
        self.rightfovEntry = QLineEdit(self)
        self.rightfovEntry.move(180, 160)
        self.rightfovEntry.resize(140, 30)
        self.rightfovEntry.setValidator(QtGui.QDoubleValidator())

        self.rgbfovLabel = QLabel(self)
        self.rgbfovLabel.move(10, 200)
        self.rgbfovLabel.setText("RGB FOV deg.")
        self.rgbfovEntry = QLineEdit(self)
        self.rgbfovEntry.move(180, 200)
        self.rgbfovEntry.resize(140, 30)
        self.rgbfovEntry.setValidator(QtGui.QDoubleValidator())

        self.lrdistanceLabel = QLabel(self)
        self.lrdistanceLabel.move(10, 240)
        self.lrdistanceLabel.resize(200, 30)
        self.lrdistanceLabel.setText("Left - Right distance cm.")
        self.lrdistanceEntry = QLineEdit(self)
        self.lrdistanceEntry.move(180, 240)
        self.lrdistanceEntry.resize(140, 30)
        self.lrdistanceEntry.setValidator(QtGui.QDoubleValidator())

        self.lrgbdistanceLabel = QLabel(self)
        self.lrgbdistanceLabel.move(10, 280)
        self.lrgbdistanceLabel.resize(200, 30)
        self.lrgbdistanceLabel.setText("Left - RGB distance cm.")
        self.lrgbdistanceEntry = QLineEdit(self)
        self.lrgbdistanceEntry.move(180, 280)
        self.lrgbdistanceEntry.resize(140, 30)
        self.lrgbdistanceEntry.setValidator(QtGui.QDoubleValidator())

        self.saveButton = QPushButton("Save", self)
        self.saveButton.resize(100, 30)
        self.saveButton.clicked.connect(self.save)

        self.cancelButton = QPushButton("Cancel", self)
        self.cancelButton.resize(100, 30)
        self.cancelButton.clicked.connect(self.cancel)

        self.toggle_depth(False)

    def toggle_depth(self, checked):
        if checked:
            self.leftfovLabel.setVisible(True)
            self.leftfovEntry.setVisible(True)
            self.rightfovLabel.setVisible(True)
            self.rightfovEntry.setVisible(True)
            self.rgbfovLabel.setVisible(True)
            self.rgbfovEntry.setVisible(True)
            self.lrdistanceLabel.setVisible(True)
            self.lrdistanceEntry.setVisible(True)
            self.lrgbdistanceLabel.setVisible(True)
            self.lrgbdistanceEntry.setVisible(True)
            self.saveButton.move(200, 330)
            self.cancelButton.move(30, 330)
            self.resize(330, 380)
        else:
            self.leftfovLabel.setVisible(False)
            self.leftfovEntry.setVisible(False)
            self.rightfovLabel.setVisible(False)
            self.rightfovEntry.setVisible(False)
            self.rgbfovLabel.setVisible(False)
            self.rgbfovEntry.setVisible(False)
            self.lrdistanceLabel.setVisible(False)
            self.lrdistanceEntry.setVisible(False)
            self.lrgbdistanceLabel.setVisible(False)
            self.lrgbdistanceEntry.setVisible(False)
            self.saveButton.move(200, 120)
            self.cancelButton.move(30, 120)
            self.resize(330, 170)

    def save(self, *args, **kwargs):
        try:
            data = {
                "name": self.nameEntry.text(),
                "color_count": int(self.colorEntry.text()),
                "mono_count": int(self.monoEntry.text()),
            }
            if self.depthPresent.isChecked():
                data.update({
                    "depth":
                    True,
                    "left_fov_deg":
                    float(self.leftfovEntry.text()),
                    "right_fov_deg":
                    float(self.rightfovEntry.text()),
                    "rgb_fov_deg":
                    float(self.rgbfovEntry.text()),
                    "left_to_right_distance_cm":
                    float(self.lrdistanceEntry.text()),
                    "left_to_rgb_distance_cm":
                    float(self.lrgbdistanceEntry.text()),
                })
            append_to_json(
                data,
                Path(__file__).parent.parent / Path('custom_devices.json'))
            self.close()
            INITIALIZE()
            self.instance.getRegisteredTools(['NodeBoxTool'])[0].refresh()
        except Exception as e:
            QMessageBox.warning(self, "Warning", str(e))

    def cancel(self):
        self.close()
예제 #20
0
class CategoryWidget(base.BaseWidget, object):

    doRefresh = Signal(object)
    doPreview = Signal(list, bool)
    doRename = Signal()
    togglePreview = Signal()

    def __init__(self, types, nodes_to_discard=None, parent=None):
        self._types = types
        self._default_nodes_to_discard = nodes_to_discard or list()
        self._category_buttons = list()
        super(CategoryWidget, self).__init__(parent=parent)

    @property
    def types(self):
        return self._types

    @property
    def nodes_to_discard(self):
        return self._default_nodes_to_discard

    @nodes_to_discard.setter
    def nodes_to_discard(self, nodes_to_discard):
        self._default_nodes_to_discard = nodes_to_discard

    def ui(self):
        super(CategoryWidget, self).ui()

        filter_layout = layouts.HorizontalLayout(spacing=2,
                                                 margins=(10, 0, 10, 0))
        self.main_layout.addLayout(filter_layout)
        refresh_icon = resources.icon('refresh')
        self._refresh_list_btn = buttons.IconButton(
            icon=refresh_icon,
            icon_padding=2,
            button_style=buttons.ButtonStyles.FlatStyle)
        self._names_filter = search.SearchFindWidget()
        self._search_lbl = QLabel('0 found')
        filter_layout.addWidget(self._refresh_list_btn)
        filter_layout.addWidget(self._names_filter)
        filter_layout.addWidget(self._search_lbl)

        self._types_layout = layouts.HorizontalLayout(spacing=2,
                                                      margins=(0, 0, 0, 0))
        self.main_layout.addLayout(self._types_layout)

        self._names_list = QTreeWidget(self)
        self._names_list.setHeaderHidden(True)
        self._names_list.setSortingEnabled(False)
        self._names_list.setRootIsDecorated(False)
        self._names_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self._names_list.sortByColumn(0, Qt.AscendingOrder)
        self._names_list.setUniformRowHeights(True)
        self._names_list.setAlternatingRowColors(True)

        self.main_layout.addWidget(self._names_list)

        bottom_buttons_layout = layouts.HorizontalLayout(spacing=2,
                                                         margins=(2, 2, 2, 2))
        bottom_buttons_layout.setAlignment(Qt.AlignLeft)
        self.main_layout.addLayout(bottom_buttons_layout)

        preview_icon = resources.icon('preview')
        self._sort_btn = buttons.BaseButton('Sort', parent=self)
        self._sort_btn.setMinimumWidth(40)
        self._all_btn = buttons.BaseButton('All', parent=self)
        self._all_btn.setMinimumWidth(40)
        self._none_btn = buttons.BaseButton('None', parent=self)
        self._none_btn.setMinimumWidth(40)
        bottom_buttons_layout.addWidget(self._sort_btn)
        bottom_buttons_layout.addWidget(self._all_btn)
        bottom_buttons_layout.addWidget(self._none_btn)

        bottom_buttons_layout.addWidget(
            dividers.get_horizontal_separator_widget())
        self._hide_default_scene_nodes_cbx = checkbox.BaseCheckBox(
            'Hide Default Scene Objects', parent=self)
        self._hide_default_scene_nodes_cbx.setChecked(True)
        bottom_buttons_layout.addWidget(self._hide_default_scene_nodes_cbx)

        self.main_layout.addLayout(dividers.DividerLayout())

        preview_layout = layouts.HorizontalLayout(spacing=2,
                                                  margins=(0, 0, 0, 0))
        self.main_layout.addLayout(preview_layout)

        self._preview_btn = buttons.BaseButton('Preview', parent=self)
        self._preview_btn.setIcon(preview_icon)
        self._preview_btn.setCheckable(True)
        self._preview_btn.setChecked(True)
        self._preview_btn.setMinimumWidth(100)
        self._preview_btn.setMaximumWidth(100)
        self._rename_btn = buttons.BaseButton(
            'Select objects in the list to rename ...', parent=self)
        self._rename_btn.setEnabled(False)
        preview_layout.addWidget(self._preview_btn)
        preview_layout.addWidget(self._rename_btn)

        self._setup_types()
        self.refresh()

    def setup_signals(self):
        self._refresh_list_btn.clicked.connect(self._on_refresh_list)
        self._names_filter.textChanged.connect(self._on_filter_names_changed)
        self._hide_default_scene_nodes_cbx.toggled.connect(
            self._on_toggle_hide_default_scene_nodes_cbx)
        self._names_list.itemSelectionChanged.connect(
            self._on_item_selection_changed)
        self._none_btn.clicked.connect(self._on_select_none_clicked)
        self._all_btn.clicked.connect(self._on_select_all_clicked)
        self._preview_btn.toggled.connect(self._on_toggle_preview)
        self._rename_btn.clicked.connect(self.doRename.emit)

    def get_names_list(self):
        return self._names_list

    def is_preview_enabled(self):
        return self._preview_btn.isChecked()

    def refresh(self, selected_objects=False, hierarchy=False):
        self._names_list.clear()
        self._names_list.setSortingEnabled(True)

        try:
            objs_names = list()
            if not selected_objects:
                objs_names.extend(dcc.all_scene_nodes(full_path=True))
            else:
                objs_names.extend(dcc.selected_nodes(full_path=True))
                if objs_names and hierarchy:
                    children_list = list()
                    for obj in objs_names:
                        children = dcc.list_children(obj,
                                                     all_hierarchy=True,
                                                     full_path=True)
                        if children:
                            children_list.extend(children)
                    children_list = list(set(children_list))
                    objs_names.extend(children_list)
            self._update_names_list(objs_names)
            self._on_filter_names_changed(self._names_filter.get_text())
        finally:
            self._names_list.setSortingEnabled(False)

    def _setup_types(self):
        for i, category_type in enumerate(self._types):
            for type_name, type_data in category_type.items():
                dcc_type = type_data.get('type', None)
                dcc_fn = type_data.get('fn', None)
                dcc_args = type_data.get('args', dict())
                type_btn = buttons.BaseButton(type_name, parent=self)
                type_btn.setCheckable(True)
                type_btn.setProperty('dcc_type', dcc_type)
                type_btn.setProperty('dcc_fn', dcc_fn)
                type_btn.setProperty('dcc_args', dcc_args)
                if i == 0:
                    type_btn.setChecked(True)
                self._types_layout.addWidget(type_btn)
                self._category_buttons.append(type_btn)
                type_btn.toggled.connect(self._on_toggle_type)

        self._others_btn = buttons.BaseButton('Others', parent=self)
        self._others_btn.setCheckable(True)
        self._types_layout.addWidget(self._others_btn)
        self._others_btn.toggled.connect(self._on_toggle_type)

    def _get_nodes_to_discard(self):
        """
        Internal function that returns list of nodes that should be discarded during renaming process
        """

        discard_nodes = self._default_nodes_to_discard[:] or list()

        if self._hide_default_scene_nodes_cbx and self._hide_default_scene_nodes_cbx.isChecked(
        ):
            discard_nodes.extend(dcc.default_scene_nodes(full_path=False))

        # discard_nodes.extend(dcc.list_nodes(node_type='camera'))

        for btn in self._category_buttons:
            if not btn.isChecked():
                dcc_type = btn.property('dcc_type')
                if dcc_type:
                    discard_nodes.extend(
                        dcc.list_nodes(node_type=btn.property('dcc_type')))
                else:
                    dcc_fn = btn.property('dcc_fn')
                    if dcc_fn:
                        dcc_args = btn.property('dcc_args')
                        if dcc.is_maya():
                            valid_args = dict()
                            for arg_name, arg_value in dcc_args.items():
                                valid_args[str(arg_name)] = arg_value
                            nodes = getattr(maya.cmds, dcc_fn)(**valid_args)
                            discard_nodes.extend(nodes)

        return list(set(discard_nodes))

    def _get_node_types(self):
        node_types = set()
        for btn in self._category_buttons:
            dcc_type = btn.property('dcc_type')
            if dcc_type:
                node_types.add(dcc_type)
            else:
                dcc_fn = btn.property('dcc_fn')
                if dcc_fn:
                    dcc_args = btn.property('dcc_args')
                    if dcc.is_maya():
                        valid_args = dict()
                        for arg_name, arg_value in dcc_args.items():
                            valid_args[str(arg_name)] = arg_value
                        nodes = getattr(maya.cmds, dcc_fn)(**valid_args)
                        for node in nodes:
                            node_type = dcc.node_type(node)
                            node_types.add(node_type)

        return list(node_types)

    def _update_names_list(self, nodes):
        """
        Internal function that updates names list with given node names
        :param nodes: list(str)
        """

        nodes_to_discard = self._get_nodes_to_discard() or list()

        nodes = list(set(nodes))

        for obj in nodes:
            if obj in nodes_to_discard:
                continue
            node_type = dcc.node_type(obj)
            if node_type not in self._get_node_types(
            ) and not self._others_btn.isChecked():
                is_valid = False
                for node_type in self._get_node_types():
                    is_valid = dcc.check_object_type(obj,
                                                     node_type,
                                                     check_sub_types=True)
                    if is_valid:
                        break
                if not is_valid:
                    continue

            node_name = dcc.node_short_name(obj)
            item = QTreeWidgetItem(self._names_list, [node_name])
            item.obj = node_name
            item.preview_name = ''
            item.full_name = obj
            if dcc.is_maya():
                sel = api.SelectionList()
                sel.add(obj)
                item.handle = maya.OpenMaya.MObjectHandle(
                    sel.get_depend_node(0))

            self._names_list.addTopLevelItem(item)

    def _on_filter_names_changed(self, filter_text):
        """
        Internal callback function that is called each time the user enters text in the search line widget
        Shows or hides elements in the list taking in account the filter_text
        :param filter_text: str, current text
        """

        nodes_found = 0
        for i in range(self._names_list.topLevelItemCount()):
            item = self._names_list.topLevelItem(i)
            # item.setHidden(filter_text not in item.text(0))
            if filter_text not in item.text(0):
                item.setHidden(True)
            else:
                item.setHidden(False)
                nodes_found += 1

        if filter_text:
            self._search_lbl.setText('{} found'.format(nodes_found))
        else:
            self._search_lbl.setText('0 found')

    def _on_item_selection_changed(self):
        """
        Internal callback function that is triggered when the user selects an item in the names list
        """

        selected_items = self._names_list.selectedItems()
        item_names = [item.obj for item in selected_items]
        if len(selected_items) > 0:
            self._rename_btn.setText('Rename')
            self._rename_btn.setEnabled(True)
        else:
            self._rename_btn.setText(
                'Select objects in the list to rename ...')
            self._rename_btn.setEnabled(False)

        # We reset name to original value
        for i in range(self._names_list.topLevelItemCount()):
            item = self._names_list.topLevelItem(i)
            if item.text(0) in item_names:
                continue
            if hasattr(item, 'obj'):
                item.setText(0, item.obj)

        self.doPreview.emit(selected_items, self._preview_btn.isChecked())

    def _on_select_all_clicked(self):
        for i in range(self._names_list.topLevelItemCount()):
            item = self._names_list.topLevelItem(i)
            item.setSelected(True)

    def _on_select_none_clicked(self):
        for i in range(self._names_list.topLevelItemCount()):
            item = self._names_list.topLevelItem(i)
            item.setSelected(False)

    def _on_refresh_list(self):
        self.doRefresh.emit(self)

    def _on_toggle_type(self, flag):
        self.doRefresh.emit(self)

    def _on_toggle_hide_default_scene_nodes_cbx(self, flag):
        self.doRefresh.emit(self)

    def _on_toggle_preview(self, flag):
        self.togglePreview.emit()
예제 #21
0
class RowTableWidget(QFrame):
    double_clicked = Signal(object)

    def __init__(self,
        auto_resize=False,
        single_row_select=True,
        context_menu_callback=None,
        last_column_stretch=True,
        has_counters=False,
        parent=None
    ):
        QFrame.__init__(self, parent)
        self._has_counters = has_counters

        self.model = None

        self.table_view = RowTableView(auto_resize, single_row_select, context_menu_callback, last_column_stretch)
        self.table_view.doubleClicked.connect(self._double_clicked)

        if has_counters:
            self.counters = Counters()
            self.counters.button_clicked.connect(self._counter_clicked)

        self.search_bar = QLineEdit()
        self.search_bar.setFixedHeight(SEARCHBAR_HEIGHT)
        self.search_bar.textChanged.connect(self.set_search_text)
        self.search_bar.setToolTip("Search bar")

        self.auto_size_button = QPushButton('<>')
        self.auto_size_button.setFixedSize(SEARCHBAR_HEIGHT, SEARCHBAR_HEIGHT)
        self.auto_size_button.clicked.connect(self._auto_size_clicked)
        self.auto_size_button.setToolTip("Auto size")

        self.status_label = QLabel(STATUS_LABEL_MESSAGE.format(0, 0))
        self.status_label.setFixedWidth(STATUS_LABEL_WIDTH)

        self.progress_bar = QProgressBar()
        self.progress_bar.setFormat('')

        layout = QGridLayout()

        layout.addWidget(self.search_bar, 0, 0, 1, 3)
        layout.addWidget(self.auto_size_button, 0, 3)
        if has_counters:
            layout.addWidget(self.counters, 1, 0, 1, 2)
            layout.addWidget(self.table_view, 1, 2, 1, 2)
        else:
            layout.addWidget(self.table_view, 1, 0, 1, 4)
        layout.addWidget(self.status_label, 2, 0)
        layout.addWidget(self.progress_bar, 2, 1, 1, 3)
        layout.setColumnStretch(2, 100)

        self.setLayout(layout)

    def set_model(self, model):
        self.model = model
        self.table_view.setModel(model)

        model.modelReset.connect(self._set_progress_maximum)
        model.modelReset.connect(self._update_status)
        if self._has_counters:
            model.modelReset.connect(self._update_counters)
            self._update_counters()
        model.progress_updated.connect(self._update_progress)

        self._set_progress_maximum()
        self._update_status()
        self.progress_bar.setVisible(model.has_background_callback)

    @property
    def selected_rows(self):
        return [self.model.data(index, Qt.UserRole) for index
                in self.table_view.selectionModel().selectedIndexes() if index.column() == 0]

    @property
    def search_text(self):
        return self.search_bar.text()

    def set_search_text(self, text):
        self.search_bar.blockSignals(True)
        self.search_bar.setText(text)
        self.search_bar.blockSignals(False)
        self.model.set_search_text(text)

    def _set_progress_maximum(self):
        self.progress_bar.setMaximum(self.model.progress_max)  # do better ?

    def _update_progress(self, value):
        self.progress_bar.setValue(value)

    def _update_status(self):
        self.status_label.setText(STATUS_LABEL_MESSAGE.format(
            self.model.rowCount(), self.model.total_row_count
        ))

    def _counter_clicked(self, entry, checked_buttons):
        entries = [entry for entry, active in checked_buttons.items() if active]
        self.model.set_search_counters(entries)

    def _update_counters(self):
        self.counters.set(self.model.counters)

    def _auto_size_clicked(self):
        with Hourglass():
            self.table_view.resizeColumnsToContents()

    def _double_clicked(self, index):
        row = self.model.data(index, Qt.UserRole)
        self.double_clicked.emit(row)

    def state(self):
        header_sizes = list()
        header = self.table_view.horizontalHeader()
        for section_index in range(header.count()):
            header_sizes.append(header.sectionSize(section_index))

        return {
            'header_sizes': header_sizes,
            'search_text': self.search_bar.text()
        }

    def load_state(self, state):
        header = self.table_view.horizontalHeader()
        for section_index, size in enumerate(state['header_sizes']):
            header.resizeSection(section_index, size)

        self.search_bar.setText(state['search_text'])
예제 #22
0
class UIVariable(QWidget, IPropertiesViewSupport):
    def __init__(self, rawVariable, variablesWidget, parent=None):
        super(UIVariable, self).__init__(parent)
        self._rawVariable = rawVariable
        self.variablesWidget = variablesWidget
        # ui
        self.horizontalLayout = QHBoxLayout(self)
        self.horizontalLayout.setSpacing(1)
        self.horizontalLayout.setContentsMargins(1, 1, 1, 1)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.widget = TypeWidget(
            findPinClassByType(self._rawVariable.dataType).color(), self)
        self.widget.setObjectName("widget")
        self.horizontalLayout.addWidget(self.widget)
        self.labelName = QLabel(self)
        self.labelName.setStyleSheet("background:transparent")
        self.labelName.setObjectName("labelName")
        self.horizontalLayout.addWidget(self.labelName)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        # find refs
        self.pbFindRefs = QPushButton("")
        self.pbFindRefs.setIcon(
            QtGui.QIcon(":/searching-magnifying-glass.png"))
        self.pbFindRefs.setObjectName("pbFindRefs")
        self.horizontalLayout.addWidget(self.pbFindRefs)
        self.pbFindRefs.clicked.connect(self.onFindRefsClicked)
        #  kill variable
        self.pbKill = QPushButton("")
        self.pbKill.setIcon(QtGui.QIcon(":/delete_icon.png"))
        self.pbKill.setObjectName("pbKill")
        self.horizontalLayout.addWidget(self.pbKill)
        self.pbKill.clicked.connect(self.onKillClicked)

        QtCore.QMetaObject.connectSlotsByName(self)
        self.setName(self._rawVariable.name)
        self._rawVariable.setWrapper(self)

    def onStructureChanged(self, name):
        self._rawVariable.structure = PinStructure[name]
        self.variablesWidget.pyFlowInstance.onRequestFillProperties(
            self.createPropertiesWidget)
        EditorHistory().saveState("Change variable struct", modify=True)

    def setDataType(self, dataType):
        self.dataType = dataType
        self._rawVariable.dataType = dataType
        EditorHistory().saveState("Change variable data type", modify=True)

    def createPropertiesWidget(self, propertiesWidget):
        baseCategory = CollapsibleFormWidget(headName="Base", modify=True)
        # name
        le_name = QLineEdit(self._rawVariable.name)
        le_name.returnPressed.connect(lambda: self.setName(le_name.text()))
        baseCategory.addWidget("Name", le_name)

        # data type
        cbTypes = EnumComboBox([
            pin.__name__ for pin in getAllPinClasses() if pin.IsValuePin()
            if pin.__name__ != "AnyPin"
        ])
        cbTypes.setCurrentIndex(cbTypes.findText(self.dataType))
        cbTypes.setEditable(False)
        cbTypes.changeCallback.connect(self.setDataType)
        propertiesWidget.addWidget(baseCategory)

        # structure type
        cbStructure = EnumComboBox(
            [i.name for i in (PinStructure.Single, PinStructure.Array)])
        cbStructure.setEditable(False)
        cbStructure.setCurrentIndex(
            cbStructure.findText(self._rawVariable.structure.name))
        cbStructure.changeCallback.connect(self.onStructureChanged)
        propertiesWidget.addWidget(baseCategory)
        baseCategory.addWidget("Type", cbTypes)
        baseCategory.addWidget("Structure", cbStructure)

        valueCategory = CollapsibleFormWidget(headName="Value")

        # current value
        if self._rawVariable.structure == PinStructure.Single:
            if not type(self._rawVariable.value) in {list, set, dict, tuple}:

                def valSetter(x):
                    self._rawVariable.value = x

                w = createInputWidget(
                    self._rawVariable.dataType, valSetter,
                    getPinDefaultValueByType(self._rawVariable.dataType))
                if w:
                    w.setWidgetValue(self._rawVariable.value)
                    w.setObjectName(self._rawVariable.name)
                    valueCategory.addWidget(self._rawVariable.name, w)

        # access level
        cb = QComboBox()
        cb.addItem('public', 0)
        cb.addItem('private', 1)
        cb.addItem('protected', 2)

        def accessLevelChanged(x):
            self._rawVariable.accessLevel = AccessLevel[x]
            EditorHistory().saveState("Change variable access level",
                                      modify=True)

        cb.currentTextChanged.connect(accessLevelChanged)
        cb.setCurrentIndex(self._rawVariable.accessLevel)
        valueCategory.addWidget('Access level', cb)
        propertiesWidget.addWidget(valueCategory)

    def onFindRefsClicked(self):
        from PyFlow.App import PyFlow
        refs = [n.getWrapper() for n in self._rawVariable.findRefs()]
        app = self.variablesWidget.pyFlowInstance
        if "Search results" not in [
                t.name() for t in app.getRegisteredTools()
        ]:
            app.invokeDockToolByName("PyFlowBase", "Search results")
        self.variablesWidget.pyFlowInstance.getCanvas(
        ).requestShowSearchResults.emit(refs)

    def onKillClicked(self):
        # check refs and ask user what to do
        refs = self._rawVariable.findRefs()
        if len(refs) > 0:
            item, accepted = QInputDialog.getItem(
                None,
                'Decide!',
                'What to do with getters and setters in canvas?',
                ['kill', 'leave'],
                editable=False)
            if accepted:
                self.variablesWidget.killVar(self)
                if item == 'kill':
                    for i in refs:
                        i.kill()
                elif item == 'leave':
                    for i in refs:
                        i.var = None
        else:
            self.variablesWidget.killVar(self)

    @property
    def dataType(self):
        return self._rawVariable.dataType

    @dataType.setter
    def dataType(self, value):
        self._rawVariable.dataType = value
        self.widget.color = findPinClassByType(
            self._rawVariable.dataType).color()
        self.widget.update()
        self.variablesWidget.onUpdatePropertyView(self)

    @property
    def packageName(self):
        return self._rawVariable.packageName

    @property
    def accessLevel(self):
        return self._rawVariable.accessLevel

    @accessLevel.setter
    def accessLevel(self, value):
        self._rawVariable.accessLevel = value

    @property
    def uid(self):
        return self._rawVariable.uid

    @uid.setter
    def uid(self, value):
        self._rawVariable.uid = value
        if self._rawVariable.uid in self.graph.getVars():
            self.graph.getVars().pop(self._rawVariable.uid)
            self.graph.getVars()[self._rawVariable.uid] = self._rawVariable

    @staticmethod
    def jsonTemplate():
        template = {
            'name': None,
            'uuid': None,
            'value': None,
            'type': None,
            'package': None,
            'accessLevel': None
        }
        return template

    def serialize(self):
        pinClass = findPinClassByType(self._rawVariable.dataType)

        template = UIVariable.jsonTemplate()
        template['name'] = self._rawVariable.name
        template['uuid'] = str(self._rawVariable.uid)

        if self._rawVariable.dataType == "AnyPin":
            # don't save any variables
            # value will be calculated for this type of variables
            template['value'] = None
        else:
            template['value'] = json.dumps(self._rawVariable.value,
                                           cls=pinClass.jsonEncoderClass())

        template['type'] = self._rawVariable.dataType
        template['package'] = self._rawVariable.packageName
        template['accessLevel'] = self._rawVariable.accessLevel.value
        return template

    @staticmethod
    def deserialize(data, graph):
        pinClass = findPinClassByType(data['dataType'])

        varUid = uuid.UUID(data['uuid'])
        var = graph.getApp().variablesWidget.createVariable(
            dataType=data['dataType'],
            accessLevel=AccessLevel(data['accessLevel']),
            uid=varUid)
        var.setName(data['name'])
        var.setDataType(data['dataType'])

        if data['dataType'] == 'AnyPin':
            var.value = getPinDefaultValueByType('AnyPin')
        else:
            var.value = json.loads(data['value'],
                                   cls=pinClass.jsonDecoderClass())

        return var

    @property
    def value(self):
        return self._rawVariable.value

    @value.setter
    def value(self, data):
        self._rawVariable.value = data

    def mousePressEvent(self, event):
        super(UIVariable, self).mousePressEvent(event)
        self.variablesWidget.onUpdatePropertyView(self)

    def setName(self, name):
        self._rawVariable.name = name
        self.labelName.setText(self._rawVariable.name)
예제 #23
0
class BaseSaveWidget(base.BaseWidget, object):
    def __init__(self, item, settings, temp_path=None, parent=None):

        # self._item = None
        self._settings = settings
        self._temp_path = temp_path
        self._options_widget = None

        # super(BaseSaveWidget, self).__init__(parent=parent)
        #
        # self.setObjectName('LibrarySaveWidget')
        # self.set_item(item)

    def ui(self):
        super(BaseSaveWidget, self).ui()

        title_layout = layouts.HorizontalLayout()
        title_layout.setContentsMargins(2, 2, 0, 0)
        title_layout.setSpacing(2)
        self._icon_lbl = QLabel()
        self._icon_lbl.setMaximumSize(QSize(14, 14))
        self._icon_lbl.setMinimumSize(QSize(14, 14))
        self._icon_lbl.setScaledContents(True)
        self._title_lbl = QLabel()
        title_layout.addWidget(self._icon_lbl)
        title_layout.addWidget(self._title_lbl)

        self._folder_widget = directory.SelectFolder('Folder',
                                                     use_app_browser=True)

        buttons_layout = layouts.HorizontalLayout()
        buttons_layout.setContentsMargins(4, 4, 4, 4)
        buttons_layout.setSpacing(4)
        buttons_frame = QFrame()
        buttons_frame.setFrameShape(QFrame.NoFrame)
        buttons_frame.setFrameShadow(QFrame.Plain)
        buttons_frame.setLayout(buttons_layout)
        buttons_layout.addStretch()
        self.save_btn = buttons.BaseButton('Save')
        self.cancel_btn = buttons.BaseButton('Cancel')
        buttons_layout.addWidget(self.save_btn, parent=self)
        buttons_layout.addWidget(self.cancel_btn, parent=self)
        buttons_layout.addStretch()

        self._options_layout = layouts.VerticalLayout()
        self._options_layout.setContentsMargins(0, 0, 0, 0)
        self._options_layout.setSpacing(2)
        self._options_frame = QFrame()
        self._options_frame.setFrameShape(QFrame.NoFrame)
        self._options_frame.setFrameShadow(QFrame.Plain)
        self._options_frame.setLineWidth(0)
        self._options_frame.setLayout(self._options_layout)

        self._extra_layout = layouts.VerticalLayout()
        self._extra_layout.setContentsMargins(0, 0, 0, 0)
        self._extra_layout.setSpacing(2)

        self.main_layout.addLayout(title_layout)
        self.main_layout.addWidget(self._folder_widget)
        self._extra_layout.addWidget(self._options_frame)
        self.main_layout.addWidget(dividers.Divider())
        self.main_layout.addLayout(self._extra_layout)
        self.main_layout.addWidget(dividers.Divider())
        self.main_layout.addWidget(buttons_frame)

    def setup_signals(self):
        self.save_btn.clicked.connect(self._on_save)
        self.cancel_btn.clicked.connect(self._on_cancel)

    def settings(self):
        """
        Returns settings object
        :return: JSONSettings
        """

        return self._settings

    def set_settings(self, settings):
        """
        Sets save widget settings
        :param settings: JSONSettings
        """

        self._settings = settings

    # def item(self):
    #     """
    #     Returns the library item to be created
    #     :return: LibraryItem
    #     """
    #
    #     return self._item

    def set_item(self, item):
        """
        Sets the base item to be created
        :param item: LibraryItem
        """

        self._item = item

        self._title_lbl.setText(item.MenuName)
        self._icon_lbl.setPixmap(QPixmap(item.type_icon_path()))
        schema = item.save_schema()
        if schema:
            options_widget = formwidget.FormWidget(self)
            options_widget.set_schema(schema)
            options_widget.set_validator(item.save_validator)
            self._options_frame.layout().addWidget(options_widget)
            self._options_widget = options_widget
            self.load_settings()
            options_widget.stateChanged.connect(self._on_options_changed)
            options_widget.validate()
        else:
            self._options_frame.setVisible(False)

    def library_window(self):
        """
        Returns library widget window for the item
        :return: LibraryWindow
        """

        return self._item.library_window()

    def set_library_window(self, library_window):
        """
        Sets the library widget for the item
        :param library_window: LibraryWindow
        """

        self._item.set_library_window(library_window)

    def name(self):
        """
        Returns the name of the field
        :return: str
        """

        return self._title_lbl.text().strip()

    def description(self):
        """
        Returns the string from the comment field
        :return: str
        """

        return self._comment.toPlainText().strip()

    def folder_frame(self):
        """
        Returns the frame that contains the folder edit, label and button
        :return: QFrame
        """

        return self._folder_frame

    def folder_path(self):
        """
        Returns the folder path
        :return: str
        """

        return self._folder_widget.folder_line.text()

    def set_folder_path(self, path):
        """
        Sets the destination folder path
        :param path: str
        """

        self._folder_widget.folder_line.setText(path)

    def default_values(self):
        """
        Returns all the default values for the save fields
        :return: dict
        """

        values = dict()
        for option in self.item().save_schema():
            values[option.get('name')] = option.get('default')

        return values

    def save_settings(self):
        """
        Saves the current state of the widget to disk
        """

        state = self._options_widget.options_state()
        self.settings().set(self.item().__class__.__name__,
                            {'SaveOptions': state})

    def load_settings(self):
        """
        Returns the settings object for saving the state of the widget
        """

        option_settings = self.settings().get(self.item().__class__.__name__,
                                              {})
        options = option_settings.get('SaveOptions', dict())
        values = self.default_values()
        if options:
            for option in self.item().save_schema():
                name = option.get('name')
                persistent = option.get('persistent')
                if not persistent and name in options:
                    options[name] = values[name]
            self._options_widget.set_state_from_options(options)

    def save(self, path, icon_path, objects=None):
        """
        Saves the item with the given objects to the given disk location path
        :param path: list(str)
        :param icon_path: str
        :param objects: str
        """

        item = self.item()
        options = self._options_widget.values()

        item.save(path=path, objects=objects, icon_path=icon_path, **options)

        self.close()

    def _save(self):
        if not self.library_window():
            return

        try:
            path = self.folder_path()
            options = self._options_widget.values()
            name = options.get('name')
            objects = dcc.selected_nodes(full_path=True) or list()
            if not path:
                raise Exception(
                    'No folder selected. Please select a destination folder')
            if not name:
                raise Exception(
                    'No name specified. Please set a name before saving')

            if not os.path.exists(self.icon_path()):
                btn = self.show_thumbnail_capture_dialog()
                if btn == QDialogButtonBox.Cancel:
                    return

            path += '/{}'.format(name)
            icon_path = self.icon_path()

            self.save(path=path, icon_path=icon_path, objects=objects)

        except Exception as e:
            messagebox.MessageBox.critical(self.library_window(),
                                           'Error while saving', str(e))
            LOGGER.error(traceback.format_exc())
            raise

        self.library_window().stack.slide_in_index(0)

    def _on_options_changed(self):
        """
        Internal callback function that is called when an option value changes
        """

        self.save_settings()

    def _on_save(self):
        if not self.library_window():
            return

        self._save()

        self.library_window().stack.slide_in_index(0)

    def _on_cancel(self):
        self.close()
        self.library_window().stack.slide_in_index(0)