File indexing completed on 2024-12-22 03:35:51
0001 /* 0002 File : ProjectParser.h 0003 Project : LabPlot 0004 Description : base class for project parsers 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2017-2024 Alexander Semke <alexander.semke@web.de> 0007 SPDX-FileCopyrightText: 2019 Stefan Gerlach <stefan.gerlach@uni.kn> 0008 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 #include "ProjectParser.h" 0012 #include "backend/core/AspectTreeModel.h" 0013 #include "backend/core/Project.h" 0014 #include "backend/core/column/Column.h" 0015 #include "backend/lib/trace.h" 0016 0017 #include <KLocalizedString> 0018 0019 /*! 0020 \class ProjectParser 0021 \brief base class for project parsers 0022 0023 \ingroup datasources 0024 */ 0025 ProjectParser::ProjectParser() 0026 : QObject() { 0027 } 0028 0029 ProjectParser::~ProjectParser() { 0030 delete m_previewProject; 0031 } 0032 0033 void ProjectParser::setProjectFileName(const QString& name) { 0034 m_projectFileName = name; 0035 0036 // delete the previous project used to generate the preview 0037 delete m_previewProject; 0038 m_previewProject = nullptr; 0039 } 0040 0041 const QString& ProjectParser::projectFileName() const { 0042 return m_projectFileName; 0043 } 0044 0045 QList<AspectType> ProjectParser::topLevelClasses() const { 0046 return m_topLevelClasses; 0047 } 0048 0049 /*! 0050 * returns the model containing the structure of the current project used for the preview in the import project dialog. 0051 * The caller takes over the ownership of the model. 0052 */ 0053 QAbstractItemModel* ProjectParser::model() { 0054 WAIT_CURSOR; 0055 PERFTRACE(QStringLiteral("project model for preview created")); 0056 delete m_previewProject; 0057 m_previewProject = new Project(); 0058 0059 bool rc = load(m_previewProject, true); 0060 AspectTreeModel* model = nullptr; 0061 if (rc) { 0062 model = new AspectTreeModel(m_previewProject); 0063 model->setReadOnly(true); 0064 } 0065 0066 RESET_CURSOR; 0067 return model; 0068 } 0069 0070 void ProjectParser::importTo(Folder* targetFolder, const QStringList& selectedPathes) { 0071 DEBUG(Q_FUNC_INFO << ", starting import of " << STDSTRING(m_projectFileName)); 0072 QDEBUG(Q_FUNC_INFO << ", selected pathes: " << selectedPathes); 0073 0074 // import the selected objects into a temporary project 0075 auto* project = new Project(); 0076 project->setPathesToLoad(selectedPathes); 0077 bool rc = load(project, false); 0078 if (!rc) { 0079 delete project; 0080 DEBUG(Q_FUNC_INFO << ", ERROR: import of " << STDSTRING(m_projectFileName) << " failed."); 0081 return; 0082 } 0083 0084 // determine the first child of the last top level child in the list of the imported objects 0085 // we want to navigate to in the project explorer after the import 0086 auto* lastTopLevelChild = project->child<AbstractAspect>(project->childCount<AbstractAspect>() - 1); 0087 AbstractAspect* childToNavigate = nullptr; 0088 if (lastTopLevelChild && lastTopLevelChild->childCount<AbstractAspect>() > 0) { 0089 childToNavigate = lastTopLevelChild->child<AbstractAspect>(0); 0090 0091 // we don't want to select columns, select rather their parent spreadsheet 0092 if (dynamic_cast<const Column*>(childToNavigate)) 0093 childToNavigate = lastTopLevelChild; 0094 } else { 0095 childToNavigate = lastTopLevelChild; 0096 } 0097 0098 // move all children from the temp project to the target folder 0099 targetFolder->beginMacro(i18n("%1: Import from %2", targetFolder->name(), m_projectFileName)); 0100 for (auto* child : project->children<AbstractAspect>()) { 0101 auto* folder = dynamic_cast<Folder*>(child); 0102 if (folder) 0103 moveFolder(targetFolder, folder); 0104 else if (child) { 0105 project->removeChild(child); 0106 0107 // remove the object to be imported in the target folder if it already exists 0108 auto* targetChild = targetFolder->child<AbstractAspect>(child->name()); 0109 if (targetChild) 0110 targetFolder->removeChild(targetChild); 0111 0112 targetFolder->addChild(child); 0113 } 0114 } 0115 targetFolder->setName(project->name()); 0116 targetFolder->endMacro(); 0117 0118 Project::restorePointers(targetFolder); 0119 Project::retransformElements(targetFolder); 0120 0121 delete project; 0122 0123 if (childToNavigate != nullptr) 0124 targetFolder->project()->navigateTo(childToNavigate->path()); 0125 0126 DEBUG(Q_FUNC_INFO << ", import of " << STDSTRING(m_projectFileName) << " DONE"); 0127 } 0128 0129 /* 0130 * moved \c sourceChildFolderToMove from its parent folder to \c targetParentFolder 0131 * keeping (not overwriting) the sub-folder structure. 0132 */ 0133 void ProjectParser::moveFolder(Folder* targetParentFolder, Folder* sourceChildFolderToMove) const { 0134 auto* targetChildFolder = targetParentFolder->child<Folder>(sourceChildFolderToMove->name()); 0135 if (targetChildFolder) { 0136 // folder exists already in the target parent folder, 0137 //-> recursively move its children from source into target parent folder 0138 for (auto* child : sourceChildFolderToMove->children<AbstractAspect>()) { 0139 auto* folder = dynamic_cast<Folder*>(child); 0140 if (folder) { 0141 moveFolder(targetChildFolder, folder); 0142 } else if (child) { 0143 sourceChildFolderToMove->removeChild(child); 0144 0145 // remove the object to be imported in the target folder if it's already existing 0146 auto* targetChild = targetChildFolder->child<AbstractAspect>(child->name()); 0147 if (targetChild) 0148 targetChildFolder->removeChild(targetChild); 0149 0150 targetChildFolder->addChild(child); 0151 } 0152 } 0153 } else { 0154 // folder doesn't exist yet in the target parent folder -> simply move it 0155 auto* sourceParentFolder = dynamic_cast<Folder*>(sourceChildFolderToMove->parentAspect()); 0156 if (sourceParentFolder) 0157 sourceParentFolder->removeChild(sourceChildFolderToMove); 0158 targetParentFolder->addChild(sourceChildFolderToMove); 0159 } 0160 }