diff --git a/docs/source/img/tutorials_images/case_study_a5_schematic.png b/docs/source/img/tutorials_images/case_study_a5_schematic.png new file mode 100644 index 000000000..6a3a9f8fa Binary files /dev/null and b/docs/source/img/tutorials_images/case_study_a5_schematic.png differ diff --git a/docs/source/img/tutorials_images/reserves_tutorial_schematic.png b/docs/source/img/tutorials_images/reserves_tutorial_schematic.png new file mode 100644 index 000000000..ad9adfd59 Binary files /dev/null and b/docs/source/img/tutorials_images/reserves_tutorial_schematic.png differ diff --git a/docs/source/img/tutorials_images/simple_system_schematic.png b/docs/source/img/tutorials_images/simple_system_schematic.png new file mode 100644 index 000000000..0839f8bb8 Binary files /dev/null and b/docs/source/img/tutorials_images/simple_system_schematic.png differ diff --git a/spinetoolbox/opener_tester.py b/spinetoolbox/opener_tester.py new file mode 100644 index 000000000..5dd0cb0d7 --- /dev/null +++ b/spinetoolbox/opener_tester.py @@ -0,0 +1,329 @@ +import sys +from PySide6.QtCore import Qt, QSize +from PySide6.QtGui import QIcon +from PySide6.QtGui import QPixmap + +from PySide6.QtCore import QSettings + + +from PySide6.QtWidgets import ( + QApplication, + QFrame, + QHBoxLayout, + QLabel, + QMainWindow, + QVBoxLayout, + QWidget, + QSpacerItem, + QSizePolicy, + QPushButton, + QStyle, + QGroupBox, + QGridLayout +) + + +class StartUpMainWindow(QMainWindow): + def __init__(self): + super().__init__() + + self.setWindowTitle("Spine - Magic ToolBox") + # Set the window icon to the PNG version + self.setWindowIcon(QIcon("image/spinetoolbox_on_wht.png")) + self.resize(800, 600) + + self.menu_bar = self.create_menu_bar() + + menu_frame = QFrame() + menu_frame.setFrameShape(QFrame.StyledPanel) + menu_frame.setStyleSheet("background-color: lightgray;") + menu_frame.setFixedWidth(200) + + menu_layout = QVBoxLayout(menu_frame) + menu_layout.setAlignment(Qt.AlignTop) + + menu_layout.addItem(QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Fixed)) + + folder_icon = self.style().standardIcon(QStyle.SP_DirIcon) + folder_icon_button = QPushButton("Open Project...") + folder_icon_button.setIcon(folder_icon) + folder_icon_button.setIconSize(folder_icon.actualSize(QSize(32, 32))) + folder_icon_button.setFlat(True) + folder_icon_button.setStyleSheet("color: black;") + folder_icon_button.setFixedSize(130, 30) + folder_icon_button.setIconSize(folder_icon.actualSize(QSize(24, 24))) + + menu_layout.addWidget(folder_icon_button) + + # add spacer + menu_layout.addItem(QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Fixed)) + + self.dropdown_groupbox = QGroupBox() + self.dropdown_layout = QVBoxLayout() + self.dropdown_groupbox.setLayout(self.dropdown_layout) + self.dropdown_groupbox.hide() + + # Create a QPushButton for the dropdown menu item + self.menu_item_2_button = QPushButton("Recent") + self.menu_item_2_button.setFlat(True) + self.menu_item_2_button.setStyleSheet("color: black;") + + # Add an arrow icon to the button + self.arrow_icon = self.style().standardIcon(QStyle.SP_MediaPlay) + self.menu_item_2_button.setIcon(self.arrow_icon) + self.menu_item_2_button.setFixedSize(80, 30) + self.menu_item_2_button.setIconSize(self.arrow_icon.actualSize(QSize(20, 20))) + + # Connect the button to the toggle_dropdown function + self.menu_item_2_button.clicked.connect(self.toggle_dropdown) + + menu_layout.addWidget(self.menu_item_2_button) + menu_layout.addWidget(self.dropdown_groupbox) + + # Add spacer + menu_layout.addItem(QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Fixed)) + + menu_layout.addWidget(QLabel("Menu Item 3")) + + # Add central menu layout + central_widget = QWidget() + main_layout = QHBoxLayout(central_widget) + main_layout.addWidget(menu_frame) + + self.setup_central_content(main_layout) + + self.setCentralWidget(central_widget) + + def setup_central_content(self, main_layout): + central_layout = QVBoxLayout() + main_layout.addLayout(central_layout) + + row1_layout = QHBoxLayout() + row2_layout = QHBoxLayout() + + central_layout.addLayout(row1_layout) + central_layout.addLayout(row2_layout) + + self.top_button1 = QPushButton("Beginner Tutorials") + row1_layout.addWidget(self.top_button1) + self.top_button1.setStyleSheet("text-align: left;") + self.top_button1.setIcon(self.arrow_icon) + self.top_button1.setIconSize(self.arrow_icon.actualSize(QSize(20, 20))) + + self.dropdown_groupbox1 = QGroupBox() + self.dropdown_layout1 = QVBoxLayout() + self.dropdown_groupbox1.setLayout(self.dropdown_layout1) + self.dropdown_groupbox1.hide() + + self.top_button1.clicked.connect(self.toggle_dropdown1) + central_layout.addWidget(self.dropdown_groupbox1) + + self.top_button2 = QPushButton("Advanced Tutorials") + row2_layout.addWidget(self.top_button2) + self.top_button2.setStyleSheet("text-align: left;") + self.top_button2.setIcon(self.arrow_icon) + self.top_button2.setIconSize(self.arrow_icon.actualSize(QSize(20, 20))) + + self.dropdown_groupbox2 = QGroupBox() + self.dropdown_layout2 = QVBoxLayout() + self.dropdown_groupbox2.setLayout(self.dropdown_layout2) + self.dropdown_groupbox2.hide() + + self.top_button2.clicked.connect(self.toggle_dropdown2) + central_layout.addWidget(self.dropdown_groupbox2) + + central_layout.addWidget(QLabel("")) + + self.create_dropdown_cards_beginners() + + + def toggle_dropdown(self): + # Toggle the dropdown state + if self.dropdown_groupbox.isHidden(): + # Show the dropdown + self.dropdown_groupbox.show() + # Change icon to arrow down when expanding + self.menu_item_2_button.setIcon(self.style().standardIcon(QStyle.SP_TitleBarUnshadeButton)) + + # Add subitems + self.add_subitems() + else: + # Hide the dropdown + self.dropdown_groupbox.hide() + # Change icon to arrow right when collapsing + self.menu_item_2_button.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) + + def create_dropdown_cards_beginners(self): + self.card1 = self.create_card( + "This tutorial provides a step-by-step guide to setup a simple energy system with Spine Toolbox for SpineOpt. " + "Spine Toolbox is used to create a workflow with databases and tools and SpineOpt is the tool that simulates/optimizes the energy system.", + "C:/Users/ErmannoLoCascio/Spine-Toolbox/docs/source/img/tutorials_images/simple_system_schematic.png", + "Open", + self.open_tutorial1) + + self.card2 = self.create_card( + "This tutorial provides a step-by-step guide to include reserve requirements in a simple energy system with Spine Toolbox for SpineOpt.", + "C:/Users/ErmannoLoCascio/Spine-Toolbox/docs/source/img/tutorials_images/reserves_tutorial_schematic.png", + "Open", + self.open_tutorial2) + + self.card3 = self.create_card( + "Welcome to this Spine Toolbox Case Study tutorial. Case Study A5 is one of the Spine Project case studies designed to verify Toolbox and Model capabilities. To this end, it reproduces an already existing study about hydropower on the Skellefte river, which models one week of operation of the fifteen power stations along the river.", + "C:/Users/ErmannoLoCascio/Spine-Toolbox/docs/source/img/tutorials_images/case_study_a5_schematic.png", + "Open", + self.open_tutorial3) + + # Add three more cards to the second dropdown menu (Advanced Tutorials) + self.card4 = self.create_card( + "Tutorial 4 description", + "image_path_for_tutorial4.png", + "Open", + self.open_tutorial4) + + self.card5 = self.create_card( + "Tutorial 5 description", + "image_path_for_tutorial5.png", + "Open", + self.open_tutorial5) + + self.card6 = self.create_card( + "Tutorial 6 description", + "image_path_for_tutorial6.png", + "Open", + self.open_tutorial6) + + # Add the newly created cards to dropdown_layout2 + self.dropdown_layout2.addWidget(self.card4) + self.dropdown_layout2.addWidget(self.card5) + self.dropdown_layout2.addWidget(self.card6) + + def add_subitems(self): + # Clear existing subitems + for i in reversed(range(self.dropdown_layout.count())): + self.dropdown_layout.itemAt(i).widget().setParent(None) + + # Add subitems + for i in range(5): + subitem_label = QLabel(f"Subitem {i + 1}") + self.dropdown_layout.addWidget(subitem_label) + + def adjust_layout(self, expand_card1): + # Adjust layout to move Button 2 down if expand_card1 is True, else move Button 2 up + central_layout = self.centralWidget().layout() + row2_layout = central_layout.itemAt(1) + + if expand_card1: + row2_layout.addWidget(self.top_button2) + else: + row2_layout.removeWidget(self.top_button2) + row2_layout.insertWidget(1, self.top_button2) + + + def create_card(self, title, image_path, button_text, button_function): + card = QWidget() + card_layout = QHBoxLayout(card) + card.setMaximumWidth(500) + + card_image = QLabel() + pixmap = QPixmap(image_path) + smaller_pixmap = pixmap.scaled(QSize(200, 200)) + card_image.setPixmap(smaller_pixmap) + card_layout.addWidget(card_image, alignment=Qt.AlignCenter) + + card_layout.addItem(QSpacerItem(50, 50, QSizePolicy.Expanding, QSizePolicy.Minimum)) + + card_text = QLabel(title) + card_text.setWordWrap(True) + card_layout.addWidget(card_text, alignment=Qt.AlignCenter) + + card_layout.addItem(QSpacerItem(20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) + + card_button = QPushButton(button_text) + card_button.setFixedSize(80, 25) + card_layout.addWidget(card_button, alignment=Qt.AlignCenter) + + card_button.clicked.connect(button_function) + card_layout.setSpacing(10) + + self.dropdown_layout1.addWidget(card) + return card + + def toggle_dropdown1(self): + if self.dropdown_groupbox1.isHidden(): + # Show the dropdown + self.dropdown_groupbox1.show() + + # Change icon to arrow down when expanding + self.top_button1.setIcon(self.style().standardIcon(QStyle.SP_TitleBarUnshadeButton)) + + # Adjust layout to move Button 2 down + self.adjust_layout(True) + + if self.dropdown_groupbox2.isVisible(): + self.dropdown_groupbox2.hide() + self.top_button2.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) + # Adjust layout to move Button 2 up + self.adjust_layout(True) + + + else: + # Hide the dropdown + self.dropdown_groupbox1.hide() + + # Change icon to arrow right when collapsing + self.top_button1.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) + + # Adjust layout to move Button 2 up + self.adjust_layout(False) + + + def toggle_dropdown2(self): + # Toggle the dropdown state + if self.dropdown_groupbox2.isHidden(): + # Show the dropdown + self.dropdown_groupbox2.show() + # Change icon to arrow down when expanding + self.top_button2.setIcon(self.style().standardIcon(QStyle.SP_TitleBarUnshadeButton)) + + if self.dropdown_groupbox1.isVisible(): + self.dropdown_groupbox1.hide() + self.top_button1.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) + # Adjust layout to move Button 2 up + self.adjust_layout(False) + + else: + # Hide the dropdown + self.dropdown_groupbox2.hide() + # Change icon to arrow right when collapsing + self.top_button2.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) + + def open_tutorial1(self): + print("Open tutorial 1") + + def open_tutorial2(self): + print("Open tutorial 2") + + def open_tutorial3(self): + print("Open tutorial 3") + + def open_tutorial4(self): + print("Open tutorial 4") + + def open_tutorial5(self): + print("Open tutorial 5") + + def open_tutorial6(self): + print("Open tutorial 6") + + def create_menu_bar(self): + menu_bar = self.menuBar() + + + + + +app = QApplication(sys.argv) +window = StartUpMainWindow() +window.show() +sys.exit(app.exec()) + diff --git a/spinetoolbox/resources_icons_rc.py b/spinetoolbox/resources_icons_rc.py index 34b5ad9be..ff7e3aff0 100644 --- a/spinetoolbox/resources_icons_rc.py +++ b/spinetoolbox/resources_icons_rc.py @@ -32137,181 +32137,181 @@ \x00\x00\x004\x00\x02\x00\x00\x00\x01\x00\x00\x00\x05\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00T\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x8aE\xfa\xa6?\ +\x00\x00\x01\x8d\xf9j$\xab\ \x00\x00\x00x\x00\x00\x00\x00\x00\x01\x00\x00\x09\xf5\ -\x00\x00\x01\x8aE\xfa\xa6>\ +\x00\x00\x01\x8d\xf9j$\xa9\ \x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x008\x89\ -\x00\x00\x01\x8aE\xfa\xa6\xa3\ +\x00\x00\x01\x8d\xf9j$\xc6\ \x00\x00\x00\x9e\x00\x01\x00\x00\x00\x01\x00\x00\x10N\ -\x00\x00\x01\x8aE\xfa\xa6?\ +\x00\x00\x01\x8d\xf9j$\xab\ \x00\x00\x02R\x00\x00\x00\x00\x00\x01\x00\x06A\x9c\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xaf\ \x00\x00\x01\xea\x00\x00\x00\x00\x00\x01\x00\x062\x92\ -\x00\x00\x01\x8aE\xfa\xa6\xa3\ +\x00\x00\x01\x8d\xf9j$\xc5\ \x00\x00\x04p\x00\x00\x00\x00\x00\x01\x00\x06\xa8\xcd\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xae\ \x00\x00\x04\xb8\x00\x00\x00\x00\x00\x01\x00\x06\xbd\xb7\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xc1\ \x00\x00\x03D\x00\x00\x00\x00\x00\x01\x00\x06\x88\x1a\ -\x00\x00\x01\x8aE\xfa\xa6\xa3\ +\x00\x00\x01\x8d\xf9j$\xc7\ \x00\x00\x04\x98\x00\x00\x00\x00\x00\x01\x00\x06\xaa\xa1\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xae\ \x00\x00\x04\x0c\x00\x00\x00\x00\x00\x01\x00\x06\x99\xa7\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xc1\ \x00\x00\x02\x80\x00\x00\x00\x00\x00\x01\x00\x06E\xb2\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xad\ \x00\x00\x02h\x00\x00\x00\x00\x00\x01\x00\x06B\xab\ -\x00\x00\x01\x8aE\xfa\xa6\xa3\ +\x00\x00\x01\x8d\xf9j$\xc6\ \x00\x00\x03\xf6\x00\x00\x00\x00\x00\x01\x00\x06\x978\ -\x00\x00\x01\x8aE\xfa\xa6_\ +\x00\x00\x01\x8d\xf9j$\xb2\ \x00\x00\x03^\x00\x00\x00\x00\x00\x01\x00\x06\x8a3\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xae\ \x00\x00\x02\xc4\x00\x00\x00\x00\x00\x01\x00\x06Q\xfb\ -\x00\x00\x01\x8aE\xfa\xa6?\ +\x00\x00\x01\x8d\xf9j$\xac\ \x00\x00\x02.\x00\x00\x00\x00\x00\x01\x00\x06?\xec\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xaf\ \x00\x00\x03(\x00\x00\x00\x00\x00\x01\x00\x06b\xb3\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xad\ \x00\x00\x01\xbe\x00\x00\x00\x00\x00\x01\x00\x060\xaf\ -\x00\x00\x01\x8aE\xfa\xa6\x91\ +\x00\x00\x01\x8d\xf9j$\xc1\ \x00\x00\x03\x98\x00\x00\x00\x00\x00\x01\x00\x06\x94o\ -\x00\x00\x01\x8e\xd1T\x9c\xe7\ +\x00\x00\x01\x90\xeaLO\xeb\ \x00\x00\x01\xa6\x00\x00\x00\x00\x00\x01\x00\x06/\x9c\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc5\ \x00\x00\x04$\x00\x00\x00\x00\x00\x01\x00\x06\xa0\x10\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc4\ \x00\x00\x03\xb0\x00\x02\x00\x00\x00\x09\x00\x00\x00Q\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x03~\x00\x02\x00\x00\x00.\x00\x00\x00#\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x02\x0a\x00\x00\x00\x00\x00\x01\x00\x065G\ -\x00\x00\x01\x8aE\xfa\xa6\xa3\ +\x00\x00\x01\x8d\xf9j$\xc7\ \x00\x00\x04T\x00\x00\x00\x00\x00\x01\x00\x06\xa3)\ -\x00\x00\x01\x8aE\xfa\xa6\xa3\ +\x00\x00\x01\x8d\xf9j$\xc7\ \x00\x00\x03\xda\x00\x00\x00\x00\x00\x01\x00\x06\x96\x00\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xad\ \x00\x00\x02\xda\x00\x00\x00\x00\x00\x01\x00\x06T\x05\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xad\ \x00\x00\x02\x9e\x00\x00\x00\x00\x00\x01\x00\x06G\x93\ -\x00\x00\x01\x8aE\xfa\xa6\xa3\ +\x00\x00\x01\x8d\xf9j$\xc7\ \x00\x00\x03\x02\x00\x00\x00\x00\x00\x01\x00\x06`G\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xac\ \x00\x00\x02R\x00\x00\x00\x00\x00\x01\x00\x07\x071\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xba\ \x00\x00\x0bZ\x00\x00\x00\x00\x00\x01\x00\x07\xb0\xb6\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xbf\ \x00\x00\x060\x00\x00\x00\x00\x00\x01\x00\x06\xec\xdf\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xc1\ \x00\x00\x08\xd2\x00\x00\x00\x00\x00\x01\x00\x07C?\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb4\ \x00\x00\x09X\x00\x00\x00\x00\x00\x01\x00\x07Z\x11\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb5\ \x00\x00\x06\xd2\x00\x00\x00\x00\x00\x01\x00\x07\x04\xd5\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xc0\ \x00\x00\x08V\x00\x00\x00\x00\x00\x01\x00\x07={\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xbe\ \x00\x00\x094\x00\x00\x00\x00\x00\x01\x00\x07XO\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xba\ \x00\x00\x0at\x00\x00\x00\x00\x00\x01\x00\x07\x98R\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xba\ \x00\x00\x07^\x00\x00\x00\x00\x00\x01\x00\x07\x19A\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xc0\ \x00\x00\x06\xf2\x00\x00\x00\x00\x00\x01\x00\x07\x0aq\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xbd\ \x00\x00\x08\xf2\x00\x00\x00\x00\x00\x01\x00\x07U\x1d\ -\x00\x00\x01\x8e\xd1T\x9c\xe6\ +\x00\x00\x01\x90\xeaLO\xe9\ \x00\x00\x086\x00\x00\x00\x00\x00\x01\x00\x07$k\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb6\ \x00\x00\x08x\x00\x00\x00\x00\x00\x01\x00\x07?\x88\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xbe\ \x00\x00\x07\xb0\x00\x00\x00\x00\x00\x01\x00\x07\x1f<\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xbf\ \x00\x00\x08\xac\x00\x00\x00\x00\x00\x01\x00\x07@\xe4\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xbe\ \x00\x00\x06V\x00\x00\x00\x00\x00\x01\x00\x06\xee\xe8\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb2\ \x00\x00\x09\xa6\x00\x00\x00\x00\x00\x01\x00\x07vV\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb6\ \x00\x00\x07v\x00\x00\x00\x00\x00\x01\x00\x07\x1b4\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb9\ \x00\x00\x0a\xc8\x00\x00\x00\x00\x00\x01\x00\x07\x9b\x1d\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xbb\ \x00\x00\x06\x1a\x00\x00\x00\x00\x00\x01\x00\x06\xeap\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xc0\ \x00\x00\x06\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xf6\xf8\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb6\ \x00\x00\x08\x12\x00\x00\x00\x00\x00\x01\x00\x07#\x09\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb8\ \x00\x00\x07\x16\x00\x00\x00\x00\x00\x01\x00\x07\x15$\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb3\ \x00\x00\x0b\x12\x00\x00\x00\x00\x00\x01\x00\x07\x9e\xdf\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xbb\ \x00\x00\x0a\x98\x00\x00\x00\x00\x00\x01\x00\x07\x9a\x18\ -\x00\x00\x01\x8aE\xfa\xa6\x81\ +\x00\x00\x01\x8d\xf9j$\xbe\ \x00\x00\x05\xfe\x00\x00\x00\x00\x00\x01\x00\x06\xe7K\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xbb\ \x00\x00\x07\x98\x00\x00\x00\x00\x00\x01\x00\x07\x1ca\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb3\ \x00\x00\x09\x90\x00\x00\x00\x00\x00\x01\x00\x07t\xa3\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb5\ \x00\x00\x0b:\x00\x00\x00\x00\x00\x01\x00\x07\xa1:\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb6\ \x00\x00\x09\xfa\x00\x00\x00\x00\x00\x01\x00\x07\x85\xe9\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xbe\ \x00\x00\x09\x1c\x00\x00\x00\x00\x00\x01\x00\x07W0\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xbf\ \x00\x00\x09z\x00\x00\x00\x00\x00\x01\x00\x07h\x7f\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xc0\ \x00\x00\x06\x9c\x00\x00\x00\x00\x00\x01\x00\x06\xf2^\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb3\ \x00\x00\x0a&\x00\x00\x00\x00\x00\x01\x00\x07\x88\xab\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xbd\ \x00\x00\x09\xca\x00\x00\x00\x00\x00\x01\x00\x07\x84S\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xbb\ \x00\x00\x07H\x00\x00\x00\x00\x00\x01\x00\x07\x16\xf2\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb8\ \x00\x00\x0a>\x00\x00\x00\x00\x00\x01\x00\x07\x8a\xf5\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb3\ \x00\x00\x06\x86\x00\x00\x00\x00\x00\x01\x00\x06\xf0\xb4\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xbe\ \x00\x00\x0aV\x00\x00\x00\x00\x00\x01\x00\x07\x8c[\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb5\ \x00\x00\x07\xe4\x00\x01\x00\x00\x00\x01\x00\x07 \x91\ -\x00\x00\x01\x8aE\xfa\xa6\x82\ +\x00\x00\x01\x8d\xf9j$\xbf\ \x00\x00\x07\xfe\x00\x00\x00\x00\x00\x01\x00\x07!k\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xb9\ \x00\x00\x0a\xec\x00\x00\x00\x00\x00\x01\x00\x07\x9d\x00\ -\x00\x00\x01\x8aE\xfa\xa6p\ +\x00\x00\x01\x8d\xf9j$\xb9\ \x00\x00\x04\xf0\x00\x00\x00\x00\x00\x01\x00\x07\x08@\ -\x00\x00\x01\x8aE\xfa\xa6q\ +\x00\x00\x01\x8d\xf9j$\xb9\ \x00\x00\x05X\x00\x00\x00\x00\x00\x01\x00\x072\xe9\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb7\ \x00\x00\x05\x84\x00\x00\x00\x00\x00\x01\x00\x07i\xd3\ -\x00\x00\x01\x8aE\xfa\xa6`\ +\x00\x00\x01\x8d\xf9j$\xb8\ \x00\x00\x05\xb0\x00\x00\x00\x00\x00\x01\x00\x06\xe3:\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc3\ \x00\x00\x05\x0e\x00\x00\x00\x00\x00\x01\x00\x06\xca\xc1\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc4\ \x00\x00\x02\x80\x00\x00\x00\x00\x00\x01\x00\x06\xc6\xaf\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc3\ \x00\x00\x04\xce\x00\x00\x00\x00\x00\x01\x00\x06\xc4\x9c\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc2\ \x00\x00\x05\xe2\x00\x00\x00\x00\x00\x01\x00\x06\xe5\x0c\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc2\ \x00\x00\x05(\x00\x00\x00\x00\x00\x01\x00\x06\xcdK\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc4\ \x00\x00\x04\xf0\x00\x00\x00\x00\x00\x01\x00\x06\xc8\x90\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc4\ \x00\x00\x05X\x00\x00\x00\x00\x00\x01\x00\x06\xcf\xfe\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc2\ \x00\x00\x05\x84\x00\x00\x00\x00\x00\x01\x00\x06\xd9\xb8\ -\x00\x00\x01\x8aE\xfa\xa6\x92\ +\x00\x00\x01\x8d\xf9j$\xc3\ \x00\x00\x01&\x00\x01\x00\x00\x00\x01\x00\x03\x04\x82\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xaf\ \x00\x00\x00\xe6\x00\x01\x00\x00\x00\x01\x00\x02\xbaN\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xb0\ \x00\x00\x01d\x00\x00\x00\x00\x00\x01\x00\x03\x10\xa8\ -\x00\x00\x01\x8aE\xfa\xa6P\ +\x00\x00\x01\x8d\xf9j$\xb1\ " def qInitResources(): diff --git a/spinetoolbox/ui/mainwindow.py b/spinetoolbox/ui/mainwindow.py index d97bd99df..be0b9cad1 100644 --- a/spinetoolbox/ui/mainwindow.py +++ b/spinetoolbox/ui/mainwindow.py @@ -14,7 +14,7 @@ ################################################################################ ## Form generated from reading UI file 'mainwindow.ui' ## -## Created by: Qt User Interface Compiler version 6.6.2 +## Created by: Qt User Interface Compiler version 6.5.2 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -219,7 +219,7 @@ def setupUi(self, MainWindow): MainWindow.setStatusBar(self.statusbar) self.dockWidget_eventlog = QDockWidget(MainWindow) self.dockWidget_eventlog.setObjectName(u"dockWidget_eventlog") - sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred) + sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.dockWidget_eventlog.sizePolicy().hasHeightForWidth()) @@ -228,7 +228,7 @@ def setupUi(self, MainWindow): self.dockWidget_eventlog.setFeatures(QDockWidget.DockWidgetClosable|QDockWidget.DockWidgetFloatable|QDockWidget.DockWidgetMovable) self.dockWidgetContents = QWidget() self.dockWidgetContents.setObjectName(u"dockWidgetContents") - sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + sizePolicy1 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy1.setHorizontalStretch(0) sizePolicy1.setVerticalStretch(0) sizePolicy1.setHeightForWidth(self.dockWidgetContents.sizePolicy().hasHeightForWidth()) diff --git a/spinetoolbox/ui/startup_box.py b/spinetoolbox/ui/startup_box.py index bac8777b5..20d22f1de 100644 --- a/spinetoolbox/ui/startup_box.py +++ b/spinetoolbox/ui/startup_box.py @@ -14,7 +14,7 @@ ################################################################################ ## Form generated from reading UI file 'startup_box.ui' ## -## Created by: Qt User Interface Compiler version 6.6.2 +## Created by: Qt User Interface Compiler version 6.5.2 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -26,47 +26,15 @@ QFont, QFontDatabase, QGradient, QIcon, QImage, QKeySequence, QLinearGradient, QPainter, QPalette, QPixmap, QRadialGradient, QTransform) -from PySide6.QtWidgets import (QApplication, QCommandLinkButton, QFrame, QGroupBox, - QLabel, QPushButton, QScrollArea, QSizePolicy, - QTabWidget, QVBoxLayout, QWidget) +from PySide6.QtWidgets import (QApplication, QFrame, QGroupBox, QLabel, + QListWidget, QListWidgetItem, QPushButton, QSizePolicy, + QTabWidget, QWidget) class Ui_Form(object): def setupUi(self, Form): if not Form.objectName(): Form.setObjectName(u"Form") Form.resize(1481, 928) - self.verticalLayoutWidget = QWidget(Form) - self.verticalLayoutWidget.setObjectName(u"verticalLayoutWidget") - self.verticalLayoutWidget.setGeometry(QRect(10, 30, 191, 791)) - self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget) - self.verticalLayout.setObjectName(u"verticalLayout") - self.verticalLayout.setContentsMargins(0, 0, 0, 0) - self.scrollArea = QScrollArea(self.verticalLayoutWidget) - self.scrollArea.setObjectName(u"scrollArea") - self.scrollArea.setWidgetResizable(True) - self.scrollAreaWidgetContents = QWidget() - self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") - self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 187, 787)) - self.label_2 = QLabel(self.scrollAreaWidgetContents) - self.label_2.setObjectName(u"label_2") - self.label_2.setGeometry(QRect(10, 70, 141, 20)) - font = QFont() - font.setPointSize(11) - font.setBold(True) - self.label_2.setFont(font) - self.label_2.setLineWidth(1) - self.commandLinkButton = QCommandLinkButton(self.scrollAreaWidgetContents) - self.commandLinkButton.setObjectName(u"commandLinkButton") - self.commandLinkButton.setGeometry(QRect(10, 20, 161, 31)) - self.commandLinkButton.setStyleSheet(u"background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 0, 0, 0), stop:1 rgba(255, 255, 255, 255));\n" -"border-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 0, 0, 0), stop:1 rgba(255, 255, 255, 255));") - icon = QIcon() - icon.addFile(u"resources/menu_icons/folder-open-solid.svg", QSize(), QIcon.Normal, QIcon.Off) - self.commandLinkButton.setIcon(icon) - self.scrollArea.setWidget(self.scrollAreaWidgetContents) - - self.verticalLayout.addWidget(self.scrollArea) - self.tabWidget = QTabWidget(Form) self.tabWidget.setObjectName(u"tabWidget") self.tabWidget.setGeometry(QRect(210, 30, 601, 791)) @@ -75,11 +43,11 @@ def setupUi(self, Form): self.label_13 = QLabel(self.tab) self.label_13.setObjectName(u"label_13") self.label_13.setGeometry(QRect(20, 460, 530, 21)) - font1 = QFont() - font1.setPointSize(12) - font1.setBold(True) - font1.setUnderline(False) - self.label_13.setFont(font1) + font = QFont() + font.setPointSize(12) + font.setBold(True) + font.setUnderline(False) + self.label_13.setFont(font) self.label_13.setLayoutDirection(Qt.LeftToRight) self.label_13.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignVCenter) self.line = QFrame(self.tab) @@ -95,7 +63,7 @@ def setupUi(self, Form): self.label = QLabel(self.tab) self.label.setObjectName(u"label") self.label.setGeometry(QRect(10, 0, 561, 21)) - self.label.setFont(font1) + self.label.setFont(font) self.label.setLayoutDirection(Qt.LeftToRight) self.label.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignVCenter) self.groupBox = QGroupBox(self.tab) @@ -196,6 +164,19 @@ def setupUi(self, Form): self.groupBox_6.setObjectName(u"groupBox_6") self.groupBox_6.setGeometry(QRect(820, 50, 151, 761)) self.groupBox_6.setMinimumSize(QSize(0, 16)) + self.groupBox_7 = QGroupBox(Form) + self.groupBox_7.setObjectName(u"groupBox_7") + self.groupBox_7.setGeometry(QRect(40, 50, 151, 761)) + self.groupBox_7.setMinimumSize(QSize(0, 16)) + self.pushButton_8 = QPushButton(self.groupBox_7) + self.pushButton_8.setObjectName(u"pushButton_8") + self.pushButton_8.setGeometry(QRect(10, 40, 131, 24)) + self.label_2 = QLabel(self.groupBox_7) + self.label_2.setObjectName(u"label_2") + self.label_2.setGeometry(QRect(10, 80, 49, 16)) + self.listWidget = QListWidget(self.groupBox_7) + self.listWidget.setObjectName(u"listWidget") + self.listWidget.setGeometry(QRect(20, 110, 121, 192)) self.retranslateUi(Form) @@ -207,8 +188,6 @@ def setupUi(self, Form): def retranslateUi(self, Form): Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None)) - self.label_2.setText(QCoreApplication.translate("Form", u"Recent", None)) - self.commandLinkButton.setText(QCoreApplication.translate("Form", u"Open...", None)) self.label_13.setText(QCoreApplication.translate("Form", u"Advanced Templates", None)) self.label.setText(QCoreApplication.translate("Form", u"Beginner Templates", None)) self.groupBox.setTitle(QCoreApplication.translate("Form", u"Simple Energy System", None)) @@ -234,5 +213,8 @@ def retranslateUi(self, Form): self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("Form", u"Templates", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("Form", u"Tutorials", None)) self.groupBox_6.setTitle(QCoreApplication.translate("Form", u"Software Info", None)) + self.groupBox_7.setTitle(QCoreApplication.translate("Form", u"Main", None)) + self.pushButton_8.setText(QCoreApplication.translate("Form", u"Open Project", None)) + self.label_2.setText(QCoreApplication.translate("Form", u"Recent", None)) # retranslateUi diff --git a/spinetoolbox/ui/startup_box.ui b/spinetoolbox/ui/startup_box.ui index 643aba804..4225df469 100644 --- a/spinetoolbox/ui/startup_box.ui +++ b/spinetoolbox/ui/startup_box.ui @@ -26,78 +26,6 @@ Form - - - - 10 - 30 - 191 - 791 - - - - - - - true - - - - - 0 - 0 - 187 - 787 - - - - - - 10 - 70 - 141 - 20 - - - - - 11 - true - - - - 1 - - - Recent - - - - - - 10 - 20 - 161 - 31 - - - - background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 0, 0, 0), stop:1 rgba(255, 255, 255, 255)); -border-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0 rgba(0, 0, 0, 0), stop:1 rgba(255, 255, 255, 255)); - - - Open... - - - - resources/menu_icons/folder-open-solid.svgresources/menu_icons/folder-open-solid.svg - - - - - - - @@ -568,6 +496,61 @@ border-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy Software Info + + + + 40 + 50 + 151 + 761 + + + + + 0 + 16 + + + + Main + + + + + 10 + 40 + 131 + 24 + + + + Open Project + + + + + + 10 + 80 + 49 + 16 + + + + Recent + + + + + + 20 + 110 + 121 + 192 + + + + diff --git a/spinetoolbox/ui_main.py b/spinetoolbox/ui_main.py index 8210977a6..815f02395 100644 --- a/spinetoolbox/ui_main.py +++ b/spinetoolbox/ui_main.py @@ -66,7 +66,6 @@ from .mvcmodels.project_item_specification_models import ProjectItemSpecificationModel, FilteredSpecificationModel from .mvcmodels.filter_execution_model import FilterExecutionModel from .project_settings import ProjectSettings -from .startup_box_old import StartUpMainWindow from .widgets.startup_box_widget import StartupBoxWidget from .widgets.set_description_dialog import SetDescriptionDialog from .widgets.multi_tab_spec_editor import MultiTabSpecEditor diff --git a/spinetoolbox/widgets/startup_box_widget.py b/spinetoolbox/widgets/startup_box_widget.py index b9d1b6cd7..b6f853cb3 100644 --- a/spinetoolbox/widgets/startup_box_widget.py +++ b/spinetoolbox/widgets/startup_box_widget.py @@ -15,15 +15,24 @@ from PySide6.QtCore import Qt, Slot, Signal from spinetoolbox.ui.startup_box import Ui_Form +from PySide6.QtWidgets import QListWidgetItem class StartupBoxWidget(QWidget): project_load_requested = Signal(str) + project_opener = Signal(str) + recent_projects = Signal(str) def __init__(self, parent=None): super().__init__(parent=parent, f=Qt.WindowType.Window) self._ui = Ui_Form() self._ui.setupUi(self) + # Connect the clicked signal of open project button + self._ui.pushButton_8.clicked.connect(self.open_project_startbox) + + # Connect the signal of recent projects + self.open_recent() + # Connect the clicked signal of each button to a specific slot self._ui.pushButton_3.clicked.connect(self.open_tutorial1) self._ui.pushButton_4.clicked.connect(self.open_tutorial2) @@ -32,6 +41,36 @@ def __init__(self, parent=None): self._ui.pushButton_7.clicked.connect(self.open_tutorial5) @Slot() + def open_project_startbox(self): + # Execute the open_project function in the ui_main.py + self.project_opener.emit(self) + + def open_recent(self): + # Access qsettings from the parent object + recents = self.parent().qsettings().value("appSettings/recentProjects", defaultValue=None) + if recents: + recents = str(recents) + recents_list = recents.split("\n") + for entry in recents_list: + name, filepath = entry.split("<>") + # Add only the name to the list widget + item = QListWidgetItem(name) + self._ui.listWidget.addItem(item) + + # Storing filepath as an attribute of the item + item.filepath = filepath + # Storing filepath as data + item.setData(Qt.UserRole, filepath) + + # Connect the itemClicked signal to the open_selected_tutorial function + self._ui.listWidget.itemClicked.connect(self.open_selected_tutorial) + + @Slot() + def open_selected_tutorial(self): + item = self._ui.listWidget.currentItem() + path = item.data(Qt.UserRole) + self.project_load_requested.emit(path) + def open_tutorial1(self): print("Open 1st tutorial") path_to_project = "C:\\Users\ErmannoLoCascio\Desktop\eScience - Mopo\spine_projects\Simple Tutorial 4" @@ -55,4 +94,4 @@ def open_tutorial4(self): @Slot() def open_tutorial5(self): path_to_project = "C:\\Users\ErmannoLoCascio\Desktop\eScience - Mopo\spine_projects\Simple Tutorial 5" - self.project_load_requested.emit(path_to_project) + self.project_load_requested.emit(path_to_project) \ No newline at end of file