1 /***************************************************************************
2  *   Copyright (c) 2008  Jeff Mitchell <mitchell@kde.org>                  *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
18  ***************************************************************************/
19 
20 #include "PopupDropperItem.h"
21 #include "PopupDropperItem_p.h"
22 #include "PopupDropper.h"
23 
24 #include <QtDebug>
25 #include <QSvgRenderer>
26 #include <QAction>
27 #include <QFont>
28 
29 ///////////////////////////////////////////////////////////
30 
PopupDropperItemPrivate(PopupDropperItem * parent)31 PopupDropperItemPrivate::PopupDropperItemPrivate( PopupDropperItem *parent )
32     : action( 0 )
33     , text( QString() )
34     , hoverTimer( 500, parent )
35     , elementId( QString() )
36     , textItem( 0 )
37     , borderRectItem( 0 )
38     , svgItem( 0 )
39     , hoverIndicatorRectItem( 0 )
40     , hoverIndicatorRectFillItem( 0 )
41     , borderWidth( 2 )
42     , hoverIndicatorRectWidth( 15 )
43     , font()
44     , submenuTrigger( false )
45     , baseTextColor()
46     , hoveredTextColor()
47     , hoveredBorderPen()
48     , hoveredFillBrush()
49     , hoverIndicatorRectFillBrush()
50     , hoveredOver( false )
51     , customBaseTextColor( false )
52     , customHoveredTextColor( false )
53     , customHoveredBorderPen( false )
54     , customHoveredFillBrush( false )
55     , subitemOpacity( 0.0 )
56     , file( QString() )
57     , svgElementRect( 0, 0, 50, 50 )
58     , sharedRenderer( 0 )
59     , horizontalOffset( 30 )
60     , textOffset( 30 )
61     , separator( false )
62     , hasLineSeparatorPen( false )
63     , lineSeparatorPen()
64     , hoverIndicatorShowStyle( PopupDropperItem::Never )
65     , orientation( PopupDropperItem::Left )
66     , textProtection( PopupDropperItem::ScaleFont )
67     , separatorStyle( PopupDropperItem::TextSeparator )
68     , pd( 0 )
69     , q( parent )
70     {
71         hoverTimer.setFrameRange( 0, 30 );
72         hoverTimer.setUpdateInterval( 20 ); // 50 fps
73         q->setAcceptDrops( true );
74         hoverIndicatorRectFillBrush.setColor( Qt::white );
75         hoveredBorderPen.setWidth( borderWidth );
76         hoveredBorderPen.setColor( Qt::white );
77         hoveredBorderPen.setStyle( Qt::SolidLine );
78         hoveredFillBrush.setColor( Qt::white );
79         hoveredFillBrush.setStyle( Qt::SolidPattern );
80     }
81 
~PopupDropperItemPrivate()82 PopupDropperItemPrivate::~PopupDropperItemPrivate()
83 {
84 }
85 
86 ///////////////////////////////////////////////////////////
87 
PopupDropperItem(QGraphicsItem * parent)88 PopupDropperItem::PopupDropperItem( QGraphicsItem *parent )
89     : QObject()
90     , QAbstractGraphicsShapeItem( parent )
91     , d( new PopupDropperItemPrivate( this ) )
92 {
93     connect( &d->hoverTimer, &QTimeLine::finished, this, &PopupDropperItem::hoverFinished );
94     connect( &d->hoverTimer, &QTimeLine::frameChanged, this, &PopupDropperItem::hoverFrameChanged );
95 }
96 
PopupDropperItem(const QString & file,QGraphicsItem * parent)97 PopupDropperItem::PopupDropperItem( const QString &file, QGraphicsItem *parent )
98     : QObject()
99     , QAbstractGraphicsShapeItem( parent )
100     , d( new PopupDropperItemPrivate( this ) )
101 {
102     d->file = file;
103     connect( &d->hoverTimer, &QTimeLine::finished, this, &PopupDropperItem::hoverFinished );
104     connect( &d->hoverTimer, &QTimeLine::frameChanged, this, &PopupDropperItem::hoverFrameChanged );
105 }
106 
~PopupDropperItem()107 PopupDropperItem::~PopupDropperItem()
108 {
109     delete d;
110 }
111 
show()112 void PopupDropperItem::show()
113 {
114 }
115 
action() const116 QAction* PopupDropperItem::action() const
117 {
118     return d->action;
119 }
120 
setAction(QAction * action)121 void PopupDropperItem::setAction( QAction *action )
122 {
123     if( !action )
124         return;
125     //note that this also sets the text
126     d->action = action;
127     d->text = action->text();
128     if( action )
129     {
130         if( !d->svgItem )
131         {
132             if( !d->file.isEmpty() )
133                 d->svgItem = new QGraphicsSvgItem( d->file, this );
134             else
135                 d->svgItem = new QGraphicsSvgItem( this );
136         }
137 
138         if( d->sharedRenderer )
139             d->svgItem->setSharedRenderer( d->sharedRenderer );
140 
141         if( d->elementId.isEmpty() )
142             d->elementId = action->property( "popupdropper_svg_id" ).toString();
143         if( !d->elementId.isEmpty() )
144         {
145             if( d->svgItem->renderer() && d->svgItem->renderer()->elementExists( d->elementId ) )
146                 d->svgItem->setElementId( d->elementId );
147         }
148 
149         if( !d->svgItem->elementId().isEmpty() && d->svgItem->renderer()->elementExists( d->svgItem->elementId() ) )
150             d->svgItem->show();
151         else
152             d->svgItem->hide();
153 
154         if( action->isSeparator() )
155             d->separator = true;
156 
157         scaleAndReposSvgItem();
158 
159         d->hoverIndicatorRectItem = new QGraphicsRectItem( this );
160 
161         QPen pen = d->hoveredBorderPen;
162         QColor color( pen.color() );
163         color.setAlpha( 255 );
164         pen.setColor( color );
165         d->hoverIndicatorRectItem->setPen( pen );
166         QBrush brush = d->hoverIndicatorRectItem->brush();
167         brush.setStyle( Qt::NoBrush );
168         d->hoverIndicatorRectItem->setBrush( brush );
169 
170         d->hoverIndicatorRectFillItem = new QGraphicsRectItem( this );
171         pen = d->hoverIndicatorRectFillItem->pen();
172         pen.setStyle( Qt::NoPen );
173         d->hoverIndicatorRectFillItem->setPen( pen );
174         d->hoverIndicatorRectFillBrush.setStyle( Qt::SolidPattern );
175 
176         if( d->hoverIndicatorShowStyle == PopupDropperItem::AlwaysShow )
177             d->hoverIndicatorRectItem->show();
178         else
179             d->hoverIndicatorRectItem->hide();
180 
181         d->hoverIndicatorRectFillItem->hide();
182 
183         reposHoverFillRects();
184     }
185 
186     if( d->pd )
187         d->pd->updateAllOverlays();
188 }
189 
hoverIndicatorShowStyle() const190 PopupDropperItem::HoverIndicatorShowStyle PopupDropperItem::hoverIndicatorShowStyle() const
191 {
192     return d->hoverIndicatorShowStyle;
193 }
194 
setHoverIndicatorShowStyle(HoverIndicatorShowStyle hover)195 void PopupDropperItem::setHoverIndicatorShowStyle( HoverIndicatorShowStyle hover )
196 {
197     d->hoverIndicatorShowStyle = hover;
198     if( !d->hoveredOver )
199     {
200         if( d->hoverIndicatorShowStyle == PopupDropperItem::AlwaysShow )
201             d->hoverIndicatorRectItem->show();
202         else
203             d->hoverIndicatorRectItem->hide();
204     }
205 }
206 
orientation() const207 PopupDropperItem::Orientation PopupDropperItem::orientation() const
208 {
209     return d->orientation;
210 }
211 
setOrientation(const Orientation orientation)212 void PopupDropperItem::setOrientation( const Orientation orientation )
213 {
214     d->orientation = orientation;
215     fullUpdate();
216 }
217 
textProtection() const218 PopupDropperItem::TextProtection PopupDropperItem::textProtection() const
219 {
220     return d->textProtection;
221 }
222 
setTextProtection(const TextProtection textProtection)223 void PopupDropperItem::setTextProtection( const TextProtection textProtection )
224 {
225     d->textProtection = textProtection;
226     fullUpdate();
227 }
228 
text() const229 QString PopupDropperItem::text() const
230 {
231     return d->text;
232 }
233 
setText(const QString & text)234 void PopupDropperItem::setText( const QString &text )
235 {
236     d->text = text;
237     if( d->textItem )
238         d->textItem->setHtml( text );
239     reposTextItem();
240 }
241 
font() const242 QFont PopupDropperItem::font() const
243 {
244     return d->font;
245 }
246 
setFont(const QFont & font)247 void PopupDropperItem::setFont( const QFont &font )
248 {
249     d->font = font;
250     if( d->textItem )
251         d->textItem->setFont( font );
252     reposTextItem();
253 }
254 
baseTextColor() const255 QColor PopupDropperItem::baseTextColor() const
256 {
257     return d->baseTextColor;
258 }
259 
setBaseTextColor(const QColor & color)260 void PopupDropperItem::setBaseTextColor( const QColor &color )
261 {
262     if( !d->hoveredOver && d->textItem )
263         d->textItem->setDefaultTextColor( color );
264     d->baseTextColor = color;
265     d->customBaseTextColor = true;
266 }
267 
hoveredTextColor() const268 QColor PopupDropperItem::hoveredTextColor() const
269 {
270     return d->hoveredTextColor;
271 }
272 
setHoveredTextColor(const QColor & color)273 void PopupDropperItem::setHoveredTextColor( const QColor &color )
274 {
275     if( d->textItem && d->hoveredOver && d->hoverTimer.state() != QTimeLine::Running )
276         d->textItem->setDefaultTextColor( color );
277     d->hoveredTextColor = color;
278     d->customHoveredTextColor = true;
279 }
280 
hoveredBorderPen() const281 QPen PopupDropperItem::hoveredBorderPen() const
282 {
283     return d->hoveredBorderPen;
284 }
285 
setHoveredBorderPen(const QPen & pen)286 void PopupDropperItem::setHoveredBorderPen( const QPen &pen )
287 {
288     d->hoveredBorderPen = pen;
289     d->customHoveredBorderPen = true;
290     if( d->borderRectItem && ( !d->hoveredOver || ( d->hoveredOver && d->hoverTimer.state() != QTimeLine::Running ) ) )
291     {
292         QPen borderPen = pen;
293     	if( !d->hoveredOver )
294     	{
295             QColor pencolor = borderPen.color();
296             pencolor.setAlpha( 0 );
297             borderPen.setColor( pencolor );
298         }
299         d->borderRectItem->setPen( borderPen );
300     }
301     if( d->hoverIndicatorRectItem && ( !d->hoveredOver || ( d->hoveredOver && d->hoverTimer.state() != QTimeLine::Running ) ) )
302     {
303         QPen borderPen = d->hoveredBorderPen;
304         QColor color = borderPen.color();
305         color.setAlpha( 255 );
306         borderPen.setColor( color );
307         d->hoverIndicatorRectItem->setPen( borderPen );
308     }
309 }
310 
hoveredFillBrush() const311 QBrush PopupDropperItem::hoveredFillBrush() const
312 {
313     return d->hoveredFillBrush;
314 }
315 
setHoveredFillBrush(const QBrush & brush)316 void PopupDropperItem::setHoveredFillBrush( const QBrush &brush )
317 {
318     d->hoveredFillBrush = brush;
319     d->customHoveredFillBrush = true;
320     if( d->borderRectItem && ( !d->hoveredOver || ( d->hoveredOver && d->hoverTimer.state() != QTimeLine::Running ) ) )
321     {
322         QBrush borderBrush = brush;
323         if( !d->hoveredOver )
324         {
325             QColor brushColor = borderBrush.color();
326             brushColor.setAlpha( 0 );
327             borderBrush.setColor( brushColor );
328         }
329         d->borderRectItem->setBrush( borderBrush );
330     }
331 }
332 
hoverIndicatorFillBrush() const333 QBrush PopupDropperItem::hoverIndicatorFillBrush() const
334 {
335     return d->hoverIndicatorRectFillBrush;
336 }
337 
setHoverIndicatorFillBrush(const QBrush & brush)338 void PopupDropperItem::setHoverIndicatorFillBrush( const QBrush &brush )
339 {
340     d->hoverIndicatorRectFillBrush = brush;
341     if( d->hoverIndicatorRectFillItem && ( d->hoveredOver && d->hoverTimer.state() != QTimeLine::Running ) )
342         d->hoverIndicatorRectFillItem->setBrush( d->hoverIndicatorRectFillBrush );
343 }
344 
customBaseTextColor() const345 bool PopupDropperItem::customBaseTextColor() const
346 {
347     return d->customBaseTextColor;
348 }
349 
customHoveredTextColor() const350 bool PopupDropperItem::customHoveredTextColor() const
351 {
352     return d->customHoveredTextColor;
353 }
354 
customHoveredBorderPen() const355 bool PopupDropperItem::customHoveredBorderPen() const
356 {
357     return d->customHoveredBorderPen;
358 }
359 
customHoveredFillBrush() const360 bool PopupDropperItem::customHoveredFillBrush() const
361 {
362     return d->customHoveredFillBrush;
363 }
364 
subitemOpacity() const365 qreal PopupDropperItem::subitemOpacity() const
366 {
367     return d->subitemOpacity;
368 }
369 
setSubitemOpacity(qreal opacity)370 void PopupDropperItem::setSubitemOpacity( qreal opacity )
371 {
372     if( d->svgItem )
373         d->svgItem->setOpacity( opacity );
374     if( d->textItem )
375         d->textItem->setOpacity( opacity );
376     if( d->borderRectItem )
377         d->borderRectItem->setOpacity( opacity );
378     if( d->hoverIndicatorRectItem )
379         d->hoverIndicatorRectItem->setOpacity( opacity );
380     if( d->hoverIndicatorRectFillItem )
381         d->hoverIndicatorRectFillItem->setOpacity( opacity );
382 }
383 
textItem() const384 QGraphicsTextItem* PopupDropperItem::textItem() const
385 {
386     return d->textItem;
387 }
388 
setTextItem(QGraphicsTextItem * textItem)389 void PopupDropperItem::setTextItem( QGraphicsTextItem *textItem )
390 {
391     d->textItem = textItem;
392     if( d->textItem )
393         d->textItem->setHtml( d->text );
394 }
395 
borderRectItem() const396 QGraphicsRectItem* PopupDropperItem::borderRectItem() const
397 {
398     return d->borderRectItem;
399 }
400 
setBorderRectItem(QGraphicsRectItem * borderRectItem)401 void PopupDropperItem::setBorderRectItem( QGraphicsRectItem *borderRectItem )
402 {
403     if( !borderRectItem )
404         return;
405 
406     d->borderRectItem = borderRectItem;
407     if( !d->hoveredOver  )
408     {
409         QPen pen = d->hoveredBorderPen;
410         QColor color = pen.color();
411         color.setAlpha( 0 );
412         pen.setColor( color );
413         d->borderRectItem->setPen( pen );
414         QBrush brush = d->hoveredFillBrush;
415         color = brush.color();
416         color.setAlpha( 0 );
417         brush.setColor( color );
418         d->borderRectItem->setBrush( brush );
419     }
420 }
421 
svgItem() const422 QGraphicsSvgItem* PopupDropperItem::svgItem() const
423 {
424     return d->svgItem;
425 }
426 
scaleAndReposSvgItem()427 void PopupDropperItem::scaleAndReposSvgItem()
428 {
429     if( !d->svgItem || !d->borderRectItem )
430         return;
431 
432     if( d->separator )
433     {
434         d->svgItem->setScale( 1.0 );
435         d->svgItem->setPos( 0, 0 );
436         return;
437     }
438 
439     //Need to scale if it is too tall or wide
440     qreal maxheight = d->svgElementRect.height() - ( 2 * d->borderRectItem->pen().width() );
441     qreal maxwidth = d->svgElementRect.width() - ( 2 * d->borderRectItem->pen().width() );
442     qreal vertScaleValue = maxheight / d->svgItem->sceneBoundingRect().height();
443     qreal horizScaleValue = maxwidth / d->svgItem->sceneBoundingRect().width();
444     qreal scaleValue = vertScaleValue < horizScaleValue ? vertScaleValue : horizScaleValue;
445 
446     d->svgItem->setScale( scaleValue );
447 
448     qreal item_center = ( d->borderRectItem->sceneBoundingRect().height() / 2 ) + d->borderRectItem->pos().y();
449 
450     if( d->orientation == PopupDropperItem::Left )
451     {
452         d->svgItem->setPos( d->horizontalOffset, item_center - ( d->svgElementRect.height() / 2 ) );
453     }
454     else
455     {
456         int rightside;
457         if( !d->pd || d->pd->viewSize().width() == 0 )
458             rightside = sceneBoundingRect().width();
459         else
460             rightside = d->pd->viewSize().width();
461 
462         d->svgItem->setPos(
463             rightside
464             - d->svgItem->sceneBoundingRect().width()
465             - d->horizontalOffset
466             , item_center - ( d->svgElementRect.height() / 2 ) );
467     }
468 }
469 
reposTextItem()470 void PopupDropperItem::reposTextItem()
471 {
472     if( !d->textItem || !d->borderRectItem )
473         return;
474     d->textItem->setFont( d->font );
475 
476     qreal item_vert_center = ( d->borderRectItem->sceneBoundingRect().height() / 2 ) + d->borderRectItem->pos().y();
477 
478     if( d->separator )
479     {
480         if( d->text.isEmpty() )
481             return;
482         qreal width = d->textItem->textWidth();
483         if( width > d->borderRectItem->sceneBoundingRect().width() )
484             d->textItem->setTextWidth( d->borderRectItem->sceneBoundingRect().width() );
485         qreal offset = ( d->borderRectItem->sceneBoundingRect().width() - width ) / 2;
486         d->textItem->setPos( offset, item_vert_center - ( d->textItem->sceneBoundingRect().height()  / 2 ) );
487         return;
488     }
489 
490     int offsetPos = d->horizontalOffset + d->textOffset + d->svgElementRect.width();
491     d->textItem->setPos(
492             ( d->orientation == PopupDropperItem::Left
493                 ? offsetPos
494                 : 0
495             )
496         , item_vert_center - ( d->textItem->sceneBoundingRect().height() / 2 ) );
497 
498     if( d->textProtection == PopupDropperItem::ScaleFont )
499     {
500         QFontMetrics fm( d->textItem->font() );
501         qreal desiredWidth = d->borderRectItem->sceneBoundingRect().width() - offsetPos;
502         while( d->textItem->font().pointSize() > 1 &&
503                 ( fm.width( d->textItem->toPlainText() ) > desiredWidth ||
504                   fm.height() > d->textItem->boundingRect().height() ) )
505         {
506             QFont font = d->textItem->font();
507             font.setPointSize( font.pointSize() - 1 );
508             d->textItem->setFont( font );
509             fm = QFontMetrics( font );
510         }
511     }
512     else if( d->textProtection == PopupDropperItem::MultiLine &&
513              ( d->textItem->textWidth() == -1 ||
514                d->textItem->textWidth() > ( d->borderRectItem->sceneBoundingRect().width() - offsetPos )
515              )
516            )
517     {
518         d->textItem->setTextWidth( d->borderRectItem->sceneBoundingRect().width() - offsetPos );
519         reposTextItem();
520     }
521 }
522 
reposHoverFillRects()523 void PopupDropperItem::reposHoverFillRects()
524 {
525     if( !d->hoverIndicatorRectItem || !d->hoverIndicatorRectFillItem || !d->textItem || !d->borderRectItem )
526         return;
527 
528     if( d->separator )
529     {
530         d->hoverIndicatorRectItem->setRect( 0, 0, 0, 0 );
531         d->hoverIndicatorRectFillItem->setRect( 0, 0, 0, 0 );
532         return;
533     }
534 
535     //qDebug() << "\n\nPUDItem boundingRect().width() = " << boundingRect().width();
536     qreal startx, starty, endx, endy, item_center;
537     //int rightside = d->borderRectItem ? d->borderRectItem->boundingRect().width() : boundingRect().width();
538     if( d->orientation == PopupDropperItem::Left )
539     {
540         startx = d->horizontalOffset
541                 - d->hoverIndicatorRectWidth
542                 - ( 2  * d->hoverIndicatorRectItem->pen().width() );
543     }
544     else
545     {
546         int rightside = (!d->pd || d->pd->viewSize().width() == 0 )
547                 ? sceneBoundingRect().width()
548                 : d->pd->viewSize().width();
549         //qDebug() << "right side = " << rightside;
550         startx = rightside - d->horizontalOffset
551                  + d->hoverIndicatorRectWidth
552                  - ( 2 * d->hoverIndicatorRectItem->pen().width() );
553     }
554 
555     item_center = ( d->borderRectItem->sceneBoundingRect().height() / 2 ) + d->borderRectItem->pos().y();
556 
557     starty = item_center - ( d->svgElementRect.height() / 2 );
558 
559     endx = d->hoverIndicatorRectWidth - ( 2 * d->hoverIndicatorRectItem->pen().width() );
560 
561     endy = d->svgElementRect.height();
562 
563     QRectF indicatorRect( startx, starty, endx, endy );
564     d->hoverIndicatorRectItem->setRect( indicatorRect );
565 
566     QRectF indicatorFillRect(
567             indicatorRect.left() + d->hoverIndicatorRectItem->pen().width()
568             , indicatorRect.bottom() - d->hoverIndicatorRectItem->pen().width()
569             , indicatorRect.width() - ( 2 * d->hoverIndicatorRectItem->pen().width() )
570             , 0 );
571     d->hoverIndicatorRectFillItem->setRect( indicatorFillRect );
572 }
573 
sharedRenderer() const574 QSvgRenderer* PopupDropperItem::sharedRenderer() const
575 {
576     return d->sharedRenderer;
577 }
578 
setSharedRenderer(QSvgRenderer * renderer)579 void PopupDropperItem::setSharedRenderer( QSvgRenderer *renderer )
580 {
581     d->sharedRenderer = renderer;
582     if( renderer && d->svgItem )
583     {
584         d->svgItem->setSharedRenderer( renderer );
585         d->svgItem->setElementId( d->elementId );
586         if( !d->svgItem->elementId().isEmpty() && d->svgItem->renderer()->elementExists( d->svgItem->elementId() ) )
587         {
588             d->svgItem->show();
589             fullUpdate();
590         }
591     }
592 }
593 
elementId() const594 QString PopupDropperItem::elementId() const
595 {
596     return d->elementId;
597 }
598 
setElementId(const QString & id)599 void PopupDropperItem::setElementId( const QString &id )
600 {
601     //qDebug() << "Element ID being set: " << id;
602     d->elementId = id;
603     if( id.isEmpty() )
604     {
605         d->svgItem->hide();
606         fullUpdate();
607     }
608     else if( d->svgItem && d->svgItem->renderer() && d->svgItem->renderer()->elementExists( id ))
609     {
610         d->svgItem->setElementId( id );
611         d->svgItem->show();
612         fullUpdate();
613     }
614 }
615 
svgElementRect() const616 QRect PopupDropperItem::svgElementRect() const
617 {
618     return d->svgElementRect;
619 }
620 
setSvgElementRect(const QRect & rect)621 void PopupDropperItem::setSvgElementRect( const QRect &rect )
622 {
623     d->svgElementRect = rect;
624 }
625 
horizontalOffset() const626 int PopupDropperItem::horizontalOffset() const
627 {
628     return d->horizontalOffset;
629 }
630 
setHorizontalOffset(int offset)631 void PopupDropperItem::setHorizontalOffset( int offset )
632 {
633     d->horizontalOffset = offset;
634 }
635 
textOffset() const636 int PopupDropperItem::textOffset() const
637 {
638     return d->textOffset;
639 }
640 
setTextOffset(int offset)641 void PopupDropperItem::setTextOffset( int offset )
642 {
643     d->textOffset = offset;
644 }
645 
isSeparator() const646 bool PopupDropperItem::isSeparator() const
647 {
648     return d->separator;
649 }
650 
setSeparator(bool separator)651 void PopupDropperItem::setSeparator( bool separator )
652 {
653     d->separator = separator;
654 }
655 
separatorStyle() const656 PopupDropperItem::SeparatorStyle PopupDropperItem::separatorStyle() const
657 {
658     return d->separatorStyle;
659 }
660 
setSeparatorStyle(SeparatorStyle style)661 void PopupDropperItem::setSeparatorStyle( SeparatorStyle style )
662 {
663     d->separatorStyle = style;
664 }
665 
hasLineSeparatorPen() const666 bool PopupDropperItem::hasLineSeparatorPen() const
667 {
668     return d->hasLineSeparatorPen;
669 }
670 
lineSeparatorPen() const671 QPen PopupDropperItem::lineSeparatorPen() const
672 {
673     return d->lineSeparatorPen;
674 }
675 
setLineSeparatorPen(const QPen & pen)676 void PopupDropperItem::setLineSeparatorPen( const QPen &pen )
677 {
678     d->lineSeparatorPen = pen;
679 }
680 
clearLineSeparatorPen()681 void PopupDropperItem::clearLineSeparatorPen()
682 {
683     d->lineSeparatorPen = QPen();
684     d->hasLineSeparatorPen = false;
685 }
686 
hoverMsecs() const687 int PopupDropperItem::hoverMsecs() const
688 {
689     return d->hoverTimer.duration();
690 }
691 
setHoverMsecs(const int msecs)692 void PopupDropperItem::setHoverMsecs( const int msecs )
693 {
694     d->hoverTimer.setDuration( msecs );
695 }
696 
hoverEntered()697 void PopupDropperItem::hoverEntered()
698 {
699     if( d->hoverIndicatorRectItem && d->hoverIndicatorRectFillItem && d->hoverIndicatorShowStyle != PopupDropperItem::Never )
700     {
701         d->hoverIndicatorRectFillItem->show();
702     }
703     d->hoverTimer.stop();
704     d->hoverTimer.setDirection( QTimeLine::Forward );
705     d->hoveredOver = true;
706     d->hoverTimer.start();
707 }
708 
hoverLeft()709 void PopupDropperItem::hoverLeft()
710 {
711     d->hoverTimer.stop();
712     d->hoverTimer.setDirection( QTimeLine::Backward );
713     d->hoveredOver = false;
714     if( d->hoverTimer.currentFrame() != 0 )
715         d->hoverTimer.start();
716 }
717 
borderWidth() const718 int PopupDropperItem::borderWidth() const
719 {
720     return d->borderWidth;
721 }
722 
setBorderWidth(int borderWidth)723 void PopupDropperItem::setBorderWidth( int borderWidth )
724 {
725     d->borderWidth = borderWidth;
726     d->hoveredBorderPen.setWidth( borderWidth );
727     if( d->borderRectItem )
728     {
729         d->borderRectItem->setPen( d->hoveredBorderPen );
730     }
731 }
732 
hoverIndicatorRectWidth() const733 int PopupDropperItem::hoverIndicatorRectWidth() const
734 {
735     return d->hoverIndicatorRectWidth;
736 }
737 
setHoverIndicatorRectWidth(int hoverIndicatorRectWidth)738 void PopupDropperItem::setHoverIndicatorRectWidth( int hoverIndicatorRectWidth )
739 {
740     d->hoverIndicatorRectWidth = hoverIndicatorRectWidth;
741     if( d->hoverIndicatorRectItem )
742     {
743         QPen pen = d->hoverIndicatorRectItem->pen();
744         pen.setWidth( d->hoverIndicatorRectWidth );
745         d->hoverIndicatorRectItem->setPen( pen );
746     }
747 }
748 
isSubmenuTrigger() const749 bool PopupDropperItem::isSubmenuTrigger() const
750 {
751     return d->submenuTrigger;
752 }
753 
setSubmenuTrigger(bool trigger)754 void PopupDropperItem::setSubmenuTrigger( bool trigger )
755 {
756     d->submenuTrigger = trigger;
757 }
758 
setPopupDropper(PopupDropper * pd)759 void PopupDropperItem::setPopupDropper( PopupDropper* pd )
760 {
761     d->pd = pd;
762 }
763 
764 //bool PopupDropperItem::operator<( const PopupDropperItem &other ) const
765 //{
766 //    return d->text < other.text();
767 //}
768 
dropped(QDropEvent * event)769 void PopupDropperItem::dropped( QDropEvent *event ) //virtual SLOT
770 {
771     Q_UNUSED( event );
772     d->hoverTimer.stop();
773     //qDebug() << "PopupDropperItem drop detected";
774     if( d->action )
775     {
776         //qDebug() << "Triggering action";
777         d->action->activate( QAction::Trigger );
778     }
779 }
780 
hoverFinished()781 void PopupDropperItem::hoverFinished() //SLOT
782 {
783     if( d->separator )
784         return;
785 
786     //qDebug() << "direction = forwards ? " << ( d->hoverTimer.direction() == QTimeLine::Forward ? "yes" : "no" );
787 
788     if( d->action && d->hoverTimer.direction() == QTimeLine::Forward )
789         d->action->activate( QAction::Hover );
790 
791     if( d->hoverTimer.direction() == QTimeLine::Forward )
792         d->textItem->setDefaultTextColor( d->hoveredTextColor );
793     else
794         d->textItem->setDefaultTextColor( d->baseTextColor );
795 
796     //Something is messed up in QTimeLine...I get hoverFinished immediately after doing a hoverLeft, but only sometimes...hence the check
797     //to see if the timeline isn't running
798     if( d->hoverIndicatorRectFillItem && d->hoverTimer.state() == QTimeLine::NotRunning && d->hoverTimer.direction() == QTimeLine::Backward )
799     {
800         d->hoverIndicatorRectFillItem->hide();
801         if( d->hoverIndicatorRectItem && d->hoverIndicatorShowStyle != PopupDropperItem::AlwaysShow )
802             d->hoverIndicatorRectItem->hide();
803     }
804 
805     if( d->pd )
806         d->pd->updateAllOverlays();
807 }
808 
hoverFrameChanged(int frame)809 void PopupDropperItem::hoverFrameChanged( int frame ) //SLOT
810 {
811     if( d->separator )
812         return;
813     //qDebug() << "hoverFrameChanged for " << static_cast<QObject*>(this) << ", frame = " << frame;
814     int range = d->hoverTimer.endFrame() - d->hoverTimer.startFrame();
815     qreal multiplier = ( 1.0 * frame ) / range;
816     int r = (int)( ( d->hoveredTextColor.red() - d->baseTextColor.red() ) * multiplier ) + d->baseTextColor.red();
817     int g = (int)( ( d->hoveredTextColor.green() - d->baseTextColor.green() ) * multiplier ) + d->baseTextColor.green();
818     int b = (int)( ( d->hoveredTextColor.blue() - d->baseTextColor.blue() ) * multiplier ) + d->baseTextColor.blue();
819     int a = (int)( ( d->hoveredTextColor.alpha() - d->baseTextColor.alpha() ) * multiplier ) + d->baseTextColor.alpha();
820 
821     d->textItem->setDefaultTextColor( QColor( r, g, b, a ) );
822 
823     QColor borderColor = d->hoveredBorderPen.color();
824     borderColor.setAlpha( (int)( borderColor.alpha() * multiplier ) );
825     QPen pen = d->borderRectItem->pen();
826     pen.setColor( borderColor );
827     d->borderRectItem->setPen( pen );
828     if( d->hoverIndicatorRectItem && d->hoverIndicatorShowStyle == PopupDropperItem::OnHover )
829     {
830         d->hoverIndicatorRectItem->setPen( pen );
831         d->hoverIndicatorRectItem->show();
832     }
833     QColor fillColor = d->hoveredFillBrush.color();
834     QBrush brush = d->borderRectItem->brush();
835     fillColor.setAlpha( (int)( fillColor.alpha() * multiplier ) );
836     brush.setColor( fillColor );
837     d->borderRectItem->setBrush( brush );
838 
839     if( d->hoverIndicatorRectItem && d->hoverIndicatorRectFillItem && d->hoverIndicatorShowStyle != PopupDropperItem::Never )
840     {
841         int hoverIndicatorPenWidth = d->hoverIndicatorRectItem->pen().width();
842         QRectF rect = d->hoverIndicatorRectFillItem->rect();
843         QRectF outerRect = d->hoverIndicatorRectItem->rect();
844         rect.setTop( ( multiplier * -1 * ( outerRect.bottom() - outerRect.top() - ( 2 * hoverIndicatorPenWidth ) ) )
845                 + outerRect.bottom()
846                 - hoverIndicatorPenWidth );
847         d->hoverIndicatorRectFillItem->setRect( rect );
848         d->hoverIndicatorRectFillItem->setBrush( d->hoverIndicatorRectFillBrush );
849         d->hoverIndicatorRectFillItem->show();
850         //qDebug() << "hoverIndicatorRectFillItem = " << d->hoverIndicatorRectFillItem;
851     }
852 
853     if( d->pd )
854         d->pd->updateAllOverlays();
855 }
856 
fullUpdate()857 void PopupDropperItem::fullUpdate()
858 {
859     scaleAndReposSvgItem();
860     reposTextItem();
861     reposHoverFillRects();
862     if( d->pd )
863         d->pd->updateAllOverlays();
864 }
865 
boundingRect() const866 QRectF PopupDropperItem::boundingRect() const
867 {
868     if( d->borderRectItem )
869         return d->borderRectItem->boundingRect();
870     else if( d->pd && d->pd->viewSize().width() != 0 )
871         return QRectF( 0, 0, d->pd->viewSize().width(), d->svgElementRect.height() );
872     else
873         return QRectF( 0, 0, d->svgElementRect.width(), d->svgElementRect.height() );
874 }
875 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)876 void PopupDropperItem::paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget )
877 {
878     Q_UNUSED( painter )
879     Q_UNUSED( option )
880     Q_UNUSED( widget )
881     return;
882 }
883 
884 
885