File indexing completed on 2024-04-28 05:38:12

0001 /***************************************************************************
0002  *      Copyright (C) 2010 by Renaud Guezennec                             *
0003  *                                                                         *
0004  *                                                                         *
0005  *   rolisteam is free software; you can redistribute it and/or modify     *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "textitem.h"
0021 #include <QDebug>
0022 #include <QFont>
0023 #include <QLineEdit>
0024 #include <QMenu>
0025 #include <QObject>
0026 #include <QPainter>
0027 #include <QStyle>
0028 
0029 #include <QGraphicsSceneWheelEvent>
0030 #include <QStyleOptionGraphicsItem>
0031 
0032 #include "controller/item_controllers/textcontroller.h"
0033 #include "controller/item_controllers/visualitemcontroller.h"
0034 #include "controller/view_controller/vectorialmapcontroller.h"
0035 #include "editors/mrichtextedit.h"
0036 #include "network/networkmessagereader.h"
0037 #include "network/networkmessagewriter.h"
0038 
0039 #include "customs/vmap.h"
0040 
0041 ///////////////////////////////////////
0042 /// Code of TextLabel
0043 ///////////////////////////////////////
0044 TextLabel::TextLabel(QGraphicsItem* parent) : QGraphicsTextItem(parent)
0045 {
0046     setFlag(QGraphicsItem::ItemIsFocusable, true);
0047 }
0048 
0049 QRectF TextLabel::textRect() const
0050 {
0051     return m_rect;
0052 }
0053 
0054 QRectF TextLabel::boundingRect() const
0055 {
0056     auto rect= QGraphicsTextItem::boundingRect();
0057 
0058     QRectF maxRect(0, 0, std::max(m_rect.width(), rect.width()), std::max(rect.height(), m_rect.height()));
0059     return maxRect;
0060 }
0061 
0062 void TextLabel::setTextRect(const QRectF& rect)
0063 {
0064     if(rect == m_rect)
0065         return;
0066 
0067     m_rect= rect;
0068     emit textRectChanged();
0069     setTextWidth(rect.width());
0070 }
0071 void TextLabel::mousePressEvent(QGraphicsSceneMouseEvent* event)
0072 {
0073     VMap* map= dynamic_cast<VMap*>(scene());
0074     if(nullptr != map)
0075     {
0076         // if(map->getSelectedtool() == Core::HANDLER)
0077         {
0078             // event->accept();
0079             setFocus(Qt::OtherFocusReason);
0080             QGraphicsTextItem::mousePressEvent(event);
0081         }
0082         // else if((map->getSelectedtool() == Core::TEXT) || (map->getSelectedtool() == Core::TEXTBORDER))
0083         {
0084             QGraphicsTextItem::mousePressEvent(event);
0085         }
0086     }
0087 }
0088 
0089 void TextLabel::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
0090 {
0091     QGraphicsTextItem::mouseDoubleClickEvent(event);
0092 }
0093 
0094 ///////////////////////////////////////
0095 /// Code of RichTextEditDialog
0096 ///////////////////////////////////////
0097 
0098 RichTextEditDialog::RichTextEditDialog()
0099 {
0100     m_richText= new MRichTextEdit(this);
0101     QVBoxLayout* lay= new QVBoxLayout(this);
0102     lay->addWidget(m_richText);
0103 
0104     QDialogButtonBox* dialogButton= new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
0105     lay->addWidget(dialogButton);
0106 
0107     connect(dialogButton, &QDialogButtonBox::accepted, this, &RichTextEditDialog::accept);
0108     connect(dialogButton, &QDialogButtonBox::rejected, this, &RichTextEditDialog::reject);
0109 
0110     setLayout(lay);
0111 }
0112 
0113 void RichTextEditDialog::setText(QString str)
0114 {
0115     m_richText->setText(str);
0116 }
0117 
0118 QString RichTextEditDialog::getText()
0119 {
0120     return m_richText->toHtml();
0121 }
0122 
0123 ///////////////////////
0124 /// Code of TextItem
0125 //
0126 //
0127 //
0128 ///////////////////////
0129 
0130 RichTextEditDialog* TextItem::m_dialog= nullptr;
0131 
0132 TextItem::TextItem(vmap::TextController* ctrl)
0133     : VisualItem(ctrl)
0134     , m_textCtrl(ctrl)
0135     , m_doc(new QTextDocument)
0136     , m_textItem(new TextLabel(this))
0137     , m_increaseFontSize(new QAction(tr("Increase Text Size")))
0138     , m_decreaseFontSize(new QAction(tr("Decrease Text Size")))
0139     , m_edit(new QAction(tr("Edit Text…")))
0140     , m_adapt(new QAction(tr("Adapt to content")))
0141 {
0142     if(nullptr == m_dialog)
0143         m_dialog= new RichTextEditDialog();
0144 
0145     connect(m_edit.get(), &QAction::triggered, this, &TextItem::editText);
0146     connect(m_adapt.get(), &QAction::triggered, this, &TextItem::sizeToTheContent);
0147 
0148     connect(m_increaseFontSize.get(), &QAction::triggered, m_textCtrl, &vmap::TextController::increaseFontSize);
0149     connect(m_decreaseFontSize.get(), &QAction::triggered, m_textCtrl, &vmap::TextController::decreaseFontSize);
0150 
0151     m_textItem->setDocument(m_doc.get());
0152     connect(m_textCtrl, &vmap::TextController::borderRectChanged, this,
0153             [this]()
0154             {
0155                 m_textItem->setTextWidth(m_textCtrl->borderRect().width());
0156                 m_textCtrl->setTextRect(m_textItem->boundingRect());
0157                 updateChildPosition();
0158             });
0159     connect(m_textCtrl, &vmap::TextController::textRectChanged, this,
0160             [this]() { m_textItem->setTextWidth(m_textCtrl->textRect().width()); });
0161     connect(m_textCtrl, &vmap::TextController::textPosChanged, this,
0162             [this](const QPointF& pos) { m_textItem->setPos(pos); });
0163 
0164     connect(m_textCtrl, &vmap::TextController::textChanged, m_doc.get(), &QTextDocument::setPlainText);
0165     connect(m_doc.get(), &QTextDocument::contentsChanged, this,
0166             [this]()
0167             {
0168                 if(!m_textCtrl)
0169                     return;
0170                 m_textCtrl->setText(m_doc->toPlainText());
0171                 auto rect= m_textItem->boundingRect();
0172                 m_textCtrl->setTextRect(rect);
0173             });
0174 
0175     for(int i= 0; i <= vmap::TextController::BottomLeft; ++i)
0176     {
0177         ChildPointItem* tmp= new ChildPointItem(m_textCtrl, i, this);
0178         tmp->setMotion(ChildPointItem::MOUSE);
0179         m_children.append(tmp);
0180     }
0181     updateChildPosition();
0182 
0183     setAcceptHoverEvents(true);
0184     m_textItem->setFocus();
0185     m_textItem->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
0186     m_textItem->setPos(QPointF(0, 0));
0187     m_textItem->setTextWidth(100);
0188     m_textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
0189     if(m_textCtrl)
0190         m_textItem->setDefaultTextColor(m_textCtrl->color());
0191     m_doc->setPlainText(tr("Text"));
0192 }
0193 
0194 QRectF TextItem::boundingRect() const
0195 {
0196     return m_textCtrl->borderRect();
0197 }
0198 void TextItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
0199 {
0200     Q_UNUSED(option)
0201     Q_UNUSED(widget)
0202     setChildrenVisible(hasFocusOrChild());
0203     if(m_textCtrl->border())
0204     {
0205         QPen pen= painter->pen();
0206         pen.setColor(m_textCtrl->color());
0207         pen.setWidth(m_textCtrl->border() ? m_textCtrl->penWidth() : 2);
0208         painter->setPen(pen);
0209         painter->drawRect(boundingRect());
0210     }
0211     if(canBeMoved() && (option->state & QStyle::State_MouseOver || isSelected()))
0212     {
0213         painter->save();
0214         QPen pen= painter->pen();
0215         pen.setColor(isSelected() ? m_selectedColor : m_highlightColor);
0216         pen.setWidth(m_highlightWidth);
0217         painter->setPen(pen);
0218         painter->drawRect(m_textCtrl->borderRect());
0219         painter->restore();
0220     }
0221 }
0222 
0223 void TextItem::setNewEnd(const QPointF& p)
0224 {
0225     Q_UNUSED(p)
0226 }
0227 
0228 void TextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
0229 {
0230     if(event->button() == Qt::LeftButton)
0231     {
0232         setChildrenVisible(false);
0233         m_menuPos= event->screenPos();
0234         editText();
0235         event->accept();
0236     }
0237     else
0238     {
0239         VisualItem::mouseDoubleClickEvent(event);
0240     }
0241 }
0242 void TextItem::wheelEvent(QGraphicsSceneWheelEvent* event)
0243 {
0244     if(!event->modifiers() & Qt::ControlModifier)
0245         VisualItem::wheelEvent(event);
0246 
0247     event->delta() > 0 ? m_textCtrl->increaseFontSize() : m_textCtrl->decreaseFontSize();
0248     event->accept();
0249 }
0250 
0251 void TextItem::updateChildPosition()
0252 {
0253     if(!m_textCtrl)
0254         return;
0255     auto rect= m_textCtrl->borderRect();
0256     m_children.value(0)->setPos(rect.topLeft());
0257     m_children.value(0)->setPlacement(ChildPointItem::TopLeft);
0258     m_children.value(1)->setPos(rect.topRight());
0259     m_children.value(1)->setPlacement(ChildPointItem::TopRight);
0260     m_children.value(2)->setPos(rect.bottomRight());
0261     m_children.value(2)->setPlacement(ChildPointItem::ButtomRight);
0262     m_children.value(3)->setPos(rect.bottomLeft());
0263     m_children.value(3)->setPlacement(ChildPointItem::ButtomLeft);
0264     update();
0265 }
0266 
0267 void TextItem::editText()
0268 {
0269     m_dialog->setText(m_textItem->toHtml());
0270     m_dialog->move(m_menuPos);
0271     if(QDialog::Accepted == m_dialog->exec())
0272     {
0273         m_textItem->setHtml(m_dialog->getText());
0274         // updateTextPosition();
0275         emit itemGeometryChanged(this);
0276     }
0277 }
0278 
0279 /*void TextItem::endOfGeometryChange(ChildPointItem::Change change)
0280 {
0281     if(change == ChildPointItem::Resizing)
0282     {
0283         auto oldScenePos= scenePos();
0284         setTransformOriginPoint(m_textCtrl->borderRect().center());
0285         auto newScenePos= scenePos();
0286         auto oldPos= pos();
0287         m_textCtrl->setPos(QPointF(oldPos.x() + (oldScenePos.x() - newScenePos.x()),
0288                                    oldPos.y() + (oldScenePos.y() - newScenePos.y())));
0289     }
0290     VisualItem::endOfGeometryChange(change);
0291 }*/
0292 
0293 void TextItem::addActionContextMenu(QMenu& menu)
0294 {
0295     menu.addAction(m_edit.get());
0296     menu.addAction(m_adapt.get());
0297 
0298     QMenu* state= menu.addMenu(tr("Font Size"));
0299     state->addAction(m_increaseFontSize.get());
0300     state->addAction(m_decreaseFontSize.get());
0301     VisualItem::addActionContextMenu(menu);
0302 }
0303 
0304 void TextItem::sizeToTheContent()
0305 {
0306     QRectF rectItem= m_textItem->boundingRect();
0307     /*  setTransformOriginPoint(m_rect.center());
0308       if(rectItem.height() < m_rect.height() + 10)
0309       {
0310           m_rect.setHeight(rectItem.height() + 10);
0311           m_resizing= true;
0312       }
0313       if(rectItem.width() < m_rect.width() + 10)
0314       {
0315           m_rect.setWidth(rectItem.width() + 10);
0316           m_resizing= true;
0317       }*/
0318     /*if(m_resizing)
0319     {
0320         endOfGeometryChange(ChildPointItem::Resizing);
0321     }*/
0322 }
0323 
0324 void TextItem::updateItemFlags()
0325 {
0326     VisualItem::updateItemFlags();
0327     if(!canBeMoved())
0328     {
0329         m_textItem->setTextInteractionFlags(Qt::NoTextInteraction);
0330     }
0331     else
0332     {
0333         m_textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
0334     }
0335 }
0336 void TextItem::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
0337 {
0338     Q_UNUSED(event)
0339     if(canBeMoved())
0340     {
0341         VMap* vmap= dynamic_cast<VMap*>(scene());
0342         if(nullptr != vmap)
0343         {
0344             /*Core::SelectableTool tool= vmap->getSelectedtool();
0345             if((Core::TEXT == tool) || (Core::TEXTBORDER == tool))
0346             {
0347                 QApplication::setOverrideCursor(QCursor(Qt::IBeamCursor));
0348             }*/
0349         }
0350     }
0351     VisualItem::hoverEnterEvent(event);
0352 }
0353 void TextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
0354 {
0355     Q_UNUSED(event)
0356     if(canBeMoved())
0357         QApplication::restoreOverrideCursor();
0358 
0359     VisualItem::hoverLeaveEvent(event);
0360 }
0361 void TextItem::keyPressEvent(QKeyEvent* event)
0362 {
0363     if(m_textItem->hasCursor())
0364     {
0365         QGraphicsItem::keyPressEvent(event);
0366     }
0367     else
0368     {
0369         VisualItem::keyPressEvent(event);
0370     }
0371 }