[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-panel-devel
Subject:    Re: [PATCH] panel placement at the center (or whatever) of the screen
From:       Marco Martin <notmart () gmail ! com>
Date:       2008-04-07 17:17:33
Message-ID: 200804071917.33477.notmart () gmail ! com
[Download RAW message or body]

On Sunday 06 April 2008, Aaron J. Seigo wrote:
> On Saturday 05 April 2008, Marco Martin wrote:
> > On Friday 04 April 2008, Aaron J. Seigo wrote:
> > > On Friday 04 April 2008, Marco Martin wrote:
> > > > uhm, what widget?
> > >
> > > the third parameter in Applet::paintInterface (and Widget::paintWidget,
> > > QGraphicsItem::paint)
> >
> > hhm, contentsrect? it always has a 0,0 position, i ought it was the
> > containment rect
>
> ah .. right. hm. paintInterface doesn't have the widget. paintWidget does,
> however. blah! i remember why i did that too: to avoid people from using
> the widget and doing unplasma things in their widgets.
>
> i'll add it to the Containment::StyleOption however (a ptr to the
> Plasma::View) and then it will work.
yay! seen your last changes and used them :D

>
> > > > anyways, using the geometry of the view(yeah, i know, bad) retrieved
> > > > in paintinterface to calc the borders, the layout margins won't get
> > > > updated,
> > >
> > > yes, it would require some caching of values (the widgets' geometry),
> > > checking them in paintInterface and if they are different recalc the
> > > margins.
> >
> > the problem is that if i call updateborders in paintinterface, or even do
> > a layout()->setMargin() with an hardcoded value it seems to have no
> > effect on the layout margins, until i manually resize the panel
>
> the layout probably just needs to be invalidated. indeed, it doesn't do
> that in the set margins call. you can call invalidate() manually. i don't
> know how fixable that will be given that the margins are set in LayoutItem
> and the invalidation is in Layout. *shrug*
oh, yeah, i why didn't think about that? grrr :)
anyways, it seems that to work it needs to be invalidated uhm, well some 
times :/ probably the layout it needs to be fully constructed/popolated?
the only way i found to check if the right margins are already set is this 
utter utter crap:
((formFactor() == Horizontal && firstApplet->size().height() != 
layout()->adjustToMargins(viewGeom).height()) ||
        (formFactor() == Vertical && firstApplet->size().width() != 
layout()->adjustToMargins(viewGeom).width()))

that of course assumes there are indeed applets in the containment and are 
well behaving so their minimum size is less than the containment size (and 
often is not the case)...
is there a less broken way?

Cheers,
Marco Martin


["panel_moving4.diff" (text/x-diff)]

Index: containments/panel/panel.cpp
===================================================================
--- containments/panel/panel.cpp	(revision 794403)
+++ containments/panel/panel.cpp	(working copy)
@@ -38,6 +38,7 @@
 #include <plasma/layouts/layout.h>
 #include <plasma/svgpanel.h>
 #include <plasma/theme.h>
+#include <plasma/view.h>
 
 using namespace Plasma;
 
@@ -47,7 +48,8 @@
       m_appletBrowserAction(0),
       m_configureAction(0),
       m_removeAction(0),
-      m_currentSize(QSize(QApplication::desktop()->screenGeometry(screen()).width(), 56))
+      m_currentSize(QSize(QApplication::desktop()->screenGeometry(screen()).width(), 56)),
+      m_lastViewGeom()
 {
     m_background = new Plasma::SvgPanel("widgets/panel-background", this);
     m_background->setBorderFlags(Plasma::SvgPanel::DrawAllBorders);
@@ -101,7 +103,7 @@
     constraintsUpdated(Plasma::LocationConstraint);
 }
 
-void Panel::updateBorders()
+void Panel::updateBorders(const QRect &geom)
 {
     Plasma::Location loc = location();
     SvgPanel::BorderFlags bFlags = SvgPanel::DrawAllBorders;
@@ -128,11 +130,11 @@
             topHeight = 0;
         }
 
-        if (geometry().x() <= r.x()) {
+        if (geom.x() <= r.x()) {
             bFlags ^= SvgPanel::DrawLeftBorder;
             leftWidth = 0;
         }
-        if (geometry().right() >= r.right()) {
+        if (geom.right() >= r.right()) {
             bFlags ^= SvgPanel::DrawRightBorder;
             rightWidth = 0;
         }
@@ -147,11 +149,11 @@
             bFlags ^= SvgPanel::DrawLeftBorder;
             leftWidth = 0;
         }
-        if (geometry().y() <= r.y()) {
+        if (geom.y() <= r.y()) {
             bFlags ^= SvgPanel::DrawTopBorder;
             topHeight = 0;
         }
-        if (geometry().bottom() >= r.bottom()) {
+        if (geom.bottom() >= r.bottom()) {
             bFlags ^= SvgPanel::DrawBottomBorder;
             bottomHeight = 0;
         }
@@ -160,7 +162,9 @@
         kDebug() << "no location!?";
     }
 
+    //invalidate the layout and set again
     if (layout()) {
+        layout()->invalidate();
         layout()->setMargin(Plasma::TopMargin, topHeight);
         layout()->setMargin(Plasma::LeftMargin, leftWidth);
         layout()->setMargin(Plasma::RightMargin, rightWidth);
@@ -191,12 +195,6 @@
         updateSize(m_currentSize);
     }
 
-    if (constraints & Plasma::ScreenConstraint ||
-        constraints & Plasma::LocationConstraint ||
-        constraints & Plasma::SizeConstraint) {
-        updateBorders();
-    }
-
     if (constraints & Plasma::ImmutableConstraint && m_appletBrowserAction) {
         // we need to update the menu items that have already been created
         bool locked = isImmutable();
@@ -222,7 +220,7 @@
 }
 
 void Panel::paintInterface(QPainter *painter,
-                           const QStyleOptionGraphicsItem *,
+                           const QStyleOptionGraphicsItem *option,
                            const QRect& contentsRect)
 {
     //FIXME: this background drawing is bad and ugly =)
@@ -230,6 +228,22 @@
     painter->save();
     painter->resetTransform();
 
+    const Containment::StyleOption *containmentOpt = qstyleoption_cast<const \
Containment::StyleOption *>(option); +    
+    QRect viewGeom;
+    if (containmentOpt) {
+        viewGeom = containmentOpt->view->geometry();
+    }
+
+    Plasma::Applet *firstApplet = applets().first();
+
+    if (viewGeom != m_lastViewGeom || firstApplet && 
+        ((formFactor() == Horizontal && firstApplet->size().height() != \
layout()->adjustToMargins(viewGeom).height()) || +        (formFactor() == Vertical && \
firstApplet->size().width() != layout()->adjustToMargins(viewGeom).width()))) { +        \
m_lastViewGeom = viewGeom; +        updateBorders(viewGeom);
+    }
+    
     // blit the background (saves all the per-pixel-products that blending does)
     painter->setCompositionMode(QPainter::CompositionMode_Source);
     painter->setRenderHint(QPainter::Antialiasing);
Index: containments/panel/panel.h
===================================================================
--- containments/panel/panel.h	(revision 794403)
+++ containments/panel/panel.h	(working copy)
@@ -72,7 +72,7 @@
     /**
      * recalculate which borders to show
      */
-    void updateBorders();
+    void updateBorders(const QRect &geom);
 
     Plasma::SvgPanel *m_background;
     KDialog* m_dialog;
@@ -83,7 +83,10 @@
     QAction* m_appletBrowserAction;
     QAction* m_configureAction;
     QAction* m_removeAction;
+
+    //cached values
     QSize m_currentSize;
+    QRect m_lastViewGeom;
 };
 
 
Index: plasma/panelview.h
===================================================================
--- plasma/panelview.h	(revision 794403)
+++ plasma/panelview.h	(working copy)
@@ -20,6 +20,8 @@
 #ifndef PLASMA_PANELVIEW_H
 #define PLASMA_PANELVIEW_H
 
+#include <kconfiggroup.h>
+
 #include <plasma/plasma.h>
 #include <plasma/view.h>
 
@@ -42,6 +44,8 @@
     * @arg parent the QWidget this panel is parented to
     */
     explicit PanelView(Plasma::Containment *panel, int id = 0, QWidget *parent = 0);
+    
+    ~PanelView();
 
     /**
      * Sets the location (screen edge) where this panel is positioned.
@@ -59,6 +63,39 @@
      */
     Plasma::Corona *corona() const;
 
+    /**
+     * Sets the offset the left border, the offset is the distance of the left
+     * border of the panel from the left border of the screen when the alignment is
+     * Qt::AlignLeft, right border and right edge if the alignment is Qt::alignRight
+     * and the distance between the center of the panel and the center of the screen if
+     * the alignment is Qt::AlignCenter.
+     * Similar way for vertical panels.
+     * @param newOffset the offset of the panel
+     */
+    void setOffset(int newOffset);
+
+    /**
+     * @return the offset of the panel from the left screen edge
+     */
+    int offset() const;
+
+    /**
+     * Sets the edge of the screen the panel will be aligned and will grow
+     * @param align the direction (for instance Qt::AlignLeft) means the panel will start
+     * from the left of the screen and grow to the right
+     */
+    void setAlignment(Qt::Alignment align);
+
+    /**
+     * @return the panel alignment
+     */
+    Qt::Alignment alignment() const;
+
+    /**
+     * Saves the view settings
+     */
+     void saveConfig();
+
 protected:
     void updateStruts();
     virtual void moveEvent(QMoveEvent *event);
@@ -69,7 +106,14 @@
     void showAppletBrowser();
 
 private:
+    Qt::Alignment alignmentFilter(Qt::Alignment align) const;
+
     Plasma::Svg *m_background;
+
+    KConfigGroup m_viewConfig;
+
+    int m_offset;
+    Qt::Alignment m_alignment;
 };
 
 #endif
Index: plasma/panelview.cpp
===================================================================
--- plasma/panelview.cpp	(revision 794403)
+++ plasma/panelview.cpp	(working copy)
@@ -33,10 +33,17 @@
 
 #include "plasmaapp.h"
 
+
 PanelView::PanelView(Plasma::Containment *panel, int id, QWidget *parent)
     : Plasma::View(panel, id, parent)
 {
     Q_ASSERT(qobject_cast<Plasma::Corona*>(panel->scene()));
+    
+    m_viewConfig =  config();
+
+    m_offset = m_viewConfig.readEntry("Offset", 0);
+    m_alignment = alignmentFilter((Qt::Alignment)m_viewConfig.readEntry("Alignment", \
(int)Qt::AlignLeft)); +
     updatePanelGeometry();
 
     if (panel) {
@@ -65,6 +72,11 @@
     updateStruts();
 }
 
+PanelView::~PanelView()
+{
+    saveConfig();
+    m_viewConfig.sync();
+}
 
 void PanelView::setLocation(Plasma::Location loc)
 {
@@ -84,6 +96,7 @@
 void PanelView::updatePanelGeometry()
 {
     kDebug() << "New panel geometry is" << containment()->geometry();
+
     QSize size = containment()->size().toSize();
     QRect geom(QPoint(0,0), size);
     int screen = containment()->screen();
@@ -95,33 +108,177 @@
 
     QRect screenGeom = QApplication::desktop()->screenGeometry(screen);
 
-    //FIXME: we need to support center, left, right, etc.. perhaps
-    //       pixel precision placed containments as well?
+    // Don't change the geometry again if a same one was asked
+    if (geom == screenGeom) {
+        return;
+    }
+
+    if (m_alignment != Qt::AlignCenter) {
+        m_offset = qMax(m_offset, 0);
+    }
+
+
+    //Sanity controls
     switch (location()) {
-        case Plasma::TopEdge:
-            geom.moveTopLeft(screenGeom.topLeft());
-            break;
-        case Plasma::LeftEdge:
-            geom.moveTopLeft(screenGeom.topLeft());
-            break;
-        case Plasma::RightEdge:
-            geom.moveTopLeft(QPoint(screenGeom.right() - size.width() + 1, screenGeom.top()));
-            break;
-        case Plasma::BottomEdge:
-        default:
-            geom.moveTopLeft(QPoint(screenGeom.left(), screenGeom.bottom() - size.height() + \
                1));
-            break;
+    case Plasma::TopEdge:
+    case Plasma::BottomEdge:
+        //resize the panel if is too large
+        if (geom.width() > screenGeom.width()) {
+            geom.setWidth(screenGeom.width());
+        }
+
+        //move the panel left/right if there is not enough room
+        if (m_alignment == Qt::AlignLeft) {
+             if (m_offset + screenGeom.left() + geom.width() > screenGeom.right() + 1) {
+                 m_offset = screenGeom.right() - geom.width();
+             }
+        } else if (m_alignment == Qt::AlignRight) {
+             if (screenGeom.right() - m_offset - geom.width() < 0 ) {
+                 m_offset = screenGeom.right() - geom.width();
+             }
+        } else if (m_alignment == Qt::AlignCenter) {
+             if (screenGeom.center().x() + m_offset + geom.width()/2 > screenGeom.right() + 1) \
{ +                 m_offset = screenGeom.right() - geom.width()/2 - screenGeom.center().x();
+             } else if (screenGeom.center().x() + m_offset - geom.width()/2 < 0) {
+                 m_offset = screenGeom.center().x() - geom.width()/2;
+             }
+        }
+        break;
+
+    case Plasma::LeftEdge:
+    case Plasma::RightEdge:
+        //resize the panel if is too tall
+        if (geom.height() > screenGeom.height()) {
+            geom.setHeight(screenGeom.height());
+        }
+
+        //move the panel bottom if there is not enough room
+        //FIXME: still using alignleft/alignright is simpler and less error prone, but \
aligntop/alignbottom is more correct? +        if (m_alignment == Qt::AlignLeft) {
+            if (m_offset + screenGeom.top() + geom.height() > screenGeom.bottom() + 1) {
+                m_offset = screenGeom.height() - geom.height();
+            }
+        } else if (m_alignment == Qt::AlignRight) {
+            if (screenGeom.bottom() - m_offset - geom.height() < 0) {
+                m_offset = screenGeom.bottom() - geom.height();
+            }
+        } else if (m_alignment == Qt::AlignCenter) {
+            if (screenGeom.center().y() + m_offset + geom.height()/2 > screenGeom.bottom() + \
1) { +                m_offset = screenGeom.bottom() - geom.height()/2 - \
screenGeom.center().y(); +             } else if (screenGeom.center().y() + m_offset - \
geom.width()/2 < 0) { +                m_offset = screenGeom.center().y() - geom.width()/2;
+             }
+        }
+        break;
+
+    //TODO: floating panels (probably they will save their own geometry)
+    default:
+        break;
     }
 
+    //Actual movement
+    switch (location()) {
+    case Plasma::TopEdge:
+        if (m_alignment == Qt::AlignLeft) {
+            geom.moveTopLeft(QPoint(m_offset, screenGeom.top()));
+        } else if (m_alignment == Qt::AlignRight) {
+            geom.moveTopRight(QPoint(screenGeom.right() - m_offset, screenGeom.top()));
+        } else if (m_alignment == Qt::AlignCenter) {
+            geom.moveCenter(QPoint(screenGeom.center().x() + m_offset, screenGeom.top() + \
geom.height()/2  - 1)); +        }
+
+        //enable borders if needed
+        //containment()->setGeometry(QRect(geom.left(), containment()->geometry().top(), \
geom.width(), geom.height())); +        break;
+
+    case Plasma::LeftEdge:
+        if (m_alignment == Qt::AlignLeft) {
+            geom.moveTopLeft(QPoint(screenGeom.left(), m_offset));
+        } else if (m_alignment == Qt::AlignRight) {
+            geom.moveBottomLeft(QPoint(screenGeom.left(), screenGeom.bottom() - m_offset));
+        } else if (m_alignment == Qt::AlignCenter) {
+            geom.moveCenter(QPoint(screenGeom.left()+geom.height()/2, screenGeom.center().y() \
+ m_offset)); +        }
+
+        //enable borders if needed
+        //containment()->setGeometry(QRect(containment()->geometry().left(), geom.top(), \
geom.width(), geom.height())); +        break;
+
+    case Plasma::RightEdge:
+        if (m_alignment == Qt::AlignLeft) {
+            geom.moveTopLeft(QPoint(screenGeom.right() - size.width() + 1, m_offset));
+        } else if (m_alignment == Qt::AlignRight) {
+            geom.moveBottomLeft(QPoint(screenGeom.right() - size.width() + 1, \
screenGeom.bottom() - m_offset)); +        } else if (m_alignment == Qt::AlignCenter) {
+            geom.moveCenter(QPoint(screenGeom.right() - size.width()/2 + 1, \
screenGeom.center().y() + m_offset)); +        }
+
+        //enable borders if needed
+        //containment()->setGeometry(QRect(containment()->geometry().left(), geom.top(), \
geom.width(), geom.height())); +        break;
+
+    case Plasma::BottomEdge:
+    default:
+        if (m_alignment == Qt::AlignLeft) {
+            geom.moveTopLeft(QPoint(m_offset, screenGeom.bottom() - size.height() + 1));
+        } else if (m_alignment == Qt::AlignRight) {
+            geom.moveTopRight(QPoint(screenGeom.right() - m_offset, screenGeom.bottom() - \
size.height() + 1)); +        } else if (m_alignment == Qt::AlignCenter) {
+            geom.moveCenter(QPoint(screenGeom.center().x() + m_offset, screenGeom.bottom() - \
size.height()/2 + 1)); +        }
+
+        //enable borders if needed
+        //containment()->setGeometry(QRect(geom.left(), containment()->geometry().top(), \
geom.width(), geom.height())); +        break;
+    }
+
     kDebug() << (QObject*)this << "thinks its panel is at " << geom;
+
     setGeometry(geom);
+    
 }
 
+void PanelView::setOffset(int newOffset)
+{
+    m_offset = newOffset;
+}
+
+int PanelView::offset() const
+{
+    return m_offset;
+}
+
+void PanelView::setAlignment(Qt::Alignment align)
+{
+    m_alignment = alignmentFilter(align);
+}
+
+Qt::Alignment PanelView::alignment() const
+{
+    return m_alignment;
+}
+
 void PanelView::showAppletBrowser()
 {
     PlasmaApp::self()->showAppletBrowser(containment());
 }
 
+void PanelView::saveConfig()
+{
+    m_viewConfig.writeEntry("Offset", m_offset);
+    m_viewConfig.writeEntry("Alignment", (int)m_alignment);
+}
+
+Qt::Alignment PanelView::alignmentFilter(Qt::Alignment align) const
+{
+    //If it's not a supported alignment default to Qt::AlignLeft
+    if (align == Qt::AlignLeft || align == Qt::AlignRight || align == Qt::AlignCenter) {
+        return align;
+    } else {
+        return Qt::AlignLeft;
+    }
+}
+
 void PanelView::updateStruts()
 {
     NETExtendedStrut strut;



_______________________________________________
Panel-devel mailing list
Panel-devel@kde.org
https://mail.kde.org/mailman/listinfo/panel-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic