Skip to content

Commit

Permalink
Start: fixes FreeCAD#17857: Icon-files of the startup screen are not …
Browse files Browse the repository at this point in the history
…removed from /tmp

It's basically a port of FreeCAD#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.
  • Loading branch information
wwmayer authored and chennes committed Nov 20, 2024
1 parent 22782e5 commit 2819ca4
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 11 deletions.
107 changes: 96 additions & 11 deletions src/Mod/Start/App/DisplayedFilesModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,20 @@

#include "PreCompiled.h"
#ifndef _PreComp_
#include <boost/algorithm/string/predicate.hpp>
#include <QByteArray>
#include <QCryptographicHash>
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#endif

#include "DisplayedFilesModel.h"
#include <App/Application.h>
#include <App/ProjectFile.h>
#include <Base/FileInfo.h>
#include <Base/Stream.h>

using namespace Start;

Expand Down Expand Up @@ -80,16 +86,89 @@ 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)
{
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();
}
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions src/Mod/Start/App/PreCompiled.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down

0 comments on commit 2819ca4

Please sign in to comment.