fix: compiler warnings

Mostly QFutureWatcher leaks, fixed by using QFuture.then
Also calculator false positive leak
This commit is contained in:
2 * r + 2 * t 2026-03-24 02:33:25 +11:00
parent a034467ed2
commit 501a14bd2a
5 changed files with 26 additions and 55 deletions

View file

@ -105,34 +105,26 @@ void CachingImageManager::updateSource(const QString& path) {
m_shaPath = path; m_shaPath = path;
const auto future = QtConcurrent::run(&CachingImageManager::sha256sum, path); QtConcurrent::run(&CachingImageManager::sha256sum, path).then(this, [path, this](const QString& sha) {
const auto watcher = new QFutureWatcher<QString>(this);
connect(watcher, &QFutureWatcher<QString>::finished, this, [watcher, path, this]() {
if (m_path != path) { if (m_path != path) {
// Object is destroyed or path has changed, ignore
watcher->deleteLater();
return; return;
} }
const QSize size = effectiveSize(); const QSize size = effectiveSize();
if (!m_item || !size.width() || !size.height()) { if (!m_item || !size.width() || !size.height()) {
watcher->deleteLater();
return; return;
} }
const QString fillMode = m_item->property("fillMode").toString(); const QString fillMode = m_item->property("fillMode").toString();
// clang-format off // clang-format off
const QString filename = QString("%1@%2x%3-%4.png") const QString filename = QString("%1@%2x%3-%4.png")
.arg(watcher->result()).arg(size.width()).arg(size.height()) .arg(sha).arg(size.width()).arg(size.height())
.arg(fillMode == "PreserveAspectCrop" ? "crop" : fillMode == "PreserveAspectFit" ? "fit" : "stretch"); .arg(fillMode == "PreserveAspectCrop" ? "crop" : fillMode == "PreserveAspectFit" ? "fit" : "stretch");
// clang-format on // clang-format on
const QUrl cache = m_cacheDir.resolved(QUrl(filename)); const QUrl cache = m_cacheDir.resolved(QUrl(filename));
if (m_cachePath == cache) { if (m_cachePath == cache) {
watcher->deleteLater();
return; return;
} }
@ -141,7 +133,6 @@ void CachingImageManager::updateSource(const QString& path) {
if (!cache.isLocalFile()) { if (!cache.isLocalFile()) {
qWarning() << "CachingImageManager::updateSource: cachePath" << cache << "is not a local file"; qWarning() << "CachingImageManager::updateSource: cachePath" << cache << "is not a local file";
watcher->deleteLater();
return; return;
} }
@ -157,11 +148,7 @@ void CachingImageManager::updateSource(const QString& path) {
if (m_shaPath == path) { if (m_shaPath == path) {
m_shaPath = QString(); m_shaPath = QString();
} }
watcher->deleteLater();
}); });
watcher->setFuture(future);
} }
QUrl CachingImageManager::cachePath() const { QUrl CachingImageManager::cachePath() const {

View file

@ -219,7 +219,7 @@ void FileSystemModel::watchDirIfRecursive(const QString& path) {
if (m_recursive && m_watchChanges) { if (m_recursive && m_watchChanges) {
const auto currentDir = m_dir; const auto currentDir = m_dir;
const bool showHidden = m_showHidden; const bool showHidden = m_showHidden;
const auto future = QtConcurrent::run([showHidden, path]() { auto future = QtConcurrent::run([showHidden, path]() {
QDir::Filters filters = QDir::Dirs | QDir::NoDotAndDotDot; QDir::Filters filters = QDir::Dirs | QDir::NoDotAndDotDot;
if (showHidden) { if (showHidden) {
filters |= QDir::Hidden; filters |= QDir::Hidden;
@ -232,16 +232,12 @@ void FileSystemModel::watchDirIfRecursive(const QString& path) {
} }
return dirs; return dirs;
}); });
const auto watcher = new QFutureWatcher<QStringList>(this); future.then(this, [currentDir, showHidden, this](const QStringList& paths) {
connect(watcher, &QFutureWatcher<QStringList>::finished, this, [currentDir, showHidden, watcher, this]() {
const auto paths = watcher->result();
if (currentDir == m_dir && showHidden == m_showHidden && !paths.isEmpty()) { if (currentDir == m_dir && showHidden == m_showHidden && !paths.isEmpty()) {
// Ignore if dir or showHidden has changed // Ignore if dir or showHidden has changed
m_watcher.addPaths(paths); m_watcher.addPaths(paths);
} }
watcher->deleteLater();
}); });
watcher->setFuture(future);
} }
} }
@ -295,7 +291,7 @@ void FileSystemModel::updateEntriesForDir(const QString& dir) {
oldPaths << entry->path(); oldPaths << entry->path();
} }
const auto future = QtConcurrent::run([=](QPromise<QPair<QSet<QString>, QSet<QString>>>& promise) { auto future = QtConcurrent::run([=](QPromise<QPair<QSet<QString>, QSet<QString>>>& promise) {
const auto flags = recursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags; const auto flags = recursive ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags;
std::optional<QDirIterator> iter; std::optional<QDirIterator> iter;
@ -353,7 +349,7 @@ void FileSystemModel::updateEntriesForDir(const QString& dir) {
newPaths.insert(path); newPaths.insert(path);
} }
if (promise.isCanceled() || newPaths == oldPaths) { if (promise.isCanceled()) {
return; return;
} }
@ -365,23 +361,17 @@ void FileSystemModel::updateEntriesForDir(const QString& dir) {
} }
m_futures.insert(dir, future); m_futures.insert(dir, future);
const auto watcher = new QFutureWatcher<QPair<QSet<QString>, QSet<QString>>>(this); future
.then(this,
connect(watcher, &QFutureWatcher<QPair<QSet<QString>, QSet<QString>>>::finished, this, [dir, watcher, this]() { [dir, this](QPair<QSet<QString>, QSet<QString>> result) {
m_futures.remove(dir); m_futures.remove(dir);
if (!result.first.isEmpty() || !result.second.isEmpty()) {
if (!watcher->future().isResultReadyAt(0)) { applyChanges(result.first, result.second);
watcher->deleteLater(); }
return; })
} .onCanceled(this, [dir, this]() {
m_futures.remove(dir);
const auto result = watcher->result(); });
applyChanges(result.first, result.second);
watcher->deleteLater();
});
watcher->setFuture(future);
} }
void FileSystemModel::applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths) { void FileSystemModel::applyChanges(const QSet<QString>& removedPaths, const QSet<QString>& addedPaths) {

View file

@ -221,7 +221,7 @@ AudioCollector::AudioCollector(QObject* parent)
, m_writeBuffer(&m_buffer2) {} , m_writeBuffer(&m_buffer2) {}
AudioCollector::~AudioCollector() { AudioCollector::~AudioCollector() {
stop(); AudioCollector::stop();
} }
void AudioCollector::start() { void AudioCollector::start() {

View file

@ -11,7 +11,7 @@ AppEntry::AppEntry(QObject* entry, unsigned int frequency, QObject* parent)
, m_entry(entry) , m_entry(entry)
, m_frequency(frequency) { , m_frequency(frequency) {
const auto mo = m_entry->metaObject(); const auto mo = m_entry->metaObject();
const auto tmo = metaObject(); const auto tmo = &AppEntry::staticMetaObject;
for (const auto& prop : for (const auto& prop :
{ "name", "comment", "execString", "startupClass", "genericName", "categories", "keywords" }) { { "name", "comment", "execString", "startupClass", "genericName", "categories", "keywords" }) {

View file

@ -1,7 +1,6 @@
#include "qalculator.hpp" #include "qalculator.hpp"
#include <libqalculate/qalculate.h> #include <libqalculate/qalculate.h>
#include <qfuturewatcher.h>
#include <qtconcurrentrun.h> #include <qtconcurrentrun.h>
namespace caelestia { namespace caelestia {
@ -11,7 +10,10 @@ QMutex Qalculator::s_calculatorMutex;
Qalculator::Qalculator(QObject* parent) Qalculator::Qalculator(QObject* parent)
: QObject(parent) { : QObject(parent) {
if (!CALCULATOR) { if (!CALCULATOR) {
new Calculator(); // Calculator constructor sets the global `calculator` pointer (CALCULATOR macro),
// but we need to assign it to a var so compiler doesn't flag it as a leak
static const auto* const instance = new Calculator();
Q_UNUSED(instance)
CALCULATOR->loadExchangeRates(); CALCULATOR->loadExchangeRates();
CALCULATOR->loadGlobalDefinitions(); CALCULATOR->loadGlobalDefinitions();
CALCULATOR->loadLocalDefinitions(); CALCULATOR->loadLocalDefinitions();
@ -79,7 +81,7 @@ void Qalculator::evalAsync(const QString& expr) {
emit busyChanged(); emit busyChanged();
} }
const auto future = QtConcurrent::run([expr]() -> QPair<QString, QString> { QtConcurrent::run([expr]() -> QPair<QString, QString> {
QMutexLocker locker(&s_calculatorMutex); QMutexLocker locker(&s_calculatorMutex);
EvaluationOptions eo; EvaluationOptions eo;
@ -109,18 +111,12 @@ void Qalculator::evalAsync(const QString& expr) {
const QString rawStr = QString::fromStdString(result); const QString rawStr = QString::fromStdString(result);
return { QString("%1 = %2").arg(parsed).arg(result), rawStr }; return { QString("%1 = %2").arg(parsed).arg(result), rawStr };
}); }).then(this, [this, gen](QPair<QString, QString> result) {
auto* watcher = new QFutureWatcher<QPair<QString, QString>>(this);
connect(watcher, &QFutureWatcher<QPair<QString, QString>>::finished, this, [this, watcher, gen]() {
watcher->deleteLater();
if (gen != m_generation) { if (gen != m_generation) {
return; return;
} }
const auto [formatted, raw] = watcher->result(); const auto& [formatted, raw] = result;
if (m_result != formatted) { if (m_result != formatted) {
m_result = formatted; m_result = formatted;
@ -135,8 +131,6 @@ void Qalculator::evalAsync(const QString& expr) {
emit busyChanged(); emit busyChanged();
} }
}); });
watcher->setFuture(future);
} }
QString Qalculator::result() const { QString Qalculator::result() const {