import logging from typing import List from PySide6.QtWidgets import * from PySide6.QtGui import * from PySide6.QtCore import Qt import urlutils from cutesettings import CuteSettings from raven.pluginregistry import PluginRegistry from raven.plugins.domain.menucontribution import MenuContribution, sort_menu_contributions from raven.plugins.domain.raction import RAction from raven.plugins.domain.rmenu import RMenu from raven.plugins.ravenlog.Tab import Tab from settingsstore import SettingsStore from highlightingdialog import HighlightingDialog from tabs import Tabs from urlutils import url_is_file from functools import reduce from raven.i18n import _ MAX_LINE_LENGTH = 4096 logging.basicConfig(level=logging.INFO) log = logging.getLogger("main") def flat_map(array: List[List]) -> List: return reduce(list.__add__, array) class MainWindow(QMainWindow): def __init__(self, *args, **kwargs): super(MainWindow, self).__init__(*args, **kwargs) self.settings = SettingsStore.load() PluginRegistry.execute("set_settings", self.settings) self.setWindowTitle(_("RavenLog")) self._restore_window() self.setDockNestingEnabled(True) self.setAcceptDrops(True) self.tabs = Tabs(self.settings) self._menu_recent_files = QMenu(_("Open &Recent"), self) self.setCentralWidget(self.tabs) self.status_bar = QStatusBar(self) self.setStatusBar(self.status_bar) self.setMenuBar(self.create_dynamic_menu_bar()) self.setTabPosition(Qt.DockWidgetArea.AllDockWidgetAreas, QTabWidget.TabPosition.North) def create_dynamic_menu_bar(self) -> QMenuBar: menu_bar = QMenuBar() menu_contributions: [MenuContribution] = flat_map(PluginRegistry.execute("get_menu_contributions")) menu_contributions.append(MenuContribution("settings", action=self._action_highlighter())) menu_contributions.append(MenuContribution("settings", action=self._action_highlight_search_terms())) menu_contributions.append(MenuContribution("settings", action=self._action_new_tab())) menu_contributions = sort_menu_contributions(menu_contributions) known_menus = [ ("file", _("&File")), ("settings", _("&Settings")), ("window", _("&Window")), ("help", _("&Help")) ] for (menu_id, menu_label) in known_menus: menu = QMenu(menu_label, self) mcs: [MenuContribution] = [mc for mc in menu_contributions if mc.menu_id == menu_id] if len(mcs) == 0: continue for menu_contribution in mcs: if menu_contribution.action: action = self._raction_to_qaction(menu_contribution.action, menu) menu.addAction(action) if menu_contribution.menu: submenu = QMenu(menu_contribution.menu.label, menu_bar) submenu.setIcon(QIcon.fromTheme(menu_contribution.menu.icon_from_theme)) menu_contribution.menu.add_change_listener( lambda qmenu=submenu, rmenu=menu_contribution.menu: self._rmenu_update(qmenu, rmenu)) self._rmenu_update(submenu, menu_contribution.menu) menu.addMenu(submenu) menu_bar.addMenu(menu) return menu_bar def _rmenu_update(self, qmenu: QMenu, rmenu: RMenu): qmenu.clear() for action in rmenu.actions: action = self._raction_to_qaction(action, qmenu) qmenu.addAction(action) def _raction_to_qaction(self, raction: RAction, qmenu: QMenu) -> QAction: action = QAction(_(raction.label), qmenu) if raction.icon_from_theme: action.setIcon(QIcon.fromTheme(raction.icon_from_theme)) if raction.icon_file: action.setIcon(QIcon(raction.icon_file)) if raction.shortcut: action.setShortcut(raction.shortcut) if raction.action: action.triggered.connect(raction.action) if raction.checkable: action.setCheckable(raction.checkable) action.setChecked(raction.checked) return action def _action_highlighter(self): manage = RAction( _("&Highlighter"), action=lambda: HighlightingDialog(self.settings).exec(), shortcut='Ctrl+H' ) return manage def _action_highlight_search_terms(self): highlight_search_terms = RAction( _("Highlight &Searches"), action=lambda checked: self.settings.set_session("general", "highlight_search_term", str(checked)) or self.update() ) highlight_search_terms.set_checkable(True) highlight_search_terms.set_checked(self.settings.session.getboolean("general", "highlight_search_term")) return highlight_search_terms def _action_new_tab(self): new_tab = RAction(_("Open Tab on Save As File")) new_tab.set_checkable(True) new_tab.set_checked(self.settings.session.getboolean("general", "open_tab_on_save_as_file")) new_tab.set_action( lambda checked: self.settings.set_session("general", "open_tab_on_save_as_file", str(checked))) return new_tab def dragEnterEvent(self, e: QDragEnterEvent): if url_is_file(e.mimeData().text()): e.accept() else: e.ignore() def dropEvent(self, e): files = urlutils.urls_to_path(e.mimeData().text()) for file in files: PluginRegistry.execute_single("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())