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:
ChrisTerBeke 2018-12-04 21:30:24 +01:00
commit 467d347008
No known key found for this signature in database
GPG key ID: A49F1AB9D7E0C263
10 changed files with 169 additions and 99 deletions

View file

@ -118,17 +118,40 @@ class PrintJobOutputModel(QObject):
self.nameChanged.emit() self.nameChanged.emit()
@pyqtProperty(int, notify = timeTotalChanged) @pyqtProperty(int, notify = timeTotalChanged)
def timeTotal(self): def timeTotal(self) -> int:
return self._time_total return self._time_total
@pyqtProperty(int, notify = timeElapsedChanged) @pyqtProperty(int, notify = timeElapsedChanged)
def timeElapsed(self): def timeElapsed(self) -> int:
return self._time_elapsed 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) @pyqtProperty(str, notify=stateChanged)
def state(self): def state(self) -> str:
return self._state 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): def updateTimeTotal(self, new_time_total):
if self._time_total != new_time_total: if self._time_total != new_time_total:
self._time_total = new_time_total self._time_total = new_time_total

View file

@ -21,7 +21,14 @@ Item
{ {
id: previewImage id: previewImage
anchors.fill: parent 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 : "" source: printJob ? printJob.previewImageUrl : ""
visible: printJob visible: printJob
} }
@ -47,11 +54,28 @@ Item
UM.RecolorImage UM.RecolorImage
{ {
id: statusImage id: overlayIcon
anchors.centerIn: printJobPreview anchors.centerIn: printJobPreview
color: UM.Theme.getColor("monitor_image_overlay") color: UM.Theme.getColor("monitor_image_overlay")
height: 0.5 * printJobPreview.height 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 sourceSize
{ {
height: height height: height

View file

@ -15,63 +15,10 @@ import UM 1.3 as UM
Item Item
{ {
id: base id: base
// The print job which all other information is dervied from
property var printJob: null 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 width: childrenRect.width
height: 18 * screenScaleFactor // TODO: Theme! height: 18 * screenScaleFactor // TODO: Theme!
@ -82,12 +29,12 @@ Item
{ {
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
} }
value: progress; value: printJob ? printJob.progress : 0
style: ProgressBarStyle style: ProgressBarStyle
{ {
background: Rectangle background: Rectangle
{ {
color: "#e4e4f2" // TODO: Theme! color: printJob && printJob.isActive ? "#e4e4f2" : "#f3f3f9" // TODO: Theme!
implicitHeight: visible ? 8 * screenScaleFactor : 0 // TODO: Theme! implicitHeight: visible ? 8 * screenScaleFactor : 0 // TODO: Theme!
implicitWidth: 180 * screenScaleFactor // TODO: Theme! implicitWidth: 180 * screenScaleFactor // TODO: Theme!
radius: 4 * screenScaleFactor // TODO: Theme! radius: 4 * screenScaleFactor // TODO: Theme!
@ -95,41 +42,74 @@ Item
progress: Rectangle progress: Rectangle
{ {
id: progressItem; id: progressItem;
color: color: printJob && printJob.isActive ? "#0a0850" : "#9392b2" // TODO: Theme!
{
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!
}
radius: 4 * screenScaleFactor // TODO: Theme! radius: 4 * screenScaleFactor // TODO: Theme!
} }
} }
} }
Label Label
{ {
id: progressLabel id: percentLabel
anchors anchors
{ {
left: progressBar.right left: progressBar.right
leftMargin: 18 * screenScaleFactor // TODO: Theme! leftMargin: 18 * screenScaleFactor // TODO: Theme!
} }
text: progressText text: Math.round(printJob.progress * 100) + "%"
color: "#374355" // TODO: Theme! color: printJob && printJob.isActive ? "#374355" : "#babac1" // TODO: Theme!
width: contentWidth width: contentWidth
font: UM.Theme.getFont("medium") // 14pt, regular 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: // FIXED-LINE-HEIGHT:
height: 18 * screenScaleFactor // TODO: Theme! height: 18 * screenScaleFactor // TODO: Theme!
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter

View file

@ -169,6 +169,30 @@ Item
height: childrenRect.height height: childrenRect.height
spacing: 18 * screenScaleFactor // TODO: Theme! 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 Item
{ {
anchors anchors
@ -183,6 +207,7 @@ Item
printJob: base.printer.activePrintJob printJob: base.printer.activePrintJob
size: parent.height size: parent.height
} }
visible: printer.activePrintJob
} }
Item Item
@ -193,14 +218,15 @@ Item
} }
width: 216 * screenScaleFactor // TODO: Theme! width: 216 * screenScaleFactor // TODO: Theme!
height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme! height: printerNameLabel.height + printerFamilyPill.height + 6 * screenScaleFactor // TODO: Theme!
visible: printer.activePrintJob
Label Label
{ {
id: printerJobNameLabel id: printerJobNameLabel
text: base.printer.activePrintJob ? base.printer.activePrintJob.name : "Untitled" // TODO: I18N color: printer.activePrintJob && printer.activePrintJob.isActive ? "#414054" : "#babac1" // TODO: Theme!
color: "#414054" // TODO: Theme!
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("large") // 16pt, bold font: UM.Theme.getFont("large") // 16pt, bold
text: base.printer.activePrintJob ? base.printer.activePrintJob.name : "Untitled" // TODO: I18N
width: parent.width width: parent.width
// FIXED-LINE-HEIGHT: // FIXED-LINE-HEIGHT:
@ -217,10 +243,10 @@ Item
topMargin: 6 * screenScaleFactor // TODO: Theme! topMargin: 6 * screenScaleFactor // TODO: Theme!
left: printerJobNameLabel.left left: printerJobNameLabel.left
} }
text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N color: printer.activePrintJob && printer.activePrintJob.isActive ? "#53657d" : "#babac1" // TODO: Theme!
color: "#53657d" // TODO: Theme!
elide: Text.ElideRight elide: Text.ElideRight
font: UM.Theme.getFont("very_small") // 12pt, regular font: UM.Theme.getFont("very_small") // 12pt, regular
text: printer.activePrintJob ? printer.activePrintJob.owner : "Anonymous" // TODO: I18N
width: parent.width width: parent.width
// FIXED-LINE-HEIGHT: // FIXED-LINE-HEIGHT:
@ -236,6 +262,7 @@ Item
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
} }
printJob: printer.activePrintJob printJob: printer.activePrintJob
visible: printer.activePrintJob
} }
} }
} }

View file

@ -386,8 +386,24 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
@pyqtSlot(int, result = str) @pyqtSlot(int, result = str)
def getDateCompleted(self, time_remaining: int) -> str: def getDateCompleted(self, time_remaining: int) -> str:
current_time = time() current_time = time()
datetime_completed = datetime.fromtimestamp(current_time + time_remaining) completed = datetime.fromtimestamp(current_time + time_remaining)
return (datetime_completed.strftime("%a %b ") + "{day}".format(day=datetime_completed.day)).upper() 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) @pyqtSlot(str)
def sendJobToTop(self, print_job_uuid: str) -> None: def sendJobToTop(self, print_job_uuid: str) -> None:

View file

@ -3,8 +3,8 @@
from UM.Job import Job from UM.Job import Job
from UM.Logger import Logger from UM.Logger import Logger
from plugins.USBPrinting.avr_isp import ispBase
from .avr_isp import ispBase
from .avr_isp.stk500v2 import Stk500v2 from .avr_isp.stk500v2 import Stk500v2
from time import time, sleep from time import time, sleep

View file

@ -1,7 +1,7 @@
{ {
"name": "USB printing", "name": "USB printing",
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.1",
"api": 5, "api": 5,
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.", "description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.",
"i18n-catalog": "cura" "i18n-catalog": "cura"

View file

@ -532,7 +532,7 @@
"package_type": "plugin", "package_type": "plugin",
"display_name": "USB Printing", "display_name": "USB Printing",
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.", "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, "sdk_version": 5,
"website": "https://ultimaker.com", "website": "https://ultimaker.com",
"author": { "author": {

View file

@ -137,6 +137,10 @@ Column
{ {
var autoSlice = UM.Preferences.getValue("general/auto_slice") var autoSlice = UM.Preferences.getValue("general/auto_slice")
prepareButtons.autoSlice = autoSlice prepareButtons.autoSlice = autoSlice
if(autoSlice)
{
CuraApplication.backend.forceSlice()
}
} }
} }

View file

@ -25,11 +25,7 @@ UM.PreferencesPage
function reset() function reset()
{ {
UM.Preferences.resetPreference("general/visible_settings") settingVisibilityPresetsModel.setActivePreset("basic")
// After calling this function update Setting visibility preset combobox.
// Reset should set default setting preset ("Basic")
visibilityPreset.currentIndex = 1
} }
resetEnabled: true; resetEnabled: true;