|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2005 by Carsten Niehaus *
|
|
|
|
* cniehaus@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. *
|
|
|
|
* *
|
|
|
|
* This program 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 General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, write to the *
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
|
|
***************************************************************************/
|
|
|
|
#include "spectrumwidget.h"
|
|
|
|
#include "spectrum.h"
|
|
|
|
#include "element.h"
|
|
|
|
#include "kalziumutils.h"
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tdeglobal.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include <tqcursor.h>
|
|
|
|
#include <tqsizepolicy.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
|
|
|
|
#include <tqglobal.h>
|
|
|
|
#if defined(Q_OS_SOLARIS)
|
|
|
|
#include <ieeefp.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
SpectrumWidget::SpectrumWidget( TQWidget *parent, const char* name ) : TQWidget( parent, name )
|
|
|
|
{
|
|
|
|
startValue = 0;
|
|
|
|
endValue = 0;
|
|
|
|
|
|
|
|
m_LMBPointCurrent.setX( -1 );
|
|
|
|
m_LMBPointPress.setX( -1 );
|
|
|
|
|
|
|
|
m_showtooltip = false;
|
|
|
|
|
|
|
|
m_realHeight = 200;
|
|
|
|
|
|
|
|
Gamma = 0.8;
|
|
|
|
IntensityMax = 255;
|
|
|
|
|
|
|
|
setType( EmissionSpectrum );
|
|
|
|
|
|
|
|
setMinimumSize( 400, 230 );
|
|
|
|
setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Expanding );
|
|
|
|
setBackgroundMode( NoBackground );
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::paintEvent( TQPaintEvent * /*e*/ )
|
|
|
|
{
|
|
|
|
if ( !m_spectrum )
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_pixmap.resize( width(), height() );
|
|
|
|
m_pixmap.fill( this, width(), height() );
|
|
|
|
|
|
|
|
TQPainter p;
|
|
|
|
p.begin( &m_pixmap, this );
|
|
|
|
p.fillRect( 0, 0, width(), m_realHeight, TQt::black );
|
|
|
|
|
|
|
|
paintBands( &p );
|
|
|
|
|
|
|
|
drawTickmarks( &p );
|
|
|
|
|
|
|
|
if ( m_showtooltip )
|
|
|
|
drawTooltip( &p );
|
|
|
|
|
|
|
|
if ( m_LMBPointPress.x() != -1 && m_LMBPointCurrent.x() != -1 )
|
|
|
|
drawZoomLine( &p );
|
|
|
|
|
|
|
|
p.end();
|
|
|
|
bitBlt( this, 0, 0, &m_pixmap );
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::drawZoomLine( TQPainter* p )
|
|
|
|
{
|
|
|
|
p->setPen( TQt::white );
|
|
|
|
p->drawLine( m_LMBPointPress.x(), m_LMBPointPress.y(), m_LMBPointCurrent.x(), m_LMBPointPress.y() );
|
|
|
|
p->drawLine( m_LMBPointCurrent.x(), m_LMBPointPress.y()+10, m_LMBPointCurrent.x(), m_LMBPointPress.y()-10 );
|
|
|
|
p->drawLine( m_LMBPointPress.x(), m_LMBPointPress.y()+10, m_LMBPointPress.x(), m_LMBPointPress.y()-10 );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::paintBands( TQPainter* p )
|
|
|
|
{
|
|
|
|
if ( m_type == AbsorptionSpectrum )
|
|
|
|
{
|
|
|
|
for ( double va = startValue; va <= endValue ; va += 0.1 )
|
|
|
|
{
|
|
|
|
int x = xPos( va );
|
|
|
|
p->setPen( linecolor( va ) );
|
|
|
|
p->drawLine( x,0,x, m_realHeight );
|
|
|
|
}
|
|
|
|
|
|
|
|
p->setPen( TQt::black );
|
|
|
|
}
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
int x = 0;
|
|
|
|
int temp = 0;
|
|
|
|
|
|
|
|
for ( TQValueList<Spectrum::band>::Iterator it = m_spectrum->bandlist()->begin();
|
|
|
|
it != m_spectrum->bandlist()->end();
|
|
|
|
++it )
|
|
|
|
{
|
|
|
|
if ( ( *it ).wavelength < startValue || ( *it ).wavelength > endValue )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
x = xPos( ( *it ).wavelength );
|
|
|
|
|
|
|
|
temp = 0;
|
|
|
|
|
|
|
|
switch ( m_type )
|
|
|
|
{
|
|
|
|
case EmissionSpectrum:
|
|
|
|
p->setPen( linecolor( ( *it ).wavelength ) );
|
|
|
|
p->drawLine( x,0,x, m_realHeight-1 );
|
|
|
|
|
|
|
|
p->setPen( TQt::black );
|
|
|
|
// p->drawLine( x,m_realHeight,x, m_realHeight );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AbsorptionSpectrum:
|
|
|
|
p->setPen( TQt::black );
|
|
|
|
p->drawLine( x,0,x, m_realHeight-1 );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQColor SpectrumWidget::linecolor( double spectrum )
|
|
|
|
{
|
|
|
|
int r,g,b;
|
|
|
|
wavelengthToRGB( spectrum, r,g,b );
|
|
|
|
|
|
|
|
TQColor c( r,g,b );
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SpectrumWidget::wavelengthToRGB( double wavelength, int& r, int& g, int& b )
|
|
|
|
{
|
|
|
|
double blue = 0.0, green = 0.0, red = 0.0, factor = 0.0;
|
|
|
|
|
|
|
|
int wavelength_ = ( int ) floor( wavelength );
|
|
|
|
if ( wavelength_ < 380 || wavelength_ > 780 )
|
|
|
|
{
|
|
|
|
//make everything white
|
|
|
|
r = g = b = 255;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if ( wavelength_ > 380 && wavelength_ < 439 )
|
|
|
|
{
|
|
|
|
red = -( wavelength-440 ) / ( 440-380 );
|
|
|
|
green = 0.0;
|
|
|
|
blue = 1.0;
|
|
|
|
|
|
|
|
}
|
|
|
|
else if ( wavelength_ > 440 && wavelength_ < 489 )
|
|
|
|
{
|
|
|
|
red = 0.0;
|
|
|
|
green = ( wavelength-440 ) / ( 490-440 );
|
|
|
|
blue = 1.0;
|
|
|
|
}
|
|
|
|
else if ( wavelength_ > 490 && wavelength_ < 509 )
|
|
|
|
{
|
|
|
|
red = 0.0;
|
|
|
|
green = 1.0;
|
|
|
|
blue = -( wavelength-510 ) / ( 510-490 );
|
|
|
|
}
|
|
|
|
else if ( wavelength_ > 510 && wavelength_ < 579 )
|
|
|
|
{
|
|
|
|
red = ( wavelength-510 ) / ( 580-510 );
|
|
|
|
green = 1.0;
|
|
|
|
blue = 0.0;
|
|
|
|
}
|
|
|
|
else if ( wavelength_ > 580 && wavelength_ < 644 )
|
|
|
|
{
|
|
|
|
red = 1.0;
|
|
|
|
green = -( wavelength-645 ) / ( 645-580 );
|
|
|
|
blue = 0.0;
|
|
|
|
}
|
|
|
|
else if ( wavelength_ > 645 && wavelength_ < 780 )
|
|
|
|
{
|
|
|
|
red = 1.0;
|
|
|
|
green = 0.0;
|
|
|
|
blue = 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( wavelength_ > 380 && wavelength_ < 419 )
|
|
|
|
factor = 0.3 + 0.7*( wavelength - 380 ) / ( 420 - 380 );
|
|
|
|
else if ( wavelength_ > 420 && wavelength_ < 700 )
|
|
|
|
factor = 1.0;
|
|
|
|
else if ( wavelength_ > 701 && wavelength_ < 780 )
|
|
|
|
factor = 0.3 + 0.7*( 780 - wavelength ) / ( 780 - 700 );
|
|
|
|
else
|
|
|
|
factor = 0.0;
|
|
|
|
|
|
|
|
r = Adjust( red, factor );
|
|
|
|
g = Adjust( green, factor );
|
|
|
|
b = Adjust( blue, factor );
|
|
|
|
}
|
|
|
|
|
|
|
|
int SpectrumWidget::Adjust( double color, double factor )
|
|
|
|
{
|
|
|
|
if ( color == 0.0 )
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return tqRound( IntensityMax * pow( color*factor, Gamma ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::drawTickmarks( TQPainter* p )
|
|
|
|
{
|
|
|
|
//the size of the text on the tickmarks
|
|
|
|
const int space = 20;
|
|
|
|
|
|
|
|
//the distance between the tickmarks in pixel
|
|
|
|
const int d = 10;
|
|
|
|
|
|
|
|
//the total number of tickmarks to draw (small and long)
|
|
|
|
const int numberOfTickmarks = ( int )floor( width()/d );
|
|
|
|
|
|
|
|
double pos = 0.0;
|
|
|
|
|
|
|
|
for ( int i = 0; i < numberOfTickmarks; i++ )
|
|
|
|
{
|
|
|
|
if( i%5 == 0 )
|
|
|
|
{//long tickmarks plus text
|
|
|
|
p->drawLine( i*d, m_realHeight, i*d, m_realHeight+10 );
|
|
|
|
if ( i%10 == 0 &&
|
|
|
|
i*d > space &&
|
|
|
|
i*d < width()-space )
|
|
|
|
{
|
|
|
|
pos = ( double ) ( i*d )/width();
|
|
|
|
p->fillRect( i*d-space, m_realHeight+12, 2*space, 15, TQt::white );
|
|
|
|
p->drawText( i*d-space, m_realHeight+12, 2*space, 15, TQt::AlignCenter, KalziumUtils::localizedValue( KalziumUtils::strippedValue( Wavelength( pos ) ), 6 ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {//small tickmarks
|
|
|
|
p->drawLine( i*d, m_realHeight, i*d, m_realHeight+5 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::keyPressEvent( TQKeyEvent *e )
|
|
|
|
{
|
|
|
|
kdDebug() << "SpectrumWidget::keyPressEvent()" << endl;
|
|
|
|
switch ( e->key() )
|
|
|
|
{
|
|
|
|
case Key_Plus:
|
|
|
|
slotZoomIn();
|
|
|
|
break;
|
|
|
|
case Key_Minus:
|
|
|
|
slotZoomOut();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::slotZoomOut()
|
|
|
|
{
|
|
|
|
kdDebug() << "SpectrumWidget::slotZoomOut() "<< startValue << ":: "<< endValue << endl;
|
|
|
|
|
|
|
|
double diff = endValue - startValue;
|
|
|
|
|
|
|
|
double offset = diff * 0.05;
|
|
|
|
|
|
|
|
endValue = endValue + offset;
|
|
|
|
startValue = startValue - offset;
|
|
|
|
|
|
|
|
//check for invalid values
|
|
|
|
if ( startValue < 0.0 )
|
|
|
|
startValue = 0.0;
|
|
|
|
|
|
|
|
if ( endValue > 800.0 )
|
|
|
|
endValue = 800.0;
|
|
|
|
|
|
|
|
setBorders( ( int ) startValue, ( int )endValue );
|
|
|
|
|
|
|
|
kdDebug() << "SpectrumWidget::slotZoomOut() "<< startValue << ":: "<< endValue << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::slotZoomIn()
|
|
|
|
{
|
|
|
|
kdDebug() << "SpectrumWidget::slotZoomIn() "<< startValue << ":: "<< endValue << endl;
|
|
|
|
|
|
|
|
double diff = endValue - startValue;
|
|
|
|
|
|
|
|
double offset = diff * 0.05;
|
|
|
|
|
|
|
|
endValue = endValue - offset;
|
|
|
|
startValue = startValue + offset;
|
|
|
|
|
|
|
|
setBorders( ( int ) startValue, ( int )endValue );
|
|
|
|
|
|
|
|
kdDebug() << "SpectrumWidget::slotZoomIn() "<< startValue << ":: "<< endValue << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::mouseMoveEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
m_LMBPointCurrent = e->pos();
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::mousePressEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
if ( e->button() == Qt::LeftButton )
|
|
|
|
m_LMBPointPress = e->pos();
|
|
|
|
if ( e->button() == Qt::RightButton )
|
|
|
|
slotZoomOut();
|
|
|
|
//FIXME
|
|
|
|
//the tooltip is not really working. Better to not have it
|
|
|
|
//in KDE 3.4 and think of a better solution.
|
|
|
|
//PrepareTooltip( Wavelength( ( double )e->pos().x()/width() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::PrepareTooltip( double wavelength )
|
|
|
|
{
|
|
|
|
Spectrum::band band;
|
|
|
|
|
|
|
|
TQValueList<Spectrum::band>::const_iterator it = m_spectrum->bandlist()->begin();
|
|
|
|
const TQValueList<Spectrum::band>::const_iterator itEnd = m_spectrum->bandlist()->end();
|
|
|
|
|
|
|
|
//find the difference in percent (1.0 is 100%, 0.1 is 10%)
|
|
|
|
double dif = 0.0;
|
|
|
|
|
|
|
|
bool foundWavelentgh = false;
|
|
|
|
|
|
|
|
//find the highest intensity
|
|
|
|
for ( ; it != itEnd; ++it )
|
|
|
|
{
|
|
|
|
double thisdif = ( *it ).wavelength / wavelength;
|
|
|
|
|
|
|
|
if ( thisdif < 0.9 || thisdif > 1.1 )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ( thisdif > 1.0 ){//convert for example 1.3 to 0.7
|
|
|
|
thisdif = thisdif-1;
|
|
|
|
thisdif = 1-thisdif;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( thisdif > dif )
|
|
|
|
{
|
|
|
|
dif = thisdif;
|
|
|
|
band = *it;
|
|
|
|
foundWavelentgh = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( foundWavelentgh )
|
|
|
|
{
|
|
|
|
m_band = band;
|
|
|
|
m_showtooltip = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_showtooltip = false;
|
|
|
|
|
|
|
|
kdDebug() << "SpectrumWidget::PrepareTooltip(): "<< m_showtooltip << endl;
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::drawTooltip( TQPainter *p )
|
|
|
|
{
|
|
|
|
p->setPen( TQt::white );
|
|
|
|
TQPoint pt = mapFromGlobal( TQCursor::pos() );
|
|
|
|
p->drawText( pt, i18n("Wavelength: %1").arg(m_band.wavelength) );
|
|
|
|
pt.setY( pt.y() + 15 );
|
|
|
|
p->drawText( pt, i18n("Intensity: %1").arg(m_band.intensity) );
|
|
|
|
pt.setY( pt.y() + 15 );
|
|
|
|
p->drawText( pt, i18n("Energy 1, Energy 2: %1, %2").arg(m_band.energy1).arg( m_band.energy2 ));
|
|
|
|
pt.setY( pt.y() + 15 );
|
|
|
|
p->drawText( pt, i18n("Term 1, Term 2: %1, %2").arg(m_band.term1).arg( m_band.term2 ));
|
|
|
|
pt.setY( pt.y() + 15 );
|
|
|
|
p->drawText( pt, i18n("J 1, J 2: %1, %2").arg(m_band.J1).arg( m_band.J2 ));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpectrumWidget::mouseReleaseEvent( TQMouseEvent *e )
|
|
|
|
{
|
|
|
|
if ( e->button() == Qt::LeftButton )
|
|
|
|
{
|
|
|
|
int left = (int)Wavelength( ( double )m_LMBPointPress.x()/width() );
|
|
|
|
int right = (int)Wavelength( ( double )e->pos().x()/width() );
|
|
|
|
|
|
|
|
if ( left == right )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( left > right )
|
|
|
|
setBorders( right, left );
|
|
|
|
else
|
|
|
|
setBorders( left, right );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_LMBPointPress.setX( -1 );
|
|
|
|
m_LMBPointCurrent.setX( -1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQPixmap SpectrumWidget::pixmap()
|
|
|
|
{
|
|
|
|
TQPixmap tmp( m_pixmap );
|
|
|
|
TQString text;
|
|
|
|
|
|
|
|
if( m_type == EmissionSpectrum )
|
|
|
|
text = i18n( "Emission spectrum of %1" ).arg( m_spectrum->parentElement()->elname() );
|
|
|
|
else
|
|
|
|
text = i18n( "Absorption spectrum of %1" ).arg( m_spectrum->parentElement()->elname() );
|
|
|
|
|
|
|
|
TQPainter p( &tmp );
|
|
|
|
p.setPen( TQt::black );
|
|
|
|
p.drawText( 30, m_realHeight + 70, text );
|
|
|
|
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "spectrumwidget.moc"
|
|
|
|
|