Bug Summary

File:librecad/src/ui/dialogs/entity/qg_dlg_mtext.cpp
Warning:line 180, column 10
Value stored to 'leftToRight' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name qg_dlg_mtext.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/runner/work/LibreCAD/LibreCAD/librecad/src -fcoverage-compilation-dir=/home/runner/work/LibreCAD/LibreCAD/librecad/src -resource-dir /usr/lib/llvm-21/lib/clang/21 -D _REENTRANT -D DWGSUPPORT -D MUPARSER_STATIC -D LC_WITH_OPENTYPE=0 -D QC_APPDIR=librecad -D LC_VERSION=2.2.2_alpha1-853-ge2a8c2931 -D LC_PRERELEASE=true; -D QT_NO_DEBUG -D QT_SVG_LIB -D QT_PRINTSUPPORT_LIB -D QT_WIDGETS_LIB -D QT_GUI_LIB -D QT_NETWORK_LIB -D QT_CORE_LIB -I . -I /usr/include -I ../../libraries/lciconengine -I ../../libraries/libdxfrw/src -I ../../libraries/libdxfrw/src/intern -I ../../libraries/jwwlib/src -I ../../libraries/shapelib/src -I ../../libraries/qtbidi -I cmd -I lib/actions -I lib/actions/visual_snap -I lib/actions/options -I lib/creation -I lib/debug -I lib/engine -I lib/engine/document -I lib/engine/document/blocks -I lib/engine/document/container -I lib/engine/document/dimstyles -I lib/engine/document/entities -I lib/engine/document/entities/support -I lib/engine/document/fonts -I lib/engine/document/io -I lib/engine/document/layers -I lib/engine/document/linetypes -I lib/engine/document/patterns -I lib/engine/document/selection -I lib/engine/document/textstyles -I lib/engine/document/ucs -I lib/engine/document/variables -I lib/engine/document/views -I lib/engine/clipboard -I lib/engine/overlays -I lib/engine/overlays/angles_base -I lib/engine/overlays/highlight -I lib/engine/overlays/preview -I lib/engine/overlays/references -I lib/engine/overlays/crosshair -I lib/engine/overlays/info_cursor -I lib/engine/overlays/overlay_box -I lib/engine/overlays/ucs_mark -I lib/engine/undo -I lib/engine/utils -I lib/engine/settings -I lib/fileio -I lib/filters -I lib/generators -I lib/generators/makercamsvg -I lib/generators/layers -I lib/generators/image -I lib/gui -I lib/gui/grid -I lib/gui/render -I lib/gui/render/headless -I lib/gui/render/widget -I lib/information -I lib/math -I lib/modification -I lib/selection -I lib/selection/metaentity -I lib/selection/metaentity/entities -I lib/printing -I lib/properties -I actions -I actions/dock_widgets -I actions/dock_widgets/block -I actions/dock_widgets/entity_info -I actions/dock_widgets/layer -I actions/dock_widgets/library -I actions/dock_widgets/ucs_list -I actions/drawing -I actions/drawing/draw -I actions/drawing/draw/arc -I actions/drawing/draw/circle -I actions/drawing/draw/curve -I actions/drawing/draw/spline -I actions/drawing/draw/dimensions -I actions/drawing/draw/ellipse -I actions/drawing/draw/hatch -I actions/drawing/draw/image -I actions/drawing/draw/line -I actions/drawing/draw/point -I actions/drawing/draw/rect -I actions/drawing/draw/polygon -I actions/drawing/draw/misc -I actions/drawing/draw/line/shapes -I actions/drawing/draw/line/misc -I actions/drawing/draw/line/shapes/rect -I actions/drawing/draw/line/shapes/polygon -I actions/drawing/draw/polyline -I actions/drawing/draw/text -I actions/drawing/edit -I actions/drawing/info -I actions/drawing/pick -I actions/drawing/modify -I actions/drawing/pen -I actions/drawing/rel_zero -I actions/drawing/selection -I actions/drawing/snap -I actions/drawing/zoom -I actions/file -I actions/options -I actions/print_preview -I ui -I ui/action_options -I ui/action_options/circle -I ui/action_options/curve -I ui/action_options/spline -I ui/action_options/dimensions -I ui/action_options/edit -I ui/action_options/image -I ui/action_options/info -I ui/action_options/insert -I ui/action_options/line -I ui/action_options/rect -I ui/action_options/polygon -I ui/action_options/misc -I ui/action_options/modify -I ui/action_options/ellipse -I ui/action_options/other -I ui/action_options/polyline -I ui/action_options/point -I ui/action_options/print_preview -I ui/action_options/selection -I ui/action_options/snap -I ui/action_options/text -I ui/actions -I ui/components -I ui/components/relative_position_assistant -I ui/components/comboboxes -I ui/components/containers -I ui/components/creators -I ui/components/layouts -I ui/components/pen -I ui/components/status_bar -I ui/components/toolbars -I ui/components/utils -I ui/dialogs -I ui/dialogs/actions -I ui/dialogs/actions/modify -I ui/dialogs/actions/quick_selection -I ui/dialogs/modify -I ui/dialogs/entity -I ui/dialogs/creators -I ui/dialogs/file -I ui/dialogs/file/export -I ui/dialogs/file/export/layers -I ui/dialogs/file/export/image -I ui/dialogs/file/export/makercam -I ui/dialogs/main -I ui/dialogs/settings -I ui/dialogs/settings/dimstyles -I ui/dialogs/settings/dimstyles/dimstyle_manager -I ui/dialogs/settings/dimstyles/dimstyle_manager/support -I ui/dialogs/settings/options_device -I ui/dialogs/settings/options_drawing -I ui/dialogs/settings/options_general -I ui/dialogs/settings/options_widget -I ui/dialogs/settings/shortcuts -I ui/dock_widgets -I ui/dock_widgets/block_widget -I ui/dock_widgets/command_line -I ui/dock_widgets/entity_info -I ui/dock_widgets/layer_widget -I ui/dock_widgets/layers_tree -I ui/dock_widgets/library_widget -I ui/dock_widgets/pen_palette -I ui/dock_widgets/pen_wizard -I ui/dock_widgets/property_sheet -I ui/dock_widgets/property_sheet/lib -I ui/dock_widgets/property_sheet/lib/properties -I ui/dock_widgets/property_sheet/lib/view -I ui/dock_widgets/property_sheet/lib/view/edit -I ui/dock_widgets/property_sheet/lib/widgets -I ui/dock_widgets/property_sheet/lib/widgets/sheet -I ui/dock_widgets/property_sheet/metaentity -I ui/dock_widgets/property_sheet/metaentity/entities -I ui/dock_widgets/property_sheet/metaentity/entities/document -I ui/dock_widgets/property_sheet/properties -I ui/dock_widgets/property_sheet/properties/action -I ui/dock_widgets/property_sheet/properties/bool -I ui/dock_widgets/property_sheet/properties/color -I ui/dock_widgets/property_sheet/properties/double -I ui/dock_widgets/property_sheet/properties/enum -I ui/dock_widgets/property_sheet/properties/int -I ui/dock_widgets/property_sheet/properties/layer -I ui/dock_widgets/property_sheet/properties/linetype -I ui/dock_widgets/property_sheet/properties/linewidth -I ui/dock_widgets/property_sheet/properties/rect -I ui/dock_widgets/property_sheet/properties/rsvector -I ui/dock_widgets/property_sheet/properties/string -I ui/dock_widgets/views_list -I ui/dock_widgets/ucs_list -I ui/dock_widgets/workspaces -I ui/dock_widgets/cad -I ui/main -I ui/main/init -I ui/main/persistence -I ui/main/release_check -I ui/main/support -I ui/main/fontviewer -I ui/main/workspaces -I ui/view -I main -I main/console_dxf2pdf -I test -I plugins -I ../res -I ../res/arrows -I ../res/controls -I ../res/dxf -I ../res/gdt -I ../res/icons -I ../res/images -I ../../../Qt/6.9.0/gcc_64/include -I ../../../Qt/6.9.0/gcc_64/include/QtSvg -I ../../../Qt/6.9.0/gcc_64/include/QtPrintSupport -I ../../../Qt/6.9.0/gcc_64/include/QtWidgets -I ../../../Qt/6.9.0/gcc_64/include/QtGui -I ../../../Qt/6.9.0/gcc_64/include/QtNetwork -I ../../../Qt/6.9.0/gcc_64/include/QtCore -I ../../generated/librecad/moc -I ../../generated/librecad/ui -I ../../../Qt/6.9.0/gcc_64/mkspecs/linux-g++ -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/x86_64-linux-gnu/c++/15 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/backward -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=gnu++1z -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/runner/work/LibreCAD/LibreCAD/out/2026-11-06-031751-4837-1 -x c++ ui/dialogs/entity/qg_dlg_mtext.cpp
1/****************************************************************************
2**
3** This file is part of the LibreCAD project, a 2D CAD program
4**
5** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
6** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
7**
8**
9** This file may be distributed and/or modified under the terms of the
10** GNU General Public License version 2 as published by the Free Software
11** Foundation and appearing in the file gpl-2.0.txt included in the
12** packaging of this file.
13**
14** This program is distributed in the hope that it will be useful,
15** but WITHOUT ANY WARRANTY; without even the implied warranty of
16** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17** GNU General Public License for more details.
18**
19** You should have received a copy of the GNU General Public License
20** along with this program; if not, write to the Free Software
21** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22**
23** This copyright notice MUST APPEAR in all copies of the script!
24**
25**********************************************************************/
26
27
28#include "qg_dlg_mtext.h"
29#include "lc_textedit.h"
30
31#include <QFileDialog>
32#include <QShortcut>
33
34#include "lc_linemath.h"
35#include "rs_font.h"
36#include "rs_fontlist.h"
37#include "rs_graphic.h"
38#include "rs_settings.h"
39
40/*
41 * Constructs a QG_DlgMText as a child of 'parent', with the
42 * name 'name' and widget flags set to 'f'.
43 *
44 * The dialog will by default be modeless, unless you set 'modal' to
45 * true to construct a modal dialog.
46 */
47QG_DlgMText::QG_DlgMText(QWidget *parent, LC_GraphicViewport *viewport, RS_MText* mtext, bool forNew)
48 :LC_EntityPropertiesDlg(parent, "MTextProperties", viewport){
49 setupUi(this);
50 auto *focusNext = new QShortcut(QKeySequence("Ctrl+Tab"), teText);
51 focusNext->setContext(Qt::WidgetShortcut);
52 connect(focusNext, &QShortcut::activated, this, [this] { focusNextPrevChild(true); });
53 m_alignmentButtons = {{bTL, bTC, bTR, bML, bMC, bMR, bBL, bBC, bBR}};
54 init();
55 setEntity(mtext, forNew);
56}
57
58QG_DlgMText::~QG_DlgMText()
59{
60 try {
61 destroy();
62 } catch(...)
63 {}
64}
65
66/*
67 * Sets the strings of the subwidgets using the current
68 * language.
69 */
70void QG_DlgMText::languageChange(){
71 retranslateUi(this);
72}
73
74void QG_DlgMText::init() {
75 cbFont->init();
76 m_font = nullptr;
77 m_entity = nullptr;
78 m_isNew = false;
79 updateUniCharComboBox(0);
80 updateUniCharButton(0);
81
82 /*
83 * Ensure tabbing order of the widgets is as we would like. Using the Edit
84 * Tab Order tool in Qt Designer omits the "pen" compound widget from the
85 * tabbing list (as the tool is not aware that this user-written widget is a
86 * tabbable thing). The .ui file can be manually edited, but then if Qt
87 * Designer is used again to alter the layout, the pen widget gets dropped
88 * out of the order once more. Seems that the only reliable way of ensuring
89 * the order is correct is to set it programmatically.
90 */
91 std::array<QWidget*,31> buttons{cbLayer, wPen, cbFont,
92 leHeight, cbDefault, leLineSpacingFactor,
93 teText, bTL, bTC,
94 bTR, bML, bMC,
95 bMR, bBL, bBC,
96 bBR, leAngle, rbLeftToRight,
97 rbRightToLeft, cbSymbol, cbUniPage,
98 cbUniChar, bUnicode, buttonBox,
99 bClear, bLoad, bSave,
100 bCut, bCopy, bPaste};
101 // the order is cyclic
102 buttons[30] = buttons.front();
103 for (auto it = std::next(buttons.cbegin()); it != buttons.cend(); ++it) {
104 setTabOrder(*std::prev(it), *it);
105 }
106
107 /*
108 * We are using the frame colour of the teText QTextEdit widget to indicate when
109 * this is the selected widget - there is no automatic highlight of this widget
110 * class on selection. Ensure that known state of frame on start, and install Qt
111 * Event filter in order to get callback on focus in/out of the widget.
112 */
113 teText->setLineWidth(2);
114 teText->setMidLineWidth(0);
115 teText->setFrameStyle(QFrame::Box|QFrame::Plain);
116 teText->installEventFilter(this);
117
118 // events
119 connect(rbLeftToRight, &QRadioButton::toggled, this, &QG_DlgMText::layoutDirectionChanged);
120}
121
122
123void QG_DlgMText::updateUniCharComboBox(int) const {
124 const QString t = cbUniPage->currentText();
125 const int i1 = t.indexOf('-');
126 const int i2 = t.indexOf(']');
127 const int min = t.mid(1, i1-1).toInt(nullptr, 16);
128 const int max = t.mid(i1+1, i2-i1-1).toInt(nullptr, 16);
129
130 cbUniChar->clear();
131 for (int c=min; c<=max; c++) {
132 cbUniChar->addItem(QString{"[%1] %2"}.arg(c, 4, 16, QChar{'0'}).arg(QChar{c}));
133 }
134}
135
136//set saveText to false, so, settings won't be saved during destroy, feature request#3445306
137void QG_DlgMText::reject() {
138 m_saveSettings=false;
139 QDialog::reject();
140}
141
142void QG_DlgMText::destroy() const {
143 if (m_saveSettings) {
144 LC_GROUP_GUARDauto _guard_settings = RS_Settings::instance()->beginGroupGuard("Draw");
145 {
146 LC_SETRS_Settings::instance()->write("TextHeight", leHeight->text());
147 LC_SETRS_Settings::instance()->write("TextFont", cbFont->currentText());
148 LC_SETRS_Settings::instance()->write("TextDefault", cbDefault->isChecked());
149 LC_SETRS_Settings::instance()->write("TextAlignment", getAlignment());
150 //RS_SETTINGS->writeEntry("/TextLetterSpacing", leLetterSpacing->text());
151 //RS_SETTINGS->writeEntry("/TextWordSpacing", leWordSpacing->text());
152 LC_SETRS_Settings::instance()->write("TextLineSpacingFactor", leLineSpacingFactor->text());
153 const bool ltr = rbLeftToRight->isChecked();
154 LC_SETRS_Settings::instance()->write("TextString", teText->toPlainText());
155 //RS_SETTINGS->writeEntry("/TextShape", getShape());
156 LC_SETRS_Settings::instance()->write("TextAngle", leAngle->text());
157 //RS_SETTINGS->writeEntry("/TextRadius", leRadius->text());
158 LC_SETRS_Settings::instance()->write("TextLeftToRight", ltr);
159 }
160 }
161}
162
163/**
164 * Sets the text m_entity represented by this dialog.
165 */
166void QG_DlgMText::setEntity(RS_MText* t, const bool isNew) {
167 m_entity = t;
168 m_isNew = isNew;
169
170 QString font;
171 QString height;
172 QString def;
173 QString alignment;
174 //QString letterSpacing;
175 //QString wordSpacing;
176 QString lineSpacingFactor;
177 QString str;
178 //QString shape;
179 QString angle;
180 bool leftToRight = locale().textDirection() == Qt::LeftToRight;
Value stored to 'leftToRight' during its initialization is never read
181
182 if (isNew) {
183 wPen->hide();
184 lLayer->hide();
185 cbLayer->hide();
186 LC_GROUPRS_Settings::instance()->beginGroup("Draw");
187 {
188 //default font depending on locale
189 //default font depending on locale (RLZ-> check this: QLocale::system().name() returns "fr_FR")
190 // QByteArray iso = RS_System::localeToISO(QLocale::system().name().toLocal8Bit());
191 font = LC_GET_STRRS_Settings::instance()->readStr("TextFont", RS_FontList::getDefaultFont());
192 height = LC_GET_STRRS_Settings::instance()->readStr("TextHeight", "1.0");
193 def = LC_GET_STRRS_Settings::instance()->readStr("TextDefault", "1");
194 alignment = LC_GET_STRRS_Settings::instance()->readStr("TextAlignment", "1");
195 //letterSpacing = RS_SETTINGS->readEntry("/TextLetterSpacing", "0");
196 //wordSpacing = RS_SETTINGS->readEntry("/TextWordSpacing", "0");
197 lineSpacingFactor = LC_GET_STRRS_Settings::instance()->readStr("TextLineSpacingFactor", "1");
198 str = LC_GET_STRRS_Settings::instance()->readStr("TextString", "");
199 //shape = RS_SETTINGS->readEntry("/TextShape", "0");
200 angle = LC_GET_STRRS_Settings::instance()->readStr("TextAngle", "0");
201 //radius = RS_SETTINGS->readEntry("/TextRadius", "10");
202 leftToRight = LC_GET_BOOLRS_Settings::instance()->readBool("TextLeftToRight", true);
203 }
204 } else {
205 font = m_entity->getStyle();
206 setFont(font);
207 height = QString::number(m_entity->getHeight());
208 if (m_font != nullptr) {
209 if (LC_LineMath::isSameLength(m_font->getLineSpacingFactor(),m_entity->getLineSpacingFactor())) {
210 def = "1";
211 } else {
212 def = "0";
213 }
214 }
215 alignment = QString::number(m_entity->getAlignment());
216 //QString letterSpacing = RS_SETTINGS->readEntry("/TextLetterSpacing", "0");
217 //QString wordSpacing = RS_SETTINGS->readEntry("/TextWordSpacing", "0");
218 lineSpacingFactor = QString::number(m_entity->getLineSpacingFactor());
219
220/* // Doesn't make sense. We don't want to show native DXF strings in the Dialog.
221#if defined(OOPL_VERSION) && defined(Q_WS_WIN)
222 QCString iso = RS_System::localeToISO( QTextCodec::locale() );
223 QTextCodec *codec = QTextCodec::codecForName(iso);
224 if (codec) {
225 str = codec->toUnicode(RS_FilterDXF::toNativeString(text->getText().local8Bit()));
226 } else {
227 str = RS_FilterDXF::toNativeString(text->getText().local8Bit());
228 }
229#else*/
230 str = m_entity->getText();
231//#endif
232 //QString shape = RS_SETTINGS->readEntry("/TextShape", "0");
233
234 const double wcsAngle = m_entity->getAngle();
235 angle = toUIAngleDeg(wcsAngle);
236
237 RS_Graphic* graphic = m_entity->getGraphic();
238 if (graphic != nullptr) {
239 const auto layerList = graphic->getLayerList();
240 cbLayer->init(*layerList, false, false);
241 }
242
243 RS_Layer* layer = m_entity->getLayer(false);
244 if (layer != nullptr) {
245 cbLayer->setLayer(*layer);
246 }
247
248 wPen->setPen(m_entity, layer, tr("Pen"));
249 leftToRight = m_entity->getDrawingDirection() != RS_MTextData::RightToLeft;
250 }
251
252 cbDefault->setChecked(def=="1");
253 setFont(font);
254 leHeight->setText(height);
255 const unsigned index = alignment.toUInt() - 1;
256 setAlignment(*m_alignmentButtons[index%m_alignmentButtons.size()]);
257 if (def!="1" || m_font==nullptr) {
258 //leLetterSpacing->setText(letterSpacing);
259 //leWordSpacing->setText(wordSpacing);
260 leLineSpacingFactor->setText(lineSpacingFactor);
261 } else {
262 //leLetterSpacing->setText(font->getLetterSpacing());
263 //leWordSpacing->setText(font->getWordSpacing());
264 leLineSpacingFactor->setText(
265 QString::number(m_font->getLineSpacingFactor()));
266 }
267 teText->setPlainText(str);
268 //setShape(shape.toInt());
269 leAngle->setText(angle);
270 //leRadius->setText(radius);
271 teText->setFocus();
272 teText->selectAll();
273 // Loading the controls must not change the entity's direction.
274 {
275 QSignalBlocker bL(rbLeftToRight);
276 QSignalBlocker bR(rbRightToLeft);
277 rbLeftToRight->setChecked(leftToRight);
278 rbRightToLeft->setChecked(!leftToRight);
279 }
280 applyDirectionVisuals();
281}
282
283void QG_DlgMText::layoutDirectionChanged() const
284{
285 const bool leftToRight = rbLeftToRight->isChecked();
286 rbRightToLeft->setChecked(!leftToRight);
287 if (m_entity != nullptr) {
288 m_entity->setDrawingDirection(leftToRight ? RS_MTextData::LeftToRight
289 : RS_MTextData::RightToLeft);
290 }
291 applyDirectionVisuals();
292}
293
294void QG_DlgMText::applyDirectionVisuals() const {
295 const bool leftToRight = rbLeftToRight->isChecked();
296 teText->setTextDirection(leftToRight ? Qt::LeftToRight : Qt::RightToLeft);
297}
298
299/**
300 * Updates the text m_entity represented by the dialog to fit the choices of the user.
301 */
302void QG_DlgMText::updateEntity() {
303 if (m_entity == nullptr) {
304 return;
305 }
306
307 m_entity->setStyle(cbFont->currentText());
308 m_entity->setHeight(leHeight->text().toDouble());
309
310 //fix for windows (causes troubles if locale returns en_us):
311 /*#if defined(OOPL_VERSION) && defined(Q_WS_WIN)
312 QCString iso = RS_System::localeToISO( QTextCodec::locale() );
313 text->setText(
314 RS_FilterDXF::toNativeString(
315 QString::fromLocal8Bit( QTextCodec::codecForName( iso )->fromUnicode( teText->text() ) )
316 )
317 );
318#else*/
319 m_entity->setText(teText->toPlainText());
320 //#endif
321 //text->setLetterSpacing(leLetterSpacing.toDouble());
322 m_entity->setLineSpacingFactor(leLineSpacingFactor->text().toDouble());
323 m_entity->setAlignment(getAlignment());
324
325 const double wcsAngle = toWCSAngle(leAngle, m_entity->getAngle());
326 m_entity->setAngle(wcsAngle);
327
328 if (m_isNew || m_entity->getDrawingDirection() == RS_MTextData::LeftToRight ||
329 m_entity->getDrawingDirection() == RS_MTextData::RightToLeft) {
330 m_entity->setDrawingDirection(rbLeftToRight->isChecked() ? RS_MTextData::LeftToRight : RS_MTextData::RightToLeft);
331 }
332 if (!m_isNew) {
333 m_entity->setPen(wPen->getPen());
334 m_entity->setLayer(cbLayer->getLayer());
335 }
336 m_entity->update();
337}
338
339size_t QG_DlgMText::alignmentButtonIdex(const QToolButton* button) const
340{
341 const auto it = std::find(m_alignmentButtons.cbegin(), m_alignmentButtons.cend(), button);
342 return it == m_alignmentButtons.cend() ? 0 : std::distance(m_alignmentButtons.cbegin(), it);
343}
344
345void QG_DlgMText::setAlignmentTL() {
346 setAlignment(*bTL);
347}
348
349void QG_DlgMText::setAlignmentTC() {
350 setAlignment(*bTC);
351}
352
353void QG_DlgMText::setAlignmentTR() {
354 setAlignment(*bTR);
355}
356
357void QG_DlgMText::setAlignmentML() {
358 setAlignment(*bML);
359}
360
361void QG_DlgMText::setAlignmentMC() {
362 setAlignment(*bMC);
363}
364
365void QG_DlgMText::setAlignmentMR() {
366 setAlignment(*bMR);
367}
368
369void QG_DlgMText::setAlignmentBL() {
370 setAlignment(*bBL);
371}
372
373void QG_DlgMText::setAlignmentBC() {
374 setAlignment(*bBC);
375}
376
377void QG_DlgMText::setAlignmentBR() {
378 setAlignment(*bBR);
379}
380
381void QG_DlgMText::setAlignment(QToolButton& button) {
382 button.setChecked(true);
383}
384
385int QG_DlgMText::getAlignment() const {
386
387 const auto it = std::find_if(m_alignmentButtons.cbegin(), m_alignmentButtons.cend(), [](const QToolButton* button){
388 return button->isChecked();});
389 const int index = (it == m_alignmentButtons.cend()) ? 0 : std::distance(m_alignmentButtons.cbegin(), it);
390 return index + 1;
391}
392
393void QG_DlgMText::setFont(const QString& f) {
394 int index = cbFont->findText(RS_FontList::resolveFontName(f));
395
396 // Issue #2069: default to the last font, likely unicode fonts
397 if (index == -1) {
398 index = cbFont->findText("unicode");
399 }
400 if (index >= 0) {
401 cbFont->setCurrentIndex(index);
402 m_font = cbFont->getFont();
403 defaultChanged(false);
404 }
405}
406
407void QG_DlgMText::defaultChanged(bool) const {
408 if (cbDefault->isChecked() && m_font != nullptr) {
409 leLineSpacingFactor->setText(
410 QString::number(m_font->getLineSpacingFactor()));
411 }
412}
413
414void QG_DlgMText::loadText() {
415 const QString fn = QFileDialog::getOpenFileName(this);
416 if (!fn.isEmpty()) {
417 load(fn);
418 }
419}
420
421void QG_DlgMText::load(const QString& fn) const {
422 QFile f(fn);
423 if (!f.open(QIODevice::ReadOnly)) {
424 return;
425 }
426
427 QTextStream ts(&f);
428 const QString contents = ts.readAll();
429 teText->setPlainText(contents);
430}
431
432void QG_DlgMText::saveText() {
433 const QString fn = QFileDialog::getSaveFileName(this);
434 if (!fn.isEmpty()) {
435 save(fn);
436 }
437}
438
439void QG_DlgMText::save(const QString& fn) const {
440 const QString text = teText->toPlainText();
441 QFile f(fn);
442 if (f.open(QIODevice::WriteOnly)) {
443 QTextStream t(&f);
444 t << text;
445 f.close();
446 }
447}
448
449void QG_DlgMText::insertSymbol(int) const {
450 const QString str = cbSymbol->currentText();
451 const int i=str.indexOf('(');
452 if (i!=-1) {
453 teText->textCursor().insertText(str.mid(i+1, 1));
454 }
455}
456
457void QG_DlgMText::updateUniCharButton(int) const {
458 const QString t = cbUniChar->currentText();
459 const int i1 = t.indexOf(']');
460 const int c = t.mid(1, i1-1).toInt(nullptr, 16);
461 bUnicode->setText(QString{QChar{c}});
462}
463
464void QG_DlgMText::insertChar() const {
465 const QString t = cbUniChar->currentText();
466 const int i1 = t.indexOf(']');
467 const int c = t.mid(1, i1-1).toInt(nullptr, 16);
468 teText->textCursor().insertText( QString{QChar{c}} );
469}
470
471/*
472 * Event filter is used to detect focus in/out of the teText QTextEdit widget.
473 * On focus in set the widget frame highlighted, on focus out revert to normal.
474 */
475bool QG_DlgMText::eventFilter(QObject *obj, QEvent *event) {
476 const int type = event->type();
477 if (type == QEvent::FocusIn) {
478 if (obj == teText) {
479 QPalette palette = teText->palette();
480 const QColor color = palette.color(QPalette::Highlight);
481 palette.setColor(QPalette::WindowText, color);
482 teText->setPalette(palette);
483 }
484 } else if (type == QEvent::FocusOut) {
485 if (obj == teText) {
486 QPalette palette = teText->palette();
487 const QColor color = palette.color(QPalette::Dark);
488 palette.setColor(QPalette::WindowText, color);
489 teText->setPalette(palette);
490 }
491 }
492 return false;
493}