on e5e440d help sign in
unity8/plugins/Unity/Indicators/indicatorsmanager.cpp
316 lines 8.5 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 <upstart.h>
25#include <nih/alloc.h>
27#include "paths.h"
30class IndicatorsManager::IndicatorData
32public:
33 IndicatorData(const QString& name, const QFileInfo& fileInfo)
34 : m_name(name)
35 , m_fileInfo(fileInfo)
36 , m_verified (true)
37 , m_upstart (NULL)
38 {
39 auto upstartsession = qgetenv("UPSTART_SESSION");
40 if (!upstartsession.isNull()) {
41 DBusConnection * conn = NULL;
42 conn = dbus_connection_open(upstartsession.constData(), NULL);
43 if (conn != NULL) {
44 m_upstart = nih_dbus_proxy_new(NULL, conn,
45 NULL,
46 DBUS_PATH_UPSTART,
47 NULL, NULL);
48 dbus_connection_unref(conn);
49 }
50 }
52 if (m_upstart != NULL) {
53 m_upstart->auto_start = FALSE;
54 }
55 }
57 ~IndicatorData ()
58 {
59 if (m_upstart != NULL) {
60 nih_unref(m_upstart, NULL);
61 m_upstart = NULL;
62 }
63 }
65 QString m_name;
66 QFileInfo m_fileInfo;
68 bool m_verified;
69 Indicator::Ptr m_indicator;
71 NihDBusProxy * m_upstart;
72};
74IndicatorsManager::IndicatorsManager(QObject* parent)
75 : QObject(parent)
76 , m_loaded(false)
80IndicatorsManager::~IndicatorsManager()
82 unload();
85void IndicatorsManager::load()
87 unload();
88 QStringList xdgLocations = shellDataDirs();//QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
90 m_fsWatcher.reset(new QFileSystemWatcher(this));
92 Q_FOREACH(const QString& xdgLocation, xdgLocations)
93 {
94 QString indicator_path = QDir::cleanPath(xdgLocation + "/unity/indicators");
95 QDir indicator_dir(indicator_path);
96 if (indicator_dir.exists())
97 {
98 // watch folder for changes.
99 m_fsWatcher->addPath(indicator_path);
101 loadDir(indicator_dir);
102 }
103 }
105 QObject::connect(m_fsWatcher.data(), SIGNAL(directoryChanged(const QString&)), this, SLOT(onDirectoryChanged(const QString&)));
106 QObject::connect(m_fsWatcher.data(), SIGNAL(fileChanged(const QString&)), this, SLOT(onFileChanged(const QString&)));
107 setLoaded(true);
110void IndicatorsManager::onDirectoryChanged(const QString& directory)
112 loadDir(QDir(directory));
115void IndicatorsManager::onFileChanged(const QString& file)
117 QFileInfo file_info(file);
118 if (!file_info.exists())
119 {
120 unloadFile(file_info);
121 return;
122 }
123 else
124 {
125 loadFile(QFileInfo(file));
126 }
129void IndicatorsManager::loadDir(const QDir& dir)
131 startVerify(dir.canonicalPath());
133 QFileInfoList indicator_files = dir.entryInfoList(QStringList(), QDir::Files|QDir::NoDotAndDotDot);
134 Q_FOREACH(const QFileInfo& indicator_file, indicator_files)
135 {
136 loadFile(indicator_file);
137 }
139 endVerify(dir.canonicalPath());
142void IndicatorsManager::loadFile(const QFileInfo& file_info)
144 QSettings indicator_settings(file_info.absoluteFilePath(), QSettings::IniFormat, this);
145 QString name = indicator_settings.value("Indicator Service/Name").toString();
147 auto iter = m_indicatorsData.find(name);
148 if (iter != m_indicatorsData.end())
149 {
150 QString newFileInfoDir = QDir::cleanPath(file_info.canonicalPath());
151 IndicatorData* currentData = (*iter);
152 currentData->m_verified = true;
154 int file_info_location = -1;
155 int current_data_location = -1;
157 QString currentDataDir = QDir::cleanPath(currentData->m_fileInfo.canonicalPath());
159 // if we've already got this indicator, we need to make sure we're not overwriting data which is
160 // from a lower priority standard path
161 QStringList xdgLocations = shellDataDirs();
162 for (int i = 0; i < xdgLocations.size(); i++)
163 {
164 QString indicatorDir = QDir::cleanPath(xdgLocations[i] + "/unity/indicators");
166 if (newFileInfoDir == indicatorDir)
167 {
168 file_info_location = i;
169 }
170 if (currentDataDir == indicatorDir)
171 {
172 current_data_location = i;
173 }
175 if (file_info_location != -1 && current_data_location != -1)
176 {
177 break;
178 }
179 }
181 // file location is higher (or of equal) priority. overwrite.
182 if (file_info_location <= current_data_location &&
183 file_info != currentData->m_fileInfo)
184 {
185 currentData->m_fileInfo = file_info;
186 Q_EMIT indicatorLoaded(name);
187 }
188 }
189 else
190 {
191 IndicatorData* data = new IndicatorData(name, file_info);
192 data->m_verified = true;
193 m_indicatorsData[name]= data;
194 Q_EMIT indicatorLoaded(name);
195 }
198void IndicatorsManager::unload()
200 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
201 while(iter.hasNext())
202 {
203 iter.next();
204 Q_EMIT indicatorAboutToBeUnloaded(iter.key());
205 }
207 qDeleteAll(m_indicatorsData);
208 m_indicatorsData.clear();
210 setLoaded(false);
213void IndicatorsManager::unloadFile(const QFileInfo& file)
215 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
216 while(iter.hasNext())
217 {
218 iter.next();
219 IndicatorData* data = iter.value();
220 if (data->m_fileInfo.absoluteFilePath() == file.absoluteFilePath())
221 {
222 if (!data->m_verified)
223 {
224 QString name = data->m_name;
225 Q_EMIT indicatorAboutToBeUnloaded(name);
227 delete data;
228 iter.remove();
229 }
230 }
231 }
233 setLoaded(m_indicatorsData.size() > 0);
236void IndicatorsManager::setLoaded(bool loaded)
238 if (loaded != m_loaded)
239 {
240 m_loaded = loaded;
241 Q_EMIT loadedChanged(m_loaded);
242 }
245void IndicatorsManager::startVerify(const QString& path)
247 QHashIterator<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 data->m_verified = false;
255 }
256 }
259void IndicatorsManager::endVerify(const QString& path)
261 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
262 while(iter.hasNext())
263 {
264 iter.next();
265 IndicatorData* data = iter.value();
266 if (data->m_fileInfo.canonicalPath() == path)
267 {
268 if (!data->m_verified)
269 {
270 QString name = data->m_name;
271 Q_EMIT indicatorAboutToBeUnloaded(name);
273 delete data;
274 iter.remove();
275 }
276 }
277 }
280Indicator::Ptr IndicatorsManager::indicator(const QString& indicator_name)
282 if (!m_indicatorsData.contains(indicator_name))
283 {
284 qWarning() << Q_FUNC_INFO << "Invalid indicator name: " << indicator_name;
285 return Indicator::Ptr();
286 }
288 IndicatorData *data = m_indicatorsData[indicator_name];
289 if (data->m_indicator)
290 {
291 return data->m_indicator;
292 }
294 Indicator::Ptr new_indicator(new Indicator(this));
295 data->m_indicator = new_indicator;
296 QSettings settings(data->m_fileInfo.absoluteFilePath(), QSettings::IniFormat, this);
297 new_indicator->init(data->m_fileInfo.fileName(), settings);
298 return new_indicator;
301QList<Indicator::Ptr> IndicatorsManager::indicators()
303 QList<Indicator::Ptr> list;
304 Q_FOREACH(IndicatorData* data, m_indicatorsData)
305 {
306 Indicator::Ptr ret = indicator(data->m_name);
307 if (ret)
308 list.append(ret);
309 }
310 return list;
313bool IndicatorsManager::isLoaded() const
315 return m_loaded;