on f063450 help sign in
unity8/plugins/IndicatorsClient/indicatorsmanager.cpp
290 lines 8.0 kB history raw
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * Authors:
5 * Michał Sawicz <michal.sawicz@canonical.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 3.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
20#include "indicatorsmanager.h"
21#include "indicatorsfactory.h"
23#include <QSettings>
24#include <QDebug>
26#include "paths.h"
29class IndicatorsManager::IndicatorData
31public:
32 IndicatorData(const QString& name, const QFileInfo& fileInfo)
33 : m_name(name)
34 , m_fileInfo(fileInfo)
35 , m_verified (true)
36 {}
38 QString m_name;
39 QFileInfo m_fileInfo;
41 bool m_verified;
42 IndicatorClientInterface::Ptr m_obj;
43};
45IndicatorsManager::IndicatorsManager(QObject* parent)
46: QObject(parent)
47, m_loaded(false)
51IndicatorsManager::~IndicatorsManager()
53 unload();
56void IndicatorsManager::load()
58 unload();
59 QStringList xdgLocations = shellDataDirs();//QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
61 m_fsWatcher.reset(new QFileSystemWatcher(this));
63 Q_FOREACH(const QString& xdgLocation, xdgLocations)
64 {
65 QString indicator_path = QDir::cleanPath(xdgLocation + "/unity/indicators");
66 QDir indicator_dir(indicator_path);
67 if (indicator_dir.exists())
68 {
69 // watch folder for changes.
70 m_fsWatcher->addPath(indicator_path);
72 load(indicator_dir);
73 }
74 }
76 QObject::connect(m_fsWatcher.data(), SIGNAL(directoryChanged(const QString&)), this, SLOT(onDirectoryChanged(const QString&)));
77 QObject::connect(m_fsWatcher.data(), SIGNAL(fileChanged(const QString&)), this, SLOT(onFileChanged(const QString&)));
78 setLoaded(true);
81void IndicatorsManager::onDirectoryChanged(const QString& direcory)
83 load(QDir(direcory));
86void IndicatorsManager::onFileChanged(const QString& file)
88 QFileInfo file_info(file);
89 if (!file_info.exists())
90 {
91 unload(file_info);
92 return;
93 }
94 else
95 {
96 load(QFileInfo(file));
97 }
100void IndicatorsManager::load(const QDir& dir)
102 startVerify(dir.canonicalPath());
104 QFileInfoList indicator_files = dir.entryInfoList(QStringList() << "*.indicator", QDir::Files);
105 Q_FOREACH(const QFileInfo& indicator_file, indicator_files)
106 {
107 load(indicator_file);
108 }
110 endVerify(dir.canonicalPath());
113void IndicatorsManager::load(const QFileInfo& file_info)
115 QSettings indicator_settings(file_info.absoluteFilePath(), QSettings::IniFormat, this);
116 indicator_settings.beginGroup("Indicator Service");
117 QString name = indicator_settings.value("Name").toString();
119 // don't bother loading if it's not registered.
120 if (!IndicatorsFactory::instance().isRegistered(name))
121 {
122 qWarning() << Q_FUNC_INFO << "Invalid plugin name: " << name << " - not registered in factory.";
123 return;
124 }
126 auto iter = m_indicatorsData.find(name);
127 if (iter != m_indicatorsData.end())
128 {
129 QString newFileInfoDir = QDir::cleanPath(file_info.canonicalPath());
130 IndicatorData* currentData = (*iter);
131 currentData->m_verified = true;
133 int file_info_location = -1;
134 int current_data_location = -1;
136 QString currentDataDir = QDir::cleanPath(currentData->m_fileInfo.canonicalPath());
138 // if we've already got this indicator, we need to make sure we're not overwriting data which is
139 // from a lower priority standard path
140 QStringList xdgLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
141 for (int i = 0; i < xdgLocations.size(); i++)
142 {
143 QString indicatorDir = QDir::cleanPath(xdgLocations[i] + "/unity/indicators");
145 if (newFileInfoDir == indicatorDir)
146 file_info_location = i;
147 if (currentDataDir == indicatorDir)
148 current_data_location = i;
150 if (file_info_location != -1 && current_data_location != -1)
151 break;
152 }
154 // file location is higher (or of equal) priority. overwrite.
155 if (file_info_location <= current_data_location &&
156 file_info != currentData->m_fileInfo)
157 {
158 currentData->m_fileInfo = file_info;
159 Q_EMIT indicatorLoaded(name);
160 }
161 }
162 else
163 {
164 IndicatorData* data = new IndicatorData(name, file_info);
165 data->m_verified = true;
166 m_indicatorsData[name]= data;
167 Q_EMIT indicatorLoaded(name);
168 }
171void IndicatorsManager::unload()
173 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
174 while(iter.hasNext())
175 {
176 iter.next();
177 IndicatorData* data = iter.value();
178 if (data->m_obj)
179 {
180 data->m_obj->shutdown();
181 }
182 Q_EMIT indicatorAboutToBeUnloaded(iter.key());
183 }
185 qDeleteAll(m_indicatorsData);
186 m_indicatorsData.clear();
188 setLoaded(false);
191void IndicatorsManager::unload(const QFileInfo& file)
193 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
194 while(iter.hasNext())
195 {
196 iter.next();
197 IndicatorData* data = iter.value();
198 if (data->m_fileInfo.absoluteFilePath() == file.absoluteFilePath())
199 {
200 if (!data->m_verified)
201 {
202 QString name = data->m_name;
203 Q_EMIT indicatorAboutToBeUnloaded(name);
205 delete data;
206 iter.remove();
207 }
208 }
209 }
211 setLoaded(m_indicatorsData.size() > 0);
214void IndicatorsManager::setLoaded(bool loaded)
216 if (loaded != m_loaded)
217 {
218 m_loaded = loaded;
219 Q_EMIT loadedChanged(m_loaded);
220 }
223void IndicatorsManager::startVerify(const QString& path)
225 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
226 while(iter.hasNext())
227 {
228 iter.next();
229 IndicatorData* data = iter.value();
230 if (data->m_fileInfo.canonicalPath() == path)
231 data->m_verified = false;
232 }
235void IndicatorsManager::endVerify(const QString& path)
237 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
238 while(iter.hasNext())
239 {
240 iter.next();
241 IndicatorData* data = iter.value();
242 if (data->m_fileInfo.canonicalPath() == path)
243 {
244 if (!data->m_verified)
245 {
246 QString name = data->m_name;
247 Q_EMIT indicatorAboutToBeUnloaded(name);
249 delete data;
250 iter.remove();
251 }
252 }
253 }
256IndicatorClientInterface::Ptr IndicatorsManager::indicator(const QString& indicator)
258 if (!m_indicatorsData.contains(indicator)) {
259 qWarning() << Q_FUNC_INFO << "Invalid plugin name: " << indicator;
260 return 0;
261 }
263 IndicatorData *data = m_indicatorsData[indicator];
264 if (data->m_obj)
265 return data->m_obj;
267 IndicatorClientInterface::Ptr plugin = IndicatorsFactory::instance().create(indicator, this);
268 if (plugin)
269 {
270 data->m_obj = plugin;
271 plugin->init(QSettings(data->m_fileInfo.absoluteFilePath(), QSettings::IniFormat, this));
272 }
273 return plugin;
276QList<IndicatorClientInterface::Ptr> IndicatorsManager::indicators()
278 QList<IndicatorClientInterface::Ptr> list;
279 Q_FOREACH(IndicatorData* data, m_indicatorsData)
280 {
281 IndicatorClientInterface::Ptr plugin = indicator(data->m_name);
282 list.append(plugin);
283 }
284 return list;
287bool IndicatorsManager::isLoaded() const
289 return m_loaded;