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

Plasma

panel.cpp

Go to the documentation of this file.
00001 /*
00002 *   Copyright 2007 by Alex Merry <alex.merry@kdemail.net>
00003 *   Copyright 2008 by Alexis Ménard <darktears31@gmail.com>
00004 *   Copyright 2008 by Aaron Seigo <aseigo@kde.org>
00005 *
00006 *   This program is free software; you can redistribute it and/or modify
00007 *   it under the terms of the GNU Library General Public License version 2,
00008 *   or (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 Library General Public
00016 *   License 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 #include "panel.h"
00022 
00023 #include <limits>
00024 
00025 #include <QApplication>
00026 #include <QGraphicsLinearLayout>
00027 #include <QPainter>
00028 #include <QBitmap>
00029 #include <QDesktopWidget>
00030 #include <QGridLayout>
00031 #include <QLabel>
00032 #include <QComboBox>
00033 #include <QAction>
00034 #include <QGraphicsLayout>
00035 
00036 
00037 #include <KDebug>
00038 #include <KIcon>
00039 #include <KDialog>
00040 #include <KIntNumInput>
00041 #include <KMessageBox>
00042 
00043 #include <Plasma/Corona>
00044 #include <Plasma/FrameSvg>
00045 #include <Plasma/Theme>
00046 #include <Plasma/View>
00047 
00048 using namespace Plasma;
00049 
00050 static const int CONTROL_BAR_HEIGHT = 22;
00051 
00052 Panel::Panel(QObject *parent, const QVariantList &args)
00053     : Containment(parent, args),
00054       m_configureAction(0)
00055 {
00056     m_background = new Plasma::FrameSvg(this);
00057     m_background->setImagePath("widgets/panel-background");
00058     m_background->setEnabledBorders(Plasma::FrameSvg::AllBorders);
00059     connect(m_background, SIGNAL(repaintNeeded()), this, SLOT(backgroundChanged()));
00060     setZValue(150);
00061     setContainmentType(Containment::PanelContainment);
00062 
00063     QSize size = QSize(args.count() ? args[0].toInt() : 1024, 22);
00064     kDebug() << "**********" << size;
00065     resize(size);
00066     setMinimumSize(size);
00067     setMaximumSize(size);
00068     setDrawWallpaper(false);
00069 
00070     connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeUpdated()));
00071     connect(this, SIGNAL(appletAdded(Plasma::Applet*,QPointF)),
00072             this, SLOT(layoutApplet(Plasma::Applet*,QPointF)));
00073     connect(this, SIGNAL(appletRemoved(Plasma::Applet*)),
00074             this, SLOT(appletRemoved(Plasma::Applet*)));
00075 }
00076 
00077 Panel::~Panel()
00078 {
00079 }
00080 
00081 void Panel::init()
00082 {
00083     Containment::init();
00084 }
00085 
00086 QList<QAction*> Panel::contextualActions()
00087 {
00088     if (!m_configureAction) {
00089         m_configureAction = new QAction(i18n("Panel Settings"), this);
00090         m_configureAction->setIcon(KIcon("configure"));
00091         connect(m_configureAction, SIGNAL(triggered()), this, SIGNAL(toolBoxToggled()));
00092     }
00093 
00094     QList<QAction*> actions;
00095     actions << action("add widgets") << m_configureAction;
00096     return actions;
00097 }
00098 
00099 void Panel::backgroundChanged()
00100 {
00101     constraintsEvent(Plasma::LocationConstraint);
00102 }
00103 
00104 void Panel::layoutApplet(Plasma::Applet* applet, const QPointF &pos)
00105 {
00106     // this gets called whenever an applet is added, and we add it to our layout
00107     QGraphicsLinearLayout *lay = dynamic_cast<QGraphicsLinearLayout*>(layout());
00108 
00109     if (!lay) {
00110         return;
00111     }
00112 
00113     Plasma::FormFactor f = formFactor();
00114     int insertIndex = -1;
00115 
00116     //Enlarge the panel if possible
00117     if (f == Plasma::Horizontal) {
00118         resize(size().width() + applet->preferredWidth(), size().height());
00119     } else {
00120         resize(size().width(), size().height() + applet->preferredHeight());
00121     }
00122     layout()->setMaximumSize(size());
00123 
00124     //if pos is (-1,-1) insert at the end of the panel
00125     if (pos != QPoint(-1, -1)) {
00126         for (int i = 0; i < lay->count(); ++i) {
00127             QRectF siblingGeometry = lay->itemAt(i)->geometry();
00128             if (f == Plasma::Horizontal) {
00129                 qreal middle = (siblingGeometry.left() + siblingGeometry.right()) / 2.0;
00130                 if (pos.x() < middle) {
00131                     insertIndex = i;
00132                     break;
00133                 } else if (pos.x() <= siblingGeometry.right()) {
00134                     insertIndex = i + 1;
00135                     break;
00136                 }
00137             } else { // Plasma::Vertical
00138                 qreal middle = (siblingGeometry.top() + siblingGeometry.bottom()) / 2.0;
00139                 if (pos.y() < middle) {
00140                     insertIndex = i;
00141                     break;
00142                 } else if (pos.y() <= siblingGeometry.bottom()) {
00143                     insertIndex = i + 1;
00144                     break;
00145                 }
00146             }
00147         }
00148     }
00149 
00150     if (insertIndex == -1) {
00151         lay->addItem(applet);
00152     } else {
00153         lay->insertItem(insertIndex, applet);
00154     }
00155 
00156     connect(applet, SIGNAL(sizeHintChanged(Qt::SizeHint)), this, SLOT(updateSize()));
00157 }
00158 
00159 void Panel::appletRemoved(Plasma::Applet* applet)
00160 {
00161     //shrink the panel if possible
00162     if (formFactor() == Plasma::Horizontal) {
00163         resize(size().width() - applet->size().width(), size().height());
00164     } else {
00165         resize(size().width(), size().height() - applet->size().height());
00166     }
00167     layout()->setMaximumSize(size());
00168 }
00169 
00170 void Panel::updateSize()
00171 {
00172     Plasma::Applet *applet = qobject_cast<Plasma::Applet *>(sender());
00173 
00174     if (applet) {
00175         if (formFactor() == Plasma::Horizontal) {
00176             const int delta = applet->preferredWidth() - applet->size().width();
00177             //setting the preferred width when delta = 0 and preferredWidth() < minimumWidth()
00178             // leads to the same thing as setPreferredWidth(minimumWidth())
00179             if (delta != 0) {
00180                 setPreferredWidth(preferredWidth() + delta);
00181             }
00182         } else if (formFactor() == Plasma::Vertical) {
00183             const int delta = applet->preferredHeight() - applet->size().height();
00184             if (delta != 0) {
00185                 setPreferredHeight(preferredHeight() + delta);
00186             }
00187         }
00188 
00189         resize(preferredSize());
00190     }
00191 }
00192 
00193 void Panel::updateBorders()
00194 {
00195     FrameSvg::EnabledBorders enabledBorders = FrameSvg::AllBorders;
00196 
00197     kDebug() << "!!!!!!!!!!!!!!!! location be:" << location();
00198     switch (location()) {
00199         case BottomEdge:
00200             enabledBorders = FrameSvg::TopBorder;
00201             break;
00202         case TopEdge:
00203             enabledBorders = FrameSvg::BottomBorder;
00204             break;
00205         case LeftEdge:
00206             enabledBorders = FrameSvg::RightBorder;
00207             break;
00208         case RightEdge:
00209             enabledBorders = FrameSvg::LeftBorder;
00210             break;
00211         default:
00212             break;
00213     }
00214 
00215     qreal topHeight = 0;
00216     qreal bottomHeight = 0;
00217     qreal leftWidth = 0;
00218     qreal rightWidth = 0;
00219 
00220     //activate borders and fetch sizes again
00221     m_background->setEnabledBorders(enabledBorders);
00222     m_background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
00223 
00224     //calculation of extra margins has to be done after getMargins
00225     if (formFactor() == Vertical) {
00226         //hardcoded extra margin for the toolbox right now
00227         if (immutability() == Mutable) {
00228             bottomHeight += 20;
00229         }
00230     //Default to horizontal for now
00231     } else {
00232         //hardcoded extra margin for the toolbox for now
00233         if (immutability() == Mutable) {
00234             if (QApplication::layoutDirection() == Qt::RightToLeft) {
00235                 leftWidth += 20;
00236             } else {
00237                 rightWidth += 20;
00238             }
00239         }
00240     }
00241 
00242 
00243     //invalidate the layout and set again
00244     if (layout()) {
00245         layout()->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
00246         layout()->invalidate();
00247     }
00248 
00249     update();
00250 }
00251 
00252 void Panel::constraintsEvent(Plasma::Constraints constraints)
00253 {
00254     kDebug() << "constraints updated with" << constraints << "!!!!!!";
00255 
00256     if (constraints & Plasma::FormFactorConstraint) {
00257         Plasma::FormFactor form = formFactor();
00258         Qt::Orientation layoutDirection = form == Plasma::Vertical ? Qt::Vertical : Qt::Horizontal;
00259 
00260         // create our layout!
00261         if (layout()) {
00262             QGraphicsLayout *lay = layout();
00263             QGraphicsLinearLayout * linearLay = dynamic_cast<QGraphicsLinearLayout *>(lay);
00264             if (linearLay) {
00265                 linearLay->setOrientation(layoutDirection);
00266             }
00267         } else {
00268             QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(this);
00269             lay->setOrientation(layoutDirection);
00270             lay->setContentsMargins(0, 0, 0, 0);
00271             lay->setSpacing(4);
00272             lay->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
00273             setLayout(lay);
00274             updateBorders();
00275 
00276             foreach (Applet *applet, applets()) {
00277                 lay->addItem(applet);
00278             }
00279         }
00280     }
00281 
00282     //we need to know if the width or height is 100%
00283     if (constraints & Plasma::LocationConstraint || constraints & Plasma::SizeConstraint) {
00284         QSize size = geometry().size().toSize();
00285         QRectF screenRect = screen() >= 0 ? QApplication::desktop()->screenGeometry(screen()) : geometry();
00286 
00287         if ((formFactor() == Horizontal && size.width() >= screenRect.width()) ||
00288             (formFactor() == Vertical && size.height() >= screenRect.height())) {
00289             m_background->setElementPrefix(location());
00290         } else {
00291             m_background->setElementPrefix(QString());
00292         }
00293 
00294         m_background->resizeFrame(size);
00295         updateBorders();
00296     }
00297 
00298     //FIXME: this seems the only way to correctly resize the layout the first time when the
00299     // saved panel size is less than the default is to setting a maximum size.
00300     // this shouldn't happen. maybe even a qgraphicslayout bug?
00301     if (layout() && (constraints & Plasma::SizeConstraint)) {
00302         layout()->setMaximumSize(size());
00303     }
00304 
00305     if (constraints & Plasma::LocationConstraint) {
00306         setFormFactorFromLocation(location());
00307     }
00308 
00309     if (constraints & Plasma::ImmutableConstraint) {
00310         bool unlocked = immutability() == Plasma::Mutable;
00311 
00312         if (m_configureAction) {
00313             m_configureAction->setEnabled(unlocked);
00314             m_configureAction->setVisible(unlocked);
00315         }
00316 
00317         updateBorders();
00318     }
00319 }
00320 
00321 void Panel::saveState(KConfigGroup &config) const
00322 {
00323     config.writeEntry("minimumSize", minimumSize());
00324     config.writeEntry("maximumSize", maximumSize());
00325 }
00326 
00327 void Panel::themeUpdated()
00328 {
00329     //if the theme is changed all the calculations needs to be done again
00330     //and resize based on the change in the theme bordersize
00331 
00332     qreal oldLeftWidth;
00333     qreal newLeftWidth;
00334     qreal oldTopHeight;
00335     qreal newTopHeight;
00336     qreal oldRightWidth;
00337     qreal newRightWidth;
00338     qreal oldBottomHeight;
00339     qreal newBottomHeight;
00340 
00341     layout()->getContentsMargins(&oldLeftWidth, &oldTopHeight, &oldRightWidth, &oldBottomHeight);
00342     m_background->getMargins(newLeftWidth, newTopHeight, newRightWidth, newBottomHeight);
00343 
00344     QSize newSize(size().width()-(oldLeftWidth - newLeftWidth)-(oldRightWidth - newRightWidth),
00345            size().height()-(oldTopHeight - newTopHeight)-(oldBottomHeight - newBottomHeight));
00346 
00347     resize(newSize);
00348 
00349     if (formFactor() == Plasma::Vertical) {
00350         setMaximumWidth(newSize.width());
00351         setMinimumWidth(newSize.width());
00352     } else {
00353         setMaximumHeight(newSize.height());
00354         setMinimumHeight(newSize.height());
00355     }
00356 
00357     updateBorders();
00358 }
00359 
00360 void Panel::paintInterface(QPainter *painter,
00361                            const QStyleOptionGraphicsItem *option,
00362                            const QRect& contentsRect)
00363 {
00364     Q_UNUSED(contentsRect)
00365 
00366     //FIXME: this background drawing is bad and ugly =)
00367     // draw the background untransformed (saves lots of per-pixel-math)
00368     painter->save();
00369     painter->resetTransform();
00370 
00371     const Containment::StyleOption *containmentOpt = qstyleoption_cast<const Containment::StyleOption *>(option);
00372 
00373     QRect viewGeom;
00374     if (containmentOpt) {
00375         viewGeom = containmentOpt->view->geometry();
00376     }
00377 
00378     // blit the background (saves all the per-pixel-products that blending does)
00379     painter->setCompositionMode(QPainter::CompositionMode_Source);
00380     painter->setRenderHint(QPainter::Antialiasing);
00381 
00382     m_background->paintFrame(painter, option->exposedRect, option->exposedRect);
00383 
00384     if (containmentOpt && containmentOpt->view) {
00385         containmentOpt->view->setMask(m_background->mask());
00386     }
00387 
00388     // restore transformation and composition mode
00389     painter->restore();
00390 }
00391 
00392 void Panel::setFormFactorFromLocation(Plasma::Location loc) {
00393     switch (loc) {
00394         case BottomEdge:
00395         case TopEdge:
00396             //kDebug() << "setting horizontal form factor";
00397             setFormFactor(Plasma::Horizontal);
00398             break;
00399         case RightEdge:
00400         case LeftEdge:
00401             //kDebug() << "setting vertical form factor";
00402             setFormFactor(Plasma::Vertical);
00403             break;
00404         case Floating:
00405             //TODO: implement a form factor for floating panels
00406             kDebug() << "Floating is unimplemented.";
00407             break;
00408         default:
00409             kDebug() << "invalid location!!";
00410     }
00411 }
00412 
00413 K_EXPORT_PLASMA_APPLET(panel, Panel)
00414 
00415 #include "panel.moc"
00416 

Plasma

Skip menu "Plasma"
  • 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
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
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