Cura.qml 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. // Copyright (c) 2019 Ultimaker B.V.
  2. // Cura is released under the terms of the LGPLv3 or higher.
  3. import QtQuick 2.7
  4. import QtQuick.Controls 1.4
  5. import QtQuick.Controls.Styles 1.4
  6. import QtQuick.Layouts 1.1
  7. import QtQuick.Dialogs 1.2
  8. import QtGraphicalEffects 1.0
  9. import UM 1.3 as UM
  10. import Cura 1.1 as Cura
  11. import "Dialogs"
  12. import "Menus"
  13. import "MainWindow"
  14. import "WelcomePages"
  15. UM.MainWindow
  16. {
  17. id: base
  18. // Cura application window title
  19. title: catalog.i18nc("@title:window", "Ultimaker Cura")
  20. backgroundColor: UM.Theme.getColor("viewport_background")
  21. UM.I18nCatalog
  22. {
  23. id: catalog
  24. name: "cura"
  25. }
  26. function showTooltip(item, position, text)
  27. {
  28. tooltip.text = text;
  29. position = item.mapToItem(backgroundItem, position.x - UM.Theme.getSize("default_arrow").width, position.y);
  30. tooltip.show(position);
  31. }
  32. function hideTooltip()
  33. {
  34. tooltip.hide();
  35. }
  36. Rectangle
  37. {
  38. id: greyOutBackground
  39. anchors.fill: parent
  40. visible: welcomeDialog.visible
  41. color: UM.Theme.getColor("window_disabled_background")
  42. opacity: 0.7
  43. z: stageMenu.z + 1
  44. MouseArea
  45. {
  46. // Prevent all mouse events from passing through.
  47. enabled: parent.visible
  48. anchors.fill: parent
  49. hoverEnabled: true
  50. acceptedButtons: Qt.AllButtons
  51. }
  52. }
  53. WelcomeDialog
  54. {
  55. id: welcomeDialog
  56. visible: true // True, so if somehow no preferences are found/loaded, it's shown anyway.
  57. z: greyOutBackground.z + 1
  58. }
  59. Component.onCompleted:
  60. {
  61. CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size"))
  62. // Workaround silly issues with QML Action's shortcut property.
  63. //
  64. // Currently, there is no way to define shortcuts as "Application Shortcut".
  65. // This means that all Actions are "Window Shortcuts". The code for this
  66. // implements a rather naive check that just checks if any of the action's parents
  67. // are a window. Since the "Actions" object is a singleton it has no parent by
  68. // default. If we set its parent to something contained in this window, the
  69. // shortcut will activate properly because one of its parents is a window.
  70. //
  71. // This has been fixed for QtQuick Controls 2 since the Shortcut item has a context property.
  72. Cura.Actions.parent = backgroundItem
  73. CuraApplication.purgeWindows()
  74. if (CuraApplication.needToShowUserAgreement || Cura.MachineManager.activeMachine == null)
  75. {
  76. welcomeDialog.visible = true
  77. }
  78. else
  79. {
  80. welcomeDialog.visible = false
  81. }
  82. // TODO: While the new onboarding process contains the user-agreement,
  83. // it should probably not entirely rely on 'needToShowUserAgreement' for show/hide.
  84. }
  85. Item
  86. {
  87. id: backgroundItem
  88. anchors.fill: parent
  89. signal hasMesh(string name) //this signal sends the filebase name so it can be used for the JobSpecs.qml
  90. function getMeshName(path)
  91. {
  92. //takes the path the complete path of the meshname and returns only the filebase
  93. var fileName = path.slice(path.lastIndexOf("/") + 1)
  94. var fileBase = fileName.slice(0, fileName.indexOf("."))
  95. return fileBase
  96. }
  97. //DeleteSelection on the keypress backspace event
  98. Keys.onPressed:
  99. {
  100. if (event.key == Qt.Key_Backspace)
  101. {
  102. Cura.Actions.deleteSelection.trigger()
  103. }
  104. }
  105. ApplicationMenu
  106. {
  107. id: applicationMenu
  108. window: base
  109. }
  110. Item
  111. {
  112. id: headerBackground
  113. anchors
  114. {
  115. top: applicationMenu.bottom
  116. left: parent.left
  117. right: parent.right
  118. }
  119. height: stageMenu.source != "" ? Math.round(mainWindowHeader.height + stageMenu.height / 2) : mainWindowHeader.height
  120. LinearGradient
  121. {
  122. anchors.fill: parent
  123. start: Qt.point(0, 0)
  124. end: Qt.point(parent.width, 0)
  125. gradient: Gradient
  126. {
  127. GradientStop
  128. {
  129. position: 0.0
  130. color: UM.Theme.getColor("main_window_header_background")
  131. }
  132. GradientStop
  133. {
  134. position: 0.5
  135. color: UM.Theme.getColor("main_window_header_background_gradient")
  136. }
  137. GradientStop
  138. {
  139. position: 1.0
  140. color: UM.Theme.getColor("main_window_header_background")
  141. }
  142. }
  143. }
  144. // This is a placehoder for adding a pattern in the header
  145. Image
  146. {
  147. id: backgroundPattern
  148. anchors.fill: parent
  149. fillMode: Image.Tile
  150. source: UM.Theme.getImage("header_pattern")
  151. horizontalAlignment: Image.AlignLeft
  152. verticalAlignment: Image.AlignTop
  153. }
  154. }
  155. MainWindowHeader
  156. {
  157. id: mainWindowHeader
  158. anchors
  159. {
  160. left: parent.left
  161. right: parent.right
  162. top: applicationMenu.bottom
  163. }
  164. }
  165. Item
  166. {
  167. id: contentItem
  168. anchors
  169. {
  170. top: mainWindowHeader.bottom
  171. bottom: parent.bottom
  172. left: parent.left
  173. right: parent.right
  174. }
  175. Keys.forwardTo: applicationMenu
  176. DropArea
  177. {
  178. // The drop area is here to handle files being dropped onto Cura.
  179. anchors.fill: parent
  180. onDropped:
  181. {
  182. if (drop.urls.length > 0)
  183. {
  184. var nonPackages = [];
  185. for (var i = 0; i < drop.urls.length; i++)
  186. {
  187. var filename = drop.urls[i];
  188. if (filename.endsWith(".curapackage"))
  189. {
  190. // Try to install plugin & close.
  191. CuraApplication.getPackageManager().installPackageViaDragAndDrop(filename);
  192. packageInstallDialog.text = catalog.i18nc("@label", "This package will be installed after restarting.");
  193. packageInstallDialog.icon = StandardIcon.Information;
  194. packageInstallDialog.open();
  195. }
  196. else
  197. {
  198. nonPackages.push(filename);
  199. }
  200. }
  201. openDialog.handleOpenFileUrls(nonPackages);
  202. }
  203. }
  204. }
  205. Toolbar
  206. {
  207. // The toolbar is the left bar that is populated by all the tools (which are dynamicly populated by
  208. // plugins)
  209. id: toolbar
  210. property int mouseX: base.mouseX
  211. property int mouseY: base.mouseY
  212. anchors
  213. {
  214. verticalCenter: parent.verticalCenter
  215. left: parent.left
  216. }
  217. visible: CuraApplication.platformActivity && !PrintInformation.preSliced
  218. }
  219. ObjectsList
  220. {
  221. id: objectsList
  222. visible: UM.Preferences.getValue("cura/use_multi_build_plate")
  223. anchors
  224. {
  225. bottom: viewOrientationControls.top
  226. left: toolbar.right
  227. margins: UM.Theme.getSize("default_margin").width
  228. }
  229. }
  230. JobSpecs
  231. {
  232. id: jobSpecs
  233. visible: CuraApplication.platformActivity
  234. anchors
  235. {
  236. left: parent.left
  237. bottom: viewOrientationControls.top
  238. margins: UM.Theme.getSize("default_margin").width
  239. bottomMargin: UM.Theme.getSize("thin_margin").width
  240. }
  241. }
  242. ViewOrientationControls
  243. {
  244. id: viewOrientationControls
  245. anchors
  246. {
  247. left: parent.left
  248. bottom: parent.bottom
  249. margins: UM.Theme.getSize("default_margin").width
  250. }
  251. }
  252. Loader
  253. {
  254. // A stage can control this area. If nothing is set, it will therefore show the 3D view.
  255. id: main
  256. anchors
  257. {
  258. // Align to the top of the stageMenu since the stageMenu may not exist
  259. top: stageMenu.source ? stageMenu.verticalCenter : parent.top
  260. left: parent.left
  261. right: parent.right
  262. bottom: parent.bottom
  263. }
  264. source: UM.Controller.activeStage != null ? UM.Controller.activeStage.mainComponent : ""
  265. }
  266. Loader
  267. {
  268. // The stage menu is, as the name implies, a menu that is defined by the active stage.
  269. // Note that this menu does not need to be set at all! It's perfectly acceptable to have a stage
  270. // without this menu!
  271. id: stageMenu
  272. anchors
  273. {
  274. left: parent.left
  275. right: parent.right
  276. top: parent.top
  277. }
  278. height: UM.Theme.getSize("stage_menu").height
  279. source: UM.Controller.activeStage != null ? UM.Controller.activeStage.stageMenuComponent : ""
  280. // HACK: This is to ensure that the parent never gets set to null, as this wreaks havoc on the focus.
  281. function onParentDestroyed()
  282. {
  283. printSetupSelector.parent = stageMenu
  284. printSetupSelector.visible = false
  285. }
  286. property Item oldParent: null
  287. // The printSetupSelector is defined here so that the setting list doesn't need to get re-instantiated
  288. // Every time the stage is changed.
  289. property var printSetupSelector: Cura.PrintSetupSelector
  290. {
  291. width: UM.Theme.getSize("print_setup_widget").width
  292. height: UM.Theme.getSize("stage_menu").height
  293. headerCornerSide: RoundedRectangle.Direction.Right
  294. onParentChanged:
  295. {
  296. if(stageMenu.oldParent !=null)
  297. {
  298. stageMenu.oldParent.Component.destruction.disconnect(stageMenu.onParentDestroyed)
  299. }
  300. stageMenu.oldParent = parent
  301. visible = parent != stageMenu
  302. parent.Component.destruction.connect(stageMenu.onParentDestroyed)
  303. }
  304. }
  305. }
  306. UM.MessageStack
  307. {
  308. anchors
  309. {
  310. horizontalCenter: parent.horizontalCenter
  311. top: parent.verticalCenter
  312. bottom: parent.bottom
  313. bottomMargin: UM.Theme.getSize("default_margin").height
  314. }
  315. primaryButton: Component
  316. {
  317. Cura.PrimaryButton
  318. {
  319. text: model.name
  320. height: UM.Theme.getSize("message_action_button").height
  321. }
  322. }
  323. secondaryButton: Component
  324. {
  325. Cura.SecondaryButton
  326. {
  327. text: model.name
  328. height: UM.Theme.getSize("message_action_button").height
  329. }
  330. }
  331. }
  332. }
  333. PrintSetupTooltip
  334. {
  335. id: tooltip
  336. }
  337. }
  338. UM.PreferencesDialog
  339. {
  340. id: preferences
  341. Component.onCompleted:
  342. {
  343. //; Remove & re-add the general page as we want to use our own instead of uranium standard.
  344. removePage(0);
  345. insertPage(0, catalog.i18nc("@title:tab","General"), Qt.resolvedUrl("Preferences/GeneralPage.qml"));
  346. removePage(1);
  347. insertPage(1, catalog.i18nc("@title:tab","Settings"), Qt.resolvedUrl("Preferences/SettingVisibilityPage.qml"));
  348. insertPage(2, catalog.i18nc("@title:tab", "Printers"), Qt.resolvedUrl("Preferences/MachinesPage.qml"));
  349. insertPage(3, catalog.i18nc("@title:tab", "Materials"), Qt.resolvedUrl("Preferences/Materials/MaterialsPage.qml"));
  350. insertPage(4, catalog.i18nc("@title:tab", "Profiles"), Qt.resolvedUrl("Preferences/ProfilesPage.qml"));
  351. //Force refresh
  352. setPage(0);
  353. }
  354. onVisibleChanged:
  355. {
  356. // When the dialog closes, switch to the General page.
  357. // This prevents us from having a heavy page like Setting Visiblity active in the background.
  358. setPage(0);
  359. }
  360. }
  361. Connections
  362. {
  363. target: Cura.Actions.preferences
  364. onTriggered: preferences.visible = true
  365. }
  366. Connections
  367. {
  368. target: CuraApplication
  369. onShowPreferencesWindow: preferences.visible = true
  370. }
  371. Connections
  372. {
  373. target: Cura.Actions.addProfile
  374. onTriggered:
  375. {
  376. preferences.show();
  377. preferences.setPage(4);
  378. // Create a new profile after a very short delay so the preference page has time to initiate
  379. createProfileTimer.start();
  380. }
  381. }
  382. Connections
  383. {
  384. target: Cura.Actions.configureMachines
  385. onTriggered:
  386. {
  387. preferences.visible = true;
  388. preferences.setPage(2);
  389. }
  390. }
  391. Connections
  392. {
  393. target: Cura.Actions.manageProfiles
  394. onTriggered:
  395. {
  396. preferences.visible = true;
  397. preferences.setPage(4);
  398. }
  399. }
  400. Connections
  401. {
  402. target: Cura.Actions.manageMaterials
  403. onTriggered:
  404. {
  405. preferences.visible = true;
  406. preferences.setPage(3)
  407. }
  408. }
  409. Connections
  410. {
  411. target: Cura.Actions.configureSettingVisibility
  412. onTriggered:
  413. {
  414. preferences.visible = true;
  415. preferences.setPage(1);
  416. if(source && source.key)
  417. {
  418. preferences.getCurrentItem().scrollToSection(source.key);
  419. }
  420. }
  421. }
  422. Timer
  423. {
  424. id: createProfileTimer
  425. repeat: false
  426. interval: 1
  427. onTriggered: preferences.getCurrentItem().createProfile()
  428. }
  429. // BlurSettings is a way to force the focus away from any of the setting items.
  430. // We need to do this in order to keep the bindings intact.
  431. Connections
  432. {
  433. target: Cura.MachineManager
  434. onBlurSettings:
  435. {
  436. contentItem.forceActiveFocus()
  437. }
  438. }
  439. ContextMenu
  440. {
  441. id: contextMenu
  442. }
  443. onPreClosing:
  444. {
  445. close.accepted = CuraApplication.getIsAllChecksPassed();
  446. if (!close.accepted)
  447. {
  448. CuraApplication.checkAndExitApplication();
  449. }
  450. }
  451. MessageDialog
  452. {
  453. id: exitConfirmationDialog
  454. title: catalog.i18nc("@title:window", "Closing Cura")
  455. text: catalog.i18nc("@label", "Are you sure you want to exit Cura?")
  456. icon: StandardIcon.Question
  457. modality: Qt.ApplicationModal
  458. standardButtons: StandardButton.Yes | StandardButton.No
  459. onYes: CuraApplication.callConfirmExitDialogCallback(true)
  460. onNo: CuraApplication.callConfirmExitDialogCallback(false)
  461. onRejected: CuraApplication.callConfirmExitDialogCallback(false)
  462. onVisibilityChanged:
  463. {
  464. if (!visible)
  465. {
  466. // reset the text to default because other modules may change the message text.
  467. text = catalog.i18nc("@label", "Are you sure you want to exit Cura?");
  468. }
  469. }
  470. }
  471. Connections
  472. {
  473. target: CuraApplication
  474. onShowConfirmExitDialog:
  475. {
  476. exitConfirmationDialog.text = message;
  477. exitConfirmationDialog.open();
  478. }
  479. }
  480. Connections
  481. {
  482. target: Cura.Actions.quit
  483. onTriggered: CuraApplication.checkAndExitApplication();
  484. }
  485. Connections
  486. {
  487. target: Cura.Actions.toggleFullScreen
  488. onTriggered: base.toggleFullscreen();
  489. }
  490. FileDialog
  491. {
  492. id: openDialog;
  493. //: File open dialog title
  494. title: catalog.i18nc("@title:window","Open file(s)")
  495. modality: UM.Application.platform == "linux" ? Qt.NonModal : Qt.WindowModal;
  496. selectMultiple: true
  497. nameFilters: UM.MeshFileHandler.supportedReadFileTypes;
  498. folder: CuraApplication.getDefaultPath("dialog_load_path")
  499. onAccepted:
  500. {
  501. // Because several implementations of the file dialog only update the folder
  502. // when it is explicitly set.
  503. var f = folder;
  504. folder = f;
  505. CuraApplication.setDefaultPath("dialog_load_path", folder);
  506. handleOpenFileUrls(fileUrls);
  507. }
  508. // Yeah... I know... it is a mess to put all those things here.
  509. // There are lots of user interactions in this part of the logic, such as showing a warning dialog here and there,
  510. // etc. This means it will come back and forth from time to time between QML and Python. So, separating the logic
  511. // and view here may require more effort but make things more difficult to understand.
  512. function handleOpenFileUrls(fileUrlList)
  513. {
  514. // look for valid project files
  515. var projectFileUrlList = [];
  516. var hasGcode = false;
  517. var nonGcodeFileList = [];
  518. for (var i in fileUrlList)
  519. {
  520. var endsWithG = /\.g$/;
  521. var endsWithGcode = /\.gcode$/;
  522. if (endsWithG.test(fileUrlList[i]) || endsWithGcode.test(fileUrlList[i]))
  523. {
  524. continue;
  525. }
  526. else if (CuraApplication.checkIsValidProjectFile(fileUrlList[i]))
  527. {
  528. projectFileUrlList.push(fileUrlList[i]);
  529. }
  530. nonGcodeFileList.push(fileUrlList[i]);
  531. }
  532. hasGcode = nonGcodeFileList.length < fileUrlList.length;
  533. // show a warning if selected multiple files together with Gcode
  534. var hasProjectFile = projectFileUrlList.length > 0;
  535. var selectedMultipleFiles = fileUrlList.length > 1;
  536. if (selectedMultipleFiles && hasGcode)
  537. {
  538. infoMultipleFilesWithGcodeDialog.selectedMultipleFiles = selectedMultipleFiles;
  539. infoMultipleFilesWithGcodeDialog.hasProjectFile = hasProjectFile;
  540. infoMultipleFilesWithGcodeDialog.fileUrls = nonGcodeFileList.slice();
  541. infoMultipleFilesWithGcodeDialog.projectFileUrlList = projectFileUrlList.slice();
  542. infoMultipleFilesWithGcodeDialog.open();
  543. }
  544. else
  545. {
  546. handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrlList, projectFileUrlList);
  547. }
  548. }
  549. function handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrlList, projectFileUrlList)
  550. {
  551. // we only allow opening one project file
  552. if (selectedMultipleFiles && hasProjectFile)
  553. {
  554. openFilesIncludingProjectsDialog.fileUrls = fileUrlList.slice();
  555. openFilesIncludingProjectsDialog.show();
  556. return;
  557. }
  558. if (hasProjectFile)
  559. {
  560. var projectFile = projectFileUrlList[0];
  561. // check preference
  562. var choice = UM.Preferences.getValue("cura/choice_on_open_project");
  563. if (choice == "open_as_project")
  564. {
  565. openFilesIncludingProjectsDialog.loadProjectFile(projectFile);
  566. }
  567. else if (choice == "open_as_model")
  568. {
  569. openFilesIncludingProjectsDialog.loadModelFiles([projectFile].slice());
  570. }
  571. else // always ask
  572. {
  573. // ask whether to open as project or as models
  574. askOpenAsProjectOrModelsDialog.fileUrl = projectFile;
  575. askOpenAsProjectOrModelsDialog.show();
  576. }
  577. }
  578. else
  579. {
  580. openFilesIncludingProjectsDialog.loadModelFiles(fileUrlList.slice());
  581. }
  582. }
  583. }
  584. MessageDialog
  585. {
  586. id: packageInstallDialog
  587. title: catalog.i18nc("@window:title", "Install Package");
  588. standardButtons: StandardButton.Ok
  589. modality: Qt.ApplicationModal
  590. }
  591. MessageDialog
  592. {
  593. id: infoMultipleFilesWithGcodeDialog
  594. title: catalog.i18nc("@title:window", "Open File(s)")
  595. icon: StandardIcon.Information
  596. standardButtons: StandardButton.Ok
  597. text: catalog.i18nc("@text:window", "We have found one or more G-Code files within the files you have selected. You can only open one G-Code file at a time. If you want to open a G-Code file, please just select only one.")
  598. property var selectedMultipleFiles
  599. property var hasProjectFile
  600. property var fileUrls
  601. property var projectFileUrlList
  602. onAccepted:
  603. {
  604. openDialog.handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrls, projectFileUrlList);
  605. }
  606. }
  607. Connections
  608. {
  609. target: Cura.Actions.open
  610. onTriggered: openDialog.open()
  611. }
  612. OpenFilesIncludingProjectsDialog
  613. {
  614. id: openFilesIncludingProjectsDialog
  615. }
  616. AskOpenAsProjectOrModelsDialog
  617. {
  618. id: askOpenAsProjectOrModelsDialog
  619. }
  620. Connections
  621. {
  622. target: CuraApplication
  623. onOpenProjectFile:
  624. {
  625. askOpenAsProjectOrModelsDialog.fileUrl = project_file;
  626. askOpenAsProjectOrModelsDialog.show();
  627. }
  628. }
  629. Connections
  630. {
  631. target: Cura.Actions.showProfileFolder
  632. onTriggered:
  633. {
  634. var path = UM.Resources.getPath(UM.Resources.Preferences, "");
  635. if(Qt.platform.os == "windows")
  636. {
  637. path = path.replace(/\\/g,"/");
  638. }
  639. Qt.openUrlExternally(path);
  640. if(Qt.platform.os == "linux")
  641. {
  642. Qt.openUrlExternally(UM.Resources.getPath(UM.Resources.Resources, ""));
  643. }
  644. }
  645. }
  646. AddMachineDialog
  647. {
  648. id: addMachineDialog
  649. onMachineAdded:
  650. {
  651. machineActionsWizard.firstRun = addMachineDialog.firstRun
  652. machineActionsWizard.start(id)
  653. }
  654. }
  655. // Dialog to handle first run machine actions
  656. UM.Wizard
  657. {
  658. id: machineActionsWizard;
  659. title: catalog.i18nc("@title:window", "Add Printer")
  660. property var machine;
  661. function start(id)
  662. {
  663. var actions = Cura.MachineActionManager.getFirstStartActions(id)
  664. resetPages() // Remove previous pages
  665. for (var i = 0; i < actions.length; i++)
  666. {
  667. actions[i].displayItem.reset()
  668. machineActionsWizard.appendPage(actions[i].displayItem, catalog.i18nc("@title", actions[i].label));
  669. }
  670. //Only start if there are actions to perform.
  671. if (actions.length > 0)
  672. {
  673. machineActionsWizard.currentPage = 0;
  674. show()
  675. }
  676. }
  677. }
  678. MessageDialog
  679. {
  680. id: messageDialog
  681. modality: Qt.ApplicationModal
  682. onAccepted: CuraApplication.messageBoxClosed(clickedButton)
  683. onApply: CuraApplication.messageBoxClosed(clickedButton)
  684. onDiscard: CuraApplication.messageBoxClosed(clickedButton)
  685. onHelp: CuraApplication.messageBoxClosed(clickedButton)
  686. onNo: CuraApplication.messageBoxClosed(clickedButton)
  687. onRejected: CuraApplication.messageBoxClosed(clickedButton)
  688. onReset: CuraApplication.messageBoxClosed(clickedButton)
  689. onYes: CuraApplication.messageBoxClosed(clickedButton)
  690. }
  691. Connections
  692. {
  693. target: CuraApplication
  694. onShowMessageBox:
  695. {
  696. messageDialog.title = title
  697. messageDialog.text = text
  698. messageDialog.informativeText = informativeText
  699. messageDialog.detailedText = detailedText
  700. messageDialog.standardButtons = buttons
  701. messageDialog.icon = icon
  702. messageDialog.visible = true
  703. }
  704. }
  705. DiscardOrKeepProfileChangesDialog
  706. {
  707. id: discardOrKeepProfileChangesDialog
  708. }
  709. Connections
  710. {
  711. target: CuraApplication
  712. onShowDiscardOrKeepProfileChanges:
  713. {
  714. discardOrKeepProfileChangesDialog.show()
  715. }
  716. }
  717. Connections
  718. {
  719. target: Cura.Actions.addMachine
  720. onTriggered: addMachineDialog.visible = true;
  721. }
  722. AboutDialog
  723. {
  724. id: aboutDialog
  725. }
  726. Connections
  727. {
  728. target: Cura.Actions.about
  729. onTriggered: aboutDialog.visible = true;
  730. }
  731. Connections
  732. {
  733. target: CuraApplication
  734. onRequestAddPrinter:
  735. {
  736. addMachineDialog.visible = true
  737. addMachineDialog.firstRun = false
  738. }
  739. }
  740. Timer
  741. {
  742. id: startupTimer;
  743. interval: 100;
  744. repeat: false;
  745. running: true;
  746. onTriggered:
  747. {
  748. if(!base.visible)
  749. {
  750. base.visible = true;
  751. }
  752. }
  753. }
  754. /**
  755. * Function to check whether a QML object has a certain type.
  756. * Taken from StackOverflow: https://stackoverflow.com/a/28384228 and
  757. * adapted to our code style.
  758. * Licensed under CC BY-SA 3.0.
  759. * \param obj The QtObject to get the name of.
  760. * \param class_name (str) The name of the class to check against. Has to be
  761. * the QtObject class name, not the QML entity name.
  762. */
  763. function qmlTypeOf(obj, class_name)
  764. {
  765. //className plus "(" is the class instance without modification.
  766. //className plus "_QML" is the class instance with user-defined properties.
  767. var str = obj.toString();
  768. return str.indexOf(class_name + "(") == 0 || str.indexOf(class_name + "_QML") == 0;
  769. }
  770. }