import os
from PySide6.QtCore import Qt
from PySide6.QtGui import QIcon, QGuiApplication
from PySide6.QtWidgets import (
QMainWindow,
QWidget, QHBoxLayout, QVBoxLayout, QSizePolicy
)
from tommy.controller.controller import Controller
from tommy.support.constant_variables import (
text_font)
from tommy.view.graph_view import GraphView
from tommy.view.imported_files_view.file_label import FileLabel
from tommy.view.imported_files_view.imported_files_view import (
ImportedFilesView)
from tommy.view.menu_bar import MenuBar
from tommy.view.plot_selection_view import (
PlotSelectionView)
from tommy.view.selected_information_view import SelectedInformationView
from tommy.view.preprocessing_view import (
PreprocessingView)
from tommy.view.settings_view.model_params_view import (
ModelParamsView)
from tommy.view.supporting_components.custom_splitter.custom_splitter_component import \
CustomSplitter
from tommy.view.topic_view.fetched_topics_view import \
FetchedTopicsView
from tommy.view.topic_view.topic_entity_component.topic_entity import (
TopicEntity)
from tommy.support.application_settings import get_assets_folder
[docs]
class MainWindow(QMainWindow):
"""Main window class for the topic modelling application"""
[docs]
def __init__(self) -> None:
"""Initialize the main window."""
super().__init__()
# Create the main Controller
self._controller: Controller = Controller()
# Initialize window
self.setWindowTitle("TOMMY")
self.set_initial_window_size()
self.setWindowIcon(
QIcon(f"{os.path.join(get_assets_folder(), "tommy.png")}"))
self.setStyleSheet(f"""
QMainWindow {{
background-color: white;
font-size: 15px;
font-family: {text_font};
border: none;
}}
QMainWindow::children {{
font-family: {text_font};
}}
QSplitter::handle {{
background-color: rgba(200, 200, 200, 200);
border: none;
}}
""")
# Create the main layout
self.layout = QHBoxLayout()
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.setSpacing(0)
# Create the custom splitter to handle resizing
self.splitter = CustomSplitter(Qt.Horizontal)
self.splitter.setStyleSheet("border: none;"
"background-color: white;")
self.splitter.setContentsMargins(0, 0, 0, 0)
self.left_container = QWidget()
self.left_layout = QVBoxLayout(self.left_container)
self.left_layout.setContentsMargins(0, 0, 0, 0)
self.left_layout.setSpacing(0)
self.center_container = QWidget()
self.center_layout = QVBoxLayout(self.center_container)
self.center_layout.setContentsMargins(0, 0, 0, 0)
self.center_layout.setSpacing(0)
self.right_container = QWidget()
self.right_layout = QVBoxLayout(self.right_container)
self.right_layout.setContentsMargins(0, 0, 0, 0)
self.right_layout.setSpacing(0)
self.splitter.addWidget(self.left_container)
self.splitter.addWidget(self.center_container)
self.splitter.addWidget(self.right_container)
# Adjust size policies and minimum widths
self.left_container.setSizePolicy(QSizePolicy.Fixed,
QSizePolicy.Expanding)
self.right_container.setSizePolicy(QSizePolicy.Expanding,
QSizePolicy.Expanding)
self.center_container.setSizePolicy(QSizePolicy.Expanding,
QSizePolicy.Expanding)
self.layout.addWidget(self.splitter)
# Set the central widget
central_widget = QWidget()
central_widget.setLayout(self.layout)
self.setCentralWidget(central_widget)
# Initialize the menu bar
self.setMenuBar(MenuBar(self,
self._controller.project_settings_controller,
self._controller.saving_loading_controller,
self._controller.export_controller,
self._controller.topic_modelling_controller))
# Create widgets
self.preprocessing_view = PreprocessingView(
self._controller.stopwords_controller,
self._controller.synonyms_controller,
self._controller.topic_modelling_controller)
self.graph_view = GraphView()
self.plot_selection_view = PlotSelectionView(
self._controller.graph_controller,
self._controller.config_controller,
self.graph_view
)
self.imported_files_view = ImportedFilesView(
self._controller.corpus_controller,
self._controller.topic_modelling_controller,
self._controller.config_controller
)
self.model_params_view = ModelParamsView(
self._controller.model_parameters_controller,
self._controller.language_controller,
self._controller.config_controller,
self._controller.topic_modelling_controller)
self.fetched_topics_view = FetchedTopicsView(
self._controller.graph_controller,
self._controller.model_parameters_controller)
self.selected_information_view = SelectedInformationView(
self._controller.graph_controller,
self._controller.model_parameters_controller)
# Initialize widgets
self.left_layout.addWidget(self.model_params_view)
self.left_layout.addWidget(self.preprocessing_view)
self.center_layout.addWidget(self.plot_selection_view)
self.center_layout.addWidget(self.graph_view)
self.center_layout.addWidget(self.imported_files_view)
self.right_layout.addWidget(self.fetched_topics_view)
self.right_layout.addWidget(self.selected_information_view)
# Adjust the splitter stretch factors
self.splitter.setStretchFactor(0, 1)
self.splitter.setStretchFactor(1, 3)
self.splitter.setStretchFactor(2,
1)
self.display_correct_initial_files()
# Initialize event handlers
self.imported_files_view.fileClicked.connect(self.on_file_clicked)
self.fetched_topics_view.topicClicked.connect(self.on_topic_clicked)
self.fetched_topics_view.topicNameChanged.connect(
self.on_topic_name_changed)
[docs]
def initialize_widget(self, widget: QWidget,
x: int, y: int, w: int, h: int) -> None:
"""
Initialize a widget on the main window.
:param widget: The widget to initialize
:param x: The x-coordinate of the widget
:param y: The y-coordinate of the widget
:param w: The width of the widget
:param h: The height of the widget
:return: None
"""
widget.setParent(self)
widget.setGeometry(x, y, w, h)
widget.show()
[docs]
def set_initial_window_size(self) -> None:
"""
Set the initial window size based on screen size.
:return: None
"""
app = QGuiApplication.instance()
screen = app.primaryScreen()
screen_geometry = screen.availableGeometry()
initial_width = max(screen_geometry.width() / 1.5, 1050)
initial_height = max(screen_geometry.height() / 1.5, 578)
self.resize(initial_width, initial_height)
[docs]
def on_file_clicked(self, file: FileLabel) -> None:
"""
Event handler for when a file is clicked.
:param file: The file that was clicked
:return: None
"""
# Show info about run if no file is selected
if not file.selected:
self.selected_information_view.display_run_info("Run Info")
return
self.selected_information_view.display_file_info(file)
[docs]
def on_topic_clicked(self, topic_entity: TopicEntity) -> None:
"""
Event handler for when a topic is clicked.
:param topic_entity: The topic that was clicked
:return: None
"""
self.imported_files_view.deselect_all_files()
self.imported_files_view.selected_label = None
# Show info about run if no topic is selected
if not topic_entity.selected:
self.imported_files_view.display_files()
self.selected_information_view.display_run_info("Run Info")
return
self.imported_files_view.on_topic_selected(topic_entity)
self.selected_information_view.display_topic_info(topic_entity)
[docs]
def on_topic_name_changed(self, topic_entity: TopicEntity) -> None:
"""
Event handler for when a topic name is changed.
:param topic_entity: The topic entity whose name was changed
:return: None
"""
if topic_entity.selected:
self.selected_information_view.display_topic_info(topic_entity)
[docs]
def display_correct_initial_files(self) -> None:
"""
Display the correct initial files in the main window.
Setting the input folder path in the project settings will
automatically notify the corpus model to extract the metadata from
the files. Once the metadata is extracted, the imported files view
will automatically get updated.
:return: None
"""
# get and immediately reset the input folder path to cause the
# project settings controller to notify its observers
path = (self._controller.project_settings_controller
.get_input_folder_path())
self._controller.project_settings_controller.set_input_folder_path(
path)
@property
def controller(self):
return self._controller
"""
This program has been developed by students from the bachelor Computer Science
at Utrecht University within the Software Project course.
© Copyright Utrecht University
(Department of Information and Computing Sciences)
"""