on bcbf76a help sign in
unity8/plugins/Unity/Indicators/indicatorsmanager.cpp
304 lines 8.1 kB history raw
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Nick Dedekind <nick.dedekind@canonical.com>
17 */
19#include "indicatorsmanager.h"
21#include <QSettings>
22#include <QDebug>
24#include <paths.h>
27class IndicatorsManager::IndicatorData
29public:
30 IndicatorData(const QString& name, const QFileInfo& fileInfo)
31 : m_name(name)
32 , m_fileInfo(fileInfo)
33 , m_verified (true)
34 {
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)
47 , m_profile(QStringLiteral("phone"))
51IndicatorsManager::~IndicatorsManager()
53 unload();
57void IndicatorsManager::load()
59 unload();
61 QStringList xdgLocations = shellDataDirs();//QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
63 m_fsWatcher.reset(new QFileSystemWatcher(this));
65 Q_FOREACH(const QString& xdgLocation, xdgLocations)
66 {
67 QString indicator_path = QDir::cleanPath(xdgLocation + "/unity/indicators");
68 QDir indicator_dir(indicator_path);
69 if (indicator_dir.exists())
70 {
71 // watch folder for changes.
72 m_fsWatcher->addPath(indicator_path);
74 loadDir(indicator_dir);
75 }
76 }
78 QObject::connect(m_fsWatcher.data(), &QFileSystemWatcher::directoryChanged, this, &IndicatorsManager::onDirectoryChanged);
79 QObject::connect(m_fsWatcher.data(), &QFileSystemWatcher::fileChanged, this, &IndicatorsManager::onFileChanged);
80 setLoaded(true);
83void IndicatorsManager::onDirectoryChanged(const QString& directory)
85 loadDir(QDir(directory));
88void IndicatorsManager::onFileChanged(const QString& file)
90 QFileInfo file_info(file);
91 if (!file_info.exists())
92 {
93 unloadFile(file_info);
94 return;
95 }
96 else
97 {
98 loadFile(QFileInfo(file));
99 }
102void IndicatorsManager::loadDir(const QDir& dir)
104 startVerify(dir.canonicalPath());
106 QFileInfoList indicator_files = dir.entryInfoList(QStringList(), QDir::Files|QDir::NoDotAndDotDot);
107 Q_FOREACH(const QFileInfo& indicator_file, indicator_files)
108 {
109 loadFile(indicator_file);
110 }
112 endVerify(dir.canonicalPath());
115void IndicatorsManager::loadFile(const QFileInfo& file_info)
117 QSettings indicator_settings(file_info.absoluteFilePath(), QSettings::IniFormat, this);
118 QString name = indicator_settings.value(QStringLiteral("Indicator Service/Name")).toString();
120 auto iter = m_indicatorsData.find(name);
121 if (iter != m_indicatorsData.end())
122 {
123 QString newFileInfoDir = QDir::cleanPath(file_info.canonicalPath());
124 IndicatorData* currentData = (*iter);
125 currentData->m_verified = true;
127 int file_info_location = -1;
128 int current_data_location = -1;
130 QString currentDataDir = QDir::cleanPath(currentData->m_fileInfo.canonicalPath());
132 // if we've already got this indicator, we need to make sure we're not overwriting data which is
133 // from a lower priority standard path
134 QStringList xdgLocations = shellDataDirs();
135 for (int i = 0; i < xdgLocations.size(); i++)
136 {
137 QString indicatorDir = QDir::cleanPath(xdgLocations[i] + "/unity/indicators");
139 if (newFileInfoDir == indicatorDir)
140 {
141 file_info_location = i;
142 }
143 if (currentDataDir == indicatorDir)
144 {
145 current_data_location = i;
146 }
148 if (file_info_location != -1 && current_data_location != -1)
149 {
150 break;
151 }
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 Q_EMIT indicatorAboutToBeUnloaded(iter.key());
178 }
180 qDeleteAll(m_indicatorsData);
181 m_indicatorsData.clear();
183 setLoaded(false);
186void IndicatorsManager::unloadFile(const QFileInfo& file)
188 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
189 while(iter.hasNext())
190 {
191 iter.next();
192 IndicatorData* data = iter.value();
193 if (data->m_fileInfo.absoluteFilePath() == file.absoluteFilePath())
194 {
195 if (!data->m_verified)
196 {
197 QString name = data->m_name;
198 Q_EMIT indicatorAboutToBeUnloaded(name);
200 delete data;
201 iter.remove();
202 }
203 }
204 }
206 setLoaded(m_indicatorsData.size() > 0);
209void IndicatorsManager::setLoaded(bool loaded)
211 if (loaded != m_loaded)
212 {
213 m_loaded = loaded;
214 Q_EMIT loadedChanged(m_loaded);
215 }
218QString IndicatorsManager::profile() const
220 return m_profile;
223void IndicatorsManager::setProfile(const QString& profile)
225 if (m_profile != profile) {
226 m_profile = profile;
227 Q_EMIT profileChanged(m_profile);
228 }
231void IndicatorsManager::startVerify(const QString& path)
233 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
234 while(iter.hasNext())
235 {
236 iter.next();
237 IndicatorData* data = iter.value();
238 if (data->m_fileInfo.canonicalPath() == path)
239 {
240 data->m_verified = false;
241 }
242 }
245void IndicatorsManager::endVerify(const QString& path)
247 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
248 while(iter.hasNext())
249 {
250 iter.next();
251 IndicatorData* data = iter.value();
252 if (data->m_fileInfo.canonicalPath() == path)
253 {
254 if (!data->m_verified)
255 {
256 QString name = data->m_name;
257 Q_EMIT indicatorAboutToBeUnloaded(name);
259 delete data;
260 iter.remove();
261 }
262 }
263 }
266Indicator::Ptr IndicatorsManager::indicator(const QString& indicator_name)
268 if (!m_indicatorsData.contains(indicator_name))
269 {
270 qWarning() << Q_FUNC_INFO << "Invalid indicator name: " << indicator_name;
271 return Indicator::Ptr();
272 }
274 IndicatorData *data = m_indicatorsData[indicator_name];
275 if (data->m_indicator)
276 {
277 return data->m_indicator;
278 }
280 Indicator::Ptr new_indicator(new Indicator(this));
281 data->m_indicator = new_indicator;
282 QSettings settings(data->m_fileInfo.absoluteFilePath(), QSettings::IniFormat, this);
283 new_indicator->init(data->m_fileInfo.fileName(), settings);
284 new_indicator->setProfile(m_profile);
285 QObject::connect(this, &IndicatorsManager::profileChanged, new_indicator.data(), &Indicator::setProfile);
286 return new_indicator;
289QVector<Indicator::Ptr> IndicatorsManager::indicators()
291 QVector<Indicator::Ptr> list;
292 Q_FOREACH(IndicatorData* data, m_indicatorsData)
293 {
294 Indicator::Ptr ret = indicator(data->m_name);
295 if (ret)
296 list.append(ret);
297 }
298 return list;
301bool IndicatorsManager::isLoaded() const
303 return m_loaded;