From 3815bc0c80e810883c1f0da7b9ea97994b3ec60e Mon Sep 17 00:00:00 2001 From: Siddhant Sharma Date: Mon, 6 Apr 2026 18:39:48 +0530 Subject: [PATCH 1/4] enh: add a toolbar and move import button to toolbar --- src/memorytext/windows/main_window.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/memorytext/windows/main_window.py b/src/memorytext/windows/main_window.py index e71a49f..4bf81dd 100644 --- a/src/memorytext/windows/main_window.py +++ b/src/memorytext/windows/main_window.py @@ -2,16 +2,18 @@ QMainWindow, QHBoxLayout, QVBoxLayout, - # QLayout, + QToolBar, QWidget, - QPushButton, ) -from PySide6.QtCore import QModelIndex +from PySide6.QtCore import Qt, QModelIndex +from PySide6.QtGui import QAction, QIcon from memorytext.views.chat_view import ChatView from memorytext.views.chat_list_view import ChatListView from memorytext.windows.import_window import ImportWindow from memorytext.services import message_service +IMPORT_ICON = QIcon.fromTheme("gtk-add") + class MainWindow(QMainWindow): def __init__(self): @@ -23,12 +25,18 @@ def __init__(self): central_widget.setLayout(main_layout) self.setCentralWidget(central_widget) + # Toolbar + toolbar = QToolBar("Main Toolbar") + self.addToolBar(toolbar) + self.import_action = QAction(IMPORT_ICON, "Import Chat") + toolbar.addAction(self.import_action) + toolbar.setMovable(False) + toolbar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon) + # Sidebar - self.import_button = QPushButton("Import chat") self.sidebar = ChatListView() self.sidebar.setFixedWidth(250) sidebar_layout = QVBoxLayout() - sidebar_layout.addWidget(self.import_button) sidebar_layout.addWidget(self.sidebar) # Messages @@ -39,7 +47,7 @@ def __init__(self): # Import Window self.import_window = None - self.import_button.clicked.connect(self.import_new_chat) + self.import_action.triggered.connect(self.import_new_chat) def load_messages(self, index: QModelIndex): convo_id = self.sidebar.model().get_id(index) # pyright: ignore[reportAttributeAccessIssue] From ef7e2fc284a8a6a410c26b468637839e11ae3c05 Mon Sep 17 00:00:00 2001 From: Siddhant Sharma Date: Mon, 6 Apr 2026 20:14:39 +0530 Subject: [PATCH 2/4] enh: add context menu to sidebar with a delete option. --- CHANGELOG.md | 16 ++++- src/memorytext/views/chat_list_view.py | 81 ++++++++++++++++++++++++-- src/memorytext/windows/main_window.py | 8 ++- 3 files changed, 98 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 157fb68..3afb90c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,23 @@ +## [Unreleased] + +### Added + +1. Add a simple toolbar at the top. +2. Add a context menu to the chat list sidebar with a delete option. + +### Changed + +1. Move the import button to the toolbar. + + ## [v0.6.0] -## Added +### Added 1. Add a common engine for the app. 2. Add storage modules to keep the services layer lighter. -## Changed +### Changed 1. Use a session factory for getting db sessions. 2. Reduce the maximum width of message bubbles. diff --git a/src/memorytext/views/chat_list_view.py b/src/memorytext/views/chat_list_view.py index 38a871a..ac63e3a 100644 --- a/src/memorytext/views/chat_list_view.py +++ b/src/memorytext/views/chat_list_view.py @@ -1,16 +1,89 @@ -from PySide6.QtWidgets import QListView +from collections.abc import Callable +from PySide6.QtWidgets import ( + QHBoxLayout, + QLabel, + QListView, + QMainWindow, + QMenu, + QPushButton, + QVBoxLayout, + QWidget, +) +from PySide6.QtCore import Qt, QPoint, Signal +from PySide6.QtGui import QAction, QIcon + from memorytext.models.chat_list import ChatList -from memorytext.services.chat_service import get_chats +from memorytext.services import chat_service + +DELETE_ICON = QIcon.fromTheme("edit-delete") class ChatListView(QListView): + chat_deleted = Signal(int) + def __init__(self): super().__init__() - chat_list = get_chats() + chat_list = chat_service.get_chats() self.chats = ChatList(chat_list) self.setModel(self.chats) + self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) + self.customContextMenuRequested.connect(self.show_context_menu) def update_data(self): - chat_list = get_chats() + chat_list = chat_service.get_chats() self.chats.set_data(chat_list) + + def show_context_menu(self, position: QPoint): + menu = QMenu(self) + index = self.indexAt(position) + if index.isValid(): + delete_action = QAction(DELETE_ICON, "Delete Chat", self) + menu.addAction(delete_action) + action = menu.exec(self.mapToGlobal(position)) + + if action == delete_action: + self.delete_conversation_id = index.data(role=Qt.ItemDataRole.UserRole) + text = "Are you sure you want to delete the chat?" + self.confirm = ConfirmationWindow(text, self.delete_chat_action) + self.confirm.show() + + def delete_chat_action(self): + if self.delete_conversation_id: + try: + chat_service.delete_chat(self.delete_conversation_id) + self.chat_deleted.emit(self.delete_conversation_id) + except Exception as e: + print(e) + raise + self.confirm.close() + self.update_data() + + +class ConfirmationWindow(QMainWindow): + def __init__(self, text: str, ok_action: Callable): + super().__init__() + self.setWindowTitle("Confirm Delete") + self.setFixedSize(500, 200) + + button_layout = QHBoxLayout() + layout = QVBoxLayout() + + self.label = QLabel(text) + layout.addWidget(self.label) + + self.ok_button = QPushButton("Ok") + button_layout.addWidget(self.ok_button) + + self.cancel_button = QPushButton("Cancel") + button_layout.addWidget(self.cancel_button) + + layout.addLayout(button_layout) + + self.cancel_button.clicked.connect(self.close) + self.ok_button.clicked.connect(ok_action) + + container = QWidget() + container.setLayout(layout) + + self.setCentralWidget(container) diff --git a/src/memorytext/windows/main_window.py b/src/memorytext/windows/main_window.py index 4bf81dd..a140372 100644 --- a/src/memorytext/windows/main_window.py +++ b/src/memorytext/windows/main_window.py @@ -12,7 +12,7 @@ from memorytext.windows.import_window import ImportWindow from memorytext.services import message_service -IMPORT_ICON = QIcon.fromTheme("gtk-add") +IMPORT_ICON = QIcon.fromTheme("list-add") class MainWindow(QMainWindow): @@ -36,6 +36,7 @@ def __init__(self): # Sidebar self.sidebar = ChatListView() self.sidebar.setFixedWidth(250) + self.sidebar.chat_deleted.connect(self.handle_chat_deletion) sidebar_layout = QVBoxLayout() sidebar_layout.addWidget(self.sidebar) @@ -57,3 +58,8 @@ def import_new_chat(self): if self.import_window is None: self.import_window = ImportWindow(parent=self) self.import_window.show() + + def handle_chat_deletion(self, deleted_conversation_id: int): + self.chat_area.set_messages( + deleted_conversation_id, message_service.get_messages + ) From 1e449536d1d47662580771b89d6173f2858e9fc1 Mon Sep 17 00:00:00 2001 From: Siddhant Sharma Date: Mon, 6 Apr 2026 23:21:58 +0530 Subject: [PATCH 3/4] enh: add an edit chat title option to chat context menu. --- CHANGELOG.md | 4 +- src/memorytext/services/chat_service.py | 10 ++++ src/memorytext/storage/chats_repo.py | 10 +++- src/memorytext/views/chat_list_view.py | 24 +++++++++ src/memorytext/windows/edit_field_window.py | 54 +++++++++++++++++++++ 5 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/memorytext/windows/edit_field_window.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 3afb90c..f13d0b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,9 @@ ### Added 1. Add a simple toolbar at the top. -2. Add a context menu to the chat list sidebar with a delete option. +2. Add a context menu to the chat list sidebar with options: + - Edit Chat Title + - Delete ### Changed diff --git a/src/memorytext/services/chat_service.py b/src/memorytext/services/chat_service.py index 31b334b..a892060 100644 --- a/src/memorytext/services/chat_service.py +++ b/src/memorytext/services/chat_service.py @@ -57,3 +57,13 @@ def delete_chat_by_title(title: str): except SQLAlchemyError: session.rollback() raise + + +def edit_chat_title(conversation_id: int, new_title: str): + with get_db_session() as session: + try: + chrepo.edit_chat_title(session, conversation_id, new_title) + session.commit() + except SQLAlchemyError: + session.rollback() + raise diff --git a/src/memorytext/storage/chats_repo.py b/src/memorytext/storage/chats_repo.py index 3e82c63..17446a0 100644 --- a/src/memorytext/storage/chats_repo.py +++ b/src/memorytext/storage/chats_repo.py @@ -1,6 +1,6 @@ from __future__ import annotations from typing import TYPE_CHECKING -from sqlalchemy import delete, select +from sqlalchemy import delete, select, update from sqlalchemy.orm import selectinload from memorytext.models.core import Conversation @@ -45,3 +45,11 @@ def delete_chat_by_title(session: Session, title: str): select(Conversation.id).where(Conversation.title == title) ) delete_chat(session, conversation_id) + + +def edit_chat_title(session: Session, conversation_id: int | None, new_title: str): + session.execute( + update(Conversation) + .where(Conversation.id == conversation_id) + .values(title=new_title) + ) diff --git a/src/memorytext/views/chat_list_view.py b/src/memorytext/views/chat_list_view.py index ac63e3a..3021a09 100644 --- a/src/memorytext/views/chat_list_view.py +++ b/src/memorytext/views/chat_list_view.py @@ -14,8 +14,10 @@ from memorytext.models.chat_list import ChatList from memorytext.services import chat_service +from memorytext.windows.edit_field_window import EditFieldWindow DELETE_ICON = QIcon.fromTheme("edit-delete") +EDIT_TITLE_ICON = QIcon.fromTheme("document-edit") class ChatListView(QListView): @@ -39,7 +41,10 @@ def show_context_menu(self, position: QPoint): index = self.indexAt(position) if index.isValid(): delete_action = QAction(DELETE_ICON, "Delete Chat", self) + edit_title_action = QAction(EDIT_TITLE_ICON, "Edit Chat Title", self) + menu.addAction(edit_title_action) menu.addAction(delete_action) + action = menu.exec(self.mapToGlobal(position)) if action == delete_action: @@ -48,6 +53,25 @@ def show_context_menu(self, position: QPoint): self.confirm = ConfirmationWindow(text, self.delete_chat_action) self.confirm.show() + if action == edit_title_action: + self.edit_conversation_id = index.data(role=Qt.ItemDataRole.UserRole) + text = "Please enter a new title." + self.edit_window = EditFieldWindow( + "Edit Chat Title", "New Title", text, self.edit_chat_title_action + ) + self.edit_window.show() + + def edit_chat_title_action(self): + new_title = self.edit_window.field_box.text() + if new_title and self.edit_conversation_id: + try: + chat_service.edit_chat_title(self.edit_conversation_id, new_title) + except Exception as e: + print(e) + raise + self.edit_window.close() + self.update_data() + def delete_chat_action(self): if self.delete_conversation_id: try: diff --git a/src/memorytext/windows/edit_field_window.py b/src/memorytext/windows/edit_field_window.py new file mode 100644 index 0000000..0410f65 --- /dev/null +++ b/src/memorytext/windows/edit_field_window.py @@ -0,0 +1,54 @@ +from __future__ import annotations +from typing import TYPE_CHECKING + +from PySide6.QtWidgets import ( + QFormLayout, + QMainWindow, + QHBoxLayout, + QVBoxLayout, + QLineEdit, + QPushButton, + QWidget, + QLabel, +) + +if TYPE_CHECKING: + from collections.abc import Callable + + +class EditFieldWindow(QMainWindow): + def __init__( + self, window_title: str, field_name: str, text: str, ok_action: Callable + ): + super().__init__() + self.setWindowTitle(window_title) + self.setFixedSize(500, 200) + + button_layout = QHBoxLayout() + form_layout = QFormLayout() + layout = QVBoxLayout() + + self.label = QLabel(text) + layout.addWidget(self.label) + + self.field_box = QLineEdit() + self.field_box.setMaximumWidth(150) + + self.ok_button = QPushButton("Ok") + button_layout.addWidget(self.ok_button) + + self.cancel_button = QPushButton("Cancel") + button_layout.addWidget(self.cancel_button) + + form_layout.addRow(f"{field_name}:", self.field_box) + + layout.addLayout(form_layout) + layout.addLayout(button_layout) + + self.cancel_button.clicked.connect(self.close) + self.ok_button.clicked.connect(ok_action) + + container = QWidget() + container.setLayout(layout) + + self.setCentralWidget(container) From 3e989abaef37e5b78f9364e7593453bd09e977af Mon Sep 17 00:00:00 2001 From: Siddhant Sharma Date: Tue, 7 Apr 2026 16:05:26 +0530 Subject: [PATCH 4/4] enh: move helper windows to separate module. --- CHANGELOG.md | 3 +- src/memorytext/views/chat_list_view.py | 38 +---- src/memorytext/windows/edit_field_window.py | 54 ------- src/memorytext/windows/helper_windows.py | 164 ++++++++++++++++++++ src/memorytext/windows/import_window.py | 93 +---------- 5 files changed, 172 insertions(+), 180 deletions(-) delete mode 100644 src/memorytext/windows/edit_field_window.py create mode 100644 src/memorytext/windows/helper_windows.py diff --git a/CHANGELOG.md b/CHANGELOG.md index f13d0b8..1cee404 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## [Unreleased] +## [v0.7.0] ### Added @@ -10,6 +10,7 @@ ### Changed 1. Move the import button to the toolbar. +2. Move helper windows to separate module. ## [v0.6.0] diff --git a/src/memorytext/views/chat_list_view.py b/src/memorytext/views/chat_list_view.py index 3021a09..60ff80e 100644 --- a/src/memorytext/views/chat_list_view.py +++ b/src/memorytext/views/chat_list_view.py @@ -1,20 +1,13 @@ -from collections.abc import Callable from PySide6.QtWidgets import ( - QHBoxLayout, - QLabel, QListView, - QMainWindow, QMenu, - QPushButton, - QVBoxLayout, - QWidget, ) from PySide6.QtCore import Qt, QPoint, Signal from PySide6.QtGui import QAction, QIcon from memorytext.models.chat_list import ChatList from memorytext.services import chat_service -from memorytext.windows.edit_field_window import EditFieldWindow +from memorytext.windows.helper_windows import ConfirmationWindow, EditFieldWindow DELETE_ICON = QIcon.fromTheme("edit-delete") EDIT_TITLE_ICON = QIcon.fromTheme("document-edit") @@ -82,32 +75,3 @@ def delete_chat_action(self): raise self.confirm.close() self.update_data() - - -class ConfirmationWindow(QMainWindow): - def __init__(self, text: str, ok_action: Callable): - super().__init__() - self.setWindowTitle("Confirm Delete") - self.setFixedSize(500, 200) - - button_layout = QHBoxLayout() - layout = QVBoxLayout() - - self.label = QLabel(text) - layout.addWidget(self.label) - - self.ok_button = QPushButton("Ok") - button_layout.addWidget(self.ok_button) - - self.cancel_button = QPushButton("Cancel") - button_layout.addWidget(self.cancel_button) - - layout.addLayout(button_layout) - - self.cancel_button.clicked.connect(self.close) - self.ok_button.clicked.connect(ok_action) - - container = QWidget() - container.setLayout(layout) - - self.setCentralWidget(container) diff --git a/src/memorytext/windows/edit_field_window.py b/src/memorytext/windows/edit_field_window.py deleted file mode 100644 index 0410f65..0000000 --- a/src/memorytext/windows/edit_field_window.py +++ /dev/null @@ -1,54 +0,0 @@ -from __future__ import annotations -from typing import TYPE_CHECKING - -from PySide6.QtWidgets import ( - QFormLayout, - QMainWindow, - QHBoxLayout, - QVBoxLayout, - QLineEdit, - QPushButton, - QWidget, - QLabel, -) - -if TYPE_CHECKING: - from collections.abc import Callable - - -class EditFieldWindow(QMainWindow): - def __init__( - self, window_title: str, field_name: str, text: str, ok_action: Callable - ): - super().__init__() - self.setWindowTitle(window_title) - self.setFixedSize(500, 200) - - button_layout = QHBoxLayout() - form_layout = QFormLayout() - layout = QVBoxLayout() - - self.label = QLabel(text) - layout.addWidget(self.label) - - self.field_box = QLineEdit() - self.field_box.setMaximumWidth(150) - - self.ok_button = QPushButton("Ok") - button_layout.addWidget(self.ok_button) - - self.cancel_button = QPushButton("Cancel") - button_layout.addWidget(self.cancel_button) - - form_layout.addRow(f"{field_name}:", self.field_box) - - layout.addLayout(form_layout) - layout.addLayout(button_layout) - - self.cancel_button.clicked.connect(self.close) - self.ok_button.clicked.connect(ok_action) - - container = QWidget() - container.setLayout(layout) - - self.setCentralWidget(container) diff --git a/src/memorytext/windows/helper_windows.py b/src/memorytext/windows/helper_windows.py new file mode 100644 index 0000000..11146e1 --- /dev/null +++ b/src/memorytext/windows/helper_windows.py @@ -0,0 +1,164 @@ +from __future__ import annotations +from typing import TYPE_CHECKING + +from PySide6.QtWidgets import ( + QComboBox, + QFormLayout, + QMainWindow, + QHBoxLayout, + QVBoxLayout, + QLineEdit, + QPushButton, + QWidget, + QLabel, +) +from PySide6.QtCore import Slot +from memorytext.services import chat_service + +if TYPE_CHECKING: + from collections.abc import Callable + + +class EditFieldWindow(QMainWindow): + def __init__( + self, window_title: str, field_name: str, text: str, ok_action: Callable + ): + super().__init__() + self.setWindowTitle(window_title) + self.setFixedSize(500, 200) + + button_layout = QHBoxLayout() + form_layout = QFormLayout() + layout = QVBoxLayout() + + self.label = QLabel(text) + layout.addWidget(self.label) + + self.field_box = QLineEdit() + self.field_box.setMaximumWidth(150) + + self.ok_button = QPushButton("Ok") + button_layout.addWidget(self.ok_button) + + self.cancel_button = QPushButton("Cancel") + button_layout.addWidget(self.cancel_button) + + form_layout.addRow(f"{field_name}:", self.field_box) + + layout.addLayout(form_layout) + layout.addLayout(button_layout) + + self.cancel_button.clicked.connect(self.close) + self.ok_button.clicked.connect(ok_action) + + container = QWidget() + container.setLayout(layout) + + self.setCentralWidget(container) + + +class ErrorWindow(QMainWindow): + def __init__(self, error: str): + super().__init__() + self.setWindowTitle("Error") + self.setFixedSize(500, 200) + + self.error_text = QLabel(text=error) + self.ok_button = QPushButton("Ok") + + self.ok_button.clicked.connect(self.close) + + layout = QVBoxLayout() + layout.addWidget(self.error_text) + layout.addWidget(self.ok_button) + + container = QWidget() + container.setLayout(layout) + + self.setCentralWidget(container) + + +class SelectUserWindow(QMainWindow): + def __init__(self, service: Callable[[str], set[str]], title: str): + super().__init__() + self.service = service + self.chat_title = title + self.initUI() + + def initUI(self): + self.participants = self.service(self.chat_title) + self.setWindowTitle("Select your username") + self.setGeometry(100, 100, 300, 200) + + button_layout = QHBoxLayout() + layout = QVBoxLayout() + + self.comboBox = QComboBox() + self.comboBox.addItems(self.participants) # pyright: ignore[reportArgumentType] + layout.addWidget(self.comboBox) + + self.default_select = str(next((name for name in self.participants), None)) + self.comboBox.setCurrentText(self.default_select) + + self.label = QLabel(f"Selected username: {self.default_select}") + layout.addWidget(self.label) + + self.ok_button = QPushButton("Ok") + button_layout.addWidget(self.ok_button) + + self.cancel_button = QPushButton("Cancel") + button_layout.addWidget(self.cancel_button) + + layout.addLayout(button_layout) + + self.cancel_button.clicked.connect(self.close) + self.ok_button.clicked.connect(self.set_username) + self.comboBox.currentTextChanged.connect(self.on_selection_changed) + + container = QWidget() + container.setLayout(layout) + + self.setCentralWidget(container) + + @Slot(str) + def on_selection_changed(self, text): + self.label.setText(f"Selected username: {text}") + + @Slot() + def set_username(self): + try: + username = self.comboBox.currentText() + chat_service.set_username(self.chat_title, username) + except Exception as e: + self.error_window = ErrorWindow(error=f"Error: {e}") + self.error_window.show() + self.close() + + +class ConfirmationWindow(QMainWindow): + def __init__(self, text: str, ok_action: Callable): + super().__init__() + self.setWindowTitle("Confirm Delete") + self.setFixedSize(500, 200) + + button_layout = QHBoxLayout() + layout = QVBoxLayout() + + self.label = QLabel(text) + layout.addWidget(self.label) + + self.ok_button = QPushButton("Ok") + button_layout.addWidget(self.ok_button) + + self.cancel_button = QPushButton("Cancel") + button_layout.addWidget(self.cancel_button) + + layout.addLayout(button_layout) + + self.cancel_button.clicked.connect(self.close) + self.ok_button.clicked.connect(ok_action) + + container = QWidget() + container.setLayout(layout) + + self.setCentralWidget(container) diff --git a/src/memorytext/windows/import_window.py b/src/memorytext/windows/import_window.py index 18622d5..de46cca 100644 --- a/src/memorytext/windows/import_window.py +++ b/src/memorytext/windows/import_window.py @@ -1,25 +1,20 @@ from __future__ import annotations -from typing import TYPE_CHECKING - from PySide6.QtWidgets import ( - QComboBox, QFileDialog, QFormLayout, QMainWindow, - QHBoxLayout, - QVBoxLayout, QLineEdit, QPushButton, QWidget, - QLabel, ) -from PySide6.QtCore import Slot from sqlalchemy.exc import IntegrityError + from memorytext.io.import_wa import import_whatsapp from memorytext.services import chat_service - -if TYPE_CHECKING: - from collections.abc import Callable +from memorytext.windows.helper_windows import ( + ErrorWindow, + SelectUserWindow, +) class ImportWindow(QMainWindow): @@ -87,81 +82,3 @@ def import_chat(self): self.error_window.show() self.close() - - -class SelectUserWindow(QMainWindow): - def __init__(self, service: Callable[[str], set[str]], title: str): - super().__init__() - self.service = service - self.chat_title = title - self.initUI() - - def initUI(self): - self.participants = self.service(self.chat_title) - self.setWindowTitle("Select your username") - self.setGeometry(100, 100, 300, 200) - - button_layout = QHBoxLayout() - layout = QVBoxLayout() - - self.comboBox = QComboBox() - self.comboBox.addItems(self.participants) # pyright: ignore[reportArgumentType] - layout.addWidget(self.comboBox) - - self.default_select = str(next((name for name in self.participants), None)) - self.comboBox.setCurrentText(self.default_select) - - self.label = QLabel(f"Selected username: {self.default_select}") - layout.addWidget(self.label) - - self.ok_button = QPushButton("Ok") - button_layout.addWidget(self.ok_button) - - self.cancel_button = QPushButton("Cancel") - button_layout.addWidget(self.cancel_button) - - layout.addLayout(button_layout) - - self.cancel_button.clicked.connect(self.close) - self.ok_button.clicked.connect(self.set_username) - self.comboBox.currentTextChanged.connect(self.on_selection_changed) - - container = QWidget() - container.setLayout(layout) - - self.setCentralWidget(container) - - @Slot(str) - def on_selection_changed(self, text): - self.label.setText(f"Selected username: {text}") - - @Slot() - def set_username(self): - try: - username = self.comboBox.currentText() - chat_service.set_username(self.chat_title, username) - except Exception as e: - self.error_window = ErrorWindow(error=f"Error: {e}") - self.error_window.show() - self.close() - - -class ErrorWindow(QMainWindow): - def __init__(self, error: str): - super().__init__() - self.setWindowTitle("Error") - self.setFixedSize(500, 200) - - self.error_text = QLabel(text=error) - self.ok_button = QPushButton("Ok") - - self.ok_button.clicked.connect(self.close) - - layout = QVBoxLayout() - layout.addWidget(self.error_text) - layout.addWidget(self.ok_button) - - container = QWidget() - container.setLayout(layout) - - self.setCentralWidget(container)