• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Applets

tasks.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>          *
00003  *   Copyright (C) 2008 by Alexis Ménard <darktears31@gmail.com>           *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
00019  ***************************************************************************/
00020 
00021 // Own
00022 #include "tasks.h"
00023 #include "windowtaskitem.h"
00024 #include "ui_tasksConfig.h"
00025 
00026 // KDE
00027 #include <KConfigDialog>
00028 
00029 // Qt
00030 #include <QGraphicsSceneWheelEvent>
00031 #include <QTimeLine>
00032 #include <QGraphicsScene>
00033 #include <QGraphicsLinearLayout>
00034 
00035 // Plasma
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     //like in Qt's designer
00069     //TODO : Qt's bug??
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     //TODO : Qt's bug??
00076     m_layout->setMaximumSize(INT_MAX,INT_MAX);
00077 
00078     //Managing the spacer by hand to hide it when taskbar is full
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     // listen for addition and removal of window tasks
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     // listen for addition and removal of starting tasks
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     //TODO: shoul we check for transiency? if so the following code can detect it.
00167 /*
00168     QHash<TaskPtr,WindowTaskItem*>::iterator it = m_windowTaskItems.begin();
00169 
00170     while (it != m_windowTaskItems.end()) {
00171         WindowTaskItem *item = it.value();
00172         if (item->windowTask()->hasTransient(task->window())) {
00173             kDebug() << "TRANSIENT TRANSIENT TRANSIENT!";
00174         }
00175         ++it;
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     //if active initialize m_activeTask at the last item inserted
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         //avoid to make all tasks disappear for a wrong minimum size of the spacer
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         //fills the pixmap of transparent, because otherwise if the first time would be filled with
00272         //a fully opaque color that would disable the alpha channel
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     //get the margins now
00300     m_taskItemBackground->getMargins(m_leftMargin, m_topMargin, m_rightMargin, m_bottomMargin);
00301     //if the task height is too little reset the top and bottom margins
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     //zero or one tasks don't cycle
00325     if (m_windowTaskItems.count() < 2) {
00326         return;
00327     }
00328 
00329     // if it's invalid move to start
00330     if (m_activeTask ==  m_windowTaskItems.constEnd()) {
00331         m_activeTask = m_windowTaskItems.begin();
00332     //mouse wheel down
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     //mouse wheel up
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     //hiding spacer
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         // listen to the relevant task manager signals
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         // listen to the relevant task manager signals
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"

Applets

Skip menu "Applets"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal