/* This file is part of the KDE project
   Copyright (C) 2010 Dag Andersen <danders@get2net.dk>

   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.
*/
// clazy:excludeall=qstring-arg
#include "FlatProxyModelTester.h"

#include "kptnodeitemmodel.h"
#include "kptproject.h"
#include "kpttask.h"

#include <QModelIndex>
#include <QStandardItemModel>
#include <QStandardItem>
#include <QSortFilterProxyModel>

#include <QTest>

namespace KPlato
{

void FlatProxyModelTester::emptyModel()
{
    QCOMPARE(m_flatmodel.columnCount(), 0);
    QCOMPARE(m_flatmodel.rowCount(), 0);
}

void FlatProxyModelTester::test()
{
    qDebug()<<"set 1 row, 1 column";
    m_standardmodel.setColumnCount(1);
    m_standardmodel.setRowCount(1);

    m_standardmodel.setHorizontalHeaderLabels(QStringList() << "Column 1");
    m_flatmodel.setSourceModel(&m_standardmodel);
    
    QCOMPARE(m_flatmodel.columnCount(), 2); // it adds an extra column
    QCOMPARE(m_flatmodel.rowCount(), 1);
    QCOMPARE(m_flatmodel.headerData(0, Qt::Horizontal), QVariant("Column 1"));
    
    m_standardmodel.setData(m_standardmodel.index(0, 0), "Index 0,0");

    QModelIndex idx = m_flatmodel.index(0, 0);
    QVERIFY(idx.isValid());
    qDebug()<<"Index 0,0:"<<idx.data();

    QCOMPARE(idx.data(), QVariant("Index 0,0"));
    
    qDebug()<<"1 row, set 2 columns";
    m_standardmodel.setColumnCount(2);
    QCOMPARE(m_flatmodel.columnCount(), 3); // it adds an extra column
    m_flatmodel.setHeaderData(1, Qt::Horizontal, "Column 2");
    QCOMPARE(m_flatmodel.headerData(1, Qt::Horizontal), QVariant("Column 2"));
    m_standardmodel.setData(m_standardmodel.index(0, 1), "Index 0,1");
    idx = m_flatmodel.index(0, 1);
    QVERIFY(idx.isValid());
    qDebug()<<"Index 0,1:"<<idx.data();
    QCOMPARE(idx.data(), QVariant("Index 0,1"));

    qDebug()<<"Set 2 rows, 2 columns";
    m_standardmodel.setRowCount(2);
    QCOMPARE(m_flatmodel.rowCount(), 2);
    m_standardmodel.setData(m_standardmodel.index(1, 0), "Index 1,0");
    idx = m_flatmodel.index(1, 0);
    QVERIFY(idx.isValid());
    qDebug()<<"Index 1,0:"<<idx.data();
    QCOMPARE(idx.data(), QVariant("Index 1,0"));

    m_standardmodel.setData(m_standardmodel.index(1, 1), "Index 1,1");
    idx = m_flatmodel.index(1, 1);
    QVERIFY(idx.isValid());
    qDebug()<<"Index 1,1:"<<idx.data();
    QCOMPARE(idx.data(), QVariant("Index 1,1"));
    
    qDebug()<<"Add child on last index, adds a new row 1 in the flat model";

    // NOTE: m_standardmodel.insertRow(0, m_standardmodel.index(1, 0));
    // does not work as there will be no columns and thus no valid indexes for this row
    QStandardItem *item = m_standardmodel.itemFromIndex(m_standardmodel.index(1, 0));
    QList<QStandardItem*> items;
    items << new QStandardItem("Child last column 1") << new QStandardItem("Child last column 2");
    item->appendRow(items);
    QModelIndex parent = m_standardmodel.index(1, 0);
    QCOMPARE(m_standardmodel.rowCount(parent), 1);
    QCOMPARE(m_flatmodel.rowCount(), 3);
    idx = m_flatmodel.index(2, 0);
    QCOMPARE(idx.data(), QVariant("Child last column 1"));
    idx = m_flatmodel.index(2, 1);
    QCOMPARE(idx.data(), QVariant("Child last column 2"));

    qDebug()<<"add child on first index";
    
    item = m_standardmodel.itemFromIndex(m_standardmodel.index(0, 0));
    items.clear();
    items << new QStandardItem("Child first column 1") << new QStandardItem("Child first column 2");
    item->appendRow(items);
    QCOMPARE(m_flatmodel.rowCount(), 4);
    idx = m_flatmodel.index(1, 0);
    QCOMPARE(idx.data(), QVariant("Child first column 1"));
    idx = m_flatmodel.index(1, 1);
    QCOMPARE(idx.data(), QVariant("Child first column 2"));

    qDebug()<<"add row (2) on top level between first and last";
    
    item = m_standardmodel.invisibleRootItem();
    items.clear();
    items << new QStandardItem("New index 1,0") << new QStandardItem("New index 1,1");
    item->insertRow(1, items);
    QCOMPARE(m_flatmodel.rowCount(), 5);
    idx = m_flatmodel.index(2, 0);
    QCOMPARE(idx.data(), QVariant("New index 1,0"));
    idx = m_flatmodel.index(2, 1);
    QCOMPARE(idx.data(), QVariant("New index 1,1"));

    qDebug()<<"Add child on middle index, adds row 3 to flat model";
    
    item = m_standardmodel.itemFromIndex(m_standardmodel.index(1, 0));
    items.clear();
    items << new QStandardItem("Child middle column 1") << new QStandardItem("Child middle column 2");
    item->appendRow(items);
    QCOMPARE(m_flatmodel.rowCount(), 6);
    idx = m_flatmodel.index(3, 0);
    QCOMPARE(idx.data().toString(), QVariant("Child middle column 1").toString());
    idx = m_flatmodel.index(3, 1);
    QCOMPARE(idx.data(), QVariant("Child middle column 2"));

    qDebug()<<"Add child on middle index's child, adds row 4 to flat model";
    
    parent = m_standardmodel.index(1, 0);
    QCOMPARE(parent.data().toString(), QString("New index 1,0"));
    idx = m_standardmodel.index(0, 0, parent);
    QCOMPARE(idx.data().toString(), QString("Child middle column 1"));
    item = m_standardmodel.itemFromIndex(idx);
    items.clear();
    items << new QStandardItem("Child of middle child column 1") << new QStandardItem("Child of middle child column 2");
    item->appendRow(items);
    QCOMPARE(m_flatmodel.rowCount(), 7);
    idx = m_flatmodel.index(4, 0);
    QCOMPARE(idx.data().toString(), QVariant("Child of middle child column 1").toString());
    idx = m_flatmodel.index(4, 1);
    QCOMPARE(idx.data(), QVariant("Child of middle child column 2"));

    qDebug()<<"Add child on middle index at row 0, adds row 3 to flat model";
    
    idx = m_standardmodel.index(1, 0);
    QCOMPARE(idx.data().toString(), QString("New index 1,0"));
    item = m_standardmodel.itemFromIndex(idx);
    items.clear();
    items << new QStandardItem("Index 1,0 -> Index 0,0") << new QStandardItem("Index 1,0 -> Index 0,1");
    item->insertRow(0, items);
    QCOMPARE(m_flatmodel.rowCount(), 8);
    idx = m_flatmodel.index(3, 0);
    QCOMPARE(idx.data().toString(), QVariant("Index 1,0 -> Index 0,0").toString());
    idx = m_flatmodel.index(3, 1);
    QCOMPARE(idx.data(), QVariant("Index 1,0 -> Index 0,1"));

    qDebug()<<"Add child on middle index at row 1, adds row 4 to flat model";
    
    idx = m_standardmodel.index(1, 0);
    QCOMPARE(idx.data().toString(), QString("New index 1,0"));
    item = m_standardmodel.itemFromIndex(idx);
    items.clear();
    items << new QStandardItem("Index 1,0 -> Index 1,0") << new QStandardItem("Index 1,0 -> Index 1,1");
    item->insertRow(1, items);
    QCOMPARE(m_flatmodel.rowCount(), 9);
    idx = m_flatmodel.index(4, 0);
    QCOMPARE(idx.data().toString(), QVariant("Index 1,0 -> Index 1,0").toString());
    idx = m_flatmodel.index(4, 1);
    QCOMPARE(idx.data(), QVariant("Index 1,0 -> Index 1,1"));

    qDebug()<<"Add child on middle index at last row (4), adds row 8 to flat model";
    
    idx = m_standardmodel.index(1, 0);
    QCOMPARE(idx.data().toString(), QString("New index 1,0"));
    item = m_standardmodel.itemFromIndex(idx);
    items.clear();
    items << new QStandardItem("Index 1,0 -> Index 4,0") << new QStandardItem("Index 1,0 -> Index 4,1");
    item->insertRow(3, items);
    QCOMPARE(m_standardmodel.rowCount(m_standardmodel.index(1, 0)), 4);
    QCOMPARE(m_flatmodel.rowCount(), 10);
    idx = m_flatmodel.index(7, 0);
    QCOMPARE(idx.data().toString(), QVariant("Index 1,0 -> Index 4,0").toString());
    idx = m_flatmodel.index(7, 1);
    QCOMPARE(idx.data(), QVariant("Index 1,0 -> Index 4,1"));
}

void FlatProxyModelTester::testInsertRemoveTop()
{
    QSortFilterProxyModel sf;
    FlatProxyModel fm;
    QStandardItemModel sm;

    sf.setSourceModel(&fm);
    fm.setSourceModel(&sm);

    sm.setHeaderData(0, Qt::Horizontal, "Column 0");
    QCOMPARE(sm.rowCount(), 0);

    // insert
    sm.insertRow(0, new QStandardItem("First"));
    QCOMPARE(sm.rowCount(), 1);
    QCOMPARE(fm.rowCount(), 1);
    QCOMPARE(sf.rowCount(), 1);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());
    QCOMPARE(sf.index(0, 0).data(), QVariant("First"));

    sm.insertRow(1, new QStandardItem("Second"));
    QCOMPARE(sm.rowCount(), 2);
    QCOMPARE(fm.rowCount(), 2);
    QCOMPARE(sf.rowCount(), 2);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());
    QCOMPARE(sm.index(1, 0).data(), sf.index(1, 0).data());
    QCOMPARE(sf.index(0, 0).data(), QVariant("First"));
    QCOMPARE(sf.index(1, 0).data(), QVariant("Second"));

    sm.insertRow(1, new QStandardItem("In between"));
    QCOMPARE(sm.rowCount(), 3);
    QCOMPARE(fm.rowCount(), 3);
    QCOMPARE(sf.rowCount(), 3);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());
    QCOMPARE(sm.index(1, 0).data(), sf.index(1, 0).data());
    QCOMPARE(sm.index(2, 0).data(), sf.index(2, 0).data());
    QCOMPARE(sf.index(0, 0).data(), QVariant("First"));
    QCOMPARE(sf.index(1, 0).data(), QVariant("In between"));
    QCOMPARE(sf.index(2, 0).data(), QVariant("Second"));

    sm.insertRow(0, new QStandardItem("Before first"));
    QCOMPARE(sm.rowCount(), 4);
    QCOMPARE(fm.rowCount(), 4);
    QCOMPARE(sf.rowCount(), 4);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());
    QCOMPARE(sm.index(1, 0).data(), sf.index(1, 0).data());
    QCOMPARE(sm.index(2, 0).data(), sf.index(2, 0).data());
    QCOMPARE(sm.index(3, 0).data(), sf.index(3, 0).data());
    QCOMPARE(sf.index(0, 0).data(), QVariant("Before first"));
    QCOMPARE(sf.index(1, 0).data(), QVariant("First"));
    QCOMPARE(sf.index(2, 0).data(), QVariant("In between"));
    QCOMPARE(sf.index(3, 0).data(), QVariant("Second"));

    // remove
    sm.removeRow(0);
    QCOMPARE(sm.rowCount(), 3);
    QCOMPARE(fm.rowCount(), 3);
    QCOMPARE(sf.rowCount(), 3);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());
    QCOMPARE(sm.index(1, 0).data(), sf.index(1, 0).data());
    QCOMPARE(sm.index(2, 0).data(), sf.index(2, 0).data());
    QCOMPARE(sf.index(0, 0).data(), QVariant("First"));
    QCOMPARE(sf.index(1, 0).data(), QVariant("In between"));
    QCOMPARE(sf.index(2, 0).data(), QVariant("Second"));

    sm.removeRow(1);
    QCOMPARE(sm.rowCount(), 2);
    QCOMPARE(fm.rowCount(), 2);
    QCOMPARE(sf.rowCount(), 2);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());
    QCOMPARE(sm.index(1, 0).data(), sf.index(1, 0).data());
    QCOMPARE(sf.index(0, 0).data(), QVariant("First"));
    QCOMPARE(sf.index(1, 0).data(), QVariant("Second"));

    sm.removeRow(1);
    QCOMPARE(sm.rowCount(), 1);
    QCOMPARE(fm.rowCount(), 1);
    QCOMPARE(sf.rowCount(), 1);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());
    QCOMPARE(sf.index(0, 0).data(), QVariant("First"));

    sm.removeRow(0);
    QCOMPARE(sm.rowCount(), 0);
    QCOMPARE(fm.rowCount(), 0);
    QCOMPARE(sf.rowCount(), 0);
}

void FlatProxyModelTester::testInsertRemoveChildren()
{
    QSortFilterProxyModel sf;
    FlatProxyModel fm;
    QStandardItemModel sm;

    sf.setSourceModel(&fm);
    fm.setSourceModel(&sm);

    sm.setHeaderData(0, Qt::Horizontal, "Column 0");
    QCOMPARE(sm.rowCount(), 0);

    QStandardItem *pitem = new QStandardItem("Parent");
    sm.insertRow(0, pitem);
    QCOMPARE(sm.rowCount(), 1);
    QCOMPARE(fm.rowCount(), 1);
    QCOMPARE(sf.rowCount(), 1);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());
    QCOMPARE(sf.index(0, 0).data(), QVariant("Parent"));

    QModelIndex parent = sm.index(0, 0);
    QVERIFY(parent.isValid());

    QStandardItem *item = new QStandardItem("First child");
    pitem->insertRow(0, item);
    QCOMPARE(sm.rowCount(parent), 1);
    QCOMPARE(fm.rowCount(), 2);
    QCOMPARE(sf.rowCount(), 2);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(1, 0).data());
    QCOMPARE(sf.index(1, 0).data(), QVariant("First child"));

    item = new QStandardItem("Second child");
    pitem->insertRow(1, item);
    QCOMPARE(sm.rowCount(parent), 2);
    QCOMPARE(fm.rowCount(), 3);
    QCOMPARE(sf.rowCount(), 3);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(1, 0).data());
    QCOMPARE(sm.index(1, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sf.index(1, 0).data(), QVariant("First child"));
    QCOMPARE(sf.index(2, 0).data(), QVariant("Second child"));

    item = new QStandardItem("In between");
    pitem->insertRow(1, item);
    QCOMPARE(sm.rowCount(parent), 3);
    QCOMPARE(fm.rowCount(), 4);
    QCOMPARE(sf.rowCount(), 4);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(1, 0).data());
    QCOMPARE(sm.index(1, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sm.index(2, 0, parent).data(), sf.index(3, 0).data());
    QCOMPARE(sf.index(1, 0).data(), QVariant("First child"));
    QCOMPARE(sf.index(2, 0).data(), QVariant("In between"));
    QCOMPARE(sf.index(3, 0).data(), QVariant("Second child"));

    item = new QStandardItem("Before first");
    pitem->insertRow(0, item);
    QCOMPARE(sm.rowCount(parent), 4);
    QCOMPARE(fm.rowCount(), 5);
    QCOMPARE(sf.rowCount(), 5);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(1, 0).data());
    QCOMPARE(sm.index(1, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sm.index(2, 0, parent).data(), sf.index(3, 0).data());
    QCOMPARE(sm.index(3, 0, parent).data(), sf.index(4, 0).data());
    QCOMPARE(sf.index(1, 0).data(), QVariant("Before first"));
    QCOMPARE(sf.index(2, 0).data(), QVariant("First child"));
    QCOMPARE(sf.index(3, 0).data(), QVariant("In between"));
    QCOMPARE(sf.index(4, 0).data(), QVariant("Second child"));

    sm.removeRow(0, parent);
    QCOMPARE(sm.rowCount(parent), 3);
    QCOMPARE(fm.rowCount(), 4);
    QCOMPARE(sf.rowCount(), 4);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(1, 0).data());
    QCOMPARE(sm.index(1, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sm.index(2, 0, parent).data(), sf.index(3, 0).data());
    QCOMPARE(sf.index(1, 0).data(), QVariant("First child"));
    QCOMPARE(sf.index(2, 0).data(), QVariant("In between"));
    QCOMPARE(sf.index(3, 0).data(), QVariant("Second child"));

    sm.removeRow(1, parent);
    QCOMPARE(sm.rowCount(parent), 2);
    QCOMPARE(fm.rowCount(), 3);
    QCOMPARE(sf.rowCount(), 3);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(1, 0).data());
    QCOMPARE(sm.index(1, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sf.index(1, 0).data(), QVariant("First child"));
    QCOMPARE(sf.index(2, 0).data(), QVariant("Second child"));

    sm.removeRow(1, parent);
    QCOMPARE(sm.rowCount(parent), 1);
    QCOMPARE(fm.rowCount(), 2);
    QCOMPARE(sf.rowCount(), 2);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(1, 0).data());
    QCOMPARE(sf.index(1, 0).data(), QVariant("First child"));

    sm.removeRow(0, parent);
    QCOMPARE(sm.rowCount(parent), 0);
    QCOMPARE(fm.rowCount(), 1);
    QCOMPARE(sf.rowCount(), 1);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());

    sm.removeRow(0);
    QCOMPARE(sm.rowCount(), 0);
    QCOMPARE(fm.rowCount(), 0);
    QCOMPARE(sf.rowCount(), 0);
}

void FlatProxyModelTester::testInsertRemoveGrandChildren()
{
    QSortFilterProxyModel sf;
    FlatProxyModel fm;
    QStandardItemModel sm;

    sf.setSourceModel(&fm);
    fm.setSourceModel(&sm);

    sm.setHeaderData(0, Qt::Horizontal, "Column 0");
    QCOMPARE(sm.rowCount(), 0);

    QStandardItem *pitem = new QStandardItem("Parent");
    sm.insertRow(0, pitem);
    QCOMPARE(sm.rowCount(), 1);
    QCOMPARE(fm.rowCount(), 1);
    QCOMPARE(sf.rowCount(), 1);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());
    QCOMPARE(sf.index(0, 0).data(), QVariant("Parent"));

    QModelIndex grandparent = sm.index(0, 0);
    QVERIFY(grandparent.isValid());

    QStandardItem *gitem = new QStandardItem("First child");
    pitem->insertRow(0, gitem);
    QCOMPARE(sm.rowCount(grandparent), 1);
    QCOMPARE(fm.rowCount(), 2);
    QCOMPARE(sf.rowCount(), 2);
    QCOMPARE(sm.index(0, 0, grandparent).data(), sf.index(1, 0).data());
    QCOMPARE(sf.index(1, 0).data(), QVariant("First child"));

    QModelIndex parent = sm.index(0, 0, grandparent);
    QVERIFY(parent.isValid());

    QStandardItem *item = new QStandardItem("First grandchild");
    gitem->insertRow(0, item);
    QCOMPARE(sm.rowCount(parent), 1);
    QCOMPARE(fm.rowCount(), 3);
    QCOMPARE(sf.rowCount(), 3);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sf.index(2, 0).data(), QVariant("First grandchild"));

    item = new QStandardItem("Second grandchild");
    gitem->insertRow(1, item);
    QCOMPARE(sm.rowCount(parent), 2);
    QCOMPARE(fm.rowCount(), 4);
    QCOMPARE(sf.rowCount(), 4);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sm.index(1, 0, parent).data(), sf.index(3, 0).data());
    QCOMPARE(sf.index(2, 0).data(), QVariant("First grandchild"));
    QCOMPARE(sf.index(3, 0).data(), QVariant("Second grandchild"));

    item = new QStandardItem("In between");
    gitem->insertRow(1, item);
    QCOMPARE(sm.rowCount(parent), 3);
    QCOMPARE(fm.rowCount(), 5);
    QCOMPARE(sf.rowCount(), 5);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sm.index(1, 0, parent).data(), sf.index(3, 0).data());
    QCOMPARE(sm.index(2, 0, parent).data(), sf.index(4, 0).data());
    QCOMPARE(sf.index(2, 0).data(), QVariant("First grandchild"));
    QCOMPARE(sf.index(3, 0).data(), QVariant("In between"));
    QCOMPARE(sf.index(4, 0).data(), QVariant("Second grandchild"));

    item = new QStandardItem("Before first");
    gitem->insertRow(0, item);
    QCOMPARE(sm.rowCount(parent), 4);
    QCOMPARE(fm.rowCount(), 6);
    QCOMPARE(sf.rowCount(), 6);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sm.index(1, 0, parent).data(), sf.index(3, 0).data());
    QCOMPARE(sm.index(2, 0, parent).data(), sf.index(4, 0).data());
    QCOMPARE(sm.index(3, 0, parent).data(), sf.index(5, 0).data());
    QCOMPARE(sf.index(2, 0).data(), QVariant("Before first"));
    QCOMPARE(sf.index(3, 0).data(), QVariant("First grandchild"));
    QCOMPARE(sf.index(4, 0).data(), QVariant("In between"));
    QCOMPARE(sf.index(5, 0).data(), QVariant("Second grandchild"));

    sm.removeRow(0, parent);
    QCOMPARE(sm.rowCount(parent), 3);
    QCOMPARE(fm.rowCount(), 5);
    QCOMPARE(sf.rowCount(), 5);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sm.index(1, 0, parent).data(), sf.index(3, 0).data());
    QCOMPARE(sm.index(2, 0, parent).data(), sf.index(4, 0).data());
    QCOMPARE(sf.index(2, 0).data(), QVariant("First grandchild"));
    QCOMPARE(sf.index(3, 0).data(), QVariant("In between"));
    QCOMPARE(sf.index(4, 0).data(), QVariant("Second grandchild"));

    sm.removeRow(1, parent);
    QCOMPARE(sm.rowCount(parent), 2);
    QCOMPARE(fm.rowCount(), 4);
    QCOMPARE(sf.rowCount(), 4);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sm.index(1, 0, parent).data(), sf.index(3, 0).data());
    QCOMPARE(sf.index(2, 0).data(), QVariant("First grandchild"));
    QCOMPARE(sf.index(3, 0).data(), QVariant("Second grandchild"));

    sm.removeRow(1, parent);
    QCOMPARE(sm.rowCount(parent), 1);
    QCOMPARE(fm.rowCount(), 3);
    QCOMPARE(sf.rowCount(), 3);
    QCOMPARE(sm.index(0, 0, parent).data(), sf.index(2, 0).data());
    QCOMPARE(sf.index(2, 0).data(), QVariant("First grandchild"));

    sm.removeRow(0, parent);
    QCOMPARE(sm.rowCount(parent), 0);
    QCOMPARE(fm.rowCount(), 2);
    QCOMPARE(sf.rowCount(), 2);
    QCOMPARE(sm.index(0, 0, grandparent).data(), sf.index(1, 0).data());
    QCOMPARE(sf.index(1, 0).data(), QVariant("First child"));

    QCOMPARE(sm.rowCount(grandparent), 1);
    sm.removeRow(0, grandparent);
    QCOMPARE(sm.rowCount(grandparent), 0);
    QCOMPARE(fm.rowCount(), 1);
    QCOMPARE(sf.rowCount(), 1);
    QCOMPARE(sm.index(0, 0).data(), sf.index(0, 0).data());
    QCOMPARE(sf.index(0, 0).data(), QVariant("Parent"));

    QCOMPARE(sm.rowCount(), 1);
    sm.removeRow(0);
    QCOMPARE(sm.rowCount(), 0);
    QCOMPARE(fm.rowCount(), 0);
    QCOMPARE(sf.rowCount(), 0);
}

void FlatProxyModelTester::testWithNodeItemModel()
{
    Project project;
    Task *t = project.createTask();
    t->setName("S1");
    project.addSubTask(t, &project);
    Task *t1 = project.createTask();
    t1->setName("S1.1");
    project.addSubTask(t1, t);
    t = project.createTask();
    t->setName("T1.1.1");
    project.addSubTask(t, t1);
    
    NodeItemModel model;
    model.setProject(&project);
    
    FlatProxyModel flatmodel;
    flatmodel.setSourceModel(&model);
    
    QCOMPARE(flatmodel.rowCount(), 3);
    QModelIndex idx = flatmodel.index(0, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("S1"));
    idx = flatmodel.index(1, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("S1.1"));
    idx = flatmodel.index(2, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("T1.1.1"));

    // test non 0 column
    int column = NodeModel::NodeType;
    idx = flatmodel.index(0, column);
    QCOMPARE(flatmodel.data(idx, Qt::EditRole), QVariant(Node::Type_Summarytask));
    idx = flatmodel.index(1, column);
    QCOMPARE(flatmodel.data(idx, Qt::EditRole), QVariant(Node::Type_Summarytask));
    idx = flatmodel.index(2, column);
    QCOMPARE(flatmodel.data(idx, Qt::EditRole), QVariant(Node::Type_Task));
    
    // test parent
    column = flatmodel.columnCount() - 1;
    idx = flatmodel.index(0, column);
    QCOMPARE(flatmodel.data(idx), QVariant());
    idx = flatmodel.index(1, column);
    QCOMPARE(flatmodel.data(idx), QVariant("S1"));
    idx = flatmodel.index(2, column);
    QCOMPARE(flatmodel.data(idx), QVariant("S1.1"));

    t = project.createTask();
    t->setName("S2");
    project.addSubTask(t, &project);
    t1 = project.createTask();
    t1->setName("S2.1");
    project.addSubTask(t1, t);
    t = project.createTask();
    t->setName("T2.1.1");
    project.addSubTask(t, t1);
    
    QCOMPARE(flatmodel.rowCount(), 6);
    idx = flatmodel.index(0, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("S1"));
    idx = flatmodel.index(1, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("S1.1"));
    idx = flatmodel.index(2, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("T1.1.1"));
    idx = flatmodel.index(3, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("S2"));
    idx = flatmodel.index(4, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("S2.1"));
    idx = flatmodel.index(5, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("T2.1.1"));

    t = project.createTask();
    t->setName("T3");
    project.addSubTask(t, &project);
    QCOMPARE(flatmodel.rowCount(), 7);
    idx = flatmodel.index(6, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("T3"));
    
    project.takeTask(t);
    QCOMPARE(flatmodel.rowCount(), 6);

    project.addSubTask(t, &project);
    QCOMPARE(flatmodel.rowCount(), 7);
    idx = flatmodel.index(6, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("T3"));
    
    project.moveTaskUp(t);
    idx = flatmodel.index(3, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("T3"));
    idx = flatmodel.index(4, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("S2"));
    idx = flatmodel.index(5, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("S2.1"));
    idx = flatmodel.index(6, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("T2.1.1"));
    
    project.moveTask(t, &project, 0);
    idx = flatmodel.index(0, 0);
    QCOMPARE(flatmodel.data(idx), QVariant("T3"));
}

} //namespace KPlato

QTEST_GUILESS_MAIN(KPlato::FlatProxyModelTester)
