19 #include "ui_locationdialog.h" 
   25 #include <QTextStream> 
   26 #include <QListWidget> 
   28 #include <kmessagebox.h> 
   29 #include <kstandarddirs.h> 
   37     ui = 
new Ui::LocationDialog();
 
   38     ui->setupUi( mainWidget() );
 
   40     ui->MapView->setLocationDialog( 
this );
 
   42     setCaption( i18n( 
"Set Geographic Location" ) );
 
   43     setButtons( KDialog::Ok|KDialog::Cancel );
 
   45     for ( 
int i=0; i<25; ++i )
 
   46         ui->TZBox->addItem( KGlobal::locale()->formatNumber( (
double)(i-12) ) );
 
   49     foreach( 
const QString& key, data->
getRulebook().keys() ) {
 
   51             ui->DSTRuleBox->addItem( key );
 
   54     connect( 
this, SIGNAL( cancelClicked() ), 
this, SLOT( reject() ) );
 
   55     connect( ui->CityFilter, SIGNAL( textChanged( 
const QString & ) ), 
this, SLOT( 
enqueueFilterCity() ) );
 
   56     connect( ui->ProvinceFilter, SIGNAL( textChanged( 
const QString & ) ), 
this, SLOT( 
enqueueFilterCity() ) );
 
   57     connect( ui->CountryFilter, SIGNAL( textChanged( 
const QString & ) ), 
this, SLOT( 
enqueueFilterCity() ) );
 
   58     connect( ui->NewCityName, SIGNAL( textChanged( 
const QString & ) ), 
this, SLOT( 
nameChanged() ) );
 
   59     connect( ui->NewProvinceName, SIGNAL( textChanged( 
const QString & ) ), 
this, SLOT( 
nameChanged() ) );
 
   60     connect( ui->NewCountryName, SIGNAL( textChanged( 
const QString & ) ), 
this, SLOT( 
nameChanged() ) );
 
   61     connect( ui->NewLong, SIGNAL( textChanged( 
const QString & ) ), 
this, SLOT( 
dataChanged() ) );
 
   62     connect( ui->NewLat, SIGNAL( textChanged( 
const QString & ) ), 
this, SLOT( 
dataChanged() ) );
 
   63     connect( ui->TZBox, SIGNAL( activated(
int) ), 
this, SLOT( 
dataChanged() ) );
 
   64     connect( ui->DSTRuleBox, SIGNAL( activated(
int) ), 
this, SLOT( 
dataChanged() ) );
 
   65     connect( ui->GeoBox, SIGNAL( itemSelectionChanged () ), 
this, SLOT( 
changeCity() ) );
 
   66     connect( ui->AddCityButton, SIGNAL( clicked() ), 
this, SLOT( 
addCity() ) );
 
   67     connect( ui->ClearFieldsButton, SIGNAL( clicked() ), 
this, SLOT( 
clearFields() ) );
 
   69     ui->DSTLabel->setText( 
"<a href=\"showrules\">" + i18n(
"DST Rule:") + 
"</a>" );
 
   70     connect( ui->DSTLabel, SIGNAL( linkActivated(
const QString &) ), 
this, SLOT( 
showTZRules() ) );
 
   74     ui->AddCityButton->setEnabled( 
false );
 
   76     ui->NewCityName->setTrapReturnKey(
true);
 
   77     ui->NewProvinceName->setTrapReturnKey(
true);
 
   78     ui->NewCountryName->setTrapReturnKey(
true);
 
   79     ui->CityFilter->setTrapReturnKey(
true);
 
   80     ui->ProvinceFilter->setTrapReturnKey(
true);
 
   81     ui->CountryFilter->setTrapReturnKey(
true);
 
   85     connect(
this,SIGNAL(okClicked()),
this,SLOT(
slotOk()));
 
   97         ui->GeoBox->addItem( loc->
fullName() );
 
   98         filteredCityList.append( loc );
 
  101         if ( loc->
TZ0() - int( loc->
TZ0() ) && ui->TZBox->findText( KGlobal::locale()->formatNumber( loc->
TZ0() ) ) != -1 ) {
 
  102             for ( 
int i=0; i < ui->TZBox->count(); ++i ) {
 
  103                 if ( ui->TZBox->itemText( i ).toDouble() > loc->
TZ0() ) {
 
  104                     ui->TZBox->addItem( KGlobal::locale()->formatNumber( loc->
TZ0() ), i-1 );
 
  112     ui->GeoBox->sortItems();
 
  114     ui->CountLabel->setText( i18np(
"One city matches search criteria",
"%1 cities match search criteria", ui->GeoBox->count()) );
 
  117     ui->GeoBox->setCurrentItem( 0 );
 
  118     for( 
int i=0; i < ui->GeoBox->count(); i++ ) {
 
  119         if ( ui->GeoBox->item(i)->text() == data->
geo()->
fullName() ) {
 
  120             ui->GeoBox->setCurrentRow( i );
 
  130         timer = 
new QTimer( 
this );
 
  131         timer->setSingleShot( 
true );
 
  132         connect( timer, SIGNAL( timeout() ), 
this, SLOT( 
filterCity() ) );
 
  141     while( !filteredCityList.isEmpty() )
 
  142         filteredCityList.takeFirst();
 
  144     nameModified = 
false;
 
  145     dataModified = 
false;
 
  146     ui->AddCityButton->setEnabled( 
false );
 
  155         if ( sc.toLower().startsWith( ui->CityFilter->text().toLower() ) &&
 
  156                 sp.toLower().startsWith( ui->ProvinceFilter->text().toLower() ) &&
 
  157                 ss.toLower().startsWith( ui->CountryFilter->text().toLower() ) ) {
 
  159             ui->GeoBox->addItem( loc->
fullName() );
 
  160             filteredCityList.append( loc );
 
  164     ui->GeoBox->sortItems();
 
  166     ui->CountLabel->setText( i18np(
"One city matches search criteria",
"%1 cities match search criteria", ui->GeoBox->count()) );
 
  168     if ( ui->GeoBox->count() > 0 )      
 
  169         ui->GeoBox->setCurrentItem( ui->GeoBox->item(0) );
 
  171     ui->MapView->repaint();
 
  178     if ( ui->GeoBox->currentItem() ) {
 
  179         for ( 
int i=0; i < filteredCityList.size(); ++i ) {
 
  181             if ( loc->
fullName() == ui->GeoBox->currentItem()->text()) {
 
  188     ui->MapView->repaint();
 
  191     if ( SelectedCity ) {
 
  193         if ( SelectedCity->
province().isEmpty() )
 
  194             ui->NewProvinceName->setText( QString() );
 
  199         ui->NewLong->showInDegrees( SelectedCity->
lng() );
 
  200         ui->NewLat->showInDegrees( SelectedCity->
lat() );
 
  201         ui->TZBox->setEditText( KGlobal::locale()->formatNumber( SelectedCity->
TZ0() ) );
 
  204         for ( 
int i=0; i < ui->DSTRuleBox->count(); ++i ) {
 
  207                 ui->DSTRuleBox->setCurrentIndex( i );
 
  213     nameModified = 
false;
 
  214     dataModified = 
false;
 
  215     ui->AddCityButton->setEnabled( 
false );
 
  220     if ( !nameModified && !dataModified ) {
 
  221         QString message = i18n( 
"This City already exists in the database." );
 
  222         KMessageBox::sorry( 0, message, i18n( 
"Error: Duplicate Entry" ) );
 
  226     bool latOk(
false), lngOk(
false), tzOk(
false);
 
  227     dms lat = ui->NewLat->createDms( 
true, &latOk );
 
  228     dms lng = ui->NewLong->createDms( 
true, &lngOk );
 
  229     QString TimeZoneString = ui->TZBox->lineEdit()->text();
 
  230     TimeZoneString.replace( KGlobal::locale()->decimalSymbol(), 
"." );
 
  231     double TZ = TimeZoneString.toDouble( &tzOk );
 
  233     if ( ui->NewCityName->text().isEmpty() || ui->NewCountryName->text().isEmpty() ) {
 
  234         QString message = i18n( 
"All fields (except province) must be filled to add this location." );
 
  235         KMessageBox::sorry( 0, message, i18n( 
"Fields are Empty" ) );
 
  237     } 
else if ( ! latOk || ! lngOk ) {
 
  238         QString message = i18n( 
"Could not parse the Latitude/Longitude." );
 
  239         KMessageBox::sorry( 0, message, i18n( 
"Bad Coordinates" ) );
 
  242         QString message = i18n( 
"Could not parse coordinates." );
 
  243         KMessageBox::sorry( 0, message, i18n( 
"Bad Coordinates" ) );
 
  246         if ( !nameModified ) {
 
  247             QString message = i18n( 
"Really override original data for this city?" );
 
  248             if ( KMessageBox::questionYesNo( 0, message, i18n( 
"Override Existing Data?" ), KGuiItem(i18n(
"Override Data")), KGuiItem(i18n(
"Do Not Override"))) == KMessageBox::No )
 
  256         QString name = ui->NewCityName->text().trimmed();
 
  257         QString province = ui->NewProvinceName->text().trimmed();
 
  258         QString country = ui->NewCountryName->text().trimmed();
 
  261         file.setFileName( KStandardDirs::locateLocal( 
"appdata", 
"mycities.dat" ) ); 
 
  263         if ( !file.open( QIODevice::ReadWrite | QIODevice::Append ) ) {
 
  264             QString message = i18n( 
"Local cities database could not be opened.\nLocation will not be recorded." );
 
  265             KMessageBox::sorry( 0, message, i18n( 
"Could Not Open File" ) );
 
  268             char ltsgn = 
'N'; 
if ( lat.
degree()<0 ) ltsgn = 
'S';
 
  269             char lgsgn = 
'E'; 
if ( lng.
degree()<0 ) lgsgn = 
'W';
 
  270             QString TZrule = ui->DSTRuleBox->currentText();
 
  272             entry = entry.sprintf( 
"%-32s : %-21s : %-21s : %2d : %2d : %2d : %c : %3d : %2d : %2d : %c : %5.1f : %2s\n",
 
  273                                    name.toLocal8Bit().data(), province.toLocal8Bit().data(), country.toLocal8Bit().data(),
 
  276                                    TZ, TZrule.toLocal8Bit().data() );
 
  284                                               ui->NewCityName->text(), ui->NewProvinceName->text(), ui->NewCountryName->text(),
 
  285                                               TZ, &data->Rulebook[ TZrule ] );
 
  287             data->geoList.append( g );
 
  293             ui->GeoBox->setCurrentItem( 0 );
 
  294             if ( ui->GeoBox->count() ) {
 
  295                 for ( 
int i=0; i<ui->GeoBox->count(); i++ ) {
 
  296                     if ( ui->GeoBox->item(i)->text() == g->
fullName() ) {
 
  297                         ui->GeoBox->setCurrentRow( i );
 
  313     while ( ! filteredCityList.isEmpty() ) filteredCityList.takeFirst();
 
  316         if ( ( abs( lng - 
int( loc->
lng()->
Degrees() ) ) < 3 ) &&
 
  317                 ( abs( lat - 
int( loc->
lat()->
Degrees() ) ) < 3 ) ) {
 
  319             ui->GeoBox->addItem( loc->
fullName() );
 
  320             filteredCityList.append( loc );
 
  324     ui->GeoBox->sortItems();
 
  325     ui->CountLabel->setText( i18np(
"One city matches search criteria",
"%1 cities match search criteria", ui->GeoBox->count()) );
 
  327     if ( ui->GeoBox->count() > 0 )      
 
  328         ui->GeoBox->setCurrentItem( ui->GeoBox->item(0) );
 
  333 bool LocationDialog::checkLongLat() {
 
  334     if ( ui->NewLong->text().isEmpty() || ui->NewLat->text().isEmpty() )
 
  338     double lng = ui->NewLong->createDms(
true, &ok).Degrees();
 
  341     double lat = ui->NewLat->createDms(
true, &ok).Degrees();
 
  345     if( fabs(lng) > 180 || fabs(lat) > 90 )
 
  352     ui->CityFilter->clear();
 
  353     ui->ProvinceFilter->clear();
 
  354     ui->CountryFilter->clear();
 
  355     ui->NewCityName->clear();
 
  356     ui->NewProvinceName->clear();
 
  357     ui->NewCountryName->clear();
 
  358     ui->NewLong->clearFields();
 
  359     ui->NewLat->clearFields();
 
  360     ui->TZBox->lineEdit()->setText( KGlobal::locale()->formatNumber( 0.0 ) );
 
  361     ui->DSTRuleBox->setCurrentIndex( 0 );
 
  363     dataModified = 
false;
 
  364     ui->AddCityButton->setEnabled( 
false );
 
  365     ui->NewCityName->setFocus();
 
  370     lines.append( i18n( 
" Start Date (Start Time)  /  Revert Date (Revert Time)" ) );
 
  372     lines.append( i18n( 
"--: No DST correction" ) );
 
  373     lines.append( i18n( 
"AU: last Sun in Oct. (02:00) / last Sun in Mar. (02:00)" ) );
 
  374     lines.append( i18n( 
"BZ:  2nd Sun in Oct. (00:00) /  3rd Sun in Feb. (00:00)" ) );
 
  375     lines.append( i18n( 
"CH:  2nd Sun in Apr. (00:00) /  2nd Sun in Sep. (00:00)" ) );
 
  376     lines.append( i18n( 
"CL:  2nd Sun in Oct. (04:00) /  2nd Sun in Mar. (04:00)" ) );
 
  377     lines.append( i18n( 
"CZ:  1st Sun in Oct. (02:45) /  3rd Sun in Mar. (02:45)" ) );
 
  378     lines.append( i18n( 
"EE: Last Sun in Mar. (00:00) / Last Sun in Oct. (02:00)" ) );
 
  379     lines.append( i18n( 
"EG: Last Fri in Apr. (00:00) / Last Thu in Sep. (00:00)" ) );
 
  380     lines.append( i18n( 
"EU: Last Sun in Mar. (01:00) / Last Sun in Oct. (01:00)" ) );
 
  381     lines.append( i18n( 
"FK:  1st Sun in Sep. (02:00) /  3rd Sun in Apr. (02:00)" ) );
 
  382     lines.append( i18n( 
"HK:  2nd Sun in May  (03:30) /  3rd Sun in Oct. (03:30)" ) );
 
  383     lines.append( i18n( 
"IQ: Apr 1 (03:00) / Oct. 1 (00:00)" ) );
 
  384     lines.append( i18n( 
"IR: Mar 21 (00:00) / Sep. 22 (00:00)" ) );
 
  385     lines.append( i18n( 
"JD: Last Thu in Mar. (00:00) / Last Thu in Sep. (00:00)" ) );
 
  386     lines.append( i18n( 
"LB: Last Sun in Mar. (00:00) / Last Sun in Oct. (00:00)" ) );
 
  387     lines.append( i18n( 
"MX:  1st Sun in May  (02:00) / Last Sun in Sep. (02:00)" ) );
 
  388     lines.append( i18n( 
"NB:  1st Sun in Sep. (02:00) /  1st Sun in Apr. (02:00)" ) );
 
  389     lines.append( i18n( 
"NZ:  1st Sun in Oct. (02:00) /  3rd Sun in Mar. (02:00)" ) );
 
  390     lines.append( i18n( 
"PY:  1st Sun in Oct. (00:00) /  1st Sun in Mar. (00:00)" ) );
 
  391     lines.append( i18n( 
"RU: Last Sun in Mar. (02:00) / Last Sun in Oct. (02:00)" ) );
 
  392     lines.append( i18n( 
"SK:  2nd Sun in May  (00:00) /  2nd Sun in Oct. (00:00)" ) );
 
  393     lines.append( i18n( 
"SY: Apr. 1 (00:00) / Oct. 1 (00:00)" ) );
 
  394     lines.append( i18n( 
"TG:  1st Sun in Nov. (02:00) / Last Sun in Jan. (02:00)" ) );
 
  395     lines.append( i18n( 
"TS:  1st Sun in Oct. (02:00) / Last Sun in Mar. (02:00)" ) );
 
  396     lines.append( i18n( 
"US:  1st Sun in Apr. (02:00) / Last Sun in Oct. (02:00)" ) );
 
  397     lines.append( i18n( 
"ZN: Apr. 1 (01:00) / Oct. 1 (00:00)" ) );
 
  399     QString message = i18n( 
"Daylight Saving Time Rules" );
 
  402     QPointer<KDialog> tzd = 
new KDialog( 
this );
 
  403     tzd->setCaption( message );
 
  404     tzd->setButtons( KDialog::Close );
 
  405     QListWidget *lw = 
new QListWidget( tzd );
 
  406     lw->addItems( lines );
 
  411     int w = int( 1.1*lw->visualItemRect( lw->item(0) ).width() );
 
  412     lw->setMinimumWidth( w );
 
  413     tzd->setMainWidget( lw );
 
  427     ui->AddCityButton->setEnabled( !ui->NewCityName->text().isEmpty() &&
 
  428                                    !ui->NewCountryName->text().isEmpty() &&
 
  439 #include "locationdialog.moc" 
void initCityList(void)
Initialize list of cities. 
 
KStarsData is the backbone of KStars. 
 
QString translatedName() const 
 
void enqueueFilterCity()
Filter by city / province / country only after a few milliseconds. 
 
void findCitiesNear(int longitude, int latitude)
Show only cities within 3 degrees of point specified by arguments. 
 
static KStarsData * Instance()
 
const double & Degrees() const 
 
void changeCity()
When the selected city in the QListBox changes, repaint the MapCanvas so that the crosshairs icon app...
 
This class provides the information needed to determine whether Daylight Savings Time (DST; a...
 
void filterCity()
When text is entered in the City/Province/Country Filter KLineEdits, the List of cities is trimmed to...
 
QString translatedProvince() const 
 
const QMap< QString, TimeZoneRule > & getRulebook()
Return map for daylight saving rules. 
 
Contains all relevant information for specifying a location on Earth: City Name, State/Province name...
 
bool addCity()
When the "Add new city" QPushButton is clicked, add the manually-entered city information to the user...
 
~LocationDialog()
Destructor (empty) 
 
QList< GeoLocation * > getGeoList()
 
An angle, stored as degrees, but expressible in many ways. 
 
LocationDialog(QWidget *parent)
Constructor. 
 
QString translatedCountry() const 
 
bool equals(TimeZoneRule *r)