/** * @file PaiObject.cpp * @date 2013-03-15 */ #include #include #include #include #include #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::GetBrothers(long long /*ownerID*/, const QUuid & /*ownerType*/) { return QList(); } 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; }