From a305f050208772322fbf42b698f4fab681cb9ce8 Mon Sep 17 00:00:00 2001 From: Rodionov Andrey Date: Sat, 17 Oct 2015 01:04:34 +0300 Subject: [PATCH] first commit --- .gitignore | 84 ++++++ README.md | 1 + application.cpp | 5 + application.h | 30 +++ attreditloodsmanmodel.cpp | 252 +++++++++++++++++ attreditloodsmanmodel.h | 85 ++++++ attrlinkkey.cpp | 13 + attrlinkkey.h | 18 ++ attrloodsmanmodel.cpp | 302 +++++++++++++++++++++ attrloodsmanmodel.h | 100 +++++++ cds_format.html | 261 ++++++++++++++++++ converttype.cpp | 112 ++++++++ converttype.h | 20 ++ dialogconnect.cpp | 95 +++++++ dialogconnect.h | 24 ++ dialogconnect.ui | 175 ++++++++++++ linkloodsmanmodel.cpp | 263 ++++++++++++++++++ linkloodsmanmodel.h | 93 +++++++ loodsmansystem.cpp | 15 ++ loodsmansystem.h | 29 ++ main.cpp | 40 +++ mainwindow.cpp | 185 +++++++++++++ mainwindow.h | 39 +++ mainwindow.ui | 139 ++++++++++ midasdata.cpp | 401 +++++++++++++++++++++++++++ midasdata.h | 188 +++++++++++++ propeditordelegate.cpp | 266 ++++++++++++++++++ propeditordelegate.h | 39 +++ statloodsmanmodel.cpp | 244 +++++++++++++++++ statloodsmanmodel.h | 87 ++++++ treeitem.cpp | 34 +++ treeitem.h | 40 +++ treeloodsmanmodel.cpp | 553 ++++++++++++++++++++++++++++++++++++++ treeloodsmanmodel.h | 131 +++++++++ treenode.h | 11 + treepropview.cpp | 129 +++++++++ treepropview.h | 29 ++ typeloodsmanmodel.cpp | 336 +++++++++++++++++++++++ typeloodsmanmodel.h | 106 ++++++++ unitsloodsmanmodel.cpp | 247 +++++++++++++++++ unitsloodsmanmodel.h | 92 +++++++ verticallite.pro | 59 ++++ 42 files changed, 5372 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 application.cpp create mode 100644 application.h create mode 100644 attreditloodsmanmodel.cpp create mode 100644 attreditloodsmanmodel.h create mode 100644 attrlinkkey.cpp create mode 100644 attrlinkkey.h create mode 100644 attrloodsmanmodel.cpp create mode 100644 attrloodsmanmodel.h create mode 100644 cds_format.html create mode 100644 converttype.cpp create mode 100644 converttype.h create mode 100644 dialogconnect.cpp create mode 100644 dialogconnect.h create mode 100644 dialogconnect.ui create mode 100644 linkloodsmanmodel.cpp create mode 100644 linkloodsmanmodel.h create mode 100644 loodsmansystem.cpp create mode 100644 loodsmansystem.h create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h create mode 100644 mainwindow.ui create mode 100644 midasdata.cpp create mode 100644 midasdata.h create mode 100644 propeditordelegate.cpp create mode 100644 propeditordelegate.h create mode 100644 statloodsmanmodel.cpp create mode 100644 statloodsmanmodel.h create mode 100644 treeitem.cpp create mode 100644 treeitem.h create mode 100644 treeloodsmanmodel.cpp create mode 100644 treeloodsmanmodel.h create mode 100644 treenode.h create mode 100644 treepropview.cpp create mode 100644 treepropview.h create mode 100644 typeloodsmanmodel.cpp create mode 100644 typeloodsmanmodel.h create mode 100644 unitsloodsmanmodel.cpp create mode 100644 unitsloodsmanmodel.h create mode 100644 verticallite.pro diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6859354 --- /dev/null +++ b/.gitignore @@ -0,0 +1,84 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +.directory +*.orig +*.dll +*.txt + +# Version project +version.h + +# qtcreator generated files +*.pro.user* +*.qmlproject.user* +*.pluginspec + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb + +# MinGW generated files +*.Debug +*.Release + +# translation related: +share/qtcreator/translations/*_tr.h +share/qtcreator/translations/qtcreator_untranslated.ts + +# Directories to ignore +# --------------------- + +debug +lib/* +lib64/* +release +.rcc +.pch +doc/doxygen/html +qch/* + +# Binaries +# -------- +bin +build diff --git a/README.md b/README.md new file mode 100644 index 0000000..95bf5c3 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Пример доступа к Лоцман PLM из Qt diff --git a/application.cpp b/application.cpp new file mode 100644 index 0000000..5c38da3 --- /dev/null +++ b/application.cpp @@ -0,0 +1,5 @@ +#include "application.h" + +Application::Application(int &c, char **v): QApplication(c, v) +{ +} diff --git a/application.h b/application.h new file mode 100644 index 0000000..30ba9c3 --- /dev/null +++ b/application.h @@ -0,0 +1,30 @@ +#ifndef APPLICATION_H +#define APPLICATION_H + +#include +#include + +class Application : public QApplication +{ + Q_OBJECT +public: + Application(int &c, char **v); + bool notify(QObject *rec, QEvent *ev) { + // cDebug() << "Called Application::notify()" << endl; + try { + return QApplication::notify(rec, ev); + } + catch (char const *str) { + qDebug() << "EXCEPTION: " << str << endl; + return false; + } + catch (...) { + qDebug() << "Unknown exception!" << endl; + //abort(); + } + } +}; + +#endif // APPLICATION_H + + diff --git a/attreditloodsmanmodel.cpp b/attreditloodsmanmodel.cpp new file mode 100644 index 0000000..1fb1456 --- /dev/null +++ b/attreditloodsmanmodel.cpp @@ -0,0 +1,252 @@ +#include "attreditloodsmanmodel.h" +#include "converttype.h" +#include +#include + +#define OBJATTR (quintptr)0 +#define LINKATTR (quintptr)1 +#define HEADROW (quintptr)-1 + +AttrEditLoodsmanModel::AttrEditLoodsmanModel(QObject *parent) : + QAbstractItemModel(parent) +{ + m_fieldNames << tr("_NAME") << tr("_ID") << tr("_ATTRTYPE") << + tr("_DEFAULT") << tr("_LIST") << tr("_ACCESSLEVEL") << + tr("_ISATTRLINK") << tr("_VALUE") << tr("_ID_UNIT") << + tr("_UNIT"); +} + +AttrEditLoodsmanModel::~AttrEditLoodsmanModel() +{ + +} + +int AttrEditLoodsmanModel::columnCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return m_fieldNames.count(); +} + +QVariant AttrEditLoodsmanModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + if(role == Qt::DisplayRole || role == Qt::EditRole){ + if (index.parent().isValid()){ + QVariantList list; + if (index.parent().row()==OBJATTR) + list = m_listAttrObj.at(index.row()); + else + list = m_listAttrLink.at(index.row()); + return list.at(index.column()); + } else + if (index.column()==0){ + if (index.row()==OBJATTR) + return tr("Атрибуты объекта"); + else + return tr("Атрибуты связи"); + } + } + return QVariant(); +} + +bool AttrEditLoodsmanModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(index); + if (role != Qt::EditRole) + return false; + + if (index.parent().isValid()){ + QVariantList list; + if (index.parent().row()==OBJATTR){ + list = m_listAttrObj.at(index.row()); + list.replace(index.column(),value); + m_listAttrObj.replace(index.row(),list); + } else { + list = m_listAttrLink.at(index.row()); + list.replace(index.column(),value); + m_listAttrLink.replace(index.row(),list); + } + return 1; + } + + return 0; +} + +Qt::ItemFlags AttrEditLoodsmanModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + Qt::ItemFlags fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + /*if ( d->isEditable( index.internalId(), index.column() ) )*/ + if (index.column()!=0) + fl |= Qt::ItemIsEditable; + return fl; +} + +QVariant AttrEditLoodsmanModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + if (m_header[section].isNull()) + return m_fieldNames.at(section); + else + return m_header[section]; + + return QVariant(); +} + +bool AttrEditLoodsmanModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(section); + + if (role != Qt::EditRole || orientation != Qt::Horizontal) + return false; + + m_header[section] = value.toString(); + emit headerDataChanged(orientation, section, section); + + return true; +} +QModelIndex AttrEditLoodsmanModel::index(int row, int column, const QModelIndex &parent) const +{ + if(!hasIndex(row, column, parent)) + return QModelIndex(); + + if (parent.isValid() ){ + if (parent.row()==OBJATTR && !parent.parent().isValid()) + return createIndex(row, column, OBJATTR); + + if (parent.row()==LINKATTR && !parent.parent().isValid()) + return createIndex(row, column,LINKATTR); + + return QModelIndex(); + } + return createIndex(row, column, HEADROW); +} + +QModelIndex AttrEditLoodsmanModel::parent(const QModelIndex &index) const +{ + if(!index.isValid()) + return QModelIndex(); + + if (index.internalId()==OBJATTR) + return createIndex(OBJATTR, 0,HEADROW); + + if (index.internalId()==LINKATTR) + return createIndex(LINKATTR, 0,HEADROW); + + return QModelIndex(); +} + +int AttrEditLoodsmanModel::rowCount(const QModelIndex &parent) const +{ + if (parent.column() > 0) + return 0; + + if (parent.isValid()){ + if (!parent.parent().isValid()){ + if (parent.row()==OBJATTR) + return m_listAttrObj.count(); + else + return m_listAttrLink.count(); + } + } return 2; + + return 0; +} + +bool AttrEditLoodsmanModel::hasChildren(const QModelIndex & parent) const +{ + if (parent.isValid()){ + if (!parent.parent().isValid()) + return true; + } else + return true; + + return false; +} + +QStringList AttrEditLoodsmanModel::fields() +{ + return m_fieldNames; +} + +void AttrEditLoodsmanModel::setFields(const QStringList &dataFields) +{ + m_fieldNames = dataFields; +} + +int AttrEditLoodsmanModel::fieldIndex(const QString &fieldName) const +{ + for (int i = 0;ifetchMoreAttr(index); + if (m_listAttrObj.count()>0){ + beginRemoveRows(this->index(0,0),0,m_listAttrObj.count()-1); + m_listAttrObj.clear(); + endRemoveRows(); + } + + if (m_listAttrLink.count()>0){ + beginRemoveRows(this->index(1,0),0,m_listAttrLink.count()-1); + m_listAttrLink.clear(); + endRemoveRows(); + } + + foreach (QVariantList value, m_treeModel->attrMap(index)){ + QVariantList item; + for (int i=0;i<10;i++){ + if (i0){ + beginInsertRows(this->index(0,0),0,m_listAttrObj.count()-1); + endInsertRows(); + } + + if (m_listAttrLink.count()>0){ + beginInsertRows(this->index(1,0),0,m_listAttrLink.count()-1); + endInsertRows(); + } +} diff --git a/attreditloodsmanmodel.h b/attreditloodsmanmodel.h new file mode 100644 index 0000000..2122340 --- /dev/null +++ b/attreditloodsmanmodel.h @@ -0,0 +1,85 @@ +#ifndef ATTREDITLOODSMANMODEL_H +#define ATTREDITLOODSMANMODEL_H + +#include +#include "typeloodsmanmodel.h" +#include "linkloodsmanmodel.h" +#include "statloodsmanmodel.h" +#include "attrloodsmanmodel.h" +#include "treeloodsmanmodel.h" + +class AttrEditLoodsmanModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit AttrEditLoodsmanModel(QObject *parent = 0); + virtual ~AttrEditLoodsmanModel(); + //! Возращает хранимые данные + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant data(long id, int column) const; + + //! Устанавливает значение для указанной записи + bool setData(const QModelIndex &index, const QVariant &value, int role); + + //! Возвращает флаг записи + Qt::ItemFlags flags(const QModelIndex &index) const; + + //! Возращает название заголовка + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + //! Устанавливает название заголовка + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role); + + //! Возращает индекс модели для строки и колонки + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + + //! Возращает индекс родителя + QModelIndex parent(const QModelIndex &index) const ; + + //! Возращает количество строк в индексе родителя + int rowCount(const QModelIndex &parent = QModelIndex()) const; + + //! Возращает количество столбцов в индексе родителя + int columnCount(const QModelIndex &parent = QModelIndex()) const; +/* + //! Удаление строки + bool removeRows(int position, int rows, const QModelIndex &parent); + + //! Вставка строки + bool insertRows(int position, int rows, const QModelIndex &parent); +*/ + //! Проверка имеются ли дети + bool hasChildren(const QModelIndex & parent) const ; + + //! Получение списка полей с данных + QStringList fields() ; + + int fieldIndex(const QString &fieldName) const; + + void setSourceModel(TreeLoodsmanModel *sourceModel); + void setCurrentNode(const QModelIndex &index); + +private: + + QList m_listAttrLink; + QList m_listAttrObj; + + //! Установка списка полей данных + void setFields(const QStringList& dataFields); + + //! Список полей данных + QStringList m_fieldNames; + TreeNode* m_root; + + TypeLoodsmanModel* m_typeModel; + AttrLoodsmanModel* m_attrModel; + TreeLoodsmanModel *m_treeModel; + + //mutable QHash cache; + + //! Список названий заголовков + QMap m_header; + +}; + +#endif // ATTREDITLOODSMANMODEL_H diff --git a/attrlinkkey.cpp b/attrlinkkey.cpp new file mode 100644 index 0000000..b9c5556 --- /dev/null +++ b/attrlinkkey.cpp @@ -0,0 +1,13 @@ +#include "attrlinkkey.h" + +AttrLinkKey::AttrLinkKey() +{ +} + +bool AttrLinkKey::operator <(const AttrLinkKey &key2) const +{ + if (id != key2.id) return id < key2.id; + if (pid != key2.pid) return pid < key2.pid; + return lid < key2.lid; + +} diff --git a/attrlinkkey.h b/attrlinkkey.h new file mode 100644 index 0000000..4f646cd --- /dev/null +++ b/attrlinkkey.h @@ -0,0 +1,18 @@ +#ifndef ATTRLINKKEY_H +#define ATTRLINKKEY_H +#include + +class AttrLinkKey; + +class AttrLinkKey +{ +public: + AttrLinkKey(); + bool operator<(const AttrLinkKey &key2) const; +public: + long id; + long pid; + QString lid; +}; + +#endif // ATTRLINKKEY_H diff --git a/attrloodsmanmodel.cpp b/attrloodsmanmodel.cpp new file mode 100644 index 0000000..2d14382 --- /dev/null +++ b/attrloodsmanmodel.cpp @@ -0,0 +1,302 @@ +#include "attrloodsmanmodel.h" + +#include "loodsmansystem.h" +#include "converttype.h" +#include +#include +#include +#include + +AttrLoodsmanModel::AttrLoodsmanModel(QObject *parent) : + QAbstractItemModel(parent) +{ + dataSet = new MidasData(); + m_root = new TreeNode; + m_root->id = 0; + m_root->isFetch = false; + cache.insert(0,m_root); + + QStringList fields; + fields << "_NAME" << "_ID" << "_ATTRTYPE" << "_DEFAULT" << "_LIST" << "_SYSTEM" + << "_ONLYLISTITEMS" << "_SYSTEM_1" << "_ACCESSLEVEL" << "_ID_NATURE"; + setFields(fields); +} + +AttrLoodsmanModel::~AttrLoodsmanModel() +{ + delete dataSet; +} + +int AttrLoodsmanModel::columnCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return m_fieldNames.count(); +} + +TreeNode *AttrLoodsmanModel::getItem(const QModelIndex & index) const +{ + if (index.isValid()) + return static_cast(index.internalPointer()); + else + return m_root; +} + +QVariant AttrLoodsmanModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + if (role == Qt::DecorationRole && index.column()==0 && !m_fieldIcon.isEmpty()){ + QPixmap pixmap; + const TreeNode *item = getItem(index); + if (item) { + pixmap.loadFromData(item->data.at(m_fieldNames.count()).toByteArray()); + return QIcon(pixmap); + } + } + + if(role == Qt::DisplayRole){ + const TreeNode *item = getItem(index); + if (item) + return item->data.at(index.column()); + } + return QVariant(); +} + +QVariant AttrLoodsmanModel::data(long id, int column) const +{ + if(cache.contains(id)){ + TreeNode *item = cache[id]; + if (item) + return item->data.at(column); + } + return QVariant(); +} + +bool AttrLoodsmanModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(index); + if (role != Qt::EditRole) + return false; + return 0; +} + +Qt::ItemFlags AttrLoodsmanModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + Qt::ItemFlags fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + /*if ( d->isEditable( index.internalId(), index.column() ) ) + fl |= Qt::ItemIsEditable;*/ + return fl; +} + +QVariant AttrLoodsmanModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole) { + return m_fieldNames.at(section); + } + return QVariant(); +} + +bool AttrLoodsmanModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(section); + + if (role != Qt::EditRole || orientation != Qt::Horizontal) + return false; + + return false; +} + +QModelIndex AttrLoodsmanModel::index(int row, int column, const QModelIndex &parent) const +{ + if(!hasIndex(row, column, parent)) + return QModelIndex(); + + const TreeNode* parentItem = getItem(parent); + + if (!parentItem) + return QModelIndex(); + + TreeNode* childItem = cache[parentItem->children.at(row)]; + + if (childItem) + return createIndex(row, column, (void*)childItem); + else + return QModelIndex(); +} + +QModelIndex AttrLoodsmanModel::parent(const QModelIndex &index) const +{ + if(!index.isValid()) + return QModelIndex(); + + const TreeNode *childItem = getItem(index); + TreeNode *parentItem = cache[childItem->parent]; + + if (!parentItem || parentItem == m_root) + return QModelIndex(); + + TreeNode *grandparent = cache[parentItem->parent]; + if (!grandparent) + return QModelIndex(); + + for (int i = 0; i < grandparent->children.count(); i++) + if (grandparent->children.at(i) == parentItem->id) + return createIndex(i, 0, (void*) parentItem); + + return QModelIndex(); +} + +int AttrLoodsmanModel::rowCount(const QModelIndex &parent) const +{ + if(parent.column() > 0) + return 0; + + return getItem(parent)->children.count(); +} + +bool AttrLoodsmanModel::hasChildren(const QModelIndex & parent) const +{ + TreeNode* node = getItem(parent); + if (node->isFetch && node->children.count()==0) + return false; + + return true; +} + +bool AttrLoodsmanModel::canFetchMore(const QModelIndex &parent) const +{ + return !getItem(parent)->isFetch; +} + +void AttrLoodsmanModel::fetchMore(const QModelIndex &parent) +{ + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + VARIANT inErrorCode; + VARIANT stErrorMessage; + + TreeNode *item; + + if(parent.isValid()){ + item = getItem(parent); + if(!item) + return; + } + + _variant_t data = loodsman->main->GetInfoAboutCurrentBase(8,&inErrorCode, &stErrorMessage); + dataSet->setData((unsigned char *)data.parray->pvData); + + if (inErrorCode.lVal!=0) + QMessageBox::warning(NULL, tr("Ошибка соединения"), from_bstr_t(stErrorMessage.bstrVal)); + + if (dataSet->first()) + do { + int childId = dataSet->fieldValue("_ID").toInt(); + long parentId = 0/*dataSet->fieldValue("_ID_PARENT_TYPE").toInt()*/; + + TreeNode *item = /*cache[parentId]*/m_root; + if (item==NULL){ + if (parentId == 0) + item = m_root; + else { + item = new TreeNode; + item->id = parentId; + cache.insert(parentId, item); + item->isFetch = true; + } + } + + TreeNode* childItem; + if (!cache.contains(childId)){ + childItem = new TreeNode; + childItem->id = childId; + childItem->isFetch = true; + cache.insert(childId, childItem); + item->children.append(childId); + } else { + childItem = cache[childId]; + childItem->data.clear(); + } + childItem->parent = parentId; + + for ( int j=0; j < m_fieldNames.count(); j++ ) + if (m_fieldNames[j] == "_LIST") + childItem->data.append( + QString::fromLocal8Bit( + dataSet->fieldValue( + m_fieldNames[j]).toByteArray().data())); + else + childItem->data.append(dataSet->fieldValue(m_fieldNames[j])); + + if (!m_fieldIcon.isEmpty()) + childItem->data.append(dataSet->fieldValue(m_fieldIcon)); + + + } while (dataSet->next()); + dataSet->clear(); + + m_root->isFetch = true; + beginInsertRows(QModelIndex(), 0,cache[0]->children.count()); + endInsertRows(); +} + +QStringList AttrLoodsmanModel::fields() +{ + return m_fieldNames; +} + +void AttrLoodsmanModel::setFields(const QStringList &dataFields) +{ + m_fieldNames = dataFields; +} + +void AttrLoodsmanModel::setFieldIcon(QString column) +{ + m_fieldIcon = column; +} + +int AttrLoodsmanModel::fieldIndex(const QString &fieldName) const +{ + for (int i = 0;i AttrLoodsmanModel::listUnits(const QString& measure) +{ + if (m_units.contains(measure)) + return m_units.value(measure); + + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + VARIANT inErrorCode; + VARIANT stErrorMessage; + + _variant_t testData = loodsman->main->GetMUnitList(to_bstr_t(measure), + &inErrorCode, + &stErrorMessage); + + if (inErrorCode.lVal!=0) + QMessageBox::warning(NULL, tr("Ошибка соединения"), from_bstr_t(stErrorMessage.bstrVal)); + + unsigned char *p = (unsigned char *)testData.parray->pvData; + MidasData* mData = new MidasData(); + mData->setData(p); + QList attrUnit; + if (mData->first()) do { + UnitsAttr unit; + unit.id = mData->fieldValue("_ID_UNIT").toString(); + unit.name = mData->fieldValue("_NAME").toString(); + unit.baseUnits = mData->fieldValue("_BASICUNIT").toBool(); + attrUnit.append(unit); + }while (mData->next()); + + m_units[measure] = attrUnit; + + return attrUnit; +} diff --git a/attrloodsmanmodel.h b/attrloodsmanmodel.h new file mode 100644 index 0000000..b529239 --- /dev/null +++ b/attrloodsmanmodel.h @@ -0,0 +1,100 @@ +#ifndef ATTRLOODSMANMODEL_H +#define ATTRLOODSMANMODEL_H + +#include +#include +#include "treenode.h" +#include "midasdata.h" + +struct UnitsAttr { + QString id; + QString name; + bool baseUnits; +}; + +class AttrLoodsmanModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit AttrLoodsmanModel(QObject *parent = 0); + ~AttrLoodsmanModel(); + + //! Возращает хранимые данные + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant data(long id, int column) const; + + //! Устанавливает значение для указанной записи + bool setData(const QModelIndex &index, const QVariant &value, int role); + + //! Возвращает флаг записи + Qt::ItemFlags flags(const QModelIndex &index) const; + + //! Возращает название заголовка + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + //! Устанавливает название заголовка + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role); + + //! Возращает индекс модели для строки и колонки + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + + //! Возращает индекс родителя + QModelIndex parent(const QModelIndex &index) const ; + + //! Возращает количество строк в индексе родителя + int rowCount(const QModelIndex &parent = QModelIndex()) const; + + //! Возращает количество столбцов в индексе родителя + int columnCount(const QModelIndex &parent = QModelIndex()) const; +/* + //! Удаление строки + bool removeRows(int position, int rows, const QModelIndex &parent); + + //! Вставка строки + bool insertRows(int position, int rows, const QModelIndex &parent); +*/ + //! Проверка имеются ли дети + bool hasChildren(const QModelIndex & parent) const ; + + //! Получение TreeItem по индексу + TreeNode *getItem(const QModelIndex &index) const; + + //! Проверка можно ли провести ленивыю инициализацию + bool canFetchMore(const QModelIndex &parent) const; + + //! Ленивая инициализация + void fetchMore(const QModelIndex &parent); + + //! Получение списка полей с данных + QStringList fields() ; + + int fieldIndex(const QString &fieldName) const; + + QList listUnits(const QString &measure); +private: + //! Установка списка полей данных + void setFields(const QStringList& dataFields ); + void setFieldIcon(QString column); + + TreeNode* m_root; + MidasData* dataSet; + + //! Список полей данных + QStringList m_fieldNames; + + //! Поле с Иконкой + QString m_fieldIcon; + + mutable QHash cache; + + //! Единицы измерения + QHash > m_units; + +signals: + +public slots: + +}; + +#endif // ATTRLOODSMANMODEL_H diff --git a/cds_format.html b/cds_format.html new file mode 100644 index 0000000..08c6db4 --- /dev/null +++ b/cds_format.html @@ -0,0 +1,261 @@ + + + + + + + TClientDataSet (Midas/DataSnap) + +

Midas/DataSnap packet format

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OffsetSize (bytes)Content
04Signature = [$96, $19, $E0, $BD] - + MIDAS/DataSnap
44Int32, 1
84Int32, 18
122FieldCount: UInt16 -
144RecordCount: Int32 - +
184Int32, 3
222HeaderSize: UInt16 - , + + .
24XFieldList: FieldList + - .
X + 242DSPropCount: UInt16 -
X + 26YDSProps: Prop[DSPropCount] - + .
HeaderSizeVaringRecordList: RecordList + - .
+

(FieldList)

+

. + .

+

array [0..FieldCount - 1] of

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OffsetSize (bytes)Content
01Len: UInt8 -
1LenFieldName: Char[Len] -
Len + 12FieldSize: Int16, - + ,
Len + 32FieldType: Int16
Len + 52FieldAttrs: Int16 - + () .
Len + 72FieldPropCount: UInt16 - +
Len + 9PFieldProps: Prop[FieldPropCount] + - .
+

(Prop)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OffsetSize (bytes)Content
01Len: UInt8 -
1LenPropName: Char[Len] -
Len+12PropSize: Int16
Len+32PropType: Int16 (FieldType)
Len + 4PropSizeData: Byte[PropSize] -
+

(RecordList)

+

, . + .

+

array [0..RecordCount - 1] of

+ + + + + + + + + + + + + + + + + + + + + +
OffsetSize (bytes)Content
01RecordStatus: UInt8
1SStatusBits: Byte[FieldCount / 4] - + 2 + . + Null + NotChanged .
+ BLANK_NULL = 1; { 'real' NULL }
+ BLANK_NOTCHANGED = 2; { Not changed , compared to original value }
S+1XFieldData[] - + not null & changed .
+ : + FixedFieldData = Byte[FieldSize]
+
: VarFieldData = + (DataLen: UInt(of FieldSize)) Byte[DataLen] - + 1-2 .
+

FieldType

+

dsfldUNKNOWN = 0; { Unknown }
+dsfldINT = 1; { signed integer }
+dsfldUINT = 2; { Unsigned integer }
+dsfldBOOL = 3; { Boolean }
+dsfldFLOATIEEE = 4; { IEEE float }
+dsfldBCD = 5; { BCD }
+dsfldDATE = 6; { Date (32 bit) }
+dsfldTIME = 7; { Time (32 bit) }
+dsfldTIMESTAMP = 8; { Time-stamp (64 bit) }
+dsfldZSTRING = 9; { Multi-byte string }
+dsfldUNICODE = 10; { unicode string }
+dsfldBYTES = 11; { bytes }
+dsfldADT = 12; { ADT (Abstract Data Type) }
+dsfldARRAY = 13; { Array type (not attribute) }
+dsfldEMBEDDEDTBL = 14; { Embedded (nested table type) }
+dsfldREF = 15; { Reference }

+

MaskFieldType = $3F; { mask to retrieve +Field Type  }
+MaskVaryingFld = $40; { Varying attribute type. }
+MaskArrayFld = $80; { Array attribute type. } +- Len: Int32, + +Data[Len].

+

(FieldAttrs)

+

fldAttrHIDDEN = $0001; { Field is hidden }
+fldAttrREADONLY = $0002; { Field is readonly }
+fldAttrREQUIRED = $0004; { Field value required }
+fldAttrLINK = $0008; { Linking field }

+

(FieldProps)

+
    +
  • WIDTH: UInt16 - , + , Field.Size. + , .
  • +
+

(DataSetProps)

+
    +
  • CHANGE_LOG: UInt32[] - + .
  • +
  • DATASET_DELTA: UInt32 = 1, + delta- ( ).
  • +
+

(RecordStatus)

+

dsRecUnmodified = $0000; { Unmodified record }
+dsRecOrg = $0001; { Original record (was changed) }
+dsRecDeleted = $0002; { Record was deleted }
+dsRecNew = $0004; { Record was inserted }
+dsRecModified = $0008; { Record was changed }
+dsUnused = $0020; { Record not used anymore (hole) }
+dsDetUpd = $0040; { Detail modification Ins/Del/Mod. }{ Can be combined with +other status. }

+ + + + +
+ + diff --git a/converttype.cpp b/converttype.cpp new file mode 100644 index 0000000..ee577d6 --- /dev/null +++ b/converttype.cpp @@ -0,0 +1,112 @@ +#include "converttype.h" + +LPWSTR toLPWSTR(QString str){ + return (LPWSTR)(str.utf16()); +} + +_bstr_t to_bstr_t(QString str){ + // return (_bstr_t)(str.utf16()); + BSTR result= SysAllocStringLen(0, str.length()); + str.toWCharArray(result); + return result; +} + +QString from_bstr_t(_bstr_t str){ + return QString::fromUtf16(reinterpret_cast((const WCHAR*)str)); +} + +QVariant from_variant_t(const _variant_t &arg){ + QVariant var; + switch(arg.vt) { + case VT_BSTR: + var = QString::fromWCharArray(arg.bstrVal); + break; + case VT_BSTR|VT_BYREF: + var = QString::fromWCharArray(*arg.pbstrVal); + break; + case VT_BOOL: + var = QVariant((bool)arg.boolVal); + break; + case VT_BOOL|VT_BYREF: + var = QVariant((bool)*arg.pboolVal); + break; + case VT_I1: + var = arg.cVal; + /*if (typeName == "char") + type = QVariant::Int;*/ + break; + case VT_I1|VT_BYREF: + var = *arg.pcVal; + /*if (typeName == "char") + type = QVariant::Int;*/ + break; + case VT_I2: + var = arg.iVal; + /*if (typeName == "short") + type = QVariant::Int;*/ + break; + case VT_I2|VT_BYREF: + var = *arg.piVal; + /*if (typeName == "short") + type = QVariant::Int;*/ + break; + case VT_I4: + var = (int)arg.lVal; + break; + case VT_I4|VT_BYREF: + var = (int)*arg.plVal; + break; + case VT_INT: + var = arg.intVal; + break; + case VT_INT|VT_BYREF: + var = *arg.pintVal; + break; + case VT_UI1: + var = arg.bVal; + break; + case VT_UI1|VT_BYREF: + var = *arg.pbVal; + break; + case VT_UI2: + var = arg.uiVal; + break; + case VT_UI2|VT_BYREF: + var = *arg.puiVal; + break; + case VT_UI4: + var = (int)arg.ulVal; + break; + case VT_UI4|VT_BYREF: + var = (int)*arg.pulVal; + break; + case VT_UINT: + var = arg.uintVal; + break; + case VT_UINT|VT_BYREF: + var = *arg.puintVal; + break; + case VT_CY: + var = arg.cyVal.int64; + break; + case VT_CY|VT_BYREF: + var = arg.pcyVal->int64; + break; + case VT_R4: + var = arg.fltVal; + break; + case VT_R4|VT_BYREF: + var = *arg.pfltVal; + break; + case VT_R8: + var = arg.dblVal; + break; + case VT_R8|VT_BYREF: + var = *arg.pdblVal; + break; + } + return var; +} + + + diff --git a/converttype.h b/converttype.h new file mode 100644 index 0000000..43594bd --- /dev/null +++ b/converttype.h @@ -0,0 +1,20 @@ +#ifndef CONVERTTYPE_H +#define CONVERTTYPE_H + +#include +#include +#include + +//! Конвертирование из QString в LPWSTR +LPWSTR toLPWSTR(QString str); + +//! Конвертирование из QString в _bstr_t +_bstr_t to_bstr_t(QString str); + +//! Конвертирование из _bstr_t в QString +QString from_bstr_t(_bstr_t str); + +//! Конвертирование из _variant_t в QVariant +QVariant from_variant_t(const _variant_t &arg); + +#endif // CONVERTTYPE_H diff --git a/dialogconnect.cpp b/dialogconnect.cpp new file mode 100644 index 0000000..f960383 --- /dev/null +++ b/dialogconnect.cpp @@ -0,0 +1,95 @@ +/* + * mainwindow.cpp + * + * Copyright 2009 Rodionov Andrey + * + * + */ + +#include "converttype.h" +#include "loodsmansystem.h" +#include "dialogconnect.h" +#include + +DialogConnect::DialogConnect(QWidget* pwgt) : QDialog(pwgt) +{ + setupUi(this); + + textLabelHostname->hide(); + editHostname->hide(); + textLabelBD->hide(); + editDatabase->hide(); + line->hide(); + + QSettings settings("NONAME", "VerticalLite"); + settings.beginGroup("DialogConnect"); + editDatabase->setText(settings.value("database").toString()); + editHostname->setText(settings.value("hostname").toString()); + editUsername->setText(settings.value("username").toString()); + settings.endGroup(); + + this->adjustSize(); + connect(pushButtonProp, SIGNAL(clicked()), this, SLOT(onClickButtonProp())); + connect(pushButtonOk, SIGNAL(clicked()), this, SLOT(onClickButtonOk())); +} + +void DialogConnect::onClickButtonProp() +{ + if (textLabelHostname->isHidden()) { + pushButtonProp->setText(tr("Кратко")); + textLabelHostname->show(); + editHostname->show(); + textLabelBD->show(); + editDatabase->show(); + line->show(); + } else { + pushButtonProp->setText(tr("Подробно")); + textLabelHostname->hide(); + editHostname->hide(); + textLabelBD->hide(); + editDatabase->hide(); + line->hide(); + + } + this->adjustSize(); +} + +void DialogConnect::onClickButtonOk() +{ + this->setDisabled(true); + COSERVERINFO ServerInfo = {0}; + ServerInfo.pwszName = toLPWSTR(editHostname->text()); + + MULTI_QI MultiQi = {0}; + MultiQi.pIID = &__uuidof(LoodsmanServerApplication::IMainSystem); + HRESULT Hr = ::CoCreateInstanceEx(__uuidof(LoodsmanServerApplication::MainSystem), NULL, + CLSCTX_REMOTE_SERVER, &ServerInfo, 1, &MultiQi); + if (Hr == S_OK) + { + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + loodsman->main.Attach((LoodsmanServerApplication::IMainSystem*)MultiQi.pItf); + + VARIANT inErrorCode; + VARIANT stErrorMessage; + loodsman->main->ConnectToDBEx(to_bstr_t(editDatabase->text()), + to_bstr_t(editUsername->text()), + to_bstr_t(editPassword->text()), + &inErrorCode,&stErrorMessage); + + if (inErrorCode.lVal!=0){ + QMessageBox::warning(this, tr("Ошибка соединения"), from_bstr_t(stErrorMessage.bstrVal)); + } else { + QSettings settings("NONAME", "VerticalLite"); + settings.beginGroup("DialogConnect"); + settings.setValue("database", editDatabase->text()); + settings.setValue("hostname", editHostname->text()); + settings.setValue("username", editUsername->text()); + settings.endGroup(); + this->accept(); + } + } else { + QMessageBox::warning(this, tr("Ошибка соединения"), QString("%1: %2"). + arg(Hr,0, 16).arg(tr("Ошибка соединения с сервером приложений"))); + } + this->setEnabled(true); +} diff --git a/dialogconnect.h b/dialogconnect.h new file mode 100644 index 0000000..3581c87 --- /dev/null +++ b/dialogconnect.h @@ -0,0 +1,24 @@ +/* + * mainwindow.h + * + * Copyright 2009 Rodionov Andrey + * + * + */ + +#ifndef DIALOGCONNECT_H +#define DIALOGCONNECT_H +#include "ui_dialogconnect.h" +#include + +class DialogConnect: public QDialog, public Ui::DialogConnect +{ + Q_OBJECT +public: + DialogConnect(QWidget* pwgt = 0); +public slots: + void onClickButtonProp(); + void onClickButtonOk(); +}; + +#endif diff --git a/dialogconnect.ui b/dialogconnect.ui new file mode 100644 index 0000000..084bd62 --- /dev/null +++ b/dialogconnect.ui @@ -0,0 +1,175 @@ + + + DialogConnect + + + + 0 + 0 + 318 + 207 + + + + Соединение... + + + + + + Пользователь + + + editUsername + + + + + + + Сервер + + + editHostname + + + + + + + + + + + + + + База данных + + + editDatabase + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + + QLineEdit::Password + + + + + + + Введите имя пользователя и пароль +для инициализации рабочего места +системы + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Пароль + + + editPassword + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Ok + + + + + + + Отмена + + + + + + + Подробно + + + + + + + + + editUsername + editPassword + editHostname + editDatabase + pushButtonOk + pushButtonCancel + pushButtonProp + + + + + pushButtonCancel + clicked() + DialogConnect + reject() + + + 251 + 130 + + + 157 + 124 + + + + + diff --git a/linkloodsmanmodel.cpp b/linkloodsmanmodel.cpp new file mode 100644 index 0000000..fb680b4 --- /dev/null +++ b/linkloodsmanmodel.cpp @@ -0,0 +1,263 @@ +#include "linkloodsmanmodel.h" +#include "loodsmansystem.h" +#include "converttype.h" +#include +#include + +LinkLoodsmanModel::LinkLoodsmanModel(QObject *parent) : + QAbstractItemModel(parent) +{ + dataSet = new MidasData(); + m_root = new TreeNode; + m_root->id = 0; + m_root->isFetch = false; + cache.insert(0,m_root); + + QStringList fields; + fields << "_ID" << "_NAME" << "_INVERSENAME" << "_TYPE" << "_ORDER"; + setFields(fields); + setFieldIcon("_ICON"); + +} + +LinkLoodsmanModel::~LinkLoodsmanModel() +{ + delete dataSet; +} + +int LinkLoodsmanModel::columnCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return m_fieldNames.count(); +} + +TreeNode *LinkLoodsmanModel::getItem(const QModelIndex & index) const +{ + if (index.isValid()) + return static_cast(index.internalPointer()); + else + return m_root; +} + +QVariant LinkLoodsmanModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + if (role == Qt::DecorationRole && index.column()==0 && !m_fieldIcon.isEmpty()){ + QPixmap pixmap; + const TreeNode *item = getItem(index); + if (item) { + pixmap.loadFromData(item->data.at(m_fieldNames.count()).toByteArray()); + return QIcon(pixmap); + } + } + + if(role == Qt::DisplayRole){ + const TreeNode *item = getItem(index); + if (item) + return item->data.at(index.column()); + } + return QVariant(); +} + +QVariant LinkLoodsmanModel::data(long id, int column) const +{ + + if(cache.contains(id)){ + TreeNode *item = cache[id]; + if (item) + return item->data.at(column); + } + return QVariant(); +} + +bool LinkLoodsmanModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(index); + if (role != Qt::EditRole) + return false; + return 0; +} + +Qt::ItemFlags LinkLoodsmanModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + Qt::ItemFlags fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + /*if ( d->isEditable( index.internalId(), index.column() ) ) + fl |= Qt::ItemIsEditable;*/ + return fl; +} + +QVariant LinkLoodsmanModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole) { + return m_fieldNames.at(section); + } + return QVariant(); +} + +bool LinkLoodsmanModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(section); + + if (role != Qt::EditRole || orientation != Qt::Horizontal) + return false; + + return false; +} + +QModelIndex LinkLoodsmanModel::index(int row, int column, const QModelIndex &parent) const +{ + if(!hasIndex(row, column, parent)) + return QModelIndex(); + + const TreeNode* parentItem = getItem(parent); + + if (!parentItem) + return QModelIndex(); + + TreeNode* childItem = cache[parentItem->children.at(row)]; + + if (childItem) + return createIndex(row, column, (void*)childItem); + else + return QModelIndex(); +} + +QModelIndex LinkLoodsmanModel::parent(const QModelIndex &index) const +{ + if(!index.isValid()) + return QModelIndex(); + + const TreeNode *childItem = getItem(index); + TreeNode *parentItem = cache[childItem->parent]; + + if (!parentItem || parentItem == m_root) + return QModelIndex(); + + TreeNode *grandparent = cache[parentItem->parent]; + if (!grandparent) + return QModelIndex(); + + for (int i = 0; i < grandparent->children.count(); i++) + if (grandparent->children.at(i) == parentItem->id) + return createIndex(i, 0, (void*) parentItem); + + return QModelIndex(); +} + +int LinkLoodsmanModel::rowCount(const QModelIndex &parent) const +{ + if(parent.column() > 0) + return 0; + + return getItem(parent)->children.count(); +} + +bool LinkLoodsmanModel::hasChildren(const QModelIndex & parent) const +{ + TreeNode* node = getItem(parent); + if (node->isFetch && node->children.count()==0) + return false; + + return true; +} + +bool LinkLoodsmanModel::canFetchMore(const QModelIndex &parent) const +{ + return !getItem(parent)->isFetch; +} + +void LinkLoodsmanModel::fetchMore(const QModelIndex &parent) +{ + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + VARIANT inErrorCode; + VARIANT stErrorMessage; + + TreeNode *item; + + if(parent.isValid()){ + item = getItem(parent); + if(!item) + return; + } + + _variant_t data = loodsman->main->GetInfoAboutCurrentBase(9,&inErrorCode, &stErrorMessage); + dataSet->setData((unsigned char *)data.parray->pvData); + + if (inErrorCode.lVal!=0) + QMessageBox::warning(NULL, tr("Ошибка соединения"), from_bstr_t(stErrorMessage.bstrVal)); + + + if (dataSet->first()){ + do { + int childId = dataSet->fieldValue("_ID").toInt(); + long parentId = 0/*dataSet->fieldValue("_ID_PARENT_TYPE").toInt()*/; + + TreeNode *item = /*cache[parentId]*/m_root; + if (item==NULL){ + if (parentId == 0) + item = m_root; + else { + item = new TreeNode; + item->id = parentId; + cache.insert(parentId, item); + item->isFetch = true; + } + } + + TreeNode* childItem; + if (!cache.contains(childId)){ + childItem = new TreeNode; + childItem->id = childId; + childItem->isFetch = true; + cache.insert(childId, childItem); + item->children.append(childId); + } else { + childItem = cache[childId]; + childItem->data.clear(); + } + + childItem->parent = parentId; + + for ( int j=0; j < m_fieldNames.count(); j++ ) + childItem->data.append(dataSet->fieldValue(m_fieldNames[j])); + if (!m_fieldIcon.isEmpty()) + childItem->data.append(dataSet->fieldValue(m_fieldIcon)); + + } while (dataSet->next()); + dataSet->clear(); + + m_root->isFetch = true; + beginInsertRows(QModelIndex(), 0,cache[0]->children.count()); + endInsertRows(); + } +} + +QStringList LinkLoodsmanModel::fields() +{ + return m_fieldNames; +} + +void LinkLoodsmanModel::setFields(const QStringList &dataFields) +{ + m_fieldNames = dataFields; +} + +void LinkLoodsmanModel::setFieldIcon(QString column) +{ + m_fieldIcon = column; +} + +int LinkLoodsmanModel::fieldIndex(const QString &fieldName) const +{ + for (int i = 0;i +#include +#include +#include + +#include "loodsmansystem.h" +#include "midasdata.h" +#include "treenode.h" + +class LinkLoodsmanModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit LinkLoodsmanModel(QObject *parent = 0); + ~LinkLoodsmanModel(); + //! Возращает хранимые данные + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant data(long id, int column) const; + + //! Устанавливает значение для указанной записи + bool setData(const QModelIndex &index, const QVariant &value, int role); + + //! Возвращает флаг записи + Qt::ItemFlags flags(const QModelIndex &index) const; + + //! Возращает название заголовка + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + //! Устанавливает название заголовка + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role); + + //! Возращает индекс модели для строки и колонки + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + + //! Возращает индекс родителя + QModelIndex parent(const QModelIndex &index) const ; + + //! Возращает количество строк в индексе родителя + int rowCount(const QModelIndex &parent = QModelIndex()) const; + + //! Возращает количество столбцов в индексе родителя + int columnCount(const QModelIndex &parent = QModelIndex()) const; +/* + //! Удаление строки + bool removeRows(int position, int rows, const QModelIndex &parent); + + //! Вставка строки + bool insertRows(int position, int rows, const QModelIndex &parent); +*/ + //! Проверка имеются ли дети + bool hasChildren(const QModelIndex & parent) const ; + + //! Получение TreeItem по индексу + TreeNode *getItem(const QModelIndex &index) const; + + //! Проверка можно ли провести ленивыю инициализацию + bool canFetchMore(const QModelIndex &parent) const; + + //! Ленивая инициализация + void fetchMore(const QModelIndex &parent); + + //! Получение списка полей с данных + QStringList fields() ; + + int fieldIndex(const QString &fieldName) const; +private: + + //! Установка списка полей данных + void setFields(const QStringList& dataFields ); + + void setFieldIcon(QString column); + + TreeNode* m_root; + MidasData* dataSet; + + //! Список полей данных + QStringList m_fieldNames; + + //! Поле с Иконкой + QString m_fieldIcon; + + mutable QHash cache; + +signals: + +public slots: + +}; + +#endif // LINKLOODSMANMODEL_H diff --git a/loodsmansystem.cpp b/loodsmansystem.cpp new file mode 100644 index 0000000..f02e1a6 --- /dev/null +++ b/loodsmansystem.cpp @@ -0,0 +1,15 @@ +#include "loodsmansystem.h" + +LoodsmanSystem::LoodsmanSystem(QObject *parent) : + QObject(parent) +{ + m_instance = this; +} + +LoodsmanSystem *LoodsmanSystem::m_instance = 0; + +LoodsmanSystem *LoodsmanSystem::instance(){ + return m_instance; +} + + diff --git a/loodsmansystem.h b/loodsmansystem.h new file mode 100644 index 0000000..c701a42 --- /dev/null +++ b/loodsmansystem.h @@ -0,0 +1,29 @@ +#ifndef LOODSMANSYSTEM_H +#define LOODSMANSYSTEM_H + +// Loodsman Library: LoodsmanServerApplication.dll +#import "libid:36281981-5E66-4277-94EE-5F490981CE89" +#include "debug/LoodsmanServerApplication.tlh" +//#include "release/LoodsmanServerApplication.tlh" +using namespace LoodsmanServerApplication; + +//#import "libid:7CC86059-0262-44D5-9AA3-033DB38F11EF" +//#include "debug/Loodsman.tlh" +//#include "release/Loodsman.tlh" +//using namespace Loodsman; + +#include + +class LoodsmanSystem : public QObject +{ + Q_OBJECT +public: + LoodsmanSystem(QObject *parent = 0); + static LoodsmanSystem *instance(); + + IMainSystemPtr main; +private: + static LoodsmanSystem *m_instance; +}; + +#endif // LOODSMANSYSTEM_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..43d2fa4 --- /dev/null +++ b/main.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include +#include "mainwindow.h" +#include "loodsmansystem.h" +#include "application.h" + +int main(int argc, char *argv[]) +{ + Application *app = new Application(argc,argv); +#if QT_VERSION < 0x050000 + QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); + QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); +#endif + // Подключение перевода для Qt + QString translatorFileName = QLatin1String("qt_"); + translatorFileName += QLocale::system().name(); + QTranslator *translator = new QTranslator(app); + if (translator->load(translatorFileName, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + app->installTranslator(translator); + + // Подключение переводов приложения + // Переводы находятся в <Каталог приложения>\translations\<Системная локализация> + QDir translationDir = QDir(qApp->applicationDirPath()); + if (translationDir.cd("translations\\"+QLocale::system().name())) + foreach(QString fileName, translationDir.entryList(QDir::Files)) + if (translator->load(fileName,translationDir.absolutePath())) + app->installTranslator(translator); + + + LoodsmanSystem loodsmanSystem; + MainWindow *window = new MainWindow(); + if (window->onActionConnect()==false) + return 0; + window->show(); + + return app->exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..e6ea23b --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,185 @@ +#include "mainwindow.h" +#include "dialogconnect.h" + +#include "ui_mainwindow.h" +#include +#include +#include +#include +#include +#include +#include "converttype.h" +#include "loodsmansystem.h" +#include "treeloodsmanmodel.h" +#include "propeditordelegate.h" +#include "midasdata.h" +#include "attrlinkkey.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent) +{ + setupUi(this); + ::CoInitialize(NULL); + ::CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE, + RPC_C_IMP_LEVEL_DELEGATE, NULL, 0, NULL); + + ldsmnTypeModel = new TypeLoodsmanModel(); + ldsmnLinkModel = new LinkLoodsmanModel(); + ldsmnAttrModel = new AttrLoodsmanModel(); + ldsmnEditAttrModel = new AttrEditLoodsmanModel(); + + connect(pshBtnTestProject,SIGNAL(clicked()),this, SLOT(listProject())); + connect(pshBtnModelTest,SIGNAL(clicked()),this, SLOT(testModel())); + connect(pshBtnTypeTest,SIGNAL(clicked()),this, SLOT(testType())); + connect(pshBtnLinkTest,SIGNAL(clicked()),this, SLOT(testLink())); + connect(pshBtnStatTest,SIGNAL(clicked()),this, SLOT(testStat())); + connect(pshBtnAttrTest,SIGNAL(clicked()),this, SLOT(testAttr())); +} + +MainWindow::~MainWindow() +{ + delete ldsmnTypeModel; + delete ldsmnLinkModel; + delete ldsmnAttrModel; + delete ldsmnEditAttrModel; + ::CoUninitialize(); +} + +bool MainWindow::onActionConnect() +{ + DialogConnect* windowConnect = new DialogConnect(this); + if (windowConnect->exec() == QDialog::Accepted) { + delete windowConnect; + return true; + } + delete windowConnect; + return false; +} + +void MainWindow::listProject() +{ + VARIANT inErrorCode; + VARIANT stErrorMessage; + + + + + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + +/* QTime timer; + timer.start(); + IDataSetPtr dataSet; +qDebug() << "Time: " << timer.elapsed() << "ms"; + dataSet.CreateInstance("Loodsman.DataSet"); + + dataSet->DATA = loodsman->main->GetProjectList2(false,&inErrorCode, &stErrorMessage); + dataSet->First(); + + long idVersion; + + for (int i=0;iFieldCount;i++){ + _bstr_t fieldName = dataSet->FieldName[i]; + _variant_t fieldValue = dataSet->FieldValue[fieldName]; + if (fieldValue.vt == 8) + qDebug() << fieldName << ": " << from_bstr_t(fieldValue.bstrVal); + else if (fieldValue.vt == 3){ + qDebug() << fieldName << ": " << fieldValue.intVal; + if (i==0) + idVersion = fieldValue.intVal; + }else + qDebug() << fieldName; + } + qDebug() << "Count" << dataSet->FieldCount; + +*/ + //_variant_t testData = loodsman->main->GetInfoAboutAttribute(to_bstr_t(QString("Масса")),2,&inErrorCode, &stErrorMessage); + _variant_t testData = loodsman->main->GetMUnitList(to_bstr_t(QString("V6CDB8F46D23C4E5CB16863CC70079F1C")),&inErrorCode, &stErrorMessage); + + //_variant_t testData = loodsman->main->GetInfoAboutCurrentBase(8,&inErrorCode, &stErrorMessage); +/* testData = loodsman->main->GetLinkAttrForTypes(to_bstr_t(QString("Технология")), + to_bstr_t(QString("Техоперация")), + to_bstr_t(QString("Состоит из ...")), + &inErrorCode, + &stErrorMessage); +*/ + unsigned char *p = (unsigned char *)testData.parray->pvData; + MidasData *mData = new MidasData(); + mData->setData(p); + + qDebug() << "2-----------------------"; + if (mData->first()) + do + for (int i=0;ifieldCount();i++){ + qDebug() << mData->fieldName(i) << ":" << mData->fieldValue(i); + } + while (mData->next()); + +} + +void MainWindow::testModel(){ + + ldsmnModel = new TreeLoodsmanModel(); + + ldsmnModel->setLinkModel(ldsmnLinkModel); + ldsmnModel->setTypeModel(ldsmnTypeModel); + ldsmnModel->setAttrModel(ldsmnAttrModel); + ldsmnLinkModel->fetchMore(QModelIndex()); + ldsmnTypeModel->fetchMore(QModelIndex()); + ldsmnAttrModel->fetchMore(QModelIndex()); + ldsmnModel->select(); + ldsmnEditAttrModel->setSourceModel(ldsmnModel); + treeViewObjAttr->setModel(ldsmnEditAttrModel); + PropEditorDelegate *propDelegate = new PropEditorDelegate(); + propDelegate->setAttrModel(ldsmnAttrModel); + + treeViewObjAttr->setItemDelegate(propDelegate); + treeViewObjAttr->model()->setHeaderData(0, Qt::Horizontal, tr("Наименование")); + treeViewObjAttr->model()->setHeaderData(7, Qt::Horizontal, tr("Значение")); + treeViewObjAttr->model()->setHeaderData(9, Qt::Horizontal, tr("ЕИ")); + treeViewObjAttr->hideColumn(1); + treeViewObjAttr->hideColumn(2); + treeViewObjAttr->hideColumn(3); + treeViewObjAttr->hideColumn(4); + treeViewObjAttr->hideColumn(5); + treeViewObjAttr->hideColumn(6); + treeViewObjAttr->hideColumn(8); + treeViewObjAttr->hideColumn(10); + treeViewObjAttr->setColumnWidth(9,40); + + treeView->setModel(ldsmnModel); + treeView->setExpandsOnDoubleClick(false); + connect(treeView,SIGNAL(clicked(QModelIndex)),this,SLOT(editAttr(QModelIndex))); +} + +void MainWindow::testType() +{ + treeViewType->setModel(ldsmnTypeModel); + //treeViewType->hideColumn(0); +} + +void MainWindow::testLink() +{ + + treeViewLink->setModel(ldsmnLinkModel); +} + +void MainWindow::testStat() +{ + StatLoodsmanModel* ldsmnStatModel = new StatLoodsmanModel(); + + QStringList fields; + fields << "_ID" << "_NAME"; + ldsmnStatModel->setFields(fields); + ldsmnStatModel->setFieldIcon("_ICON"); + treeViewStat->setModel(ldsmnStatModel); +} + +void MainWindow::testAttr() +{ + treeViewAttr->setModel(ldsmnAttrModel); +} + +void MainWindow::editAttr(QModelIndex index) +{ + ldsmnEditAttrModel->setCurrentNode(index); +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..d202f0e --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,39 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include "ui_mainwindow.h" + +#include "typeloodsmanmodel.h" +#include "linkloodsmanmodel.h" +#include "statloodsmanmodel.h" +#include "attrloodsmanmodel.h" +#include "treeloodsmanmodel.h" +#include "attreditloodsmanmodel.h" + +class MainWindow : public QMainWindow, private Ui::MainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); +public slots: + bool onActionConnect(); + +private slots: + void listProject(); + void testModel(); + void testType(); + void testLink(); + void testStat(); + void testAttr(); + void editAttr(QModelIndex index); +private: + TreeLoodsmanModel* ldsmnModel; + TypeLoodsmanModel* ldsmnTypeModel; + LinkLoodsmanModel* ldsmnLinkModel; + AttrLoodsmanModel* ldsmnAttrModel; + AttrEditLoodsmanModel* ldsmnEditAttrModel; +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..a6cec92 --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,139 @@ + + + MainWindow + + + + 0 + 0 + 570 + 563 + + + + Главное окно + + + + + + + Qt::Horizontal + + + + Qt::Vertical + + + + + + + Qt::Vertical + + + + + + + + + + + + + + Тест проекта + + + + + + + Тест модели + + + + + + + Тест типов + + + + + + + Тест связей + + + + + + + Тест состояний + + + + + + + Тест атрибутов + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 171 + + + + + + + + + + + + 0 + 0 + 570 + 18 + + + + + + TopToolBarArea + + + false + + + + + + + + TreePropView + QTreeView +
treepropview.h
+
+
+ + +
diff --git a/midasdata.cpp b/midasdata.cpp new file mode 100644 index 0000000..65da9ef --- /dev/null +++ b/midasdata.cpp @@ -0,0 +1,401 @@ +#include "midasdata.h" +#include +#include +#include + +MidasData::MidasData(QObject *parent) : + QObject(parent) +{ +} + +bool MidasData::first() +{ + if (recordCount()>0){ + m_current = 0; + return true; + } + return false; + +} + +void MidasData::last() +{ + m_current = recordCount()-1; +} + +quint16 MidasData::fieldCount() +{ + + return m_field.count(); +} + +qint32 MidasData::recordCount() +{ + return m_record.count(); +} + + +MidasField MidasData::field(long index){ + + return m_field.at(index); +} + +QString MidasData::fieldName(long index) +{ + return m_field.at(index).fieldName; +} + +void MidasData::setData(unsigned char *data) +{ + m_field.clear(); + fillField(data); + m_record.clear(); + fillRecord(data); + first(); +} + +unsigned char *MidasData::data() +{ + return NULL; +} + +unsigned char MidasData::getStsBit(unsigned char* stsBit, long index){ + + int idxChar = (int)(index/4); + int shiftBit = index - idxChar * 4; + unsigned char status = stsBit[idxChar]; + status = (status >> shiftBit*2) & 3; + return status; +} + +int MidasData::indexOf(QString name){ + for (int i=0;i= 0){ + m_current--; + return true; + } + return false; +} + +void MidasData::clear() +{ + m_field.clear(); + m_record.clear(); +} + +void MidasData::fillField(unsigned char *data) +{ + MidasField retField; + long offsetField = 24; + + quint16 fieldCount; + memcpy(&fieldCount,(data+12),sizeof(fieldCount)); + + for (long i=0;i=0 && value < recordCount()){ + m_record.at(value); + m_record.first(); + return true; + } + return false; + +} + +QVariant MidasData::fieldValue(QString name) +{ + int index = indexOf(name); + + if (index!=-1) + return fieldValue(index); + return QVariant(); +} diff --git a/midasdata.h b/midasdata.h new file mode 100644 index 0000000..b4b9ed0 --- /dev/null +++ b/midasdata.h @@ -0,0 +1,188 @@ +#ifndef MIDASDATA_H +#define MIDASDATA_H + +#include +#include +#include +#include + +enum MidasStsBit{ + bitNull = 1, //! Поле пустое + bitNotChange = 2, //! Поле не изменено + bitNotAll = 3 //! Поле пустое и не изменено +}; + +enum MidasRecordStatus{ + dsRecUnmodified = 0x0000,//! { Unmodified record } + dsRecOrg = 0x0001, //! { Original record (was changed) } + dsRecDeleted = 0x0002, //! { Record was deleted } + dsRecNew = 0x0004, //! { Record was inserted } + dsRecModified = 0x0008, //! { Record was changed } + dsUnused = 0x0020, //! { Record not used anymore (hole) } + dsDetUpd = 0x0040 //! { Detail modification Ins/Del/Mod. }{ Can be combined with other status. } +}; + +enum MidasAttrs{ + fldAttrHIDDEN = 0x0001, //! { Field is hidden } + fldAttrREADONLY = 0x0002, //! { Field is readonly } + fldAttrREQUIRED = 0x0004, //! { Field value required } + fldAttrLINK = 0x0008 //! { Linking field } +}; + +enum MidasFieldType{ + dsfldUNKNOWN = 0, //! { Unknown } + dsfldINT = 1, //! { signed integer } + dsfldUINT = 2, //! { Unsigned integer } + dsfldBOOL = 3, //! { Boolean } + dsfldFLOATIEEE = 4, //! { IEEE float } + dsfldBCD = 5, //! { BCD } + dsfldDATE = 6, //! { Date (32 bit) } + dsfldTIME = 7, //! { Time (32 bit) } + dsfldTIMESTAMP = 8, //! { Time-stamp (64 bit) } + dsfldZSTRING = 9, //! { Multi-byte string } + dsfldUNICODE = 10, //! { unicode string } + dsfldBYTES = 11, //! { bytes } + dsfldADT = 12, //! { ADT (Abstract Data Type) } + dsfldARRAY = 13, //! { Array type (not attribute) } + dsfldEMBEDDEDTBL = 14, //! { Embedded (nested table type) } + dsfldREF = 15 //! { Reference } +}; + +enum MidasMaskField { + MaskFieldType = 0x3F, //! { mask to retrieve Field Type } + MaskVaryingFld = 0x40, //! { Varying attribute type. } + MaskArrayFld = 0x80 //! { Array attribute type. } - Данные массива предваряются длиной Len: Int32, за которой следуют его элементы Data[Len]. +}; + +/* Пример структуры пакета MIDAS/DATASNAP + +struct MidasProp{ + quint32 CHANGE_LOG[]; // UInt32[] - массив из целых чисел. + quint32 DATASET_DELTA;// UInt32 = 1, если в пакете передается delta-набор (набор изменений). +}; + +struct MidasRecord{ + quint8 recordStatus; // Статус записи: MidasRecordStatus + unsigned char statusBit[fieldCount/4]; // На каждое поле в массиве статусных битов отводится 2 бита от младшего к старшему. Данные полей содержащих Null или NotChanged в запись не попадают. + // BLANK_NULL = 1; { 'real' NULL } + // BLANK_NOTCHANGED = 2; { Not changed , compared to original value } + unsigned char fieldData[]; // FieldData[] - пишутся только not null & changed значения. + // Для полей фиксированного размера: FixedFieldData = Byte[FieldSize] + // Для полей переменного размера: VarFieldData = (DataLen: UInt(of FieldSize)) Byte[DataLen] - те обычно данные предваряются 1-2 байтами размера. +}; + +struct MidasFieldProp{ + quint8 len; // Длина имени свойства + char propName[len]; // Имя свойства + qint16 propSize; // Для строк - длина фиксированной части, те размера + qint16 propType; // Тип свойства: MidasFieldType + unsigned char data[propSize]; // Данные свойства +}; + +struct MidasField{ + quint8 len; // Длина имени поля + char fieldName[len]; // Имя поля + qint16 fieldSize; // Для строк - длина фиксированной части, те размера + qint16 fieldType; // Тип Поля: MidasFieldType + qint16 fieldAttrs; // Атрибуты (флаги) поля: MidasAttrs + quint16 propCount; // Количество свойств поля + MidasFieldProp props[propCount]; // Cвойства поля + // WIDTH: UInt16 - для полей переменного размера, например строк, равно Field.Size. Те это предельный размер данных, хранимых в поле. +}; + +struct MidasPacket{ + unsigned char signature[4]; // Сигнатура пакета MIDAS/DataSnap [$96, $19, $E0, $BD] + qint32 skip1; // Int32, обычно равно 1 + qint32 skip2; // Int32, обычно равно 18 + quint16 fieldCount; // UInt16 - количество полей + qint32 recordCount; // Int32 - количество записей в пакете + qint32 skip3; // Int32, обычно равно 3 + quint16 headerSize; // UInt16 - вероятно, размер всего заголовка включая описания полей и свойств. + MidasField fieldList[fieldCount]; // Структура описания полей. + quint16 propCount; // UInt16 - количество свойств + MidasProp props[propCount]; // Свойства набора + MidasRecord recordList[recordCount]; // Данные записей (начинается с headerSize) +}; +*/ + +struct MidasField{ + QString fieldName; //! Имя поля + qint16 fieldSize; //! Для строк - длина фиксированной части, те размера + qint16 fieldType; //! Тип Поля: MidasFieldType + qint16 fieldAttrs; //! Атрибуты (флаги) поля: MidasAttrs + quint16 propCount; //! Количество свойств поля +}; + +typedef QVector MidasRecord; + +class MidasData : public QObject +{ + Q_OBJECT +public: + explicit MidasData(QObject *parent = 0); + + //! Переход на начало + bool first(); + //! Переход в конец + void last(); + //! Переход на следующую + bool next(); + //! Переход на предыдущую + bool prior(); + + //! Очистка полей и записей + void clear(); + + //! Заполнение полей + void fillField(unsigned char* data); + + //! Заполнение записей + /*! Не реализована обработка: dsfldADT,dsfldARRAY, dsfldEMBEDDEDTBL, dsfldREF и MaskArrayFld + */ + void fillRecord(unsigned char* data); + + //! Текущая запись + long currentRecord(); + //! Установить текущую запись + bool setCurrentRecord(long value); + + //! Получение значения поля по его имени + QVariant fieldValue(QString name); + //! Получение значения поля по индексу + QVariant fieldValue(long index); + + //! Получение имени поля по индексу + QString fieldName(long index); + + //! Чтение данных пакета MIDAS + void setData(unsigned char* data); + //! Получение данных пакета MIDAS + unsigned char* data(); + + //! Кол-во полей + quint16 fieldCount(); + //! Кол-во записей + qint32 recordCount(); + + //! Получение описания поля по индексу + MidasField field(long index); + + //! Получение индекса поля по его имени + int indexOf(QString name); +private: + //! Получение статусных битов значения записи + unsigned char getStsBit(unsigned char *stsBit, long index); + //! Список полей + QVector m_field; + //! Список записей + QVector m_record; + //! Текущая запись + long m_current; + +signals: + +public slots: + +}; + +#endif // MIDASDATA_H diff --git a/propeditordelegate.cpp b/propeditordelegate.cpp new file mode 100644 index 0000000..688d14d --- /dev/null +++ b/propeditordelegate.cpp @@ -0,0 +1,266 @@ +#include "propeditordelegate.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +PropEditorDelegate::PropEditorDelegate(QObject *parent) : + QItemDelegate(parent) +{ + m_colors.reserve(6); + m_colors.push_back(QColor(255, 230, 191)); + m_colors.push_back(QColor(255, 255, 191)); + m_colors.push_back(QColor(191, 255, 191)); + m_colors.push_back(QColor(199, 255, 255)); + m_colors.push_back(QColor(234, 191, 255)); + m_colors.push_back(QColor(255, 191, 239)); +} + +QWidget *PropEditorDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + + long id = index.sibling(index.row(),1/*_ID*/).data().toInt(); + + // Единицы измерения + if (index.column()==9/*_UNIT*/) + if (!m_attrModel->data(id, m_attrModel->fieldIndex("_ID_NATURE")).toString().isEmpty()) + { + QComboBox* pRes = new QComboBox(parent); + QList listUnits = m_attrModel->listUnits( + m_attrModel->data(id, m_attrModel->fieldIndex("_ID_NATURE")).toString()); + + QStandardItemModel *model = new QStandardItemModel(listUnits.count(), 2); + + for (int row = 0; row < listUnits.count(); ++row) { + QStandardItem *item = new QStandardItem(listUnits.at(row).id); + model->setItem(row, 1, item); + item = new QStandardItem(listUnits.at(row).name); + model->setItem(row, 0, item); + } + + pRes->setModel(model); + return pRes; + } else + return 0; + + // Список значений + if (index.column()==7/*_VALUE*/ && + !m_attrModel->data(id, m_attrModel->fieldIndex("_LIST")).toString().isEmpty()) + { + QComboBox* pRes = new QComboBox(parent); + QStringList list = m_attrModel->data(id, m_attrModel->fieldIndex("_LIST")).toString().split("\r\n"); + QStringListModel *model = new QStringListModel(pRes); + model->setStringList(list); + pRes->setModel(model); + return pRes; + } + + // Календарь + if (index.data(Qt::EditRole).type() == QVariant::Date) { + QDateEdit* pRes = new QDateEdit(parent); + pRes->setCalendarPopup(true); + pRes->setDisplayFormat("dd.MM.yyyy HH:mm"); + return pRes; + } + + // Логическое + if (index.data(Qt::EditRole).type() == QVariant::Bool) { + QCheckBox* pRes = new QCheckBox(parent); + return pRes; + } + + return QItemDelegate::createEditor(parent,option,index); +} + +void PropEditorDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + long id = index.sibling(index.row(),1/*_ID*/).data().toInt(); + + // Установка значения по умолчанию + if (!m_attrModel->data(id, m_attrModel->fieldIndex("_DEFAULT")).isNull() && + index.column()==7/*_VALUE*/ && index.data().isNull()){ + if (editor->inherits("QLineEdit")) + (qobject_cast(editor))->setText(index.data().toString()); + else if (editor->inherits("QSpinBox")) + (qobject_cast(editor))->setValue(index.data().toInt()); + else if (editor->inherits("QDoubleSpinBox")) + (qobject_cast(editor))->setValue(index.data().toDouble()); + return; + } + + // Список значений + if (index.column()==7/*_VALUE*/ && + !m_attrModel->data(id, m_attrModel->fieldIndex("_LIST")).toString().isEmpty()) + { + QComboBox *pRes = static_cast(editor); + for (int row=0;rowmodel()->rowCount();row++) + if (pRes->model()->index(row,0).data()==index.sibling(index.row(),7/*_ID_UNIT*/).data()){ + pRes->setCurrentIndex(row); + return; + } + pRes->setCurrentIndex(0); + return; + } + + // Единицы измерения + if (index.column()==9/*_UNIT*/){ + QComboBox *pRes = static_cast(editor); + for (int row=0;rowmodel()->rowCount();row++) + if (pRes->model()->index(row,1).data()==index.sibling(index.row(),8/*_ID_UNIT*/).data()){ + pRes->setCurrentIndex(row); + return; + } + pRes->setCurrentIndex(0); + return; + } + + // Календарь + if (index.data(Qt::EditRole).type() == QVariant::Date) { + QDateEdit *pRes = static_cast(editor); + pRes->setDate(index.model()->data(index, Qt::EditRole).toDate()); + return; + } + + // Логическое + if (index.data(Qt::EditRole).type() == QVariant::Bool) { + QCheckBox *pRes = static_cast(editor); + pRes->setChecked(index.model()->data(index, Qt::EditRole).toBool()); + return; + } + + QItemDelegate::setEditorData(editor,index); + return; +} + +void PropEditorDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const +{ + // Единицы измерения + if (index.column()==9/*_UNIT*/ && editor->inherits("QComboBox")){ + QComboBox *pRes = static_cast(editor); + model->setData(index,pRes->currentText(),Qt::EditRole); + model->setData(index.sibling(index.row(),8/*_ID_UNIT*/), + pRes->model()->index(pRes->currentIndex(),1).data().toString(), + Qt::EditRole + ); + return; + } + + // Список значений + if (editor->inherits("QComboBox")) { + QComboBox *pRes = static_cast(editor); + model->setData(index,pRes->currentText(),Qt::EditRole); + return; + } + + // Календарь + if (index.data(Qt::EditRole).type() == QVariant::Date) { + QDateEdit *pRes = static_cast(editor); + model->setData(index,pRes->date(),Qt::EditRole); + return; + } + + // Логическое + if (index.data(Qt::EditRole).type() == QVariant::Bool) { + QCheckBox *pRes = static_cast(editor); + model->setData(index,pRes->isChecked(),Qt::EditRole); + return; + } + + QItemDelegate::setModelData(editor,model,index); + return; +} + +void PropEditorDelegate::updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + Q_UNUSED(index) + + editor->setGeometry(option.rect); + return; +} + +void PropEditorDelegate::paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + QStyleOptionViewItemV3 opt = option; + + bool isHeader = false; + if (!index.parent().isValid()) + isHeader = true; + + bool isModified = false; + + if (index.column() == 0 && isModified) { + opt.font.setBold(true); + opt.fontMetrics = QFontMetrics(opt.font); + } + + QColor c; + if (isHeader) { + c = opt.palette.color(QPalette::Dark); + opt.palette.setColor(QPalette::Text, opt.palette.color(QPalette::BrightText)); + } else { + c = QColor(255, 230, 191); + if (c.isValid() && (opt.features & QStyleOptionViewItemV2::Alternate)) + c = c.lighter(112); + } + if (c.isValid()) + painter->fillRect(option.rect, c); + opt.state &= ~QStyle::State_HasFocus; + + // Логический + if (index.model()->data(index, Qt::EditRole).type() == QVariant::Bool){ + QSize size = QSize(5,5);//check(option, option.rect, Qt::Checked).size(); + QRect checkboxRect = QStyle::alignedRect(option.direction, (Qt::AlignVCenter|Qt::AlignLeft), size, option.rect); + drawCheck(painter,option,checkboxRect,Qt::Checked); + } else + QItemDelegate::paint(painter, opt, index); + + opt.palette.setCurrentColorGroup(QPalette::Active); + QColor color = static_cast(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt)); + painter->save(); + painter->setPen(QPen(color)); + if (/*!lastColumn(index.column()) &&*/ !isHeader) { + int right = (option.direction == Qt::LeftToRight) ? option.rect.right() : option.rect.left(); + painter->drawLine(right, option.rect.y(), right, option.rect.bottom()); + } + painter->restore(); +} + +QColor PropEditorDelegate::calcBgColor(const QModelIndex &index) const +{ + QModelIndex i = index; + while (i.parent().isValid()) + i = i.parent(); + + long rowColor; + if (i.row() +#include "attrloodsmanmodel.h" + +class PropEditorDelegate : public QItemDelegate +{ + Q_OBJECT +public: + explicit PropEditorDelegate(QObject *parent = 0); + virtual QWidget * createEditor ( QWidget * parent, + const QStyleOptionViewItem & option, + const QModelIndex & index ) const; + virtual void setEditorData( QWidget * editor, + const QModelIndex & index ) const; + virtual void setModelData( QWidget * editor, QAbstractItemModel * model, + const QModelIndex & index ) const; + virtual void updateEditorGeometry(QWidget *editor, + const QStyleOptionViewItem &option, + const QModelIndex & index) const; + virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + QColor calcBgColor(const QModelIndex &index) const; + + virtual QSize sizeHint(const QStyleOptionViewItem &option, + const QModelIndex &index) const; + + void setAttrModel(AttrLoodsmanModel* model); +signals: + +public slots: + +private: + QVector m_colors; + AttrLoodsmanModel* m_attrModel; +}; + +#endif // PROPEDITORDELEGATE_H diff --git a/statloodsmanmodel.cpp b/statloodsmanmodel.cpp new file mode 100644 index 0000000..32ea35c --- /dev/null +++ b/statloodsmanmodel.cpp @@ -0,0 +1,244 @@ +#include "statloodsmanmodel.h" +#include "loodsmansystem.h" +#include "converttype.h" +#include "QMessageBox" +#include + +StatLoodsmanModel::StatLoodsmanModel(QObject *parent) : + QAbstractItemModel(parent) +{ + dataSet = new MidasData(); + m_root = new TreeNode; + m_root->id = 0; + m_root->isFetch = false; + cache.insert(0,m_root); +} + +StatLoodsmanModel::~StatLoodsmanModel() +{ + delete dataSet; +} + +int StatLoodsmanModel::columnCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return m_fieldNames.count(); +} + +TreeNode *StatLoodsmanModel::getItem(const QModelIndex & index) const +{ + if (index.isValid()) + return static_cast(index.internalPointer()); + else + return m_root; +} + +QVariant StatLoodsmanModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + if (role == Qt::DecorationRole && index.column()==0 && !m_fieldIcon.isEmpty()){ + QPixmap pixmap; + const TreeNode *item = getItem(index); + if (item) { + pixmap.loadFromData(item->data.at(m_fieldNames.count()).toByteArray()); + return QIcon(pixmap); + } + } + + if(role == Qt::DisplayRole){ + const TreeNode *item = getItem(index); + if (item) + return item->data.at(index.column()); + } + return QVariant(); +} + +bool StatLoodsmanModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(index); + if (role != Qt::EditRole) + return false; + return 0; +} + +Qt::ItemFlags StatLoodsmanModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + Qt::ItemFlags fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + /*if ( d->isEditable( index.internalId(), index.column() ) ) + fl |= Qt::ItemIsEditable;*/ + return fl; +} + +QVariant StatLoodsmanModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole) { + return m_fieldNames.at(section); + } + return QVariant(); +} + +bool StatLoodsmanModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(section); + + if (role != Qt::EditRole || orientation != Qt::Horizontal) + return false; + + return false; +} + +QModelIndex StatLoodsmanModel::index(int row, int column, const QModelIndex &parent) const +{ + if(!hasIndex(row, column, parent)) + return QModelIndex(); + + const TreeNode* parentItem = getItem(parent); + + if (!parentItem) + return QModelIndex(); + + TreeNode* childItem = cache[parentItem->children.at(row)]; + + if (childItem) + return createIndex(row, column, (void*)childItem); + else + return QModelIndex(); +} + +QModelIndex StatLoodsmanModel::parent(const QModelIndex &index) const +{ + if(!index.isValid()) + return QModelIndex(); + + const TreeNode *childItem = getItem(index); + TreeNode *parentItem = cache[childItem->parent]; + + if (!parentItem || parentItem == m_root) + return QModelIndex(); + + TreeNode *grandparent = cache[parentItem->parent]; + if (!grandparent) + return QModelIndex(); + + for (int i = 0; i < grandparent->children.count(); i++) + if (grandparent->children.at(i) == parentItem->id) + return createIndex(i, 0, (void*) parentItem); + + return QModelIndex(); +} + +int StatLoodsmanModel::rowCount(const QModelIndex &parent) const +{ + if(parent.column() > 0) + return 0; + + return getItem(parent)->children.count(); +} + +bool StatLoodsmanModel::hasChildren(const QModelIndex & parent) const +{ + TreeNode* node = getItem(parent); + if (node->isFetch && node->children.count()==0) + return false; + + return true; +} + +bool StatLoodsmanModel::canFetchMore(const QModelIndex &parent) const +{ + return !getItem(parent)->isFetch; +} + +void StatLoodsmanModel::fetchMore(const QModelIndex &parent) +{ + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + VARIANT inErrorCode; + VARIANT stErrorMessage; + + TreeNode *item; + + if(parent.isValid()){ + item = getItem(parent); + if(!item) + return; + } + + _variant_t data = loodsman->main->GetInfoAboutCurrentBase(7,&inErrorCode, &stErrorMessage); + dataSet->setData((unsigned char *)data.parray->pvData); + + if (inErrorCode.lVal!=0) + QMessageBox::warning(NULL, tr("Ошибка соединения"), from_bstr_t(stErrorMessage.bstrVal)); + + if (dataSet->first()){ + do { + int childId = dataSet->fieldValue("_ID").toInt(); + long parentId = 0/*dataSet->fieldValue("_ID_PARENT_TYPE").toInt()*/; + + TreeNode *item = /*cache[parentId]*/m_root; + if (item==NULL){ + if (parentId == 0) + item = m_root; + else { + item = new TreeNode; + item->id = parentId; + cache.insert(parentId, item); + item->isFetch = true; + } + } + + TreeNode* childItem; + if (!cache.contains(childId)){ + childItem = new TreeNode; + childItem->id = childId; + childItem->isFetch = true; + cache.insert(childId, childItem); + item->children.append(childId); + } else { + childItem = cache[childId]; + childItem->data.clear(); + } + + childItem->parent = parentId; + + for ( int j=0; j < m_fieldNames.count(); j++ ) + childItem->data.append(dataSet->fieldValue(m_fieldNames[j])); + if (!m_fieldIcon.isEmpty()) + childItem->data.append(dataSet->fieldValue(m_fieldIcon)); + } while (dataSet->next()); + dataSet->clear(); + + m_root->isFetch = true; + beginInsertRows(QModelIndex(), 0,cache[0]->children.count()); + endInsertRows(); + } +} + +QStringList StatLoodsmanModel::fields() +{ + return m_fieldNames; +} + +void StatLoodsmanModel::setFields(const QStringList &dataFields) +{ + m_fieldNames = dataFields; +} + +void StatLoodsmanModel::setFieldIcon(QString column) +{ + m_fieldIcon = column; +} + +int StatLoodsmanModel::fieldIndex(const QString &fieldName) const +{ + for (int i = 0;i +#include +#include "treenode.h" +#include "midasdata.h" + +class StatLoodsmanModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit StatLoodsmanModel(QObject *parent = 0); + ~StatLoodsmanModel(); + + //! Возращает хранимые данные + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + //! Устанавливает значение для указанной записи + bool setData(const QModelIndex &index, const QVariant &value, int role); + + //! Возвращает флаг записи + Qt::ItemFlags flags(const QModelIndex &index) const; + + //! Возращает название заголовка + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + //! Устанавливает название заголовка + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role); + + //! Возращает индекс модели для строки и колонки + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + + //! Возращает индекс родителя + QModelIndex parent(const QModelIndex &index) const ; + + //! Возращает количество строк в индексе родителя + int rowCount(const QModelIndex &parent = QModelIndex()) const; + + //! Возращает количество столбцов в индексе родителя + int columnCount(const QModelIndex &parent = QModelIndex()) const; +/* + //! Удаление строки + bool removeRows(int position, int rows, const QModelIndex &parent); + + //! Вставка строки + bool insertRows(int position, int rows, const QModelIndex &parent); +*/ + //! Проверка имеются ли дети + bool hasChildren(const QModelIndex & parent) const ; + + //! Получение TreeItem по индексу + TreeNode *getItem(const QModelIndex &index) const; + + //! Проверка можно ли провести ленивыю инициализацию + bool canFetchMore(const QModelIndex &parent) const; + + //! Ленивая инициализация + void fetchMore(const QModelIndex &parent); + + //! Получение списка полей с данных + QStringList fields() ; + + //! Установка списка полей данных + void setFields(const QStringList& dataFields ); + + void setFieldIcon(QString column); + int fieldIndex(const QString &fieldName) const; +private: + TreeNode* m_root; + MidasData* dataSet; + + //! Список полей данных + QStringList m_fieldNames; + + //! Поле с Иконкой + QString m_fieldIcon; + + mutable QHash cache; +signals: + +public slots: + +}; + +#endif // STATLOODSMANMODEL_H diff --git a/treeitem.cpp b/treeitem.cpp new file mode 100644 index 0000000..9769677 --- /dev/null +++ b/treeitem.cpp @@ -0,0 +1,34 @@ +#include "treeitem.h" +#include "converttype.h" +#include "loodsmansystem.h" +#include +#include +#include "midasdata.h" + +TreeItem::TreeItem(long rootid, TreeItem *parent) : + QObject(parent) +{ + id = rootid; + m_parent = parent; + m_fetchedMore = false; +} + +TreeItem *TreeItem::childAt(int i) const +{ + return (m_children.count() > i)? m_children.at(i) : 0; +} + +void TreeItem::setFectMore(bool flag) +{ + this->m_fetchedMore = flag; +} + +bool TreeItem::canFetchMore() const +{ + return !m_fetchedMore; +} + +void TreeItem::append(TreeItem *item) +{ + m_children.append(item); +} diff --git a/treeitem.h b/treeitem.h new file mode 100644 index 0000000..ef5d8bb --- /dev/null +++ b/treeitem.h @@ -0,0 +1,40 @@ +#ifndef TREEITEM_H +#define TREEITEM_H +#include +#include + +class TreeItem : public QObject +{ + Q_OBJECT +public: + explicit TreeItem(long rootid,TreeItem *parent = 0); + + TreeItem* childAt(int i) const; + + TreeItem* parent() const{ + return m_parent; + } + bool hasChildren(){ + return (!(m_fetchedMore && m_children.empty())); + } + int childCount()const{ + return m_children.count(); + } + + void setFectMore(bool flag); + + bool canFetchMore() const; + + void append(TreeItem *item); + + long id; + +private: + QList m_children; + TreeItem* m_parent; + bool m_fetchedMore; + + int fieldNumber; +}; + +#endif // TREEITEM_H diff --git a/treeloodsmanmodel.cpp b/treeloodsmanmodel.cpp new file mode 100644 index 0000000..b982b25 --- /dev/null +++ b/treeloodsmanmodel.cpp @@ -0,0 +1,553 @@ +#include "treeloodsmanmodel.h" +#include "loodsmansystem.h" +#include "converttype.h" +#include +#include +#include +#include + +TreeLoodsmanModel::TreeLoodsmanModel(TreeItem *parent) : + QAbstractItemModel(parent) +{ + m_root = new TreeItem(0); + dataSet = new MidasData(); +} + +TreeLoodsmanModel::~TreeLoodsmanModel() +{ + delete dataSet; +} + +int TreeLoodsmanModel::columnCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return m_fieldNames.count(); +} + +TreeItem *TreeLoodsmanModel::getItem(const QModelIndex & index) const +{ + if (index.isValid()) + return static_cast(index.internalPointer()); + else + return m_root; +} + +QVariant TreeLoodsmanModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid() || role != Qt::DisplayRole) + return QVariant(); + + if(role == Qt::DisplayRole){ + TreeItem *item = getItem(index); + if (item) + return m_data[item->id]->at(index.column()); + } + return QVariant(); +} + +bool TreeLoodsmanModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(index); + if (role != Qt::EditRole) + return false; + return 0; +} + +Qt::ItemFlags TreeLoodsmanModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + Qt::ItemFlags fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + /*if ( d->isEditable( index.internalId(), index.column() ) ) + fl |= Qt::ItemIsEditable;*/ + return fl; +} + +QVariant TreeLoodsmanModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole) { + return m_fieldNames.at(section); + } + return QVariant(); +} + +bool TreeLoodsmanModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(section); + + if (role != Qt::EditRole || orientation != Qt::Horizontal) + return false; + + return false; +} + +QModelIndex TreeLoodsmanModel::index(int row, int column, const QModelIndex &parent) const +{ + if(!hasIndex(row, column, parent)) + return QModelIndex(); + + const TreeItem* parentItem = getItem(parent); + + if (!parentItem) + return QModelIndex(); + + TreeItem* childItem = parentItem->childAt(row); + + if (childItem) + return createIndex(row, column, (void*)childItem); + else + return QModelIndex(); +} + +QModelIndex TreeLoodsmanModel::parent(const QModelIndex &index) const +{ + if(!index.isValid()) + return QModelIndex(); + + const TreeItem *childItem = getItem(index); + TreeItem *parentItem = childItem->parent(); + + if (!parentItem || parentItem == m_root) + return QModelIndex(); + + TreeItem *grandparent = parentItem->parent(); + if (!grandparent) + return QModelIndex(); + + for (int i = 0; i < grandparent->childCount(); i++) + if (grandparent->childAt(i) == parentItem) + return createIndex(i, 0, (void*) parentItem); + + return QModelIndex(); +} + +int TreeLoodsmanModel::rowCount(const QModelIndex &parent) const +{ + if(parent.column() > 0) + return 0; + + /*if(getItem(parent)->canFetchMore()){ + TreeItem* item = parent.isValid()? static_cast(parent.internalPointer()) : m_root; + if(item) + item->populateChildren(); + }*/ + + return getItem(parent)->childCount(); +} + +bool TreeLoodsmanModel::hasChildren(const QModelIndex & parent) const +{ + Q_UNUSED(parent); + + //bool result = getItem(parent)->hasChildren(); + + return getItem(parent)->hasChildren(); +} + +bool TreeLoodsmanModel::canFetchMore(const QModelIndex &parent) const +{ + return getItem(parent)->canFetchMore(); +} + +void TreeLoodsmanModel::fetchMore(const QModelIndex &parent) +{ + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + VARIANT inErrorCode; + VARIANT stErrorMessage; + + TreeItem *item; + + if(parent.isValid()){ + item = getItem(parent); + if(!item) + return; + + _variant_t data = loodsman->main->GetTree2(item->id, + to_bstr_t(m_linkType), + 0, + &inErrorCode, &stErrorMessage); + dataSet->setData((unsigned char *)data.parray->pvData); + }else{ + item = m_root; + + _variant_t data = loodsman->main->GetProjectList2(item->id,&inErrorCode, &stErrorMessage); + dataSet->setData((unsigned char *)data.parray->pvData); + } + + + if (inErrorCode.lVal!=0) + QMessageBox::warning(NULL, tr("Ошибка соединения"), from_bstr_t(stErrorMessage.bstrVal)); + + for (int i=0;irecordCount();i++){ + if (i==0) + dataSet->first(); + else + dataSet->next(); + + int childId = dataSet->fieldValue(QString("_ID_VERSION")).toInt(); + TreeItem *childItem = new TreeItem(childId,item); + + QList* listData = new QList; + + // Запись данных + if (m_data[childId] == NULL){ + if (item->id == 0) + for ( int j=0; j < m_prjFieldNames.count(); j++ ){ + listData->append(dataSet->fieldValue(m_prjFieldNames[j])); + } + else + for ( int j=0; j < m_fieldNames.count(); j++ ){ + listData->append(dataSet->fieldValue(m_fieldNames[j])); + } + m_data[childId] = listData; + } + item->append(childItem); + } + dataSet->clear(); + item->setFectMore(true); + + // Обновление + if (item->id == 0) + beginInsertRows(QModelIndex(), 0, item->childCount()); + else + beginInsertRows(parent, 0, item->childCount()); + endInsertRows(); +} + +void TreeLoodsmanModel::fetchMoreAttr(const QModelIndex &parent) +{ + TreeItem *item; + if(parent.isValid()){ + item = getItem(parent); + if(!item) + return; + } + + long objId = item->id; + if (m_attrVal.contains(objId)) + return; + + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + VARIANT inErrorCode; + VARIANT stErrorMessage; + + /* ЗАГРУЖАЕТ ВСЕ АТРИБУТЫ ВЫБРАННОГО ТИПА БЕЗ ЗНАЧЕНИЙ */ + AttrMap attrMap; + long typeId = data(parent.sibling(parent.row(),fieldIndex("_ID_TYPE"))).toInt(); + + if (typeId >0){ + QList listIdAttr = m_typeModel->listAttr(typeId); + for (int i=0;i listData; + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_NAME"))); + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_ID"))); + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_ATTRTYPE"))); + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_DEFAULT"))); + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_LIST"))); + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_ACCESSLEVEL"))); + // isAttrLink + listData.append(false); + attrMap.insert(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_NAME")).toString(), + listData); + } + } + + long parentTypeId = data(parent.parent().sibling(parent.parent().row(),fieldIndex("_ID_TYPE"))).toInt(); + long linkId = data(parent.sibling(parent.row(),fieldIndex("_ID_LINKTYPE"))).toInt(); + + if (typeId >0 && parentTypeId>0 && linkId>0){ + QString objLink = m_linkModel->data(linkId,m_linkModel->fieldIndex("_NAME")).toString(); + QList listIdAttr = m_typeModel->listAttrLink(typeId,parentTypeId,objLink); + + for (int i=0;i listData; + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_NAME"))); + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_ID"))); + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_ATTRTYPE"))); + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_DEFAULT"))); + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_LIST"))); + listData.append(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_ACCESSLEVEL"))); + // isAttrLink + listData.append(true); + attrMap.insert(m_attrModel->data(idAttr,m_attrModel->fieldIndex("_NAME")).toString(), + listData); + } + } + + /* ЗАГРУЖАЕТ ЗНАЧЕНИЕ АТРИБУТОВ + 0 - строковое значение; + 1 - целочисленное значение; + 2 - действительное число; + 3 - дата и время; + 5 - текст; + 6 - изображение); + + 0 - BSTR + 1 - int + 2 - double + 3 - DateTime + 5 - массив байт (Значение представляет собой одномерный вариантный массив (тип VT_UI1 (VC++), varByte(Delphi))) + 6 - массив байт (Значение представляет собой одномерный вариантный массив (тип VT_UI1 (VC++), varByte(Delphi))) + */ + + long objLinkId = data(parent.sibling(parent.row(),fieldIndex("_ID_LINK"))).toInt(); + + _variant_t testData = loodsman->main->GetAttributesValues2( + to_bstr_t(QString("%1").arg(objId)), + "",&inErrorCode, &stErrorMessage); + + unsigned char *p = (unsigned char *)testData.parray->pvData; + MidasData* mData = new MidasData(); + mData->setData(p); + if (mData->first()){ + do{ + QString name = mData->fieldValue("_NAME").toString(); + QList listData = attrMap.value(name); + QStringList list; + QDateTime dt; + switch (listData.at(2).toInt()) { + case 0: + listData.append(mData->fieldValue("_VALUE").toString()); + break; + case 1: + listData.append(mData->fieldValue("_VALUE").toInt()); + break; + case 2: + listData.append(mData->fieldValue("_VALUE").toDouble()); + break; + case 3: + list = mData->fieldValue("_VALUE").toString().split(QRegExp("\\s+")); + if (list.count()>0) + dt.setDate(QDate::fromString(list.at(0),"dd.MM.yyyy")); + if (list.count()>1) + dt.setTime(QTime::fromString(list.at(1),"HH:mm")); + listData.append(dt); + break; + default: + listData.append(mData->fieldValue("_VALUE")); + } + listData.append(mData->fieldValue("_ID_UNIT")); + listData.append(mData->fieldValue("_UNIT")); + attrMap[name] = listData; + }while (mData->next()); + } + + if (objLinkId > 0) + { + testData = loodsman->main->GetLinkAttributes( + objLinkId, + &inErrorCode, &stErrorMessage); + + p = (unsigned char *)testData.parray->pvData; + mData->clear(); + mData->setData(p); + if (mData->first()){ + do{ + QString name = mData->fieldValue("_NAME").toString(); + QList listData = attrMap.value(name); + QStringList list; + QDateTime dt; + switch (listData.at(2).toInt()) { + case 0: + listData.append(mData->fieldValue("_VALUE").toString()); + break; + case 1: + listData.append(mData->fieldValue("_VALUE").toInt()); + break; + case 2: + listData.append(mData->fieldValue("_VALUE").toDouble()); + break; + case 3: + list = mData->fieldValue("_VALUE").toString().split(QRegExp("\\s+")); + if (list.count()>0) + dt.setDate(QDate::fromString(list.at(0),"dd.MM.yyyy")); + if (list.count()>1) + dt.setTime(QTime::fromString(list.at(1),"HH:mm")); + listData.append(dt); + break; + default: + listData.append(mData->fieldValue("_VALUE")); + } + listData.append(mData->fieldValue("_ID_UNIT")); + listData.append(mData->fieldValue("_UNIT")); + attrMap[name] = listData; + }while (mData->next()); + } + } + m_attrVal.insert(objId,attrMap); +} + +QStringList TreeLoodsmanModel::fields(bool isProject) +{ + return (isProject)?m_prjFieldNames:m_fieldNames; +} + +void TreeLoodsmanModel::setFields(const QStringList &dataFields, bool isProject) +{ + if (isProject) + m_prjFieldNames = dataFields; + else + m_fieldNames = dataFields; +} + +void TreeLoodsmanModel::setLinkType(const QStringList &linkType) +{ + foreach(QString linkName,linkType){ + if (m_linkType.isEmpty()) + m_linkType = linkName; + else + m_linkType = m_linkType + QString(char(1)) + linkName; + } +} + +QAbstractItemModel* TreeLoodsmanModel::getAttrModel(const QModelIndex &parent) +{ + fetchMoreAttr(parent); + TreeItem *item; + if(parent.isValid()){ + item = getItem(parent); + if(!item) + return 0; + } + + QStandardItemModel* attrModel = new QStandardItemModel(0,10); + attrModel->setHeaderData(0, Qt::Horizontal, tr("_NAME")); + attrModel->setHeaderData(1, Qt::Horizontal, tr("_ID")); + attrModel->setHeaderData(2, Qt::Horizontal, tr("_ATTRTYPE")); + attrModel->setHeaderData(3, Qt::Horizontal, tr("_DEFAULT")); + attrModel->setHeaderData(4, Qt::Horizontal, tr("_LIST")); + attrModel->setHeaderData(5, Qt::Horizontal, tr("_ACCESSLEVEL")); + attrModel->setHeaderData(6, Qt::Horizontal, tr("_ISATTRLINK")); + attrModel->setHeaderData(7, Qt::Horizontal, tr("_VALUE")); + attrModel->setHeaderData(8, Qt::Horizontal, tr("_ID_UNIT")); + attrModel->setHeaderData(9, Qt::Horizontal, tr("_UNIT")); + + QStandardItem *parentItem = attrModel->invisibleRootItem(); + QStandardItem *oitem = new QStandardItem(tr("Атрибуты объекта")); + parentItem->appendRow(oitem); + QStandardItem *litem = new QStandardItem(tr("Атрибуты связи")); + parentItem->appendRow(litem); + + long objId = item->id; + foreach (QList value, m_attrVal.value(objId)){ + QList listoitem; + for (int i=0;i<10;i++){ + QStandardItem *item = new QStandardItem(); + if (isetData(value.at(i), Qt::EditRole); + else + if (i==7) + switch (value.at(2).toInt()) { + case 0: + item->setData(QVariant::String, Qt::EditRole); + break; + case 1: + item->setData(QVariant::Int, Qt::EditRole); + break; + case 2: + item->setData(QVariant::Double, Qt::EditRole); + break; + case 3: + item->setData(QVariant::DateTime, Qt::EditRole); + break; + default: + item->setData(QVariant::String, Qt::EditRole); + } + else + item->setData(QVariant::String, Qt::EditRole); + listoitem << item; + } + if (value.at(6)==true) + litem->appendRow(listoitem); + else + oitem->appendRow(listoitem); + } + + attrModel->submit(); + /*QStandardItemModel* model = new QStandardItemModel(); + QStandardItem *parentItem = model->invisibleRootItem(); + for (int i = 0; i < 4; ++i) { + QStandardItem *item = new QStandardItem(QString("item %0").arg(i)); + parentItem->appendRow(item); + parentItem = item; + } + return model;*/ + return attrModel; +} + +AttrMap TreeLoodsmanModel::attrMap(const QModelIndex &parent) +{ + fetchMoreAttr(parent); + TreeItem *item; + if(parent.isValid()){ + item = getItem(parent); + if(!item) + return AttrMap(); + } + + long objId = item->id; + return m_attrVal.value(objId); +} + +long TreeLoodsmanModel::fieldIndex(const QString &fieldName, bool isProject) +{ + if (isProject){ + for (long i = 0;ifetchMore(QModelIndex()); + + for (int row = 0; row < m_linkModel->rowCount(); row++){ + QModelIndex indexName = m_linkModel->index(row, m_linkModel->fieldIndex("_NAME")); + QModelIndex indexType = m_linkModel->index(row, m_linkModel->fieldIndex("_TYPE")); + if (m_linkModel->data(indexType)==0) + linkList << m_linkModel->data(indexName).toString(); + } + setLinkType(linkList); +} diff --git a/treeloodsmanmodel.h b/treeloodsmanmodel.h new file mode 100644 index 0000000..966a072 --- /dev/null +++ b/treeloodsmanmodel.h @@ -0,0 +1,131 @@ +#ifndef TREELOODSMANMODEL_H +#define TREELOODSMANMODEL_H + +#include +#include +#include +#include +#include "treeitem.h" +#include "loodsmansystem.h" +#include "midasdata.h" + +#include "typeloodsmanmodel.h" +#include "linkloodsmanmodel.h" +#include "statloodsmanmodel.h" +#include "attrloodsmanmodel.h" + +typedef QMap AttrMap; + +class TreeLoodsmanModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit TreeLoodsmanModel(TreeItem *parent = 0); + ~TreeLoodsmanModel(); + + //! Возращает хранимые данные + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + //! Устанавливает значение для указанной записи + bool setData(const QModelIndex &index, const QVariant &value, int role); + + //! Возвращает флаг записи + Qt::ItemFlags flags(const QModelIndex &index) const; + + //! Возращает название заголовка + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + //! Устанавливает название заголовка + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role); + + //! Возращает индекс модели для строки и колонки + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + + //! Возращает индекс родителя + QModelIndex parent(const QModelIndex &index) const ; + + //! Возращает количество строк в индексе родителя + int rowCount(const QModelIndex &parent = QModelIndex()) const; + + //! Возращает количество столбцов в индексе родителя + int columnCount(const QModelIndex &parent = QModelIndex()) const; +/* + //! Удаление строки + bool removeRows(int position, int rows, const QModelIndex &parent); + + //! Вставка строки + bool insertRows(int position, int rows, const QModelIndex &parent); +*/ + //! Проверка имеются ли дети + bool hasChildren(const QModelIndex & parent) const ; + + //! Получение TreeItem по индексу + TreeItem *getItem(const QModelIndex &index) const; + + //! Проверка можно ли провести ленивыю инициализацию + bool canFetchMore(const QModelIndex &parent) const; + + //! Получение списка полей с данных + QStringList fields(bool isProject) ; + + //! Ленивая инициализация + void fetchMore(const QModelIndex &parent); + + //! Получение модели атрибутов для объекта + QAbstractItemModel *getAttrModel(const QModelIndex &parent); + + //! Получение индекса поля + long fieldIndex(const QString &fieldName, bool isProject = false); + + void setTypeModel(TypeLoodsmanModel *model); + void setLinkModel(LinkLoodsmanModel *model); + void setStatModel(StatLoodsmanModel *model); + void setAttrModel(AttrLoodsmanModel *model); + + void select(); + + //! Ленивое чтение атрибутов объекта + void fetchMoreAttr(const QModelIndex &parent); + + //! Получение атрибутов + AttrMap attrMap(const QModelIndex &parent); +private: + + + + //! Установка списка полей данных + void setFields(const QStringList& dataFields , bool isProject); + + //! Установка списка полей данных + void setLinkType(const QStringList& linkType); + + //! Данные узла дерева + TreeItem* m_root; + MidasData* dataSet; + + //! Список полей данных + QStringList m_fieldNames; + + //! Список полей данных + QStringList m_prjFieldNames; + + //! Список связей + QString m_linkType; + + //! Значение атрибутов [id_obj,id_attr,список свойств атрибута] + QMap m_attrVal; + + TypeLoodsmanModel* m_typeModel; + LinkLoodsmanModel* m_linkModel; + StatLoodsmanModel* m_statModel; + AttrLoodsmanModel* m_attrModel; + + mutable QMap* > m_data; + +signals: + +public slots: + +}; + +#endif // TREELOODSMANMODEL_H diff --git a/treenode.h b/treenode.h new file mode 100644 index 0000000..83126da --- /dev/null +++ b/treenode.h @@ -0,0 +1,11 @@ +#ifndef TREENODE_H +#define TREENODE_H +struct TreeNode +{ + long id; + long parent; + QList children; + QList data; + bool isFetch; +}; +#endif // TREENODE_H diff --git a/treepropview.cpp b/treepropview.cpp new file mode 100644 index 0000000..65c4efb --- /dev/null +++ b/treepropview.cpp @@ -0,0 +1,129 @@ +#include "treepropview.h" +#include +#include +#include +#include +#include +#include + +TreePropView::TreePropView(QWidget *parent) : + QTreeView(parent) +{ + m_colors.reserve(6); + m_colors.push_back(QColor(255, 230, 191)); + m_colors.push_back(QColor(255, 255, 191)); + m_colors.push_back(QColor(191, 255, 191)); + m_colors.push_back(QColor(199, 255, 255)); + m_colors.push_back(QColor(234, 191, 255)); + m_colors.push_back(QColor(255, 191, 239)); + + QPixmap pix(14, 14); + pix.fill(Qt::transparent); + QStyleOption branchOption; + QRect r(QPoint(0, 0), pix.size()); + branchOption.rect = QRect(2, 2, 9, 9); + branchOption.palette = this->palette(); + branchOption.state = QStyle::State_Children; + QPainter p; + // Закрытое состояние + p.begin(&pix); + style()->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p); + p.end(); + QIcon rc = pix; + rc.addPixmap(pix, QIcon::Selected, QIcon::Off); + m_iconClosed = QIcon(pix); + // Открытое состояние + branchOption.state |= QStyle::State_Open; + pix.fill(Qt::transparent); + p.begin(&pix); + style()->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, &p); + p.end(); + m_iconOpen = QIcon(pix); + + setRootIsDecorated(false); + setAlternatingRowColors(true); +} + +void TreePropView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItemV3 opt = option; + + if (!index.parent().isValid()) { + const QColor c = option.palette.color(QPalette::Dark); + painter->fillRect(option.rect, c); + opt.font.setBold(true); + } else { + const QColor c = calcBgColor(index); + if (c.isValid()) { + painter->fillRect(option.rect, c); + opt.palette.setColor(QPalette::AlternateBase, c.lighter(112)); + } + } + QTreeView::drawRow(painter, opt, index); + QColor color = static_cast(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt)); + painter->save(); + painter->setPen(QPen(color)); + painter->drawLine(opt.rect.x(), opt.rect.bottom(), opt.rect.right(), opt.rect.bottom()); + painter->restore(); +} + +void TreePropView::mousePressEvent(QMouseEvent *event) +{ + QModelIndex index = indexAt(event->pos()); + if (index.isValid()&& (event->button() == Qt::LeftButton)) { + if (index.parent().isValid()) { + if (!index.column()==0) + edit(index); + } else if (!rootIsDecorated()) { + setExpanded(index,!isExpanded(index)); + if (isExpanded(index)) + model()->setData(index,m_iconOpen,Qt::DecorationRole); + else + model()->setData(index,m_iconClosed,Qt::DecorationRole); + } + setCurrentIndex(index); + return; + } + if (index.column()==0) + return; + + QTreeView::mousePressEvent(event); +} + +void TreePropView::setModel(QAbstractItemModel *model) +{ + connect(model,SIGNAL(dataChanged(QModelIndex,QModelIndex)),this,SLOT(updateHeaderRow(QModelIndex,QModelIndex))); + QTreeView::setModel(model); + this->expandAll(); + for (int i=0;irowCount();i++){ + this->setFirstColumnSpanned(i,QModelIndex(),true); + QModelIndex index = model->index(i,0); + if (isExpanded(index)) + model->setData(index,m_iconOpen,Qt::DecorationRole); + else + model->setData(index,m_iconClosed,Qt::DecorationRole); + } +} + +void TreePropView::updateHeaderRow(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + Q_UNUSED(bottomRight) + + if (!this->rootIsDecorated() && !topLeft.parent().isValid()) + setFirstColumnSpanned(topLeft.row(),QModelIndex(),true); +} + +QColor TreePropView::calcBgColor(const QModelIndex &index) const +{ + QModelIndex i = index; + while (i.parent().isValid()) + i = i.parent(); + + long rowColor; + if (i.row() +#include + +class TreePropView : public QTreeView +{ + Q_OBJECT +public: + explicit TreePropView(QWidget *parent = 0); + void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; + void mousePressEvent(QMouseEvent *event); + void setModel(QAbstractItemModel *model); + +signals: + +public slots: + void updateHeaderRow(const QModelIndex &topLeft, const QModelIndex &bottomRight); + +private: + QColor calcBgColor(const QModelIndex &index) const; + + QIcon m_iconClosed; + QIcon m_iconOpen; + QVector m_colors; +}; + +#endif // TREEVIEWPROP_H diff --git a/typeloodsmanmodel.cpp b/typeloodsmanmodel.cpp new file mode 100644 index 0000000..ddabb4b --- /dev/null +++ b/typeloodsmanmodel.cpp @@ -0,0 +1,336 @@ +#include "typeloodsmanmodel.h" +#include "loodsmansystem.h" +#include "converttype.h" +#include +#include +#include + +TypeLoodsmanModel::TypeLoodsmanModel(TreeItem *parent) : + QAbstractItemModel(parent) +{ + dataSet = new MidasData(); + m_root = new TreeNodeType; + m_root->id = 0; + m_root->isFetch = false; + cache.insert(0,m_root); + m_fieldIcon = -1; + + QStringList fields; + fields << "_ID_TYPE" << "_TYPENAME" << "_IS_ABSTRACT" + << "_DOCUMENT" << "_ID_PARENT_TYPE"; + setFields(fields); + setFieldIcon("_ICON"); +} + +TypeLoodsmanModel::~TypeLoodsmanModel() +{ + delete dataSet; +} + +int TypeLoodsmanModel::columnCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return m_fieldNames.count(); +} + +TreeNodeType *TypeLoodsmanModel::getItem(const QModelIndex & index) const +{ + if (index.isValid()) + return static_cast(index.internalPointer()); + else + return m_root; +} + +QVariant TypeLoodsmanModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + if (role == Qt::DecorationRole && index.column()==0 && !m_fieldIcon.isEmpty()){ + QPixmap pixmap; + const TreeNodeType *item = getItem(index); + if (item) { + pixmap.loadFromData(item->data.at(m_fieldNames.count()).toByteArray()); + return QIcon(pixmap); + } + } + + if(role == Qt::DisplayRole){ + const TreeNodeType *item = getItem(index); + if (item) + return item->data.at(index.column()); + } + return QVariant(); +} + +QVariant TypeLoodsmanModel::data(long id, int column) const +{ + if(cache.contains(id)){ + TreeNodeType *item = cache[id]; + if (item) + return item->data.at(column); + } + return QVariant(); +} + +bool TypeLoodsmanModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(index); + if (role != Qt::EditRole) + return false; + return 0; +} + +Qt::ItemFlags TypeLoodsmanModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + Qt::ItemFlags fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + /*if ( d->isEditable( index.internalId(), index.column() ) ) + fl |= Qt::ItemIsEditable;*/ + return fl; +} + +QVariant TypeLoodsmanModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole) { + return m_fieldNames.at(section); + } + return QVariant(); +} + +bool TypeLoodsmanModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(section); + + if (role != Qt::EditRole || orientation != Qt::Horizontal) + return false; + + return false; +} + +QModelIndex TypeLoodsmanModel::index(int row, int column, const QModelIndex &parent) const +{ + if(!hasIndex(row, column, parent)) + return QModelIndex(); + + const TreeNodeType* parentItem = getItem(parent); + + if (!parentItem) + return QModelIndex(); + + TreeNodeType* childItem = cache[parentItem->children.at(row)]; + + if (childItem) + return createIndex(row, column, (void*)childItem); + else + return QModelIndex(); +} + +QModelIndex TypeLoodsmanModel::parent(const QModelIndex &index) const +{ + if(!index.isValid()) + return QModelIndex(); + + const TreeNodeType *childItem = getItem(index); + TreeNodeType *parentItem = cache[childItem->parent]; + + if (!parentItem || parentItem == m_root) + return QModelIndex(); + + TreeNodeType *grandparent = cache[parentItem->parent]; + if (!grandparent) + return QModelIndex(); + + for (int i = 0; i < grandparent->children.count(); i++) + if (grandparent->children.at(i) == parentItem->id) + return createIndex(i, 0, (void*) parentItem); + + return QModelIndex(); +} + +int TypeLoodsmanModel::rowCount(const QModelIndex &parent) const +{ + if(parent.column() > 0) + return 0; + + return getItem(parent)->children.count(); +} + +bool TypeLoodsmanModel::hasChildren(const QModelIndex & parent) const +{ + TreeNodeType* node = getItem(parent); + if (node->isFetch && node->children.count()==0) + return false; + + return true; +} + +bool TypeLoodsmanModel::canFetchMore(const QModelIndex &parent) const +{ + return !getItem(parent)->isFetch; +} + +void TypeLoodsmanModel::fetchMore(const QModelIndex &parent) +{ + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + VARIANT inErrorCode; + VARIANT stErrorMessage; + + TreeNodeType *item; + + if(parent.isValid()){ + item = getItem(parent); + if(!item) + return; + } + + _variant_t data = loodsman->main->GetInfoAboutCurrentBase(61,&inErrorCode, &stErrorMessage); + dataSet->setData((unsigned char *)data.parray->pvData); + + if (inErrorCode.lVal!=0) + QMessageBox::warning(NULL, tr("Ошибка соединения"), from_bstr_t(stErrorMessage.bstrVal)); + + if (dataSet->first()){ + do { + int childId = dataSet->fieldValue("_ID_TYPE").toInt(); + long parentId = dataSet->fieldValue("_ID_PARENT_TYPE").toInt(); + + TreeNodeType *item = cache[parentId]; + if (item==NULL){ + if (parentId == 0) + item = m_root; + else { + item = new TreeNodeType; + item->id = parentId; + cache.insert(parentId, item); + item->isFetch = true; + } + } + + TreeNodeType* childItem; + if (!cache.contains(childId)){ + childItem = new TreeNodeType; + childItem->id = childId; + childItem->isFetch = true; + cache.insert(childId, childItem); + item->children.append(childId); + } else { + childItem = cache[childId]; + childItem->data.clear(); + } + childItem->parent = parentId; + + for ( int j=0; j < m_fieldNames.count(); j++ ) + childItem->data.append(dataSet->fieldValue(m_fieldNames[j])); + + if (!m_fieldIcon.isEmpty()) + childItem->data.append(dataSet->fieldValue(m_fieldIcon)); + } while (dataSet->next()); + dataSet->clear(); + + m_root->isFetch = true; + beginInsertRows(QModelIndex(), 0,cache[0]->children.count()); + endInsertRows(); + } +} + +QList TypeLoodsmanModel::listAttr(long typeId){ + + if (m_attr.contains(typeId)) + return m_attr.value(typeId); + + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + VARIANT inErrorCode; + VARIANT stErrorMessage; + QString objType = data(typeId,fieldIndex("_TYPENAME")).toString(); + + _variant_t testData = loodsman->main->GetInfoAboutType(to_bstr_t(objType), + 1, + &inErrorCode, + &stErrorMessage); + + if (inErrorCode.lVal!=0) + QMessageBox::warning(NULL, tr("Ошибка соединения"), from_bstr_t(stErrorMessage.bstrVal)); + + unsigned char *p = (unsigned char *)testData.parray->pvData; + MidasData* mData = new MidasData(); + mData->setData(p); + QList attrMap; + if (mData->first()) do + attrMap.append(mData->fieldValue("_ID").toInt()); + while (mData->next()); + + m_attr[typeId] = attrMap; + + return attrMap; +} + +QList TypeLoodsmanModel::listAttrLink(long masterTypeId, long slaveTypeId, QString linkName) +{ + AttrLinkKey key; + key.id = masterTypeId; + key.pid = slaveTypeId; + key.lid = linkName; + + if (m_attrLink.contains(key)) + return m_attrLink.value(key); + + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + VARIANT inErrorCode; + VARIANT stErrorMessage; + QString objType = data(masterTypeId,fieldIndex("_TYPENAME")).toString(); + QString parentObjType = data(slaveTypeId,fieldIndex("_TYPENAME")).toString();; + QString objLink = linkName; + + _variant_t testData = loodsman->main->GetLinkAttrForTypes(to_bstr_t(parentObjType), + to_bstr_t(objType), + to_bstr_t(objLink), + &inErrorCode, + &stErrorMessage); + + unsigned char *p = (unsigned char *)testData.parray->pvData; + MidasData* mData = new MidasData(); + mData->setData(p); + + QList attrMap; + if (mData->first()) do + attrMap.append(mData->fieldValue("_ID").toInt()); + while (mData->next()); + + + m_attrLink[key] = attrMap; + + return attrMap; +} + +QStringList TypeLoodsmanModel::fields() +{ + return m_fieldNames; +} + +void TypeLoodsmanModel::setFields(const QStringList &dataFields) +{ + m_fieldNames = dataFields; +} + +void TypeLoodsmanModel::setFieldIcon(QString column) +{ + m_fieldIcon = column; +} + +int TypeLoodsmanModel::fieldIndex(const QString &fieldName) const +{ + for (int i = 0;i +#include "attrlinkkey.h" +#include "treeitem.h" +#include "midasdata.h" +#include "treenode.h" + +struct TreeNodeType:public TreeNode +{ + +}; + +class TypeLoodsmanModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit TypeLoodsmanModel(TreeItem *parent = 0); + ~TypeLoodsmanModel(); + + //! Возращает хранимые данные + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant data(long id, int column) const; + + //! Устанавливает значение для указанной записи + bool setData(const QModelIndex &index, const QVariant &value, int role); + + //! Возвращает флаг записи + Qt::ItemFlags flags(const QModelIndex &index) const; + + //! Возращает название заголовка + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + //! Устанавливает название заголовка + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role); + + //! Возращает индекс модели для строки и колонки + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + + //! Возращает индекс родителя + QModelIndex parent(const QModelIndex &index) const ; + + //! Возращает количество строк в индексе родителя + int rowCount(const QModelIndex &parent = QModelIndex()) const; + + //! Возращает количество столбцов в индексе родителя + int columnCount(const QModelIndex &parent = QModelIndex()) const; +/* + //! Удаление строки + bool removeRows(int position, int rows, const QModelIndex &parent); + + //! Вставка строки + bool insertRows(int position, int rows, const QModelIndex &parent); +*/ + //! Проверка имеются ли дети + bool hasChildren(const QModelIndex & parent) const ; + + //! Получение TreeItem по индексу + TreeNodeType *getItem(const QModelIndex &index) const; + + //! Проверка можно ли провести ленивыю инициализацию + bool canFetchMore(const QModelIndex &parent) const; + + //! Ленивая инициализация + void fetchMore(const QModelIndex &parent); + + //! Получение списка атрибутов + QList listAttr(long typeId); + QList listAttrLink(long masterTypeId, long slaveTypeId, QString linkName); + + //! Получение списка полей с данных + QStringList fields() ; + + //! Возращает индекс поля или если не найдено поле -1 + int fieldIndex( const QString & fieldName ) const; + +private: + + //! Установка списка полей данных + void setFields(const QStringList& dataFields ); + + //! Установить поле с иконкой + void setFieldIcon(QString column); + + + TreeNodeType* m_root; + MidasData* dataSet; + + //! Список полей данных + QStringList m_fieldNames; + + //! Поле с Иконкой + QString m_fieldIcon; + + mutable QHash cache; + QMap > m_attr; + QMap > m_attrLink; + +signals: + +public slots: + +}; + +#endif // TYPELOODSMANMODEL_H diff --git a/unitsloodsmanmodel.cpp b/unitsloodsmanmodel.cpp new file mode 100644 index 0000000..562624e --- /dev/null +++ b/unitsloodsmanmodel.cpp @@ -0,0 +1,247 @@ +#include "unitsloodsmanmodel.h" +#include "loodsmansystem.h" +#include "converttype.h" +#include +#include +#include + +UnitsLoodsmanModel::UnitsLoodsmanModel(QObject *parent) : + QAbstractItemModel(parent) +{ + dataSet = new MidasData(); + m_root = new TreeNode; + m_root->id = 0; + m_root->isFetch = false; + cache.insert(0,m_root); +} + +UnitsLoodsmanModel::~UnitsLoodsmanModel() +{ + delete dataSet; +} + +int UnitsLoodsmanModel::columnCount(const QModelIndex& parent) const +{ + Q_UNUSED(parent); + return m_fieldNames.count(); +} + +TreeNode *UnitsLoodsmanModel::getItem(const QModelIndex & index) const +{ + if (index.isValid()) + return static_cast(index.internalPointer()); + else + return m_root; +} + +QVariant UnitsLoodsmanModel::data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + if (role == Qt::DecorationRole && index.column()==0 && !m_fieldIcon.isEmpty()){ + QPixmap pixmap; + const TreeNode *item = getItem(index); + if (item) { + pixmap.loadFromData(item->data.at(m_fieldNames.count()).toByteArray()); + return QIcon(pixmap); + } + } + + if(role == Qt::DisplayRole){ + const TreeNode *item = getItem(index); + if (item) + return item->data.at(index.column()); + } + return QVariant(); +} + +bool UnitsLoodsmanModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(index); + if (role != Qt::EditRole) + return false; + return 0; +} + +Qt::ItemFlags UnitsLoodsmanModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + Qt::ItemFlags fl = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + /*if ( d->isEditable( index.internalId(), index.column() ) ) + fl |= Qt::ItemIsEditable;*/ + return fl; +} + +QVariant UnitsLoodsmanModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if ( orientation == Qt::Horizontal && role == Qt::DisplayRole) { + return m_fieldNames.at(section); + } + return QVariant(); +} + +bool UnitsLoodsmanModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) +{ + Q_UNUSED(value); + Q_UNUSED(section); + + if (role != Qt::EditRole || orientation != Qt::Horizontal) + return false; + + return false; +} + +QModelIndex UnitsLoodsmanModel::index(int row, int column, const QModelIndex &parent) const +{ + if(!hasIndex(row, column, parent)) + return QModelIndex(); + + const TreeNode* parentItem = getItem(parent); + + if (!parentItem) + return QModelIndex(); + + TreeNode* childItem = cache[parentItem->children.at(row)]; + + if (childItem) + return createIndex(row, column, (void*)childItem); + else + return QModelIndex(); +} + +QModelIndex UnitsLoodsmanModel::parent(const QModelIndex &index) const +{ + if(!index.isValid()) + return QModelIndex(); + + const TreeNode *childItem = getItem(index); + TreeNode *parentItem = cache[childItem->parent]; + + if (!parentItem || parentItem == m_root) + return QModelIndex(); + + TreeNode *grandparent = cache[parentItem->parent]; + if (!grandparent) + return QModelIndex(); + + for (int i = 0; i < grandparent->children.count(); i++) + if (grandparent->children.at(i) == parentItem->id) + return createIndex(i, 0, (void*) parentItem); + + return QModelIndex(); +} + +int UnitsLoodsmanModel::rowCount(const QModelIndex &parent) const +{ + if(parent.column() > 0) + return 0; + + return getItem(parent)->children.count(); +} + +bool UnitsLoodsmanModel::hasChildren(const QModelIndex & parent) const +{ + TreeNode* node = getItem(parent); + if (node->isFetch && node->children.count()==0) + return false; + + return true; +} + +bool UnitsLoodsmanModel::canFetchMore(const QModelIndex &parent) const +{ + return !getItem(parent)->isFetch; +} + +void UnitsLoodsmanModel::fetchMore(const QModelIndex &parent) +{ + LoodsmanSystem* loodsman = LoodsmanSystem::instance(); + VARIANT inErrorCode; + VARIANT stErrorMessage; + + TreeNode *item; + + if(parent.isValid()){ + item = getItem(parent); + if(!item) + return; + } + + _variant_t data = loodsman->main->GetInfoAboutCurrentBase(9,&inErrorCode, &stErrorMessage); + dataSet->setData((unsigned char *)data.parray->pvData); + + if (inErrorCode.lVal!=0) + QMessageBox::warning(NULL, tr("Ошибка соединения"), from_bstr_t(stErrorMessage.bstrVal)); + + + if (dataSet->first()){ + do { + int childId = dataSet->fieldValue("_ID").toInt(); + long parentId = 0/*dataSet->fieldValue("_ID_PARENT_TYPE").toInt()*/; + + TreeNode *item = /*cache[parentId]*/m_root; + if (item==NULL){ + if (parentId == 0) + item = m_root; + else { + item = new TreeNode; + item->id = parentId; + cache.insert(parentId, item); + item->isFetch = true; + } + } + + TreeNode* childItem; + if (!cache.contains(childId)){ + childItem = new TreeNode; + childItem->id = childId; + childItem->isFetch = true; + cache.insert(childId, childItem); + item->children.append(childId); + } else { + childItem = cache[childId]; + childItem->data.clear(); + } + + childItem->parent = parentId; + + for ( int j=0; j < m_fieldNames.count(); j++ ) + childItem->data.append(dataSet->fieldValue(m_fieldNames[j])); + if (!m_fieldIcon.isEmpty()) + childItem->data.append(dataSet->fieldValue(m_fieldIcon)); + + } while (dataSet->next()); + dataSet->clear(); + + m_root->isFetch = true; + beginInsertRows(QModelIndex(), 0,cache[0]->children.count()); + endInsertRows(); + } +} + +QStringList UnitsLoodsmanModel::fields() +{ + return m_fieldNames; +} + +void UnitsLoodsmanModel::setFields(const QStringList &dataFields) +{ + m_fieldNames = dataFields; +} + +void UnitsLoodsmanModel::setFieldIcon(QString column) +{ + m_fieldIcon = column; +} + +int UnitsLoodsmanModel::fieldIndex(const QString &fieldName) const +{ + for (int i = 0;i +#include +#include +#include + +#include "loodsmansystem.h" +#include "midasdata.h" +#include "treenode.h" + +class UnitsLoodsmanModel : public QAbstractItemModel +{ + Q_OBJECT +public: + explicit UnitsLoodsmanModel(QObject *parent = 0); + ~UnitsLoodsmanModel(); + + //! Возращает хранимые данные + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + //! Устанавливает значение для указанной записи + bool setData(const QModelIndex &index, const QVariant &value, int role); + + //! Возвращает флаг записи + Qt::ItemFlags flags(const QModelIndex &index) const; + + //! Возращает название заголовка + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + //! Устанавливает название заголовка + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role); + + //! Возращает индекс модели для строки и колонки + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + + //! Возращает индекс родителя + QModelIndex parent(const QModelIndex &index) const ; + + //! Возращает количество строк в индексе родителя + int rowCount(const QModelIndex &parent = QModelIndex()) const; + + //! Возращает количество столбцов в индексе родителя + int columnCount(const QModelIndex &parent = QModelIndex()) const; +/* + //! Удаление строки + bool removeRows(int position, int rows, const QModelIndex &parent); + + //! Вставка строки + bool insertRows(int position, int rows, const QModelIndex &parent); +*/ + //! Проверка имеются ли дети + bool hasChildren(const QModelIndex & parent) const ; + + //! Получение TreeItem по индексу + TreeNode *getItem(const QModelIndex &index) const; + + //! Проверка можно ли провести ленивыю инициализацию + bool canFetchMore(const QModelIndex &parent) const; + + //! Ленивая инициализация + void fetchMore(const QModelIndex &parent); + + //! Получение списка полей с данных + QStringList fields() ; + + //! Установка списка полей данных + void setFields(const QStringList& dataFields ); + + void setFieldIcon(QString column); + + int fieldIndex(const QString &fieldName) const; +private: + TreeNode* m_root; + MidasData* dataSet; + + //! Список полей данных + QStringList m_fieldNames; + + //! Поле с Иконкой + QString m_fieldIcon; + + mutable QHash cache; + +signals: + +public slots: + +}; + +#endif // UNITSLOODSMANMODEL_H diff --git a/verticallite.pro b/verticallite.pro new file mode 100644 index 0000000..d38f835 --- /dev/null +++ b/verticallite.pro @@ -0,0 +1,59 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2012-06-01T11:05:15 +# +#------------------------------------------------- + +QT += core gui + + +TARGET = verticallite +TEMPLATE = app + +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets +} + +SOURCES += main.cpp\ + mainwindow.cpp \ + dialogconnect.cpp \ + loodsmansystem.cpp \ + treeloodsmanmodel.cpp \ + treeitem.cpp \ + converttype.cpp \ + application.cpp \ + midasdata.cpp \ + typeloodsmanmodel.cpp \ + linkloodsmanmodel.cpp \ + statloodsmanmodel.cpp \ + attrloodsmanmodel.cpp \ + attreditloodsmanmodel.cpp \ + attrlinkkey.cpp \ + propeditordelegate.cpp \ + treepropview.cpp \ + unitsloodsmanmodel.cpp + +HEADERS += mainwindow.h \ + dialogconnect.h \ + converttype.h \ + loodsmansystem.h \ + treeloodsmanmodel.h \ + treeitem.h \ + application.h \ + midasdata.h \ + typeloodsmanmodel.h \ + linkloodsmanmodel.h \ + statloodsmanmodel.h \ + treenode.h \ + attrloodsmanmodel.h \ + attreditloodsmanmodel.h \ + attrlinkkey.h \ + propeditordelegate.h \ + treepropview.h \ + unitsloodsmanmodel.h + +FORMS += mainwindow.ui \ + dialogconnect.ui + +RESOURCES += +