Cura.qml 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  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. ObjectSelector
  232. {
  233. id: objectSelector
  234. visible: CuraApplication.platformActivity
  235. anchors
  236. {
  237. bottom: jobSpecs.top
  238. left: toolbar.right
  239. leftMargin: UM.Theme.getSize("default_margin").width
  240. rightMargin: UM.Theme.getSize("default_margin").width
  241. bottomMargin: UM.Theme.getSize("narrow_margin").height
  242. }
  243. }
  244. JobSpecs
  245. {
  246. id: jobSpecs
  247. visible: CuraApplication.platformActivity
  248. anchors
  249. {
  250. left: toolbar.right
  251. bottom: viewOrientationControls.top
  252. leftMargin: UM.Theme.getSize("default_margin").width
  253. rightMargin: UM.Theme.getSize("default_margin").width
  254. bottomMargin: UM.Theme.getSize("thin_margin").width
  255. topMargin: UM.Theme.getSize("thin_margin").width
  256. }
  257. }
  258. ViewOrientationControls
  259. {
  260. id: viewOrientationControls
  261. anchors
  262. {
  263. left: toolbar.right
  264. bottom: parent.bottom
  265. margins: UM.Theme.getSize("default_margin").width
  266. }
  267. }
  268. Loader
  269. {
  270. // A stage can control this area. If nothing is set, it will therefore show the 3D view.
  271. id: main
  272. anchors
  273. {
  274. // Align to the top of the stageMenu since the stageMenu may not exist
  275. top: stageMenu.source ? stageMenu.verticalCenter : parent.top
  276. left: parent.left
  277. right: parent.right
  278. bottom: parent.bottom
  279. }
  280. source: UM.Controller.activeStage != null ? UM.Controller.activeStage.mainComponent : ""
  281. }
  282. Loader
  283. {
  284. // The stage menu is, as the name implies, a menu that is defined by the active stage.
  285. // Note that this menu does not need to be set at all! It's perfectly acceptable to have a stage
  286. // without this menu!
  287. id: stageMenu
  288. anchors
  289. {
  290. left: parent.left
  291. right: parent.right
  292. top: parent.top
  293. }
  294. height: UM.Theme.getSize("stage_menu").height
  295. source: UM.Controller.activeStage != null ? UM.Controller.activeStage.stageMenuComponent : ""
  296. // HACK: This is to ensure that the parent never gets set to null, as this wreaks havoc on the focus.
  297. function onParentDestroyed()
  298. {
  299. printSetupSelector.parent = stageMenu
  300. printSetupSelector.visible = false
  301. }
  302. property Item oldParent: null
  303. // The printSetupSelector is defined here so that the setting list doesn't need to get re-instantiated
  304. // Every time the stage is changed.
  305. property var printSetupSelector: Cura.PrintSetupSelector
  306. {
  307. width: UM.Theme.getSize("print_setup_widget").width
  308. height: UM.Theme.getSize("stage_menu").height
  309. headerCornerSide: RoundedRectangle.Direction.Right
  310. onParentChanged:
  311. {
  312. if(stageMenu.oldParent !=null)
  313. {
  314. stageMenu.oldParent.Component.destruction.disconnect(stageMenu.onParentDestroyed)
  315. }
  316. stageMenu.oldParent = parent
  317. visible = parent != stageMenu
  318. parent.Component.destruction.connect(stageMenu.onParentDestroyed)
  319. }
  320. }
  321. }
  322. UM.MessageStack
  323. {
  324. anchors
  325. {
  326. horizontalCenter: parent.horizontalCenter
  327. top: parent.verticalCenter
  328. bottom: parent.bottom
  329. bottomMargin: UM.Theme.getSize("default_margin").height
  330. }
  331. primaryButton: Component
  332. {
  333. Cura.PrimaryButton
  334. {
  335. text: model.name
  336. height: UM.Theme.getSize("message_action_button").height
  337. }
  338. }
  339. secondaryButton: Component
  340. {
  341. Cura.SecondaryButton
  342. {
  343. text: model.name
  344. height: UM.Theme.getSize("message_action_button").height
  345. }
  346. }
  347. }
  348. }
  349. PrintSetupTooltip
  350. {
  351. id: tooltip
  352. sourceWidth: UM.Theme.getSize("print_setup_widget").width
  353. }
  354. }
  355. UM.PreferencesDialog
  356. {
  357. id: preferences
  358. Component.onCompleted:
  359. {
  360. //; Remove & re-add the general page as we want to use our own instead of uranium standard.
  361. removePage(0);
  362. insertPage(0, catalog.i18nc("@title:tab","General"), Qt.resolvedUrl("Preferences/GeneralPage.qml"));
  363. removePage(1);
  364. insertPage(1, catalog.i18nc("@title:tab","Settings"), Qt.resolvedUrl("Preferences/SettingVisibilityPage.qml"));
  365. insertPage(2, catalog.i18nc("@title:tab", "Printers"), Qt.resolvedUrl("Preferences/MachinesPage.qml"));
  366. insertPage(3, catalog.i18nc("@title:tab", "Materials"), Qt.resolvedUrl("Preferences/Materials/MaterialsPage.qml"));
  367. insertPage(4, catalog.i18nc("@title:tab", "Profiles"), Qt.resolvedUrl("Preferences/ProfilesPage.qml"));
  368. //Force refresh
  369. setPage(0);
  370. }
  371. onVisibleChanged:
  372. {
  373. // When the dialog closes, switch to the General page.
  374. // This prevents us from having a heavy page like Setting Visiblity active in the background.
  375. setPage(0);
  376. }
  377. }
  378. Connections
  379. {
  380. target: Cura.Actions.preferences
  381. onTriggered: preferences.visible = true
  382. }
  383. Connections
  384. {
  385. target: CuraApplication
  386. onShowPreferencesWindow: preferences.visible = true
  387. }
  388. Connections
  389. {
  390. target: Cura.Actions.addProfile
  391. onTriggered:
  392. {
  393. preferences.show();
  394. preferences.setPage(4);
  395. // Create a new profile after a very short delay so the preference page has time to initiate
  396. createProfileTimer.start();
  397. }
  398. }
  399. Connections
  400. {
  401. target: Cura.Actions.configureMachines
  402. onTriggered:
  403. {
  404. preferences.visible = true;
  405. preferences.setPage(2);
  406. }
  407. }
  408. Connections
  409. {
  410. target: Cura.Actions.manageProfiles
  411. onTriggered:
  412. {
  413. preferences.visible = true;
  414. preferences.setPage(4);
  415. }
  416. }
  417. Connections
  418. {
  419. target: Cura.Actions.manageMaterials
  420. onTriggered:
  421. {
  422. preferences.visible = true;
  423. preferences.setPage(3)
  424. }
  425. }
  426. Connections
  427. {
  428. target: Cura.Actions.configureSettingVisibility
  429. onTriggered:
  430. {
  431. preferences.visible = true;
  432. preferences.setPage(1);
  433. if(source && source.key)
  434. {
  435. preferences.getCurrentItem().scrollToSection(source.key);
  436. }
  437. }
  438. }
  439. Timer
  440. {
  441. id: createProfileTimer
  442. repeat: false
  443. interval: 1
  444. onTriggered: preferences.getCurrentItem().createProfile()
  445. }
  446. // BlurSettings is a way to force the focus away from any of the setting items.
  447. // We need to do this in order to keep the bindings intact.
  448. Connections
  449. {
  450. target: Cura.MachineManager
  451. onBlurSettings:
  452. {
  453. contentItem.forceActiveFocus()
  454. }
  455. }
  456. ContextMenu
  457. {
  458. id: contextMenu
  459. }
  460. onPreClosing:
  461. {
  462. close.accepted = CuraApplication.getIsAllChecksPassed();
  463. if (!close.accepted)
  464. {
  465. CuraApplication.checkAndExitApplication();
  466. }
  467. }
  468. MessageDialog
  469. {
  470. id: exitConfirmationDialog
  471. title: catalog.i18nc("@title:window", "Closing Cura")
  472. text: catalog.i18nc("@label", "Are you sure you want to exit Cura?")
  473. icon: StandardIcon.Question
  474. modality: Qt.ApplicationModal
  475. standardButtons: StandardButton.Yes | StandardButton.No
  476. onYes: CuraApplication.callConfirmExitDialogCallback(true)
  477. onNo: CuraApplication.callConfirmExitDialogCallback(false)
  478. onRejected: CuraApplication.callConfirmExitDialogCallback(false)
  479. onVisibilityChanged:
  480. {
  481. if (!visible)
  482. {
  483. // reset the text to default because other modules may change the message text.
  484. text = catalog.i18nc("@label", "Are you sure you want to exit Cura?");
  485. }
  486. }
  487. }
  488. Connections
  489. {
  490. target: CuraApplication
  491. onShowConfirmExitDialog:
  492. {
  493. exitConfirmationDialog.text = message;
  494. exitConfirmationDialog.open();
  495. }
  496. }
  497. Connections
  498. {
  499. target: Cura.Actions.quit
  500. onTriggered: CuraApplication.checkAndExitApplication();
  501. }
  502. Connections
  503. {
  504. target: Cura.Actions.toggleFullScreen
  505. onTriggered: base.toggleFullscreen()
  506. }
  507. Connections
  508. {
  509. target: Cura.Actions.exitFullScreen
  510. onTriggered: base.exitFullscreen()
  511. }
  512. FileDialog
  513. {
  514. id: openDialog;
  515. //: File open dialog title
  516. title: catalog.i18nc("@title:window","Open file(s)")
  517. modality: Qt.WindowModal
  518. selectMultiple: true
  519. nameFilters: UM.MeshFileHandler.supportedReadFileTypes;
  520. folder: CuraApplication.getDefaultPath("dialog_load_path")
  521. onAccepted:
  522. {
  523. // Because several implementations of the file dialog only update the folder
  524. // when it is explicitly set.
  525. var f = folder;
  526. folder = f;
  527. CuraApplication.setDefaultPath("dialog_load_path", folder);
  528. handleOpenFileUrls(fileUrls);
  529. }
  530. // Yeah... I know... it is a mess to put all those things here.
  531. // There are lots of user interactions in this part of the logic, such as showing a warning dialog here and there,
  532. // etc. This means it will come back and forth from time to time between QML and Python. So, separating the logic
  533. // and view here may require more effort but make things more difficult to understand.
  534. function handleOpenFileUrls(fileUrlList)
  535. {
  536. // look for valid project files
  537. var projectFileUrlList = [];
  538. var hasGcode = false;
  539. var nonGcodeFileList = [];
  540. for (var i in fileUrlList)
  541. {
  542. var endsWithG = /\.g$/;
  543. var endsWithGcode = /\.gcode$/;
  544. if (endsWithG.test(fileUrlList[i]) || endsWithGcode.test(fileUrlList[i]))
  545. {
  546. continue;
  547. }
  548. else if (CuraApplication.checkIsValidProjectFile(fileUrlList[i]))
  549. {
  550. projectFileUrlList.push(fileUrlList[i]);
  551. }
  552. nonGcodeFileList.push(fileUrlList[i]);
  553. }
  554. hasGcode = nonGcodeFileList.length < fileUrlList.length;
  555. // show a warning if selected multiple files together with Gcode
  556. var hasProjectFile = projectFileUrlList.length > 0;
  557. var selectedMultipleFiles = fileUrlList.length > 1;
  558. if (selectedMultipleFiles && hasGcode)
  559. {
  560. infoMultipleFilesWithGcodeDialog.selectedMultipleFiles = selectedMultipleFiles;
  561. infoMultipleFilesWithGcodeDialog.hasProjectFile = hasProjectFile;
  562. infoMultipleFilesWithGcodeDialog.fileUrls = nonGcodeFileList.slice();
  563. infoMultipleFilesWithGcodeDialog.projectFileUrlList = projectFileUrlList.slice();
  564. infoMultipleFilesWithGcodeDialog.open();
  565. }
  566. else
  567. {
  568. handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrlList, projectFileUrlList);
  569. }
  570. }
  571. function handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrlList, projectFileUrlList)
  572. {
  573. // we only allow opening one project file
  574. if (selectedMultipleFiles && hasProjectFile)
  575. {
  576. openFilesIncludingProjectsDialog.fileUrls = fileUrlList.slice();
  577. openFilesIncludingProjectsDialog.show();
  578. return;
  579. }
  580. if (hasProjectFile)
  581. {
  582. var projectFile = projectFileUrlList[0];
  583. // check preference
  584. var choice = UM.Preferences.getValue("cura/choice_on_open_project");
  585. if (choice == "open_as_project")
  586. {
  587. openFilesIncludingProjectsDialog.loadProjectFile(projectFile);
  588. }
  589. else if (choice == "open_as_model")
  590. {
  591. openFilesIncludingProjectsDialog.loadModelFiles([projectFile].slice());
  592. }
  593. else // always ask
  594. {
  595. // ask whether to open as project or as models
  596. askOpenAsProjectOrModelsDialog.fileUrl = projectFile;
  597. askOpenAsProjectOrModelsDialog.show();
  598. }
  599. }
  600. else
  601. {
  602. openFilesIncludingProjectsDialog.loadModelFiles(fileUrlList.slice());
  603. }
  604. }
  605. }
  606. MessageDialog
  607. {
  608. id: packageInstallDialog
  609. title: catalog.i18nc("@window:title", "Install Package");
  610. standardButtons: StandardButton.Ok
  611. modality: Qt.ApplicationModal
  612. }
  613. MessageDialog
  614. {
  615. id: infoMultipleFilesWithGcodeDialog
  616. title: catalog.i18nc("@title:window", "Open File(s)")
  617. icon: StandardIcon.Information
  618. standardButtons: StandardButton.Ok
  619. 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.")
  620. property var selectedMultipleFiles
  621. property var hasProjectFile
  622. property var fileUrls
  623. property var projectFileUrlList
  624. onAccepted:
  625. {
  626. openDialog.handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrls, projectFileUrlList);
  627. }
  628. }
  629. Connections
  630. {
  631. target: Cura.Actions.open
  632. onTriggered: openDialog.open()
  633. }
  634. OpenFilesIncludingProjectsDialog
  635. {
  636. id: openFilesIncludingProjectsDialog
  637. }
  638. AskOpenAsProjectOrModelsDialog
  639. {
  640. id: askOpenAsProjectOrModelsDialog
  641. }
  642. Connections
  643. {
  644. target: CuraApplication
  645. onOpenProjectFile:
  646. {
  647. askOpenAsProjectOrModelsDialog.fileUrl = project_file;
  648. askOpenAsProjectOrModelsDialog.show();
  649. }
  650. }
  651. Connections
  652. {
  653. target: Cura.Actions.showProfileFolder
  654. onTriggered:
  655. {
  656. var path = UM.Resources.getPath(UM.Resources.Preferences, "");
  657. if(Qt.platform.os == "windows")
  658. {
  659. path = path.replace(/\\/g,"/");
  660. }
  661. Qt.openUrlExternally(path);
  662. if(Qt.platform.os == "linux")
  663. {
  664. Qt.openUrlExternally(UM.Resources.getPath(UM.Resources.Resources, ""));
  665. }
  666. }
  667. }
  668. MessageDialog
  669. {
  670. id: messageDialog
  671. modality: Qt.ApplicationModal
  672. onAccepted: CuraApplication.messageBoxClosed(clickedButton)
  673. onApply: CuraApplication.messageBoxClosed(clickedButton)
  674. onDiscard: CuraApplication.messageBoxClosed(clickedButton)
  675. onHelp: CuraApplication.messageBoxClosed(clickedButton)
  676. onNo: CuraApplication.messageBoxClosed(clickedButton)
  677. onRejected: CuraApplication.messageBoxClosed(clickedButton)
  678. onReset: CuraApplication.messageBoxClosed(clickedButton)
  679. onYes: CuraApplication.messageBoxClosed(clickedButton)
  680. }
  681. Connections
  682. {
  683. target: CuraApplication
  684. onShowMessageBox:
  685. {
  686. messageDialog.title = title
  687. messageDialog.text = text
  688. messageDialog.informativeText = informativeText
  689. messageDialog.detailedText = detailedText
  690. messageDialog.standardButtons = buttons
  691. messageDialog.icon = icon
  692. messageDialog.visible = true
  693. }
  694. }
  695. DiscardOrKeepProfileChangesDialog
  696. {
  697. id: discardOrKeepProfileChangesDialog
  698. }
  699. Connections
  700. {
  701. target: CuraApplication
  702. onShowDiscardOrKeepProfileChanges:
  703. {
  704. discardOrKeepProfileChangesDialog.show()
  705. }
  706. }
  707. Cura.WizardDialog
  708. {
  709. id: addMachineDialog
  710. title: catalog.i18nc("@title:window", "Add Printer")
  711. model: CuraApplication.getAddPrinterPagesModel()
  712. progressBarVisible: false
  713. }
  714. Cura.WizardDialog
  715. {
  716. id: whatsNewDialog
  717. title: catalog.i18nc("@title:window", "What's New")
  718. model: CuraApplication.getWhatsNewPagesModel()
  719. progressBarVisible: false
  720. }
  721. Connections
  722. {
  723. target: Cura.Actions.whatsNew
  724. onTriggered: whatsNewDialog.show()
  725. }
  726. Connections
  727. {
  728. target: Cura.Actions.addMachine
  729. onTriggered:
  730. {
  731. // Make sure to show from the first page when the dialog shows up.
  732. addMachineDialog.resetModelState()
  733. addMachineDialog.show()
  734. }
  735. }
  736. AboutDialog
  737. {
  738. id: aboutDialog
  739. }
  740. Connections
  741. {
  742. target: Cura.Actions.about
  743. onTriggered: aboutDialog.visible = true;
  744. }
  745. Timer
  746. {
  747. id: startupTimer
  748. interval: 100
  749. repeat: false
  750. running: true
  751. onTriggered:
  752. {
  753. if (!base.visible)
  754. {
  755. base.visible = true
  756. }
  757. }
  758. }
  759. /**
  760. * Function to check whether a QML object has a certain type.
  761. * Taken from StackOverflow: https://stackoverflow.com/a/28384228 and
  762. * adapted to our code style.
  763. * Licensed under CC BY-SA 3.0.
  764. * \param obj The QtObject to get the name of.
  765. * \param class_name (str) The name of the class to check against. Has to be
  766. * the QtObject class name, not the QML entity name.
  767. */
  768. function qmlTypeOf(obj, class_name)
  769. {
  770. //className plus "(" is the class instance without modification.
  771. //className plus "_QML" is the class instance with user-defined properties.
  772. var str = obj.toString();
  773. return str.indexOf(class_name + "(") == 0 || str.indexOf(class_name + "_QML") == 0;
  774. }
  775. }