/*************************************************************************** * Copyright (C) 2008 by Marco Martin * * Copyright (C) 2010 by Chani Armitage * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ #include "activitybar.h" #include #include #include #include #include #include #include #include #include #include #include ActivityBar::ActivityBar(QObject *parent, const QVariantList &args) : Plasma::Applet(parent, args), m_engine(0) { resize(200, 60); setAspectRatioMode(Plasma::IgnoreAspectRatio); setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding)); } ActivityBar::~ActivityBar() { } void ActivityBar::init() { QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this); m_tabBar = new Plasma::TabBar(this); m_tabBar->nativeWidget()->setDrawBase(false); layout->addItem(m_tabBar); layout->setContentsMargins(0,0,0,0); //layout->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding)); //This is an awful hack, but I need to keep the old behaviour for plasma-netbook //while using the new activity API for plasma-desktop. //TODO 4.6 convert netbook to the activity API so we won't need this if (qApp->applicationName() == "plasma-desktop") { m_engine = dataEngine("org.kde.activities"); Plasma::DataEngine::Data data = m_engine->query("Status"); QStringList activities = data["Running"].toStringList(); //kDebug() << "$$$$$$$$$$$$# sources:" << activities.size(); foreach (const QString &id, activities) { insertActivity(id); } m_engine->connectAllSources(this); connect(m_engine, SIGNAL(sourceAdded(QString)), this, SLOT(activityAdded(QString))); connect(m_engine, SIGNAL(sourceRemoved(QString)), this, SLOT(activityRemoved(QString))); connect(m_tabBar, SIGNAL(currentChanged(int)), this, SLOT(switchActivity(int))); } else { m_tabBar->nativeWidget()->installEventFilter(this); if (containment()) { Plasma::Corona *c = containment()->corona(); if (!c) { kDebug() << "No corona, can't happen"; setFailedToLaunch(true); return; } QList containments = c->containments(); foreach (Plasma::Containment *cont, containments) { if (cont->containmentType() == Plasma::Containment::PanelContainment || cont->containmentType() == Plasma::Containment::CustomPanelContainment || c->offscreenWidgets().contains(cont)) { continue; } insertContainment(cont); connect(cont, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed(QObject*))); connect(cont, SIGNAL(screenChanged(int,int,Plasma::Containment*)), this, SLOT(screenChanged(int,int,Plasma::Containment*))); connect(cont, SIGNAL(contextChanged(Plasma::Context*)), this, SLOT(contextChanged(Plasma::Context*))); } connect(c, SIGNAL(containmentAdded(Plasma::Containment*)), this, SLOT(containmentAdded(Plasma::Containment*))); } connect(m_tabBar, SIGNAL(currentChanged(int)), this, SLOT(switchContainment(int))); connect(KWindowSystem::self(), SIGNAL(currentDesktopChanged(int)), this, SLOT(currentDesktopChanged(int))); } setPreferredSize(m_tabBar->nativeWidget()->sizeHint()); emit sizeHintChanged(Qt::PreferredSize); } void ActivityBar::insertContainment(Plasma::Containment *cont) { QList::iterator i = m_containments.begin(); int index = 0; int myScreen = containment()->screen(); for (; i != m_containments.end(); ++i) { if (cont->id() < (*i)->id()) { m_containments.insert(i, cont); break; } ++index; } if (i == m_containments.end()) { m_containments.append(cont); } if (cont->activity().isNull()) { m_tabBar->insertTab(index, cont->name()); } else { m_tabBar->insertTab(index, cont->activity()); } QString iconName = cont->icon(); if (!iconName.isEmpty() && iconName != "user-desktop") { m_tabBar->nativeWidget()->setTabIcon(index, KIcon(iconName)); } if (cont->screen() != -1 && cont->screen() == myScreen && (cont->desktop() == -1 || cont->desktop() == KWindowSystem::currentDesktop()-1)) { m_tabBar->setCurrentIndex(index); } } void ActivityBar::insertActivity(const QString &id) { //assumption: activities are always added at the end of the list //kDebug() << "activity" << id; m_activities.append(id); m_tabBar->addTab(QString()); //name will be added on dataUpdated } void ActivityBar::constraintsEvent(Plasma::Constraints constraints) { if (constraints & Plasma::FormFactorConstraint || constraints & Plasma::SizeConstraint) { if ((formFactor() == Plasma::Vertical || size().height() > size().width()) && m_tabBar->nativeWidget()->shape() != QTabBar::RoundedWest) { m_tabBar->nativeWidget()->setShape(QTabBar::RoundedWest); } else if (m_tabBar->nativeWidget()->shape() != QTabBar::RoundedNorth && (formFactor() == Plasma::Horizontal || size().height() <= size().width())) { m_tabBar->nativeWidget()->setShape(QTabBar::RoundedNorth); } else { return; } setPreferredSize(m_tabBar->nativeWidget()->sizeHint()); setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); emit sizeHintChanged(Qt::PreferredSize); } } bool ActivityBar::eventFilter(QObject *watched, QEvent *event) { //request an activate also if the user clicks on the current active tab if (watched == m_tabBar->nativeWidget() && event->type() == QEvent::MouseButtonRelease) { QMouseEvent *me = static_cast(event); switchContainment(m_tabBar->nativeWidget()->tabAt(me->pos())); } return false; } void ActivityBar::switchContainment(int newActive) { Plasma::Containment *ownCont = containment(); if (!ownCont || newActive > m_containments.count()-1 || newActive < 0) { return; } Plasma::Corona *c = containment()->corona(); if (!c) { return; } Plasma::Containment *oldCont = c->containmentForScreen(ownCont->screen(), KWindowSystem::currentDesktop() - 1); if (oldCont) { m_containments[newActive]->setScreen(oldCont->screen(), oldCont->desktop()); } else { m_containments[newActive]->setScreen(ownCont->screen(), ownCont->desktop()); } } void ActivityBar::switchActivity(int newActive) { if (newActive >= m_activities.count() || newActive < 0) { return; } Plasma::Service *service = m_engine->serviceForSource(m_activities.at(newActive)); KConfigGroup op = service->operationDescription("setCurrent"); Plasma::ServiceJob *job = service->startOperationCall(op); connect(job, SIGNAL(finished(KJob*)), service, SLOT(deleteLater())); } void ActivityBar::currentDesktopChanged(const int currentDesktop) { Plasma::Corona *c = containment()->corona(); if (!c) { return; } //-1 because kwindowsystem counts desktop from 1 :) Plasma::Containment *cont = c->containmentForScreen(containment()->screen(), currentDesktop - 1); if (!cont) { return; } int index = m_containments.indexOf(cont); if (index != -1) { m_tabBar->setCurrentIndex(index); } } void ActivityBar::containmentAdded(Plasma::Containment *cont) { if (cont->containmentType() == Plasma::Containment::PanelContainment || cont->containmentType() == Plasma::Containment::CustomPanelContainment || m_containments.contains(cont) || (containment() && containment()->corona()->offscreenWidgets().contains(cont))) { return; } insertContainment(cont); connect(cont, SIGNAL(destroyed(QObject*)), this, SLOT(containmentDestroyed(QObject*))); connect(cont, SIGNAL(screenChanged(int,int,Plasma::Containment*)), this, SLOT(screenChanged(int,int,Plasma::Containment*))); connect(cont, SIGNAL(contextChanged(Plasma::Context*)), this, SLOT(contextChanged(Plasma::Context*))); setPreferredSize(m_tabBar->nativeWidget()->sizeHint()); emit sizeHintChanged(Qt::PreferredSize); } void ActivityBar::activityAdded(const QString &id) { insertActivity(id); m_engine->connectSource(id, this); setPreferredSize(m_tabBar->nativeWidget()->sizeHint()); emit sizeHintChanged(Qt::PreferredSize); } void ActivityBar::containmentDestroyed(QObject *obj) { Plasma::Containment *destroyedContainment = static_cast(obj); int index = m_containments.indexOf(destroyedContainment); if (index != -1) { m_containments.removeAt(index); m_tabBar->blockSignals(true); m_tabBar->removeTab(index); m_tabBar->blockSignals(false); } setPreferredSize(m_tabBar->nativeWidget()->sizeHint()); emit sizeHintChanged(Qt::PreferredSize); } void ActivityBar::activityRemoved(const QString &id) { int index = m_activities.indexOf(id); if (index < 0) { return; } m_activities.removeAt(index); m_tabBar->blockSignals(true); m_tabBar->removeTab(index); m_tabBar->blockSignals(false); setPreferredSize(m_tabBar->nativeWidget()->sizeHint()); emit sizeHintChanged(Qt::PreferredSize); } void ActivityBar::screenChanged(int wasScreen, int isScreen, Plasma::Containment *cont) { Q_UNUSED(wasScreen) //Q_UNUSED(isScreen) int index = m_containments.indexOf(cont); //FIXME: how is supposed to work containment()->desktop() when the pervirtialthing is off? if (index != -1 && containment()->screen() == isScreen && (cont->desktop() == -1 || cont->desktop() == KWindowSystem::currentDesktop()-1)) { m_tabBar->setCurrentIndex(index); } } void ActivityBar::contextChanged(Plasma::Context *context) { Plasma::Containment *cont = qobject_cast(sender()); if (!cont) { return; } int index = m_containments.indexOf(cont); if (index != -1) { m_tabBar->setTabText(index, context->currentActivity()); } } void ActivityBar::dataUpdated(const QString &source, const Plasma::DataEngine::Data &data) { //kDebug() << "$$$$$$$$$$$$$$$$$$$" << source; if (source == "Status") { //special source, not used yet return; } int index = m_activities.indexOf(source); if (data["State"].toString() == "Stopped") { if (index >= 0) { //take it out m_activities.removeAt(index); m_tabBar->blockSignals(true); m_tabBar->removeTab(index); m_tabBar->blockSignals(false); setPreferredSize(m_tabBar->nativeWidget()->sizeHint()); emit sizeHintChanged(Qt::PreferredSize); } return; } else if (index < 0) { //add it back in index = m_activities.size(); insertActivity(source); } //update the actual content m_tabBar->setTabText(index, data["Name"].toString().replace('&', "&&")); QString iconName = data["Icon"].toString(); if (!iconName.isEmpty() && iconName != "user-desktop") { m_tabBar->nativeWidget()->setTabIcon(index, KIcon(iconName)); } if (data["Current"].toBool()) { m_tabBar->setCurrentIndex(index); } setPreferredSize(m_tabBar->nativeWidget()->sizeHint()); emit sizeHintChanged(Qt::PreferredSize); } #include "activitybar.moc"