from PyQt5.QtWidgets import QGroupBox, QCheckBox, QLineEdit, QDialog, QTableWidget, QVBoxLayout, QTableWidgetItem, QPushButton, QHBoxLayout, QFileDialog from PyQt5.QtCore import Qt, pyqtSignal from PyQt5.QtGui import QPalette, QColor from logline_leviathan.gui.ui_helper import UIHelper from logline_leviathan.file_processor.file_processor_thread import FileProcessorThread from logline_leviathan.database.database_manager import EntityTypesTable, session_scope import os class FileSettingsWindow(QDialog): def __init__(self, file_paths, main_window=None): super().__init__(main_window) self.file_paths = file_paths self.main_window = main_window # Reference to MainWindow self.ui_helper = UIHelper(self) self.processing_thread = None self.initUI() def initUI(self): self.layout = QVBoxLayout(self) # Button layout self.buttonLayout = QHBoxLayout() self.removeSelectedButton = QPushButton("Remove Selected Files") self.removeAllButton = QPushButton("Remove All") self.addFilesButton = QPushButton("Add Files to Selection") self.addDirButton = QPushButton("Add Directory to Selection") self.buttonLayout.addWidget(self.removeSelectedButton) self.buttonLayout.addWidget(self.removeAllButton) self.buttonLayout.addWidget(self.addFilesButton) self.buttonLayout.addWidget(self.addDirButton) # Connect buttons to functions self.removeSelectedButton.clicked.connect(self.removeSelected) self.removeAllButton.clicked.connect(self.removeAll) self.addFilesButton.clicked.connect(self.openFileNameDialog) self.addDirButton.clicked.connect(self.openDirNameDialog) self.layout.addLayout(self.buttonLayout) self.filterLineEdit = QLineEdit() self.filterLineEdit.setPlaceholderText("Filter files...") self.filterLineEdit.textChanged.connect(self.filterTableItems) self.layout.insertWidget(1, self.filterLineEdit) # Inserting QLineEdit above the table # Table widget self.tableWidget = QTableWidget() self.tableWidget.setColumnCount(1) self.tableWidget.setHorizontalHeaderLabels(["File Path"]) self.layout.addWidget(self.tableWidget) self.populateTable() # Close button self.closeButton = QPushButton("Close") self.layout.addWidget(self.closeButton) self.closeButton.clicked.connect(self.close) def populateTable(self): self.tableWidget.clearContents() self.tableWidget.setRowCount(len(self.file_paths)) for row, file_path in enumerate(self.file_paths): self.tableWidget.setItem(row, 0, QTableWidgetItem(file_path)) self.tableWidget.resizeColumnsToContents() def filterTableItems(self, text): for row in range(self.tableWidget.rowCount()): item = self.tableWidget.item(row, 0) self.tableWidget.setRowHidden(row, text.lower() not in item.text().lower()) def removeSelected(self): if self.isProcessing(): self.main_window.showProcessingWarning() return # Get the selected rows from the table selected_rows = self.tableWidget.selectionModel().selectedRows() # Extract file paths from the selected rows selected_files = [self.tableWidget.item(row.row(), 0).text() for row in selected_rows] # Remove each selected file for file_path in selected_files: if file_path in self.file_paths: self.file_paths.remove(file_path) # Remove from local file_paths list self.main_window.removeSingleFile(file_path) # Call method in main_window # Refresh the table and update the file count self.populateTable() self.main_window.updateFileCountLabel() def removeAll(self): if self.isProcessing(): self.main_window.showProcessingWarning() return self.main_window.clearFileSelection() self.main_window.updateFileCountLabel() def openFileNameDialog(self): if self.isProcessing(): self.main_window.showProcessingWarning() return self.main_window.openFileNameDialog() self.main_window.updateFileCountLabel() def openDirNameDialog(self): if self.isProcessing(): self.main_window.showProcessingWarning() return self.main_window.openDirNameDialog() self.main_window.updateFileCountLabel() def isProcessing(self): return self.processing_thread and self.processing_thread.isRunning() class AnalysisSettingsWindow(QDialog): parsersUpdated = pyqtSignal() def __init__(self, main_window=None): super().__init__(main_window) self.main_window = main_window self.ui_helper = UIHelper(self) self.initUI() def initUI(self): self.layout = QHBoxLayout(self) # Create the QGroupBox self.parserSettingsGroupBox = QGroupBox("Parser Settings") self.parserSettingsGroupBoxLayout = QVBoxLayout() self.toggleAllButtonsLayout = QHBoxLayout() self.parserSettingsGroupBoxLayout.addLayout(self.toggleAllButtonsLayout) self.enableAllButton = QPushButton("Enable All") self.disableAllButton = QPushButton("Disable All") self.toggleAllButtonsLayout.addWidget(self.enableAllButton) self.enableAllButton.clicked.connect(self.enableAllCheckboxes) self.toggleAllButtonsLayout.addWidget(self.disableAllButton) self.disableAllButton.clicked.connect(self.disableAllCheckboxes) self.parserSettingsGroupBox.setLayout(self.parserSettingsGroupBoxLayout) self.layout.addWidget(self.parserSettingsGroupBox) # Populate the QGroupBox self.populateGroupBox() self.configDirectoriesGroupBox = QGroupBox("Config Directories") self.configDirectoriesGroupBoxLayout = QVBoxLayout() self.configDirectoriesGroupBox.setLayout(self.configDirectoriesGroupBoxLayout) self.configDirectoriesGroupBoxLayout.setAlignment(Qt.AlignTop) self.layout.addWidget(self.configDirectoriesGroupBox) # Inspect Regex Button self.inspectRegexButton = QPushButton('YAML-Konfigurationsdatei inspizieren...', self) self.inspectRegexButton.clicked.connect(self.openRegexLibrary) self.configDirectoriesGroupBoxLayout.addWidget(self.inspectRegexButton) self.openWordlistPathButton = QPushButton('Wordlist-Verzeichnis oeffnen...', self) self.openWordlistPathButton.clicked.connect(self.openWordlistPath) self.configDirectoriesGroupBoxLayout.addWidget(self.openWordlistPathButton) self.openScriptsPathButton = QPushButton('Scripts-Verzeichnis oeffnen...', self) self.openScriptsPathButton.clicked.connect(self.openScriptsPath) self.configDirectoriesGroupBoxLayout.addWidget(self.openScriptsPathButton) # Close Button self.closeButton = QPushButton("Close") self.layout.addWidget(self.closeButton) self.closeButton.clicked.connect(self.close) def populateGroupBox(self): self.parserSettingsGroupBoxLayout.setAlignment(Qt.AlignTop) with session_scope() as db_session: entity_types = db_session.query(EntityTypesTable).all() self.checkboxes = [] for et in entity_types: # Omit entries that start with "category_" if et.entity_type.startswith("category_"): continue parser_info = [] if et.regex_pattern: parser_info.append("regex") if et.script_parser: parser_info.append("script") checkBoxText = f"{et.gui_name} ({', '.join(parser_info)})" if parser_info else et.gui_name checkBox = QCheckBox(checkBoxText) # Fetch the current state of parser_enabled from the database for each entity type current_parser_enabled = db_session.query(EntityTypesTable).filter(EntityTypesTable.entity_type_id == et.entity_type_id).first().parser_enabled checkBox.setChecked(current_parser_enabled) color = 'green' if current_parser_enabled else 'red' checkBox.setStyleSheet(f"QCheckBox {{ color: {color}; }}") self.parserSettingsGroupBoxLayout.addWidget(checkBox) self.checkboxes.append((checkBox, et.entity_type_id)) checkBox.toggled.connect(lambda checked, et_id=et.entity_type_id: self.updateParserEnabled(checked, et_id)) def enableAllCheckboxes(self): for checkBox, _ in self.checkboxes: checkBox.setChecked(True) def disableAllCheckboxes(self): for checkBox, _ in self.checkboxes: checkBox.setChecked(False) def updateParserEnabled(self, checked, entity_type_id): with session_scope() as db_session: # Using a session context manager et = db_session.query(EntityTypesTable).filter_by(entity_type_id=entity_type_id).first() if et: et.parser_enabled = checked db_session.commit() # Commit changes if self.main_window: self.main_window.refreshApplicationState() # Refresh the UI state self.refreshGroupBox() # Refresh the group box to reflect changes def refreshGroupBox(self): # Clear and repopulate the group box for checkBox, _ in self.checkboxes: checkBox.deleteLater() # Properly delete the checkbox self.populateGroupBox() self.parsersUpdated.emit() def openWordlistPath(self): wordlist_path = os.path.join(os.getcwd(), 'data', 'wordlist') if os.path.exists(wordlist_path): self.ui_helper.openFile(wordlist_path) # Call openFile method on the UIHelper instance else: #self.statusLabel.setText(" wordlist nicht unter ./daten/ gefunden.") pass def openRegexLibrary(self): path_to_yaml = os.path.join(os.getcwd(), 'data', 'entities.yaml') if os.path.exists(path_to_yaml): self.ui_helper.openFile(path_to_yaml) # Call openFile method on the UIHelper instance else: #self.statusLabel.setText(" entities.yaml nicht unter ./daten/ gefunden.") pass def openScriptsPath(self): scripts_path = os.path.join(os.getcwd(), 'data', 'parser') if os.path.exists(scripts_path): self.ui_helper.openFile(scripts_path) # Call openFile method on the UIHelper instance else: #self.statusLabel.setText(" scripts nicht unter ./daten/ gefunden.") pass