Files
krowlog/main.py

220 lines
7.3 KiB
Python

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 cutesettings import CuteSettings
from ravenui import RavenUI
from settingsstore import SettingsStore
from highlightingdialog import HighlightingDialog
from tabs import Tabs
from urlutils import url_is_file
MAX_LINE_LENGTH = 4096
logging.basicConfig(level=logging.INFO)
log = logging.getLogger("main")
raven_icon = "icon7.png"
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.settings = SettingsStore.load()
self.setWindowTitle(self.tr("RavenLog"))
self._restore_window()
self.setDockNestingEnabled(True)
self.setAcceptDrops(True)
self.tabs = Tabs(self.settings)
self._menu_recent_files = QMenu(self.tr("Open &Recent"), self)
self.setCentralWidget(self.tabs)
self.status_bar = QStatusBar(self)
self.setStatusBar(self.status_bar)
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.settings_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(QIcon.fromTheme("document-open"), self.tr("&Open..."), self)
open_file.setShortcut('Ctrl+O')
open_file.triggered.connect(self._open_file_dialog)
# Linux: QIcon.fromTheme("exit")
close_action = QAction(QIcon.fromTheme("close"), self.tr("E&xit", "menu item to close the application"), self)
close_action.setShortcut('Ctrl+X')
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 settings_menu(self) -> QMenu:
result = QMenu(self.tr("&Settings"), self)
manage = QAction(self.tr("&Highlighter"), self)
manage.setShortcut('Ctrl+H')
manage.triggered.connect(lambda: HighlightingDialog(self.settings).exec())
result.addAction(manage)
highlight_search_terms = QAction(self.tr("Highlight &Searches"), self)
highlight_search_terms.setCheckable(True)
highlight_search_terms.setChecked(self.settings.session.getboolean("general", "highlight_search_term"))
highlight_search_terms.triggered.connect(
lambda checked: self.settings.set_session("general", "highlight_search_term", str(checked)) or self.update()
)
result.addAction(highlight_search_terms)
new_tab = QAction(self.tr("Open Tab on Save As File"), self)
new_tab.setCheckable(True)
new_tab.setChecked(self.settings.session.getboolean("general", "open_tab_on_save_as_file"))
new_tab.triggered.connect(
lambda checked: self.settings.set_session("general", "open_tab_on_save_as_file", str(checked)))
result.addAction(new_tab)
return result
def help_menu(self) -> QMenu:
help_menu = QMenu(self.tr("&Help", "name of the help menu"), self)
about_action = QAction(QIcon(raven_icon), 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 _restore_window(self):
qsettings = CuteSettings()
geometry_restored = False
geometry = qsettings.value("mainWindow/geometry")
if geometry:
geometry_restored = self.restoreGeometry(geometry)
if not geometry_restored:
self.setGeometry(0, 0, 800, 600)
def closeEvent(self, event):
self.destruct()
def destruct(self):
self.tabs.destruct()
self.close()
SettingsStore.save(self.settings)
CuteSettings().set_value("mainWindow/geometry", self.saveGeometry())
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(raven_icon))
# 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()
#window.open_file("/home/andi/ws/performanceDb/data/production/logs_2018-09-06_2018-09-06.csv")
#window.open_file("/home/andi/ws/performanceDb/data/production/vapbdcom.csv")
#window.open_file("/var/log/syslog")
#window.open_file("/home/andi/ws/ravenlog/example.log")
window.open_file("C:\\Users\\andi\\ws\\some.log")
signal.signal(signal.SIGINT, stop_signal)
signal.signal(signal.SIGTERM, stop_signal)
app.exec()