Browse Source

Merge pull request #1554 from LipuFei/feature_CURA-3495_open_in_one

CURA-3495 Open project/models menu
jack 8 years ago
parent
commit
af43b2e8c4

+ 8 - 9
cura/CuraApplication.py

@@ -4,6 +4,7 @@ from PyQt5.QtNetwork import QLocalServer
 from PyQt5.QtNetwork import QLocalSocket
 
 from UM.Qt.QtApplication import QtApplication
+from UM.FileHandler.ReadFileJob import ReadFileJob
 from UM.Scene.SceneNode import SceneNode
 from UM.Scene.Camera import Camera
 from UM.Math.Vector import Vector
@@ -247,10 +248,13 @@ class CuraApplication(QtApplication):
         Preferences.getInstance().addPreference("cura/dialog_on_project_save", True)
         Preferences.getInstance().addPreference("cura/asked_dialog_on_project_save", False)
         Preferences.getInstance().addPreference("cura/choice_on_profile_override", "always_ask")
+        Preferences.getInstance().addPreference("cura/choice_on_open_project", "always_ask")
 
         Preferences.getInstance().addPreference("cura/currency", "€")
         Preferences.getInstance().addPreference("cura/material_settings", "{}")
 
+        Preferences.getInstance().addPreference("view/invert_zoom", False)
+
         for key in [
             "dialog_load_path",  # dialog_save_path is in LocalFileOutputDevicePlugin
             "dialog_profile_path",
@@ -1122,7 +1126,7 @@ class CuraApplication(QtApplication):
     fileLoaded = pyqtSignal(str)
 
     def _onJobFinished(self, job):
-        if type(job) is not ReadMeshJob or not job.getResult():
+        if (not isinstance(job, ReadMeshJob) and not isinstance(job, ReadFileJob)) or not job.getResult():
             return
 
         f = QUrl.fromLocalFile(job.getFileName())
@@ -1267,15 +1271,10 @@ class CuraApplication(QtApplication):
         """
         Checks if the given file URL is a valid project file.
         """
-        file_url_prefix = 'file:///'
-
-        file_name = file_url
-        if file_name.startswith(file_url_prefix):
-            file_name = file_name[len(file_url_prefix):]
-
-        workspace_reader = self.getWorkspaceFileHandler().getReaderForFile(file_name)
+        file_path = QUrl(file_url).toLocalFile()
+        workspace_reader = self.getWorkspaceFileHandler().getReaderForFile(file_path)
         if workspace_reader is None:
             return False  # non-project files won't get a reader
 
-        result = workspace_reader.preRead(file_name, show_dialog=False)
+        result = workspace_reader.preRead(file_path, show_dialog=False)
         return result == WorkspaceReader.PreReadResult.accepted

+ 125 - 0
resources/qml/AskOpenAsProjectOrModelsDialog.qml

@@ -0,0 +1,125 @@
+// Copyright (c) 2015 Ultimaker B.V.
+// Cura is released under the terms of the AGPLv3 or higher.
+
+import QtQuick 2.2
+import QtQuick.Controls 1.1
+import QtQuick.Controls.Styles 1.1
+import QtQuick.Layouts 1.1
+import QtQuick.Dialogs 1.1
+
+import UM 1.3 as UM
+import Cura 1.0 as Cura
+
+
+UM.Dialog
+{
+    // This dialog asks the user whether he/she wants to open a project file as a project or import models.
+    id: base
+
+    title: catalog.i18nc("@title:window", "Open project file")
+    width: 420
+    height: 140
+
+    maximumHeight: height
+    maximumWidth: width
+    minimumHeight: height
+    minimumWidth: width
+
+    modality: UM.Application.platform == "linux" ? Qt.NonModal : Qt.WindowModal;
+
+    property var fileUrl
+
+    function loadProjectFile(projectFile)
+    {
+        UM.WorkspaceFileHandler.readLocalFile(projectFile);
+
+        var meshName = backgroundItem.getMeshName(projectFile.toString());
+        backgroundItem.hasMesh(decodeURIComponent(meshName));
+    }
+
+    function loadModelFiles(fileUrls)
+    {
+        for (var i in fileUrls)
+            Printer.readLocalFile(fileUrls[i]);
+
+        var meshName = backgroundItem.getMeshName(fileUrls[0].toString());
+        backgroundItem.hasMesh(decodeURIComponent(meshName));
+    }
+
+    onVisibleChanged:
+    {
+        if (visible)
+        {
+            var rememberMyChoice = UM.Preferences.getValue("cura/choice_on_open_project") != "always_ask";
+            rememberChoiceCheckBox.checked = rememberMyChoice;
+        }
+    }
+
+    Column
+    {
+        anchors.fill: parent
+        anchors.margins: UM.Theme.getSize("default_margin").width
+        anchors.left: parent.left
+        anchors.right: parent.right
+        spacing: UM.Theme.getSize("default_margin").width
+
+        Label
+        {
+            text: catalog.i18nc("@text:window", "This is a Cura project file. Would you like to open it as a project\nor import the models from it?")
+            anchors.margins: UM.Theme.getSize("default_margin").width
+            wrapMode: Text.WordWrap
+        }
+
+        CheckBox
+        {
+            id: rememberChoiceCheckBox
+            text: catalog.i18nc("@text:window", "Remember my choice")
+            anchors.margins: UM.Theme.getSize("default_margin").width
+            checked: UM.Preferences.getValue("cura/choice_on_open_project") != "always_ask"
+        }
+
+        // Buttons
+        Item
+        {
+            anchors.right: parent.right
+            anchors.left: parent.left
+            height: childrenRect.height
+
+            Button
+            {
+                id: openAsProjectButton
+                text: catalog.i18nc("@action:button", "Open as project");
+                anchors.right: importModelsButton.left
+                anchors.rightMargin: UM.Theme.getSize("default_margin").width
+                isDefault: true
+                onClicked:
+                {
+                    // update preference
+                    if (rememberChoiceCheckBox.checked)
+                        UM.Preferences.setValue("cura/choice_on_open_project", "open_as_project");
+
+                    // load this file as project
+                    base.hide();
+                    loadProjectFile(base.fileUrl);
+                }
+            }
+
+            Button
+            {
+                id: importModelsButton
+                text: catalog.i18nc("@action:button", "Import models");
+                anchors.right: parent.right
+                onClicked:
+                {
+                    // update preference
+                    if (rememberChoiceCheckBox.checked)
+                        UM.Preferences.setValue("cura/choice_on_open_project", "open_as_model");
+
+                    // load models from this project file
+                    base.hide();
+                    loadModelFiles([base.fileUrl]);
+                }
+            }
+        }
+    }
+}

+ 23 - 1
resources/qml/Cura.qml

@@ -773,9 +773,26 @@ UM.MainWindow
             }
 
             if (hasProjectFile)
-                openFilesIncludingProjectsDialog.loadProjectFile(projectFileUrlList[0]);
+            {
+                var projectFile = projectFileUrlList[0];
+
+                // check preference
+                var choice = UM.Preferences.getValue("cura/choice_on_open_project");
+                if (choice == "open_as_project")
+                    openFilesIncludingProjectsDialog.loadProjectFile(projectFile);
+                else if (choice == "open_as_model")
+                    openFilesIncludingProjectsDialog.loadModelFiles([projectFile]);
+                else    // always ask
+                {
+                    // ask whether to open as project or as models
+                    askOpenAsProjectOrModelsDialog.fileUrl = projectFile;
+                    askOpenAsProjectOrModelsDialog.show();
+                }
+            }
             else
+            {
                 openFilesIncludingProjectsDialog.loadModelFiles(fileUrls);
+            }
         }
     }
 
@@ -790,6 +807,11 @@ UM.MainWindow
         id: openFilesIncludingProjectsDialog
     }
 
+    AskOpenAsProjectOrModelsDialog
+    {
+        id: askOpenAsProjectOrModelsDialog
+    }
+
     EngineLog
     {
         id: engineLog;

+ 38 - 3
resources/qml/Menus/RecentFilesMenu.qml

@@ -4,7 +4,7 @@
 import QtQuick 2.2
 import QtQuick.Controls 1.1
 
-import UM 1.2 as UM
+import UM 1.3 as UM
 import Cura 1.0 as Cura
 
 Menu
@@ -25,8 +25,38 @@ Menu
                 var path = modelData.toString()
                 return (index + 1) + ". " + path.slice(path.lastIndexOf("/") + 1);
             }
-            onTriggered: {
-                Printer.readLocalFile(modelData);
+            onTriggered:
+            {
+                var toShowDialog = false;
+                var toOpenAsProject = false;
+                var toOpenAsModel = false;
+
+                if (CuraApplication.checkIsValidProjectFile(modelData)) {
+                    // check preference
+                    var choice = UM.Preferences.getValue("cura/choice_on_open_project");
+
+                    if (choice == "open_as_project")
+                        toOpenAsProject = true;
+                    else if (choice == "open_as_model")
+                        toOpenAsModel = true;
+                    else
+                        toShowDialog = true;
+                }
+                else {
+                    toOpenAsModel = true;
+                }
+
+                if (toShowDialog) {
+                    askOpenAsProjectOrModelsDialog.fileUrl = modelData;
+                    askOpenAsProjectOrModelsDialog.show();
+                    return;
+                }
+
+                // open file in the prefered way
+                if (toOpenAsProject)
+                    UM.WorkspaceFileHandler.readLocalFile(modelData);
+                else if (toOpenAsModel)
+                    Printer.readLocalFile(modelData);
                 var meshName = backgroundItem.getMeshName(modelData.toString())
                 backgroundItem.hasMesh(decodeURIComponent(meshName))
             }
@@ -34,4 +64,9 @@ Menu
         onObjectAdded: menu.insertItem(index, object)
         onObjectRemoved: menu.removeItem(object)
     }
+
+    Cura.AskOpenAsProjectOrModelsDialog
+    {
+        id: askOpenAsProjectOrModelsDialog
+    }
 }

+ 65 - 0
resources/qml/Preferences/GeneralPage.qml

@@ -37,6 +37,18 @@ UM.PreferencesPage
         }
     }
 
+    function setDefaultOpenProjectOption(code)
+    {
+        for (var i = 0; i < choiceOnOpenProjectDropDownButton.model.count; ++i)
+        {
+            if (choiceOnOpenProjectDropDownButton.model.get(i).code == code)
+            {
+                choiceOnOpenProjectDropDownButton.currentIndex = i
+                break;
+            }
+        }
+    }
+
     function reset()
     {
         UM.Preferences.resetPreference("general/language")
@@ -65,6 +77,9 @@ UM.PreferencesPage
         UM.Preferences.resetPreference("cura/choice_on_profile_override")
         setDefaultDiscardOrKeepProfile(UM.Preferences.getValue("cura/choice_on_profile_override"))
 
+        UM.Preferences.resetPreference("cura/choice_on_open_project")
+        setDefaultOpenProjectOption(UM.Preferences.getValue("cura/choice_on_open_project"))
+
         if (plugins.find("id", "SliceInfoPlugin") > -1) {
             UM.Preferences.resetPreference("info/send_slice_info")
             sendDataCheckbox.checked = boolCheck(UM.Preferences.getValue("info/send_slice_info"))
@@ -389,6 +404,56 @@ UM.PreferencesPage
                 }
             }
 
+            UM.TooltipArea {
+                width: childrenRect.width
+                height: childrenRect.height
+                text: catalog.i18nc("@info:tooltip", "Default behavior when opening a project file")
+
+                Column
+                {
+                    spacing: 4
+
+                    Label
+                    {
+                        text: catalog.i18nc("@window:text", "Default behavior when opening a project file: ")
+                    }
+
+                    ComboBox
+                    {
+                        id: choiceOnOpenProjectDropDownButton
+                        width: 200
+
+                        model: ListModel
+                        {
+                            id: openProjectOptionModel
+
+                            Component.onCompleted: {
+                                append({ text: catalog.i18nc("@option:openProject", "Always ask"), code: "always_ask" })
+                                append({ text: catalog.i18nc("@option:openProject", "Always open as a project"), code: "open_as_project" })
+                                append({ text: catalog.i18nc("@option:openProject", "Always import models"), code: "open_as_model" })
+                            }
+                        }
+
+                        currentIndex:
+                        {
+                            var index = 0;
+                            var currentChoice = UM.Preferences.getValue("cura/choice_on_open_project");
+                            for (var i = 0; i < model.count; ++i)
+                            {
+                                if (model.get(i).code == currentChoice)
+                                {
+                                    index = i;
+                                    break;
+                                }
+                            }
+                            return index;
+                        }
+
+                        onActivated: UM.Preferences.setValue("cura/choice_on_open_project", model.get(index).code)
+                    }
+                }
+            }
+
             Item
             {
                 //: Spacer