File indexing completed on 2025-01-05 04:25:41
0001 /**************************************************************************************** 0002 * Copyright (c) 2003-2005 Max Howell <max.howell@methylblue.com> * 0003 * Copyright (c) 2005-2013 Mark Kretschmann <kretschmann@kde.org> * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify it under * 0006 * the terms of the GNU General Public License as published by the Free Software * 0007 * Foundation; either version 2 of the License, or (at your option) any later * 0008 * version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0011 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0012 * PARTICULAR PURPOSE. See the GNU General Pulic License for more details. * 0013 * * 0014 * You should have received a copy of the GNU General Public License along with * 0015 * this program. If not, see <http://www.gnu.org/licenses/>. * 0016 ****************************************************************************************/ 0017 0018 #include "BlockAnalyzer.h" 0019 0020 #include "AnalyzerWorker.h" 0021 #include "BlockRenderer.h" 0022 #include "BlockWorker.h" 0023 #include "PaletteHandler.h" 0024 #include "core/support/Debug.h" 0025 0026 #include <cmath> 0027 0028 #include <QPainter> 0029 #include <QQuickWindow> 0030 #include <QScreen> 0031 #include <QSGTexture> 0032 0033 0034 BlockAnalyzer::BlockAnalyzer( QQuickItem *parent ) 0035 : Analyzer::Base( parent ) 0036 , m_columns( 0 ) //int 0037 , m_rows( 0 ) //int 0038 , m_fadeBarsPixmaps( FADE_SIZE ) //vector<QPixmap> 0039 { 0040 setTextureFollowsItemSize( true ); 0041 setObjectName( "Blocky" ); 0042 0043 m_columnWidth = config().readEntry( "columnWidth", 4 ); 0044 m_fallSpeed = (FallSpeed) config().readEntry( "fallSpeed", (int) Medium ); 0045 m_showFadebars = config().readEntry( "showFadebars", true ); 0046 0047 paletteChange( The::paletteHandler()->palette() ); 0048 connect( The::paletteHandler(), &PaletteHandler::newPalette, this, &BlockAnalyzer::paletteChange ); 0049 connect( this, &QQuickItem::windowChanged, this, &BlockAnalyzer::newWindow ); 0050 } 0051 0052 QQuickFramebufferObject::Renderer* 0053 BlockAnalyzer::createRenderer() const 0054 { 0055 return new BlockRenderer; 0056 } 0057 0058 Analyzer::Worker * BlockAnalyzer::createWorker() const 0059 { 0060 auto worker = new BlockWorker( m_rows, m_columns, m_step, m_showFadebars ); 0061 if( window() ) 0062 worker->setRefreshRate( window()->screen()->refreshRate() ); 0063 connect( worker, &BlockWorker::finished, this, &QQuickFramebufferObject::update, Qt::QueuedConnection ); 0064 connect( this, &BlockAnalyzer::stepChanged, worker, &BlockWorker::setStep, Qt::QueuedConnection ); 0065 connect( this, &BlockAnalyzer::rowsChanged, worker, &BlockWorker::setRows, Qt::QueuedConnection ); 0066 connect( this, &BlockAnalyzer::columnsChanged, worker, &BlockWorker::setColumns, Qt::QueuedConnection ); 0067 connect( this, &BlockAnalyzer::refreshRateChanged, worker, &BlockWorker::setRefreshRate, Qt::QueuedConnection ); 0068 connect( this, &BlockAnalyzer::showFadebarsChanged, worker, &BlockWorker::setShowFadebars, Qt::QueuedConnection ); 0069 return worker; 0070 } 0071 0072 void 0073 BlockAnalyzer::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) 0074 { 0075 QQuickFramebufferObject::geometryChanged( newGeometry, oldGeometry ); 0076 0077 if( !newGeometry.isValid() ) 0078 return; 0079 0080 const int oldRows = m_rows; 0081 0082 // Rounded up so that the last column/line is covered if partially visible 0083 m_columns = std::lround( std::ceil( (double)newGeometry.width() / ( m_columnWidth + 1 ) ) ); 0084 Q_EMIT columnsChanged( m_columns ); 0085 m_rows = std::ceil( (double)newGeometry.height() / ( BLOCK_HEIGHT + 1 ) ); 0086 Q_EMIT rowsChanged( m_rows ); 0087 0088 setScopeSize( m_columns ); 0089 0090 if( m_rows != oldRows ) 0091 { 0092 m_barPixmap = QPixmap( m_columnWidth, m_rows * ( BLOCK_HEIGHT + 1 ) ); 0093 0094 determineStep(); 0095 paletteChange( The::paletteHandler()->palette() ); 0096 } 0097 else 0098 drawBackground( The::paletteHandler()->palette() ); 0099 } 0100 0101 void 0102 BlockAnalyzer::determineStep() 0103 { 0104 // falltime is dependent on rowcount due to our digital resolution (ie we have boxes/blocks of pixels) 0105 0106 const qreal fallTime = 1.0 / pow( 1.5, m_fallSpeed ); // time to fall from top to bottom 0107 m_step = qreal( m_rows ) / fallTime; // the amount of rows to fall per second 0108 Q_EMIT stepChanged( m_step ); 0109 } 0110 0111 void 0112 BlockAnalyzer::paletteChange( const QPalette& palette ) //virtual 0113 { 0114 const QColor bg = palette.color( QPalette::Active, QPalette::Base ); 0115 const QColor abg = palette.color( QPalette::Active, QPalette::AlternateBase ); 0116 const QColor highlight = palette.color( QPalette::Active, QPalette::Highlight ); 0117 0118 m_topBarPixmap = QPixmap( m_columnWidth, BLOCK_HEIGHT ); 0119 m_topBarPixmap.fill( highlight ); 0120 0121 m_barPixmap.fill( QColor( ( highlight.red() + bg.red() ) / 2, ( highlight.green() + bg.green() ) / 2, ( highlight.blue() + bg.blue() ) / 2 ) ); 0122 0123 QPainter p( &m_barPixmap ); 0124 0125 int h, s, v; 0126 palette.color( QPalette::Active, QPalette::Dark ).getHsv( &h, &s, &v ); 0127 const QColor fade = QColor::fromHsv( h + 30, s, v ); 0128 0129 const double dr = fade.red() - abg.red(); 0130 const double dg = fade.green() - abg.green(); 0131 const double db = fade.blue() - abg.blue(); 0132 const int r = abg.red(), g = abg.green(), b = abg.blue(); 0133 0134 // Precalculate all fade-bar pixmaps 0135 for( int y = 0; y < FADE_SIZE; ++y ) 0136 { 0137 m_fadeBarsPixmaps[y] = QPixmap( m_columnWidth, m_rows * ( BLOCK_HEIGHT + 1 ) ); 0138 0139 m_fadeBarsPixmaps[y].fill( palette.color( QPalette::Active, QPalette::Base ) ); 0140 const double Y = 1.0 - ( log10( ( FADE_SIZE ) - y ) / log10( ( FADE_SIZE ) ) ); 0141 QPainter f( &m_fadeBarsPixmaps[y] ); 0142 for( int z = 0; z < m_rows; ++z ) 0143 f.fillRect( 0, 0144 z * ( BLOCK_HEIGHT + 1 ), 0145 m_columnWidth, BLOCK_HEIGHT, 0146 QColor( r + int( dr * Y ), g + int( dg * Y ), b + int( db * Y ) ) ); 0147 } 0148 0149 m_pixmapsChanged = true; 0150 drawBackground( palette ); 0151 } 0152 0153 void 0154 BlockAnalyzer::drawBackground( const QPalette &palette ) 0155 { 0156 const QColor bg = palette.color( QPalette::Active, QPalette::Base ); 0157 const QColor abg = palette.color( QPalette::Active, QPalette::AlternateBase ); 0158 0159 // background gets stretched if it is too big 0160 m_backgroundPixmap = QPixmap( width(), height() ); 0161 m_backgroundPixmap.fill( bg ); 0162 0163 QPainter p( &m_backgroundPixmap ); 0164 for( int x = 0; x < m_columns; ++x ) 0165 for( int y = 0; y < m_rows; ++y ) 0166 p.fillRect( x * ( m_columnWidth + 1 ), y * ( BLOCK_HEIGHT + 1 ), m_columnWidth, BLOCK_HEIGHT, abg ); 0167 0168 m_pixmapsChanged = true; 0169 0170 update(); 0171 } 0172 0173 void 0174 BlockAnalyzer::setFallSpeed( FallSpeed fallSpeed ) 0175 { 0176 DEBUG_BLOCK 0177 0178 debug() << "Fall speed set to:" << fallSpeed; 0179 0180 if( m_fallSpeed == fallSpeed ) 0181 return; 0182 0183 m_fallSpeed = fallSpeed; 0184 config().writeEntry( "fallSpeed", (int) m_fallSpeed ); 0185 Q_EMIT fallSpeedChanged(); 0186 0187 determineStep(); 0188 } 0189 0190 void 0191 BlockAnalyzer::setColumnWidth( int columnWidth ) 0192 { 0193 DEBUG_BLOCK 0194 0195 debug() << "Column width set to:" << columnWidth; 0196 0197 if( columnWidth < 1 ) 0198 { 0199 warning() << "Column width can not be smaller than one!"; 0200 columnWidth = 1; 0201 } 0202 0203 if( m_columnWidth == columnWidth ) 0204 return; 0205 0206 m_columnWidth = columnWidth; 0207 config().writeEntry( "columnWidth", m_columnWidth ); 0208 Q_EMIT columnWidthChanged(); 0209 0210 m_columns = std::lround( std::ceil( (double)width() / ( m_columnWidth + 1 ) ) ); 0211 Q_EMIT columnsChanged( m_columns ); 0212 setScopeSize( m_columns ); 0213 m_barPixmap = QPixmap( m_columnWidth, m_rows * ( BLOCK_HEIGHT + 1 ) ); 0214 paletteChange( The::paletteHandler()->palette() ); 0215 } 0216 0217 void 0218 BlockAnalyzer::setShowFadebars( bool showFadebars ) 0219 { 0220 DEBUG_BLOCK 0221 0222 debug() << "Show fadebars:" << showFadebars; 0223 0224 if( m_showFadebars == showFadebars ) 0225 return; 0226 0227 m_showFadebars = showFadebars; 0228 Q_EMIT showFadebarsChanged( m_showFadebars ); 0229 } 0230 0231 void 0232 BlockAnalyzer::newWindow( QQuickWindow* window ) 0233 { 0234 if( window ) 0235 Q_EMIT refreshRateChanged( window->screen()->refreshRate() ); 0236 }