| File: | usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h |
| Warning: | line 319, column 9 Potential memory leak |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* workspace_state.cpp | |||
| 2 | * | |||
| 3 | * Wireshark - Network traffic analyzer | |||
| 4 | * By Gerald Combs <[email protected]> | |||
| 5 | * Copyright 1998 Gerald Combs | |||
| 6 | * | |||
| 7 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
| 8 | */ | |||
| 9 | ||||
| 10 | #include "config.h" | |||
| 11 | ||||
| 12 | #include "workspace_state.h" | |||
| 13 | ||||
| 14 | #include <algorithm> | |||
| 15 | #include <QFile> | |||
| 16 | #include <QTextStream> | |||
| 17 | #include <QDir> | |||
| 18 | #include <QRegularExpression> | |||
| 19 | #include <QtConcurrent> | |||
| 20 | #include <QThreadPool> | |||
| 21 | ||||
| 22 | #include <wsutil/filesystem.h> | |||
| 23 | #include <app/application_flavor.h> | |||
| 24 | ||||
| 25 | #include <ui/recent.h> | |||
| 26 | #include <epan/prefs.h> | |||
| 27 | ||||
| 28 | WorkspaceState::WorkspaceState(QObject *parent) | |||
| 29 | : QObject(parent) | |||
| 30 | { | |||
| 31 | } | |||
| 32 | ||||
| 33 | WorkspaceState::~WorkspaceState() | |||
| 34 | { | |||
| 35 | } | |||
| 36 | ||||
| 37 | WorkspaceState* WorkspaceState::instance() | |||
| 38 | { | |||
| 39 | // Meyer's Singleton - thread-safe in C++11 and later | |||
| 40 | static WorkspaceState* instance_ = new WorkspaceState(); | |||
| 41 | return instance_; | |||
| 42 | } | |||
| 43 | ||||
| 44 | QString WorkspaceState::recentCommonFilePath() const | |||
| 45 | { | |||
| 46 | // recent_common is NOT profile-specific (from_profile = false) | |||
| 47 | char *rf_path = get_persconffile_path( | |||
| 48 | RECENT_COMMON_FILE_NAME, | |||
| 49 | false, // from_profile = false | |||
| 50 | application_configuration_environment_prefix() | |||
| 51 | ); | |||
| 52 | ||||
| 53 | QString path = QString::fromUtf8(rf_path); | |||
| 54 | g_free(rf_path); | |||
| 55 | ||||
| 56 | return path; | |||
| 57 | } | |||
| 58 | ||||
| 59 | QString WorkspaceState::recentProfileFilePath() const | |||
| 60 | { | |||
| 61 | // recent is profile-specific (from_profile = true) | |||
| 62 | char *rf_path = get_persconffile_path( | |||
| 63 | RECENT_PROFILE_FILE_NAME, | |||
| 64 | true, // from_profile = true | |||
| 65 | application_configuration_environment_prefix() | |||
| 66 | ); | |||
| 67 | ||||
| 68 | QString path = QString::fromUtf8(rf_path); | |||
| 69 | g_free(rf_path); | |||
| 70 | ||||
| 71 | return path; | |||
| 72 | } | |||
| 73 | ||||
| 74 | bool WorkspaceState::parseRecentFile(const QString &filePath, | |||
| 75 | std::function<void(const QString &key, const QString &value)> handler) | |||
| 76 | { | |||
| 77 | QFile file(filePath); | |||
| 78 | if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | |||
| 79 | return false; | |||
| 80 | } | |||
| 81 | ||||
| 82 | QTextStream in(&file); | |||
| 83 | // Match: key: value (with optional whitespace) | |||
| 84 | static const QRegularExpression keyValueRe(QStringLiteral("^([^:]+):\\s*(.*)$")(QString(QtPrivate::qMakeStringPrivate(u"" "^([^:]+):\\s*(.*)$" )))); | |||
| 85 | ||||
| 86 | while (!in.atEnd()) { | |||
| 87 | QString line = in.readLine(); | |||
| 88 | ||||
| 89 | // Skip empty lines and comments | |||
| 90 | if (line.isEmpty() || line.startsWith('#')) { | |||
| 91 | continue; | |||
| 92 | } | |||
| 93 | ||||
| 94 | QRegularExpressionMatch match = keyValueRe.match(line); | |||
| 95 | if (match.hasMatch()) { | |||
| 96 | QString key = match.captured(1).trimmed(); | |||
| 97 | QString value = match.captured(2); | |||
| 98 | handler(key, value); | |||
| 99 | } | |||
| 100 | } | |||
| 101 | ||||
| 102 | file.close(); | |||
| 103 | return true; | |||
| 104 | } | |||
| 105 | ||||
| 106 | bool WorkspaceState::loadCommonState(QString *errorPath, int *errorCode) | |||
| 107 | { | |||
| 108 | QString filePath = recentCommonFilePath(); | |||
| 109 | ||||
| 110 | QFile file(filePath); | |||
| 111 | if (!file.exists()) { | |||
| 112 | // File doesn't exist yet - not an error, just no state to load | |||
| 113 | return true; | |||
| 114 | } | |||
| 115 | ||||
| 116 | if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | |||
| 117 | if (errorPath) *errorPath = filePath; | |||
| 118 | if (errorCode) *errorCode = errno(*__errno_location ()); | |||
| 119 | return false; | |||
| 120 | } | |||
| 121 | file.close(); | |||
| 122 | ||||
| 123 | // Clear existing state before loading | |||
| 124 | QList<RecentFileInfo> newFileList; | |||
| 125 | ||||
| 126 | bool success = parseRecentFile(filePath, [&newFileList](const QString &key, const QString &value) { | |||
| 127 | if (key == KEY_CAPTURE_FILE) { | |||
| 128 | // Recent files are stored oldest first, newest last | |||
| 129 | // We append to maintain that order | |||
| 130 | if (!value.isEmpty()) { | |||
| 131 | RecentFileInfo info; | |||
| 132 | info.size = 0; | |||
| 133 | info.accessible = false; | |||
| 134 | info.filename = value; | |||
| 135 | newFileList.append(info); | |||
| 136 | } | |||
| 137 | } | |||
| 138 | // Future: handle other keys here | |||
| 139 | // else if (key == KEY_DISPLAY_FILTER) { ... } | |||
| 140 | }); | |||
| 141 | ||||
| 142 | if (success) { | |||
| 143 | recent_capture_files_.clear(); | |||
| 144 | recent_capture_files_.append(newFileList); | |||
| 145 | ||||
| 146 | // Queue async status checks for all loaded files | |||
| 147 | for (const RecentFileInfo &info : newFileList) { | |||
| 148 | queueFileStatusCheck(info.filename); | |||
| 149 | } | |||
| 150 | ||||
| 151 | emit stateLoaded(); | |||
| 152 | } | |||
| 153 | ||||
| 154 | return success; | |||
| 155 | } | |||
| 156 | ||||
| 157 | const QList<RecentFileInfo>& WorkspaceState::recentCaptureFiles() const | |||
| 158 | { | |||
| 159 | return recent_capture_files_; | |||
| 160 | } | |||
| 161 | ||||
| 162 | QStringList WorkspaceState::recentCaptureFilenames() const | |||
| 163 | { | |||
| 164 | QStringList filenames; | |||
| 165 | ||||
| 166 | for (const RecentFileInfo &info : recent_capture_files_) { | |||
| 167 | filenames.append(info.filename); | |||
| 168 | } | |||
| 169 | return filenames; | |||
| 170 | } | |||
| 171 | ||||
| 172 | void WorkspaceState::addRecentCaptureFile(const QString &filePath) | |||
| 173 | { | |||
| 174 | if (filePath.isEmpty()) { | |||
| 175 | return; | |||
| 176 | } | |||
| 177 | ||||
| 178 | // Remove existing entry if present (Qt5-compatible approach) | |||
| 179 | auto matchesPath = [&filePath](const RecentFileInfo &info) { | |||
| 180 | #ifdef Q_OS_WIN | |||
| 181 | return info.filename.compare(filePath, Qt::CaseInsensitive) == 0; | |||
| 182 | #else | |||
| 183 | return info.filename == filePath; | |||
| 184 | #endif | |||
| 185 | }; | |||
| 186 | recent_capture_files_.erase( | |||
| 187 | std::remove_if(recent_capture_files_.begin(), recent_capture_files_.end(), matchesPath), | |||
| 188 | recent_capture_files_.end()); | |||
| 189 | ||||
| 190 | // Add to end (newest last, matching the file format) | |||
| 191 | RecentFileInfo info; | |||
| 192 | info.size = 0; | |||
| 193 | info.accessible = false; | |||
| 194 | info.filename = filePath; | |||
| 195 | recent_capture_files_.append(info); | |||
| 196 | ||||
| 197 | // Trim to max size (remove oldest = front of list) | |||
| 198 | int maxRecentFiles = static_cast<int>(prefs.gui_recent_files_count_max); | |||
| 199 | if (recent_capture_files_.size() > maxRecentFiles) { | |||
| 200 | recent_capture_files_ = recent_capture_files_.mid(recent_capture_files_.size() - maxRecentFiles); | |||
| 201 | } | |||
| 202 | ||||
| 203 | // Queue async status check for the newly added file | |||
| 204 | queueFileStatusCheck(filePath); | |||
| 205 | ||||
| 206 | emit recentCaptureFilesChanged(); | |||
| 207 | write_recent(); // Persist immediately | |||
| 208 | } | |||
| 209 | ||||
| 210 | void WorkspaceState::removeRecentCaptureFile(const QString &filePath) | |||
| 211 | { | |||
| 212 | // Qt5-compatible approach using std::remove_if | |||
| 213 | auto matchesPath = [&filePath](const RecentFileInfo &info) { | |||
| 214 | #ifdef Q_OS_WIN | |||
| 215 | return info.filename.compare(filePath, Qt::CaseInsensitive) == 0; | |||
| 216 | #else | |||
| 217 | return info.filename == filePath; | |||
| 218 | #endif | |||
| 219 | }; | |||
| 220 | auto originalSize = recent_capture_files_.size(); | |||
| 221 | auto newEnd = std::remove_if(recent_capture_files_.begin(), recent_capture_files_.end(), matchesPath); | |||
| 222 | recent_capture_files_.erase(newEnd, recent_capture_files_.end()); | |||
| 223 | ||||
| 224 | if (recent_capture_files_.size() < originalSize) { | |||
| 225 | emit recentCaptureFilesChanged(); | |||
| 226 | write_recent(); // Persist immediately | |||
| 227 | } | |||
| 228 | } | |||
| 229 | ||||
| 230 | void WorkspaceState::clearRecentCaptureFiles() | |||
| 231 | { | |||
| 232 | if (!recent_capture_files_.isEmpty()) { | |||
| 233 | recent_capture_files_.clear(); | |||
| 234 | emit recentCaptureFilesChanged(); | |||
| 235 | write_recent(); // Persist immediately | |||
| 236 | } | |||
| 237 | } | |||
| 238 | ||||
| 239 | void WorkspaceState::queueFileStatusCheck(const QString &filename) | |||
| 240 | { | |||
| 241 | // Force deep copy for thread safety | |||
| 242 | QString filenameCopy = QString::fromStdU16String(filename.toStdU16String()); | |||
| 243 | ||||
| 244 | QThreadPool::globalInstance()->start([this, filenameCopy]() { | |||
| 245 | QFileInfo fileInfo(filenameCopy); | |||
| 246 | qint64 size = 0; | |||
| 247 | bool accessible = false; | |||
| 248 | ||||
| 249 | if (fileInfo.isFile() && fileInfo.isReadable()) { | |||
| ||||
| 250 | size = fileInfo.size(); | |||
| 251 | accessible = true; | |||
| 252 | } | |||
| 253 | ||||
| 254 | // Queue the result back to the main thread | |||
| 255 | QMetaObject::invokeMethod(this, [this, filenameCopy, size, accessible]() { | |||
| 256 | onFileStatusChecked(filenameCopy, size, accessible); | |||
| 257 | }, Qt::QueuedConnection); | |||
| 258 | }); | |||
| 259 | } | |||
| 260 | ||||
| 261 | void WorkspaceState::onFileStatusChecked(const QString &filename, qint64 size, bool accessible) | |||
| 262 | { | |||
| 263 | for (RecentFileInfo &info : recent_capture_files_) { | |||
| 264 | #ifdef Q_OS_WIN | |||
| 265 | if (info.filename.compare(filename, Qt::CaseInsensitive) == 0) { | |||
| 266 | #else | |||
| 267 | if (info.filename == filename) { | |||
| 268 | #endif | |||
| 269 | if (info.size != size || info.accessible != accessible) { | |||
| 270 | info.size = size; | |||
| 271 | info.accessible = accessible; | |||
| 272 | emit recentFileStatusChanged(filename); | |||
| 273 | } | |||
| 274 | break; | |||
| 275 | } | |||
| 276 | } | |||
| 277 | } |
| 1 | // Copyright (C) 2022 The Qt Company Ltd. | |||
| 2 | // Copyright (C) 2019 Intel Corporation. | |||
| 3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | |||
| 4 | ||||
| 5 | #ifndef QOBJECTDEFS_H | |||
| 6 | #define QOBJECTDEFS_H | |||
| 7 | ||||
| 8 | #if defined(__OBJC__) && !defined(__cplusplus201703L) | |||
| 9 | # warning "File built in Objective-C mode (.m), but using Qt requires Objective-C++ (.mm)" | |||
| 10 | #endif | |||
| 11 | ||||
| 12 | #include <QtCore/qnamespace.h> | |||
| 13 | #include <QtCore/qobjectdefs_impl.h> | |||
| 14 | #include <QtCore/qtmetamacros.h> | |||
| 15 | ||||
| 16 | QT_BEGIN_NAMESPACE | |||
| 17 | ||||
| 18 | class QByteArray; | |||
| 19 | struct QArrayData; | |||
| 20 | ||||
| 21 | class QString; | |||
| 22 | ||||
| 23 | #ifndef QT_NO_META_MACROS | |||
| 24 | // macro for onaming members | |||
| 25 | #ifdef METHOD | |||
| 26 | #undef METHOD | |||
| 27 | #endif | |||
| 28 | #ifdef SLOT | |||
| 29 | #undef SLOT | |||
| 30 | #endif | |||
| 31 | #ifdef SIGNAL | |||
| 32 | #undef SIGNAL | |||
| 33 | #endif | |||
| 34 | #endif // QT_NO_META_MACROS | |||
| 35 | ||||
| 36 | Q_CORE_EXPORT__attribute__((visibility("default"))) const char *qFlagLocation(const char *method); | |||
| 37 | ||||
| 38 | #ifndef QT_NO_META_MACROS | |||
| 39 | # define QMETHOD_CODE0 0 // member type codes | |||
| 40 | # define QSLOT_CODE1 1 | |||
| 41 | # define QSIGNAL_CODE2 2 | |||
| 42 | # define QT_PREFIX_CODE(code, a)"code" "a" QT_STRINGIFY(code)"code" #a | |||
| 43 | # define QT_STRINGIFY_METHOD(a)"0" "a" QT_PREFIX_CODE(QMETHOD_CODE, a)"0" "a" | |||
| 44 | # define QT_STRINGIFY_SLOT(a)"1" "a" QT_PREFIX_CODE(QSLOT_CODE, a)"1" "a" | |||
| 45 | # define QT_STRINGIFY_SIGNAL(a)"2" "a" QT_PREFIX_CODE(QSIGNAL_CODE, a)"2" "a" | |||
| 46 | # ifndef QT_NO_DEBUG | |||
| 47 | # define QLOCATION"\0" "/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" "47" "\0" __FILE__"/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" QT_STRINGIFY(__LINE__)"47" | |||
| 48 | # ifndef QT_NO_KEYWORDS | |||
| 49 | # define METHOD(a)qFlagLocation("0" "a" "\0" "/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" "49") qFlagLocation(QT_STRINGIFY_METHOD(a)"0" "a" QLOCATION"\0" "/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" "49") | |||
| 50 | # endif | |||
| 51 | # define SLOT(a)qFlagLocation("1" "a" "\0" "/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" "51") qFlagLocation(QT_STRINGIFY_SLOT(a)"1" "a" QLOCATION"\0" "/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" "51") | |||
| 52 | # define SIGNAL(a)qFlagLocation("2" "a" "\0" "/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" "52") qFlagLocation(QT_STRINGIFY_SIGNAL(a)"2" "a" QLOCATION"\0" "/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" "52") | |||
| 53 | # else | |||
| 54 | # ifndef QT_NO_KEYWORDS | |||
| 55 | # define METHOD(a)qFlagLocation("0" "a" "\0" "/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" "55") QT_STRINGIFY_METHOD(a)"0" "a" | |||
| 56 | # endif | |||
| 57 | # define SLOT(a)qFlagLocation("1" "a" "\0" "/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" "57") QT_STRINGIFY_SLOT(a)"1" "a" | |||
| 58 | # define SIGNAL(a)qFlagLocation("2" "a" "\0" "/usr/include/x86_64-linux-gnu/qt6/QtCore/qobjectdefs.h" ":" "58") QT_STRINGIFY_SIGNAL(a)"2" "a" | |||
| 59 | # endif | |||
| 60 | #endif // QT_NO_META_MACROS | |||
| 61 | ||||
| 62 | #define Q_ARG(type, data)QArgument<type >("type", data) QArgument<type >(#type, data) | |||
| 63 | #define Q_RETURN_ARG(type, data)QReturnArgument<type >("type", data) QReturnArgument<type >(#type, data) | |||
| 64 | ||||
| 65 | class QObject; | |||
| 66 | class QMetaMethod; | |||
| 67 | class QMetaEnum; | |||
| 68 | class QMetaProperty; | |||
| 69 | class QMetaClassInfo; | |||
| 70 | ||||
| 71 | namespace QtPrivate { | |||
| 72 | class QMetaTypeInterface; | |||
| 73 | } | |||
| 74 | ||||
| 75 | struct QMethodRawArguments | |||
| 76 | { | |||
| 77 | void **arguments; | |||
| 78 | }; | |||
| 79 | ||||
| 80 | class Q_CORE_EXPORT__attribute__((visibility("default"))) QGenericArgument | |||
| 81 | { | |||
| 82 | public: | |||
| 83 | inline QGenericArgument(const char *aName = nullptr, const void *aData = nullptr) | |||
| 84 | : _data(aData), _name(aName) {} | |||
| 85 | inline void *data() const { return const_cast<void *>(_data); } | |||
| 86 | inline const char *name() const { return _name; } | |||
| 87 | ||||
| 88 | private: | |||
| 89 | const void *_data; | |||
| 90 | const char *_name; | |||
| 91 | }; | |||
| 92 | ||||
| 93 | class Q_CORE_EXPORT__attribute__((visibility("default"))) QGenericReturnArgument: public QGenericArgument | |||
| 94 | { | |||
| 95 | public: | |||
| 96 | inline QGenericReturnArgument(const char *aName = nullptr, void *aData = nullptr) | |||
| 97 | : QGenericArgument(aName, aData) | |||
| 98 | {} | |||
| 99 | }; | |||
| 100 | ||||
| 101 | template <class T> | |||
| 102 | class QArgument: public QGenericArgument | |||
| 103 | { | |||
| 104 | public: | |||
| 105 | inline QArgument(const char *aName, const T &aData) | |||
| 106 | : QGenericArgument(aName, static_cast<const void *>(&aData)) | |||
| 107 | {} | |||
| 108 | }; | |||
| 109 | template <class T> | |||
| 110 | class QArgument<T &>: public QGenericArgument | |||
| 111 | { | |||
| 112 | public: | |||
| 113 | inline QArgument(const char *aName, T &aData) | |||
| 114 | : QGenericArgument(aName, static_cast<const void *>(&aData)) | |||
| 115 | {} | |||
| 116 | }; | |||
| 117 | ||||
| 118 | ||||
| 119 | template <typename T> | |||
| 120 | class QReturnArgument: public QGenericReturnArgument | |||
| 121 | { | |||
| 122 | public: | |||
| 123 | inline QReturnArgument(const char *aName, T &aData) | |||
| 124 | : QGenericReturnArgument(aName, static_cast<void *>(&aData)) | |||
| 125 | {} | |||
| 126 | }; | |||
| 127 | ||||
| 128 | struct Q_CORE_EXPORT__attribute__((visibility("default"))) QMetaObject | |||
| 129 | { | |||
| 130 | class Connection; | |||
| 131 | const char *className() const; | |||
| 132 | const QMetaObject *superClass() const; | |||
| 133 | ||||
| 134 | bool inherits(const QMetaObject *metaObject) const noexcept; | |||
| 135 | QObject *cast(QObject *obj) const | |||
| 136 | { return const_cast<QObject *>(cast(const_cast<const QObject *>(obj))); } | |||
| 137 | const QObject *cast(const QObject *obj) const; | |||
| 138 | ||||
| 139 | #if !defined(QT_NO_TRANSLATION) || defined(Q_CLANG_QDOC) | |||
| 140 | QString tr(const char *s, const char *c, int n = -1) const; | |||
| 141 | #endif // QT_NO_TRANSLATION | |||
| 142 | ||||
| 143 | QMetaType metaType() const; | |||
| 144 | ||||
| 145 | int methodOffset() const; | |||
| 146 | int enumeratorOffset() const; | |||
| 147 | int propertyOffset() const; | |||
| 148 | int classInfoOffset() const; | |||
| 149 | ||||
| 150 | int constructorCount() const; | |||
| 151 | int methodCount() const; | |||
| 152 | int enumeratorCount() const; | |||
| 153 | int propertyCount() const; | |||
| 154 | int classInfoCount() const; | |||
| 155 | ||||
| 156 | int indexOfConstructor(const char *constructor) const; | |||
| 157 | int indexOfMethod(const char *method) const; | |||
| 158 | int indexOfSignal(const char *signal) const; | |||
| 159 | int indexOfSlot(const char *slot) const; | |||
| 160 | int indexOfEnumerator(const char *name) const; | |||
| 161 | int indexOfProperty(const char *name) const; | |||
| 162 | int indexOfClassInfo(const char *name) const; | |||
| 163 | ||||
| 164 | QMetaMethod constructor(int index) const; | |||
| 165 | QMetaMethod method(int index) const; | |||
| 166 | QMetaEnum enumerator(int index) const; | |||
| 167 | QMetaProperty property(int index) const; | |||
| 168 | QMetaClassInfo classInfo(int index) const; | |||
| 169 | QMetaProperty userProperty() const; | |||
| 170 | ||||
| 171 | static bool checkConnectArgs(const char *signal, const char *method); | |||
| 172 | static bool checkConnectArgs(const QMetaMethod &signal, | |||
| 173 | const QMetaMethod &method); | |||
| 174 | static QByteArray normalizedSignature(const char *method); | |||
| 175 | static QByteArray normalizedType(const char *type); | |||
| 176 | ||||
| 177 | // internal index-based connect | |||
| 178 | static Connection connect(const QObject *sender, int signal_index, | |||
| 179 | const QObject *receiver, int method_index, | |||
| 180 | int type = 0, int *types = nullptr); | |||
| 181 | // internal index-based disconnect | |||
| 182 | static bool disconnect(const QObject *sender, int signal_index, | |||
| 183 | const QObject *receiver, int method_index); | |||
| 184 | static bool disconnectOne(const QObject *sender, int signal_index, | |||
| 185 | const QObject *receiver, int method_index); | |||
| 186 | // internal slot-name based connect | |||
| 187 | static void connectSlotsByName(QObject *o); | |||
| 188 | ||||
| 189 | // internal index-based signal activation | |||
| 190 | static void activate(QObject *sender, int signal_index, void **argv); | |||
| 191 | static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv); | |||
| 192 | static void activate(QObject *sender, int signal_offset, int local_signal_index, void **argv); | |||
| 193 | ||||
| 194 | static bool invokeMethod(QObject *obj, const char *member, | |||
| 195 | Qt::ConnectionType, | |||
| 196 | QGenericReturnArgument ret, | |||
| 197 | QGenericArgument val0 = QGenericArgument(nullptr), | |||
| 198 | QGenericArgument val1 = QGenericArgument(), | |||
| 199 | QGenericArgument val2 = QGenericArgument(), | |||
| 200 | QGenericArgument val3 = QGenericArgument(), | |||
| 201 | QGenericArgument val4 = QGenericArgument(), | |||
| 202 | QGenericArgument val5 = QGenericArgument(), | |||
| 203 | QGenericArgument val6 = QGenericArgument(), | |||
| 204 | QGenericArgument val7 = QGenericArgument(), | |||
| 205 | QGenericArgument val8 = QGenericArgument(), | |||
| 206 | QGenericArgument val9 = QGenericArgument()); | |||
| 207 | ||||
| 208 | static inline bool invokeMethod(QObject *obj, const char *member, | |||
| 209 | QGenericReturnArgument ret, | |||
| 210 | QGenericArgument val0 = QGenericArgument(nullptr), | |||
| 211 | QGenericArgument val1 = QGenericArgument(), | |||
| 212 | QGenericArgument val2 = QGenericArgument(), | |||
| 213 | QGenericArgument val3 = QGenericArgument(), | |||
| 214 | QGenericArgument val4 = QGenericArgument(), | |||
| 215 | QGenericArgument val5 = QGenericArgument(), | |||
| 216 | QGenericArgument val6 = QGenericArgument(), | |||
| 217 | QGenericArgument val7 = QGenericArgument(), | |||
| 218 | QGenericArgument val8 = QGenericArgument(), | |||
| 219 | QGenericArgument val9 = QGenericArgument()) | |||
| 220 | { | |||
| 221 | return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3, | |||
| 222 | val4, val5, val6, val7, val8, val9); | |||
| 223 | } | |||
| 224 | ||||
| 225 | static inline bool invokeMethod(QObject *obj, const char *member, | |||
| 226 | Qt::ConnectionType type, | |||
| 227 | QGenericArgument val0 = QGenericArgument(nullptr), | |||
| 228 | QGenericArgument val1 = QGenericArgument(), | |||
| 229 | QGenericArgument val2 = QGenericArgument(), | |||
| 230 | QGenericArgument val3 = QGenericArgument(), | |||
| 231 | QGenericArgument val4 = QGenericArgument(), | |||
| 232 | QGenericArgument val5 = QGenericArgument(), | |||
| 233 | QGenericArgument val6 = QGenericArgument(), | |||
| 234 | QGenericArgument val7 = QGenericArgument(), | |||
| 235 | QGenericArgument val8 = QGenericArgument(), | |||
| 236 | QGenericArgument val9 = QGenericArgument()) | |||
| 237 | { | |||
| 238 | return invokeMethod(obj, member, type, QGenericReturnArgument(), val0, val1, val2, | |||
| 239 | val3, val4, val5, val6, val7, val8, val9); | |||
| 240 | } | |||
| 241 | ||||
| 242 | static inline bool invokeMethod(QObject *obj, const char *member, | |||
| 243 | QGenericArgument val0 = QGenericArgument(nullptr), | |||
| 244 | QGenericArgument val1 = QGenericArgument(), | |||
| 245 | QGenericArgument val2 = QGenericArgument(), | |||
| 246 | QGenericArgument val3 = QGenericArgument(), | |||
| 247 | QGenericArgument val4 = QGenericArgument(), | |||
| 248 | QGenericArgument val5 = QGenericArgument(), | |||
| 249 | QGenericArgument val6 = QGenericArgument(), | |||
| 250 | QGenericArgument val7 = QGenericArgument(), | |||
| 251 | QGenericArgument val8 = QGenericArgument(), | |||
| 252 | QGenericArgument val9 = QGenericArgument()) | |||
| 253 | { | |||
| 254 | return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0, | |||
| 255 | val1, val2, val3, val4, val5, val6, val7, val8, val9); | |||
| 256 | } | |||
| 257 | ||||
| 258 | #ifdef Q_CLANG_QDOC | |||
| 259 | template<typename Functor, typename FunctorReturnType> | |||
| 260 | static bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr); | |||
| 261 | template<typename Functor, typename FunctorReturnType> | |||
| 262 | static bool invokeMethod(QObject *context, Functor function, FunctorReturnType *ret); | |||
| 263 | #else | |||
| 264 | ||||
| 265 | // invokeMethod() for member function pointer | |||
| 266 | template <typename Func> | |||
| 267 | static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction | |||
| 268 | && !std::is_convertible<Func, const char*>::value | |||
| 269 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type | |||
| 270 | invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object, | |||
| 271 | Func function, | |||
| 272 | Qt::ConnectionType type = Qt::AutoConnection, | |||
| 273 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr) | |||
| 274 | { | |||
| 275 | return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), type, ret); | |||
| 276 | } | |||
| 277 | ||||
| 278 | template <typename Func> | |||
| 279 | static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction | |||
| 280 | && !std::is_convertible<Func, const char*>::value | |||
| 281 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type | |||
| 282 | invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object, | |||
| 283 | Func function, | |||
| 284 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret) | |||
| 285 | { | |||
| 286 | return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), Qt::AutoConnection, ret); | |||
| 287 | } | |||
| 288 | ||||
| 289 | // invokeMethod() for function pointer (not member) | |||
| 290 | template <typename Func> | |||
| 291 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction | |||
| 292 | && !std::is_convertible<Func, const char*>::value | |||
| 293 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type | |||
| 294 | invokeMethod(QObject *context, Func function, | |||
| 295 | Qt::ConnectionType type = Qt::AutoConnection, | |||
| 296 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr) | |||
| 297 | { | |||
| 298 | return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), type, ret); | |||
| 299 | } | |||
| 300 | ||||
| 301 | template <typename Func> | |||
| 302 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction | |||
| 303 | && !std::is_convertible<Func, const char*>::value | |||
| 304 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type | |||
| 305 | invokeMethod(QObject *context, Func function, | |||
| 306 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret) | |||
| 307 | { | |||
| 308 | return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), Qt::AutoConnection, ret); | |||
| 309 | } | |||
| 310 | ||||
| 311 | // invokeMethod() for Functor | |||
| 312 | template <typename Func> | |||
| 313 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction | |||
| 314 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1 | |||
| 315 | && !std::is_convertible<Func, const char*>::value, bool>::type | |||
| 316 | invokeMethod(QObject *context, Func function, | |||
| 317 | Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr) | |||
| 318 | { | |||
| 319 | return invokeMethodImpl(context, | |||
| ||||
| 320 | new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)), | |||
| 321 | type, | |||
| 322 | ret); | |||
| 323 | } | |||
| 324 | ||||
| 325 | template <typename Func> | |||
| 326 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction | |||
| 327 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1 | |||
| 328 | && !std::is_convertible<Func, const char*>::value, bool>::type | |||
| 329 | invokeMethod(QObject *context, Func function, decltype(function()) *ret) | |||
| 330 | { | |||
| 331 | return invokeMethodImpl(context, | |||
| 332 | new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)), | |||
| 333 | Qt::AutoConnection, | |||
| 334 | ret); | |||
| 335 | } | |||
| 336 | ||||
| 337 | #endif | |||
| 338 | ||||
| 339 | QObject *newInstance(QGenericArgument val0 = QGenericArgument(nullptr), | |||
| 340 | QGenericArgument val1 = QGenericArgument(), | |||
| 341 | QGenericArgument val2 = QGenericArgument(), | |||
| 342 | QGenericArgument val3 = QGenericArgument(), | |||
| 343 | QGenericArgument val4 = QGenericArgument(), | |||
| 344 | QGenericArgument val5 = QGenericArgument(), | |||
| 345 | QGenericArgument val6 = QGenericArgument(), | |||
| 346 | QGenericArgument val7 = QGenericArgument(), | |||
| 347 | QGenericArgument val8 = QGenericArgument(), | |||
| 348 | QGenericArgument val9 = QGenericArgument()) const; | |||
| 349 | ||||
| 350 | enum Call { | |||
| 351 | InvokeMetaMethod, | |||
| 352 | ReadProperty, | |||
| 353 | WriteProperty, | |||
| 354 | ResetProperty, | |||
| 355 | CreateInstance, | |||
| 356 | IndexOfMethod, | |||
| 357 | RegisterPropertyMetaType, | |||
| 358 | RegisterMethodArgumentMetaType, | |||
| 359 | BindableProperty, | |||
| 360 | CustomCall | |||
| 361 | }; | |||
| 362 | ||||
| 363 | int static_metacall(Call, int, void **) const; | |||
| 364 | static int metacall(QObject *, Call, int, void **); | |||
| 365 | ||||
| 366 | template <const QMetaObject &MO> static constexpr const QMetaObject *staticMetaObject() | |||
| 367 | { | |||
| 368 | return &MO; | |||
| 369 | } | |||
| 370 | ||||
| 371 | struct SuperData { | |||
| 372 | using Getter = const QMetaObject *(*)(); | |||
| 373 | const QMetaObject *direct; | |||
| 374 | SuperData() = default; | |||
| 375 | constexpr SuperData(std::nullptr_t) : direct(nullptr) {} | |||
| 376 | constexpr SuperData(const QMetaObject *mo) : direct(mo) {} | |||
| 377 | ||||
| 378 | constexpr const QMetaObject *operator->() const { return operator const QMetaObject *(); } | |||
| 379 | ||||
| 380 | #ifdef QT_NO_DATA_RELOCATION | |||
| 381 | Getter indirect = nullptr; | |||
| 382 | constexpr SuperData(Getter g) : direct(nullptr), indirect(g) {} | |||
| 383 | constexpr operator const QMetaObject *() const | |||
| 384 | { return indirect ? indirect() : direct; } | |||
| 385 | template <const QMetaObject &MO> static constexpr SuperData link() | |||
| 386 | { return SuperData(QMetaObject::staticMetaObject<MO>); } | |||
| 387 | #else | |||
| 388 | constexpr SuperData(Getter g) : direct(g()) {} | |||
| 389 | constexpr operator const QMetaObject *() const | |||
| 390 | { return direct; } | |||
| 391 | template <const QMetaObject &MO> static constexpr SuperData link() | |||
| 392 | { return SuperData(QMetaObject::staticMetaObject<MO>()); } | |||
| 393 | #endif | |||
| 394 | }; | |||
| 395 | ||||
| 396 | struct Data { // private data | |||
| 397 | SuperData superdata; | |||
| 398 | const uint *stringdata; | |||
| 399 | const uint *data; | |||
| 400 | typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); | |||
| 401 | StaticMetacallFunction static_metacall; | |||
| 402 | const SuperData *relatedMetaObjects; | |||
| 403 | const QtPrivate::QMetaTypeInterface *const *metaTypes; | |||
| 404 | void *extradata; //reserved for future use | |||
| 405 | } d; | |||
| 406 | ||||
| 407 | private: | |||
| 408 | static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret); | |||
| 409 | friend class QTimer; | |||
| 410 | }; | |||
| 411 | ||||
| 412 | class Q_CORE_EXPORT__attribute__((visibility("default"))) QMetaObject::Connection { | |||
| 413 | void *d_ptr; //QObjectPrivate::Connection* | |||
| 414 | explicit Connection(void *data) : d_ptr(data) { } | |||
| 415 | friend class QObject; | |||
| 416 | friend class QObjectPrivate; | |||
| 417 | friend struct QMetaObject; | |||
| 418 | bool isConnected_helper() const; | |||
| 419 | public: | |||
| 420 | ~Connection(); | |||
| 421 | Connection(); | |||
| 422 | Connection(const Connection &other); | |||
| 423 | Connection &operator=(const Connection &other); | |||
| 424 | #ifdef Q_QDOC | |||
| 425 | operator bool() const; | |||
| 426 | #else | |||
| 427 | // still using the restricted bool trick here, in order to support | |||
| 428 | // code using copy-init (e.g. `bool ok = connect(...)`) | |||
| 429 | typedef void *Connection::*RestrictedBool; | |||
| 430 | operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; } | |||
| 431 | #endif | |||
| 432 | ||||
| 433 | Connection(Connection &&other) noexcept : d_ptr(qExchange(other.d_ptr, nullptr)) {} | |||
| 434 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Connection)Connection &operator=(Connection &&other) noexcept { swap(other); return *this; } | |||
| 435 | void swap(Connection &other) noexcept { qt_ptr_swap(d_ptr, other.d_ptr); } | |||
| 436 | }; | |||
| 437 | ||||
| 438 | inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept | |||
| 439 | { | |||
| 440 | lhs.swap(rhs); | |||
| 441 | } | |||
| 442 | ||||
| 443 | inline const QMetaObject *QMetaObject::superClass() const | |||
| 444 | { return d.superdata; } | |||
| 445 | ||||
| 446 | namespace QtPrivate { | |||
| 447 | /* Trait that tells is a the Object has a Q_OBJECT macro */ | |||
| 448 | template <typename Object> struct HasQ_OBJECT_Macro { | |||
| 449 | template <typename T> | |||
| 450 | static char test(int (T::*)(QMetaObject::Call, int, void **)); | |||
| 451 | static int test(int (Object::*)(QMetaObject::Call, int, void **)); | |||
| 452 | enum { Value = sizeof(test(&Object::qt_metacall)) == sizeof(int) }; | |||
| 453 | }; | |||
| 454 | } | |||
| 455 | ||||
| 456 | QT_END_NAMESPACE | |||
| 457 | ||||
| 458 | #endif // QOBJECTDEFS_H |