Issue #10: Local filesystem origin implementation - Add openDocumentInteractive() method to FileOrigin interface for UI-based file opening (shows file dialog) - Add saveDocumentAsInteractive() method for UI-based save as - Implement LocalFileOrigin::openDocumentInteractive() with full file dialog support, filter list building, and module handler integration - Implement LocalFileOrigin::saveDocumentAsInteractive() delegating to Gui::Document::saveAs() Issue #12: Modify Std_* commands to delegate to current origin - StdCmdNew::activated() now delegates to origin->newDocument() and sets up view orientation for the new document - StdCmdOpen::activated() delegates to origin->openDocumentInteractive() with connection state checking for authenticated origins - StdCmdSave::activated() uses document's owning origin (via findOwningOrigin) for save, falling back to saveDocumentAsInteractive if no filename - StdCmdSaveAs::activated() delegates to origin->saveDocumentAsInteractive() - Updated isActive() methods to check for active document The Std_* commands now work seamlessly with both LocalFileOrigin and SiloOrigin. When Local origin is selected, standard file dialogs appear. When Silo origin is selected, Silo's search/creation dialogs appear. Import and Export commands are left unchanged as they operate on document content rather than document lifecycle. Closes #10, Closes #12
277 lines
10 KiB
C++
277 lines
10 KiB
C++
/***************************************************************************
|
|
* 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 *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#ifndef GUI_FILEORIGIN_H
|
|
#define GUI_FILEORIGIN_H
|
|
|
|
#include <string>
|
|
#include <QIcon>
|
|
#include <FCGlobal.h>
|
|
#include <fastsignals/signal.h>
|
|
|
|
namespace App {
|
|
class Document;
|
|
}
|
|
|
|
namespace Gui {
|
|
|
|
/**
|
|
* @brief Classification of origin types
|
|
*/
|
|
enum class OriginType {
|
|
Local, ///< Local filesystem storage
|
|
PLM, ///< Product Lifecycle Management system (e.g., Silo)
|
|
Cloud, ///< Generic cloud storage
|
|
Custom ///< User-defined origin type
|
|
};
|
|
|
|
/**
|
|
* @brief Connection state for origins that require network access
|
|
*/
|
|
enum class ConnectionState {
|
|
Disconnected, ///< Not connected
|
|
Connecting, ///< Connection in progress
|
|
Connected, ///< Successfully connected
|
|
Error ///< Connection error occurred
|
|
};
|
|
|
|
/**
|
|
* @brief Abstract base class for document origin handlers
|
|
*
|
|
* FileOrigin provides an interface for different storage backends
|
|
* that can handle FreeCAD documents. Each origin defines workflows
|
|
* for creating, opening, saving, and managing documents.
|
|
*
|
|
* Key insight: Origins don't change where files are stored - all documents
|
|
* are always saved locally. Origins change the workflow and identity model:
|
|
* - Local: Document identity = file path, no external tracking
|
|
* - PLM: Document identity = database UUID, syncs with external system
|
|
*/
|
|
class GuiExport FileOrigin
|
|
{
|
|
public:
|
|
virtual ~FileOrigin() = default;
|
|
|
|
///@name Identity Methods
|
|
//@{
|
|
/** Unique identifier for this origin instance */
|
|
virtual std::string id() const = 0;
|
|
/** Display name for UI */
|
|
virtual std::string name() const = 0;
|
|
/** Short nickname for compact UI elements (e.g., toolbar) */
|
|
virtual std::string nickname() const = 0;
|
|
/** Icon for UI representation */
|
|
virtual QIcon icon() const = 0;
|
|
/** Origin type classification */
|
|
virtual OriginType type() const = 0;
|
|
//@}
|
|
|
|
///@name Workflow Characteristics
|
|
//@{
|
|
/** Whether this origin tracks documents externally (e.g., in a database) */
|
|
virtual bool tracksExternally() const = 0;
|
|
/** Whether this origin requires user authentication */
|
|
virtual bool requiresAuthentication() const = 0;
|
|
//@}
|
|
|
|
///@name Capability Queries
|
|
//@{
|
|
/** Whether this origin supports revision history */
|
|
virtual bool supportsRevisions() const { return false; }
|
|
/** Whether this origin supports Bill of Materials */
|
|
virtual bool supportsBOM() const { return false; }
|
|
/** Whether this origin supports part numbers */
|
|
virtual bool supportsPartNumbers() const { return false; }
|
|
/** Whether this origin supports assemblies natively */
|
|
virtual bool supportsAssemblies() const { return false; }
|
|
//@}
|
|
|
|
///@name Connection State
|
|
//@{
|
|
/** Get current connection state */
|
|
virtual ConnectionState connectionState() const { return ConnectionState::Connected; }
|
|
/** Attempt to connect/authenticate */
|
|
virtual bool connect() { return true; }
|
|
/** Disconnect from origin */
|
|
virtual void disconnect() {}
|
|
/** Signal emitted when connection state changes */
|
|
fastsignals::signal<void(ConnectionState)> signalConnectionStateChanged;
|
|
//@}
|
|
|
|
///@name Document Identity
|
|
//@{
|
|
/**
|
|
* Get document identity string (path for local, UUID for PLM)
|
|
* This is the immutable tracking key for the document.
|
|
* @param doc The App document to get identity for
|
|
* @return Identity string or empty if not owned by this origin
|
|
*/
|
|
virtual std::string documentIdentity(App::Document* doc) const = 0;
|
|
|
|
/**
|
|
* Get human-readable document identity (path for local, part number for PLM)
|
|
* This is for display purposes in the UI.
|
|
* @param doc The App document
|
|
* @return Display identity string or empty if not owned
|
|
*/
|
|
virtual std::string documentDisplayId(App::Document* doc) const = 0;
|
|
|
|
/**
|
|
* Check if this origin owns the given document.
|
|
* Ownership is determined by document properties, not file path.
|
|
* @param doc The document to check
|
|
* @return true if this origin owns the document
|
|
*/
|
|
virtual bool ownsDocument(App::Document* doc) const = 0;
|
|
//@}
|
|
|
|
///@name Property Synchronization
|
|
//@{
|
|
/**
|
|
* Sync document properties to the origin backend.
|
|
* For local origin this is a no-op. For PLM origins this pushes
|
|
* property changes to the database.
|
|
* @param doc The document to sync
|
|
* @return true if sync succeeded
|
|
*/
|
|
virtual bool syncProperties(App::Document* doc) { (void)doc; return true; }
|
|
//@}
|
|
|
|
///@name Core Document Operations
|
|
//@{
|
|
/**
|
|
* Create a new document managed by this origin.
|
|
* Local: Creates empty document
|
|
* PLM: Shows part creation form
|
|
* @param name Optional document name
|
|
* @return The created document or nullptr on failure
|
|
*/
|
|
virtual App::Document* newDocument(const std::string& name = "") = 0;
|
|
|
|
/**
|
|
* Open a document by identity (non-interactive).
|
|
* Local: Opens file at path
|
|
* PLM: Opens document by UUID (downloads if needed)
|
|
* @param identity Document identity (path or UUID)
|
|
* @return The opened document or nullptr on failure
|
|
*/
|
|
virtual App::Document* openDocument(const std::string& identity) = 0;
|
|
|
|
/**
|
|
* Open a document interactively (shows dialog).
|
|
* Local: Shows file picker dialog
|
|
* PLM: Shows search/browse dialog
|
|
* @return The opened document or nullptr if cancelled/failed
|
|
*/
|
|
virtual App::Document* openDocumentInteractive() = 0;
|
|
|
|
/**
|
|
* Save the document.
|
|
* Local: Saves to disk (if path known)
|
|
* PLM: Saves to disk and syncs with external system
|
|
* @param doc The document to save
|
|
* @return true if save succeeded
|
|
*/
|
|
virtual bool saveDocument(App::Document* doc) = 0;
|
|
|
|
/**
|
|
* Save document with new identity (non-interactive).
|
|
* @param doc The document to save
|
|
* @param newIdentity New identity (path or part number)
|
|
* @return true if save succeeded
|
|
*/
|
|
virtual bool saveDocumentAs(App::Document* doc, const std::string& newIdentity) = 0;
|
|
|
|
/**
|
|
* Save document interactively (shows dialog).
|
|
* Local: Shows file picker for new path
|
|
* PLM: Shows migration or copy workflow dialog
|
|
* @param doc The document to save
|
|
* @return true if save succeeded
|
|
*/
|
|
virtual bool saveDocumentAsInteractive(App::Document* doc) = 0;
|
|
//@}
|
|
|
|
///@name Extended Operations (PLM-specific, default to no-op)
|
|
//@{
|
|
/** Commit document changes to external system */
|
|
virtual bool commitDocument(App::Document* doc) { (void)doc; return false; }
|
|
/** Pull latest changes from external system */
|
|
virtual bool pullDocument(App::Document* doc) { (void)doc; return false; }
|
|
/** Push local changes to external system */
|
|
virtual bool pushDocument(App::Document* doc) { (void)doc; return false; }
|
|
/** Show document info dialog */
|
|
virtual void showInfo(App::Document* doc) { (void)doc; }
|
|
/** Show Bill of Materials dialog */
|
|
virtual void showBOM(App::Document* doc) { (void)doc; }
|
|
//@}
|
|
|
|
protected:
|
|
FileOrigin() = default;
|
|
|
|
// Non-copyable
|
|
FileOrigin(const FileOrigin&) = delete;
|
|
FileOrigin& operator=(const FileOrigin&) = delete;
|
|
};
|
|
|
|
|
|
/**
|
|
* @brief Local filesystem origin - default origin for local files
|
|
*
|
|
* This is the default origin that handles documents stored on the
|
|
* local filesystem without any external tracking or synchronization.
|
|
*/
|
|
class GuiExport LocalFileOrigin : public FileOrigin
|
|
{
|
|
public:
|
|
LocalFileOrigin();
|
|
~LocalFileOrigin() override = default;
|
|
|
|
// Identity
|
|
std::string id() const override { return "local"; }
|
|
std::string name() const override { return "Local Files"; }
|
|
std::string nickname() const override { return "Local"; }
|
|
QIcon icon() const override;
|
|
OriginType type() const override { return OriginType::Local; }
|
|
|
|
// Characteristics
|
|
bool tracksExternally() const override { return false; }
|
|
bool requiresAuthentication() const override { return false; }
|
|
|
|
// Document identity
|
|
std::string documentIdentity(App::Document* doc) const override;
|
|
std::string documentDisplayId(App::Document* doc) const override;
|
|
bool ownsDocument(App::Document* doc) const override;
|
|
|
|
// Document operations
|
|
App::Document* newDocument(const std::string& name = "") override;
|
|
App::Document* openDocument(const std::string& identity) override;
|
|
App::Document* openDocumentInteractive() override;
|
|
bool saveDocument(App::Document* doc) override;
|
|
bool saveDocumentAs(App::Document* doc, const std::string& newIdentity) override;
|
|
bool saveDocumentAsInteractive(App::Document* doc) override;
|
|
};
|
|
|
|
} // namespace Gui
|
|
|
|
#endif // GUI_FILEORIGIN_H
|