Summary: | OSD Preview shows after opening the config dialog on windows | ||
---|---|---|---|
Product: | [Applications] konversation | Reporter: | Bernd Buschinski <b.buschinski> |
Component: | general | Assignee: | Konversation Developers <konversation-devel> |
Status: | RESOLVED FIXED | ||
Severity: | normal | ||
Priority: | NOR | ||
Version: | 1.2.3 | ||
Target Milestone: | --- | ||
Platform: | Microsoft Windows | ||
OS: | Microsoft Windows | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: |
Description
Bernd Buschinski
2010-04-22 17:26:59 UTC
commit 8354d0bd2ae0e4eb11b2b16d62b6430688f0b3ab Author: Carlo Segato <brandon.ml@gmail.com> Date: Sat Apr 24 16:17:41 2010 +0200 don't show the osd preview when opening the config dialog but only in the osd config page BUG:235080 diff --git a/src/config/osd_config.cpp b/src/config/osd_config.cpp index 40890c4..2b4bb92 100644 --- a/src/config/osd_config.cpp +++ b/src/config/osd_config.cpp @@ -1,197 +1,197 @@ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. -*/ - -/* - Copyright (C) 2005 Ivor Hewitt <ivor@ivor.org> - Copyright (C) 2005 Ismail Donmez <ismail@kde.org> - Copyright (C) 2006 Dario Abatianni <eisfuchs@tigress.com> - Copyright (C) 2006 John Tapsell <johnflux@gmail.com> - Copyright (C) 2006 Peter Simonsson <psn@linux.se> -*/ - -#include "osd_config.h" -#include "preferences.h" -#include "osd.h" -#include "application.h" - -#include <kcombobox.h> -#include <kcolorbutton.h> -#include <QCheckBox> -#include <kfontrequester.h> -#include <QDesktopWidget> -#include <kconfigdialog.h> - - -OSD_Config::OSD_Config( QWidget* parent, const char* name, Qt::WFlags fl ) - : QWidget(parent, fl) -{ - setObjectName(QString::fromLatin1(name)); - setupUi(this); - - bool enableScreenChooser = false; - QRect screenRect; - - for(int i = 0; i < QApplication::desktop()->numScreens(); ++i) { - kcfg_OSDScreen->addItem(QString::number(i)); - screenRect = QApplication::desktop()->screenGeometry(i); - - //Check if we're using xinerama or not - if(screenRect.left() != 0 || screenRect.top() != 0) { - enableScreenChooser = true; - } - } - - kcfg_OSDScreen->setEnabled(enableScreenChooser); - - m_pOSDPreview = new OSDPreviewWidget("Konversation"); - connect(m_pOSDPreview, SIGNAL(positionChanged()), this, SLOT(slotPositionChanged())); - - connect( kcfg_OSDFont, SIGNAL(fontSelected(const QFont&)), this, SLOT(slotUpdateFont(const QFont&))); - - slotOSDEnabledChanged(kcfg_UseOSD->isChecked()); - slotCustomColorsChanged(kcfg_OSDUseCustomColors->isChecked()); - slotScreenChanged(Preferences::self()->oSDScreen()); - slotDrawShadowChanged( kcfg_OSDDrawShadow->isChecked()); - slotUpdateFont(Preferences::self()->oSDFont()); - - kcfg_OSDOffsetX->hide(); - kcfg_OSDOffsetY->hide(); - kcfg_OSDAlignment->hide(); - - //Connect config page entries to control the OSDPreview - connect ( kcfg_UseOSD, SIGNAL( toggled( bool ) ), this, SLOT( slotOSDEnabledChanged(bool) ) ); - connect ( kcfg_OSDUseCustomColors, SIGNAL(toggled(bool)), this, SLOT(slotCustomColorsChanged(bool))); - connect ( kcfg_OSDTextColor, SIGNAL(changed(const QColor&)), this, SLOT(slotTextColorChanged(const QColor&))); - connect ( kcfg_OSDBackgroundColor, SIGNAL(changed(const QColor&)), this, SLOT(slotBackgroundColorChanged(const QColor&))); - connect ( kcfg_OSDScreen, SIGNAL(activated(int)), this, SLOT(slotScreenChanged(int))); - connect ( kcfg_OSDDrawShadow, SIGNAL(toggled(bool)), this, SLOT(slotDrawShadowChanged(bool))); -} - -OSD_Config::~OSD_Config() -{ - delete m_pOSDPreview; -} - -void OSD_Config::loadSettings() -{ -} - -void OSD_Config::restorePageToDefaults() -{ -} - -void OSD_Config::saveSettings() -{ - //Update the current OSD. - Application *konvApp=static_cast<Application *>(KApplication::kApplication()); - - konvApp->osd->setEnabled(kcfg_UseOSD->isChecked()); - if (kcfg_UseOSD->isChecked()) - { - konvApp->osd->setFont(Preferences::self()->oSDFont()); - if(kcfg_OSDUseCustomColors->isChecked()) - { - konvApp->osd->setTextColor(kcfg_OSDTextColor->color()); - QPalette p = konvApp->osd->palette(); - p.setColor(konvApp->osd->backgroundRole(), kcfg_OSDBackgroundColor->color()); - konvApp->osd->setPalette(p); - } - else - { - konvApp->osd->unsetColors(); - } - - konvApp->osd->setDuration(kcfg_OSDDuration->value()); - konvApp->osd->setScreen(kcfg_OSDScreen->currentIndex()); - konvApp->osd->setShadow(kcfg_OSDDrawShadow->isChecked()); - - //x is ignored anyway, but leave incase we use in future - konvApp->osd->setOffset(kcfg_OSDOffsetX->value(), kcfg_OSDOffsetY->value()); - konvApp->osd->setAlignment((OSDWidget::Alignment)kcfg_OSDAlignment->value()); - } - -} - -void OSD_Config::showEvent(QShowEvent*) -{ - //Update the preview - m_pOSDPreview->setAlignment((OSDWidget::Alignment)( kcfg_OSDAlignment->value() ) ); - m_pOSDPreview->setOffset(kcfg_OSDOffsetX->value(),kcfg_OSDOffsetY->value()); - - m_pOSDPreview->setVisible(kcfg_UseOSD->isChecked()); -} - -void OSD_Config::hideEvent(QHideEvent*) -{ - m_pOSDPreview->setVisible(false); -} - -bool OSD_Config::hasChanged() -{ - // follow the interface, no Non-KConfigXT settings here, so none have changed - return false; -} - -void OSD_Config::slotOSDEnabledChanged(bool on) -{ - if ( isVisible() ) - m_pOSDPreview->setVisible(on); -} - -void OSD_Config::slotPositionChanged() -{ - kcfg_OSDScreen->setCurrentIndex(m_pOSDPreview->screen()); - - kcfg_OSDAlignment->setValue( m_pOSDPreview->alignment() ); - kcfg_OSDOffsetX->setValue( m_pOSDPreview->x()); - kcfg_OSDOffsetY->setValue( m_pOSDPreview->y()); -} - - -void OSD_Config::slotCustomColorsChanged(bool on) -{ - if(on) - { - m_pOSDPreview->setTextColor(kcfg_OSDTextColor->color()); - QPalette p = m_pOSDPreview->palette(); - p.setColor(m_pOSDPreview->backgroundRole(), kcfg_OSDBackgroundColor->color()); - m_pOSDPreview->setPalette(p); - } - else - m_pOSDPreview->unsetColors(); -} -void OSD_Config::slotTextColorChanged(const QColor& color) -{ - if(kcfg_OSDUseCustomColors->isChecked()) - m_pOSDPreview->setTextColor(color); -} - -void OSD_Config::slotBackgroundColorChanged(const QColor& color) -{ - if(kcfg_OSDUseCustomColors->isChecked()) { - QPalette p = m_pOSDPreview->palette(); - p.setColor(m_pOSDPreview->backgroundRole(), color); - m_pOSDPreview->setPalette(p); - } -} - -void OSD_Config::slotScreenChanged(int index) -{ - m_pOSDPreview->setScreen(index); -} - -void OSD_Config::slotDrawShadowChanged(bool on) -{ - m_pOSDPreview->setShadow(on); -} - -void OSD_Config::slotUpdateFont(const QFont& font) -{ - m_pOSDPreview->setFont(font); -} - -#include "osd_config.moc" +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +/* + Copyright (C) 2005 Ivor Hewitt <ivor@ivor.org> + Copyright (C) 2005 Ismail Donmez <ismail@kde.org> + Copyright (C) 2006 Dario Abatianni <eisfuchs@tigress.com> + Copyright (C) 2006 John Tapsell <johnflux@gmail.com> + Copyright (C) 2006 Peter Simonsson <psn@linux.se> +*/ + +#include "osd_config.h" +#include "preferences.h" +#include "osd.h" +#include "application.h" + +#include <kcombobox.h> +#include <kcolorbutton.h> +#include <QCheckBox> +#include <kfontrequester.h> +#include <QDesktopWidget> +#include <kconfigdialog.h> + + +OSD_Config::OSD_Config( QWidget* parent, const char* name, Qt::WFlags fl ) + : QWidget(parent, fl) +{ + setObjectName(QString::fromLatin1(name)); + setupUi(this); + + bool enableScreenChooser = false; + QRect screenRect; + + for(int i = 0; i < QApplication::desktop()->numScreens(); ++i) { + kcfg_OSDScreen->addItem(QString::number(i)); + screenRect = QApplication::desktop()->screenGeometry(i); + + //Check if we're using xinerama or not + if(screenRect.left() != 0 || screenRect.top() != 0) { + enableScreenChooser = true; + } + } + + kcfg_OSDScreen->setEnabled(enableScreenChooser); + + m_pOSDPreview = new OSDPreviewWidget("Konversation"); + connect(m_pOSDPreview, SIGNAL(positionChanged()), this, SLOT(slotPositionChanged())); + + connect( kcfg_OSDFont, SIGNAL(fontSelected(const QFont&)), this, SLOT(slotUpdateFont(const QFont&))); + + slotOSDEnabledChanged(kcfg_UseOSD->isChecked()); + slotCustomColorsChanged(kcfg_OSDUseCustomColors->isChecked()); + slotScreenChanged(Preferences::self()->oSDScreen()); + slotDrawShadowChanged( kcfg_OSDDrawShadow->isChecked()); + slotUpdateFont(Preferences::self()->oSDFont()); + + kcfg_OSDOffsetX->hide(); + kcfg_OSDOffsetY->hide(); + kcfg_OSDAlignment->hide(); + + //Connect config page entries to control the OSDPreview + connect ( kcfg_UseOSD, SIGNAL( toggled( bool ) ), this, SLOT( slotOSDEnabledChanged(bool) ) ); + connect ( kcfg_OSDUseCustomColors, SIGNAL(toggled(bool)), this, SLOT(slotCustomColorsChanged(bool))); + connect ( kcfg_OSDTextColor, SIGNAL(changed(const QColor&)), this, SLOT(slotTextColorChanged(const QColor&))); + connect ( kcfg_OSDBackgroundColor, SIGNAL(changed(const QColor&)), this, SLOT(slotBackgroundColorChanged(const QColor&))); + connect ( kcfg_OSDScreen, SIGNAL(activated(int)), this, SLOT(slotScreenChanged(int))); + connect ( kcfg_OSDDrawShadow, SIGNAL(toggled(bool)), this, SLOT(slotDrawShadowChanged(bool))); +} + +OSD_Config::~OSD_Config() +{ + delete m_pOSDPreview; +} + +void OSD_Config::loadSettings() +{ +} + +void OSD_Config::restorePageToDefaults() +{ +} + +void OSD_Config::saveSettings() +{ + //Update the current OSD. + Application *konvApp=static_cast<Application *>(KApplication::kApplication()); + + konvApp->osd->setEnabled(kcfg_UseOSD->isChecked()); + if (kcfg_UseOSD->isChecked()) + { + konvApp->osd->setFont(Preferences::self()->oSDFont()); + if(kcfg_OSDUseCustomColors->isChecked()) + { + konvApp->osd->setTextColor(kcfg_OSDTextColor->color()); + QPalette p = konvApp->osd->palette(); + p.setColor(konvApp->osd->backgroundRole(), kcfg_OSDBackgroundColor->color()); + konvApp->osd->setPalette(p); + } + else + { + konvApp->osd->unsetColors(); + } + + konvApp->osd->setDuration(kcfg_OSDDuration->value()); + konvApp->osd->setScreen(kcfg_OSDScreen->currentIndex()); + konvApp->osd->setShadow(kcfg_OSDDrawShadow->isChecked()); + + //x is ignored anyway, but leave incase we use in future + konvApp->osd->setOffset(kcfg_OSDOffsetX->value(), kcfg_OSDOffsetY->value()); + konvApp->osd->setAlignment((OSDWidget::Alignment)kcfg_OSDAlignment->value()); + } + +} + +void OSD_Config::showEvent(QShowEvent*) +{ + //Update the preview + m_pOSDPreview->setAlignment((OSDWidget::Alignment)( kcfg_OSDAlignment->value() ) ); + m_pOSDPreview->setOffset(kcfg_OSDOffsetX->value(),kcfg_OSDOffsetY->value()); + + if (kcfg_UseOSD->isChecked()) m_pOSDPreview->show(); +} + +void OSD_Config::hideEvent(QHideEvent*) +{ + m_pOSDPreview->setVisible(false); +} + +bool OSD_Config::hasChanged() +{ + // follow the interface, no Non-KConfigXT settings here, so none have changed + return false; +} + +void OSD_Config::slotOSDEnabledChanged(bool on) +{ + if ( isVisible() ) + on ? m_pOSDPreview->show() : m_pOSDPreview->setVisible(false); +} + +void OSD_Config::slotPositionChanged() +{ + kcfg_OSDScreen->setCurrentIndex(m_pOSDPreview->screen()); + + kcfg_OSDAlignment->setValue( m_pOSDPreview->alignment() ); + kcfg_OSDOffsetX->setValue( m_pOSDPreview->x()); + kcfg_OSDOffsetY->setValue( m_pOSDPreview->y()); +} + + +void OSD_Config::slotCustomColorsChanged(bool on) +{ + if(on) + { + m_pOSDPreview->setTextColor(kcfg_OSDTextColor->color()); + QPalette p = m_pOSDPreview->palette(); + p.setColor(m_pOSDPreview->backgroundRole(), kcfg_OSDBackgroundColor->color()); + m_pOSDPreview->setPalette(p); + } + else + m_pOSDPreview->unsetColors(); +} +void OSD_Config::slotTextColorChanged(const QColor& color) +{ + if(kcfg_OSDUseCustomColors->isChecked()) + m_pOSDPreview->setTextColor(color); +} + +void OSD_Config::slotBackgroundColorChanged(const QColor& color) +{ + if(kcfg_OSDUseCustomColors->isChecked()) { + QPalette p = m_pOSDPreview->palette(); + p.setColor(m_pOSDPreview->backgroundRole(), color); + m_pOSDPreview->setPalette(p); + } +} + +void OSD_Config::slotScreenChanged(int index) +{ + m_pOSDPreview->setScreen(index); +} + +void OSD_Config::slotDrawShadowChanged(bool on) +{ + m_pOSDPreview->setShadow(on); +} + +void OSD_Config::slotUpdateFont(const QFont& font) +{ + m_pOSDPreview->setFont(font); +} + +#include "osd_config.moc" diff --git a/src/viewer/osd.cpp b/src/viewer/osd.cpp index 578464b..b0d01a3 100644 --- a/src/viewer/osd.cpp +++ b/src/viewer/osd.cpp @@ -1,516 +1,515 @@ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. -*/ - -/* - Copyright (C) 2004 Christian Muehlhaeuser <chris@chris.de> - Copyright (C) 2004-2006 Seb Ruiz <ruiz@kde.org> - Copyright (C) 2004-2005 Max Howell <max.howell@methylblue.com> - Copyright (C) 2005 Gábor Lehel <illissius@gmail.com> - Copyright (C) 2008 Mark Kretschmann <kretschmann@kde.org> -*/ - -#include "osd.h" -#include "common.h" - -#include <QDesktopWidget> -#include <QMouseEvent> -#include <QPainter> -#include <QPixmap> -#include <QBitmap> -#include <QRegExp> -#include <QTimer> - -#include <KApplication> -#include <KLocale> -#include <KDebug> - - -namespace ShadowEngine -{ - QImage makeShadow( const QPixmap &textPixmap, const QColor &bgColor ); -} - -OSDWidget::OSDWidget(const QString &appName, QWidget *parent, const char *name ) - : QWidget( parent ) - , m_appName( appName ) - , m_duration( 5000 ) - , m_timer( new QTimer( this ) ) - , m_timerMin( new QTimer( this ) ) - , m_alignment( Middle ) - , m_screen( 0 ) - , m_y( MARGIN ) - , m_drawShadow( true ) -{ - Qt::WindowFlags flags; - flags = Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint; - // The best of both worlds. On Windows, setting the widget as a popup avoids a task manager entry. On linux, a popup steals focus. - // Therefore we go need to do it platform specific :( - #ifdef Q_OS_WIN - flags |= Qt::Tool; - #else - flags |= Qt::Window | Qt::X11BypassWindowManagerHint; - #endif - setWindowFlags( flags ); - setObjectName( name ); - setFocusPolicy( Qt::NoFocus ); - unsetColors(); - - m_timer->setSingleShot( true ); - - connect( m_timer, SIGNAL( timeout() ), SLOT( hide() ) ); - connect( m_timerMin, SIGNAL( timeout() ), SLOT( minReached() ) ); - - //or crashes, KWindowSystem bug I think, crashes in QWidget::icon() - kapp->setTopWidget( this ); -} - -OSDWidget::~OSDWidget() -{ - delete m_timer; - delete m_timerMin; -} - -void OSDWidget::show( const QString &text, bool preemptive ) -{ - if ( preemptive || !m_timerMin->isActive() ) - { - m_currentText = Konversation::removeIrcMarkup(text); - - show(); - } - else textBuffer.append( Konversation::removeIrcMarkup(text) ); //queue -} - -void OSDWidget::show() //virtual -{ - if ( !isEnabled() || m_currentText.isEmpty() ) - return; - - const uint M = fontMetrics().width( 'x' ); - - const QRect oldGeometry = QRect( pos(), size() ); - const QRect newGeometry = determineMetrics( M ); - - if( newGeometry.width() > 0 && newGeometry.height() > 0 ) - { - m_m = M; - m_size = newGeometry.size(); - setGeometry( newGeometry ); - QWidget::show(); - - if ( m_duration ) //duration 0 -> stay forever - { - m_timer->start( m_duration ); //calls hide() - m_timerMin->start( 1500 ); //calls minReached() - } - } - else - kWarning() << "Attempted to make an invalid sized OSD"; - - update(); -} - -void OSDWidget::minReached() //SLOT -{ - if ( !textBuffer.isEmpty() ) - { - show( textBuffer.first(), true ); - textBuffer.removeFirst(); - - if( m_duration ) - //timerMin is still running - m_timer->start( m_duration ); - } - else m_timerMin->stop(); -} - -void OSDWidget::setDuration( int ms ) -{ - m_duration = ms; - - if( !m_duration ) m_timer->stop(); -} - -QRect OSDWidget::determineMetrics( const int M ) -{ - // determine a sensible maximum size, don't cover the whole desktop or cross the screen - const QSize margin( ( M + MARGIN ) * 2, ( M + MARGIN ) * 2 ); //margins - const QSize max = QApplication::desktop()->screen( m_screen )->size() - margin; - - // If we don't do that, the boundingRect() might not be suitable for drawText() (Qt issue N67674) - m_currentText.replace( QRegExp( " +\n" ), "\n" ); - // remove consecutive line breaks - m_currentText.replace( QRegExp( "\n+" ), "\n" ); - - QFont titleFont = font(); - titleFont.setBold(true); - QFontMetrics titleFm( titleFont ); - - // The osd cannot be larger than the screen - QRect titleRect = titleFm.boundingRect( 0, 0, max.width() - M, titleFm.height(), Qt::AlignLeft, m_appName ); - QRect textRect = fontMetrics().boundingRect( 0, 0, max.width(), max.height(), Qt::AlignCenter | Qt::TextWordWrap, m_currentText ); - textRect.setHeight( textRect.height() + M + M ); - - if ( textRect.width() < titleRect.width() ) - textRect.setWidth( titleRect.width() ); - - textRect.adjust( 0, 0, M*2, titleRect.height() + M ); - - // expand in all directions by M - textRect.adjust( -M, -M, M, M ); - - const QSize newSize = textRect.size(); - const QRect screen = QApplication::desktop()->screenGeometry( m_screen ); - QPoint newPos( MARGIN, m_y ); - - switch( m_alignment ) - { - case Left: - break; - - case Right: - newPos.rx() = screen.width() - MARGIN - newSize.width(); - break; - - case Center: - newPos.ry() = ( screen.height() - newSize.height() ) / 2; - - //FALL THROUGH - - case Middle: - newPos.rx() = ( screen.width() - newSize.width() ) / 2; - break; - } - - //ensure we don't dip below the screen - if ( newPos.y() + newSize.height() > screen.height() - MARGIN ) - newPos.ry() = screen.height() - MARGIN - newSize.height(); - - // correct for screen position - newPos += screen.topLeft(); - - return QRect( newPos, textRect.size() ); -} - -void OSDWidget::paintEvent( QPaintEvent *e ) -{ - int M = m_m; - QSize size = m_size; - - QFont titleFont = font(); - titleFont.setBold(true); - - QPoint point; - QRect rect( point, size ); - rect.adjust( 0, 0, -1, -1 ); - - QColor shadowColor; - { - int h, s, v; - palette().color( QPalette::Normal, QPalette::Foreground ).getHsv( &h, &s, &v ); - shadowColor = v > 128 ? Qt::black : Qt::white; - } - - int align = Qt::AlignCenter | Qt::TextWordWrap; - - QPainter p( this ); - QBitmap mask( e->rect().size() ); - QPainter maskPainter( &mask ); - - p.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing ); - p.setClipRect( e->rect() ); - - const qreal xround = 20.0; - const qreal yround = 20.0; - - // Masking for transparency - mask.fill( Qt::color0 ); - maskPainter.setBrush( Qt::color1 ); - maskPainter.drawRoundedRect( e->rect(), xround, yround ); - setMask( mask ); - - p.drawRoundedRect( e->rect(), xround, yround ); - - p.setPen( Qt::white ); // Revert this when the background can be colorized again. - rect.adjust( M, M, -M, -M ); - - int graphicsHeight = 0; - - rect.setBottom( rect.bottom() - graphicsHeight ); - - // Draw "shadow" text effect (black outline) - if( m_drawShadow ) - { - QPixmap pixmap( rect.size() + QSize( 10, 10 ) ); - pixmap.fill( Qt::black ); - - QPainter p2( &pixmap ); - p2.setFont( font() ); - p2.setPen( Qt::white ); - p2.setBrush( Qt::white ); - p2.drawText( QRect( QPoint( 5, 5 ), rect.size() ), align, m_currentText ); - p2.end(); - - p.drawImage( rect.topLeft() - QPoint( 5, 5 ), ShadowEngine::makeShadow( pixmap, shadowColor ) ); - - pixmap.fill( Qt::black ); - pixmap.scaled( QSize(e->rect().width()-1, e->rect().height()-1) + QSize( 10, 10 ) ); - - p2.begin( &pixmap ); - p2.setFont( titleFont ); - p2.setPen( Qt::white ); - p2.setBrush( Qt::white ); - p2.drawText( QRect( QPoint( 5, 5 ), QSize(e->rect().width()-1, e->rect().height()-1) ), Qt::AlignLeft, m_appName ); - p2.end(); - - p.drawImage( QPoint(M*2, M/2) - QPoint( 5, 5 ), ShadowEngine::makeShadow( pixmap, shadowColor ) ); - } - p.setPen( palette().color( QPalette::Active, QPalette::WindowText ) ); - //p.setPen( Qt::white ); // This too. - p.setFont( font() ); - p.drawText( rect, align, m_currentText ); - - p.setFont( titleFont ); - p.drawText( M * 2, (M/2), e->rect().width()-1, e->rect().height()-1, Qt::AlignLeft, m_appName ); -} - -void OSDWidget::resizeEvent(QResizeEvent *e) -{ - //setMask(m_background->mask()); - QWidget::resizeEvent( e ); -} - -bool OSDWidget::event( QEvent *e ) -{ - switch( e->type() ) - { - case QEvent::ApplicationPaletteChange: - //if( !AmarokConfig::osdUseCustomColors() ) - // unsetColors(); //use new palette's colours - return true; - - default: - return QWidget::event( e ); - } -} - -void OSDWidget::mousePressEvent( QMouseEvent* ) -{ - hide(); -} - -void OSDWidget::unsetColors() -{ - QPalette p = QApplication::palette(); - QPalette newPal = palette(); - - newPal.setColor( QPalette::Active, QPalette::WindowText, p.color( QPalette::Active, QPalette::WindowText ) ); - newPal.setColor( QPalette::Active, QPalette::Window , p.color( QPalette::Active, QPalette::Window ) ); - setPalette( newPal ); -} - -void OSDWidget::setOffset( int /*x*/, int y ) -{ - //m_offset = QPoint( x, y ); - m_y = y; -} - -void OSDWidget::setScreen( int screen ) -{ - const int n = QApplication::desktop()->numScreens(); - m_screen = ( screen >= n ) ? n - 1 : screen; -} - - -///////////////////////////////////////////////////////////////////////////////////////// -// Class OSDPreviewWidget -///////////////////////////////////////////////////////////////////////////////////////// - -OSDPreviewWidget::OSDPreviewWidget( const QString &appName, QWidget *parent, const char *name ) - : OSDWidget( appName, parent, name ) - , m_dragging( false ) -{ - setObjectName( "osdpreview" ); - m_currentText = i18n( "OSD Preview - drag to reposition" ); - m_duration = 0; - //m_alignment = static_cast<Alignment>( AmarokConfig::osdAlignment() ); - //m_y = AmarokConfig::osdYOffset(); - QFont f = font(); - f.setPointSize( 16 ); - setFont( f ); - //setTranslucent( AmarokConfig::osdUseTranslucency() ); - show( m_currentText ); -} - -void OSDPreviewWidget::mousePressEvent( QMouseEvent *event ) -{ - m_dragOffset = event->pos(); - - if( event->button() == Qt::LeftButton && !m_dragging ) - { - grabMouse( Qt::SizeAllCursor ); - m_dragging = true; - } -} - -void OSDPreviewWidget::mouseReleaseEvent( QMouseEvent * /*event*/ ) -{ - if( m_dragging ) - { - m_dragging = false; - releaseMouse(); - - // compute current Position && offset - QDesktopWidget *desktop = QApplication::desktop(); - int currentScreen = desktop->screenNumber( pos() ); - - if( currentScreen != -1 ) - { - // set new data - m_screen = currentScreen; - m_y = QWidget::y(); - - emit positionChanged(); - } - } -} - -void OSDPreviewWidget::mouseMoveEvent( QMouseEvent *e ) -{ - if( m_dragging && this == mouseGrabber() ) - { - // Here we implement a "snap-to-grid" like positioning system for the preview widget - - const QRect screen = QApplication::desktop()->screenGeometry( m_screen ); - const uint hcenter = screen.width() / 2; - const uint eGlobalPosX = e->globalPos().x() - screen.left(); - const uint snapZone = screen.width() / 24; - - QPoint destination = e->globalPos() - m_dragOffset - screen.topLeft(); - int maxY = screen.height() - height() - MARGIN; - if( destination.y() < MARGIN ) - destination.ry() = MARGIN; - if( destination.y() > maxY ) - destination.ry() = maxY; - - if( eGlobalPosX < ( hcenter - snapZone ) ) - { - m_alignment = Left; - destination.rx() = MARGIN; - } - else if( eGlobalPosX > ( hcenter + snapZone ) ) - { - m_alignment = Right; - destination.rx() = screen.width() - MARGIN - width(); - } - else { - const uint eGlobalPosY = e->globalPos().y() - screen.top(); - const uint vcenter = screen.height() / 2; - - destination.rx() = hcenter - width() / 2; - - if( eGlobalPosY >= ( vcenter - snapZone ) && eGlobalPosY <= ( vcenter + snapZone ) ) - { - m_alignment = Center; - destination.ry() = vcenter - height() / 2; - } - else m_alignment = Middle; - } - - destination += screen.topLeft(); - - move( destination ); - } -} - -/* Code copied from kshadowengine.cpp - * - * Copyright (C) 2003 Laur Ivan <laurivan@eircom.net> - * - * Many thanks to: - * - Bernardo Hung <deciare@gta.igs.net> for the enhanced shadow - * algorithm (currently used) - * - Tim Jansen <tim@tjansen.de> for the API updates and fixes. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License version 2 as published by the Free Software Foundation. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -namespace ShadowEngine -{ - // Not sure, doesn't work above 10 - static const int MULTIPLICATION_FACTOR = 3; - // Multiplication factor for pixels directly above, under, or next to the text - static const double AXIS_FACTOR = 2.0; - // Multiplication factor for pixels diagonal to the text - static const double DIAGONAL_FACTOR = 0.1; - // Self explanatory - static const int MAX_OPACITY = 200; - - double decay( QImage&, int, int ); - - QImage makeShadow( const QPixmap& textPixmap, const QColor &bgColor ) - { - const int w = textPixmap.width(); - const int h = textPixmap.height(); - const int bgr = bgColor.red(); - const int bgg = bgColor.green(); - const int bgb = bgColor.blue(); - - int alphaShadow; - - // This is the source pixmap - QImage img = textPixmap.toImage(); - - QImage result( w, h, QImage::Format_ARGB32 ); - result.fill( 0 ); // fill with black - - static const int M = 5; - for( int i = M; i < w - M; i++) { - for( int j = M; j < h - M; j++ ) - { - alphaShadow = (int) decay( img, i, j ); - - result.setPixel( i,j, qRgba( bgr, bgg , bgb, qMin( MAX_OPACITY, alphaShadow ) ) ); - } - } - - return result; - } - - double decay( QImage& source, int i, int j ) - { - //if ((i < 1) || (j < 1) || (i > source.width() - 2) || (j > source.height() - 2)) - // return 0; - - double alphaShadow; - alphaShadow =(qGray(source.pixel(i-1,j-1)) * DIAGONAL_FACTOR + - qGray(source.pixel(i-1,j )) * AXIS_FACTOR + - qGray(source.pixel(i-1,j+1)) * DIAGONAL_FACTOR + - qGray(source.pixel(i ,j-1)) * AXIS_FACTOR + - 0 + - qGray(source.pixel(i ,j+1)) * AXIS_FACTOR + - qGray(source.pixel(i+1,j-1)) * DIAGONAL_FACTOR + - qGray(source.pixel(i+1,j )) * AXIS_FACTOR + - qGray(source.pixel(i+1,j+1)) * DIAGONAL_FACTOR) / MULTIPLICATION_FACTOR; - - return alphaShadow; - } -} - -#include "osd.moc" +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +*/ + +/* + Copyright (C) 2004 Christian Muehlhaeuser <chris@chris.de> + Copyright (C) 2004-2006 Seb Ruiz <ruiz@kde.org> + Copyright (C) 2004-2005 Max Howell <max.howell@methylblue.com> + Copyright (C) 2005 Gábor Lehel <illissius@gmail.com> + Copyright (C) 2008 Mark Kretschmann <kretschmann@kde.org> +*/ + +#include "osd.h" +#include "common.h" + +#include <QDesktopWidget> +#include <QMouseEvent> +#include <QPainter> +#include <QPixmap> +#include <QBitmap> +#include <QRegExp> +#include <QTimer> + +#include <KApplication> +#include <KLocale> +#include <KDebug> + + +namespace ShadowEngine +{ + QImage makeShadow( const QPixmap &textPixmap, const QColor &bgColor ); +} + +OSDWidget::OSDWidget(const QString &appName, QWidget *parent, const char *name ) + : QWidget( parent ) + , m_appName( appName ) + , m_duration( 5000 ) + , m_timer( new QTimer( this ) ) + , m_timerMin( new QTimer( this ) ) + , m_alignment( Middle ) + , m_screen( 0 ) + , m_y( MARGIN ) + , m_drawShadow( true ) +{ + Qt::WindowFlags flags; + flags = Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint; + // The best of both worlds. On Windows, setting the widget as a popup avoids a task manager entry. On linux, a popup steals focus. + // Therefore we go need to do it platform specific :( + #ifdef Q_OS_WIN + flags |= Qt::Tool; + #else + flags |= Qt::Window | Qt::X11BypassWindowManagerHint; + #endif + setWindowFlags( flags ); + setObjectName( name ); + setFocusPolicy( Qt::NoFocus ); + unsetColors(); + + m_timer->setSingleShot( true ); + + connect( m_timer, SIGNAL( timeout() ), SLOT( hide() ) ); + connect( m_timerMin, SIGNAL( timeout() ), SLOT( minReached() ) ); + + //or crashes, KWindowSystem bug I think, crashes in QWidget::icon() + kapp->setTopWidget( this ); +} + +OSDWidget::~OSDWidget() +{ + delete m_timer; + delete m_timerMin; +} + +void OSDWidget::show( const QString &text, bool preemptive ) +{ + if ( preemptive || !m_timerMin->isActive() ) + { + m_currentText = Konversation::removeIrcMarkup(text); + + show(); + } + else textBuffer.append( Konversation::removeIrcMarkup(text) ); //queue +} + +void OSDWidget::show() //virtual +{ + if ( !isEnabled() || m_currentText.isEmpty() ) + return; + + const uint M = fontMetrics().width( 'x' ); + + const QRect oldGeometry = QRect( pos(), size() ); + const QRect newGeometry = determineMetrics( M ); + + if( newGeometry.width() > 0 && newGeometry.height() > 0 ) + { + m_m = M; + m_size = newGeometry.size(); + setGeometry( newGeometry ); + QWidget::show(); + + if ( m_duration ) //duration 0 -> stay forever + { + m_timer->start( m_duration ); //calls hide() + m_timerMin->start( 1500 ); //calls minReached() + } + } + else + kWarning() << "Attempted to make an invalid sized OSD"; + + update(); +} + +void OSDWidget::minReached() //SLOT +{ + if ( !textBuffer.isEmpty() ) + { + show( textBuffer.first(), true ); + textBuffer.removeFirst(); + + if( m_duration ) + //timerMin is still running + m_timer->start( m_duration ); + } + else m_timerMin->stop(); +} + +void OSDWidget::setDuration( int ms ) +{ + m_duration = ms; + + if( !m_duration ) m_timer->stop(); +} + +QRect OSDWidget::determineMetrics( const int M ) +{ + // determine a sensible maximum size, don't cover the whole desktop or cross the screen + const QSize margin( ( M + MARGIN ) * 2, ( M + MARGIN ) * 2 ); //margins + const QSize max = QApplication::desktop()->screen( m_screen )->size() - margin; + + // If we don't do that, the boundingRect() might not be suitable for drawText() (Qt issue N67674) + m_currentText.replace( QRegExp( " +\n" ), "\n" ); + // remove consecutive line breaks + m_currentText.replace( QRegExp( "\n+" ), "\n" ); + + QFont titleFont = font(); + titleFont.setBold(true); + QFontMetrics titleFm( titleFont ); + + // The osd cannot be larger than the screen + QRect titleRect = titleFm.boundingRect( 0, 0, max.width() - M, titleFm.height(), Qt::AlignLeft, m_appName ); + QRect textRect = fontMetrics().boundingRect( 0, 0, max.width(), max.height(), Qt::AlignCenter | Qt::TextWordWrap, m_currentText ); + textRect.setHeight( textRect.height() + M + M ); + + if ( textRect.width() < titleRect.width() ) + textRect.setWidth( titleRect.width() ); + + textRect.adjust( 0, 0, M*2, titleRect.height() + M ); + + // expand in all directions by M + textRect.adjust( -M, -M, M, M ); + + const QSize newSize = textRect.size(); + const QRect screen = QApplication::desktop()->screenGeometry( m_screen ); + QPoint newPos( MARGIN, m_y ); + + switch( m_alignment ) + { + case Left: + break; + + case Right: + newPos.rx() = screen.width() - MARGIN - newSize.width(); + break; + + case Center: + newPos.ry() = ( screen.height() - newSize.height() ) / 2; + + //FALL THROUGH + + case Middle: + newPos.rx() = ( screen.width() - newSize.width() ) / 2; + break; + } + + //ensure we don't dip below the screen + if ( newPos.y() + newSize.height() > screen.height() - MARGIN ) + newPos.ry() = screen.height() - MARGIN - newSize.height(); + + // correct for screen position + newPos += screen.topLeft(); + + return QRect( newPos, textRect.size() ); +} + +void OSDWidget::paintEvent( QPaintEvent *e ) +{ + int M = m_m; + QSize size = m_size; + + QFont titleFont = font(); + titleFont.setBold(true); + + QPoint point; + QRect rect( point, size ); + rect.adjust( 0, 0, -1, -1 ); + + QColor shadowColor; + { + int h, s, v; + palette().color( QPalette::Normal, QPalette::Foreground ).getHsv( &h, &s, &v ); + shadowColor = v > 128 ? Qt::black : Qt::white; + } + + int align = Qt::AlignCenter | Qt::TextWordWrap; + + QPainter p( this ); + QBitmap mask( e->rect().size() ); + QPainter maskPainter( &mask ); + + p.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing ); + p.setClipRect( e->rect() ); + + const qreal xround = 20.0; + const qreal yround = 20.0; + + // Masking for transparency + mask.fill( Qt::color0 ); + maskPainter.setBrush( Qt::color1 ); + maskPainter.drawRoundedRect( e->rect(), xround, yround ); + setMask( mask ); + + p.drawRoundedRect( e->rect(), xround, yround ); + + p.setPen( Qt::white ); // Revert this when the background can be colorized again. + rect.adjust( M, M, -M, -M ); + + int graphicsHeight = 0; + + rect.setBottom( rect.bottom() - graphicsHeight ); + + // Draw "shadow" text effect (black outline) + if( m_drawShadow ) + { + QPixmap pixmap( rect.size() + QSize( 10, 10 ) ); + pixmap.fill( Qt::black ); + + QPainter p2( &pixmap ); + p2.setFont( font() ); + p2.setPen( Qt::white ); + p2.setBrush( Qt::white ); + p2.drawText( QRect( QPoint( 5, 5 ), rect.size() ), align, m_currentText ); + p2.end(); + + p.drawImage( rect.topLeft() - QPoint( 5, 5 ), ShadowEngine::makeShadow( pixmap, shadowColor ) ); + + pixmap.fill( Qt::black ); + pixmap.scaled( QSize(e->rect().width()-1, e->rect().height()-1) + QSize( 10, 10 ) ); + + p2.begin( &pixmap ); + p2.setFont( titleFont ); + p2.setPen( Qt::white ); + p2.setBrush( Qt::white ); + p2.drawText( QRect( QPoint( 5, 5 ), QSize(e->rect().width()-1, e->rect().height()-1) ), Qt::AlignLeft, m_appName ); + p2.end(); + + p.drawImage( QPoint(M*2, M/2) - QPoint( 5, 5 ), ShadowEngine::makeShadow( pixmap, shadowColor ) ); + } + p.setPen( palette().color( QPalette::Active, QPalette::WindowText ) ); + //p.setPen( Qt::white ); // This too. + p.setFont( font() ); + p.drawText( rect, align, m_currentText ); + + p.setFont( titleFont ); + p.drawText( M * 2, (M/2), e->rect().width()-1, e->rect().height()-1, Qt::AlignLeft, m_appName ); +} + +void OSDWidget::resizeEvent(QResizeEvent *e) +{ + //setMask(m_background->mask()); + QWidget::resizeEvent( e ); +} + +bool OSDWidget::event( QEvent *e ) +{ + switch( e->type() ) + { + case QEvent::ApplicationPaletteChange: + //if( !AmarokConfig::osdUseCustomColors() ) + // unsetColors(); //use new palette's colours + return true; + + default: + return QWidget::event( e ); + } +} + +void OSDWidget::mousePressEvent( QMouseEvent* ) +{ + hide(); +} + +void OSDWidget::unsetColors() +{ + QPalette p = QApplication::palette(); + QPalette newPal = palette(); + + newPal.setColor( QPalette::Active, QPalette::WindowText, p.color( QPalette::Active, QPalette::WindowText ) ); + newPal.setColor( QPalette::Active, QPalette::Window , p.color( QPalette::Active, QPalette::Window ) ); + setPalette( newPal ); +} + +void OSDWidget::setOffset( int /*x*/, int y ) +{ + //m_offset = QPoint( x, y ); + m_y = y; +} + +void OSDWidget::setScreen( int screen ) +{ + const int n = QApplication::desktop()->numScreens(); + m_screen = ( screen >= n ) ? n - 1 : screen; +} + + +///////////////////////////////////////////////////////////////////////////////////////// +// Class OSDPreviewWidget +///////////////////////////////////////////////////////////////////////////////////////// + +OSDPreviewWidget::OSDPreviewWidget( const QString &appName, QWidget *parent, const char *name ) + : OSDWidget( appName, parent, name ) + , m_dragging( false ) +{ + setObjectName( "osdpreview" ); + m_currentText = i18n( "OSD Preview - drag to reposition" ); + m_duration = 0; + //m_alignment = static_cast<Alignment>( AmarokConfig::osdAlignment() ); + //m_y = AmarokConfig::osdYOffset(); + QFont f = font(); + f.setPointSize( 16 ); + setFont( f ); + //setTranslucent( AmarokConfig::osdUseTranslucency() ); +} + +void OSDPreviewWidget::mousePressEvent( QMouseEvent *event ) +{ + m_dragOffset = event->pos(); + + if( event->button() == Qt::LeftButton && !m_dragging ) + { + grabMouse( Qt::SizeAllCursor ); + m_dragging = true; + } +} + +void OSDPreviewWidget::mouseReleaseEvent( QMouseEvent * /*event*/ ) +{ + if( m_dragging ) + { + m_dragging = false; + releaseMouse(); + + // compute current Position && offset + QDesktopWidget *desktop = QApplication::desktop(); + int currentScreen = desktop->screenNumber( pos() ); + + if( currentScreen != -1 ) + { + // set new data + m_screen = currentScreen; + m_y = QWidget::y(); + + emit positionChanged(); + } + } +} + +void OSDPreviewWidget::mouseMoveEvent( QMouseEvent *e ) +{ + if( m_dragging && this == mouseGrabber() ) + { + // Here we implement a "snap-to-grid" like positioning system for the preview widget + + const QRect screen = QApplication::desktop()->screenGeometry( m_screen ); + const uint hcenter = screen.width() / 2; + const uint eGlobalPosX = e->globalPos().x() - screen.left(); + const uint snapZone = screen.width() / 24; + + QPoint destination = e->globalPos() - m_dragOffset - screen.topLeft(); + int maxY = screen.height() - height() - MARGIN; + if( destination.y() < MARGIN ) + destination.ry() = MARGIN; + if( destination.y() > maxY ) + destination.ry() = maxY; + + if( eGlobalPosX < ( hcenter - snapZone ) ) + { + m_alignment = Left; + destination.rx() = MARGIN; + } + else if( eGlobalPosX > ( hcenter + snapZone ) ) + { + m_alignment = Right; + destination.rx() = screen.width() - MARGIN - width(); + } + else { + const uint eGlobalPosY = e->globalPos().y() - screen.top(); + const uint vcenter = screen.height() / 2; + + destination.rx() = hcenter - width() / 2; + + if( eGlobalPosY >= ( vcenter - snapZone ) && eGlobalPosY <= ( vcenter + snapZone ) ) + { + m_alignment = Center; + destination.ry() = vcenter - height() / 2; + } + else m_alignment = Middle; + } + + destination += screen.topLeft(); + + move( destination ); + } +} + +/* Code copied from kshadowengine.cpp + * + * Copyright (C) 2003 Laur Ivan <laurivan@eircom.net> + * + * Many thanks to: + * - Bernardo Hung <deciare@gta.igs.net> for the enhanced shadow + * algorithm (currently used) + * - Tim Jansen <tim@tjansen.de> for the API updates and fixes. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +namespace ShadowEngine +{ + // Not sure, doesn't work above 10 + static const int MULTIPLICATION_FACTOR = 3; + // Multiplication factor for pixels directly above, under, or next to the text + static const double AXIS_FACTOR = 2.0; + // Multiplication factor for pixels diagonal to the text + static const double DIAGONAL_FACTOR = 0.1; + // Self explanatory + static const int MAX_OPACITY = 200; + + double decay( QImage&, int, int ); + + QImage makeShadow( const QPixmap& textPixmap, const QColor &bgColor ) + { + const int w = textPixmap.width(); + const int h = textPixmap.height(); + const int bgr = bgColor.red(); + const int bgg = bgColor.green(); + const int bgb = bgColor.blue(); + + int alphaShadow; + + // This is the source pixmap + QImage img = textPixmap.toImage(); + + QImage result( w, h, QImage::Format_ARGB32 ); + result.fill( 0 ); // fill with black + + static const int M = 5; + for( int i = M; i < w - M; i++) { + for( int j = M; j < h - M; j++ ) + { + alphaShadow = (int) decay( img, i, j ); + + result.setPixel( i,j, qRgba( bgr, bgg , bgb, qMin( MAX_OPACITY, alphaShadow ) ) ); + } + } + + return result; + } + + double decay( QImage& source, int i, int j ) + { + //if ((i < 1) || (j < 1) || (i > source.width() - 2) || (j > source.height() - 2)) + // return 0; + + double alphaShadow; + alphaShadow =(qGray(source.pixel(i-1,j-1)) * DIAGONAL_FACTOR + + qGray(source.pixel(i-1,j )) * AXIS_FACTOR + + qGray(source.pixel(i-1,j+1)) * DIAGONAL_FACTOR + + qGray(source.pixel(i ,j-1)) * AXIS_FACTOR + + 0 + + qGray(source.pixel(i ,j+1)) * AXIS_FACTOR + + qGray(source.pixel(i+1,j-1)) * DIAGONAL_FACTOR + + qGray(source.pixel(i+1,j )) * AXIS_FACTOR + + qGray(source.pixel(i+1,j+1)) * DIAGONAL_FACTOR) / MULTIPLICATION_FACTOR; + + return alphaShadow; + } +} + +#include "osd.moc" |