Cura.qml 28 KB

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