Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / plasma / applets / tasks / taskgroupitem.cpp
blob19780ed8a3e2bafe27b4c44fe4aa2f933c4a0b79
1 /***************************************************************************
2 * Copyright (C) 2007 by Robert Knight *
3 * robertknight@gmail.com *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
21 // Own
22 #include "taskgroupitem.h"
24 // Qt
25 #include <QPainter>
26 #include <QGraphicsScene>
28 // KDE
29 #include <KColorScheme>
30 #include <KDebug>
31 #include <KGlobalSettings>
32 #include <QStyleOptionGraphicsItem>
34 // Plasma
35 #include "plasma/theme.h"
37 TaskGroupItem::TaskGroupItem(QGraphicsItem *parent, QObject *parentObject)
38 : AbstractTaskItem(parent, parentObject),
39 _activeTask(-1),
40 _borderStyle(NoBorder),
41 //_potentialDropAction(NoAction),
42 _caretIndex(0),
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) {
73 items << entry.task;
76 return items;
79 void TaskGroupItem::insertTask(AbstractTaskItem *item, int index)
81 if (index == -1) {
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());
89 if (parentGroup) {
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)
107 bool found = false;
108 for (int i = 0; i < _tasks.count(); i++) {
109 if (_tasks[i].task == item) {
110 _tasks.removeAt(i);
111 found = true;
112 break;
116 if (!found) {
117 return;
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());
127 if (parentGroup) {
128 parentGroup->removeTask(this);
129 scene()->removeItem(this);
130 deleteLater();
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) {
149 return;
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();
160 }else{
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) {
181 return 0;
184 QFontMetrics titleFontMetrics(titleFont());
185 return titleFontMetrics.height();
188 QFont TaskGroupItem::titleFont()
190 return KGlobalSettings::smallestReadableFont();
193 void TaskGroupItem::setColor(const QColor &color)
195 _color = color;
198 QColor TaskGroupItem::color() const
200 return _color;
203 void TaskGroupItem::setBorderStyle(BorderStyle style)
205 _borderStyle = style;
208 TaskGroupItem::BorderStyle TaskGroupItem::borderStyle() const
210 return _borderStyle;
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,
227 QWidget *)
229 painter->setRenderHint(QPainter::Antialiasing);
231 // draw group border
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!
240 return;
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) {
252 entry.task->close();
254 finished();
257 void TaskGroupItem::drawBorder(QPainter *painter,
258 const QStyleOptionGraphicsItem *option,
259 const QRectF &area)
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());
273 #if 0
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);
286 #endif
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);
298 // draw caption
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()),
303 text());
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);
318 updateGeometry();
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"