1 /*
2 * fileformat.h
3 * Copyright 2008-2015, Thorbjørn Lindeijer <bjorn@lindeijer.nl>
4 *
5 * This file is part of libtiled.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 * EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #pragma once
30
31 #include "pluginmanager.h"
32
33 #include <QObject>
34
35
36 namespace Tiled {
37
38
39 class TILEDSHARED_EXPORT FileFormat : public QObject
40 {
41 Q_OBJECT
42
43 public:
44 enum Capability {
45 NoCapability = 0x0,
46 Read = 0x1,
47 Write = 0x2,
48 ReadWrite = Read | Write
49 };
50 Q_DECLARE_FLAGS(Capabilities, Capability)
51
52 enum Option {
53 WriteMinimized = 0x1,
54 };
55 Q_DECLARE_FLAGS(Options, Option)
56
57 explicit FileFormat(QObject *parent = nullptr);
58
59 /**
60 * Returns whether this format has Read and/or Write capabilities.
61 */
62 virtual Capabilities capabilities() const;
63
64 /**
65 * Returns whether this format has all given capabilities.
66 */
67 bool hasCapabilities(Capabilities caps) const;
68
69 /**
70 * Returns name filter for files in this map format.
71 */
72 virtual QString nameFilter() const = 0;
73
74 /**
75 * Returns short name for this map format
76 */
77 virtual QString shortName() const = 0;
78
79 /**
80 * Returns whether this map format supports reading the given file.
81 *
82 * Generally would do a file extension check.
83 */
84 virtual bool supportsFile(const QString &fileName) const = 0;
85
86 /**
87 * Returns the error to be shown to the user if an error occurred while
88 * trying to read or write a file.
89 */
90 virtual QString errorString() const = 0;
91 };
92
93 } // namespace Tiled
94
95 Q_DECLARE_INTERFACE(Tiled::FileFormat, "org.mapeditor.FileFormat")
Q_DECLARE_OPERATORS_FOR_FLAGS(Tiled::FileFormat::Capabilities)96 Q_DECLARE_OPERATORS_FOR_FLAGS(Tiled::FileFormat::Capabilities)
97 Q_DECLARE_OPERATORS_FOR_FLAGS(Tiled::FileFormat::Options)
98
99 namespace Tiled {
100
101 /**
102 * Convenience class that can be used when implementing file dialogs.
103 */
104 template<typename Format>
105 class FormatHelper
106 {
107 public:
108 FormatHelper(FileFormat::Capabilities capabilities,
109 QString initialFilter = QString())
110 : mFilter(std::move(initialFilter))
111 {
112 PluginManager::each<Format>([this,capabilities](Format *format) {
113 if (format->hasCapabilities(capabilities)) {
114 const QString nameFilter = format->nameFilter();
115
116 if (!mFilter.isEmpty())
117 mFilter += QStringLiteral(";;");
118 mFilter += nameFilter;
119
120 mFormats.append(format);
121 mFormatByNameFilter.insert(nameFilter, format);
122 }
123 });
124 }
125
126 const QString &filter() const
127 { return mFilter; }
128
129 const QList<Format*> &formats() const
130 { return mFormats; }
131
132 Format *findFormat(const QString &shortName) const
133 {
134 auto it = std::find_if(mFormats.begin(),
135 mFormats.end(),
136 [&] (Format *format) { return format->shortName() == shortName; });
137 return it != mFormats.end() ? *it : nullptr;
138 }
139
140 Format *formatByNameFilter(const QString &nameFilter) const
141 { return mFormatByNameFilter.value(nameFilter); }
142
143 private:
144 QString mFilter;
145 QList<Format*> mFormats;
146 QMap<QString, Format*> mFormatByNameFilter;
147 };
148
149 template<typename Format>
150 Format *findFileFormat(const QString &shortName, FileFormat::Capabilities capabilities = FileFormat::Write)
151 {
152 if (shortName.isEmpty())
153 return nullptr;
154
155 return PluginManager::find<Format>([&](Format *format) {
156 return format->hasCapabilities(capabilities) && format->shortName() == shortName;
157 });
158 }
159
160 } // namespace Tiled
161