mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
CURA-3495 open project/models in one dialog
This commit is contained in:
parent
b35a97c770
commit
e00c68344a
4 changed files with 138 additions and 48 deletions
|
@ -25,6 +25,7 @@ from UM.Settings.InstanceContainer import InstanceContainer
|
||||||
from UM.Settings.Validator import Validator
|
from UM.Settings.Validator import Validator
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
|
from UM.Workspace.WorkspaceReader import WorkspaceReader
|
||||||
|
|
||||||
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
|
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
|
||||||
from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
|
from UM.Operations.RemoveSceneNodeOperation import RemoveSceneNodeOperation
|
||||||
|
@ -1260,3 +1261,21 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
def addNonSliceableExtension(self, extension):
|
def addNonSliceableExtension(self, extension):
|
||||||
self._non_sliceable_extensions.append(extension)
|
self._non_sliceable_extensions.append(extension)
|
||||||
|
|
||||||
|
@pyqtSlot(str, result=bool)
|
||||||
|
def checkIsValidProjectFile(self, file_url):
|
||||||
|
"""
|
||||||
|
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)
|
||||||
|
if workspace_reader is None:
|
||||||
|
return False # non-project files won't get a reader
|
||||||
|
|
||||||
|
result = workspace_reader.preRead(file_name, show_dialog=False)
|
||||||
|
return result == WorkspaceReader.PreReadResult.accepted
|
||||||
|
|
|
@ -47,7 +47,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
self._id_mapping[old_id] = self._container_registry.uniqueName(old_id)
|
self._id_mapping[old_id] = self._container_registry.uniqueName(old_id)
|
||||||
return self._id_mapping[old_id]
|
return self._id_mapping[old_id]
|
||||||
|
|
||||||
def preRead(self, file_name):
|
def preRead(self, file_name, show_dialog=True, *args, **kwargs):
|
||||||
self._3mf_mesh_reader = Application.getInstance().getMeshFileHandler().getReaderForFile(file_name)
|
self._3mf_mesh_reader = Application.getInstance().getMeshFileHandler().getReaderForFile(file_name)
|
||||||
if self._3mf_mesh_reader and self._3mf_mesh_reader.preRead(file_name) == WorkspaceReader.PreReadResult.accepted:
|
if self._3mf_mesh_reader and self._3mf_mesh_reader.preRead(file_name) == WorkspaceReader.PreReadResult.accepted:
|
||||||
pass
|
pass
|
||||||
|
@ -167,6 +167,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||||
Logger.log("w", "File %s is not a valid workspace.", file_name)
|
Logger.log("w", "File %s is not a valid workspace.", file_name)
|
||||||
return WorkspaceReader.PreReadResult.failed
|
return WorkspaceReader.PreReadResult.failed
|
||||||
|
|
||||||
|
# In case we use preRead() to check if a file is a valid project file, we don't want to show a dialog.
|
||||||
|
if not show_dialog:
|
||||||
|
return WorkspaceReader.PreReadResult.accepted
|
||||||
|
|
||||||
# Show the dialog, informing the user what is about to happen.
|
# Show the dialog, informing the user what is about to happen.
|
||||||
self._dialog.setMachineConflict(machine_conflict)
|
self._dialog.setMachineConflict(machine_conflict)
|
||||||
self._dialog.setQualityChangesConflict(quality_changes_conflict)
|
self._dialog.setQualityChangesConflict(quality_changes_conflict)
|
||||||
|
|
|
@ -12,7 +12,6 @@ Item
|
||||||
{
|
{
|
||||||
property alias newProject: newProjectAction;
|
property alias newProject: newProjectAction;
|
||||||
property alias open: openAction;
|
property alias open: openAction;
|
||||||
property alias loadWorkspace: loadWorkspaceAction;
|
|
||||||
property alias quit: quitAction;
|
property alias quit: quitAction;
|
||||||
|
|
||||||
property alias undo: undoAction;
|
property alias undo: undoAction;
|
||||||
|
@ -284,7 +283,7 @@ Item
|
||||||
Action
|
Action
|
||||||
{
|
{
|
||||||
id: openAction;
|
id: openAction;
|
||||||
text: catalog.i18nc("@action:inmenu menubar:file","&Open File...");
|
text: catalog.i18nc("@action:inmenu menubar:file","&Open File(s)...");
|
||||||
iconName: "document-open";
|
iconName: "document-open";
|
||||||
shortcut: StandardKey.Open;
|
shortcut: StandardKey.Open;
|
||||||
}
|
}
|
||||||
|
@ -296,12 +295,6 @@ Item
|
||||||
shortcut: StandardKey.New
|
shortcut: StandardKey.New
|
||||||
}
|
}
|
||||||
|
|
||||||
Action
|
|
||||||
{
|
|
||||||
id: loadWorkspaceAction
|
|
||||||
text: catalog.i18nc("@action:inmenu menubar:file","&Open Project...");
|
|
||||||
}
|
|
||||||
|
|
||||||
Action
|
Action
|
||||||
{
|
{
|
||||||
id: showEngineLogAction;
|
id: showEngineLogAction;
|
||||||
|
|
|
@ -78,11 +78,6 @@ UM.MainWindow
|
||||||
|
|
||||||
RecentFilesMenu { }
|
RecentFilesMenu { }
|
||||||
|
|
||||||
MenuItem
|
|
||||||
{
|
|
||||||
action: Cura.Actions.loadWorkspace
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuSeparator { }
|
MenuSeparator { }
|
||||||
|
|
||||||
MenuItem
|
MenuItem
|
||||||
|
@ -752,27 +747,43 @@ UM.MainWindow
|
||||||
id: openDialog;
|
id: openDialog;
|
||||||
|
|
||||||
//: File open dialog title
|
//: File open dialog title
|
||||||
title: catalog.i18nc("@title:window","Open file")
|
title: catalog.i18nc("@title:window","Open file(s)")
|
||||||
modality: UM.Application.platform == "linux" ? Qt.NonModal : Qt.WindowModal;
|
modality: UM.Application.platform == "linux" ? Qt.NonModal : Qt.WindowModal;
|
||||||
selectMultiple: true
|
selectMultiple: true
|
||||||
nameFilters: UM.MeshFileHandler.supportedReadFileTypes;
|
nameFilters: UM.MeshFileHandler.supportedReadFileTypes;
|
||||||
folder: CuraApplication.getDefaultPath("dialog_load_path")
|
folder: CuraApplication.getDefaultPath("dialog_load_path")
|
||||||
onAccepted:
|
onAccepted:
|
||||||
{
|
{
|
||||||
//Because several implementations of the file dialog only update the folder
|
// Because several implementations of the file dialog only update the folder
|
||||||
//when it is explicitly set.
|
// when it is explicitly set.
|
||||||
var f = folder;
|
var f = folder;
|
||||||
folder = f;
|
folder = f;
|
||||||
|
|
||||||
CuraApplication.setDefaultPath("dialog_load_path", folder);
|
CuraApplication.setDefaultPath("dialog_load_path", folder);
|
||||||
|
|
||||||
for(var i in fileUrls)
|
// look for valid project files
|
||||||
|
var projectFileUrlList = [];
|
||||||
|
for (var i in fileUrls)
|
||||||
{
|
{
|
||||||
Printer.readLocalFile(fileUrls[i])
|
if (CuraApplication.checkIsValidProjectFile(fileUrls[i]))
|
||||||
|
projectFileUrlList.push(fileUrls[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var meshName = backgroundItem.getMeshName(fileUrls[0].toString())
|
// we only allow opening one project file
|
||||||
backgroundItem.hasMesh(decodeURIComponent(meshName))
|
var selectedMultipleFiles = fileUrls.length > 1;
|
||||||
|
var hasProjectFile = projectFileUrlList.length > 0;
|
||||||
|
var selectedMultipleWithProjectFile = hasProjectFile && selectedMultipleFiles;
|
||||||
|
if (selectedMultipleWithProjectFile)
|
||||||
|
{
|
||||||
|
askOpenProjectOrModelsDialog.fileUrls = fileUrls;
|
||||||
|
askOpenProjectOrModelsDialog.show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasProjectFile)
|
||||||
|
loadProjectFile(projectFileUrlList[0]);
|
||||||
|
else
|
||||||
|
loadModelFiles(fileUrls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,38 +793,101 @@ UM.MainWindow
|
||||||
onTriggered: openDialog.open()
|
onTriggered: openDialog.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
FileDialog
|
function loadProjectFile(projectFile)
|
||||||
{
|
{
|
||||||
id: openWorkspaceDialog;
|
UM.WorkspaceFileHandler.readLocalFile(projectFile);
|
||||||
|
|
||||||
//: File open dialog title
|
var meshName = backgroundItem.getMeshName(projectFile.toString());
|
||||||
title: catalog.i18nc("@title:window","Open workspace")
|
backgroundItem.hasMesh(decodeURIComponent(meshName));
|
||||||
modality: UM.Application.platform == "linux" ? Qt.NonModal : Qt.WindowModal;
|
|
||||||
selectMultiple: false
|
|
||||||
nameFilters: UM.WorkspaceFileHandler.supportedReadFileTypes;
|
|
||||||
folder: CuraApplication.getDefaultPath("dialog_load_path")
|
|
||||||
onAccepted:
|
|
||||||
{
|
|
||||||
//Because several implementations of the file dialog only update the folder
|
|
||||||
//when it is explicitly set.
|
|
||||||
var f = folder;
|
|
||||||
folder = f;
|
|
||||||
|
|
||||||
CuraApplication.setDefaultPath("dialog_load_path", folder);
|
|
||||||
|
|
||||||
for(var i in fileUrls)
|
|
||||||
{
|
|
||||||
UM.WorkspaceFileHandler.readLocalFile(fileUrls[i])
|
|
||||||
}
|
|
||||||
var meshName = backgroundItem.getMeshName(fileUrls[0].toString())
|
|
||||||
backgroundItem.hasMesh(decodeURIComponent(meshName))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections
|
function loadModelFiles(fileUrls)
|
||||||
{
|
{
|
||||||
target: Cura.Actions.loadWorkspace
|
for (var i in fileUrls)
|
||||||
onTriggered: openWorkspaceDialog.open()
|
Printer.readLocalFile(fileUrls[i]);
|
||||||
|
|
||||||
|
var meshName = backgroundItem.getMeshName(fileUrls[0].toString());
|
||||||
|
backgroundItem.hasMesh(decodeURIComponent(meshName));
|
||||||
|
}
|
||||||
|
|
||||||
|
UM.Dialog
|
||||||
|
{
|
||||||
|
// This dialog asks the user whether he/she wants to open the project file we have detected or the model files.
|
||||||
|
id: askOpenProjectOrModelsDialog
|
||||||
|
|
||||||
|
title: catalog.i18nc("@title:window", "Open file(s)")
|
||||||
|
width: 620
|
||||||
|
height: 250
|
||||||
|
|
||||||
|
maximumHeight: height
|
||||||
|
maximumWidth: width
|
||||||
|
minimumHeight: height
|
||||||
|
minimumWidth: width
|
||||||
|
|
||||||
|
modality: UM.Application.platform == "linux" ? Qt.NonModal : Qt.WindowModal;
|
||||||
|
|
||||||
|
property var fileUrls: []
|
||||||
|
property int spacerHeight: 10
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
Text
|
||||||
|
{
|
||||||
|
id: askOpenProjectOrModelsDialogText
|
||||||
|
text: catalog.i18nc("@text:window", "We have found multiple project file(s) within the files you have\nselected. You can open only one project file at a time. We\nsuggest to only import models from those files. Would you like\nto proceed?")
|
||||||
|
anchors.margins: UM.Theme.getSize("default_margin").width
|
||||||
|
font: UM.Theme.getFont("default")
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
Item // Spacer
|
||||||
|
{
|
||||||
|
height: askOpenProjectOrModelsDialog.spacerHeight
|
||||||
|
width: height
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
Item
|
||||||
|
{
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
height: childrenRect.height
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: cancelButton
|
||||||
|
text: catalog.i18nc("@action:button", "Cancel");
|
||||||
|
anchors.right: importAllAsModelsButton.left
|
||||||
|
anchors.rightMargin: UM.Theme.getSize("default_margin").width
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
// cancel
|
||||||
|
askOpenProjectOrModelsDialog.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button
|
||||||
|
{
|
||||||
|
id: importAllAsModelsButton
|
||||||
|
text: catalog.i18nc("@action:button", "Import all as models");
|
||||||
|
anchors.right: parent.right
|
||||||
|
isDefault: true
|
||||||
|
onClicked:
|
||||||
|
{
|
||||||
|
// load models from all selected file
|
||||||
|
loadModelFiles(askOpenProjectOrModelsDialog.fileUrls);
|
||||||
|
|
||||||
|
askOpenProjectOrModelsDialog.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EngineLog
|
EngineLog
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue