17#include "indicatorsmanager.h"
21#include <QDBusConnection>
22#include <QDBusConnectionInterface>
23#include <QDBusServiceWatcher>
24#include <QRegularExpression>
28class IndicatorsManager::IndicatorData
31 IndicatorData(
const QString& name,
const QFileInfo& fileInfo)
33 , m_fileInfo(fileInfo)
42 Indicator::Ptr m_indicator;
45IndicatorsManager::IndicatorsManager(QObject* parent)
48 , m_profile(QStringLiteral(
"phone"))
52IndicatorsManager::~IndicatorsManager()
57void IndicatorsManager::load()
61 m_fsWatcher.reset(
new QFileSystemWatcher(
this));
63 for (
const auto &xdgPath : shellDataDirs()) {
65 const auto unityPath = QDir::cleanPath(xdgPath +
"/unity/indicators");
66 if (QFile::exists(unityPath)) {
68 m_fsWatcher->addPath(unityPath);
72 const auto ayatanaPath = QDir::cleanPath(xdgPath +
"/ayatana/indicators");
73 if (QFile::exists(ayatanaPath)) {
75 m_fsWatcher->addPath(ayatanaPath);
80 QObject::connect(m_fsWatcher.data(), &QFileSystemWatcher::directoryChanged,
this, &IndicatorsManager::onDirectoryChanged);
81 QObject::connect(m_fsWatcher.data(), &QFileSystemWatcher::fileChanged,
this, &IndicatorsManager::onFileChanged);
85void IndicatorsManager::onDirectoryChanged(
const QString& directory)
87 loadDir(QDir(directory));
90void IndicatorsManager::onFileChanged(
const QString& file)
92 QFileInfo file_info(file);
93 if (!file_info.exists())
95 unloadFile(file_info);
100 loadFile(QFileInfo(file));
104void IndicatorsManager::loadDir(
const QDir& dir)
106 startVerify(dir.canonicalPath());
108 const QFileInfoList indicator_files = dir.entryInfoList(QStringList(), QDir::Files|QDir::NoDotAndDotDot);
109 Q_FOREACH(
const QFileInfo& indicator_file, indicator_files)
111 loadFile(indicator_file);
114 endVerify(dir.canonicalPath());
117void IndicatorsManager::loadFile(
const QFileInfo& file_info)
120 QString service = file_info.fileName ();
121 QRegularExpression regex (
"^com\\.canonical\\.indicator\\.fake\\d$");
122 QRegularExpressionMatch match = regex.match (service);
123 bool test = match.hasMatch ();
127 QDBusConnection connection = QDBusConnection::sessionBus ();
128 QDBusConnectionInterface *
interface = connection.interface ();
130 bool registered = interface->isServiceRegistered (service);
134 auto watcher =
new QDBusServiceWatcher (service, connection, QDBusServiceWatcher::WatchForRegistration,
this);
136 connect (watcher, &QDBusServiceWatcher::serviceRegistered,
this, [
this, file_info, watcher] ()
138 watcher->deleteLater ();
139 this->loadFile (file_info);
146 QSettings indicator_settings(file_info.absoluteFilePath(), QSettings::IniFormat,
this);
147 const QString name = indicator_settings.value(QStringLiteral(
"Indicator Service/Name")).toString();
149 auto iter = m_indicatorsData.constFind(name);
150 if (iter != m_indicatorsData.constEnd())
152 const QString newFileInfoDir = QDir::cleanPath(file_info.canonicalPath());
153 IndicatorData* currentData = (*iter);
154 currentData->m_verified =
true;
156 int file_info_location = -1;
157 int current_data_location = -1;
159 const QString currentDataDir = QDir::cleanPath(currentData->m_fileInfo.canonicalPath());
163 QStringList xdgLocations = shellDataDirs();
164 for (
int i = 0; i < xdgLocations.size(); i++)
166 const QString xdgLocation = QDir::cleanPath(xdgLocations[i]);
168 if (newFileInfoDir.startsWith(xdgLocation))
170 file_info_location = i;
172 if (currentDataDir.startsWith(xdgLocation))
174 current_data_location = i;
177 if (file_info_location != -1 && current_data_location != -1)
184 if (file_info_location <= current_data_location &&
185 file_info != currentData->m_fileInfo)
187 currentData->m_fileInfo = file_info;
188 Q_EMIT indicatorLoaded(name);
193 IndicatorData* data =
new IndicatorData(name, file_info);
194 data->m_verified =
true;
195 m_indicatorsData[name]= data;
196 Q_EMIT indicatorLoaded(name);
200void IndicatorsManager::unload()
202 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
203 while(iter.hasNext())
206 Q_EMIT indicatorAboutToBeUnloaded(iter.key());
209 qDeleteAll(m_indicatorsData);
210 m_indicatorsData.clear();
215void IndicatorsManager::unloadFile(
const QFileInfo& file)
217 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
218 while(iter.hasNext())
221 IndicatorData* data = iter.value();
222 if (data->m_fileInfo.absoluteFilePath() == file.absoluteFilePath())
224 if (!data->m_verified)
226 const QString name = data->m_name;
227 Q_EMIT indicatorAboutToBeUnloaded(name);
235 setLoaded(m_indicatorsData.size() > 0);
238void IndicatorsManager::setLoaded(
bool loaded)
240 if (loaded != m_loaded)
243 Q_EMIT loadedChanged(m_loaded);
247QString IndicatorsManager::profile()
const
252void IndicatorsManager::setProfile(
const QString& profile)
254 if (m_profile != profile) {
256 Q_EMIT profileChanged(m_profile);
260void IndicatorsManager::startVerify(
const QString& path)
262 QHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
263 while(iter.hasNext())
266 IndicatorData* data = iter.value();
267 if (data->m_fileInfo.canonicalPath() == path)
269 data->m_verified =
false;
274void IndicatorsManager::endVerify(
const QString& path)
276 QMutableHashIterator<QString, IndicatorData*> iter(m_indicatorsData);
277 while(iter.hasNext())
280 IndicatorData* data = iter.value();
281 if (data->m_fileInfo.canonicalPath() == path)
283 if (!data->m_verified)
285 const QString name = data->m_name;
286 Q_EMIT indicatorAboutToBeUnloaded(name);
295Indicator::Ptr IndicatorsManager::indicator(
const QString& indicator_name)
297 if (!m_indicatorsData.contains(indicator_name))
299 qWarning() << Q_FUNC_INFO <<
"Invalid indicator name: " << indicator_name;
300 return Indicator::Ptr();
303 IndicatorData *data = m_indicatorsData.value(indicator_name);
304 if (data->m_indicator)
306 return data->m_indicator;
309 Indicator::Ptr new_indicator(
new Indicator(
this));
310 data->m_indicator = new_indicator;
311 QSettings settings(data->m_fileInfo.absoluteFilePath(), QSettings::IniFormat,
this);
312 new_indicator->init(data->m_fileInfo.fileName(), settings);
319 if ((new_indicator->identifier() == QStringLiteral(
"ayatana-indicator-session"))
320 || new_indicator->identifier() == QStringLiteral(
"ayatana-indicator-keyboard")) {
321 new_indicator->setProfile(QString(m_profile).replace(QStringLiteral(
"phone"), QStringLiteral(
"desktop")));
323 new_indicator->setProfile(m_profile);
326 QObject::connect(
this, &IndicatorsManager::profileChanged, new_indicator.data(), &Indicator::setProfile);
327 return new_indicator;
330QVector<Indicator::Ptr> IndicatorsManager::indicators()
332 QVector<Indicator::Ptr> list;
333 Q_FOREACH(IndicatorData* data, m_indicatorsData)
335 Indicator::Ptr ret = indicator(data->m_name);
342bool IndicatorsManager::isLoaded()
const