3 #include <QCryptographicHash>
5 #include <QDirIterator>
19 cachePath(GetIconCachePath()),
22 QSettings::NativeFormat)
32 auto map =
s.value(
"widgets").toMap();
33 for (QString key : map.keys())
35 QStringList w = map[key].toString().split(
":");
36 QStringList keyparts = key.split(
":");
40 elem.pluginPath = keyparts[0];
41 elem.lastModified = QDateTime::fromMSecsSinceEpoch(w[0].toLongLong());
42 elem.hash = w[1].toLatin1();
61 if (pluginPath.isEmpty())
66 QFileInfo info(pluginPath);
72 if (elem.pluginPath == pluginPath)
74 if (info.lastModified() == elem.lastModified)
79 else if (
getHash(pluginPath) == elem.hash)
82 << info.lastModified().toString() <<
" <> "
83 << elem.lastModified.toString();
90 <<
"Plugin filestamp and hash is different - loading plugin again.";
102 ARMARX_INFO_S <<
"Found plugin " << pluginPath <<
" in cache";
110 pluginData[
""].widgets[widgetName] = widgetCreator;
120 WidgetCreatorMap::const_iterator it =
data.widgets.find(widgetName);
121 if (it !=
data.widgets.end())
131 WidgetCreatorMap::const_iterator it =
data.widgets.find(widgetName);
132 if (it !=
data.widgets.end())
148 for (
const auto& elem :
data.widgets)
150 result << elem.first;
163 result.insert(
data.widgets.begin(),
data.widgets.end());
171 QDirIterator it(
":", QDirIterator::Subdirectories);
174 QString path = it.next().remove(0, 1);
175 auto newPath =
cachePath +
"/resources/" + path;
181 if (!path.isEmpty() && !QFile::exists(newPath))
209 for (
const QString& item : items)
211 if (
str.contains(item, Qt::CaseInsensitive))
222 widgetNames.removeDuplicates();
223 auto preload = [
this](QStringList widgetNames,
int delayMS)
225 QStringList blacklist = {
"libPointCloudViewerGuiPlugin"};
226 usleep(delayMS * 1000);
227 for (QString widgetName : widgetNames)
238 <<
"skipping blacklisted plugin for preload: " <<
data.pluginPath;
241 for (
auto& elem :
data.widgets)
247 if (widgetName == elem.first)
249 pluginPath =
data.pluginPath;
250 if (!
data.pluginLoader && !pluginPath.isEmpty())
252 auto pluginLoader = QSharedPointer<QPluginLoader>(
253 new QPluginLoader(pluginPath));
255 pluginLoader->load();
266 preloadFuture = std::async(std::launch::async, preload, widgetNames, delayMS);
280 QFile file(pluginPath);
282 if (file.open(QIODevice::ReadOnly))
284 QByteArray fileData = file.readAll();
285 hashData = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
287 return hashData.toHex();
294 QMap<QString, QVariant> widgetMap =
s.value(
"widgets").toMap();
295 widgetMap.remove(pluginPath +
":" + widgetName);
296 s.setValue(
"widgets", widgetMap);
298 QMap<QString, PluginData> newPluginDataMap;
301 if (
pluginData[key].pluginPath != pluginPath &&
302 pluginData[key].widgets.count(widgetName) == 0)
314 ARMARX_INFO <<
"Removing plugin " << pluginPath <<
" from cache";
315 QMap<QString, QVariant> widgetMap =
s.value(
"widgets").toMap();
316 QMap<QString, QVariant> newWidgetMap;
317 for (
auto key : widgetMap.keys())
319 if (!key.contains(pluginPath))
321 newWidgetMap[key] = widgetMap[key];
324 QMap<QString, PluginData> newPluginDataMap;
333 s.setValue(
"widgets", widgetMap);
339 QDateTime time = QFileInfo(pluginPath).lastModified();
341 QMap<QString, QVariant> widgetMap =
s.value(
"widgets").toMap();
342 ARMARX_DEBUG_S <<
"Updating last modified timestamp of plugin " << pluginPath <<
" to "
344 auto& pluginDataElement =
pluginData[pluginPath];
345 for (
auto& widget : pluginDataElement.widgets)
347 widgetMap[pluginPath +
":" + widget.first] = QString::number(time.toMSecsSinceEpoch()) +
348 ":" + pluginDataElement.hash +
":" +
352 assert(QString::number(time.toMSecsSinceEpoch()).toLongLong() == time.toMSecsSinceEpoch());
354 pluginDataElement.lastModified = time;
355 s.setValue(
"widgets", widgetMap);
361 auto start = IceUtil::Time::now();
362 QByteArray hashData =
getHash(pluginPath);
363 ARMARX_DEBUG_S <<
"Hashing took " << (IceUtil::Time::now() - start).toMicroSecondsDouble();
364 QSharedPointer<QPluginLoader> loader(
new QPluginLoader(pluginPath));
369 QMap<QString, QVariant> widgetMap =
s.value(
"widgets").toMap();
370 QDateTime time = QFileInfo(pluginPath).lastModified();
371 for (
auto& elem : widgets)
373 widgetMap[pluginPath +
":" + elem.first] =
374 QString::number(time.toMSecsSinceEpoch()) +
":" + hashData +
":" + elem.first;
377 s.setValue(
"widgets", widgetMap);
380 pluginData[pluginPath] = {loader, pluginPath, hashData, time, widgets};
386 ARMARX_INFO_S <<
"Loading widget " << widgetName <<
" from cache ";
389 QSharedPointer<QPluginLoader> loader;
393 QMap<QString, QVariant> map;
396 map =
s.value(
"widgets").toMap();
398 for (
auto key : map.keys())
400 QStringList w = map[key].toString().split(
":");
401 QStringList keyparts = key.split(
":");
404 if (w[2] == widgetName)
406 pluginPath = keyparts[0];
407 if (QFile::exists(pluginPath))
409 hash = w[1].toLatin1();
410 loader = QSharedPointer<QPluginLoader>(
new QPluginLoader(pluginPath));
412 time = QDateTime::fromMSecsSinceEpoch(w[0].toLongLong());
427 return PluginData{loader, pluginPath, hash, time, widgets};
435 QObject* plugin = loader->instance();
444 for (
auto elem : newWidgets)
447 QIcon icon = info->getIcon();
450 icon.pixmap(256, 64).save(
GetIconPath(elem.first));
452 icon = info->getCategoryIcon();
458 result.insert(newWidgets.begin(), newWidgets.end());
461 manager->registerKnownObjectFactoriesWithIce();
476 <<
"\nError string:\n"
477 << loader->errorString().toStdString();