FreeCAD

Форк
0
/
TaskShapeBuilder.cpp 
625 строк · 21.2 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24

25
#ifndef _PreComp_
26
# include <QButtonGroup>
27
# include <QMessageBox>
28
# include <QTextStream>
29
# include <sstream>
30
# include <TopExp.hxx>
31
# include <TopTools_IndexedMapOfShape.hxx>
32
#endif
33

34
#include <App/Application.h>
35
#include <App/Document.h>
36
#include <App/DocumentObject.h>
37
#include <Base/Console.h>
38
#include <Gui/Application.h>
39
#include <Gui/BitmapFactory.h>
40
#include <Gui/Command.h>
41
#include <Gui/Document.h>
42
#include <Gui/Selection.h>
43
#include <Gui/SelectionFilter.h>
44
#include <Gui/SelectionObject.h>
45
#include <Mod/Part/App/PartFeature.h>
46

47
#include "TaskShapeBuilder.h"
48
#include "ui_TaskShapeBuilder.h"
49
#include "BoxSelection.h"
50

51

52
using namespace PartGui;
53

54
namespace PartGui {
55
    class ShapeSelection : public Gui::SelectionFilterGate
56
    {
57
    public:
58
        enum Type {VERTEX, EDGE, FACE, ALL};
59
        Type mode{ALL};
60
        ShapeSelection()
61
            : Gui::SelectionFilterGate(nullPointer())
62
        {
63
        }
64
        void setMode(Type mode)
65
        {
66
            this->mode = mode;
67
        }
68
        bool allow(App::Document*, App::DocumentObject* obj, const char*sSubName) override
69
        {
70
            if (!obj || !obj->isDerivedFrom(Part::Feature::getClassTypeId()))
71
                return false;
72
            if (!sSubName || sSubName[0] == '\0')
73
                return (mode == ALL);
74
            std::string element(sSubName);
75
            switch (mode) {
76
            case VERTEX:
77
                return element.substr(0,6) == "Vertex";
78
            case EDGE:
79
                return element.substr(0,4) == "Edge";
80
            case FACE:
81
                return element.substr(0,4) == "Face";
82
            default:
83
                return true;
84
            }
85
        }
86
    };
87
}
88

89
class ShapeBuilderWidget::Private
90
{
91
public:
92
    Ui_TaskShapeBuilder ui;
93
    QButtonGroup bg;
94
    ShapeSelection* gate;
95
    BoxSelection selection;
96
    Private()
97
    {
98
        Gui::Command::runCommand(Gui::Command::App, "from FreeCAD import Base");
99
        Gui::Command::runCommand(Gui::Command::App, "import Part");
100
    }
101
    ~Private() = default;
102
};
103

104
/* TRANSLATOR PartGui::ShapeBuilderWidget */
105

106
ShapeBuilderWidget::ShapeBuilderWidget(QWidget* parent)
107
  : d(new Private())
108
{
109
    Q_UNUSED(parent);
110
    d->ui.setupUi(this);
111
    d->ui.label->setText(QString());
112
    d->bg.addButton(d->ui.radioButtonEdgeFromVertex, 0);
113
    d->bg.addButton(d->ui.radioButtonWireFromEdge, 1);
114
    d->bg.addButton(d->ui.radioButtonFaceFromVertex, 2);
115
    d->bg.addButton(d->ui.radioButtonFaceFromEdge, 3);
116
    d->bg.addButton(d->ui.radioButtonShellFromFace, 4);
117
    d->bg.addButton(d->ui.radioButtonSolidFromShell, 5);
118
    d->bg.setExclusive(true);
119

120
    connect(d->ui.selectButton, &QPushButton::clicked,
121
            this, &ShapeBuilderWidget::onSelectButtonClicked);
122
    connect(d->ui.createButton, &QPushButton::clicked,
123
            this, &ShapeBuilderWidget::onCreateButtonClicked);
124
#if QT_VERSION < QT_VERSION_CHECK(5,15,0)
125
    connect(&d->bg, qOverload<int>(&QButtonGroup::buttonClicked),
126
            this, &ShapeBuilderWidget::switchMode);
127
#else
128
    connect(&d->bg, &QButtonGroup::idClicked,
129
            this, &ShapeBuilderWidget::switchMode);
130
#endif
131

132
    d->gate = new ShapeSelection();
133
    Gui::Selection().addSelectionGate(d->gate);
134

135
    d->bg.button(0)->setChecked(true);
136
    switchMode(0);
137
}
138

139
ShapeBuilderWidget::~ShapeBuilderWidget()
140
{
141
    Gui::Selection().rmvSelectionGate();
142
    delete d;
143
}
144

145
void ShapeBuilderWidget::onSelectionChanged(const Gui::SelectionChanges& msg)
146
{
147
    if (d->ui.checkFaces->isChecked()) {
148
        if (msg.Type == Gui::SelectionChanges::AddSelection) {
149
            std::string subName(msg.pSubName);
150
            if (!subName.empty()) {
151
                // From the shape get all faces and add them to the selection
152
                bool blocked = blockSelection(true);
153
                App::Document* doc = App::GetApplication().getDocument(msg.pDocName);
154
                App::DocumentObject* obj = doc->getObject(msg.pObjectName);
155
                if (obj->isDerivedFrom<Part::Feature>()) {
156
                    TopoDS_Shape myShape = static_cast<Part::Feature*>(obj)->Shape.getValue();
157
                    TopTools_IndexedMapOfShape all_faces;
158
                    TopExp::MapShapes(myShape, TopAbs_FACE, all_faces);
159
                    for (int i=1; i<= all_faces.Extent(); i++) {
160
                        TopoDS_Shape face = all_faces(i);
161
                        if (!face.IsNull()) {
162
                            std::stringstream str;
163
                            str << "Face" << i;
164
                            Gui::Selection().addSelection(msg.pDocName, msg.pObjectName, str.str().c_str());
165
                        }
166
                    }
167
                }
168

169
                blockSelection(blocked);
170
            }
171
        }
172
    }
173
}
174

175
void ShapeBuilderWidget::onCreateButtonClicked()
176
{
177
    int mode = d->bg.checkedId();
178
    Gui::Document* doc = Gui::Application::Instance->activeDocument();
179
    if (!doc)
180
        return;
181

182
    try {
183
        if (mode == 0) {
184
            createEdgeFromVertex();
185
        }
186
        else if (mode == 1) {
187
            createWireFromEdge();
188
        }
189
        else if (mode == 2) {
190
            createFaceFromVertex();
191
        }
192
        else if (mode == 3) {
193
            createFaceFromEdge();
194
        }
195
        else if (mode == 4) {
196
            createShellFromFace();
197
        }
198
        else if (mode == 5) {
199
            createSolidFromShell();
200
        }
201
        doc->getDocument()->recompute();
202
        Gui::Selection().clearSelection();
203
    }
204
    catch (const Base::Exception& e) {
205
        Base::Console().Error("%s\n", e.what());
206
    }
207
}
208

209
void ShapeBuilderWidget::onSelectButtonClicked()
210
{
211
    int id = d->bg.checkedId();
212
    if (id == 0 || id == 2) {
213
        d->selection.start(TopAbs_VERTEX);
214
    }
215
    else if (id == 1 || id == 3) {
216
        d->selection.start(TopAbs_EDGE);
217
    }
218
    else if (id == 4) {
219
        d->selection.start(TopAbs_FACE);
220
    }
221
    else {
222
        QMessageBox::warning(this, tr("Unsupported"), tr("Box selection for shells is not supported"));
223
    }
224
}
225

226
void ShapeBuilderWidget::createEdgeFromVertex()
227
{
228
    Gui::SelectionFilter vertexFilter  ("SELECT Part::Feature SUBELEMENT Vertex COUNT 2");
229
    bool matchVertex = vertexFilter.match();
230
    if (!matchVertex) {
231
        QMessageBox::critical(this, tr("Wrong selection"), tr("Select two vertices"));
232
        return;
233
    }
234

235
    std::vector<Gui::SelectionObject> sel = vertexFilter.Result[0];
236
    std::vector<QString> elements;
237
    std::vector<Gui::SelectionObject>::iterator it;
238
    std::vector<std::string>::const_iterator jt;
239
    for (it=sel.begin();it!=sel.end();++it) {
240
        for (jt=it->getSubNames().begin();jt!=it->getSubNames().end();++jt) {
241
            QString line;
242
            QTextStream str(&line);
243
            str << "App.ActiveDocument." << it->getFeatName() << ".Shape." << jt->c_str() << ".Point";
244
            elements.push_back(line);
245
        }
246
    }
247

248
    // should actually never happen
249
    if (elements.size() != 2) {
250
        QMessageBox::critical(this, tr("Wrong selection"), tr("Select two vertices"));
251
        return;
252
    }
253

254
    QString cmd;
255
    cmd = QString::fromLatin1(
256
        "_=Part.makeLine(%1, %2)\n"
257
        "if _.isNull(): raise RuntimeError('Failed to create edge')\n"
258
        "App.ActiveDocument.addObject('Part::Feature','Edge').Shape=_\n"
259
        "del _\n"
260
    ).arg(elements[0], elements[1]);
261

262
    try {
263
        Gui::Application::Instance->activeDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Edge"));
264
        Gui::Command::runCommand(Gui::Command::App, cmd.toLatin1());
265
        Gui::Application::Instance->activeDocument()->commitCommand();
266
    }
267
    catch (const Base::Exception&) {
268
        Gui::Application::Instance->activeDocument()->abortCommand();
269
        throw;
270
    }
271
}
272

273
void ShapeBuilderWidget::createWireFromEdge()
274
{
275
    Gui::SelectionFilter edgeFilter  ("SELECT Part::Feature SUBELEMENT Edge COUNT 1..");
276
    bool matchEdge = edgeFilter.match();
277
    if (!matchEdge) {
278
        QMessageBox::critical(this, tr("Wrong selection"), tr("Select one or more edges"));
279
        return;
280
    }
281

282
    std::vector<Gui::SelectionObject> sel = edgeFilter.Result[0];
283
    std::vector<Gui::SelectionObject>::iterator it;
284
    std::vector<std::string>::const_iterator jt;
285

286
    QString list;
287
    QTextStream str(&list);
288
    str << "[";
289
    for (it=sel.begin();it!=sel.end();++it) {
290
        for (jt=it->getSubNames().begin();jt!=it->getSubNames().end();++jt) {
291
            str << "App.ActiveDocument." << it->getFeatName() << ".Shape." << jt->c_str() << ", ";
292
        }
293
    }
294
    str << "]";
295

296
    QString cmd;
297
    cmd = QString::fromLatin1(
298
        "_=Part.Wire(Part.__sortEdges__(%1))\n"
299
        "if _.isNull(): raise RuntimeError('Failed to create a wire')\n"
300
        "App.ActiveDocument.addObject('Part::Feature','Wire').Shape=_\n"
301
        "del _\n"
302
    ).arg(list);
303
    try {
304
        Gui::Application::Instance->activeDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Wire"));
305
        Gui::Command::runCommand(Gui::Command::App, cmd.toLatin1());
306
        Gui::Application::Instance->activeDocument()->commitCommand();
307
    }
308
    catch (const Base::Exception&) {
309
        Gui::Application::Instance->activeDocument()->abortCommand();
310
        throw;
311
    }
312
}
313

314
void ShapeBuilderWidget::createFaceFromVertex()
315
{
316
    Gui::SelectionFilter vertexFilter  ("SELECT Part::Feature SUBELEMENT Vertex COUNT 3..");
317
    bool matchVertex = vertexFilter.match();
318
    if (!matchVertex) {
319
        QMessageBox::critical(this, tr("Wrong selection"), tr("Select three or more vertices"));
320
        return;
321
    }
322

323
    std::vector<Gui::SelectionObject> sel = vertexFilter.Result[0];
324
    std::vector<Gui::SelectionObject>::iterator it;
325
    std::vector<std::string>::const_iterator jt;
326

327
    QString list;
328
    QTextStream str(&list);
329
    str << "[";
330
    for (it=sel.begin();it!=sel.end();++it) {
331
        for (jt=it->getSubNames().begin();jt!=it->getSubNames().end();++jt) {
332
            str << "App.ActiveDocument." << it->getFeatName() << ".Shape." << jt->c_str() << ".Point, ";
333
        }
334
    }
335
    str << "]";
336

337
    QString cmd;
338
    if (d->ui.checkPlanar->isChecked()) {
339
        cmd = QString::fromLatin1(
340
            "_=Part.Face(Part.makePolygon(%1, True))\n"
341
            "if _.isNull(): raise RuntimeError('Failed to create face')\n"
342
            "App.ActiveDocument.addObject('Part::Feature','Face').Shape=_\n"
343
            "del _\n"
344
        ).arg(list);
345
    }
346
    else {
347
        cmd = QString::fromLatin1(
348
            "_=Part.makeFilledFace(Part.makePolygon(%1, True).Edges)\n"
349
            "if _.isNull(): raise RuntimeError('Failed to create face')\n"
350
            "App.ActiveDocument.addObject('Part::Feature','Face').Shape=_\n"
351
            "del _\n"
352
        ).arg(list);
353
    }
354

355
    try {
356
        Gui::Application::Instance->activeDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Face"));
357
        Gui::Command::runCommand(Gui::Command::App, cmd.toLatin1());
358
        Gui::Application::Instance->activeDocument()->commitCommand();
359
    }
360
    catch (const Base::Exception&) {
361
        Gui::Application::Instance->activeDocument()->abortCommand();
362
        throw;
363
    }
364
}
365

366
void ShapeBuilderWidget::createFaceFromEdge()
367
{
368
    Gui::SelectionFilter edgeFilter  ("SELECT Part::Feature SUBELEMENT Edge COUNT 1..");
369
    bool matchEdge = edgeFilter.match();
370
    if (!matchEdge) {
371
        QMessageBox::critical(this, tr("Wrong selection"), tr("Select one or more edges"));
372
        return;
373
    }
374

375
    std::vector<Gui::SelectionObject> sel = edgeFilter.Result[0];
376
    std::vector<Gui::SelectionObject>::iterator it;
377
    std::vector<std::string>::const_iterator jt;
378

379
    QString list;
380
    QTextStream str(&list);
381
    str << "[";
382
    for (it=sel.begin();it!=sel.end();++it) {
383
        for (jt=it->getSubNames().begin();jt!=it->getSubNames().end();++jt) {
384
            str << "App.ActiveDocument." << it->getFeatName() << ".Shape." << jt->c_str() << ", ";
385
        }
386
    }
387
    str << "]";
388

389
    QString cmd;
390
    if (d->ui.checkPlanar->isChecked()) {
391
        cmd = QString::fromLatin1(
392
            "_=Part.Face(Part.Wire(Part.__sortEdges__(%1)))\n"
393
            "if _.isNull(): raise RuntimeError('Failed to create face')\n"
394
            "App.ActiveDocument.addObject('Part::Feature','Face').Shape=_\n"
395
            "del _\n"
396
        ).arg(list);
397
    }
398
    else {
399
        cmd = QString::fromLatin1(
400
            "_=Part.makeFilledFace(Part.__sortEdges__(%1))\n"
401
            "if _.isNull(): raise RuntimeError('Failed to create face')\n"
402
            "App.ActiveDocument.addObject('Part::Feature','Face').Shape=_\n"
403
            "del _\n"
404
        ).arg(list);
405
    }
406

407
    try {
408
        Gui::Application::Instance->activeDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Face"));
409
        Gui::Command::runCommand(Gui::Command::App, cmd.toLatin1());
410
        Gui::Application::Instance->activeDocument()->commitCommand();
411
    }
412
    catch (const Base::Exception&) {
413
        Gui::Application::Instance->activeDocument()->abortCommand();
414
        throw;
415
    }
416
}
417

418
void ShapeBuilderWidget::createShellFromFace()
419
{
420
    Gui::SelectionFilter faceFilter  ("SELECT Part::Feature SUBELEMENT Face COUNT 2..");
421
    bool matchFace = faceFilter.match();
422
    if (!matchFace) {
423
        QMessageBox::critical(this, tr("Wrong selection"), tr("Select two or more faces"));
424
        return;
425
    }
426

427
    std::vector<Gui::SelectionObject> sel = faceFilter.Result[0];
428

429
    QString list;
430
    QTextStream str(&list);
431
    if (d->ui.checkFaces->isChecked()) {
432
        std::set<const App::DocumentObject*> obj;
433
        for (const auto& it : sel)
434
            obj.insert(it.getObject());
435
        str << "[]";
436
        for (auto it : obj) {
437
            str << "+ App.ActiveDocument." << it->getNameInDocument() << ".Shape.Faces";
438
        }
439
    }
440
    else {
441
        str << "[";
442
        for (const auto& it : sel) {
443
            for (const auto& jt : it.getSubNames()) {
444
                str << "App.ActiveDocument." << it.getFeatName() << ".Shape." << jt.c_str() << ", ";
445
            }
446
        }
447
        str << "]";
448
    }
449

450
    QString cmd;
451
    if (d->ui.checkRefine->isEnabled() && d->ui.checkRefine->isChecked()) {
452
        cmd = QString::fromLatin1(
453
            "_=Part.Shell(%1)\n"
454
            "if _.isNull(): raise RuntimeError('Failed to create shell')\n"
455
            "App.ActiveDocument.addObject('Part::Feature','Shell').Shape=_.removeSplitter()\n"
456
            "del _\n"
457
        ).arg(list);
458
    }
459
    else {
460
        cmd = QString::fromLatin1(
461
            "_=Part.Shell(%1)\n"
462
            "if _.isNull(): raise RuntimeError('Failed to create shell')\n"
463
            "App.ActiveDocument.addObject('Part::Feature','Shell').Shape=_\n"
464
            "del _\n"
465
        ).arg(list);
466
    }
467

468
    try {
469
        Gui::Application::Instance->activeDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Shell"));
470
        Gui::Command::runCommand(Gui::Command::App, cmd.toLatin1());
471
        Gui::Application::Instance->activeDocument()->commitCommand();
472
    }
473
    catch (const Base::Exception&) {
474
        Gui::Application::Instance->activeDocument()->abortCommand();
475
        throw;
476
    }
477
}
478

479
void ShapeBuilderWidget::createSolidFromShell()
480
{
481
    Gui::SelectionFilter partFilter  ("SELECT Part::Feature COUNT 1");
482
    bool matchPart = partFilter.match();
483
    if (!matchPart) {
484
        QMessageBox::critical(this, tr("Wrong selection"), tr("Select only one part object"));
485
        return;
486
    }
487

488
    QString line;
489
    QTextStream str(&line);
490

491
    std::vector<Gui::SelectionObject> sel = partFilter.Result[0];
492
    std::vector<Gui::SelectionObject>::iterator it;
493
    for (it=sel.begin();it!=sel.end();++it) {
494
        str << "App.ActiveDocument." << it->getFeatName() << ".Shape";
495
        break;
496
    }
497

498
    QString cmd;
499
    if (d->ui.checkRefine->isEnabled() && d->ui.checkRefine->isChecked()) {
500
        cmd = QString::fromLatin1(
501
            "shell=%1\n"
502
            "if shell.ShapeType != 'Shell': raise RuntimeError('Part object is not a shell')\n"
503
            "_=Part.Solid(shell)\n"
504
            "if _.isNull(): raise RuntimeError('Failed to create solid')\n"
505
            "App.ActiveDocument.addObject('Part::Feature','Solid').Shape=_.removeSplitter()\n"
506
            "del _\n"
507
        ).arg(line);
508
    }
509
    else {
510
        cmd = QString::fromLatin1(
511
            "shell=%1\n"
512
            "if shell.ShapeType != 'Shell': raise RuntimeError('Part object is not a shell')\n"
513
            "_=Part.Solid(shell)\n"
514
            "if _.isNull(): raise RuntimeError('Failed to create solid')\n"
515
            "App.ActiveDocument.addObject('Part::Feature','Solid').Shape=_\n"
516
            "del _\n"
517
        ).arg(line);
518
    }
519

520
    try {
521
        Gui::Application::Instance->activeDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Solid"));
522
        Gui::Command::runCommand(Gui::Command::App, cmd.toLatin1());
523
        Gui::Application::Instance->activeDocument()->commitCommand();
524
    }
525
    catch (const Base::Exception&) {
526
        Gui::Application::Instance->activeDocument()->abortCommand();
527
        throw;
528
    }
529
}
530

531
void ShapeBuilderWidget::switchMode(int mode)
532
{
533
    Gui::Selection().clearSelection();
534
    if (mode == 0) {
535
        d->gate->setMode(ShapeSelection::VERTEX);
536
        d->ui.label->setText(tr("Select two vertices to create an edge"));
537
        d->ui.checkPlanar->setEnabled(false);
538
        d->ui.checkFaces->setEnabled(false);
539
        d->ui.checkRefine->setEnabled(false);
540
    }
541
    else if (mode == 1) {
542
        d->gate->setMode(ShapeSelection::EDGE);
543
        d->ui.label->setText(tr("Select adjacent edges"));
544
        d->ui.checkPlanar->setEnabled(true);
545
        d->ui.checkFaces->setEnabled(false);
546
        d->ui.checkRefine->setEnabled(false);
547
    }
548
    else if (mode == 2) {
549
        d->gate->setMode(ShapeSelection::VERTEX);
550
        d->ui.label->setText(tr("Select a list of vertices"));
551
        d->ui.checkPlanar->setEnabled(true);
552
        d->ui.checkFaces->setEnabled(false);
553
        d->ui.checkRefine->setEnabled(false);
554
    }
555
    else if (mode == 3) {
556
        d->gate->setMode(ShapeSelection::EDGE);
557
        d->ui.label->setText(tr("Select a closed set of edges"));
558
        d->ui.checkPlanar->setEnabled(true);
559
        d->ui.checkFaces->setEnabled(false);
560
        d->ui.checkRefine->setEnabled(false);
561
    }
562
    else if (mode == 4) {
563
        d->gate->setMode(ShapeSelection::FACE);
564
        d->ui.label->setText(tr("Select adjacent faces"));
565
        d->ui.checkPlanar->setEnabled(false);
566
        d->ui.checkFaces->setEnabled(true);
567
        d->ui.checkRefine->setEnabled(true);
568
    }
569
    else {
570
        d->gate->setMode(ShapeSelection::ALL);
571
        d->ui.label->setText(tr("All shape types can be selected"));
572
        d->ui.checkPlanar->setEnabled(false);
573
        d->ui.checkFaces->setEnabled(false);
574
        d->ui.checkRefine->setEnabled(true);
575
    }
576
}
577

578
bool ShapeBuilderWidget::accept()
579
{
580
    return true;
581
}
582

583
bool ShapeBuilderWidget::reject()
584
{
585
    return true;
586
}
587

588
void ShapeBuilderWidget::changeEvent(QEvent *e)
589
{
590
    QWidget::changeEvent(e);
591
    if (e->type() == QEvent::LanguageChange) {
592
        d->ui.retranslateUi(this);
593
    }
594
}
595

596

597
/* TRANSLATOR PartGui::TaskShapeBuilder */
598

599
TaskShapeBuilder::TaskShapeBuilder()
600
{
601
    widget = new ShapeBuilderWidget();
602
    addTaskBox(Gui::BitmapFactory().pixmap("Part_Shapebuilder"), widget);
603
}
604

605
TaskShapeBuilder::~TaskShapeBuilder() = default;
606

607
void TaskShapeBuilder::open()
608
{
609
}
610

611
void TaskShapeBuilder::clicked(int)
612
{
613
}
614

615
bool TaskShapeBuilder::accept()
616
{
617
    return widget->accept();
618
}
619

620
bool TaskShapeBuilder::reject()
621
{
622
    return widget->reject();
623
}
624

625
#include "moc_TaskShapeBuilder.cpp"
626

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.