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
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()
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