File indexing completed on 2024-11-24 03:56:26

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #pragma once
0008 #include <QDebug>
0009 #include <QAbstractItemModel>
0010 
0011 namespace app::debug {
0012 
0013 namespace detail {
0014 
0015     inline void print_model_column(const QAbstractItemModel* model, int i, bool flags, const std::vector<int>& roles, const QModelIndex& index, int indent)
0016     {
0017         auto logger = qDebug();
0018         logger.noquote();
0019         auto colindex = model->index(index.row(), i, index.parent());
0020         for ( int role : roles )
0021         {
0022             logger << QString(4*indent, ' ') << "  *" << model->data(colindex, role);
0023             if ( flags )
0024                 logger << model->flags(colindex);
0025         }
0026     }
0027 
0028     struct DebugSlot
0029     {
0030         QString prefix;
0031         QString signal;
0032 
0033         template<class T>
0034         decltype(std::declval<QDebug&>() << std::declval<T>()) print(QDebug& stream, T&& t, bool)
0035         {
0036             return stream << std::forward<T>(t);
0037         }
0038 
0039         template<class T>
0040         void print(QDebug&, T&&, ...){}
0041         void print_all(QDebug&) {}
0042 
0043         template<class T, class... Args>
0044         void print_all(QDebug& stream, T&& t, Args&&... args)
0045         {
0046             print(stream, std::forward<T>(t), true);
0047             print_all(stream, std::forward<Args>(args)...);
0048         }
0049 
0050         template<class... Args>
0051         void operator()(Args&&... args)
0052         {
0053             auto stream = qDebug();
0054             if ( !prefix.isEmpty() )
0055                 stream << prefix;
0056             stream << signal;
0057             print_all(stream, std::forward<Args>(args)...);
0058         }
0059     };
0060 
0061 } // namespace detail
0062 
0063 inline void print_model_row(const QAbstractItemModel* model, const QModelIndex& index, const std::vector<int>& columns = {}, bool flags = false, const std::vector<int>& roles = {Qt::DisplayRole}, int indent = 0)
0064 {
0065     int rows = model->rowCount(index);
0066     int cols = model->columnCount(index);
0067 
0068     qDebug().noquote() << QString(4*indent, ' ') << index << "rows" << rows << "cols" << cols << "ptr" << index.internalId();
0069 
0070     if ( columns.empty() )
0071     {
0072         for ( int i = 0; i < cols; i++ )
0073             detail::print_model_column(model, i, flags, roles, index, indent);
0074     }
0075     else
0076     {
0077         for ( int i : columns )
0078             detail::print_model_column(model, i, flags, roles, index, indent);
0079     }
0080 }
0081 
0082 inline void print_model(const QAbstractItemModel* model, const std::vector<int>& columns = {}, bool flags = false, const std::vector<int>& roles = {Qt::DisplayRole}, const QModelIndex& index = {}, int indent = 0)
0083 {
0084     print_model_row(model, index, columns, flags, roles, indent);
0085     for ( int i = 0; i < model->rowCount(index); i++ )
0086     {
0087         QModelIndex ci = model->index(i, 0, index);
0088         if ( !ci.isValid() )
0089             qDebug().noquote() << QString(4*(indent+1), ' ') << "invalid";
0090         else
0091             print_model(model, columns, flags, roles, ci, indent+1);
0092     }
0093 }
0094 
0095 inline void connect_debug(QAbstractItemModel* model, const QString& prefix)
0096 {
0097     QObject::connect(model, &QAbstractItemModel::columnsAboutToBeInserted,  model, detail::DebugSlot{prefix, "columnsAboutToBeInserted"});
0098     QObject::connect(model, &QAbstractItemModel::columnsAboutToBeMoved,     model, detail::DebugSlot{prefix, "columnsAboutToBeMoved"});
0099     QObject::connect(model, &QAbstractItemModel::columnsAboutToBeRemoved,   model, detail::DebugSlot{prefix, "columnsAboutToBeRemoved"});
0100     QObject::connect(model, &QAbstractItemModel::columnsInserted,           model, detail::DebugSlot{prefix, "columnsInserted"});
0101     QObject::connect(model, &QAbstractItemModel::columnsMoved,              model, detail::DebugSlot{prefix, "columnsMoved"});
0102     QObject::connect(model, &QAbstractItemModel::columnsRemoved,            model, detail::DebugSlot{prefix, "columnsRemoved"});
0103     QObject::connect(model, &QAbstractItemModel::dataChanged,               model, detail::DebugSlot{prefix, "dataChanged"});
0104     QObject::connect(model, &QAbstractItemModel::headerDataChanged,         model, detail::DebugSlot{prefix, "headerDataChanged"});
0105     QObject::connect(model, &QAbstractItemModel::layoutAboutToBeChanged,    model, detail::DebugSlot{prefix, "layoutAboutToBeChanged"});
0106     QObject::connect(model, &QAbstractItemModel::layoutChanged,             model, detail::DebugSlot{prefix, "layoutChanged"});
0107     QObject::connect(model, &QAbstractItemModel::modelAboutToBeReset,       model, detail::DebugSlot{prefix, "modelAboutToBeReset"});
0108     QObject::connect(model, &QAbstractItemModel::modelReset,                model, detail::DebugSlot{prefix, "modelReset"});
0109     QObject::connect(model, &QAbstractItemModel::rowsAboutToBeInserted,     model, detail::DebugSlot{prefix, "rowsAboutToBeInserted"});
0110     QObject::connect(model, &QAbstractItemModel::rowsAboutToBeMoved,        model, detail::DebugSlot{prefix, "rowsAboutToBeMoved"});
0111     QObject::connect(model, &QAbstractItemModel::rowsAboutToBeRemoved,      model, detail::DebugSlot{prefix, "rowsAboutToBeRemoved"});
0112     QObject::connect(model, &QAbstractItemModel::rowsInserted,              model, detail::DebugSlot{prefix, "rowsInserted"});
0113     QObject::connect(model, &QAbstractItemModel::rowsMoved,                 model, detail::DebugSlot{prefix, "rowsMoved"});
0114     QObject::connect(model, &QAbstractItemModel::rowsRemoved,               model, detail::DebugSlot{prefix, "rowsRemoved"});
0115 }
0116 
0117 } // namespace app::debug