235 lines
6.3 KiB
C++
235 lines
6.3 KiB
C++
#ifndef UTILS_HPP
|
|
#define UTILS_HPP
|
|
|
|
// #include "tierrow.hpp"
|
|
|
|
#include <optional>
|
|
|
|
#include <QWidget>
|
|
#include <QString>
|
|
#include <QException>
|
|
|
|
//change this stupid name
|
|
inline void callOnMeAndChildren(QObject* obj, void (*func)(QObject*))
|
|
{
|
|
func(obj);
|
|
for (auto w : obj->children())
|
|
{
|
|
callOnMeAndChildren(w, func);
|
|
}
|
|
}
|
|
template <typename T>
|
|
void callOnMeAndChildren(QObject* obj, void (*func)(T*))
|
|
{
|
|
if (auto casted = dynamic_cast<T*>(obj))
|
|
{
|
|
func(casted);
|
|
}
|
|
for (auto w : obj->children())
|
|
{
|
|
callOnMeAndChildren(w, func);
|
|
}
|
|
}
|
|
|
|
inline QString makeBgColorString(QColor color)
|
|
{
|
|
return QString("background-color: rgba(%1,%2,%3,%4)")
|
|
.arg(QString::number(color.red()),
|
|
QString::number(color.green()),
|
|
QString::number(color.blue()),
|
|
QString::number(color.alphaF()));
|
|
}
|
|
|
|
template <typename T>
|
|
T* findParentOfType(QObject* obj)
|
|
{
|
|
auto parent = obj->parent();
|
|
if (!parent)
|
|
return nullptr;
|
|
else if (auto asT = dynamic_cast<T*>(parent))
|
|
{
|
|
return asT;
|
|
}
|
|
else
|
|
{
|
|
return findParentOfType<T>(parent);
|
|
}
|
|
}
|
|
|
|
inline QColor blend(QColor first, QColor second, float portionFirst)
|
|
{
|
|
const float& pf = portionFirst;
|
|
const float ps = 1 - pf;
|
|
return QColor(
|
|
first.red()*pf + second.red()*ps,
|
|
first.green()*pf + second.green()*ps,
|
|
first.blue()*pf + second.blue()*ps
|
|
);
|
|
}
|
|
|
|
inline QPoint midpoint(QWidget* wid)
|
|
{
|
|
const auto& size = wid->size();
|
|
return QPoint(size.width() / 2,
|
|
size.height() / 2);
|
|
}
|
|
|
|
inline QPoint midpoint(QSize size)
|
|
{
|
|
return QPoint(size.width() / 2,
|
|
size.height() / 2);
|
|
}
|
|
|
|
class InvalidEnumException : public QException
|
|
{
|
|
public:
|
|
InvalidEnumException(int value, QString type = "")
|
|
: type(type), value(value)
|
|
{
|
|
_what = InvalidEnumException::_makeWhat(value, type).toLocal8Bit();
|
|
}
|
|
template<typename T,
|
|
typename = std::enable_if<std::is_enum_v<T>>>
|
|
InvalidEnumException(T value, QString type)
|
|
: InvalidEnumException(static_cast<int>(value), type)
|
|
{
|
|
|
|
}
|
|
const char* what() const noexcept override
|
|
{
|
|
return _what.data();
|
|
}
|
|
private:
|
|
const QString type;
|
|
const int value;
|
|
QByteArray _what;
|
|
inline static QString _makeWhat(int value, QString type)
|
|
{
|
|
QString str;
|
|
if (!type.isEmpty())
|
|
str = "Type: " + type + " ";
|
|
str += "Value: " + QString::number(value);
|
|
return str;
|
|
}
|
|
};
|
|
|
|
enum class ComparePoint
|
|
{
|
|
TopLeft,
|
|
TopCenter,
|
|
TopRight,
|
|
MiddleLeft,
|
|
MiddleCenter,
|
|
MiddleRight,
|
|
BottomLeft,
|
|
BottomCenter,
|
|
BottomRight,
|
|
};
|
|
|
|
constexpr std::tuple<float, float> compareMultiplier(ComparePoint point)
|
|
{
|
|
switch (point)
|
|
{
|
|
case ComparePoint::TopLeft: return {0, 0};
|
|
case ComparePoint::TopCenter: return {0.5, 0};
|
|
case ComparePoint::TopRight: return {1, 0};
|
|
case ComparePoint::MiddleLeft: return {0, 0.5};
|
|
case ComparePoint::MiddleCenter: return {0.5, 0.5};
|
|
case ComparePoint::MiddleRight: return {1, 0.5};
|
|
case ComparePoint::BottomLeft: return {0, 1};
|
|
case ComparePoint::BottomCenter: return {0.5, 1};
|
|
case ComparePoint::BottomRight: return {1, 1};
|
|
default: throw InvalidEnumException(point, "ComparePoint");
|
|
}
|
|
}
|
|
|
|
constexpr QPoint getPoint(QSize size, ComparePoint point)
|
|
{
|
|
const auto scale = compareMultiplier(point);
|
|
return QPoint(size.width() * std::get<0>(scale),
|
|
size.height() * std::get<1>(scale));
|
|
}
|
|
|
|
constexpr QPoint getPoint(QRect rect, ComparePoint point)
|
|
{
|
|
return rect.topLeft() + getPoint(rect.size(), point);
|
|
}
|
|
|
|
constexpr QPoint getPoint(QWidget* wid, ComparePoint point)
|
|
{
|
|
return getPoint(wid->geometry(), point);
|
|
}
|
|
|
|
constexpr bool isAfter(QPointF reference, QPointF test,
|
|
[[maybe_unused]] ComparePoint point)
|
|
{
|
|
if (test.y() > reference.y())
|
|
return true;
|
|
return test.x() > reference.x();
|
|
}
|
|
|
|
inline bool isAfter(QWidget* reference, QPointF test, ComparePoint point)
|
|
{
|
|
// const auto scale = compareMultiplier(point);
|
|
// const auto ref = reference->pos() + QPoint(reference->size().width() * std::get<0>(scale),
|
|
// reference->size().height() * std::get<1>(scale));
|
|
const auto ref = getPoint(reference, point);
|
|
return isAfter(ref, test, point);
|
|
}
|
|
|
|
inline bool isAfter(QPointF reference, QWidget* test, ComparePoint point)
|
|
{
|
|
// const auto scale = compareMultiplier(point);
|
|
// const auto tst = test->pos() + QPoint(test->size().width() * std::get<0>(scale),
|
|
// test->size().height() * std::get<1>(scale));
|
|
const auto tst = getPoint(test, point);
|
|
return isAfter(reference, tst, point);
|
|
}
|
|
|
|
inline bool isAfter(QWidget* reference, QWidget* test, ComparePoint point)
|
|
{
|
|
// const auto scale = compareMultiplier(point);
|
|
// const auto tst = test->pos() + QPoint(test->size().width() * std::get<0>(scale),
|
|
// test->size().height() * std::get<1>(scale));
|
|
const auto tst = getPoint(test, point);
|
|
return isAfter(reference, tst, point);
|
|
}
|
|
|
|
class IndexOutOfRangeException : public QException
|
|
{
|
|
public:
|
|
IndexOutOfRangeException(qsizetype index,
|
|
std::optional<qsizetype> min, std::optional<qsizetype> max)
|
|
: index(index), min(min), max(max)
|
|
{
|
|
QString str = "";
|
|
str += "Value: " + QString::number(index);
|
|
if (min.has_value())
|
|
str += " Min: " + QString::number(min.value());
|
|
if (max.has_value())
|
|
str += " Max: " + QString::number(max.value());
|
|
_what = str.toLocal8Bit();
|
|
}
|
|
const char* what() const noexcept override
|
|
{
|
|
return _what.data();
|
|
}
|
|
//assumes inclusive
|
|
static void ThrowIf(qsizetype index,
|
|
std::optional<qsizetype> min, std::optional<qsizetype> max)
|
|
{
|
|
if ((min.has_value() && index < min.value()) ||
|
|
(max.has_value() && index > max.value()))
|
|
{
|
|
throw IndexOutOfRangeException(index, min, max);
|
|
}
|
|
}
|
|
private:
|
|
const qsizetype index;
|
|
const std::optional<qsizetype> min;
|
|
const std::optional<qsizetype> max;
|
|
QByteArray _what;
|
|
};
|
|
|
|
#endif // UTILS_HPP
|