add more spacing
[personal-kdebase.git] / workspace / plasma / applets / tasks / abstracttaskitem.cpp
blobe9e50ace40a27fdb2efcb4172483baa751d20f56
1 /***************************************************************************
2 * Copyright (C) 2007 by Robert Knight <robertknight@gmail.com> *
3 * Copyright (C) 2008 by Alexis Ménard <darktears31@gmail.com> *
4 * Copyright (C) 2008 by Marco Martin <notmart@gmail.com> *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
20 ***************************************************************************/
22 // Own
23 #include "abstracttaskitem.h"
25 // Qt
26 #include <QGraphicsSceneContextMenuEvent>
27 #include <QStyleOptionGraphicsItem>
28 #include <QGraphicsView>
29 #include <QTimer>
30 #include <QApplication>
31 #include <QTextLayout>
32 #include <QGraphicsLinearLayout>
34 // KDE
35 #include <KAuthorized>
36 #include <KDebug>
37 #include <KIcon>
38 #include <KIconEffect>
39 #include <KLocalizedString>
40 #include <KGlobalSettings>
41 #include <KIconLoader>
42 #include <KColorUtils>
44 #include <taskmanager/task.h>
45 #include <taskmanager/taskmanager.h>
46 #include <taskmanager/taskgroup.h>
48 #include <Plasma/Theme>
49 #include <Plasma/PaintUtils>
50 #include <Plasma/FrameSvg>
51 #include <Plasma/ToolTipManager>
53 #include "tasks.h"
54 #include "taskgroupitem.h"
55 #include "layoutwidget.h"
57 AbstractTaskItem::AbstractTaskItem(QGraphicsWidget *parent, Tasks *applet, const bool showTooltip)
58 : QGraphicsWidget(parent),
59 m_abstractItem(0),
60 m_applet(applet),
61 m_activateTimer(0),
62 m_flags(0),
63 m_animId(0),
64 m_alpha(1),
65 m_backgroundPrefix("normal"),
66 m_updateTimerId(0),
67 m_attentionTimerId(0),
68 m_attentionTicks(0),
69 m_fadeIn(true),
70 m_showTooltip(showTooltip),
71 m_showingTooltip(false)
73 setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
74 setAcceptsHoverEvents(true);
75 setAcceptDrops(true);
77 Plasma::ToolTipManager::self()->registerWidget(this);
78 setPreferredSize(basicPreferredSize());
79 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(syncActiveRect()));
80 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), SLOT(queueUpdate()));
81 connect(applet, SIGNAL(settingsChanged()), this, SLOT(checkSettings()));
84 QSize AbstractTaskItem::basicPreferredSize() const
86 QFontMetrics fm(KGlobalSettings::taskbarFont());
87 QSize mSize = fm.size(0, "M");
88 int iconsize = KIconLoader::SizeSmall;
90 //the 4 should be the default spacing between layout items, is there a way to fetch it without hardcoding?
91 // in small panels, we'll reduce the spacing a bit so it's easier to cramp the text in and still get two rows
92 int topMargin = m_applet->itemTopMargin();
93 int bottomMargin = m_applet->itemBottomMargin();
94 if (m_applet->size().height() < 44) {
95 topMargin = 1;
96 bottomMargin = 1;
97 } else if (m_applet->size().height() < 64) {
98 topMargin = qMax(1, topMargin/2);
99 bottomMargin = qMax(1, bottomMargin/2);
101 return QSize(mSize.width()*12 + m_applet->itemLeftMargin() + m_applet->itemRightMargin() + KIconLoader::SizeSmall,
102 qMax(mSize.height(), iconsize) + topMargin + bottomMargin);
105 AbstractTaskItem::~AbstractTaskItem()
107 if (m_animId) {
108 Plasma::Animator::self()->stopCustomAnimation(m_animId);
111 Plasma::ToolTipManager::self()->unregisterWidget(this);
114 void AbstractTaskItem::checkSettings()
116 TaskGroupItem *group = qobject_cast<TaskGroupItem *>(this);
118 if (group && !group->collapsed()) {
119 m_showTooltip = false;
120 } else if (m_showTooltip != m_applet->showTooltip()) {
121 m_showTooltip = !m_showTooltip;
125 void AbstractTaskItem::setShowTooltip(const bool showit)
127 m_showTooltip = showit;
130 void AbstractTaskItem::setText(const QString &text)
132 m_text = text;
135 void AbstractTaskItem::setIcon(const QIcon &icon)
137 m_icon = icon; //icon.pixmap(MinTaskIconSize);
140 QIcon AbstractTaskItem::icon() const
142 return m_icon;
145 QString AbstractTaskItem::text() const
147 return m_text;
150 void AbstractTaskItem::setTaskFlags(const TaskFlags flags)
152 if (((m_flags & TaskWantsAttention) != 0) != ((flags & TaskWantsAttention) != 0)) {
153 //kDebug() << "task attention state changed" << m_attentionTimerId;
154 if (flags & TaskWantsAttention) {
155 // start attention getting
156 if (!m_attentionTimerId) {
157 m_attentionTimerId = startTimer(500);
159 } else if (m_attentionTimerId) {
160 killTimer(m_attentionTimerId);
161 m_attentionTimerId = 0;
162 // stop attention getting
166 m_flags = flags;
168 QString newBackground;
169 if (m_flags & TaskIsMinimized) {
170 newBackground = "minimized";
171 } else if (m_flags & TaskHasFocus) {
172 newBackground = "focus";
173 } else {
174 newBackground = "normal";
177 if (newBackground != m_backgroundPrefix) {
178 fadeBackground(newBackground, 100, true);
182 void AbstractTaskItem::fadeBackground(const QString &newBackground, int duration, bool fadeIn)
184 m_oldBackgroundPrefix = m_backgroundPrefix;
185 m_backgroundPrefix = newBackground;
187 if (m_animId) {
188 Plasma::Animator::self()->stopCustomAnimation(m_animId);
191 m_fadeIn = fadeIn;
192 m_animId = Plasma::Animator::self()->customAnimation(40 / (1000 / duration), duration,Plasma::Animator::LinearCurve, this, "animationUpdate");
196 AbstractTaskItem::TaskFlags AbstractTaskItem::taskFlags() const
198 return m_flags;
201 void AbstractTaskItem::toolTipAboutToShow()
203 if (m_showTooltip) {
204 m_showingTooltip = true;
205 updateToolTip();
206 } else {
207 Plasma::ToolTipManager::self()->clearContent(this);
211 void AbstractTaskItem::toolTipHidden()
213 m_showingTooltip = false;
214 Plasma::ToolTipManager::self()->clearContent(this);
217 void AbstractTaskItem::queueUpdate()
219 if (m_updateTimerId || m_attentionTimerId) {
220 return;
223 if (m_lastUpdate.elapsed() < 200) {
224 m_updateTimerId = startTimer(200);
225 return;
228 update();
229 m_lastUpdate.restart();
232 void AbstractTaskItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
234 Q_UNUSED(event)
236 fadeBackground("hover", 175, true);
239 void AbstractTaskItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
241 Q_UNUSED(event)
243 QString backgroundPrefix;
245 if (m_flags & TaskWantsAttention) {
246 backgroundPrefix = "attention";
247 } else if (m_flags & TaskIsMinimized) {
248 backgroundPrefix = "minimized";
249 } else if (m_flags & TaskHasFocus) {
250 backgroundPrefix = "focus";
251 } else {
252 backgroundPrefix = "normal";
255 fadeBackground(backgroundPrefix, 150, false);
258 void AbstractTaskItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
260 if (event->button() == Qt::LeftButton/* || event->button() == Qt::MidButton*/) {
261 activate();
265 void AbstractTaskItem::mousePressEvent(QGraphicsSceneMouseEvent *)
267 update();
270 void AbstractTaskItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
272 //kDebug();
273 if (QPoint(event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < QApplication::startDragDistance()) {
274 return;
275 } //Wait a bit before starting drag
277 /* if((m_applet->taskSortOrder() != Tasks::NoSorting) && (m_applet->taskSortOrder() != Tasks::GroupSorting)){ //FIXME check somhow if drag is allowed
278 return;
281 QByteArray data;
282 data.resize(sizeof(AbstractTaskItem*));
283 AbstractTaskItem *selfPtr = this;
284 memcpy(data.data(), &selfPtr, sizeof(AbstractTaskItem*));
286 QMimeData* mimeData = new QMimeData();
287 setAdditionalMimeData(mimeData);
289 QDrag *drag = new QDrag(event->widget());
290 drag->setMimeData(mimeData);
291 drag->setPixmap(m_icon.pixmap(20));
292 // drag->setDragCursor( set the correct cursor //TODO
293 drag->exec();
296 void AbstractTaskItem::timerEvent(QTimerEvent *event)
298 if (event->timerId() == m_updateTimerId) {
299 killTimer(m_updateTimerId);
300 update();
301 m_updateTimerId = 0;
302 } else if (event->timerId() == m_attentionTimerId) {
303 ++m_attentionTicks;
304 if (m_attentionTicks > 6) {
305 killTimer(m_attentionTimerId);
306 m_attentionTimerId = 0;
307 m_attentionTicks = 0;
310 if (m_attentionTicks % 2 == 0) {
311 fadeBackground("attention", 100, false);
312 } else {
313 fadeBackground("normal", 150, false);
316 update();
320 void AbstractTaskItem::paint(QPainter *painter,
321 const QStyleOptionGraphicsItem *option,
322 QWidget *widget)
324 painter->setRenderHint(QPainter::Antialiasing);
326 // draw background
327 drawBackground(painter, option, widget);
329 // draw icon and text
330 drawTask(painter, option, widget);
333 void AbstractTaskItem::syncActiveRect()
335 Plasma::FrameSvg *itemBackground = m_applet->itemBackground();
337 if (!itemBackground) {
338 return;
341 itemBackground->setElementPrefix("normal");
343 qreal left, top, right, bottom;
344 itemBackground->getMargins(left, top, right, bottom);
346 itemBackground->setElementPrefix("focus");
347 qreal activeLeft, activeTop, activeRight, activeBottom;
348 itemBackground->getMargins(activeLeft, activeTop, activeRight, activeBottom);
350 m_activeRect = QRectF(QPointF(0, 0), size());
351 m_activeRect.adjust(left - activeLeft, top - activeTop,
352 -(right - activeRight), -(bottom - activeBottom));
354 itemBackground->setElementPrefix(m_backgroundPrefix);
357 void AbstractTaskItem::drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
359 // Do not paint with invalid sizes, the happens when the layout is being initialized
360 if (!option->rect.isValid()) {
361 return;
364 /*FIXME -could be done more elegant with caching in tasks in a qhash <size,svg>.
365 -do not use size() directly because this introduces the blackline syndrome.
366 -This line is only needed when we have different items in the taskbar because of an expanded group for example. otherwise the resizing in the resizeEvent is sufficient
368 Plasma::FrameSvg *itemBackground = m_applet->itemBackground();
370 if (!itemBackground) {
371 return;
374 //if the size is changed have to resize all the elements
375 if (itemBackground->size() != size().toSize() && itemBackground->size() != m_activeRect.size().toSize()) {
376 syncActiveRect();
378 itemBackground->setElementPrefix("focus");
379 m_applet->resizeItemBackground(m_activeRect.size().toSize());
380 itemBackground->setElementPrefix("normal");
381 m_applet->resizeItemBackground(size().toSize());
382 itemBackground->setElementPrefix("minimized");
383 m_applet->resizeItemBackground(size().toSize());
384 itemBackground->setElementPrefix("attention");
385 m_applet->resizeItemBackground(size().toSize());
386 itemBackground->setElementPrefix("hover");
387 m_applet->resizeItemBackground(m_activeRect.size().toSize());
389 //restore the prefix
390 itemBackground->setElementPrefix(m_backgroundPrefix);
395 if (!m_animId && ~option->state & QStyle::State_Sunken) {
396 itemBackground->setElementPrefix(m_backgroundPrefix);
397 if (itemBackground->frameSize() == m_activeRect.size().toSize()) {
398 itemBackground->paintFrame(painter, m_activeRect.topLeft());
399 } else {
400 itemBackground->paintFrame(painter);
402 //itemBackground->paintFrame(painter, backgroundPosition);
403 return;
406 itemBackground->setElementPrefix(m_oldBackgroundPrefix);
407 QPixmap oldBackground;
409 if (option->state & QStyle::State_Sunken) {
410 oldBackground = QPixmap(m_activeRect.size().toSize());
411 oldBackground.fill(Qt::transparent);
412 m_alpha = 0.4;
413 } else {
414 oldBackground = itemBackground->framePixmap();
417 itemBackground->setElementPrefix(m_backgroundPrefix);
418 QPixmap result = Plasma::PaintUtils::transition(oldBackground, itemBackground->framePixmap(), m_alpha);
420 if (result.size() == m_activeRect.size().toSize()) {
421 painter->drawPixmap(m_activeRect.topLeft(), result);
422 } else {
423 painter->drawPixmap(QPoint(0,0), result);
426 return;
429 void AbstractTaskItem::drawTask(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
431 Q_UNUSED(option)
433 QRectF bounds = boundingRect().adjusted(m_applet->itemLeftMargin(), m_applet->itemTopMargin(), -m_applet->itemRightMargin(), -m_applet->itemBottomMargin());
435 if ((!m_animId && ~option->state & QStyle::State_MouseOver) ||
436 (m_oldBackgroundPrefix != "hover" && m_backgroundPrefix != "hover")) {
437 m_icon.paint(painter, iconRect(bounds).toRect());
438 } else {
439 KIconEffect *effect = KIconLoader::global()->iconEffect();
440 QPixmap result = m_icon.pixmap(iconRect(bounds).toRect().size());
442 if (effect->hasEffect(KIconLoader::Desktop, KIconLoader::ActiveState)) {
443 if (qFuzzyCompare(qreal(1.0), m_alpha)) {
444 result = effect->apply(result, KIconLoader::Desktop, KIconLoader::ActiveState);
445 } else {
446 result = Plasma::PaintUtils::transition(
447 result,
448 effect->apply(result, KIconLoader::Desktop,
449 KIconLoader::ActiveState), m_fadeIn?m_alpha:1-m_alpha);
452 painter->drawPixmap(iconRect(bounds).topLeft(), result);
455 painter->setPen(QPen(textColor(), 1.0));
457 QRect rect = textRect(bounds).toRect();
458 if (rect.height() > 20) {
459 rect.adjust(2, 2, -2, -2); // Create a text margin
461 QTextLayout layout;
462 layout.setFont(KGlobalSettings::taskbarFont());
463 layout.setTextOption(textOption());
465 layoutText(layout, m_text, rect.size());
466 drawTextLayout(painter, layout, rect);
468 TaskGroupItem *groupItem = qobject_cast<TaskGroupItem *>(this);
469 if (groupItem) {
470 QFont font(KGlobalSettings::smallestReadableFont());
471 QFontMetrics fm(font);
472 QRectF rect(expanderRect(bounds));
474 Plasma::FrameSvg *itemBackground = m_applet->itemBackground();
476 if (itemBackground && itemBackground->hasElement(expanderElement())) {
477 QSizeF arrowSize(itemBackground->elementSize(expanderElement()));
478 QRectF arrowRect(rect.center()-QPointF(arrowSize.width()/2, arrowSize.height()+fm.xHeight()/2), arrowSize);
479 itemBackground->paint(painter, arrowRect, expanderElement());
481 painter->setFont(font);
482 rect.setTop(arrowRect.bottom());
483 painter->drawText(rect, Qt::AlignHCenter|Qt::AlignTop, QString::number(groupItem->memberList().count()));
484 } else {
485 painter->setFont(font);
486 painter->drawText(rect, Qt::AlignCenter, QString::number(groupItem->memberList().count()));
491 QTextOption AbstractTaskItem::textOption() const
493 Qt::LayoutDirection direction = QApplication::layoutDirection();
494 Qt::Alignment alignment = QStyle::visualAlignment(direction, Qt::AlignLeft | Qt::AlignVCenter);
496 QTextOption option;
497 option.setTextDirection(direction);
498 option.setAlignment(alignment);
500 return option;
503 QSize AbstractTaskItem::layoutText(QTextLayout &layout, const QString &text,
504 const QSize &constraints) const
506 QFontMetrics metrics(layout.font());
507 int leading = metrics.leading();
508 int height = 0;
509 int maxWidth = constraints.width();
510 int widthUsed = 0;
511 int lineSpacing = metrics.lineSpacing();
512 QTextLine line;
514 layout.setText(text);
516 layout.beginLayout();
517 while ((line = layout.createLine()).isValid()) {
518 height += leading;
520 // Make the last line that will fit infinitely long.
521 // drawTextLayout() will handle this by fading the line out
522 // if it won't fit in the contraints.
523 if (height + 2 * lineSpacing > constraints.height()) {
524 line.setPosition(QPoint(0, height));
525 break;
528 line.setLineWidth(maxWidth);
529 line.setPosition(QPoint(0, height));
531 height += int(line.height());
532 widthUsed = int(qMax(qreal(widthUsed), line.naturalTextWidth()));
534 layout.endLayout();
536 return QSize(widthUsed, height);
539 void AbstractTaskItem::drawTextLayout(QPainter *painter, const QTextLayout &layout, const QRect &rect) const
541 if (rect.width() < 1 || rect.height() < 1) {
542 return;
545 QPixmap pixmap(rect.size());
546 pixmap.fill(Qt::transparent);
548 QPainter p(&pixmap);
549 p.setPen(painter->pen());
551 // Create the alpha gradient for the fade out effect
552 QLinearGradient alphaGradient(0, 0, 1, 0);
553 alphaGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
554 if (layout.textOption().textDirection() == Qt::LeftToRight)
556 alphaGradient.setColorAt(0, QColor(0, 0, 0, 255));
557 alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
558 } else
560 alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
561 alphaGradient.setColorAt(1, QColor(0, 0, 0, 255));
564 QFontMetrics fm(layout.font());
565 int textHeight = layout.lineCount() * fm.lineSpacing();
567 QPointF position = textHeight < rect.height() ?
568 QPointF(0, (rect.height() - textHeight) / 2 + (fm.tightBoundingRect("M").height() - fm.xHeight())) : QPointF(0, 0);
569 QList<QRect> fadeRects;
570 int fadeWidth = 30;
572 // Draw each line in the layout
573 for (int i = 0; i < layout.lineCount(); i++)
575 QTextLine line = layout.lineAt(i);
576 line.draw(&p, position);
578 // Add a fade out rect to the list if the line is too long
579 if (line.naturalTextWidth() > rect.width())
581 int x = int(qMin(line.naturalTextWidth(), (qreal)pixmap.width())) - fadeWidth;
582 int y = int(line.position().y() + position.y());
583 QRect r = QStyle::visualRect(layout.textOption().textDirection(), pixmap.rect(),
584 QRect(x, y, fadeWidth, int(line.height())));
585 fadeRects.append(r);
589 // Reduce the alpha in each fade out rect using the alpha gradient
590 if (!fadeRects.isEmpty())
592 p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
593 foreach (const QRect &rect, fadeRects) {
594 p.fillRect(rect, alphaGradient);
598 p.end();
601 QColor shadowColor;
602 if (textColor().value() < 128) {
603 shadowColor = Qt::white;
604 } else {
605 shadowColor = Qt::black;
608 QImage shadow = pixmap.toImage();
609 Plasma::PaintUtils::shadowBlur(shadow, 2, shadowColor);
611 painter->drawImage(rect.topLeft() + QPoint(1,2), shadow);
612 painter->drawPixmap(rect.topLeft(), pixmap);
617 void AbstractTaskItem::animationUpdate(qreal progress)
619 if (qFuzzyCompare(qreal(1.0), progress)) {
620 m_animId = 0;
621 m_fadeIn = true;
624 m_alpha = progress;
626 // explicit update
627 update();
630 void AbstractTaskItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
632 if (event->mimeData()->hasFormat(TaskManager::Task::mimetype()) ||
633 event->mimeData()->hasFormat(TaskManager::Task::groupMimetype())) {
634 event->ignore(); //ignore it so the taskbar gets the event
635 return;
638 event->accept();
640 if (!m_activateTimer) {
641 m_activateTimer = new QTimer(this);
642 m_activateTimer->setSingleShot(true);
643 m_activateTimer->setInterval(300);
644 connect(m_activateTimer, SIGNAL(timeout()), this, SLOT(activate()));
646 m_activateTimer->start();
649 void AbstractTaskItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
651 Q_UNUSED(event);
653 // restart the timer so that activate() is only called after the mouse
654 // stops moving
655 if (m_activateTimer) {
656 m_activateTimer->start();
660 void AbstractTaskItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
662 Q_UNUSED(event);
664 if (m_activateTimer) {
665 delete m_activateTimer;
666 m_activateTimer = 0;
670 QRect AbstractTaskItem::iconGeometry() const
672 if (!scene() || !boundingRect().isValid()) {
673 return QRect();
676 QGraphicsView *parentView = 0;
677 QGraphicsView *possibleParentView = 0;
678 // The following was taken from Plasma::Applet, it doesn't make sense to make the item an applet, and this was the easiest way around it.
679 foreach (QGraphicsView *view, scene()->views()) {
680 if (view->sceneRect().intersects(sceneBoundingRect()) ||
681 view->sceneRect().contains(scenePos())) {
682 if (view->isActiveWindow()) {
683 parentView = view;
684 break;
685 } else {
686 possibleParentView = view;
691 if (!parentView) {
692 parentView = possibleParentView;
694 if (!parentView) {
695 return QRect();
699 QRect rect = parentView->mapFromScene(mapToScene(boundingRect())).boundingRect().adjusted(0, 0, 1, 1);
700 rect.moveTopLeft(parentView->mapToGlobal(rect.topLeft()));
701 return rect;
704 void AbstractTaskItem::publishIconGeometry() const
708 void AbstractTaskItem::publishIconGeometry(const QRect &rect) const
712 void AbstractTaskItem::setGeometry(const QRectF& geometry)
714 QGraphicsWidget::setGeometry(geometry);
715 publishIconGeometry();
718 QRectF AbstractTaskItem::iconRect(const QRectF &b) const
720 QRectF bounds(b);
721 const int right = bounds.right();
722 //leave enough space for the text. useful in vertical panel
723 bounds.setWidth(qMax(bounds.width() / 3, qMin(minimumSize().height(), bounds.width())));
725 //restore right position if the layout is RTL
726 if (QApplication::layoutDirection() == Qt::RightToLeft) {
727 bounds.moveRight(right);
730 QSize iconSize = m_icon.actualSize(bounds.size().toSize());
732 return QStyle::alignedRect(QApplication::layoutDirection(), Qt::AlignLeft | Qt::AlignVCenter,
733 iconSize, bounds.toRect());
736 QRectF AbstractTaskItem::expanderRect(const QRectF &bounds) const
738 const TaskGroupItem *groupItem = qobject_cast<const TaskGroupItem *>(this);
739 if (!groupItem) {
740 return QRectF();
743 QFontMetrics fm(KGlobalSettings::smallestReadableFont());
744 Plasma::FrameSvg *itemBackground = m_applet->itemBackground();
746 QSize expanderSize(qMax(fm.width(QString::number(groupItem->memberList().count())),
747 itemBackground ? itemBackground->elementSize(expanderElement()).width() : 0),
748 size().height());
750 return QStyle::alignedRect(QApplication::layoutDirection(), Qt::AlignRight | Qt::AlignVCenter,
751 expanderSize, bounds.toRect());
754 QRectF AbstractTaskItem::textRect(const QRectF &bounds) const
756 QSize size(bounds.size().toSize());
757 QRectF effectiveBounds(bounds);
759 size.rwidth() -= int(iconRect(bounds).width()) + qMax(0, IconTextSpacing - 2);
760 if (!isWindowItem()) {
761 size.rwidth() -= int(expanderRect(bounds).width()) + qMax(0, IconTextSpacing - 2);
763 if (QApplication::layoutDirection() == Qt::RightToLeft) {
764 effectiveBounds.setLeft(expanderRect(bounds).right());
765 } else {
766 effectiveBounds.setRight(expanderRect(bounds).left());
770 return QStyle::alignedRect(QApplication::layoutDirection(), Qt::AlignRight | Qt::AlignVCenter,
771 size, effectiveBounds.toRect());
774 QColor AbstractTaskItem::textColor() const
776 QColor color;
777 qreal bias;
778 Plasma::Theme *theme = Plasma::Theme::defaultTheme();
780 if ((m_oldBackgroundPrefix == "attention" || m_backgroundPrefix == "attention") &&
781 m_applet->itemBackground() && m_applet->itemBackground()->hasElement("hint-attention-button-color")) {
782 if (!m_animId && m_backgroundPrefix != "attention") {
783 color = theme->color(Plasma::Theme::TextColor);
784 } else if (!m_animId) {
785 color = theme->color(Plasma::Theme::ButtonTextColor);
786 } else {
787 if (m_oldBackgroundPrefix == "attention") {
788 bias = 1 - m_alpha;
789 } else {
790 bias = m_alpha;
793 color = KColorUtils::mix(theme->color(Plasma::Theme::TextColor),
794 theme->color(Plasma::Theme::ButtonTextColor), bias);
796 } else {
797 color = theme->color(Plasma::Theme::TextColor);
800 if (m_flags & TaskIsMinimized) {
801 color.setAlphaF(0.85);
804 return color;
807 QString AbstractTaskItem::expanderElement() const
809 switch (m_applet->location()) {
810 case Plasma::TopEdge:
811 return "group-expander-top";
812 case Plasma::RightEdge:
813 return "group-expander-right";
814 case Plasma::LeftEdge:
815 return "group-expander-left";
816 case Plasma::BottomEdge:
817 default:
818 return "group-expander-bottom";
823 bool AbstractTaskItem::isGroupMember(const TaskGroupItem *group) const
825 if (!m_abstractItem || !group) {
826 kDebug() <<"no task";
827 return false;
830 return m_abstractItem->isGroupMember(group->group());
834 bool AbstractTaskItem::isGrouped() const
836 if (!m_abstractItem) {
837 kDebug() <<"no item";
838 return false;
840 return m_abstractItem->isGrouped();
843 TaskGroupItem * AbstractTaskItem::parentGroup() const
845 return qobject_cast<TaskGroupItem*>(parentWidget());
848 TaskManager::AbstractItemPtr AbstractTaskItem::abstractItem()
850 return m_abstractItem;
853 #include "abstracttaskitem.moc"