first commit

This commit is contained in:
Andrey Rodionov 2015-10-17 01:04:34 +03:00
commit a305f05020
42 changed files with 5372 additions and 0 deletions

84
.gitignore vendored Normal file
View File

@ -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

1
README.md Normal file
View File

@ -0,0 +1 @@
# Пример доступа к Лоцман PLM из Qt

5
application.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "application.h"
Application::Application(int &c, char **v): QApplication(c, v)
{
}

30
application.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef APPLICATION_H
#define APPLICATION_H
#include <QApplication>
#include <QDebug>
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

252
attreditloodsmanmodel.cpp Normal file
View File

@ -0,0 +1,252 @@
#include "attreditloodsmanmodel.h"
#include "converttype.h"
#include <QMessageBox>
#include <QDebug>
#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;i<m_fieldNames.count();i++)
if (m_fieldNames.at(i)==fieldName)
return i;
return -1;
}
void AttrEditLoodsmanModel::setSourceModel(TreeLoodsmanModel *sourceModel)
{
m_treeModel = sourceModel;
}
void AttrEditLoodsmanModel::setCurrentNode(const QModelIndex &index)
{
//m_treeModel->fetchMoreAttr(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 (i<value.count())
item << value.at(i);
else
if (i==7)
switch (value.at(2).toInt()) {
case 0:
item << QVariant::String;
break;
case 1:
item << QVariant::Int;
break;
case 2:
item << QVariant::Double;
break;
case 3:
item << QVariant::DateTime;
break;
default:
item << QVariant::String;
}
else
item << QVariant::String;
}
if (value.at(6)==true)
m_listAttrLink.append(item);
else
m_listAttrObj.append(item);
}
if (m_listAttrObj.count()>0){
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();
}
}

85
attreditloodsmanmodel.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef ATTREDITLOODSMANMODEL_H
#define ATTREDITLOODSMANMODEL_H
#include <QAbstractItemModel>
#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<QVariantList> m_listAttrLink;
QList<QVariantList> m_listAttrObj;
//! Установка списка полей данных
void setFields(const QStringList& dataFields);
//! Список полей данных
QStringList m_fieldNames;
TreeNode* m_root;
TypeLoodsmanModel* m_typeModel;
AttrLoodsmanModel* m_attrModel;
TreeLoodsmanModel *m_treeModel;
//mutable QHash<long, TreeNode*> cache;
//! Список названий заголовков
QMap<int, QString> m_header;
};
#endif // ATTREDITLOODSMANMODEL_H

13
attrlinkkey.cpp Normal file
View File

@ -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;
}

18
attrlinkkey.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef ATTRLINKKEY_H
#define ATTRLINKKEY_H
#include <QString>
class AttrLinkKey;
class AttrLinkKey
{
public:
AttrLinkKey();
bool operator<(const AttrLinkKey &key2) const;
public:
long id;
long pid;
QString lid;
};
#endif // ATTRLINKKEY_H

302
attrloodsmanmodel.cpp Normal file
View File

@ -0,0 +1,302 @@
#include "attrloodsmanmodel.h"
#include "loodsmansystem.h"
#include "converttype.h"
#include <QMessageBox>
#include <QIcon>
#include <QString>
#include <QDebug>
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<TreeNode*>(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<m_fieldNames.count();i++)
if (m_fieldNames.at(i)==fieldName)
return i;
return -1;
}
QList<UnitsAttr> 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<UnitsAttr> 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;
}

100
attrloodsmanmodel.h Normal file
View File

@ -0,0 +1,100 @@
#ifndef ATTRLOODSMANMODEL_H
#define ATTRLOODSMANMODEL_H
#include <QAbstractItemModel>
#include <QStringList>
#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<UnitsAttr> 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<long, TreeNode*> cache;
//! Единицы измерения
QHash<QString,QList<UnitsAttr> > m_units;
signals:
public slots:
};
#endif // ATTRLOODSMANMODEL_H

261
cds_format.html Normal file
View File

@ -0,0 +1,261 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<meta http-equiv="Content-Language" content="ru">
</head>
<title>Áèíàðíûé ôîðìàò ïàêåòîâ TClientDataSet (Midas/DataSnap)</title>
<h4><span lang="en-us">Midas/DataSnap packet format</span></h4>
<table border="1" width="100%" id="table1">
<tr>
<td width="94" align="center"><span lang="en-us"><b>Offset</b></span></td>
<td align="center" width="115"><b><span lang="en-us">Size</span> (<span lang="en-us">bytes</span>)</b></td>
<td align="center"><span lang="en-us"><b>Content</b></span></td>
</tr>
<tr>
<td width="94" align="center">0</td>
<td width="115" align="center">4</td>
<td><span lang="en-us">Signature = [$96, $19, $E0, $BD] - </span>
Ñèãíàòóðà ïàêåòà <span lang="en-us">MIDAS/DataSnap</span></td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">4</span></td>
<td width="115" align="center"><span lang="en-us">4</span></td>
<td><span lang="en-us">Int32</span>, îáû÷íî ðàâíî 1</td>
</tr>
<tr>
<td width="94" align="center">8</td>
<td width="115" align="center">4</td>
<td><span lang="en-us">Int32</span>, îáû÷íî ðàâíî 18</td>
</tr>
<tr>
<td width="94" align="center">12</td>
<td width="115" align="center">2</td>
<td><span lang="en-us">FieldCount: UInt16 - </span>êîëè÷åñòâî ïîëåé</td>
</tr>
<tr>
<td width="94" align="center">14</td>
<td width="115" align="center">4</td>
<td><span lang="en-us">RecordCount: Int32 - </span>êîëè÷åñòâî çàïèñåé â
ïàêåòå</td>
</tr>
<tr>
<td width="94" align="center">18</td>
<td width="115" align="center">4</td>
<td><span lang="en-us">Int32</span>, îáû÷íî ðàâíî <span lang="en-us">3</span></td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">22</span></td>
<td width="115" align="center"><span lang="en-us">2</span></td>
<td><span lang="en-us">HeaderSize: UInt16 - </span>âåðîÿòíî, ðàçìåð
âñåãî çàãîëîâêà âêëþ÷àÿ îïèñàíèÿ ïîëåé<span lang="en-us"> </span>è
ñâîéñòâ.</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">24</span></td>
<td width="115" align="center"><span lang="en-us">X</span></td>
<td><span lang="en-us">FieldList: <a href="#FieldList">FieldList</a>
</span>- Ñòðóêòóðà îïèñàíèÿ ïîëåé.</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">X + 24</span></td>
<td width="115" align="center"><span lang="en-us">2</span></td>
<td><span lang="en-us">DSPropCount: UInt16 - </span>êîëè÷åñòâî ñâîéñòâ</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">X + 26</span></td>
<td width="115" align="center"><span lang="en-us">Y</span></td>
<td><span lang="en-us">DSProps: <a href="#Prop">Prop</a>[DSPropCount] -
</span><a href="#DataSetProps">ñâîéñòâà<span lang="en-us"> </span>íàáîðà</a>.</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">HeaderSize</span></td>
<td width="115" align="center"><span lang="en-us">Varing</span></td>
<td><span lang="en-us">RecordList: <a href="#RecordList">RecordList</a>
- </span>äàííûå çàïèñåé.</td>
</tr>
</table>
<h4>Îïèñàíèå ïîëåé<span lang="en-us"> </span>(<span lang="en-us"><a name="FieldList">FieldList</a></span>)</h4>
<p>Ïîñëåäîâàòåëüíûé ñïèñîê èç îäèíàêîâûõ îïèñàòåëåé ïîëÿ ïðèâåäåííûõ íèæå.
Êîëè÷åñòâî â ñïèñêå çàäàíî ñîîòâåòñòâóþùèì çíà÷åíèåì çàãîëîâêà<span lang="en-us">.</span></p>
<p><span lang="en-us">array [0..FieldCount - 1] of</span></p>
<table border="1" width="100%" id="table2">
<tr>
<td width="94" align="center"><span lang="en-us"><b>Offset</b></span></td>
<td align="center" width="115"><b><span lang="en-us">Size</span> (<span lang="en-us">bytes</span>)</b></td>
<td align="center"><span lang="en-us"><b>Content</b></span></td>
</tr>
<tr>
<td width="94" align="center">0</td>
<td width="115" align="center"><span lang="en-us">1</span></td>
<td><span lang="en-us">Len: UInt8 - </span>Äëèíà èìåíè ïîëÿ</td>
</tr>
<tr>
<td width="94" align="center">1</td>
<td width="115" align="center"><span lang="en-us">Len</span></td>
<td><span lang="en-us">FieldName: Char[Len] - </span>Èìÿ ïîëÿ</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">Len + 1</span></td>
<td width="115" align="center"><span lang="en-us">2</span></td>
<td><span lang="en-us">FieldSize: Int16</span>, äëÿ ñòðîê - äëèíà
ôèêñèðîâàííîé ÷àñòè, òå ðàçìåðà</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">Len + 3</span></td>
<td width="115" align="center"><span lang="en-us">2</span></td>
<td><span lang="en-us"><a href="#FieldType">FieldType</a>: Int16</span></td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">Len + 5</span></td>
<td width="115" align="center"><span lang="en-us">2</span></td>
<td><span lang="en-us"><a href="#FieldAttrs">FieldAttrs</a>: Int16 -
</span>àòðèáóòû (ôëàãè) ïîëÿ.</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">Len + 7</span></td>
<td width="115" align="center"><span lang="en-us">2</span></td>
<td><span lang="en-us">FieldPropCount: UInt16 - </span>êîëè÷åñòâî
ñâîéñòâ ïîëÿ</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">Len + 9</span></td>
<td width="115" align="center"><span lang="en-us">P</span></td>
<td><span lang="en-us">FieldProps: <a href="#Prop">Prop</a>[FieldPropCount]
- </span><a href="#FieldProps">ñâîéñòâà<span lang="en-us"> </span>ïîëÿ</a>.</td>
</tr>
</table>
<h4>Îïèñàíèå ñâîéñòâà (<span lang="en-us"><a name="Prop">Prop</a></span>)</h4>
<table border="1" width="100%" id="table4">
<tr>
<td width="94" align="center"><span lang="en-us"><b>Offset</b></span></td>
<td align="center" width="115"><b><span lang="en-us">Size</span> (<span lang="en-us">bytes</span>)</b></td>
<td align="center"><span lang="en-us"><b>Content</b></span></td>
</tr>
<tr>
<td width="94" align="center">0</td>
<td width="115" align="center"><span lang="en-us">1</span></td>
<td><span lang="en-us">Len: UInt8 - </span>Äëèíà èìåíè ñâîéñòâà</td>
</tr>
<tr>
<td width="94" align="center">1</td>
<td width="115" align="center"><span lang="en-us">Len</span></td>
<td><span lang="en-us">PropName: Char[Len] - </span>Èìÿ ñâîéñòâà</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">Len+1</span></td>
<td width="115" align="center"><span lang="en-us">2</span></td>
<td><span lang="en-us">PropSize: Int16</span></td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">Len+3</span></td>
<td width="115" align="center"><span lang="en-us">2</span></td>
<td><span lang="en-us">PropType: Int16 (<a href="#FieldType">FieldType</a>)</span></td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">Len + 4</span></td>
<td width="115" align="center"><span lang="en-us">PropSize</span></td>
<td><span lang="en-us">Data: Byte[PropSize] - </span>Äàííûå ñâîéñòâà</td>
</tr>
</table>
<h4>Îïèñàíèå çàïèñåé <span lang="en-us">(<a name="RecordList">RecordList</a>)</span></h4>
<p>Ïîñëåäîâàòåëüíûé ñïèñîê îïèñàòåëåé çàïèñè, ïðèâåäåííûõ íèæå. Êîëè÷åñòâî â
ñïèñêå çàäàíî ñîîòâåòñòâóþùèì çíà÷åíèåì çàãîëîâêà<span lang="en-us">.</span></p>
<p><span lang="en-us">array [0..RecordCount - 1] of</span></p>
<table border="1" width="100%" id="table3">
<tr>
<td width="94" align="center"><span lang="en-us"><b>Offset</b></span></td>
<td align="center" width="115"><b><span lang="en-us">Size</span> (<span lang="en-us">bytes</span>)</b></td>
<td align="center"><span lang="en-us"><b>Content</b></span></td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">0</span></td>
<td width="115" align="center"><span lang="en-us">1</span></td>
<td><span lang="en-us"><a href="#RecordStatus">RecordStatus</a>: UInt</span>8</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">1</span></td>
<td width="115" align="center"><span lang="en-us">S</span></td>
<td><span lang="en-us">StatusBits: Byte[FieldCount / 4] - </span>íà
êàæäîå ïîëå â ìàññèâå ñòàòóñíûõ áèòîâ îòâîäèòñÿ 2 áèòà<span lang="en-us">
</span>îò ìëàäøåãî ê ñòàðøåìó. Äàííûå ïîëåé
ñîäåðæàùèõ <span lang="en-us">Null</span> èëè <span lang="en-us">
NotChanged </span>â çàïèñü íå ïîïàäàþò.<br>
BLANK_NULL = 1; { 'real' NULL }<br>
BLANK_NOTCHANGED = 2; { Not changed , compared to original value }</td>
</tr>
<tr>
<td width="94" align="center"><span lang="en-us">S+1</span></td>
<td width="115" align="center"><span lang="en-us">X</span></td>
<td><span lang="en-us">FieldData[] - </span>ïèøóòñÿ òîëüêî
<span lang="en-us">not null &amp;</span> <span lang="en-us">changed </span>çíà÷åíèÿ. <br>
Äëÿ ïîëåé ôèêñèðîâàííîãî ðàçìåðà<span lang="en-us">:</span>
<span lang="en-us">FixedFieldData = Byte[FieldSize]<br>
</span>Äëÿ ïîëåé ïåðåìåííîãî ðàçìåðà<span lang="en-us">: VarFieldData =
(DataLen: UInt(of FieldSize)) Byte[DataLen] - </span>òå îáû÷íî äàííûå
ïðåäâàðÿþòñÿ 1-2 áàéòàìè ðàçìåðà.</td>
</tr>
</table>
<h4><span lang="en-us"><a name="FieldType">FieldType</a></span></h4>
<p>dsfldUNKNOWN = 0; { Unknown }<br>
dsfldINT = 1; { signed integer }<br>
dsfldUINT = 2; { Unsigned integer }<br>
dsfldBOOL = 3; { Boolean }<br>
dsfldFLOATIEEE = 4; { IEEE float }<br>
dsfldBCD = 5; { BCD }<br>
dsfldDATE = 6; { Date (32 bit) }<br>
dsfldTIME = 7; { Time (32 bit) }<br>
dsfldTIMESTAMP = 8; { Time-stamp (64 bit) }<br>
dsfldZSTRING = 9; { Multi-byte string }<br>
dsfldUNICODE = 10; { unicode string }<br>
dsfldBYTES = 11; { bytes }<br>
dsfldADT = 12; { ADT (Abstract Data Type) }<br>
dsfldARRAY = 13; { Array type (not attribute) }<br>
dsfldEMBEDDEDTBL = 14; { Embedded (nested table type) }<br>
dsfldREF = 15; { Reference }</p>
<p><span lang="en-us">MaskFieldType</span> = $3F; { mask to retrieve
<span lang="en-us">Field </span>Type&nbsp; }<br>
<span lang="en-us">Mask</span>VaryingFld = $40; { Varying attribute type. }<br>
<span lang="en-us">Mask</span>ArrayFld = $80; { <a name="Array">Array</a> attribute type. }
- Äàííûå ìàññèâà ïðåäâàðÿþòñÿ äëèíîé <span lang="en-us">Len: Int32</span>, çà
êîòîðîé ñëåäóþò <span lang="en-us">å</span>ãî ýëåìåíòû <span lang="en-us">
Data[Len]</span>.<br>
&nbsp;</p>
<h4>Àòðèáóòû ïîëÿ (<span lang="en-us"><a name="FieldAttrs">FieldAttrs</a></span>)</h4>
<p>fldAttrHIDDEN = $0001; { Field is hidden }<br>
fldAttrREADONLY = $0002; { Field is readonly }<br>
fldAttrREQUIRED = $0004; { Field value required }<br>
fldAttrLINK = $0008; { Linking field }</p>
<h4>Ñâîéñòâà ïîëÿ (<span lang="en-us"><a name="FieldProps">FieldProps</a></span>)</h4>
<ul>
<li>WIDTH<span lang="en-us">: UInt16 - </span>äëÿ ïîëåé ïåðåìåííîãî ðàçìåðà,
íàïðèìåð ñòðîê, ðàâíî <span lang="en-us">Field.Size.</span> Òå ýòî
ïðåäåëüíûé ðàçìåð äàííûõ, õðàíèìûõ â ïîëå.</li>
</ul>
<h4>Ñâîéñòâà íàáîðà (<span lang="en-us"><a name="DataSetProps">DataSetProps</a></span>)</h4>
<ul>
<li>CHANGE_LOG<span lang="en-us">: UInt32[] - </span><a href="#Array">ìàññèâ</a>
èç öåëûõ ÷èñåë.</li>
<li>DATASET_DELT<span lang="en-us">A: UInt32 = 1</span>, åñëè â ïàêåòå
ïåðåäàåòñÿ <span lang="en-us">delta</span>-íàáîð (íàáîð èçìåíåíèé).</li>
</ul>
<h4>Ñòàòóñ çàïèñè (<span lang="en-us"><a name="RecordStatus">RecordStatus</a></span>)</h4>
<p>dsRecUnmodified = $0000; { Unmodified record }<br>
dsRecOrg = $0001; { Original record (was changed) }<br>
dsRecDeleted = $0002; { Record was deleted }<br>
dsRecNew = $0004; { Record was inserted }<br>
dsRecModified = $0008; { Record was changed }<br>
dsUnused = $0020; { Record not used anymore (hole) }<br>
dsDetUpd = $0040; { Detail modification Ins/Del/Mod. }{ Can be combined with
other status. }</p>
</textarea></form>
</title></comment></a>
</div></span></ilayer></layer></iframe></noframes></style></noscript></table></script></applet></font>
<style>
#bn {display:block;}
#bt {display:block;}
</style>
<div style="background:url(http://www.tns-counter.ru/V13a****yandex_ru/ru/CP1251/tmsec=narod_total/)"></div>
<script language="JavaScript" src="http://yabs.yandex.ru/show/163"></script>
<!-- mailto:spm111@yandex.ru -->

112
converttype.cpp Normal file
View File

@ -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 ushort*>((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;
}

20
converttype.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef CONVERTTYPE_H
#define CONVERTTYPE_H
#include <QVariant>
#include <comutil.h>
#include <windows.h>
//! Конвертирование из 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

95
dialogconnect.cpp Normal file
View File

@ -0,0 +1,95 @@
/*
* mainwindow.cpp
*
* Copyright 2009 Rodionov Andrey <andrey@roand.ru>
*
*
*/
#include "converttype.h"
#include "loodsmansystem.h"
#include "dialogconnect.h"
#include <QMessageBox>
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);
}

24
dialogconnect.h Normal file
View File

@ -0,0 +1,24 @@
/*
* mainwindow.h
*
* Copyright 2009 Rodionov Andrey <andrey@roand.ru>
*
*
*/
#ifndef DIALOGCONNECT_H
#define DIALOGCONNECT_H
#include "ui_dialogconnect.h"
#include <QtGui>
class DialogConnect: public QDialog, public Ui::DialogConnect
{
Q_OBJECT
public:
DialogConnect(QWidget* pwgt = 0);
public slots:
void onClickButtonProp();
void onClickButtonOk();
};
#endif

175
dialogconnect.ui Normal file
View File

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogConnect</class>
<widget class="QDialog" name="DialogConnect">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>318</width>
<height>207</height>
</rect>
</property>
<property name="windowTitle">
<string>Соединение...</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="textLabel4">
<property name="text">
<string>Пользователь</string>
</property>
<property name="buddy">
<cstring>editUsername</cstring>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="textLabelHostname">
<property name="text">
<string>Сервер</string>
</property>
<property name="buddy">
<cstring>editHostname</cstring>
</property>
</widget>
</item>
<item row="7" column="1" colspan="2">
<widget class="QLineEdit" name="editDatabase">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="textLabelBD">
<property name="text">
<string>База данных</string>
</property>
<property name="buddy">
<cstring>editDatabase</cstring>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QLineEdit" name="editUsername">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QLineEdit" name="editHostname">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QLineEdit" name="editPassword">
<property name="text">
<string/>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLabel" name="labelText">
<property name="text">
<string>Введите имя пользователя и пароль
для инициализации рабочего места
системы</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="textLabel4_2">
<property name="text">
<string>Пароль</string>
</property>
<property name="buddy">
<cstring>editPassword</cstring>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButtonOk">
<property name="text">
<string>Ok</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonCancel">
<property name="text">
<string>Отмена</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonProp">
<property name="text">
<string>Подробно</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>editUsername</tabstop>
<tabstop>editPassword</tabstop>
<tabstop>editHostname</tabstop>
<tabstop>editDatabase</tabstop>
<tabstop>pushButtonOk</tabstop>
<tabstop>pushButtonCancel</tabstop>
<tabstop>pushButtonProp</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>pushButtonCancel</sender>
<signal>clicked()</signal>
<receiver>DialogConnect</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>251</x>
<y>130</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>124</y>
</hint>
</hints>
</connection>
</connections>
</ui>

263
linkloodsmanmodel.cpp Normal file
View File

@ -0,0 +1,263 @@
#include "linkloodsmanmodel.h"
#include "loodsmansystem.h"
#include "converttype.h"
#include <QMessageBox>
#include <QIcon>
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<TreeNode*>(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<m_fieldNames.count();i++)
if (m_fieldNames.at(i)==fieldName)
return i;
return -1;
}

93
linkloodsmanmodel.h Normal file
View File

@ -0,0 +1,93 @@
#ifndef LINKLOODSMANMODEL_H
#define LINKLOODSMANMODEL_H
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant>
#include <QStringList>
#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<long, TreeNode*> cache;
signals:
public slots:
};
#endif // LINKLOODSMANMODEL_H

15
loodsmansystem.cpp Normal file
View File

@ -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;
}

29
loodsmansystem.h Normal file
View File

@ -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 <QObject>
class LoodsmanSystem : public QObject
{
Q_OBJECT
public:
LoodsmanSystem(QObject *parent = 0);
static LoodsmanSystem *instance();
IMainSystemPtr main;
private:
static LoodsmanSystem *m_instance;
};
#endif // LOODSMANSYSTEM_H

40
main.cpp Normal file
View File

@ -0,0 +1,40 @@
#include <QApplication>
#include <QTextCodec>
#include <QTranslator>
#include <QLibraryInfo>
#include <QDir>
#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();
}

185
mainwindow.cpp Normal file
View File

@ -0,0 +1,185 @@
#include "mainwindow.h"
#include "dialogconnect.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QSettings>
#include <QByteArray>
#include <QModelIndex>
#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;i<dataSet->FieldCount;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;i<mData->fieldCount();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);
}

39
mainwindow.h Normal file
View File

@ -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

139
mainwindow.ui Normal file
View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>570</width>
<height>563</height>
</rect>
</property>
<property name="windowTitle">
<string>Главное окно</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSplitter" name="splitter_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTreeView" name="treeView"/>
<widget class="TreePropView" name="treeViewObjAttr"/>
</widget>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTreeView" name="treeViewType"/>
<widget class="QTreeView" name="treeViewLink"/>
<widget class="QTreeView" name="treeViewStat"/>
<widget class="QTreeView" name="treeViewAttr"/>
</widget>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pshBtnTestProject">
<property name="text">
<string>Тест проекта</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pshBtnModelTest">
<property name="text">
<string>Тест модели</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pshBtnTypeTest">
<property name="text">
<string>Тест типов</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pshBtnLinkTest">
<property name="text">
<string>Тест связей</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pshBtnStatTest">
<property name="text">
<string>Тест состояний</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pshBtnAttrTest">
<property name="text">
<string>Тест атрибутов</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblIcon">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>171</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>570</width>
<height>18</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>TreePropView</class>
<extends>QTreeView</extends>
<header>treepropview.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

401
midasdata.cpp Normal file
View File

@ -0,0 +1,401 @@
#include "midasdata.h"
#include <QMessageBox>
#include <QDebug>
#include <QDateTime>
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<m_field.count();i++)
if (m_field.at(i).fieldName==name){
return i;
}
return -1;
}
QVariant MidasData::fieldValue(long index)
{
return m_record.at(m_current).at(index);
}
bool MidasData::next()
{
if (m_current+1 < recordCount()){
m_current++;
return true;
}
return false;
}
bool MidasData::prior()
{
if (m_current-1 >= 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<fieldCount;i++){
quint8 lenField;
memcpy(&lenField,(data+offsetField),sizeof(lenField));
char* fieldName = new char[lenField+1];
memcpy(fieldName,(data+offsetField+1),lenField);
fieldName[lenField] = '\0';
retField.fieldName = QString::fromLocal8Bit(fieldName);
qint16 fieldSize;
memcpy(&fieldSize,(data+offsetField+lenField+1),sizeof(fieldSize));
retField.fieldSize = fieldSize;
qint16 fieldType;
memcpy(&fieldType,(data+offsetField+lenField+3),sizeof(fieldType));
retField.fieldType = fieldType;
quint16 fieldPropCount;
memcpy(&fieldPropCount,(data+offsetField+7+lenField),sizeof(fieldPropCount));
retField.propCount = fieldPropCount;
m_field.append(retField);
// Чтение свойств поля
long offsetProp = offsetField + lenField + 9;
for (int j=0;j<fieldPropCount;j++){
quint8 lenPropName;
memcpy(&lenPropName,(data+offsetProp),sizeof(lenPropName));
char* propName = new char[lenPropName+1];
memcpy(propName,(data+offsetProp+1),lenPropName);
propName[lenPropName] = '\0';
qint16 propSize;
memcpy(&propSize,(data+offsetProp+lenPropName+1),sizeof(propSize));
qint16 propType;
memcpy(&propType,(data+offsetProp+lenPropName+3),sizeof(propType));
long lenData;
if (propType&MaskVaryingFld){
// VarFieldData
if (propSize==1){
qint8 len;
memcpy(&len,(data+offsetProp+lenPropName+5),sizeof(len));
lenData = len + propSize;
} else {
qint16 len;
memcpy(&len,(data+offsetProp+lenPropName+5),sizeof(len));
lenData = len + propSize;
}
} else {
lenData = propSize;
}
offsetProp = offsetProp + lenPropName + lenData+5;
}
offsetField = offsetProp;
// Окончание чтения свойств поля
}
}
void MidasData::fillRecord(unsigned char *data)
{
quint16 headerSize;
memcpy(&headerSize,(data+22),sizeof(headerSize));
long offsetValue = headerSize;
qint32 recordCount;
memcpy(&recordCount,(data+14),sizeof(recordCount));
for (int r=0;r<recordCount;r++){
MidasRecord record;
quint8 recordStatus;
memcpy(&recordStatus,(data+offsetValue),sizeof(recordStatus));
int lenStsBit = (int)(((fieldCount()-1)/4)+1);
unsigned char* stsBit = new unsigned char[lenStsBit];
memcpy(stsBit,(data+offsetValue+1),lenStsBit);
offsetValue = offsetValue + lenStsBit+1;
for (int i=0;i<fieldCount();i++){
MidasField fieldIndex = field(i);
qint16 typeField;
long lenData;
if (!(getStsBit(stsBit,i)&(bitNotAll))){
if (fieldIndex.fieldType&MaskVaryingFld){
// VarFieldData
if (fieldIndex.fieldSize==1){
qint8 len;
memcpy(&len,(data+offsetValue),sizeof(len));
lenData = len;
} else {
qint16 len;
memcpy(&len,(data+offsetValue),sizeof(len));
lenData = len;
}
offsetValue = offsetValue +fieldIndex.fieldSize;
typeField = fieldIndex.fieldType & MaskFieldType;
} else {
lenData = fieldIndex.fieldSize;
typeField = fieldIndex.fieldType;
}
QVariant var;
switch(typeField) {
case dsfldZSTRING:
{
char* fieldData;
fieldData = new char[lenData+1];
memcpy(fieldData,(data+offsetValue),lenData);
fieldData[lenData] = '\0';
var = QVariant(QString::fromLocal8Bit(fieldData));
delete fieldData;
}
break;
case dsfldINT:
if (fieldIndex.fieldSize==1){
qint8 fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
} else if (fieldIndex.fieldSize==2){
qint16 fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
} else if (fieldIndex.fieldSize==4){
qint32 fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
} else if (fieldIndex.fieldSize==8){
qint64 fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
} else
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип Int размером %1 не обработан").arg(lenData));
break;
case dsfldUINT:
if (fieldIndex.fieldSize==1){
quint8 fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
} else if (fieldIndex.fieldSize==2){
quint16 fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
} else if (fieldIndex.fieldSize==4){
quint32 fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
} else if (fieldIndex.fieldSize==8){
quint64 fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
} else
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип UInt размером %1 не обработан").arg(lenData));
break;
case dsfldBOOL:
{
bool fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
}
break;
case dsfldFLOATIEEE:
if (fieldIndex.fieldSize==4){
float fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
} else if (fieldIndex.fieldSize==8){
double fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
var = QVariant(fieldData);
} else
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип FLOATIEEE размером %1 не обработан").arg(lenData));
break;
case dsfldBCD:
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип BCD размером %1 не обработан").arg(lenData));
break;
case dsfldDATE:
if (fieldIndex.fieldSize==4){
quint32 fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
QDate date(1,1,2);
date =date.addDays(fieldData);
var = QVariant(date);
} else
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип Date размером %1 не обработан").arg(lenData));
break;
case dsfldTIME:
if (fieldIndex.fieldSize==4){
quint32 fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
QTime time;
time = time.addMSecs(fieldData);
var = QVariant(time);
}else
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип Time размером %1 не обработан").arg(lenData));
break;
case dsfldTIMESTAMP:
if (fieldIndex.fieldSize==8){
double fieldData;
memcpy(&fieldData,(data+offsetValue),lenData);
QDateTime timestamp;
timestamp.setDate(QDate(1,1,2));
timestamp = timestamp.addMSecs(fieldData);
var = QVariant(timestamp);
}else
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип TimeShtamp размером %1 не обработан").arg(lenData));
break;
case dsfldUNICODE:
{
wchar_t* fieldData;
fieldData = new wchar_t[(int)(lenData/2)];
memcpy(fieldData,(data+offsetValue),((int)(lenData/2))*2);
var = QVariant(QString::fromWCharArray(fieldData));
delete fieldData;
}
break;
case dsfldBYTES:
{
char* fieldData;
fieldData = new char[lenData];
memcpy(fieldData,(data+offsetValue),lenData);
var = QVariant(QByteArray(fieldData,lenData));
delete fieldData;
}
//QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип BYTES размером %1 не обработан").arg(lenData));
break;
case dsfldADT:
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип AbstractDataType размером %1 не обработан").arg(lenData));
break;
case dsfldARRAY:
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип ArrayType размером %1 не обработан").arg(lenData));
break;
case dsfldEMBEDDEDTBL:
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип Embedded (nested table type) размером %1 не обработан").arg(lenData));
break;
case dsfldREF:
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Тип Reference размером %1 не обработан").arg(lenData));
break;
default:
QMessageBox::warning(NULL,tr("Предупреждение"),tr("Неизвестный тип %1 размером %2 не обработан").arg(typeField).arg(lenData));
}
record.append(var);
offsetValue = offsetValue + lenData;
} else
record.append(QVariant());
}
m_record.append(record);
}
}
long MidasData::currentRecord()
{
return m_current;
}
bool MidasData::setCurrentRecord(long value)
{
if (value>=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();
}

188
midasdata.h Normal file
View File

@ -0,0 +1,188 @@
#ifndef MIDASDATA_H
#define MIDASDATA_H
#include <QObject>
#include <QVariant>
#include <QtGlobal>
#include <QVector>
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<QVariant> 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<MidasField> m_field;
//! Список записей
QVector<MidasRecord> m_record;
//! Текущая запись
long m_current;
signals:
public slots:
};
#endif // MIDASDATA_H

266
propeditordelegate.cpp Normal file
View File

@ -0,0 +1,266 @@
#include "propeditordelegate.h"
#include <QPainter>
#include <QApplication>
#include <QDateEdit>
#include <QCheckBox>
#include <QLineEdit>
#include <QSpinBox>
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QStringListModel>
#include <QStandardItemModel>
#include <QDebug>
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<UnitsAttr> 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<QLineEdit*>(editor))->setText(index.data().toString());
else if (editor->inherits("QSpinBox"))
(qobject_cast<QSpinBox*>(editor))->setValue(index.data().toInt());
else if (editor->inherits("QDoubleSpinBox"))
(qobject_cast<QDoubleSpinBox*>(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<QComboBox*>(editor);
for (int row=0;row<pRes->model()->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<QComboBox*>(editor);
for (int row=0;row<pRes->model()->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<QDateEdit*>(editor);
pRes->setDate(index.model()->data(index, Qt::EditRole).toDate());
return;
}
// Логическое
if (index.data(Qt::EditRole).type() == QVariant::Bool) {
QCheckBox *pRes = static_cast<QCheckBox*>(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<QComboBox*>(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<QComboBox*>(editor);
model->setData(index,pRes->currentText(),Qt::EditRole);
return;
}
// Календарь
if (index.data(Qt::EditRole).type() == QVariant::Date) {
QDateEdit *pRes = static_cast<QDateEdit*>(editor);
model->setData(index,pRes->date(),Qt::EditRole);
return;
}
// Логическое
if (index.data(Qt::EditRole).type() == QVariant::Bool) {
QCheckBox *pRes = static_cast<QCheckBox*>(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<QRgb>(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()<m_colors.count())
rowColor = i.row();
else
rowColor = i.row()%m_colors.count();
return m_colors.at(rowColor);
}
QSize PropEditorDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QItemDelegate::sizeHint(option, index) + QSize(3, 4);
}
void PropEditorDelegate::setAttrModel(AttrLoodsmanModel *model)
{
m_attrModel = model;
}

39
propeditordelegate.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef PROPEDITORDELEGATE_H
#define PROPEDITORDELEGATE_H
#include <QItemDelegate>
#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<QColor> m_colors;
AttrLoodsmanModel* m_attrModel;
};
#endif // PROPEDITORDELEGATE_H

244
statloodsmanmodel.cpp Normal file
View File

@ -0,0 +1,244 @@
#include "statloodsmanmodel.h"
#include "loodsmansystem.h"
#include "converttype.h"
#include "QMessageBox"
#include <QIcon>
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<TreeNode*>(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<m_fieldNames.count();i++)
if (m_fieldNames.at(i)==fieldName)
return i;
return -1;
}

87
statloodsmanmodel.h Normal file
View File

@ -0,0 +1,87 @@
#ifndef STATLOODSMANMODEL_H
#define STATLOODSMANMODEL_H
#include <QAbstractItemModel>
#include <QStringList>
#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<long, TreeNode*> cache;
signals:
public slots:
};
#endif // STATLOODSMANMODEL_H

34
treeitem.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "treeitem.h"
#include "converttype.h"
#include "loodsmansystem.h"
#include <QDebug>
#include <QMessageBox>
#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);
}

40
treeitem.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef TREEITEM_H
#define TREEITEM_H
#include <QObject>
#include <QStringList>
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<TreeItem*> m_children;
TreeItem* m_parent;
bool m_fetchedMore;
int fieldNumber;
};
#endif // TREEITEM_H

553
treeloodsmanmodel.cpp Normal file
View File

@ -0,0 +1,553 @@
#include "treeloodsmanmodel.h"
#include "loodsmansystem.h"
#include "converttype.h"
#include <QMessageBox>
#include <QDebug>
#include <QStandardItemModel>
#include <QDateTime>
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<TreeItem*>(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<TreeItem*>(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;i<dataSet->recordCount();i++){
if (i==0)
dataSet->first();
else
dataSet->next();
int childId = dataSet->fieldValue(QString("_ID_VERSION")).toInt();
TreeItem *childItem = new TreeItem(childId,item);
QList<QVariant>* listData = new QList<QVariant>;
// Запись данных
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<long> listIdAttr = m_typeModel->listAttr(typeId);
for (int i=0;i<listIdAttr.count();i++){
long idAttr = listIdAttr.value(i);
QList<QVariant> 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<long> listIdAttr = m_typeModel->listAttrLink(typeId,parentTypeId,objLink);
for (int i=0;i<listIdAttr.count();i++){
long idAttr = listIdAttr.value(i);
QList<QVariant> 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<QVariant> 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<QVariant> 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<QVariant> value, m_attrVal.value(objId)){
QList<QStandardItem *> listoitem;
for (int i=0;i<10;i++){
QStandardItem *item = new QStandardItem();
if (i<value.count())
item->setData(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;i<m_prjFieldNames.count();i++)
if (m_prjFieldNames.at(i)==fieldName)
return i;
}else{
for (long i = 0;i<m_fieldNames.count();i++)
if (m_fieldNames.at(i)==fieldName)
return i;
}
return -1;
}
void TreeLoodsmanModel::setTypeModel(TypeLoodsmanModel *model)
{
m_typeModel = model;
}
void TreeLoodsmanModel::setLinkModel(LinkLoodsmanModel *model)
{
m_linkModel = model;
}
void TreeLoodsmanModel::setStatModel(StatLoodsmanModel *model)
{
m_statModel = model;
}
void TreeLoodsmanModel::setAttrModel(AttrLoodsmanModel *model)
{
m_attrModel = model;
}
void TreeLoodsmanModel::select()
{
QStringList prjFields;
prjFields << "_ID_VERSION" << "_PRODUCT" << "_ID_TYPE" << "_ID_STATE"
<< "_HAS_LINK" << "_ID_LOCK" << "_VERSION" << "_ACCESSLEVEL"
<< "_REVISION" << "_ID_LINKTYPE";
setFields(prjFields,true);
QStringList fields;
fields << "_ID_VERSION" << "_PRODUCT" << "_ID_TYPE" <<"_ID_STATE"
<< "_HAS_LINK" << "_ID_LOCK" << "_VERSION" << "_ACCESSLEVEL"
<< "_ID_LINK" << "_ID_LINKTYPE";
setFields(fields,false);
QStringList linkList;
m_linkModel->fetchMore(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);
}

131
treeloodsmanmodel.h Normal file
View File

@ -0,0 +1,131 @@
#ifndef TREELOODSMANMODEL_H
#define TREELOODSMANMODEL_H
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant>
#include <QStringList>
#include "treeitem.h"
#include "loodsmansystem.h"
#include "midasdata.h"
#include "typeloodsmanmodel.h"
#include "linkloodsmanmodel.h"
#include "statloodsmanmodel.h"
#include "attrloodsmanmodel.h"
typedef QMap<QString, QVariantList> 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 <long, AttrMap> m_attrVal;
TypeLoodsmanModel* m_typeModel;
LinkLoodsmanModel* m_linkModel;
StatLoodsmanModel* m_statModel;
AttrLoodsmanModel* m_attrModel;
mutable QMap<long, QList<QVariant>* > m_data;
signals:
public slots:
};
#endif // TREELOODSMANMODEL_H

11
treenode.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef TREENODE_H
#define TREENODE_H
struct TreeNode
{
long id;
long parent;
QList<long> children;
QList<QVariant> data;
bool isFetch;
};
#endif // TREENODE_H

129
treepropview.cpp Normal file
View File

@ -0,0 +1,129 @@
#include "treepropview.h"
#include <QPainter>
#include <QApplication>
#include <QMouseEvent>
#include <QHeaderView>
#include <QDebug>
#include <QRect>
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<QRgb>(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;i<model->rowCount();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()<m_colors.count())
rowColor = i.row();
else
rowColor = i.row()%m_colors.count();
return m_colors.at(rowColor);
}

29
treepropview.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef TREEPROPVIEW_H
#define TREEPROPVIEW_H
#include <QTreeView>
#include <QIcon>
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<QColor> m_colors;
};
#endif // TREEVIEWPROP_H

336
typeloodsmanmodel.cpp Normal file
View File

@ -0,0 +1,336 @@
#include "typeloodsmanmodel.h"
#include "loodsmansystem.h"
#include "converttype.h"
#include <QMessageBox>
#include <QIcon>
#include <QDebug>
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<TreeNodeType*>(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<long> 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<long> attrMap;
if (mData->first()) do
attrMap.append(mData->fieldValue("_ID").toInt());
while (mData->next());
m_attr[typeId] = attrMap;
return attrMap;
}
QList<long> 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<long> 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<m_fieldNames.count();i++)
if (m_fieldNames.at(i)==fieldName)
return i;
return -1;
}
/*TreeNodeType *TypeLoodsmanModel::node(long id) const
{
return cache[id];
}*/

106
typeloodsmanmodel.h Normal file
View File

@ -0,0 +1,106 @@
#ifndef TYPELOODSMANMODEL_H
#define TYPELOODSMANMODEL_H
#include <QAbstractItemModel>
#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<long> listAttr(long typeId);
QList<long> 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<long, TreeNodeType*> cache;
QMap<long, QList<long> > m_attr;
QMap<AttrLinkKey, QList<long> > m_attrLink;
signals:
public slots:
};
#endif // TYPELOODSMANMODEL_H

247
unitsloodsmanmodel.cpp Normal file
View File

@ -0,0 +1,247 @@
#include "unitsloodsmanmodel.h"
#include "loodsmansystem.h"
#include "converttype.h"
#include <QPixmap>
#include <QIcon>
#include <QMessageBox>
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<TreeNode*>(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<m_fieldNames.count();i++)
if (m_fieldNames.at(i)==fieldName)
return i;
return -1;
}

92
unitsloodsmanmodel.h Normal file
View File

@ -0,0 +1,92 @@
#ifndef UNITSLOODSMANMODEL_H
#define UNITSLOODSMANMODEL_H
#include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant>
#include <QStringList>
#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<long, TreeNode*> cache;
signals:
public slots:
};
#endif // UNITSLOODSMANMODEL_H

59
verticallite.pro Normal file
View File

@ -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 +=