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