Connect signal/slot
[kdeartwork.git] / kscreensaver / kdesavers / science.cpp
blobf12ca2825c214daf8aef34beb199625d59a95c95
1 //-----------------------------------------------------------------------------
2 //
3 // kscience - screen saver for KDE
4 //
5 // Copyright (c) Rene Beutler 1998
6 //
8 #include <config.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <sys/types.h>
13 #include <time.h>
15 #include <qpainter.h>
16 #include <qpixmap.h>
17 #include <qlabel.h>
18 #include <q3listbox.h>
19 #include <qcheckbox.h>
20 #include <qslider.h>
21 #include <qlayout.h>
22 //Added by qt3to4:
23 #include <QVBoxLayout>
24 #include <QHBoxLayout>
25 #include <QPaintEvent>
27 #include <kapplication.h>
28 #include <kglobal.h>
29 #include <kmessagebox.h>
30 #include <klocale.h>
31 #include <kconfig.h>
32 #include <kstandarddirs.h>
33 #include <krandomsequence.h>
35 #include "science.h"
36 #include "science.moc"
38 #if defined Q_WS_X11 && !defined K_WS_QTONLY
39 #include <X11/Xlib.h>
40 #include <X11/Xutil.h>
41 #endif
43 #define SCI_DEFAULT_MODE 0
44 #define SCI_DEFAULT_MOVEX 6
45 #define SCI_DEFAULT_MOVEY 8
46 #define SCI_DEFAULT_SIZE 15
47 #define SCI_DEFAULT_INTENSITY 4
48 #define SCI_DEFAULT_SPEED 70
49 #define SCI_DEFAULT_INVERSE false
50 #define SCI_DEFAULT_GRAVITY false
51 #define SCI_DEFAULT_HIDE false
52 #define SCI_MAX_SPEED 100
53 #define SCI_MAX_MOVE 20
55 #undef Below
58 // libkscreensaver interface
59 class KScienceSaverInterface : public KScreenSaverInterface
63 public:
64 virtual KAboutData* aboutData() {
65 return new KAboutData( "kscience.kss", I18N_NOOP( "Science Screen Saver" ), "2.2.0", I18N_NOOP( "Science Screen Saver" ) );
69 virtual KScreenSaver* create( WId id )
71 return new KScienceSaver( id );
74 virtual QDialog* setup()
76 return new KScienceSetup();
80 int main( int argc, char *argv[] )
82 KScienceSaverInterface kss;
83 return kScreenSaverMain( argc, argv, kss );
86 static struct {
87 QString name;
88 bool inverseEnable;
89 } modeInfo[MAX_MODES];
91 enum { MODE_WHIRL=0, MODE_CURVATURE, MODE_SPHERE, MODE_WAVE, MODE_EXPONENTIAL, MODE_CONTRACTION };
93 void initModeInfo()
95 modeInfo[MODE_WHIRL].name = i18n( "Whirl" );
96 modeInfo[MODE_WHIRL].inverseEnable = true;
98 modeInfo[MODE_SPHERE].name = i18n( "Sphere" );
99 modeInfo[MODE_SPHERE].inverseEnable = true;
101 modeInfo[MODE_EXPONENTIAL].name = i18n( "Exponential" );
102 modeInfo[MODE_EXPONENTIAL].inverseEnable = false;
104 modeInfo[MODE_CONTRACTION].name = i18n( "Contraction" );
105 modeInfo[MODE_CONTRACTION].inverseEnable = false;
107 modeInfo[MODE_WAVE].name = i18n( "Wave" );
108 modeInfo[MODE_WAVE].inverseEnable = false;
110 modeInfo[MODE_CURVATURE].name = i18n( "Curvature" );
111 modeInfo[MODE_CURVATURE].inverseEnable = true;
114 //-----------------------------------------------------------------------------
115 // KPreviewWidget
118 KPreviewWidget::KPreviewWidget( QWidget *parent ) :
119 QWidget ( parent ) { }
121 void KPreviewWidget::paintEvent( QPaintEvent *event )
123 if( saver != 0 )
124 saver->do_refresh( event->rect() );
127 void KPreviewWidget::notifySaver( KScienceSaver *s )
129 saver = s;
132 //-----------------------------------------------------------------------------
133 // Screen Saver
136 struct KScienceData
138 T32bit **offset;
139 XImage *buffer;
140 XImage *xRootWin;
141 GC gc;
144 KScienceSaver::KScienceSaver( WId id, bool s, bool gP )
145 : KScreenSaver( id )
147 d = new KScienceData;
148 d->gc = XCreateGC(QX11Info::display(), id, 0, 0);
149 d->xRootWin = 0;
150 d->buffer = 0;
152 moveOn = true;
153 grabPixmap = gP;
154 setup = s;
156 vx = vy = 0.0;
157 readSettings();
159 if( !grabPixmap )
161 grabRootWindow();
162 initialize();
163 do_refresh( QRect ( 0, 0, width(), height() ) );
166 connect( &timer, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
167 timer.start( SCI_MAX_SPEED - speed[mode] );
170 KScienceSaver::~KScienceSaver()
172 timer.stop();
173 releaseLens();
174 if ( d->xRootWin )
175 XDestroyImage( d->xRootWin );
176 XFreeGC(QX11Info::display(), d->gc );
177 delete d;
180 void KScienceSaver::myAssert( bool term, const char *eMsg )
182 if( !term ) {
183 fprintf(stderr, "Error in KScreensaver - mode Science: %s\n", eMsg);
184 releaseLens();
185 exit(-1);
189 void KScienceSaver::initialize()
191 KRandomSequence rnd;
192 initLens();
193 signed int ws = (signed int) (width() - diam);
194 signed int hs = (signed int) (height() - diam);
196 x = (ws > 0) ? (rnd.getDouble() * ws ) : 0.0;
197 y = (hs > 0) ? (rnd.getDouble() * hs ) : 0.0;
199 xcoord = (int) x;
200 ycoord = (int) y;
202 switch( bpp ) {
203 case 1 : applyLens = &KScienceSaver::applyLens8bpp; break;
204 case 2 : applyLens = &KScienceSaver::applyLens16bpp; break;
205 case 3 : applyLens = &KScienceSaver::applyLens24bpp; break;
206 case 4 : applyLens = &KScienceSaver::applyLens32bpp; break;
207 default: myAssert( false, "unsupported colordepth "\
208 "(only 8, 16, 24, 32 bpp supported)" );
212 void KScienceSaver::initWhirlLens()
214 double dx, dy, r, phi, intens;
215 T32bit *off;
216 T32bit xo, yo;
218 intens = double( intensity[mode] + 1) / 5.0;
219 if( inverse[mode] )
220 intens = -intens;
222 for(int y = side-1; y >= 0; y--)
224 dy = y - origin;
225 off = d->offset[y] = (T32bit *) malloc(sizeof(T32bit) * side);
226 myAssert( off != 0, "too few memory" );
227 for(int x = side-1; x >= 0; x--)
229 dx = x - origin;
230 r = sqrt( dx*dx + dy*dy );
232 if( r < radius )
234 if ( dx == 0.0 )
235 phi = (dy > 0.0) ? M_PI_2 :-(M_PI_2);
236 else
237 phi = atan2( dy, dx );
238 phi += intens * ( radius - r ) / ( r+7.0 );
239 xo = (T32bit) ( origin + r*cos( phi ) - x );
240 yo = (T32bit) ( origin + r*sin( phi ) - y );
241 off[x] = xo*bpp + yo*imgnext;
243 else
244 if( hideBG[mode] )
245 off[x] = (border-y)*imgnext + (border-x)*bpp;
246 else
247 off[x] = 0;
252 void KScienceSaver::initSphereLens()
254 double dx, dy, r, xr, yr, phi, intens;
255 T32bit *off;
256 T32bit xo, yo;
258 intens = 1.0 - double( intensity[mode] ) / 20.0;
260 if( inverse[mode] )
261 intens = -intens;
263 for(int y = side-1; y >= 0; y--)
265 dy = y - origin;
266 off = d->offset[y] = (T32bit *) malloc(sizeof(T32bit) * side);
267 myAssert( off != 0, "too few memory" );
268 for(int x = side-1; x >= 0; x--)
270 dx = x - origin;
271 r = sqrt( dx*dx + dy*dy );
273 if( r < radius )
275 xr = (double) radius*cos(asin(dy/radius));
276 yr = (double) radius*cos(asin(dx/radius));
277 phi = (xr != 0.0) ? asin(dx/xr) : 0.0;
278 xo = (T32bit) (origin + intens*2.0*phi*xr / M_PI - x);
279 phi = (yr != 0.0) ? asin(dy/yr) : 0.0;
280 yo = (T32bit) (origin + intens*2.0*phi*yr / M_PI - y);
281 off[x] = xo*bpp + yo*imgnext;
283 else
284 if( hideBG[mode] )
285 off[x] = (border-y)*imgnext + (border-x)*bpp;
286 else
287 off[x] = 0;
292 void KScienceSaver::initExponentialLens()
294 double dx, dy, r, rnew, f, intens;
295 T32bit *off;
296 T32bit xo, yo;
298 if( mode == MODE_EXPONENTIAL )
299 intens = - (0.1 + 0.8 * double( intensity[mode] + 2) / 10.0);
300 else
301 intens = 0.9 - 0.8 * double( intensity[mode] ) / 10.0;
303 for(int y = side-1; y >= 0; y--)
305 dy = y - origin;
306 off = d->offset[y] = (T32bit *) malloc(sizeof(T32bit) * side);
307 myAssert( off != 0, "too few memory" );
308 for(int x = side-1; x >= 0; x--)
310 dx = x - origin;
311 r = sqrt( dx*dx + dy*dy );
313 if( r < radius )
315 if( r == 0.0 )
316 f = 0.0;
317 else
319 rnew = radius*(pow(r, intens) / pow(radius, intens));
320 f = double ((int)rnew % radius) / r;
322 xo = (T32bit) ( origin + f*dx - x );
323 yo = (T32bit) ( origin + f*dy - y );
324 off[x] = xo*bpp + yo*imgnext;
326 else
327 if( hideBG[mode] )
328 off[x] = (border-y)*imgnext + (border-x)*bpp;
329 else
330 off[x] = 0;
335 void KScienceSaver::initCurvatureLens()
337 double dx, dy, r, f, intens;
338 T32bit *off;
339 T32bit xo, yo;
341 intens = (double) radius*intensity[mode] / 20.0;
342 if( inverse[mode] ) intens = -intens;
344 for(int y = side-1; y >= 0; y--)
346 dy = y - origin;
347 off = d->offset[y] = (T32bit *) malloc(sizeof(T32bit) * side);
348 myAssert( off != 0, "too few memory" );
349 for(int x = side-1; x >= 0; x--)
351 dx = x - origin;
352 r = sqrt( dx*dx + dy*dy );
354 if( r < radius )
356 if( r == 0.0 )
357 f = 0.0;
358 else
359 f = (r - intens * sin(M_PI * r/(double)radius)) / r;
360 xo = (T32bit) ( origin + f*dx - x );
361 yo = (T32bit) ( origin + f*dy - y );
362 off[x] = xo*bpp + yo*imgnext;
364 else
365 if( hideBG[mode] )
366 off[x] = (border-y)*imgnext + (border-x)*bpp;
367 else
368 off[x] = 0;
373 void KScienceSaver::initWaveLens()
375 double dx, dy, r, rnew, f, intens, k;
376 T32bit *off;
377 T32bit xo, yo;
379 intens = (double) intensity[mode] + 1.0;
380 k = (intensity[mode] % 2) ? -12.0 : 12.0;
382 for(int y = side-1; y >= 0; y--)
384 dy = y - origin;
385 off = d->offset[y] = (T32bit *) malloc(sizeof(T32bit) * side);
386 myAssert( off != 0, "too few memory" );
387 for(int x = side-1; x >= 0; x--)
389 dx = x - origin;
390 r = sqrt( dx*dx + dy*dy );
392 if( r < radius )
394 if( r == 0.0 )
395 f = 0.0;
396 else
398 rnew = r - k * sin( M_PI * intens * r/(double)radius);
399 f = double ((int)rnew % radius) / r;
401 xo = (T32bit) ( origin + f*dx - x );
402 yo = (T32bit) ( origin + f*dy - y );
403 off[x] = xo*bpp + yo*imgnext;
405 else
406 if( hideBG[mode] )
407 off[x] = (border-y)*imgnext + (border-x)*bpp;
408 else
409 off[x] = 0;
414 void KScienceSaver::initLens()
416 int min = (width() < height()) ? width() : height();
417 border = 1 + SCI_MAX_MOVE;
419 radius = (size[mode] * min) / 100;
420 if( radius<<1 == min ) radius--;
421 diam = radius << 1;
422 myAssert( diam < min, "assertion violated: diam < min" );
423 origin = radius + border;
424 side = origin << 1;
426 d->buffer = XSubImage( d->xRootWin, 0, 0, side, side );
427 myAssert( d->buffer != 0, "can't allocate pixmap" );
429 d->offset = (T32bit **) malloc( sizeof(T32bit *) * side );
430 myAssert( d->offset != 0, "too few memory" );
432 switch( mode ) {
433 case MODE_WHIRL: initWhirlLens(); break;
434 case MODE_SPHERE: initSphereLens(); break;
435 case MODE_EXPONENTIAL:
436 case MODE_CONTRACTION: initExponentialLens(); break;
437 case MODE_CURVATURE: initCurvatureLens(); break;
438 case MODE_WAVE: initWaveLens(); break;
439 default: myAssert( false, "internal error (wrong mode in initLens() )" );
443 void KScienceSaver::releaseLens()
445 if( d->offset != 0 ) {
446 for(int i=0; i<side; i++)
447 if( d->offset[i] != 0 ) free( d->offset[i] );
448 free( d->offset );
449 d->offset = 0;
451 if( d->buffer != 0 ) {
452 XDestroyImage( d->buffer );
453 d->buffer = 0;
457 void KScienceSaver::setMode( int m )
459 timer.stop();
461 releaseLens();
462 int old = mode;
463 mode = m;
464 vx = copysign( moveX[mode], vx );
465 vy = copysign( moveY[mode], vy );
466 int dm = diam;
467 initLens();
468 if( hideBG[old] ^ hideBG[m] )
469 do_refresh( QRect( 0, 0, width(), height() ) );
470 else
471 if( diam < dm )
473 do_refresh( QRect( (int) x+diam, (int) y, dm-diam, diam ) );
474 do_refresh( QRect( (int) x, (int) y+diam, dm, dm-diam ) );
477 timer.start( SCI_MAX_SPEED - speed[mode] );
480 void KScienceSaver::setMoveX( int s )
482 timer.stop();
484 moveX[mode] = s;
485 vx = copysign( moveX[mode], vx );
487 timer.start( SCI_MAX_SPEED - speed[mode] );
490 void KScienceSaver::setMoveY( int s )
492 timer.stop();
494 moveY[mode] = s;
495 vy = copysign( moveY[mode], vy );
497 timer.start( SCI_MAX_SPEED - speed[mode] );
500 void KScienceSaver::setMove( bool s )
502 moveOn = s;
505 void KScienceSaver::setSize( int s )
507 timer.stop();
509 releaseLens();
510 int dm = diam;
511 size[mode] = s;
512 initLens();
513 if( diam < dm )
515 do_refresh( QRect( (int) x+diam, (int) y, dm-diam, diam ) );
516 do_refresh( QRect( (int) x, (int) y+diam, dm, dm-diam ) );
519 timer.start( SCI_MAX_SPEED - speed[mode] );
522 void KScienceSaver::setSpeed( int s )
524 speed[mode] = s;
526 timer.changeInterval( SCI_MAX_SPEED - speed[mode] );
529 void KScienceSaver::setIntensity( int i )
531 timer.stop();
533 releaseLens();
534 intensity[mode] = i;
535 initLens();
537 timer.start( SCI_MAX_SPEED - speed[mode]);
540 void KScienceSaver::setInverse( bool b )
542 timer.stop();
544 releaseLens();
545 inverse[mode] = b;
546 initLens();
548 timer.start( SCI_MAX_SPEED - speed[mode]);
551 void KScienceSaver::setGravity( bool b )
553 timer.stop();
555 releaseLens();
556 gravity[mode] = b;
557 vy = copysign( moveY[mode], vy );
558 initLens();
560 timer.start( SCI_MAX_SPEED - speed[mode]);
563 void KScienceSaver::setHideBG( bool b )
565 timer.stop();
567 releaseLens();
568 hideBG[mode] = b;
569 initLens();
570 do_refresh( QRect( 0, 0, width(), height() ) );
572 timer.start( SCI_MAX_SPEED - speed[mode]);
575 void KScienceSaver::readSettings()
577 KConfig *config = KGlobal::config();
578 QString sMode;
580 config->setGroup( "Settings" );
581 mode = config->readNumEntry( "ModeNr", SCI_DEFAULT_MODE );
583 for(int i=0; i < MAX_MODES; i++)
585 sMode.setNum( i );
586 config->setGroup( "Mode" + sMode );
587 moveX[i] = config->readNumEntry( "MoveX", SCI_DEFAULT_MOVEX);
588 moveY[i] = config->readNumEntry( "MoveY", SCI_DEFAULT_MOVEY);
589 size[i] = config->readNumEntry( "Size", SCI_DEFAULT_SIZE);
590 speed[i] = config->readNumEntry( "Speed", SCI_DEFAULT_SPEED);
591 intensity[i] = config->readNumEntry( "Intensity", SCI_DEFAULT_INTENSITY);
592 inverse[i] = config->readBoolEntry( "Inverse", SCI_DEFAULT_INVERSE);
593 gravity[i] = config->readBoolEntry( "Gravity", SCI_DEFAULT_GRAVITY);
594 hideBG[i] = config->readBoolEntry( "HideBG", SCI_DEFAULT_HIDE);
597 vx = copysign( moveX[mode], vx );
598 vy = copysign( moveY[mode], vy );
601 void KScienceSaver::do_refresh( const QRect & rect )
603 if( grabPixmap )
604 return;
605 rect.normalize();
607 if( hideBG[mode] )
609 XSetWindowBackground( QX11Info::display(), winId(), QColor(Qt::black).pixel() );
610 XClearArea( QX11Info::display(), winId(), rect.left(), rect.top(),
611 rect.width(), rect.height(), false );
613 else
615 myAssert( d->xRootWin != 0, "root window not grabbed" );
616 XPutImage( QX11Info::display(), winId(), d->gc, d->xRootWin,
617 rect.left(), rect.top(),
618 rect.left(), rect.top(),
619 rect.width(), rect.height() );
623 void KScienceSaver::slotTimeout()
625 if( grabPixmap ) {
626 if( !QWidget::find(winId())->isActiveWindow() )
627 return;
628 grabPreviewWidget();
629 grabPixmap = false;
630 initialize();
631 if( hideBG[mode] )
632 do_refresh( QRect ( 0, 0, width(), height() ) );
635 signed int oldx = xcoord, oldy = ycoord;
637 if( gravity[mode] ) {
638 double h = double(y+1.0) / double(height()-diam);
639 if( h > 1.0 ) h = 1.0;
640 vy = sqrt( h ) * ( (vy > 0.0) ? moveY[mode] : -moveY[mode] );
642 myAssert( abs((int)rint(vy)) <= border, "assertion violated: vy <= border" );
644 if( moveOn )
646 x += vx;
647 y += vy;
650 if( x <= 0.0 ) {
651 vx = -vx;
652 x = 0.0;
654 if( int(x) + diam >= width()) {
655 vx = -vx;
656 myAssert( width()-diam > 0, "assertion violated: width-diam > 0" );
657 x = (double) (width() - diam - 1);
659 if( y <= 0.0 ) {
660 vy = -vy;
661 y = 0.0;
663 if( int(y) + diam >= height() ) {
664 vy = -vy;
665 myAssert( height() - diam > 0, "assertion violated: height-diam > 0" );
666 y = (double) (height() - diam - 1);
669 xcoord = (int) x ;
670 ycoord = (int) y ;
671 signed int dx = (signed int) xcoord - oldx;
672 signed int dy = (signed int) ycoord - oldy;
673 signed int xs, ys, xd, yd, w, h;
675 if( dx > 0 ) {
676 w = diam+dx;
677 xd = oldx;
678 xs = border-dx;
679 if( dy > 0 ) {
680 h = diam+dy;
681 yd = oldy;
682 ys = border-dy;
684 else {
685 h = diam-dy;
686 yd = ycoord;
687 ys = border;
690 else {
691 w = diam-dx;
692 xd = xcoord;
693 xs = border;
694 if( dy > 0 ) {
695 h = diam+dy;
696 yd = oldy;
697 ys = border-dy;
698 } else {
699 h = diam-dy;
700 yd = ycoord;
701 ys = border;
705 if( xd + w >= width() ) w = width() - xd - 1;
706 if( yd + h >= height() ) h = height() - yd - 1;
708 //printf("%d: (dx: %3d, dy: %3d), diam: %3d, (xc: %3d, yc: %3d), (xs: %3d, ys: %3d), (xd: %3d, yd: %3d), (w: %3d, h: %3d)\n", mode, dx, dy, diam, xcoord, ycoord, xs, ys, xd, yd, w, h);
709 myAssert( dx <= border && dy <=border, "assertion violated: dx or dy <= border");
710 myAssert( xcoord >= 0 && ycoord >= 0, "assertion violated: xcoord, ycoord >= 0 ");
711 myAssert( xd+w < width(), "assertion violated: xd+w < width" );
712 myAssert( yd+h < height(), "assertion violated: yd+h < height" );
714 if( hideBG[mode] )
715 blackPixel( xcoord, ycoord );
716 (this->*applyLens)(xs, ys, xd, yd, w, h);
717 XPutImage( QX11Info::display(), winId(), d->gc, d->buffer, 0, 0, xd, yd, w, h );
718 if( hideBG[mode] )
719 blackPixelUndo( xcoord, ycoord );
722 void KScienceSaver::grabRootWindow()
724 Display *dsp = QX11Info::display();
725 Window rootwin = RootWindow( dsp, QX11Info::appScreen() );
727 // grab contents of root window
728 if( d->xRootWin )
729 XDestroyImage( d->xRootWin );
731 d->xRootWin = XGetImage( dsp, rootwin, 0, 0, width(),
732 height(), AllPlanes, ZPixmap);
733 myAssert( d->xRootWin, "unable to grab root window\n" );
735 imgnext = d->xRootWin->bytes_per_line;
736 bpp = ( d->xRootWin->bits_per_pixel ) >> 3;
739 void KScienceSaver::grabPreviewWidget()
741 myAssert( QWidget::find(winId())->isActiveWindow(), "can't grab preview widget: dialog not active()" );
743 if( d->xRootWin )
744 XDestroyImage( d->xRootWin );
746 Display *dsp = QX11Info::display();
747 d->xRootWin = XGetImage( dsp, winId(), 0, 0, width(), height(), AllPlanes, ZPixmap);
748 myAssert( d->xRootWin, "unable to grab preview window\n" );
750 imgnext = d->xRootWin->bytes_per_line;
751 bpp = ( d->xRootWin->bits_per_pixel ) >> 3;
754 void KScienceSaver::blackPixel( int x, int y )
756 unsigned char black = (char) BlackPixel( QX11Info::display(), QX11Info::appScreen() );
757 unsigned int adr = x*bpp + y*imgnext;
759 for(int i=0; i<bpp; i++) {
760 blackRestore[i] = d->xRootWin->data[adr];
761 d->xRootWin->data[adr++] = black;
765 void KScienceSaver::blackPixelUndo( int x, int y )
767 unsigned int adr = x*bpp + y*imgnext;
768 for(int i=0; i<bpp; i++)
769 d->xRootWin->data[adr++] = blackRestore[i];
772 // hm....
774 void KScienceSaver::applyLens8bpp(int xs, int ys, int xd, int yd, int w, int h)
776 T32bit *off;
777 char *img1, *img2, *data;
778 signed int ix, iy, datanext = d->buffer->bytes_per_line - w;
780 img1 = d->xRootWin->data + xd + yd*imgnext;
781 data = d->buffer->data;
782 for(iy = ys; iy < ys+h; iy++)
784 off = d->offset[iy] + xs;
785 img2 = img1;
786 for(ix = w; ix > 0; ix--)
787 *data++ = img2++[*off++];
788 img1 += imgnext;
789 data += datanext;
794 void KScienceSaver::applyLens16bpp(int xs, int ys, int xd, int yd, int w, int h)
796 T32bit *off;
797 char *img1, *img2, *data;
798 int ix, iy, datanext = d->buffer->bytes_per_line - (w << 1);
800 img1 = d->xRootWin->data + (xd << 1) + yd*imgnext;
801 data = d->buffer->data;
802 for(iy = ys; iy < ys+h; iy++)
804 off = d->offset[iy] + xs;
805 img2 = img1;
806 for(ix = w; ix > 0; ix--) {
807 *data++ = img2++[*off];
808 *data++ = img2++[*off++];
810 img1 += imgnext;
811 data += datanext;
815 void KScienceSaver::applyLens24bpp(int xs, int ys, int xd, int yd, int w, int h)
817 T32bit *off;
818 char *img1, *img2, *data;
819 signed int ix, iy, datanext = d->buffer->bytes_per_line - 3*w;
821 img1 = d->xRootWin->data + 3*xd + yd*imgnext;
822 data = d->buffer->data;
823 for(iy = ys; iy < ys+h; iy++)
825 off = d->offset[iy] + xs;
826 img2 = img1;
827 for(ix = w; ix > 0; ix--) {
828 *data++ = img2++[*off];
829 *data++ = img2++[*off];
830 *data++ = img2++[*off++];
832 img1 += imgnext;
833 data += datanext;
837 void KScienceSaver::applyLens32bpp(int xs, int ys, int xd, int yd, int w, int h)
839 T32bit *off;
840 char *img1, *img2, *data;
841 signed int ix, iy, datanext = d->buffer->bytes_per_line - (w << 2);
843 img1 = d->xRootWin->data + (xd << 2) + yd*imgnext;
844 data = d->buffer->data;
845 for(iy = ys; iy < ys+h; iy++)
847 off = d->offset[iy] + xs;
848 img2 = img1;
849 for(ix = w; ix > 0; ix--) {
850 *data++ = img2++[*off];
851 *data++ = img2++[*off];
852 *data++ = img2++[*off];
853 *data++ = img2++[*off++];
855 img1 += imgnext;
856 data += datanext;
861 //-----------------------------------------------------------------------------
863 KScienceSetup::KScienceSetup( QWidget *parent, const char *name )
864 : KDialog( parent)
865 , saver( 0 )
867 setCaption(i18n( "Setup Science Screen Saver" ));
868 setModal(true);
869 setButtons(Ok|Cancel|Help);
870 setDefaultButton(Ok);
871 showButtonSeparator(true);
872 readSettings();
873 initModeInfo();
875 QWidget *main = new QWidget(this);
876 setMainWidget(main);
878 QHBoxLayout *lt = new QHBoxLayout( main, 0, spacingHint());
879 QVBoxLayout *ltm = new QVBoxLayout;
880 lt->addLayout( ltm );
881 QVBoxLayout *ltc = new QVBoxLayout;
882 lt->addLayout( ltc );
884 // mode
885 QLabel *label = new QLabel( i18n("Mode:"), main );
886 ltm->addWidget( label );
888 Q3ListBox *c = new Q3ListBox( main );
889 for(int i = 0; i<MAX_MODES; i++)
890 c->insertItem( modeInfo[i].name );
891 c->setCurrentItem( mode );
892 c->setFixedHeight( 5 * c->fontMetrics().height() );
893 connect( c, SIGNAL( highlighted( int ) ), SLOT( slotMode( int ) ) );
894 ltm->addWidget( c );
896 // inverse
897 QCheckBox *cbox = checkInverse = new QCheckBox( i18n("Inverse"), main );
898 cbox->setEnabled( modeInfo[mode].inverseEnable );
899 cbox->setChecked( inverse[mode] );
900 connect( cbox, SIGNAL( clicked() ), SLOT( slotInverse() ) );
901 ltm->addWidget( cbox );
903 // gravity
904 cbox = checkGravity = new QCheckBox( i18n("Gravity"), main );
905 cbox->setChecked( gravity[mode] );
906 connect( cbox, SIGNAL( clicked() ), SLOT( slotGravity() ) );
907 ltm->addWidget( cbox );
909 // hide background
910 cbox = checkHideBG = new QCheckBox( i18n("Hide background"), main );
911 cbox->setChecked( hideBG[mode] );
912 connect( cbox, SIGNAL( clicked() ), SLOT( slotHideBG() ) );
913 ltm->addWidget( cbox );
914 ltm->addStretch();
916 // size
917 label = new QLabel( i18n("Size:"), main );
918 ltc->addWidget( label );
920 slideSize = new QSlider(9, 50, 5, size[mode], Qt::Horizontal,
921 main );
922 slideSize->setMinimumSize( 90, 20 );
923 slideSize->setTickPosition(QSlider::TicksBelow);
924 slideSize->setTickInterval(5);
925 connect( slideSize, SIGNAL( sliderMoved( int ) ),
926 SLOT( slotSize( int ) ) );
927 connect( slideSize, SIGNAL( sliderPressed() ),
928 SLOT( slotSliderPressed() ) );
929 connect( slideSize, SIGNAL( sliderReleased() ),
930 SLOT( slotSliderReleased() ) );
932 ltc->addWidget( slideSize );
934 // intensity
935 label = new QLabel( i18n("Intensity:"), main );
936 ltc->addWidget( label );
938 slideIntensity = new QSlider(0, 10, 1, intensity[mode],
939 Qt::Horizontal, main );
940 slideIntensity->setMinimumSize( 90, 20 );
941 slideIntensity->setTickPosition(QSlider::TicksBelow);
942 slideIntensity->setTickInterval(1);
943 connect( slideIntensity, SIGNAL( sliderMoved( int ) ),
944 SLOT( slotIntensity( int )) );
945 connect( slideIntensity, SIGNAL( sliderPressed() ),
946 SLOT( slotSliderPressed() ) );
947 connect( slideIntensity, SIGNAL( sliderReleased() ),
948 SLOT( slotSliderReleased() ) );
949 ltc->addWidget( slideIntensity );
951 // speed
952 label = new QLabel( i18n("Speed:"), main );
953 ltc->addWidget( label );
955 slideSpeed = new QSlider(0, SCI_MAX_SPEED, 10, speed[mode],
956 Qt::Horizontal, main );
957 slideSpeed->setMinimumSize( 90, 20 );
958 slideSpeed->setTickPosition(QSlider::TicksBelow);
959 slideSpeed->setTickInterval(10);
960 connect( slideSpeed, SIGNAL( sliderMoved( int ) ),
961 SLOT( slotSpeed( int ) ) );
962 ltc->addWidget( slideSpeed );
964 // motion
965 label = new QLabel( i18n("Motion:"), main );
966 ltc->addWidget( label );
968 QHBoxLayout *ltcm = new QHBoxLayout;
969 ltc->addLayout( ltcm );
971 slideMoveX = new QSlider(0, SCI_MAX_MOVE, 5, moveX[mode],
972 Qt::Horizontal, main );
973 slideMoveX->setMinimumSize( 40, 20 );
974 slideMoveX->setTickPosition(QSlider::TicksBelow);
975 slideMoveX->setTickInterval(5);
976 connect( slideMoveX, SIGNAL( sliderMoved( int ) ),
977 SLOT( slotMoveX( int ) ) );
978 ltcm->addWidget( slideMoveX );
980 slideMoveY = new QSlider(0, SCI_MAX_MOVE, 5, moveY[mode],
981 Qt::Horizontal, main );
982 slideMoveY->setMinimumSize( 40, 20 );
983 slideMoveY->setTickPosition(QSlider::TicksBelow);
984 slideMoveY->setTickInterval(5);
985 connect( slideMoveY, SIGNAL( sliderMoved( int ) ),
986 SLOT( slotMoveY( int ) ) );
987 ltcm->addWidget( slideMoveY );
989 ltc->addStretch();
991 // preview
992 preview = new KPreviewWidget( main );
993 preview->setFixedSize( 220, 170 );
994 QPixmap p( KStandardDirs::locate("data", "kscreensaver/pics/kscience.png") );
995 if( p.isNull() )
996 preview->setBackgroundColor( Qt::black );
997 else
998 preview->setBackgroundPixmap( p );
999 preview->show(); // otherwise saver does not get correct size
1000 lt->addWidget( preview );
1002 // let the preview window display before creating the saver
1003 kapp->processEvents();
1005 saver = new KScienceSaver( preview->winId(), true, !p.isNull() );
1006 preview->notifySaver( saver );
1007 connect(this,SIGNAL(okClicked()),SLOT(slotOk()));
1010 KScienceSetup::~KScienceSetup()
1012 delete saver; // be sure to delete this first
1015 void KScienceSetup::updateSettings()
1017 // update dialog
1018 slideMoveX ->setValue( moveX[mode] );
1019 slideMoveY ->setValue( moveY[mode] );
1020 slideSize ->setValue( size[mode] );
1021 slideSpeed ->setValue( speed[mode] );
1022 slideIntensity->setValue( intensity[mode] );
1023 checkInverse ->setEnabled( modeInfo[mode].inverseEnable );
1024 checkInverse ->setChecked( inverse[mode] );
1025 checkGravity ->setChecked( gravity[mode] );
1026 checkHideBG ->setChecked( hideBG[mode] );
1029 // read settings from config file
1030 void KScienceSetup::readSettings()
1032 KConfig *config = KGlobal::config();
1033 QString sMode;
1035 config->setGroup( "Settings" );
1036 mode = config->readNumEntry( "ModeNr", SCI_DEFAULT_MODE );
1038 for(int i=0; i < MAX_MODES; i++)
1040 sMode.setNum( i );
1041 config->setGroup( "Mode" + sMode );
1042 moveX[i] = config->readNumEntry( "MoveX", SCI_DEFAULT_MOVEX);
1043 moveY[i] = config->readNumEntry( "MoveY", SCI_DEFAULT_MOVEY);
1044 size[i] = config->readNumEntry( "Size", SCI_DEFAULT_SIZE);
1045 speed[i] = config->readNumEntry( "Speed", SCI_DEFAULT_SPEED);
1046 intensity[i] = config->readNumEntry( "Intensity", SCI_DEFAULT_INTENSITY);
1047 inverse[i] = config->readBoolEntry( "Inverse", SCI_DEFAULT_INVERSE);
1048 gravity[i] = config->readBoolEntry( "Gravity", SCI_DEFAULT_GRAVITY);
1049 hideBG[i] = config->readBoolEntry( "HideBG", SCI_DEFAULT_HIDE);
1053 void KScienceSetup::slotMode( int m )
1055 mode = m;
1057 if( saver )
1058 saver->setMode( mode );
1060 updateSettings();
1063 void KScienceSetup::slotInverse( )
1065 inverse[mode] = checkInverse->isChecked();
1067 if( saver )
1068 saver->setInverse( inverse[mode] );
1071 void KScienceSetup::slotGravity( )
1073 gravity[mode] = checkGravity->isChecked();
1075 if( saver )
1076 saver->setGravity( gravity[mode] );
1079 void KScienceSetup::slotHideBG( )
1081 hideBG[mode] = checkHideBG->isChecked();
1083 if( saver )
1084 saver->setHideBG( hideBG[mode] );
1087 void KScienceSetup::slotMoveX( int x )
1089 moveX[mode] = x;
1091 if( saver )
1092 saver->setMoveX( x );
1095 void KScienceSetup::slotMoveY( int y )
1097 moveY[mode] = y;
1099 if( saver )
1100 saver->setMoveY( y );
1103 void KScienceSetup::slotSize( int s )
1105 size[mode] = s;
1107 if( saver )
1108 saver->setSize( s );
1111 void KScienceSetup::slotSpeed( int s )
1113 speed[mode] = s;
1115 if( saver )
1116 saver->setSpeed( s );
1119 void KScienceSetup::slotIntensity( int i )
1121 intensity[mode] = i;
1123 if( saver )
1124 saver->setIntensity( i );
1127 void KScienceSetup::slotSliderPressed()
1129 if( saver )
1130 saver->setMove( false );
1133 void KScienceSetup::slotSliderReleased()
1135 if( saver )
1136 saver->setMove( true );
1139 // Ok pressed - save settings and exit
1140 void KScienceSetup::slotOk()
1142 KConfig *config = KGlobal::config();
1143 QString sSize, sSpeed, sIntensity, sMode;
1145 config->setGroup( "Settings" );
1146 config->writeEntry( "ModeNr", mode );
1148 for(int i=0; i<MAX_MODES; i++)
1150 sMode.setNum( i );
1151 config->setGroup( "Mode" + sMode );
1152 config->writeEntry( "MoveX", moveX[i] );
1153 config->writeEntry( "MoveY", moveY[i] );
1154 config->writeEntry( "Size", size[i] );
1155 config->writeEntry( "Speed", speed[i] );
1156 config->writeEntry( "Intensity", intensity[i] );
1157 config->writeEntry( "Inverse", inverse[i] );
1158 config->writeEntry( "Gravity", gravity[i] );
1159 config->writeEntry( "HideBG", hideBG[i] );
1162 config->sync();
1164 accept();
1167 void KScienceSetup::slotHelp()
1169 QString about = i18n("Science Version 0.26.5\n\nWritten by Rene Beutler (1998)\nrbeutler@g26.ethz.ch");
1170 KMessageBox::about(this,
1171 about);