Просмотр исходного кода

Show machine actions page optionally

Lipu Fei 6 лет назад
Родитель
Сommit
6dbae6f088

+ 46 - 2
cura/Machines/Models/FirstStartMachineActionsModel.py

@@ -1,9 +1,9 @@
 # Copyright (c) 2019 Ultimaker B.V.
 # Cura is released under the terms of the LGPLv3 or higher.
 
-from typing import Optional
+from typing import Optional, Dict, Any
 
-from PyQt5.QtCore import QObject, Qt
+from PyQt5.QtCore import QObject, Qt, pyqtProperty, pyqtSignal, pyqtSlot
 
 from UM.Qt.ListModel import ListModel
 
@@ -27,6 +27,8 @@ class FirstStartMachineActionsModel(ListModel):
         self.addRoleName(self.ContentRole, "content")
         self.addRoleName(self.ActionRole, "action")
 
+        self._current_action_index = 0
+
         from cura.CuraApplication import CuraApplication
         self._application = CuraApplication.getInstance()
 
@@ -36,6 +38,47 @@ class FirstStartMachineActionsModel(ListModel):
         self._application.getMachineManager().globalContainerChanged.connect(self._update)
         self._update()
 
+    currentActionIndexChanged = pyqtSignal()
+    allFinished = pyqtSignal()  # Emitted when all actions have been finished.
+
+    @pyqtProperty(int, notify = currentActionIndexChanged)
+    def currentActionIndex(self) -> int:
+        return self._current_action_index
+
+    @pyqtProperty("QVariantMap", notify = currentActionIndexChanged)
+    def currentItem(self) -> Optional[Dict[str, Any]]:
+        if self._current_action_index >= self.count:
+            return dict()
+        else:
+            return self.getItem(self._current_action_index)
+
+    @pyqtProperty(bool, notify = currentActionIndexChanged)
+    def hasMoreActions(self) -> bool:
+        return self._current_action_index < self.count - 1
+
+    @pyqtSlot()
+    def goToNextAction(self) -> None:
+        # finish the current item
+        if "action" in self.currentItem:
+            self.currentItem["action"].setFinished()
+
+        if not self.hasMoreActions:
+            self.allFinished.emit()
+            self.reset()
+            return
+
+        self._current_action_index += 1
+        self.currentActionIndexChanged.emit()
+
+    # Resets the current action index to 0 so the wizard panel can show actions from the beginning.
+    @pyqtSlot()
+    def reset(self) -> None:
+        self._current_action_index = 0
+        self.currentActionIndexChanged.emit()
+
+        if self.count == 0:
+            self.allFinished.emit()
+
     def _update(self) -> None:
         global_stack = self._application.getMachineManager().activeMachine
         if global_stack is None:
@@ -53,6 +96,7 @@ class FirstStartMachineActionsModel(ListModel):
                               })
 
         self.setItems(item_list)
+        self.reset()
 
 
 __all__ = ["FirstStartMachineActionsModel"]

+ 72 - 20
cura/UI/WelcomePagesModel.py

@@ -13,7 +13,20 @@ from UM.Resources import Resources
 if TYPE_CHECKING:
     from PyQt5.QtCore import QObject
 
-
+#
+# This is the Qt ListModel that contains all welcome pages data. Each page is a page that can be shown as a step in the
+# welcome wizard dialog. Each item in this ListModel represents a page, which contains the following fields:
+#
+#  - id           : A unique page_id which can be used in function goToPage(page_id)
+#  - page_url     : The QUrl to the QML file that contains the content of this page
+#  - next_page_id : (OPTIONAL) The next page ID to go to when this page finished. This is optional. If this is not
+#                   provided, it will go to the page with the current index + 1
+#  - should_show_function : (OPTIONAL) An optional function that returns True/False indicating if this page should be
+#                           shown. By default all pages should be shown. If a function returns False, that page will
+#                           be skipped and its next page will be shown.
+#
+# Note that in any case, a page that has its "should_show_function" == False will ALWAYS be skipped.
+#
 class WelcomePagesModel(ListModel):
 
     IdRole = Qt.UserRole + 1  # Page ID
@@ -57,26 +70,40 @@ class WelcomePagesModel(ListModel):
             self.currentPageIndexChanged.emit()
 
     # Goes to the next page.
+    # If "from_index" is given, it will look for the next page to show starting from the "from_index" page instead of
+    # the "self._current_page_index".
     @pyqtSlot()
-    def goToNextPage(self) -> None:
-        page_item = self._items[self._current_page_index]
-        # Check if there's a "next_page_id" assigned. If so, go to that page. Otherwise, go to the page with the
-        # current index + 1.
-        next_page_id = page_item.get("next_page_id")
-        next_page_index = self._current_page_index + 1
-        if next_page_id:
-            idx = self.getPageIndexById(next_page_id)
-            if idx is None:
-                # FIXME: If we cannot find the next page, we cannot do anything here.
-                Logger.log("e", "Cannot find page with ID [%s]", next_page_id)
+    def goToNextPage(self, from_index: Optional[int] = None) -> None:
+        # Look for the next page that should be shown
+        current_index = self._current_page_index if from_index is None else from_index
+        while True:
+            page_item = self._items[current_index]
+
+            # Check if there's a "next_page_id" assigned. If so, go to that page. Otherwise, go to the page with the
+            # current index + 1.
+            next_page_id = page_item.get("next_page_id")
+            next_page_index = current_index + 1
+            if next_page_id:
+                idx = self.getPageIndexById(next_page_id)
+                if idx is None:
+                    # FIXME: If we cannot find the next page, we cannot do anything here.
+                    Logger.log("e", "Cannot find page with ID [%s]", next_page_id)
+                    return
+                next_page_index = idx
+
+            # If we have reached the last page, emit allFinished signal and reset.
+            if next_page_index == len(self._items):
+                self.allFinished.emit()
+                self.resetState()
                 return
-            next_page_index = idx
 
-        # If we have reached the last page, emit allFinished signal and reset.
-        if next_page_index == len(self._items):
-            self.allFinished.emit()
-            self.resetState()
-            return
+            # Check if the this page should be shown (default yes), if not, keep looking for the next one.
+            next_page_item = self.getItem(next_page_index)
+            if self._shouldPageBeShown(next_page_index):
+                break
+
+            Logger.log("d", "Page [%s] should not be displayed, look for the next page.", next_page_item["id"])
+            current_index = next_page_index
 
         # Move to the next page
         self._setCurrentPageIndex(next_page_index)
@@ -101,8 +128,19 @@ class WelcomePagesModel(ListModel):
             Logger.log("e", "Cannot find page with ID [%s]", page_index)
             return
 
-        # Move to that page
-        self._setCurrentPageIndex(page_index)
+        if self._shouldPageBeShown(page_index):
+            # Move to that page if it should be shown
+            self._setCurrentPageIndex(page_index)
+        else:
+            # Find the next page to show starting from the "page_index"
+            self.goToNextPage(from_index = page_index)
+
+    # Checks if the page with the given index should be shown by calling the "should_show_function" associated with it.
+    # If the function is not present, returns True (show page by default).
+    def _shouldPageBeShown(self, page_index: int) -> bool:
+        next_page_item = self.getItem(page_index)
+        should_show_function = next_page_item.get("should_show_function", lambda: True)
+        return should_show_function()
 
     # Resets the state of the WelcomePagesModel. This functions does the following:
     #  - Resets current_page_index to 0
@@ -154,6 +192,7 @@ class WelcomePagesModel(ListModel):
         self._pages.append({"id": "machine_actions",
                             "page_url": self._getBuiltinWelcomePagePath("FirstStartMachineActionsContent.qml"),
                             "next_page_id": "cloud",
+                            "should_show_function": self.shouldShowMachineActions,
                             })
         self._pages.append({"id": "cloud",
                             "page_url": self._getBuiltinWelcomePagePath("CloudContent.qml"),
@@ -161,6 +200,19 @@ class WelcomePagesModel(ListModel):
 
         self.setItems(self._pages)
 
+    # Indicates if the machine action panel should be shown by checking if there's any first start machine actions
+    # available.
+    def shouldShowMachineActions(self) -> bool:
+        from cura.CuraApplication import CuraApplication
+        application = CuraApplication.getInstance()
+        global_stack = application.getMachineManager().activeMachine
+        if global_stack is None:
+            return False
+
+        definition_id = global_stack.definition.getId()
+        first_start_actions = application.getMachineActionManager().getFirstStartActions(definition_id)
+        return len(first_start_actions) > 0
+
     def addPage(self) -> None:
         pass
 

+ 17 - 31
resources/qml/WelcomePages/FirstStartMachineActionsContent.qml

@@ -17,25 +17,19 @@ Item
 
     property var machineActionsModel: CuraApplication.getFirstStartMachineActionsModel()
 
-    property int currentActionIndex: 0
-    property var currentActionItem: currentActionIndex >= machineActionsModel.count
-                                    ? null : machineActionsModel.getItem(currentActionIndex)
-    property bool hasActions: machineActionsModel.count > 0
-
-    // Reset to the first page if the model gets changed.
-    Connections
+    Component.onCompleted:
     {
-        target: machineActionsModel
-        onItemsChanged: currentActionIndex = 0
+        // Reset the action to start from the beginning when it is shown.
+        machineActionsModel.reset()
     }
 
-    onVisibleChanged:
+    // Go to the next page when all machine actions have been finished
+    Connections
     {
-        if (visible)
+        target: machineActionsModel
+        onAllFinished:
         {
-            // Reset the action to start from the beginning when it is shown.
-            currentActionIndex = 0
-            if (!hasActions)
+            if (visible)
             {
                 base.showNextPage()
             }
@@ -49,7 +43,7 @@ Item
         anchors.topMargin: UM.Theme.getSize("welcome_pages_default_margin").height
         anchors.horizontalCenter: parent.horizontalCenter
         horizontalAlignment: Text.AlignHCenter
-        text: currentActionItem == null ? "" : currentActionItem.title
+        text: machineActionsModel.currentItem.title == undefined ? "" : machineActionsModel.currentItem.title
         color: UM.Theme.getColor("primary_button")
         font: UM.Theme.getFont("large_bold")
         renderType: Text.NativeRendering
@@ -63,7 +57,13 @@ Item
         anchors.left: parent.left
         anchors.right: parent.right
 
-        data: currentActionItem == undefined ? null : currentActionItem.content
+        data: machineActionsModel.currentItem.content == undefined ? emptyItem : machineActionsModel.currentItem.content
+    }
+
+    // An empty item in case there's no currentItem.content to show
+    Item
+    {
+        id: emptyItem
     }
 
     Cura.PrimaryButton
@@ -75,20 +75,6 @@ Item
         text: catalog.i18nc("@button", "Next")
         width: UM.Theme.getSize("welcome_pages_button").width
         fixedWidthMode: true
-        onClicked:
-        {
-            // If no more first-start actions to show, go to the next page.
-            if (currentActionIndex + 1 >= machineActionsModel.count)
-            {
-                currentActionIndex = 0
-                base.showNextPage()
-                return
-            }
-
-            // notify the current MachineAction that it has finished
-            currentActionItem.action.setFinished()
-            // move on to the next MachineAction
-            currentActionIndex++
-        }
+        onClicked: machineActionsModel.goToNextAction()
     }
 }