/* * Copyright (C) 2015-2018 Département de l'Instruction Publique (DIP-SEM) * * Copyright (C) 2013 Open Education Foundation * * Copyright (C) 2010-2013 Groupement d'Intérêt Public pour * l'Education Numérique en Afrique (GIP ENA) * * This file is part of OpenBoard. * * OpenBoard is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License, * with a specific linking exception for the OpenSSL project's * "OpenSSL" library (or with modified versions of it that use the * same license as the "OpenSSL" library). * * OpenBoard is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBoard. If not, see <http://www.gnu.org/licenses/>. */ #include <QtGui> #include <QtSvg> #include "core/UBApplication.h" #include "UBGraphicsGroupContainerItem.h" #include "UBGraphicsTextItemDelegate.h" #include "UBGraphicsScene.h" #include "gui/UBResources.h" #include "domain/UBGraphicsTextItem.h" #include "domain/UBGraphicsDelegateFrame.h" #include "core/UBSettings.h" #include "board/UBBoardController.h" #include "board/UBBoardView.h" #include "core/memcheck.h" const int UBGraphicsTextItemDelegate::sMinPixelSize = 8; const int UBGraphicsTextItemDelegate::sMinPointSize = 8; AlignTextButton::AlignTextButton(const QString &fileName, QGraphicsItem *pDelegated, QGraphicsItem *parent, Qt::WindowFrameSection section) : DelegateButton(fileName, pDelegated, parent, section) , lft(new QSvgRenderer(QString(":/images/leftAligned.svg"))) , cntr(new QSvgRenderer(QString(":/images/centerAligned.svg"))) , rght(new QSvgRenderer(QString(":/images/rightAligned.svg"))) , mxd(new QSvgRenderer(QString(":/images/notAligned.svg"))) , mHideMixed(true) { setKind(k_left); } AlignTextButton::~AlignTextButton() { if (lft) delete lft; if (cntr) delete cntr; if (rght) delete rght; if (mxd) delete mxd; } void AlignTextButton::setKind(int pKind) { if (mHideMixed && pKind == k_mixed) { qDebug() << "Mixed button is hidden, can't process it"; return; } mKind = pKind; QSvgRenderer *rndrer = rndFromKind(pKind); Q_ASSERT(rndrer); setSharedRenderer(rndrer); } void AlignTextButton::setNextKind() { int mxKind = MAX_KIND; if (mHideMixed) { mxKind--; } setKind(mKind == mxKind ? 0 : ++mKind); } int AlignTextButton::nextKind() const { int mxKind = MAX_KIND; if (mHideMixed) { mxKind--; } int result = mKind; return mKind == mxKind ? 0 : ++result; } UBGraphicsTextItemDelegate::UBGraphicsTextItemDelegate(UBGraphicsTextItem* pDelegated, QObject *) : UBGraphicsItemDelegate(pDelegated,0, GF_COMMON | GF_REVOLVABLE | GF_TITLE_BAR_USED) , mFontButton(0) , mColorButton(0) , mDecreaseSizeButton(0) , mIncreaseSizeButton(0) , mAlignButton(0) , mLastFontPixelSize(-1) , delta(5) { delegated()->setData(UBGraphicsItemData::ItemEditable, QVariant(true)); delegated()->setPlainText(""); QTextCursor curCursor = delegated()->textCursor(); QTextCharFormat format; QFont font(createDefaultFont()); font.setPointSize(UBSettings::settings()->fontPointSize()); format.setFont(font); if (UBSettings::settings()->isDarkBackground()) { if (UBGraphicsTextItem::lastUsedTextColor == Qt::black) UBGraphicsTextItem::lastUsedTextColor = Qt::white; } else { if (UBGraphicsTextItem::lastUsedTextColor == Qt::white) UBGraphicsTextItem::lastUsedTextColor = Qt::black; } delegated()->setDefaultTextColor(UBGraphicsTextItem::lastUsedTextColor); format.setForeground(QBrush(UBGraphicsTextItem::lastUsedTextColor)); curCursor.mergeCharFormat(format); delegated()->setTextCursor(curCursor); delegated()->setFont(font); delegated()->adjustSize(); delegated()->contentsChanged(); connect(delegated()->document(), SIGNAL(cursorPositionChanged(QTextCursor)), this, SLOT(onCursorPositionChanged(QTextCursor))); connect(delegated()->document(), SIGNAL(modificationChanged(bool)), this, SLOT(onModificationChanged(bool))); } UBGraphicsTextItemDelegate::~UBGraphicsTextItemDelegate() { // NOOP } QFont UBGraphicsTextItemDelegate::createDefaultFont() { QTextCharFormat textFormat; QString fFamily = UBSettings::settings()->fontFamily(); if (!fFamily.isEmpty()) textFormat.setFontFamily(fFamily); bool bold = UBSettings::settings()->isBoldFont(); if (bold) textFormat.setFontWeight(QFont::Bold); bool italic = UBSettings::settings()->isItalicFont(); if (italic) textFormat.setFontItalic(true); QFont font(fFamily, -1, bold ? QFont::Bold : -1, italic); int pointSize = UBSettings::settings()->fontPointSize(); if (pointSize > 0) { font.setPointSize(pointSize); } return font; } void UBGraphicsTextItemDelegate::createControls() { UBGraphicsItemDelegate::createControls(); if (!mFontButton) { mFontButton = new DelegateButton(":/images/font.svg", mDelegated, mFrame, Qt::TitleBarArea); connect(mFontButton, SIGNAL(clicked(bool)), this, SLOT(pickFont())); mButtons << mFontButton; } if (!mColorButton) { mColorButton = new DelegateButton(":/images/color.svg", mDelegated, mFrame, Qt::TitleBarArea); connect(mColorButton, SIGNAL(clicked(bool)), this, SLOT(pickColor())); mButtons << mColorButton; } if (!mDecreaseSizeButton) { mDecreaseSizeButton = new DelegateButton(":/images/minus.svg", mDelegated, mFrame, Qt::TitleBarArea); connect(mDecreaseSizeButton, SIGNAL(clicked(bool)), this, SLOT(decreaseSize())); mButtons << mDecreaseSizeButton; } if (!mIncreaseSizeButton) { mIncreaseSizeButton = new DelegateButton(":/images/plus.svg", mDelegated, mFrame, Qt::TitleBarArea); connect(mIncreaseSizeButton, SIGNAL(clicked(bool)), this, SLOT(increaseSize())); mButtons << mIncreaseSizeButton; } if (!mAlignButton) { mAlignButton = new AlignTextButton(":/images/plus.svg", mDelegated, mFrame, Qt::TitleBarArea); connect(mAlignButton, SIGNAL(clicked()), this, SLOT(alignButtonProcess())); mButtons << mAlignButton; } foreach(DelegateButton* button, mButtons) { button->hide(); button->setFlag(QGraphicsItem::ItemIsSelectable, true); } // Claudio: on changing the zvlaue the frame is updated updateSelectionFrame and // the default value for the operation mode is set (scaling). This isn't the right // mode for text so we call that here. frame()->setOperationMode(UBGraphicsDelegateFrame::Resizing); } /** * @brief Calculate the width of the toolbar containing the text item-related buttons * @return The space between the left-most and right-most buttons in pixels */ qreal UBGraphicsTextItemDelegate::titleBarWidth() { if (!mFontButton) return 0; // refresh the frame and buttons' positions positionHandles(); qreal titleBarWidth(0); qreal frameLeftCoordinate = mFontButton->pos().x(); qreal frameRightCoordinate = frameLeftCoordinate; foreach(DelegateButton* button, mButtons) { if (button->getSection() == Qt::TitleBarArea) { frameLeftCoordinate = qMin(button->pos().x(), frameLeftCoordinate); frameRightCoordinate = qMax(button->pos().x() + button->boundingRect().width(), frameRightCoordinate); } } return frameRightCoordinate - frameLeftCoordinate; } void UBGraphicsTextItemDelegate::freeButtons() { mButtons.removeOne(mFontButton); delete mFontButton; mFontButton = 0; mButtons.removeOne(mColorButton); delete mColorButton; mColorButton = 0; mButtons.removeOne(mDecreaseSizeButton); delete mDecreaseSizeButton; mDecreaseSizeButton = 0; mButtons.removeOne(mIncreaseSizeButton); delete mIncreaseSizeButton; mIncreaseSizeButton = 0; mButtons.removeOne(mAlignButton); delete mAlignButton; mAlignButton = 0; UBGraphicsItemDelegate::freeButtons(); } void UBGraphicsTextItemDelegate::contentsChanged() { delegated()->contentsChanged(); } // This method is used to filter the available fonts. Only the web-compliant fonts // will remain in the font list. void UBGraphicsTextItemDelegate::customize(QFontDialog &fontDialog) { fontDialog.setOption(QFontDialog::DontUseNativeDialog); if (UBSettings::settings()->isDarkBackground()) { fontDialog.setStyleSheet("background-color: white;"); } QListView *fontNameListView = NULL; QList<QListView*> listViews = fontDialog.findChildren<QListView*>(); if (listViews.count() > 0) { fontNameListView = listViews.at(0); foreach (QListView* listView, listViews) { if (listView->pos().x() < fontNameListView->pos().x()) fontNameListView = listView; } } if (fontNameListView) { QStringListModel *stringListModel = dynamic_cast<QStringListModel*>(fontNameListView->model()); if (stringListModel) { QStringList dialogFontNames = stringListModel->stringList(); QStringList safeWebFontNames; safeWebFontNames.append("Arial"); safeWebFontNames.append("Arial Black"); safeWebFontNames.append("Comic Sans MS"); safeWebFontNames.append("Courier New"); safeWebFontNames.append("Georgia"); safeWebFontNames.append("Impact"); safeWebFontNames.append("Times New Roman"); safeWebFontNames.append("Trebuchet MS"); safeWebFontNames.append("Verdana"); QStringList customFontList = UBResources::resources()->customFontList(); int index = 0; foreach (QString dialogFontName, dialogFontNames){ if (safeWebFontNames.contains(dialogFontName, Qt::CaseInsensitive) || customFontList.contains(dialogFontName, Qt::CaseSensitive)) index++; else stringListModel->removeRow(index); } } } QList<QComboBox*> comboBoxes = fontDialog.findChildren<QComboBox*>(); if (comboBoxes.count() > 0) comboBoxes.at(0)->setEnabled(false); } void UBGraphicsTextItemDelegate::pickFont() { if (mDelegated && mDelegated->scene() && mDelegated->scene()->views().size() > 0) { QFontDialog fontDialog(delegated()->textCursor().charFormat().font(), static_cast<QGraphicsView*>(UBApplication::boardController->controlView())); customize(fontDialog); if (fontDialog.exec()) { QFont selectedFont = fontDialog.selectedFont(); UBSettings::settings()->setFontFamily(selectedFont.family()); UBSettings::settings()->setBoldFont(selectedFont.bold()); UBSettings::settings()->setItalicFont(selectedFont.italic()); UBSettings::settings()->setFontPointSize(selectedFont.pointSize()); //setting format for selected item QTextCursor curCursor = delegated()->textCursor(); QTextCharFormat format; format.setFont(selectedFont); curCursor.mergeCharFormat(format); delegated()->setTextCursor(curCursor); if (curCursor.selectedText().length() == 0) delegated()->setFont(selectedFont); delegated()->setSelected(true); delegated()->document()->adjustSize(); delegated()->contentsChanged(); } } } void UBGraphicsTextItemDelegate::pickColor() { if (mDelegated && mDelegated->scene() && mDelegated->scene()->views().size() > 0) { QColorDialog colorDialog(delegated()->defaultTextColor(), static_cast<QGraphicsView*>(UBApplication::boardController->controlView())); colorDialog.setWindowTitle(tr("Text Color")); colorDialog.setOption(QColorDialog::DontUseNativeDialog); if (UBSettings::settings()->isDarkBackground()) { colorDialog.setStyleSheet("background-color: white;"); } if (colorDialog.exec()) { QColor selectedColor = colorDialog.selectedColor(); delegated()->setDefaultTextColor(selectedColor); QTextCursor curCursor = delegated()->textCursor(); QTextCharFormat format; format.setForeground(QBrush(selectedColor)); curCursor.mergeCharFormat(format); delegated()->setTextCursor(curCursor); if (!curCursor.hasSelection()) UBGraphicsTextItem::lastUsedTextColor = selectedColor; delegated()->setSelected(true); delegated()->document()->adjustSize(); delegated()->contentsChanged(); } } } void UBGraphicsTextItemDelegate::decreaseSize() { ChangeTextSize(-delta, changeSize); } void UBGraphicsTextItemDelegate::increaseSize() { ChangeTextSize(delta, changeSize); } void UBGraphicsTextItemDelegate::alignButtonProcess() { qDebug() << "alignButtonProcess() clicked"; QObject *sndr = sender(); if (sndr == mAlignButton) { qDebug() << "Align button"; AlignTextButton *asAlText = static_cast<AlignTextButton*>(mAlignButton); if (asAlText->nextKind() == AlignTextButton::k_mixed) { restoreTextCursorFormats(); asAlText->setNextKind(); return; } asAlText->setNextKind(); QTextCursor cur = delegated()->textCursor(); QTextBlockFormat fmt = cur.blockFormat(); switch (asAlText->kind()) { case AlignTextButton::k_left: fmt.setAlignment(Qt::AlignLeft); break; case AlignTextButton::k_center: fmt.setAlignment(Qt::AlignCenter); break; case AlignTextButton::k_right: fmt.setAlignment(Qt::AlignRight); break; case AlignTextButton::k_mixed: break; } delegated()->setTextCursor(cur); cur.setBlockFormat(fmt); delegated()->setFocus(); } qDebug() << "sender process" << sndr; } void UBGraphicsTextItemDelegate::onCursorPositionChanged(const QTextCursor &cursor) { qDebug() << "cursor position changed"; qDebug() << "-----------------------"; qDebug() << "we have a selection!" << cursor.selectionStart(); qDebug() << "-----------------------"; } void UBGraphicsTextItemDelegate::onModificationChanged(bool ch) { Q_UNUSED(ch); qDebug() << "modification changed"; } void UBGraphicsTextItemDelegate::onContentChanged() { qDebug() << "onContentChanged"; } UBGraphicsTextItem* UBGraphicsTextItemDelegate::delegated() { return static_cast<UBGraphicsTextItem*>(mDelegated); } void UBGraphicsTextItemDelegate::setEditable(bool editable) { if (editable) { delegated()->setTextInteractionFlags(Qt::TextEditorInteraction); mDelegated->setData(UBGraphicsItemData::ItemEditable, QVariant(true)); } else { QTextCursor cursor(delegated()->document()); cursor.clearSelection(); delegated()->setTextCursor(cursor); delegated()->setTextInteractionFlags(Qt::NoTextInteraction); mDelegated->setData(UBGraphicsItemData::ItemEditable, QVariant(false)); } } void UBGraphicsTextItemDelegate::remove(bool canUndo) { UBGraphicsItemDelegate::remove(canUndo); } bool UBGraphicsTextItemDelegate::isEditable() { return mDelegated->data(UBGraphicsItemData::ItemEditable).toBool(); } void UBGraphicsTextItemDelegate::decorateMenu(QMenu *menu) { UBGraphicsItemDelegate::decorateMenu(menu); mEditableAction = menu->addAction(tr("Editable"), this, SLOT(setEditable(bool))); mEditableAction->setCheckable(true); mEditableAction->setChecked(isEditable()); } void UBGraphicsTextItemDelegate::updateMenuActionState() { UBGraphicsItemDelegate::updateMenuActionState(); } bool UBGraphicsTextItemDelegate::mousePressEvent(QGraphicsSceneMouseEvent *event) { mSelectionData.mButtonIsPressed = true; qDebug() << "Reporting selection of the cursor (mouse press)" << delegated()->textCursor().selection().isEmpty(); qDebug() << QString("Anchor: %1\nposition: %2 (mouse press)").arg(delegated()->textCursor().anchor()).arg(delegated()->textCursor().position()); if (!UBGraphicsItemDelegate::mousePressEvent(event)) { return false; } return true; } bool UBGraphicsTextItemDelegate::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (mSelectionData.mButtonIsPressed) { qDebug() << "Reporting selection of the cursor (mouse move)" << delegated()->textCursor().selection().isEmpty(); qDebug() << QString("Anchor: %1\nposition: %2 (mouse mouse move)").arg(delegated()->textCursor().anchor()).arg(delegated()->textCursor().position()); } if (!UBGraphicsItemDelegate::mouseMoveEvent(event)) { return false; } return true; } bool UBGraphicsTextItemDelegate::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { mSelectionData.mButtonIsPressed = false; qDebug() << "Reporting selection of the cursor (mouse release)" << delegated()->textCursor().selection().isEmpty(); qDebug() << QString("Anchor: %1\nposition: %2 (mouse mouse release)").arg(delegated()->textCursor().anchor()).arg(delegated()->textCursor().position()); updateAlighButtonState(); if (!UBGraphicsItemDelegate::mouseReleaseEvent(event)) { return false; } return true; } bool UBGraphicsTextItemDelegate::keyPressEvent(QKeyEvent *event) { Q_UNUSED(event); return true; } bool UBGraphicsTextItemDelegate::keyReleaseEvent(QKeyEvent *event) { if (!delegated()->hasFocus()) { return true; } switch (event->key()) { case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: case Qt::Key_Down: updateAlighButtonState(); break; } qDebug() << "Key has been released" << QString::number(event->key(), 16); return true; } void UBGraphicsTextItemDelegate::ChangeTextSize(qreal factor, textChangeMode changeMode) { // round it to the nearest hundredth factor = floor(factor*100+0.5)/100.; if (scaleSize == changeMode) { if (1 == factor) return; } else if (0 == factor) return; UBGraphicsTextItem *item = dynamic_cast<UBGraphicsTextItem*>(delegated()); if (item && (QString() == item->toPlainText())) return; QTextCursor cursor = delegated()->textCursor(); QTextCharFormat textFormat; int anchorPos = cursor.anchor(); int cursorPos = cursor.position(); if (0 == anchorPos-cursorPos) { // If nothing is selected, then we select all the text cursor.setPosition (0, QTextCursor::MoveAnchor); cursor.setPosition (cursor.document()->characterCount()-1, QTextCursor::KeepAnchor); } // Now we got the real start and stop positions int startPos = qMin(cursor.anchor(), cursor.position()); int endPos = qMax(cursor.anchor(), cursor.position()); QFont curFont; QFont nextCharFont; bool bEndofTheSameBlock; int iBlockLen; int iPointSize; int iNextPointSize; int iCursorPos = startPos; QBrush curBrush; QBrush nextCharBrush; // we search continuous blocks of the text with the same PointSize and allpy new settings for them. cursor.setPosition (startPos, QTextCursor::MoveAnchor); while(iCursorPos < endPos) { bEndofTheSameBlock = false; iBlockLen = 0; // Here we get the point size of the first character cursor.setPosition (iCursorPos+1, QTextCursor::KeepAnchor); curFont = cursor.charFormat().font(); curBrush = cursor.charFormat().foreground(); iPointSize = curFont.pointSize(); // Then we position the end cursor to the start cursor position cursor.setPosition (iCursorPos, QTextCursor::KeepAnchor); do { // Get the next character font size cursor.setPosition (iCursorPos+iBlockLen+1, QTextCursor::KeepAnchor); nextCharFont = cursor.charFormat().font(); nextCharBrush = cursor.charFormat().foreground(); iNextPointSize = nextCharFont.pointSize(); if ( (iPointSize != iNextPointSize) || (iCursorPos+iBlockLen >= endPos) || (curFont.family().compare(nextCharFont.family()) != 0) || (curFont.italic() != nextCharFont.italic()) || (curFont.bold() != nextCharFont.bold()) || (curFont.underline() != nextCharFont.underline()) || (curBrush != nextCharBrush)) { bEndofTheSameBlock = true; break; } iBlockLen++; }while(!bEndofTheSameBlock); //setting new parameters QFont tmpFont = curFont; int iNewPointSize = (changeSize == changeMode) ? (iPointSize + factor) : (iPointSize * factor); tmpFont.setPointSize( (iNewPointSize > 0)?iNewPointSize:1); textFormat.setFont(tmpFont); textFormat.setForeground(curBrush); cursor.setPosition (iCursorPos+iBlockLen, QTextCursor::KeepAnchor); cursor.mergeCharFormat(textFormat); iCursorPos += iBlockLen; cursor.setPosition (iCursorPos, QTextCursor::MoveAnchor); curFont = nextCharFont; } delegated()->setFont(curFont); UBSettings::settings()->setFontPointSize(iPointSize); //returning initial selection cursor.setPosition (anchorPos, QTextCursor::MoveAnchor); cursor.setPosition (cursorPos, QTextCursor::KeepAnchor); delegated()->setTextCursor(cursor); } void UBGraphicsTextItemDelegate::recolor() { QTextCursor cursor = delegated()->textCursor(); QTextCharFormat textFormat; int anchorPos = cursor.anchor(); int cursorPos = cursor.position(); if (0 == anchorPos-cursorPos) { // If nothing is selected, then we select all the text cursor.setPosition (0, QTextCursor::MoveAnchor); cursor.setPosition (cursor.document()->characterCount()-1, QTextCursor::KeepAnchor); } int startPos = qMin(cursor.anchor(), cursor.position()); int endPos = qMax(cursor.anchor(), cursor.position()); QFont curFont; QFont nextCharFont; bool bEndofTheSameBlock; int iBlockLen; int iCursorPos = startPos; QBrush curBrush; QBrush nextCharBrush; cursor.setPosition (startPos, QTextCursor::MoveAnchor); while(iCursorPos < endPos) { bEndofTheSameBlock = false; iBlockLen = 0; // Here we get the point size of the first character cursor.setPosition (iCursorPos+1, QTextCursor::KeepAnchor); curBrush = cursor.charFormat().foreground(); // Then we position the end cursor to the start cursor position cursor.setPosition (iCursorPos, QTextCursor::KeepAnchor); do { cursor.setPosition (iCursorPos+iBlockLen+1, QTextCursor::KeepAnchor); nextCharBrush = cursor.charFormat().foreground(); if (curBrush != nextCharBrush || (iCursorPos+iBlockLen >= endPos)) { bEndofTheSameBlock = true; break; } iBlockLen++; }while(!bEndofTheSameBlock); //setting new parameters if (UBSettings::settings()->isDarkBackground()) { if (curBrush.color() == Qt::black) { curBrush = QBrush(Qt::white); } } else { if (curBrush.color() == Qt::white) { curBrush = QBrush(Qt::black); } } cursor.setPosition (iCursorPos+iBlockLen, QTextCursor::KeepAnchor); textFormat.setForeground(curBrush); cursor.mergeCharFormat(textFormat); iCursorPos += iBlockLen; cursor.setPosition (iCursorPos, QTextCursor::MoveAnchor); curFont = nextCharFont; } delegated()->setFont(curFont); //returning initial selection cursor.setPosition (anchorPos, QTextCursor::MoveAnchor); cursor.setPosition (cursorPos, QTextCursor::KeepAnchor); delegated()->setTextCursor(cursor); } void UBGraphicsTextItemDelegate::updateAlighButtonState() { if (!mAlignButton) { return; } qDebug() << "new cursor position" << delegated()->textCursor().position(); AlignTextButton *asAlBtn = static_cast<AlignTextButton*>(mAlignButton); if (!oneBlockSelection()) { asAlBtn->setMixedButtonVisible(true); asAlBtn->setKind(AlignTextButton::k_mixed); saveTextCursorFormats(); return; } asAlBtn->setMixedButtonVisible(false); Qt::Alignment cf = delegated()->textCursor().blockFormat().alignment(); qDebug() << "getting alignment" << cf; if (cf & Qt::AlignCenter) { asAlBtn->setKind(AlignTextButton::k_center); } else if (cf & Qt::AlignRight) { asAlBtn->setKind(AlignTextButton::k_right); } else { asAlBtn->setKind(AlignTextButton::k_left); } } bool UBGraphicsTextItemDelegate::oneBlockSelection() { const QTextCursor cursor = delegated()->textCursor(); int pos = cursor.position(); int anchor = cursor.anchor(); // no selection if (pos == anchor) { return true; } //selecton within one text block QTextBlock blck = cursor.block(); if (blck.contains(pos) && blck.contains(anchor)) { return true; } //otherwise return false; } void UBGraphicsTextItemDelegate::saveTextCursorFormats() { mSelectionData.anchor = delegated()->textCursor().anchor(); mSelectionData.position = delegated()->textCursor().position(); mSelectionData.html = delegated()->document()->toHtml(); } void UBGraphicsTextItemDelegate::restoreTextCursorFormats() { delegated()->document()->setHtml(mSelectionData.html); int min = qMin(mSelectionData.position, mSelectionData.anchor); int max = qMax(mSelectionData.position, mSelectionData.anchor); int steps = max - min; QTextCursor tcrsr = delegated()->textCursor(); tcrsr.setPosition(mSelectionData.position); tcrsr.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, steps); delegated()->setTextCursor(tcrsr); } void UBGraphicsTextItemDelegate::scaleTextSize(qreal multiplyer) { ChangeTextSize(multiplyer, scaleSize); } QVariant UBGraphicsTextItemDelegate::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { if (change == QGraphicsItem::ItemSelectedChange) { if (delegated()->isSelected()) { QTextCursor c = delegated()->textCursor(); if (c.hasSelection()) { c.clearSelection(); delegated()->setTextCursor(c); } } } return UBGraphicsItemDelegate::itemChange(change, value); }