diff --git a/CHANGELOG.md b/CHANGELOG.md index 823b4d310..f04315f9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/) ## [Unreleased] -### Added +### Added + +new item added 123 -### Changed -### Deprecated ### Removed @@ -802,5 +802,3 @@ Many parts of the Spine data structure have been redesigned. ## [0.1] - 2018-08-20 -### Added -- Basic functionality diff --git a/docs/source/img/tutorials_images/advanced_material_thumbmail.png b/docs/source/img/tutorials_images/advanced_material_thumbmail.png new file mode 100644 index 000000000..b9dfe54a1 Binary files /dev/null and b/docs/source/img/tutorials_images/advanced_material_thumbmail.png differ diff --git a/docs/source/img/tutorials_images/data_structure_thumbnail.png b/docs/source/img/tutorials_images/data_structure_thumbnail.png new file mode 100644 index 000000000..7e245384e Binary files /dev/null and b/docs/source/img/tutorials_images/data_structure_thumbnail.png differ diff --git a/docs/source/img/tutorials_images/say_hello_thumbnail.png b/docs/source/img/tutorials_images/say_hello_thumbnail.png new file mode 100644 index 000000000..8e471cd75 Binary files /dev/null and b/docs/source/img/tutorials_images/say_hello_thumbnail.png differ diff --git a/docs/source/img/tutorials_images/workflow_thumbnail.png b/docs/source/img/tutorials_images/workflow_thumbnail.png new file mode 100644 index 000000000..7aa6e1e43 Binary files /dev/null and b/docs/source/img/tutorials_images/workflow_thumbnail.png differ diff --git a/spinetoolbox/changelog_diff.py b/spinetoolbox/changelog_diff.py index 9db200db0..5d2eea41e 100644 --- a/spinetoolbox/changelog_diff.py +++ b/spinetoolbox/changelog_diff.py @@ -2,21 +2,55 @@ import os import difflib from .config import CHANGELOG_PATH +import re +''' def save_changelog_to_settings(settings): if os.path.isfile(CHANGELOG_PATH): with open(CHANGELOG_PATH, "r") as fp: cl = fp.readlines() settings.setValue("changeLog", cl) +''' -def get_changelog_diff(settings): + +def pick_latest_release(settings): if os.path.isfile(CHANGELOG_PATH): with open(CHANGELOG_PATH, "r") as fp: - current_changelog = fp.readlines() - old_changelog = settings.value("changelog", None) - if not old_changelog: - return None - diff = [li for li in difflib.ndiff(old_changelog, current_changelog) if li[0] != ' '] - return diff - return None \ No newline at end of file + current_changelog = fp.read() + + # Use regex to find all headers (e.g., ## [Version]) + headers = re.findall(r'^## \[.*?\]', current_changelog, re.MULTILINE) + + if headers: + # Assume the first header is the latest release (e.g., Unreleased or latest version) + latest_release_header = headers[0] + + # Find the position of the latest release + latest_release_start = current_changelog.find(latest_release_header) + next_header_start = None + + # Find the next header to delimit the section + for header in headers[1:]: + pos = current_changelog.find(header, latest_release_start + len(latest_release_header)) + if pos != -1: + next_header_start = pos + break + + # Extract the content of the latest release section + if next_header_start: + latest_release_content = current_changelog[latest_release_start:next_header_start].strip() + else: + # No further header; take till the end of the file + latest_release_content = current_changelog[latest_release_start:].strip() + + # Split the content into lines for further processing + diff = [line.strip() for line in latest_release_content.splitlines() if line.strip()] + + return diff + else: + print("No headers found in the changelog.") + return [] + else: + print(f"Changelog not found at {CHANGELOG_PATH}") + return [] \ No newline at end of file diff --git a/spinetoolbox/ui/startup_box.py b/spinetoolbox/ui/startup_box.py index d780c4b67..585f4cdf2 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.5.2 +## Created by: Qt User Interface Compiler version 6.7.3 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -41,10 +41,27 @@ def setupUi(self, Form): self.groupBox_6.setMinimumSize(QSize(0, 16)) self.listWidget_2 = QListWidget(self.groupBox_6) self.listWidget_2.setObjectName(u"listWidget_2") - self.listWidget_2.setGeometry(QRect(10, 40, 171, 561)) + self.listWidget_2.setGeometry(QRect(10, 60, 171, 541)) self.listWidget_2.setStyleSheet(u"background-color: rgb(240, 240, 240);\n" "border-color: rgb(240, 240, 240);") - self.listWidget_2.setProperty("showDropIndicator", True) + self.listWidget_2.setProperty(u"showDropIndicator", True) + self.listWidget_2.setProperty(u"isWrapping", False) + self.listWidget_2.setWordWrap(True) + self.label_17 = QLabel(self.groupBox_6) + self.label_17.setObjectName(u"label_17") + self.label_17.setGeometry(QRect(10, 20, 171, 31)) + font = QFont() + font.setFamilies([u"Courier"]) + font.setPointSize(11) + font.setBold(False) + font.setItalic(True) + self.label_17.setFont(font) + self.label_17.setAutoFillBackground(False) + self.label_17.setStyleSheet(u"") + self.label_17.setFrameShape(QFrame.Shape.StyledPanel) + self.label_17.setFrameShadow(QFrame.Shadow.Raised) + self.label_17.setLineWidth(1) + self.label_17.setScaledContents(False) self.groupBox_7 = QGroupBox(Form) self.groupBox_7.setObjectName(u"groupBox_7") self.groupBox_7.setGeometry(QRect(50, 40, 151, 611)) @@ -73,9 +90,9 @@ def setupUi(self, Form): self.scrollArea_2.setObjectName(u"scrollArea_2") self.scrollArea_2.setGeometry(QRect(10, 10, 661, 561)) self.scrollArea_2.setStyleSheet(u"") - self.scrollArea_2.setFrameShape(QFrame.NoFrame) - self.scrollArea_2.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) - self.scrollArea_2.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + self.scrollArea_2.setFrameShape(QFrame.Shape.NoFrame) + self.scrollArea_2.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + self.scrollArea_2.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.scrollArea_2.setWidgetResizable(False) self.scrollAreaWidgetContents_3 = QWidget() self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3") @@ -83,17 +100,17 @@ def setupUi(self, Form): self.label_3 = QLabel(self.scrollAreaWidgetContents_3) self.label_3.setObjectName(u"label_3") self.label_3.setGeometry(QRect(10, 10, 670, 21)) - font = QFont() - font.setPointSize(12) - font.setBold(True) - font.setUnderline(False) - self.label_3.setFont(font) - self.label_3.setLayoutDirection(Qt.LeftToRight) + font1 = QFont() + font1.setPointSize(12) + font1.setBold(True) + font1.setUnderline(False) + self.label_3.setFont(font1) + self.label_3.setLayoutDirection(Qt.LayoutDirection.LeftToRight) self.label_14 = QLabel(self.scrollAreaWidgetContents_3) self.label_14.setObjectName(u"label_14") self.label_14.setGeometry(QRect(10, 430, 670, 21)) - self.label_14.setFont(font) - self.label_14.setLayoutDirection(Qt.LeftToRight) + self.label_14.setFont(font1) + self.label_14.setLayoutDirection(Qt.LayoutDirection.LeftToRight) self.groupBox_4 = QGroupBox(self.scrollAreaWidgetContents_3) self.groupBox_4.setObjectName(u"groupBox_4") self.groupBox_4.setGeometry(QRect(10, 50, 631, 101)) @@ -104,6 +121,11 @@ def setupUi(self, Form): self.pushButton = QPushButton(self.groupBox_4) self.pushButton.setObjectName(u"pushButton") self.pushButton.setGeometry(QRect(510, 46, 101, 20)) + self.label_10 = QLabel(self.groupBox_4) + self.label_10.setObjectName(u"label_10") + self.label_10.setGeometry(QRect(20, 30, 60, 51)) + self.label_10.setPixmap(QPixmap(u"../../docs/source/img/tutorials_images/say_hello_thumbnail.png")) + self.label_10.setScaledContents(True) self.groupBox_10 = QGroupBox(self.scrollAreaWidgetContents_3) self.groupBox_10.setObjectName(u"groupBox_10") self.groupBox_10.setGeometry(QRect(10, 170, 631, 111)) @@ -114,6 +136,11 @@ def setupUi(self, Form): self.pushButton_2 = QPushButton(self.groupBox_10) self.pushButton_2.setObjectName(u"pushButton_2") self.pushButton_2.setGeometry(QRect(510, 52, 101, 21)) + self.label_11 = QLabel(self.groupBox_10) + self.label_11.setObjectName(u"label_11") + self.label_11.setGeometry(QRect(20, 30, 60, 51)) + self.label_11.setPixmap(QPixmap(u"../../docs/source/img/tutorials_images/data_structure_thumbnail.png")) + self.label_11.setScaledContents(True) self.groupBox_11 = QGroupBox(self.scrollAreaWidgetContents_3) self.groupBox_11.setObjectName(u"groupBox_11") self.groupBox_11.setGeometry(QRect(10, 300, 631, 101)) @@ -124,6 +151,11 @@ def setupUi(self, Form): self.pushButton_4 = QPushButton(self.groupBox_11) self.pushButton_4.setObjectName(u"pushButton_4") self.pushButton_4.setGeometry(QRect(510, 48, 101, 21)) + self.label_15 = QLabel(self.groupBox_11) + self.label_15.setObjectName(u"label_15") + self.label_15.setGeometry(QRect(20, 30, 60, 51)) + self.label_15.setPixmap(QPixmap(u"../../docs/source/img/tutorials_images/workflow_thumbnail.png")) + self.label_15.setScaledContents(True) self.groupBox_13 = QGroupBox(self.scrollAreaWidgetContents_3) self.groupBox_13.setObjectName(u"groupBox_13") self.groupBox_13.setGeometry(QRect(10, 460, 631, 101)) @@ -134,6 +166,11 @@ def setupUi(self, Form): self.pushButton_5 = QPushButton(self.groupBox_13) self.pushButton_5.setObjectName(u"pushButton_5") self.pushButton_5.setGeometry(QRect(510, 40, 101, 21)) + self.label_16 = QLabel(self.groupBox_13) + self.label_16.setObjectName(u"label_16") + self.label_16.setGeometry(QRect(20, 30, 60, 51)) + self.label_16.setPixmap(QPixmap(u"../../docs/source/img/tutorials_images/advanced_material_thumbmail.png")) + self.label_16.setScaledContents(True) self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_3) self.tabWidget.addTab(self.tab_2, "") self.tab = QWidget() @@ -143,9 +180,9 @@ def setupUi(self, Form): self.scrollArea = QScrollArea(self.tab) self.scrollArea.setObjectName(u"scrollArea") self.scrollArea.setEnabled(True) - self.scrollArea.setFrameShape(QFrame.NoFrame) - self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) - self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + self.scrollArea.setFrameShape(QFrame.Shape.NoFrame) + self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.scrollArea.setWidgetResizable(False) self.scrollAreaWidgetContents_2 = QWidget() self.scrollAreaWidgetContents_2.setObjectName(u"scrollAreaWidgetContents_2") @@ -153,20 +190,20 @@ def setupUi(self, Form): self.label = QLabel(self.scrollAreaWidgetContents_2) self.label.setObjectName(u"label") self.label.setGeometry(QRect(10, 10, 670, 21)) - self.label.setFont(font) - self.label.setLayoutDirection(Qt.LeftToRight) + self.label.setFont(font1) + self.label.setLayoutDirection(Qt.LayoutDirection.LeftToRight) self.label_13 = QLabel(self.scrollAreaWidgetContents_2) self.label_13.setObjectName(u"label_13") self.label_13.setGeometry(QRect(10, 280, 621, 21)) - self.label_13.setFont(font) - self.label_13.setLayoutDirection(Qt.LeftToRight) + self.label_13.setFont(font1) + self.label_13.setLayoutDirection(Qt.LayoutDirection.LeftToRight) self.groupBox_8 = QGroupBox(self.scrollAreaWidgetContents_2) self.groupBox_8.setObjectName(u"groupBox_8") self.groupBox_8.setGeometry(QRect(10, 120, 631, 131)) self.label_5 = QLabel(self.groupBox_8) self.label_5.setObjectName(u"label_5") self.label_5.setGeometry(QRect(90, 20, 351, 71)) - self.label_5.setTextFormat(Qt.PlainText) + self.label_5.setTextFormat(Qt.TextFormat.PlainText) self.label_5.setScaledContents(False) self.label_5.setWordWrap(True) self.pushButton_3 = QPushButton(self.groupBox_8) @@ -181,14 +218,14 @@ def setupUi(self, Form): self.label_12 = QLabel(self.groupBox_3) self.label_12.setObjectName(u"label_12") self.label_12.setGeometry(QRect(70, 20, 371, 91)) - self.label_12.setTextFormat(Qt.PlainText) + self.label_12.setTextFormat(Qt.TextFormat.PlainText) self.label_12.setScaledContents(False) self.label_12.setWordWrap(True) self.label_4 = QLabel(self.scrollAreaWidgetContents_2) self.label_4.setObjectName(u"label_4") self.label_4.setGeometry(QRect(20, 50, 531, 31)) self.label_4.setAutoFillBackground(False) - self.label_4.setTextFormat(Qt.RichText) + self.label_4.setTextFormat(Qt.TextFormat.RichText) self.scrollArea.setWidget(self.scrollAreaWidgetContents_2) self.verticalLayout_3.addWidget(self.scrollArea) @@ -206,6 +243,7 @@ def setupUi(self, Form): def retranslateUi(self, Form): Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None)) self.groupBox_6.setTitle(QCoreApplication.translate("Form", u"Software Info", None)) + self.label_17.setText(QCoreApplication.translate("Form", u"

TextLabel

", 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)) @@ -215,15 +253,19 @@ def retranslateUi(self, Form): self.groupBox_4.setTitle(QCoreApplication.translate("Form", u"Hello World", None)) self.label_6.setText(QCoreApplication.translate("Form", u" In this guide you will learn two ways of running a \u201cHello, World!\u201d program on Spine Toolbox.", None)) self.pushButton.setText(QCoreApplication.translate("Form", u"Open Document", None)) + self.label_10.setText("") self.groupBox_10.setTitle(QCoreApplication.translate("Form", u"Introduction to Spine Data Structure", None)) self.label_7.setText(QCoreApplication.translate("Form", u"Learn more on the Spine Data Structure through this GitHub document.", None)) self.pushButton_2.setText(QCoreApplication.translate("Form", u"Open Document", None)) + self.label_11.setText("") self.groupBox_11.setTitle(QCoreApplication.translate("Form", u"Setting up a Workflow", None)) self.label_8.setText(QCoreApplication.translate("Form", u"This documento will show how to add a Tool item to your project.", None)) self.pushButton_4.setText(QCoreApplication.translate("Form", u"Open Document", None)) + self.label_15.setText("") self.groupBox_13.setTitle(QCoreApplication.translate("Form", u"Executing Projects", None)) self.label_9.setText(QCoreApplication.translate("Form", u"This document describes how executing a project works and what resources are passed between project items at execution time.", None)) self.pushButton_5.setText(QCoreApplication.translate("Form", u"Open Document", None)) + self.label_16.setText("") self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("Form", u"Learning materials", None)) self.label.setText(QCoreApplication.translate("Form", u"Spine Toolbox", None)) self.label_13.setText(QCoreApplication.translate("Form", u"Model specific workflows", None)) diff --git a/spinetoolbox/ui/startup_box.ui b/spinetoolbox/ui/startup_box.ui index 80f0051f7..d2524fec9 100644 --- a/spinetoolbox/ui/startup_box.ui +++ b/spinetoolbox/ui/startup_box.ui @@ -35,9 +35,9 @@ 10 - 40 + 60 171 - 561 + 541 @@ -47,6 +47,51 @@ border-color: rgb(240, 240, 240); true + + false + + + true + + + + + + 10 + 20 + 171 + 31 + + + + + Courier + 11 + true + false + + + + false + + + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + 1 + + + <html><head/><body><p><span style=" color:#1a0ec1;">TextLabel</span></p></body></html> + + + false + @@ -153,13 +198,13 @@ border-color: rgb(240, 240, 240); - QFrame::NoFrame + QFrame::Shape::NoFrame - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff false @@ -190,7 +235,7 @@ border-color: rgb(240, 240, 240); - Qt::LeftToRight + Qt::LayoutDirection::LeftToRight Introductory Learning Material @@ -213,7 +258,7 @@ border-color: rgb(240, 240, 240); - Qt::LeftToRight + Qt::LayoutDirection::LeftToRight Advanced Learning Material @@ -260,6 +305,25 @@ border-color: rgb(240, 240, 240); Open Document + + + + 20 + 30 + 60 + 51 + + + + + + + ../../docs/source/img/tutorials_images/say_hello_thumbnail.png + + + true + + @@ -302,6 +366,25 @@ border-color: rgb(240, 240, 240); Open Document + + + + 20 + 30 + 60 + 51 + + + + + + + ../../docs/source/img/tutorials_images/data_structure_thumbnail.png + + + true + + @@ -344,6 +427,25 @@ border-color: rgb(240, 240, 240); Open Document + + + + 20 + 30 + 60 + 51 + + + + + + + ../../docs/source/img/tutorials_images/workflow_thumbnail.png + + + true + + @@ -386,6 +488,25 @@ border-color: rgb(240, 240, 240); Open Document + + + + 20 + 30 + 60 + 51 + + + + + + + ../../docs/source/img/tutorials_images/advanced_material_thumbmail.png + + + true + + @@ -401,13 +522,13 @@ border-color: rgb(240, 240, 240); true - QFrame::NoFrame + QFrame::Shape::NoFrame - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff + Qt::ScrollBarPolicy::ScrollBarAlwaysOff false @@ -438,7 +559,7 @@ border-color: rgb(240, 240, 240); - Qt::LeftToRight + Qt::LayoutDirection::LeftToRight Spine Toolbox @@ -461,7 +582,7 @@ border-color: rgb(240, 240, 240); - Qt::LeftToRight + Qt::LayoutDirection::LeftToRight Model specific workflows @@ -492,7 +613,7 @@ border-color: rgb(240, 240, 240); https://spine-toolbox.readthedocs.io/en/latest/data_import_export.html - Qt::PlainText + Qt::TextFormat::PlainText false @@ -553,7 +674,7 @@ border-color: rgb(240, 240, 240); 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. - Qt::PlainText + Qt::TextFormat::PlainText false @@ -579,7 +700,7 @@ border-color: rgb(240, 240, 240); <html><head/><body><p>Prerequisites: To run the following project templates, make sure to install both Julia and SpineOpt.</p></body></html> - Qt::RichText + Qt::TextFormat::RichText diff --git a/spinetoolbox/ui_main.py b/spinetoolbox/ui_main.py index 22160a823..a7203994d 100644 --- a/spinetoolbox/ui_main.py +++ b/spinetoolbox/ui_main.py @@ -51,6 +51,7 @@ ) from spine_engine.load_project_items import load_item_specification_factories from spinetoolbox.server.engine_client import ClientSecurityModel, EngineClient, RemoteEngineInitFailed +from .changelog_diff import pick_latest_release from .config import SPINE_TOOLBOX_REPO_URL from .widgets.startup_box_widget import StartupBoxWidget from .config import MAINWINDOW_SS, DEFAULT_WORK_DIR, ONLINE_DOCUMENTATION_URL @@ -242,10 +243,11 @@ def __init__(self): self.startup_box_widget.show() # Get the changelog differences - diff = get_changelog_diff(self._qsettings) + diff = pick_latest_release(self._qsettings) - # Connect to set_changelog_diff the function in the start_up_box.py - self.startup_box_widget.set_changelog_diff(diff) + if diff is not None: + # Connect to set_changelog_diff the function in the start_up_box.py + self.startup_box_widget.set_changelog_diff(diff) def eventFilter(self, obj, ev): # Save/restore splitter states when hiding/showing execution lists @@ -2039,7 +2041,7 @@ def closeEvent(self, event): for item_type in self.item_factories: for editor in self.get_all_multi_tab_spec_editors(item_type): editor.close() - save_changelog_to_settings(self._qsettings) + #save_changelog_to_settings(self._qsettings) event.accept() def _serialize_selected_items(self): diff --git a/spinetoolbox/widgets/startup_box_widget.py b/spinetoolbox/widgets/startup_box_widget.py index d839eb82f..556d6938b 100644 --- a/spinetoolbox/widgets/startup_box_widget.py +++ b/spinetoolbox/widgets/startup_box_widget.py @@ -17,6 +17,9 @@ from PySide6.QtWidgets import QListWidgetItem import webbrowser +from PySide6.QtGui import QFont, QColor, QBrush + + class StartupBoxWidget(QWidget): project_load_requested = Signal(str) @@ -58,12 +61,63 @@ def __init__(self, parent=None): self._ui.pushButton_5.clicked.connect(self.open_link4) def set_changelog_diff(self, diff_list): - # Add diff_list items to listWidget_2 - for item in diff_list: + # Filter out empty rows or rows with only whitespace + filtered_diff_list = [item for item in diff_list if item.strip()] + + version_set = False # Flag to ensure the version is set only once + + # Clear the label first to avoid overlapping text + self._ui.label_17.clear() + + for line in filtered_diff_list: + line = line.strip() + + # Check for versioning lines (with ##) + if line.startswith("##"): + # Extract version text (e.g., ## [Unreleased] or ## [1.0]) + line_content = line[3:].strip() # Remove the "##" part + + # Check if the line contains version info within brackets + if "[" in line_content and "]" in line_content and not version_set: + # Extract version text within brackets + version = line_content[line_content.find("[") + 1:line_content.find("]")] + # Display the version in label_17 only once + self._ui.label_17.setText(version) + version_set = True # Set the flag to avoid overwriting the version + continue # Skip adding this line to listWidget_2 + + # Create a list widget item + item = QListWidgetItem() + + # Check for subtitle headers (with ###) + if line.startswith("###"): + # Subtitle (e.g., ### Added) - bold gray, font size 9px + line_content = line[3:].strip() # Remove the "###" part + font = QFont("Arial", 9, QFont.Bold) # Font size 9px, bold + item.setFont(font) + item.setForeground(QBrush(QColor("#555555"))) # Lighter gray color + + # Check for bullet points (with -) + elif line.startswith("-"): + # Bullet point (e.g., - The Filter button) - font size 8px, gray + line_content = line[1:].strip() # Remove the "-" part + font = QFont("Arial", 8) # Font size 8px for bullet points + item.setFont(font) + item.setForeground(QBrush(QColor("#888888"))) # Gray color + + # Handle plain text (regular paragraphs) + else: + line_content = line.strip() + font = QFont("Arial", 8) # Font size 8px for plain text + item.setFont(font) + item.setForeground(QBrush(QColor("#888888"))) # Gray color + + # Set the cleaned-up text content + item.setText(line_content) + + # Add the styled item to listWidget_2 self._ui.listWidget_2.addItem(item) - - @Slot() def open_project_startbox(self): # Execute the open_project function in the ui_main.py