diff --git a/CHANGELOG.md b/CHANGELOG.md index 3654e68..aca0c4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 1.4.6 +* Added checkbox in the View menu to turn off the log view in case you're using an external log viewer + ## 1.4.5 * Copying of hook file is now an option in the settings that defaults to False diff --git a/dcs_code_injector/__init__.py b/dcs_code_injector/__init__.py index 4eb531b..b529d02 100644 --- a/dcs_code_injector/__init__.py +++ b/dcs_code_injector/__init__.py @@ -1,4 +1,6 @@ import os -VERSION = "1.4.5" -ICON = os.path.join(os.path.dirname(__file__), "ui", "icons", "icon.png") \ No newline at end of file +VERSION = "1.4.6" +ICON = os.path.join(os.path.dirname(__file__), "ui", "icons", "icon.png") +LOGO = os.path.join(os.path.dirname(__file__), "ui", "icons", "logo.png") +UI_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ui") \ No newline at end of file diff --git a/dcs_code_injector/app.py b/dcs_code_injector/app.py index 0ff0f7d..c25fea2 100644 --- a/dcs_code_injector/app.py +++ b/dcs_code_injector/app.py @@ -8,14 +8,12 @@ from ez_settings import EZSettings from qt_material import apply_stylesheet -from . import ICON -from . import utils +from . import ICON, utils, UI_DIR, LOGO from .dcs_code_injector_window import CodeInjectorWindow from .constants import sk, DEFAULT_HIGHLIGHTING_RULES SETTINGS_DIR = os.path.join(os.path.expanduser('~'),'Documents', "dcs_code_injector") SETTINGS_PATH = os.path.join(SETTINGS_DIR, "settings.json") -UI_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ui") SPLASH_DIR = os.path.join(UI_DIR, "splashscreens") application = QApplication() @@ -69,7 +67,7 @@ def main(): splash = QSplashScreen(QPixmap(splashscreens[random.randint(0, len(splashscreens) - 1)])) splash.show() - application.setWindowIcon(QIcon(ICON)) + application.setWindowIcon(QIcon(LOGO)) application.processEvents() theme = EZSettings().get(sk.theme, sk.theme_material_neon) diff --git a/dcs_code_injector/constants.py b/dcs_code_injector/constants.py index cc3a6b5..383d4de 100644 --- a/dcs_code_injector/constants.py +++ b/dcs_code_injector/constants.py @@ -54,6 +54,8 @@ class SettingConstants: theme_fusion_dark = "Fusion Dark" theme = "theme" copy_hook_on_startup = "copy_hook_on_startup" + update_log_view = "update_log_view" + sk = SettingConstants diff --git a/dcs_code_injector/dcs_code_injector_window.py b/dcs_code_injector/dcs_code_injector_window.py index 14fd462..ce68945 100644 --- a/dcs_code_injector/dcs_code_injector_window.py +++ b/dcs_code_injector/dcs_code_injector_window.py @@ -2,7 +2,6 @@ from PySide6.QtGui import * from PySide6.QtCore import * -import os import json import pathlib import socket @@ -10,15 +9,12 @@ from functools import partial from ez_settings import EZSettings -from datetime import datetime, timedelta -from pygtail import Pygtail from .settings_dialog import SettingsDialog from .version_dialog import AboutDialog from .code_editor import CodeTextEdit from .favorites import FavoritesWidget from .log_view import LogView -from .log_highlighter import LogHighlighter from .ui.dcs_code_injector_window_ui import Ui_MainWindow from .constants import sk @@ -52,25 +48,16 @@ def __init__(self): self.about_dialog = AboutDialog() - self.last_log_file_size = 0 + # self.last_log_file_size = 0 self.txt_log = LogView() + self.txt_log.showSettings.connect(self.show_settings) + self.txt_log.playErrorSound.connect(self.play_error_sound) self.txt_log_layout.addWidget(self.txt_log) - self.log_file = EZSettings().get(sk.log_file, "") - self.previous = [] - LogHighlighter(self.txt_log.document()) - self.read_log() self.connect_ui_signals() self.load() - # self.update_code_views_font() - - self.timer = QTimer() - self.timer.setInterval(500) - self.timer.timeout.connect(self.read_log) - self.timer.start() - self.back_up_settings_file() if EZSettings().get(sk.copy_hook_on_startup, False): self.copy_hook_file() @@ -78,42 +65,6 @@ def __init__(self): self.show() self.init_done = True - - def read_log(self): - """ - Reads the log file and updates the log view. - Handles the time shifting for the log entries. - """ - - if not os.path.isfile(self.log_file): - self.show_settings() - self.log_file = EZSettings().get(sk.log_file, "") - - if not self.init_done: - with open(self.log_file, "r") as readfile: - self.add_text_to_log(readfile.read()) - - for line in Pygtail(self.log_file): - try: - line = line.replace(" ", " ") - time_str = line[0:22] - time = datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S.%f") - shift_hours = EZSettings().get(sk.shift_hours, 0) - time += timedelta(hours=shift_hours) - shifted_time_str = time.strftime("%Y-%m-%d %H:%M:%S.%f")[:-4] - line = line.replace(time_str, shifted_time_str) - - diff = datetime.now() - time - if ("mission script error" in line.lower() and - diff.total_seconds() > 0.7 and - self.init_done and - EZSettings().get(sk.play_sound_on_mission_scripting_error, True)): - self.play_error_sound() - - self.add_text_to_log(line) - except ValueError as err: - self.add_text_to_log(line) - def connect_ui_signals(self): """ Connects the UI signals to their respective slots. @@ -121,14 +72,16 @@ def connect_ui_signals(self): self.tab_widget.tabBarDoubleClicked.connect(self.rename_tab) self.tab_widget.tabCloseRequested.connect(self.close_tab) + self.action_settings.triggered.connect(self.show_settings) self.action_back_up_settings_file.triggered.connect(self.back_up_settings_file) - self.action_clear_log.triggered.connect(self.clear_log) + self.action_clear_log.triggered.connect(self.txt_log.clear) self.action_search.triggered.connect(self.txt_log.toggle_search) self.action_add_new_tab.triggered.connect(lambda _: self.add_new_tab(name="UNNAMED", code="-- add code here")) self.action_copy_hook_file.triggered.connect(self.copy_hook_file) self.action_increase_code_font_size.triggered.connect(lambda _: self.adjust_font_size(self.tab_widget.currentWidget(), True)) self.action_decrease_code_font_size.triggered.connect(lambda _: self.adjust_font_size(self.tab_widget.currentWidget(), False)) + self.action_log_view_enabled.toggled.connect(self.enabled_log_view) self.action_pick_log_font.triggered.connect(lambda _: self.pick_font("log")) self.action_increase_log_font_size.triggered.connect(lambda _: self.adjust_font_size(self.txt_log, True)) self.action_decrease_log_font_size.triggered.connect(lambda _: self.adjust_font_size(self.txt_log, False)) @@ -166,13 +119,6 @@ def adjust_font_size(self, widget, increase): self.txt_log.setStyleSheet(f"font: {size}pt 'Courier New';") EZSettings().set(sk.log_font_size, size) - def clear_log(self): - """ - "Clears" the log view by just adding 60 newlines to push everything up - """ - - self.add_text_to_log("\n" * 60) - def connect_favorite_button(self, favorite_button): """ Connects the favorite button to its respective slots. @@ -239,6 +185,14 @@ def rename_tab(self): self.tab_widget.setTabText(self.tab_widget.currentIndex(), name) self.save_code() + def enabled_log_view(self): + enable = self.action_log_view_enabled.isChecked() + self.txt_log.enable_updating(enable) + if enable: + self.splitter.setSizes([500, 200]) + else: + self.splitter.setSizes([0, 4000]) + def load(self): """ Loads the settings and initializes the UI accordingly. @@ -250,6 +204,8 @@ def load(self): if setting.startswith("btn_"): self.favorites_widget.add_new_button(setting.replace("btn_", ""), EZSettings().get(setting)) + self.action_log_view_enabled.setChecked(EZSettings().get(sk.update_log_view, True)) + def save_code(self): """ Saves the code in the current tab to the settings. @@ -276,18 +232,7 @@ def add_code_to_log(self, text, header_text="CODE BLOCK"): line_number += 1 numbered_lines.append(f"\n------------------ /{header_text} -------------------\n") complete_text = "\n".join(numbered_lines) - self.add_text_to_log(complete_text) - - def add_text_to_log(self, complete_text): - """ - Adds the given text to the log view. - - :param complete_text: the text to be added to the log - """ - - self.txt_log.moveCursor(QTextCursor.End) - self.txt_log.insertPlainText(complete_text) - self.txt_log.verticalScrollBar().setValue(self.txt_log.verticalScrollBar().maximum()) + self.txt_log.add_text(complete_text) def send_code(self, code): self.add_code_to_log(code) diff --git a/dcs_code_injector/log_view.py b/dcs_code_injector/log_view.py index dd8ad0d..a7b4464 100644 --- a/dcs_code_injector/log_view.py +++ b/dcs_code_injector/log_view.py @@ -1,33 +1,59 @@ +from datetime import datetime, timedelta + from PySide6.QtWidgets import * from PySide6.QtGui import * from PySide6.QtCore import * from PySide6.QtCore import Qt +import os + +from pygtail import Pygtail + +from .log_highlighter import LogHighlighter from .ui.dcs_code_injector_search_ui import Ui_Form from .constants import sk from ez_settings import EZSettings class LogView(QPlainTextEdit): + showSettings = Signal() + playErrorSound = Signal() def __init__(self): """ Constructor for the LogView class. """ + self.init_done = False super().__init__() self.font = EZSettings().get(sk.log_font, sk.default_font) self.font_size = EZSettings().get(sk.log_font_size, 10) self.__update_font() + # make search widget self.search_widget = SearchBox() self.search_widget.txt_search.returnPressed.connect(self.search_text) - - self.last_search_position = 0 - self.grid_layout = QGridLayout(self) self.grid_layout.setContentsMargins(0, 10 , 15, 0) self.grid_layout.addWidget(self.search_widget, 0, 0, 0, 0, Qt.AlignTop | Qt.AlignRight) + + + self.last_search_position = 0 + + self.log_file = EZSettings().get(sk.log_file, "") + if not os.path.isfile(self.log_file): + self.showSettings.emit() + self.log_file = EZSettings().get(sk.log_file, "") + + self.timer = QTimer() + self.timer.setInterval(500) + self.timer.timeout.connect(self.read_log) + if EZSettings().get(sk.update_log_view, True): + self.timer.start() + + LogHighlighter(self.document()) + self.setReadOnly(True) + self.init_done = True def set_font(self, font): self.font = font @@ -39,6 +65,13 @@ def set_font_size(self, font_size): EZSettings().set(sk.log_font_size, font_size) self.__update_font() + def enable_updating(self, value): + EZSettings().set(sk.update_log_view, value) + if value: + self.timer.start() + else: + self.timer.stop() + def toggle_search(self): """ Toggles the visibility of the search widget. @@ -66,6 +99,44 @@ def search_text(self): else: self.last_search_position = 0 + def add_text(self, complete_text): + self.moveCursor(QTextCursor.End) + self.insertPlainText(complete_text) + self.verticalScrollBar().setValue(self.verticalScrollBar().maximum()) + + def clear(self): + self.add_text("\n" * 60) + + def read_log(self): + if not os.path.isfile(self.log_file): + self.showSettings.emit() + self.log_file = EZSettings().get(sk.log_file, "") + + if not self.init_done: + with open(self.log_file, "r") as readfile: + self.add_text(readfile.read()) + + for line in Pygtail(self.log_file): + try: + line = line.replace(" ", " ") + time_str = line[0:22] + time = datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S.%f") + shift_hours = EZSettings().get(sk.shift_hours, 0) + time += timedelta(hours=shift_hours) + shifted_time_str = time.strftime("%Y-%m-%d %H:%M:%S.%f")[:-4] + line = line.replace(time_str, shifted_time_str) + + diff = datetime.now() - time + if ("mission script error" in line.lower() and + diff.total_seconds() > 0.7 and + self.init_done and + EZSettings().get(sk.play_sound_on_mission_scripting_error, True)): + self.playErrorSound.emit() + + self.add_text(line) + except ValueError as err: + self.add_text(line) + def __update_font(self): self.setStyleSheet(f"font: {self.font_size}pt '{self.font}';") diff --git a/dcs_code_injector/ui/dcs_code_injector_window_ui.py b/dcs_code_injector/ui/dcs_code_injector_window_ui.py index a1f99a8..6b8d381 100644 --- a/dcs_code_injector/ui/dcs_code_injector_window_ui.py +++ b/dcs_code_injector/ui/dcs_code_injector_window_ui.py @@ -57,6 +57,10 @@ def setupUi(self, MainWindow): self.action_material_neon.setObjectName(u"action_material_neon") self.action_fusion_dark = QAction(MainWindow) self.action_fusion_dark.setObjectName(u"action_fusion_dark") + self.action_log_view_enabled = QAction(MainWindow) + self.action_log_view_enabled.setObjectName(u"action_log_view_enabled") + self.action_log_view_enabled.setCheckable(True) + self.action_log_view_enabled.setChecked(True) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) @@ -114,6 +118,7 @@ def setupUi(self, MainWindow): self.menuTools.addAction(self.action_search) self.menuTools.addSeparator() self.menuTools.addAction(self.action_copy_hook_file) + self.menuView.addAction(self.action_log_view_enabled) self.menuView.addAction(self.action_increase_log_font_size) self.menuView.addAction(self.action_decrease_log_font_size) self.menuView.addAction(self.action_pick_log_font) @@ -177,6 +182,7 @@ def retranslateUi(self, MainWindow): self.action_pick_code_font.setText(QCoreApplication.translate("MainWindow", u"Pick code font", None)) self.action_material_neon.setText(QCoreApplication.translate("MainWindow", u"Material Neon", None)) self.action_fusion_dark.setText(QCoreApplication.translate("MainWindow", u"Fusion Dark", None)) + self.action_log_view_enabled.setText(QCoreApplication.translate("MainWindow", u"Log view enabled", None)) self.menuFile.setTitle(QCoreApplication.translate("MainWindow", u"File", None)) self.menuTools.setTitle(QCoreApplication.translate("MainWindow", u"Tools", None)) self.menuView.setTitle(QCoreApplication.translate("MainWindow", u"View", None)) diff --git a/dcs_code_injector/ui/dcs_code_injector_window_ui.ui b/dcs_code_injector/ui/dcs_code_injector_window_ui.ui index bdbd38a..ac09758 100644 --- a/dcs_code_injector/ui/dcs_code_injector_window_ui.ui +++ b/dcs_code_injector/ui/dcs_code_injector_window_ui.ui @@ -79,6 +79,7 @@ + @@ -205,6 +206,17 @@ Fusion Dark + + + true + + + true + + + Log view enabled + + diff --git a/dcs_code_injector/ui/icons/logo.png b/dcs_code_injector/ui/icons/logo.png new file mode 100644 index 0000000..b4c7ece Binary files /dev/null and b/dcs_code_injector/ui/icons/logo.png differ diff --git a/dcs_code_injector/version_dialog.py b/dcs_code_injector/version_dialog.py index f6b2724..aede984 100644 --- a/dcs_code_injector/version_dialog.py +++ b/dcs_code_injector/version_dialog.py @@ -1,12 +1,13 @@ -from . import VERSION +from . import VERSION, LOGO + from PySide6.QtWidgets import * +from PySide6.QtGui import * class AboutDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("About DCS Code Injector") - # self.setWindowIcon(QIcon(ICON)) layout = QVBoxLayout() @@ -14,11 +15,15 @@ def __init__(self, parent=None): lbl_title = QLabel(title) lbl_title.setStyleSheet("font-size: 14pt") + lbl_image = QLabel() + lbl_image.setPixmap(QPixmap(LOGO)) + msg = f"Version {VERSION}" - msg += f"\n(c) Niels Vaes" + msg += f"\n©️ Niels Vaes" lbl_version = QLabel(msg) layout.addWidget(lbl_title) + layout.addWidget(lbl_image) layout.addWidget(lbl_version) close_button = QPushButton("Close")