mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-12 02:38:59 +08:00
Revert making the open file dialog a separate LocalFileProvider plugin
This reverts commits 00de7497a4c2986cf8fd13be8f598a0f615f3d63 to 5f6b3b52c1848416c98f7d276fe02f08d067f675 CURA-7868
This commit is contained in:
parent
606ec587fe
commit
96c4d66029
@ -1,47 +0,0 @@
|
|||||||
# 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()
|
|
@ -1,171 +0,0 @@
|
|||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
# 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() }
|
|
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"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"
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2021 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.7
|
import QtQuick 2.7
|
||||||
@ -96,7 +96,7 @@ Item
|
|||||||
id: openFileButton
|
id: openFileButton
|
||||||
height: UM.Theme.getSize("stage_menu").height
|
height: UM.Theme.getSize("stage_menu").height
|
||||||
width: UM.Theme.getSize("stage_menu").height
|
width: UM.Theme.getSize("stage_menu").height
|
||||||
onClicked: CuraApplication.getFileProviderModel().triggerFirst()
|
onClicked: Cura.Actions.open.trigger()
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
|
||||||
contentItem: Item
|
contentItem: Item
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2021 Ultimaker B.V.
|
// Copyright (c) 2018 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
pragma Singleton
|
pragma Singleton
|
||||||
@ -12,6 +12,7 @@ import Cura 1.0 as Cura
|
|||||||
Item
|
Item
|
||||||
{
|
{
|
||||||
property alias newProject: newProjectAction;
|
property alias newProject: newProjectAction;
|
||||||
|
property alias open: openAction;
|
||||||
property alias quit: quitAction;
|
property alias quit: quitAction;
|
||||||
|
|
||||||
property alias undo: undoAction;
|
property alias undo: undoAction;
|
||||||
@ -412,6 +413,14 @@ Item
|
|||||||
onTriggered: CuraApplication.resetAll();
|
onTriggered: CuraApplication.resetAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Action
|
||||||
|
{
|
||||||
|
id: openAction;
|
||||||
|
text: catalog.i18nc("@action:inmenu menubar:file","&Open File(s)...");
|
||||||
|
iconName: "document-open";
|
||||||
|
shortcut: StandardKey.Open;
|
||||||
|
}
|
||||||
|
|
||||||
Action
|
Action
|
||||||
{
|
{
|
||||||
id: newProjectAction
|
id: newProjectAction
|
||||||
|
@ -619,6 +619,114 @@ UM.MainWindow
|
|||||||
onTriggered: base.exitFullscreen()
|
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
|
MessageDialog
|
||||||
{
|
{
|
||||||
id: packageInstallDialog
|
id: packageInstallDialog
|
||||||
@ -627,6 +735,51 @@ UM.MainWindow
|
|||||||
modality: Qt.ApplicationModal
|
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
|
Connections
|
||||||
{
|
{
|
||||||
target: Cura.Actions.showProfileFolder
|
target: Cura.Actions.showProfileFolder
|
||||||
|
@ -22,7 +22,7 @@ Menu
|
|||||||
MenuItem
|
MenuItem
|
||||||
{
|
{
|
||||||
id: openMenu
|
id: openMenu
|
||||||
onTriggered: CuraApplication.getFileProviderModel().triggerFirst()
|
action: Cura.Actions.open
|
||||||
visible: (base.fileProviderModel.count == 1)
|
visible: (base.fileProviderModel.count == 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2021 Ultimaker B.V.
|
// Copyright (c) 2020 Ultimaker B.V.
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.2
|
||||||
@ -21,8 +21,21 @@ Menu
|
|||||||
model: CuraApplication.getFileProviderModel()
|
model: CuraApplication.getFileProviderModel()
|
||||||
MenuItem
|
MenuItem
|
||||||
{
|
{
|
||||||
text: model.displayText
|
text:
|
||||||
onTriggered: CuraApplication.getFileProviderModel().trigger(model.name)
|
{
|
||||||
|
return model.displayText;
|
||||||
|
}
|
||||||
|
onTriggered:
|
||||||
|
{
|
||||||
|
if (model.index == 0) // The 0th element is the "From Disk" option, which should activate the open local file dialog
|
||||||
|
{
|
||||||
|
Cura.Actions.open.trigger()
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CuraApplication.getFileProviderModel().trigger(model.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
shortcut: model.shortcut
|
shortcut: model.shortcut
|
||||||
}
|
}
|
||||||
onObjectAdded: openFilesMenu.insertItem(index, object)
|
onObjectAdded: openFilesMenu.insertItem(index, object)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user