Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | // This file is part of Pate, Kate' Python scripting plugin. |
---|---|
2 | // |
3 | // Copyright (C) 2006 Paul Giannaros <paul@giannaros.org> |
4 | // Copyright (C) 2012, 2013 Shaheed Haque <srhaque@theiet.org> |
5 | // Copyright (C) 2013 Alex Turbov <i.zaufi@gmail.com> |
6 | // |
7 | // This library is free software; you can redistribute it and/or |
8 | // modify it under the terms of the GNU Lesser General Public |
9 | // License as published by the Free Software Foundation; either |
10 | // version 2.1 of the License, or (at your option) version 3, or any |
11 | // later version accepted by the membership of KDE e.V. (or its |
12 | // successor approved by the membership of KDE e.V.), which shall |
13 | // act as a proxy defined in Section 6 of version 3 of the license. |
14 | // |
15 | // This library is distributed in the hope that it will be useful, |
16 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 | // Lesser General Public License for more details. |
19 | // |
20 | // You should have received a copy of the GNU Lesser General Public |
21 | // License along with this library. If not, see <http://www.gnu.org/licenses/>. |
22 | // |
23 | |
24 | #ifndef __PATE_ENGINE_H__ |
25 | # define __PATE_ENGINE_H__ |
26 | |
27 | # include "version_checker.h" |
28 | |
29 | # include <KService> |
30 | # include <KUrl> |
31 | # include <Python.h> |
32 | # include <QAbstractItemModel> |
33 | # include <QList> |
34 | # include <QStringList> |
35 | |
36 | namespace Pate { |
37 | class Python; // fwd decl |
38 | |
39 | /** |
40 | * The Engine class hosts the Python interpreter, loading |
41 | * it into memory within Kate, and then with finding and |
42 | * loading all of the Pate plugins. |
43 | * |
44 | * \attention Qt/KDE do not use exceptions (unfortunately), |
45 | * so this class must be initialized in two steps: |
46 | * - create an instance (via constructor) |
47 | * - try to initialize the rest (via \c Engine::tryInitializeGetFailureReason()) |
48 | * If latter returns a non empty (failure reason) string, the only member |
49 | * can be called is conversion to boolean! (which is implemented as safe-bool idiom [1]) |
50 | * Calling others leads to UB! |
51 | * |
52 | * \sa [1] http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool |
53 | */ |
54 | class Engine : public QAbstractItemModel |
55 | { |
56 | Q_OBJECT |
57 | |
58 | typedef void (Engine::*bool_type)() const; |
59 | void unspecified_true_bool_type() const {} |
60 | |
61 | public: |
62 | /// \todo Turn into a class w/ accessors |
63 | class PluginState |
64 | { |
65 | public: |
66 | /// \name Immutable accessors |
67 | //@{ |
68 | QString pythonModuleName() const; |
69 | const QString& errorReason() const; |
70 | bool isEnabled() const; |
71 | bool isBroken() const; |
72 | bool isUnstable() const; |
73 | //@} |
74 | |
75 | private: |
76 | friend class Engine; |
77 | |
78 | PluginState(); |
79 | /// Transfort Python module name into a file path part |
80 | QString moduleFilePathPart() const; |
81 | |
82 | KService::Ptr m_service; |
83 | QString m_pythonModule; |
84 | QString m_errorReason; |
85 | bool m_enabled; |
86 | bool m_broken; |
87 | bool m_unstable; |
88 | bool m_isDir; |
89 | }; |
90 | |
91 | /// Default constructor: initialize Python interpreter |
92 | Engine(); |
93 | /// Cleanup everything on unload |
94 | ~Engine(); |
95 | |
96 | //BEGIN QAbstractItemModel interface |
97 | virtual int columnCount(const QModelIndex&) const /*override*/; |
98 | virtual int rowCount(const QModelIndex&) const /*override*/; |
99 | virtual QModelIndex index(int, int, const QModelIndex&) const /*override*/; |
100 | virtual QModelIndex parent(const QModelIndex&) const /*override*/; |
101 | virtual QVariant headerData(int, Qt::Orientation, int) const /*override*/; |
102 | virtual QVariant data(const QModelIndex&, int) const /*override*/; |
103 | virtual Qt::ItemFlags flags(const QModelIndex&) const /*override*/; |
104 | virtual bool setData(const QModelIndex&, const QVariant&, int) /*override*/; |
105 | //END QAbstractItemModel interface |
106 | |
107 | void readSessionPluginsConfiguration(KConfigBase*); |
108 | void writeSessionPluginsConfiguration(KConfigBase*); |
109 | |
110 | void setEnabledPlugins(const QStringList&); ///< Set enabled plugins to the model |
111 | void tryLoadEnabledPlugins(); ///< Try to load enabled plugins |
112 | QStringList enabledPlugins() const; ///< Form a list of enabled plugins |
113 | const QList<PluginState>& plugins() const; ///< Provide immutable access to found plugins |
114 | QString tryInitializeGetFailureReason(); ///< Try to initialize Python interpreter |
115 | operator bool_type() const; ///< Check if instance is usable |
116 | void setBroken(); ///< Make it broken by some external reason |
117 | |
118 | public Q_SLOTS: |
119 | void readGlobalPluginsConfiguration(); ///< Load plugins' configuration. |
120 | void saveGlobalPluginsConfiguration(); ///< Write out plugins' configuration. |
121 | void unloadAllModules(); |
122 | |
123 | protected: |
124 | void scanPlugins(); ///< Search for available plugins |
125 | void loadModule(int); ///< Load module by index in \c m_plugins |
126 | void unloadModule(int); ///< Unload module by index in \c m_plugins |
127 | |
128 | private: |
129 | // Simulate strong typed enums from C++11 |
130 | struct Column |
131 | { |
132 | enum type |
133 | { |
134 | NAME |
135 | , COMMENT |
136 | , LAST__ |
137 | }; |
138 | }; |
139 | |
140 | static bool isServiceUsable(const KService::Ptr&); ///< Make sure that service is usable |
141 | static bool setModuleProperties(PluginState&); |
142 | static void verifyDependenciesSetStatus(PluginState&); |
143 | static QPair<QString, version_checker> parseDependency(const QString&); |
144 | static version tryObtainVersionFromTuple(PyObject*); |
145 | static version tryObtainVersionFromString(PyObject*); |
146 | |
147 | PyObject* m_configuration; ///< Application-wide configuration data |
148 | PyObject* m_sessionConfiguration; ///< Session-wide configuration data |
149 | QList<PluginState> m_plugins; ///< List of available plugins |
150 | bool m_engineIsUsable; ///< Is engine loaded Ok? |
151 | }; |
152 | |
153 | inline QString Engine::PluginState::pythonModuleName() const |
154 | { |
155 | return m_service->library(); |
156 | } |
157 | inline QString Pate::Engine::PluginState::moduleFilePathPart() const |
158 | { |
159 | /// \todo Use \c QString::split() and \c KUrl to form a valid path |
160 | return m_service->library().replace(".", "/"); |
161 | } |
162 | inline const QString& Engine::PluginState::errorReason() const |
163 | { |
164 | return m_errorReason; |
165 | } |
166 | inline bool Engine::PluginState::isEnabled() const |
167 | { |
168 | return m_enabled; |
169 | } |
170 | inline bool Engine::PluginState::isBroken() const |
171 | { |
172 | return m_broken; |
173 | } |
174 | inline bool Engine::PluginState::isUnstable() const |
175 | { |
176 | return m_unstable; |
177 | } |
178 | |
179 | inline const QList<Engine::PluginState>& Engine::plugins() const |
180 | { |
181 | return m_plugins; |
182 | } |
183 | |
184 | inline Engine::operator bool_type() const |
185 | { |
186 | return m_engineIsUsable ? &Engine::unspecified_true_bool_type : 0; |
187 | } |
188 | |
189 | inline void Engine::setBroken() |
190 | { |
191 | m_engineIsUsable = false; |
192 | } |
193 | |
194 | } // namespace Pate |
195 | #endif // __PATE_ENGINE_H__ |
196 | // kate: indent-width 4; |
197 |
Warning: That file was not part of the compilation database. It may have many parsing errors.