📄 osd.cpp
字号:
p2.setPen( Qt::white ); p2.setBrush( Qt::white ); p2.drawText( QRect(QPoint(5,5), rect.size()), align , m_text ); p2.end(); p.drawImage( rect.topLeft() - QPoint(5,5), ShadowEngine::makeShadow( pixmap, shadowColor ) ); } p.setPen( foregroundColor() ); p.setFont( font() ); p.drawText( rect, align, m_text ); p.end();}boolOSDWidget::event( QEvent *e ){ switch( e->type() ) { case QEvent::ApplicationPaletteChange: if( !AmarokConfig::osdUseCustomColors() ) unsetColors(); //use new palette's colours return true; case QEvent::Paint: bitBlt( this, 0, 0, &m_buffer ); return true; default: return QWidget::event( e ); }}voidOSDWidget::mousePressEvent( QMouseEvent* ){ hide();}voidOSDWidget::unsetColors(){ const QColorGroup c = QApplication::palette().active(); setPaletteForegroundColor( c.highlightedText() ); setPaletteBackgroundColor( c.highlight() );}voidOSDWidget::setScreen( int screen ){ const int n = QApplication::desktop()->numScreens(); m_screen = (screen >= n) ? n-1 : screen;}boolOSDWidget::useMoodbar( void ){ return (m_moodbarBundle.moodbar().state() == Moodbar::Loaded && AmarokConfig::showMoodbar() );}////// OSDPreviewWidget below /////////////////////#include <kcursor.h>#include <kiconloader.h>#include <klocale.h>namespace Amarok{ QImage icon() { return QImage( KIconLoader().iconPath( "amarok", -KIcon::SizeHuge ) ); }}OSDPreviewWidget::OSDPreviewWidget( QWidget *parent ) : OSDWidget( parent, "osdpreview" ) , m_dragging( false ){ m_text = i18n( "OSD Preview - drag to reposition" ); m_duration = 0; m_cover = Amarok::icon();}void OSDPreviewWidget::mousePressEvent( QMouseEvent *event ){ m_dragOffset = event->pos(); if( event->button() == LeftButton && !m_dragging ) { grabMouse( KCursor::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 ); }}////// Amarok::OSD below /////////////////////#include "enginecontroller.h"#include "metabundle.h"#include <qregexp.h>Amarok::OSD::OSD(): OSDWidget( 0 ){ connect( CollectionDB::instance(), SIGNAL( coverChanged( const QString&, const QString& ) ), this, SLOT( slotCoverChanged( const QString&, const QString& ) ) ); connect( CollectionDB::instance(), SIGNAL( imageFetched( const QString& ) ), this, SLOT( slotImageChanged( const QString& ) ) );}voidAmarok::OSD::show( const MetaBundle &bundle ) //slot{#ifdef Q_WS_X11 QString text = ""; if( bundle.url().isEmpty() ) text = i18n( "No track playing" ); else { QValueVector<QString> tags; tags.append(bundle.prettyTitle()); for( int i = 0; i < PlaylistItem::NUM_COLUMNS; ++i ) tags.append(bundle.prettyText( i )); if( bundle.length() <= 0 ) tags[PlaylistItem::Length+1] = QString::null; if( AmarokConfig::osdUsePlaylistColumns() ) { QString tag; QValueVector<int> availableTags; //eg, ones that aren't empty static const QValueList<int> parens = //display these in parentheses QValueList<int>() << PlaylistItem::PlayCount << PlaylistItem::Year << PlaylistItem::Comment << PlaylistItem::Genre << PlaylistItem::Length << PlaylistItem::Bitrate << PlaylistItem::LastPlayed << PlaylistItem::Score << PlaylistItem::Filesize; OSDWidget::setMoodbar(); OSDWidget::setRating( 0 ); for( int i = 0, n = Playlist::instance()->numVisibleColumns(); i < n; ++i ) { const int column = Playlist::instance()->mapToLogicalColumn( i ); if( !tags.at( column + 1 ).isEmpty() && column != PlaylistItem::Rating ) availableTags.append(column); if( column == PlaylistItem::Rating ) OSDWidget::setRating( bundle.rating() ); else if( column == PlaylistItem::Mood ) OSDWidget::setMoodbar( bundle ); } for( int n = availableTags.count(), i = 0; i < n; ++i ) { const int column = availableTags.at( i ); QString append = ( i == 0 ) ? "" : ( n > 1 && i == n / 2 ) ? "\n" : ( parens.contains( column ) || parens.contains( availableTags.at( i - 1 ) ) ) ? " " : i18n(" - "); append += ( parens.contains( column ) ? "(%1)" : "%1" ); text += append.arg( tags.at( column + 1 ) ); } } else { QMap<QString, QString> args; args["prettytitle"] = bundle.prettyTitle(); for( int i = 0; i < PlaylistItem::NUM_COLUMNS; ++i ) args[bundle.exactColumnName( i ).lower()] = bundle.prettyText( i ); if( bundle.length() <= 0 ) args["length"] = QString::null; uint time=EngineController::instance()->engine()->position(); uint sec=(time/1000)%60; //is there a better way to calculate the time? time /= 1000; uint min=(time/60)%60; time /= 60; uint hour=(time/60)%60; QString timeformat=""; if(hour!=0) { timeformat += QString::number(hour); timeformat +=":"; } timeformat +=QString::number(min); timeformat +=":"; if(sec<10) timeformat +="0"; timeformat +=QString::number(sec); args["elapsed"]=timeformat; QStringx osd = AmarokConfig::osdText(); // hacky, but works... if( osd.contains( "%rating" ) ) OSDWidget::setRating( AmarokConfig::useRatings() ? bundle.rating() : 0 ); else OSDWidget::setRating( 0 ); osd.replace( "%rating", "" ); if( osd.contains( "%moodbar" ) && AmarokConfig::showMoodbar() ) OSDWidget::setMoodbar( bundle ); osd.replace( "%moodbar", "" ); text = osd.namedOptArgs( args ); // KDE 3.3 rejects \n in the .kcfg file, and KConfig turns \n into \\n, so... text.replace( "\\n", "\n" ); } if ( AmarokConfig::osdCover() ) { //avoid showing the generic cover. we can overwrite this by passing an arg. //get large cover for scaling if big cover needed QString location = QString::null; if( bundle.podcastBundle() ) location = CollectionDB::instance()->podcastImage( bundle, false, 0 ); else location = CollectionDB::instance()->albumImage( bundle, false, 0 ); if ( location.find( "nocover" ) != -1 ) setImage( Amarok::icon() ); else setImage( location ); } text = text.stripWhiteSpace(); } if( text.isEmpty() ) text = MetaBundle::prettyTitle( bundle.url().fileName() ).stripWhiteSpace(); if( text.startsWith( "- " ) ) //When we only have a title tag, _something_ prepends a fucking hyphen. Remove that. text = text.mid( 2 ); if( text.isEmpty() ) //still text = i18n("No information available for this track"); OSDWidget::show( text );#else Q_UNUSED( bundle );#endif}voidAmarok::OSD::applySettings(){ setAlignment( static_cast<OSDWidget::Alignment>( AmarokConfig::osdAlignment() ) ); setDuration( AmarokConfig::osdDuration() );#ifdef Q_WS_X11 setEnabled( AmarokConfig::osdEnabled() );#else setEnabled( false );#endif setOffset( AmarokConfig::osdYOffset() ); setScreen( AmarokConfig::osdScreen() ); setFont( AmarokConfig::osdFont() ); setDrawShadow( AmarokConfig::osdDrawShadow() ); setTranslucency( AmarokConfig::osdUseFakeTranslucency() ); if( AmarokConfig::osdUseCustomColors() ) { setTextColor( AmarokConfig::osdTextColor() ); setBackgroundColor( AmarokConfig::osdBackgroundColor() ); } else unsetColors();}voidAmarok::OSD::forceToggleOSD(){#ifdef Q_WS_X11 if ( !isShown() ) { const bool b = isEnabled(); setEnabled( true ); show( EngineController::instance()->bundle() ); setEnabled( b ); } else hide();#endif}voidAmarok::OSD::slotCoverChanged( const QString &artist, const QString &album ){ if( AmarokConfig::osdCover() && artist == EngineController::instance()->bundle().artist() && album == EngineController::instance()->bundle().album() ) { QString location = CollectionDB::instance()->albumImage( artist, album, false, 0 ); if( location.find( "nocover" ) != -1 ) setImage( Amarok::icon() ); else setImage( location ); }}voidAmarok::OSD::slotImageChanged( const QString &remoteURL ){ QString url = EngineController::instance()->bundle().url().url(); PodcastEpisodeBundle peb; if( CollectionDB::instance()->getPodcastEpisodeBundle( url, &peb ) ) { PodcastChannelBundle pcb; if( CollectionDB::instance()->getPodcastChannelBundle( peb.parent().url(), &pcb ) ) { if( pcb.imageURL().url() == remoteURL ) { QString location = CollectionDB::instance()->podcastImage( remoteURL, false, 0 ); if( location == CollectionDB::instance()->notAvailCover( false, 0 ) ) setImage( Amarok::icon() ); else setImage( location ); } } }}/* 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 Steet, 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 ) { QImage result; 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.convertToImage().convertDepth( 32 ); result.create( w, h, 32 ); result.fill( 0 ); // fill with black result.setAlphaBuffer( true ); 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"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -