Cura.qml 29 KB

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