/*************************************************************************** * Copyright (c) 2025 Kindred Systems * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #include #include #include #include #include #include #include #include "FileOrigin.h" #include "Application.h" #include "BitmapFactory.h" #include "Document.h" #include "FileDialog.h" #include "MainWindow.h" namespace Gui { // Property name used by PLM origins (Silo) to mark tracked documents static const char* SILO_ITEM_ID_PROP = "SiloItemId"; //=========================================================================== // LocalFileOrigin //=========================================================================== LocalFileOrigin::LocalFileOrigin() { } QIcon LocalFileOrigin::icon() const { return BitmapFactory().iconFromTheme("document-new"); } std::string LocalFileOrigin::documentIdentity(App::Document* doc) const { if (!doc || !ownsDocument(doc)) { return {}; } return doc->FileName.getValue(); } std::string LocalFileOrigin::documentDisplayId(App::Document* doc) const { // For local files, identity and display ID are the same (file path) return documentIdentity(doc); } bool LocalFileOrigin::ownsDocument(App::Document* doc) const { if (!doc) { return false; } // Local origin owns documents that do NOT have PLM tracking properties. // Check all objects for SiloItemId property - if any have it, // this document is owned by a PLM origin, not local. for (auto* obj : doc->getObjects()) { if (obj->getPropertyByName(SILO_ITEM_ID_PROP)) { return false; } } return true; } App::Document* LocalFileOrigin::newDocument(const std::string& name) { std::string docName = name.empty() ? "Unnamed" : name; return App::GetApplication().newDocument(docName.c_str(), docName.c_str()); } App::Document* LocalFileOrigin::openDocument(const std::string& identity) { if (identity.empty()) { return nullptr; } return App::GetApplication().openDocument(identity.c_str()); } App::Document* LocalFileOrigin::openDocumentInteractive() { // Build file filter list for Open dialog QString formatList; const char* supported = QT_TR_NOOP("Supported formats"); const char* allFiles = QT_TR_NOOP("All files (*.*)"); formatList = QObject::tr(supported); formatList += QLatin1String(" ("); std::vector filetypes = App::GetApplication().getImportTypes(); // Make sure FCStd is the very first fileformat auto it = std::find(filetypes.begin(), filetypes.end(), "FCStd"); if (it != filetypes.end()) { filetypes.erase(it); filetypes.insert(filetypes.begin(), "FCStd"); } for (it = filetypes.begin(); it != filetypes.end(); ++it) { formatList += QLatin1String(" *."); formatList += QLatin1String(it->c_str()); } formatList += QLatin1String(");;"); std::map FilterList = App::GetApplication().getImportFilters(); // Make sure the format name for FCStd is the very first in the list for (auto jt = FilterList.begin(); jt != FilterList.end(); ++jt) { if (jt->first.find("*.FCStd") != std::string::npos) { formatList += QLatin1String(jt->first.c_str()); formatList += QLatin1String(";;"); FilterList.erase(jt); break; } } for (const auto& filter : FilterList) { formatList += QLatin1String(filter.first.c_str()); formatList += QLatin1String(";;"); } formatList += QObject::tr(allFiles); QString selectedFilter; QStringList fileList = FileDialog::getOpenFileNames( getMainWindow(), QObject::tr("Open Document"), QString(), formatList, &selectedFilter ); if (fileList.isEmpty()) { return nullptr; } // Load the files with the associated modules SelectModule::Dict dict = SelectModule::importHandler(fileList, selectedFilter); if (dict.isEmpty()) { QMessageBox::critical( getMainWindow(), qApp->translate("StdCmdOpen", "Cannot Open File"), qApp->translate("StdCmdOpen", "Loading the file %1 is not supported").arg(fileList.front()) ); return nullptr; } App::Document* lastDoc = nullptr; for (SelectModule::Dict::iterator it = dict.begin(); it != dict.end(); ++it) { // Set flag indicating that this load/restore has been initiated by the user Application::Instance->setStatus(Gui::Application::UserInitiatedOpenDocument, true); Application::Instance->open(it.key().toUtf8(), it.value().toLatin1()); Application::Instance->setStatus(Gui::Application::UserInitiatedOpenDocument, false); lastDoc = App::GetApplication().getActiveDocument(); Application::Instance->checkPartialRestore(lastDoc); Application::Instance->checkRestoreError(lastDoc); } return lastDoc; } bool LocalFileOrigin::saveDocument(App::Document* doc) { if (!doc) { return false; } // If document has never been saved, we need a path const char* fileName = doc->FileName.getValue(); if (!fileName || fileName[0] == '\0') { // No file name set - would need UI interaction for Save As // This will be handled by the command layer return false; } return doc->save(); } bool LocalFileOrigin::saveDocumentAs(App::Document* doc, const std::string& newIdentity) { if (!doc || newIdentity.empty()) { return false; } return doc->saveAs(newIdentity.c_str()); } bool LocalFileOrigin::saveDocumentAsInteractive(App::Document* doc) { if (!doc) { return false; } // Get Gui document for save dialog Gui::Document* guiDoc = Application::Instance->getDocument(doc); if (!guiDoc) { return false; } // Use Gui::Document::saveAs() which handles the file dialog return guiDoc->saveAs(); } } // namespace Gui