1 /***************************************************************************
2 * Copyright (C) 2007 by Robert Knight *
3 * robertknight@gmail.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
19 ***************************************************************************/
22 #include "taskgroupitem.h"
26 #include <QGraphicsScene>
29 #include <KColorScheme>
31 #include <KGlobalSettings>
32 #include <QStyleOptionGraphicsItem>
35 #include "plasma/theme.h"
37 TaskGroupItem::TaskGroupItem(QGraphicsItem
*parent
, QObject
*parentObject
)
38 : AbstractTaskItem(parent
, parentObject
),
40 _borderStyle(NoBorder
),
41 //_potentialDropAction(NoAction),
43 _allowSubGroups(true),
44 m_geometryUpdateTimerId(-1)
46 //setAcceptDrops(true);
48 m_layout
= new Plasma::BoxLayout(Plasma::BoxLayout::LeftToRight
, this);
49 m_layout
->setMargin(0);
50 m_layout
->setSpacing(5);
51 m_layout
->setMultiRow(true);
54 QSizeF
TaskGroupItem::maximumSize() const
56 return Widget::maximumSize();
59 void TaskGroupItem::setAllowSubGroups(bool allow
)
61 _allowSubGroups
= allow
;
64 bool TaskGroupItem::allowSubGroups() const
66 return _allowSubGroups
;
69 QList
<AbstractTaskItem
*> TaskGroupItem::tasks() const
71 QList
<AbstractTaskItem
*> items
;
72 foreach(TaskEntry entry
, _tasks
) {
79 void TaskGroupItem::insertTask(AbstractTaskItem
*item
, int index
)
82 index
= _tasks
.count();
85 Q_ASSERT( index
>= 0 && index
<= _tasks
.count() );
87 // remove item from existing group if any
88 TaskGroupItem
*parentGroup
= dynamic_cast<TaskGroupItem
*>(item
->parentItem());
90 parentGroup
->removeTask(item
);
93 connect(item
, SIGNAL(activated(AbstractTaskItem
*)),
94 this, SLOT(updateActive(AbstractTaskItem
*)));
95 connect(item
, SIGNAL(windowSelected(AbstractTaskItem
*)),
96 this, SIGNAL(activated(AbstractTaskItem
*)));
98 item
->setParentItem(this);
99 _tasks
.insert(index
, TaskEntry(item
));
101 layout()->addItem(item
);
102 queueGeometryUpdate();
105 void TaskGroupItem::removeTask(AbstractTaskItem
*item
)
108 for (int i
= 0; i
< _tasks
.count(); i
++) {
109 if (_tasks
[i
].task
== item
) {
120 layout()->removeItem(item
);
121 item
->setParentItem(0);
122 queueGeometryUpdate();
124 // if the group is now empty then ask the parent to remove it
125 if (_tasks
.count() == 0) {
126 TaskGroupItem
* parentGroup
= dynamic_cast<TaskGroupItem
*>(parentItem());
128 parentGroup
->removeTask(this);
129 scene()->removeItem(this);
134 disconnect(item
, SIGNAL(activated(AbstractTaskItem
*)),
135 this, SIGNAL(activated(AbstractTaskItem
*)));
136 disconnect(item
, SIGNAL(windowSelected(AbstractTaskItem
*)),
137 this, SIGNAL(activated(AbstractTaskItem
*)));
140 void TaskGroupItem::updateActive(AbstractTaskItem
*task
)
142 _activeTask
= _tasks
.indexOf(TaskEntry(task
));
145 void TaskGroupItem::cycle(int delta
)
147 //only cycle active task if there are 2 tasks or more
148 if (_tasks
.count() < 2) {
152 if (_activeTask
== -1) {
153 _tasks
[0].task
->activate();
155 //cycle active task with the circular array tecnique
156 else if (delta
< 0) {
157 //if _activeTask < _tasks.count() the new _activeTask
158 //will be _activeTask+1, else it will be 1
159 _tasks
[(_activeTask
+1)%_tasks
.count()].task
->activate();
161 //if _activeTask > 1 the new _activeTask
162 //will be _activeTask-1, else it will be _tasks.count()
163 _tasks
[(_tasks
.count() + _activeTask
-1 )%_tasks
.count()].task
->activate();
167 void TaskGroupItem::reorderTasks(int from
, int to
)
169 Q_ASSERT( from
>= 0 && from
< _tasks
.size() );
170 Q_ASSERT( to
>= 0 && to
< _tasks
.size() );
172 kDebug() << "Reordering from" << from
<< "to" << to
;
174 AbstractTaskItem
* task
= _tasks
.takeAt(from
).task
;
175 _tasks
.insert(to
,TaskEntry(task
));
178 qreal
TaskGroupItem::titleHeight() const
180 if (_borderStyle
!= CaptionBorder
) {
184 QFontMetrics
titleFontMetrics(titleFont());
185 return titleFontMetrics
.height();
188 QFont
TaskGroupItem::titleFont()
190 return KGlobalSettings::smallestReadableFont();
193 void TaskGroupItem::setColor(const QColor
&color
)
198 QColor
TaskGroupItem::color() const
203 void TaskGroupItem::setBorderStyle(BorderStyle style
)
205 _borderStyle
= style
;
208 TaskGroupItem::BorderStyle
TaskGroupItem::borderStyle() const
213 void TaskGroupItem::setDirection(Plasma::BoxLayout::Direction dir
)
215 m_layout
->setDirection(dir
);
217 m_layout
->setMultiRow(dir
!= Plasma::BoxLayout::TopToBottom
);
220 Plasma::BoxLayout::Direction
TaskGroupItem::direction()
222 return m_layout
->direction();
225 void TaskGroupItem::paint(QPainter
*painter
,
226 const QStyleOptionGraphicsItem
*option
,
229 painter
->setRenderHint(QPainter::Antialiasing
);
232 // adjust area slightly to get a sharp border with anti-aliasing enabled
233 drawBorder(painter
, option
, QRectF(option
->rect
).adjusted(0.5,0.5,-0.5,-0.5));
236 void TaskGroupItem::activate()
238 if (!dynamic_cast<TaskGroupItem
*>(parentItem())) {
239 // this is the root group, and we don't want to activate *every* window!
243 // this is a task sub-group, so let's activate the windows in it
244 foreach(TaskEntry entry
, _tasks
) {
245 entry
.task
->activate();
249 void TaskGroupItem::close()
251 foreach(TaskEntry entry
, _tasks
) {
257 void TaskGroupItem::drawBorder(QPainter
*painter
,
258 const QStyleOptionGraphicsItem
*option
,
261 QFont smallFont
= KGlobalSettings::smallestReadableFont();
262 QFontMetrics
smallFontMetrics(smallFont
);
264 if (_color
.isValid()) {
265 painter
->setPen(QPen(Qt::NoPen
));
266 painter
->setBrush(_color
);
267 painter
->drawRect(area
);
270 if (_borderStyle
== CaptionBorder
) {
271 const QRectF
titleArea(area
.top(),area
.left(),area
.width(),titleHeight());
274 const int cornerSize
= 5;
275 QPainterPath
borderPath(area
.topLeft() + QPointF(0,titleSize
));
276 borderPath
.quadTo(area
.topLeft(), area
.topLeft() + QPointF(cornerSize
,0));
277 borderPath
.lineTo(area
.topRight() - QPointF(cornerSize
,0));
278 borderPath
.quadTo(area
.topRight(), area
.topRight() + QPointF(0,titleSize
) );
279 borderPath
.lineTo(area
.bottomRight());
280 borderPath
.lineTo(area
.bottomLeft());
281 borderPath
.lineTo(area
.topLeft() + QPointF(0,titleSize
));
282 borderPath
.lineTo(area
.topRight() + QPointF(0,titleSize
));
285 painter
->drawPath(borderPath
);
288 // FIXME Check KColorScheme usage here
290 QLinearGradient
titleGradient(titleArea
.topLeft(), titleArea
.bottomLeft());
291 KColorScheme
colorScheme(QPalette::Active
, KColorScheme::View
, Plasma::Theme::self()->colors());
292 titleGradient
.setColorAt(0, colorScheme
.shade(_color
,KColorScheme::DarkShade
));
293 titleGradient
.setColorAt(1, colorScheme
.shade(_color
,KColorScheme::MidShade
));
295 painter
->setBrush(titleGradient
);
296 painter
->drawRect(titleArea
);
299 painter
->setPen(QPen(option
->palette
.text(),1.0));
300 QFontMetricsF
titleFontMetrics(titleFont());
301 painter
->drawText(area
.topLeft() + QPointF(0,titleArea
.height()
302 - titleFontMetrics
.descent()),
307 void TaskGroupItem::queueGeometryUpdate()
309 if (m_geometryUpdateTimerId
== -1) {
310 m_geometryUpdateTimerId
= startTimer(200);
314 void TaskGroupItem::timerEvent(QTimerEvent
*event
)
316 if (event
->timerId() == m_geometryUpdateTimerId
) {
317 killTimer(m_geometryUpdateTimerId
);
319 m_geometryUpdateTimerId
= -1;
323 void TaskGroupItem::hoverEnterEvent(QGraphicsSceneHoverEvent
*event
)
325 Widget::hoverEnterEvent(event
);
328 void TaskGroupItem::hoverLeaveEvent(QGraphicsSceneHoverEvent
*event
)
330 Widget::hoverLeaveEvent(event
);
333 #include "taskgroupitem.moc"