22 #include "geoeditwidget.h"
24 #include "autoqpointer_p.h"
26 #include <kabc/addressee.h>
28 #include <kcombobox.h>
30 #include <klocalizedstring.h>
31 #include <kstandarddirs.h>
33 #include <QtCore/QFile>
34 #include <QtCore/QTextStream>
35 #include <QDoubleSpinBox>
36 #include <QGridLayout>
40 #include <QPushButton>
43 class GeoMapWidget :
public QWidget
46 GeoMapWidget(
QWidget *parent = 0)
49 mWorld =
QPixmap(KStandardDirs::locate(
"data",
QLatin1String(
"akonadi/contact/pics/world.jpg")));
57 void setCoordinates(
const KABC::Geo &coordinates)
59 mCoordinates = coordinates;
74 if (mCoordinates.isValid()) {
75 const double latMid =
height() / 2;
76 const double longMid =
width() / 2;
77 const double latOffset = (mCoordinates.latitude() * latMid) / 90;
78 const double longOffset = (mCoordinates.longitude() * longMid) / 180;
80 const int x = (int)(longMid + longOffset);
81 const int y = (int)(latMid - latOffset);
90 KABC::Geo mCoordinates;
93 GeoEditWidget::GeoEditWidget(
QWidget *parent)
99 mMap =
new GeoMapWidget;
100 layout->
addWidget(mMap, 0, 0, 1, 4, Qt::AlignCenter | Qt::AlignVCenter);
102 QLabel *label =
new QLabel(i18nc(
"@label",
"Latitude:"));
106 mLatitudeLabel =
new QLabel;
109 label =
new QLabel(i18nc(
"@label",
"Longitude:"));
113 mLongitudeLabel =
new QLabel;
114 layout->
addWidget(mLongitudeLabel, 1, 3);
116 mChangeButton =
new QPushButton(i18nc(
"@label Change the coordinates",
"Change..."));
117 layout->
addWidget(mChangeButton, 2, 0, 1, 4, Qt::AlignRight);
121 connect(mChangeButton, SIGNAL(clicked()), SLOT(changeClicked()));
126 GeoEditWidget::~GeoEditWidget()
130 void GeoEditWidget::loadContact(
const KABC::Addressee &contact)
132 mCoordinates = contact.geo();
136 void GeoEditWidget::storeContact(KABC::Addressee &contact)
const
138 contact.setGeo(mCoordinates);
141 void GeoEditWidget::setReadOnly(
bool readOnly)
143 mChangeButton->setEnabled(!readOnly);
146 void GeoEditWidget::updateView()
148 if (!mCoordinates.isValid()) {
149 mLatitudeLabel->setText(i18nc(
"@label Coordinates are not available",
"n/a"));
150 mLongitudeLabel->setText(i18nc(
"@label Coordinates are not available",
"n/a"));
152 mLatitudeLabel->setText(i18nc(
"@label The formatted coordinates",
"%1 %2", mCoordinates.latitude(),
QChar(176)));
153 mLongitudeLabel->setText(i18nc(
"@label The formatted coordinates",
"%1 %2", mCoordinates.longitude(),
QChar(176)));
155 mMap->setCoordinates(mCoordinates);
158 void GeoEditWidget::changeClicked()
162 mCoordinates = dlg->coordinates();
167 static double calculateCoordinate(
const QString &coordinate)
170 int d = 0, m = 0, s = 0;
200 return - (d + m / 60.0 + s / 3600.0);
202 return d + m / 60.0 + s / 3600.0;
206 GeoDialog::GeoDialog(
const KABC::Geo &coordinates,
QWidget *parent)
208 , mCoordinates(coordinates)
210 KGlobal::locale()->insertCatalog(
QLatin1String(
"timezones4"));
211 setCaption(i18nc(
"@title:window",
"Coordinate Selection"));
212 setButtons(Ok | Cancel);
213 setDefaultButton(Ok);
214 showButtonSeparator(
true);
222 mCityCombo =
new KComboBox(page);
225 QGroupBox *decimalGroup =
new QGroupBox(i18nc(
"@title:group Decimal representation of coordinates",
"Decimal"), page);
230 QLabel *label =
new QLabel(i18nc(
"@label:spinbox",
"Latitude:"), decimalGroup);
234 mLatitude->setMinimum(-90);
235 mLatitude->setMaximum(90);
236 mLatitude->setSingleStep(1);
237 mLatitude->setValue(0);
238 mLatitude->setDecimals(6);
239 mLatitude->setSuffix(
QChar(176));
240 decimalLayout->
addWidget(mLatitude, 0, 1);
242 label =
new QLabel(i18nc(
"@label:spinbox",
"Longitude:"), decimalGroup);
246 mLongitude->setMinimum(-180);
247 mLongitude->setMaximum(180);
248 mLongitude->setSingleStep(1);
249 mLongitude->setValue(0);
250 mLongitude->setDecimals(6);
251 mLongitude->setSuffix(
QChar(176));
252 decimalLayout->
addWidget(mLongitude, 1, 1);
254 QGroupBox *sexagesimalGroup =
new QGroupBox(i18nc(
"@title:group",
"Sexagesimal"), page);
256 sexagesimalGroup->
setLayout(sexagesimalLayout);
259 label =
new QLabel(i18nc(
"@label:spinbox",
"Latitude:"), sexagesimalGroup);
260 sexagesimalLayout->
addWidget(label, 0, 0);
262 mLatDegrees =
new QSpinBox(sexagesimalGroup);
263 mLatDegrees->setMinimum(0);
264 mLatDegrees->setMaximum(90);
265 mLatDegrees->setValue(1);
266 mLatDegrees->setSuffix(
QChar(176));
267 mLatDegrees->setWrapping(
false);
269 sexagesimalLayout->
addWidget(mLatDegrees, 0, 1);
271 mLatMinutes =
new QSpinBox(sexagesimalGroup);
272 mLatMinutes->setMinimum(0);
273 mLatMinutes->setMaximum(59);
274 mLatMinutes->setValue(1);
277 sexagesimalLayout->
addWidget(mLatMinutes, 0, 2);
279 mLatSeconds =
new QSpinBox(sexagesimalGroup);
280 mLatSeconds->setMinimum(0);
281 mLatSeconds->setMaximum(59);
282 mLatSeconds->setValue(1);
284 sexagesimalLayout->
addWidget(mLatSeconds, 0, 3);
286 mLatDirection =
new KComboBox(sexagesimalGroup);
287 mLatDirection->addItem(i18nc(
"@item:inlistbox Latitude direction",
"North"));
288 mLatDirection->addItem(i18nc(
"@item:inlistbox Latitude direction",
"South"));
289 sexagesimalLayout->
addWidget(mLatDirection, 0, 4);
291 label =
new QLabel(i18nc(
"@label:spinbox",
"Longitude:"), sexagesimalGroup);
292 sexagesimalLayout->
addWidget(label, 1, 0);
294 mLongDegrees =
new QSpinBox(sexagesimalGroup);
295 mLongDegrees->setMinimum(0);
296 mLongDegrees->setMaximum(180);
297 mLongDegrees->setValue(1);
298 mLongDegrees->setSuffix(
QChar(176));
300 sexagesimalLayout->
addWidget(mLongDegrees, 1, 1);
302 mLongMinutes =
new QSpinBox(sexagesimalGroup);
303 mLongMinutes->setMinimum(0);
304 mLongMinutes->setMaximum(59);
305 mLongMinutes->setValue(1);
307 sexagesimalLayout->
addWidget(mLongMinutes, 1, 2);
309 mLongSeconds =
new QSpinBox(sexagesimalGroup);
310 mLongSeconds->setMinimum(0);
311 mLongSeconds->setMaximum(59);
312 mLongSeconds->setValue(1);
314 sexagesimalLayout->
addWidget(mLongSeconds, 1, 3);
316 mLongDirection =
new KComboBox(sexagesimalGroup);
317 mLongDirection->addItem(i18nc(
"@item:inlistbox Longtitude direction",
"East"));
318 mLongDirection->addItem(i18nc(
"@item:inlistbox Longtitude direction",
"West"));
319 sexagesimalLayout->
addWidget(mLongDirection, 1, 4);
326 connect(mCityCombo, SIGNAL(activated(
int)),
327 SLOT(cityInputChanged()));
328 connect(mLatitude, SIGNAL(valueChanged(
double)),
329 SLOT(decimalInputChanged()));
330 connect(mLongitude, SIGNAL(valueChanged(
double)),
331 SLOT(decimalInputChanged()));
332 connect(mLatDegrees, SIGNAL(valueChanged(
int)),
333 SLOT(sexagesimalInputChanged()));
334 connect(mLatMinutes, SIGNAL(valueChanged(
int)),
335 SLOT(sexagesimalInputChanged()));
336 connect(mLatSeconds, SIGNAL(valueChanged(
int)),
337 SLOT(sexagesimalInputChanged()));
338 connect(mLatDirection, SIGNAL(activated(
int)),
339 SLOT(sexagesimalInputChanged()));
340 connect(mLongDegrees, SIGNAL(valueChanged(
int)),
341 SLOT(sexagesimalInputChanged()));
342 connect(mLongMinutes, SIGNAL(valueChanged(
int)),
343 SLOT(sexagesimalInputChanged()));
344 connect(mLongSeconds, SIGNAL(valueChanged(
int)),
345 SLOT(sexagesimalInputChanged()));
346 connect(mLongDirection, SIGNAL(activated(
int)),
347 SLOT(sexagesimalInputChanged()));
352 KABC::Geo GeoDialog::coordinates()
const
357 void GeoDialog::cityInputChanged()
359 if (mCityCombo->currentIndex() != 0) {
360 GeoData geoData = mGeoDataMap[mCityCombo->currentText()];
361 mCoordinates.setLatitude(geoData.latitude);
362 mCoordinates.setLongitude(geoData.longitude);
364 mCoordinates.setLatitude(0);
365 mCoordinates.setLongitude(0);
368 updateInputs(ExceptCity);
371 void GeoDialog::decimalInputChanged()
373 mCoordinates.setLatitude(mLatitude->value());
374 mCoordinates.setLongitude(mLongitude->value());
376 updateInputs(ExceptDecimal);
379 void GeoDialog::sexagesimalInputChanged()
381 double latitude = (double)(mLatDegrees->value() + (double)mLatMinutes->value() /
382 60 + (double)mLatSeconds->value() / 3600);
383 latitude *= (mLatDirection->currentIndex() == 1 ? -1 : 1);
385 double longitude = (double)(mLongDegrees->value() + (double)mLongMinutes->value() /
386 60 + (double)mLongSeconds->value() / 3600);
387 longitude *= (mLongDirection->currentIndex() == 1 ? -1 : 1);
389 mCoordinates.setLatitude(latitude);
390 mCoordinates.setLongitude(longitude);
392 updateInputs(ExceptSexagesimal);
395 void GeoDialog::updateInputs(ExceptType type)
397 mCityCombo->blockSignals(
true);
398 mLatitude->blockSignals(
true);
399 mLongitude->blockSignals(
true);
400 mLatDegrees->blockSignals(
true);
401 mLatMinutes->blockSignals(
true);
402 mLatSeconds->blockSignals(
true);
403 mLatDirection->blockSignals(
true);
404 mLongDegrees->blockSignals(
true);
405 mLongMinutes->blockSignals(
true);
406 mLongSeconds->blockSignals(
true);
407 mLongDirection->blockSignals(
true);
409 if (!(type &ExceptDecimal)) {
410 mLatitude->setValue(mCoordinates.latitude());
411 mLongitude->setValue(mCoordinates.longitude());
414 if (!(type &ExceptSexagesimal)) {
415 int degrees, minutes, seconds;
416 double latitude = mCoordinates.latitude();
417 double longitude = mCoordinates.longitude();
419 latitude *= (latitude < 0 ? -1 : 1);
420 longitude *= (longitude < 0 ? -1 : 1);
422 degrees = (int)(latitude * 1);
423 minutes = (int)((latitude - degrees) * 60);
424 seconds = (int)((
double)((double)latitude - (
double)degrees - ((double)minutes / (
double)60)) * (double)3600);
426 mLatDegrees->setValue(degrees);
427 mLatMinutes->setValue(minutes);
428 mLatSeconds->setValue(seconds);
430 mLatDirection->setCurrentIndex(mLatitude->value() < 0 ? 1 : 0);
432 degrees = (int)(longitude * 1);
433 minutes = (int)((longitude - degrees) * 60);
434 seconds = (int)((
double)(longitude - (double)degrees - ((
double)minutes / 60)) * 3600);
436 mLongDegrees->setValue(degrees);
437 mLongMinutes->setValue(minutes);
438 mLongSeconds->setValue(seconds);
439 mLongDirection->setCurrentIndex(mLongitude->value() < 0 ? 1 : 0);
442 if (!(type &ExceptCity)) {
443 const int index = nearestCity(mCoordinates.longitude(), mCoordinates.latitude());
445 mCityCombo->setCurrentIndex(index + 1);
447 mCityCombo->setCurrentIndex(0);
451 mCityCombo->blockSignals(
false);
452 mLatitude->blockSignals(
false);
453 mLongitude->blockSignals(
false);
454 mLatDegrees->blockSignals(
false);
455 mLatMinutes->blockSignals(
false);
456 mLatSeconds->blockSignals(
false);
457 mLatDirection->blockSignals(
false);
458 mLongDegrees->blockSignals(
false);
459 mLongMinutes->blockSignals(
false);
460 mLongSeconds->blockSignals(
false);
461 mLongDirection->blockSignals(
false);
464 void GeoDialog::loadCityList()
469 QFile file(KStandardDirs::locate(
"data",
QLatin1String(
"akonadi/contact/data/zone.tab")));
471 if (file.open(QIODevice::ReadOnly)) {
485 country = line.
left(2);
487 pos = coord.indexIn(line, 0);
489 c = line.
mid(pos, coord.matchedLength());
492 pos = name.indexIn(line, pos);
494 n = line.
mid(pos, name.matchedLength()).trimmed();
504 geoData.latitude = calculateCoordinate(c.
left(pos));
505 geoData.longitude = calculateCoordinate(c.
mid(pos));
506 geoData.country = country;
514 items.
prepend(i18nc(
"@item:inlistbox Undefined location",
"Undefined"));
515 mCityCombo->addItems(items);
521 int GeoDialog::nearestCity(
double x,
double y)
const
525 for (it = mGeoDataMap.
begin(); it != mGeoDataMap.
end(); ++it, ++pos) {
526 double dist = ((*it).longitude - x) * ((*it).longitude - x) +
527 ((*it).latitude - y) * ((*it).latitude - y);
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
void setAlignment(QFlags< Qt::AlignmentFlag >)
QString & remove(int position, int n)
void setSpacing(int spacing)
void setBuddy(QWidget *buddy)
QString & insert(int position, QChar ch)
void setRowStretch(int row, int stretch)
void setPen(const QColor &color)
void drawEllipse(const QRectF &rectangle)
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
int toInt(bool *ok, int base) const
void setBrush(const QBrush &brush)
void setMargin(int margin)
QString right(int n) const
A QPointer which when destructed, deletes the object it points to.
QString mid(int position, int n) const
QString left(int n) const
void prepend(const T &value)
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool begin(QPaintDevice *device)