Files
msg-viewer-with-eml-export/extra-options/simple-PyQt6-gui.py
2025-03-16 21:24:17 +00:00

219 lines
7.6 KiB
Python

from PyQt6.QtWidgets import QApplication, QMainWindow, QTextEdit, QMenuBar
from PyQt6.QtWidgets import QTabWidget, QVBoxLayout, QWidget, QFileDialog, QTabBar
from PyQt6.QtGui import QAction
from PyQt6.QtCore import Qt, QEvent
import os, sys
application_name = "MSG Viewer"
"""
This is simple PyQt6 interface to open text files in tabs.
"""
class TabContent(QWidget):
def __init__(self):
super().__init__()
# Create the text editor for each tab
self.text_area = QTextEdit(self)
self.text_area.setObjectName("Container")
self.text_area.setStyleSheet(
"""#Container {
background: qlineargradient(x1:0 y1:0, x2:1 y2:1, stop:0 #051c2a stop:1 #44315f);
border-radius: 5px;
}"""
)
layout = QVBoxLayout(self)
layout.addWidget(self.text_area)
self.setLayout(layout)
def setText(self, text):
self.text_area.setPlainText(text)
def getText(self):
return self.text_area.toPlainText()
def setReadOnly(self, readonly):
self.text_area.setReadOnly(readonly)
def isReadOnly(self):
return self.text_area.isReadOnly()
class AppMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# Create the tab widget that will hold the tabs
self.tabs = QTabWidget(self)
self.tabs.setTabsClosable(True) # Enable the close button on tabs
self.tabs.setMovable(True) # Enable the moving (reordering) of tabs
self.tabs.tabCloseRequested.connect(self.close_tab) # Connect to tab close event
self.tabs.currentChanged.connect(self.on_tab_changed) # Listen for tab change event
self.setCentralWidget(self.tabs)
# Enable middle-click closing for tabs
self.tabs.tabBar().installEventFilter(self)
# Set the window title and size
self.setWindowTitle(application_name)
self.setGeometry(100, 100, 800, 600)
# Create the menu bar with toolbar buttons
self.createToolbar()
def createToolbar(self):
# Create a menu bar
self.menuBar = QMenuBar()
self.setMenuBar(self.menuBar)
# Action to open a file
self.open_btn = QAction("Open", self)
self.open_btn.triggered.connect(self.open_file)
self.open_btn.setStatusTip("Open MSG file")
self.menuBar.addAction(self.open_btn)
# Action to toggle between Edit and Read-Only modes
self.edit_btn = QAction("ReadOnly", self) # Default to "ReadOnly"
self.edit_btn.setStatusTip("Make message read-only")
self.edit_btn.triggered.connect(self.edit_file)
self.edit_btn.setVisible(False)
self.menuBar.addAction(self.edit_btn)
# Action to save the file
self.save_btn = QAction("Extract", self)
self.save_btn.setStatusTip("Save current file")
self.save_btn.triggered.connect(self.save_file)
self.save_btn.setVisible(False)
self.menuBar.addAction(self.save_btn)
self.menuBar.setStyleSheet("""
QMenuBar {
background-color: #9a9c9a;
border-bottom: 1px solid #000000;
padding: 2px;
}
QMenuBar::item {
background-color: #292626;
padding: 5px 10px;
border: 1px solid transparent;
margin: 2px;
font-weight: bold;
}
QMenuBar::item:selected {
background-color: #d0d0d0;
border: 1px solid #999999;
color: black;
border-radius: 3px;
}
QMenuBar::item:pressed {
background-color: #b0b0b0;
}
""")
def open_file(self):
# Open a file using a file dialog
file, _ = QFileDialog.getOpenFileName(
self,
"Open File",
"",
"All Files (*);;HTML Files (*.html);;Text Files (*.txt)"
)
if file:
try:
# Read the content of the file
with open(file, 'r', encoding="utf-8") as f:
file_content = f.read()
# Create a new tab
tab_content = TabContent()
tab_content.setText(file_content)
tab_index = self.tabs.addTab(tab_content, os.path.basename(file))
self.tabs.setCurrentIndex(tab_index)
# Enable save and edit actions
self.save_btn.setVisible(True)
self.edit_btn.setVisible(True)
# Set the editor to Read-Only mode by default
tab_content.setReadOnly(True)
self.edit_btn.setText("Edit")
except Exception as e:
print(f"Error opening file: {e}")
def edit_file(self):
# Get the current active tab
current_tab = self.tabs.currentWidget()
# Toggle between Edit and ReadOnly modes
if self.edit_btn.text() == "Edit":
current_tab.setReadOnly(False) # Allow editing
self.edit_btn.setText("ReadOnly")
self.edit_btn.setStatusTip("Make message read-only")
else:
current_tab.setReadOnly(True) # Make read-only
self.edit_btn.setText("Edit")
self.edit_btn.setStatusTip("Allows Editing of the message")
def save_file(self):
# Get the current active tab
current_tab = self.tabs.currentWidget()
# Open a file dialog to save the file
file, _ = QFileDialog.getSaveFileName(
self,
"Save File",
"",
"All Files (*);;HTML Files (*.html);;Text Files (*.txt)"
)
if file:
try:
# Save the content of the text area to the file
with open(file, 'w', encoding="utf-8") as f:
f.write(current_tab.getText())
self.setWindowTitle(f"{application_name} - {os.path.basename(file)}")
except Exception as e:
print(f"Error saving file: {e}")
def close_tab(self, index):
# This function will be triggered when a user clicks on the "X" button of a tab
widget = self.tabs.widget(index)
if widget:
self.tabs.removeTab(index)
widget.deleteLater() # Free up the memory of the widget
def on_tab_changed(self, index):
# This function is called when the user switches between tabs
current_tab = self.tabs.widget(index)
if current_tab:
# Set the "Edit/ReadOnly" button text based on the current tab's state
if current_tab.isReadOnly():
self.edit_btn.setText("Edit")
self.edit_btn.setStatusTip("Allows Editing of the message")
else:
self.edit_btn.setText("ReadOnly")
self.edit_btn.setStatusTip("Make message read-only")
def eventFilter(self, source, event):
# Listen for middle mouse button clicks to close tabs
if source == self.tabs.tabBar() and event.type() == QEvent.Type.MouseButtonPress:
if event.button() == Qt.MouseButton.MiddleButton:
index = self.tabs.tabBar().tabAt(event.pos())
if index != -1:
self.tabs.removeTab(index)
return True
return super().eventFilter(source, event)
def main():
app = QApplication(sys.argv)
app.setStyle("Fusion")
app_window = AppMainWindow()
app_window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()