Cura.qml 26 KB

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