Cura.qml 27 KB

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