Files
qad/libs/blockview/blockeditor.cpp
peri4 7ce2b31ec9 version 2.17.0
iconedlabel icon size scale in auto scale mode
BlockItem decors visibility logic flags
2023-06-05 23:26:23 +03:00

389 lines
12 KiB
C++

#include "blockeditor.h"
#include "blockview.h"
#include "drawtools.h"
#include "ui_blockeditor.h"
#include <QComboBox>
#include <QFile>
#include <QFileDialog>
#include <QTimer>
#include <QToolBar>
BlockEditor::BlockEditor(QWidget * parent): QWidget(parent), ui(new Ui::BlockEditor) {
init = false;
m_editorMode = false;
m_pinsEditable = true;
ui->setupUi(this);
src_title = windowTitle();
connect(ui->blockView->scene(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
block.setFlags(QGraphicsItem::GraphicsItemFlags());
block.is_blockeditor = true;
ui->blockView->addItem(&block);
ui->blockView->viewport()->installEventFilter(this);
DrawTools * drawtools = new DrawTools(ui->blockView);
connect(drawtools, SIGNAL(itemCreated(QGraphicsItem *)), this, SLOT(addItem(QGraphicsItem *)));
drawtools->textEditCombo()->addItems(QStringList() << "%name"
<< "%value"
<< "%id");
ui->layoutProperties->addWidget(drawtools->propertyWidget());
ui->actionRemove_items->setEnabled(false);
ui->button_color->setColor(Qt::lightGray);
ui->treePins->setItemDelegateForColumn(1, new PinBusDelegate());
connect(ui->treePins, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(updateBlock()));
ui->treePins->viewport()->installEventFilter(this);
QToolBar * bar;
bar = new QToolBar(ui->widgetBar);
bar->setOrientation(Qt::Vertical);
bar->addActions(drawtools->actionsForAdd());
ui->widgetBar->setMinimumSize(bar->sizeHint());
bar = new QToolBar(ui->widgetBarZ);
bar->setOrientation(Qt::Vertical);
bar->addActions(drawtools->actionsForZ());
bar->addSeparator();
bar->addActions(QList<QAction *>() << ui->actionRemove_items);
ui->widgetBarZ->setMinimumSize(bar->sizeHint());
init = true;
on_buttonClear_clicked();
}
BlockEditor::~BlockEditor() {
init = false;
delete ui;
}
void BlockEditor::loadFile(QString path) {
if (path.isEmpty()) return;
QFile f(path);
if (f.open(QIODevice::ReadOnly)) {
cur_file = path;
loadModel(f.readAll());
QDir::setCurrent(QFileInfo(path).dir().path());
}
setWindowTitle(src_title + QString(" - %1").arg(QFileInfo(path).baseName()));
}
void BlockEditor::loadModel(const QByteArray & model) {
BlockItem b;
b.loadModel(model);
ui->spin_w->setValue(b.width());
ui->spin_h->setValue(b.height());
ui->spin_margin->setValue(b.pinsMargin());
ui->button_color->setColor(b.color());
block.loadModel(model);
treePinsClear();
ui->treePins->blockSignals(true);
QVector<BlockItemPin *> pins = block.pins();
foreach(BlockItemPin * p, pins) {
QTreeWidgetItem * ti = new QTreeWidgetItem(QStringList() << p->text() << QString::number(p->busType()));
ti->setData(0, Qt::UserRole, qulonglong(p));
ti->setData(0, Qt::UserRole + 1, (int)p->alignment());
ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled);
pin_tli[p->alignment()]->addChild(ti);
}
foreach(QGraphicsItem * i, block.decors()) {
i->setData(bvidMoveParent, false);
i->setData(bvidCorrectMove, true);
}
ui->treePins->blockSignals(false);
}
QByteArray BlockEditor::saveModel() {
return block.saveModel();
}
void BlockEditor::setEditorMode(bool editorMode) {
m_editorMode = editorMode;
ui->buttonClear->setVisible(!editorMode);
ui->buttonSave->setVisible(!editorMode);
ui->buttonSaveAs->setVisible(!editorMode);
ui->buttonLoad->setVisible(!editorMode);
}
void BlockEditor::setPinsEditable(bool pinsEditable) {
m_pinsEditable = pinsEditable;
ui->treePins->setVisible(pinsEditable);
ui->buttonPinAdd->setVisible(pinsEditable);
ui->buttonPinClear->setVisible(pinsEditable);
ui->buttonPinDelete->setVisible(pinsEditable);
ui->buttonPinDup->setVisible(pinsEditable);
ui->groupPins->setVisible(pinsEditable);
}
void BlockEditor::selectionChanged() {
if (!init) return;
ui->actionRemove_items->setEnabled(!ui->blockView->scene()->selectedItems().isEmpty());
}
void BlockEditor::addItem(QGraphicsItem * item) {
block.addDecor(item);
item->setData(bvidMoveParent, false);
item->setData(bvidCorrectMove, true);
}
void BlockEditor::updateBlock() {
block.setSize(ui->spin_w->value(), ui->spin_h->value());
block.setColor(ui->button_color->color());
block.setPinsMargin(ui->spin_margin->value());
}
void BlockEditor::treePinsClear() {
ui->treePins->blockSignals(true);
ui->treePins->clear();
QFont bf(font());
bf.setBold(true);
QList<int> al = QList<int>() << Qt::AlignLeft << Qt::AlignRight << Qt::AlignTop << Qt::AlignBottom;
QStringList an = QStringList() << "Left"
<< "Right"
<< "Top"
<< "Bottom";
pin_tli.clear();
for (int i = 0; i < al.size(); ++i) {
QTreeWidgetItem * ti = new QTreeWidgetItem();
ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);
ti->setData(0, Qt::UserRole, al[i]);
ti->setText(0, an[i]);
ti->setFont(0, bf);
ui->treePins->addTopLevelItem(ti);
ti->setFirstColumnSpanned(true);
ti->setExpanded(true);
pin_tli[al[i]] = ti;
}
ui->treePins->blockSignals(false);
}
bool BlockEditor::eventFilter(QObject * o, QEvent * e) {
if (!init) QWidget::eventFilter(o, e);
if (o == ui->treePins->viewport()) {
if (e->type() == QEvent::Drop) {
QTimer::singleShot(0, this, SLOT(arrangePins()));
}
}
if (o == ui->blockView->viewport()) {
if (e->type() == QEvent::Resize) {
ui->blockView->centerOn(&block);
}
}
return QWidget::eventFilter(o, e);
}
void BlockEditor::changeEvent(QEvent * e) {
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange: ui->retranslateUi(this); break;
default: break;
}
}
void BlockEditor::on_actionRemove_items_triggered() {
QList<QGraphicsItem *> si = ui->blockView->scene()->selectedItems();
foreach(QGraphicsItem * i, si)
block.removeDecor(i);
}
void BlockEditor::on_buttonSave_clicked() {
if (cur_file.isEmpty()) {
on_buttonSaveAs_clicked();
return;
}
QFile f(cur_file);
if (f.open(QIODevice::WriteOnly)) {
f.write(saveModel());
}
}
void BlockEditor::on_buttonSaveAs_clicked() {
QString c = QFileDialog::getSaveFileName(this, "Save block model to file", cur_file, "*.blockmodel");
if (!c.isEmpty()) {
QFile f(c);
if (f.open(QIODevice::WriteOnly)) {
cur_file = c;
f.write(saveModel());
setWindowTitle(src_title + QString(" - %1").arg(QFileInfo(c).baseName()));
}
}
}
void BlockEditor::on_buttonLoad_clicked() {
QString c = QFileDialog::getOpenFileName(this, "Save block model to file", cur_file, "*.blockmodel");
loadFile(c);
}
void BlockEditor::on_buttonClear_clicked() {
BlockItem b;
ui->spin_w->setValue(b.width());
ui->spin_h->setValue(b.height());
ui->spin_margin->setValue(b.pinsMargin());
ui->button_color->setColor(b.color());
block.loadModel(QByteArray());
treePinsClear();
}
void BlockEditor::on_buttonPinAdd_clicked() {
ui->treePins->blockSignals(true);
QTreeWidgetItem * ti = new QTreeWidgetItem(QStringList() << ""
<< "0");
ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled);
ti->setData(0, Qt::UserRole, qulonglong(block.addPin(Qt::AlignLeft, ti->text(1).toInt(), ti->text(0))));
ti->setData(0, Qt::UserRole + 1, (int)Qt::AlignLeft);
pin_tli[Qt::AlignLeft]->addChild(ti);
ui->treePins->setCurrentItem(ti);
ui->treePins->blockSignals(false);
updateBlock();
}
void BlockEditor::on_buttonPinDup_clicked() {
QTreeWidgetItem * ci = ui->treePins->currentItem();
if (ci == 0) return;
ui->treePins->blockSignals(true);
QTreeWidgetItem * ti = ci->clone();
ti->setText(0, ti->text(0));
ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled);
Qt::Alignment al = (Qt::Alignment)ci->data(0, Qt::UserRole + 1).toInt();
ti->setData(0, Qt::UserRole, qulonglong(block.addPin(al, ci->text(1).toInt(), ci->text(0))));
ti->setData(0, Qt::UserRole + 1, (int)al);
pin_tli[al]->addChild(ti);
ui->treePins->setCurrentItem(ti);
ui->treePins->blockSignals(false);
}
void BlockEditor::on_buttonPinDelete_clicked() {
ui->treePins->blockSignals(true);
QList<QTreeWidgetItem *> si = ui->treePins->selectedItems();
foreach(QTreeWidgetItem * i, si) {
if (!i->parent()) continue;
block.removePin((BlockItemPin *)(i->data(0, Qt::UserRole).toLongLong()));
delete i;
}
ui->treePins->blockSignals(false);
}
void BlockEditor::on_buttonPinClear_clicked() {
treePinsClear();
block.clearPins();
}
void BlockEditor::on_treePins_itemChanged(QTreeWidgetItem * item, int column) {
if (!item) return;
BlockItemPin * pin = (BlockItemPin *)item->data(0, Qt::UserRole).toULongLong();
if (!pin) return;
switch (column) {
case 0:
ui->treePins->blockSignals(true);
item->setText(0, item->text(0));
pin->setText(item->text(0));
ui->treePins->blockSignals(false);
break;
case 1: pin->setBusType(item->text(1).toInt()); break;
};
}
void BlockEditor::arrangePins() {
QVector<BlockItemPin *> pins = block.pins();
QList<QTreeWidgetItem *> tli = pin_tli.values();
foreach(QTreeWidgetItem * ti, tli) {
for (int i = 0; i < ti->childCount(); ++i) {
foreach(BlockItemPin * p, pins)
if (p == (BlockItemPin *)(ti->child(i)->data(0, Qt::UserRole).toULongLong())) {
p->setAlignment((Qt::Alignment)ti->data(0, Qt::UserRole).toInt());
BlockItemPin * np = block.addPin(p, false);
ti->child(i)->setData(0, Qt::UserRole, qulonglong(np));
ti->child(i)->setData(0, Qt::UserRole + 1, ti->data(0, Qt::UserRole).toInt());
break;
}
}
}
block.arrangePins();
}
/// ***********************************************************
/// ***********************************************************
/// ***********************************************************
/// ***********************************************************
QWidget * PinAlignDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const {
QComboBox * combo = new QComboBox(parent);
int cv = index.data().toInt();
combo->addItem("Left", int(Qt::AlignLeft));
if (cv == Qt::AlignLeft) combo->setCurrentIndex(0);
combo->addItem("Right", int(Qt::AlignRight));
if (cv == Qt::AlignRight) combo->setCurrentIndex(1);
combo->addItem("Top", int(Qt::AlignTop));
if (cv == Qt::AlignTop) combo->setCurrentIndex(2);
combo->addItem("Bottom", int(Qt::AlignBottom));
if (cv == Qt::AlignBottom) combo->setCurrentIndex(3);
combo->setGeometry(option.rect);
return combo;
}
QString PinAlignDelegate::displayText(const QVariant & value, const QLocale & locale) const {
int cv = value.toInt();
switch (cv) {
case Qt::AlignLeft: return tr("Left"); break;
case Qt::AlignRight: return tr("Right"); break;
case Qt::AlignTop: return tr("Top"); break;
case Qt::AlignBottom: return tr("Bottom"); break;
}
return tr("unknown");
}
void PinAlignDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const {
model->setData(index, ((QComboBox *)editor)->itemData(((QComboBox *)editor)->currentIndex()).toInt());
}
/// ***********************************************************
/// ***********************************************************
/// ***********************************************************
/// ***********************************************************
QWidget * PinBusDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const {
QSpinBox * spin = new QSpinBox(parent);
spin->setMinimum(-2147483648);
spin->setMaximum(2147483647);
spin->setValue(index.data().toInt());
return spin;
}
QString PinBusDelegate::displayText(const QVariant & value, const QLocale & locale) const {
int cv = value.toInt();
return QString::number(cv);
}
void PinBusDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const {
model->setData(index, ((QSpinBox *)editor)->value());
}