📄 zonemap.cpp
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS. All rights reserved.**** This file is part of the Qtopia Environment.** ** This program is free software; you can redistribute it and/or modify it** under the terms of the GNU General Public License as published by the** Free Software Foundation; either version 2 of the License, or (at your** option) any later version.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** This program is distributed in the hope that it will be useful, but** WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU General Public License for more details.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "sun.h"#include "zonemap.h"#include <qtopia/resource.h>#include <qtopia/timestring.h>#include <qtopia/timezone.h>#include <qtopia/qpeapplication.h>#ifdef QTOPIA_PHONE# include <qtopia/contextbar.h>#include <qtopia/global.h>#endif#include <qdatetime.h>#include <qfile.h>#include <qimage.h>#include <qlabel.h>#include <qlist.h>#include <qmessagebox.h>#include <qpixmap.h>#include <qpainter.h>#include <qregexp.h>#include <qtextstream.h>#include <qtimer.h>#include <qtoolbutton.h>#include <qwhatsthis.h>#include <limits.h>// the map file...#ifndef Q_OS_WIN32static const char strZONEINFO[] = "/usr/share/zoneinfo/zone.tab";#elsestatic const char strZONEINFO[] = "./etc/zoneinfo/zone.tab";#endifstatic const char strMAP[] = "worldtime/simple_grid_400";// The label offset (how far away from pointer)static const int iLABELOFFSET = 8;// the size of the dot to draw, and where to start itstatic const int iCITYSIZE = 3;const int iCITYOFFSET = 2;// the darkening functionstatic inline void darken( QImage *pImage, int start, int stop, int row );static void dayNight( QImage *pImage );ZoneMap::ZoneMap( QWidget *parent, const char* name ) : QScrollView( parent, name ), ox( 0 ), oy( 0 ), minMovement( 1 ), maxMovement( 4 ), drawableW( -1 ), drawableH( -1 ), bZoom( FALSE ), bIllum( TRUE ), m_cursor_x( -1 ), m_cursor_y( -1 ), citiesInit( FALSE ), accelHori(0), accelVert(0){#ifdef QTOPIA_PHONE setMargin(2);#endif setFocusPolicy( StrongFocus ); cursorTimer = new QTimer(this); connect(cursorTimer, SIGNAL(timeout()), this, SLOT(cursorTimeout())); // get the map loaded // just set the current image to point pixCurr = new QPixmap(); QPixmap pixZoom = Resource::loadPixmap( "worldtime/mag" ); cmdZoom = new QToolButton( this ); cmdZoom->setPixmap( pixZoom ); cmdZoom->setToggleButton( true ); cmdZoom->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, cmdZoom->sizePolicy().hasHeightForWidth() ) ); cmdZoom->setMaximumSize( cmdZoom->sizeHint() ); // probably don't need this, but just in case... cmdZoom->move( width() - cmdZoom->width(), height() - cmdZoom->height() ); QWhatsThis::add( cmdZoom, tr("Click to zoom the map in/out.") ); lblCity = new QLabel( tr( "CITY" ), this ); lblCity->setMinimumSize( lblCity->sizeHint() ); lblCity->setFrameStyle( QFrame::Plain | QFrame::Box ); lblCity->setBackgroundColor( yellow ); lblCity->hide(); // A timer to make sure the label gets hidden tHide = new QTimer( this ); QObject::connect( tHide, SIGNAL( timeout() ), lblCity, SLOT( hide() ) ); QObject::connect( tHide, SIGNAL( timeout() ), this, SLOT( slotRedraw() ) ); QTimer *tUpdate = new QTimer( this ); QObject::connect( tUpdate, SIGNAL( timeout() ), this, SLOT( slotUpdate() ) ); QObject::connect( qApp, SIGNAL( timeChanged() ), this, SLOT( slotUpdate() ) ); QObject::connect( cmdZoom, SIGNAL( toggled(bool) ), this, SLOT( slotZoom(bool) ) ); QObject::connect( &norm, SIGNAL( signalNewPoint(const QPoint&) ), this, SLOT( slotFindCity(const QPoint&) ) ); // update the sun's movement every 5 minutes tUpdate->start( 5 * 60 * 1000 ); // May as well read in the timezone information too... cities.setAutoDelete(TRUE);#ifdef QTOPIA_PHONE ContextBar::setLabel(this, Key_Select, ContextBar::Select);#endif QTimer::singleShot( 0, this, SLOT(initCities()) );}ZoneMap::~ZoneMap(){ delete pixCurr;}void ZoneMap::viewportMousePressEvent( QMouseEvent* event ){ // add the mouse event into the normalizer, and get the average, // pass it along slotRedraw(); norm.start(); norm.addEvent( event->pos() );}void ZoneMap::viewportMouseMoveEvent( QMouseEvent* event ){ if ((event->x() >= 0 && event->x() < viewport()->width()) && (event->y() >= 0 && event->y() < viewport()->height())) { norm.addEvent( event->pos() ); }}void ZoneMap::viewportMouseReleaseEvent( QMouseEvent* ){ // get the averaged points in case a timeout hasn't occurred, // more for "mouse clicks" norm.stop(); if (m_last.isValid()) { emit signalTz( m_last.id() ); m_last = TimeZone(); } tHide->start( 2000, true );}void ZoneMap::beginEditing(){#ifdef QTOPIA_PHONE if ( Global::mousePreferred() || !isModalEditing() ) { if( !Global::mousePreferred() ) setModalEditing( TRUE );#endif tHide->stop(); if (m_cursor.isValid()) showCity(m_cursor); else slotFindCity( QPoint( contentsWidth(), contentsHeight() ) / 2 );#ifdef QTOPIA_PHONE }#endif}int ZoneMap::heightForWidth(int w) const{ float scale = .5; return int(float(w) * scale);}void ZoneMap::keyPressEvent( QKeyEvent *ke ){#ifdef QTOPIA_PHONE if ( /* style().guiStyle() == KeyPadStyle */ TRUE ) { switch( ke->key() ) { case Key_Select: if( !Global::mousePreferred() ) { if ( !isModalEditing() ) { beginEditing(); return; } } break; case Key_No: case Key_Back: if ( !Global::mousePreferred() && isModalEditing() ) { setModalEditing( FALSE ); tHide->start( 0, true ); } else { ke->ignore(); } return; break; default: if( !Global::mousePreferred() ) { if ( !isModalEditing() ) { ke->ignore(); return; } } } }#endif switch ( ke->key() ) {#ifdef TEST_ACCESS_TO_CITIES case Key_T: testAccess(); break;#endif case Key_Left: if (!ke->isAutoRepeat() && accelHori == 0) { accelHori = -1; cursorTimer->changeInterval(500); updateCursor(); } break; case Key_Right: if (!ke->isAutoRepeat() && accelHori == 0) { accelHori = 1; cursorTimer->changeInterval(500); updateCursor(); } break; case Key_Up: if (!ke->isAutoRepeat() && accelVert == 0) { accelVert = -1; cursorTimer->changeInterval(500); updateCursor(); } break; case Key_Down: if (!ke->isAutoRepeat() && accelVert == 0) { accelVert = 1; cursorTimer->changeInterval(500); updateCursor(); } break; case Key_Space: case Key_Enter: case Key_Return:#ifdef QTOPIA_PHONE case Key_Select:#endif#ifdef QTOPIA_PHONE if( !Global::mousePreferred() )#endif if ( m_cursor.isValid() ) { emit signalTz( m_cursor.id()); tHide->start( 0, true );#ifdef QTOPIA_PHONE setModalEditing( FALSE );#endif } break; default: QScrollView::keyPressEvent(ke); }}void ZoneMap::keyReleaseEvent( QKeyEvent *ke ){ switch(ke->key()) { case Key_Up: case Key_Down: if (!ke->isAutoRepeat() && accelVert != 0) { accelVert = 0; if (accelHori == 0) cursorTimer->stop(); } break; case Key_Left: case Key_Right: if (!ke->isAutoRepeat() && accelHori != 0) { accelHori = 0; if (accelVert == 0) cursorTimer->stop(); } break; default: QScrollView::keyReleaseEvent(ke); }}/* accelerating cursor movement */void ZoneMap::cursorTimeout() { if (accelHori < 0 && accelHori > -5) accelHori = -5; else if (accelHori > 0 && accelHori < 5) accelHori = 5; if (accelVert < 0 && accelVert > -5) accelVert = -5; else if (accelVert > 0 && accelVert < 5) accelVert = 5; updateCursor(); cursorTimer->changeInterval(100);}// how many multiples of 100 ms to hold down before movement rate changesstatic const char accel_rate = 5;void ZoneMap::updateCursor(){ // accellerate timer after first one.. uint mx, my; uint habs = QABS(accelHori); uint vabs = QABS(accelVert); mx = minMovement << (habs / accel_rate); // min movement doubles. my = minMovement << (vabs / accel_rate); if (mx < maxMovement) { if (accelHori < 0) accelHori--; else if (accelHori > 0) accelHori++; } else { mx = maxMovement; } if (my < maxMovement) { if (accelVert < 0) accelVert--; else if (accelVert > 0) accelVert++; } else { my = maxMovement; } if (m_cursor_x != -1 && m_cursor_y != -1) { int nx = m_cursor_x; int ny = m_cursor_y; // horizontal movement if (accelHori < 0) { nx -= mx; if (nx < 0) nx = 0; } else if (accelHori > 0) { nx += mx; if (nx > contentsWidth()) nx = contentsWidth(); } // vertical movement if (accelVert < 0) { ny -= my; if (ny < 0) ny = 0; } else if (accelVert > 0) { ny += my; if (ny > contentsHeight()) ny = contentsHeight(); } setCursorPoint(nx, ny); ensureVisible(nx, ny); }}QRect expandTo(const QRect &in, const QPoint &p) { if (in.isValid()) { QRect r(in); if (p.x() < r.left()) r.setLeft(p.x()); else if (p.x() > r.right()) r.setRight(p.x()); if (p.y() < r.top()) r.setTop(p.y()); else if (p.y() > r.bottom()) r.setBottom(p.y()); return r; } else { return QRect(p.x(), p.y(), 1, 1); }}void ZoneMap::setCursorPoint(int ox, int oy){ if (ox != m_cursor_x || oy != m_cursor_y) { // Old Location Window Coords int olwx, olwy; zoneToWin( m_cursor.lon(), m_cursor.lat(), olwx, olwy); // New Location Window Coords int nlwx, nlwy; QRect bounds(m_cursor_x, m_cursor_y, 1,1); bounds = expandTo(bounds, QPoint(ox, oy)); bounds = expandTo(bounds, QPoint(olwx, olwy)); m_cursor_x = ox; m_cursor_y = oy; // zone coords x and y.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -