Cura.qml 26 KB

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