File indexing completed on 2024-05-12 13:04:45
0001 /* 0002 * This file is part of the KDE project 0003 * 0004 * SPDX-FileCopyrightText: 2013 Dan Leinir Turthra Jensen <admin@leinir.dk> 0005 * 0006 * SPDX-License-Identifier: LGPL-2.0-or-later 0007 * 0008 */ 0009 0010 #include "CQLinkArea.h" 0011 0012 #include <QGraphicsSceneMouseEvent> 0013 #include <QPainter> 0014 0015 struct LinkLayerLink 0016 { 0017 QRectF linkRect; 0018 QUrl linkTarget; 0019 }; 0020 0021 class CQLinkArea::Private 0022 { 0023 public: 0024 Private() 0025 : clickInProgress(false) 0026 , wiggleFactor(4) 0027 {} 0028 QVariantList links; 0029 QList<LinkLayerLink> realLinks; 0030 0031 bool clickInProgress; 0032 QPointF clickLocation; 0033 int wiggleFactor; 0034 0035 QSizeF sourceSize; 0036 0037 QColor linkColor; 0038 }; 0039 0040 CQLinkArea::CQLinkArea(QDeclarativeItem* parent) 0041 : QDeclarativeItem(parent) 0042 , d(new Private) 0043 { 0044 setFlag(QGraphicsItem::ItemHasNoContents, false); 0045 setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton | Qt::MidButton); 0046 setAcceptTouchEvents(true); 0047 } 0048 0049 CQLinkArea::~CQLinkArea() 0050 { 0051 delete d; 0052 } 0053 0054 void CQLinkArea::paint(QPainter* painter, const QStyleOptionGraphicsItem* , QWidget* ) 0055 { 0056 painter->save(); 0057 painter->setPen(Qt::transparent); 0058 painter->setBrush(QBrush(d->linkColor)); 0059 foreach(const LinkLayerLink& link, d->realLinks) { 0060 QRectF target( 0061 (link.linkRect.y() / d->sourceSize.height()) * height(), 0062 (link.linkRect.x() / d->sourceSize.width()) * width(), 0063 (link.linkRect.height() / d->sourceSize.height()) * height(), 0064 (link.linkRect.width() / d->sourceSize.width()) * width()); 0065 painter->drawRect(target); 0066 } 0067 painter->restore(); 0068 } 0069 0070 QVariantList CQLinkArea::links() const 0071 { 0072 return d->links; 0073 } 0074 0075 void CQLinkArea::setLinks(const QVariantList& newLinks) 0076 { 0077 d->links = newLinks; 0078 // run through the new data and cache a data list with the information 0079 // so we don't have to interpret the QObjects all the time 0080 d->realLinks.clear(); 0081 foreach(const QVariant& var, newLinks) { 0082 QObject* obj = var.value<QObject*>(); 0083 if (!obj) { 0084 continue; 0085 } 0086 LinkLayerLink link; 0087 link.linkRect = obj->property("linkRect").toRectF().adjusted(-d->wiggleFactor, -d->wiggleFactor, d->wiggleFactor, d->wiggleFactor); 0088 link.linkTarget = obj->property("linkTarget").toUrl(); 0089 d->realLinks.append(link); 0090 } 0091 emit linksChanged(); 0092 } 0093 0094 QSizeF CQLinkArea::sourceSize() const 0095 { 0096 return d->sourceSize; 0097 } 0098 0099 void CQLinkArea::setSourceSize(const QSizeF& size) 0100 { 0101 if (size != d->sourceSize) { 0102 d->sourceSize = size; 0103 emit sourceSizeChanged(); 0104 update(); 0105 } 0106 } 0107 0108 QColor CQLinkArea::linkColor() const 0109 { 0110 return d->linkColor; 0111 } 0112 0113 void CQLinkArea::setLinkColor(const QColor& color) 0114 { 0115 if (color != d->linkColor) { 0116 d->linkColor = color; 0117 d->linkColor.setAlphaF( 0.25 ); 0118 emit linkColorChanged(); 0119 update(); 0120 } 0121 } 0122 0123 void CQLinkArea::mousePressEvent(QGraphicsSceneMouseEvent* event) 0124 { 0125 d->clickInProgress = true; 0126 d->clickLocation = event->pos(); 0127 } 0128 0129 void CQLinkArea::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) 0130 { 0131 d->clickInProgress = false; 0132 // Don't activate anything if the finger has moved too far 0133 QRect rect((d->clickLocation - QPointF(d->wiggleFactor, d->wiggleFactor)).toPoint(), QSize(d->wiggleFactor * 2, d->wiggleFactor * 2)); 0134 if (!rect.contains(event->pos().toPoint())) { 0135 return; 0136 } 0137 QUrl url; 0138 QPointF inverted(event->pos().y(), event->pos().x()); 0139 foreach(const LinkLayerLink& link, d->realLinks) { 0140 QRectF scaledTarget( 0141 (link.linkRect.x() / d->sourceSize.width()) * width(), 0142 (link.linkRect.y() / d->sourceSize.height()) * height(), 0143 (link.linkRect.width() / d->sourceSize.width()) * width(), 0144 (link.linkRect.height() / d->sourceSize.height()) * height() ); 0145 0146 if (scaledTarget.contains(inverted)) { 0147 url = link.linkTarget; 0148 break; 0149 } 0150 } 0151 if (url.isEmpty()) { 0152 emit clicked(); 0153 } else { 0154 emit linkClicked(url); 0155 } 0156 } 0157 0158 void CQLinkArea::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) 0159 { 0160 Q_UNUSED(event) 0161 emit doubleClicked(); 0162 }