File size: 4,227 Bytes
985c397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************

 *                                                                          *

 *   Copyright (c) 2025 The FreeCAD Project Association AISBL               *

 *                                                                          *

 *   This file is part of FreeCAD.                                          *

 *                                                                          *

 *   FreeCAD is free software: you can redistribute it and/or modify it     *

 *   under the terms of the GNU Lesser General Public License as            *

 *   published by the Free Software Foundation, either version 2.1 of the   *

 *   License, or (at your option) any later version.                        *

 *                                                                          *

 *   FreeCAD is distributed in the hope that it will be useful, but         *

 *   WITHOUT ANY WARRANTY; without even the implied warranty of             *

 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU       *

 *   Lesser General Public License for more details.                        *

 *                                                                          *

 *   You should have received a copy of the GNU Lesser General Public       *

 *   License along with FreeCAD. If not, see                                *

 *   <https://www.gnu.org/licenses/>.                                       *

 *                                                                          *

 ***************************************************************************/

#include <QCryptographicHash>
#include <QDateTime>
#include <QFileInfo>
#include <QString>
#include <QTimeZone>
#include <QUrl>
#include <fmt/format.h>

#include "FileUtilities.h"
#include <Base/TimeInfo.h>


void Start::createThumbnailsDir()

{
    if (!thumbnailsParentDir.exists(defaultThumbnailName)) {
        thumbnailsParentDir.mkpath(defaultThumbnailName);
    }
}

QString Start::getMD5Hash(const QString& path)

{
    // Use MD5 hash as specified here:
    // https://specifications.freedesktop.org/thumbnail-spec/0.8.0/thumbsave.html
    QUrl url(path);
    url.setScheme(QStringLiteral("file"));
    QCryptographicHash hash(QCryptographicHash::Md5);
    hash.addData(url.toEncoded());
    const QByteArray ba = hash.result().toHex();
    return QString::fromLatin1(ba);
}

QString Start::getPathToCachedThumbnail(const QString& path)

{
    const QString md5 = getMD5Hash(path) + QLatin1String(".png");
    return thumbnailsDir.absoluteFilePath(md5);
}

bool Start::useCachedThumbnail(const QString& image, const QString& project)

{
    const QFileInfo f1(image);
    const QFileInfo f2(project);
    if (!f1.exists()) {
        return false;
    }
    if (!f2.exists()) {
        return false;
    }

    return f1.lastModified() > f2.lastModified();
}

std::string Start::humanReadableSize(uint64_t bytes)

{
    if (bytes == 0) {
        return "0 B";
    }

    // uint64_t can't express numbers higher than the EB range (< 20 EB)
    constexpr std::array units {"B", "kB", "MB", "GB", "TB", "PB", "EB"};
    constexpr double unitFactor = 1000.0;

    const double logBaseFactor = std::log10(unitFactor);  // change to constexpr on c++26
    const auto unitIndex = static_cast<size_t>(std::log10(bytes) / logBaseFactor);

    // unitIndex can't be out of range because uint64_t can't express numbers higher than the EB
    // range
    const auto unit = units.at(unitIndex);

    const double scaledValue = static_cast<double>(bytes) / std::pow(unitFactor, unitIndex);

    const bool isByteUnit = unitIndex == 0;
    const size_t precision = isByteUnit ? 0 : 1;
    return fmt::format("{:.{}f} {}", scaledValue, precision, unit);
}

std::string Start::getLastModifiedAsString(const Base::FileInfo& file)

{
    Base::TimeInfo lastModified = file.lastModified();
    return QDateTime::fromSecsSinceEpoch(lastModified.getTime_t())
        .toTimeZone(QTimeZone::utc())
        .toString(Qt::ISODate)
        .toStdString();
}