on cedbc3f help sign in
unity8/plugins/Unity/Indicators/indicatorsmanager.cpp
285 lines 7.7 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 {}
36 QString m_name;
37 QFileInfo m_fileInfo;
39 bool m_verified;
40 Indicator::Ptr m_indicator;
41};
43IndicatorsManager::IndicatorsManager(QObject* parent)
44 : QObject(parent)
45 , m_loaded(false)
49IndicatorsManager::~IndicatorsManager()
51 unload();
54void IndicatorsManager::load()
56 unload();
57 QStringList xdgLocations = shellDataDirs();//QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
59 m_fsWatcher.reset(new QFileSystemWatcher(this));
61 Q_FOREACH(const QString& xdgLocation, xdgLocations)
62 {
63 QString indicator_path = QDir::cleanPath(xdgLocation + "/unity/indicators");
64 QDir indicator_dir(indicator_path);
65 if (indicator_dir.exists())
66 {
67 // watch folder for changes.
68 m_fsWatcher->addPath(indicator_path);
70 loadDir(indicator_dir);
71 }
72 }
74 QObject::connect(m_fsWatcher.data(), SIGNAL(directoryChanged(const QString&)), this, SLOT(onDirectoryChanged(const QString&)));
75 QObject::connect(m_fsWatcher.data(), SIGNAL(fileChanged(const QString&)), this, SLOT(onFileChanged(const QString&)));
76 setLoaded(true);
79void IndicatorsManager::onDirectoryChanged(const QString& directory)
81 loadDir(QDir(directory));
84void IndicatorsManager::onFileChanged(const QString& file)
86 QFileInfo file_info(file);
87 if (!file_info.exists())
88 {
89 unloadFile(file_info);
90 return;
91 }
92 else
93 {
94 loadFile(QFileInfo(file));
95 }
98void IndicatorsManager::loadDir(const QDir& dir)
100 startVerify(dir.canonicalPath());
102 QFileInfoList indicator_files = dir.entryInfoList(QStringList(), QDir::Files|QDir::NoDotAndDotDot);
103 Q_FOREACH(const QFileInfo& indicator_file, indicator_files)
104 {
105 loadFile(indicator_file);
106 }
108 endVerify(dir.canonicalPath());
111void IndicatorsManager::loadFile(const QFileInfo& file_info)
113 QSettings indicator_settings(file_info.absoluteFilePath(), QSettings::IniFormat, this);
114 QString name = indicator_settings.value("Indicator Service/Name").toString();
116 auto iter = m_indicatorsData.find(name);
117 if (iter != m_indicatorsData.end())
118 {
119 QString newFileInfoDir = QDir::cleanPath(file_info.canonicalPath());
120 IndicatorData* currentData = (*iter);
121 currentData->m_verified = true;
123 int file_info_location = -1;
124 int current_data_location = -1;
126 QString currentDataDir = QDir::cleanPath(currentData->m_fileInfo.canonicalPath());
128 // if we've already got this indicator, we need to make sure we're not overwriting data which is
129 // from a lower priority standard path
130 QStringList xdgLocations = shellDataDirs();
131 for (int i = 0; i < xdgLocations.size(); i++)
132 {
133 QString indicatorDir = QDir::cleanPath(xdgLocations[i] + "/unity/indicators");
135 if (newFileInfoDir == indicatorDir)
136 {
137 file_info_location = i;
138 }
139 if (currentDataDir == indicatorDir)
140 {
141 current_data_location = i;
142 }
144 if (file_info_location != -1 && current_data_location != -1)
145 {
146 break;
147 }
148 }
150 // file location is higher (or of equal) priority. overwrite.
151 if (file_info_location <= current_data_location &&
152 file_info != currentData->m_fileInfo)
153 {
154 currentData->m_fileInfo = file_info;
155 Q_EMIT indicatorLoaded(name);
156 }
157 }
158 else
159 {
160 IndicatorData* data = new IndicatorData(name, file_info);
161 data->m_verified = true;
162 m_indicatorsData[name]= data;
163 Q_EMIT indicatorLoaded(name);
164 }
167void IndicatorsManager::unload()
169 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
170 while(iter.hasNext())
171 {
172 iter.next();
173 Q_EMIT indicatorAboutToBeUnloaded(iter.key());
174 }
176 qDeleteAll(m_indicatorsData);
177 m_indicatorsData.clear();
179 setLoaded(false);
182void IndicatorsManager::unloadFile(const QFileInfo& file)
184 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
185 while(iter.hasNext())
186 {
187 iter.next();
188 IndicatorData* data = iter.value();
189 if (data->m_fileInfo.absoluteFilePath() == file.absoluteFilePath())
190 {
191 if (!data->m_verified)
192 {
193 QString name = data->m_name;
194 Q_EMIT indicatorAboutToBeUnloaded(name);
196 delete data;
197 iter.remove();
198 }
199 }
200 }
202 setLoaded(m_indicatorsData.size() > 0);
205void IndicatorsManager::setLoaded(bool loaded)
207 if (loaded != m_loaded)
208 {
209 m_loaded = loaded;
210 Q_EMIT loadedChanged(m_loaded);
211 }
214void IndicatorsManager::startVerify(const QString& path)
216 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
217 while(iter.hasNext())
218 {
219 iter.next();
220 IndicatorData* data = iter.value();
221 if (data->m_fileInfo.canonicalPath() == path)
222 {
223 data->m_verified = false;
224 }
225 }
228void IndicatorsManager::endVerify(const QString& path)
230 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
231 while(iter.hasNext())
232 {
233 iter.next();
234 IndicatorData* data = iter.value();
235 if (data->m_fileInfo.canonicalPath() == path)
236 {
237 if (!data->m_verified)
238 {
239 QString name = data->m_name;
240 Q_EMIT indicatorAboutToBeUnloaded(name);
242 delete data;
243 iter.remove();
244 }
245 }
246 }
249Indicator::Ptr IndicatorsManager::indicator(const QString& indicator_name)
251 if (!m_indicatorsData.contains(indicator_name))
252 {
253 qWarning() << Q_FUNC_INFO << "Invalid indicator name: " << indicator_name;
254 return Indicator::Ptr();
255 }
257 IndicatorData *data = m_indicatorsData[indicator_name];
258 if (data->m_indicator)
259 {
260 return data->m_indicator;
261 }
263 Indicator::Ptr new_indicator(new Indicator(this));
264 data->m_indicator = new_indicator;
265 QSettings settings(data->m_fileInfo.absoluteFilePath(), QSettings::IniFormat, this);
266 new_indicator->init(data->m_fileInfo.fileName(), settings);
267 return new_indicator;
270QList<Indicator::Ptr> IndicatorsManager::indicators()
272 QList<Indicator::Ptr> list;
273 Q_FOREACH(IndicatorData* data, m_indicatorsData)
274 {
275 Indicator::Ptr ret = indicator(data->m_name);
276 if (ret)
277 list.append(ret);
278 }
279 return list;
282bool IndicatorsManager::isLoaded() const
284 return m_loaded;