| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #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" |
| |
|