/* * Copyright (C) 2012 Webdoc SA * * This file is part of Open-Sankoré. * * Open-Sankoré is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation, version 2, * 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). * * Open-Sankoré 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with Open-Sankoré; if not, see * . */ #include #include #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 "core/memcheck.h" const int UBGraphicsTextItemDelegate::sMinPixelSize = 8; const int UBGraphicsTextItemDelegate::sMinPointSize = 8; UBGraphicsTextItemDelegate::UBGraphicsTextItemDelegate(UBGraphicsTextItem* pDelegated, QObject * parent) : UBGraphicsItemDelegate(pDelegated,0, parent, true) , 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); curCursor.mergeCharFormat(format); delegated()->setTextCursor(curCursor); delegated()->setFont(font); delegated()->adjustSize(); delegated()->contentsChanged(); // NOOP } 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 pixSize = UBSettings::settings()->fontPixelSize(); // if (pixSize > 0) { // mLastFontPixelSize = pixSize; // font.setPixelSize(pixSize); // } int pointSize = UBSettings::settings()->fontPointSize(); if (pointSize > 0) { // mLastFontPixelSize = pointSize; font.setPointSize(pointSize); } return font; } void UBGraphicsTextItemDelegate::buildButtons() { UBGraphicsItemDelegate::buildButtons(); mFontButton = new DelegateButton(":/images/font.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); mColorButton = new DelegateButton(":/images/color.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); mDecreaseSizeButton = new DelegateButton(":/images/minus.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); mIncreaseSizeButton = new DelegateButton(":/images/plus.svg", mDelegated, mToolBarItem, Qt::TitleBarArea); connect(mFontButton, SIGNAL(clicked(bool)), this, SLOT(pickFont())); connect(mColorButton, SIGNAL(clicked(bool)), this, SLOT(pickColor())); connect(mDecreaseSizeButton, SIGNAL(clicked(bool)), this, SLOT(decreaseSize())); connect(mIncreaseSizeButton, SIGNAL(clicked(bool)), this, SLOT(increaseSize())); QList itemsOnToolBar; itemsOnToolBar << mFontButton << mColorButton << mDecreaseSizeButton << mIncreaseSizeButton; mToolBarItem->setItemsOnToolBar(itemsOnToolBar); mToolBarItem->setShifting(true); mToolBarItem->setVisibleOnBoard(true); } void UBGraphicsTextItemDelegate::contentsChanged() { positionHandles(); 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; QList listViews = fontDialog.findChildren(); 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(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 comboBoxes = fontDialog.findChildren(); 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(), mDelegated->scene()->views().at(0)); 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); 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(), mDelegated->scene()->views().at(0)); colorDialog.setWindowTitle(tr("Text Color")); if (UBSettings::settings()->isDarkBackground()) { colorDialog.setStyleSheet("background-color: white;"); } if (colorDialog.exec()) { QColor selectedColor = colorDialog.selectedColor(); delegated()->setDefaultTextColor(selectedColor); // delegated()->setColorOnDarkBackground(selectedColor); // delegated()->setColorOnLightBackground(selectedColor); QTextCursor curCursor = delegated()->textCursor(); QTextCharFormat format; format.setForeground(QBrush(selectedColor)); curCursor.mergeCharFormat(format); delegated()->setTextCursor(curCursor); UBGraphicsTextItem::lastUsedTextColor = selectedColor; delegated()->setSelected(true); delegated()->contentsChanged(); } } } void UBGraphicsTextItemDelegate::decreaseSize() { ChangeTextSize(-delta, changeSize); } void UBGraphicsTextItemDelegate::increaseSize() { ChangeTextSize(delta, changeSize); } UBGraphicsTextItem* UBGraphicsTextItemDelegate::delegated() { return static_cast(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(); } void UBGraphicsTextItemDelegate::positionHandles() { UBGraphicsItemDelegate::positionHandles(); if (mDelegated->isSelected() || (mDelegated->parentItem() && UBGraphicsGroupContainerItem::Type == mDelegated->parentItem()->type())) { if (mToolBarItem->isVisibleOnBoard()) { qreal AntiScaleRatio = 1 / (UBApplication::boardController->systemScaleFactor() * UBApplication::boardController->currentZoom()); mToolBarItem->setScale(AntiScaleRatio); QRectF toolBarRect = mToolBarItem->rect(); toolBarRect.setWidth(delegated()->boundingRect().width()/AntiScaleRatio); mToolBarItem->setRect(toolBarRect); mToolBarItem->positionHandles(); mToolBarItem->update(); if (mToolBarItem->isShifting()) mToolBarItem->setPos(0,-mToolBarItem->boundingRect().height()*AntiScaleRatio); else mToolBarItem->setPos(0, 0); UBGraphicsGroupContainerItem *group = qgraphicsitem_cast(mDelegated->parentItem()); mToolBarItem->hide(); if (mToolBarItem->parentItem()) { if (group && group->getCurrentItem() == mDelegated && group->isSelected()) mToolBarItem->show(); if (!group) mToolBarItem->show(); } } } else { mToolBarItem->hide(); } } void UBGraphicsTextItemDelegate::ChangeTextSize(qreal factor, textChangeMode changeMode) { if (scaleSize == changeMode) { if (1 == factor) return; } else if (0 == factor) return; UBGraphicsTextItem *item = dynamic_cast(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) { 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; bool bEndofTheSameBlock; int iBlockLen; int iPointSize; int iNextPointSize; int iCursorPos = startPos; // 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; cursor.setPosition (iCursorPos+1, QTextCursor::KeepAnchor); iPointSize = cursor.charFormat().font().pointSize(); cursor.setPosition (iCursorPos, QTextCursor::KeepAnchor); curFont = cursor.charFormat().font(); do { iBlockLen++; cursor.setPosition (iCursorPos+iBlockLen+1, QTextCursor::KeepAnchor); iNextPointSize = cursor.charFormat().font().pointSize(); cursor.setPosition (iCursorPos+iBlockLen, QTextCursor::KeepAnchor); if ((iPointSize != iNextPointSize)||(iCursorPos+iBlockLen >= endPos)) bEndofTheSameBlock = true; }while(!bEndofTheSameBlock); //setting new parameners int iNewPointSize = (changeSize == changeMode) ? (iPointSize + factor) : (iPointSize * factor); curFont.setPointSize( (iNewPointSize > 0)?iNewPointSize:1); textFormat.setFont(curFont); cursor.mergeCharFormat(textFormat); iCursorPos += iBlockLen; cursor.setPosition (iCursorPos, QTextCursor::MoveAnchor); } 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::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); }