/*************************************************************************** * Copyright (c) 2021 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library 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 Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "DlgSettingsCacheDirectory.h" #include "ui_DlgSettingsCacheDirectory.h" using namespace Gui::Dialog; /* TRANSLATOR Gui::Dialog::DlgSettingsCacheDirectory */ QString DlgSettingsCacheDirectory::currentSize; DlgSettingsCacheDirectory::DlgSettingsCacheDirectory(QWidget* parent) : PreferencePage(parent) , ui(new Ui_DlgSettingsCacheDirectory) { ui->setupUi(this); ui->labelCache->setToolTip(tr("Notify the user if the cache size exceeds the specified limit")); if (currentSize.isEmpty()) { currentSize = tr("Unknown"); } setCurrentCacheSize(currentSize); QString path = QString::fromStdString(App::Application::getUserCachePath()); ui->cacheLocation->setText(path); ui->comboBoxLimit->addItem(QStringLiteral("100 MB"), 100); ui->comboBoxLimit->addItem(QStringLiteral("300 MB"), 300); ui->comboBoxLimit->addItem(QStringLiteral("500 MB"), 500); ui->comboBoxLimit->addItem(QStringLiteral("1 GB"), 1024); ui->comboBoxLimit->addItem(QStringLiteral("2 GB"), 2048); ui->comboBoxLimit->addItem(QStringLiteral("3 GB"), 3072); connect(ui->pushButtonCheck, &QPushButton::clicked, this, &DlgSettingsCacheDirectory::runCheck); connect(ui->openButton, &QPushButton::clicked, this, &DlgSettingsCacheDirectory::openDirectory); } DlgSettingsCacheDirectory::~DlgSettingsCacheDirectory() = default; void DlgSettingsCacheDirectory::saveSettings() { ApplicationCacheSettings::setCheckPeriod(ui->comboBoxPeriod->currentIndex()); ApplicationCacheSettings::setCacheSizeLimit(ui->comboBoxLimit->currentData().toUInt()); } void DlgSettingsCacheDirectory::loadSettings() { int period = ApplicationCacheSettings::getCheckPeriod(); if (period >= 0 && period < ui->comboBoxPeriod->count()) { ui->comboBoxPeriod->setCurrentIndex(period); } unsigned int limit = ApplicationCacheSettings::getCacheSizeLimit(); int index = ui->comboBoxLimit->findData(limit); // if not found then add a new item with this value if (index < 0) { ui->comboBoxLimit->addItem(QStringLiteral("%1 MB").arg(limit), limit); index = ui->comboBoxLimit->count() - 1; } ui->comboBoxLimit->setCurrentIndex(index); } void DlgSettingsCacheDirectory::resetSettingsToDefaults() { ParameterGrp::handle hGrp; hGrp = WindowParameter::getDefaultParameter()->GetGroup("CacheDirectory"); // reset "Limit" parameter hGrp->RemoveUnsigned("Limit"); // reset "Period" parameter hGrp->RemoveInt("Period"); // finally reset all the parameters associated to Gui::Pref* widgets PreferencePage::resetSettingsToDefaults(); } void DlgSettingsCacheDirectory::changeEvent(QEvent* e) { if (e->type() == QEvent::LanguageChange) { int period = ui->comboBoxPeriod->currentIndex(); ui->retranslateUi(this); ui->comboBoxPeriod->setCurrentIndex(period); setCurrentCacheSize(currentSize); } QWidget::changeEvent(e); } void DlgSettingsCacheDirectory::setCurrentCacheSize(const QString& str) { currentSize = str; ui->labelCurrentCache->setText(tr("Current cache size: %1").arg(str)); } void DlgSettingsCacheDirectory::runCheck() { Gui::Dialog::ApplicationCache cache; unsigned int sizeInMB = ui->comboBoxLimit->currentData().toUInt(); cache.setLimit(ApplicationCache::toBytes(sizeInMB)); qint64 total = cache.size(); setCurrentCacheSize(ApplicationCache::toString(total)); // When performing the clean-up then recompute the new cache size if (cache.performAction(total)) { total = cache.size(); setCurrentCacheSize(ApplicationCache::toString(total)); } } void DlgSettingsCacheDirectory::openDirectory() { QString path = QString::fromStdString(App::Application::getUserCachePath()); QUrl url = QUrl::fromLocalFile(path); QDesktopServices::openUrl(url); } // ---------------------------------------------------------------------------- ApplicationCache::ApplicationCache() { limit = std::pow(1024, 3); setPeriod(Period::Weekly); } /*! * \brief ApplicationCache::setPeriod * Set the period to check for the cache size * \param period */ void ApplicationCache::setPeriod(ApplicationCache::Period period) { switch (period) { case Period::Always: numDays = -1; break; case Period::Daily: numDays = 1; break; case Period::Weekly: numDays = 7; break; case Period::Monthly: numDays = 31; break; case Period::Yearly: numDays = 365; break; case Period::Never: numDays = std::numeric_limits::max(); break; } } /*! * \brief ApplicationCache::setLimit * Set the limit in bytes to perform a check * \param value */ void ApplicationCache::setLimit(qint64 value) { limit = value; } /*! * \brief ApplicationCache::periodicCheckOfSize * Checks if the periodic check should be performed now * \return */ bool ApplicationCache::periodicCheckOfSize() const { QString vendor = QString::fromLatin1(App::Application::Config()["ExeVendor"].c_str()); QString application = QString::fromStdString(App::Application::getExecutableName()); QSettings settings(vendor, application); QString key = QStringLiteral("LastCacheCheck"); QDate date = settings.value(key).toDate(); QDate now = QDate::currentDate(); // get the days since the last check int days = date.daysTo(now); if (date.isNull()) { days = 1000; } if (days >= numDays) { settings.setValue(key, now); return true; } return false; } /*! * \brief ApplicationCache::performAction * If the cache size \a total is higher than the limit then show a dialog to the user * \param total */ bool ApplicationCache::performAction(qint64 total) { bool performed = false; if (total > limit) { QString path = QString::fromStdString(App::Application::getUserCachePath()); QMessageBox msgBox(Gui::getMainWindow()); msgBox.setIcon(QMessageBox::Warning); msgBox.setWindowTitle(tr("Cache Directory")); QString hint = tr("The cache directory %1 exceeds the size of %2.") .arg(path, ApplicationCache::toString(limit)); QString ask = tr("Clear it now?"); QString warn = tr("Warning: Make sure that this is the only running %1 instance " "and that no documents are opened as this may result into data loss!") .arg(QCoreApplication::applicationName()); msgBox.setText(QStringLiteral("%1 %2\n\n\n%3").arg(hint, ask, warn)); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Open); msgBox.setDefaultButton(QMessageBox::No); while (true) { int ret = msgBox.exec(); if (ret == QMessageBox::Open) { QUrl url = QUrl::fromLocalFile(path); QDesktopServices::openUrl(url); } else { if (ret == QMessageBox::Yes) { clearDirectory(path); performed = true; } break; } } } return performed; } /*! * \brief ApplicationCache::size * Determines the size of the cache. * \return */ qint64 ApplicationCache::size() const { qint64 total = dirSize(QString::fromStdString(App::Application::getUserCachePath())); return total; } /*! * \internal */ void ApplicationCache::clearDirectory(const QString& path) { // Add the transient directories and the lock files to the ignore list QDir tmp = QString::fromUtf8(App::Application::getUserCachePath().c_str()); tmp.setNameFilters(QStringList() << QStringLiteral("*.lock")); tmp.setFilter(QDir::Files); QList dirs; std::vector docs = App::GetApplication().getDocuments(); for (auto it : docs) { QDir dir(QString::fromStdString(it->TransientDir.getStrValue())); QFileInfo fi(dir.absolutePath()); dirs.append(fi); } DocumentRecoveryCleaner cleaner; cleaner.setIgnoreFiles(tmp.entryList()); cleaner.setIgnoreDirectories(dirs); cleaner.clearDirectory(QFileInfo(path)); } /*! * \internal */ qint64 ApplicationCache::dirSize(QString dirPath) const { qint64 total = 0; QDir dir(dirPath); QDir::Filters fileFilters = QDir::Files; const auto& files = dir.entryList(fileFilters); for (const QString& filePath : files) { QFileInfo fi(dir, filePath); total += fi.size(); } // traverse sub-directories recursively QDir::Filters dirFilters = QDir::Dirs | QDir::NoDotAndDotDot; const auto& dirs = dir.entryList(dirFilters); for (const QString& subDirPath : dirs) { total += dirSize(dirPath + QDir::separator() + subDirPath); } return total; } /*! * \brief ApplicationCache::applyUserSettings * Set period and limit according to user settings */ void ApplicationCache::applyUserSettings() { int period = ApplicationCacheSettings::getCheckPeriod(); setPeriod(static_cast(period)); unsigned int sizeInMB = ApplicationCacheSettings::getCacheSizeLimit(); setLimit(ApplicationCache::toBytes(sizeInMB)); } qint64 ApplicationCache::toBytes(unsigned int sizeInMB) { qint64 value = static_cast(sizeInMB) * 1024 * 1024; return value; } QString ApplicationCache::toString(qint64 size) { QStringList units = {QStringLiteral("Bytes"), QStringLiteral("KB"), QStringLiteral("MB"), QStringLiteral("GB")}; int i; double outputSize = size; for (i = 0; i < units.size() - 1; i++) { if (outputSize < 1024) { break; } outputSize /= 1024; } return QStringLiteral("%1 %2").arg(QLocale().toString(outputSize, 'f', 2), units[i]); } // ---------------------------------------------------------------------------- unsigned int ApplicationCacheSettings::getCacheSizeLimit() { ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("CacheDirectory"); return hGrp->GetUnsigned("Limit", 500); } void ApplicationCacheSettings::setCacheSizeLimit(unsigned int limit) { ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("CacheDirectory"); hGrp->SetUnsigned("Limit", limit); } int ApplicationCacheSettings::getCheckPeriod() { ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("CacheDirectory"); return hGrp->GetInt("Period", static_cast(ApplicationCache::Period::Weekly)); } void ApplicationCacheSettings::setCheckPeriod(int period) { ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("CacheDirectory"); hGrp->SetInt("Period", period); } #include "moc_DlgSettingsCacheDirectory.cpp"