Start: fixes #17857: Icon-files of the startup screen are not removed from /tmp
It's basically a port of #10951 to the new start page implementation. Note: Icon files are not removed but re-used instead. The commit adds some new functions: * getThumbnailsImage() Returns the name of the PNG inside a project file * getThumbnailsName() Returns the directory name containing the image files * getThumnailsParentDir() Returns the parent directory of the directory containing the image files * getThumbnailsDir() Returns the path to the thumbnail directory. There is no need to always create a unique directory after each restart because it doesn't harm if the thumbnail directoy contains deprecated files. * createThumbnailsDir() Creates the thumbnail directoy if it doesn't exist yet. * getSha1Hash Helper function to compute a SHA-1 hash of a given path. If the same path is passed then the hash value will be the same. This way it can be avoided to create a different image file from a project file after each restart. * getUniquePNG Computes the path of a PNG image file for a given project file. It's also possible to pass an arbitrary string as argument. * useCachedPNG If the PNG image exists and if it's newer than the project file True is returned and False otherwise. For a given project file it is checked if the thumbnail directory already contains a cached image. If it's newer than the project file it will used, otherwise it will be re-created. Fix freecadCanOpen() abd DisplayedFilesModel::addFile() to also check for lower-case file extensions.
This commit is contained in:
@@ -23,7 +23,11 @@
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <QByteArray>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#endif
|
||||
@@ -31,6 +35,8 @@
|
||||
#include "DisplayedFilesModel.h"
|
||||
#include <App/Application.h>
|
||||
#include <App/ProjectFile.h>
|
||||
#include <Base/FileInfo.h>
|
||||
#include <Base/Stream.h>
|
||||
|
||||
using namespace Start;
|
||||
|
||||
@@ -80,6 +86,68 @@ FileStats fileInfoFromFreeCADFile(const std::string& path)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string getThumbnailsImage()
|
||||
{
|
||||
return "thumbnails/Thumbnail.png";
|
||||
}
|
||||
|
||||
QString getThumbnailsName()
|
||||
{
|
||||
return QString::fromLatin1("FreeCADStartThumbnails");
|
||||
}
|
||||
|
||||
QDir getThumnailsParentDir()
|
||||
{
|
||||
return QDir::temp();
|
||||
}
|
||||
|
||||
QString getThumbnailsDir()
|
||||
{
|
||||
QDir dir = getThumnailsParentDir();
|
||||
return dir.absoluteFilePath(getThumbnailsName());
|
||||
}
|
||||
|
||||
void createThumbnailsDir()
|
||||
{
|
||||
QString name = getThumbnailsName();
|
||||
QDir dir(getThumnailsParentDir());
|
||||
if (!dir.exists(name)) {
|
||||
dir.mkpath(name);
|
||||
}
|
||||
}
|
||||
|
||||
QString getSha1Hash(const std::string& path)
|
||||
{
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
hash.addData(path.c_str(), static_cast<int>(path.size()));
|
||||
QByteArray ba1 = hash.result().toHex();
|
||||
hash.reset();
|
||||
hash.addData(ba1);
|
||||
QByteArray ba2 = hash.result().toHex();
|
||||
return QString::fromLatin1(ba2);
|
||||
}
|
||||
|
||||
QString getUniquePNG(const std::string& path)
|
||||
{
|
||||
QDir dir = getThumbnailsDir();
|
||||
QString sha1 = getSha1Hash(path) + QLatin1String(".png");
|
||||
return dir.absoluteFilePath(sha1);
|
||||
}
|
||||
|
||||
bool useCachedPNG(const std::string& image, const std::string& project)
|
||||
{
|
||||
Base::FileInfo f1(image);
|
||||
Base::FileInfo f2(project);
|
||||
if (!f1.exists()) {
|
||||
return false;
|
||||
}
|
||||
if (!f2.exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return f1.lastModified() > f2.lastModified();
|
||||
}
|
||||
|
||||
/// Load the thumbnail image data (if any) that is stored in an FCStd file.
|
||||
/// \returns The image bytes, or an empty QByteArray (if no thumbnail was stored)
|
||||
QByteArray loadFCStdThumbnail(const std::string& pathToFCStdFile)
|
||||
@@ -87,9 +155,20 @@ QByteArray loadFCStdThumbnail(const std::string& pathToFCStdFile)
|
||||
App::ProjectFile proj(pathToFCStdFile);
|
||||
if (proj.loadDocument()) {
|
||||
try {
|
||||
std::string thumbnailFile = proj.extractInputFile("thumbnails/Thumbnail.png");
|
||||
if (!thumbnailFile.empty()) {
|
||||
auto inputFile = QFile(QString::fromStdString(thumbnailFile));
|
||||
std::string thumbnailFile = getUniquePNG(pathToFCStdFile).toStdString();
|
||||
if (!useCachedPNG(thumbnailFile, pathToFCStdFile)) {
|
||||
static std::string thumb = getThumbnailsImage();
|
||||
if (proj.containsFile(thumb)) {
|
||||
createThumbnailsDir();
|
||||
Base::FileInfo fi(thumbnailFile);
|
||||
Base::ofstream str(fi);
|
||||
proj.readInputFileDirect(thumb, str);
|
||||
str.close();
|
||||
}
|
||||
}
|
||||
|
||||
auto inputFile = QFile(QString::fromStdString(thumbnailFile));
|
||||
if (inputFile.exists()) {
|
||||
inputFile.open(QIODevice::OpenModeFlag::ReadOnly);
|
||||
return inputFile.readAll();
|
||||
}
|
||||
@@ -115,6 +194,19 @@ FileStats getFileInfo(const std::string& path)
|
||||
result.insert(std::make_pair(DisplayedFilesModelRoles::baseName, file.fileName()));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool freecadCanOpen(const QString& extension)
|
||||
{
|
||||
std::string ext = extension.toStdString();
|
||||
auto importTypes = App::GetApplication().getImportTypes();
|
||||
return std::find_if(importTypes.begin(),
|
||||
importTypes.end(),
|
||||
[&ext](const auto& item) {
|
||||
return boost::iequals(item, ext);
|
||||
})
|
||||
!= importTypes.end();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
DisplayedFilesModel::DisplayedFilesModel(QObject* parent)
|
||||
@@ -177,13 +269,6 @@ QVariant DisplayedFilesModel::data(const QModelIndex& index, int roleAsInt) cons
|
||||
return {};
|
||||
}
|
||||
|
||||
bool freecadCanOpen(const QString& extension)
|
||||
{
|
||||
auto importTypes = App::GetApplication().getImportTypes();
|
||||
return std::find(importTypes.begin(), importTypes.end(), extension.toStdString())
|
||||
!= importTypes.end();
|
||||
}
|
||||
|
||||
void DisplayedFilesModel::addFile(const QString& filePath)
|
||||
{
|
||||
QFileInfo qfi(filePath);
|
||||
@@ -194,7 +279,7 @@ void DisplayedFilesModel::addFile(const QString& filePath)
|
||||
return;
|
||||
}
|
||||
_fileInfoCache.emplace_back(getFileInfo(filePath.toStdString()));
|
||||
if (qfi.completeSuffix() == QLatin1String("FCStd")) {
|
||||
if (qfi.completeSuffix().toLower() == QLatin1String("fcstd")) {
|
||||
auto thumbnail = loadFCStdThumbnail(filePath.toStdString());
|
||||
if (!thumbnail.isEmpty()) {
|
||||
_imageCache.insert(filePath, thumbnail);
|
||||
|
||||
@@ -42,7 +42,13 @@
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
// boost
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
// Qt (should never include GUI files, only QtCore)
|
||||
#include <QByteArray>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
|
||||
Reference in New Issue
Block a user