mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-25 11:22:50 +00:00
330 lines
9 KiB
C++
330 lines
9 KiB
C++
/*
|
|
Copyright (C) 2010 Klarälvdalens Datakonsult AB,
|
|
a KDAB Group company, info@kdab.net,
|
|
author Stephen Kelly <stephen@kdab.com>
|
|
|
|
This library is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU Library General Public License as published by
|
|
the Free Software Foundation; either version 2 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 Library General Public
|
|
License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to the
|
|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
02110-1301, USA.
|
|
*/
|
|
|
|
#include "modeleventlogger.h"
|
|
#include "modeldumper.h"
|
|
#include "indexfinder.h"
|
|
|
|
#include "eventloggerregister.h"
|
|
|
|
#include <QStringList>
|
|
#include <QFile>
|
|
#include <QDebug>
|
|
|
|
#ifdef Grantlee_FOUND
|
|
#include <grantlee_core.h>
|
|
#include "grantlee_paths.h"
|
|
|
|
/**
|
|
Don't escape the code generation output.
|
|
|
|
'const QString &' should not become 'const QString &'
|
|
*/
|
|
class NoEscapeOutputStream : public Grantlee::OutputStream
|
|
{
|
|
public:
|
|
NoEscapeOutputStream()
|
|
: Grantlee::OutputStream()
|
|
{
|
|
|
|
}
|
|
|
|
NoEscapeOutputStream(QTextStream* stream)
|
|
: OutputStream( stream )
|
|
{
|
|
|
|
}
|
|
|
|
virtual QSharedPointer< Grantlee::OutputStream > clone( QTextStream *stream ) const {
|
|
return QSharedPointer<Grantlee::OutputStream>( new NoEscapeOutputStream );
|
|
}
|
|
|
|
virtual QString escape( const QString& input ) const {
|
|
return input;
|
|
}
|
|
};
|
|
#endif
|
|
|
|
class ModelWrapper : public QAbstractItemModel
|
|
{
|
|
public:
|
|
ModelWrapper( QAbstractItemModel */*model*/, QObject* parent = 0)
|
|
: QAbstractItemModel(parent)
|
|
{
|
|
|
|
}
|
|
|
|
QModelIndexList per() const {
|
|
return persistentIndexList();
|
|
}
|
|
|
|
virtual QModelIndex index(int /*row*/, int /*column*/, const QModelIndex& /*parent*/ = QModelIndex()) const { return QModelIndex(); }
|
|
virtual int rowCount(const QModelIndex& /*parent*/ = QModelIndex()) const { return 0; }
|
|
virtual QModelIndex parent(const QModelIndex& /*child*/) const { return QModelIndex(); }
|
|
virtual int columnCount(const QModelIndex& /*parent*/ = QModelIndex()) const {return 0; }
|
|
virtual QVariant data(const QModelIndex& /*index*/, int /*role*/ = Qt::DisplayRole) const { return QVariant(); }
|
|
};
|
|
|
|
|
|
ModelEvent::ModelEvent(QObject* parent)
|
|
: QObject(parent)
|
|
{
|
|
|
|
}
|
|
|
|
static const char * const sTypes[] = {
|
|
"Init",
|
|
"RowsInserted",
|
|
"RowsRemoved",
|
|
"DataChanged",
|
|
"LayoutChanged",
|
|
"ModelReset"
|
|
};
|
|
|
|
QString ModelEvent::type() const
|
|
{
|
|
return QLatin1String(*(sTypes + m_type));
|
|
}
|
|
|
|
// ModelEvent::Type ModelEvent::type() const
|
|
// {
|
|
// return m_type;
|
|
// }
|
|
|
|
void ModelEvent::setType(ModelEvent::Type type)
|
|
{
|
|
m_type = type;
|
|
}
|
|
|
|
int ModelEvent::start() const
|
|
{
|
|
return m_start;
|
|
}
|
|
|
|
void ModelEvent::setStart(int start)
|
|
{
|
|
m_start = start;
|
|
}
|
|
|
|
int ModelEvent::end() const
|
|
{
|
|
return m_end;
|
|
}
|
|
|
|
void ModelEvent::setEnd(int end)
|
|
{
|
|
m_end = end;
|
|
}
|
|
|
|
QString ModelEvent::rowAncestors() const
|
|
{
|
|
QString result("QList<int>()");
|
|
|
|
foreach( const int row, m_rowAncestors)
|
|
{
|
|
result.append(" << ");
|
|
result.append(QString::number(row));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// QList< int > ModelEvent::rowAncestors() const
|
|
// {
|
|
// return m_rowAncestors;
|
|
// }
|
|
|
|
void ModelEvent::setRowAncestors(QList< int > rowAncestors)
|
|
{
|
|
m_rowAncestors = rowAncestors;
|
|
}
|
|
|
|
bool ModelEvent::hasInterpretString() const
|
|
{
|
|
return !m_interpretString.isEmpty();
|
|
}
|
|
|
|
QString ModelEvent::interpretString() const
|
|
{
|
|
return m_interpretString;
|
|
}
|
|
|
|
void ModelEvent::setInterpretString(const QString& interpretString)
|
|
{
|
|
m_interpretString = interpretString;
|
|
}
|
|
|
|
ModelEventLogger::ModelEventLogger(QAbstractItemModel *model, QObject* parent)
|
|
: QObject(parent), m_model(model), m_modelDumper(new ModelDumper), m_numLogs(0)
|
|
{
|
|
connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(dataChanged(QModelIndex,QModelIndex)));
|
|
connect(model, SIGNAL(layoutAboutToBeChanged()), SLOT(layoutAboutToBeChanged()));
|
|
connect(model, SIGNAL(layoutChanged()), SLOT(layoutChanged()));
|
|
connect(model, SIGNAL(modelReset()), SLOT(modelReset()));
|
|
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(rowsInserted(QModelIndex,int,int)));
|
|
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(rowsRemoved(QModelIndex,int,int)));
|
|
|
|
ModelEvent *modelEvent = new ModelEvent(this);
|
|
modelEvent->setType(ModelEvent::Init);
|
|
modelEvent->setInterpretString(m_modelDumper->dumpModel(model));
|
|
|
|
m_modelName = QString::fromLatin1(model->metaObject()->className()).toLower();
|
|
|
|
m_initEvent = QVariant::fromValue(static_cast<QObject*>(modelEvent));
|
|
|
|
EventLoggerRegister::instance()->registerLogger(this);
|
|
}
|
|
|
|
void ModelEventLogger::writeLog()
|
|
{
|
|
#ifdef Grantlee_FOUND
|
|
QString logFileName = QString("main.%1.%2.%3.cpp").arg(m_modelName).arg(reinterpret_cast<qint64>(this)).arg(m_numLogs++);
|
|
qDebug() << "Writing to " << logFileName;
|
|
QFile outputFile(logFileName);
|
|
const bool logFileOpened = outputFile.open(QFile::WriteOnly | QFile::Text);
|
|
Q_ASSERT(logFileOpened);
|
|
Q_UNUSED(logFileOpened);
|
|
|
|
Grantlee::Engine engine;
|
|
Grantlee::FileSystemTemplateLoader::Ptr loader(new Grantlee::FileSystemTemplateLoader);
|
|
loader->setTemplateDirs(QStringList() << ":/templates");
|
|
engine.addTemplateLoader(loader);
|
|
engine.setPluginPaths(QStringList() << GRANTLEE_PLUGIN_PATH);
|
|
|
|
// Write out.
|
|
Grantlee::Template t = engine.loadByName("main.cpp");
|
|
if (!t->error())
|
|
{
|
|
Grantlee::Context c;
|
|
c.insert("initEvent", m_initEvent);
|
|
c.insert("events", m_events);
|
|
|
|
QTextStream textStream(&outputFile);
|
|
NoEscapeOutputStream outputStream(&textStream);
|
|
t->render(&outputStream, &c);
|
|
}
|
|
outputFile.close();
|
|
|
|
if (t->error())
|
|
qDebug() << t->errorString();
|
|
#else
|
|
qDebug() << "Grantlee not found. No log written.";
|
|
#endif
|
|
}
|
|
|
|
ModelEventLogger::~ModelEventLogger()
|
|
{
|
|
writeLog();
|
|
delete m_modelDumper;
|
|
EventLoggerRegister::instance()->unregisterLogger(this);
|
|
}
|
|
|
|
void ModelEventLogger::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
|
{
|
|
ModelEvent *modelEvent = new ModelEvent(this);
|
|
modelEvent->setType(ModelEvent::DataChanged);
|
|
modelEvent->setRowAncestors(IndexFinder::indexToIndexFinder(topLeft.parent()).rows());
|
|
modelEvent->setStart(topLeft.row());
|
|
modelEvent->setEnd(bottomRight.row());
|
|
|
|
m_events.append(QVariant::fromValue(static_cast<QObject*>(modelEvent)));
|
|
}
|
|
|
|
void ModelEventLogger::persistChildren(const QModelIndex &/*parent*/)
|
|
{
|
|
}
|
|
|
|
void ModelEventLogger::layoutAboutToBeChanged()
|
|
{
|
|
m_oldPaths.clear();
|
|
m_persistentIndexes.clear();
|
|
const QModelIndexList list = static_cast<const ModelWrapper*>(m_model)->per();
|
|
foreach(const QPersistentModelIndex &idx, list)
|
|
{
|
|
m_persistentIndexes.append(idx);
|
|
m_oldPaths.append(IndexFinder::indexToIndexFinder(idx).rows());
|
|
}
|
|
}
|
|
|
|
void ModelEventLogger::layoutChanged()
|
|
{
|
|
ModelEvent *modelEvent = new ModelEvent(this);
|
|
modelEvent->setType(ModelEvent::LayoutChanged);
|
|
modelEvent->setInterpretString(m_modelDumper->dumpModel(m_model));
|
|
|
|
QList<PersistentChange*> changes;
|
|
|
|
for( int i = 0; i < m_persistentIndexes.size(); ++i)
|
|
{
|
|
const QPersistentModelIndex pIdx = m_persistentIndexes.at(i);
|
|
if (!pIdx.isValid())
|
|
{
|
|
PersistentChange *change = new PersistentChange(this);
|
|
change->newPath = QList<int>();
|
|
change->oldPath = m_oldPaths.at(i);
|
|
changes.append(change);
|
|
continue;
|
|
}
|
|
const QList<int> rows = IndexFinder::indexToIndexFinder(pIdx).rows();
|
|
if (m_oldPaths.at(i) == rows)
|
|
continue;
|
|
|
|
PersistentChange *change = new PersistentChange(this);
|
|
change->newPath = rows;
|
|
change->oldPath = m_oldPaths.at(i);
|
|
changes.append(change);
|
|
}
|
|
|
|
modelEvent->setChanges(changes);
|
|
|
|
m_events.append(QVariant::fromValue(static_cast<QObject*>(modelEvent)));
|
|
}
|
|
|
|
void ModelEventLogger::modelReset()
|
|
{
|
|
ModelEvent *modelEvent = new ModelEvent(this);
|
|
modelEvent->setType(ModelEvent::ModelReset);
|
|
modelEvent->setInterpretString(m_modelDumper->dumpModel(m_model));
|
|
|
|
m_events.append(QVariant::fromValue(static_cast<QObject*>(modelEvent)));
|
|
}
|
|
|
|
void ModelEventLogger::rowsInserted(const QModelIndex& parent, int start, int end)
|
|
{
|
|
ModelEvent *modelEvent = new ModelEvent(this);
|
|
modelEvent->setType(ModelEvent::RowsInserted);
|
|
modelEvent->setRowAncestors(IndexFinder::indexToIndexFinder(parent).rows());
|
|
modelEvent->setStart(start);
|
|
QString s = m_modelDumper->dumpTree(m_model, parent, start, end);
|
|
modelEvent->setInterpretString(s);
|
|
|
|
m_events.append(QVariant::fromValue(static_cast<QObject*>(modelEvent)));
|
|
}
|
|
|
|
void ModelEventLogger::rowsRemoved(const QModelIndex& parent, int start, int end)
|
|
{
|
|
ModelEvent *modelEvent = new ModelEvent(this);
|
|
modelEvent->setType(ModelEvent::RowsRemoved);
|
|
modelEvent->setRowAncestors(IndexFinder::indexToIndexFinder(parent).rows());
|
|
modelEvent->setStart(start);
|
|
modelEvent->setEnd(end);
|
|
|
|
m_events.append(QVariant::fromValue(static_cast<QObject*>(modelEvent)));
|
|
}
|