Back to index

kdeartwork  4.3.2
SolarWinds.cpp
Go to the documentation of this file.
00001 /*
00002  *  Terence Welsh Screensaver - Solar Winds
00003  *  http://www.reallyslick.com/
00004  *
00005  *  Ported to KDE by Karl Robillard
00006  *  Copyright (C) 2002  Terence M. Welsh
00007  *
00008  *  This program is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU General Public License as
00010  *  published by the Free Software Foundation; either version 2 of 
00011  *  the License, or (at your option) any later version.
00012  *   
00013  *  This program is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *  GNU General Public License for more details.
00017  *   
00018  *  You should have received a copy of the GNU General Public License
00019  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 #include <stdio.h>
00023 #include <math.h>
00024 #include <stdlib.h>
00025 #include <time.h>
00026 #include <qtimer.h>
00027 #include "SolarWinds.h"
00028 #include "SolarWinds.moc"
00029 
00030 
00031 #define NUMCONSTS   9
00032 #define PIx2        6.28318530718f
00033 #define DEG2RAD     0.0174532925f
00034 
00035 
00036 // Useful random number macro
00037 // Don't forget to initialize with srand()
00038 
00039 // This is the original myRandf() which does not work on Linux.
00040 // I grabed the inline version from Flux.cpp.
00041 //#define myRandf(x) (float(rand()) * (x * 0.0000305185095f))
00042 
00043 inline float myRandf(float x){
00044     return(float(rand() * x) / float(RAND_MAX));
00045 }
00046 
00047 
00048 // Context pointer to allow many instances.
00049 static SWindsWidget* _ec = 0;
00050 
00051 
00052 struct Emitter
00053 {
00054     float x, y, z;
00055 };
00056 
00057 
00058 struct Particle
00059 {
00060     float x, y, z;
00061     float r, g, b;
00062 };
00063 
00064 
00065 class wind
00066 {
00067 public:
00068 
00069     wind();
00070     ~wind();
00071     void update();
00072 
00073     Emitter* emitters;
00074     Particle* particles;
00075     int** linelist;
00076     int* lastparticle;
00077     int whichparticle;
00078     int partCount;
00079     int emitCount;
00080     bool useLines;
00081     float c[NUMCONSTS];
00082     float ct[NUMCONSTS];
00083     float cv[NUMCONSTS];
00084 };
00085 
00086 
00087 wind::wind()
00088 {
00089     int i;
00090 
00091     partCount = _ec->dParticles;
00092     emitCount = _ec->dEmitters;
00093     useLines  = (_ec->dGeometry == 2);
00094 
00095     emitters = new Emitter[emitCount];
00096     for(i=0; i<emitCount; i++)
00097     {
00098         emitters[i].x = myRandf(60.0f) - 30.0f;
00099         emitters[i].y = myRandf(60.0f) - 30.0f;
00100         emitters[i].z = myRandf(30.0f) - 15.0f;
00101     }
00102 
00103     particles = new Particle[partCount];
00104     for(i=0; i<partCount; i++)
00105     {
00106         particles[i].x = 0.0f;
00107         particles[i].y = 0.0f;
00108         particles[i].z = 100.0f;  // start particles behind viewer
00109     }
00110 
00111     whichparticle = 0;
00112 
00113     if( useLines )
00114     {
00115         linelist = new int*[partCount];
00116         for(i=0; i<partCount; i++)
00117         {
00118             linelist[i] = new int[2];
00119             linelist[i][0] = -1;
00120             linelist[i][1] = -1;
00121         }
00122         lastparticle = new int[emitCount];
00123         for(i=0; i<emitCount; i++)
00124             lastparticle[i] = i;
00125     }
00126 
00127     float windspeed = (float) (_ec->dWindspeed);
00128     for(i=0; i<NUMCONSTS; i++)
00129     {
00130         ct[i] = myRandf(PIx2);
00131         cv[i] = myRandf(0.00005f * windspeed * windspeed)
00132                 + 0.00001f * windspeed * windspeed;
00133         //printf( "KR ct %g cv %g\n", ct[i], cv[i] );
00134     }
00135 }
00136 
00137 
00138 wind::~wind()
00139 {
00140     delete[] emitters;
00141     delete[] particles;
00142 
00143     if( useLines )
00144     {
00145         int i;
00146         for(i=0; i<partCount; i++)
00147             delete[] linelist[i];
00148         delete[] linelist;
00149         delete[] lastparticle;
00150     }
00151 }
00152 
00153 
00154 void wind::update()
00155 {
00156     int i;
00157     float x, y, z;
00158     float temp;
00159     float particleSpeed = (float) _ec->dParticlespeed;
00160 
00161     float evel = float(_ec->dEmitterspeed) * 0.01f;
00162     float pvel = particleSpeed * 0.01f;
00163     float pointsize = 0.04f * _ec->dSize;
00164     float linesize = 0.005f * _ec->dSize;
00165 
00166     // update constants
00167     for(i=0; i<NUMCONSTS; i++)
00168     {
00169         ct[i] += cv[i];
00170         if(ct[i] > PIx2)
00171             ct[i] -= PIx2;
00172         c[i] = cos(ct[i]);
00173     }
00174 
00175     // calculate emissions
00176     for(i=0; i<emitCount; i++)
00177     {
00178         emitters[i].z += evel;  // emitter moves toward viewer
00179         if(emitters[i].z > 15.0f)
00180         {
00181             // reset emitter
00182             emitters[i].x = myRandf(60.0f) - 30.0f;
00183             emitters[i].y = myRandf(60.0f) - 30.0f;
00184             emitters[i].z = -15.0f;
00185         }
00186 
00187         particles[whichparticle].x = emitters[i].x;
00188         particles[whichparticle].y = emitters[i].y;
00189         particles[whichparticle].z = emitters[i].z;
00190 
00191         if( useLines )
00192         {
00193             // link particles to form lines
00194             if(linelist[whichparticle][0] >= 0)
00195                 linelist[linelist[whichparticle][0]][1] = -1;
00196             linelist[whichparticle][0] = -1;
00197             if(emitters[i].z == -15.0f)
00198                 linelist[whichparticle][1] = -1;
00199             else
00200                 linelist[whichparticle][1] = lastparticle[i];
00201             linelist[lastparticle[i]][0] = whichparticle;
00202             lastparticle[i] = whichparticle;
00203         }
00204 
00205         whichparticle++;
00206         if(whichparticle >= partCount)
00207             whichparticle = 0;
00208     }
00209 
00210     // calculate particle positions and colors
00211     // first modify constants that affect colors
00212     c[6] *= 9.0f / particleSpeed;
00213     c[7] *= 9.0f / particleSpeed;
00214     c[8] *= 9.0f / particleSpeed;
00215     // then update each particle
00216     for(i=0; i<partCount; i++)
00217     {
00218         Particle* part = particles + i;
00219 
00220         // store old positions
00221         x = part->x;
00222         y = part->y;
00223         z = part->z;
00224 
00225         // make new positins
00226         part->x = x + (c[0] * y + c[1] * z) * pvel;
00227         part->y = y + (c[2] * z + c[3] * x) * pvel;
00228         part->z = z + (c[4] * x + c[5] * y) * pvel;
00229 
00230         // calculate colors
00231         part->r = fabs((part->x - x) * c[6]);
00232         part->g = fabs((part->y - y) * c[7]);
00233         part->b = fabs((part->z - z) * c[8]);
00234 
00235         // clamp colors
00236         if( part->r > 1.0f )
00237             part->r = 1.0f;
00238         if( part->g > 1.0f )
00239             part->g = 1.0f;
00240         if( part->b > 1.0f )
00241             part->b = 1.0f;
00242     }
00243 
00244     // draw particles
00245     switch(_ec->dGeometry)
00246     {
00247     case 0:  // lights
00248         for(i=0; i<partCount; i++)
00249         {
00250             glColor3fv(&particles[i].r);
00251             glPushMatrix();
00252                 glTranslatef(particles[i].x, particles[i].y, particles[i].z);
00253                 glCallList(1);
00254             glPopMatrix();
00255 #if 0
00256             if( i == 0 )
00257                 printf( "KR %d %g %g %g\n", i,
00258                     particles[i].x, particles[i].y, particles[i].z);
00259 #endif
00260         }
00261         break;
00262 
00263     case 1:  // points
00264         for(i=0; i<partCount; i++)
00265         {
00266             temp = particles[i].z + 40.0f;
00267             if(temp < 0.01f)
00268                 temp = 0.01f;
00269             glPointSize(pointsize * temp);
00270 
00271             glBegin(GL_POINTS);
00272                 glColor3fv(&particles[i].r);
00273                 glVertex3fv(&particles[i].x);
00274             glEnd();
00275         }
00276         break;
00277 
00278     case 2:  // lines
00279         for(i=0; i<partCount; i++)
00280         {
00281             temp = particles[i].z + 40.0f;
00282             if(temp < 0.01f)
00283                 temp = 0.01f;
00284             glLineWidth(linesize * temp);
00285 
00286             glBegin(GL_LINES);
00287             if(linelist[i][1] >= 0)
00288             {
00289                 glColor3fv(&particles[i].r);
00290                 if(linelist[i][0] == -1)
00291                     glColor3f(0.0f, 0.0f, 0.0f);
00292                 glVertex3fv(&particles[i].x);
00293 
00294                 glColor3fv(&particles[linelist[i][1]].r);
00295                 if(linelist[linelist[i][1]][1] == -1)
00296                     glColor3f(0.0f, 0.0f, 0.0f);
00297                 glVertex3fv(&particles[linelist[i][1]].x);
00298             }
00299             glEnd();
00300         }
00301     }
00302 }
00303 
00304 
00305 //----------------------------------------------------------------------------
00306 
00307 
00308 SWindsWidget::SWindsWidget( QWidget* parent )
00309                       : QGLWidget(parent), _winds(0)
00310 {
00311     setDefaults( Regular );
00312 
00313     _frameTime = 1000 / 60;
00314     _timer = new QTimer( this );
00315     _timer->setSingleShot( true );
00316     connect( _timer, SIGNAL(timeout()), this, SLOT(nextFrame()) );
00317 }
00318 
00319 
00320 SWindsWidget::~SWindsWidget()
00321 {
00322     // Free memory
00323     delete[] _winds;
00324 }
00325 
00326 
00327 void SWindsWidget::paintGL()
00328 {
00329     glLoadIdentity();
00330 
00331     if( ! dBlur )
00332     {
00333         glClear(GL_COLOR_BUFFER_BIT);
00334     }
00335     else
00336     {
00337         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00338         glColor4f(0.0f, 0.0f, 0.0f, 0.5f - (float(dBlur) * 0.0049f));
00339 
00340         glBegin(GL_QUADS);
00341             glVertex3f(-40.0f, -17.0f, 0.0f);
00342             glVertex3f(40.0f, -17.0f, 0.0f);
00343             glVertex3f(40.0f, 17.0f, 0.0f);
00344             glVertex3f(-40.0f, 17.0f, 0.0f);
00345         glEnd();
00346 
00347         if(!dGeometry)
00348             glBlendFunc(GL_ONE, GL_ONE);
00349         else
00350             glBlendFunc(GL_SRC_ALPHA, GL_ONE);  // Necessary for point and line smoothing (I don't know why)
00351                 // Maybe it's just my video card...
00352     }
00353 
00354     // You should need to draw twice if using blur, once to each buffer.
00355     // But wglSwapLayerBuffers appears to copy the back to the
00356     // front instead of just switching the pointers to them.  It turns
00357     // out that both NVidia and 3dfx prefer to use PFD_SWAP_COPY instead
00358     // of PFD_SWAP_EXCHANGE in the PIXELFORMATDESCRIPTOR.  I don't know why...
00359     // So this may not work right on other platforms or all video cards.
00360 
00361     // Update surfaces
00362     if( _winds )
00363     {
00364         _ec = this;
00365         int i;
00366         for(i=0; i<dWinds; i++)
00367             _winds[i].update();
00368     }
00369 
00370     glFlush();
00371 }
00372 
00373 
00374 void SWindsWidget::resizeGL( int w, int h )
00375 {
00376     glViewport(0, 0, w, h );
00377 
00378     glMatrixMode(GL_PROJECTION);
00379     glLoadIdentity();
00380     gluPerspective(90.0, (float) w / (float) h, 1.0, 10000);
00381     glTranslatef(0.0, 0.0, -15.0);
00382     glMatrixMode(GL_MODELVIEW);
00383     glLoadIdentity();
00384 }
00385 
00386 
00387 // Window initialization
00388 void SWindsWidget::initializeGL()
00389 {
00390     updateParameters();
00391     _timer->start( _frameTime );
00392 }
00393 
00394 
00395 #ifdef UNIT_TEST
00396 void SWindsWidget::keyPressEvent( QKeyEvent* e )
00397 {
00398     if( e->key() == Qt::Key_0 ) { setDefaults( 0 ); updateParameters(); }
00399     if( e->key() == Qt::Key_1 ) { setDefaults( 1 ); updateParameters(); }
00400     if( e->key() == Qt::Key_2 ) { setDefaults( 2 ); updateParameters(); }
00401     if( e->key() == Qt::Key_3 ) { setDefaults( 3 ); updateParameters(); }
00402     if( e->key() == Qt::Key_4 ) { setDefaults( 4 ); updateParameters(); }
00403     if( e->key() == Qt::Key_5 ) { setDefaults( 5 ); updateParameters(); }
00404 }
00405 #endif
00406 
00407 
00408 void SWindsWidget::nextFrame()
00409 {
00410     updateGL();
00411     _timer->start( _frameTime );
00412 }
00413 
00414 
00415 void SWindsWidget::updateParameters()
00416 {
00417     int i, j;
00418     float x, y, temp;
00419 
00420     srand((unsigned)time(NULL));
00421     rand(); rand(); rand(); rand(); rand();
00422 
00423     glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
00424     glClear(GL_COLOR_BUFFER_BIT);
00425 
00426     if(!dGeometry)
00427         glBlendFunc(GL_ONE, GL_ONE);
00428     else
00429         glBlendFunc(GL_SRC_ALPHA, GL_ONE);  // Necessary for point and line smoothing (I don't know why)
00430     glEnable(GL_BLEND);
00431 
00432     if( ! dGeometry )
00433     {
00434         // Init lights
00435         for(i=0; i<LIGHTSIZE; i++)
00436         {
00437             for(j=0; j<LIGHTSIZE; j++)
00438             {
00439                 x = float(i - LIGHTSIZE / 2) / float(LIGHTSIZE / 2);
00440                 y = float(j - LIGHTSIZE / 2) / float(LIGHTSIZE / 2);
00441                 temp = 1.0f - float(sqrt((x * x) + (y * y)));
00442                 if(temp > 1.0f)
00443                     temp = 1.0f;
00444                 if(temp < 0.0f)
00445                     temp = 0.0f;
00446                 lightTexture[i][j] = (unsigned char) (255.0f * temp);
00447             }
00448         }
00449 
00450         glEnable(GL_TEXTURE_2D);
00451         glBindTexture(GL_TEXTURE_2D, 1);
00452         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00453         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00454         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00455         glTexImage2D(GL_TEXTURE_2D, 0, 1, LIGHTSIZE, LIGHTSIZE, 0,
00456                      GL_LUMINANCE, GL_UNSIGNED_BYTE, lightTexture);
00457 
00458         temp = 0.02f * dSize;
00459         glNewList(1, GL_COMPILE);
00460             glBindTexture(GL_TEXTURE_2D, 1);
00461             glBegin(GL_TRIANGLE_STRIP);
00462                 glTexCoord2f(0.0f, 0.0f);
00463                 glVertex3f(-temp, -temp, 0.0f);
00464                 glTexCoord2f(1.0f, 0.0f);
00465                 glVertex3f(temp, -temp, 0.0f);
00466                 glTexCoord2f(0.0f, 1.0f);
00467                 glVertex3f(-temp, temp, 0.0f);
00468                 glTexCoord2f(1.0f, 1.0f);
00469                 glVertex3f(temp, temp, 0.0f);
00470             glEnd();
00471         glEndList();
00472     }
00473     else if(dGeometry == 1)
00474     {
00475         // init point smoothing
00476         glEnable(GL_POINT_SMOOTH);
00477         glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
00478 
00479         glDisable(GL_TEXTURE_2D);
00480     }
00481     else if(dGeometry == 2)
00482     {
00483         // init line smoothing
00484         glEnable(GL_LINE_SMOOTH);
00485         glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
00486 
00487         glDisable(GL_TEXTURE_2D);
00488     }
00489 
00490 
00491     // Initialize surfaces
00492     _ec = this;
00493     delete[] _winds;
00494     _winds = new wind[dWinds];
00495 }
00496 
00497 
00501 void SWindsWidget::setDefaults(int which)
00502 {
00503     switch(which)
00504     {
00505     case CosmicStrings:
00506         dWinds = 1;
00507         dEmitters = 50;
00508         dParticles = 3000;
00509         dGeometry = 2;
00510         dSize = 20;
00511         dWindspeed = 10;
00512         dEmitterspeed = 10;
00513         dParticlespeed = 10;
00514         dBlur = 10;
00515         break;
00516 
00517     case ColdPricklies:
00518         dWinds = 1;
00519         dEmitters = 300;
00520         dParticles = 3000;
00521         dGeometry = 2;
00522         dSize = 5;
00523         dWindspeed = 20;
00524         dEmitterspeed = 100;
00525         dParticlespeed = 15;
00526         dBlur = 70;
00527         break;
00528 
00529     case SpaceFur:
00530         dWinds = 2;
00531         dEmitters = 400;
00532         dParticles = 1600;
00533         dGeometry = 2;
00534         dSize = 15;
00535         dWindspeed = 20;
00536         dEmitterspeed = 15;
00537         dParticlespeed = 10;
00538         dBlur = 0;
00539         break;
00540 
00541     case Jiggly:
00542         dWinds = 1;
00543         dEmitters = 40;
00544         dParticles = 1200;
00545         dGeometry = 1;
00546         dSize = 20;
00547         dWindspeed = 100;
00548         dEmitterspeed = 20;
00549         dParticlespeed = 4;
00550         dBlur = 50;
00551         break;
00552 
00553     case Undertow:
00554         dWinds = 1;
00555         dEmitters = 400;
00556         dParticles = 1200;
00557         dGeometry = 0;
00558         dSize = 40;
00559         dWindspeed = 20;
00560         dEmitterspeed = 1;
00561         dParticlespeed = 100;
00562         dBlur = 50;
00563         break;
00564 
00565     case Regular:
00566     default:
00567         dWinds = 1;
00568         dEmitters = 30;
00569         dParticles = 2000;
00570         dGeometry = 0;
00571         dSize = 50;
00572         dWindspeed = 20;
00573         dEmitterspeed = 15;
00574         dParticlespeed = 10;
00575         dBlur = 40;
00576         break;
00577     }
00578 }
00579 
00580 
00581 //----------------------------------------------------------------------------
00582 
00583 
00584 #ifndef UNIT_TEST
00585 #include <klocale.h>
00586 #include <kglobal.h>
00587 #include <kconfig.h>
00588 
00589 
00590 // libkscreensaver interface
00591 class KSolarWindsSaverInterface : public KScreenSaverInterface
00592 {
00593 
00594 
00595 public:
00596     virtual KAboutData* aboutData() {
00597         return new KAboutData( "ksolarwinds.kss", "klock", ki18n( "Solar Winds" ), "1.0", ki18n( "Solar Winds" ) );
00598     }
00599 
00600 
00601     virtual KScreenSaver* create( WId id )
00602     {
00603         return new KSWindsScreenSaver( id );
00604     }
00605 
00606     virtual QDialog* setup()
00607     {
00608         return new KSWindsSetup;
00609     }
00610 };
00611 
00612 int main( int argc, char *argv[] )
00613 {
00614     KSolarWindsSaverInterface kss;
00615     return kScreenSaverMain( argc, argv, kss );
00616 }
00617 
00618 
00619 //----------------------------------------------------------------------------
00620 
00621 
00622 KSWindsScreenSaver::KSWindsScreenSaver( WId id ) : KScreenSaver( id )
00623 {
00624     _flux = new SWindsWidget;
00625 
00626     readSettings();
00627 
00628     embed( _flux );
00629     _flux->show();
00630 }
00631 
00632 
00633 KSWindsScreenSaver::~KSWindsScreenSaver()
00634 {
00635 }
00636 
00637 
00638 static int filterRandom( int n )
00639 {
00640     if( (n < 0) || (n >= SWindsWidget::DefaultModes) )
00641     {
00642         srand((unsigned)time(NULL));
00643         n = rand() % SWindsWidget::DefaultModes;
00644     }
00645     return n;
00646 }
00647 
00648 
00649 void KSWindsScreenSaver::readSettings()
00650 {
00651     KConfigGroup config(KGlobal::config(), "Settings");
00652 
00653     _mode = config.readEntry( "Mode", (int)SWindsWidget::Regular );
00654     _flux->setDefaults( filterRandom(_mode) );
00655 }
00656 
00657 
00661 void KSWindsScreenSaver::setMode( int id )
00662 {
00663     _mode = id;
00664     _flux->setDefaults( filterRandom(id) );
00665     _flux->updateParameters();
00666 }
00667 
00668 
00669 //----------------------------------------------------------------------------
00670 
00671 
00672 #include <qlayout.h>
00673 #include <qlabel.h>
00674 #include <qcombobox.h>
00675 #include <kmessagebox.h>
00676 
00677 
00678 static const char* defaultText[] =
00679 {
00680     I18N_NOOP( "Regular" ),
00681     I18N_NOOP( "Cosmic Strings" ),
00682     I18N_NOOP( "Cold Pricklies" ),
00683     I18N_NOOP( "Space Fur" ),
00684     I18N_NOOP( "Jiggly" ),
00685     I18N_NOOP( "Undertow" ),
00686     I18N_NOOP( "(Random)" ),
00687     0
00688 };
00689 
00690 
00691 KSWindsSetup::KSWindsSetup( QWidget* parent )
00692         : KDialog( parent)
00693 {
00694     setButtonText( Help, i18n( "A&bout" ) );
00695        setButtons(Ok|Cancel|Help);
00696        setDefaultButton(Ok);
00697        setCaption(i18n( "Setup Solar Wind" ));
00698        setModal(true);
00699        showButtonSeparator(true);
00700     QWidget *main = new QWidget(this);
00701        setMainWidget(main);
00702 
00703     QHBoxLayout* top = new QHBoxLayout( main );
00704     top->setSpacing( spacingHint() );
00705 
00706     QVBoxLayout* leftCol = new QVBoxLayout;
00707     top->addLayout( leftCol );
00708 
00709     QLabel* label = new QLabel( i18n("Mode:"), main );
00710     leftCol->addWidget( label );
00711 
00712     modeW = new QComboBox( main );
00713     int i = 0;
00714     while (defaultText[i])
00715         modeW->addItem( i18n(defaultText[i++]) );
00716     leftCol->addWidget( modeW );
00717 
00718     leftCol->addStretch();
00719 
00720     // Preview
00721     QWidget* preview;
00722     preview = new QWidget( main );
00723     preview->setFixedSize( 220, 165 );
00724     {
00725         QPalette palette;
00726         palette.setColor( preview->backgroundRole(), Qt::black );
00727         preview->setPalette( palette );
00728        preview->setAutoFillBackground(true);
00729     }
00730     preview->show();    // otherwise saver does not get correct size
00731     _saver = new KSWindsScreenSaver( preview->winId() );
00732     top->addWidget(preview);
00733 
00734     // Now that we have _saver...
00735     modeW->setCurrentIndex( _saver->mode() );    // set before we connect
00736     connect( modeW, SIGNAL(activated(int)), _saver, SLOT(setMode(int)) );
00737        connect( this, SIGNAL(okClicked()), this, SLOT(slotOk()));
00738        connect( this, SIGNAL(helpClicked()),this,SLOT(slotHelp()));
00739 }
00740 
00741 
00742 KSWindsSetup::~KSWindsSetup()
00743 {
00744     delete _saver;
00745 }
00746 
00747 
00748 void KSWindsSetup::slotHelp()
00749 {
00750     KMessageBox::about(this,
00751         i18n("<h3>Solar Winds 1.0</h3>\n<p>Copyright (c) 2002 Terence M. Welsh<br>\n<a href=\"http://www.reallyslick.com/\">http://www.reallyslick.com/</a></p>\n\n<p>Ported to KDE by Karl Robillard</p>"),
00752         QString(), KMessageBox::AllowLink);
00753 }
00754 
00755 
00759 void KSWindsSetup::slotOk()
00760 {
00761     KConfigGroup config(KGlobal::config(), "Settings");
00762 
00763     QString val;
00764     val.setNum( modeW->currentIndex() );
00765     config.writeEntry("Mode", val );
00766 
00767     config.sync();
00768     accept();
00769 }
00770 #endif
00771 
00772 
00773 //----------------------------------------------------------------------------
00774 
00775 
00776 #ifdef UNIT_TEST
00777 // moc SolarWinds.h -o SolarWinds.moc
00778 // g++ -g -DUNIT_TEST SolarWinds.cpp -I/usr/lib/qt3/include -lqt -L/usr/lib/qt3/lib -lGLU -lGL
00779 
00780 #include <qapplication.h>
00781 
00782 int main( int argc, char** argv )
00783 {
00784     QApplication app( argc, argv );
00785 
00786     SWindsWidget w;
00787     app.setMainWidget( &w );
00788     w.show();
00789 
00790     return app.exec();
00791 }
00792 #endif
00793 
00794 
00795 //EOF