import logging import os import signal from PyQt6 import QtCore from PyQt6.QtWidgets import * from PyQt6.QtCore import * from PyQt6.QtGui import * import sys import urlutils from aboutdialog import AboutDialog from ravenui import RavenUI from settingsstore import SettingsStore from tabs import Tabs from urlutils import url_is_file MAX_LINE_LENGTH = 4096 logging.basicConfig(level=logging.INFO) log = logging.getLogger("main") class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.settings = SettingsStore.load() self.setWindowTitle(self.tr("RavenLog")) self.setGeometry(0, 0, 640, 480) self.setDockNestingEnabled(True) self.setAcceptDrops(True) self.tabs = Tabs(self.settings) self.tabs.create_tab("/home/andi/ws/performanceDb/data/production/logs_2018-09-06_2018-09-06.csv") self.tabs.create_tab("/home/andi/ws/performanceDb/data/production/vapbdcom.csv") self.tabs.create_tab("/home/andi/ws/ravenlog/example.log") self.tabs.create_tab("/var/log/syslog") self._menu_recent_files = QMenu(self.tr("Open &Recent"), self) self.setCentralWidget(self.tabs) self.setStatusBar(QStatusBar(self)) self.setMenuBar(self.create_menu_bar()) def create_menu_bar(self) -> QMenuBar: menu_bar = QMenuBar() menu_bar.addMenu(self.file_menu()) menu_bar.addMenu(self.help_menu()) return menu_bar def file_menu(self) -> QMenu: file_menu = QMenu(self.tr("&File", "name of the file menu"), self) open_file = QAction(self.tr("&Open..."), self) open_file.triggered.connect(self._open_file_dialog) close_action = QAction(self.tr("E&xit", "menu item to close the application"), self) close_action.triggered.connect(self.destruct) self._update_recent_files_menu() file_menu.addAction(open_file) file_menu.addMenu(self._menu_recent_files) file_menu.addAction(close_action) return file_menu def help_menu(self) -> QMenu: help_menu = QMenu(self.tr("&Help", "name of the help menu"), self) about_action = QAction(self.tr("&About"), self) about_action.triggered.connect(lambda: AboutDialog().exec()) help_menu.addAction(about_action) return help_menu def _update_recent_files_menu(self): self._menu_recent_files.clear() files = self._get_recent_files() for file in files: action = QAction(os.path.basename(file), self) action.triggered.connect(lambda x, f=file: self._open_file(f)) self._menu_recent_files.addAction(action) def _open_file_dialog(self) -> None: current_file = self.tabs.current_file() directory = os.path.dirname(current_file) if current_file else '' dialog = QFileDialog(self) (selected_file, _filter) = dialog.getOpenFileName( caption=self.tr("Open File"), directory=directory ) if selected_file: self.tabs.create_tab(selected_file) self._remember_recent_file(selected_file) def _open_file(self, file: str) -> None: self.tabs.create_tab(file) self._remember_recent_file(file) def _get_recent_files(self) -> [str]: recent_files = self.settings.session.get('general', 'recent_files', fallback='') files = recent_files.split(os.pathsep) if "" in files: files.remove("") return files def _remember_recent_file(self, file: str): files = self._get_recent_files() if file in files: files.remove(file) files.insert(0, file) recent_files = os.pathsep.join(files[:10]) self.settings.set_session('general', 'recent_files', recent_files) self._update_recent_files_menu() def dragEnterEvent(self, e: QDragEnterEvent): if e.mimeData().hasFormat('text/plain') and url_is_file(e.mimeData().text()): e.accept() else: e.ignore() def dropEvent(self, e): file = urlutils.url_to_path(e.mimeData().text()) self._open_file(file) def closeEvent(self, event): self.destruct() def destruct(self): self.tabs.destruct() self.close() SettingsStore.save(self.settings) def stop_signal(signum, _stackframe): """ Handle terminate signal """ try: log.info("Terminate signal received. %s", signum) QtCore.QCoreApplication.quit() except Exception: log.exception("Exception occurred while terminating") sys.exit(1) sys.exit(0) if __name__ == "__main__": app = QApplication(sys.argv) app.setWindowIcon(QIcon("icon7.png")) # translator = QTranslator() # if translator.load(QLocale("de"), "messages_de.ts"): # app.installTranslator(translator) # workaround to make signals work in QT apps. # They do not work out of the box, because the main thread # is running in C++ code once app.exec() is executed # Forcing an empty lambda to be executed periodically gives # control back to python and allows python to react to signals timer = QTimer() timer.timeout.connect(lambda: None) timer.start(100) window = MainWindow() RavenUI.window = window window.show() signal.signal(signal.SIGINT, stop_signal) signal.signal(signal.SIGTERM, stop_signal) app.exec()