FreeCAD

Форк
0
/
DlgExpressionInput.cpp 
283 строки · 9.4 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name>             *
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., 51 Franklin Street,      *
19
 *   Fifth Floor, Boston, MA  02110-1301, USA                              *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
#include <QApplication>
26
#include <QMenu>
27
#include <QMouseEvent>
28
#endif
29

30
#include <App/Application.h>
31
#include <App/DocumentObject.h>
32
#include <App/ExpressionParser.h>
33
#include <Base/Tools.h>
34

35
#include "DlgExpressionInput.h"
36
#include "ui_DlgExpressionInput.h"
37
#include "Tools.h"
38

39

40
using namespace App;
41
using namespace Gui::Dialog;
42

43
DlgExpressionInput::DlgExpressionInput(const App::ObjectIdentifier & _path,
44
                                       std::shared_ptr<const Expression> _expression,
45
                                       const Base::Unit & _impliedUnit, QWidget *parent)
46
  : QDialog(parent)
47
  , ui(new Ui::DlgExpressionInput)
48
  , expression(_expression ? _expression->copy() : nullptr)
49
  , path(_path)
50
  , discarded(false)
51
  , impliedUnit(_impliedUnit)
52
  , minimumWidth(10)
53
{
54
    assert(path.getDocumentObject());
55

56
    // Setup UI
57
    ui->setupUi(this);
58

59
    // Connect signal(s)
60
    connect(ui->expression, &ExpressionLineEdit::textChanged,
61
        this, &DlgExpressionInput::textChanged);
62
    connect(ui->discardBtn, &QPushButton::clicked,
63
        this, &DlgExpressionInput::setDiscarded);
64

65
    if (expression) {
66
        ui->expression->setText(Base::Tools::fromStdString(expression->toString()));
67
    }
68
    else {
69
        QVariant text = parent->property("text");
70
        if (text.canConvert<QString>()) {
71
            ui->expression->setText(text.toString());
72
        }
73
    }
74

75
    // Set document object on line edit to create auto completer
76
    DocumentObject * docObj = path.getDocumentObject();
77
    ui->expression->setDocumentObject(docObj);
78

79
    // There are some platforms where setting no system background causes a black
80
    // rectangle to appear. To avoid this the 'NoSystemBackground' parameter can be
81
    // set to false. Then a normal non-modal dialog will be shown instead (#0002440).
82
    bool noBackground = App::GetApplication().GetParameterGroupByPath
83
        ("User parameter:BaseApp/Preferences/Expression")->GetBool("NoSystemBackground", false);
84

85
    if (noBackground) {
86
#if defined(Q_OS_MAC)
87
        setWindowFlags(Qt::Widget | Qt::Popup | Qt::FramelessWindowHint);
88
#else
89
        setWindowFlags(Qt::SubWindow | Qt::Widget | Qt::Popup | Qt::FramelessWindowHint);
90
#endif
91
        setAttribute(Qt::WA_NoSystemBackground, true);
92
        setAttribute(Qt::WA_TranslucentBackground, true);
93
    }
94
    else {
95
        ui->expression->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
96
        ui->horizontalSpacer_3->changeSize(0, 2);
97
        ui->verticalLayout->setContentsMargins(9, 9, 9, 9);
98
        this->adjustSize();
99
        // It is strange that (at least on Linux) DlgExpressionInput will shrink
100
        // to be narrower than ui->expression after calling adjustSize() above.
101
        // Why?
102
        if(this->width() < ui->expression->width() + 18)
103
            this->resize(ui->expression->width()+18,this->height());
104
    }
105
    ui->expression->setFocus();
106
}
107

108
DlgExpressionInput::~DlgExpressionInput()
109
{
110
    delete ui;
111
}
112

113
void NumberRange::setRange(double min, double max)
114
{
115
    minimum = min;
116
    maximum = max;
117
    defined = true;
118
}
119

120
void NumberRange::clearRange()
121
{
122
    defined = false;
123
}
124

125
void NumberRange::throwIfOutOfRange(const Base::Quantity& value) const
126
{
127
    if (!defined)
128
        return;
129

130
    if (value.getValue() < minimum || value.getValue() > maximum) {
131
        Base::Quantity minVal(minimum, value.getUnit());
132
        Base::Quantity maxVal(maximum, value.getUnit());
133
        QString valStr = value.getUserString();
134
        QString minStr = minVal.getUserString();
135
        QString maxStr = maxVal.getUserString();
136
        QString error = QString::fromLatin1("Value out of range (%1 out of [%2, %3])").arg(valStr, minStr, maxStr);
137

138
        throw Base::ValueError(error.toStdString());
139
    }
140
}
141

142
void DlgExpressionInput::setRange(double minimum, double maximum)
143
{
144
    numberRange.setRange(minimum, maximum);
145
}
146

147
void DlgExpressionInput::clearRange()
148
{
149
    numberRange.clearRange();
150
}
151

152
QPoint DlgExpressionInput::expressionPosition() const
153
{
154
    return ui->expression->pos();
155
}
156

157
void DlgExpressionInput::textChanged(const QString &text)
158
{
159
    if (text.isEmpty()) {
160
        ui->okBtn->setDisabled(true);
161
        ui->discardBtn->setDefault(true);
162
        return;
163
    }
164

165
    ui->okBtn->setDefault(true);
166

167
    try {
168
        //resize the input field according to text size
169
        QFontMetrics fm(ui->expression->font());
170
        int width = QtTools::horizontalAdvance(fm, text) + 15;
171
        if (width < minimumWidth)
172
            ui->expression->setMinimumWidth(minimumWidth);
173
        else
174
            ui->expression->setMinimumWidth(width);
175

176
        if(this->width() < ui->expression->minimumWidth())
177
            setMinimumWidth(ui->expression->minimumWidth());
178

179
        //now handle expression
180
        std::shared_ptr<Expression> expr(ExpressionParser::parse(path.getDocumentObject(), text.toUtf8().constData()));
181

182
        if (expr) {
183
            std::string error = path.getDocumentObject()->ExpressionEngine.validateExpression(path, expr);
184

185
            if (!error.empty())
186
                throw Base::RuntimeError(error.c_str());
187

188
            std::unique_ptr<Expression> result(expr->eval());
189

190
            expression = expr;
191
            ui->okBtn->setEnabled(true);
192
            ui->msg->clear();
193

194
            //set default palette as we may have read text right now
195
            ui->msg->setPalette(ui->okBtn->palette());
196

197
            auto * n = Base::freecad_dynamic_cast<NumberExpression>(result.get());
198
            if (n) {
199
                Base::Quantity value = n->getQuantity();
200
                QString msg = value.getUserString();
201

202
                if (!value.isValid()) {
203
                    throw Base::ValueError("Not a number");
204
                }
205
                else if (!impliedUnit.isEmpty()) {
206
                    if (!value.getUnit().isEmpty() && value.getUnit() != impliedUnit)
207
                        throw Base::UnitsMismatchError("Unit mismatch between result and required unit");
208

209
                    value.setUnit(impliedUnit);
210

211
                }
212
                else if (!value.getUnit().isEmpty()) {
213
                    msg += QString::fromUtf8(" (Warning: unit discarded)");
214

215
                    QPalette p(ui->msg->palette());
216
                    p.setColor(QPalette::WindowText, Qt::red);
217
                    ui->msg->setPalette(p);
218
                }
219

220
                numberRange.throwIfOutOfRange(value);
221

222
                ui->msg->setText(msg);
223
            }
224
            else {
225
                ui->msg->setText(Base::Tools::fromStdString(result->toString()));
226
            }
227

228
        }
229
    }
230
    catch (Base::Exception & e) {
231
        ui->msg->setText(QString::fromUtf8(e.what()));
232
        QPalette p(ui->msg->palette());
233
        p.setColor(QPalette::WindowText, Qt::red);
234
        ui->msg->setPalette(p);
235
        ui->okBtn->setDisabled(true);
236
    }
237
}
238

239
void DlgExpressionInput::setDiscarded()
240
{
241
    discarded = true;
242
    reject();
243
}
244

245
void DlgExpressionInput::setExpressionInputSize(int width, int height)
246
{
247
    if (ui->expression->minimumHeight() < height)
248
        ui->expression->setMinimumHeight(height);
249

250
    if (ui->expression->minimumWidth() < width)
251
        ui->expression->setMinimumWidth(width);
252

253
    minimumWidth = width;
254
}
255

256
void DlgExpressionInput::mouseReleaseEvent(QMouseEvent* ev)
257
{
258
    Q_UNUSED(ev);
259
}
260

261
void DlgExpressionInput::mousePressEvent(QMouseEvent* ev)
262
{
263
    Q_UNUSED(ev);
264

265
    // The 'FramelessWindowHint' is also set when the background is transparent.
266
    if (windowFlags() & Qt::FramelessWindowHint) {
267
        //we need to reject the dialog when clicked on the background. As the background is transparent
268
        //this is the expected behaviour for the user
269
        bool on = ui->expression->completerActive();
270
        if (!on)
271
            this->reject();
272
    }
273
}
274

275
void DlgExpressionInput::show()
276
{
277
    QDialog::show();
278
    this->activateWindow();
279
    ui->expression->selectAll();
280
}
281

282

283
#include "moc_DlgExpressionInput.cpp"
284

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

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

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

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