diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp index 5ec8dcf16..ca55c7b41 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_update.cpp @@ -171,11 +171,13 @@ void DlgUpdate::finishedUpdateCheck(bool needToUpdate, bool isCompatible, Releas publishDate = release->getPublishDate().toString(QLocale().dateFormat(QLocale::LongFormat)); if (isCompatible) { - if (QtUtils::confirm(window(), tr("Update Available"), - tr("A new version of Cockatrice is available!") + "

" + "" + tr("New version") + - QString(": %1
").arg(release->getName()) + "" + tr("Released") + - QString(": %1 (").arg(publishDate, release->getDescriptionUrl()) + - tr("Changelog") + ")

" + tr("Do you want to update now?"))) { + const QString message = tr("A new version of Cockatrice is available!") + "

" + "" + + tr("New version") + QString(": %1
").arg(release->getName()) + "" + + tr("Released") + + QString(": %1 (").arg(publishDate, release->getDescriptionUrl()) + + tr("Changelog") + ")

" + tr("Do you want to update now?"); + + if (QtUtils::confirm(window(), tr("Update Available"), message)) { downloadUpdate(release->getName()); } else { closeDialog(); diff --git a/libcockatrice_utility/CMakeLists.txt b/libcockatrice_utility/CMakeLists.txt index cc0168cb8..748f6b90f 100644 --- a/libcockatrice_utility/CMakeLists.txt +++ b/libcockatrice_utility/CMakeLists.txt @@ -21,6 +21,7 @@ set(UTILITY_HEADERS libcockatrice/utility/card_ref.h libcockatrice/utility/color.h libcockatrice/utility/cryptoutil.h + libcockatrice/utility/debouncer.h libcockatrice/utility/expression.h libcockatrice/utility/levenshtein.h libcockatrice/utility/local_server_name.h diff --git a/libcockatrice_utility/libcockatrice/utility/debouncer.h b/libcockatrice_utility/libcockatrice/utility/debouncer.h new file mode 100644 index 000000000..54635db4f --- /dev/null +++ b/libcockatrice_utility/libcockatrice/utility/debouncer.h @@ -0,0 +1,62 @@ +#ifndef COCKATRICE_DEBOUNCER_H +#define COCKATRICE_DEBOUNCER_H + +#include +#include +#include +#include + +namespace QtUtils +{ +/** + * @brief Runs the most recent call() after a period without further calls. + * + * Typical use is coalescing rapid model or editor updates into one refresh: + * + * debouncer.call([this] { refresh(); }); + * + * The pending callback is owned by the debouncer and replaced when call() is invoked + * again. The debouncer must outlive any callback it schedules; parenting it to the + * owning widget is usually enough. + */ +class Debouncer : public QObject +{ +public: + explicit Debouncer(int intervalMs, QObject *parent = nullptr) : QObject(parent) + { + timer.setSingleShot(true); + timer.setInterval(intervalMs); + connect(&timer, &QTimer::timeout, this, [this] { + if (callback) { + auto pending = std::move(callback); + callback = nullptr; + pending(); + } + }); + } + + /** + * @brief Schedules @p newCallback, replacing any callback not run yet. + */ + void call(std::function newCallback) + { + callback = std::move(newCallback); + timer.start(); + } + + /** + * @brief Drops the pending callback and stops the timer. + */ + void cancel() + { + timer.stop(); + callback = nullptr; + } + +private: + QTimer timer; + std::function callback; +}; +} // namespace QtUtils + +#endif // COCKATRICE_DEBOUNCER_H