Beispiel #1
0
def show_text(txt,
              parent,
              type_text: bool = False,
              run: bool = True,
              min_width: int = 500,
              min_height: int = 400,
              title: str = APP_NAME_SHORT,
              copy_btn: bool = False,
              send_issue: bool = False):
    diag = QDialog(parent)
    diag.setWindowTitle(title)
    layout = QVBoxLayout(diag)
    diag.setLayout(layout)
    text = QTextBrowser()
    text.setOpenExternalLinks(True)
    if type_text:
        text.setPlainText(txt)
    else:
        text.setHtml(txt)
    layout.addWidget(text)
    box = QDialogButtonBox(QDialogButtonBox.Close)
    layout.addWidget(box)
    if copy_btn:

        def onCopy():
            QApplication.clipboard().setText(text.toPlainText())

        btn = QPushButton("Copy to Clipboard")
        btn.clicked.connect(onCopy)
        box.addButton(btn, QDialogButtonBox.ActionRole)

    if send_issue:

        def on_send():
            title = 'An error occurred'
            body = text.toPlainText()
            IssueReporter().sent_report(title, body)

        btn = QPushButton("Report Issue")
        btn.clicked.connect(on_send)
        box.addButton(btn, QDialogButtonBox.ActionRole)

    def onReject():
        QDialog.reject(diag)

    box.rejected.connect(onReject)
    diag.setMinimumHeight(min_height)
    diag.setMinimumWidth(min_width)
    if run:
        diag.exec_()
    else:
        return diag
Beispiel #2
0
class MainWindow(Ui_MainWindow, QMainWindow):
    def __init__(self, instrument: Instrument, nx_classes: Dict):
        super().__init__()
        self.instrument = instrument
        self.nx_classes = nx_classes

    def setupUi(self, main_window):
        super().setupUi(main_window)

        self.export_to_nexus_file_action.triggered.connect(
            self.save_to_nexus_file)
        self.open_nexus_file_action.triggered.connect(self.open_nexus_file)
        self.open_json_file_action.triggered.connect(self.open_json_file)
        self.open_idf_file_action.triggered.connect(self.open_idf_file)
        self.export_to_filewriter_JSON_action.triggered.connect(
            self.save_to_filewriter_json)
        self.export_to_forwarder_JSON_action.triggered.connect(
            self.save_to_forwarder_json)

        # Clear the 3d view when closed
        QApplication.instance().aboutToQuit.connect(self.sceneWidget.delete)

        self.widget = silx.gui.hdf5.Hdf5TreeView()
        self.widget.setAcceptDrops(True)
        self.widget.setDragEnabled(True)
        self.treemodel = self.widget.findHdf5TreeModel()
        self.treemodel.setDatasetDragEnabled(True)
        self.treemodel.setFileDropEnabled(True)
        self.treemodel.setFileMoveEnabled(True)
        self.treemodel.insertH5pyObject(self.instrument.nexus.nexus_file)
        self.instrument.nexus.file_changed.connect(
            self.update_nexus_file_structure_view)
        self.silx_tab_layout.addWidget(self.widget)
        self.instrument.nexus.show_entries_dialog.connect(
            self.show_entries_dialog)

        self.instrument.nexus.component_added.connect(
            self.sceneWidget.add_component)
        self.instrument.nexus.component_removed.connect(
            self.sceneWidget.delete_component)
        self.component_tree_view_tab.set_up_model(self.instrument)
        self.instrument.nexus.transformation_changed.connect(
            self._update_transformations_3d_view)

        self.widget.setVisible(True)

        self._set_up_file_writer_control_window(main_window)
        self.file_writer_control_window = None

    def _set_up_file_writer_control_window(self, main_window):
        try:
            import confluent_kafka  # noqa: F401

            self.control_file_writer_action = QAction(main_window)
            self.control_file_writer_action.setText("Control file-writer")
            self.file_menu.addAction(self.control_file_writer_action)
            self.control_file_writer_action.triggered.connect(
                self.show_control_file_writer_window)
        except ImportError:
            pass

    def show_control_file_writer_window(self):
        if self.file_writer_control_window is None:
            from nexus_constructor.file_writer_ctrl_window import FileWriterCtrl

            self.file_writer_ctrl_window = FileWriterCtrl(
                self.instrument, QSettings("ess", "nexus-constructor"))
            self.file_writer_ctrl_window.show()

    def show_edit_component_dialog(self):
        selected_component = self.component_tree_view_tab.component_tree_view.selectedIndexes(
        )[0].internalPointer()
        self.show_add_component_window(selected_component)

    def show_entries_dialog(self, map_of_entries: dict, nexus_file: h5py.File):
        """
        Shows the entries dialog when loading a nexus file if there are multiple entries.
        :param map_of_entries: A map of the entry groups, with the key being the name of the group and value being the actual h5py group object.
        :param nexus_file: A reference to the nexus file.
        """
        self.entries_dialog = QDialog()
        self.entries_dialog.setMinimumWidth(400)
        self.entries_dialog.setWindowTitle(
            "Multiple Entries found. Please choose the entry name from the list."
        )
        combo = QComboBox()

        # Populate the combo box with the names of the entry groups.
        [combo.addItem(x) for x in map_of_entries.keys()]
        ok_button = QPushButton()

        ok_button.setText("OK")
        ok_button.clicked.connect(self.entries_dialog.close)

        def _load_current_entry():
            self.instrument.nexus.load_file(
                map_of_entries[combo.currentText()], nexus_file)
            self._update_views()

        # Connect the clicked signal of the ok_button to instrument.load_file and pass the file and entry group object.
        ok_button.clicked.connect(_load_current_entry)

        self.entries_dialog.setLayout(QGridLayout())

        self.entries_dialog.layout().addWidget(QLabel("Entry:"))
        self.entries_dialog.layout().addWidget(combo)
        self.entries_dialog.layout().addWidget(ok_button)
        self.entries_dialog.show()

    def update_nexus_file_structure_view(self, nexus_file):
        self.treemodel.clear()
        self.treemodel.insertH5pyObject(nexus_file)

    def save_to_nexus_file(self):
        filename = file_dialog(True, "Save Nexus File", NEXUS_FILE_TYPES)
        self.instrument.nexus.save_file(filename)

    def open_idf_file(self):
        filename = file_dialog(False, "Open IDF file", {"IDF files": ["xml"]})
        self._load_idf(filename)

    def _load_idf(self, filename):
        try:
            builder = NexusBuilder(
                str(uuid.uuid4()),
                idf_file=filename,
                file_in_memory=True,
                nx_entry_name="entry",
            )
            builder.add_instrument_geometry_from_idf()
            self.instrument.nexus.load_nexus_file(builder.target_file)
            self._update_views()
            QMessageBox.warning(
                self,
                "Mantid IDF loaded",
                "Please manually check the instrument for accuracy.",
            )
        except Exception:
            QMessageBox.critical(self, "IDF Error",
                                 "Error whilst loading IDF file")

    def save_to_filewriter_json(self):
        filename = file_dialog(True, "Save Filewriter JSON File",
                               JSON_FILE_TYPES)
        if filename:
            with open(filename, "w") as file:
                filewriter_json_writer.write_nexus_structure_to_json(
                    self.instrument, file)

    def save_to_forwarder_json(self):
        filename = file_dialog(True, "Save Forwarder JSON File",
                               JSON_FILE_TYPES)
        if filename:
            provider_type, ok_pressed = QInputDialog.getItem(
                None,
                "Provider type",
                "Select provider type for PVs",
                ["ca", "pva"],
                0,
                False,
            )
            default_broker, ok_pressed = QInputDialog.getText(
                None,
                "Default broker",
                "Default Broker: (This will only be used for streams that do not already have a broker)",
                text="broker:port",
                echo=QLineEdit.Normal,
            )
            if ok_pressed:
                with open(filename, "w") as file:
                    nexus_constructor.json.forwarder_json_writer.generate_forwarder_command(
                        file,
                        self.instrument.nexus.entry,
                        provider_type=provider_type,
                        default_broker=default_broker,
                    )

    def open_nexus_file(self):
        filename = file_dialog(False, "Open Nexus File", NEXUS_FILE_TYPES)
        existing_file = self.instrument.nexus.nexus_file
        if self.instrument.nexus.open_file(filename):
            self._update_views()
            existing_file.close()

    def open_json_file(self):
        filename = file_dialog(False, "Open File Writer JSON File",
                               JSON_FILE_TYPES)
        if filename:
            with open(filename, "r") as json_file:
                json_data = json_file.read()

                try:
                    nexus_file = json_to_nexus(json_data)
                except Exception as exception:
                    show_warning_dialog(
                        "Provided file not recognised as valid JSON",
                        "Invalid JSON",
                        f"{exception}",
                        parent=self,
                    )
                    return

                existing_file = self.instrument.nexus.nexus_file
                if self.instrument.nexus.load_nexus_file(nexus_file):
                    self._update_views()
                    existing_file.close()

    def _update_transformations_3d_view(self):
        self.sceneWidget.clear_all_transformations()
        for component in self.instrument.get_component_list():
            if component.name != "sample":
                self.sceneWidget.add_transformation(component.name,
                                                    component.transform)

    def _update_views(self):
        self.sceneWidget.clear_all_transformations()
        self.sceneWidget.clear_all_components()
        self.component_tree_view_tab.set_up_model(self.instrument)
        self._update_3d_view_with_component_shapes()

    def _update_3d_view_with_component_shapes(self):
        for component in self.instrument.get_component_list():
            shape, positions = component.shape
            self.sceneWidget.add_component(component.name, shape, positions)
            self.sceneWidget.add_transformation(component.name,
                                                component.transform)

    def show_add_component_window(self, component: Component = None):
        self.add_component_window = QDialog()
        self.add_component_window.ui = AddComponentDialog(
            self.instrument,
            self.component_tree_view_tab.component_model,
            component,
            nx_classes=self.nx_classes,
            parent=self,
        )
        self.add_component_window.ui.setupUi(self.add_component_window)
        self.add_component_window.show()
Beispiel #3
0
    def executeProject(self, mainWindow, project_name):
        if project_name == "SmartGroceries":
            self.referenceItemsLabels = {}
            self.itemInHand = None
            self.itemsInCart = list()
            self.currentOrderReferenceItems = list()
            self.currentOrderUserId = 0
            self.recommendedItemsButtons = list()
            self.previousRecommendations = list()
            self.numberOfGoodRecommendations = 0
            self.supportedUsers = range(1, 1001)

            products = pd.read_csv(
                os.path.join(
                    os.path.dirname(os.path.dirname(
                        os.path.abspath(__file__))), "projects",
                    "SmartGroceries", "data", "products.csv"))
            aisles = pd.read_csv(
                os.path.join(
                    os.path.dirname(os.path.dirname(
                        os.path.abspath(__file__))), "projects",
                    "SmartGroceries", "data", "aisles.csv"))
            test_data = pd.read_csv(
                os.path.join(
                    os.path.dirname(os.path.dirname(
                        os.path.abspath(__file__))), "projects",
                    "SmartGroceries", "data", "test_set.csv"))
            # print(products)
            # print(aisles)
            # print(test_data)
            aisle_name_to_id = {
                k: v
                for k, v in zip(aisles.aisle, aisles.aisle_id)
            }
            product_name_to_id = {
                k: v
                for k, v in zip(products.product_name, products.product_id)
            }
            product_id_to_name = {
                k: v
                for k, v in zip(products.product_id, products.product_name)
            }

            def changeCurrentitem(itemName):
                if itemName == "":
                    self.itemInHand = None
                    currentItemLabel.setText(
                        f"<b>Select an item from the list or from the recommendations</b>s"
                    )
                    addToCartButton.setEnabled(False)
                else:
                    self.itemInHand = product_name_to_id[itemName]
                    currentItemLabel.setText(f"Add <b>{itemName}</b> to Cart")
                    addToCartButton.setEnabled(True)
                    addToCartButton.setFocus()

            def handleNewOrderButtonClicked():
                grouped = test_data.groupby('order_id')
                while True:
                    order_number = random.sample(grouped.indices.keys(), 1)[0]
                    currentOrder = grouped.get_group(order_number)
                    self.currentOrderReferenceItems = currentOrder.product_id.tolist(
                    )
                    self.currentOrderUserId = currentOrder.user_id.iloc[0]
                    if len(
                            self.currentOrderReferenceItems
                    ) > 1 and self.currentOrderUserId in self.supportedUsers:
                        break
                print(self.currentOrderReferenceItems)
                orderInfo = f"<b>Order ID: </b>{currentOrder.order_id.iloc[0]}<br>"
                orderInfo += f"<b>User ID: </b>{self.currentOrderUserId} | <b>DOW: </b>{calendar.day_name[currentOrder.order_dow.iloc[0]]} | <b>Hour of Day: </b>{currentOrder.order_hour_of_day.iloc[0]}  | <b>Number of Items: </b>{len(self.currentOrderReferenceItems)}"
                orderInfo += "<br><b>Items in the Reference Order:</b>"

                for widget in self.referenceItemsLabels.values():
                    item = referenceItemsLayout.itemAt(0)
                    widget.setVisible(False)
                    referenceItemsLayout.removeItem(item)
                    del item
                self.referenceItemsLabels.clear()
                currentCartItems.clear()
                self.itemsInCart.clear()
                self.previousRecommendations.clear()
                self.numberOfGoodRecommendations = 0

                updateCurrentRecommendations(list())
                for product in self.currentOrderReferenceItems:
                    refItemName = product_id_to_name[product]
                    refItemLabel = QPushButton(refItemName)
                    refItemLabel.setContentsMargins(QMargins(0, 0, 0, 0))
                    refItemLabel.setStyleSheet("Text-align:left")
                    refItemLabel.setFlat(False)
                    refItemLabel.clicked.connect(
                        partial(changeCurrentitem, refItemName))
                    self.referenceItemsLabels[product] = refItemLabel
                    orderInfoLabel.setText(
                        f"<b>Order Information</b><br>{orderInfo}")

                for referenceItemLabel in self.referenceItemsLabels.values():
                    referenceItemsLayout.addWidget(referenceItemLabel)

                runAutoButton.setFocus()

            def handleRunAutomatically():
                for referenceItemLabel in self.referenceItemsLabels.values():
                    referenceItemLabel.click()
                    addToCartButton.click()

            def updateCurrentRecommendations(recommendations):
                for widget in self.recommendedItemsButtons:
                    item = recommendationsLayout.itemAt(0)
                    widget.setVisible(False)
                    recommendationsLayout.removeItem(item)
                    del item
                self.recommendedItemsButtons.clear()
                for product in recommendations:
                    recItemName = product_id_to_name[product]
                    recItemButton = QPushButton(recItemName)
                    recItemButton.setContentsMargins(QMargins(0, 0, 0, 0))
                    recItemButton.setStyleSheet("Text-align:left;")
                    if product not in self.currentOrderReferenceItems:
                        recItemButton.setFlat(True)
                    recItemButton.clicked.connect(
                        partial(changeCurrentitem, recItemName))
                    self.recommendedItemsButtons.append(recItemButton)
                for recItemButton in self.recommendedItemsButtons:
                    recommendationsLayout.addWidget(recItemButton)
                if len(recommendations) > 0:
                    currentRecommendationsLabel.setVisible(True)
                else:
                    currentRecommendationsLabel.setVisible(False)
                self.previousRecommendations += recommendations

            def handleAddToCartButtonClicked():
                print(self.currentOrderReferenceItems)
                print(self.itemInHand)
                if self.itemInHand not in self.currentOrderReferenceItems:
                    QMessageBox(
                        QMessageBox.Critical, "Error adding item to cart",
                        "You can only add items that exists in the reference order"
                    ).exec_()
                    return
                elif self.itemInHand in self.itemsInCart:
                    QMessageBox(QMessageBox.Critical,
                                "Error adding item to cart",
                                "This item is already in the cart").exec_()
                    return
                self.referenceItemsLabels[self.itemInHand].setFlat(True)
                self.itemsInCart.append(self.itemInHand)
                currentCartItems.addItem(product_id_to_name[self.itemInHand])
                if self.itemInHand in self.previousRecommendations:
                    self.numberOfGoodRecommendations += 1
                    self.referenceItemsLabels[self.itemInHand].setStyleSheet(
                        "Text-align:left; background-color:green;")
                    self.referenceItemsLabels[self.itemInHand].setFlat(False)

                #update recommendations
                result = self._sendCommand(
                    "PROCESS_PROJECT_GROUP_2", ";".join([
                        str(self.currentOrderUserId),
                        ",".join([str(x) for x in self.itemsInCart]),
                        ",".join([
                            str(x) for x in set(self.previousRecommendations)
                        ])
                    ]))
                if result == FAILURE_CODE:
                    self.log(
                        "Processing Failed, error getting recommendations from the RPi"
                    )
                    return
                else:
                    try:
                        recommendations = [int(id) for id in result.split(',')]
                    except:
                        recommendations = []

                updateCurrentRecommendations(recommendations)
                if len(self.itemsInCart) == len(
                        self.currentOrderReferenceItems):
                    completionMessage = QMessageBox(
                        QMessageBox.Information, "Order Completed",
                        f"Order Completed with {self.numberOfGoodRecommendations} Good Recommendation(s)\nPress New Order to start a new order"
                    )
                    if self.numberOfGoodRecommendations == 0:
                        completionMessage.setIconPixmap(
                            QPixmap('images/this_is_fine.jpg'))
                    completionMessage.setWindowIcon(appIcon)
                    completionMessage.exec_()
                    newOrderButton.setFocus()

            def aisleChanged():
                aisle_number = aisle_name_to_id[
                    selectAisleCombobox.currentText()]
                products_in_aisle = products[
                    products.aisle_id == aisle_number].product_name.tolist()
                selectproductCombobox.clear()
                selectproductCombobox.addItem("")
                selectproductCombobox.addItems(products_in_aisle)

            def itemChanged():
                current_item = selectproductCombobox.currentText()
                changeCurrentitem(current_item)

            dialog = QDialog(mainWindow)
            appIcon = QIcon("images/this_is_fine.jpg")
            dialog.setWindowIcon(appIcon)
            dialog.setMinimumWidth(600)
            dialog.setWindowTitle("Smart Groceries Demo")
            layout = QVBoxLayout()
            newOrderButton = QPushButton("New Order")
            orderInfoLabel = QLabel()
            orderInfoLabel.setTextFormat(Qt.RichText)
            chooseItemLayout = QHBoxLayout()
            verticalSpacer = QSpacerItem(20, 20)
            currentCartItems = QListWidget()

            layoutWidget = QWidget()
            referenceItemsLayout = QVBoxLayout(layoutWidget)
            referenceItemsLayout.setSpacing(0)
            referenceItemsLayout.setMargin(0)
            scroll = QScrollArea(dialog)
            scroll.setWidgetResizable(True)
            scroll.setMinimumHeight(150)
            scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
            scroll.setWidget(layoutWidget)

            selectAisleLabel = QLabel("Aisle: ")
            selectProductLabel = QLabel("Product: ")
            selectAisleCombobox = QComboBox()
            selectproductCombobox = QComboBox()
            chooseItemLayout.addWidget(selectAisleLabel, 0, Qt.AlignLeft)
            chooseItemLayout.addWidget(selectAisleCombobox, 0, Qt.AlignLeft)
            chooseItemLayout.addWidget(selectProductLabel, 0, Qt.AlignLeft)
            chooseItemLayout.addWidget(selectproductCombobox, 0, Qt.AlignLeft)

            addToCartButton = QPushButton("Add to Cart")
            currentItemLabel = QLabel()
            currentItemLabel.setTextFormat(Qt.RichText)
            if self.itemInHand is None:
                currentItemLabel.setText(
                    f"<b>Select an item from the list or from the recommendations</b>"
                )
            addToCartButton.setDisabled(True)
            currentItemLayout = QHBoxLayout()
            currentItemLayout.addWidget(currentItemLabel)
            currentItemLayout.addWidget(addToCartButton)
            recommendationsLayout = QVBoxLayout()
            recommendationsLayout.setSpacing(0)
            recommendationsLayout.setMargin(0)

            newOrderButton.clicked.connect(handleNewOrderButtonClicked)
            addToCartButton.clicked.connect(handleAddToCartButtonClicked)
            selectproductCombobox.currentIndexChanged.connect(itemChanged)
            selectAisleCombobox.currentIndexChanged.connect(aisleChanged)
            selectAisleCombobox.addItems(aisles.aisle.tolist())

            layout.addWidget(newOrderButton)
            layout.addSpacerItem(verticalSpacer)
            layout.addWidget(orderInfoLabel)
            layout.addWidget(scroll)
            layout.addSpacerItem(verticalSpacer)
            layout.addLayout(chooseItemLayout)
            layout.addSpacerItem(verticalSpacer)
            itemsInTheCartLabel = QLabel("<b>Items in the Cart<b>")
            layout.addWidget(itemsInTheCartLabel)
            itemsInTheCartLabel.setTextFormat(Qt.RichText)
            layout.addWidget(currentCartItems)
            layout.addSpacerItem(verticalSpacer)
            currentRecommendationsLabel = QLabel(
                "<b>Current Recommendations<b>")
            layout.addWidget(currentRecommendationsLabel)
            currentRecommendationsLabel.setTextFormat(Qt.RichText)
            currentRecommendationsLabel.setVisible(False)
            layout.addLayout(recommendationsLayout)
            layout.addSpacerItem(verticalSpacer)
            layout.addLayout(currentItemLayout)
            runAutoButton = QPushButton("Run and Watch. TRUST ME, IT IS FUN!")
            layout.addWidget(runAutoButton)
            runAutoButton.clicked.connect(handleRunAutomatically)
            dialog.setLayout(layout)
            handleNewOrderButtonClicked()
            dialog.exec_()
            return