diff --git a/mslib/msui/mscolab.py b/mslib/msui/mscolab.py index 2c59ace2d..95b7be246 100644 --- a/mslib/msui/mscolab.py +++ b/mslib/msui/mscolab.py @@ -577,6 +577,8 @@ def __init__(self, parent=None, data_dir=None): else: self.data_dir = data_dir self.create_dir() + # Variable to store filtered operations + self.filtered_operations = [] def view_description(self): data = { @@ -1383,6 +1385,41 @@ def operation_category_handler(self, update_operations=True): else: self.add_operations_to_ui() + def apply_regex_filter(self): + + """ + Filters the operations list based on a regex pattern provided by the user. + """ + pattern = self.ui.regexFilterLe.text() + if not pattern: + # If no pattern, reset to show all operations + self.filtered_operations = self.operations + else: + try: + regex = re.compile(pattern) + self.filtered_operations = [op for op in self.operations if regex.search(op['path'])] + except re.error: + show_popup(self.ui, "Error", "Invalid regex pattern!", icon=2) + self.filtered_operations = self.operations + + # Update the UI with the filtered operations + self.display_operations(self.filtered_operations) + + def display_operations(self, operations): + """ + Displays the given list of operations in the UI. + """ + self.ui.listOperationsMSC.clear() + for operation in operations: + operation_desc = f'{operation["path"]} - {operation["access_level"]}' + widgetItem = QtWidgets.QListWidgetItem(operation_desc) + widgetItem.op_id = operation["op_id"] + widgetItem.operation_category = operation["category"] + widgetItem.operation_path = operation["path"] + widgetItem.access_level = operation["access_level"] + widgetItem.active_operation_description = operation["description"] + self.ui.listOperationsMSC.addItem(widgetItem) + def server_options_handler(self, index): selected_option = self.ui.serverOptionsCb.currentText() self.ui.serverOptionsCb.blockSignals(True) diff --git a/mslib/msui/msui_mainwindow.py b/mslib/msui/msui_mainwindow.py index f1ec9768b..3a1501efc 100644 --- a/mslib/msui/msui_mainwindow.py +++ b/mslib/msui/msui_mainwindow.py @@ -466,6 +466,9 @@ def __init__(self, mscolab_data_dir=None, tutorial_mode=False, *args): self.actionSaveActiveFlightTrackAs.triggered.connect(self.save_as_handler) self.actionCloseSelectedFlightTrack.triggered.connect(self.close_selected_flight_track) + # regex filter + self.regexFilterLe.textChanged.connect(self.apply_filter) + # Views menu. self.actionTopView.triggered.connect(functools.partial(self.create_view_handler, "topview")) self.actionSideView.triggered.connect(functools.partial(self.create_view_handler, "sideview")) @@ -538,6 +541,10 @@ def __init__(self, mscolab_data_dir=None, tutorial_mode=False, *args): self.actionUpdater.triggered.connect(self.updater.show) self.openOperationsGb.hide() + def apply_filter(self): + # Trigger filtering in MSColab + self.mscolab.apply_regex_filter() + def bring_main_window_to_front(self): self.show() self.raise_() diff --git a/mslib/msui/qt5/ui_mainwindow.py b/mslib/msui/qt5/ui_mainwindow.py index 2b8056f50..6de5e4174 100644 --- a/mslib/msui/qt5/ui_mainwindow.py +++ b/mslib/msui/qt5/ui_mainwindow.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'mslib/msui/ui/ui_mainwindow.ui' # -# Created by: PyQt5 UI code generator 5.15.7 +# Created by: PyQt5 UI code generator 5.12.3 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -14,7 +14,7 @@ class Ui_MSUIMainWindow(object): def setupUi(self, MSUIMainWindow): MSUIMainWindow.setObjectName("MSUIMainWindow") - MSUIMainWindow.resize(738, 749) + MSUIMainWindow.resize(811, 835) MSUIMainWindow.setMinimumSize(QtCore.QSize(507, 736)) self.centralwidget = QtWidgets.QWidget(MSUIMainWindow) self.centralwidget.setObjectName("centralwidget") @@ -112,52 +112,90 @@ def setupUi(self, MSUIMainWindow): self.gridLayout_3 = QtWidgets.QGridLayout(self.openOperationsGb) self.gridLayout_3.setContentsMargins(8, 8, 8, 8) self.gridLayout_3.setObjectName("gridLayout_3") - self.workingStatusLabel = QtWidgets.QLabel(self.openOperationsGb) - self.workingStatusLabel.setWordWrap(True) - self.workingStatusLabel.setObjectName("workingStatusLabel") - self.gridLayout_3.addWidget(self.workingStatusLabel, 6, 0, 1, 2) self.activeOperationDesc = QtWidgets.QLabel(self.openOperationsGb) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.activeOperationDesc.sizePolicy().hasHeightForWidth()) + self.activeOperationDesc.setSizePolicy(sizePolicy) self.activeOperationDesc.setObjectName("activeOperationDesc") - self.gridLayout_3.addWidget(self.activeOperationDesc, 1, 0, 1, 2) - self.activeOperationsLabel = QtWidgets.QLabel(self.openOperationsGb) - self.activeOperationsLabel.setObjectName("activeOperationsLabel") - self.gridLayout_3.addWidget(self.activeOperationsLabel, 2, 0, 1, 1) - self.workLocallyCheckbox = QtWidgets.QCheckBox(self.openOperationsGb) - self.workLocallyCheckbox.setObjectName("workLocallyCheckbox") - self.gridLayout_3.addWidget(self.workLocallyCheckbox, 10, 0, 1, 1) - self.filterCategoryCb = QtWidgets.QComboBox(self.openOperationsGb) + self.gridLayout_3.addWidget(self.activeOperationDesc, 0, 0, 1, 1) + self.groupBox = QtWidgets.QGroupBox(self.openOperationsGb) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth()) + self.groupBox.setSizePolicy(sizePolicy) + self.groupBox.setMinimumSize(QtCore.QSize(0, 0)) + self.groupBox.setMaximumSize(QtCore.QSize(16777215, 90)) + self.groupBox.setObjectName("groupBox") + self.categoryLabel = QtWidgets.QLabel(self.groupBox) + self.categoryLabel.setGeometry(QtCore.QRect(10, 30, 111, 23)) + self.categoryLabel.setObjectName("categoryLabel") + self.filterCategoryCb = QtWidgets.QComboBox(self.groupBox) + self.filterCategoryCb.setGeometry(QtCore.QRect(170, 30, 151, 21)) self.filterCategoryCb.setAutoFillBackground(False) self.filterCategoryCb.setEditable(False) self.filterCategoryCb.setObjectName("filterCategoryCb") self.filterCategoryCb.addItem("") - self.gridLayout_3.addWidget(self.filterCategoryCb, 9, 1, 1, 1) + self.regexlable = QtWidgets.QLabel(self.groupBox) + self.regexlable.setGeometry(QtCore.QRect(10, 60, 131, 16)) + self.regexlable.setObjectName("regexlable") + self.regexFilterLe = QtWidgets.QLineEdit(self.groupBox) + self.regexFilterLe.setGeometry(QtCore.QRect(170, 60, 151, 23)) + self.regexFilterLe.setObjectName("regexFilterLe") + self.gridLayout_3.addWidget(self.groupBox, 9, 0, 1, 2) + self.pbOpenOperationArchive = QtWidgets.QPushButton(self.openOperationsGb) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.pbOpenOperationArchive.sizePolicy().hasHeightForWidth()) + self.pbOpenOperationArchive.setSizePolicy(sizePolicy) + self.pbOpenOperationArchive.setObjectName("pbOpenOperationArchive") + self.gridLayout_3.addWidget(self.pbOpenOperationArchive, 12, 0, 1, 2) + self.activeOperationsLabel = QtWidgets.QLabel(self.openOperationsGb) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.activeOperationsLabel.sizePolicy().hasHeightForWidth()) + self.activeOperationsLabel.setSizePolicy(sizePolicy) + self.activeOperationsLabel.setObjectName("activeOperationsLabel") + self.gridLayout_3.addWidget(self.activeOperationsLabel, 1, 0, 1, 1) + self.workLocallyCheckbox = QtWidgets.QCheckBox(self.openOperationsGb) + self.workLocallyCheckbox.setObjectName("workLocallyCheckbox") + self.gridLayout_3.addWidget(self.workLocallyCheckbox, 11, 0, 1, 1) self.serverOptionsCb = QtWidgets.QComboBox(self.openOperationsGb) self.serverOptionsCb.setObjectName("serverOptionsCb") self.serverOptionsCb.addItem("") self.serverOptionsCb.addItem("") self.serverOptionsCb.addItem("") - self.gridLayout_3.addWidget(self.serverOptionsCb, 10, 1, 1, 1) - self.categoryLabel = QtWidgets.QLabel(self.openOperationsGb) - self.categoryLabel.setObjectName("categoryLabel") - self.gridLayout_3.addWidget(self.categoryLabel, 9, 0, 1, 1) + self.gridLayout_3.addWidget(self.serverOptionsCb, 11, 1, 1, 1) + self.workingStatusLabel = QtWidgets.QLabel(self.openOperationsGb) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.workingStatusLabel.sizePolicy().hasHeightForWidth()) + self.workingStatusLabel.setSizePolicy(sizePolicy) + self.workingStatusLabel.setWordWrap(True) + self.workingStatusLabel.setObjectName("workingStatusLabel") + self.gridLayout_3.addWidget(self.workingStatusLabel, 8, 0, 1, 1) self.listOperationsMSC = QtWidgets.QListWidget(self.openOperationsGb) - self.listOperationsMSC.setObjectName("listOperationsMSC") - self.gridLayout_3.addWidget(self.listOperationsMSC, 4, 0, 1, 2) - self.pbOpenOperationArchive = QtWidgets.QPushButton(self.openOperationsGb) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.pbOpenOperationArchive.sizePolicy().hasHeightForWidth()) - self.pbOpenOperationArchive.setSizePolicy(sizePolicy) - self.pbOpenOperationArchive.setObjectName("pbOpenOperationArchive") - self.gridLayout_3.addWidget(self.pbOpenOperationArchive, 11, 0, 1, 2) + sizePolicy.setHeightForWidth(self.listOperationsMSC.sizePolicy().hasHeightForWidth()) + self.listOperationsMSC.setSizePolicy(sizePolicy) + self.listOperationsMSC.setMinimumSize(QtCore.QSize(0, 0)) + self.listOperationsMSC.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.listOperationsMSC.setObjectName("listOperationsMSC") + self.gridLayout_3.addWidget(self.listOperationsMSC, 7, 0, 1, 2) self.horizontalLayout.addWidget(self.openOperationsGb) self.verticalLayout_2.addLayout(self.horizontalLayout) self.gridLayout.addLayout(self.verticalLayout_2, 0, 0, 1, 2) self.gridLayout.setColumnStretch(0, 1) MSUIMainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MSUIMainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 738, 22)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 811, 20)) self.menubar.setNativeMenuBar(False) self.menubar.setObjectName("menubar") self.menuFile = QtWidgets.QMenu(self.menubar) @@ -280,13 +318,12 @@ def setupUi(self, MSUIMainWindow): self.retranslateUi(MSUIMainWindow) self.filterCategoryCb.setCurrentIndex(0) - self.actionQuit.triggered.connect(MSUIMainWindow.close) # type: ignore + self.actionQuit.triggered.connect(MSUIMainWindow.close) QtCore.QMetaObject.connectSlotsByName(MSUIMainWindow) MSUIMainWindow.setTabOrder(self.connectBtn, self.userOptionsTb) MSUIMainWindow.setTabOrder(self.userOptionsTb, self.listFlightTracks) MSUIMainWindow.setTabOrder(self.listFlightTracks, self.listViews) - MSUIMainWindow.setTabOrder(self.listViews, self.listOperationsMSC) - MSUIMainWindow.setTabOrder(self.listOperationsMSC, self.workLocallyCheckbox) + MSUIMainWindow.setTabOrder(self.listViews, self.workLocallyCheckbox) MSUIMainWindow.setTabOrder(self.workLocallyCheckbox, self.serverOptionsCb) def retranslateUi(self, MSUIMainWindow): @@ -304,22 +341,24 @@ def retranslateUi(self, MSUIMainWindow): "Save a flight track to name it.")) self.openViewsLabel.setText(_translate("MSUIMainWindow", "Open Views:")) self.listViews.setToolTip(_translate("MSUIMainWindow", "Double-click a view to bring it to the front.")) - self.workingStatusLabel.setText(_translate("MSUIMainWindow", "No operations selected")) self.activeOperationDesc.setText(_translate("MSUIMainWindow", "Select Operation to View Description")) - self.activeOperationsLabel.setText(_translate("MSUIMainWindow", "Operations")) - self.workLocallyCheckbox.setToolTip(_translate("MSUIMainWindow", "Check to work asynchronously from the server")) - self.workLocallyCheckbox.setText(_translate("MSUIMainWindow", "Work Asynchronously")) + self.groupBox.setTitle(_translate("MSUIMainWindow", "Filter flight operations")) + self.categoryLabel.setText(_translate("MSUIMainWindow", "Filter by category:")) self.filterCategoryCb.setWhatsThis(_translate("MSUIMainWindow", "filter by operation category")) self.filterCategoryCb.setCurrentText(_translate("MSUIMainWindow", "ANY")) self.filterCategoryCb.setItemText(0, _translate("MSUIMainWindow", "ANY")) + self.regexlable.setText(_translate("MSUIMainWindow", "Regex filter pattern:")) + self.pbOpenOperationArchive.setText(_translate("MSUIMainWindow", "Operation Archive")) + self.activeOperationsLabel.setText(_translate("MSUIMainWindow", "Operations")) + self.workLocallyCheckbox.setToolTip(_translate("MSUIMainWindow", "Check to work asynchronously from the server")) + self.workLocallyCheckbox.setText(_translate("MSUIMainWindow", "Work Asynchronously")) self.serverOptionsCb.setToolTip(_translate("MSUIMainWindow", "Fetch/Save Server options")) self.serverOptionsCb.setItemText(0, _translate("MSUIMainWindow", "Server Options")) self.serverOptionsCb.setItemText(1, _translate("MSUIMainWindow", "Fetch From Server")) self.serverOptionsCb.setItemText(2, _translate("MSUIMainWindow", "Save To Server")) - self.categoryLabel.setText(_translate("MSUIMainWindow", "Category:")) + self.workingStatusLabel.setText(_translate("MSUIMainWindow", "No operations selected")) self.listOperationsMSC.setToolTip(_translate("MSUIMainWindow", "List of mscolab operations.\n" "Double click a operation to activate and view its description.")) - self.pbOpenOperationArchive.setText(_translate("MSUIMainWindow", "Operation Archive")) self.menuFile.setTitle(_translate("MSUIMainWindow", "&File")) self.menuImportFlightTrack.setTitle(_translate("MSUIMainWindow", "Import Flight Track")) self.menuExportActiveFlightTrack.setTitle(_translate("MSUIMainWindow", "Export Flight Track")) diff --git a/mslib/msui/ui/ui_mainwindow.ui b/mslib/msui/ui/ui_mainwindow.ui index 9f6209063..077d1a1f4 100644 --- a/mslib/msui/ui/ui_mainwindow.ui +++ b/mslib/msui/ui/ui_mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 738 - 749 + 811 + 835 @@ -233,31 +233,137 @@ Save a flight track to name it. 8 - - + + + + + 0 + 0 + + - No operations selected + Select Operation to View Description - - true + + + + + + + 0 + 0 + + + + 0 + 0 + + + + + 16777215 + 90 + + + + Filter flight operations + + + + + 10 + 30 + 111 + 23 + + + + Filter by category: + + + + + + 170 + 30 + 151 + 21 + + + + filter by operation category + + + false + + + false + + + ANY + + + 0 + + + + ANY + + + + + + + 10 + 60 + 131 + 16 + + + + Regex filter pattern: + + + + + + 170 + 60 + 151 + 23 + + + - - + + + + + 0 + 0 + + - Select Operation to View Description + Operation Archive - + + + + 0 + 0 + + Operations - + Check to work asynchronously from the server @@ -267,31 +373,7 @@ Save a flight track to name it. - - - - filter by operation category - - - false - - - false - - - ANY - - - 0 - - - - ANY - - - - - + Fetch/Save Server options @@ -313,31 +395,45 @@ Save a flight track to name it. - - + + + + + 0 + 0 + + - Category: + No operations selected - - - - - - List of mscolab operations. -Double click a operation to activate and view its description. + + true - - + + - + 0 0 - - Operation Archive + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + List of mscolab operations. +Double click a operation to activate and view its description. @@ -355,8 +451,8 @@ Double click a operation to activate and view its description. 0 0 - 738 - 22 + 811 + 20 @@ -627,7 +723,6 @@ Double click a operation to activate and view its description. userOptionsTb listFlightTracks listViews - listOperationsMSC workLocallyCheckbox serverOptionsCb