// (c) 2005 Christian Muehlhaeuser // (c) 2006 Seb Ruiz // License: GNU General Public License V2 #include "amarok.h" #include "amarokconfig.h" #include "app.h" #include "contextbrowser.h" #include "htmlview.h" #include "playlist.h" //appendMedia() #include #include // External CSS opening #include // External CSS opening #include //kapp #include #include //kapp #include // gradient background image #include #include //locate file #include KTempFile *HTMLView::m_bgGradientImage = 0; KTempFile *HTMLView::m_headerGradientImage = 0; KTempFile *HTMLView::m_shadowGradientImage = 0; int HTMLView::m_instances = 0; HTMLView::HTMLView( TQWidget *parentWidget, const char *widgetname, const bool DNDEnabled, const bool JScriptEnabled ) : KHTMLPart( parentWidget, widgetname ) { m_instances++; setJavaEnabled( false ); setPluginsEnabled( false ); setDNDEnabled( DNDEnabled ); setJScriptEnabled( JScriptEnabled ); KActionCollection* ac = actionCollection(); ac->setAutoConnectShortcuts( true ); m_copy = KStdAction::copy( this, TQT_SLOT( copyText() ), ac, "htmlview_copy" ); m_selectAll = KStdAction::selectAll( this, TQT_SLOT( selectAll() ), ac, "htmlview_select_all" ); { KPopupMenu m; m_copy->plug( &m ); m_selectAll->plug( &m ); m_copy->unplug( &m ); m_selectAll->unplug( &m ); } connect( this, TQT_SIGNAL( selectionChanged() ), TQT_SLOT( enableCopyAction() ) ); enableCopyAction(); } HTMLView::~HTMLView() { m_instances--; if ( m_instances < 1 ) { delete m_bgGradientImage; delete m_headerGradientImage; delete m_shadowGradientImage; } } void HTMLView::enableCopyAction() { m_copy->setEnabled( hasSelection() ); } void HTMLView::selectAll() { KHTMLPart::selectAll(); } void HTMLView::copyText() { TQString text = selectedText(); // Copy both to clipboard and X11-selection TQApplication::clipboard()->setText( text, TQClipboard::Clipboard ); TQApplication::clipboard()->setText( text, TQClipboard::Selection ); } void HTMLView::paletteChange() { delete m_bgGradientImage; delete m_headerGradientImage; delete m_shadowGradientImage; m_bgGradientImage = m_headerGradientImage = m_shadowGradientImage = 0; } TQString HTMLView::loadStyleSheet() { TQString themeName = AmarokConfig::contextBrowserStyleSheet().latin1(); const TQString file = kapp->dirs()->findResource( "data","amarok/themes/" + themeName + "/stylesheet.css" ); TQString styleSheet; if ( themeName != "Default" && TQFile::exists( file ) ) { const TQString CSSLocation = kapp->dirs()->findResource( "data","amarok/themes/" + themeName + "/stylesheet.css" ); TQFile ExternalCSS( CSSLocation ); if ( !ExternalCSS.open( IO_ReadOnly ) ) return TQString(); //FIXME: should actually return the default style sheet, then const TQString pxSize = TQString::number( ContextBrowser::instance()->fontMetrics().height() - 4 ); const TQString fontFamily = AmarokConfig::useCustomFonts() ? AmarokConfig::contextBrowserFont().family() : TQApplication::font().family(); const TQString text = ContextBrowser::instance()->colorGroup().text().name(); const TQString link = ContextBrowser::instance()->colorGroup().link().name(); const TQString fg = ContextBrowser::instance()->colorGroup().highlightedText().name(); const TQString bg = ContextBrowser::instance()->colorGroup().highlight().name(); const TQString base = ContextBrowser::instance()->colorGroup().base().name(); const TQColor bgColor = ContextBrowser::instance()->colorGroup().highlight(); TQColor gradientColor = bgColor; //we have to set the color for body due to a KHTML bug //KHTML sets the base color but not the text color styleSheet = TQString( "body { margin: 8px; font-size: %1px; color: %2; background-color: %3; font-family: %4; }" ) .arg( pxSize ) .arg( text ) .arg( AmarokConfig::schemeAmarok() ? fg : TQString(gradientColor.name()) ) .arg( fontFamily ); TQTextStream eCSSts( &ExternalCSS ); TQString tmpCSS = eCSSts.read(); ExternalCSS.close(); tmpCSS.replace( "./", KURL::fromPathOrURL( CSSLocation ).directory( false ) ); tmpCSS.replace( "AMAROK_FONTSIZE-2", pxSize ); tmpCSS.replace( "AMAROK_FONTSIZE", pxSize ); tmpCSS.replace( "AMAROK_FONTSIZE+2", pxSize ); tmpCSS.replace( "AMAROK_FONTFAMILY", fontFamily ); tmpCSS.replace( "AMAROK_TEXTCOLOR", text ); tmpCSS.replace( "AMAROK_LINKCOLOR", link ); tmpCSS.replace( "AMAROK_BGCOLOR", bg ); tmpCSS.replace( "AMAROK_FGCOLOR", fg ); tmpCSS.replace( "AMAROK_BASECOLOR", base ); tmpCSS.replace( "AMAROK_DARKBASECOLOR", ContextBrowser::instance()->colorGroup().base().dark( 120 ).name() ); tmpCSS.replace( "AMAROK_GRADIENTCOLOR", gradientColor.name() ); styleSheet += tmpCSS; } else { int pxSize = ContextBrowser::instance()->fontMetrics().height() - 4; const TQString fontFamily = AmarokConfig::useCustomFonts() ? AmarokConfig::contextBrowserFont().family() : TQApplication::font().family(); const TQString text = ContextBrowser::instance()->colorGroup().text().name(); const TQString link = ContextBrowser::instance()->colorGroup().link().name(); const TQString fg = ContextBrowser::instance()->colorGroup().highlightedText().name(); const TQString bg = ContextBrowser::instance()->colorGroup().highlight().name(); const TQColor baseColor = ContextBrowser::instance()->colorGroup().base(); const TQColor bgColor = ContextBrowser::instance()->colorGroup().highlight(); const TQColor gradientColor = bgColor; if ( !m_bgGradientImage ) { m_bgGradientImage = new KTempFile( locateLocal( "tmp", "gradient" ), ".png", 0600 ); TQImage image = KImageEffect::gradient( TQSize( 600, 1 ), gradientColor, gradientColor.light( 130 ), KImageEffect::PipeCrossGradient ); image.save( m_bgGradientImage->file(), "PNG" ); m_bgGradientImage->close(); } if ( !m_headerGradientImage ) { m_headerGradientImage = new KTempFile( locateLocal( "tmp", "gradient_header" ), ".png", 0600 ); TQImage imageH = KImageEffect::unbalancedGradient( TQSize( 1, 10 ), bgColor, gradientColor.light( 130 ), KImageEffect::VerticalGradient, 100, -100 ); imageH.copy( 0, 1, 1, 9 ).save( m_headerGradientImage->file(), "PNG" ); m_headerGradientImage->close(); } if ( !m_shadowGradientImage ) { m_shadowGradientImage = new KTempFile( locateLocal( "tmp", "gradient_shadow" ), ".png", 0600 ); TQImage imageS = KImageEffect::unbalancedGradient( TQSize( 1, 10 ), baseColor, TQt::gray, KImageEffect::VerticalGradient, 100, -100 ); imageS.save( m_shadowGradientImage->file(), "PNG" ); m_shadowGradientImage->close(); } //unlink the files for us on deletion m_bgGradientImage->setAutoDelete( true ); m_headerGradientImage->setAutoDelete( true ); m_shadowGradientImage->setAutoDelete( true ); //we have to set the color for body due to a KHTML bug //KHTML sets the base color but not the text color styleSheet = TQString( "body { margin: 4px; font-size: %1px; color: %2; background-color: %3; background-image: url( %4 ); background-repeat: repeat; font-family: %5; }" ) .arg( pxSize ) .arg( text ) .arg( AmarokConfig::schemeAmarok() ? fg : TQString(gradientColor.name()) ) .arg( m_bgGradientImage->name() ) .arg( fontFamily ); //text attributes styleSheet += TQString( "h1 { font-size: %1px; }" ).arg( pxSize + 8 ); styleSheet += TQString( "h2 { font-size: %1px; }" ).arg( pxSize + 6 ); styleSheet += TQString( "h3 { font-size: %1px; }" ).arg( pxSize + 4 ); styleSheet += TQString( "h4 { font-size: %1px; }" ).arg( pxSize + 3 ); styleSheet += TQString( "h5 { font-size: %1px; }" ).arg( pxSize + 2 ); styleSheet += TQString( "h6 { font-size: %1px; }" ).arg( pxSize + 1 ); styleSheet += TQString( "a { font-size: %1px; color: %2; }" ).arg( pxSize ).arg( text ); styleSheet += TQString( ".info { display: block; margin-left: 4px; font-weight: normal; }" ); styleSheet += TQString( ".song a { display: block; padding: 1px 2px; font-weight: normal; text-decoration: none; }" ); styleSheet += TQString( ".song a:hover { color: %1; background-color: %2; }" ).arg( fg ).arg( bg ); styleSheet += TQString( ".song-title { font-weight: bold; }" ); styleSheet += TQString( ".song-place { font-size: %1px; font-weight: bold; }" ).arg( pxSize + 3 ); //box: the base container for every block (border hilighted on hover, 'A' without underlining) styleSheet += TQString( ".box { border: solid %1 1px; text-align: left; margin-bottom: 10px; }" ).arg( bg ); styleSheet += TQString( ".box a { text-decoration: none; }" ); styleSheet += TQString( ".box:hover { border: solid %1 1px; }" ).arg( text ); //box contents: header, body, rows and alternate-rows styleSheet += TQString( ".box-header { color: %1; background-color: %2; background-image: url( %4 ); background-repeat: repeat-x; font-size: %3px; font-weight: bold; padding: 1px 0.5em; border-bottom: 1px solid #000; }" ) .arg( fg ) .arg( bg ) .arg( pxSize + 2 ) .arg( m_headerGradientImage->name() ); styleSheet += TQString( ".box-body { padding: 2px; background-color: %1; background-image: url( %2 ); background-repeat: repeat-x; font-size:%3px; }" ) .arg( ContextBrowser::instance()->colorGroup().base().name() ) .arg( m_shadowGradientImage->name() ) .arg( pxSize ); //"Related Artists" related styles styleSheet += TQString( ".box-header-nav { color: %1; background-color: %2; font-size: %3px; font-weight: bold; padding: 1px 0.5em; border-bottom: 1px solid #000; text-align: right; }" ) .arg( fg ) .arg( bg ) .arg( pxSize ); //"Albums by ..." related styles styleSheet += TQString( ".album-header:hover { color: %1; background-color: %2; cursor: pointer; }" ).arg( fg ).arg( bg ); styleSheet += TQString( ".album-header:hover a { color: %1; }" ).arg( fg ); styleSheet += TQString( ".album-body { background-color: %1; border-bottom: solid %2 1px; border-top: solid %3 1px; }" ).arg( ContextBrowser::instance()->colorGroup().base().name() ).arg( bg ).arg( bg ); styleSheet += TQString( ".album-title { font-weight: bold; }" ); styleSheet += TQString( ".album-info { float:right; padding-right:4px; font-size: %1px }" ).arg( pxSize ); styleSheet += TQString( ".album-length { float:right; padding-right:4px; font-size: %1px; clear:right; }" ).arg( pxSize ); styleSheet += TQString( ".album-image { padding-right: 4px; }" ); styleSheet += TQString( ".album-song a { display: block; padding: 1px 2px; font-weight: normal; text-decoration: none; }" ); styleSheet += TQString( ".album-song a:hover { color: %1; background-color: %2; }" ).arg( fg ).arg( bg ); styleSheet += TQString( ".album-song-trackno { font-weight: bold; }" ); styleSheet += TQString( ".disc-separator { color: %1; border-bottom: 1px solid %2; }" ).arg( bg ).arg( bg ); styleSheet += TQString( ".disc-separator a { display: block; padding: 1px 2px; font-weight: normal; text-decoration: none; }" ); styleSheet += TQString( ".disc-separator a:hover { color: %1; background-color: %2; }" ).arg( fg ).arg( bg ); styleSheet += TQString( ".button { width: 100%; }" ); //boxes used to display score (sb: score box) styleSheet += TQString( ".sbtext { text-align: right; padding: 0px 4px; }" ); styleSheet += TQString( ".sbinner { height: 8px; background-color: %1; border: solid %2 1px; }" ) .arg( ContextBrowser::instance()->colorGroup().highlight().name() ) .arg( ContextBrowser::instance()->colorGroup().highlightedText().name() ); styleSheet += TQString( ".sbouter { width: 52px; height: 10px; background-color: %1; border: solid %2 1px; }" ) .arg( ContextBrowser::instance()->colorGroup().base().dark( 120 ).name() ) .arg( ContextBrowser::instance()->colorGroup().highlight().name() ); styleSheet += TQString( ".ratingBox { padding: 0px 4px; }" ); styleSheet += TQString( ".ratingStar { height: 0.9em; }" ); styleSheet += TQString( ".statsBox { border-left: solid %1 1px; }" ) .arg( ContextBrowser::instance()->colorGroup().base().dark( 120 ).name() ); styleSheet += TQString( "#current_box-header-album { font-weight: normal; }" ); styleSheet += TQString( "#current_box-information-td { text-align: right; vertical-align: bottom; padding: 3px; }" ); styleSheet += TQString( "#current_box-largecover-td { text-align: left; width: 100px; padding: 0; vertical-align: bottom; }" ); styleSheet += TQString( "#current_box-largecover-image { padding: 4px; vertical-align: bottom; }" ); styleSheet += TQString( "#wiki_box-body a { color: %1; }" ).arg( link ); styleSheet += TQString( "#wiki_box-body a:hover { text-decoration: underline; }" ); //labels in tag dialog styleSheet += ".label a:hover { font-weight: bold; }"; styleSheet += TQString( ".label.size1 { font-size: %1px; }" ).arg( pxSize ); styleSheet += TQString( ".label.size2 { font-size: %1px; }" ).arg( pxSize + 1 ); styleSheet += TQString( ".label.size3 { font-size: %1px; }" ).arg( pxSize + 2 ); styleSheet += TQString( ".label.size4 { font-size: %1px; }" ).arg( pxSize + 3 ); styleSheet += TQString( ".label.size5 { font-size: %1px; }" ).arg( pxSize + 4); styleSheet += TQString( ".label.size6 { font-size: %1px; }" ).arg( pxSize + 5 ); styleSheet += TQString( ".label.size7 { font-size: %1px; }" ).arg( pxSize + 6 ); styleSheet += TQString( ".label.size8 { font-size: %1px; }" ).arg( pxSize + 7 ); styleSheet += TQString( ".label.size9 { font-size: %1px; }" ).arg( pxSize + 8 ); styleSheet += TQString( ".label.size10 { font-size: %1px; }" ).arg( pxSize + 9 ); } return styleSheet; } void HTMLView::set( const TQString& data ) { begin(); setUserStyleSheet( loadStyleSheet() ); write( data ); end(); } void HTMLView::openURLRequest( const KURL &url ) { // here, http urls are streams. For webpages we use externalurl // NOTE there have been no links to streams! http now used for wiki tab. if ( url.protocol() == "file" ) Playlist::instance()->insertMedia( url, Playlist::DefaultOptions ); } #include "htmlview.moc"