24 #include <tdeabc/geo.h>
25 #include <tdeaccelmanager.h>
26 #include <kcombobox.h>
28 #include <kiconloader.h>
29 #include <tdelocale.h>
30 #include <knuminput.h>
31 #include <kstandarddirs.h>
33 #include <tqcheckbox.h>
35 #include <tqgroupbox.h>
38 #include <tqlistbox.h>
39 #include <tqpainter.h>
41 #include <tqpushbutton.h>
45 #include "geowidget.h"
47 GeoWidget::GeoWidget( TDEABC::AddressBook *ab, TQWidget *parent,
const char *name )
48 : KAB::ContactEditorWidget( ab, parent, name ), mReadOnly( false )
52 TQGridLayout *topLayout =
new TQGridLayout(
this, 4, 3 );
53 topLayout->setMargin( KDialog::marginHint() );
54 topLayout->setSpacing( KDialog::spacingHint() );
56 label =
new TQLabel(
this );
57 label->setPixmap( TDEGlobal::iconLoader()->loadIcon(
"applications-internet",
58 TDEIcon::Desktop, TDEIcon::SizeMedium ) );
59 label->setAlignment( TQt::AlignTop );
60 topLayout->addMultiCellWidget( label, 0, 3, 0, 0 );
62 mGeoIsValid =
new TQCheckBox( i18n(
"Use geo data" ),
this );
63 topLayout->addMultiCellWidget( mGeoIsValid, 0, 0, 1, 2 );
65 label =
new TQLabel( i18n(
"Latitude:" ),
this );
66 topLayout->addWidget( label, 1, 1 );
68 mLatitudeBox =
new KDoubleSpinBox( -90, 90, 1, 0, 6,
this );
69 mLatitudeBox->setEnabled(
false );
70 mLatitudeBox->setSuffix(
"°" );
71 topLayout->addWidget( mLatitudeBox, 1, 2 );
72 label->setBuddy( mLatitudeBox );
74 label =
new TQLabel( i18n(
"Longitude:" ),
this );
75 topLayout->addWidget( label, 2, 1 );
77 mLongitudeBox =
new KDoubleSpinBox( -180, 180, 1, 0, 6,
this );
78 mLongitudeBox->setEnabled(
false );
79 mLongitudeBox->setSuffix(
"°" );
80 topLayout->addWidget( mLongitudeBox, 2, 2 );
81 label->setBuddy( mLongitudeBox );
83 mExtendedButton =
new TQPushButton( i18n(
"Edit Geo Data..." ),
this );
84 mExtendedButton->setEnabled(
false );
85 topLayout->addMultiCellWidget( mExtendedButton, 3, 3, 1, 2 );
87 connect( mLatitudeBox, TQ_SIGNAL( valueChanged(
double ) ),
88 TQ_SLOT( setModified() ) );
89 connect( mLongitudeBox, TQ_SIGNAL( valueChanged(
double ) ),
90 TQ_SLOT( setModified() ) );
91 connect( mExtendedButton, TQ_SIGNAL( clicked() ),
92 TQ_SLOT( editGeoData() ) );
94 connect( mGeoIsValid, TQ_SIGNAL( toggled(
bool ) ),
95 mLatitudeBox, TQ_SLOT( setEnabled(
bool ) ) );
96 connect( mGeoIsValid, TQ_SIGNAL( toggled(
bool ) ),
97 mLongitudeBox, TQ_SLOT( setEnabled(
bool ) ) );
98 connect( mGeoIsValid, TQ_SIGNAL( toggled(
bool ) ),
99 mExtendedButton, TQ_SLOT( setEnabled(
bool ) ) );
100 connect( mGeoIsValid, TQ_SIGNAL( toggled(
bool ) ),
101 TQ_SLOT( setModified() ) );
104 GeoWidget::~GeoWidget()
108 void GeoWidget::loadContact( TDEABC::Addressee *addr )
110 TDEABC::Geo geo = addr->geo();
112 if ( geo.isValid() ) {
114 mGeoIsValid->setChecked(
true );
115 mLatitudeBox->setValue( geo.latitude() );
116 mLongitudeBox->setValue( geo.longitude() );
118 mGeoIsValid->setChecked(
false );
121 void GeoWidget::storeContact( TDEABC::Addressee *addr )
125 if ( mGeoIsValid->isChecked() ) {
126 geo.setLatitude( mLatitudeBox->value() );
127 geo.setLongitude( mLongitudeBox->value() );
129 geo.setLatitude( 91 );
130 geo.setLongitude( 181 );
136 void GeoWidget::setReadOnly(
bool readOnly )
138 mReadOnly = readOnly;
140 mGeoIsValid->setEnabled( !mReadOnly );
143 void GeoWidget::editGeoData()
145 GeoDialog dlg(
this );
147 dlg.setLatitude( mLatitudeBox->value() );
148 dlg.setLongitude( mLongitudeBox->value() );
151 mLatitudeBox->setValue( dlg.latitude() );
152 mLongitudeBox->setValue( dlg.longitude() );
160 GeoDialog::GeoDialog( TQWidget *parent,
const char *name )
161 : KDialogBase( Plain, i18n(
"Geo Data Input" ), Ok | Cancel, Ok,
162 parent, name, true, true ),
163 mUpdateSexagesimalInput( true )
165 TQFrame *page = plainPage();
167 TQGridLayout *topLayout =
new TQGridLayout( page, 2, 2, marginHint(),
169 topLayout->setRowStretch( 1, 1 );
171 mMapWidget =
new GeoMapWidget( page );
172 topLayout->addMultiCellWidget( mMapWidget, 0, 1, 0, 0 );
174 mCityCombo =
new KComboBox( page );
175 topLayout->addWidget( mCityCombo, 0, 1 );
177 TQGroupBox *sexagesimalGroup =
new TQGroupBox( 0, TQt::Vertical, i18n(
"Sexagesimal" ), page );
178 TQGridLayout *sexagesimalLayout =
new TQGridLayout( sexagesimalGroup->layout(),
179 2, 5, spacingHint() );
181 TQLabel *label =
new TQLabel( i18n(
"Latitude:" ), sexagesimalGroup );
182 sexagesimalLayout->addWidget( label, 0, 0 );
184 mLatDegrees =
new TQSpinBox( 0, 90, 1, sexagesimalGroup );
185 mLatDegrees->setSuffix(
"°" );
186 mLatDegrees->setWrapping(
false );
187 label->setBuddy( mLatDegrees );
188 sexagesimalLayout->addWidget( mLatDegrees, 0, 1 );
190 mLatMinutes =
new TQSpinBox( 0, 59, 1, sexagesimalGroup );
191 mLatMinutes->setSuffix(
"'" );
192 sexagesimalLayout->addWidget( mLatMinutes, 0, 2 );
194 mLatSeconds =
new TQSpinBox( 0, 59, 1, sexagesimalGroup );
195 mLatSeconds->setSuffix(
"\"" );
196 sexagesimalLayout->addWidget( mLatSeconds, 0, 3 );
198 mLatDirection =
new KComboBox( sexagesimalGroup );
199 mLatDirection->insertItem( i18n(
"North" ) );
200 mLatDirection->insertItem( i18n(
"South" ) );
201 sexagesimalLayout->addWidget( mLatDirection, 0, 4 );
203 label =
new TQLabel( i18n(
"Longitude:" ), sexagesimalGroup );
204 sexagesimalLayout->addWidget( label, 1, 0 );
206 mLongDegrees =
new TQSpinBox( 0, 180, 1, sexagesimalGroup );
207 mLongDegrees->setSuffix(
"°" );
208 label->setBuddy( mLongDegrees );
209 sexagesimalLayout->addWidget( mLongDegrees, 1, 1 );
211 mLongMinutes =
new TQSpinBox( 0, 59, 1, sexagesimalGroup );
212 mLongMinutes->setSuffix(
"'" );
213 sexagesimalLayout->addWidget( mLongMinutes, 1, 2 );
215 mLongSeconds =
new TQSpinBox( 0, 59, 1, sexagesimalGroup );
216 mLongSeconds->setSuffix(
"\"" );
217 sexagesimalLayout->addWidget( mLongSeconds, 1, 3 );
219 mLongDirection =
new KComboBox( sexagesimalGroup );
220 mLongDirection->insertItem( i18n(
"East" ) );
221 mLongDirection->insertItem( i18n(
"West" ) );
222 sexagesimalLayout->addWidget( mLongDirection, 1, 4 );
224 topLayout->addWidget( sexagesimalGroup, 1, 1 );
228 connect( mMapWidget, TQ_SIGNAL( changed() ),
229 TQ_SLOT( geoMapChanged() ) );
230 connect( mCityCombo, TQ_SIGNAL( activated(
int ) ),
231 TQ_SLOT( cityInputChanged() ) );
232 connect( mLatDegrees, TQ_SIGNAL( valueChanged(
int ) ),
233 TQ_SLOT( sexagesimalInputChanged() ) );
234 connect( mLatMinutes, TQ_SIGNAL( valueChanged(
int ) ),
235 TQ_SLOT( sexagesimalInputChanged() ) );
236 connect( mLatSeconds, TQ_SIGNAL( valueChanged(
int ) ),
237 TQ_SLOT( sexagesimalInputChanged() ) );
238 connect( mLatDirection, TQ_SIGNAL( activated(
int ) ),
239 TQ_SLOT( sexagesimalInputChanged() ) );
240 connect( mLongDegrees, TQ_SIGNAL( valueChanged(
int ) ),
241 TQ_SLOT( sexagesimalInputChanged() ) );
242 connect( mLongMinutes, TQ_SIGNAL( valueChanged(
int ) ),
243 TQ_SLOT( sexagesimalInputChanged() ) );
244 connect( mLongSeconds, TQ_SIGNAL( valueChanged(
int ) ),
245 TQ_SLOT( sexagesimalInputChanged() ) );
246 connect( mLongDirection, TQ_SIGNAL( activated(
int ) ),
247 TQ_SLOT( sexagesimalInputChanged() ) );
249 TDEAcceleratorManager::manage(
this );
252 GeoDialog::~GeoDialog()
256 void GeoDialog::setLatitude(
double latitude )
258 mLatitude = latitude;
262 double GeoDialog::latitude()
const
267 void GeoDialog::setLongitude(
double longitude )
269 mLongitude = longitude;
273 double GeoDialog::longitude()
const
278 void GeoDialog::sexagesimalInputChanged()
280 mLatitude = (double)( mLatDegrees->value() + (double)mLatMinutes->value() /
281 60 + (double)mLatSeconds->value() / 3600 );
283 mLatitude *= ( mLatDirection->currentItem() == 1 ? -1 : 1 );
285 mLongitude = (double)( mLongDegrees->value() + (double)mLongMinutes->value() /
286 60 + (double)mLongSeconds->value() / 3600 );
288 mLongitude *= ( mLongDirection->currentItem() == 1 ? -1 : 1 );
290 mUpdateSexagesimalInput =
false;
295 void GeoDialog::geoMapChanged()
297 mLatitude = mMapWidget->latitude();
298 mLongitude = mMapWidget->longitude();
303 void GeoDialog::cityInputChanged()
305 if ( mCityCombo->currentItem() != 0 ) {
306 GeoData data = mGeoDataMap[ mCityCombo->currentText() ];
307 mLatitude = data.latitude;
308 mLongitude = data.longitude;
310 mLatitude = mLongitude = 0;
315 void GeoDialog::updateInputs()
318 mCityCombo->blockSignals(
true );
319 mLatDegrees->blockSignals(
true );
320 mLatMinutes->blockSignals(
true );
321 mLatSeconds->blockSignals(
true );
322 mLatDirection->blockSignals(
true );
323 mLongDegrees->blockSignals(
true );
324 mLongMinutes->blockSignals(
true );
325 mLongSeconds->blockSignals(
true );
326 mLongDirection->blockSignals(
true );
328 mMapWidget->setLatitude( mLatitude );
329 mMapWidget->setLongitude( mLongitude );
330 mMapWidget->update();
332 if ( mUpdateSexagesimalInput ) {
333 int degrees, minutes, seconds;
334 double latitude = mLatitude;
335 double longitude = mLongitude;
337 latitude *= ( mLatitude < 0 ? -1 : 1 );
338 longitude *= ( mLongitude < 0 ? -1 : 1 );
340 degrees = (int)( latitude * 1 );
341 minutes = (int)( ( latitude - degrees ) * 60 );
342 seconds = (int)( (
double)( (double)latitude - (
double)degrees - ( (double)minutes / (
double)60 ) ) * (double)3600 );
344 mLatDegrees->setValue( degrees );
345 mLatMinutes->setValue( minutes );
346 mLatSeconds->setValue( seconds );
348 mLatDirection->setCurrentItem( mLatitude < 0 ? 1 : 0 );
350 degrees = (int)( longitude * 1 );
351 minutes = (int)( ( longitude - degrees ) * 60 );
352 seconds = (int)( (
double)( longitude - (double)degrees - ( (
double)minutes / 60 ) ) * 3600 );
354 mLongDegrees->setValue( degrees );
355 mLongMinutes->setValue( minutes );
356 mLongSeconds->setValue( seconds );
357 mLongDirection->setCurrentItem( mLongitude < 0 ? 1 : 0 );
359 mUpdateSexagesimalInput =
true;
361 int pos = nearestCity( mLongitude, mLatitude );
363 mCityCombo->setCurrentItem( pos + 1 );
365 mCityCombo->setCurrentItem( 0 );
367 mCityCombo->blockSignals(
false );
368 mLatDegrees->blockSignals(
false );
369 mLatMinutes->blockSignals(
false );
370 mLatSeconds->blockSignals(
false );
371 mLatDirection->blockSignals(
false );
372 mLongDegrees->blockSignals(
false );
373 mLongMinutes->blockSignals(
false );
374 mLongSeconds->blockSignals(
false );
375 mLongDirection->blockSignals(
false );
378 void GeoDialog::loadCityList()
383 TQFile file( locate(
"data",
"kaddressbook/zone.tab" ) );
385 if ( file.open( IO_ReadOnly ) ) {
386 TQTextStream s( &file );
388 TQString line, country;
389 TQRegExp coord(
"[+-]\\d+[+-]\\d+" );
390 TQRegExp name(
"[^\\s]+/[^\\s]+" );
394 line = s.readLine().stripWhiteSpace();
395 if ( line.isEmpty() || line[ 0 ] ==
'#' )
398 country = line.left( 2 );
400 pos = coord.search( line, 0 );
402 c = line.mid( pos, coord.matchedLength() );
404 pos = name.search(line, pos);
406 n = line.mid( pos, name.matchedLength() ).stripWhiteSpace();
407 n.replace(
'_',
" " );
410 if ( !c.isEmpty() && !n.isEmpty() ) {
411 pos = c.find(
"+", 1 );
413 pos = c.find(
"-", 1 );
416 data.latitude = calculateCoordinate( c.left( pos ) );
417 data.longitude = calculateCoordinate( c.mid( pos ) );
418 data.country = country;
420 mGeoDataMap.insert( n, data );
424 TQStringList items( mGeoDataMap.keys() );
425 items.prepend( i18n(
"Undefined" ) );
426 mCityCombo->insertStringList( items );
432 double GeoDialog::calculateCoordinate(
const TQString &coordinate )
const
435 int d = 0, m = 0, s = 0;
436 TQString str = coordinate;
438 neg = str.left( 1 ) ==
"-";
441 switch ( str.length() ) {
443 d = str.left( 2 ).toInt();
444 m = str.mid( 2 ).toInt();
447 d = str.left( 3 ).toInt();
448 m = str.mid( 3 ).toInt();
451 d = str.left( 2 ).toInt();
452 m = str.mid( 2, 2 ).toInt();
453 s = str.right( 2 ).toInt();
456 d = str.left( 3 ).toInt();
457 m = str.mid( 3, 2 ).toInt();
458 s = str.right( 2 ).toInt();
465 return - ( d + m / 60.0 + s / 3600.0 );
467 return d + m / 60.0 + s / 3600.0;
470 int GeoDialog::nearestCity(
double x,
double y )
const
472 TQMap<TQString, GeoData>::ConstIterator it;
474 for ( it = mGeoDataMap.begin(); it != mGeoDataMap.end(); ++it, ++pos ) {
475 double dist = ( (*it).longitude - x ) * ( (*it).longitude - x ) +
476 ( (*it).latitude - y ) * ( (*it).latitude - y );
485 GeoMapWidget::GeoMapWidget( TQWidget *parent,
const char *name )
486 : TQWidget( parent, name ), mLatitude( 0 ), mLongitude( 0 )
488 setBackgroundMode( NoBackground );
490 setFixedSize( 400, 200 );
495 GeoMapWidget::~GeoMapWidget()
499 void GeoMapWidget::setLatitude(
double latitude )
501 mLatitude = latitude;
504 double GeoMapWidget::latitude()
const
509 void GeoMapWidget::setLongitude(
double longitude )
511 mLongitude = longitude;
514 double GeoMapWidget::longitude()
const
519 void GeoMapWidget::mousePressEvent( TQMouseEvent *event )
521 double latMid = height() / 2;
522 double longMid = width() / 2;
524 double latOffset = latMid -
event->y();
525 double longOffset =
event->x() - longMid;
527 mLatitude = ( latOffset * 90 ) / latMid;
528 mLongitude = ( longOffset * 180 ) / longMid;
533 void GeoMapWidget::paintEvent( TQPaintEvent* )
540 p.begin( &pm,
this );
542 p.setPen( TQColor( 255, 0, 0 ) );
543 p.setBrush( TQColor( 255, 0, 0 ) );
545 TQPixmap world( locate(
"data",
"kaddressbook/pics/world.jpg" ) );
546 p.drawPixmap( 0, 0, world );
548 double latMid = h / 2;
549 double longMid = w / 2;
551 double latOffset = ( mLatitude * latMid ) / 90;
552 double longOffset = ( mLongitude * longMid ) / 180;
554 int x = (int)(longMid + longOffset);
555 int y = (int)(latMid - latOffset);
556 p.drawEllipse( x, y, 4, 4 );
559 bitBlt(
this, 0, 0, &pm );
562 #include "geowidget.moc"