logplus/Workflow/WFEngine/ObjectModel/ObjectModelBase/src/PaiObject.cpp
2026-01-16 17:18:41 +08:00

1343 lines
34 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file PaiObject.cpp
* @date 2013-03-15
*/
#include <QFile>
#include <QTime>
#include <QTextStream>
#include <QMutex>
#include <QObject>
#include "PaiObject.h"
#include "PaiObjectRecycler.h"
#include "PaiHtmlProperties.h"
#include "PaiLazyLoadNode.h"
// #include "error.h"
// #include "Log.h"
#include "PaiMetaTypes.h"
using namespace pai::objectmodel;
// IMPLEMENT_PAI_OBJECT(PaiObject)
// pai::objectmodel::PaiObjectEventAgent pai::objectmodel::PaiObject::m_EventAgent;
PaiObject::PaiObject(PaiObject* pParent) :
m_flags(VisibibleOnTree | Syncabled),
m_properties(QObject::tr("Loading...")),
m_pParent(pParent),
m_OwnerID(-1),
m_id(QUuid::createUuid()),
m_dbid(0),
m_name(""), // 初始化名字必须为空,请不要轻易修改其初始化方法
m_TimeStamp(0),
m_EventEnabled(false), // 默认都不可以发送事件
m_SyncLockFlag(false),
m_type(pai::ios::UNKNOW)
{
m_pChildMutex = new QMutex();
}
PaiObject::~PaiObject()
{
if(m_children.count() > 0)
{
ReleaseChildren();
}
delete m_pChildMutex;
}
void PaiObject::Delete()
{
// ReleaseChildren();
// // 并不真正释放该控件,而是放入回收站来管理,由回收站决定何时释放
// m_pParent = NULL;
// GetObjectModelService()->GetObjectRecycler()->Push(this);
}
void PaiObject::ReleaseChildren()
{
// QList< PaiObject* >::iterator it = m_children.begin();
// while(it != m_children.end())
// {
// m_EventAgent.RemoveObjectChild(this, (*it));
// (*it)->Delete();
// ++it;
// }
// m_children.clear();
}
void PaiObject::Clone(const PaiObject & srcObject)
{
if(GetTypeID() != srcObject.GetTypeID())
{
QString errMsg = QObject::tr("Clone PaiObject failed! the type of %1 seems different with %2!").
arg(srcObject.GetName()).arg(GetName());
// throw pai::error::invalid_argument(errMsg.toStdString());
}
// m_id 不在Clone()函数拷贝之列
m_dbid = srcObject.m_dbid;
m_IconName = srcObject.m_IconName;
m_TypeName = srcObject.m_TypeName;
m_type = srcObject.m_type;
m_properties = srcObject.m_properties;
m_flags = srcObject.m_flags;
m_TimeStamp = srcObject.m_TimeStamp;
// 直接用m_name进行比对GetName是虚函数可能返回的不是m_name的值
if(m_name != srcObject.m_name)
{
SetName(srcObject.m_name); // a signal will be emit to changed the name of data tree node
}
}
void PaiObject::SetType(const pai::ios::DATA_TYPE & type)
{
m_type = type;
}
pai::ios::DATA_TYPE PaiObject::GetType() const
{
return m_type;
}
void PaiObject::SetID(const QUuid & id)
{
m_id = id;
}
QUuid PaiObject::GetID() const
{
return m_id;
}
void PaiObject::SetDBID(long long id)
{
if(m_dbid != id)
{
m_dbid = id;
// m_EventAgent.ObjectPropertyChanged(this, QString("DBID"), QVariant(m_dbid));
}
}
long long PaiObject::GetDBID() const
{
return m_dbid;
}
void PaiObject::SetOwnerID(long long id)
{
m_OwnerID = id;
}
long long PaiObject::GetOwnerID() const
{
return m_OwnerID;
}
PaiObject* PaiObject::GetParent() const
{
return m_pParent;
}
void PaiObject::SetParent(PaiObject*pParent)
{
m_pParent=pParent;
}
bool PaiObject::AddLazyLoadChild(MountTree mountTree)
{
if(GetChildrenCount() == 0)
{
bool bHasModified = HasModified();
bool bAdded = AddChild(new PaiLazyLoadNode, mountTree);
SetModified(bHasModified, false);
return bAdded;
}
return false;
}
bool PaiObject::RemoveLazyLoadChild()
{
foreach(PaiObject *pChild, m_children)
{
if(pChild->GetTypeID() == QUuid(PaiLazyLoadNode::GetTypeIDString()))
{
bool bHasModified = HasModified();
bool bRemoved = RemoveChild(pChild, true);
SetModified(bHasModified, false);
return bRemoved;
}
}
return false;
}
bool PaiObject::AddChild(PaiObject *pChild, MountTree mountTree)
{
m_pChildMutex->lock();
if(!m_children.contains(pChild))
{
foreach(PaiObject *pChildObj, m_children)
{
if((pChildObj->GetID() == pChild->GetID()) ||
((pChild->GetDBID() != 0) && (pChildObj->GetDBID() == pChild->GetDBID())))
{
m_pChildMutex->unlock();
return false;
}
}
if(pChild->m_pParent != this)
{
pChild->m_pParent = this;
}
SetFlagEnable(Modified, true);
m_children.push_back(pChild);
if(mountTree == MountOnTree)
{
// m_EventAgent.AddObjectChildren(this, QList< PaiObject* > () << pChild);
}
m_pChildMutex->unlock();
return true;
}
m_pChildMutex->unlock();
return false;
}
void PaiObject::SyncChildren(QList< PaiObject* > & children)
{
m_pChildMutex->lock();
// 检查并去掉重复添加项
QString repearItems;
for(int i = 0; i < children.count(); ++i)
{
PaiObject *pSrcObj = children.at(i);
for(int j = i + 1; j < children.count(); ++j)
{
PaiObject *pDestObj = children.at(j);
if((!pSrcObj) || ((pSrcObj->GetDBID() != 0) && (pSrcObj->GetDBID() == pDestObj->GetDBID())))
{
repearItems += (QObject::tr("%1:%2\n").arg(pDestObj->GetName()).arg(pDestObj->GetDBID()));
delete pDestObj;
children.removeOne(pDestObj);
--j; // 下一次循环仍在该位置
}
}
}
QList< PaiObject* > removedData = m_children;
QList< PaiObject* > addedData;
QList< PaiObject* > needUpdateData;
QList< PaiObject* > newUpdateData;
// 查询需要新添加和要删除的孩子
foreach(PaiObject *pChild, children)
{
PaiObject *pTreeData = GetChild(pChild->GetDBID());
if(pTreeData)
{
removedData.removeAll(pTreeData);
newUpdateData.append(pChild);
needUpdateData.append(pTreeData);
}
else
{
if(!pChild->HasFlag(Closed) && pChild->HasFlag(Syncabled))
{
pChild->AddLazyLoadChild(MountNoTree);
}
pChild->m_pParent = this;
addedData.append(pChild);
}
}
children.clear(); // 尽早清除,防止再被使用
SetFlagEnable(Modified, true);
// 添加新增的孩子
if(!addedData.empty())
{
m_children.append(addedData);
}
// RemoveChild也会加锁所以为了不发生死锁先解锁
m_pChildMutex->unlock();
// 同步去除的孩子
foreach(PaiObject *pChild, removedData)
{
if(!pChild->HasFlag(PaiObject::IgnoreSyncDB))
{
RemoveChild(pChild, true);
}
}
removedData.clear();
// 更新需要更新的对象
for(int i = 0; i < needUpdateData.count(); ++i)
{
if(newUpdateData.at(i)->GetTimeStamp() > needUpdateData.at(i)->GetTimeStamp())
{
needUpdateData.at(i)->SyncRefreshMsg(*(newUpdateData.at(i)));
delete newUpdateData.at(i);
}
}
needUpdateData.clear();
newUpdateData.clear();
// // 解锁之后再发送信号,防止在主线程执行死锁
// if(!addedData.empty())
// {
// m_EventAgent.AddObjectChildren(this, addedData);
// // 向数据树发送关闭信号(如果将来采取更换图标的方式,则不需要以下调用)
// foreach(PaiObject *pChild, addedData)
// {
// if(pChild->HasFlag(Closed))
// {
// m_EventAgent.CloseObject(pChild, true);
// }
// }
// }
// if(!repearItems.isEmpty())
// {
// pai::log::Error((QObject::tr("Refresh \"%1\" failed! Found repeat item:\n%2").arg(GetName()).arg(repearItems)).toStdString());
// //m_EventAgent.RefreshObjectFailed(this, QObject::tr("Refresh \"%1\" failed! Found repeat item:\n%2").arg(repearItems));
// }
}
bool PaiObject::InsertChild(int index, PaiObject *pChild)
{
if((pChild == NULL) || (index < 0) || (index > m_children.count()))
{
return false;
}
m_pChildMutex->lock();
if(!m_children.contains(pChild))
{
foreach(PaiObject *pChildObj, m_children)
{
if((pChildObj->GetID() == pChild->GetID()) ||
((pChild->GetDBID() != 0) && (pChildObj->GetDBID() == pChild->GetDBID())))
{
m_pChildMutex->unlock();
return false;
}
}
if(pChild->m_pParent != this)
{
pChild->m_pParent = this;
}
SetFlagEnable(Modified, true);
m_children.insert(index, pChild);
// m_EventAgent.InsertObjectChild(this, pChild, index);
m_pChildMutex->unlock();
return true;
}
m_pChildMutex->unlock();
return false;
}
bool PaiObject::RemoveChild(PaiObject *pChild, bool deleteChild)
{
m_pChildMutex->lock();
int nRemoved = m_children.removeAll(pChild);
SetFlagEnable(Modified, true);
if(deleteChild && (nRemoved == 1))
{
pChild->SetFlagEnable(Deleting, true);
// m_EventAgent.RemoveObjectChild(this, pChild);
pChild->Delete();
}
m_pChildMutex->unlock();
return nRemoved == 1;
}
bool PaiObject::CloseObject(QString *pErrorMessage)
{
if(!HasFlag(Closed)) // 如果没有关闭则采取关闭操作
{
if(TryDelete(*pErrorMessage) == false)
{
return false;
}
// 更改数据库
if(!EnableToDB(INACTIVE))
{
return false;
}
// 设置关闭标志
SetFlagEnable(PaiObject::Closed, true);
// 去掉子项,这个必须在发送关闭信号之前否则影响主工具栏对action的检查见34860
foreach(PaiObject *pObj, m_children)
{
RemoveChild(pObj, true);
}
// 向数据树发送关闭信号(如果将来采取更换图标的方式,则不需要以下调用)
// m_EventAgent.CloseObject(this, true);
}
return true;
}
bool PaiObject::OpenObject()
{
if(HasFlag(Closed)) // 如果没有打开则采取打开操作
{
// // 更改数据库
// if(!EnableToDB(ACTIVE))
// {
// return false;
// }
// // 设置打开标志
// SetFlagEnable(PaiObject::Closed, false);
// // 挂载子项这里从异步改为同步是因为下面发送信号引起的主工具栏检查action权限时需要工程先挂载好工区否则判断错误。见34860
// SyncDB(Own | Children | Force);
// // 向数据树发送打开信号(如果将来采取更换图标的方式,则不需要以下调用)
// m_EventAgent.CloseObject(this, false);
}
return true;
}
void PaiObject::SetExpand(bool expand)
{
// m_EventAgent.ObjectPropertyChanged(this, QString("NodeExpand"), QVariant(expand));
}
void PaiObject::GetChildren(QList< PaiObject* > & children) const
{
children = m_children;
}
int PaiObject::GetChildrenCount()
{
return m_children.count();
}
bool PaiObject::HasChildren()
{
return !m_children.isEmpty();
}
PaiObject* PaiObject::GetChild(const long long dbid) const
{
foreach(PaiObject* pChild, m_children)
{
if(pChild)
{
if(pChild->GetDBID() == dbid)
{
return pChild;
}
}
}
return NULL;
}
PaiObject* PaiObject::GetObject(const QUuid & id) const
{
if(this->m_id == id)
{
return const_cast< pai::objectmodel::PaiObject* > (this);
}
foreach(PaiObject *pChild, m_children)
{
if(pChild != NULL)
{
PaiObject *pFindObj = pChild->GetObject(id);
if(pFindObj != NULL)
{
return pFindObj;
}
}
}
return NULL;
}
PaiObject* PaiObject::GetObject(const long long dbid) const
{
if(dbid == m_dbid)
{
return const_cast< pai::objectmodel::PaiObject* > (this);
}
foreach(PaiObject *pChild, m_children)
{
if(pChild != NULL)
{
PaiObject* pFindObj = pChild->GetObject(dbid);
if(pFindObj)
{
return pFindObj;
}
}
}
return NULL;
}
void PaiObject::GetObjects(QList< PaiObject* > & objects) const
{
objects.append(const_cast< PaiObject* > (this));
foreach(PaiObject *pChild, m_children)
{
if(pChild != NULL)
{
pChild->GetObjects(objects);
}
}
}
QList< PaiObject* > PaiObject::GetObjects(const long long dbid) const
{
QList< PaiObject* > ids;
QList< PaiObject* > objs;
GetObjects(objs);
foreach(PaiObject *pObj, objs)
{
if(pObj && (pObj->GetDBID() == dbid))
{
ids.append(pObj);
}
}
return ids;
}
QList< PaiObject* > PaiObject::GetObjects() const
{
QList< PaiObject* > objs;
GetObjects(objs);
return objs;
}
PaiObject* PaiObject::GetObjectByName(const QString & name,int depth) const
{
if(this->m_name == name)
{
return const_cast< pai::objectmodel::PaiObject* > (this);
}
depth--;
if(depth>=0)
foreach(PaiObject *pChild, m_children)
{
PaiObject *pFindObj = pChild->GetObjectByName(name,depth);
if(pFindObj != NULL)
{
return pFindObj;
}
}
return NULL;
}
PaiObject* PaiObject::GetObjectByName(const QString & name) const
{
if(this->m_name == name)
{
return const_cast< pai::objectmodel::PaiObject* > (this);
}
foreach(PaiObject *pChild, m_children)
{
PaiObject *pFindObj = pChild->GetObjectByName(name);
if(pFindObj != NULL)
{
return pFindObj;
}
}
return NULL;
}
PaiObject* PaiObject::GetObjectByName(const QString & name, const QUuid & objectType) const
{
QString name1=name;
if(name1.indexOf("(3")>=0) {
name1=name1.replace("(3",":");
}
if((this->GetTypeID() == objectType) && (this->m_name == name1))
{
return const_cast< pai::objectmodel::PaiObject* > (this);
}
foreach(PaiObject *pChild, m_children)
{
PaiObject *pFindObject = pChild->GetObjectByName(name1, objectType);
if(pFindObject != NULL)
{
return pFindObject;
}
}
return NULL;
}
PaiObject* PaiObject::GetChildByType(const QUuid & typeID) const
{
foreach(PaiObject *pChild, m_children)
{
if(pChild->GetTypeID() == typeID)
{
return const_cast< pai::objectmodel::PaiObject* > (pChild);
}
}
return NULL;
}
PaiObject* PaiObject::GetObjectByType(const QUuid & typeID, int depth) const
{
if(this->GetTypeID() == typeID)
{
return const_cast< pai::objectmodel::PaiObject* > (this);
}
depth--;
if(depth >= 0)
{
foreach(PaiObject *pChild, m_children)
{
if(pChild)
{
pChild = pChild->GetObjectByType(typeID, depth);
if(pChild)
{
return pChild;
}
}
}
}
return NULL;
}
void PaiObject::GetObjectByType(QList< pai::objectmodel::PaiObject* > & children, const QUuid & typeID, int depth) const
{
if(this->GetTypeID() == typeID)
{
children.append(const_cast< pai::objectmodel::PaiObject* > (this));
}
depth--;
if(depth >= 0)
{
foreach(PaiObject *pChild, m_children)
{
if(pChild)
{
pChild->GetObjectByType(children, typeID, depth);
}
}
}
return;
}
void PaiObject::SetName(const QString & newName)
{
QString oldName(m_name);
if(oldName != newName)
{
m_name = newName;
SetFlagEnable(Modified, true);
// // 对象名发生改变,该信号可以通知数据树,更新为最新的名字
// m_EventAgent.ObjectPropertyChanged(this, QString("Name"), QVariant(m_name));
// // 对象被重命名,初始化命名,不算重命名,这里排除
// if(!oldName.isEmpty())
// {
// m_EventAgent.RenamedObject(this, newName, oldName);
// }
}
}
QString PaiObject::GetName() const
{
return m_name;
}
QString PaiObject::GetPhysicalFile() const
{
return QString("");
}
QString PaiObject::GetVisibleFile() const
{
QString fullPathName(m_name);
PaiObject* pParent = m_pParent;
while(pParent != NULL)
{
if(pParent->m_name != "")
{
fullPathName.prepend("/");
fullPathName.prepend(pParent->m_name);
}
pParent = pParent->m_pParent;
}
return fullPathName.prepend("/");
}
void PaiObject::SetIconName(const QString & iconName)
{
m_IconName = iconName;
}
QString PaiObject::GetIconName() const
{
return m_IconName;
}
QString PaiObject::GetBigIconName() const
{
QString iconName = m_IconName;
iconName.insert(iconName.lastIndexOf('.'), "_big");
return iconName;
}
bool PaiObject::HasFlag(Flag flag) const
{
return (m_flags & flag) == flag;
}
void PaiObject::SetFlagEnable(Flag flag, bool enable)
{
if(enable)
{
m_flags |= flag;
}
else
{
m_flags = m_flags & ~flag;
}
// m_EventAgent.ObjectPropertyChanged(this, QString("Flag"), QVariant(m_flags));
}
bool PaiObject::HasDataModified() const
{
return HasFlag(DataModified);
}
bool PaiObject::HasModified() const
{
if(HasFlag(Modified))
{
return true;
}
foreach(PaiObject *pChild, m_children)
{
if(pChild->HasModified())
{
return true;
}
}
return false;
}
void PaiObject::SetModified(bool modified, bool recursive)
{
SetFlagEnable(Modified, modified);
if(recursive)
{
foreach(PaiObject *pChild, m_children)
{
pChild->SetModified(modified, recursive);
}
}
}
QString PaiObject::GetNextChildName(const QString & childNamePrefix)
{
int nOrderNum = 0;
QString nextChildName = childNamePrefix + "1";//缺省值,如果没有孩子则返回它
int i = 0;
while(i != m_children.size())
{
nextChildName = childNamePrefix + QString::number(++nOrderNum);
i = 0;
foreach(PaiObject *pChild, m_children)
{
if(pChild->GetName() == nextChildName)
{
break;
}
++i;
}
}
return nextChildName;
}
bool PaiObject::Save(QString * /*pErrorMessage*/)
{
return false;
}
bool PaiObject::Update(QString * /*pErrorMessage*/)
{
return false;
}
bool PaiObject::SaveToDB(QString * /*pErrorMessage*/)
{
return false;
}
bool PaiObject::UpdateToDB(QString * /*pErrorMessage*/)
{
return false;
}
bool PaiObject::Erase(QString * /*pErrorMessage*/)
{
// 此处抛出异常,既可以保证需要删除的派生类有提示,也可防止不能删除的派生类被删除
// throw pai::error::io_error("Please define [Erase] function in derived class!");
return false;
}
bool PaiObject::EnableToDB(const int& /*status*/, QString * /*pErrorMessage*/)
{
return false;
}
QString PaiObject::GetProperties()
{
// try
{
std::vector< std::vector< pai::ios::property::PropertyItem > > itemgroup;
pai::ios::property::Property property;
property.GetProperty(GetDBID(), GetType(), itemgroup);
QString typeName;
if((itemgroup.size()) > 0 && (itemgroup.at(0).size() > 0))
{
typeName = "Type: " + QString(itemgroup.at(0).at(0).GetPropertyValue().c_str());
}
PaiHtmlProperties properties(GetBigIconName(), GetName(), typeName);
m_properties = properties.GetHtml(itemgroup); // 更新备份的属性信息加快相应速度
return m_properties;
}
// catch(pai::error::generic_error& e)
// {
// pai::log::Error(_FLF(QObject::tr("%1\nErrorCode:%2").arg(e.what()).arg(e.which()).toStdString()));
// return QObject::tr("Sorry, load properties failed!");
// }
// catch(std::exception &e)
// {
// pai::log::Error(_FLF(QObject::tr("Load properties filed:%1\n%2").arg(GetName()).arg(e.what()).toStdString()));
// return QObject::tr("Sorry, load properties failed!");
// }
// catch(...)
// {
// pai::log::Error(_FLF(QObject::tr("Unknown error when load properties for \"%1\"").arg(GetName()).toStdString()));
// return QObject::tr("Sorry, load properties failed!");
// }
}
QString PaiObject::GetBackupProperties() const
{
return m_properties;
}
void PaiObject::SetEventEnabled(bool yes)
{
m_EventEnabled = yes;
}
bool PaiObject::IsEventEnabled()
{
return m_EventEnabled;
}
bool PaiObject::IsBigDataObject() const
{
return false;
}
bool PaiObject::GetSyncChildren(QList< PaiObject* > & /*children*/)
{
return true;
}
QList<PaiObject*> PaiObject::GetBrothers(long long /*ownerID*/, const QUuid & /*ownerType*/)
{
return QList<PaiObject*>();
}
QString PaiObject::GetTypeName() const
{
return m_TypeName;
}
void PaiObject::SetTypeName(const QString & typeName)
{
m_TypeName = typeName;
}
bool PaiObject::Load(const long long /*dbid*/)
{
// 此处抛出异常,既可以保证需要从后台加载的派生类有提示,也可防止不能加载的派生类被错误加载
// throw pai::error::io_error("Please define [Load] function in derived class!");
return false;
}
bool PaiObject::Reload()
{
return Load(GetDBID());
}
bool PaiObject::SyncDB(pai::SyncModes mode)
{
// if(mode & pai::Own)
// {
// PaiObject *pObj = GetObjectModelService()->CreateObject(GetTypeID());
// if(pObj)
// {
// try
// {
// pObj->Load(GetDBID());
// //校验Load函数的DBID设置的正确性
// if(pObj->GetDBID() > 0 && pObj->GetDBID() != this->GetDBID())
// {
// throw pai::error::db_error("Load failure with database ID.", pai::error::ERR_NO_RESULT);
// }
// //更新与数据库不同步对象
// SyncRefreshMsg(*pObj);
// }
// catch(pai::error::generic_error & e)
// {
// if(e.which() == pai::error::ERR_NO_RESULT)
// {
// PaiObject * pParent = this->GetParent();
// if(pParent)
// {
// pParent->RemoveChild(this, true);
// delete pObj;
// pObj = NULL;
// return true;
// }
// }
// pai::log::Error(_FLF(QObject::tr("%1\nMore details:%2 ErrCode:%3") .arg(e.get_ui_message()).arg(
// e.what()).arg(e.which()).toStdString()));
// ::LogStackTrace(::GetStackTrace());
// // 此处异常信息应为已经格式化的用户可读信息,如不对,须在它处修改。
// m_EventAgent.RefreshObjectFailed(this, QObject::tr("Load %1 failed!").arg(e.what()));
// }
// catch(...)
// {
// pai::log::Error(_FLF(QObject::tr("Load \"%1\" failed!").arg(GetName()).toStdString()));
// ::LogStackTrace(::GetStackTrace());
// m_EventAgent.RefreshObjectFailed(this, QObject::tr("Load \"%1\" failed!").arg(GetName()));
// }
// delete pObj;
// pObj = NULL;
// }
// }
// if(mode & pai::Recursion)
// {
// return SyncChildren(true);
// }
// else if(mode & Children)
// {
// return SyncChildren(false);
// }
return true;
}
bool PaiObject::SyncChildren(bool recursion)
{
return true;
// // 降低同时多个线程同时同步统一个对象的几率
// while(m_SyncLockFlag)
// {
// // Sleep是以毫秒为单位不要用QT的sleep函数系统更改时间后该函数会出问题
// turtle::GetTurtleAPI()->Sleep(1000);
// }
// m_SyncLockFlag = true;
// try
// {
// if(HasFlag(PaiObject::Closed) || !HasFlag(PaiObject::Syncabled))
// {
// m_SyncLockFlag = false;
// return true;
// }
// // 设置已同步标志位,该语句尽量考前以防止该函数同时被调用
// SetFlagEnable(PaiObject::ChildrenLoaded, true);
// QList< PaiObject* > children;
// QTime tmpTime(0, 0, 0, 0);
// tmpTime.start();
// bool success = GetSyncChildren(children);
// // ----------------- 记录接口相应时间TODO 将会移除 ------------------------------
// int timeSpan = tmpTime.elapsed();
// QFile file("/tmp/refresh.csv");
// if(!file.exists())
// {
// file.open(QIODevice::Append | QIODevice::WriteOnly | QIODevice::Text);
// file.close();
// }
// if(!file.isOpen())
// {
// file.open(QIODevice::Append | QIODevice::WriteOnly | QIODevice::Text);
// }
// QTextStream txtOutput(&file);
// txtOutput << GetName() << "," << GetTypeName() << ", " << children.count() << " ," << timeSpan << endl;
// file.close();
// if(success)
// {
// // 去掉LazyLoad节点
// RemoveLazyLoadChild();
// // 同步节点孩子
// SyncChildren(children);
// // 备份属性信息,便于快速显示
// GetProperties();
// // 递归同步
// if(recursion)
// {
// foreach(PaiObject *pObject, m_children)
// {
// if(!HasFlag(PaiObject::Closed) && HasFlag(PaiObject::Syncabled))
// {
// pObject->SyncChildren(recursion);
// }
// }
// }
// }
// else
// {
// m_EventAgent.RefreshObjectFailed(this, QObject::tr("Get children failed!"));
// }
// file.close();
// m_SyncLockFlag = false;
// return success;
// }
// catch(pai::error::generic_error & e)
// {
// m_SyncLockFlag = false;
// pai::log::Error(_FLF(QObject::tr("%1\nMore details:%2 ErrCode:%3")
// .arg(e.get_ui_message()).arg(e.what()).arg(e.which()).toStdString()));
// ::LogStackTrace(::GetStackTrace());
// // 此处异常信息应为已经格式化的用户可读信息,如不对,须在它处修改。
// m_EventAgent.RefreshObjectFailed(this, QObject::tr("Refresh \"%1\" failed! -- %2").arg(GetName()).arg(e.what()));
// return false;
// }
// catch(std::exception &e)
// {
// m_SyncLockFlag = false;
// pai::log::Error(_FLF(QObject::tr("%1").arg(e.what()).toStdString()));
// ::LogStackTrace(::GetStackTrace());
// m_EventAgent.RefreshObjectFailed(this, QObject::tr("Refresh \"%1\" failed! -- %2").arg(GetName()).arg(e.what()));
// return false;
// }
// catch(...)
// {
// m_SyncLockFlag = false;
// pai::log::Error(_FLF(QObject::tr("Refresh \"%1\" failed!").arg(GetName()).toStdString()));
// ::LogStackTrace(::GetStackTrace());
// m_EventAgent.RefreshObjectFailed(this, QObject::tr("Refresh \"%1\" failed!").arg(GetName()));
// return false;
// }
}
void PaiObject::SetIgnoreSyncDB(bool ignore)
{
SetFlagEnable(PaiObject::IgnoreSyncDB, ignore);
}
void PaiObject::SetShadowNode(bool shadow)
{
SetFlagEnable(PaiObject::ShadowNode, shadow);
}
void PaiObject::SetSyncabled(bool enable)
{
SetFlagEnable(PaiObject::Syncabled, enable);
}
bool PaiObject::HasPermissionFlag(int type) const
{
//此处只是用来处理PaiObject对象PaiProject与PaiSurvey分别单独实现
//缺省继承工区的权限,这里耦合了PaiSurvey的类型ID
PaiObject *survey = GetForebear(QUuid("{eea801c0-a17f-4dea-b639-c88c4cfe8752}"));
if(survey != NULL)
{
if(type >= 2 && (!(type & 16)))//这里的2就是JIOService发布的EOperation.h中的UPDATE的枚举值;这里的16就是JIOService发布的EOperation.h中的MANAGE_PERMISSION的枚举值
{
return (survey->HasPermissionFlag(2));//如果工区有更新权限则孩子有crud全部权限,否则对该type没有权限
}
return survey->HasPermissionFlag(type); //获取工区对应的权限
}
return true;
}
QVariant PaiObject::GetSortData(const SortKeyFlag key) const
{
if(key == Sort_By_Name)
{
return GetName();
}
else if(key == Sort_By_CreateTime)
{
return GetCreateTime();
}
else
{
return QVariant(); // 默认不调整顺序
}
}
long long PaiObject::GetCreateTime() const
{
return -1;
}
int PaiObject::SortDataCompare(PaiObject *pSrc, PaiObject *pDest, const SortKeyFlag key)
{
if(pSrc && pDest)
{
QVariant src = pSrc->GetSortData(key);
QVariant dest = pDest->GetSortData(key);
//特殊处理一下joblog,无论任何排序规则
if(src.userType() == qMetaTypeId< pai::AlwaysBottom > ())//src is a JobLog
{
return 1;
}
if(dest.userType() == qMetaTypeId< pai::AlwaysBottom > ())//dest is a JobLog
{
return -1;
}
if(key == Sort_Key_Null)
{
return 0;
}
if((src.type() == QVariant::String) && (dest.type() == QVariant::String)) // 字符串比较
{
return SpecialCompare(src.toString(), dest.toString());
}
else if((src.type() == QVariant::Int) && (dest.type() == QVariant::Int)) // 整形比较
{
return src.toInt() - dest.toInt();
}
else if((src.type() == QVariant::LongLong) && (dest.type() == QVariant::LongLong)) // 整形比较
{
// 防止长整型转化为整型产生溢出
if(src.toLongLong() - dest.toLongLong() == 0)
{
return 0;
}
else if(src.toLongLong() - dest.toLongLong() < 0)
{
return -1;
}
else
{
return 1;
}
}
else if((src.type() == QVariant::Double) && (dest.type() == QVariant::Double)) // 浮点数比较
{
if(qAbs(src.toDouble() - dest.toDouble()) < 10e-20)
{
return 0;
}
else if((src.toDouble() - dest.toDouble()) > 0)
{
return 1;
}
else
{
return -1;
}
}
else
{
return 0; // 不支持部分目前认为相等
}
}
return 0; // 认为相等
}
void PaiObject::Rename(const QString & /*newName*/, OverrideFlag /*override*/)
{
// 此处抛出异常,既可以保证需要重命名的派生类有提示,也可防止不能重命名的派生类被重命名
// throw pai::error::io_error("Please define [Rename] function in derived class!");
}
long long PaiObject::GetTimeStamp() const
{
return m_TimeStamp;
}
void PaiObject::SetTimeStamp(const long long timeStamp)
{
// 只有有更新才可以修改
if(timeStamp > GetTimeStamp())
{
m_TimeStamp = timeStamp;
// 通知有更新
// m_EventAgent.ObjectPropertyChanged(this, QString("Update"), m_TimeStamp);
}
}
int PaiObject::SpecialCompare(const QString & tag1, const QString & tag2)
{
int ret = QString::compare(tag1, tag2, Qt::CaseInsensitive);
int i = 0;
const int sep = 'a' - 'A';//英文字母大小写的差值
while(tag1.length() > i && tag2.length() > i)
{
char a = tag1.at(i).toLatin1();
char b = tag2.at(i).toLatin1();
if(tag1.at(i) == tag2.at(i))
{
//如果相等则继续比较
}
else if(a >= 'A' && a <= 'z' && b >= 'A' && b <= 'z')
{
//如果两个都是英文字母,且是相同字母(只是大小写的却别),则返回差异
if(a - b == sep || b - a == sep)
{
ret = a - b;
}
break;
}
else
{
//如果不相等,则直接退出循环
break;
}
i++;
}
return ret;
}
void PaiObject::SyncRefreshMsg(const PaiObject & latestObject)
{
if(latestObject.m_dbid > 0 && m_dbid != latestObject.m_dbid)
{
QString errMsg = QObject::tr("SyncRefreshMsg from \"%1\" to \"%2\" failed! \n"
"the DBID must be the same one(%3, %4)!").arg(latestObject.GetName()).arg(GetName())
.arg(latestObject.GetDBID()).arg(GetDBID());
// throw pai::error::invalid_argument(errMsg.toStdString());
}
if(latestObject.GetTimeStamp() > GetTimeStamp())
{
//在与数据库不同步的情况下,更新当前对象同步数据库
Clone(latestObject);
// m_EventAgent.RefreshedObject(this);
}
}
PaiObject* PaiObject::GetForebear(const QUuid & typeID) const
{
PaiObject *pParent = GetParent();
while(pParent)
{
if(pParent->GetTypeID() == typeID)
{
return pParent;
}
pParent = pParent->GetParent();
}
return NULL;
}
bool PaiObject::TryDelete(QString & message)
{
// if(GetObjectModelService()->GetObjectLockManager()->IsObjectLocked(GetDBID(), true) == true)
// {
// QMap< long long, QString > map = GetObjectModelService()->GetObjectLockManager()->GetLockedObjects(this);
// if(message.isEmpty() == false)
// {
// message.append("\n");
// }
// foreach(const QString & info, map)
// {
// message.append(info);
// }
// return false;
// }
// else
{
return true;
}
}
int PaiObject::GetMemorySize()
{
return 0;
}