Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

zonemap.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 // changes by Maximilian Reiss <harlekin@handhelds.org>
00022 
00023 #include "sun.h"
00024 #include "zonemap.h"
00025 
00026 /* OPIE */
00027 #include <opie2/odebug.h>
00028 #include <opie2/oresource.h>
00029 
00030 #include <qpe/qpeapplication.h>
00031 
00032 /* QT */
00033 #include <qfile.h>
00034 #include <qlabel.h>
00035 #include <qmessagebox.h>
00036 #include <qtextstream.h>
00037 #include <qtimer.h>
00038 #include <qtoolbutton.h>
00039 #include <qlayout.h>
00040 #include <qhbox.h>
00041 #include <qlistview.h>
00042 #include <qwhatsthis.h>
00043 
00044 /* STD */
00045 #include <limits.h>
00046 
00047 // the map file...
00048 static const char strZONEINFO[] = "/usr/share/zoneinfo/zone.tab";
00049 static const char strMAP[] = "citytime/simple_grid_400";
00050 
00051 // the maximum distance we'll allow the pointer to be away from a city
00052 // and still show the city's time
00053 static const int iTHRESHOLD = 50000;
00054 
00055 // The label offset (how far away from pointer)
00056 static const int iLABELOFFSET = 8;
00057 
00058 // the size of the dot to draw, and where to start it
00059 static const int iCITYSIZE = 3;
00060 const int iCITYOFFSET = 2;
00061 
00062 // the darkening function
00063 static inline void darken( QImage *pImage, int start, int stop, int row );
00064 static void dayNight( QImage *pImage );
00065 
00066 ZoneField::ZoneField( const QString& strLine )
00067 {
00068     // make a bunch of RegExp's to match the data from the line
00069     QRegExp regCoord( "[-+][0-9]+" );   // the latitude
00070     QRegExp regCountry( "[A-Za-z]+/" ); // the country (not good enough)
00071     QRegExp regCity( "[A-Za-z_-]*" ); // the city
00072 
00073     int iStart,
00074     iStop,
00075         iLen,
00076         tmp;
00077     QString strTmp;
00078     // we should be able to assume that the country code is always the first
00079     // two chars, so just grap them and let it go...
00080     strCountryCode = strLine.left( 2 );
00081     iStart = regCoord.match( strLine, 0, &iLen );
00082     if ( iStart >= 0 ) {
00083     strTmp = strLine.mid( iStart, iLen );
00084     tmp = strTmp.toInt();
00085     // okay, there are two versions of the format, make a decision based on
00086     // the size...
00087     // Oh BTW, we are storing everything in seconds!
00088     if ( iLen < 7 ) {
00089         _y = tmp / 100;
00090         _y *= 60;
00091         _y += tmp % 100;
00092         _y *= 60;
00093     } else {
00094         _y = tmp / 10000;
00095         _y *= 60;
00096         tmp %= 10000;
00097         _y += tmp / 100;
00098         _y *= 60;
00099         tmp %= 100;
00100         _y += tmp;
00101     }
00102     }
00103     iStart = regCoord.match( strLine, iStart + iLen, &iLen );
00104     if ( iStart >= 0 ) {
00105     strTmp = strLine.mid( iStart, iLen );
00106     tmp = strTmp.toInt();
00107     if ( iLen < 8 ) {
00108         _x = tmp / 100;
00109         _x *= 60;
00110         _x += tmp % 100;
00111         _x *= 60;
00112     } else {
00113         _x = tmp / 10000;
00114         _x *= 60;
00115         tmp %= 10000;
00116         _x += tmp / 100;
00117         _x *= 60;
00118         tmp %= 100;
00119         _x += tmp;
00120     }
00121     }
00122     iStart = regCountry.match( strLine, 0, &iLen );
00123     // help with the shortcoming in 2.x regexp...
00124     iStop = strLine.findRev( '/' );
00125     if ( iStart >= 0 ) {
00126     iLen = (iStop - iStart) + 1;
00127     strCountry = strLine.mid( iStart, iLen );
00128     }
00129     // now match the city...
00130     iStart = regCity.match( strLine, iStart + iLen, &iLen );
00131     if ( iStart >= 0 ) {
00132     strCity = strLine.mid( iStart, iLen );
00133     }
00134 }
00135 
00136 void ZoneField::showStructure( void ) const
00137 {
00138     odebug << "Country: " << strCountry << "" << oendl;
00139     odebug << "City: " << strCity << "" << oendl;
00140     odebug << "x: " << _x << "" << oendl;
00141     odebug << "y: " << _y << "\n" << oendl;
00142 }
00143 
00144 ZoneMap::ZoneMap( QWidget *parent, const char* name )
00145     : QScrollView( parent, name ),
00146       pLast( 0 ),
00147       pRepaint( 0 ),
00148       ox( 0 ),
00149       oy( 0 ),
00150       drawableW( -1 ),
00151       drawableH( -1 ),
00152       bZoom( FALSE ),
00153       bIllum( TRUE ),
00154       cursor( 0 )
00155 {
00156     viewport()->setFocusPolicy( StrongFocus );
00157 
00158     // set mouse tracking so we can use the mouse move event
00159     zones.setAutoDelete( true );
00160     // get the map loaded
00161     // just set the current image to point
00162     pixCurr = new QPixmap();
00163 
00164     QPixmap pixZoom = Opie::Core::OResource::loadPixmap( "mag", Opie::Core::OResource::SmallIcon );
00165 
00166     cmdZoom = new QToolButton( this, "Zoom command" );
00167     cmdZoom->setUsesBigPixmap( qApp->desktop()->size().width() > 330 );
00168     cmdZoom->setPixmap( pixZoom );
00169     cmdZoom->setToggleButton( true );
00170 
00171     cmdZoom->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0,
00172                             (QSizePolicy::SizeType)0,
00173                             cmdZoom->sizePolicy().hasHeightForWidth() ) );
00174     cmdZoom->setMaximumSize( cmdZoom->sizeHint() );
00175     // probably don't need this, but just in case...
00176     cmdZoom->move( width() - cmdZoom->width(), height() - cmdZoom->height() );
00177 
00178 
00179     lblCity = new QLabel( tr( "CITY" ), this, "City Label" );
00180     lblCity->setMinimumSize( lblCity->sizeHint() );
00181     lblCity->setFrameStyle( QFrame::Plain | QFrame::Box );
00182     lblCity->setBackgroundColor( yellow );
00183     lblCity->hide();
00184 
00185     // A timer to make sure the label gets hidden
00186     tHide = new QTimer( this, "Label Timer" );
00187     QObject::connect( tHide, SIGNAL( timeout() ),
00188                       lblCity, SLOT( hide() ) );
00189     QObject::connect( tHide, SIGNAL( timeout() ),
00190                       this, SLOT( slotRedraw() ) );
00191     QTimer *tUpdate = new QTimer( this, "Update Timer" );
00192     QObject::connect( tUpdate, SIGNAL( timeout() ),
00193                       this, SLOT( slotUpdate() ) );
00194     QObject::connect( qApp, SIGNAL( timeChanged() ),
00195                       this, SLOT( slotUpdate() ) );
00196     QObject::connect( cmdZoom, SIGNAL( toggled(bool) ),
00197                       this, SLOT( slotZoom(bool) ) );
00198     QObject::connect( &norm, SIGNAL( signalNewPoint(const QPoint&) ),
00199                       this, SLOT( slotFindCity(const QPoint&) ) );
00200     QObject::connect( qApp, SIGNAL( clockChanged(bool) ),
00201                       this, SLOT( changeClock(bool) ) );
00202     // update the sun's movement every 5 minutes
00203     tUpdate->start( 5 * 60 * 1000 );
00204     // May as well read in the timezone information too...
00205     readZones();
00206 }
00207 
00208 ZoneMap::~ZoneMap()
00209 {
00210 }
00211 
00212 void ZoneMap::readZones( void )
00213 {
00214     QFile fZone( strZONEINFO );
00215     if ( !fZone.open( IO_ReadOnly ) ) {
00216     QMessageBox::warning (this,
00217         tr( "Unable to Find Timezone Info" ),
00218         tr( "<p>Unable to find any timezone information in %1" )
00219         .arg( strZONEINFO ));
00220     exit(-1);
00221     } else {
00222     QTextStream tZone( &fZone );
00223     while ( !tZone.atEnd() ) {
00224         QString strLine = tZone.readLine();
00225         // only pass on lines that aren't comments
00226         if ( strLine[0] != '#' ) {
00227         zones.append( new ZoneField( strLine ) );
00228         }
00229     }
00230     fZone.close();
00231     }
00232 }
00233 
00234 void ZoneMap::viewportMousePressEvent( QMouseEvent* event )
00235 {
00236     // add the mouse event into the normalizer, and get the average,
00237     // pass it along
00238     slotRedraw();
00239     norm.start();
00240     norm.addEvent( event->pos() );
00241 }
00242 
00243 void ZoneMap::viewportMouseMoveEvent( QMouseEvent* event )
00244 {
00245     norm.addEvent( event->pos() );
00246 }
00247 
00248 void ZoneMap::viewportMouseReleaseEvent( QMouseEvent* )
00249 {
00250     // get the averaged points in case a timeout hasn't occurred,
00251     // more for "mouse clicks"
00252     norm.stop();
00253     if ( pLast != NULL ) {
00254     emit signalTz( pLast->country(), pLast->city() );
00255     pLast = NULL;
00256     }
00257     tHide->start( 2000, true );
00258 }
00259 
00260 void ZoneMap::keyPressEvent( QKeyEvent *ke )
00261 {
00262     switch ( ke->key() ) {
00263     case Key_Left:
00264     case Key_Right:
00265     case Key_Up:
00266     case Key_Down: {
00267         tHide->stop();
00268         if ( !cursor )
00269             slotFindCity( QPoint( contentsWidth(), contentsHeight() ) / 2 );
00270         ZoneField *city = findCityNear( cursor, ke->key() );
00271         if ( city ) {
00272             cursor = city;
00273             int tmpx, tmpy;
00274             zoneToWin( cursor->x(), cursor->y(), tmpx, tmpy );
00275             ensureVisible( tmpx, tmpy );
00276             showCity( cursor );
00277             tHide->start( 3000, true );
00278         }
00279         }
00280         break;
00281 
00282     case Key_Space:
00283     case Key_Enter:
00284     case Key_Return:
00285         if ( cursor ) {
00286         emit signalTz( cursor->country(), cursor->city() );
00287         tHide->start( 0, true );
00288         }
00289         break;
00290     }
00291 }
00292 
00293 ZoneField *ZoneMap::findCityNear( ZoneField *city, int key )
00294 {
00295     ZoneField *pZone;
00296     ZoneField *pClosest = 0;
00297     long ddist = LONG_MAX;
00298 
00299     QListIterator<ZoneField> it( zones );
00300     for (; it.current(); ++it) {
00301     pZone = it.current();
00302     long dx = (pZone->x() - city->x())/100;
00303     long dy = (pZone->y() - city->y())/100;
00304     switch ( key ) {
00305         case Key_Right:
00306         case Key_Left:
00307         if ( key == Key_Left )
00308             dx = -dx;
00309         if ( dx > 0 ) {
00310             long dist = QABS(dy)*4 + dx;
00311             if ( dist < ddist ) {
00312             ddist = dist;
00313             pClosest = pZone;
00314             }
00315         }
00316         break;
00317         case Key_Down:
00318         case Key_Up:
00319         if ( key == Key_Down )
00320             dy = -dy;
00321         if ( dy > 0 ) {
00322             long dist = QABS(dx)*4 + dy;
00323             if ( dist < ddist ) {
00324             ddist = dist;
00325             pClosest = pZone;
00326             }
00327         }
00328         break;
00329     }
00330     }
00331 
00332     return pClosest;
00333 }
00334 
00335 void ZoneMap::slotFindCity( const QPoint &pos )
00336 {
00337     lblCity->hide();
00338     // given coordinates on the screen find the closest city and display the
00339     // label close to it
00340     int tmpx, tmpy, x, y;
00341     long lDistance,
00342          lClosest;
00343     ZoneField *pZone,
00344               *pClosest;
00345 
00346     if ( tHide->isActive() ) {
00347         tHide->stop();
00348     }
00349     viewportToContents(pos.x(), pos.y(), tmpx, tmpy);
00350     winToZone( tmpx, tmpy, x, y );
00351     // Find city alogorithim: start out at an (near) infinite distance away and
00352     // then find the closest city, (similar to the Z-buffer technique, I guess)
00353     // the only problem is that this is all done with doubles, but I don't know
00354     // another way to do it at the moment.  Another problem is a linked list is
00355     // used obviously something indexed would help
00356     QListIterator<ZoneField> it( zones );
00357     pClosest = 0;
00358     lClosest = LONG_MAX;
00359     for (; it.current(); ++it) {
00360     pZone = it.current();
00361     // use the manhattenLength, a good enough of an appoximation here
00362     lDistance = QABS( x - pZone->x() ) + QABS( y - pZone->y() );
00363     // first to zero wins!
00364     if ( lDistance < lClosest ) {
00365         lClosest = lDistance;
00366         pClosest = pZone;
00367     }
00368     }
00369 
00370     // Okay, we found the closest city, but it might still be too far away.
00371     if ( lClosest <= iTHRESHOLD ) {
00372     showCity( pClosest );
00373     cursor = pClosest;
00374     }
00375 }
00376 
00377 void ZoneMap::showCity( ZoneField *city )
00378 {
00379     pLast = city;
00380     // we'll use city and country a couple of times, get them to save some
00381     // time
00382     QString strCity = pLast->city();
00383     QString strCountry = pLast->country();
00384     // Display the time at this location by setting the environment timezone
00385     // getting the current time [there] and then swapping back the variable
00386     // so no one notices...
00387     QString strSave;
00388     char *p = getenv( "TZ" );
00389     if ( p ) {
00390     strSave = p;
00391     }
00392     // set the timezone :)
00393     setenv( "TZ", strCountry + strCity, true );
00394     lblCity->setText( strCity.replace( QRegExp("_"), " ") + "\n" +
00395               TimeString::shortTime( ampm ) );
00396     lblCity->setMinimumSize( lblCity->sizeHint() );
00397     // undue our damage...
00398     unsetenv( "TZ" );
00399     if ( p )
00400     setenv( "TZ", strSave, true );
00401     // Now decide where to move the label, x & y can be reused
00402     int tmpx, tmpy, x, y;
00403     zoneToWin( pLast->x(), pLast->y(), tmpx, tmpy );
00404     contentsToViewport(tmpx, tmpy, x, y);
00405     if ( lblCity->width() > drawableW - x ) {
00406     // oops... try putting it on the right
00407     x = x - lblCity->width() - iLABELOFFSET;
00408     } else {
00409     // the default...
00410     x += iLABELOFFSET;
00411     }
00412     if ( lblCity->height() > drawableH - y ) {
00413     // move it up...
00414     y = y - lblCity->height() - iLABELOFFSET;
00415     } else if ( y < 0 ) {
00416     // the city is actually off the screen...
00417     // this only happens on the a zoom when you are near the top,
00418     // a quick workaround..
00419     y = iLABELOFFSET;
00420     } else {
00421     // the default
00422     y += iLABELOFFSET;
00423     }
00424 
00425     // draw in the city and the label
00426     if ( pRepaint ) {
00427     int repx,
00428         repy;
00429     zoneToWin( pRepaint->x(), pRepaint->y(), repx, repy );
00430     updateContents( repx - iCITYOFFSET, repy - iCITYOFFSET,
00431             iCITYSIZE, iCITYSIZE );
00432     }
00433     updateContents( tmpx - iCITYOFFSET, tmpy - iCITYOFFSET, iCITYSIZE,
00434             iCITYSIZE );
00435     pRepaint = pLast;
00436 
00437     lblCity->move( x, y );
00438     lblCity->show();
00439 }
00440 
00441 void ZoneMap::resizeEvent( QResizeEvent *e )
00442 {
00443     // keep the zoom button down in the corner
00444     QSize _size = e->size();
00445     cmdZoom->move( _size.width() - cmdZoom->width(),
00446                    _size.height() - cmdZoom->height() );
00447     if ( !bZoom ) {
00448     drawableW = width() - 2 * frameWidth();
00449     drawableH = height() - 2 * frameWidth();
00450     makeMap( drawableW, drawableH );
00451     resizeContents( drawableW, drawableH );
00452     }
00453 }
00454 
00455 void ZoneMap::showZones( void ) const
00456 {
00457     // go through the zones in the list and just display the values...
00458     QListIterator<ZoneField> itZone( zones );
00459     for ( itZone.toFirst(); itZone.current(); ++itZone ) {
00460     ZoneField *pZone = itZone.current();
00461     pZone->showStructure();
00462     }
00463 }
00464 
00465 
00466 QWidget* ZoneMap::selectionWidget( QWidget *parent) {
00467 
00468     QWidget *returnWidget = new QWidget( parent );
00469 
00470     QVBoxLayout *layout = new QVBoxLayout( returnWidget );
00471     QHBox *hBox = new QHBox( returnWidget );
00472     QListView *continentView = new QListView( hBox );
00473     continentView->addColumn( tr("Continent") );
00474     QWhatsThis::add( continentView, tr("Select a continent/country here, then select a city") );
00475     connect ( continentView, SIGNAL( clicked(QListViewItem*) ), this, SLOT( slotGetCities(QListViewItem*) ) );
00476 
00477     QStringList continentList;
00478     QListIterator<ZoneField> itZone( zones );
00479     for ( itZone.toFirst(); itZone.current(); ++itZone ) {
00480     ZoneField *pZone = itZone.current();
00481         if ( continentList.contains( pZone->country() ) == 0 ) {
00482             QString name;
00483             QListViewItem *item;
00484             if ( !(pZone->country().length() > 24) ) {
00485                 name = pZone->country().left(pZone->country().length()-1 );
00486             } else {
00487                 name = pZone->country().left( 24 );
00488             }
00489             item = new QListViewItem( continentView, name, pZone->country() );
00490             continentList.append( pZone->country() );
00491         }
00492     }
00493 
00494     cityView = new QListView( hBox );
00495     cityView->addColumn( tr("City") );
00496 
00497     layout->addWidget( hBox );
00498     return returnWidget;
00499 }
00500 
00501 void ZoneMap::slotGetCities( QListViewItem * contItem) {
00502 
00503     cityView->clear();
00504     selectedCont = contItem->text( 1 );
00505     QListIterator<ZoneField> itZone( zones );
00506     for ( itZone.toFirst(); itZone.current(); ++itZone ) {
00507     ZoneField *pZone = itZone.current();
00508         if ( pZone->country() == contItem->text( 1 ) ) {
00509             QListViewItem *item;
00510             item = new QListViewItem( cityView, pZone->city() );
00511             connect ( cityView, SIGNAL( clicked(QListViewItem*) ), this, SLOT( slotCitySelected(QListViewItem*) ) );
00512         }
00513     }
00514 }
00515 
00516 void ZoneMap::slotCitySelected( QListViewItem *cityItem ) {
00517     if ( cityItem ) {
00518         emit signalTz( selectedCont, cityItem->text( 0 ) );
00519     }
00520 }
00521 
00522 void ZoneMap::drawCities( QPainter *p )
00523 {
00524     int x, y, j;
00525     // draw in the cities
00526     // for testing only as when you put it
00527     // on the small screen it looks awful and not to mention useless
00528     p->setPen( red );
00529     QListIterator<ZoneField> itZone( zones );
00530     for ( itZone.toFirst(), j = 0; itZone.current(); ++itZone, j++ ) {
00531     ZoneField *pZone = itZone.current();
00532     zoneToWin( pZone->x(), pZone->y(), x, y );
00533     if ( x > wImg )
00534         x = x - wImg;
00535     p->drawRect( x - iCITYOFFSET, y - iCITYOFFSET, iCITYSIZE, iCITYSIZE);
00536     }
00537 }
00538 
00539 static void dayNight(QImage *pImage)
00540 {
00541     // create a mask the functions from sun.h
00542     double dJulian,
00543            dSunRad,
00544            dSunDecl,
00545            dSunRadius,
00546            dSunLong;
00547     int wImage = pImage->width(),
00548         hImage = pImage->height(),
00549         iStart,
00550         iStop,
00551         iMid,
00552         relw,
00553         i;
00554     short wtab[ wImage ];
00555     time_t tCurrent;
00556     struct tm *pTm;
00557 
00558     // get the position of the sun bassed on our current time...
00559     tCurrent = time( NULL );
00560     pTm = gmtime( &tCurrent );
00561     dJulian = jtime( pTm );
00562     sunpos( dJulian, 0, &dSunRad, &dSunDecl, &dSunRadius, &dSunLong );
00563 
00564     // now get the projected illumination
00565     projillum( wtab, wImage, hImage, dSunDecl );
00566     relw = wImage - int( wImage * 0.0275 );
00567 
00568     // draw the map, keeping in mind that we may go too far off the map...
00569     iMid = ( relw * ( 24*60 - pTm->tm_hour * 60 - pTm->tm_min ) ) / ( 24*60 );
00570 
00571     for ( i = 0; i < hImage; i++ ) {
00572     if ( wtab[i] > 0 ) {
00573         iStart = iMid - wtab[i];
00574         iStop = iMid + wtab[i];
00575         if ( iStart < 0 ) {
00576         darken( pImage, iStop, wImage + iStart, i );
00577         } else if ( iStop > wImage ) {
00578         darken( pImage, iStop - wImage, iStart, i );
00579         } else {
00580         darken( pImage, 0, iStart, i );
00581         darken( pImage, iStop, wImage, i );
00582         }
00583     } else {
00584         darken( pImage, 0, wImage, i );
00585     }
00586     }
00587 }
00588 
00589 static inline void darken( QImage *pImage, int start, int stop, int row )
00590 {
00591     int colors,
00592         j;
00593     uchar *p;
00594 
00595     // assume that the image is similar to the one we have...
00596     colors = pImage->numColors() / 2;
00597 
00598     p = pImage->scanLine( row );
00599     for ( j = start; j <= stop; j++ ) {
00600     if ( p[j] < colors )
00601         p[j] += colors;
00602     }
00603 }
00604 
00605 void ZoneMap::makeMap( int w, int h )
00606 {
00607     QImage imgOrig = Opie::Core::OResource::loadImage( strMAP );
00608     if ( imgOrig.isNull() ) {
00609     QMessageBox::warning( this,
00610                           tr( "Couldn't Find Map" ),
00611                           tr( "<p>Couldn't load map: %1, exiting")
00612                               .arg( strMAP ) );
00613     exit(-1);
00614     }
00615 
00616     // set up the color table for darkening...
00617     imgOrig = imgOrig.convertDepth( 8 );
00618     int numColors = imgOrig.numColors();
00619     // double the colors
00620     imgOrig.setNumColors( 2 * numColors );
00621     // darken the new ones...
00622     for ( int i = 0; i < numColors; i++ ) {
00623     QRgb rgb = imgOrig.color( i );
00624     imgOrig.setColor ( i + numColors, qRgb(  2 * qRed( rgb ) / 3,
00625                        2 * qGreen( rgb ) / 3, 2 * qBlue( rgb ) / 3 ) );
00626     }
00627 
00628     // else go one with making the map...
00629     if ( bIllum ) {
00630     // do a daylight mask
00631     dayNight(&imgOrig);
00632     }
00633     // redo the width and height
00634     wImg = w;
00635     hImg = h;
00636     ox = ( wImg / 2 ) - int( wImg * 0.0275 );
00637     oy = hImg / 2;
00638     pixCurr->convertFromImage( imgOrig.smoothScale(w, h),
00639                                QPixmap::ThresholdDither );
00640 }
00641 
00642 void ZoneMap::drawCity( QPainter *p, const ZoneField *pCity )
00643 {
00644     int x,
00645         y;
00646 
00647     p->setPen( red );
00648     zoneToWin( pCity->x(), pCity->y(), x, y );
00649     p->drawRect( x - iCITYOFFSET, y - iCITYOFFSET, iCITYSIZE, iCITYSIZE );
00650 }
00651 
00652 void ZoneMap::drawContents( QPainter *p, int cx, int cy, int cw, int ch )
00653 {
00654     // if there is a need to resize, then do it...
00655     // get our drawable area
00656     drawableW = width() - 2 * frameWidth();
00657     drawableH = height() - 2 * frameWidth();
00658 
00659     int pixmapW = pixCurr->width(),
00660         pixmapH = pixCurr->height();
00661     if ( !bZoom &&  ( ( pixmapW != drawableW ) ||
00662                       ( pixmapH != drawableH) ) ) {
00663     makeMap( drawableW, drawableH );
00664     }
00665 
00666     // taken from the scrollview example...
00667     int rowheight = pixCurr->height();
00668     int toprow = cy / rowheight;
00669     int bottomrow = ( cy + ch + rowheight - 1 ) / rowheight;
00670     int colwidth = pixCurr->width();
00671     int leftcol= cx / colwidth;
00672     int rightcol= ( cx + cw + colwidth - 1 ) / colwidth;
00673     for ( int r = toprow; r <= bottomrow; r++ ) {
00674     int py = r * rowheight;
00675     for ( int c = leftcol; c <= rightcol; c++ ) {
00676         int px = c * colwidth;
00677         p->drawPixmap( px, py, *pixCurr );
00678     }
00679     }
00680 
00681     // Draw that city!
00682     if ( pLast )
00683     drawCity( p, pLast );
00684 }
00685 
00686 void ZoneMap::slotZoom( bool setZoom )
00687 {
00688     bZoom = setZoom;
00689     if ( bZoom ) {
00690     makeMap( 2 * wImg , 2 * hImg );
00691     resizeContents( wImg, hImg );
00692     } else {
00693     makeMap( drawableW, drawableH );
00694     resizeContents( drawableW, drawableH );
00695     }
00696 }
00697 
00698 void ZoneMap::slotIllum( bool setIllum )
00699 {
00700     bIllum = !setIllum;
00701     // make the map...
00702     makeMap( pixCurr->width(), pixCurr->height() );
00703     updateContents( 0, 0, wImg, hImg );
00704 }
00705 
00706 void ZoneMap::slotUpdate( void )
00707 {
00708     // recalculate the light, most people will never see this,
00709     // but it is good to be complete
00710     makeMap ( pixCurr->width(), pixCurr->height() );
00711     updateContents( contentsX(), contentsY(), drawableW, drawableH );
00712 }
00713 
00714 void ZoneMap::slotRedraw( void )
00715 {
00716     // paint over that pesky city...
00717     int x,
00718         y;
00719     if ( pRepaint ) {
00720     pLast = 0;
00721     zoneToWin(pRepaint->x(), pRepaint->y(), x, y);
00722     updateContents( x - iCITYOFFSET, y - iCITYOFFSET, iCITYSIZE, iCITYSIZE);
00723         pRepaint = 0;
00724     }
00725 }
00726 
00727 void ZoneMap::changeClock( bool whichClock )
00728 {
00729     ampm = whichClock;
00730 }

Generated on Sat Nov 5 16:15:57 2005 for OPIE by  doxygen 1.4.2