not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / plasma / applets / systemtray / ui / taskarea.cpp
blob873ea90c1b6fff75bb708ba5dc1702061bc962d2
1 /***************************************************************************
2 * taskarea.cpp *
3 * *
4 * Copyright (C) 2008 Jason Stubbs <jasonbstubbs@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 #include "taskarea.h"
24 #include <QtCore/QSet>
25 #include <QtGui/QApplication>
26 #include <QtGui/QGraphicsLinearLayout>
27 #include <QtGui/QWidget> // QWIDGETSIZE_MAX
29 #include <KIcon>
31 #include <Plasma/IconWidget>
33 #include "../core/manager.h"
34 #include "../core/task.h"
36 #include "applet.h"
37 #include "compactlayout.h"
40 namespace SystemTray
44 class TaskArea::Private
46 public:
47 Private(SystemTray::Applet *h)
48 : host(h),
49 unhider(0),
50 topLayout(new QGraphicsLinearLayout(Qt::Horizontal)),
51 taskLayout(new CompactLayout()),
52 lastItemMargin(0),
53 lastItemCount(0),
54 showingHidden(false),
55 hasHiddenTasks(false),
56 hasTasksThatCanHide(false)
60 SystemTray::Applet *host;
61 Plasma::IconWidget *unhider;
62 QGraphicsLinearLayout *topLayout;
63 CompactLayout *taskLayout;
64 //This item gives a bit of extra margin that separes the last items and the "normal" ones
65 QGraphicsWidget *lastItemMargin;
67 QSet<QString> hiddenTypes;
68 int lastItemCount;
69 bool showingHidden : 1;
70 bool hasHiddenTasks : 1;
71 bool hasTasksThatCanHide : 1;
75 TaskArea::TaskArea(SystemTray::Applet *parent)
76 : QGraphicsWidget(parent),
77 d(new Private(parent))
79 setLayout(d->topLayout);
80 d->topLayout->addItem(d->taskLayout);
81 d->topLayout->setContentsMargins(0, 0, 0, 0);
85 TaskArea::~TaskArea()
87 delete d;
91 void TaskArea::setHiddenTypes(const QStringList &hiddenTypes)
93 d->hiddenTypes = QSet<QString>::fromList(hiddenTypes);
96 bool TaskArea::isHiddenType(const QString &typeId, bool always) const
98 if (always) {
99 return !d->showingHidden && d->hiddenTypes.contains(typeId);
100 } else {
101 return d->hiddenTypes.contains(typeId);
105 void TaskArea::syncTasks(const QList<SystemTray::Task*> &tasks)
107 d->hasTasksThatCanHide = false;
108 d->hasHiddenTasks = false;
109 foreach (Task *task, tasks) {
110 kDebug() << "checking" << task->name() << d->showingHidden;
111 addWidgetForTask(task);
114 checkUnhideTool();
115 d->topLayout->invalidate();
116 emit sizeHintChanged(Qt::PreferredSize);
119 void TaskArea::addTask(Task *task)
121 addWidgetForTask(task);
122 checkUnhideTool();
123 emit sizeHintChanged(Qt::PreferredSize);
126 void TaskArea::addWidgetForTask(SystemTray::Task *task)
128 QGraphicsWidget *widget = findWidget(task);
129 if (!task->isEmbeddable() && !widget) {
130 kDebug() << "task is not embeddable, so FAIL" << task->name();
131 return;
134 d->hasTasksThatCanHide = d->hasTasksThatCanHide || isHiddenType(task->typeId(), false);
136 if (isHiddenType(task->typeId())) {
137 kDebug() << "is a hidden type";
138 d->hasHiddenTasks = true;
139 if (widget) {
140 kDebug() << "just hiding the widget";
141 widget->hide();
143 } else if (widget) {
144 kDebug() << "widget already exists!";
145 widget->show();
146 } else {
147 widget = task->widget(d->host);
149 if (widget) {
150 switch (task->order()) {
151 case SystemTray::Task::First:
152 d->taskLayout->insertItem(0, widget);
153 break;
154 case SystemTray::Task::Normal:
155 d->taskLayout->insertItem(d->taskLayout->count() - d->lastItemCount, widget);
156 break;
157 case SystemTray::Task::Last:
158 /*on the first added "last" task add also a little separator: the size depends from the applet margins,
159 in order to make the background of the last items look "balanced"*/
160 if (d->lastItemCount == 0) {
161 QGraphicsWidget *applet = dynamic_cast<QGraphicsWidget *>(parentItem());
163 if (applet) {
164 qreal left, top, right, bottom;
165 applet->getContentsMargins(&left, &top, &right, &bottom);
166 d->lastItemMargin = new QGraphicsWidget();
168 d->lastItemMargin->setMinimumSize(right, bottom);
171 ++d->lastItemCount;
172 d->taskLayout->addItem(widget);
173 break;
179 void TaskArea::checkSizes()
181 d->taskLayout->updateGeometry();
182 d->topLayout->updateGeometry();
184 // this bit of braindamage is due to the "quirks" of QGrahics[Linear]Layout
185 QSizeF s = d->taskLayout->effectiveSizeHint(Qt::PreferredSize);
186 if (d->unhider) {
187 if (d->topLayout->orientation() == Qt::Horizontal) {
188 s.setWidth(s.width() + d->unhider->size().width());
189 } else {
190 s.setHeight(s.height() + d->unhider->size().height());
194 setPreferredSize(s);
197 void TaskArea::removeTask(Task *task)
199 foreach (QGraphicsWidget *widget, task->associatedWidgets()) {
200 if (d->taskLayout->containsItem(widget)) {
201 if (task->order() == Task::Last) {
202 --d->lastItemCount;
203 //we have removed the last item, remove also the spacer
204 if (d->lastItemCount == 0 && d->lastItemMargin) {
205 d->taskLayout->removeItem(d->lastItemMargin);
206 d->lastItemMargin->deleteLater();
207 d->lastItemMargin = 0;
211 d->taskLayout->removeItem(widget);
212 d->topLayout->invalidate();
213 emit sizeHintChanged(Qt::PreferredSize);
214 break;
219 int TaskArea::leftEasement() const
221 if (d->unhider) {
222 const int cheat = 6;
224 if (d->topLayout->orientation() == Qt::Horizontal) {
225 return d->unhider->size().width() / 2 + cheat;
226 } else {
227 return d->unhider->size().height() / 2 + cheat;
231 return 0;
234 int TaskArea::rightEasement() const
236 int extraMargin = 0;
237 if (d->lastItemMargin) {
238 extraMargin = qMin(d->lastItemMargin->size().width(), d->lastItemMargin->size().height());
240 return d->lastItemCount * 24 + int(qreal(extraMargin)/2.0);
243 bool TaskArea::hasHiddenTasks() const
245 return d->hasHiddenTasks;
248 void TaskArea::setOrientation(Qt::Orientation o)
250 d->topLayout->setOrientation(o);
252 if (d->unhider) {
253 d->unhider->setOrientation(o);
254 if (d->topLayout->orientation() == Qt::Horizontal) {
255 d->unhider->setMaximumSize(26, QWIDGETSIZE_MAX);
256 d->unhider->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
257 } else {
258 d->unhider->setMaximumSize(QWIDGETSIZE_MAX, 26);
259 d->unhider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
262 updateUnhideToolIcon();
265 void TaskArea::initUnhideTool()
267 if (d->unhider) {
268 return;
271 d->unhider = new Plasma::IconWidget(this);
272 d->unhider->setMinimumSize(16, 16);
273 updateUnhideToolIcon();
275 if (d->topLayout->orientation() == Qt::Horizontal) {
276 d->unhider->setMaximumSize(22, QWIDGETSIZE_MAX);
277 d->unhider->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
278 } else {
279 d->unhider->setMaximumSize(QWIDGETSIZE_MAX, 22);
280 d->unhider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
283 d->topLayout->removeItem(d->taskLayout);
284 //d->topLayout->insertItem(0, d->unhider);
285 d->topLayout->addItem(d->unhider);
286 d->topLayout->addItem(d->taskLayout);
287 connect(d->unhider, SIGNAL(clicked()), this, SLOT(toggleHiddenItems()));
289 emit sizeHintChanged(Qt::PreferredSize);
292 void TaskArea::updateUnhideToolIcon()
294 if (!d->unhider) {
295 return;
298 if (!d->showingHidden && d->topLayout->orientation() == Qt::Vertical) {
299 d->unhider->setSvg("widgets/systemtray", "expander-up");
300 } else if(d->showingHidden && d->topLayout->orientation() == Qt::Vertical){
301 d->unhider->setSvg("widgets/systemtray", "expander-down");
302 }else if (d->showingHidden || QApplication::layoutDirection() == Qt::RightToLeft) {
303 d->unhider->setSvg("widgets/systemtray", "expander-right");
304 } else {
305 d->unhider->setSvg("widgets/systemtray", "expander-left");
309 void TaskArea::toggleHiddenItems()
311 d->showingHidden = !d->showingHidden;
312 updateUnhideToolIcon();
313 syncTasks(d->host->manager()->tasks());
314 emit sizeHintChanged(Qt::PreferredSize);
317 void TaskArea::checkUnhideTool()
319 if (d->hasTasksThatCanHide) {
320 initUnhideTool();
321 } else {
322 // hide the show tool
323 d->topLayout->removeItem(d->unhider);
324 d->unhider->deleteLater();
325 d->unhider = 0;
329 QGraphicsWidget* TaskArea::findWidget(Task *task)
331 foreach (QGraphicsWidget *widget, task->associatedWidgets()) {
332 if (d->taskLayout->containsItem(widget)) {
333 return widget;
337 return 0;
343 #include "taskarea.moc"