Bug 134387

Summary: This applet needs to contrain it's max size
Product: [Unmaintained] kweather-kde3 Reporter: david.hubert.cook
Component: generalAssignee: geiseri
Status: RESOLVED FIXED    
Severity: normal    
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description david.hubert.cook 2006-09-20 13:26:16 UTC
Version:            (using KDE 3.5.3, Kubuntu Package 4:3.5.3-0ubuntu0.1 dapper)
Compiler:          Target: i486-linux-gnu
OS:                Linux (i686) release 2.6.16.27

KDE panel supports a 'custom size' option, where the user can
choose a size in pixels.  (I typically choose a value around 150.
Note that user can also place the panel on any of the four sides of
the screen, so make sure you test both horizontal and vertical placement.)

When a user does this, well-behaved applets contrain their size to
a reasonable smaller value, so that they do NOT occupy too large of
a percentage of the total panel space.  A good example of this is
the clock applet.  (KMenu also does this.)

Kweather needs to contrain itself, like Clock and Kmenu do.

TIA...

Dave
Comment 1 Martin Koller 2006-12-28 01:06:14 UTC
SVN commit 617101 by mkoller:

BUG: 81098
BUG: 73202
BUG: 134387

Fix layouting in all different display modes and kicker orientation modes
Always use a sane font size and limit overall size of applet


 M  +209 -68   dockwidget.cpp  
 M  +2 -2      weatherbutton.h  


--- branches/KDE/3.5/kdetoys/kweather/dockwidget.cpp #617100:617101
@@ -21,7 +21,7 @@
 #include "weatherservice_stub.h"
 
 #include <qtooltip.h>
-#include <qvbox.h>
+#include <qlayout.h>
 #include <qlabel.h>
 #include <qtimer.h>
 
@@ -32,11 +32,11 @@
 dockwidget::dockwidget(const QString &location, QWidget *parent,
         const char *name) : QWidget(parent,name), m_locationCode( location ), m_orientation( Horizontal )
 {
+    m_font = KGlobalSettings::generalFont();
     initDock();
     connect(m_button, SIGNAL( clicked() ), SIGNAL( buttonClicked() ));
 
     m_weatherService = new WeatherService_stub( "KWeatherService", "WeatherService" );
-    m_font = KGlobalSettings::generalFont();
 
     setBackgroundOrigin( AncestorOrigin );
 }
@@ -176,6 +176,18 @@
     m_lblWind->setMargin(0);
     m_lblPres->setMargin(0);
 
+    QBoxLayout *mainLayout = new QBoxLayout(this, QBoxLayout::TopToBottom);
+    mainLayout->setSpacing(0);
+    mainLayout->setMargin(0);
+    mainLayout->addWidget(m_button, 0, Qt::AlignCenter);
+
+    QBoxLayout *layout = new QBoxLayout(mainLayout, QBoxLayout::TopToBottom);
+    layout->setSpacing(0);
+    layout->setMargin(0);
+    layout->addWidget(m_lblTemp);
+    layout->addWidget(m_lblWind);
+    layout->addWidget(m_lblPres);
+
     updateFont();
 
     QTimer::singleShot( 0, this, SLOT( showWeather() ) );
@@ -187,86 +199,168 @@
     kdDebug(12004) << "Changing to size " << size << endl;
     resize(size);
 
-    int w = size.width();
-    int h = size.height();
-
-    if (m_orientation == Horizontal)
+    if ( m_orientation == Horizontal ) // Kicker in horizontal mode
     {
-        // in case we previously set this to hcenter previously
-        // and now change the layout
-        m_lblTemp->setAlignment(AlignVCenter);
+        int h = size.height();
 
-        // Kicker in horizontal mode
-        if( m_mode == ShowAll)
+        if ( m_mode == ShowAll )
         {
-            m_lblTemp->setGeometry(h+1, 0, w-h, h/3);
-            m_lblWind->setGeometry(h+1, h/3, w-h, h/3);
-            m_lblPres->setGeometry(h+1, 2*h/3, w-h, h/3);
-            m_button->setGeometry(0, 0, h, h);
+            if ( h <= 128 )  // left to right layout
+            {
+                static_cast<QBoxLayout*>(layout())->setDirection(QBoxLayout::LeftToRight);
+                m_lblTemp->setAlignment(Qt::AlignAuto | Qt::AlignVCenter);
+                m_lblWind->setAlignment(Qt::AlignAuto | Qt::AlignVCenter);
+                m_lblPres->setAlignment(Qt::AlignAuto | Qt::AlignVCenter);
+            }
+            else  // top to bottom
+            {
+                static_cast<QBoxLayout*>(layout())->setDirection(QBoxLayout::TopToBottom);
+                QFontMetrics fm(m_font);
+                h = 128 - (3 * fm.height());  // 3 lines of text below the button
+                m_lblTemp->setAlignment(Qt::AlignCenter);
+                m_lblWind->setAlignment(Qt::AlignCenter);
+                m_lblPres->setAlignment(Qt::AlignCenter);
+            }
+            m_button->setFixedSize(h, h);
         }
-        else if ( m_mode == ShowTempOnly)
+        else if ( m_mode == ShowTempOnly )
         {
-            if (h > 32)
+            if ( h <= 32 )  // left to right
             {
-                m_lblTemp->setAlignment(AlignVCenter | AlignHCenter);
-                m_lblTemp->setGeometry(1, h - h/5, w - 2, h/5);
-                m_button->setGeometry(0, 0, 4*h/5, 4*h/5);
+                static_cast<QBoxLayout*>(layout())->setDirection(QBoxLayout::LeftToRight);
+                m_lblTemp->setAlignment(Qt::AlignAuto | Qt::AlignVCenter);
             }
-            else
+            else  // top to bottom
             {
-                m_lblTemp->setGeometry(h+1, 0, w-h, h);
-                m_button->setGeometry(0, 0, h, h );
+                static_cast<QBoxLayout*>(layout())->setDirection(QBoxLayout::TopToBottom);
+                QFontMetrics fm(m_font);
+                h = QMIN(128, h) - fm.height();
+                m_lblTemp->setAlignment(Qt::AlignCenter);
             }
+            m_button->setFixedSize(h, h);
         }
         else
         {
-            m_button->setGeometry(0, 0, h, h );
+            h = QMIN(h, 128);
+            m_button->setFixedSize(h, h);
         }
     }
-    else
+    else // Kicker in vertical mode
     {
-        // Kicker in vertical mode
-        if( m_mode == ShowAll)
+        int w = size.width();
+        int h = size.height();
+
+        if ( m_mode == ShowAll )
         {
-            m_lblTemp->setGeometry(0, w, w, w/3);
-            m_lblWind->setGeometry(0, 4*w/3, w, w/3);
-            m_lblPres->setGeometry(0, 5*w/3, w, w/3);
+            if ( w <= 128 )  // top to bottom
+            {
+                static_cast<QBoxLayout*>(layout())->setDirection(QBoxLayout::TopToBottom);
+                m_lblTemp->setAlignment(Qt::AlignCenter);
+                m_lblWind->setAlignment(Qt::AlignCenter);
+                m_lblPres->setAlignment(Qt::AlignCenter);
+
+                QFontMetrics fm(m_font);
+                h = h - (3 * fm.height());  // 3 lines of text below the button
+                h = QMIN(w, h);
+            }
+            else  // left to right layout
+            {
+                static_cast<QBoxLayout*>(layout())->setDirection(QBoxLayout::LeftToRight);
+                m_lblTemp->setAlignment(Qt::AlignAuto | Qt::AlignVCenter);
+                m_lblWind->setAlignment(Qt::AlignAuto | Qt::AlignVCenter);
+                m_lblPres->setAlignment(Qt::AlignAuto | Qt::AlignVCenter);
+            }
+            m_button->setFixedSize(h, h);
         }
-        else if ( m_mode == ShowTempOnly)
+        else if ( m_mode == ShowTempOnly )
         {
-            m_lblTemp->setGeometry(1, w, w, h-(w+1) );
+            if ( w <= 128 )  // top to bottom
+            {
+                static_cast<QBoxLayout*>(layout())->setDirection(QBoxLayout::TopToBottom);
+                m_lblTemp->setAlignment(Qt::AlignCenter);
+
+                h = w;
+            }
+            else  // left to right layout
+            {
+                static_cast<QBoxLayout*>(layout())->setDirection(QBoxLayout::LeftToRight);
+                m_lblTemp->setAlignment(Qt::AlignAuto | Qt::AlignVCenter);
+
+                h = static_cast<int>(w * 0.33);
+            }
+            m_button->setFixedSize(h, h);
         }
-        m_button->setGeometry(0, 0, w, w );
+        else
+        {
+            w = QMIN(w, 128);
+            m_button->setFixedSize(w, w);
+        }
     }
-    updateFont();
 }
 
 int dockwidget::widthForHeight(int h)
 {
-    int w=h;
-    QFontMetrics fm(m_font);
+    int w;
+    QFontInfo fi(KGlobalSettings::generalFont());
 
-    if( m_mode == ShowAll)
+    if ( m_mode == ShowAll )
     {
-        m_font.setPixelSize( h/3-2 );
-        w = h + QMAX(fm.width(m_lblWind->text()),
-        fm.width(m_lblPres->text())) + 1;
+        if ( h <= 128 )  // left to right layout
+        {
+            int pixelSize = h/3 - 3;
+            pixelSize = QMIN(pixelSize, fi.pixelSize());  // don't make it too large
+            m_font.setPixelSize(pixelSize);
+            QFontMetrics fm(m_font);
+            w = h + QMAX(fm.width(m_lblWind->text()), fm.width(m_lblPres->text())) + 1;
+        }
+        else  // top to bottom
+        {
+            if ( fi.pixelSize() * 3 <= (h/2) )  // half icon, half text
+            {
+                m_font = KGlobalSettings::generalFont();
+            }
+            else
+            {
+                m_font.setPixelSize(h/2/3);
+            }
+            QFontMetrics fm(m_font);
+            // size of icon
+            h = 128 - (3 * fm.height());  // 3 lines of text below the button
+            w = QMAX(fm.width(m_lblWind->text()), fm.width(m_lblPres->text())) + 1;
+            w = QMAX(h, w);  // at least width of square icon
+        }
     }
-    else if ( m_mode == ShowTempOnly)
+    else if ( m_mode == ShowTempOnly )
     {
-        QFontInfo fi( KGlobalSettings::generalFont() );
-        int pixelSize = QMIN( h, fi.pixelSize() );
-        m_font.setPixelSize( pixelSize );
-
-        if (h > 32)
+        if ( h <= 32 )  // left to right layout
         {
-            w = 4*h/5;
+            int pixelSize = h - 3;
+            pixelSize = QMIN(pixelSize, fi.pixelSize());  // don't make it too large
+            m_font.setPixelSize(pixelSize);
+            QFontMetrics fm(m_font);
+            w = h + fm.width(m_lblTemp->text()) + 1;
         }
-        else
+        else  // top to bottom
         {
-            w = h + fm.width(m_lblTemp->text()) + 1;
+            if ( fi.pixelSize() <= (h/2) )  // half icon, half text
+            {
+                m_font = KGlobalSettings::generalFont();
+            }
+            else
+            {
+                m_font.setPixelSize(h/2);
+            }
+            QFontMetrics fm(m_font);
+            // size of icon
+            h = QMIN(128, h) - fm.height();
+            w = fm.width(m_lblTemp->text()) + 1;
+            w = QMAX(h, w);  // at least width of square icon
         }
     }
+    else
+    {
+        w = QMIN(128, h);  // don't make it too large
+    }
 
     updateFont();
     return w;
@@ -275,33 +369,80 @@
 int dockwidget::heightForWidth( int w )
 {
     int h;
-    // Adjust the height of the font to compensate for width
-    int startSize = w;
-    int width = w + 1;
 
     if ( m_mode == ShowAll )
     {
-       while( (width > w)  && (startSize > 0))
-       {
-           m_font.setPixelSize( --startSize );
-           QFontMetrics fm(m_font);
-           width = QMAX(fm.width(m_lblWind->text()),
-                        fm.width(m_lblPres->text()));
-       }
-       h = ( w * 2 );
+        QFontMetrics fmg(KGlobalSettings::generalFont());
+        int maxWidth = fmg.width("888 km/h NNWW");  // a good approximation
+
+        if ( w <= 128 )  // top to bottom
+        {
+            if ( maxWidth <= w )  // enough space to use global font
+            {
+                m_font = KGlobalSettings::generalFont();
+            }
+            else  // we have to reduce the fontsize
+            {
+                m_font.setPixelSize(static_cast<int>(fmg.height() * double(w) / maxWidth));
+            }
+
+            QFontMetrics fm(m_font);
+            h = w + (3 * fm.height());  // 3 lines of text below the button
+        }
+        else
+        {
+            if ( w >= (maxWidth * 1.5) )  // half of text width shall be icon
+            {
+                m_font = KGlobalSettings::generalFont();
+            }
+            else
+            {
+                m_font.setPixelSize(static_cast<int>(fmg.height() * (w*0.66) / maxWidth));
+            }
+
+            QFontMetrics fm(m_font);
+            h = 3 * fm.height();  // 3 lines of text
+
+        }
     }
     else if ( m_mode == ShowTempOnly )
     {
-       while( (width > w)  && (startSize > 0))
-       {
-           m_font.setPixelSize( --startSize );
-           QFontMetrics fm(m_font);
-           width = fm.width(m_lblTemp->text());
-       }
-       h = w + startSize + 2;
+        QFontMetrics fmg(KGlobalSettings::generalFont());
+        int maxWidth = fmg.width("888.88 CC");  // a good approximation
+
+        if ( w <= 128 )  // top to bottom
+        {
+            if ( maxWidth <= w )  // enough space to use global font
+            {
+                m_font = KGlobalSettings::generalFont();
+            }
+            else  // we have to reduce the fontsize
+            {
+                m_font.setPixelSize(static_cast<int>(fmg.height() * double(w) / maxWidth));
+            }
+
+            QFontMetrics fm(m_font);
+            h = w + fm.height();  // text below the button
+        }
+        else
+        {
+            if ( w >= (maxWidth * 1.5) )  // half of text width shall be icon
+            {
+                m_font = KGlobalSettings::generalFont();
+            }
+            else
+            {
+                m_font.setPixelSize(static_cast<int>(fmg.height() * (w*0.66) / maxWidth));
+            }
+
+            QFontMetrics fm(m_font);
+            h = QMAX(fm.height(), static_cast<int>(w * 0.33));
+        }
     }
     else
-        h = w;
+    {
+        h = QMIN(128, w);  // don't make it too large
+    }
 
     updateFont();
     return h;
--- branches/KDE/3.5/kdetoys/kweather/weatherbutton.h #617100:617101
@@ -34,8 +34,8 @@
   protected:
     void drawButton( QPainter *p );
     void drawButtonLabel( QPainter *p );
-    QSize margin() const { return QSize( 5, 5 ); }
-    QSize pixmapSize() const { return size() - margin(); }
+    QSize margin() const { return QSize( 3, 3 ); }
+    QSize pixmapSize() const { return size() - margin()*2; }
     QPoint pixmapOrigin() const;
     void generateIcons();