From 807efb1e10b664c295d5b9a627c39084281eec6d Mon Sep 17 00:00:00 2001 From: Chris PeBenito <cpebenito@tresys.com> Date: Thu, 31 Mar 2016 11:29:15 -0400 Subject: [PATCH] ApolMainWindow: handle closing the policy * Close all tabs when closing the policy * Close the policy if using the "open policy" action and policy load succeeds. * Warn the user the above actions will close analysis tabs (if any tabs are open) * Set analysis widgets to delete on close since widgets are not deleted by QTabWidget.clear() or .removeTab() --- data/apol.ui | 15 +++++++++++--- setoolsgui/apol/mainwindow.py | 36 +++++++++++++++++++++++++++++++++- setoolsgui/apol/terulequery.py | 4 +++- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/data/apol.ui b/data/apol.ui index 7011f74..3cbc27e 100644 --- a/data/apol.ui +++ b/data/apol.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>MainWindow</class> - <widget class="QMainWindow" name="MainWindow"> + <class>ApolMainWindow_ui</class> + <widget class="QMainWindow" name="ApolMainWindow_ui"> <property name="geometry"> <rect> <x>0</x> @@ -68,6 +68,7 @@ <string>&File</string> </property> <addaction name="open_policy"/> + <addaction name="close_policy_action"/> <addaction name="separator"/> <addaction name="exit_apol"/> </widget> @@ -204,13 +205,21 @@ <string>Ctrl+W</string> </property> </action> + <action name="close_policy_action"> + <property name="text"> + <string>Close Policy</string> + </property> + <property name="toolTip"> + <string>Close the current policy. Closes all analyses too.</string> + </property> + </action> </widget> <resources/> <connections> <connection> <sender>exit_apol</sender> <signal>triggered()</signal> - <receiver>MainWindow</receiver> + <receiver>ApolMainWindow_ui</receiver> <slot>close()</slot> <hints> <hint type="sourcelabel"> diff --git a/setoolsgui/apol/mainwindow.py b/setoolsgui/apol/mainwindow.py index d232461..4e7d822 100644 --- a/setoolsgui/apol/mainwindow.py +++ b/setoolsgui/apol/mainwindow.py @@ -85,6 +85,7 @@ class ApolMainWindow(SEToolsWidget, QMainWindow): # connect signals self.open_policy.triggered.connect(self.select_policy) + self.close_policy_action.triggered.connect(self.close_policy) self.open_permmap.triggered.connect(self.select_permmap) self.new_analysis.triggered.connect(self.choose_analysis) self.AnalysisTabs.tabCloseRequested.connect(self.close_tab) @@ -105,10 +106,26 @@ class ApolMainWindow(SEToolsWidget, QMainWindow): self.setWindowTitle("apol") def select_policy(self): + old_policy = self._policy + + if old_policy and self.AnalysisTabs.count() > 0: + reply = QMessageBox.question( + self, "Continue?", + "Loading a policy will close all existing analyses. Continue?", + QMessageBox.Yes | QMessageBox.No) + + if reply == QMessageBox.No: + return + filename = QFileDialog.getOpenFileName(self, "Open policy file", ".")[0] if filename: self.load_policy(filename) + if self._policy != old_policy: + # policy loading succeeded, clear any + # existing tabs + self.AnalysisTabs.clear() + def load_policy(self, filename): try: self._policy = SELinuxPolicy(filename) @@ -121,6 +138,20 @@ class ApolMainWindow(SEToolsWidget, QMainWindow): if self._permmap: self._permmap.map_policy(self._policy) + def close_policy(self): + if self.AnalysisTabs.count() > 0: + reply = QMessageBox.question( + self, "Continue?", + "Loading a policy will close all existing analyses. Continue?", + QMessageBox.Yes | QMessageBox.No) + + if reply == QMessageBox.No: + return + + self.AnalysisTabs.clear() + self._policy = None + self.update_window_title() + def select_permmap(self): filename = QFileDialog.getOpenFileName(self, "Open permission map file", ".")[0] if filename: @@ -159,6 +190,7 @@ class ApolMainWindow(SEToolsWidget, QMainWindow): newtab.setObjectName(counted_name) newanalysis = tabclass(newtab, self._policy, self._permmap) + newanalysis.setAttribute(Qt.WA_DeleteOnClose) # create a vertical layout in the tab, place the analysis ui inside. tabLayout = QVBoxLayout() @@ -180,19 +212,21 @@ class ApolMainWindow(SEToolsWidget, QMainWindow): self.tab_editor.setFocus() def close_active_tab(self): + """Close the active tab. This is called from the context menu.""" index = self.AnalysisTabs.currentIndex() if index >= 0: self.close_tab(index) def rename_active_tab(self): + """Rename the active tab.""" index = self.AnalysisTabs.currentIndex() if index >= 0: self.tab_name_editor(index) def close_tab(self, index): + """Close a tab specified by index.""" widget = self.AnalysisTabs.widget(index) widget.close() - widget.deleteLater() self.AnalysisTabs.removeTab(index) def rename_tab(self): diff --git a/setoolsgui/apol/terulequery.py b/setoolsgui/apol/terulequery.py index ae71654..3dafddc 100644 --- a/setoolsgui/apol/terulequery.py +++ b/setoolsgui/apol/terulequery.py @@ -377,7 +377,9 @@ class TERuleQueryTab(SEToolsWidget, QScrollArea): # if query is broad, show warning. if not any((self.query.source, self.query.target, self.query.tclass, self.query.perms, - self.query.xperms, self.query.default, self.query.boolean)): + self.query.xperms, self.query.default, self.query.boolean)) \ + and max_results > 1000: + reply = QMessageBox.question( self, "Continue?", "This is a broad query, estimated to return {0} results. Continue?".