File indexing completed on 2024-05-19 04:56:13

0001 /**
0002  * \file debugutils.cpp
0003  * Utility functions for debugging.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 13 Jan 2013
0008  *
0009  * Copyright (C) 2013-2024  Urs Fleisch
0010  *
0011  * This file is part of Kid3.
0012  *
0013  * Kid3 is free software; you can redistribute it and/or modify
0014  * it under the terms of the GNU General Public License as published by
0015  * the Free Software Foundation; either version 2 of the License, or
0016  * (at your option) any later version.
0017  *
0018  * Kid3 is distributed in the hope that it will be useful,
0019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0021  * GNU General Public License for more details.
0022  *
0023  * You should have received a copy of the GNU General Public License
0024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0025  */
0026 
0027 #include "debugutils.h"
0028 #include <QMetaObject>
0029 #include <QMetaMethod>
0030 
0031 /**
0032  * Constructor.
0033  * @param parent parent object
0034  */
0035 DebugUtils::SignalEmissionDumper::SignalEmissionDumper(QObject* parent)
0036   : QObject(parent)
0037 {
0038 }
0039 
0040 #ifndef QT_NO_DEBUG
0041 
0042 /**
0043  * Monitor signal emissions of object
0044  * @param obj object to monitor
0045  */
0046 void DebugUtils::SignalEmissionDumper::connectObject(QObject* obj)
0047 {
0048   const QMetaObject* metaObject = obj->metaObject();
0049   for (int i = 0; i < metaObject->methodCount(); ++i) {
0050     if (QByteArray sig = metaObject->method(i).methodSignature();
0051         metaObject->indexOfSignal(sig) != -1) {
0052       sig.prepend(QSIGNAL_CODE + '0');
0053       connect(obj, sig, this, SLOT(printSignal()));
0054     }
0055   }
0056 }
0057 
0058 /**
0059  * @brief Print emitted signal to debug output.
0060  */
0061 void DebugUtils::SignalEmissionDumper::printSignal()
0062 {
0063   if (QObject* obj = sender()) {
0064     if (int idx = senderSignalIndex(); idx != -1) {
0065       if (QByteArray sig = obj->metaObject()->method(idx).methodSignature();
0066           !sig.isEmpty()) {
0067         qDebug("SIGNAL OUT %s::%s %s",
0068                obj->metaObject()->className(),
0069                qPrintable(obj->objectName().isEmpty()
0070                           ? QLatin1String("unnamed") : obj->objectName()),
0071                sig.constData());
0072       }
0073     }
0074   }
0075 }
0076 
0077 
0078 /**
0079  * Dump an item model.
0080  * @param model item model to dump
0081  * @param parent parent model index
0082  * @param indent number of spaces to indent
0083  */
0084 void DebugUtils::dumpModel(const QAbstractItemModel& model,
0085                            const QModelIndex& parent, int indent)
0086 {
0087   if (indent == 0) {
0088     QString name(model.objectName());
0089     if (name.isEmpty()) {
0090       if (const QMetaObject* metaObject = model.metaObject()) {
0091         name = QString::fromLatin1(metaObject->className());
0092       }
0093     }
0094     qDebug("Dump for %s", qPrintable(name));
0095     QString columnStr;
0096     for (int i = 0; i < model.columnCount(parent); ++i) {
0097       if (i != 0)
0098         columnStr += QLatin1String(", ");
0099       columnStr += QString::number(i);
0100       columnStr += QLatin1String(": ");
0101       columnStr += model.headerData(i, Qt::Horizontal).toString();
0102     }
0103     qDebug("%s", qPrintable(columnStr));
0104   }
0105   if (!model.hasChildren(parent))
0106     return;
0107 
0108   for (int row = 0; row < model.rowCount(parent); ++row) {
0109     QString rowStr(indent, QLatin1Char(' '));
0110     QString rowHeader(model.headerData(row, Qt::Vertical).toString());
0111     rowStr += QString::number(row);
0112     if (!rowHeader.isEmpty()) {
0113       rowStr += QLatin1Char(' ');
0114       rowStr += rowHeader;
0115     }
0116     rowStr += QLatin1Char(':');
0117     QModelIndexList indexesWithChildren;
0118     for (int column = 0; column < model.columnCount(parent); ++column) {
0119       QModelIndex idx(model.index(row, column, parent));
0120       if (column > 0)
0121         rowStr += QLatin1String(",");
0122       rowStr += QString(QLatin1String("%1%2:"))
0123           .arg(model.hasChildren(idx) ? QLatin1String("p") : QLatin1String(""))
0124           .arg(column);
0125       rowStr += model.data(idx).toString();
0126       if (model.hasChildren(idx))
0127         indexesWithChildren.append(idx);
0128     }
0129     qDebug("%s", qPrintable(rowStr));
0130     const auto idxs = indexesWithChildren;
0131     for (const QModelIndex& idx : idxs) {
0132       dumpModel(model, idx, indent + 2);
0133     }
0134   }
0135 }
0136 
0137 #else
0138 
0139 void DebugUtils::SignalEmissionDumper::connectObject(QObject*) {}
0140 void DebugUtils::SignalEmissionDumper::printSignal() {}
0141 
0142 #endif