File indexing completed on 2024-05-19 04:07:53

0001 /*
0002     SPDX-FileCopyrightText: 2011 Stefan Majewsky <majewsky@gmx.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef PALAPELI_PUZZLE_H
0008 #define PALAPELI_PUZZLE_H
0009 
0010 #include <QObject>
0011 #include <QMetaType>
0012 
0013 #include <iostream>
0014 #define CAST_ERROR(x) std::cerr << qPrintable(x) << std::endl; //TODO: these errors should be reported to Puzzle
0015 
0016 namespace Palapeli
0017 {
0018     class Puzzle;
0019 
0020     class PuzzleComponent
0021     {
0022         public:
0023             enum Type
0024             {
0025                 //data components
0026                 Metadata = 0,        ///< Palapeli::MetadataComponent
0027                 Contents,            ///< Palapeli::ContentsComponent
0028                 CreationContext,     ///< Palapeli::CreationContextComponent
0029                 //storage components
0030                 Copy,                ///< Palapeli::CopyComponent
0031                 DirectoryStorage,    ///< Palapeli::DirectoryStorageComponent
0032                 ArchiveStorage,      ///< Palapeli::ArchiveStorageComponent
0033                 CollectionStorage,   ///< Palapeli::CollectionStorageComponent
0034                 RetailStorage        ///< Palapeli::RetailStorageComponent
0035             };
0036 
0037             PuzzleComponent();
0038             virtual ~PuzzleComponent();
0039 
0040             virtual Type type() const = 0;
0041             Palapeli::Puzzle* puzzle() const;
0042             ///This method will be called in worker threads to create a new
0043             ///component of the given @a type from the information in this
0044             ///component. 0 is a useful result if the cast is not possible
0045             ///for semantical reasons (e.g. cannot infer contents from
0046             ///metadata) or technical reasons (e.g. puzzle file corrupted).
0047             ///
0048             ///The default implementation represents a non-castable
0049             ///component and returns 0 for any type.
0050             virtual Palapeli::PuzzleComponent* cast(Type type) const;
0051         private:
0052             friend class Palapeli::Puzzle;
0053             Palapeli::Puzzle* m_puzzle;
0054     };
0055 
0056     class Puzzle : public QObject
0057     {
0058         Q_OBJECT
0059         public:
0060             ///Takes ownership of @a mainComponent.
0061             Puzzle(Palapeli::PuzzleComponent* mainComponent, const QString& location, const QString& identifier);
0062             ~Puzzle() override;
0063 
0064             ///Returns an identifier for use with puzzles loaded from the file
0065             ///system. Rationale: The identifier must be unique during the
0066             ///session, but should also be the same for the same puzzle over
0067             ///the course of multiple sessions (in order to store savegames).
0068             static QString fsIdentifier(const QString& location);
0069 
0070             ///Returns the component for the given @a type, or 0 if this
0071             ///component is not available. Access to the component storage is
0072             ///not memory-ordered or anything. If you need a thread-safe
0073             ///interface, use get() instead.
0074             const Palapeli::PuzzleComponent* component(Palapeli::PuzzleComponent::Type type) const;
0075             ///@overload plus casting; same restrictions apply
0076             template <typename T> const T* component() const
0077             {
0078                 return dynamic_cast<const T*>(component((Palapeli::PuzzleComponent::Type) T::ComponentType));
0079             }
0080             ///Requests that the given component @a type is made available.
0081             const Palapeli::PuzzleComponent *get(Palapeli::PuzzleComponent::Type type);
0082 
0083             QString identifier() const;
0084             QString location() const;
0085             void setLocation(const QString& location);
0086 
0087             ///Deletes the component with the given @a type from this puzzle.
0088             ///Because the component might be in use elsewhere in the program,
0089             ///this operation is highly dangerous, but it's nonetheless required
0090             ///for the ContentsComponent because that one keeps very much data
0091             ///in memory.
0092             void dropComponent(Palapeli::PuzzleComponent::Type type);
0093         private:
0094             struct Private;
0095             Private* const d;
0096     };
0097 }
0098 
0099 Q_DECLARE_METATYPE(Palapeli::Puzzle*)
0100 
0101 #endif // PALAPELI_PUZZLE_H