mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-07 06:57:28 -06:00
Merge branch 'CURA-8441_campaign_links' of github.com:Ultimaker/Cura
This commit is contained in:
commit
8b2904ee3b
18 changed files with 29 additions and 28 deletions
|
@ -28,6 +28,6 @@
|
||||||
<image>https://raw.githubusercontent.com/Ultimaker/Cura/master/screenshot.png</image>
|
<image>https://raw.githubusercontent.com/Ultimaker/Cura/master/screenshot.png</image>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
</screenshots>
|
</screenshots>
|
||||||
<url type="homepage">https://ultimaker.com/en/products/cura-software?utm_source=cura&utm_medium=software&utm_campaign=resources</url>
|
<url type="homepage">https://ultimaker.com/software/ultimaker-cura?utm_source=cura&utm_medium=software&utm_campaign=cura-update-linux</url>
|
||||||
<translation type="gettext">Cura</translation>
|
<translation type="gettext">Cura</translation>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -35,7 +35,7 @@ class CuraActions(QObject):
|
||||||
# Starting a web browser from a signal handler connected to a menu will crash on windows.
|
# Starting a web browser from a signal handler connected to a menu will crash on windows.
|
||||||
# So instead, defer the call to the next run of the event loop, since that does work.
|
# So instead, defer the call to the next run of the event loop, since that does work.
|
||||||
# Note that weirdly enough, only signal handlers that open a web browser fail like that.
|
# Note that weirdly enough, only signal handlers that open a web browser fail like that.
|
||||||
event = CallFunctionEvent(self._openUrl, [QUrl("https://ultimaker.com/en/resources/manuals/software")], {})
|
event = CallFunctionEvent(self._openUrl, [QUrl("https://ultimaker.com/en/resources/manuals/software?utm_source=cura&utm_medium=software&utm_campaign=dropdown-documentation")], {})
|
||||||
cura.CuraApplication.CuraApplication.getInstance().functionEvent(event)
|
cura.CuraApplication.CuraApplication.getInstance().functionEvent(event)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
|
|
@ -161,7 +161,7 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
self.default_theme = "cura-light"
|
self.default_theme = "cura-light"
|
||||||
|
|
||||||
self.change_log_url = "https://ultimaker.com/ultimaker-cura-latest-features"
|
self.change_log_url = "https://ultimaker.com/ultimaker-cura-latest-features?utm_source=cura&utm_medium=software&utm_campaign=cura-update-features"
|
||||||
|
|
||||||
self._boot_loading_time = time.time()
|
self._boot_loading_time = time.time()
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ if TYPE_CHECKING:
|
||||||
from cura.OAuth2.Models import UserProfile, OAuth2Settings
|
from cura.OAuth2.Models import UserProfile, OAuth2Settings
|
||||||
from UM.Preferences import Preferences
|
from UM.Preferences import Preferences
|
||||||
|
|
||||||
MYCLOUD_LOGOFF_URL = "https://mycloud.ultimaker.com/logoff"
|
MYCLOUD_LOGOFF_URL = "https://account.ultimaker.com/logoff?utm_source=cura&utm_medium=software&utm_campaign=change-account-before-adding-printers"
|
||||||
|
|
||||||
class AuthorizationService:
|
class AuthorizationService:
|
||||||
"""The authorization service is responsible for handling the login flow, storing user credentials and providing
|
"""The authorization service is responsible for handling the login flow, storing user credentials and providing
|
||||||
|
@ -209,10 +209,11 @@ class AuthorizationService:
|
||||||
link to force the a browser logout from mycloud.ultimaker.com
|
link to force the a browser logout from mycloud.ultimaker.com
|
||||||
:return: The authentication URL, properly formatted and encoded
|
:return: The authentication URL, properly formatted and encoded
|
||||||
"""
|
"""
|
||||||
auth_url = "{}?{}".format(self._auth_url, urlencode(query_parameters_dict))
|
auth_url = f"{self._auth_url}?{urlencode(query_parameters_dict)}"
|
||||||
if force_browser_logout:
|
if force_browser_logout:
|
||||||
# The url after '?next=' should be urlencoded
|
connecting_char = "&" if "?" in MYCLOUD_LOGOFF_URL else "?"
|
||||||
auth_url = "{}?next={}".format(MYCLOUD_LOGOFF_URL, quote_plus(auth_url))
|
# The url after 'next=' should be urlencoded
|
||||||
|
auth_url = f"{MYCLOUD_LOGOFF_URL}{connecting_char}next={quote_plus(auth_url)}"
|
||||||
return auth_url
|
return auth_url
|
||||||
|
|
||||||
def _onAuthStateChanged(self, auth_response: AuthenticationResponse) -> None:
|
def _onAuthStateChanged(self, auth_response: AuthenticationResponse) -> None:
|
||||||
|
|
|
@ -96,7 +96,7 @@ Item
|
||||||
visible: createNewProjectButtonVisible && !manager.userAccountCanCreateNewLibraryProject && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed)
|
visible: createNewProjectButtonVisible && !manager.userAccountCanCreateNewLibraryProject && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed)
|
||||||
tooltip: "Maximum number of projects reached. Please upgrade your subscription to create more projects."
|
tooltip: "Maximum number of projects reached. Please upgrade your subscription to create more projects."
|
||||||
|
|
||||||
onClicked: Qt.openUrlExternally("https://ultimaker.com/software/ultimaker-essentials/sign-up-cura?utm_source=cura&utm_medium=software&utm_campaign=lib-max")
|
onClicked: Qt.openUrlExternally("https://ultimaker.com/software/enterprise-software?utm_source=cura&utm_medium=software&utm_campaign=MaxProjLink")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ Item
|
||||||
id: visitDigitalLibraryButton
|
id: visitDigitalLibraryButton
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
text: "Visit Digital Library"
|
text: "Visit Digital Library"
|
||||||
onClicked: Qt.openUrlExternally(CuraApplication.ultimakerDigitalFactoryUrl + "/app/library")
|
onClicked: Qt.openUrlExternally(CuraApplication.ultimakerDigitalFactoryUrl + "/app/library?utm_source=cura&utm_medium=software&utm_campaign=empty-library")
|
||||||
visible: searchBar.text === "" //Show the link to Digital Library when there are no projects in the user's Library.
|
visible: searchBar.text === "" //Show the link to Digital Library when there are no projects in the user's Library.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,7 +319,7 @@ class DFFileExportAndUploadManager:
|
||||||
|
|
||||||
def _onMessageActionTriggered(self, message, action):
|
def _onMessageActionTriggered(self, message, action):
|
||||||
if action == "open_df_project":
|
if action == "open_df_project":
|
||||||
project_url = "{}/app/library/project/{}?wait_for_new_files=true".format(CuraApplication.getInstance().ultimakerDigitalFactoryUrl, self._library_project_id)
|
project_url = "{}/app/library/project/{}?wait_for_new_files=true&utm_source=cura&utm_medium=software&utm_campaign=saved-library-file-message".format(CuraApplication.getInstance().ultimakerDigitalFactoryUrl, self._library_project_id)
|
||||||
QDesktopServices.openUrl(QUrl(project_url))
|
QDesktopServices.openUrl(QUrl(project_url))
|
||||||
message.hide()
|
message.hide()
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ Rectangle
|
||||||
text: catalog.i18nc("@info:tooltip", "Go to Web Marketplace")
|
text: catalog.i18nc("@info:tooltip", "Go to Web Marketplace")
|
||||||
Label
|
Label
|
||||||
{
|
{
|
||||||
text: "<a href='%2'>".arg(toolbox.getWebMarketplaceUrl("materials")) + catalog.i18nc("@label", "Search materials") + "</a>"
|
text: "<a href='%2'>".arg(toolbox.getWebMarketplaceUrl("materials") + "?utm_source=cura&utm_medium=software&utm_campaign=marketplace-search") + catalog.i18nc("@label", "Search materials") + "</a>"
|
||||||
width: contentWidth
|
width: contentWidth
|
||||||
height: contentHeight
|
height: contentHeight
|
||||||
horizontalAlignment: Text.AlignRight
|
horizontalAlignment: Text.AlignRight
|
||||||
|
|
|
@ -91,7 +91,7 @@ Item
|
||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onClicked: Qt.openUrlExternally(toolbox.getWebMarketplaceUrl("plugins"))
|
onClicked: Qt.openUrlExternally(toolbox.getWebMarketplaceUrl("plugins") + "?utm_source=cura&utm_medium=software&utm_campaign=marketplace-button")
|
||||||
UM.RecolorImage
|
UM.RecolorImage
|
||||||
{
|
{
|
||||||
id: cloudMarketplaceButton
|
id: cloudMarketplaceButton
|
||||||
|
|
|
@ -173,7 +173,7 @@ Cura.MachineAction
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
wrapMode: Text.WordWrap
|
wrapMode: Text.WordWrap
|
||||||
renderType: Text.NativeRendering
|
renderType: Text.NativeRendering
|
||||||
text: catalog.i18nc("@label", "If your printer is not listed, read the <a href='%1'>network printing troubleshooting guide</a>").arg("https://support.ultimaker.com/hc/en-us/articles/360012795419");
|
text: catalog.i18nc("@label", "If your printer is not listed, read the <a href='%1'>network printing troubleshooting guide</a>").arg("https://ultimaker.com/en/cura/troubleshooting/network?utm_source=cura&utm_medium=software&utm_campaign=manage-network-printer");
|
||||||
onLinkActivated: Qt.openUrlExternally(link)
|
onLinkActivated: Qt.openUrlExternally(link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
icon="",
|
icon="",
|
||||||
description=I18N_CATALOG.i18nc("@action:tooltip", "Track the print in Ultimaker Digital Factory"),
|
description=I18N_CATALOG.i18nc("@action:tooltip", "Track the print in Ultimaker Digital Factory"),
|
||||||
button_align=message.ActionButtonAlignment.ALIGN_RIGHT)
|
button_align=message.ActionButtonAlignment.ALIGN_RIGHT)
|
||||||
df_url = f"https://digitalfactory.ultimaker.com/app/jobs/{self._cluster.cluster_id}?utm_source=cura&utm_medium=software&utm_campaign=monitor-button"
|
df_url = f"https://digitalfactory.ultimaker.com/app/jobs/{self._cluster.cluster_id}?utm_source=cura&utm_medium=software&utm_campaign=message-printjob-sent"
|
||||||
message.pyQtActionTriggered.connect(lambda message, action: (QDesktopServices.openUrl(QUrl(df_url)), message.hide()))
|
message.pyQtActionTriggered.connect(lambda message, action: (QDesktopServices.openUrl(QUrl(df_url)), message.hide()))
|
||||||
|
|
||||||
message.show()
|
message.show()
|
||||||
|
@ -334,11 +334,11 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
|
|
||||||
@pyqtSlot(name="openPrintJobControlPanel")
|
@pyqtSlot(name="openPrintJobControlPanel")
|
||||||
def openPrintJobControlPanel(self) -> None:
|
def openPrintJobControlPanel(self) -> None:
|
||||||
QDesktopServices.openUrl(QUrl(self.clusterCloudUrl))
|
QDesktopServices.openUrl(QUrl(self.clusterCloudUrl)+ "?utm_source=cura&utm_medium=software&utm_campaign=monitor-manage-browser")
|
||||||
|
|
||||||
@pyqtSlot(name="openPrinterControlPanel")
|
@pyqtSlot(name="openPrinterControlPanel")
|
||||||
def openPrinterControlPanel(self) -> None:
|
def openPrinterControlPanel(self) -> None:
|
||||||
QDesktopServices.openUrl(QUrl(self.clusterCloudUrl))
|
QDesktopServices.openUrl(QUrl(self.clusterCloudUrl + "?utm_source=cura&utm_medium=software&utm_campaign=monitor-manage-printer"))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def clusterData(self) -> CloudClusterResponse:
|
def clusterData(self) -> CloudClusterResponse:
|
||||||
|
@ -357,4 +357,4 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
|
||||||
"""Gets the URL on which to monitor the cluster via the cloud."""
|
"""Gets the URL on which to monitor the cluster via the cloud."""
|
||||||
|
|
||||||
root_url_prefix = "-staging" if self._account.is_staging else ""
|
root_url_prefix = "-staging" if self._account.is_staging else ""
|
||||||
return "https://mycloud{}.ultimaker.com/app/jobs/{}".format(root_url_prefix, self.clusterData.cluster_id)
|
return "https://digitalfactory{}.ultimaker.com/app/jobs/{}".format(root_url_prefix, self.clusterData.cluster_id)
|
||||||
|
|
|
@ -332,7 +332,7 @@ class CloudOutputDeviceManager:
|
||||||
|
|
||||||
message_text += self.i18n_catalog.i18nc(
|
message_text += self.i18n_catalog.i18nc(
|
||||||
"info:status",
|
"info:status",
|
||||||
"To establish a connection, please visit the {website_link}".format(website_link = "<a href='https://digitalfactory.ultimaker.com/'>{}</a>.".format(digital_factory_string))
|
"To establish a connection, please visit the {website_link}".format(website_link = "<a href='https://digitalfactory.ultimaker.com?utm_source=cura&utm_medium=software&utm_campaign=change-account-connect-printer'>{}</a>.".format(digital_factory_string))
|
||||||
)
|
)
|
||||||
self._removed_printers_message.setText(message_text)
|
self._removed_printers_message.setText(message_text)
|
||||||
self._removed_printers_message.addAction("keep_printer_configurations_action",
|
self._removed_printers_message.addAction("keep_printer_configurations_action",
|
||||||
|
@ -419,7 +419,7 @@ class CloudOutputDeviceManager:
|
||||||
machine.setMetaDataEntry("group_name", device.name)
|
machine.setMetaDataEntry("group_name", device.name)
|
||||||
machine.setMetaDataEntry("group_size", device.clusterSize)
|
machine.setMetaDataEntry("group_size", device.clusterSize)
|
||||||
digital_factory_string = self.i18n_catalog.i18nc("info:name", "Ultimaker Digital Factory")
|
digital_factory_string = self.i18n_catalog.i18nc("info:name", "Ultimaker Digital Factory")
|
||||||
digital_factory_link = "<a href='https://digitalfactory.ultimaker.com/'>{digital_factory_string}</a>".format(digital_factory_string = digital_factory_string)
|
digital_factory_link = "<a href='https://digitalfactory.ultimaker.com?utm_source=cura&utm_medium=software&utm_campaign=change-account-remove-printer'>{digital_factory_string}</a>".format(digital_factory_string = digital_factory_string)
|
||||||
removal_warning_string = self.i18n_catalog.i18nc("@message {printer_name} is replaced with the name of the printer", "{printer_name} will be removed until the next account sync.").format(printer_name = device.name) \
|
removal_warning_string = self.i18n_catalog.i18nc("@message {printer_name} is replaced with the name of the printer", "{printer_name} will be removed until the next account sync.").format(printer_name = device.name) \
|
||||||
+ "<br>" + self.i18n_catalog.i18nc("@message {printer_name} is replaced with the name of the printer", "To remove {printer_name} permanently, visit {digital_factory_link}").format(printer_name = device.name, digital_factory_link = digital_factory_link) \
|
+ "<br>" + self.i18n_catalog.i18nc("@message {printer_name} is replaced with the name of the printer", "To remove {printer_name} permanently, visit {digital_factory_link}").format(printer_name = device.name, digital_factory_link = digital_factory_link) \
|
||||||
+ "<br><br>" + self.i18n_catalog.i18nc("@message {printer_name} is replaced with the name of the printer", "Are you sure you want to remove {printer_name} temporarily?").format(printer_name = device.name)
|
+ "<br><br>" + self.i18n_catalog.i18nc("@message {printer_name} is replaced with the name of the printer", "Are you sure you want to remove {printer_name} temporarily?").format(printer_name = device.name)
|
||||||
|
|
|
@ -60,6 +60,6 @@ Column
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
height: UM.Theme.getSize("account_button").height
|
height: UM.Theme.getSize("account_button").height
|
||||||
text: catalog.i18nc("@button", "Create a free Ultimaker account")
|
text: catalog.i18nc("@button", "Create a free Ultimaker account")
|
||||||
onClicked: Qt.openUrlExternally(CuraApplication.ultimakerCloudAccountRootUrl + "/app/create")
|
onClicked: Qt.openUrlExternally("https://ultimaker.com/ultimaker-cura-account-sign-up?utm_source=cura&utm_medium=software&utm_campaign=menu-signup")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ Column
|
||||||
width: UM.Theme.getSize("account_button").width
|
width: UM.Theme.getSize("account_button").width
|
||||||
height: UM.Theme.getSize("account_button").height
|
height: UM.Theme.getSize("account_button").height
|
||||||
text: "Ultimaker Digital Factory"
|
text: "Ultimaker Digital Factory"
|
||||||
onClicked: Qt.openUrlExternally(CuraApplication.ultimakerDigitalFactoryUrl)
|
onClicked: Qt.openUrlExternally(CuraApplication.ultimakerDigitalFactoryUrl + "?utm_source=cura&utm_medium=software&utm_campaign=menu-visit-DF")
|
||||||
fixedWidthMode: false
|
fixedWidthMode: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ Column
|
||||||
width: UM.Theme.getSize("account_button").width
|
width: UM.Theme.getSize("account_button").width
|
||||||
height: UM.Theme.getSize("account_button").height
|
height: UM.Theme.getSize("account_button").height
|
||||||
text: catalog.i18nc("@button", "Ultimaker Account")
|
text: catalog.i18nc("@button", "Ultimaker Account")
|
||||||
onClicked: Qt.openUrlExternally(CuraApplication.ultimakerCloudAccountRootUrl)
|
onClicked: Qt.openUrlExternally(CuraApplication.ultimakerCloudAccountRootUrl + "?utm_source=cura&utm_medium=software&utm_campaign=menu-visit-account")
|
||||||
fixedWidthMode: false
|
fixedWidthMode: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ Item
|
||||||
Action
|
Action
|
||||||
{
|
{
|
||||||
id: showTroubleShootingAction
|
id: showTroubleShootingAction
|
||||||
onTriggered: Qt.openUrlExternally("https://ultimaker.com/en/troubleshooting")
|
onTriggered: Qt.openUrlExternally("https://ultimaker.com/en/troubleshooting?utm_source=cura&utm_medium=software&utm_campaign=dropdown-troubleshooting")
|
||||||
text: catalog.i18nc("@action:inmenu", "Show Online Troubleshooting Guide");
|
text: catalog.i18nc("@action:inmenu", "Show Online Troubleshooting Guide");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import Cura 1.7 as Cura
|
||||||
//
|
//
|
||||||
// This component gets activated when the user presses the "Add cloud printers" button from the "Add a Printer" page.
|
// This component gets activated when the user presses the "Add cloud printers" button from the "Add a Printer" page.
|
||||||
// It contains a busy indicator that remains active until the user logs in and adds a cloud printer in his/her account.
|
// It contains a busy indicator that remains active until the user logs in and adds a cloud printer in his/her account.
|
||||||
// Once a cloud printer is added in mycloud.ultimaker.com, Cura discovers it (in a time window of 30 sec) and displays
|
// Once a cloud printer is added in digitalfactory.ultimaker.com, Cura discovers it (in a time window of 30 sec) and displays
|
||||||
// the newly added printers in this page.
|
// the newly added printers in this page.
|
||||||
//
|
//
|
||||||
Item
|
Item
|
||||||
|
|
|
@ -251,7 +251,7 @@ Item
|
||||||
onClicked:
|
onClicked:
|
||||||
{
|
{
|
||||||
// open the troubleshooting URL with web browser
|
// open the troubleshooting URL with web browser
|
||||||
const url = "https://ultimaker.com/in/cura/troubleshooting/network"
|
const url = "https://ultimaker.com/in/cura/troubleshooting/network?utm_source=cura&utm_medium=software&utm_campaign=add-network-printer"
|
||||||
Qt.openUrlExternally(url)
|
Qt.openUrlExternally(url)
|
||||||
}
|
}
|
||||||
onEntered:
|
onEntered:
|
||||||
|
|
|
@ -215,7 +215,7 @@ Item
|
||||||
id: createAccountButton
|
id: createAccountButton
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
text: catalog.i18nc("@text", "Create a free Ultimaker Account")
|
text: catalog.i18nc("@text", "Create a free Ultimaker Account")
|
||||||
onClicked: Qt.openUrlExternally(CuraApplication.ultimakerCloudAccountRootUrl + "/app/create")
|
onClicked: Qt.openUrlExternally("https://ultimaker.com/ultimaker-cura-account-sign-up?utm_source=cura&utm_medium=software&utm_campaign=onboarding-signup")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,7 +238,7 @@ def test__generate_auth_url() -> None:
|
||||||
"response_type": "code"
|
"response_type": "code"
|
||||||
}
|
}
|
||||||
auth_url = authorization_service._generate_auth_url(query_parameters_dict, force_browser_logout = False)
|
auth_url = authorization_service._generate_auth_url(query_parameters_dict, force_browser_logout = False)
|
||||||
assert MYCLOUD_LOGOFF_URL + "?next=" not in auth_url
|
assert MYCLOUD_LOGOFF_URL + "&next=" not in auth_url
|
||||||
|
|
||||||
auth_url = authorization_service._generate_auth_url(query_parameters_dict, force_browser_logout = True)
|
auth_url = authorization_service._generate_auth_url(query_parameters_dict, force_browser_logout = True)
|
||||||
assert MYCLOUD_LOGOFF_URL + "?next=" in auth_url
|
assert MYCLOUD_LOGOFF_URL + "&next=" in auth_url
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue