FreeCAD

Форк
0
/
mrichtextedit.cpp 
857 строк · 28.0 Кб
1
/*
2
** Copyright (C) 2013 Jiří Procházka (Hobrasoft)
3
** Contact: http://www.hobrasoft.cz/
4
**
5
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
6
** Contact: http://www.qt-project.org/legal
7
**
8
** $QT_BEGIN_LICENSE:LGPL$
9
** GNU Lesser General Public License Usage
10
** This file is under the terms of the GNU Lesser General Public License
11
** version 2.1 as published by the Free Software Foundation and appearing
12
** in the file LICENSE.LGPL included in the packaging of this file.
13
** Please review the following information to ensure the
14
** GNU Lesser General Public License version 2.1 requirements
15
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16
**
17
** In addition, as a special exception, Digia gives you certain additional
18
** rights.  These rights are described in the Digia Qt LGPL Exception
19
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20
**
21
** $QT_END_LICENSE$
22
*/
23

24
/********************************
25
 * includes changes by wandererfan@gmail.com
26
 * for FreeCAD project https://www.freecad.org/
27
 ********************************/
28

29
#include "PreCompiled.h"
30

31
#ifndef _PreComp_
32
# include <algorithm>
33
# include <iostream>
34
# include <QApplication>
35
# include <QBitmap>
36
# include <QClipboard>
37
# include <QColorDialog>
38
# include <QDialog>
39
# include <QFileDialog>
40
# include <QFontDatabase>
41
# include <QImageReader>
42
# include <QInputDialog>
43
# include <QMenu>
44
# include <QMimeData>
45
# include <QPlainTextEdit>
46
# include <QRegularExpression>
47
# include <QSettings>
48
# include <QTextList>
49
#endif
50

51
#include <App/Application.h>
52
#include <Base/Console.h>
53
#include <Base/Tools.h>
54
#include <Gui/FileDialog.h>
55
#include <Mod/TechDraw/App/Preferences.h>
56

57
#include "mrichtextedit.h"
58
#include "PreferencesGui.h"
59

60

61
using namespace TechDrawGui;
62
using namespace TechDraw;
63

64
MRichTextEdit::MRichTextEdit(QWidget *parent, QString textIn) : QWidget(parent) {
65
    setupUi(this);
66
    m_lastBlockList = nullptr;
67
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
68
    f_textedit->setTabStopWidth(40);
69
#else
70
    f_textedit->setTabStopDistance(40);
71
#endif
72
//    setDefFontSize(getDefFontSizeNum());
73
    setDefFontSize(TechDrawGui::PreferencesGui::labelFontSizePX());
74
    m_defFont = getDefFont().family();
75
    f_textedit->setFont(getDefFont());
76

77
    connect(f_save, &QToolButton::clicked,
78
            this, &MRichTextEdit::onSave);
79
    connect(f_exit, &QToolButton::clicked,
80
            this, &MRichTextEdit::onExit);
81

82
    connect(f_textedit, &MTextEdit::currentCharFormatChanged,
83
            this, &MRichTextEdit::slotCurrentCharFormatChanged);
84
    connect(f_textedit, &MTextEdit::cursorPositionChanged,
85
            this, &MRichTextEdit::slotCursorPositionChanged);
86
    connect(f_textedit, &MTextEdit::selectionChanged,
87
            this, &MRichTextEdit::onSelectionChanged);
88

89

90
    m_fontsize_h1 = m_defFontSize + 8;
91
    m_fontsize_h2 = m_defFontSize + 6;
92
    m_fontsize_h3 = m_defFontSize + 4;
93
    m_fontsize_h4 = m_defFontSize + 2;
94

95
//TODO: should check for existing text and set font to match
96
    fontChanged(getDefFont());
97
    bgColorChanged(f_textedit->textColor());
98

99
    // paragraph formatting
100
    m_paragraphItems    << tr("Standard")
101
                        << tr("Heading 1")
102
                        << tr("Heading 2")
103
                        << tr("Heading 3")
104
                        << tr("Heading 4")
105
                        << tr("Monospace")
106
                        << QString::fromUtf8(" ");
107
    f_paragraph->addItems(m_paragraphItems);
108

109
    connect(f_paragraph, qOverload<int>(&QComboBox::activated),
110
            this, &MRichTextEdit::textStyle);
111

112
    // undo & redo
113

114
    f_undo->setShortcut(QKeySequence::Undo);
115
    f_redo->setShortcut(QKeySequence::Redo);
116

117
    connect(f_textedit->document(), &QTextDocument::undoAvailable,
118
            f_undo, &QToolButton::setEnabled);
119
    connect(f_textedit->document(), &QTextDocument::redoAvailable,
120
            f_redo, &QToolButton::setEnabled);
121

122
    f_undo->setEnabled(f_textedit->document()->isUndoAvailable());
123
    f_redo->setEnabled(f_textedit->document()->isRedoAvailable());
124

125
    connect(f_undo, &QToolButton::clicked, f_textedit, &MTextEdit::undo);
126
    connect(f_redo, &QToolButton::clicked, f_textedit, &MTextEdit::redo);
127

128
    // cut, copy & paste
129

130
    f_cut->setShortcut(QKeySequence::Cut);
131
    f_copy->setShortcut(QKeySequence::Copy);
132
    f_paste->setShortcut(QKeySequence::Paste);
133

134
    f_cut->setEnabled(false);
135
    f_copy->setEnabled(false);
136

137
    connect(f_cut, &QToolButton::clicked, f_textedit, &MTextEdit::cut);
138
    connect(f_copy, &QToolButton::clicked, f_textedit, &MTextEdit::copy);
139
    connect(f_paste, &QToolButton::clicked, f_textedit, &MTextEdit::paste);
140

141
    connect(f_textedit, &MTextEdit::copyAvailable, f_cut, &QToolButton::setEnabled);
142
    connect(f_textedit, &MTextEdit::copyAvailable, f_copy, &QToolButton::setEnabled);
143

144
#ifndef QT_NO_CLIPBOARD
145
    connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &MRichTextEdit::slotClipboardDataChanged);
146
#endif
147

148
    // link
149

150
    f_link->setShortcut(QKeySequence(QString::fromUtf8("CTRL+L")));
151

152
    connect(f_link, &QToolButton::clicked, this, &MRichTextEdit::textLink);
153

154
    // bold, italic & underline
155

156
    f_bold->setShortcut(QKeySequence(QString::fromUtf8("CTRL+B")));
157
    f_italic->setShortcut(QKeySequence(QString::fromUtf8("CTRL+I")));
158
    f_underline->setShortcut(QKeySequence(QString::fromUtf8("CTRL+U")));
159

160
    connect(f_bold, &QToolButton::clicked, this, &MRichTextEdit::textBold);
161
    connect(f_italic, &QToolButton::clicked, this, &MRichTextEdit::textItalic);
162
    connect(f_underline, &QToolButton::clicked, this, &MRichTextEdit::textUnderline);
163
    connect(f_strikeout, &QToolButton::clicked, this, &MRichTextEdit::textStrikeout);
164

165
    QAction *removeFormat = new QAction(tr("Remove character formatting"), this);
166
    removeFormat->setShortcut(QKeySequence(QString::fromUtf8("CTRL+M")));
167
    connect(removeFormat, &QAction::triggered, this, &MRichTextEdit::textRemoveFormat);
168
    f_textedit->addAction(removeFormat);
169

170
    QAction *removeAllFormat = new QAction(tr("Remove all formatting"), this);
171
    connect(removeAllFormat, &QAction::triggered, this, &MRichTextEdit::textRemoveAllFormat);
172
    f_textedit->addAction(removeAllFormat);
173

174
    QAction *textsource = new QAction(tr("Edit document source"), this);
175
    textsource->setShortcut(QKeySequence(QString::fromUtf8("CTRL+O")));
176
    connect(textsource, &QAction::triggered, this, &MRichTextEdit::textSource);
177
    f_textedit->addAction(textsource);
178

179
    QMenu *menu = new QMenu(this);
180
    menu->addAction(removeAllFormat);
181
    menu->addAction(removeFormat);
182
    menu->addAction(textsource);
183
    f_menu->setMenu(menu);
184
    f_menu->setPopupMode(QToolButton::InstantPopup);
185

186
    // lists
187

188
    f_list_bullet->setShortcut(QKeySequence(QString::fromUtf8("CTRL+-")));
189
    f_list_ordered->setShortcut(QKeySequence(QString::fromUtf8("CTRL+=")));
190

191
    connect(f_list_bullet, &QToolButton::clicked, this, &MRichTextEdit::listBullet);
192
    connect(f_list_ordered, &QToolButton::clicked, this, &MRichTextEdit::listOrdered);
193

194
    // indentation
195

196
    f_indent_dec->setShortcut(QKeySequence(QString::fromUtf8("CTRL+, ")));
197
    f_indent_inc->setShortcut(QKeySequence(QString::fromUtf8("CTRL+.")));
198

199
    connect(f_indent_inc, &QToolButton::clicked, this, &MRichTextEdit::increaseIndentation);
200
    connect(f_indent_dec, &QToolButton::clicked, this, &MRichTextEdit::decreaseIndentation);
201

202
    // font size
203

204
    const auto sizes = QFontDatabase::standardSizes();
205
    for(int size: sizes) {
206
        f_fontsize->addItem(QString::number(size));
207
    }
208
    //TODO: void QComboBox::setEditText(const QString &text) to " " when multiple select
209
#if QT_VERSION < QT_VERSION_CHECK(5,15,0)
210
    connect(f_fontsize, qOverload<const QString&>(&QComboBox::currentIndexChanged),
211
            this, &MRichTextEdit::textSize);
212
#else
213
    connect(f_fontsize, qOverload<int>(&QComboBox::currentIndexChanged), this, [=](int index) {
214
        textSize(f_fontsize->itemText(index));
215
    });
216
#endif
217

218
    // text foreground color
219

220
    connect(f_fgcolor, &QToolButton::clicked, this, &MRichTextEdit::textFgColor);
221

222
    // text background color
223

224
    connect(f_bgcolor, &QToolButton::clicked, this, &MRichTextEdit::textBgColor);
225

226
    // images
227
    connect(f_image, &QToolButton::clicked, this, &MRichTextEdit::insertImage);
228

229
    //set initial font size when editing existing text
230
    if (!textIn.isEmpty()) {
231
        //insert existing text with cursor at beginning
232
        QTextCursor cursor = f_textedit->textCursor();
233
        cursor.movePosition(QTextCursor::Start);
234
        cursor.insertHtml(textIn);
235
        cursor.movePosition(QTextCursor::Start);
236
        f_textedit->setTextCursor(cursor);
237

238
        //set current font size to match inserted text at cursor pos
239
        QTextCharFormat fmt = cursor.charFormat();
240
        double currSize = fmt.fontPointSize();
241
        int intSize = round(currSize);
242
        QString qsSize = QString::number(intSize);
243
        addFontSize(qsSize);
244
        int fSize = f_fontsize->findText(qsSize);
245
        f_fontsize  ->setCurrentIndex(fSize);
246
    } else {
247
        QTextCursor cursor = f_textedit->textCursor();
248
        cursor.movePosition(QTextCursor::Start);
249
        f_textedit->setTextCursor(cursor);
250

251
        QTextCharFormat fmt = cursor.charFormat();
252
        fmt.setFontPointSize(getDefFontSizeNum());
253

254
        addFontSize(getDefFontSize());
255

256
        f_fontsize->setCurrentIndex(f_fontsize->findText(getDefFontSize()));
257
    }
258

259
}
260

261

262
void MRichTextEdit::textSource() {
263
    QDialog *dialog = new QDialog(this);
264
    QPlainTextEdit *pte = new QPlainTextEdit(dialog);
265
    pte->setPlainText( f_textedit->toHtml() );
266
    QGridLayout *gl = new QGridLayout(dialog);
267
    gl->addWidget(pte, 0,0, 1,1);
268
    dialog->setWindowTitle(tr("Document source"));
269
    dialog->setMinimumWidth (400);
270
    dialog->setMinimumHeight(600);
271
    dialog->exec();
272

273
    f_textedit->setHtml(pte->toPlainText());
274

275
    delete dialog;
276
}
277

278

279
void MRichTextEdit::textRemoveFormat() {
280
    QTextCharFormat fmt;
281
    fmt.setFontWeight(QFont::Normal);
282
    fmt.setFontUnderline  (false);
283
    fmt.setFontStrikeOut  (false);
284
    fmt.setFontItalic     (false);
285
    fmt.setFontPointSize  (m_defFontSize);
286
//  fmt.setFontFamily     ("Helvetica");
287
//  fmt.setFontStyleHint  (QFont::SansSerif);
288
//  fmt.setFontFixedPitch (true);
289

290
    f_bold      ->setChecked(false);
291
    f_underline ->setChecked(false);
292
    f_italic    ->setChecked(false);
293
    f_strikeout ->setChecked(false);
294
    f_fontsize  ->setCurrentIndex(f_fontsize->findText(getDefFontSize()));
295

296
//  QTextBlockFormat bfmt = cursor.blockFormat();
297
//  bfmt->setIndent(0);
298

299
    fmt.clearBackground();
300

301
    mergeFormatOnWordOrSelection(fmt);
302
}
303

304

305
void MRichTextEdit::textRemoveAllFormat() {
306
    f_bold      ->setChecked(false);
307
    f_underline ->setChecked(false);
308
    f_italic    ->setChecked(false);
309
    f_strikeout ->setChecked(false);
310
    f_fontsize  ->setCurrentIndex(f_fontsize->findText(getDefFontSize()));
311
    QString text = f_textedit->toPlainText();
312
    f_textedit->setPlainText(text);
313
}
314

315

316
void MRichTextEdit::textBold() {
317
    QTextCharFormat fmt;
318
    fmt.setFontWeight(f_bold->isChecked() ? QFont::Bold : QFont::Normal);
319
    mergeFormatOnWordOrSelection(fmt);
320
}
321

322

323
void MRichTextEdit::focusInEvent(QFocusEvent *) {
324
    f_textedit->setFocus(Qt::TabFocusReason);
325
}
326

327
void MRichTextEdit::keyPressEvent(QKeyEvent *event) {
328
    if (event->key() == Qt::Key_Return && event->modifiers() == Qt::ControlModifier) {
329
        onSave();
330
        return;
331
    }
332

333
    QWidget::keyPressEvent(event);
334
}
335

336

337
void MRichTextEdit::textUnderline() {
338
    QTextCharFormat fmt;
339
    fmt.setFontUnderline(f_underline->isChecked());
340
    mergeFormatOnWordOrSelection(fmt);
341
}
342

343
void MRichTextEdit::textItalic() {
344
    QTextCharFormat fmt;
345
    fmt.setFontItalic(f_italic->isChecked());
346
    mergeFormatOnWordOrSelection(fmt);
347
}
348

349
void MRichTextEdit::textStrikeout() {
350
    QTextCharFormat fmt;
351
    fmt.setFontStrikeOut(f_strikeout->isChecked());
352
    mergeFormatOnWordOrSelection(fmt);
353
}
354

355
void MRichTextEdit::textSize(const QString &pointsAsString) {
356
//    qDebug() << "MRTE::textSize(" << p << ")";
357
    qreal pointSize = pointsAsString.toFloat();
358
    if (pointsAsString.toFloat() > 0) {
359
        QTextCharFormat fmt;
360
        fmt.setFontPointSize(pointSize);
361
        mergeFormatOnWordOrSelection(fmt);
362
    }
363
}
364

365
void MRichTextEdit::textLink(bool checked) {
366
    bool unlink = false;
367
    QTextCharFormat fmt;
368
    if (checked) {
369
        QString url = f_textedit->currentCharFormat().anchorHref();
370
        bool ok;
371
        QString newUrl = QInputDialog::getText(this, tr("Create a link"),
372
                                        tr("Link URL:"), QLineEdit::Normal,
373
                                        url,
374
                                        &ok,
375
                                        Qt::MSWindowsFixedSizeDialogHint);
376
        if (ok) {
377
            fmt.setAnchor(true);
378
            fmt.setAnchorHref(newUrl);
379
            fmt.setForeground(QApplication::palette().color(QPalette::Link));
380
            fmt.setFontUnderline(true);
381
          } else {
382
            unlink = true;
383
            }
384
      } else {
385
        unlink = true;
386
        }
387
    if (unlink) {
388
        fmt.setAnchor(false);
389
        fmt.setForeground(QApplication::palette().color(QPalette::Text));
390
        fmt.setFontUnderline(false);
391
        }
392
    mergeFormatOnWordOrSelection(fmt);
393
}
394

395
void MRichTextEdit::textStyle(int index) {
396
    //TODO: would prefer select font vs paragraph style.
397
    QTextCursor cursor = f_textedit->textCursor();
398
    cursor.beginEditBlock();
399

400
    // standard
401
    if (!cursor.hasSelection()) {
402
        cursor.select(QTextCursor::BlockUnderCursor);
403
        }
404
    QTextCharFormat fmt;
405
    cursor.setCharFormat(fmt);
406
    f_textedit->setCurrentCharFormat(fmt);
407

408
    if (index == ParagraphHeading1
409
            || index == ParagraphHeading2
410
            || index == ParagraphHeading3
411
            || index == ParagraphHeading4 ) {
412
        if (index == ParagraphHeading1) {
413
            fmt.setFontPointSize(m_fontsize_h1);
414
            }
415
        if (index == ParagraphHeading2) {
416
            fmt.setFontPointSize(m_fontsize_h2);
417
            }
418
        if (index == ParagraphHeading3) {
419
            fmt.setFontPointSize(m_fontsize_h3);
420
            }
421
        if (index == ParagraphHeading4) {
422
            fmt.setFontPointSize(m_fontsize_h4);
423
            }
424
        if (index == ParagraphHeading2 || index == ParagraphHeading4) {
425
            fmt.setFontItalic(true);
426
            }
427

428
        fmt.setFontWeight(QFont::Bold);
429
        }
430
    if (index == ParagraphMonospace) {
431
        fmt = cursor.charFormat();
432
#if QT_VERSION < QT_VERSION_CHECK(5,13,0)
433
        fmt.setFontFamily(QString::fromUtf8("Monospace"));
434
#else
435
        fmt.setFontFamilies(QStringList() << QString::fromUtf8("Monospace"));
436
#endif
437
        fmt.setFontStyleHint(QFont::Monospace);
438
        fmt.setFontFixedPitch(true);
439
        }
440
    cursor.setCharFormat(fmt);
441
    f_textedit->setCurrentCharFormat(fmt);
442

443
    cursor.endEditBlock();
444
}
445

446
void MRichTextEdit::textFgColor() {
447
    QColor col;
448
    if (Gui::DialogOptions::dontUseNativeColorDialog()){
449
        col = QColorDialog::getColor(f_textedit->textColor(), this, QLatin1String(""), QColorDialog::DontUseNativeDialog);
450
    } else {
451
        col = QColorDialog::getColor(f_textedit->textColor(), this);
452
    }
453
    QTextCursor cursor = f_textedit->textCursor();
454
    if (!cursor.hasSelection()) {
455
        cursor.select(QTextCursor::WordUnderCursor);
456
        }
457
    QTextCharFormat fmt = cursor.charFormat();
458
    if (col.isValid()) {
459
        fmt.setForeground(col);
460
      } else {
461
        fmt.clearForeground();
462
        }
463
    cursor.setCharFormat(fmt);
464
    f_textedit->setCurrentCharFormat(fmt);
465
    fgColorChanged(col);
466
}
467

468
void MRichTextEdit::textBgColor() {
469
    QColor col;
470
    if (Gui::DialogOptions::dontUseNativeColorDialog()){
471
        col = QColorDialog::getColor(f_textedit->textBackgroundColor(), this, QLatin1String(""), QColorDialog::DontUseNativeDialog);
472
    } else {
473
        col = QColorDialog::getColor(f_textedit->textBackgroundColor(), this);
474
    }
475
    QTextCursor cursor = f_textedit->textCursor();
476
    if (!cursor.hasSelection()) {
477
        cursor.select(QTextCursor::WordUnderCursor);
478
        }
479
    QTextCharFormat fmt = cursor.charFormat();
480
    if (col.isValid()) {
481
        fmt.setBackground(col);
482
      } else {
483
        fmt.clearBackground();
484
        }
485
    cursor.setCharFormat(fmt);
486
    f_textedit->setCurrentCharFormat(fmt);
487
    bgColorChanged(col);
488
}
489

490
void MRichTextEdit::listBullet(bool checked) {
491
    if (checked) {
492
        f_list_ordered->setChecked(false);
493
        }
494
    list(checked, QTextListFormat::ListDisc);
495
}
496

497
void MRichTextEdit::listOrdered(bool checked) {
498
    if (checked) {
499
        f_list_bullet->setChecked(false);
500
        }
501
    list(checked, QTextListFormat::ListDecimal);
502
}
503

504
void MRichTextEdit::list(bool checked, QTextListFormat::Style style) {
505
    QTextCursor cursor = f_textedit->textCursor();
506
    cursor.beginEditBlock();
507
    if (!checked) {
508
        QTextBlockFormat obfmt = cursor.blockFormat();
509
        QTextBlockFormat bfmt;
510
        bfmt.setIndent(obfmt.indent());
511
        cursor.setBlockFormat(bfmt);
512
      } else {
513
        QTextListFormat listFmt;
514
        if (cursor.currentList()) {
515
            listFmt = cursor.currentList()->format();
516
            }
517
        listFmt.setStyle(style);
518
        cursor.createList(listFmt);
519
        }
520
    cursor.endEditBlock();
521
}
522

523
void MRichTextEdit::mergeFormatOnWordOrSelection(const QTextCharFormat &format) {
524
    QTextCursor cursor = f_textedit->textCursor();
525
    if (!cursor.hasSelection()) {
526
        cursor.select(QTextCursor::WordUnderCursor);
527
        }
528
    cursor.mergeCharFormat(format);
529
    f_textedit->mergeCurrentCharFormat(format);
530
    f_textedit->setFocus(Qt::TabFocusReason);
531
}
532

533
void MRichTextEdit::slotCursorPositionChanged() {
534
//    qDebug() << "MRTE::slotCursorPositionChanged()";
535
    //why do we change text style when selecting text?
536
    QTextCursor cursor = f_textedit->textCursor();
537
    if (cursor.hasSelection()) {                       //let selection logic handle this
538
        return;
539
    }
540
    //set font size widget to match curr char size
541
    QTextCharFormat fmt = cursor.charFormat();
542
    double currSize = fmt.fontPointSize();
543
    int fSize = f_fontsize->findText(QString::number(currSize));
544
    f_fontsize  ->setCurrentIndex(fSize);
545

546
    QTextList *l = f_textedit->textCursor().currentList();
547

548
    if (m_lastBlockList &&
549
        (l == m_lastBlockList ||
550
        (l && m_lastBlockList && l->format().style() == m_lastBlockList->format().style()) ) ) {
551
        return;
552
    }
553
    m_lastBlockList = l;
554
    if (l) {
555
        QTextListFormat lfmt = l->format();
556
        if (lfmt.style() == QTextListFormat::ListDisc) {
557
            f_list_bullet->setChecked(true);
558
            f_list_ordered->setChecked(false);
559
          } else if (lfmt.style() == QTextListFormat::ListDecimal) {
560
            f_list_bullet->setChecked(false);
561
            f_list_ordered->setChecked(true);
562
          } else {
563
            f_list_bullet->setChecked(false);
564
            f_list_ordered->setChecked(false);
565
            }
566
      } else {
567
        f_list_bullet->setChecked(false);
568
        f_list_ordered->setChecked(false);
569
        }
570
}
571

572
void MRichTextEdit::fontChanged(const QFont &font) {
573
//    qDebug() << "MRTE::fontChanged()";
574
    //TODO: change this to real font selector
575
    f_fontsize->setCurrentIndex(f_fontsize->findText(QString::number(font.pointSize())));
576
    f_bold->setChecked(font.bold());
577
    f_italic->setChecked(font.italic());
578
    f_underline->setChecked(font.underline());
579
    f_strikeout->setChecked(font.strikeOut());
580
    if (font.pointSize() == m_fontsize_h1) {
581
        f_paragraph->setCurrentIndex(ParagraphHeading1);
582
      } else if (font.pointSize() == m_fontsize_h2) {
583
        f_paragraph->setCurrentIndex(ParagraphHeading2);
584
      } else if (font.pointSize() == m_fontsize_h3) {
585
        f_paragraph->setCurrentIndex(ParagraphHeading3);
586
      } else if (font.pointSize() == m_fontsize_h4) {
587
        f_paragraph->setCurrentIndex(ParagraphHeading4);
588
      } else {
589
        if (font.fixedPitch() && font.family() == QString::fromUtf8("Monospace")) {
590
            f_paragraph->setCurrentIndex(ParagraphMonospace);
591
          } else {
592
            f_paragraph->setCurrentIndex(ParagraphStandard);
593
            }
594
        }
595
    if (f_textedit->textCursor().currentList()) {
596
        QTextListFormat lfmt = f_textedit->textCursor().currentList()->format();
597
        if (lfmt.style() == QTextListFormat::ListDisc) {
598
            f_list_bullet->setChecked(true);
599
            f_list_ordered->setChecked(false);
600
          } else if (lfmt.style() == QTextListFormat::ListDecimal) {
601
            f_list_bullet->setChecked(false);
602
            f_list_ordered->setChecked(true);
603
          } else {
604
            f_list_bullet->setChecked(false);
605
            f_list_ordered->setChecked(false);
606
            }
607
      } else {
608
        f_list_bullet->setChecked(false);
609
        f_list_ordered->setChecked(false);
610
      }
611
}
612

613
void MRichTextEdit::fgColorChanged(const QColor &color) {
614
    QSize iconSize(16, 16);
615
    QIcon fgIcon = f_fgcolor->icon();
616
    QPixmap fgPix = fgIcon.pixmap(iconSize, QIcon::Mode::Normal, QIcon::State::On);
617
    QPixmap filler(iconSize);
618
    if (color.isValid() ) {
619
        filler.fill(color);
620
        filler.setMask(fgPix.createMaskFromColor(Qt::transparent, Qt::MaskInColor) );
621
        f_fgcolor->setIcon(filler);
622
    }
623
}
624

625
void MRichTextEdit::bgColorChanged(const QColor &color) {
626
    QSize iconSize(16, 16);
627
    QIcon bgIcon = f_bgcolor->icon();
628
    QPixmap bgPix = bgIcon.pixmap(iconSize, QIcon::Mode::Normal, QIcon::State::On);
629
    QPixmap filler(iconSize);
630
    if (color.isValid() ) {
631
        filler.fill(color);
632
        filler.setMask(bgPix.createMaskFromColor(Qt::transparent, Qt::MaskOutColor) );
633
        f_bgcolor->setIcon(filler);
634
    }
635
}
636

637
void MRichTextEdit::slotCurrentCharFormatChanged(const QTextCharFormat &format) {
638
//    qDebug() << "MRTE::slotCurrentCharFormatChanged()";
639
    Q_UNUSED(format);
640
    //again, why do we do all this just because the cursor moved?
641
    //can it be this simple???
642
//    fontChanged(format.font());
643
//    bgColorChanged((format.background().isOpaque()) ? format.background().color() : QColor());
644
//    fgColorChanged((format.foreground().isOpaque()) ? format.foreground().color() : QColor());
645
//    f_link->setChecked(format.isAnchor());
646
}
647

648
void MRichTextEdit::slotClipboardDataChanged() {
649
#ifndef QT_NO_CLIPBOARD
650
    if (const QMimeData *md = QApplication::clipboard()->mimeData())
651
        f_paste->setEnabled(md->hasText());
652
#endif
653
}
654

655
QString MRichTextEdit::toHtml() const {
656
    QString s = f_textedit->toHtml();
657
    // convert emails to links
658
    s = s.replace(QRegularExpression(
659
                QString::fromUtf8("(<[^a][^>]+>(?:<span[^>]+>)?|\\s)([a-zA-Z\\d]+@[a-zA-Z\\d]+\\.[a-zA-Z]+)")),
660
                QString::fromUtf8("\\1<a href=\"mailto:\\2\">\\2</a>"));
661
    // convert links
662
    s = s.replace(QRegularExpression(
663
                QString::fromUtf8("(<[^a][^>]+>(?:<span[^>]+>)?|\\s)((?:https?|ftp|file)://[^\\s'\"<>]+)")),
664
                QString::fromUtf8( "\\1<a href=\"\\2\">\\2</a>"));
665
    // see also: Utils::linkify()
666
    return s;
667
}
668

669
void MRichTextEdit::increaseIndentation() {
670
    indent(+1);
671
}
672

673
void MRichTextEdit::decreaseIndentation() {
674
    indent(-1);
675
}
676

677
void MRichTextEdit::indent(int delta) {
678
    QTextCursor cursor = f_textedit->textCursor();
679
    cursor.beginEditBlock();
680
    QTextBlockFormat bfmt = cursor.blockFormat();
681
    int ind = bfmt.indent();
682
    if (ind + delta >= 0) {
683
        bfmt.setIndent(ind + delta);
684
        }
685
    cursor.setBlockFormat(bfmt);
686
    cursor.endEditBlock();
687
}
688

689
void MRichTextEdit::setText(const QString& text) {
690
    if (text.isEmpty()) {
691
        setPlainText(text);
692
        return;
693
        }
694
    if (text[0] == QChar::fromLatin1('<')) {
695
        setHtml(text);
696
      } else {
697
        setPlainText(text);
698
        }
699
}
700

701
void MRichTextEdit::insertImage() {
702
    QSettings s;
703
    QString attdir = s.value(QString::fromUtf8("general/filedialog-path")).toString();
704
    QString file = QFileDialog::getOpenFileName(this,
705
                                    tr("Select an image"),
706
                                    attdir,
707
                                    tr("JPEG (*.jpg);; GIF (*.gif);; PNG (*.png);; BMP (*.bmp);; All (*)"));
708
    QImage image = QImageReader(file).read();
709

710
    f_textedit->dropImage(image,
711
                QFileInfo(file).suffix().toUpper());
712
}
713

714
void MRichTextEdit::onSave()
715
{
716
    QString result = toHtml();
717
    Q_EMIT saveText(result);
718
}
719

720
void MRichTextEdit::onExit()
721
{
722
    Q_EMIT editorFinished();
723
}
724

725
void MRichTextEdit::onSelectionChanged()
726
{
727
//    qDebug() << "MRTE::onSelectionChanged()";
728
    if (hasMultipleSizes()) {
729
        f_fontsize->setEditText(QString());
730
        f_fontsize->setCurrentIndex(-1);
731
    } else {
732
        QTextCursor cursor = f_textedit->textCursor();
733
        QTextCharFormat fmt = cursor.charFormat();
734
        double currSize = fmt.fontPointSize();
735
        int fSize = f_fontsize->findText(QString::number(currSize));
736
        f_fontsize  ->setCurrentIndex(fSize);
737
    }
738
}
739

740
//does selection have multiple sizes?
741
bool MRichTextEdit::hasMultipleSizes()
742
{
743
//    qDebug() << "MRTE::hasMultipleSizes()";
744
    QTextCursor cursor = f_textedit->textCursor();
745
    if (cursor.hasSelection()) {
746
        int begin = cursor.selectionStart();
747
        int end   = cursor.selectionEnd();
748
        int currPos;
749
        std::vector<QString> foundSizes;
750
        std::map<QString, int> countMap;
751
        for (currPos = begin; currPos < end; currPos++) {
752
            cursor.setPosition(currPos);
753
            QTextCharFormat fmt = cursor.charFormat();
754
            double currSize = fmt.fontPointSize();
755
            QString asQS = QString::number(currSize, 'f', 2);
756
            foundSizes.push_back(asQS);
757
            auto ret = countMap.insert(std::pair<QString, int>(asQS, 1));
758
            if (!ret.second) {            //already have this size
759
                ret.first->second++;      //bump count
760
            }
761
        }
762
        if (countMap.size() > 1) {
763
            return true;
764
        }
765
    }
766
    return false;
767
}
768

769
void MRichTextEdit::setDefFontSize(int fontSize)
770
{
771
//    Base::Console().Message("MRTE::setDefFontSize(%d)\n", fs);
772
    m_defFontSize = fontSize;
773
    m_fontsize_h1 = fontSize + 8;
774
    m_fontsize_h2 = fontSize + 6;
775
    m_fontsize_h3 = fontSize + 4;
776
    m_fontsize_h4 = fontSize + 2;
777

778
    QString newSize = QString::number(fontSize);
779
    f_fontsize->findText(newSize);
780
    int idx = f_fontsize->findText(newSize);
781
    if (idx > -1) {
782
        f_fontsize->setCurrentIndex(idx);
783
    } else {
784
        f_fontsize->setCurrentIndex(0);
785
    }
786
    textSize(newSize);
787
}
788

789
int MRichTextEdit::getDefFontSizeNum()
790
{
791
//    Base::Console().Message("MRTE::getDefFontSizeNum()\n");
792
    double fontSize = TechDraw::Preferences::dimFontSizeMM();
793

794
    //this conversion is only approximate. the factor changes for different fonts.
795
//    double mmToPts = 2.83;  //theoretical value
796
    double mmToPts = 2.00;  //practical value. seems to be reasonable for common fonts.
797

798
    return round(fontSize * mmToPts);
799
}
800

801
QString MRichTextEdit::getDefFontSize()
802
{
803
//    Base::Console().Message("MRTE::getDefFontSize()\n");
804
    return QString::number(getDefFontSizeNum());
805
}
806

807
//not used.
808
void MRichTextEdit::setDefFont(QString fontName)
809
{
810
    m_defFont = fontName;
811
}
812

813
QFont MRichTextEdit::getDefFont()
814
{
815
    QString family = Base::Tools::fromStdString(Preferences::labelFont());
816
    m_defFont = family;
817
    QFont result;
818
    result.setFamily(family);
819
    return result;
820
}
821

822
// add a new fontSize to the list
823
// this seems like massive overkill for integer point<->mm conversion factor
824
// if the conversion factor is float, will generate non-standard sizes
825
void MRichTextEdit::addFontSize(QString fontSize)
826
{
827
//    Base::Console().Message("MRTE::addFontSize(%s)\n", qPrintable(fs));
828
    QStringList newList;
829
    int fsVal = fontSize.toInt();
830
    int size = f_fontsize->count();
831
    bool added = false;
832
    for (int i = 0; i < size; i++) {
833
        QString item = f_fontsize->itemText(i);
834
        int itemVal = item.toInt();
835
        if (added) {
836
            newList << item;
837
            continue;
838
        }
839
        if (itemVal < fsVal) {
840
            newList << item;
841
        } else if (itemVal == fsVal) {  // already in list
842
            newList << item;
843
            added = true;
844
        } else {             //item > fs, add both
845
            newList << fontSize;
846
            newList << item;
847
            added = true;
848
        }
849
    }
850
    if (!added) {   //bigger than all choices, add to end of list
851
        newList << fontSize;
852
    }
853
    f_fontsize->clear();
854
    f_fontsize->addItems(newList);
855
}
856

857
#include <Mod/TechDraw/Gui/moc_mrichtextedit.cpp>
858

859

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

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

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

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