228 lines
7.7 KiB
Python
228 lines
7.7 KiB
Python
import logging
|
|
import os
|
|
import signal
|
|
import ctypes
|
|
|
|
from PyQt6 import QtCore
|
|
from PyQt6.QtWidgets import *
|
|
from PyQt6.QtCore import *
|
|
from PyQt6.QtGui import *
|
|
import sys
|
|
|
|
import constants
|
|
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")
|
|
|
|
|
|
|
|
|
|
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(constants.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 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(constants.raven_icon)) # works only for Linux
|
|
|
|
# make icon appear in Windows
|
|
# see https://stackoverflow.com/questions/1551605/how-to-set-applications-taskbar-icon-in-windows-7/1552105#1552105
|
|
if sys.platform == 'win32' or sys.platform == 'cygwin':
|
|
myappid = 'opentext.ravenlog' # arbitrary string
|
|
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
|
|
|
|
# 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()
|