2022-08-26 18:31:27 +08:00
# include "jkqtpexampleapplication.h"
# include <QElapsedTimer>
# include <QCommandLineParser>
# include <QCommandLineOption>
# include <QWindow>
# include <QWidget>
2023-08-14 20:26:13 +08:00
# include <QMessageBox>
2022-08-26 18:31:27 +08:00
# include "jkqtplotter/jkqtplotter.h"
2022-08-29 04:48:14 +08:00
JKQTPExampleApplication : : JKQTPExampleApplication ( int & argc , char * * argv , bool _waitForScreenshotReady ) :
2022-08-26 18:31:27 +08:00
QApplication ( argc , argv ) ,
2022-08-29 04:48:14 +08:00
waitForScreenshotReady ( _waitForScreenshotReady ) ,
readyForScreenshot ( ! _waitForScreenshotReady ) ,
2022-08-26 18:31:27 +08:00
saveScreenshot ( false ) ,
saveSmallScreenshot ( false ) ,
saveScreenshotPlot ( false ) ,
saveSmallScreenshotPlot ( false ) ,
2022-08-27 03:23:19 +08:00
scaleDownFromHighDPI ( false ) ,
2022-09-26 08:07:07 +08:00
iterateFunctorSteps ( false ) ,
iterateFunctorStepsSupressInitial ( false ) ,
2022-08-26 18:31:27 +08:00
screenshotBasename ( " screenshot " )
{
screenshotDir = QDir : : current ( ) ;
2022-09-26 08:07:07 +08:00
//for (int i=0; i<argc; i++) std::cout<<" argv["<<i<<"]="<<argv[i]<<"\n";
2022-08-26 18:31:27 +08:00
}
JKQTPExampleApplication : : ~ JKQTPExampleApplication ( )
{
}
2022-09-26 08:07:07 +08:00
void JKQTPExampleApplication : : addExportStepFunctor ( const std : : function < void ( ) > & f )
{
2023-08-14 19:50:21 +08:00
functors < < Data ( f ) ;
}
void JKQTPExampleApplication : : addExportStepPlot ( JKQTPlotter * plot )
{
functors < < Data ( plot ) ;
}
void JKQTPExampleApplication : : addExportStepPlotFunctor ( const std : : function < JKQTPlotter * ( ) > & fplot )
{
functors < < Data ( fplot ) ;
2022-09-26 08:07:07 +08:00
}
2022-08-26 18:31:27 +08:00
void JKQTPExampleApplication : : readCmdLine ( ) {
QCommandLineParser parser ;
parser . setApplicationDescription ( QString ( " JKQTPlotter example program '%1' " ) . arg ( applicationName ( ) ) ) ;
parser . addHelpOption ( ) ;
parser . addVersionOption ( ) ;
QCommandLineOption outputDirectoryOption ( " screenshotdir " , " write results into this directory. " , " outputdir " , applicationDirPath ( ) ) ;
parser . addOption ( outputDirectoryOption ) ;
QCommandLineOption basenameOption ( " screenshotbasename " , " basename for screenshots. " , " basename " , QFileInfo ( applicationFilePath ( ) ) . baseName ( ) ) ;
parser . addOption ( basenameOption ) ;
QCommandLineOption screenshotOption ( QStringList ( ) < < " screenshot " , " save screenshot(s) of the window(s). " ) ;
parser . addOption ( screenshotOption ) ;
QCommandLineOption smallscreenshotOption ( QStringList ( ) < < " smallscreenshot " , " save small screenshot(s) of the window(s). " ) ;
parser . addOption ( smallscreenshotOption ) ;
QCommandLineOption screenshotPlotOption ( QStringList ( ) < < " screenshotplot " , " save screenshot(s) of the plot(s). " ) ;
parser . addOption ( screenshotPlotOption ) ;
QCommandLineOption smallscreenshotPlotOption ( QStringList ( ) < < " smallscreenshotplot " , " save screenshot(s) of the plot(s). " ) ;
parser . addOption ( smallscreenshotPlotOption ) ;
2022-08-27 03:23:19 +08:00
QCommandLineOption scaleDownFromHighDPIOption ( QStringList ( ) < < " scalescreenshotdownfromhighdpi " , " if on high-dpi device, rescale to standard size. " ) ;
parser . addOption ( scaleDownFromHighDPIOption ) ;
QCommandLineOption disablehighdpiOption ( QStringList ( ) < < " disablehighdpi " , " idisable high-dpi support. " ) ;
parser . addOption ( disablehighdpiOption ) ;
2022-09-26 08:07:07 +08:00
QCommandLineOption iterateFunctorStepsOption ( QStringList ( ) < < " iteratefunctorsteps " , " iterate over steps defined by addExportStepFunctor() in code. " ) ;
parser . addOption ( iterateFunctorStepsOption ) ;
QCommandLineOption iterateFunctorStepsSupressInitialOption ( QStringList ( ) < < " iteratefunctorsteps_suppressinitial " , " iterate over steps defined by addExportStepFunctor() in code. " ) ;
parser . addOption ( iterateFunctorStepsSupressInitialOption ) ;
2022-08-26 18:31:27 +08:00
2024-01-05 07:13:39 +08:00
//parser.process(*this);
parser . parse ( arguments ( ) ) ;
2022-08-26 18:31:27 +08:00
screenshotDir = QDir ( parser . value ( outputDirectoryOption ) ) ;
2022-08-27 03:23:19 +08:00
screenshotBasename = parser . value ( basenameOption ) . split ( ' , ' ) ;
2022-08-26 18:31:27 +08:00
saveScreenshot = parser . isSet ( screenshotOption ) ;
saveSmallScreenshot = parser . isSet ( smallscreenshotOption ) ;
saveScreenshotPlot = parser . isSet ( screenshotPlotOption ) ;
saveSmallScreenshotPlot = parser . isSet ( smallscreenshotPlotOption ) ;
2022-08-27 03:23:19 +08:00
scaleDownFromHighDPI = parser . isSet ( scaleDownFromHighDPIOption ) ;
2022-09-26 08:07:07 +08:00
iterateFunctorSteps = parser . isSet ( iterateFunctorStepsOption ) ;
iterateFunctorStepsSupressInitial = parser . isSet ( iterateFunctorStepsSupressInitialOption ) ;
2022-08-26 18:31:27 +08:00
}
QRect JKQTPExampleApplication : : getBoundsWithoutColor ( QImage qImage , const QColor & exclusionColor )
{
QRect ofTheKing ;
int maxX = 0 ; int minX = qImage . width ( ) ;
int maxY = 0 ; int minY = qImage . height ( ) ;
for ( int x = 0 ; x < qImage . width ( ) ; x + + )
for ( int y = 0 ; y < qImage . height ( ) ; y + + )
if ( QColor : : fromRgb ( qImage . pixel ( x , y ) ) ! = exclusionColor )
{
if ( x < minX ) minX = x ;
if ( x > maxX ) maxX = x ;
if ( y < minY ) minY = y ;
if ( y > maxY ) maxY = y ;
}
if ( minX > maxX | | minY > maxY )
ofTheKing = QRect ( ) ;
else
ofTheKing . setCoords ( minX , minY , maxX + 1 , maxY + 1 ) ;
return ofTheKing ;
2023-08-14 19:50:21 +08:00
}
void JKQTPExampleApplication : : saveWidget ( QWidget * w , int iVisible ) {
JKQTPlotter * plot = dynamic_cast < JKQTPlotter * > ( w ) ;
QString bn = screenshotBasename . value ( iVisible , screenshotBasename . value ( 0 ) ) ;
if ( iVisible > 0 & & screenshotBasename . value ( iVisible , " " ) = = " " ) {
bn + = QString ( " _win%1 " ) . arg ( iVisible , 2 , 10 , QLatin1Char ( ' 0 ' ) ) ;
}
2023-08-14 20:26:13 +08:00
//QMessageBox::information(nullptr, "DEBUG", bn+": w="+QString::number(reinterpret_cast<uint64_t>(w))+", plot="+QString::number(reinterpret_cast<uint64_t>(plot)));
2023-08-14 19:50:21 +08:00
if ( w ) {
QPixmap pix_win = w - > grab ( ) ;
/*QPixmap pix;
if ( screenshotIncludeWindowTitle ) {
pix = w - > screen ( ) - > grabWindow ( 0 , w - > frameGeometry ( ) . x ( ) , w - > frameGeometry ( ) . y ( ) , w - > frameGeometry ( ) . width ( ) , w - > frameGeometry ( ) . height ( ) ) ;
} else {
pix = pix_win ;
} */
if ( saveScreenshot | | ( saveScreenshotPlot & & ! plot ) ) {
if ( scaleDownFromHighDPI & & pix_win . devicePixelRatio ( ) > 1.0 ) {
pix_win . scaled ( ( QSizeF ( pix_win . size ( ) ) / pix_win . devicePixelRatio ( ) ) . toSize ( ) ) . save ( screenshotDir . absoluteFilePath ( bn + " .png " ) ) ;
} else {
pix_win . save ( screenshotDir . absoluteFilePath ( bn + " .png " ) ) ;
}
}
if ( saveSmallScreenshot | | ( saveSmallScreenshotPlot & & ! plot ) ) {
QPixmap img = pix_win . scaledToWidth ( 150 , Qt : : SmoothTransformation ) ;
img . save ( screenshotDir . absoluteFilePath ( bn + " _small.png " ) ) ;
}
}
if ( plot ) {
QString bnp = bn + " _plot " ;
QImage gr = plot - > grabPixelImage ( ) ;
if ( saveScreenshotPlot ) {
QString fn = bn + " .png " ;
if ( saveScreenshot ) fn = bnp + " .png " ;
if ( scaleDownFromHighDPI & & gr . devicePixelRatio ( ) > 1.0 ) {
gr . scaled ( ( QSizeF ( gr . size ( ) ) / gr . devicePixelRatio ( ) ) . toSize ( ) ) . save ( screenshotDir . absoluteFilePath ( fn ) ) ;
} else {
gr . save ( screenshotDir . absoluteFilePath ( fn ) ) ;
}
}
if ( saveSmallScreenshotPlot ) {
QString fn = bn + " _small.png " ;
if ( saveSmallScreenshot ) fn = bnp + " _small.png " ;
QImage img = gr . scaledToWidth ( 150 , Qt : : SmoothTransformation ) ;
img . save ( screenshotDir . absoluteFilePath ( fn ) ) ;
}
}
}
2022-08-26 18:31:27 +08:00
int JKQTPExampleApplication : : exec ( )
{
readCmdLine ( ) ;
2022-09-26 08:07:07 +08:00
QList < JKQTPlotter * > plotterList ;
auto checkPlottersResizeDone = [ plotterList ] ( ) {
if ( plotterList . isEmpty ( ) ) return true ;
for ( JKQTPlotter * p : plotterList ) {
if ( p - > isResizeTimerRunning ( ) ) return false ;
}
return true ;
} ;
for ( QWidget * w : allWidgets ( ) ) {
JKQTPlotter * plot = dynamic_cast < JKQTPlotter * > ( w ) ;
if ( plot ) plotterList < < plot ;
}
QWidgetList widgets = topLevelWidgets ( ) ;
std : : sort ( widgets . begin ( ) , widgets . end ( ) , [ ] ( const QWidget * a , const QWidget * b ) {
if ( a & & b ) return a - > windowTitle ( ) . toLower ( ) < b - > windowTitle ( ) . toLower ( ) ;
if ( a ) return true ;
if ( b ) return false ;
return a < b ;
} ) ;
2023-08-14 19:50:21 +08:00
2022-09-26 08:07:07 +08:00
if ( iterateFunctorSteps ) {
2023-08-14 19:50:21 +08:00
QVector < Data > localfunctors = functors ;
if ( ! iterateFunctorStepsSupressInitial ) localfunctors . prepend ( Data ( [ ] ( ) { } ) ) ;
2022-09-26 08:07:07 +08:00
int iVisible = 0 ;
//std::cout<<localfunctors.size()<<" functors\n";
for ( auto & f : localfunctors ) {
//std::cout<<"iVisible="<<iVisible<<" f="<<std::boolalpha<<static_cast<bool>(f)<<"\n";
2023-08-14 19:50:21 +08:00
QWidgetList widgets_local = widgets ;
switch ( f . type ) {
case Data : : FunctorType :
if ( f . f ) f . f ( ) ;
break ;
case Data : : PlotterType :
widgets_local . clear ( ) ;
if ( f . p ) widgets_local < < f . p ;
break ;
case Data : : PlotterFunctorType :
widgets_local . clear ( ) ;
if ( f . plotf ) widgets_local < < f . plotf ( ) ;
break ;
}
2022-09-26 08:07:07 +08:00
//JKQTPlotter::setGlobalResizeDelay(10);
QElapsedTimer timer ;
timer . start ( ) ;
while ( timer . elapsed ( ) < JKQTPlotter : : getGlobalResizeDelay ( ) * 3 / 2 | | ! readyForScreenshot | | ! checkPlottersResizeDone ( ) ) {
QApplication : : processEvents ( ) ;
QApplication : : processEvents ( ) ;
}
timer . start ( ) ;
while ( timer . elapsed ( ) < 50 ) {
QApplication : : processEvents ( ) ;
QApplication : : processEvents ( ) ;
}
2023-08-14 19:50:21 +08:00
for ( int i = 0 ; i < widgets_local . size ( ) ; i + + ) {
QWidget * w = widgets_local [ i ] ;
2022-09-26 08:07:07 +08:00
if ( w - > isVisible ( ) ) {
saveWidget ( w , iVisible ) ;
2022-11-01 03:34:01 +08:00
iVisible + + ;
2022-09-26 08:07:07 +08:00
}
}
2022-08-29 04:48:14 +08:00
}
2022-09-26 08:07:07 +08:00
return 0 ;
} else if ( saveScreenshot | | saveSmallScreenshot | | saveScreenshotPlot | | saveSmallScreenshotPlot ) {
//std::cout<<"non-functor-mode\n";
2022-08-29 04:48:14 +08:00
//JKQTPlotter::setGlobalResizeDelay(10);
2022-08-26 18:31:27 +08:00
QElapsedTimer timer ;
timer . start ( ) ;
2022-08-29 04:48:14 +08:00
while ( timer . elapsed ( ) < JKQTPlotter : : getGlobalResizeDelay ( ) * 3 / 2 | | ! readyForScreenshot | | ! checkPlottersResizeDone ( ) ) {
QApplication : : processEvents ( ) ;
QApplication : : processEvents ( ) ;
}
timer . start ( ) ;
while ( timer . elapsed ( ) < 50 ) {
QApplication : : processEvents ( ) ;
2022-08-26 18:31:27 +08:00
QApplication : : processEvents ( ) ;
}
int iVisible = 0 ;
for ( int i = 0 ; i < widgets . size ( ) ; i + + ) {
QWidget * w = widgets [ i ] ;
if ( w - > isVisible ( ) ) {
2022-09-26 08:07:07 +08:00
saveWidget ( w , iVisible ) ;
2022-08-26 18:31:27 +08:00
iVisible + + ;
}
2022-09-26 08:07:07 +08:00
2022-08-26 18:31:27 +08:00
}
return 0 ;
} else {
return QApplication : : exec ( ) ;
}
}
2022-08-29 04:48:14 +08:00
void JKQTPExampleApplication : : notifyReadyForScreenshot ( )
{
readyForScreenshot = true ;
}