Back to index

kdeartwork  4.3.2
kvm.cpp
Go to the documentation of this file.
00001 /*-
00002  * kvm.cpp - The Vm screensaver for KDE
00003  * Copyright (c) 2000 by Artur Rataj
00004  * This file is distributed under the terms of the GNU General Public License
00005  *
00006  * This file is partially based on kmatrix screen saver -- original copyright follows:
00007  * kmatrix.c - The Matrix screensaver for KDE
00008  * by Eric Plante Copyright (c) 1999
00009  * Distributed under the Gnu Public License
00010  *
00011  * Much of this code taken from xmatrix.c from xscreensaver;
00012  * original copyright follows:
00013  * xscreensaver, Copyright (c) 1999 Jamie Zawinski <jwz@jwz.org>
00014  *
00015  * Permission to use, copy, modify, distribute, and sell this software and its
00016  * documentation for any purpose is hereby granted without fee, provided that
00017  * the above copyright notice appear in all copies and that both that
00018  * copyright notice and this permission notice appear in supporting
00019  * documentation.  No representations are made about the suitability of this
00020  * software for any purpose.  It is provided "as is" without express or
00021  * implied warranty.
00022  *
00023  */
00024 // layout management added 1998/04/19 by Mario Weilguni <mweilguni@kde.org>
00025 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 
00029 /* for AIX at least */
00030 #include <time.h>
00031 
00032 #include <qcolor.h>
00033 #include <qlabel.h>
00034 #include <qlayout.h>
00035 #include <qslider.h>
00036 #include <qpainter.h>
00037 #include <qbitmap.h>
00038 
00039 #include <kapplication.h>
00040 #include <kconfig.h>
00041 #include <klocale.h>
00042 #include <kglobal.h>
00043 #include <kmessagebox.h>
00044 
00045 #ifdef DEBUG_MEM
00046 #include <mcheck.h>
00047 #endif
00048 
00049 #include "kvm.h"
00050 
00051 #include "vm.xpm"
00052 #include "vm.xbm"
00053 
00054 #define CHAR_HEIGHT 22
00055 
00056 
00057 // libkscreensaver interface
00058 class kVmSaverInterface : public KScreenSaverInterface
00059 {
00060 
00061 
00062 public:
00063     virtual KAboutData* aboutData() {
00064         return new KAboutData( "kvm.kss", "klock", ki18n( "Virtual Machine" ), "2.2.0", ki18n( "Virtual Machine" ) );
00065     }
00066 
00067 
00068     virtual KScreenSaver* create( WId id )
00069     {
00070         return new kVmSaver( id );
00071     }
00072 
00073     virtual QDialog* setup()
00074     {
00075         return new kVmSetup();
00076     }
00077 };
00078 
00079 int main( int argc, char *argv[] )
00080 {
00081     kVmSaverInterface kss;
00082     return kScreenSaverMain( argc, argv, kss );
00083 }
00084 
00085 
00086 
00087 static void
00088 load_images (m_state *state)
00089 {
00090   if ( QPixmap::defaultDepth() > 1 )
00091     {
00092       state->images = QPixmap( vm );
00093     }
00094   else
00095     {
00096       state->images = QBitmap::fromData( QSize(vm_width, vm_height), vm_bits );
00097     }
00098   state->image_width = state->images.width();
00099   state->image_height = state->images.height();
00100   state->nglyphs = state->image_height / CHAR_HEIGHT;
00101 }
00102 
00103 
00104 static m_state *
00105 init_pool ( QWidget *w )
00106 {
00107   m_state *state = new m_state;
00108   state->w = w;
00109 
00110   load_images (state);
00111 
00112   state->char_width = state->image_width / 4;
00113   state->char_height = CHAR_HEIGHT;
00114 
00115   state->grid_width  = w->width()  / state->char_width;
00116   state->grid_height = w->height() / state->char_height;
00117   state->grid_margin_x = w->width()%state->char_width/2;
00118   state->grid_margin_y = w->height()%state->char_height/2;
00119   state->show_threads = 1;
00120   vm_init_pool( &(state->pool), state->grid_width*state->grid_height,
00121                 THREAD_MAX_STACK_SIZE, MAX_THREADS_NUM );
00122    //vm_enable_reverse( state->pool, 1 );
00123    state->modified = new char[state->grid_height*state->grid_width];
00124    for( int x = 0; x < state->grid_width*state->grid_height; ++x )
00125     state->modified[x] = 1;
00126   return state;
00127 }
00128 
00129 static void
00130 draw_pool (m_state *state)
00131 {
00132   int x, y;
00133   struct tvm_process*       curr_thread;
00134 
00135   if( state->show_threads ) {
00136    curr_thread = state->pool->processes;
00137    while( curr_thread ) {
00138     state->modified[curr_thread->position] = 2;
00139     curr_thread = curr_thread->next;
00140    }
00141   }
00142   for (y = 0; y < state->grid_height; y++)
00143     for (x = 0; x < state->grid_width; x++) {
00144      int index = state->grid_width * y + x;
00145      if( state->modified[index] )
00146       {
00147         int op = state->pool->area[index];
00148         int pos_y;
00149         int pos_x = 0;
00150         switch( op ) {
00151          case VM_OP_STOP:
00152           pos_y = 14;
00153           break;
00154 
00155          case VM_OP_EXEC:
00156           pos_y = 15;
00157           break;
00158 
00159          case VM_OP_COPY:
00160           pos_y = 12;
00161           break;
00162 
00163          default:
00164           pos_y = op - VM_OP_PUSH;
00165           if( pos_y < 0 ) {
00166            pos_y = -pos_y;
00167            pos_x = 1;
00168           }
00169           break;
00170         }
00171         if( state->show_threads )
00172          if( state->modified[index] == 1 )
00173           pos_x += 2;
00174           QPainter p(state->w);
00175           p.setPen( Qt::green );
00176           p.setBrush( Qt::black );
00177           p.drawPixmap( state->grid_margin_x + x*state->char_width,
00178                          state->grid_margin_y + y*state->char_height,
00179                          state->images, pos_x*state->char_width,
00180                          pos_y*state->char_height,
00181                          state->char_width, state->char_height );
00182        --state->modified[index];
00183       }
00184     }
00185 }
00186 
00187 //-----------------------------------------------------------------------------
00188 
00189 kVmSaver::kVmSaver( WId id ) : KScreenSaver( id )
00190 {
00191        readSettings();
00192 
00193         QPalette palette;
00194         palette.setColor( backgroundRole(), Qt::black );
00195         setPalette( palette );
00196        setAutoFillBackground(true);
00197 
00198         setSpeed( speed );
00199         setRefreshTimeout( refreshTimeout );
00200 
00201         refreshStep = 0;
00202 
00203         pool_state = init_pool( this );
00204         vm_default_initstate( time(0), &(pool_state->pool->vm_random_data) );
00205        connect( &timer, SIGNAL( timeout() ), SLOT( update() ) );
00206         timer.start( 100 - speed );
00207         show();
00208 }
00209 
00210 kVmSaver::~kVmSaver()
00211 {
00212        timer.stop();
00213         vm_done_pool( pool_state->pool );
00214         delete[] pool_state->modified;
00215 }
00216 
00217 void kVmSaver::setSpeed( int spd )
00218 {
00219        speed = spd;
00220 //     timer.start( (100 - speed)*(100 - speed)*(100 - speed)/10000 );
00221        timer.start( (100 - speed) );
00222 }
00223 void kVmSaver::setRefreshTimeout( const int refreshTimeout )
00224 {
00225  this->refreshTimeout = refreshTimeout;
00226 }
00227 
00228 void kVmSaver::readSettings()
00229 {
00230        KConfigGroup config(KGlobal::config(), "Settings");
00231 
00232        speed = config.readEntry( "Speed", 50 );
00233        refreshTimeout = config.readEntry( "DisplayRefreshTimeout", 0 );
00234 }
00235 int kVmSaver::getRandom( const int max_value ) {
00236  return (int)( vm_random(&(pool_state->pool->vm_random_data))*1.0*(max_value + 1.0)/
00237                (VM_RAND_MAX + 1.0) );
00238 // return (int)( rand()*1.0*(max_value + 1.0)/
00239 //               (RAND_MAX + 1.0) );
00240 }
00241 void kVmSaver::modifyArea( const int op ) {
00242  int position;
00243 
00244  vm_modify( pool_state->pool, position =
00245             getRandom(pool_state->pool->area_size - 1), op );
00246  pool_state->modified[position] = 1;
00247 }
00248 
00249 void kVmSaver::paintEvent(QPaintEvent *)
00250 {
00251  setAttribute( Qt::WA_NoSystemBackground ); // Only after initial clear
00252 
00253  for( int i = 0; i < 1; ++i ) {
00254   if( getRandom(2) == 0 )
00255    modifyArea( VM_OP_PUSH + getRandom(11) - getRandom(11) );
00256   if( getRandom(8) == 0 )
00257    modifyArea( VM_OP_STOP );
00258   if( getRandom(8) == 0 )
00259    modifyArea( VM_OP_COPY );
00260   if( getRandom(8) == 0 )
00261    modifyArea( VM_OP_EXEC );
00262 //  if( getRandom(5) == 0 )
00263 //   modifyArea( VM_OP_WAIT );
00264  }
00265  if( getRandom(0) == 0 )
00266   vm_exec( pool_state->pool, getRandom(pool_state->pool->area_size - 1), 0,
00267            vm_get_reverse( pool_state->pool ) );
00268  vm_iterate( pool_state->pool, pool_state->modified );
00269 // if( refreshStep++ >= refreshTimeout*refreshTimeout*refreshTimeout ) {
00270  if( refreshStep++ >= refreshTimeout ) {
00271   draw_pool( pool_state );
00272   refreshStep = 0;
00273  }
00274 }
00275 
00276 //-----------------------------------------------------------------------------
00277 
00278 kVmSetup::kVmSetup( QWidget *parent )
00279        : KDialog( parent)
00280 {
00281        setCaption(i18n( "Setup Virtual Machine" ));
00282        setButtons(Ok|Cancel|Help);
00283        setDefaultButton(Ok);
00284        setModal(true);
00285        readSettings();
00286 
00287        setButtonText( Help, i18n( "A&bout" ) );
00288        QWidget *main = new QWidget(this);
00289        setMainWidget(main);
00290 
00291        QHBoxLayout *tl = new QHBoxLayout( main );
00292         tl->setSpacing( spacingHint() );
00293        QVBoxLayout *tl1 = new QVBoxLayout();
00294        tl->addLayout(tl1);
00295 
00296        QLabel *label = new QLabel( i18n("Virtual machine speed:"), main );
00297        tl1->addWidget(label);
00298 
00299        QSlider *slider = new QSlider( Qt::Horizontal, main );
00300        slider->setMinimumSize( 120, 20 );
00301        slider->setRange( 0, 100 );
00302         slider->setSingleStep( 10 );
00303        slider->setPageStep( 20 );
00304        slider->setTickPosition( QSlider::TicksBelow );
00305        slider->setTickInterval( 10 );
00306        slider->setValue( speed );
00307        connect( slider, SIGNAL( valueChanged( int ) ),
00308                SLOT( slotSpeed( int ) ) );
00309        tl1->addWidget(slider);
00310 
00311        label = new QLabel( i18n("Display update speed:"), main );
00312        tl1->addWidget(label);
00313 
00314        slider = new QSlider( Qt::Horizontal, main );
00315        slider->setMinimumSize( 120, 20 );
00316        slider->setRange( 0, MAX_REFRESH_TIMEOUT );
00317        slider->setSingleStep( MAX_REFRESH_TIMEOUT/10 );
00318        slider->setPageStep( MAX_REFRESH_TIMEOUT/5 );
00319        slider->setTickPosition( QSlider::TicksBelow );
00320        slider->setTickInterval( MAX_REFRESH_TIMEOUT/10 );
00321        slider->setValue( MAX_REFRESH_TIMEOUT - refreshTimeout );
00322        connect( slider, SIGNAL( valueChanged( int ) ),
00323                SLOT( slotRefreshTimeout( int ) ) );
00324        tl1->addWidget(slider);
00325        tl1->addStretch();
00326 
00327        preview = new QWidget( main );
00328        preview->setFixedSize( 220, 165 );
00329        preview->show();    // otherwise saver does not get correct size
00330        saver = new kVmSaver( preview->winId() );
00331        tl->addWidget(preview);
00332        connect(this,SIGNAL(okClicked()),this,SLOT(slotOk()));
00333        connect(this,SIGNAL(helpClicked()),this,SLOT(slotHelp()));
00334 }
00335 
00336 kVmSetup::~kVmSetup()
00337 {
00338     delete saver;
00339 }
00340 
00341 void kVmSetup::readSettings()
00342 {
00343        KConfigGroup config(KGlobal::config(), "Settings");
00344 
00345        speed = config.readEntry( "Speed", 50 );
00346        if ( speed > 100 )
00347               speed = 100;
00348        else if ( speed < 0 )
00349               speed = 0;
00350        refreshTimeout = config.readEntry( "DisplayRefreshTimeout", 0 );
00351        if ( refreshTimeout > MAX_REFRESH_TIMEOUT )
00352               refreshTimeout = MAX_REFRESH_TIMEOUT;
00353        else if ( refreshTimeout < 0 )
00354               refreshTimeout = 0;
00355 }
00356 
00357 void kVmSetup::slotSpeed( int num )
00358 {
00359        speed = num;
00360        if ( saver )
00361               saver->setSpeed( num );
00362 }
00363 void kVmSetup::slotRefreshTimeout( int num )
00364 {
00365        refreshTimeout = MAX_REFRESH_TIMEOUT - num;
00366        if ( saver )
00367               saver->setRefreshTimeout( refreshTimeout );
00368 }
00369 
00370 void kVmSetup::slotOk()
00371 {
00372        KConfigGroup config(KGlobal::config(), "Settings");
00373 
00374        QString sspeed;
00375        sspeed.setNum( speed );
00376        config.writeEntry( "Speed", sspeed );
00377        sspeed.setNum( refreshTimeout );
00378        config.writeEntry( "DisplayRefreshTimeout", sspeed );
00379 
00380        config.sync();
00381        accept();
00382 }
00383 
00384 void kVmSetup::slotHelp()
00385 {
00386        KMessageBox::about(this,
00387               i18n("Virtual Machine Version 0.1\n\nCopyright (c) 2000 Artur Rataj <art@zeus.polsl.gliwice.pl>\n"),
00388                i18n("About Virtual Machine")
00389        );
00390 }
00391 
00392 #include "kvm.moc"
00393