Version: (using KDE KDE 3.2.2) Installed from: Debian testing/unstable Packages kweather seems to automatically scale the display font to fit available width. It also seems to automatically adjust the precision of numbers (e.g., "62.6" vs. "59"). The problem is that when the number precision changes, and hence the number of digits, the font size will adjust on the fly. Since this affects the height of the font, when kweather is in a vertical panel it causes the entire panel layout to be recalculated. This unwanted visual activity could easily be solved by fixing the precision of the numbers.
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();