On new install or update, have highlights not just changelog.

Place images in resources/images/whats_new/N.format and texts in resources/texts/whats_new/N.format where N is the ordinal and format the respective allowed formats.

CURA-8014
This commit is contained in:
Remco Burema 2021-03-24 12:00:05 +01:00
parent bcf180985d
commit 5083db8d44
No known key found for this signature in database
GPG Key ID: 215C49431D43F98C
10 changed files with 307 additions and 26 deletions

View File

@ -1,8 +1,12 @@
# Copyright (c) 2019 Ultimaker B.V.
# Copyright (c) 2021 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher.
from .WelcomePagesModel import WelcomePagesModel
import os
from typing import Optional, Dict, List, Tuple
from PyQt5.QtCore import pyqtProperty, pyqtSlot
from UM.Logger import Logger
from UM.Resources import Resources
#
# This Qt ListModel is more or less the same the WelcomePagesModel, except that this model is only for showing the
@ -10,13 +14,84 @@ from .WelcomePagesModel import WelcomePagesModel
#
class WhatsNewPagesModel(WelcomePagesModel):
image_formats = [".png", ".jpg", ".jpeg", ".gif", ".svg"]
text_formats = [".txt", ".htm", ".html"]
image_key = "image"
text_key = "text"
@classmethod
def _collectOrdinalFiles(cls, resource_type: int, include: List[str]) -> Tuple[Dict[int, str], int]:
result = {} # Dict[int, str]
highest = -1
try:
folder_path = Resources.getPath(resource_type, "whats_new")
for _, _, files in os.walk(folder_path):
for filename in files:
basename = os.path.basename(filename)
base, ext = os.path.splitext(basename)
if ext not in include or not base.isdigit():
continue
page_no = int(base)
highest = max(highest, page_no)
result[page_no] = os.path.join(folder_path, filename)
except FileNotFoundError:
Logger.logException("w", "Could not find 'whats_new' folder for resource-type {0}".format(resource_type))
return result, highest
@classmethod
def _loadText(cls, filename: str) -> str:
result = ""
try:
with open(filename, "r", encoding="utf-8") as file:
result = file.read()
except OSError:
Logger.logException("w", "Could not open {0}".format(filename))
return result
def initialize(self) -> None:
self._pages = []
self._pages.append({"id": "whats_new",
"page_url": self._getBuiltinWelcomePagePath("WhatsNewContent.qml"),
"next_page_button_text": self._catalog.i18nc("@action:button", "Skip"),
"next_page_id": "changelog"
})
self._pages.append({"id": "changelog",
"page_url": self._getBuiltinWelcomePagePath("ChangelogContent.qml"),
"next_page_button_text": self._catalog.i18nc("@action:button", "Close"),
})
self.setItems(self._pages)
images, max_image = WhatsNewPagesModel._collectOrdinalFiles(Resources.Images, WhatsNewPagesModel.image_formats)
texts, max_text = WhatsNewPagesModel._collectOrdinalFiles(Resources.Texts, WhatsNewPagesModel.text_formats)
highest = max(max_image, max_text)
self._subpages = [] # List[Dict[str, str]]
for n in range(0, highest + 1):
self._subpages.append({
WhatsNewPagesModel.image_key: None if n not in images else images[n],
WhatsNewPagesModel.text_key: None if n not in texts else self._loadText(texts[n])
})
if len(self._subpages) == 0:
self._subpages.append({WhatsNewPagesModel.text_key: "~ There Is Nothing New Under The Sun ~"})
def _getSubpageItem(self, page: int, item: str) -> Optional[str]:
if 0 <= page < self.subpageCount and item in self._subpages[page]:
return self._subpages[page][item]
else:
return None
@pyqtProperty(int, constant = True)
def subpageCount(self) -> int:
return len(self._subpages)
@pyqtSlot(int, result = str)
def getSubpageImageSource(self, page: int) -> str:
result = self._getSubpageItem(page, WhatsNewPagesModel.image_key)
return "file:///" + (result if result else Resources.getPath(Resources.Images, "cura-icon.png"))
@pyqtSlot(int, result = str)
def getSubpageText(self, page: int) -> str:
result = self._getSubpageItem(page, WhatsNewPagesModel.text_key)
return result if result else "* * *"
__all__ = ["WhatsNewPagesModel"]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,59 @@
// Copyright (c) 2019 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import UM 1.3 as UM
import Cura 1.1 as Cura
//
// This component contains the content for the "What's new in Ultimaker Cura" page of the welcome on-boarding process.
//
Item
{
UM.I18nCatalog { id: catalog; name: "cura" }
Label
{
id: titleLabel
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignHCenter
text: catalog.i18nc("@label", "Release Notes / 'Changelog'")
color: UM.Theme.getColor("primary_button")
font: UM.Theme.getFont("huge")
renderType: Text.NativeRendering
}
Cura.ScrollableTextArea
{
id: changelogTextArea
anchors.top: titleLabel.bottom
anchors.bottom: getStartedButton.top
anchors.topMargin: UM.Theme.getSize("wide_margin").height
anchors.bottomMargin: UM.Theme.getSize("wide_margin").height
anchors.left: parent.left
anchors.right: parent.right
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
textArea.text: CuraApplication.getTextManager().getChangeLogText()
textArea.textFormat: Text.RichText
textArea.wrapMode: Text.WordWrap
textArea.readOnly: true
textArea.font: UM.Theme.getFont("medium")
textArea.onLinkActivated: Qt.openUrlExternally(link)
}
Cura.PrimaryButton
{
id: getStartedButton
anchors.right: parent.right
anchors.bottom: parent.bottom
text: base.currentItem.next_page_button_text
onClicked: base.showNextPage()
}
}

View File

@ -1,8 +1,9 @@
// Copyright (c) 2019 Ultimaker B.V.
// Copyright (c) 2021 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import UM 1.3 as UM
import Cura 1.1 as Cura
@ -10,9 +11,12 @@ import Cura 1.1 as Cura
//
// This component contains the content for the "What's new in Ultimaker Cura" page of the welcome on-boarding process.
// Previously this was just the changelog, but now it will just have the larger stories, the changelog has its own page.
//
Item
{
property var manager: CuraApplication.getWhatsNewPagesModel()
UM.I18nCatalog { id: catalog; name: "cura" }
Label
@ -21,39 +25,170 @@ Item
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignHCenter
text: catalog.i18nc("@label", "What's new in Ultimaker Cura")
text: catalog.i18nc("@label", "What's New")
color: UM.Theme.getColor("primary_button")
font: UM.Theme.getFont("huge")
renderType: Text.NativeRendering
}
Cura.ScrollableTextArea
Item
{
id: whatsNewTextArea
id: topSpacer
anchors.top: titleLabel.bottom
anchors.bottom: getStartedButton.top
anchors.topMargin: UM.Theme.getSize("wide_margin").height
anchors.bottomMargin: UM.Theme.getSize("wide_margin").height
anchors.left: parent.left
anchors.right: parent.right
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
textArea.text: CuraApplication.getTextManager().getChangeLogText()
textArea.textFormat: Text.RichText
textArea.wrapMode: Text.WordWrap
textArea.readOnly: true
textArea.font: UM.Theme.getFont("medium")
textArea.onLinkActivated: Qt.openUrlExternally(link)
height: UM.Theme.getSize("default_margin").height
width: UM.Theme.getSize("default_margin").width
}
Cura.PrimaryButton
Rectangle
{
id: getStartedButton
anchors.right: parent.right
anchors
{
top: topSpacer.bottom
bottom: whatsNewDots.top
horizontalCenter: parent.horizontalCenter
margins: UM.Theme.getSize("default_margin").width
}
height: parent.height - (UM.Theme.getSize("default_margin").height * 2)
width: parent.width - (UM.Theme.getSize("default_margin").width * 2)
color: UM.Theme.getColor("viewport_overlay")
StackLayout
{
id: whatsNewViewport
anchors
{
top: parent.top
horizontalCenter: parent.horizontalCenter
margins: UM.Theme.getSize("default_margin").width / 2
}
height: parent.height - (UM.Theme.getSize("default_margin").height * 2)
width: parent.width - (UM.Theme.getSize("default_margin").width * 2)
currentIndex: whatsNewDots.currentIndex
Repeater
{
anchors
{
horizontalCenter: parent.horizontalCenter
top: parent.top
margins: UM.Theme.getSize("default_margin").width / 2
}
model: manager.subpageCount
Rectangle
{
anchors
{
horizontalCenter: parent.horizontalCenter
top: parent.top
margins: UM.Theme.getSize("default_margin").width / 2
}
color: UM.Theme.getColor("viewport_overlay")
Image
{
id: subpageImage
anchors
{
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: UM.Theme.getSize("default_margin").width
}
width: parent.width - (UM.Theme.getSize("default_margin").width * 2)
height: (parent.height - (UM.Theme.getSize("default_margin").width * 2)) * 0.8
fillMode: Image.PreserveAspectFit
source: manager.getSubpageImageSource(index)
}
Cura.ScrollableTextArea
{
id: subpageText
anchors
{
top: subpageImage.bottom
bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
}
width: parent.width - (UM.Theme.getSize("default_margin").width * 2)
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
back_color: UM.Theme.getColor("viewport_overlay")
do_borders: false
textArea.wrapMode: TextEdit.Wrap
textArea.text: manager.getSubpageText(index)
textArea.textFormat: Text.RichText
textArea.readOnly: true
textArea.font: UM.Theme.getFont("medium")
textArea.onLinkActivated: Qt.openUrlExternally(link)
}
}
}
}
}
PageIndicator
{
id: whatsNewDots
currentIndex: whatsNewViewport.currentIndex
count: whatsNewViewport.count
interactive: true
anchors
{
bottom: bottomSpacer.top
horizontalCenter: parent.horizontalCenter
}
delegate:
Rectangle
{
implicitWidth: UM.Theme.getSize("thin_margin").width
implicitHeight: UM.Theme.getSize("thin_margin").height
radius: width / 2
color:
index === whatsNewViewport.currentIndex ?
UM.Theme.getColor("primary") :
UM.Theme.getColor("viewport_overlay")
}
}
Item
{
id: bottomSpacer
anchors.bottom: whatsNewNextButton.top
height: UM.Theme.getSize("default_margin").height / 2
width: UM.Theme.getSize("default_margin").width / 2
}
Cura.TertiaryButton
{
id: whatsNewNextButton
anchors.left: parent.left
anchors.bottom: parent.bottom
text: base.currentItem.next_page_button_text
onClicked: base.showNextPage()
}
Cura.PrimaryButton
{
id: whatsNewSubpageButton
anchors.right: parent.right
anchors.bottom: parent.bottom
text: catalog.i18nc("@button", "Next")
onClicked:
whatsNewDots.currentIndex === (whatsNewDots.count - 1) ?
base.showNextPage() :
++whatsNewDots.currentIndex
}
}

View File

@ -15,13 +15,16 @@ ScrollView
{
property alias textArea: _textArea
property var back_color: UM.Theme.getColor("main_background")
property var do_borders: true
clip: true
background: Rectangle // Border
{
color: UM.Theme.getColor("main_background")
color: back_color
border.color: UM.Theme.getColor("thick_lining")
border.width: UM.Theme.getSize("default_lining").width
border.width: do_borders ? UM.Theme.getSize("default_lining").width : 0
}
TextArea

View File

@ -0,0 +1,5 @@
<h4>Hot New Feature (1/2)</h4>
<p>
Lorem ipsum et cetera ad infinitum dolce et gabana carpe diem. <br/>
Link to <a href="https://example.com">EXAMPLE</a>.
</p>

View File

@ -0,0 +1,2 @@
<h4>Hot New Feature (2/2)</h4>
<p>Pa's wijze lynx bezag vroom het fikse aquaduct.</p>

View File

@ -0,0 +1,2 @@
<h4>The other thing we wanted to tell you!</h4>
<p>The quick brown fox jumps over the lazy dog.</p>