00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "tasks.h"
00023 #include "windowtaskitem.h"
00024 #include "ui_tasksConfig.h"
00025
00026
00027 #include <KConfigDialog>
00028
00029
00030 #include <QGraphicsSceneWheelEvent>
00031 #include <QTimeLine>
00032 #include <QGraphicsScene>
00033 #include <QGraphicsLinearLayout>
00034
00035
00036 #include <plasma/containment.h>
00037 #include <plasma/panelsvg.h>
00038 #include <plasma/theme.h>
00039
00040 Tasks::Tasks(QObject* parent, const QVariantList &arguments)
00041 : Plasma::Applet(parent, arguments),
00042 m_activeTask(0),
00043 m_taskItemBackground(0),
00044 m_taskAlphaPixmap(0),
00045 m_colorScheme(0),
00046 m_leftMargin(0),
00047 m_topMargin(0),
00048 m_rightMargin(0),
00049 m_bottomMargin(0)
00050 {
00051 setHasConfigurationInterface(true);
00052 setAspectRatioMode(Plasma::IgnoreAspectRatio);
00053 m_screenTimer.setSingleShot(true);
00054 m_screenTimer.setInterval(300);
00055 resize(500, 58);
00056 connect(&m_screenTimer, SIGNAL(timeout()), this, SLOT(checkScreenChange()));
00057 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeRefresh()));
00058 }
00059
00060 Tasks::~Tasks()
00061 {
00062 delete m_taskAlphaPixmap;
00063 }
00064
00065 void Tasks::init()
00066 {
00067 setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
00068
00069
00070 setMaximumSize(INT_MAX,INT_MAX);
00071
00072 m_layout = new QGraphicsLinearLayout(this);
00073 m_layout->setContentsMargins(0,0,0,0);
00074 m_layout->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
00075
00076 m_layout->setMaximumSize(INT_MAX,INT_MAX);
00077
00078
00079 m_spacer = new QGraphicsWidget(this);
00080 m_spacer->setMinimumSize(QSizeF(0,0));
00081 m_layout->addItem(m_spacer);
00082 m_layout->setStretchFactor(m_spacer, 1);
00083
00084 if (formFactor() == Plasma::Vertical) {
00085 m_layout->setOrientation(Qt::Vertical);
00086 } else {
00087 m_layout->setOrientation(Qt::Horizontal);
00088 }
00089 setLayout(m_layout);
00090
00091 KConfigGroup cg = config();
00092 #ifdef TOOLTIP_MANAGER
00093 m_showTooltip = cg.readEntry("showTooltip", true);
00094 #endif
00095 m_showOnlyCurrentDesktop = cg.readEntry("showOnlyCurrentDesktop", false);
00096 m_showOnlyCurrentScreen = cg.readEntry("showOnlyCurrentScreen", false);
00097
00098
00099 connect(TaskManager::TaskManager::self(), SIGNAL(taskAdded(TaskPtr)),
00100 this, SLOT(addWindowTask(TaskPtr)));
00101 connect(TaskManager::TaskManager::self(), SIGNAL(taskRemoved(TaskPtr)),
00102 this, SLOT(removeWindowTask(TaskPtr)));
00103
00104
00105 connect(TaskManager::TaskManager::self(), SIGNAL(startupAdded(StartupPtr)),
00106 this, SLOT(addStartingTask(StartupPtr)));
00107 connect(TaskManager::TaskManager::self(), SIGNAL(startupRemoved(StartupPtr)),
00108 this, SLOT(removeStartingTask(StartupPtr)));
00109
00110 reconnect();
00111 }
00112
00113 void Tasks::addStartingTask(StartupPtr task)
00114 {
00115 WindowTaskItem* item = new WindowTaskItem(this, m_showTooltip);
00116 item->setStartupTask(task);
00117 m_startupTaskItems.insert(task, item);
00118 insertItemBeforeSpacer(item);
00119 }
00120
00121 void Tasks::removeStartingTask(StartupPtr task)
00122 {
00123 if (m_startupTaskItems.contains(task)) {
00124 WindowTaskItem *item = m_startupTaskItems.take(task);
00125 m_layout->removeItem(item);
00126 scene()->removeItem(item);
00127 }
00128
00129 adjustStretch();
00130 }
00131
00132 void Tasks::registerWindowTasks()
00133 {
00134 TaskManager::TaskManager *manager = TaskManager::TaskManager::self();
00135
00136 TaskManager::TaskDict tasks = manager->tasks();
00137 QMapIterator<WId,TaskPtr> iter(tasks);
00138
00139 while (iter.hasNext()) {
00140 iter.next();
00141 addWindowTask(iter.value());
00142 }
00143 }
00144
00145 void Tasks::addWindowTask(TaskPtr task)
00146 {
00147 if (!task->showInTaskbar()) {
00148 return;
00149 }
00150
00151 if (m_showOnlyCurrentDesktop && !task->isOnCurrentDesktop()) {
00152 return;
00153 }
00154
00155 if (m_showOnlyCurrentScreen && !isOnMyScreen(task)) {
00156 return;
00157 }
00158
00159 NET::WindowType type = task->info().windowType(NET::NormalMask | NET::DialogMask |
00160 NET::OverrideMask | NET::UtilityMask);
00161 if (type == NET::Utility) {
00162 kDebug() << "skipping utility window" << task->name();
00163 return;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 WindowTaskItem *item = 0;
00180 foreach (const StartupPtr &startup, m_startupTaskItems.keys()) {
00181 if (startup->matchesWindow(task->window())) {
00182 item = dynamic_cast<WindowTaskItem *>(m_startupTaskItems.take(startup));
00183 break;
00184 }
00185 }
00186
00187 if (!item) {
00188 item = new WindowTaskItem(this, m_showTooltip);
00189 insertItemBeforeSpacer(item);
00190 }
00191 item->setWindowTask(task);
00192 m_windowTaskItems.insert(task, item);
00193
00194
00195 if (task->isActive()) {
00196 m_activeTask = m_windowTaskItems.find(task);
00197 } else if (m_windowTaskItems.count() == 1) {
00198 m_activeTask = m_windowTaskItems.begin();
00199 }
00200
00201 connect(item, SIGNAL(activated(WindowTaskItem*)),
00202 this, SLOT(updateActive(WindowTaskItem*)));
00203 }
00204
00205 void Tasks::removeWindowTask(TaskPtr task)
00206 {
00207 if (m_windowTaskItems.contains(task)) {
00208 WindowTaskItem *item = m_windowTaskItems.take(task);
00209 m_layout->removeItem(item);
00210 scene()->removeItem(item);
00211 item->deleteLater();
00212 m_activeTask = m_windowTaskItems.end();
00213 }
00214
00215 adjustStretch();
00216 }
00217
00218 void Tasks::removeAllWindowTasks()
00219 {
00220 QHash<TaskPtr,WindowTaskItem*>::iterator it = m_windowTaskItems.begin();
00221
00222 while (it != m_windowTaskItems.end()) {
00223 WindowTaskItem *item = it.value();
00224 m_layout->removeItem(item);
00225 scene()->removeItem(item);
00226 item->deleteLater();
00227 ++it;
00228 }
00229
00230 m_windowTaskItems.clear();
00231 m_activeTask = m_windowTaskItems.end();
00232 }
00233
00234 void Tasks::constraintsEvent(Plasma::Constraints constraints)
00235 {
00236 if (constraints & Plasma::LocationConstraint) {
00237 if (formFactor() == Plasma::Vertical) {
00238 m_layout->setOrientation(Qt::Vertical);
00239 } else {
00240 m_layout->setOrientation(Qt::Horizontal);
00241 }
00242
00243 m_spacer->setMaximumSize(INT_MAX, INT_MAX);
00244 }
00245
00246 if (constraints & Plasma::SizeConstraint) {
00247 adjustStretch();
00248 }
00249 }
00250
00251 Plasma::PanelSvg* Tasks::itemBackground()
00252 {
00253 if (!m_taskItemBackground) {
00254 QString tasksThemePath = Plasma::Theme::defaultTheme()->imagePath("widgets/tasks");
00255
00256 if (!tasksThemePath.isEmpty()) {
00257 m_taskItemBackground = new Plasma::PanelSvg(this);
00258 m_taskItemBackground->setImagePath(tasksThemePath);
00259 m_taskItemBackground->setCacheAllRenderedPanels(true);
00260 }
00261 }
00262
00263 return m_taskItemBackground;
00264 }
00265
00266 QPixmap *Tasks::taskAlphaPixmap(const QSize &size)
00267 {
00268 if (!m_taskAlphaPixmap) {
00269 m_taskAlphaPixmap = new QPixmap(size);
00270
00271
00272
00273 m_taskAlphaPixmap->fill(Qt::transparent);
00274 } else if (m_taskAlphaPixmap->size() != size) {
00275 delete m_taskAlphaPixmap;
00276 m_taskAlphaPixmap = new QPixmap(size);
00277 m_taskAlphaPixmap->fill(Qt::transparent);
00278 }
00279
00280 return m_taskAlphaPixmap;
00281 }
00282
00283 void Tasks::resizeItemBackground(const QSizeF &size)
00284 {
00285 if (!m_taskItemBackground) {
00286 itemBackground();
00287
00288 if (!m_taskItemBackground) {
00289 return;
00290 }
00291 }
00292
00293 if (m_taskItemBackground->panelSize() == size) {
00294 return;
00295 }
00296
00297 m_taskItemBackground->clearCache();
00298 m_taskItemBackground->resizePanel(size);
00299
00300 m_taskItemBackground->getMargins(m_leftMargin, m_topMargin, m_rightMargin, m_bottomMargin);
00301
00302 if (size.height() - m_topMargin - m_bottomMargin < KIconLoader::SizeSmall) {
00303 m_topMargin = 0;
00304 m_bottomMargin = 0;
00305 }
00306 }
00307
00308 KColorScheme *Tasks::colorScheme()
00309 {
00310 if (!m_colorScheme) {
00311 m_colorScheme = new KColorScheme(QPalette::Active, KColorScheme::View, Plasma::Theme::defaultTheme()->colorScheme());
00312 }
00313
00314 return m_colorScheme;
00315 }
00316
00317 void Tasks::updateActive(WindowTaskItem *task)
00318 {
00319 m_activeTask = m_windowTaskItems.find(task->windowTask());
00320 }
00321
00322 void Tasks::wheelEvent(QGraphicsSceneWheelEvent *e)
00323 {
00324
00325 if (m_windowTaskItems.count() < 2) {
00326 return;
00327 }
00328
00329
00330 if (m_activeTask == m_windowTaskItems.constEnd()) {
00331 m_activeTask = m_windowTaskItems.begin();
00332
00333 } else if (e->delta() < 0) {
00334 m_activeTask++;
00335
00336 if (m_activeTask == m_windowTaskItems.constEnd()) {
00337 m_activeTask = m_windowTaskItems.begin();
00338 }
00339
00340 } else {
00341 if (m_activeTask == m_windowTaskItems.constBegin()) {
00342 m_activeTask = m_windowTaskItems.end();
00343 }
00344
00345 m_activeTask--;
00346 }
00347
00348 m_activeTask.value()->activate();
00349 }
00350
00351 void Tasks::currentDesktopChanged(int)
00352 {
00353 if (!m_showOnlyCurrentDesktop) {
00354 return;
00355 }
00356
00357 removeAllWindowTasks();
00358 registerWindowTasks();
00359 }
00360
00361 void Tasks::taskMovedDesktop(TaskPtr task)
00362 {
00363 if (!m_showOnlyCurrentDesktop) {
00364 return;
00365 }
00366
00367 if (!task->isOnCurrentDesktop()) {
00368 removeWindowTask(task);
00369 } else if (!m_windowTaskItems.contains(task)) {
00370 addWindowTask(task);
00371 }
00372 }
00373
00374 void Tasks::windowChangedGeometry(TaskPtr task)
00375 {
00376 if (!m_geometryTasks.contains(task)) {
00377 m_geometryTasks.append(task);
00378 }
00379
00380 if (!m_screenTimer.isActive()) {
00381 m_screenTimer.start();
00382 }
00383 }
00384
00385 void Tasks::checkScreenChange()
00386 {
00387 foreach (const TaskPtr &task, m_geometryTasks) {
00388 if (!isOnMyScreen(task)) {
00389 removeWindowTask(task);
00390 } else if (!m_windowTaskItems.contains(task)) {
00391 addWindowTask(task);
00392 }
00393 }
00394
00395 m_geometryTasks.clear();
00396 }
00397
00398 void Tasks::insertItemBeforeSpacer(QGraphicsWidget * item)
00399 {
00400 if (m_layout->count() == 1) {
00401 m_layout->insertItem(0,item);
00402 }
00403 else {
00404 m_layout->insertItem(m_layout->count()-1,item);
00405 }
00406
00407 adjustStretch();
00408 }
00409
00410 void Tasks::adjustStretch()
00411 {
00412 if (m_layout->count() < 2) {
00413 m_spacer->setMaximumSize(INT_MAX, INT_MAX);
00414 return;
00415 }
00416
00417 QGraphicsLayoutItem *item = m_layout->itemAt(0);
00418
00419
00420 if (m_layout->orientation() == Qt::Horizontal) {
00421 int itemSize = size().width() / m_layout->count();
00422 int prefSize = item->preferredSize().width();
00423
00424 if (itemSize < prefSize) {
00425 m_spacer->setMaximumWidth(0);
00426 } else if (itemSize > prefSize + 10) {
00427 m_spacer->setMaximumWidth(INT_MAX);
00428 }
00429 } else {
00430 int itemSize = size().height() / m_layout->count();
00431 int prefSize = item->preferredSize().height();
00432
00433 if (itemSize < prefSize) {
00434 m_spacer->setMaximumHeight(0);
00435 } else if (itemSize > prefSize + 10) {
00436 m_spacer->setMaximumHeight(INT_MAX);
00437 }
00438 }
00439
00440 }
00441
00442 bool Tasks::isOnMyScreen(TaskPtr task)
00443 {
00444 Plasma::Containment* appletContainment = containment();
00445
00446 if (appletContainment) {
00447 if (appletContainment->screen() != -1) {
00448 if (!TaskManager::TaskManager::isOnScreen(appletContainment->screen(),
00449 task->window())) {
00450 return false;
00451 }
00452 }
00453 }
00454 return true;
00455 }
00456
00457 void Tasks::createConfigurationInterface(KConfigDialog *parent)
00458 {
00459 QWidget *widget = new QWidget;
00460 m_ui.setupUi(widget);
00461 parent->setButtons(KDialog::Ok | KDialog::Cancel | KDialog::Apply);
00462 connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
00463 connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
00464 parent->addPage(widget, parent->windowTitle(), icon());
00465
00466 #ifdef TOOLTIP_MANAGER
00467 m_ui.showTooltip->setChecked(m_showTooltip);
00468 #else
00469 m_ui.showTooltip->hide();
00470 #endif
00471 m_ui.showOnlyCurrentDesktop->setChecked(m_showOnlyCurrentDesktop);
00472 m_ui.showOnlyCurrentScreen->setChecked(m_showOnlyCurrentScreen);
00473 }
00474
00475 void Tasks::configAccepted()
00476 {
00477 bool changed = false;
00478
00479 if (m_showOnlyCurrentDesktop != (m_ui.showOnlyCurrentDesktop->isChecked())) {
00480 m_showOnlyCurrentDesktop = !m_showOnlyCurrentDesktop;
00481 KConfigGroup cg = config();
00482 cg.writeEntry("showOnlyCurrentDesktop", m_showOnlyCurrentDesktop);
00483 changed = true;
00484 }
00485 if (m_showOnlyCurrentScreen != (m_ui.showOnlyCurrentScreen->isChecked())) {
00486 m_showOnlyCurrentScreen = !m_showOnlyCurrentScreen;
00487 KConfigGroup cg = config();
00488 cg.writeEntry("showOnlyCurrentScreen", m_showOnlyCurrentScreen);
00489 changed = true;
00490 }
00491
00492 if (changed) {
00493 reconnect();
00494 }
00495 #ifdef TOOLTIP_MANAGER
00496 if (m_showTooltip != (m_ui.showTooltip->checkState() == Qt::Checked)) {
00497 m_showTooltip = !m_showTooltip;
00498 foreach (AbstractTaskItem *taskItem, m_windowTaskItems) {
00499 WindowTaskItem *windowTaskItem = dynamic_cast<WindowTaskItem *>(taskItem);
00500 if (windowTaskItem) {
00501 windowTaskItem->setShowTooltip(m_showTooltip);
00502 }
00503 }
00504 KConfigGroup cg = config();
00505 cg.writeEntry("showTooltip", m_showTooltip);
00506 changed = true;
00507 }
00508 #endif
00509 if (changed) {
00510 update();
00511 emit configNeedsSaving();
00512 }
00513 }
00514
00515 void Tasks::reconnect()
00516 {
00517 disconnect(TaskManager::TaskManager::self(), SIGNAL(desktopChanged(int)),
00518 this, SLOT(currentDesktopChanged(int)));
00519 disconnect(TaskManager::TaskManager::self(), SIGNAL(windowChanged(TaskPtr)),
00520 this, SLOT(taskMovedDesktop(TaskPtr)));
00521 if (m_showOnlyCurrentDesktop) {
00522
00523 connect(TaskManager::TaskManager::self(), SIGNAL(desktopChanged(int)),
00524 this, SLOT(currentDesktopChanged(int)));
00525 connect(TaskManager::TaskManager::self(), SIGNAL(windowChanged(TaskPtr)),
00526 this, SLOT(taskMovedDesktop(TaskPtr)));
00527 }
00528
00529 disconnect(TaskManager::TaskManager::self(), SIGNAL(windowChangedGeometry(TaskPtr)),
00530 this, SLOT(windowChangedGeometry(TaskPtr)));
00531 if (m_showOnlyCurrentScreen) {
00532
00533 connect(TaskManager::TaskManager::self(), SIGNAL(windowChangedGeometry(TaskPtr)),
00534 this, SLOT(windowChangedGeometry(TaskPtr)));
00535 TaskManager::TaskManager::self()->trackGeometry();
00536 }
00537
00538 removeAllWindowTasks();
00539 registerWindowTasks();
00540 }
00541
00542 void Tasks::themeRefresh()
00543 {
00544 delete m_taskItemBackground;
00545 m_taskItemBackground = 0;
00546
00547 delete m_colorScheme;
00548 m_colorScheme = 0;
00549
00550 foreach (WindowTaskItem *taskItem, m_windowTaskItems) {
00551 taskItem->update();
00552 }
00553 }
00554
00555 K_EXPORT_PLASMA_APPLET(tasks, Tasks)
00556
00557 #include "tasks.moc"