#include "qcd_model.h" #include "cdutils_interface.h" #include "cdutils_core.h" #include "cdutils_x.h" #include "piqt.h" #include #include #include #include #include "qvariantedit.h" #include "qad_types.h" using namespace CDUtils; // CDKItem CDItem::CDItem(CDUtils::Interface * i, int _index, CDItem::CDItemType type, CDItem *parent) { interface = i; index_ = _index; parent_ = parent; type_ = type; item_count = 0; expanded = true; } CDItem::~CDItem() { qDeleteAll(childs); } QVariant CDItem::data(int column, int role) const { if (role == Qt::BackgroundRole) { switch (type_) { case ItemCDType: { CDType & t(interface->section(buildPath())[index_]); if (t.errorString().isEmpty()) return QBrush(QColor(255, 250, 230)); else return QBrush(QColor(255, 128, 128)); } case ItemCDSection: return QBrush(QColor(230, 250, 230)); } } if (role == Qt::CheckStateRole && type_ == ItemCDType) { CDType & t(interface->section(buildPath())[index_]); if (column == cValue && t.cd_type() == CDType::cdK) { if (t.type() == "b") return t.toBool() ? Qt::Checked : Qt::Unchecked; else QVariant(); } if (column == cName_Cmd && t.cd_type() == CDType::cdX) { return t.isSelectedX() ? Qt::Checked : Qt::Unchecked; } } if (role == Qt::ToolTipRole && type_ == ItemCDType) { CDType & t(interface->section(buildPath())[index_]); return PI2QString(t.errorString()); } if (role != Qt::DisplayRole && role != Qt::EditRole) return QVariant(); PIDeque path = buildPath(); CDSection & rs = interface->section(path); CDSection s; switch (type_) { case ItemCDType: switch (column) { case cID: return QString::number(index_); case cName_Cmd: return PI2QString(rs[index_].name()); case cType: return stringType(rs[index_].type()); case cXMode: return QVariant::fromValue(xModeEnum(rs[index_].xmode())); case cXAvg: return rs[index_].avg(); case cExpression: return PI2QString(rs[index_].formula()); case cValue: return value(rs[index_], role); case cComment: return PI2QString(rs[index_].comment()); default: break; } break; case ItemCDSection: s = rs.section(index_); // piCout << rs.name << rs.alias << s.name << s.alias; switch (column) { case cID: return QString("[") + QString::number(index_) + QString("]"); case cName_Cmd: return PI2QString(s.alias); case cType: return PI2QString(s.name); default: break; } break; } return QVariant(); } QVariant CDItem::value(CDType & t, int role) const { if (t.type() == "f") return t.toDouble(); if (t.type() == "n") return t.toInt(); if (t.type() == "b") return t.toBool(); if (t.type() == "e") { QAD::Enum et = PI2QADEnum(t.enumValues()); et.selectValue(t.toInt()); if (role == Qt::EditRole) return QVariant::fromValue(et); else return et.selectedName(); } return PI2QString(t.value()); } bool CDItem::setData(int column, const QVariant & value) { if (type_ == ItemCDType) { CDType & t(interface->section(buildPath())[index_]); if ((column == cExpression || column == cValue) && (t.cd_type() == CDType::cdK)) { interface->section(buildPath())[index_].setValue(Q2PIString(value.toString())); interface->calculate(); return true; } if (t.cd_type() == CDType::cdX) { switch (column) { case cName_Cmd: X.setEnabled(t, value.toBool()); return true; case cXMode: t.setXMode((CDType::XMode)value.toInt()); return true; case cXAvg: t.setAvg(piMax(value.toInt(), 1)); return true; default: break; } } } return false; } PIDeque CDItem::buildPath() const { PIDeque path; CDItem * p = parent_; while (p) { path.push_front(p->index_); p = p->parent_; } path.take_front(); return path; } QString CDItem::stringType(const PIString & t) const { QString n = PI2QString(t); if (n.isEmpty()) return QString(""); switch (n[0].toLatin1()) { case 'l': return QString("list"); break; case 'b': return QString("bool"); break; case 'n': return QString("int"); break; case 'f': return QString("double"); break; case 'c': return QString("color"); break; case 'r': return QString("rect"); break; case 'a': return QString("rect"); break; case 'p': return QString("point"); break; case 'v': return QString("vector"); break; case 'i': return QString("IP"); break; case 'e': return QString("enum"); break; case 'F': return QString("file"); break; case 'D': return QString("dir"); break; } return QString("string"); } QAD::Enum CDItem::xModeEnum(int v) const { QAD::Enum ret; ret << QAD::Enumerator(CDType::X_Current, "Current") << QAD::Enumerator(CDType::X_All_Avg, "All, Averaging"); ret.selectValue(v); return ret; } // CDKDelegate CDDelegate::CDDelegate(QObject *parent) : QStyledItemDelegate(parent) { } void CDDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { CDItem * item = ((CDItemModel*)index.model())->getItem(index); if (item) { if (item->itemType() == CDItem::ItemCDType && item->interface->cdType() == CDType::cdC) { QStyleOptionButton bo; bo.direction = option.direction; bo.fontMetrics = option.fontMetrics; bo.palette = option.palette; bo.rect = option.rect; bo.state = option.state;// & ~(QStyle::State_HasFocus | QStyle::State_MouseOver); bo.text = item->data(1, Qt::DisplayRole).toString(); QWidget * v = (QWidget*)(painter->device()); if (v) { QPoint cp = v->mapFromGlobal(QCursor::pos()); if (bo.rect.contains(cp, true)) { //bo.state |= QStyle::State_MouseOver; if (qApp->mouseButtons().testFlag(Qt::LeftButton)) bo.state |= QStyle::State_On; } } qApp->style()->drawControl(QStyle::CE_PushButton, &bo, painter); return; } } QStyledItemDelegate::paint(painter, option, index); } QWidget * CDDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { return new QVariantEdit(parent); } void CDDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QVariantEdit *edit = static_cast(editor); edit->setValue(index.model()->data(index, Qt::EditRole)); } void CDDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QVariantEdit *edit = static_cast(editor); QVariant v = edit->value(); if (v.canConvert()) { QAD::Enum et = v.value(); model->setData(index, et.selectedValue(), Qt::EditRole); } else model->setData(index, v, Qt::EditRole); } void CDDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { editor->setGeometry(option.rect); } QSize CDDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { QSize s = QStyledItemDelegate::sizeHint(option, index); s.setWidth(s.width() + 20); return s; } // CDItemModel CDItemModel::CDItemModel(int type_, QObject *parent) : QAbstractItemModel(parent) { interface = new Interface((CDType::cdT)type_); root = 0; internalRebuild(); } CDItemModel::~CDItemModel() { delete root; delete interface; } QVariant CDItemModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); CDItem * item = getItem(index); return item->data(index.column(), role); } QVariant CDItemModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { switch (section) { case cID: return tr("Index"); case cName_Cmd: return interface->cdType() == CDType::cdC ? tr("Command") : tr("Name"); case cType: return tr("Type"); case cXMode: return tr("Mode"); case cXAvg: return tr("Averaging"); case cExpression: return tr("Expression"); case cValue: return tr("Value"); case cComment: return tr("Comment"); } } return QVariant(); } QModelIndex CDItemModel::index(int row, int column, const QModelIndex &parent) const { if (parent.isValid() && parent.column() != cID) return QModelIndex(); CDItem * p = getItem(parent); CDItem * c = p->childs.value(row, 0); if (c) return createIndex(row, column, c); else return QModelIndex(); } QModelIndex CDItemModel::parent(const QModelIndex &index) const { if (!index.isValid()) return QModelIndex(); CDItem * c = getItem(index); CDItem * p = c->parent_; if (p == root) return QModelIndex(); return createIndex(p->parent_->childs.indexOf(p), cID, p); } int CDItemModel::rowCount(const QModelIndex &parent) const { CDItem * p = getItem(parent); return p->childs.count(); } int CDItemModel::columnCount(const QModelIndex &parent) const { return cLastColumn; } Qt::ItemFlags CDItemModel::flags(const QModelIndex & index) const { if (!index.isValid()) return Qt::ItemFlags(); Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable; CDItem * item = getItem(index); if (!item) return Qt::ItemFlags(); if (item->type_ == CDItem::ItemCDType) { CDType & t(interface->section(item->buildPath())[item->index_]); if (t.cd_type() == CDType::cdK) { if (index.column() == cExpression || index.column() == cValue) f |= Qt::ItemIsEditable; if (index.column() == cValue && t.type() == "b") f |= Qt::ItemIsUserCheckable; if (index.column() == cName_Cmd) f |= Qt::ItemIsDragEnabled; } if (t.cd_type() == CDType::cdX) { if (index.column() == cXMode || index.column() == cXAvg) f |= Qt::ItemIsEditable; if (index.column() == cName_Cmd) f |= Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled; } } return f; } bool CDItemModel::setData(const QModelIndex & index, const QVariant & value, int role) { if (role == Qt::CheckStateRole && (index.column() == cName_Cmd || index.column() == cValue)) { CDItem * item = getItem(index); if (item->type_ == CDItem::ItemCDType) { CDType & t(interface->section(item->buildPath())[item->index_]); if (index.column() == cValue && (t.cd_type() == CDType::cdK)) { if (t.type() == "b") { bool result = item->setData(index.column(), PI2QString(PIString::fromBool(value.toBool()))); QModelIndex rin(CDItemModel::index(index.row(), cExpression, index.parent())); emit dataChanged(rin, rin); return result; } } if (index.column() == cName_Cmd && (t.cd_type() == CDType::cdX)) { bool result = item->setData(index.column(), value); //QModelIndex rin(CDItemModel::index(index.row(), 1, index.parent())); //emit dataChanged(rin, rin); return result; } } } if (role != Qt::EditRole) return false; CDItem * item = getItem(index); bool result = item->setData(index.column(), value); if (result) { QModelIndex rin(CDItemModel::index(index.row(), cExpression, index.parent())); emit dataChanged(rin, rin); emit dataChanged(index, index); } return result; } QMimeData * CDItemModel::mimeData(const QModelIndexList & indexes) const { if (indexes.size() == 1) { QModelIndex index = indexes[0]; if (index.isValid()/* && interface->cdType() == CDType::cdX*/) { CDItem * item = getItem(index); if (item) { CDType & t(interface->section(item->buildPath())[item->index_]); QMimeData * mime = new QMimeData(); mime->setText(PI2QString(CDCore::instance()->typeLetter(interface->cdType()) + CDCore::pathToString(t.path()))); return mime; } } } return QAbstractItemModel::mimeData(indexes); } void CDItemModel::rebuildModel() { beginResetModel(); internalRebuild(); endResetModel(); } void CDItemModel::buildItem(CDItem * it, CDSection & r) { //piCout << "build item" << r.name << r.alias; auto i = r.cd.makeIterator(); while (i.next()) { it->childs << new CDItem(interface, i.key(), CDItem::ItemCDType, it); } it->item_count = it->childs.size(); auto j = r.s.makeIterator(); while (j.next()) { it->childs << new CDItem(interface, j.key(), CDItem::ItemCDSection, it); buildItem(it->childs.back(), j.value()); } } void CDItemModel::updateModel() { beginResetModel(); endResetModel(); } void CDItemModel::internalRebuild() { //qDebug() << "[CDKItemModel]" << "internalRebuild()"; if (root) delete root; root = new CDItem(interface, 0, CDItem::ItemCDSection, 0); CDSection & r = interface->root(); buildItem(root, r); } CDItem * CDItemModel::getItem(const QModelIndex &index) const { if (index.isValid()) { CDItem * item = static_cast(index.internalPointer()); if (item) return item; } return root; } QModelIndex CDItemModel::indexByPath(const PIDeque & path, int column) const { if (path.isEmpty()) return QModelIndex(); CDItem * item = root; //piCout << path << "..."; bool ok = false; for (int i = 0; i < path.size_s() - 1; ++i) { ok = false; foreach (CDItem * j, item->childs) if (j->type_ == CDItem::ItemCDSection && j->index_ == path[i]) { item = j; ok = true; break; } if (!ok) return QModelIndex(); } ok = false; foreach (CDItem * j, item->childs) if (j->type_ == CDItem::ItemCDType && j->index_ == path.back()) { item = j; ok = true; break; } if (!ok || !item->parent_) return QModelIndex(); QModelIndex ret = createIndex(item->parent_->childs.indexOf(item), column, item); //piCout << path << Q2PIString(item->data(cName_Cmd, Qt::DisplayRole).toString()) << getItem(ret)->buildPath(); return ret; }