diff --git a/CMakeLists.txt b/CMakeLists.txt
index f6fc684..cbb6231 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,7 +3,7 @@ cmake_policy(SET CMP0017 NEW) # need include() with .cmake
cmake_policy(SET CMP0072 NEW) # FindOpenGL prefers GLVND by default
project(QAD)
set(QAD_MAJOR 2)
-set(QAD_MINOR 24)
+set(QAD_MINOR 25)
set(QAD_REVISION 0)
set(QAD_SUFFIX )
set(QAD_COMPANY SHS)
diff --git a/libs/piqt/qad_timers.cpp b/libs/piqt/qad_timers.cpp
new file mode 100644
index 0000000..933dcc2
--- /dev/null
+++ b/libs/piqt/qad_timers.cpp
@@ -0,0 +1 @@
+#include "qad_timers.h"
diff --git a/libs/piqt/qad_timers.h b/libs/piqt/qad_timers.h
new file mode 100644
index 0000000..786fe3d
--- /dev/null
+++ b/libs/piqt/qad_timers.h
@@ -0,0 +1,76 @@
+/*
+ QAD - Qt ADvanced
+
+ Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
+
+ This program 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 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 this program. If not, see .
+*/
+
+#ifndef qad_timers_H
+#define qad_timers_H
+
+#include "qad_utils_export.h"
+
+#include
+#include
+#include
+#include
+
+
+template
+class QAD_UTILS_EXPORT IndexedTimer {
+public:
+ ~IndexedTimer() {
+ for (auto & i: timers)
+ i.destroy();
+ timers.clear();
+ }
+
+ void bindIndexedTimer(Index index, std::function func) { timers[index].func = func; }
+ void stopIndexedTimer(Index index) {
+ auto & t(timers[index]);
+ if (!t.isValid()) return;
+ t.destroy();
+ }
+ void startIndexedTimer(Index index, PISystemTime interval, std::function func = nullptr) {
+ stopIndexedTimer(index);
+ __TimerSlot & t(timers[index]);
+ if (func) t.func = func;
+ if (!t.func) {
+ qDebug() << "[IndexedTimer] startIndexedTimer error: null function!";
+ return;
+ }
+ t.timer = new QTimer();
+ QObject::connect(t.timer, &QTimer::timeout, t.func);
+ t.timer->start(interval.toMilliseconds());
+ }
+ bool isIndexedTimerStarted(Index index) const { return timers.value(index).isValid(); }
+
+private:
+ struct __TimerSlot {
+ bool isValid() const { return timer; }
+ void destroy() {
+ if (!timer) return;
+ delete timer;
+ timer = nullptr;
+ }
+ std::function func = nullptr;
+ QTimer * timer = nullptr;
+ };
+
+ QMap timers;
+};
+
+
+#endif