PrintJobContextMenu.qml 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // Copyright (c) 2018 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.2
  4. import QtQuick.Controls 2.0
  5. import QtQuick.Controls.Styles 1.4
  6. import QtQuick.Dialogs 1.1
  7. import QtGraphicalEffects 1.0
  8. import UM 1.3 as UM
  9. Item {
  10. id: root;
  11. property var printJob: null;
  12. property var started: isStarted(printJob);
  13. property var assigned: isAssigned(printJob);
  14. Button {
  15. id: button;
  16. background: Rectangle {
  17. color: UM.Theme.getColor("viewport_background"); // TODO: Theme!
  18. height: button.height;
  19. opacity: button.down || button.hovered ? 1 : 0;
  20. radius: Math.round(0.5 * width);
  21. width: button.width;
  22. }
  23. contentItem: Label {
  24. color: UM.Theme.getColor("monitor_context_menu_dots");
  25. font.pixelSize: 25 * screenScaleFactor;
  26. horizontalAlignment: Text.AlignHCenter;
  27. text: button.text;
  28. verticalAlignment: Text.AlignVCenter;
  29. }
  30. height: width;
  31. hoverEnabled: true;
  32. onClicked: parent.switchPopupState();
  33. text: "\u22EE"; //Unicode; Three stacked points.
  34. visible: {
  35. if (!printJob) {
  36. return false;
  37. }
  38. var states = ["queued", "sent_to_printer", "pre_print", "printing", "pausing", "paused", "resuming"];
  39. return states.indexOf(printJob.state) !== -1;
  40. }
  41. width: 35 * screenScaleFactor; // TODO: Theme!
  42. }
  43. Popup {
  44. id: popup;
  45. background: Item {
  46. anchors.fill: parent;
  47. DropShadow {
  48. anchors.fill: pointedRectangle;
  49. color: UM.Theme.getColor("monitor_shadow");
  50. radius: UM.Theme.getSize("monitor_shadow_radius").width;
  51. source: pointedRectangle;
  52. transparentBorder: true;
  53. verticalOffset: 2 * screenScaleFactor;
  54. }
  55. Item {
  56. id: pointedRectangle;
  57. anchors {
  58. horizontalCenter: parent.horizontalCenter;
  59. verticalCenter: parent.verticalCenter;
  60. }
  61. height: parent.height - 10 * screenScaleFactor; // Because of the shadow
  62. width: parent.width - 10 * screenScaleFactor; // Because of the shadow
  63. Rectangle {
  64. id: point;
  65. anchors {
  66. right: bloop.right;
  67. rightMargin: 24 * screenScaleFactor;
  68. }
  69. color: UM.Theme.getColor("monitor_context_menu_background");
  70. height: 14 * screenScaleFactor;
  71. transform: Rotation {
  72. angle: 45;
  73. }
  74. width: 14 * screenScaleFactor;
  75. y: 1 * screenScaleFactor;
  76. }
  77. Rectangle {
  78. id: bloop;
  79. anchors {
  80. bottom: parent.bottom;
  81. bottomMargin: 8 * screenScaleFactor; // Because of the shadow
  82. top: parent.top;
  83. topMargin: 8 * screenScaleFactor; // Because of the shadow + point
  84. }
  85. color: UM.Theme.getColor("monitor_context_menu_background");
  86. width: parent.width;
  87. }
  88. }
  89. }
  90. clip: true;
  91. closePolicy: Popup.CloseOnPressOutside;
  92. contentItem: Column {
  93. id: popupOptions;
  94. anchors {
  95. top: parent.top;
  96. topMargin: UM.Theme.getSize("default_margin").height + 10 * screenScaleFactor; // Account for the point of the box
  97. }
  98. height: childrenRect.height + spacing * popupOptions.children.length + UM.Theme.getSize("default_margin").height;
  99. spacing: Math.floor(UM.Theme.getSize("default_margin").height / 2);
  100. width: parent.width;
  101. PrintJobContextMenuItem {
  102. onClicked: {
  103. sendToTopConfirmationDialog.visible = true;
  104. popup.close();
  105. }
  106. text: catalog.i18nc("@label", "Move to top");
  107. visible: {
  108. if (printJob && printJob.state == "queued" && !assigned) {
  109. if (OutputDevice && OutputDevice.queuedPrintJobs[0]) {
  110. return OutputDevice.queuedPrintJobs[0].key != printJob.key;
  111. }
  112. }
  113. return false;
  114. }
  115. }
  116. PrintJobContextMenuItem {
  117. onClicked: {
  118. deleteConfirmationDialog.visible = true;
  119. popup.close();
  120. }
  121. text: catalog.i18nc("@label", "Delete");
  122. visible: {
  123. if (!printJob) {
  124. return false;
  125. }
  126. var states = ["queued", "sent_to_printer"];
  127. return states.indexOf(printJob.state) !== -1;
  128. }
  129. }
  130. PrintJobContextMenuItem {
  131. enabled: visible && !(printJob.state == "pausing" || printJob.state == "resuming");
  132. onClicked: {
  133. if (printJob.state == "paused") {
  134. printJob.setState("print");
  135. popup.close();
  136. return;
  137. }
  138. if (printJob.state == "printing") {
  139. printJob.setState("pause");
  140. popup.close();
  141. return;
  142. }
  143. }
  144. text: {
  145. if (!printJob) {
  146. return "";
  147. }
  148. switch(printJob.state) {
  149. case "paused":
  150. return catalog.i18nc("@label", "Resume");
  151. case "pausing":
  152. return catalog.i18nc("@label", "Pausing...");
  153. case "resuming":
  154. return catalog.i18nc("@label", "Resuming...");
  155. default:
  156. catalog.i18nc("@label", "Pause");
  157. }
  158. }
  159. visible: {
  160. if (!printJob) {
  161. return false;
  162. }
  163. var states = ["printing", "pausing", "paused", "resuming"];
  164. return states.indexOf(printJob.state) !== -1;
  165. }
  166. }
  167. PrintJobContextMenuItem {
  168. enabled: visible && printJob.state !== "aborting";
  169. onClicked: {
  170. abortConfirmationDialog.visible = true;
  171. popup.close();
  172. }
  173. text: printJob.state == "aborting" ? catalog.i18nc("@label", "Aborting...") : catalog.i18nc("@label", "Abort");
  174. visible: {
  175. if (!printJob) {
  176. return false;
  177. }
  178. var states = ["pre_print", "printing", "pausing", "paused", "resuming"];
  179. return states.indexOf(printJob.state) !== -1;
  180. }
  181. }
  182. }
  183. enter: Transition {
  184. NumberAnimation {
  185. duration: 75;
  186. property: "visible";
  187. }
  188. }
  189. exit: Transition {
  190. NumberAnimation {
  191. duration: 75;
  192. property: "visible";
  193. }
  194. }
  195. height: contentItem.height + 2 * padding;
  196. onClosed: visible = false;
  197. onOpened: visible = true;
  198. padding: UM.Theme.getSize("monitor_shadow_radius").width;
  199. transformOrigin: Popup.Top;
  200. visible: false;
  201. width: 182 * screenScaleFactor;
  202. x: (button.width - width) + 26 * screenScaleFactor;
  203. y: button.height + 5 * screenScaleFactor; // Because shadow
  204. }
  205. MessageDialog {
  206. id: sendToTopConfirmationDialog;
  207. Component.onCompleted: visible = false;
  208. icon: StandardIcon.Warning;
  209. onYes: OutputDevice.sendJobToTop(printJob.key);
  210. standardButtons: StandardButton.Yes | StandardButton.No;
  211. text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to move %1 to the top of the queue?").arg(printJob.name) : "";
  212. title: catalog.i18nc("@window:title", "Move print job to top");
  213. }
  214. MessageDialog {
  215. id: deleteConfirmationDialog;
  216. Component.onCompleted: visible = false;
  217. icon: StandardIcon.Warning;
  218. onYes: OutputDevice.deleteJobFromQueue(printJob.key);
  219. standardButtons: StandardButton.Yes | StandardButton.No;
  220. text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to delete %1?").arg(printJob.name) : "";
  221. title: catalog.i18nc("@window:title", "Delete print job");
  222. }
  223. MessageDialog {
  224. id: abortConfirmationDialog;
  225. Component.onCompleted: visible = false;
  226. icon: StandardIcon.Warning;
  227. onYes: printJob.setState("abort");
  228. standardButtons: StandardButton.Yes | StandardButton.No;
  229. text: printJob && printJob.name ? catalog.i18nc("@label %1 is the name of a print job.", "Are you sure you want to abort %1?").arg(printJob.name) : "";
  230. title: catalog.i18nc("@window:title", "Abort print");
  231. }
  232. // Utils
  233. function switchPopupState() {
  234. popup.visible ? popup.close() : popup.open();
  235. }
  236. function isStarted(job) {
  237. if (!job) {
  238. return false;
  239. }
  240. return ["pre_print", "printing", "pausing", "paused", "resuming", "aborting"].indexOf(job.state) !== -1;
  241. }
  242. function isAssigned(job) {
  243. if (!job) {
  244. return false;
  245. }
  246. return job.assignedPrinter ? true : false;
  247. }
  248. function getMenuLength() {
  249. var visible = 0;
  250. for (var i = 0; i < popupOptions.children.length; i++) {
  251. if (popupOptions.children[i].visible) {
  252. visible++;
  253. }
  254. }
  255. return visible;
  256. }
  257. }