mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-18 20:28:01 -06:00
Merge branch 'ui_rework_4_0' into STAR-322_cloud-connection
* ui_rework_4_0: Ensure that reset always correctly gets set to basic Remove semi-colon Simplify preview icon logic Always return a string for preview icon Update USBPrinting version to 1.0.1 Fix module importing in USBPrinting When toggling auto-slice, force a re-slice Fix multi-argument i18n string Improve printer status handling Make "finishes at" single translatable string Improve exposed progress prop Simplify logic slightly Handle idle, unavailable, and unreachable states Improve printer status and progress bar Improve date rendering Add some typings Move isActive and timeRemaining logic from QML to Python
This commit is contained in:
commit
467d347008
10 changed files with 169 additions and 99 deletions
|
@ -118,17 +118,40 @@ class PrintJobOutputModel(QObject):
|
|||
self.nameChanged.emit()
|
||||
|
||||
@pyqtProperty(int, notify = timeTotalChanged)
|
||||
def timeTotal(self):
|
||||
def timeTotal(self) -> int:
|
||||
return self._time_total
|
||||
|
||||
@pyqtProperty(int, notify = timeElapsedChanged)
|
||||
def timeElapsed(self):
|
||||
def timeElapsed(self) -> int:
|
||||
return self._time_elapsed
|
||||
|
||||
@pyqtProperty(int, notify = timeElapsedChanged)
|
||||
def timeRemaining(self) -> int:
|
||||
# Never get a negative time remaining
|
||||
return max(self.timeTotal - self.timeElapsed, 0)
|
||||
|
||||
@pyqtProperty(float, notify = timeElapsedChanged)
|
||||
def progress(self) -> float:
|
||||
result = self.timeElapsed / self.timeTotal
|
||||
# Never get a progress past 1.0
|
||||
return min(result, 1.0)
|
||||
|
||||
@pyqtProperty(str, notify=stateChanged)
|
||||
def state(self):
|
||||
def state(self) -> str:
|
||||
return self._state
|
||||
|
||||
@pyqtProperty(bool, notify=stateChanged)
|
||||
def isActive(self) -> bool:
|
||||
inactiveStates = [
|
||||
"pausing",
|
||||
"paused",
|
||||
"resuming",
|
||||
"wait_cleanup"
|
||||
]
|
||||
if self.state in inactiveStates and self.timeRemaining > 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
def updateTimeTotal(self, new_time_total):
|
||||
if self._time_total != new_time_total:
|
||||
self._time_total = new_time_total
|
||||
|
|
|
@ -21,7 +21,14 @@ Item
|
|||
{
|
||||
id: previewImage
|
||||
anchors.fill: parent
|
||||
opacity: printJob && printJob.state == "error" ? 0.5 : 1.0
|
||||
opacity:
|
||||
{
|
||||
if (printJob && (printJob.state == "error" || !printJob.isActive))
|
||||
{
|
||||
return 0.5
|
||||
}
|
||||
return 1.0
|
||||
}
|
||||
source: printJob ? printJob.previewImageUrl : ""
|
||||
visible: printJob
|
||||
}
|
||||
|
@ -47,11 +54,28 @@ Item
|
|||
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: statusImage
|
||||
id: overlayIcon
|
||||
anchors.centerIn: printJobPreview
|
||||
color: UM.Theme.getColor("monitor_image_overlay")
|
||||
height: 0.5 * printJobPreview.height
|
||||
source: printJob && printJob.state == "error" ? "../svg/aborted-icon.svg" : ""
|
||||
source:
|
||||
{
|
||||
switch(printJob.state)
|
||||
{
|
||||
case "error":
|
||||
return "../svg/aborted-icon.svg"
|
||||
case "wait_cleanup":
|
||||
return printJob.timeTotal > printJob.timeElapsed ? "../svg/aborted-icon.svg" : ""
|
||||
case "pausing":
|
||||
return "../svg/paused-icon.svg"
|
||||
case "paused":
|
||||
return "../svg/paused-icon.svg"
|
||||
case "resuming":
|
||||
return "../svg/paused-icon.svg"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
sourceSize
|
||||
{
|
||||
height: height
|
||||
|
|
|
@ -15,63 +15,10 @@ import UM 1.3 as UM
|
|||
Item
|
||||
{
|
||||
id: base
|
||||
|
||||
// The print job which all other information is dervied from
|
||||
property var printJob: null
|
||||
property var progress:
|
||||
{
|
||||
if (!printJob)
|
||||
{
|
||||
return 0
|
||||
}
|
||||
var result = printJob.timeElapsed / printJob.timeTotal
|
||||
if (result > 1.0)
|
||||
{
|
||||
result = 1.0
|
||||
}
|
||||
return result
|
||||
}
|
||||
property var remainingTime:
|
||||
{
|
||||
if (!printJob) {
|
||||
return 0
|
||||
}
|
||||
/* Sometimes total minus elapsed is less than 0. Use Math.max() to prevent remaining
|
||||
time from ever being less than 0. Negative durations cause strange behavior such
|
||||
as displaying "-1h -1m". */
|
||||
return Math.max(printer.activePrintJob.timeTotal - printer.activePrintJob.timeElapsed, 0)
|
||||
}
|
||||
property var progressText:
|
||||
{
|
||||
if (!printJob)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
switch (printJob.state)
|
||||
{
|
||||
case "wait_cleanup":
|
||||
if (printJob.timeTotal > printJob.timeElapsed)
|
||||
{
|
||||
return catalog.i18nc("@label:status", "Aborted")
|
||||
}
|
||||
return catalog.i18nc("@label:status", "Finished")
|
||||
case "pre_print":
|
||||
case "sent_to_printer":
|
||||
return catalog.i18nc("@label:status", "Preparing")
|
||||
case "aborted":
|
||||
return catalog.i18nc("@label:status", "Aborted")
|
||||
case "wait_user_action":
|
||||
return catalog.i18nc("@label:status", "Aborted")
|
||||
case "pausing":
|
||||
return catalog.i18nc("@label:status", "Pausing")
|
||||
case "paused":
|
||||
return OutputDevice.formatDuration( remainingTime )
|
||||
case "resuming":
|
||||
return catalog.i18nc("@label:status", "Resuming")
|
||||
case "queued":
|
||||
return catalog.i18nc("@label:status", "Action required")
|
||||
default:
|
||||
return OutputDevice.formatDuration( remainingTime )
|
||||
}
|
||||
}
|
||||
|
||||
width: childrenRect.width
|
||||
height: 18 * screenScaleFactor // TODO: Theme!
|
||||
|
||||
|
@ -82,12 +29,12 @@ Item
|
|||
{
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
value: progress;
|
||||
value: printJob ? printJob.progress : 0
|
||||
style: ProgressBarStyle
|
||||
{
|
||||
background: Rectangle
|
||||
{
|
||||
color: "#e4e4f2" // TODO: Theme!
|
||||
color: printJob && printJob.isActive ? "#e4e4f2" : "#f3f3f9" // TODO: Theme!
|
||||
implicitHeight: visible ? 8 * screenScaleFactor : 0 // TODO: Theme!
|
||||
implicitWidth: 180 * screenScaleFactor // TODO: Theme!
|
||||
radius: 4 * screenScaleFactor // TODO: Theme!
|
||||
|
@ -95,41 +42,74 @@ Item
|
|||
progress: Rectangle
|
||||
{
|
||||
id: progressItem;
|
||||
color:
|
||||
{
|
||||
if (printJob)
|
||||
{
|
||||
var state = printJob.state
|
||||
var inactiveStates = [
|
||||
"pausing",
|
||||
"paused",
|
||||
"resuming",
|
||||
"wait_cleanup"
|
||||
]
|
||||
if (inactiveStates.indexOf(state) > -1 && remainingTime > 0)
|
||||
{
|
||||
return UM.Theme.getColor("monitor_progress_fill_inactive")
|
||||
}
|
||||
}
|
||||
return "#0a0850" // TODO: Theme!
|
||||
}
|
||||
color: printJob && printJob.isActive ? "#0a0850" : "#9392b2" // TODO: Theme!
|
||||
radius: 4 * screenScaleFactor // TODO: Theme!
|
||||
}
|
||||
}
|
||||
}
|
||||
Label
|
||||
{
|
||||
id: progressLabel
|
||||
id: percentLabel
|
||||
anchors
|
||||
{
|
||||
left: progressBar.right
|
||||
leftMargin: 18 * screenScaleFactor // TODO: Theme!
|
||||
}
|
||||
text: progressText
|
||||
color: "#374355" // TODO: Theme!
|
||||
text: Math.round(printJob.progress * 100) + "%"
|
||||
color: printJob && printJob.isActive ? "#374355" : "#babac1" // TODO: Theme!
|
||||
width: contentWidth
|
||||
font: UM.Theme.getFont("medium") // 14pt, regular
|
||||
|
||||
// FIXED-LINE-HEIGHT:
|
||||
height: 18 * screenScaleFactor // TODO: Theme!
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
Label
|
||||
{
|
||||
id: statusLabel
|
||||
anchors
|
||||
{
|
||||
left: percentLabel.right
|
||||
leftMargin: 18 * screenScaleFactor // TODO: Theme!
|
||||
}
|
||||
color: "#374355" // TODO: Theme!
|
||||
font: UM.Theme.getFont("medium") // 14pt, regular
|
||||
text:
|
||||
{
|
||||
if (!printJob)
|
||||
{
|
||||
return ""
|
||||
}
|
||||
switch (printJob.state)
|
||||
{
|
||||
case "wait_cleanup":
|
||||
if (printJob.timeTotal > printJob.timeElapsed)
|
||||
{
|
||||
return catalog.i18nc("@label:status", "Aborted")
|
||||
}
|
||||
return catalog.i18nc("@label:status", "Finished")
|
||||
case "sent_to_printer":
|
||||
return catalog.i18nc("@label:status", "Preparing...")
|
||||
case "pre_print":
|
||||
return catalog.i18nc("@label:status", "Preparing...")
|
||||
case "aborting": // NOTE: Doesn't exist but maybe should someday
|
||||
return catalog.i18nc("@label:status", "Aborting...")
|
||||
case "aborted": // NOTE: Unused, see above
|
||||
return catalog.i18nc("@label:status", "Aborted")
|
||||
case "pausing":
|
||||
return catalog.i18nc("@label:status", "Pausing...")
|
||||
case "paused":
|
||||
return catalog.i18nc("@label:status", "Paused")
|
||||
case "resuming":
|
||||
return catalog.i18nc("@label:status", "Resuming...")
|
||||
case "queued":
|
||||
return catalog.i18nc("@label:status", "Action required")
|
||||
default:
|
||||
return catalog.i18nc("@label:status", "Finishes %1 at %2".arg(OutputDevice.getDateCompleted( printJob.timeRemaining )).arg(OutputDevice.getTimeCompleted( printJob.timeRemaining )))
|
||||
}
|
||||
}
|
||||
width: contentWidth
|
||||
|
||||
// FIXED-LINE-HEIGHT:
|
||||
height: 18 * screenScaleFactor // TODO: Theme!
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
|
|
@ -169,6 +169,30 @@ Item
|
|||
height: childrenRect.height
|
||||
spacing: 18 * screenScaleFactor // TODO: Theme!
|
||||
|
||||
Label
|
||||
{
|
||||
id: printerStatus
|
||||
anchors
|
||||
{
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
color: "#414054" // TODO: Theme!
|
||||
font: UM.Theme.getFont("large") // 16pt, bold
|
||||
text: {
|
||||
if (printer && printer.state == "disabled"){
|
||||
return catalog.i18nc("@label:status", "Unavailable")
|
||||
}
|
||||
if (printer && printer.state == "unreachable"){
|
||||
return catalog.i18nc("@label:status", "Unavailable")
|
||||
}
|
||||
if (printer && !printer.activePrintJob)
|
||||
{
|
||||
return catalog.i18nc("@label:status", "Idle")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
Item
|
||||
{
|
||||
anchors
|
||||
|
@ -183,6 +207,7 @@ Item
|
|||
printJob: base.printer.activePrintJob
|
||||
size: parent.height
|
||||
}
|
||||
visible: printer.activePrintJob
|
||||
}
|
||||
|
||||
Item
|
||||
|
@ -193,14 +218,15 @@ Item
|
|||
}
|
||||
width: 216 * screenScaleFactor // TODO: Theme!
|
||||
height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
|
||||
visible: printer.activePrintJob
|
||||
|
||||
Label
|
||||
{
|
||||
id: printerJobNameLabel
|
||||
text: base.printer.activePrintJob ? base.printer.activePrintJob.name : "Untitled" // TODO: I18N
|
||||
color: "#414054" // TODO: Theme!
|
||||
color: printer.activePrintJob && printer.activePrintJob.isActive ? "#414054" : "#babac1" // TODO: Theme!
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("large") // 16pt, bold
|
||||
text: base.printer.activePrintJob ? base.printer.activePrintJob.name : "Untitled" // TODO: I18N
|
||||
width: parent.width
|
||||
|
||||
// FIXED-LINE-HEIGHT:
|
||||
|
@ -217,10 +243,10 @@ Item
|
|||
topMargin: 6 * screenScaleFactor // TODO: Theme!
|
||||
left: printerJobNameLabel.left
|
||||
}
|
||||
text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N
|
||||
color: "#53657d" // TODO: Theme!
|
||||
color: printer.activePrintJob && printer.activePrintJob.isActive ? "#53657d" : "#babac1" // TODO: Theme!
|
||||
elide: Text.ElideRight
|
||||
font: UM.Theme.getFont("very_small") // 12pt, regular
|
||||
text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N
|
||||
width: parent.width
|
||||
|
||||
// FIXED-LINE-HEIGHT:
|
||||
|
@ -236,6 +262,7 @@ Item
|
|||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
printJob: printer.activePrintJob
|
||||
visible: printer.activePrintJob
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -386,8 +386,24 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
|||
@pyqtSlot(int, result = str)
|
||||
def getDateCompleted(self, time_remaining: int) -> str:
|
||||
current_time = time()
|
||||
datetime_completed = datetime.fromtimestamp(current_time + time_remaining)
|
||||
return (datetime_completed.strftime("%a %b ") + "{day}".format(day=datetime_completed.day)).upper()
|
||||
completed = datetime.fromtimestamp(current_time + time_remaining)
|
||||
today = datetime.fromtimestamp(current_time)
|
||||
|
||||
# If finishing date is more than 7 days out, using "Mon Dec 3 at HH:MM" format
|
||||
if completed.toordinal() > today.toordinal() + 7:
|
||||
return completed.strftime("%a %b ") + "{day}".format(day=completed.day)
|
||||
|
||||
# If finishing date is within the next week, use "Monday at HH:MM" format
|
||||
elif completed.toordinal() > today.toordinal() + 1:
|
||||
return completed.strftime("%a")
|
||||
|
||||
# If finishing tomorrow, use "tomorrow at HH:MM" format
|
||||
elif completed.toordinal() > today.toordinal():
|
||||
return "tomorrow"
|
||||
|
||||
# If finishing today, use "today at HH:MM" format
|
||||
else:
|
||||
return "today"
|
||||
|
||||
@pyqtSlot(str)
|
||||
def sendJobToTop(self, print_job_uuid: str) -> None:
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
from UM.Job import Job
|
||||
from UM.Logger import Logger
|
||||
from plugins.USBPrinting.avr_isp import ispBase
|
||||
|
||||
from .avr_isp import ispBase
|
||||
from .avr_isp.stk500v2 import Stk500v2
|
||||
|
||||
from time import time, sleep
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "USB printing",
|
||||
"author": "Ultimaker B.V.",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"api": 5,
|
||||
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.",
|
||||
"i18n-catalog": "cura"
|
||||
|
|
|
@ -532,7 +532,7 @@
|
|||
"package_type": "plugin",
|
||||
"display_name": "USB Printing",
|
||||
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.",
|
||||
"package_version": "1.0.0",
|
||||
"package_version": "1.0.1",
|
||||
"sdk_version": 5,
|
||||
"website": "https://ultimaker.com",
|
||||
"author": {
|
||||
|
|
|
@ -137,6 +137,10 @@ Column
|
|||
{
|
||||
var autoSlice = UM.Preferences.getValue("general/auto_slice")
|
||||
prepareButtons.autoSlice = autoSlice
|
||||
if(autoSlice)
|
||||
{
|
||||
CuraApplication.backend.forceSlice()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,11 +25,7 @@ UM.PreferencesPage
|
|||
|
||||
function reset()
|
||||
{
|
||||
UM.Preferences.resetPreference("general/visible_settings")
|
||||
|
||||
// After calling this function update Setting visibility preset combobox.
|
||||
// Reset should set default setting preset ("Basic")
|
||||
visibilityPreset.currentIndex = 1
|
||||
settingVisibilityPresetsModel.setActivePreset("basic")
|
||||
}
|
||||
resetEnabled: true;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue