10 #include <QDirIterator>
13 #include <QCryptographicHash>
19 cachePath(GetIconCachePath()),
21 s(
armarx::
ArmarXDataPath::GetDefaultUserConfigPath().c_str() + settingsApplicationName, QSettings::NativeFormat)
31 auto map =
s.value(
"widgets").toMap();
32 for (QString key : map.keys())
34 QStringList w = map[key].toString().split(
":");
35 QStringList keyparts = key.split(
":");
39 elem.pluginPath = keyparts[0];
40 elem.lastModified = QDateTime::fromMSecsSinceEpoch(w[0].toLongLong());
41 elem.hash = w[1].toLatin1();
59 if (pluginPath.isEmpty())
64 QFileInfo info(pluginPath) ;
70 if (elem.pluginPath == pluginPath)
72 if (info.lastModified() == elem.lastModified)
77 else if (
getHash(pluginPath) == elem.hash)
79 ARMARX_DEBUG_S <<
"Same hash - timestamps " << info.lastModified().toString() <<
" <> " << elem.lastModified.toString() ;
85 ARMARX_VERBOSE_S <<
"Plugin filestamp and hash is different - loading plugin again.";
97 ARMARX_INFO_S <<
"Found plugin " << pluginPath <<
" in cache";
104 pluginData[
""].widgets[widgetName] = widgetCreator;
113 WidgetCreatorMap::const_iterator it =
data.widgets.find(widgetName);
114 if (it !=
data.widgets.end())
124 WidgetCreatorMap::const_iterator it =
data.widgets.find(widgetName);
125 if (it !=
data.widgets.end())
140 for (
const auto& elem :
data.widgets)
142 result << elem.first;
155 result.insert(
data.widgets.begin(),
data.widgets.end());
162 QDirIterator it(
":", QDirIterator::Subdirectories);
165 QString path = it.next().remove(0, 1);
166 auto newPath =
cachePath +
"/resources/" + path;
172 if (!path.isEmpty() && !QFile::exists(newPath))
196 for (
const QString& item : items)
198 if (
str.contains(item, Qt::CaseInsensitive))
208 widgetNames.removeDuplicates();
209 auto preload = [
this](QStringList widgetNames,
int delayMS)
211 QStringList blacklist = {
"libPointCloudViewerGuiPlugin"};
212 usleep(delayMS * 1000);
213 for (QString widgetName : widgetNames)
225 for (
auto& elem :
data.widgets)
231 if (widgetName == elem.first)
233 pluginPath =
data.pluginPath;
234 if (!
data.pluginLoader && !pluginPath.isEmpty())
236 auto pluginLoader = QSharedPointer<QPluginLoader>(
new QPluginLoader(pluginPath));
238 pluginLoader->load();
249 preloadFuture = std::async(std::launch::async, preload, widgetNames, delayMS);
261 QFile file(pluginPath);
263 if (file.open(QIODevice::ReadOnly))
265 QByteArray fileData = file.readAll();
266 hashData = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
268 return hashData.toHex();
274 QMap<QString, QVariant> widgetMap =
s.value(
"widgets").toMap();
275 widgetMap.remove(pluginPath +
":" + widgetName);
276 s.setValue(
"widgets", widgetMap);
278 QMap<QString, PluginData> newPluginDataMap;
292 ARMARX_INFO <<
"Removing plugin " << pluginPath <<
" from cache";
293 QMap<QString, QVariant> widgetMap =
s.value(
"widgets").toMap();
294 QMap<QString, QVariant> newWidgetMap;
295 for (
auto key : widgetMap.keys())
297 if (!key.contains(pluginPath))
299 newWidgetMap[key] = widgetMap[key];
302 QMap<QString, PluginData> newPluginDataMap;
311 s.setValue(
"widgets", widgetMap);
316 QDateTime time = QFileInfo(pluginPath).lastModified();
318 QMap<QString, QVariant> widgetMap =
s.value(
"widgets").toMap();
319 ARMARX_DEBUG_S <<
"Updating last modified timestamp of plugin " << pluginPath <<
" to " << time.toString();
320 auto& pluginDataElement =
pluginData[pluginPath];
321 for (
auto& widget : pluginDataElement.widgets)
323 widgetMap[pluginPath +
":" + widget.first] = QString::number(time.toMSecsSinceEpoch()) +
":" + pluginDataElement.hash +
":" + widget.first;
326 assert(QString::number(time.toMSecsSinceEpoch()).toLongLong() == time.toMSecsSinceEpoch());
328 pluginDataElement.lastModified = time;
329 s.setValue(
"widgets", widgetMap);
334 auto start = IceUtil::Time::now();
335 QByteArray hashData =
getHash(pluginPath);
336 ARMARX_DEBUG_S <<
"Hashing took " << (IceUtil::Time::now() - start).toMicroSecondsDouble();
337 QSharedPointer<QPluginLoader> loader(
new QPluginLoader(pluginPath));
342 QMap<QString, QVariant> widgetMap =
s.value(
"widgets").toMap();
343 QDateTime time = QFileInfo(pluginPath).lastModified();
344 for (
auto& elem : widgets)
346 widgetMap[pluginPath +
":" + elem.first] = QString::number(time.toMSecsSinceEpoch()) +
":" + hashData +
":" + elem.first;
349 s.setValue(
"widgets", widgetMap);
352 pluginData[pluginPath] = {loader, pluginPath, hashData, time, widgets};
358 ARMARX_INFO_S <<
"Loading widget " << widgetName <<
" from cache ";
361 QSharedPointer<QPluginLoader> loader;
365 QMap<QString, QVariant> map;
368 map =
s.value(
"widgets").toMap();
370 for (
auto key : map.keys())
372 QStringList w = map[key].toString().split(
":");
373 QStringList keyparts = key.split(
":");
376 if (w[2] == widgetName)
378 pluginPath = keyparts[0];
379 if (QFile::exists(pluginPath))
381 hash = w[1].toLatin1();
382 loader = QSharedPointer<QPluginLoader>(
new QPluginLoader(pluginPath));
384 time = QDateTime::fromMSecsSinceEpoch(w[0].toLongLong());
401 return PluginData {loader, pluginPath, hash, time, widgets};
408 QObject* plugin = loader->instance();
417 for (
auto elem : newWidgets)
420 QIcon icon = info->getIcon();
423 icon.pixmap(256, 64).save(
GetIconPath(elem.first));
425 icon = info->getCategoryIcon();
431 result.insert(newWidgets.begin(), newWidgets.end());
434 manager->registerKnownObjectFactoriesWithIce();
450 <<
"\nError string:\n" << loader->errorString().toStdString();