File indexing completed on 2024-05-05 17:09:08
0001 /* 0002 * This file is part of the KDE project 0003 * 0004 * Copyright (C) 2013 Dan Leinir Turthra Jensen <admin@leinir.dk> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 * 0021 */ 0022 0023 #include "CQLinkArea.h" 0024 0025 #include <QGraphicsSceneMouseEvent> 0026 #include <QPainter> 0027 0028 struct LinkLayerLink 0029 { 0030 QRectF linkRect; 0031 QUrl linkTarget; 0032 }; 0033 0034 class CQLinkArea::Private 0035 { 0036 public: 0037 Private() 0038 : clickInProgress(false) 0039 , wiggleFactor(4) 0040 {} 0041 QVariantList links; 0042 QList<LinkLayerLink> realLinks; 0043 0044 bool clickInProgress; 0045 QPointF clickLocation; 0046 int wiggleFactor; 0047 0048 QSizeF sourceSize; 0049 0050 QColor linkColor; 0051 }; 0052 0053 CQLinkArea::CQLinkArea(QDeclarativeItem* parent) 0054 : QDeclarativeItem(parent) 0055 , d(new Private) 0056 { 0057 setFlag(QGraphicsItem::ItemHasNoContents, false); 0058 setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton | Qt::MidButton); 0059 setAcceptTouchEvents(true); 0060 } 0061 0062 CQLinkArea::~CQLinkArea() 0063 { 0064 delete d; 0065 } 0066 0067 void CQLinkArea::paint(QPainter* painter, const QStyleOptionGraphicsItem* , QWidget* ) 0068 { 0069 painter->save(); 0070 painter->setPen(Qt::transparent); 0071 painter->setBrush(QBrush(d->linkColor)); 0072 foreach(const LinkLayerLink& link, d->realLinks) { 0073 QRectF target( 0074 (link.linkRect.y() / d->sourceSize.height()) * height(), 0075 (link.linkRect.x() / d->sourceSize.width()) * width(), 0076 (link.linkRect.height() / d->sourceSize.height()) * height(), 0077 (link.linkRect.width() / d->sourceSize.width()) * width()); 0078 painter->drawRect(target); 0079 } 0080 painter->restore(); 0081 } 0082 0083 QVariantList CQLinkArea::links() const 0084 { 0085 return d->links; 0086 } 0087 0088 void CQLinkArea::setLinks(const QVariantList& newLinks) 0089 { 0090 d->links = newLinks; 0091 // run through the new data and cache a data list with the information 0092 // so we don't have to interpret the QObjects all the time 0093 d->realLinks.clear(); 0094 foreach(const QVariant& var, newLinks) { 0095 QObject* obj = var.value<QObject*>(); 0096 if (!obj) { 0097 continue; 0098 } 0099 LinkLayerLink link; 0100 link.linkRect = obj->property("linkRect").toRectF().adjusted(-d->wiggleFactor, -d->wiggleFactor, d->wiggleFactor, d->wiggleFactor); 0101 link.linkTarget = obj->property("linkTarget").toUrl(); 0102 d->realLinks.append(link); 0103 } 0104 emit linksChanged(); 0105 } 0106 0107 QSizeF CQLinkArea::sourceSize() const 0108 { 0109 return d->sourceSize; 0110 } 0111 0112 void CQLinkArea::setSourceSize(const QSizeF& size) 0113 { 0114 if (size != d->sourceSize) { 0115 d->sourceSize = size; 0116 emit sourceSizeChanged(); 0117 update(); 0118 } 0119 } 0120 0121 QColor CQLinkArea::linkColor() const 0122 { 0123 return d->linkColor; 0124 } 0125 0126 void CQLinkArea::setLinkColor(const QColor& color) 0127 { 0128 if (color != d->linkColor) { 0129 d->linkColor = color; 0130 d->linkColor.setAlphaF( 0.25 ); 0131 emit linkColorChanged(); 0132 update(); 0133 } 0134 } 0135 0136 void CQLinkArea::mousePressEvent(QGraphicsSceneMouseEvent* event) 0137 { 0138 d->clickInProgress = true; 0139 d->clickLocation = event->pos(); 0140 } 0141 0142 void CQLinkArea::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) 0143 { 0144 d->clickInProgress = false; 0145 // Don't activate anything if the finger has moved too far 0146 QRect rect((d->clickLocation - QPointF(d->wiggleFactor, d->wiggleFactor)).toPoint(), QSize(d->wiggleFactor * 2, d->wiggleFactor * 2)); 0147 if (!rect.contains(event->pos().toPoint())) { 0148 return; 0149 } 0150 QUrl url; 0151 QPointF inverted(event->pos().y(), event->pos().x()); 0152 foreach(const LinkLayerLink& link, d->realLinks) { 0153 QRectF scaledTarget( 0154 (link.linkRect.x() / d->sourceSize.width()) * width(), 0155 (link.linkRect.y() / d->sourceSize.height()) * height(), 0156 (link.linkRect.width() / d->sourceSize.width()) * width(), 0157 (link.linkRect.height() / d->sourceSize.height()) * height() ); 0158 0159 if (scaledTarget.contains(inverted)) { 0160 url = link.linkTarget; 0161 break; 0162 } 0163 } 0164 if (url.isEmpty()) { 0165 emit clicked(); 0166 } else { 0167 emit linkClicked(url); 0168 } 0169 } 0170 0171 void CQLinkArea::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) 0172 { 0173 Q_UNUSED(event) 0174 emit doubleClicked(); 0175 }