You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
872 lines
27 KiB
872 lines
27 KiB
/* |
|
* 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); |
|
}
|
|
|