1 /****************************************************************************************
2 * Copyright (c) 2014 Ralf Engels <ralf-engels@gmx.de> *
3 * *
4 * This program is free software; you can redistribute it and/or modify it under *
5 * the terms of the GNU General Public License as published by the Free Software *
6 * Foundation; either version 2 of the License, or (at your option) any later *
7 * version. *
8 * *
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY *
10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
11 * PARTICULAR PURPOSE. See the GNU General Public License for more details. *
12 * *
13 * You should have received a copy of the GNU General Public License along with *
14 * this program. If not, see <http://www.gnu.org/licenses/>. *
15 ****************************************************************************************/
16
17 #define DEBUG_PREFIX "StorageManager"
18
19 #include "StorageManager.h"
20
21 #include <core/storage/SqlStorage.h>
22 #include <core/storage/StorageFactory.h>
23
24 #include <core/support/Amarok.h>
25 #include <core/support/Debug.h>
26
27 #include <KConfigGroup>
28 #include <KLocalizedString>
29
30 /** A SqlStorage that doesn't do anything.
31 *
32 * An object of this type is used whenever we couldn't
33 * load a better SqlStorage.
34 *
35 * The reason is that plugins don't have to check for
36 * a null pointer as SqlStorage every time.
37 */
38 class EmptySqlStorage : public SqlStorage
39 {
40 public:
EmptySqlStorage()41 EmptySqlStorage() {}
~EmptySqlStorage()42 ~EmptySqlStorage() override {}
43
sqlDatabasePriority() const44 virtual int sqlDatabasePriority() const
45 { return 10; }
46
type() const47 virtual QString type() const { return QStringLiteral("Empty"); }
48
escape(const QString & text) const49 QString escape( const QString &text) const override { return text; }
50
query(const QString &)51 QStringList query( const QString &) override { return QStringList(); }
insert(const QString &,const QString &)52 int insert( const QString &, const QString &) override { return 0; }
53
boolTrue() const54 QString boolTrue() const override { return QString(); }
boolFalse() const55 QString boolFalse() const override { return QString(); }
56
idType() const57 QString idType() const override { return QString(); }
textColumnType(int) const58 QString textColumnType( int ) const override { return QString(); }
exactTextColumnType(int) const59 QString exactTextColumnType( int ) const override { return QString(); }
60
exactIndexableTextColumnType(int) const61 QString exactIndexableTextColumnType( int ) const override { return QString(); }
longTextColumnType() const62 QString longTextColumnType() const override { return QString(); }
randomFunc() const63 QString randomFunc() const override { return QString(); }
64
getLastErrors() const65 QStringList getLastErrors() const override { return QStringList(); }
66
67 /** Clears the list of the last errors. */
clearLastErrors()68 void clearLastErrors() override { }
69 };
70
71
72 struct StorageManager::Private
73 {
74 QSharedPointer<SqlStorage> sqlDatabase;
75
76 /** A list that collects errors from database plugins
77 *
78 * StoragePlugin factories can report errors that
79 * prevent the storage from even being created.
80 *
81 * This list collects them.
82 */
83 QStringList errorList;
84 };
85
86 StorageManager *StorageManager::s_instance = nullptr;
87
88
89 StorageManager *
instance()90 StorageManager::instance()
91 {
92 if( !s_instance ) {
93 s_instance = new StorageManager();
94 s_instance->init();
95 }
96
97 return s_instance;
98 }
99
100 void
destroy()101 StorageManager::destroy()
102 {
103 if( s_instance ) {
104 delete s_instance;
105 s_instance = nullptr;
106 }
107 }
108
StorageManager()109 StorageManager::StorageManager()
110 : QObject()
111 , d( new Private )
112 {
113 DEBUG_BLOCK
114
115 setObjectName( QStringLiteral("StorageManager") );
116 qRegisterMetaType<SqlStorage *>( "SqlStorage*" );
117 d->sqlDatabase = QSharedPointer<SqlStorage>( new EmptySqlStorage );
118 }
119
~StorageManager()120 StorageManager::~StorageManager()
121 {
122 DEBUG_BLOCK
123
124 delete d;
125 }
126
127 QSharedPointer<SqlStorage>
sqlStorage() const128 StorageManager::sqlStorage() const
129 {
130 return d->sqlDatabase;
131 }
132
133 void
init()134 StorageManager::init()
135 {
136 }
137
138 void
setFactories(const QList<QSharedPointer<Plugins::PluginFactory>> & factories)139 StorageManager::setFactories( const QList<QSharedPointer<Plugins::PluginFactory> > &factories )
140 {
141 for( const auto &pFactory : factories )
142 {
143 auto factory = qobject_cast<StorageFactory*>( pFactory );
144 if( !factory )
145 continue;
146
147 connect( factory.data(), &StorageFactory::newStorage,
148 this, &StorageManager::slotNewStorage );
149 connect( factory.data(), &StorageFactory::newError,
150 this, &StorageManager::slotNewError );
151 }
152 }
153
154 QStringList
getLastErrors() const155 StorageManager::getLastErrors() const
156 {
157 if( !d->errorList.isEmpty() )
158 return d->errorList;
159 if( d->sqlDatabase.dynamicCast<EmptySqlStorage>() )
160 {
161 QStringList list;
162 list << i18n( "The configured database plugin could not be loaded." );
163 return list;
164 }
165 return d->errorList;
166 }
167
168 void
clearLastErrors()169 StorageManager::clearLastErrors()
170 {
171 d->errorList.clear();
172 }
173
174 void
slotNewStorage(QSharedPointer<SqlStorage> newStorage)175 StorageManager::slotNewStorage( QSharedPointer<SqlStorage> newStorage )
176 {
177 DEBUG_BLOCK
178
179 if( !newStorage )
180 {
181 warning() << "Warning, newStorage in slotNewStorage is 0";
182 return;
183 }
184
185 if( d->sqlDatabase && !d->sqlDatabase.dynamicCast<EmptySqlStorage>() )
186 {
187 warning() << "Warning, newStorage when we already have a storage";
188 return; // once we have the database set we can't change it since
189 // plugins might have already created their tables in the old database
190 // or caching data from it.
191 }
192
193 d->sqlDatabase = newStorage;
194 }
195
196 void
slotNewError(const QStringList & errorMessageList)197 StorageManager::slotNewError( const QStringList &errorMessageList )
198 {
199 d->errorList << errorMessageList;
200 }
201
202
203