aboutsummaryrefslogtreecommitdiff
path: root/lib/util.h
blob: 2a323cf342db2f43fbac78f16c43a0a0782d01c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/******************************************************************************
 * Copyright (C) 2016 Kitsune Ral <kitsune-ral@users.sf.net>
 *
 * This library 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 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#pragma once

#include <QtCore/QMetaEnum>
#include <QtCore/QDebug>
#include <QtCore/QPointer>

#include <functional>
#include <memory>

namespace QMatrixClient
{
    // The below enables pretty-printing of enums in logs
#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
#define REGISTER_ENUM(EnumName) Q_ENUM(EnumName)
#else
    // Thanks to Olivier for spelling it and for making Q_ENUM to replace it:
    // https://woboq.com/blog/q_enum.html
#define REGISTER_ENUM(EnumName) \
    Q_ENUMS(EnumName) \
    friend QDebug operator<<(QDebug dbg, EnumName val) \
    { \
        static int enumIdx = staticMetaObject.indexOfEnumerator(#EnumName); \
        return dbg << Event::staticMetaObject.enumerator(enumIdx).valueToKey(int(val)); \
    }
#endif

    /** static_cast<> for unique_ptr's */
    template <typename T1, typename PtrT2>
    inline auto unique_ptr_cast(PtrT2&& p)
    {
        return std::unique_ptr<T1>(static_cast<T1*>(p.release()));
    }

#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
    // Copy-pasted from Qt 5.10
    template <typename T>
    Q_DECL_CONSTEXPR typename std::add_const<T>::type &qAsConst(T &t) Q_DECL_NOTHROW { return t; }
    // prevent rvalue arguments:
    template <typename T>
    static void qAsConst(const T &&) Q_DECL_EQ_DELETE;
#endif

    /** A guard pointer that disconnects an interested object upon destruction
     * It's almost QPointer<> except that you have to initialise it with one
     * more additional parameter - a pointer to a QObject that will be
     * disconnected from signals of the underlying pointer upon the guard's
     * destruction.
     */
    template <typename T>
    class ConnectionsGuard : public QPointer<T>
    {
        public:
            ConnectionsGuard(T* publisher, QObject* subscriber)
                : QPointer<T>(publisher), subscriber(subscriber)
            { }
            ~ConnectionsGuard()
            {
                if (*this)
                    (*this)->disconnect(subscriber);
            }
            ConnectionsGuard(ConnectionsGuard&&) noexcept = default;
            ConnectionsGuard& operator=(ConnectionsGuard&&) noexcept = default;
            ConnectionsGuard& operator=(const ConnectionsGuard&) = delete;
            using QPointer<T>::operator=;

        private:
            QObject* subscriber;
    };
}  // namespace QMatrixClient