⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 osd.cpp

📁 Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 经过两年开发后
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * 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. * * osd.cpp:   Shows some text in a pretty way independent to the WM * begin:     Fre Sep 26 2003 * copyright: (C) 2004 Christian Muehlhaeuser <chris@chris.de> *            (C) 2004-2006 Seb Ruiz <me@sebruiz.net> *            (C) 2004, 2005 Max Howell *            (C) 2005 Gábor Lehel <illissius@gmail.com> */#include "amarok.h"#include "amarokconfig.h"#include "collectiondb.h"    //for albumCover location#include "debug.h"#include "enginecontroller.h"#include "osd.h"#include "playlist.h"        //if osdUsePlaylistColumns()#include "playlistitem.h"    //ditto#include "podcastbundle.h"#include "qstringx.h"#include "starmanager.h"#include <kapplication.h>#include <kpixmap.h>#include <kpixmapeffect.h>#include <kstandarddirs.h>   //locate#include <qbitmap.h>#include <qpainter.h>#include <qpixmap.h>#include <qregexp.h>#include <qtimer.h>#include <qvaluevector.h>namespace ShadowEngine{    QImage makeShadow( const QPixmap &textPixmap, const QColor &bgColor );}#define MOODBAR_HEIGHT 20OSDWidget::OSDWidget( QWidget *parent, const char *name )        : QWidget( parent, name, WType_TopLevel | WNoAutoErase | WStyle_Customize | WX11BypassWM | WStyle_StaysOnTop )        , m_duration( 2000 )        , m_timer( new QTimer( this ) )        , m_alignment( Middle )        , m_screen( 0 )        , m_y( MARGIN )        , m_drawShadow( false )        , m_translucency( false )        , m_rating( 0 )        , m_volume( false ){    setFocusPolicy( NoFocus );    setBackgroundMode( NoBackground );    unsetColors();    connect( m_timer, SIGNAL(timeout()), SLOT(hide()) );    connect( CollectionDB::instance(), SIGNAL( ratingChanged( const QString&, int ) ),             this, SLOT( ratingChanged( const QString&, int ) ) );    //or crashes, KWin bug I think, crashes in QWidget::icon()    kapp->setTopWidget( this );}voidOSDWidget::show( const QString &text, QImage newImage ){#ifdef Q_WS_X11    m_text = text;    if ( !newImage.isNull() )    {        m_cover = newImage;        int w = m_scaledCover.width();        int h = m_scaledCover.height();        m_scaledCover = m_cover.smoothScale(w, h);    }    show();#else    Q_UNUSED( text );    Q_UNUSED( newImage );#endif}voidOSDWidget::ratingChanged( const short rating ){    //m_text = '\n' + i18n( "Rating changed" );    setRating( rating ); //Checks isEnabled() before doing anything    if( useMoodbar() )        OSDWidget::setMoodbar( EngineController::instance()->bundle() );    if( isShown() )        show();}voidOSDWidget::ratingChanged( const QString& path, int rating ){    const MetaBundle &currentTrack = EngineController::instance()->bundle();    if( currentTrack.isFile() && currentTrack.url().path() == path )        ratingChanged( rating );}voidOSDWidget::volChanged( unsigned char volume ){    if ( isEnabled() )    {        m_volume = true;        m_newvolume = volume;        m_text = m_newvolume ? i18n("Volume: %1%").arg( m_newvolume ) : i18n("Mute");        show();    }}voidOSDWidget::show() //virtual{#ifdef Q_WS_X11    if ( !isEnabled() || m_text.isEmpty() )        return;    const uint M = fontMetrics().width( 'x' );    const QRect oldGeometry = QRect( pos(), size() );    const QRect newGeometry = determineMetrics( M );    if( m_translucency && !isShown() || !newGeometry.intersects( oldGeometry ) )        m_screenshot = QPixmap::grabWindow( qt_xrootwin(),                newGeometry.x(), newGeometry.y(),                newGeometry.width(), newGeometry.height() );    else if( m_translucency )    {        const QRect unite = oldGeometry.unite( newGeometry );        KPixmap pix = QPixmap::grabWindow( qt_xrootwin(), unite.x(), unite.y(), unite.width(), unite.height() );        QPoint p = oldGeometry.topLeft() - unite.topLeft();        bitBlt( &pix, p, &m_screenshot );        m_screenshot.resize( newGeometry.size() );        p = newGeometry.topLeft() - unite.topLeft();        bitBlt( &m_screenshot, 0, 0, &pix, p.x(), p.y() );    }    if( newGeometry.width() > 0 && newGeometry.height() > 0 )    {        render( M, newGeometry.size() );        setGeometry( newGeometry );        QWidget::show();        bitBlt( this, 0, 0, &m_buffer );        if( m_duration ) //duration 0 -> stay forever            m_timer->start( m_duration, true ); //calls hide()    }    else        warning() << "Attempted to make an invalid sized OSD\n";#endif}QRectOSDWidget::determineMetrics( const uint M ){    // sometimes we only have a tiddly cover    const QSize minImageSize = m_cover.size().boundedTo( QSize(100,100) );    // 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 image = m_cover.isNull() ? QSize( 0, 0 ) : minImageSize;    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_text.replace( QRegExp(" +\n"), "\n" );    // remove consecutive line breaks    m_text.replace( QRegExp("\n+"), "\n" );    // The osd cannot be larger than the screen    QRect rect = fontMetrics().boundingRect( 0, 0,            max.width() - image.width(), max.height(),            AlignCenter | WordBreak, m_text );    if( m_volume )    {        static const QString tmp = QString ("******").insert( 3,            ( i18n("Volume: 100%").length() >= i18n("Mute").length() )?            i18n("Volume: 100%") : i18n("Mute") );        QRect tmpRect = fontMetrics().boundingRect( 0, 0,            max.width() - image.width(), max.height() - fontMetrics().height(),            AlignCenter | WordBreak, tmp );        tmpRect.setHeight( tmpRect.height() + fontMetrics().height() / 2 );        rect = tmpRect;    }    if( m_rating )    {        QPixmap* star = StarManager::instance()->getStar( 1, true );        if( rect.width() < star->width() * 5 )            rect.setWidth( star->width() * 5 ); //changes right edge position        rect.setHeight( rect.height() + star->height() + M ); //changes bottom edge pos    }    if( useMoodbar() )        rect.setHeight( rect.height() + MOODBAR_HEIGHT + M );    if( !m_cover.isNull() )    {        const int availableWidth = max.width() - rect.width() - M; //WILL be >= (minImageSize.width() - M)        m_scaledCover = m_cover.smoothScale(                QMIN( availableWidth, m_cover.width() ),                QMIN( rect.height(), m_cover.height() ),                QImage::ScaleMin ); //this will force us to be with our bounds        int shadowWidth = 0;        if( m_drawShadow && !m_scaledCover.hasAlpha() &&          ( m_scaledCover.width() > 22 || m_scaledCover.height() > 22 ) )            shadowWidth = static_cast<uint>( m_scaledCover.width() / 100.0 * 6.0 );        const int widthIncludingImage = rect.width()                + m_scaledCover.width()                + shadowWidth                + M; //margin between text + image        rect.setWidth( widthIncludingImage );    }    // expand in all directions by M    rect.addCoords( -M, -M, M, M );    const QSize newSize = rect.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, rect.size() );}voidOSDWidget::render( const uint M, const QSize &size ){    /// render with margin/spacing @param M and @param size    QPoint point;    QRect rect( point, size );    // From qt sources    const uint xround = (M * 200) / size.width();    const uint yround = (M * 200) / size.height();    {   /// apply the mask        static QBitmap mask;        mask.resize( size );        mask.fill( Qt::black );        QPainter p( &mask );        p.setBrush( Qt::white );        p.drawRoundRect( rect, xround, yround );        setMask( mask );    }    QColor shadowColor;    {        int h,s,v;        foregroundColor().getHsv( &h, &s, &v );        shadowColor = v > 128 ? Qt::black : Qt::white;    }    int align = Qt::AlignCenter | WordBreak;    m_buffer.resize( rect.size() );    QPainter p( &m_buffer );    if( m_translucency )    {        KPixmap background( m_screenshot );        KPixmapEffect::fade( background, 0.80, backgroundColor() );        p.drawPixmap( 0, 0, background );    }    else        p.fillRect( rect, backgroundColor() );    p.setPen( backgroundColor().dark() );    p.drawRoundRect( rect, xround, yround );    rect.addCoords( M, M, -M, -M );    if( !m_cover.isNull() )    {        QRect r( rect );        r.setTop( (size.height() - m_scaledCover.height()) / 2 );        r.setSize( m_scaledCover.size() );        if( !m_scaledCover.hasAlpha() && m_drawShadow &&          ( m_scaledCover.width() > 22 || m_scaledCover.height() > 22 ) ) {            // don't draw a shadow for eg, the Amarok icon            QImage shadow;            const uint shadowSize = static_cast<uint>( m_scaledCover.width() / 100.0 * 6.0 );            const QString folder = Amarok::saveLocation( "covershadow-cache/" );            const QString file = QString( "shadow_albumcover%1x%2.png" ).arg( m_scaledCover.width()  + shadowSize )                                                                        .arg( m_scaledCover.height() + shadowSize );            if ( QFile::exists( folder + file ) )                shadow.load( folder + file );            else {                shadow.load( locate( "data", "amarok/images/shadow_albumcover.png" ) );                shadow = shadow.smoothScale( m_scaledCover.width() + shadowSize, m_scaledCover.height() + shadowSize );                shadow.save( folder + file, "PNG" );            }            QPixmap target;            target.convertFromImage( shadow ); //FIXME slow            copyBlt( &target, 0, 0, &m_scaledCover );            m_scaledCover = target;            r.setTop( (size.height() - m_scaledCover.height()) / 2 );            r.setSize( m_scaledCover.size() );        }        p.drawPixmap( r.topLeft(), m_scaledCover );        rect.rLeft() += m_scaledCover.width() + M;    }    if( m_volume )    {        QPixmap vol;        vol = QPixmap( rect.width(), rect.height() + fontMetrics().height() / 4 );        QPixmap buf( vol.size() );        QRect r( rect );        r.setLeft( rect.left() + rect.width() / 2 - vol.width() / 2 );        r.setTop( size.height() / 2 - vol.height() / 2);        KPixmap pixmapGradient;        { // gradient            QBitmap mask;            mask.resize( vol.size() );            mask.fill( Qt::black );            QPainter p( &mask );            p.setBrush( Qt::white );            p.drawRoundRect ( 3, 3, vol.width() - 6, vol.height() - 6,                M * 300 / vol.width(), 99 );            p.end();            pixmapGradient = QPixmap( vol.size() );            KPixmapEffect::gradient( pixmapGradient, colorGroup().background(),                colorGroup().highlight(), KPixmapEffect::EllipticGradient );            pixmapGradient.setMask( mask );        }        if( m_translucency )        {            KPixmap background( m_screenshot );            KPixmapEffect::fade( background, 0.80, backgroundColor() );            bitBlt( &vol, -r.left(), -r.top(), &background );        }        else            vol.fill( backgroundColor() );        { // vol ( bg-alpha )            static QBitmap mask;            mask.resize( vol.size() );            mask.fill( Qt::white );            QPainter p( &mask );            p.setBrush( Qt::black );            p.drawRoundRect ( 1, 1, rect.width()-2, rect.height() + fontMetrics().height() / 4 - 2,                M * 300 / vol.width(), 99 );            p.setBrush( Qt::white );            p.drawRoundRect ( 3, 3, vol.width() - 6, vol.height() - 6,                M * 300 / vol.width(), 99 );            p.end();            vol.setMask( mask );        }        buf.fill( backgroundColor().dark() );        const int offset = int( double( vol.width() * m_newvolume ) / 100 );        bitBlt( &buf, 0, 0, &vol ); // bg        bitBlt( &buf, 0, 0, &pixmapGradient, 0, 0, offset );        p.drawPixmap( r.left(), r.top(), buf );        m_volume = false;    }    QPixmap* star = StarManager::instance()->getStar( m_rating/2, true );    int graphicsHeight = 0;    if( useMoodbar() )    {        QPixmap moodbar          = m_moodbarBundle.moodbar().draw( rect.width(), MOODBAR_HEIGHT );        QRect r( rect );        r.setTop( rect.bottom() - moodbar.height()                  - (m_rating ? star->height() + M : 0) );        graphicsHeight += moodbar.height() + M;        p.drawPixmap( r.left(), r.top(), moodbar );        m_moodbarBundle = MetaBundle();    }    if( m_rating > 0 )    {        QRect r( rect );        //Align to center...        r.setLeft(( rect.left() + rect.width() / 2 ) - star->width() * m_rating / 4 );        r.setTop( rect.bottom() - star->height() );        graphicsHeight += star->height() + M;        bool half = m_rating%2;        if( half )        {            QPixmap* halfStar = StarManager::instance()->getHalfStar( m_rating/2 + 1, true );            p.drawPixmap( r.left() + star->width() * ( m_rating / 2 ), r.top(), *halfStar );            star = StarManager::instance()->getStar( m_rating/2 + 1, true );        }        for( int i = 0; i < m_rating/2; i++ )        {            p.drawPixmap( r.left() + i * star->width(), r.top(), *star );        }        m_rating = 0;    }    rect.setBottom( rect.bottom() - graphicsHeight );    if( m_drawShadow )    {        QPixmap pixmap( rect.size() + QSize(10,10) );        pixmap.fill( Qt::black );        pixmap.setMask( pixmap.createHeuristicMask( true ) );        QPainter p2( &pixmap );        p2.setFont( font() );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -