/****************************************************************************
** Copyright (C) 2001-2020 Klaralvdalens Datakonsult AB. All rights reserved.
**
** This file is part of the KD Chart library.
**
** Licensees holding valid commercial KD Chart licenses may use this file in
** accordance with the KD Chart Commercial License Agreement provided with
** the Software.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 and version 3 as published by the
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** Contact info@kdab.com if any conditions of this licensing are not
** clear to you.
**
**********************************************************************/
#include "ProjectModel.h"
#include <QList>
#include <QDateTime>
#include <QFile>
#include <QDebug>
#include <KDGanttGlobal>
#include <KDGanttStyleOptionGanttItem>
#include <cassert>
#include "MyItemDelegate.h"
#include "kdganttconstraint.h"
#include "ProjectNode.h"
ProjectModel::ProjectModel( QObject* parent )
: QAbstractItemModel( parent ), m_root( new ProjectNode(this) ), m_pConstraintModel(nullptr)
{
}
ProjectModel::~ProjectModel()
{
delete m_root;
}
bool ProjectModel::load( const QString& filename )
{
Q_UNUSED(filename)
// TODO: read data
delete m_root;
m_root = new ProjectNode(this);
return true;
}
bool ProjectModel::save( const QString& filename )
{
Q_UNUSED(filename);
return true;
}
int ProjectModel::getNodeIndex(ProjectNode* pNode, ProjectNode*& pParent)
{
// todo: 递归查找
pParent = m_root;
return m_root->childNumber(pNode);
}
int ProjectModel::getNodeIndex(ProjectNode* pNode)
{
return m_root->childNumber(pNode);
}
ProjectNode* ProjectModel::getNode(int idx, ProjectNode* pParent)
{
if (!pParent)
{
pParent = m_root;
}
if (idx < pParent->childCount())
{
return pParent->child(idx);
}
else
{
return nullptr;
}
}
#define DEBUG_OUT(x) qDebug() << (x)
void ProjectModel::updateRelation()
{
DEBUG_OUT("============================================================");
for (int i = 0; i < m_root->childCount(); i++)
{
ProjectNode* pRefNode = m_root->child(i);
//updateRelation(pRefNode);
for (int j = 0; j < m_root->childCount(); j++)
{
ProjectNode* pThisNode = m_root->child(j);
QList< NodeContraint>* pConstraints = pThisNode->getConstraintList();
for(int c = 0; c < pConstraints->size(); c++)
{
if (pConstraints->at(c).pRefNode == pRefNode && pConstraints->at(c).pSelfNode == pThisNode)
{
// 如果当前的参考节点匹配, 则调整自身节点
KDGantt::Constraint::RelationType eNextRelationType = pConstraints->at(c).eRelationType;
int iNextMs = pConstraints->at(c).iTimeMs;
pThisNode->recalcRefTime(pRefNode, eNextRelationType, iNextMs);
DEBUG_OUT(QString::asprintf("%d %d ref=%d : %d->recalcRefTime", i, j, this->getNodeIndex(pRefNode), this->getNodeIndex(pThisNode)));
updateRelation(pThisNode);
}
}
}
}
}
void ProjectModel::updateRelation(ProjectNode* pRefNode)
{
DEBUG_OUT(QString::asprintf("enter Recurve pRef = %d", this->getNodeIndex(pRefNode)));
for (int j = 0; j < m_root->childCount(); j++)
{
ProjectNode* pThisNode = m_root->child(j);
QList< NodeContraint>* pConstraints = pThisNode->getConstraintList();
for (int c = 0; c < pConstraints->size(); c++)
{
if (pConstraints->at(c).pRefNode == pRefNode && pConstraints->at(c).pSelfNode == pThisNode)
{
// 如果当前的参考节点匹配, 则调整自身节点
KDGantt::Constraint::RelationType eNextRelationType = pConstraints->at(c).eRelationType;
int iNextMs = pConstraints->at(c).iTimeMs;
DEBUG_OUT(QString::asprintf("c=%d %d ref=%d : %d->recalcRefTime", c, j, this->getNodeIndex(pRefNode), this->getNodeIndex(pThisNode)));
pThisNode->recalcRefTime(pRefNode, eNextRelationType, iNextMs);
updateRelation(pThisNode);
}
}
}
DEBUG_OUT(QString::asprintf("exit Recurve pRef = %d", this->getNodeIndex(pRefNode)));
}
bool ProjectModel::hasStartConstraint(ProjectNode* pNode)
{
QList< NodeContraint>* pConstraints = pNode->getConstraintList();
for (int c = 0; c < pConstraints->size(); c++)
{
if ((KDGantt::Constraint::RelationType::FinishStart == pConstraints->at(c).eRelationType)
|| (KDGantt::Constraint::RelationType::StartStart == pConstraints->at(c).eRelationType))
{
return true;
}
}
return false;
}
bool ProjectModel::hasFinishConstraint(ProjectNode* pNode)
{
QList< NodeContraint>* pConstraints = pNode->getConstraintList();
for (int c = 0; c < pConstraints->size(); c++)
{
if ((KDGantt::Constraint::RelationType::FinishFinish == pConstraints->at(c).eRelationType)
|| (KDGantt::Constraint::RelationType::StartFinish == pConstraints->at(c).eRelationType))
{
return true;
}
}
return false;
}
bool ProjectModel::hasConstraint(ProjectNode* pNodeA, ProjectNode* pNodeB)
{
// todo: 需要改为递归查找
for (int j = 0; j < m_root->childCount(); j++)
{
ProjectNode* pThisNode = m_root->child(j);
QList< NodeContraint>* pConstraints = pThisNode->getConstraintList();
for (int c = 0; c < pConstraints->size(); c++)
{
if (
((pConstraints->at(c).pRefNode == pNodeA) && (pConstraints->at(c).pSelfNode == pNodeB))
|| ((pConstraints->at(c).pRefNode == pNodeB) && (pConstraints->at(c).pSelfNode == pNodeA))
)
{
return true;
}
}
}
return false;
}
void ProjectModel::updateConstraint()
{
// 更新关系
updateRelation();
// 清除关系
// m_pConstraintModel->cleanup(); //clearup未实现
m_pConstraintModel->clear();
for (int j = 0; j < m_root->childCount(); j++)
{
ProjectNode* pThisNode = m_root->child(j);
QList< NodeContraint>* pConstraints = pThisNode->getConstraintList();
for (int c = 0; c < pConstraints->size(); c++)
{
ProjectNode* pParent_Start = nullptr;
int iStart = getNodeIndex(pConstraints->at(c).pRefNode, pParent_Start);
ProjectNode* pParent_End = nullptr;
int iEnd = getNodeIndex(pConstraints->at(c).pSelfNode, pParent_End);
KDGantt::Constraint constr(this->index(iStart, 0, QModelIndex()), this->index(iEnd, 0, QModelIndex()), pConstraints->at(c).eConstraintType, pConstraints->at(c).eRelationType);
m_pConstraintModel->addConstraint(constr);
}
}
//for (int i = 0; i < lstNodeConstraints.size(); i++)
//{
// ProjectNode* pParent_Start = nullptr;
// int iStart = getNodeIndex(lstNodeConstraints.at(i).pRefNode, pParent_Start);
// ProjectNode* pParent_End = nullptr;
// int iEnd = getNodeIndex(lstNodeConstraints.at(i).pSelfNode, pParent_End);
// KDGantt::Constraint c(this->index(iStart, 0, QModelIndex()), this->index(iEnd, 0, QModelIndex()), lstNodeConstraints.at(i).eConstraintType, lstNodeConstraints.at(i).eRelationType);
// m_pConstraintModel->addConstraint(c);
//}
}
int ProjectModel::rowCount( const QModelIndex& idx ) const
{
if ( idx.isValid() ) return static_cast<ProjectNode*>( idx.internalPointer() )->childCount();
else return m_root->childCount();
}
int ProjectModel