SVN_SILENT made messages (.desktop file)
[kdeartwork.git] / kscreensaver / kdesavers / Flux.cpp
blob7633636c4ea90f82f1479ed2117b8fe8c25e2ce1
1 /*
2 * Terence Welsh Screensaver - Flux
3 * http://www.reallyslick.com/
5 * Ported to KDE by Karl Robillard
6 * Copyright (C) 2002 Terence M. Welsh
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 TODO
25 [ ] Regular and others are messed up after Sparkler.
26 Insane seems to reset them.
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <math.h>
33 #include <time.h>
34 #include <qtimer.h>
36 #include "Flux.h"
37 #include "Flux.moc"
40 #define NUMCONSTS 8
41 #define PIx2 6.28318530718f
42 #define DEG2RAD 0.0174532925f
45 void hsl2rgb(float h, float s, float l, float &r, float &g, float &b)
47 // hue influence
48 if(h < 0.166667){ // full red, some green
49 r = 1.0;
50 g = h * 6.0f;
51 b = 0.0;
53 else {
54 if(h < 0.5){ // full green
55 g = 1.0;
56 if(h < 0.333333){ // some red
57 r = 1.0f - ((h - 0.166667f) * 6.0f);
58 b = 0.0;
60 else{ // some blue
61 b = (h - 0.333333f) * 6.0f;
62 r = 0.0;
65 else{
66 if(h < 0.833333){ // full blue
67 b = 1.0;
68 if(h < 0.666667){ // some green
69 g = 1.0f - ((h - 0.5f) * 6.0f);
70 r = 0.0;
72 else{ // some red
73 r = (h - 0.666667f) * 6.0f;
74 g = 0.0;
77 else{ // full red, some blue
78 r = 1.0;
79 b = 1.0f - ((h - 0.833333f) * 6.0f);
80 g = 0.0;
85 // saturation influence
86 r = 1.0f - (s * (1.0f - r));
87 g = 1.0f - (s * (1.0f - g));
88 b = 1.0f - (s * (1.0f - b));
90 // luminosity influence
91 r *= l;
92 g *= l;
93 b *= l;
97 // Useful random number macros
98 // Don't forget to initialize with srand()
99 inline int myRandi(int x){
100 return((rand() * x) / RAND_MAX);
102 inline float myRandf(float x){
103 return(float(rand() * x) / float(RAND_MAX));
107 //----------------------------------------------------------------------------
110 // Flux context to allow many instances.
111 static FluxWidget* _fc = 0;
113 static int whichparticle;
116 // This class is poorly named. It's actually a whole trail of particles.
117 class particle
119 public:
121 particle();
122 ~particle();
123 float update(float *c);
125 private:
127 float** vertices;
128 short trails;
129 short counter;
130 float offset[3];
134 particle::particle()
136 // Offsets are somewhat like default positions for the head of each
137 // particle trail. Offsets spread out the particle trails and keep
138 // them from all overlapping.
139 offset[0] = cos(PIx2 * float(whichparticle) / float(_fc->dParticles));
140 offset[1] = float(whichparticle) / float(_fc->dParticles) - 0.5f;
141 offset[2] = sin(PIx2 * float(whichparticle) / float(_fc->dParticles));
142 whichparticle++;
144 // Initialize memory and set initial positions out of view of the camera
145 trails = _fc->dTrail;
146 vertices = new float*[ trails ];
148 int i;
149 for(i=0; i<trails; i++)
151 vertices[i] = new float[5]; // 0,1,2 = position, 3 = hue, 4 = saturation
152 vertices[i][0] = 0.0f;
153 vertices[i][1] = 3.0f;
154 vertices[i][2] = 0.0f;
155 vertices[i][3] = 0.0f;
156 vertices[i][4] = 0.0f;
159 counter = 0;
163 particle::~particle()
165 for(int i=0; i<trails; i++)
166 delete[] vertices[i];
167 delete[] vertices;
171 float particle::update(float *c)
173 int i, p, growth;
174 float rgb[3];
175 float cx, cy, cz; // Containment variables
176 float luminosity;
177 static float expander = 1.0f + 0.0005f * float(_fc->dExpansion);
178 static float blower = 0.001f * float(_fc->dWind);
179 //static float otherxyz[3];
180 float depth = 0;
182 // Record old position
183 int oldc = counter;
184 float oldpos[3];
185 oldpos[0] = vertices[oldc][0];
186 oldpos[1] = vertices[oldc][1];
187 oldpos[2] = vertices[oldc][2];
189 counter ++;
190 if(counter >= _fc->dTrail)
191 counter = 0;
193 // Here's the iterative math for calculating new vertex positions
194 // first calculate limiting terms which keep vertices from constantly
195 // flying off to infinity
196 cx = vertices[oldc][0] * (1.0f - 1.0f / (vertices[oldc][0] * vertices[oldc][0] + 1.0f));
197 cy = vertices[oldc][1] * (1.0f - 1.0f / (vertices[oldc][1] * vertices[oldc][1] + 1.0f));
198 cz = vertices[oldc][2] * (1.0f - 1.0f / (vertices[oldc][2] * vertices[oldc][2] + 1.0f));
199 // then calculate new positions
200 vertices[counter][0] = vertices[oldc][0] + c[6] * offset[0] - cx
201 + c[2] * vertices[oldc][1]
202 + c[5] * vertices[oldc][2];
203 vertices[counter][1] = vertices[oldc][1] + c[6] * offset[1] - cy
204 + c[1] * vertices[oldc][2]
205 + c[4] * vertices[oldc][0];
206 vertices[counter][2] = vertices[oldc][2] + c[6] * offset[2] - cz
207 + c[0] * vertices[oldc][0]
208 + c[3] * vertices[oldc][1];
210 // Pick a hue
211 vertices[counter][3] = cx * cx + cy * cy + cz * cz;
212 if(vertices[counter][3] > 1.0f)
213 vertices[counter][3] = 1.0f;
214 vertices[counter][3] += c[7];
215 // Limit the hue (0 - 1)
216 if(vertices[counter][3] > 1.0f)
217 vertices[counter][3] -= 1.0f;
218 if(vertices[counter][3] < 0.0f)
219 vertices[counter][3] += 1.0f;
220 // Pick a saturation
221 vertices[counter][4] = c[0] + vertices[counter][3];
222 // Limit the saturation (0 - 1)
223 if(vertices[counter][4] < 0.0f)
224 vertices[counter][4] = -vertices[counter][4];
225 vertices[counter][4] -= float(int(vertices[counter][4]));
226 vertices[counter][4] = 1.0f - (vertices[counter][4] * vertices[counter][4]);
228 // Bring particles back if they escape
229 if(!counter){
230 if((vertices[0][0] > 1000000000.0f) || (vertices[0][0] < -1000000000.0f)
231 || (vertices[0][1] > 1000000000.0f) || (vertices[0][1] < -1000000000.0f)
232 || (vertices[2][2] > 1000000000.0f) || (vertices[0][2] < -1000000000.0f)){
233 vertices[0][0] = myRandf(2.0f) - 1.0f;
234 vertices[0][1] = myRandf(2.0f) - 1.0f;
235 vertices[0][2] = myRandf(2.0f) - 1.0f;
239 // Draw every vertex in particle trail
240 p = counter;
241 growth = 0;
242 luminosity = _fc->lumdiff;
243 for(i=0; i<_fc->dTrail; i++){
244 p ++;
245 if(p >= _fc->dTrail)
246 p = 0;
247 growth++;
249 // assign color to particle
250 hsl2rgb(vertices[p][3], vertices[p][4], luminosity, rgb[0], rgb[1], rgb[2]);
251 glColor3fv(rgb);
253 glPushMatrix();
254 if(_fc->dGeometry == 1) // Spheres
255 glTranslatef(vertices[p][0], vertices[p][1], vertices[p][2]);
256 else{ // Points or lights
257 depth = _fc->cosCameraAngle * vertices[p][2] - _fc->sinCameraAngle * vertices[p][0];
258 glTranslatef(_fc->cosCameraAngle * vertices[p][0] + _fc->sinCameraAngle
259 * vertices[p][2], vertices[p][1], depth);
261 if(_fc->dGeometry){ // Spheres or lights
262 switch(_fc->dTrail - growth){
263 case 0:
264 glScalef(0.259f, 0.259f, 0.259f);
265 break;
266 case 1:
267 glScalef(0.5f, 0.5f, 0.5f);
268 break;
269 case 2:
270 glScalef(0.707f, 0.707f, 0.707f);
271 break;
272 case 3:
273 glScalef(0.866f, 0.866f, 0.866f);
274 break;
275 case 4:
276 glScalef(0.966f, 0.966f, 0.966f);
279 switch(_fc->dGeometry){
280 case 0: // Points
281 switch(_fc->dTrail - growth){
282 case 0:
283 glPointSize(float(_fc->dSize * (depth + 200.0f) * 0.001036f));
284 break;
285 case 1:
286 glPointSize(float(_fc->dSize * (depth + 200.0f) * 0.002f));
287 break;
288 case 2:
289 glPointSize(float(_fc->dSize * (depth + 200.0f) * 0.002828f));
290 break;
291 case 3:
292 glPointSize(float(_fc->dSize * (depth + 200.0f) * 0.003464f));
293 break;
294 case 4:
295 glPointSize(float(_fc->dSize * (depth + 200.0f) * 0.003864f));
296 break;
297 default:
298 glPointSize(float(_fc->dSize * (depth + 200.0f) * 0.004f));
300 glBegin(GL_POINTS);
301 glVertex3f(0.0f,0.0f,0.0f);
302 glEnd();
303 break;
304 case 1: // Spheres
305 case 2: // Lights
306 glCallList(1);
308 glPopMatrix();
309 vertices[p][0] *= expander;
310 vertices[p][1] *= expander;
311 vertices[p][2] *= expander;
312 vertices[p][2] += blower;
313 luminosity += _fc->lumdiff;
316 // Find distance between new position and old position and return it
317 oldpos[0] -= vertices[counter][0];
318 oldpos[1] -= vertices[counter][1];
319 oldpos[2] -= vertices[counter][2];
320 return(float(sqrt(oldpos[0] * oldpos[0] + oldpos[1] * oldpos[1] + oldpos[2] * oldpos[2])));
324 // This class is a set of particle trails and constants that enter
325 // into their equations of motion.
326 class flux
328 public:
330 flux();
331 ~flux();
332 void update();
334 particle *particles;
335 int randomize;
336 float c[NUMCONSTS]; // constants
337 float cv[NUMCONSTS]; // constants' change velocities
338 int currentSmartConstant;
339 float oldDistance;
343 flux::flux()
345 whichparticle = 0;
347 particles = new particle[_fc->dParticles];
348 randomize = 1;
350 float instability = _fc->dInstability;
351 int i;
352 for(i=0; i<NUMCONSTS; i++)
354 c[i] = myRandf(2.0f) - 1.0f;
355 cv[i] = myRandf(0.000005f * instability * instability)
356 + 0.000001f * instability * instability;
359 currentSmartConstant = 0;
360 oldDistance = 0.0f;
364 flux::~flux()
366 delete[] particles;
370 void flux::update()
372 int i;
374 // randomize constants
375 if(_fc->dRandomize){
376 randomize --;
377 if(randomize <= 0){
378 for(i=0; i<NUMCONSTS; i++)
379 c[i] = myRandf(2.0f) - 1.0f;
380 int temp = 101 - _fc->dRandomize;
381 temp = temp * temp;
382 randomize = temp + myRandi(temp);
386 // update constants
387 for(i=0; i<NUMCONSTS; i++){
388 c[i] += cv[i];
389 if(c[i] >= 1.0f){
390 c[i] = 1.0f;
391 cv[i] = -cv[i];
393 if(c[i] <= -1.0f){
394 c[i] = -1.0f;
395 cv[i] = -cv[i];
399 // update all particles in this flux field
400 float dist;
401 for(i=0; i<_fc->dParticles; i++)
402 dist = particles[i].update(c);
404 // use dist from last particle to activate smart constants
405 _fc->dSmart = 0;
406 if(_fc->dSmart){
407 const float upper = 0.4f;
408 const float lower = 0.2f;
409 int beSmart = 0;
410 if(dist > upper && dist > oldDistance)
411 beSmart = 1;
412 if(dist < lower && dist < oldDistance)
413 beSmart = 1;
414 if(beSmart){
415 cv[currentSmartConstant] = -cv[currentSmartConstant];
416 currentSmartConstant ++;
417 if(currentSmartConstant >= _fc->dSmart)
418 currentSmartConstant = 0;
420 oldDistance = dist;
425 //----------------------------------------------------------------------------
428 FluxWidget::FluxWidget( QWidget* parent )
429 : QGLWidget(parent), _fluxes(0)
431 setDefaults( Regular );
433 _frameTime = 1000 / 60;
434 _timer = new QTimer( this );
435 connect( _timer, SIGNAL(timeout()), this, SLOT(nextFrame()) );
439 FluxWidget::~FluxWidget()
441 // Free memory
442 delete[] _fluxes;
446 void FluxWidget::paintGL()
448 // clear the screen
449 glLoadIdentity();
451 if(dBlur) // partially
453 int viewport[4];
454 glGetIntegerv(GL_VIEWPORT, viewport);
455 float viewRatio = float(viewport[2]) / float(viewport[3]);
457 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
458 glEnable(GL_BLEND);
459 glDisable(GL_DEPTH_TEST);
460 glColor4f(0.0f, 0.0f, 0.0f, 0.5f - (float(sqrt(sqrt(double(dBlur)))) * 0.15495f));
461 glBegin(GL_TRIANGLE_STRIP);
462 glVertex3f(-3.0f * viewRatio, -3.0f, 0.0f);
463 glVertex3f(3.0f * viewRatio, -3.0f, 0.0f);
464 glVertex3f(-3.0f * viewRatio, 3.0f, 0.0f);
465 glVertex3f(3.0f * viewRatio, 3.0f, 0.0f);
466 glEnd();
468 else // completely
470 glClear(GL_COLOR_BUFFER_BIT);
473 cameraAngle += 0.01f * float(dRotation);
474 if(cameraAngle >= 360.0f)
475 cameraAngle -= 360.0f;
476 if(dGeometry == 1) // Only rotate for spheres
477 glRotatef(cameraAngle, 0.0f, 1.0f, 0.0f);
478 else
480 cosCameraAngle = cos(cameraAngle * DEG2RAD);
481 sinCameraAngle = sin(cameraAngle * DEG2RAD);
484 // set up blend modes for rendering particles
485 switch(dGeometry)
487 case 0: // Blending for points
488 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
489 glEnable(GL_BLEND);
490 glEnable(GL_POINT_SMOOTH);
491 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
492 break;
494 case 1: // No blending for spheres, but we need z-buffering
495 glDisable(GL_BLEND);
496 glEnable(GL_DEPTH_TEST);
497 glClear(GL_DEPTH_BUFFER_BIT);
498 break;
500 case 2: // Blending for lights
501 glBlendFunc(GL_ONE, GL_ONE);
502 glEnable(GL_BLEND);
505 // Update particles
506 if( _fluxes )
508 _fc = this;
509 int i;
510 for(i=0; i<dFluxes; i++)
511 _fluxes[i].update();
514 glFlush();
518 void FluxWidget::resizeGL( int w, int h )
520 glViewport(0, 0, w, h );
522 glMatrixMode(GL_PROJECTION);
523 glLoadIdentity();
524 gluPerspective(100.0, (float) w / (float) h, 0.01, 200);
525 glTranslatef(0.0, 0.0, -2.5);
526 glMatrixMode(GL_MODELVIEW);
527 glLoadIdentity();
531 // Window initialization
532 void FluxWidget::initializeGL()
534 //resizeGL( width(), height() );
536 updateParameters();
537 _timer->setSingleShot(true);
538 _timer->start( _frameTime );
542 #ifdef UNIT_TEST
543 void FluxWidget::keyPressEvent( QKeyEvent* e )
545 if( e->key() == Qt::Key_0 ) { setDefaults( 0 ); updateParameters(); }
546 if( e->key() == Qt::Key_1 ) { setDefaults( 1 ); updateParameters(); }
547 if( e->key() == Qt::Key_2 ) { setDefaults( 2 ); updateParameters(); }
548 if( e->key() == Qt::Key_3 ) { setDefaults( 3 ); updateParameters(); }
549 if( e->key() == Qt::Key_4 ) { setDefaults( 4 ); updateParameters(); }
550 if( e->key() == Qt::Key_5 ) { setDefaults( 5 ); updateParameters(); }
552 #endif
555 void FluxWidget::nextFrame()
557 updateGL();
558 _timer->setSingleShot(true);
559 _timer->start( _frameTime );
564 May be called at any time - makes no OpenGL calls.
566 void FluxWidget::setDefaults( int which )
568 switch(which)
570 case Hypnotic:
571 dFluxes = 2;
572 dParticles = 10;
573 dTrail = 40;
574 dGeometry = 2;
575 dSize = 15;
576 dRandomize = 80;
577 dExpansion = 20;
578 dRotation = 0;
579 dWind = 40;
580 dInstability = 10;
581 dBlur = 30;
582 break;
584 case Insane:
585 dFluxes = 4;
586 dParticles = 30;
587 dTrail = 8;
588 dGeometry = 2;
589 dSize = 25;
590 dRandomize = 0;
591 dExpansion = 80;
592 dRotation = 60;
593 dWind = 40;
594 dInstability = 100;
595 dBlur = 10;
596 break;
598 case Sparklers:
599 dFluxes = 3;
600 dParticles = 20;
601 dTrail = 6;
602 dGeometry = 1;
603 dSize = 20;
604 dComplexity = 3;
605 dRandomize = 85;
606 dExpansion = 60;
607 dRotation = 30;
608 dWind = 20;
609 dInstability = 30;
610 dBlur = 0;
611 break;
613 case Paradigm:
614 dFluxes = 1;
615 dParticles = 40;
616 dTrail = 40;
617 dGeometry = 2;
618 dSize = 5;
619 dRandomize = 90;
620 dExpansion = 30;
621 dRotation = 20;
622 dWind = 10;
623 dInstability = 5;
624 dBlur = 10;
625 break;
627 case Galactic:
628 dFluxes = 1;
629 dParticles = 2;
630 dTrail = 1500;
631 dGeometry = 2;
632 dSize = 10;
633 dRandomize = 0;
634 dExpansion = 5;
635 dRotation = 25;
636 dWind = 0;
637 dInstability = 5;
638 dBlur = 0;
639 break;
641 case Regular:
642 default:
643 dFluxes = 1;
644 dParticles = 20;
645 dTrail = 40;
646 dGeometry = 2;
647 dSize = 15;
648 dRandomize = 0;
649 dExpansion = 40;
650 dRotation = 30;
651 dWind = 20;
652 dInstability = 20;
653 dBlur = 0;
654 break;
660 Called after dGeometry, dTrail, or dFluxes is changed
661 (such as with setDefaults).
663 void FluxWidget::updateParameters()
665 int i, j;
666 float x, y, temp;
668 srand((unsigned)time(NULL));
669 rand(); rand(); rand(); rand(); rand();
671 cameraAngle = 0.0f;
673 glFrontFace(GL_CCW);
674 glEnable(GL_CULL_FACE);
675 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
676 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
678 if(dGeometry == 0)
680 glDisable(GL_LIGHTING);
681 glDisable(GL_COLOR_MATERIAL);
682 glDisable(GL_TEXTURE_2D);
684 glEnable(GL_POINT_SMOOTH);
685 //glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
687 else if(dGeometry == 1) // Spheres and their lighting
689 glNewList(1, GL_COMPILE);
690 GLUquadricObj* qobj = gluNewQuadric();
691 gluSphere(qobj, 0.005f * dSize, dComplexity + 2, dComplexity + 1);
692 gluDeleteQuadric(qobj);
693 glEndList();
695 glDisable(GL_TEXTURE_2D);
696 glEnable(GL_LIGHTING);
697 glEnable(GL_LIGHT0);
699 float ambient[4] = {0.0f, 0.0f, 0.0f, 0.0f};
700 float diffuse[4] = {1.0f, 1.0f, 1.0f, 0.0f};
701 float specular[4] = {1.0f, 1.0f, 1.0f, 0.0f};
702 float position[4] = {500.0f, 500.0f, 500.0f, 0.0f};
704 glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
705 glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
706 glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
707 glLightfv(GL_LIGHT0, GL_POSITION, position);
708 glEnable(GL_COLOR_MATERIAL);
709 glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
711 else if(dGeometry == 2) // Init lights
713 for(i=0; i<LIGHTSIZE; i++)
715 for(j=0; j<LIGHTSIZE; j++)
717 x = float(i - LIGHTSIZE / 2) / float(LIGHTSIZE / 2);
718 y = float(j - LIGHTSIZE / 2) / float(LIGHTSIZE / 2);
719 temp = 1.0f - float(sqrt((x * x) + (y * y)));
720 if(temp > 1.0f)
721 temp = 1.0f;
722 if(temp < 0.0f)
723 temp = 0.0f;
724 lightTexture[i][j] = (unsigned char) (255.0f * temp * temp);
728 glDisable(GL_LIGHTING);
729 glDisable(GL_COLOR_MATERIAL);
731 glEnable(GL_TEXTURE_2D);
732 glBindTexture(GL_TEXTURE_2D, 1);
733 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
734 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
735 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
736 glTexImage2D(GL_TEXTURE_2D, 0, 1, LIGHTSIZE, LIGHTSIZE, 0,
737 GL_LUMINANCE, GL_UNSIGNED_BYTE, lightTexture);
739 temp = float(dSize) * 0.005f;
740 glNewList(1, GL_COMPILE);
741 glBindTexture(GL_TEXTURE_2D, 1);
742 glBegin(GL_TRIANGLES);
743 glTexCoord2f(0.0f, 0.0f);
744 glVertex3f(-temp, -temp, 0.0f);
745 glTexCoord2f(1.0f, 0.0f);
746 glVertex3f(temp, -temp, 0.0f);
747 glTexCoord2f(1.0f, 1.0f);
748 glVertex3f(temp, temp, 0.0f);
749 glTexCoord2f(0.0f, 0.0f);
750 glVertex3f(-temp, -temp, 0.0f);
751 glTexCoord2f(1.0f, 1.0f);
752 glVertex3f(temp, temp, 0.0f);
753 glTexCoord2f(0.0f, 1.0f);
754 glVertex3f(-temp, temp, 0.0f);
755 glEnd();
756 glEndList();
759 // Initialize luminosity difference
760 lumdiff = 1.0f / float(dTrail);
762 _fc = this;
763 delete[] _fluxes;
764 _fluxes = new flux[dFluxes];
768 //----------------------------------------------------------------------------
771 #ifndef UNIT_TEST
772 #include <klocale.h>
773 #include <kglobal.h>
774 #include <kconfig.h>
777 // libkscreensaver interface
778 class KFluxSaverInterface : public KScreenSaverInterface
782 public:
783 virtual KAboutData* aboutData() {
784 return new KAboutData( "kflux.kss", 0, ki18n( "Flux" ), "1.0", ki18n( "Flux" ) );
788 virtual KScreenSaver* create( WId id )
790 return new KFluxScreenSaver( id );
793 virtual QDialog* setup()
795 return new KFluxSetup;
799 int main( int argc, char *argv[] )
801 KFluxSaverInterface kss;
802 return kScreenSaverMain( argc, argv, kss );
806 //----------------------------------------------------------------------------
809 KFluxScreenSaver::KFluxScreenSaver( WId id ) : KScreenSaver( id )
811 _flux = new FluxWidget;
813 readSettings();
815 embed( _flux );
816 _flux->show();
820 KFluxScreenSaver::~KFluxScreenSaver()
825 static int filterRandom( int n )
827 if( (n < 0) || (n >= FluxWidget::DefaultModes) )
829 srand((unsigned)time(NULL));
830 n = rand() % FluxWidget::DefaultModes;
832 return n;
836 void KFluxScreenSaver::readSettings()
838 KConfigGroup config(KGlobal::config(), "Settings");
840 _mode = config.readEntry( "Mode", (int)FluxWidget::Regular );
841 _flux->setDefaults( filterRandom(_mode) );
846 Any invalid mode will select one at random.
848 void KFluxScreenSaver::setMode( int id )
850 _mode = id;
851 _flux->setDefaults( filterRandom(id) );
852 _flux->updateParameters();
856 //----------------------------------------------------------------------------
859 #include <qlayout.h>
860 #include <qpushbutton.h>
861 #include <qlabel.h>
862 #include <qcombobox.h>
863 #include <kmessagebox.h>
866 static const char* defaultText[] =
868 I18N_NOOP( "Regular" ),
869 I18N_NOOP( "Hypnotic" ),
870 I18N_NOOP( "Insane" ),
871 I18N_NOOP( "Sparklers" ),
872 I18N_NOOP( "Paradigm" ),
873 I18N_NOOP( "Galactic" ),
874 I18N_NOOP( "(Random)" ),
879 KFluxSetup::KFluxSetup( QWidget* parent )
880 : KDialog( parent)
882 setButtonText( Help, i18n( "A&bout" ) );
883 setButtons(Ok|Cancel|Help);
884 setDefaultButton(Ok);
885 setModal(true);
886 showButtonSeparator(true);
887 QWidget *main = new QWidget(this);
888 setMainWidget(main);
890 QHBoxLayout* top = new QHBoxLayout( main );
891 top->setSpacing( spacingHint() );
892 QVBoxLayout* leftCol = new QVBoxLayout;
893 top->addLayout( leftCol );
895 // Parameters
896 QLabel* label = new QLabel( i18n("Mode:"), main );
897 leftCol->addWidget( label );
899 modeW = new QComboBox( main );
900 int i = 0;
901 while (defaultText[i])
902 modeW->addItem( i18n(defaultText[i++]) );
903 leftCol->addWidget( modeW );
905 leftCol->addStretch();
907 // Preview
908 QWidget* preview;
909 preview = new QWidget( main );
910 preview->setFixedSize( 220, 165 );
912 QPalette palette;
913 palette.setColor( preview->backgroundRole(), Qt::black );
914 preview->setPalette( palette );
916 preview->show(); // otherwise saver does not get correct size
917 _saver = new KFluxScreenSaver( preview->winId() );
918 top->addWidget(preview);
920 // Now that we have _saver...
921 modeW->setCurrentIndex( _saver->mode() ); // set before we connect
922 connect( modeW, SIGNAL(activated(int)), _saver, SLOT(setMode(int)) );
923 connect( this, SIGNAL(okClicked()), SLOT(slotOk()));
924 connect(this, SIGNAL(helpClicked()),SLOT(slotHelp()));
928 KFluxSetup::~KFluxSetup()
930 delete _saver;
934 void KFluxSetup::slotHelp()
936 KMessageBox::about(this,
937 i18n("<h3>Flux 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>"),
938 QString(), KMessageBox::AllowLink);
943 Ok pressed - save settings and exit
945 void KFluxSetup::slotOk()
947 KConfigGroup config(KGlobal::config(), "Settings");
949 QString val;
950 val.setNum( modeW->currentIndex() );
951 config.writeEntry("Mode", val );
953 config.sync();
954 accept();
956 #endif
959 //----------------------------------------------------------------------------
962 #ifdef UNIT_TEST
963 // moc Flux.h -o Flux.moc
964 // g++ -g -DUNIT_TEST Flux.cpp -I/usr/lib/qt3/include -lqt -L/usr/lib/qt3/lib -lGLU -lGL
966 #include <qapplication.h>
968 int main( int argc, char** argv )
970 QApplication app( argc, argv );
972 FluxWidget w;
973 w.setDefaults( FluxWidget::Sparklers );
974 app.setMainWidget( &w );
975 w.show();
977 return app.exec();
979 #endif
982 //EOF