on 9a701bc help sign in
unity8/plugins/Unity/Indicators/indicatorsmanager.cpp
307 lines 8.3 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>
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 , m_upstart (NULL)
37 {
38 auto upstartsession = qgetenv("UPSTART_SESSION");
39 if (!upstartsession.isNull()) {
40 DBusConnection * conn = NULL;
41 conn = dbus_connection_open(upstartsession.constData(), NULL);
42 if (conn != NULL) {
43 m_upstart = nih_dbus_proxy_new(NULL, conn,
44 NULL,
45 DBUS_PATH_UPSTART,
46 NULL, NULL);
47 dbus_connection_unref(conn);
48 }
49 }
51 if (m_upstart != NULL) {
52 m_upstart->auto_start = FALSE;
53 }
54 }
56 QString m_name;
57 QFileInfo m_fileInfo;
59 bool m_verified;
60 Indicator::Ptr m_indicator;
62 NihDBusProxy * m_upstart;
63};
65IndicatorsManager::IndicatorsManager(QObject* parent)
66 : QObject(parent)
67 , m_loaded(false)
71IndicatorsManager::~IndicatorsManager()
73 unload();
76void IndicatorsManager::load()
78 unload();
79 QStringList xdgLocations = shellDataDirs();//QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
81 m_fsWatcher.reset(new QFileSystemWatcher(this));
83 Q_FOREACH(const QString& xdgLocation, xdgLocations)
84 {
85 QString indicator_path = QDir::cleanPath(xdgLocation + "/unity/indicators");
86 QDir indicator_dir(indicator_path);
87 if (indicator_dir.exists())
88 {
89 // watch folder for changes.
90 m_fsWatcher->addPath(indicator_path);
92 loadDir(indicator_dir);
93 }
94 }
96 QObject::connect(m_fsWatcher.data(), SIGNAL(directoryChanged(const QString&)), this, SLOT(onDirectoryChanged(const QString&)));
97 QObject::connect(m_fsWatcher.data(), SIGNAL(fileChanged(const QString&)), this, SLOT(onFileChanged(const QString&)));
98 setLoaded(true);
101void IndicatorsManager::onDirectoryChanged(const QString& directory)
103 loadDir(QDir(directory));
106void IndicatorsManager::onFileChanged(const QString& file)
108 QFileInfo file_info(file);
109 if (!file_info.exists())
110 {
111 unloadFile(file_info);
112 return;
113 }
114 else
115 {
116 loadFile(QFileInfo(file));
117 }
120void IndicatorsManager::loadDir(const QDir& dir)
122 startVerify(dir.canonicalPath());
124 QFileInfoList indicator_files = dir.entryInfoList(QStringList(), QDir::Files|QDir::NoDotAndDotDot);
125 Q_FOREACH(const QFileInfo& indicator_file, indicator_files)
126 {
127 loadFile(indicator_file);
128 }
130 endVerify(dir.canonicalPath());
133void IndicatorsManager::loadFile(const QFileInfo& file_info)
135 QSettings indicator_settings(file_info.absoluteFilePath(), QSettings::IniFormat, this);
136 QString name = indicator_settings.value("Indicator Service/Name").toString();
138 auto iter = m_indicatorsData.find(name);
139 if (iter != m_indicatorsData.end())
140 {
141 QString newFileInfoDir = QDir::cleanPath(file_info.canonicalPath());
142 IndicatorData* currentData = (*iter);
143 currentData->m_verified = true;
145 int file_info_location = -1;
146 int current_data_location = -1;
148 QString currentDataDir = QDir::cleanPath(currentData->m_fileInfo.canonicalPath());
150 // if we've already got this indicator, we need to make sure we're not overwriting data which is
151 // from a lower priority standard path
152 QStringList xdgLocations = shellDataDirs();
153 for (int i = 0; i < xdgLocations.size(); i++)
154 {
155 QString indicatorDir = QDir::cleanPath(xdgLocations[i] + "/unity/indicators");
157 if (newFileInfoDir == indicatorDir)
158 {
159 file_info_location = i;
160 }
161 if (currentDataDir == indicatorDir)
162 {
163 current_data_location = i;
164 }
166 if (file_info_location != -1 && current_data_location != -1)
167 {
168 break;
169 }
170 }
172 // file location is higher (or of equal) priority. overwrite.
173 if (file_info_location <= current_data_location &&
174 file_info != currentData->m_fileInfo)
175 {
176 currentData->m_fileInfo = file_info;
177 Q_EMIT indicatorLoaded(name);
178 }
179 }
180 else
181 {
182 IndicatorData* data = new IndicatorData(name, file_info);
183 data->m_verified = true;
184 m_indicatorsData[name]= data;
185 Q_EMIT indicatorLoaded(name);
186 }
189void IndicatorsManager::unload()
191 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
192 while(iter.hasNext())
193 {
194 iter.next();
195 Q_EMIT indicatorAboutToBeUnloaded(iter.key());
196 }
198 qDeleteAll(m_indicatorsData);
199 m_indicatorsData.clear();
201 setLoaded(false);
204void IndicatorsManager::unloadFile(const QFileInfo& file)
206 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
207 while(iter.hasNext())
208 {
209 iter.next();
210 IndicatorData* data = iter.value();
211 if (data->m_fileInfo.absoluteFilePath() == file.absoluteFilePath())
212 {
213 if (!data->m_verified)
214 {
215 QString name = data->m_name;
216 Q_EMIT indicatorAboutToBeUnloaded(name);
218 delete data;
219 iter.remove();
220 }
221 }
222 }
224 setLoaded(m_indicatorsData.size() > 0);
227void IndicatorsManager::setLoaded(bool loaded)
229 if (loaded != m_loaded)
230 {
231 m_loaded = loaded;
232 Q_EMIT loadedChanged(m_loaded);
233 }
236void IndicatorsManager::startVerify(const QString& path)
238 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
239 while(iter.hasNext())
240 {
241 iter.next();
242 IndicatorData* data = iter.value();
243 if (data->m_fileInfo.canonicalPath() == path)
244 {
245 data->m_verified = false;
246 }
247 }
250void IndicatorsManager::endVerify(const QString& path)
252 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
253 while(iter.hasNext())
254 {
255 iter.next();
256 IndicatorData* data = iter.value();
257 if (data->m_fileInfo.canonicalPath() == path)
258 {
259 if (!data->m_verified)
260 {
261 QString name = data->m_name;
262 Q_EMIT indicatorAboutToBeUnloaded(name);
264 delete data;
265 iter.remove();
266 }
267 }
268 }
271Indicator::Ptr IndicatorsManager::indicator(const QString& indicator_name)
273 if (!m_indicatorsData.contains(indicator_name))
274 {
275 qWarning() << Q_FUNC_INFO << "Invalid indicator name: " << indicator_name;
276 return Indicator::Ptr();
277 }
279 IndicatorData *data = m_indicatorsData[indicator_name];
280 if (data->m_indicator)
281 {
282 return data->m_indicator;
283 }
285 Indicator::Ptr new_indicator(new Indicator(this));
286 data->m_indicator = new_indicator;
287 QSettings settings(data->m_fileInfo.absoluteFilePath(), QSettings::IniFormat, this);
288 new_indicator->init(data->m_fileInfo.fileName(), settings);
289 return new_indicator;
292QList<Indicator::Ptr> IndicatorsManager::indicators()
294 QList<Indicator::Ptr> list;
295 Q_FOREACH(IndicatorData* data, m_indicatorsData)
296 {
297 Indicator::Ptr ret = indicator(data->m_name);
298 if (ret)
299 list.append(ret);
300 }
301 return list;
304bool IndicatorsManager::isLoaded() const
306 return m_loaded;