26 #define YUILogComponent "qt-ui" 27 #include <yui/YUILog.h> 30 #include <qdatetimeedit.h> 34 #include "YQTimezoneSelector.h" 35 #include "YQWidgetCaption.h" 36 #include <yui/YEvent.h> 37 #include <QVBoxLayout> 39 #include <QMouseEvent> 70 bool operator<(
const Location& l2)
const;
75 QList<Location> locations;
77 Location findBest(
const QPoint &pos )
const;
83 QPoint pixPosition(
const Location &pos )
const;
85 QPoint pixToWindow(
const QPoint &pos )
const;
92 convert_pos (
const QString &pos,
int digits)
94 if (pos.length() < 4 || digits > 9)
return 0.0;
96 QString whole = pos.left( digits + 1 );
97 QString fraction = pos.mid( digits + 1 );
99 float t1 = whole.toFloat();
100 float t2 = fraction.toFloat();
103 return t1 + t2/pow (10.0, fraction.length() );
105 return t1 - t2/pow (10.0, fraction.length());
109 bool YQTimezoneSelectorPrivate::Location::operator<(
const Location& l1 )
const 111 return l1.latitude < latitude;
116 : QFrame( (QWidget *) parent->widgetRep() )
117 , YTimezoneSelector( parent, pixmap, timezones )
121 setWidgetRep(
this );
122 setMouseTracking(
true);
123 d->_pix.load( fromUTF8( pixmap ) );
125 setStretchable( YD_HORIZ,
true );
126 setStretchable( YD_VERT,
true );
129 FILE *tzfile = fopen (
"/usr/share/zoneinfo/zone.tab",
"r");
130 while (fgets (buf,
sizeof(buf), tzfile))
132 if (*buf ==
'#')
continue;
135 QStringList arr = sbuf.trimmed().split(
'\t' );
138 while ( split_index < arr[1].length() && arr[1][split_index] !=
'-' && arr[1][split_index] !=
'+' )
142 loc.country = arr[0];
144 std::map<std::string, std::string>::const_iterator tooltip = timezones.find( loc.zone.toStdString() );
145 if (tooltip == timezones.end() )
148 loc.tip = fromUTF8( tooltip->second );
149 if ( arr.size() > 3 )
150 loc.comment = arr[3];
151 loc.latitude = convert_pos ( arr[1].left( split_index ), 2);
152 loc.longitude = convert_pos ( arr[1].mid( split_index ), 3);
154 loc.pix_pos = d->pixPosition( loc );
156 d->locations.push_back( loc );
161 std::sort( d->locations.begin(), d->locations.end() );
163 d->blink =
new QTimer(
this );
164 d->blink->setInterval( 200 );
165 connect( d->blink, &pclass(d->blink)::timeout,
166 this, &pclass(
this)::slotBlink );
192 resize( newWidth, newHeight );
196 QPoint YQTimezoneSelectorPrivate::pixPosition(
const Location &pos )
const 198 return QPoint( (
int) ( _pix.width() / 2 + _pix.width() / 2 * pos.longitude / 180 ),
199 (
int) ( _pix.height() / 2 - _pix.height() / 2 * pos.latitude / 90 ) ) ;
203 void YQTimezoneSelector::mousePressEvent ( QMouseEvent * event )
205 if ( event->button() == Qt::RightButton )
208 d->cachePix = QPixmap();
210 else if ( event->button() == Qt::LeftButton )
212 d->_best = d->findBest( event->pos() );
214 if ( d->_zoom.isNull() )
216 QPoint click =
event->pos();
218 d->_zoom.rx() = (int) (
double( click.x() ) * d->_pix.width() / width() );
219 d->_zoom.ry() = (int) (
double( click.y() ) * d->_pix.height() / height() );
222 d->cachePix = QPixmap();
235 void YQTimezoneSelector::paintEvent( QPaintEvent *event )
237 QFrame::paintEvent( event );
240 if ( d->cachePix.width() != width() || d->cachePix.height() != height() )
241 d->cachePix = QPixmap();
243 if ( d->_zoom.isNull() )
245 if ( d->cachePix.isNull() )
247 QImage t = d->_pix.scaled( width(), height(), Qt::KeepAspectRatio );
248 d->cachePix = QPixmap::fromImage( t );
250 p.drawPixmap( ( width() - d->cachePix.width() ) / 2, ( height() - d->cachePix.height() ) / 2, d->cachePix );
252 Q_INIT_RESOURCE( qt_icons );
253 QIcon icon = QIcon::fromTheme(
"zoom-in", QIcon(
":/zoom-in" ) );
255 if ( !icon.isNull() )
256 setCursor( QCursor( icon.pixmap( QSize( 16, 16 ) ) ) );
260 int left = qMin( qMax( d->_zoom.x() - width() / 2, 0 ), d->_pix.width() - width() );
261 int top = qMin( qMax( d->_zoom.y() - height() / 2, 0 ), d->_pix.height() - height() );
263 if ( d->cachePix.isNull() )
264 d->cachePix = QPixmap::fromImage( d->_pix.copy( QRect( QPoint( left, top ), size() ) ) );
266 p.drawPixmap( 0, 0, d->cachePix );
268 setCursor( Qt::CrossCursor );
271 p.setBrush( QColor(
"#D8DF57" ) );
272 p.setPen( QColor(
"#B9DFD6" ) );
274 for ( QList<YQTimezoneSelectorPrivate::Location>::const_iterator it = d->locations.begin(); it != d->locations.end(); ++it )
276 if ( !d->highlight || ( *it ).zone != d->_best.zone )
278 if ( d->_zoom.isNull() )
279 p.drawEllipse( QRect( d->pixToWindow( ( *it ).pix_pos ) - QPoint( 1,1 ), QSize( 3, 3 ) ) );
281 p.drawEllipse( QRect( d->pixToWindow( ( *it ).pix_pos ) - QPoint( 2,2 ), QSize( 5, 5 ) ) );
284 if ( d->highlight > 0 )
286 static const QColor blinks[] = { QColor(
"#00ff00" ), QColor(
"#22dd00" ), QColor(
"#44bb00" ),
287 QColor(
"#669900" ), QColor(
"#887700" ), QColor(
"#aa5500" ),
288 QColor(
"#887700" ), QColor(
"#669900" ), QColor(
"#44bb00" ),
289 QColor(
"#22dd00" ) };
290 int index = d->highlight - 1;
291 p.setPen( blinks[ index ] );
292 p.setBrush( blinks[ index ] );
294 p.drawEllipse( QRect( d->pixToWindow( d->_best.pix_pos ) - QPoint( 2,2 ), QSize( 5, 5 ) ) );
299 QFontMetrics fm( f );
301 QPoint off = d->pixToWindow( d->_best.pix_pos ) + QPoint( 11, 4 );
302 #if QT_VERSION >= 0x051100 303 int tw = fm.horizontalAdvance( d->_best.tip );
306 int tw = fm.width( d->_best.tip );
308 if ( tw + off.x() > width() )
309 off.rx() = d->pixToWindow( d->_best.pix_pos ).x() - tw - 10;
311 p.setPen( Qt::black );
312 p.drawText( off, d->_best.tip );
314 p.setPen( Qt::white );
315 p.drawText( off - QPoint( 1, 1 ), d->_best.tip );
322 double min_dist = 2000;
324 for ( QList<Location>::const_iterator it = locations.begin(); it != locations.end(); ++it )
326 double dist = QPoint( pixToWindow( ( *it ).pix_pos ) - pos ).manhattanLength ();
327 if ( dist < min_dist )
336 bool YQTimezoneSelector::event(QEvent *event)
338 if (event->type() == QEvent::ToolTip)
340 QHelpEvent *helpEvent =
static_cast<QHelpEvent *
>(event);
343 QToolTip::showText(helpEvent->globalPos(), best.tip );
345 return QWidget::event(event);
351 return d->_best.zone.toStdString();
354 QPoint YQTimezoneSelectorPrivate::pixToWindow(
const QPoint &pos )
const 356 if ( _zoom.isNull() )
358 return QPoint( (
int) (
double( pos.x() ) * cachePix.width() / _pix.width() ) + ( parent->width() - cachePix.width() ) / 2,
359 (
int) ( double( pos.y() ) * cachePix.height() / _pix.height() ) + ( parent->height() - cachePix.height() ) /2 );
361 int left = qMin( qMax( _zoom.x() - parent->width() / 2, 0 ), _pix.width() - parent->width() );
362 int top = qMin( qMax( _zoom.y() - parent->height() / 2, 0 ), _pix.height() - parent->height() );
364 return QPoint( pos.x() - left, pos.y() - top );
369 QString zone = fromUTF8( _zone );
371 if ( d->_best.zone == zone )
376 for ( QList<YQTimezoneSelectorPrivate::Location>::const_iterator it = d->locations.begin(); it != d->locations.end(); ++it )
378 if ( ( *it ).zone == zone )
383 d->_zoom = d->_best.pix_pos;
387 d->cachePix = QPixmap();
394 void YQTimezoneSelector::slotBlink()
396 if ( d->_best.zone.isNull() )
402 if ( d->highlight++ > 9 )
405 QPoint current = d->pixToWindow( d->_best.pix_pos );
406 update( QRect( current - QPoint( 3, 3 ), QSize( 7, 7 ) ) );
virtual int preferredHeight()
Preferred height of the widget.
virtual void setSize(int newWidth, int newHeight)
Set the new size of the widget.
virtual std::string currentZone() const
subclasses have to implement this to return value
YQTimezoneSelector(YWidget *parent, const std::string &pixmap, const std::map< std::string, std::string > &timezones)
Constructor.
void sendEvent(YEvent *event)
Widget event handlers (slots) call this when an event occured that should be the answer to a UserInpu...
virtual ~YQTimezoneSelector()
Destructor.
virtual int preferredWidth()
Preferred width of the widget.
virtual void setCurrentZone(const std::string &zone, bool zoom)
subclasses have to implement this to set value
static YQUI * ui()
Access the global Qt-UI.