|
|
|
/*
|
|
|
|
**************************************************************************
|
|
|
|
description
|
|
|
|
--------------------
|
|
|
|
copyright : (C) 2001-2002 by Andreas Zehender
|
|
|
|
email : zehender@kde.org
|
|
|
|
**************************************************************************
|
|
|
|
|
|
|
|
**************************************************************************
|
|
|
|
* *
|
|
|
|
* 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. *
|
|
|
|
* *
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
#include "pmpovraywidget.h"
|
|
|
|
#include "pmpovrayrenderwidget.h"
|
|
|
|
#include "pmpovrayoutputwidget.h"
|
|
|
|
#include "pmshell.h"
|
|
|
|
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdemessagebox.h>
|
|
|
|
#include <kimageio.h>
|
|
|
|
#include <tdefiledialog.h>
|
|
|
|
#include <tdetempfile.h>
|
|
|
|
#include <tdeio/netaccess.h>
|
|
|
|
#include <tdeglobalsettings.h>
|
|
|
|
#include <kpushbutton.h>
|
|
|
|
#include <kstdguiitem.h>
|
|
|
|
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqprogressbar.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqscrollview.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <tqapplication.h>
|
|
|
|
|
|
|
|
const int timerIntervall = 1000;
|
|
|
|
bool PMPovrayWidget::s_imageFormatsRegistered = false;
|
|
|
|
|
|
|
|
PMPovrayWidget::PMPovrayWidget( TQWidget* parent, const char* name )
|
|
|
|
: KDialog( parent, name )
|
|
|
|
{
|
|
|
|
TQVBoxLayout* topLayout = new TQVBoxLayout( this, KDialog::marginHint( ), KDialog::spacingHint( ) );
|
|
|
|
topLayout->addStretch( );
|
|
|
|
|
|
|
|
TQHBoxLayout* renderLayout = new TQHBoxLayout( );
|
|
|
|
topLayout->addLayout( renderLayout, 2 );
|
|
|
|
m_pScrollView = new TQScrollView( this );
|
|
|
|
m_pScrollView->setBackgroundMode( PaletteBase );
|
|
|
|
renderLayout->addWidget( m_pScrollView, 2 );
|
|
|
|
m_pRenderWidget = new PMPovrayRenderWidget( m_pScrollView->viewport( ) );
|
|
|
|
m_pRenderWidget->setFixedSize( 200, 200 );
|
|
|
|
m_pScrollView->addChild( m_pRenderWidget );
|
|
|
|
topLayout->addStretch( );
|
|
|
|
|
|
|
|
TQHBoxLayout* progressLayout = new TQHBoxLayout( topLayout );
|
|
|
|
m_pProgressBar = new TQProgressBar( this );
|
|
|
|
m_pProgressBar->hide( );
|
|
|
|
progressLayout->addWidget( m_pProgressBar, 1 );
|
|
|
|
m_pProgressLabel = new TQLabel( this );
|
|
|
|
progressLayout->addWidget( m_pProgressLabel, 2 );
|
|
|
|
|
|
|
|
TQHBoxLayout* buttonLayout = new TQHBoxLayout( topLayout );
|
|
|
|
m_pStopButton = new TQPushButton( i18n( "Stop" ), this );
|
|
|
|
m_pStopButton->setEnabled( false );
|
|
|
|
buttonLayout->addWidget( m_pStopButton );
|
|
|
|
m_pSuspendButton = new TQPushButton( i18n( "Suspend" ), this );
|
|
|
|
m_pSuspendButton->setEnabled( false );
|
|
|
|
buttonLayout->addWidget( m_pSuspendButton );
|
|
|
|
m_pResumeButton = new TQPushButton( i18n( "Resume" ), this );
|
|
|
|
m_pResumeButton->setEnabled( false );
|
|
|
|
buttonLayout->addWidget( m_pResumeButton );
|
|
|
|
buttonLayout->addStretch( 1 );
|
|
|
|
m_pPovrayOutputButton = new TQPushButton( i18n( "Povray Output" ), this );
|
|
|
|
buttonLayout->addWidget( m_pPovrayOutputButton );
|
|
|
|
|
|
|
|
buttonLayout = new TQHBoxLayout( topLayout );
|
|
|
|
m_pSaveButton = new KPushButton( KStdGuiItem::saveAs(), this );
|
|
|
|
m_pSaveButton->setEnabled( false );
|
|
|
|
buttonLayout->addWidget( m_pSaveButton );
|
|
|
|
buttonLayout->addStretch( 1 );
|
|
|
|
TQPushButton* closeButton = new KPushButton( KStdGuiItem::close(), this );
|
|
|
|
buttonLayout->addWidget( closeButton );
|
|
|
|
|
|
|
|
connect( m_pRenderWidget, TQ_SIGNAL( finished( int ) ),
|
|
|
|
TQ_SLOT( slotRenderingFinished( int ) ) );
|
|
|
|
connect( m_pRenderWidget, TQ_SIGNAL( progress( int ) ),
|
|
|
|
TQ_SLOT( slotProgress( int ) ) );
|
|
|
|
connect( m_pRenderWidget, TQ_SIGNAL( lineFinished( int ) ),
|
|
|
|
TQ_SLOT( slotLineFinished( int ) ) );
|
|
|
|
|
|
|
|
connect( m_pStopButton, TQ_SIGNAL( clicked( ) ), TQ_SLOT( slotStop( ) ) );
|
|
|
|
connect( m_pSuspendButton, TQ_SIGNAL( clicked( ) ), TQ_SLOT( slotSuspend( ) ) );
|
|
|
|
connect( m_pResumeButton, TQ_SIGNAL( clicked( ) ), TQ_SLOT( slotResume( ) ) );
|
|
|
|
connect( m_pSaveButton, TQ_SIGNAL( clicked( ) ), TQ_SLOT( slotSave( ) ) );
|
|
|
|
connect( closeButton, TQ_SIGNAL( clicked( ) ), TQ_SLOT( slotClose( ) ) );
|
|
|
|
connect( m_pPovrayOutputButton, TQ_SIGNAL( clicked( ) ),
|
|
|
|
TQ_SLOT( slotPovrayOutput( ) ) );
|
|
|
|
|
|
|
|
m_bRunning = false;
|
|
|
|
m_pProgressTimer = new TQTimer( this );
|
|
|
|
connect( m_pProgressTimer, TQ_SIGNAL( timeout( ) ),
|
|
|
|
TQ_SLOT( slotUpdateSpeed( ) ) );
|
|
|
|
|
|
|
|
setCaption( i18n( "Render Window" ) );
|
|
|
|
|
|
|
|
m_height = m_width = 0;
|
|
|
|
m_stopped = false;
|
|
|
|
|
|
|
|
m_pPovrayOutputWidget = new PMPovrayOutputWidget( );
|
|
|
|
connect( m_pRenderWidget, TQ_SIGNAL( povrayMessage( const TQString& ) ),
|
|
|
|
m_pPovrayOutputWidget, TQ_SLOT( slotText( const TQString& ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
PMPovrayWidget::~PMPovrayWidget( )
|
|
|
|
{
|
|
|
|
delete m_pPovrayOutputWidget;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool PMPovrayWidget::render( const TQByteArray& scene, const PMRenderMode& m,
|
|
|
|
const KURL& documentURL )
|
|
|
|
{
|
|
|
|
bool updateSize = ( m_height != m.height( ) ) || ( m_width != m.width( ) );
|
|
|
|
m_height = m.height( );
|
|
|
|
m_width = m.width( );
|
|
|
|
m_bRunning = false;
|
|
|
|
m_pPovrayOutputWidget->slotClear( );
|
|
|
|
m_stopped = false;
|
|
|
|
|
|
|
|
m_pRenderWidget->setFixedSize( m_width, m_height );
|
|
|
|
TQSize maxSize( m_width + m_pScrollView->frameWidth( ) * 2,
|
|
|
|
m_height + m_pScrollView->frameWidth( ) * 2 );
|
|
|
|
m_pScrollView->setMaximumSize( maxSize );
|
|
|
|
|
|
|
|
if( updateSize )
|
|
|
|
{
|
|
|
|
int w, h;
|
|
|
|
|
|
|
|
w = maxSize.width( ) + KDialog::spacingHint( ) * 2;
|
|
|
|
h = maxSize.height( ) + m_pSaveButton->sizeHint( ).height( ) * 2
|
|
|
|
+ KDialog::spacingHint( ) * 6;
|
|
|
|
if( m_pProgressLabel->sizeHint( ).height( )
|
|
|
|
> m_pProgressBar->sizeHint( ).height( ) )
|
|
|
|
h += m_pProgressLabel->sizeHint( ).height( );
|
|
|
|
else
|
|
|
|
h += m_pProgressBar->sizeHint( ).height( );
|
|
|
|
|
|
|
|
w += 16;
|
|
|
|
h += 16;
|
|
|
|
|
|
|
|
#if ( ( TDE_VERSION_MAJOR == 3 ) && ( TDE_VERSION_MINOR <= 1 ) )
|
|
|
|
TQWidget* dw = TQApplication::desktop( );
|
|
|
|
if( w > dw->width( ) )
|
|
|
|
w = dw->width( );
|
|
|
|
if( h > dw->height( ) )
|
|
|
|
h = dw->height( );
|
|
|
|
#else
|
|
|
|
TQRect dw = TDEGlobalSettings::desktopGeometry(this);
|
|
|
|
if( w > dw.width() )
|
|
|
|
w = dw.width();
|
|
|
|
if( h > dw.height() )
|
|
|
|
h = dw.height();
|
|
|
|
#endif
|
|
|
|
resize( w, h );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_pRenderWidget->render( scene, m, documentURL ) )
|
|
|
|
{
|
|
|
|
m_bRunning = true;
|
|
|
|
m_pProgressBar->setProgress( 0 );
|
|
|
|
m_pProgressBar->show( );
|
|
|
|
m_pProgressLabel->setText( i18n( "running" ) );
|
|
|
|
m_pStopButton->setEnabled( true );
|
|
|
|
m_pSuspendButton->setEnabled( true );
|
|
|
|
m_pResumeButton->setEnabled( false );
|
|
|
|
m_pSaveButton->setEnabled( false );
|
|
|
|
|
|
|
|
m_lastSpeedTime = TQTime( );
|
|
|
|
m_pProgressTimer->start( timerIntervall, true );
|
|
|
|
m_speedInfo = false;
|
|
|
|
m_speed = 0;
|
|
|
|
m_line = 0;
|
|
|
|
m_immediateUpdate = false;
|
|
|
|
showSpeed( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_bRunning;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::slotStop( )
|
|
|
|
{
|
|
|
|
m_stopped = true;
|
|
|
|
m_pRenderWidget->killRendering( );
|
|
|
|
m_pSaveButton->setEnabled( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::slotSuspend( )
|
|
|
|
{
|
|
|
|
m_pRenderWidget->suspendRendering( );
|
|
|
|
m_pSuspendButton->setEnabled( false );
|
|
|
|
m_pResumeButton->setEnabled( true );
|
|
|
|
m_pSaveButton->setEnabled( true );
|
|
|
|
|
|
|
|
m_pProgressTimer->stop( );
|
|
|
|
m_lastSpeedTime = TQTime( );
|
|
|
|
m_speedInfo = false;
|
|
|
|
m_immediateUpdate = false;
|
|
|
|
m_pProgressLabel->setText( i18n( "suspended" ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::slotResume( )
|
|
|
|
{
|
|
|
|
m_pRenderWidget->resumeRendering( );
|
|
|
|
m_pSuspendButton->setEnabled( true );
|
|
|
|
m_pResumeButton->setEnabled( false );
|
|
|
|
m_pSaveButton->setEnabled( false );
|
|
|
|
|
|
|
|
m_pProgressTimer->start( timerIntervall, true );
|
|
|
|
showSpeed( m_speed );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::slotClose( )
|
|
|
|
{
|
|
|
|
hide( );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::slotSave( )
|
|
|
|
{
|
|
|
|
KTempFile* tempFile = 0;
|
|
|
|
TQFile* file = 0;
|
|
|
|
bool ok = true;
|
|
|
|
|
|
|
|
if( !s_imageFormatsRegistered )
|
|
|
|
{
|
|
|
|
KImageIO::registerFormats( );
|
|
|
|
s_imageFormatsRegistered = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
KURL url = KFileDialog::getSaveURL( TQString(), KImageIO::pattern( KImageIO::Writing ) );
|
|
|
|
if( url.isEmpty( ) )
|
|
|
|
return;
|
|
|
|
if( !PMShell::overwriteURL( url ) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if( !url.isValid( ) )
|
|
|
|
{
|
|
|
|
KMessageBox::error( this, i18n( "Malformed URL" ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString format = KImageIO::type( url.fileName( ) );
|
|
|
|
if( format.isEmpty( ) )
|
|
|
|
{
|
|
|
|
KMessageBox::error( this, i18n( "Unknown image format.\n"
|
|
|
|
"Please enter a valid suffix." ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !KImageIO::canWrite( format ) )
|
|
|
|
{
|
|
|
|
KMessageBox::error( this, i18n( "Format is not supported for writing." ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( url.isLocalFile( ) )
|
|
|
|
{
|
|
|
|
// Local file
|
|
|
|
file = new TQFile( url.path( ) );
|
|
|
|
if( !file->open( IO_WriteOnly ) )
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Remote file
|
|
|
|
// provide a temp file
|
|
|
|
tempFile = new KTempFile( );
|
|
|
|
if( tempFile->status( ) != 0 )
|
|
|
|
ok = false;
|
|
|
|
else
|
|
|
|
file = tempFile->file( );
|
|
|
|
}
|
|
|
|
|
|
|
|
if( ok )
|
|
|
|
{
|
|
|
|
TQImageIO iio( file, format.latin1( ) );
|
|
|
|
iio.setImage( m_pRenderWidget->image( ) );
|
|
|
|
ok = iio.write( );
|
|
|
|
|
|
|
|
if( ok )
|
|
|
|
{
|
|
|
|
if( tempFile )
|
|
|
|
{
|
|
|
|
tempFile->close( );
|
|
|
|
ok = TDEIO::NetAccess::upload( tempFile->name( ), url );
|
|
|
|
tempFile->unlink( );
|
|
|
|
file = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
file->close( );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
KMessageBox::error( this, i18n( "Couldn't correctly write the image.\n"
|
|
|
|
"Wrong image format?" ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
KMessageBox::error( this, i18n( "Couldn't write the image.\n"
|
|
|
|
"Permission denied." ) );
|
|
|
|
|
|
|
|
|
|
|
|
delete file;
|
|
|
|
delete tempFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::slotPovrayOutput( )
|
|
|
|
{
|
|
|
|
m_pPovrayOutputWidget->show( );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::slotRenderingFinished( int returnStatus )
|
|
|
|
{
|
|
|
|
kdDebug( PMArea ) << "Povray exited with status " << returnStatus << endl;
|
|
|
|
m_bRunning = false;
|
|
|
|
if( returnStatus == 0 )
|
|
|
|
m_pSaveButton->setEnabled( true );
|
|
|
|
m_pStopButton->setEnabled( false );
|
|
|
|
m_pSuspendButton->setEnabled( false );
|
|
|
|
m_pResumeButton->setEnabled( false );
|
|
|
|
m_pProgressLabel->setText( i18n( "finished" ) );
|
|
|
|
m_pProgressTimer->stop( );
|
|
|
|
|
|
|
|
if( ( returnStatus != 0 ) && !m_stopped )
|
|
|
|
{
|
|
|
|
KMessageBox::error( this, i18n( "Povray exited abnormally.\n"
|
|
|
|
"See the povray output for details." )
|
|
|
|
.arg( returnStatus ) );
|
|
|
|
}
|
|
|
|
else if( m_pRenderWidget->povrayOutput( ).contains( "ERROR" ) )
|
|
|
|
{
|
|
|
|
KMessageBox::error( this, i18n( "There were errors while rendering.\n"
|
|
|
|
"See the povray output for details." ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::slotProgress( int i )
|
|
|
|
{
|
|
|
|
m_pProgressBar->setProgress( i );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::slotLineFinished( int line )
|
|
|
|
{
|
|
|
|
m_speedInfo = true;
|
|
|
|
TQTime ct = TQTime::currentTime( );
|
|
|
|
|
|
|
|
if( !m_lastSpeedTime.isNull( ) )
|
|
|
|
{
|
|
|
|
int msecs = m_lastSpeedTime.msecsTo( ct );
|
|
|
|
if( msecs < 1 )
|
|
|
|
msecs = 1;
|
|
|
|
|
|
|
|
double g = 1.0 / ( ( double ) msecs / 500.0 + 1.0 );
|
|
|
|
m_speed = g * m_speed +
|
|
|
|
1000 * ( 1.0 - g ) * m_width * ( line - m_line ) / msecs;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( m_immediateUpdate )
|
|
|
|
{
|
|
|
|
m_immediateUpdate = false;
|
|
|
|
showSpeed( m_speed );
|
|
|
|
m_pProgressTimer->start( timerIntervall, true );
|
|
|
|
m_speedInfo = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_lastSpeedTime = ct;
|
|
|
|
m_line = line;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::slotUpdateSpeed( )
|
|
|
|
{
|
|
|
|
if( m_speedInfo )
|
|
|
|
{
|
|
|
|
showSpeed( m_speed );
|
|
|
|
m_pProgressTimer->start( timerIntervall, true );
|
|
|
|
m_speedInfo = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_immediateUpdate = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PMPovrayWidget::showSpeed( double pps )
|
|
|
|
{
|
|
|
|
TQString num;
|
|
|
|
if( pps >= 1000000 )
|
|
|
|
{
|
|
|
|
num.setNum( pps / 100000, 'g', 3 );
|
|
|
|
num += 'M';
|
|
|
|
}
|
|
|
|
else if( pps >= 1000 )
|
|
|
|
{
|
|
|
|
num.setNum( pps / 1000, 'g', 3 );
|
|
|
|
num += 'K';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
num.setNum( pps, 'g', 3 );
|
|
|
|
|
|
|
|
m_pProgressLabel->setText( i18n( "running, %1 pixels/second" ).arg( num ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "pmpovraywidget.moc"
|