on cddaf44 help sign in
unity8/plugins/IndicatorsClient/indicatorsmanager.cpp
278 lines 7.5 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"
22#include <QSettings>
23#include <QDebug>
25#include "paths.h"
28class IndicatorsManager::IndicatorData
30public:
31 IndicatorData(const QString& name, const QFileInfo& fileInfo)
32 : m_name(name)
33 , m_fileInfo(fileInfo)
34 , m_verified (true)
35 {}
37 QString m_name;
38 QFileInfo m_fileInfo;
40 bool m_verified;
41 Indicator::Ptr m_indicator;
42};
44IndicatorsManager::IndicatorsManager(QObject* parent)
45: QObject(parent)
46, m_loaded(false)
50IndicatorsManager::~IndicatorsManager()
52 unload();
55void IndicatorsManager::load()
57 unload();
58 QStringList xdgLocations = shellDataDirs();//QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
60 m_fsWatcher.reset(new QFileSystemWatcher(this));
62 Q_FOREACH(const QString& xdgLocation, xdgLocations)
63 {
64 QString indicator_path = QDir::cleanPath(xdgLocation + "/unity/indicators");
65 QDir indicator_dir(indicator_path);
66 if (indicator_dir.exists())
67 {
68 // watch folder for changes.
69 m_fsWatcher->addPath(indicator_path);
71 load(indicator_dir);
72 }
73 }
75 QObject::connect(m_fsWatcher.data(), SIGNAL(directoryChanged(const QString&)), this, SLOT(onDirectoryChanged(const QString&)));
76 QObject::connect(m_fsWatcher.data(), SIGNAL(fileChanged(const QString&)), this, SLOT(onFileChanged(const QString&)));
77 setLoaded(true);
80void IndicatorsManager::onDirectoryChanged(const QString& direcory)
82 load(QDir(direcory));
85void IndicatorsManager::onFileChanged(const QString& file)
87 QFileInfo file_info(file);
88 if (!file_info.exists())
89 {
90 unload(file_info);
91 return;
92 }
93 else
94 {
95 load(QFileInfo(file));
96 }
99void IndicatorsManager::load(const QDir& dir)
101 startVerify(dir.canonicalPath());
103 QFileInfoList indicator_files = dir.entryInfoList(QStringList(), QDir::Files|QDir::NoDotAndDotDot);
104 Q_FOREACH(const QFileInfo& indicator_file, indicator_files)
105 {
106 load(indicator_file);
107 }
109 endVerify(dir.canonicalPath());
112void IndicatorsManager::load(const QFileInfo& file_info)
114 QSettings indicator_settings(file_info.absoluteFilePath(), QSettings::IniFormat, this);
115 QString name = indicator_settings.value("Indicator Service/Name").toString();
117 auto iter = m_indicatorsData.find(name);
118 if (iter != m_indicatorsData.end())
119 {
120 QString newFileInfoDir = QDir::cleanPath(file_info.canonicalPath());
121 IndicatorData* currentData = (*iter);
122 currentData->m_verified = true;
124 int file_info_location = -1;
125 int current_data_location = -1;
127 QString currentDataDir = QDir::cleanPath(currentData->m_fileInfo.canonicalPath());
129 // if we've already got this indicator, we need to make sure we're not overwriting data which is
130 // from a lower priority standard path
131 QStringList xdgLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
132 for (int i = 0; i < xdgLocations.size(); i++)
133 {
134 QString indicatorDir = QDir::cleanPath(xdgLocations[i] + "/unity/indicators");
136 if (newFileInfoDir == indicatorDir)
137 file_info_location = i;
138 if (currentDataDir == indicatorDir)
139 current_data_location = i;
141 if (file_info_location != -1 && current_data_location != -1)
142 break;
143 }
145 // file location is higher (or of equal) priority. overwrite.
146 if (file_info_location <= current_data_location &&
147 file_info != currentData->m_fileInfo)
148 {
149 currentData->m_fileInfo = file_info;
150 Q_EMIT indicatorLoaded(name);
151 }
152 }
153 else
154 {
155 IndicatorData* data = new IndicatorData(name, file_info);
156 data->m_verified = true;
157 m_indicatorsData[name]= data;
158 Q_EMIT indicatorLoaded(name);
159 }
162void IndicatorsManager::unload()
164 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
165 while(iter.hasNext())
166 {
167 iter.next();
168 Q_EMIT indicatorAboutToBeUnloaded(iter.key());
169 }
171 qDeleteAll(m_indicatorsData);
172 m_indicatorsData.clear();
174 setLoaded(false);
177void IndicatorsManager::unload(const QFileInfo& file)
179 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
180 while(iter.hasNext())
181 {
182 iter.next();
183 IndicatorData* data = iter.value();
184 if (data->m_fileInfo.absoluteFilePath() == file.absoluteFilePath())
185 {
186 if (!data->m_verified)
187 {
188 QString name = data->m_name;
189 Q_EMIT indicatorAboutToBeUnloaded(name);
191 delete data;
192 iter.remove();
193 }
194 }
195 }
197 setLoaded(m_indicatorsData.size() > 0);
200void IndicatorsManager::setLoaded(bool loaded)
202 if (loaded != m_loaded)
203 {
204 m_loaded = loaded;
205 Q_EMIT loadedChanged(m_loaded);
206 }
209void IndicatorsManager::startVerify(const QString& path)
211 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
212 while(iter.hasNext())
213 {
214 iter.next();
215 IndicatorData* data = iter.value();
216 if (data->m_fileInfo.canonicalPath() == path)
217 data->m_verified = false;
218 }
221void IndicatorsManager::endVerify(const QString& path)
223 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
224 while(iter.hasNext())
225 {
226 iter.next();
227 IndicatorData* data = iter.value();
228 if (data->m_fileInfo.canonicalPath() == path)
229 {
230 if (!data->m_verified)
231 {
232 QString name = data->m_name;
233 Q_EMIT indicatorAboutToBeUnloaded(name);
235 delete data;
236 iter.remove();
237 }
238 }
239 }
242Indicator::Ptr IndicatorsManager::indicator(const QString& indicator)
244 if (!m_indicatorsData.contains(indicator))
245 {
246 qWarning() << Q_FUNC_INFO << "Invalid plugin name: " << indicator;
247 return 0;
248 }
250 IndicatorData *data = m_indicatorsData[indicator];
251 if (data->m_indicator)
252 return data->m_indicator;
254 Indicator::Ptr plugin = std::make_shared<Indicator>(this);
255 if (plugin)
256 {
257 data->m_indicator = plugin;
258 QSettings settings(data->m_fileInfo.absoluteFilePath(), QSettings::IniFormat, this);
259 plugin->init(data->m_fileInfo.fileName(), settings);
260 }
261 return plugin;
264QList<Indicator::Ptr> IndicatorsManager::indicators()
266 QList<Indicator::Ptr> list;
267 Q_FOREACH(IndicatorData* data, m_indicatorsData)
268 {
269 Indicator::Ptr plugin = indicator(data->m_name);
270 list.append(plugin);
271 }
272 return list;
275bool IndicatorsManager::isLoaded() const
277 return m_loaded;