| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| #include <QMessageBox> |
|
|
| #include <App/AutoTransaction.h> |
| #include <App/Document.h> |
| #include <App/ExpressionParser.h> |
| #include <App/Range.h> |
| #include <Base/Tools.h> |
| #include <Gui/CommandT.h> |
|
|
| #include "DlgSheetConf.h" |
| #include "ui_DlgSheetConf.h" |
|
|
|
|
| using namespace App; |
| using namespace Spreadsheet; |
| using namespace SpreadsheetGui; |
|
|
| DlgSheetConf::DlgSheetConf(Sheet* sheet, Range range, QWidget* parent) |
| : QDialog(parent) |
| , sheet(sheet) |
| , ui(new Ui::DlgSheetConf) |
| { |
| ui->setupUi(this); |
|
|
| if (range.colCount() == 1) { |
| auto to = range.to(); |
| to.setCol(CellAddress::MAX_COLUMNS - 1); |
| range = Range(range.from(), to); |
| } |
|
|
| ui->lineEditStart->setText(QString::fromLatin1(range.from().toString().c_str())); |
| ui->lineEditEnd->setText(QString::fromLatin1(range.to().toString().c_str())); |
|
|
| ui->lineEditProp->setDocumentObject(sheet, false); |
|
|
| connect(ui->btnDiscard, &QPushButton::clicked, this, &DlgSheetConf::onDiscard); |
|
|
| CellAddress from, to; |
| std::string rangeConf; |
| ObjectIdentifier path; |
| auto prop = prepare(from, to, rangeConf, path, true); |
| if (prop) { |
| ui->lineEditProp->setText(QString::fromUtf8(path.toString().c_str())); |
| if (auto group = prop->getGroup()) { |
| ui->lineEditGroup->setText(QString::fromUtf8(group)); |
| } |
| } |
|
|
| ui->lineEditStart->setText(QString::fromLatin1(from.toString().c_str())); |
| ui->lineEditEnd->setText(QString::fromLatin1(to.toString().c_str())); |
| } |
|
|
| DlgSheetConf::~DlgSheetConf() |
| { |
| delete ui; |
| } |
|
|
| App::Property* DlgSheetConf::prepare( |
| CellAddress& from, |
| CellAddress& to, |
| std::string& rangeConf, |
| ObjectIdentifier& path, |
| bool init |
| ) |
| { |
| from = sheet->getCellAddress(ui->lineEditStart->text().trimmed().toLatin1().constData()); |
| to = sheet->getCellAddress(ui->lineEditEnd->text().trimmed().toLatin1().constData()); |
|
|
| if (from.col() >= to.col()) { |
| FC_THROWM(Base::RuntimeError, "Invalid cell range"); |
| } |
|
|
| |
| to.setRow(from.row()); |
|
|
| CellAddress confFrom(from.row() + 1, from.col()); |
| rangeConf = confFrom.toString(); |
| |
| |
| |
| |
| |
| |
| rangeConf += ":|"; |
|
|
| if (!init) { |
| std::string exprTxt(ui->lineEditProp->text().trimmed().toUtf8().constData()); |
| ExpressionPtr expr; |
| try { |
| expr.reset(App::Expression::parse(sheet, exprTxt)); |
| } |
| catch (Base::Exception& e) { |
| e.reportException(); |
| FC_THROWM(Base::RuntimeError, "Failed to parse expression for property"); |
| } |
| if (expr->hasComponent() || !expr->isDerivedFrom<App::VariableExpression>()) { |
| FC_THROWM(Base::RuntimeError, "Invalid property expression: " << expr->toString()); |
| } |
|
|
| path = static_cast<App::VariableExpression*>(expr.get())->getPath(); |
| auto obj = path.getDocumentObject(); |
| if (!obj) { |
| FC_THROWM(Base::RuntimeError, "Invalid object referenced in: " << expr->toString()); |
| } |
|
|
| int pseudoType; |
| auto prop = path.getProperty(&pseudoType); |
| if (pseudoType |
| || (prop |
| && (!prop->isDerivedFrom<App::PropertyEnumeration>() |
| || !prop->testStatus(App::Property::PropDynamic)))) { |
| FC_THROWM(Base::RuntimeError, "Invalid property referenced in: " << expr->toString()); |
| } |
| return prop; |
| } |
|
|
| Cell* cell = sheet->getCell(from); |
| if (cell && cell->getExpression()) { |
| auto expr = cell->getExpression(); |
| if (expr->isDerivedFrom<FunctionExpression>()) { |
| auto fexpr = freecad_cast<FunctionExpression*>(cell->getExpression()); |
| if (fexpr |
| && (fexpr->getFunction() == FunctionExpression::HREF |
| || fexpr->getFunction() == FunctionExpression::HIDDENREF) |
| && fexpr->getArgs().size() == 1) { |
| expr = fexpr->getArgs().front(); |
| } |
| } |
| auto vexpr = freecad_cast<VariableExpression*>(expr); |
| if (vexpr) { |
| auto prop = freecad_cast<PropertyEnumeration*>(vexpr->getPath().getProperty()); |
| if (prop) { |
| auto obj = freecad_cast<DocumentObject*>(prop->getContainer()); |
| if (obj && prop->hasName()) { |
| path = ObjectIdentifier(sheet); |
| path.setDocumentObjectName(obj, true); |
| path << ObjectIdentifier::SimpleComponent(prop->getName()); |
| return prop; |
| } |
| } |
| } |
| } |
| return nullptr; |
| } |
|
|
| void DlgSheetConf::accept() |
| { |
| bool commandActive = false; |
| try { |
| std::string rangeConf; |
| CellAddress from, to; |
| ObjectIdentifier path; |
| App::Property* prop = prepare(from, to, rangeConf, path, false); |
|
|
| Range range(from, to); |
|
|
| |
| Range r(sheet->getRange(rangeConf.c_str())); |
| do { |
| auto cell = sheet->getCell(*r); |
| if (cell && cell->getExpression()) { |
| ExpressionPtr expr(cell->getExpression()->eval()); |
| if (expr->isDerivedFrom<StringExpression>()) { |
| continue; |
| } |
| } |
| FC_THROWM( |
| Base::RuntimeError, |
| "Expects cell " << r.address() << " evaluates to string.\n" |
| << rangeConf << " is supposed to contain a list of configuration names" |
| ); |
| } while (r.next()); |
|
|
| std::string exprTxt(ui->lineEditProp->text().trimmed().toUtf8().constData()); |
| App::ExpressionPtr expr(App::Expression::parse(sheet, exprTxt)); |
| if (expr->hasComponent() || !expr->isDerivedFrom<App::VariableExpression>()) { |
| FC_THROWM(Base::RuntimeError, "Invalid property expression: " << expr->toString()); |
| } |
|
|
| AutoTransaction guard("Setup conf table"); |
| commandActive = true; |
|
|
| |
| int count = range.rowCount() * range.colCount(); |
| for (int i = 0; i < count; ++i) { |
| auto r = range; |
| auto binding = sheet->getCellBinding(r); |
| if (!binding) { |
| break; |
| } |
| Gui::cmdAppObjectArgs( |
| sheet, |
| "setExpression('.cells.%s.%s.%s', None)", |
| binding == PropertySheet::BindingNormal ? "Bind" : "BindHiddenRef", |
| r.from().toString(), |
| r.to().toString() |
| ); |
| } |
|
|
| auto obj = path.getDocumentObject(); |
| if (!obj) { |
| FC_THROWM(Base::RuntimeError, "Object not found"); |
| } |
|
|
| |
| std::string propName = path.getPropertyName(); |
| QString groupName = ui->lineEditGroup->text().trimmed(); |
| if (!prop) { |
| prop = obj->addDynamicProperty( |
| "App::PropertyEnumeration", |
| propName.c_str(), |
| groupName.toUtf8().constData() |
| ); |
| } |
| else if (groupName.size()) { |
| obj->changeDynamicProperty(prop, groupName.toUtf8().constData(), nullptr); |
| } |
| prop->setStatus(App::Property::CopyOnChange, true); |
|
|
| |
| Gui::cmdAppObjectArgs( |
| obj, |
| "setExpression('%s.Enum', '%s.cells[<<%s>>]')", |
| propName, |
| sheet->getFullName(), |
| rangeConf |
| ); |
|
|
| Gui::cmdAppObjectArgs(obj, "recompute()"); |
|
|
| |
| |
| |
| |
| Gui::cmdAppObjectArgs( |
| sheet, |
| "set('%s', '=hiddenref(%s.String)')", |
| from.toString(CellAddress::Cell::ShowRowColumn), |
| prop->getFullName() |
| ); |
|
|
| |
| range = Range(from.row(), from.col() + 1, to.row(), to.col()); |
|
|
| |
| |
| Gui::cmdAppObjectArgs( |
| sheet, |
| "setExpression('.cells.Bind.%s.%s', " |
| "'tuple(.cells, <<%s>> + str(hiddenref(%s)+%d), <<%s>> + str(hiddenref(%s)+%d))')", |
| range.from().toString(CellAddress::Cell::ShowRowColumn), |
| range.to().toString(CellAddress::Cell::ShowRowColumn), |
| range.from().toString(CellAddress::Cell::ShowColumn), |
| prop->getFullName(), |
| from.row() + 2, |
| range.to().toString(CellAddress::Cell::ShowColumn), |
| prop->getFullName(), |
| from.row() + 2 |
| ); |
|
|
| Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); |
| Gui::Command::commitCommand(); |
| QDialog::accept(); |
| } |
| catch (Base::Exception& e) { |
| e.reportException(); |
| QMessageBox::critical(this, tr("Setup Configuration Table"), QString::fromUtf8(e.what())); |
| if (commandActive) { |
| Gui::Command::abortCommand(); |
| } |
| } |
| } |
|
|
| void DlgSheetConf::onDiscard() |
| { |
| bool commandActive = false; |
| try { |
| std::string rangeConf; |
| CellAddress from, to; |
| ObjectIdentifier path; |
| auto prop = prepare(from, to, rangeConf, path, true); |
|
|
| Range range(from, to); |
|
|
| AutoTransaction guard("Unsetup conf table"); |
| commandActive = true; |
|
|
| |
| int count = range.rowCount() * range.colCount(); |
| for (int i = 0; i < count; ++i) { |
| auto r = range; |
| auto binding = sheet->getCellBinding(r); |
| if (!binding) { |
| break; |
| } |
| Gui::cmdAppObjectArgs( |
| sheet, |
| "setExpression('.cells.%s.%s.%s', None)", |
| binding == PropertySheet::BindingNormal ? "Bind" : "BindHiddenRef", |
| r.from().toString(), |
| r.to().toString() |
| ); |
| } |
|
|
| Gui::cmdAppObjectArgs(sheet, "clear('%s')", from.toString(CellAddress::Cell::ShowRowColumn)); |
|
|
| if (prop && prop->getName()) { |
| auto obj = path.getDocumentObject(); |
| if (!obj) { |
| FC_THROWM(Base::RuntimeError, "Object not found"); |
| } |
| Gui::cmdAppObjectArgs(obj, "setExpression('%s.Enum', None)", prop->getName()); |
| if (prop->testStatus(Property::PropDynamic)) { |
| Gui::cmdAppObjectArgs(obj, "removeProperty('%s')", prop->getName()); |
| } |
| } |
|
|
| Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); |
| Gui::Command::commitCommand(); |
| QDialog::accept(); |
| } |
| catch (Base::Exception& e) { |
| e.reportException(); |
| QMessageBox::critical(this, tr("Unsetup Configuration Table"), QString::fromUtf8(e.what())); |
| if (commandActive) { |
| Gui::Command::abortCommand(); |
| } |
| } |
| } |
|
|
| #include "moc_DlgSheetConf.cpp" |
|
|