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

Plasma

panelcontroller.cpp

Go to the documentation of this file.
00001  /*
00002  *   Copyright 2008 Marco Martin <notmart@gmail.com>
00003  *
00004  *   This program is free software; you can redistribute it and/or modify
00005  *   it under the terms of the GNU Library General Public License as
00006  *   published by the Free Software Foundation; either version 2, or
00007  *   (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details
00013  *
00014  *   You should have received a copy of the GNU Library General Public
00015  *   License along with this program; if not, write to the
00016  *   Free Software Foundation, Inc.,
00017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  */
00019 
00020 #include "panelcontroller.h"
00021 
00022 #include <QAction>
00023 #include <QApplication>
00024 #include <QBoxLayout>
00025 #include <QDesktopWidget>
00026 #include <QFrame>
00027 #include <QMouseEvent>
00028 #include <QPainter>
00029 #include <QToolButton>
00030 
00031 #include <KColorUtils>
00032 #include <KIcon>
00033 #include <KWindowSystem>
00034 
00035 #include <plasma/containment.h>
00036 #include <plasma/corona.h>
00037 #include <plasma/paintutils.h>
00038 #include <plasma/theme.h>
00039 
00040 #include "plasmaapp.h"
00041 #include "positioningruler.h"
00042 #include "toolbutton.h"
00043 
00044 class PanelController::ButtonGroup: public QFrame
00045 {
00046 public:
00047     ButtonGroup(QWidget *parent)
00048        : QFrame(parent)
00049     {
00050     }
00051 
00052     void paintEvent(QPaintEvent *event)
00053     {
00054         QPainter painter(this);
00055         painter.setRenderHint(QPainter::Antialiasing, true);
00056 
00057         painter.translate(0.5, 0.5);
00058 
00059         QColor textColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
00060 
00061 
00062         int x;
00063         int y;
00064         if (event->rect().height() > event->rect().width()) {
00065             x = event->rect().left();
00066             y = event->rect().bottom();
00067         } else {
00068             x = event->rect().right();
00069             y = event->rect().top();
00070         }
00071 
00072         QLinearGradient gradient(x, y, event->rect().right(), event->rect().bottom());
00073         textColor.setAlphaF(0);
00074         gradient.setColorAt(0.1, textColor);
00075         textColor.setAlphaF(0.4);
00076         gradient.setColorAt(1, textColor);
00077 
00078         painter.setBrush(Qt::NoBrush);
00079         QPen pen;
00080         pen.setBrush(gradient);
00081         painter.setPen(pen);
00082         painter.drawPath(Plasma::PaintUtils::roundedRectangle(event->rect().adjusted(1,1,-1,-1), 4));
00083     }
00084 };
00085 
00086 class PanelController::ResizeHandle: public QWidget
00087 {
00088 public:
00089     ResizeHandle(QWidget *parent)
00090        : QWidget(parent),
00091          m_mouseOver(false)
00092     {
00093         setCursor(Qt::SizeVerCursor);
00094     }
00095 
00096     QSize sizeHint() const
00097     {
00098         return QSize(4, 4);
00099     }
00100 
00101     void paintEvent(QPaintEvent *event)
00102     {
00103         QPainter painter(this);
00104         QColor backColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
00105 
00106         if (m_mouseOver) {
00107             backColor.setAlphaF(0.50);
00108         } else {
00109             backColor.setAlphaF(0.30);
00110         }
00111 
00112         painter.fillRect(event->rect(), backColor);
00113 
00114         // draw 3 dots to resemble other resize handles
00115         int diameter = qMin(width(), height());
00116         QRect dotRect(QPoint(0,0), QSize(diameter, diameter));
00117         dotRect.moveCenter(mapFromParent(geometry().center()));
00118 
00119         painter.setRenderHint(QPainter::Antialiasing, true);
00120 
00121         paintDot(&painter, dotRect);
00122 
00123         //other two dots
00124         if (size().width() > size().height()) {
00125             dotRect.translate(-diameter*2, 0);
00126             paintDot(&painter, dotRect);
00127             dotRect.translate(diameter*4, 0);
00128             paintDot(&painter, dotRect);
00129         } else {
00130             dotRect.translate(0, -diameter*2);
00131             paintDot(&painter, dotRect);
00132             dotRect.translate(0, diameter*4);
00133             paintDot(&painter, dotRect);
00134         }
00135     }
00136 
00137 protected:
00138     void enterEvent(QEvent * event)
00139     {
00140         m_mouseOver = true;
00141         update();
00142     }
00143 
00144     void leaveEvent(QEvent * event)
00145     {
00146         m_mouseOver = false;
00147         update();
00148     }
00149 
00150 private:
00151     void paintDot(QPainter *painter, QRect dotRect)
00152     {
00153         QLinearGradient gradient(dotRect.left(), dotRect.top(), dotRect.left(), dotRect.bottom());
00154         QColor firstColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor);
00155         firstColor.setAlphaF(0.6);
00156         QColor secondColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
00157         secondColor.setAlphaF(0.6);
00158         gradient.setColorAt(0, firstColor);
00159         gradient.setColorAt(1, secondColor);
00160 
00161         painter->setBrush(gradient);
00162         painter->setPen(Qt::NoPen);
00163         painter->drawEllipse(dotRect);
00164     }
00165 
00166     bool m_mouseOver;
00167 };
00168 
00169 class PanelController::Private
00170 {
00171 public:
00172     Private(PanelController *panelControl)
00173        : q(panelControl),
00174          containment(0),
00175          orientation(Qt::Horizontal),
00176          location(Plasma::BottomEdge),
00177          extLayout(0),
00178          layout(0),
00179          dragging(NoElement),
00180          startDragPos(0,0),
00181          leftAlignTool(0),
00182          centerAlignTool(0),
00183          rightAlignTool(0)
00184     {
00185     }
00186 
00187     ToolButton *addTool(QAction *action, QWidget *parent, Qt::ToolButtonStyle style = Qt::ToolButtonTextBesideIcon)
00188     {
00189         ToolButton *tool = new ToolButton(parent);
00190         tool->setToolButtonStyle(style);
00191         tool->setAction(action);
00192         actionWidgets.append(tool);
00193 
00194         return tool;
00195     }
00196 
00197     ToolButton *addTool(const QString icon, const QString iconText, QWidget *parent, Qt::ToolButtonStyle style = Qt::ToolButtonTextBesideIcon, bool checkButton = false)
00198     {
00199         //TODO take advantage of setDefaultAction using the containment's actions if possible
00200         ToolButton *tool = new ToolButton(parent);
00201 
00202         tool->setIcon(KIcon(icon));
00203         tool->setText(iconText);
00204         tool->setToolButtonStyle(style);
00205 
00206         if (style == Qt::ToolButtonIconOnly) {
00207             tool->setToolTip(iconText);
00208         }
00209 
00210         tool->setCheckable(checkButton);
00211         tool->setAutoExclusive(checkButton);
00212 
00213         return tool;
00214     }
00215 
00216     void resizePanelHeight(const int newHeight)
00217     {
00218         if (!containment) {
00219             return;
00220         }
00221 
00222         switch (location) {
00223         case Plasma::LeftEdge:
00224         case Plasma::RightEdge:
00225             containment->resize(QSize(newHeight, (int)containment->size().height()));
00226             containment->setMinimumSize(QSize(newHeight, (int)containment->minimumSize().height()));
00227             containment->setMaximumSize(QSize(newHeight, (int)containment->maximumSize().height()));
00228             break;
00229         case Plasma::TopEdge:
00230         case Plasma::BottomEdge:
00231         default:
00232             containment->resize(QSize((int)containment->size().width(), newHeight));
00233             containment->setMinimumSize(QSize((int)containment->minimumSize().width(), newHeight));
00234             containment->setMaximumSize(QSize((int)containment->maximumSize().width(), newHeight));
00235             break;
00236        }
00237     }
00238 
00239     void rulersMoved(int offset, int minLength, int maxLength)
00240     {
00241          if (!containment) {
00242             return;
00243          }
00244 
00245          QSize preferredSize(containment->size().toSize());
00246 
00247          switch (location) {
00248          case Plasma::LeftEdge:
00249          case Plasma::RightEdge:
00250              containment->resize(QSize((int)containment->size().width(), qBound(minLength, preferredSize.height(), maxLength)));
00251              containment->setMinimumSize(QSize((int)containment->minimumSize().width(), minLength));
00252              containment->setMaximumSize(QSize((int)containment->maximumSize().width(), maxLength));
00253              break;
00254          case Plasma::TopEdge:
00255          case Plasma::BottomEdge:
00256          default:
00257              containment->resize(QSize(qBound(minLength, preferredSize.width(), maxLength), (int)containment->size().height()));
00258              containment->setMinimumSize(QSize(minLength, (int)containment->minimumSize().height()));
00259              containment->setMaximumSize(QSize(maxLength, (int)containment->maximumSize().height()));
00260              break;
00261         }
00262 
00263         emit q->offsetChanged(offset);
00264     }
00265 
00266     void alignToggled(bool toggle)
00267     {
00268         if (!toggle) {
00269             return;
00270         }
00271 
00272         if (q->sender() == leftAlignTool) {
00273             emit q->alignmentChanged(Qt::AlignLeft);
00274             ruler->setAlignment(Qt::AlignLeft);
00275         } else if (q->sender() == centerAlignTool) {
00276             emit q->alignmentChanged(Qt::AlignCenter);
00277             ruler->setAlignment(Qt::AlignCenter);
00278         } else if (q->sender() == rightAlignTool) {
00279             emit q->alignmentChanged(Qt::AlignRight);
00280             ruler->setAlignment(Qt::AlignRight);
00281         }
00282 
00283         emit q->offsetChanged(0);
00284         ruler->setOffset(0);
00285     }
00286 
00287      enum DragElement { NoElement = 0,
00288                         ResizeHandleElement,
00289                         PanelControllerElement
00290                       };
00291 
00292     PanelController *q;
00293     Plasma::Containment *containment;
00294     Qt::Orientation orientation;
00295     Plasma::Location location;
00296     QBoxLayout *extLayout;
00297     QBoxLayout *layout;
00298     QBoxLayout *alignLayout;
00299     DragElement dragging;
00300     QPoint startDragPos;
00301 
00302     //Alignment buttons
00303     ToolButton *leftAlignTool;
00304     ToolButton *centerAlignTool;
00305     ToolButton *rightAlignTool;
00306 
00307     //Widgets for actions
00308     QList<QWidget *> actionWidgets;
00309 
00310     ResizeHandle *panelHeightHandle;
00311     PositioningRuler *ruler;
00312 
00313     static const int minimumHeight = 10;
00314 };
00315 
00316 PanelController::PanelController(QWidget* parent)
00317    : QWidget(0),
00318      d(new Private(this))
00319 {
00320     //setWindowFlags(Qt::Popup);
00321     setWindowFlags(Qt::FramelessWindowHint);
00322     KWindowSystem::setState(winId(), NET::SkipTaskbar | NET::SkipPager | NET::Sticky);
00323     setAttribute(Qt::WA_DeleteOnClose);
00324     setFocus(Qt::ActiveWindowFocusReason);
00325     //Resize handles
00326     d->panelHeightHandle = new ResizeHandle(this);
00327 
00328     //layout setup
00329     d->extLayout = new QBoxLayout(QBoxLayout::TopToBottom, this);
00330     d->extLayout->setContentsMargins(0, 1, 0, 0);
00331     setLayout(d->extLayout);
00332     d->extLayout->addWidget(d->panelHeightHandle);
00333 
00334     d->layout = new QBoxLayout(QBoxLayout::LeftToRight);
00335     d->layout->setContentsMargins(4, 4, 4, 4);
00336     if (QApplication::layoutDirection() == Qt::RightToLeft) {
00337         d->layout->setDirection(QBoxLayout::RightToLeft);
00338     } else {
00339         d->layout->setDirection(QBoxLayout::LeftToRight);
00340     }
00341     d->layout->setSpacing(4);
00342     d->layout->addStretch();
00343     d->extLayout->addLayout(d->layout);
00344 
00345     //Add buttons
00346 
00347     //alignment
00348     //first the container
00349     QFrame *alignFrame = new ButtonGroup(this);
00350     d->alignLayout = new QBoxLayout(d->layout->direction(), alignFrame);
00351     alignFrame->setLayout(d->alignLayout);
00352     d->layout->addWidget(alignFrame);
00353     
00354     d->leftAlignTool = d->addTool("format-justify-left", i18n("Align panel to left"), alignFrame,  Qt::ToolButtonIconOnly, true);
00355     d->alignLayout->addWidget(d->leftAlignTool);
00356     d->leftAlignTool->setChecked(true);
00357     connect(d->leftAlignTool, SIGNAL(toggled(bool)), this, SLOT(alignToggled(bool)));
00358 
00359     d->centerAlignTool = d->addTool("format-justify-center", i18n("Align panel to center"), alignFrame,  Qt::ToolButtonIconOnly, true);
00360     d->alignLayout->addWidget(d->centerAlignTool);
00361     connect(d->centerAlignTool, SIGNAL(clicked(bool)), this, SLOT(alignToggled(bool)));
00362 
00363     d->rightAlignTool = d->addTool("format-justify-right", i18n("Align panel to right"), alignFrame,  Qt::ToolButtonIconOnly, true);
00364     d->alignLayout->addWidget(d->rightAlignTool);
00365     connect(d->rightAlignTool, SIGNAL(clicked(bool)), this, SLOT(alignToggled(bool)));
00366 
00367     d->layout->addStretch();
00368 
00369     //other buttons
00370     d->layout->addSpacing(20);
00371     ToolButton *closeControllerTool = d->addTool("window-close", i18n("Close this configuration window"), this, Qt::ToolButtonIconOnly, false);
00372     d->layout->addWidget(closeControllerTool);
00373     connect(closeControllerTool, SIGNAL(clicked()), this, SLOT(hideController()));
00374 
00375     d->ruler = new PositioningRuler(this);
00376     connect(d->ruler, SIGNAL(rulersMoved(int, int, int)), this, SLOT(rulersMoved(int, int, int)));
00377     d->extLayout->addWidget(d->ruler);
00378 }
00379 
00380 PanelController::~PanelController()
00381 {
00382     //TODO: should we try and only call this when something has actually been
00383     //      altered that we care about?
00384     PlasmaApp::self()->corona()->requestConfigSync();
00385     delete d;
00386 }
00387 
00388 void PanelController::setContainment(Plasma::Containment *containment)
00389 {
00390     if (!containment) {
00391         return;
00392     }
00393 
00394     d->containment = containment;
00395 
00396     QWidget *child;
00397     while (!d->actionWidgets.isEmpty()) {
00398         child = d->actionWidgets.first();
00399         d->layout->removeWidget(child);
00400         d->actionWidgets.removeFirst();
00401         child->deleteLater();
00402     }
00403 
00404     int insertIndex = d->layout->count() - 2;
00405 
00406     QAction *action = containment->action("add widgets");
00407     if (action) {
00408         ToolButton *addWidgetTool = d->addTool(action, this);
00409         d->layout->insertWidget(insertIndex, addWidgetTool);
00410         ++insertIndex;
00411         connect(addWidgetTool, SIGNAL(clicked()), this, SLOT(hideController()));
00412     }
00413 
00414     action = containment->action("lock widgets");
00415     if (action) {
00416         ToolButton *lockWidgetsTool = d->addTool(action, this);
00417         d->layout->insertWidget(insertIndex, lockWidgetsTool);
00418         ++insertIndex;
00419         connect(lockWidgetsTool, SIGNAL(clicked()), this, SLOT(hideController()));
00420     }
00421 
00422     action = containment->action("remove");
00423     if (action) {
00424         ToolButton *removePanelTool = d->addTool(action, this);
00425         d->layout->insertWidget(insertIndex, removePanelTool);
00426         ++insertIndex;
00427         connect(removePanelTool, SIGNAL(clicked()), this, SLOT(hideController()));
00428     }
00429 
00430     QRect screenGeom = QApplication::desktop()->screenGeometry(d->containment->screen());
00431 
00432     switch (d->location) {
00433     case Plasma::LeftEdge:
00434     case Plasma::RightEdge:
00435         d->ruler->setAvailableLength(screenGeom.height());
00436         d->ruler->setMaxLength(qMin((int)containment->maximumSize().height(), screenGeom.height()));
00437         d->ruler->setMinLength(containment->minimumSize().height());
00438         break;
00439     case Plasma::TopEdge:
00440     case Plasma::BottomEdge:
00441     default:
00442         d->ruler->setAvailableLength(screenGeom.width());
00443         d->ruler->setMaxLength(qMin((int)containment->maximumSize().width(), screenGeom.width()));
00444         d->ruler->setMinLength(containment->minimumSize().width());
00445         break;
00446     }
00447 }
00448 
00449 QSize PanelController::sizeHint() const
00450 {
00451     QRect screenGeom =
00452     QApplication::desktop()->screenGeometry(d->containment->screen());
00453 
00454     switch (d->location) {
00455     case Plasma::LeftEdge:
00456     case Plasma::RightEdge:
00457         return QSize(QWidget::sizeHint().width(), screenGeom.height());
00458         break;
00459     case Plasma::TopEdge:
00460     case Plasma::BottomEdge:
00461     default:
00462         return QSize(screenGeom.width(), QWidget::sizeHint().height());
00463         break;
00464     }
00465 }
00466 
00467 QPoint PanelController::positionForPanelGeometry(const QRect &panelGeom) const
00468 {
00469     QRect screenGeom =
00470     QApplication::desktop()->screenGeometry(d->containment->screen());
00471 
00472     switch (d->location) {
00473     case Plasma::LeftEdge:
00474         return QPoint(panelGeom.right(), screenGeom.top());
00475         break;
00476     case Plasma::RightEdge:
00477         return QPoint(panelGeom.left() - width(), screenGeom.top());
00478         break;
00479     case Plasma::TopEdge:
00480         return QPoint(screenGeom.left(), panelGeom.bottom());
00481         break;
00482     case Plasma::BottomEdge:
00483     default:
00484         return QPoint(screenGeom.left(), panelGeom.top() - height());
00485         break;
00486     }
00487 }
00488 
00489 void PanelController::setLocation(const Plasma::Location &loc)
00490 {
00491     if (d->location == loc) {
00492         return;
00493     }
00494 
00495     d->location = loc;
00496     d->ruler->setLocation(loc);
00497     QRect screenGeom =
00498     QApplication::desktop()->screenGeometry(d->containment->screen());
00499 
00500     switch (loc) {
00501     case Plasma::LeftEdge:
00502         d->layout->setDirection(QBoxLayout::TopToBottom);
00503         //The external layout gwts auto flipped when QApplication::layoutDirection() changes
00504         //and it shouldn't, the internal one no and it should, so i must manually invert both
00505         if (QApplication::layoutDirection() == Qt::RightToLeft) {
00506             d->extLayout->setDirection(QBoxLayout::LeftToRight);
00507         } else {
00508             d->extLayout->setDirection(QBoxLayout::RightToLeft);
00509         }
00510         d->extLayout->setContentsMargins(1, 0, 0, 0);
00511         d->panelHeightHandle->setCursor(Qt::SizeHorCursor);
00512         d->panelHeightHandle->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
00513 
00514         d->ruler->setAvailableLength(screenGeom.height());
00515         break;
00516     case Plasma::RightEdge:
00517         d->layout->setDirection(QBoxLayout::TopToBottom);
00518         if (QApplication::layoutDirection() == Qt::RightToLeft) {
00519             d->extLayout->setDirection(QBoxLayout::RightToLeft);
00520         } else {
00521             d->extLayout->setDirection(QBoxLayout::LeftToRight);
00522         }
00523         d->extLayout->setContentsMargins(1, 0, 0, 0);
00524         d->panelHeightHandle->setCursor(Qt::SizeHorCursor);
00525         d->panelHeightHandle->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
00526 
00527         d->ruler->setAvailableLength(screenGeom.height());
00528         break;
00529     case Plasma::TopEdge:
00530         if (QApplication::layoutDirection() == Qt::RightToLeft) {
00531             d->layout->setDirection(QBoxLayout::RightToLeft);
00532         } else {
00533             d->layout->setDirection(QBoxLayout::LeftToRight);
00534         }
00535         d->extLayout->setDirection(QBoxLayout::BottomToTop);
00536         d->extLayout->setContentsMargins(0, 0, 0, 1);
00537         d->panelHeightHandle->setCursor(Qt::SizeVerCursor);
00538         d->panelHeightHandle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
00539 
00540         d->ruler->setAvailableLength(screenGeom.width());
00541         break;
00542     case Plasma::BottomEdge:
00543     default:
00544         if (QApplication::layoutDirection() == Qt::RightToLeft) {
00545             d->layout->setDirection(QBoxLayout::RightToLeft);
00546         } else {
00547             d->layout->setDirection(QBoxLayout::LeftToRight);
00548         }
00549         d->extLayout->setDirection(QBoxLayout::TopToBottom);
00550         d->extLayout->setContentsMargins(0, 1, 0, 0);
00551         d->panelHeightHandle->setCursor(Qt::SizeVerCursor);
00552         d->panelHeightHandle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
00553 
00554         d->ruler->setAvailableLength(screenGeom.width());
00555         break;
00556     }
00557 
00558     d->alignLayout->setDirection(d->layout->direction());
00559     if (d->alignLayout->parentWidget()) {
00560         d->alignLayout->parentWidget()->setMaximumSize(d->alignLayout->sizeHint());
00561     }
00562 
00563     d->ruler->setMaximumSize(d->ruler->sizeHint());
00564 }
00565 
00566 Plasma::Location PanelController::location() const
00567 {
00568     return d->location;
00569 }
00570 
00571 void PanelController::setOffset(int newOffset)
00572 {
00573     if (newOffset != d->ruler->offset()) {
00574         d->ruler->setOffset(newOffset);
00575     }
00576 }
00577 
00578 int PanelController::offset()
00579 {
00580     return d->ruler->offset();
00581 }
00582 
00583 void PanelController::setAlignment(const Qt::Alignment &newAlignment)
00584 {
00585     if (newAlignment != d->ruler->alignment()) {
00586         if (newAlignment == Qt::AlignLeft) {
00587             d->leftAlignTool->setChecked(true);
00588         } else if (newAlignment == Qt::AlignCenter) {
00589             d->centerAlignTool->setChecked(true);
00590         } else if (newAlignment == Qt::AlignRight) {
00591             d->rightAlignTool->setChecked(true);
00592         }
00593 
00594         d->ruler->setAlignment(newAlignment);
00595     }
00596 }
00597 
00598 int PanelController::alignment()
00599 {
00600     return d->ruler->alignment();
00601 }
00602 
00603 void PanelController::hideController()
00604 {
00605     hide();
00606 }
00607 
00608 void PanelController::paintEvent(QPaintEvent *event)
00609 {
00610     QPainter painter(this);
00611     painter.setCompositionMode(QPainter::CompositionMode_Source );
00612     QColor backColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor);
00613     backColor.setAlphaF(0.75);
00614     painter.fillRect(event->rect(), backColor);
00615 }
00616 
00617 void PanelController::mousePressEvent(QMouseEvent *event)
00618 {
00619     if (d->panelHeightHandle->geometry().contains(event->pos()) ) {
00620         d->startDragPos = event->pos();
00621         d->dragging = Private::ResizeHandleElement;
00622     } else if (QRect(QPoint(0, 0), size()).contains(event->pos()) && !d->ruler->geometry().contains(event->pos()) ) {
00623         d->dragging = Private::PanelControllerElement;
00624         setCursor(Qt::SizeAllCursor);
00625     }
00626 
00627     QWidget::mousePressEvent(event);
00628 }
00629 
00630 void PanelController::mouseReleaseEvent(QMouseEvent *event)
00631 {
00632     Q_UNUSED(event)
00633 
00634     //FIXME: for now resizes here instead of on mouse move, for a serious performance problem, maybe in Qt
00635     QRect screenGeom =
00636     QApplication::desktop()->screenGeometry(d->containment->screen());
00637     if (d->dragging == Private::ResizeHandleElement) {
00638         switch (location()) {
00639         case Plasma::LeftEdge:
00640             d->resizePanelHeight(geometry().left() - screenGeom.left());
00641             break;
00642         case Plasma::RightEdge:
00643             d->resizePanelHeight(screenGeom.right() - geometry().right());
00644             break;
00645         case Plasma::TopEdge:
00646             d->resizePanelHeight(geometry().top() - screenGeom.top());
00647             break;
00648         case Plasma::BottomEdge:
00649         default:
00650             d->resizePanelHeight(screenGeom.bottom() - geometry().bottom());
00651             break;
00652         }
00653     }
00654 
00655     //resets properties saved during the drag
00656     d->startDragPos = QPoint(0, 0);
00657     d->dragging = Private::NoElement;
00658     setCursor(Qt::ArrowCursor);
00659 }
00660 
00661 void PanelController::mouseMoveEvent(QMouseEvent *event)
00662 {
00663     if (d->dragging == Private::NoElement || !d->containment) {
00664         return;
00665     }
00666 
00667     QDesktopWidget *desktop = QApplication::desktop();
00668     QRect screenGeom = desktop->screenGeometry(d->containment->screen());
00669 
00670     if (d->dragging == Private::PanelControllerElement) {
00671         //only move when the mouse cursor is out of the controller to avoid an endless reposition cycle
00672         if (geometry().contains(event->globalPos())) {
00673             return;
00674         }
00675 
00676         if (!screenGeom.contains(event->globalPos())) {
00677             //move panel to new screen if dragged there
00678             int targetScreen = desktop->screenNumber(event->globalPos());
00679             //kDebug() << "Moving panel from screen" << d->containment->screen() << "to screen" << targetScreen;
00680             d->containment->setScreen(targetScreen);
00681             return;
00682         }
00683 
00684         //create a dead zone so you can go across the middle without having it hop to one side
00685         float dzFactor = 0.35;
00686         QPoint offset = QPoint(screenGeom.width()*dzFactor,screenGeom.height()*dzFactor);
00687         QRect deadzone = QRect(screenGeom.topLeft()+offset, screenGeom.bottomRight()-offset);
00688         if (deadzone.contains(event->globalPos())) {
00689             //kDebug() << "In the deadzone:" << deadzone;
00690             return;
00691         }
00692 
00693         const Plasma::Location oldLocation = d->containment->location();
00694         Plasma::Location newLocation = oldLocation;
00695         float screenAspect = float(screenGeom.height())/screenGeom.width();
00696 
00697         /* Use diagonal lines so we get predictable behavior when moving the panel
00698          * y=topleft.y+(x-topleft.x)*aspectratio   topright < bottomleft
00699          * y=bottomleft.y-(x-topleft.x)*aspectratio   topleft < bottomright
00700          */
00701         if (event->globalY() < screenGeom.y()+(event->globalX()-screenGeom.x())*screenAspect) {
00702             if (event->globalY() < screenGeom.bottomLeft().y()-(event->globalX()-screenGeom.x())*screenAspect) {
00703                 if (d->containment->location() == Plasma::TopEdge) {
00704                     return;
00705                 } else {
00706                     newLocation = Plasma::TopEdge;
00707                 }
00708             } else if (d->containment->location() == Plasma::RightEdge) {
00709                     return;
00710             } else {
00711                 newLocation = Plasma::RightEdge;
00712             }
00713         } else {
00714             if (event->globalY() < screenGeom.bottomLeft().y()-(event->globalX()-screenGeom.x())*screenAspect) {
00715                 if (d->containment->location() == Plasma::LeftEdge) {
00716                     return;
00717                 } else {
00718                     newLocation = Plasma::LeftEdge;
00719                 }
00720             } else if(d->containment->location() == Plasma::BottomEdge) {
00721                     return;
00722             } else {
00723                 newLocation = Plasma::BottomEdge;
00724             }
00725         }
00726 
00727 
00728         //If the orientation changed swap width and height
00729         if (oldLocation != newLocation) {
00730             emit locationChanged(newLocation);
00731         }
00732 
00733         return;
00734     } 
00735 
00736     //Resize handle moved
00737     switch (location()) {
00738     case Plasma::LeftEdge:
00739         if (mapToGlobal(event->pos()).x() -
00740             d->startDragPos.x() - d->minimumHeight >
00741             screenGeom.left()) {
00742             move(mapToGlobal(event->pos()).x() - d->startDragPos.x(), pos().y());
00743             //FIXME: Panel resize deferred, should be here
00744         }
00745         break;
00746     case Plasma::RightEdge:
00747         if (mapToGlobal(event->pos()).x() -
00748             d->startDragPos.x() + width() + d->minimumHeight <
00749             screenGeom.right()) {
00750             move(mapToGlobal(event->pos()).x() - d->startDragPos.x(), pos().y());
00751         }
00752         break;
00753     case Plasma::TopEdge:
00754         if (mapToGlobal(event->pos()).y() -
00755             d->startDragPos.y() - d->minimumHeight >
00756             screenGeom.top()) {
00757             move(pos().x(), mapToGlobal(event->pos()).y() - d->startDragPos.y());
00758         }
00759         break;
00760     case Plasma::BottomEdge:
00761     default:
00762         if (mapToGlobal(event->pos()).y() -
00763             d->startDragPos.y() + height() + d->minimumHeight <
00764             screenGeom.bottom()) {
00765             move(pos().x(), mapToGlobal(event->pos()).y() - d->startDragPos.y());
00766         }
00767         break;
00768     }
00769 }
00770 
00771 void PanelController::focusOutEvent(QFocusEvent * event)
00772 {
00773     Q_UNUSED(event)
00774     close();
00775 }
00776 
00777 #include "panelcontroller.moc"

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
  •   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