mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-04-28 23:04:34 +08:00
Move open dialogue to separate file provider plug-in
We can now define plug-ins that specify where to open files from. This is one of the places where you can open files. This breaks the main button to open files in the interface. It needs to be redirected to trigger the plug-in to show the open file dialogue. Contributest o issue CURA-7868.
This commit is contained in:
parent
4b375ce2fe
commit
00de7497a4
47
plugins/LocalFileProvider/LocalFileProvider.py
Normal file
47
plugins/LocalFileProvider/LocalFileProvider.py
Normal file
@ -0,0 +1,47 @@
|
||||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import os.path
|
||||
|
||||
from UM.FileProvider import FileProvider # The plug-in type we're going to implement.
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Logger import Logger
|
||||
from UM.PluginRegistry import PluginRegistry # To get resources from the plug-in folder.
|
||||
from cura.CuraApplication import CuraApplication # To create QML elements.
|
||||
|
||||
i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
class LocalFileProvider(FileProvider):
|
||||
"""
|
||||
Allows the user to open files from their local file system.
|
||||
|
||||
These files will then be interpreted through the file handlers.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.menu_item_display_text = i18n_catalog.i18nc("@menu Open files from local disk", "Local disk")
|
||||
self.shortcut = "Ctrl+O"
|
||||
|
||||
self._dialog = None # Lazy-load this QML element.
|
||||
|
||||
def _load_file_dialog(self):
|
||||
"""
|
||||
Loads the file dialog QML element into the QML context so that it can be shown.
|
||||
:return:
|
||||
"""
|
||||
plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
|
||||
if plugin_path is None:
|
||||
plugin_path = os.path.dirname(__file__)
|
||||
path = os.path.join(plugin_path, "OpenLocalFile.qml")
|
||||
self._dialog = CuraApplication.getInstance().createQmlComponent(path)
|
||||
if self._dialog is None:
|
||||
Logger.log("e", "Unable to create open file dialogue.")
|
||||
|
||||
def run(self):
|
||||
if self._dialog is None:
|
||||
self._load_file_dialog()
|
||||
if self._dialog is None:
|
||||
return # Will already have logged an error in _load_file_dialog.
|
||||
self._dialog.show()
|
171
plugins/LocalFileProvider/OpenLocalFile.qml
Normal file
171
plugins/LocalFileProvider/OpenLocalFile.qml
Normal file
@ -0,0 +1,171 @@
|
||||
// Copyright (c) 2021 Ultimaker B.V.
|
||||
// Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Dialogs 1.2
|
||||
|
||||
import UM 1.3 as UM
|
||||
import Cura 1.1 as Cura
|
||||
|
||||
Item
|
||||
{
|
||||
id: base
|
||||
|
||||
function show()
|
||||
{
|
||||
openDialog.visible = true;
|
||||
}
|
||||
|
||||
UM.I18nCatalog
|
||||
{
|
||||
id: catalog
|
||||
name: "cura"
|
||||
}
|
||||
|
||||
FileDialog
|
||||
{
|
||||
id: openDialog;
|
||||
|
||||
//: File open dialog title
|
||||
title: catalog.i18nc("@title:window","Open file(s)")
|
||||
modality: Qt.WindowModal
|
||||
selectMultiple: true
|
||||
nameFilters: UM.MeshFileHandler.supportedReadFileTypes;
|
||||
folder:
|
||||
{
|
||||
//Because several implementations of the file dialog only update the folder when it is explicitly set.
|
||||
folder = CuraApplication.getDefaultPath("dialog_load_path");
|
||||
return 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);
|
||||
|
||||
handleOpenFileUrls(fileUrls);
|
||||
}
|
||||
|
||||
// Yeah... I know... it is a mess to put all those things here.
|
||||
// There are lots of user interactions in this part of the logic, such as showing a warning dialog here and there,
|
||||
// etc. This means it will come back and forth from time to time between QML and Python. So, separating the logic
|
||||
// and view here may require more effort but make things more difficult to understand.
|
||||
function handleOpenFileUrls(fileUrlList)
|
||||
{
|
||||
// look for valid project files
|
||||
var projectFileUrlList = [];
|
||||
var hasGcode = false;
|
||||
var nonGcodeFileList = [];
|
||||
for (var i in fileUrlList)
|
||||
{
|
||||
var endsWithG = /\.g$/;
|
||||
var endsWithGcode = /\.gcode$/;
|
||||
if (endsWithG.test(fileUrlList[i]) || endsWithGcode.test(fileUrlList[i]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (CuraApplication.checkIsValidProjectFile(fileUrlList[i]))
|
||||
{
|
||||
projectFileUrlList.push(fileUrlList[i]);
|
||||
}
|
||||
nonGcodeFileList.push(fileUrlList[i]);
|
||||
}
|
||||
hasGcode = nonGcodeFileList.length < fileUrlList.length;
|
||||
|
||||
// show a warning if selected multiple files together with Gcode
|
||||
var hasProjectFile = projectFileUrlList.length > 0;
|
||||
var selectedMultipleFiles = fileUrlList.length > 1;
|
||||
if (selectedMultipleFiles && hasGcode)
|
||||
{
|
||||
infoMultipleFilesWithGcodeDialog.selectedMultipleFiles = selectedMultipleFiles;
|
||||
infoMultipleFilesWithGcodeDialog.hasProjectFile = hasProjectFile;
|
||||
infoMultipleFilesWithGcodeDialog.fileUrls = nonGcodeFileList.slice();
|
||||
infoMultipleFilesWithGcodeDialog.projectFileUrlList = projectFileUrlList.slice();
|
||||
infoMultipleFilesWithGcodeDialog.open();
|
||||
}
|
||||
else
|
||||
{
|
||||
handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrlList, projectFileUrlList);
|
||||
}
|
||||
}
|
||||
|
||||
function handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrlList, projectFileUrlList)
|
||||
{
|
||||
// we only allow opening one project file
|
||||
if (selectedMultipleFiles && hasProjectFile)
|
||||
{
|
||||
openFilesIncludingProjectsDialog.fileUrls = fileUrlList.slice();
|
||||
openFilesIncludingProjectsDialog.show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasProjectFile)
|
||||
{
|
||||
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].slice());
|
||||
}
|
||||
else // always ask
|
||||
{
|
||||
// ask whether to open as project or as models
|
||||
askOpenAsProjectOrModelsDialog.fileUrl = projectFile;
|
||||
askOpenAsProjectOrModelsDialog.show();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
openFilesIncludingProjectsDialog.loadModelFiles(fileUrlList.slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog
|
||||
{
|
||||
id: infoMultipleFilesWithGcodeDialog
|
||||
title: catalog.i18nc("@title:window", "Open File(s)")
|
||||
icon: StandardIcon.Information
|
||||
standardButtons: StandardButton.Ok
|
||||
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.")
|
||||
|
||||
property var selectedMultipleFiles
|
||||
property var hasProjectFile
|
||||
property var fileUrls
|
||||
property var projectFileUrlList
|
||||
|
||||
onAccepted:
|
||||
{
|
||||
openDialog.handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrls, projectFileUrlList);
|
||||
}
|
||||
}
|
||||
|
||||
Cura.AskOpenAsProjectOrModelsDialog
|
||||
{
|
||||
id: askOpenAsProjectOrModelsDialog
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: CuraApplication
|
||||
onOpenProjectFile:
|
||||
{
|
||||
askOpenAsProjectOrModelsDialog.fileUrl = project_file;
|
||||
askOpenAsProjectOrModelsDialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
Cura.OpenFilesIncludingProjectsDialog
|
||||
{
|
||||
id: openFilesIncludingProjectsDialog
|
||||
}
|
||||
}
|
11
plugins/LocalFileProvider/__init__.py
Normal file
11
plugins/LocalFileProvider/__init__.py
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from . import LocalFileProvider
|
||||
|
||||
|
||||
def getMetaData():
|
||||
return {}
|
||||
|
||||
def register(app):
|
||||
return { "file_provider": LocalFileProvider.LocalFileProvider() }
|
8
plugins/LocalFileProvider/plugin.json
Normal file
8
plugins/LocalFileProvider/plugin.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Local File Provider",
|
||||
"description": "Enables opening files from the local file system.",
|
||||
"author": "Ultimaker B.V.",
|
||||
"version": "1.0.0",
|
||||
"api": "7.4.0",
|
||||
"i18n-catalog": "cura"
|
||||
}
|
@ -619,114 +619,6 @@ UM.MainWindow
|
||||
onTriggered: base.exitFullscreen()
|
||||
}
|
||||
|
||||
FileDialog
|
||||
{
|
||||
id: openDialog;
|
||||
|
||||
//: File open dialog title
|
||||
title: catalog.i18nc("@title:window","Open file(s)")
|
||||
modality: Qt.WindowModal
|
||||
selectMultiple: true
|
||||
nameFilters: UM.MeshFileHandler.supportedReadFileTypes;
|
||||
folder:
|
||||
{
|
||||
//Because several implementations of the file dialog only update the folder when it is explicitly set.
|
||||
folder = CuraApplication.getDefaultPath("dialog_load_path");
|
||||
return 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);
|
||||
|
||||
handleOpenFileUrls(fileUrls);
|
||||
}
|
||||
|
||||
// Yeah... I know... it is a mess to put all those things here.
|
||||
// There are lots of user interactions in this part of the logic, such as showing a warning dialog here and there,
|
||||
// etc. This means it will come back and forth from time to time between QML and Python. So, separating the logic
|
||||
// and view here may require more effort but make things more difficult to understand.
|
||||
function handleOpenFileUrls(fileUrlList)
|
||||
{
|
||||
// look for valid project files
|
||||
var projectFileUrlList = [];
|
||||
var hasGcode = false;
|
||||
var nonGcodeFileList = [];
|
||||
for (var i in fileUrlList)
|
||||
{
|
||||
var endsWithG = /\.g$/;
|
||||
var endsWithGcode = /\.gcode$/;
|
||||
if (endsWithG.test(fileUrlList[i]) || endsWithGcode.test(fileUrlList[i]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (CuraApplication.checkIsValidProjectFile(fileUrlList[i]))
|
||||
{
|
||||
projectFileUrlList.push(fileUrlList[i]);
|
||||
}
|
||||
nonGcodeFileList.push(fileUrlList[i]);
|
||||
}
|
||||
hasGcode = nonGcodeFileList.length < fileUrlList.length;
|
||||
|
||||
// show a warning if selected multiple files together with Gcode
|
||||
var hasProjectFile = projectFileUrlList.length > 0;
|
||||
var selectedMultipleFiles = fileUrlList.length > 1;
|
||||
if (selectedMultipleFiles && hasGcode)
|
||||
{
|
||||
infoMultipleFilesWithGcodeDialog.selectedMultipleFiles = selectedMultipleFiles;
|
||||
infoMultipleFilesWithGcodeDialog.hasProjectFile = hasProjectFile;
|
||||
infoMultipleFilesWithGcodeDialog.fileUrls = nonGcodeFileList.slice();
|
||||
infoMultipleFilesWithGcodeDialog.projectFileUrlList = projectFileUrlList.slice();
|
||||
infoMultipleFilesWithGcodeDialog.open();
|
||||
}
|
||||
else
|
||||
{
|
||||
handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrlList, projectFileUrlList);
|
||||
}
|
||||
}
|
||||
|
||||
function handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrlList, projectFileUrlList)
|
||||
{
|
||||
// we only allow opening one project file
|
||||
if (selectedMultipleFiles && hasProjectFile)
|
||||
{
|
||||
openFilesIncludingProjectsDialog.fileUrls = fileUrlList.slice();
|
||||
openFilesIncludingProjectsDialog.show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasProjectFile)
|
||||
{
|
||||
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].slice());
|
||||
}
|
||||
else // always ask
|
||||
{
|
||||
// ask whether to open as project or as models
|
||||
askOpenAsProjectOrModelsDialog.fileUrl = projectFile;
|
||||
askOpenAsProjectOrModelsDialog.show();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
openFilesIncludingProjectsDialog.loadModelFiles(fileUrlList.slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageDialog
|
||||
{
|
||||
id: packageInstallDialog
|
||||
@ -735,51 +627,12 @@ UM.MainWindow
|
||||
modality: Qt.ApplicationModal
|
||||
}
|
||||
|
||||
MessageDialog
|
||||
{
|
||||
id: infoMultipleFilesWithGcodeDialog
|
||||
title: catalog.i18nc("@title:window", "Open File(s)")
|
||||
icon: StandardIcon.Information
|
||||
standardButtons: StandardButton.Ok
|
||||
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.")
|
||||
|
||||
property var selectedMultipleFiles
|
||||
property var hasProjectFile
|
||||
property var fileUrls
|
||||
property var projectFileUrlList
|
||||
|
||||
onAccepted:
|
||||
{
|
||||
openDialog.handleOpenFiles(selectedMultipleFiles, hasProjectFile, fileUrls, projectFileUrlList);
|
||||
}
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.Actions.open
|
||||
onTriggered: openDialog.open()
|
||||
}
|
||||
|
||||
OpenFilesIncludingProjectsDialog
|
||||
{
|
||||
id: openFilesIncludingProjectsDialog
|
||||
}
|
||||
|
||||
AskOpenAsProjectOrModelsDialog
|
||||
{
|
||||
id: askOpenAsProjectOrModelsDialog
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: CuraApplication
|
||||
onOpenProjectFile:
|
||||
{
|
||||
askOpenAsProjectOrModelsDialog.fileUrl = project_file;
|
||||
askOpenAsProjectOrModelsDialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
Connections
|
||||
{
|
||||
target: Cura.Actions.showProfileFolder
|
||||
|
Loading…
x
Reference in New Issue
Block a user