summaryrefslogtreecommitdiff
authoreilers <eilers>2003-03-04 16:31:18 (UTC)
committer eilers <eilers>2003-03-04 16:31:18 (UTC)
commit628a783e5d7ec07b5c073c94a77b614439d937ba (patch) (unidiff)
tree30e64e15b94051b185b4c4eecb849e3767d7610b
parent8642232f4435bc5341037527d1eb12d1f39781f4 (diff)
downloadopie-628a783e5d7ec07b5c073c94a77b614439d937ba.zip
opie-628a783e5d7ec07b5c073c94a77b614439d937ba.tar.gz
opie-628a783e5d7ec07b5c073c94a77b614439d937ba.tar.bz2
Name parser completely rewritten ! It is now possible to have as much middle
names as your parents payed for ;) If you have a lastname which was build out of words like "Klara Anne Marie Freifrau von Lichtenstein" or "Carlos Marcos del los Rios" you have to use a "," to separate between first andd last names like this: "del los Rios, Carlos Marcos" or "Freifrau von Lichtenstein, Klara Anne Marie"..
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--core/pim/addressbook/TODO2
-rw-r--r--core/pim/addressbook/contacteditor.cpp235
-rw-r--r--core/pim/addressbook/version.h4
3 files changed, 79 insertions, 162 deletions
diff --git a/core/pim/addressbook/TODO b/core/pim/addressbook/TODO
index a0d50a3..106747e 100644
--- a/core/pim/addressbook/TODO
+++ b/core/pim/addressbook/TODO
@@ -29,7 +29,6 @@ Urgent:
29- Category is on the wrong position after changing to personal and back to normal 29- Category is on the wrong position after changing to personal and back to normal
30 ( Temporarily workaround: Category is never deactivated.. :S ) 30 ( Temporarily workaround: Category is never deactivated.. :S )
31 31
32- Fix handling of 3 Firstnames
33 32
34Important: 33Important:
35---------- 34----------
@@ -114,3 +113,4 @@ Fixed/Ready:
114- Default Email-button: A lot of problems: 113- Default Email-button: A lot of problems:
115 If on second tab: The combo chooser is on the top left of the screen ! :( 114 If on second tab: The combo chooser is on the top left of the screen ! :(
116- Default Email-Button: Sometimes not hiding the textfields completely 115- Default Email-Button: Sometimes not hiding the textfields completely
116- Fix handling of 3 Firstnames
diff --git a/core/pim/addressbook/contacteditor.cpp b/core/pim/addressbook/contacteditor.cpp
index d1338f6..7bc5bde 100644
--- a/core/pim/addressbook/contacteditor.cpp
+++ b/core/pim/addressbook/contacteditor.cpp
@@ -157,61 +157,66 @@ void ContactEditor::init() {
157 txtJobTitle = new QLineEdit( container ); 157 txtJobTitle = new QLineEdit( container );
158 gl->addWidget( txtJobTitle, 1, 1 ); 158 gl->addWidget( txtJobTitle, 1, 1 );
159 159
160 l = new QLabel( tr( "Organization" ), container ); 160 l = new QLabel( tr("Suffix"), container );
161 gl->addWidget( l, 2, 0 ); 161 gl->addWidget( l, 2, 0 );
162 txtSuffix = new QLineEdit( container );
163 gl->addWidget( txtSuffix, 2, 1 );
164
165 l = new QLabel( tr( "Organization" ), container );
166 gl->addWidget( l, 3, 0 );
162 txtOrganization = new QLineEdit( container ); 167 txtOrganization = new QLineEdit( container );
163 gl->addWidget( txtOrganization, 2, 1 ); 168 gl->addWidget( txtOrganization, 3, 1 );
164 169
165 // Chooser 1 170 // Chooser 1
166 cmbChooserField1 = new QComboBox( FALSE, container ); 171 cmbChooserField1 = new QComboBox( FALSE, container );
167 cmbChooserField1->setMaximumWidth( 90 ); 172 cmbChooserField1->setMaximumWidth( 90 );
168 gl->addWidget( cmbChooserField1, 3, 0 ); 173 gl->addWidget( cmbChooserField1, 4, 0 );
169 // Textfield for chooser 1. 174 // Textfield for chooser 1.
170 // Now use Widgetstack to contain the textfield and the default-email combo ! 175 // Now use Widgetstack to contain the textfield and the default-email combo !
171 m_widgetStack1 = new QWidgetStack( container ); 176 m_widgetStack1 = new QWidgetStack( container );
172 txtChooserField1 = new QLineEdit( m_widgetStack1 ); 177 txtChooserField1 = new QLineEdit( m_widgetStack1 );
173 m_widgetStack1 -> addWidget( txtChooserField1, TextField ); 178 m_widgetStack1 -> addWidget( txtChooserField1, TextField );
174 gl->addWidget( m_widgetStack1, 3, 1 ); 179 gl->addWidget( m_widgetStack1, 4, 1 );
175 m_widgetStack1 -> raiseWidget( TextField ); 180 m_widgetStack1 -> raiseWidget( TextField );
176 181
177 // Chooser 2 182 // Chooser 2
178 cmbChooserField2 = new QComboBox( FALSE, container ); 183 cmbChooserField2 = new QComboBox( FALSE, container );
179 cmbChooserField2->setMaximumWidth( 90 ); 184 cmbChooserField2->setMaximumWidth( 90 );
180 gl->addWidget( cmbChooserField2, 4, 0 ); 185 gl->addWidget( cmbChooserField2, 5, 0 );
181 // Textfield for chooser 2 186 // Textfield for chooser 2
182 // Now use WidgetStack to contain the textfield and the default-email combo! 187 // Now use WidgetStack to contain the textfield and the default-email combo!
183 m_widgetStack2 = new QWidgetStack( container ); 188 m_widgetStack2 = new QWidgetStack( container );
184 txtChooserField2 = new QLineEdit( m_widgetStack2 ); 189 txtChooserField2 = new QLineEdit( m_widgetStack2 );
185 m_widgetStack2 -> addWidget( txtChooserField2, TextField ); 190 m_widgetStack2 -> addWidget( txtChooserField2, TextField );
186 gl->addWidget( m_widgetStack2, 4, 1 ); 191 gl->addWidget( m_widgetStack2, 5, 1 );
187 m_widgetStack2 -> raiseWidget( TextField ); 192 m_widgetStack2 -> raiseWidget( TextField );
188 193
189 // Chooser 3 194 // Chooser 3
190 cmbChooserField3 = new QComboBox( FALSE, container ); 195 cmbChooserField3 = new QComboBox( FALSE, container );
191 cmbChooserField3->setMaximumWidth( 90 ); 196 cmbChooserField3->setMaximumWidth( 90 );
192 gl->addWidget( cmbChooserField3, 5, 0 ); 197 gl->addWidget( cmbChooserField3, 6, 0 );
193 // Textfield for chooser 2 198 // Textfield for chooser 2
194 // Now use WidgetStack to contain the textfield and the default-email combo! 199 // Now use WidgetStack to contain the textfield and the default-email combo!
195 m_widgetStack3 = new QWidgetStack( container ); 200 m_widgetStack3 = new QWidgetStack( container );
196 txtChooserField3 = new QLineEdit( m_widgetStack3 ); 201 txtChooserField3 = new QLineEdit( m_widgetStack3 );
197 m_widgetStack3 -> addWidget( txtChooserField3, TextField ); 202 m_widgetStack3 -> addWidget( txtChooserField3, TextField );
198 gl->addWidget( m_widgetStack3, 5, 1 ); 203 gl->addWidget( m_widgetStack3, 6, 1 );
199 m_widgetStack3 -> raiseWidget( TextField ); 204 m_widgetStack3 -> raiseWidget( TextField );
200 205
201 l = new QLabel( tr( "File As" ), container ); 206 l = new QLabel( tr( "File As" ), container );
202 gl->addWidget( l, 6, 0 ); 207 gl->addWidget( l, 7, 0 );
203 cmbFileAs = new QComboBox( TRUE, container ); 208 cmbFileAs = new QComboBox( TRUE, container );
204 gl->addWidget( cmbFileAs, 6, 1 ); 209 gl->addWidget( cmbFileAs, 7, 1 );
205 210
206 labCat = new QLabel( tr( "Category" ), container ); 211 labCat = new QLabel( tr( "Category" ), container );
207 gl->addWidget( labCat, 7, 0 ); 212 gl->addWidget( labCat, 8, 0 );
208 cmbCat = new CategorySelect( container ); 213 cmbCat = new CategorySelect( container );
209 gl->addWidget( cmbCat, 7, 1 ); 214 gl->addWidget( cmbCat, 8, 1 );
210 labCat->show(); 215 labCat->show();
211 cmbCat->show(); 216 cmbCat->show();
212 217
213 btnNote = new QPushButton( tr( "Notes..." ), container ); 218 btnNote = new QPushButton( tr( "Notes..." ), container );
214 gl->addWidget( btnNote, 8, 1 ); 219 gl->addWidget( btnNote, 9, 1 );
215 220
216 tabMain->insertTab( tabViewport, tr( "General" ) ); 221 tabMain->insertTab( tabViewport, tr( "General" ) );
217 222
@@ -618,10 +623,10 @@ void ContactEditor::init() {
618 txtLastName = new QLineEdit( dlgName ); 623 txtLastName = new QLineEdit( dlgName );
619 gl->addWidget( txtLastName, 2, 1 ); 624 gl->addWidget( txtLastName, 2, 1 );
620 625
621 l = new QLabel( tr("Suffix"), dlgName ); 626 // l = new QLabel( tr("Suffix"), dlgName );
622 gl->addWidget( l, 3, 0 ); 627 // gl->addWidget( l, 3, 0 );
623 txtSuffix = new QLineEdit( dlgName ); 628 // txtSuffix = new QLineEdit( dlgName );
624 gl->addWidget( txtSuffix, 3, 1 ); 629 // gl->addWidget( txtSuffix, 3, 1 );
625 space = new QSpacerItem(1,1, 630 space = new QSpacerItem(1,1,
626 QSizePolicy::Maximum, 631 QSizePolicy::Maximum,
627 QSizePolicy::MinimumExpanding ); 632 QSizePolicy::MinimumExpanding );
@@ -1015,14 +1020,16 @@ void ContactEditor::slotAddressTypeChange( int index ) {
1015 1020
1016void ContactEditor::slotFullNameChange( const QString &textChanged ) { 1021void ContactEditor::slotFullNameChange( const QString &textChanged ) {
1017 1022
1023 qWarning( "ContactEditor::slotFullNameChange( %s )", textChanged.latin1() );
1024
1018 int index = cmbFileAs->currentItem(); 1025 int index = cmbFileAs->currentItem();
1019 1026
1020 cmbFileAs->clear(); 1027 cmbFileAs->clear();
1021 1028
1022 cmbFileAs->insertItem( parseName( textChanged, 0 ) ); 1029 cmbFileAs->insertItem( parseName( textChanged, NAME_FL ) );
1023 cmbFileAs->insertItem( parseName( textChanged, 1 ) ); 1030 cmbFileAs->insertItem( parseName( textChanged, NAME_FMLS ) );
1024 cmbFileAs->insertItem( parseName( textChanged, 2 ) ); 1031 cmbFileAs->insertItem( parseName( textChanged, NAME_LF ) );
1025 cmbFileAs->insertItem( parseName( textChanged, 3 ) ); 1032 cmbFileAs->insertItem( parseName( textChanged, NAME_LFM ) );
1026 1033
1027 cmbFileAs->setCurrentItem( index ); 1034 cmbFileAs->setCurrentItem( index );
1028 1035
@@ -1058,7 +1065,7 @@ void ContactEditor::slotName() {
1058 txtFirstName->setText( parseName(txtFullName->text(), NAME_F) ); 1065 txtFirstName->setText( parseName(txtFullName->text(), NAME_F) );
1059 txtMiddleName->setText( parseName(txtFullName->text(), NAME_M) ); 1066 txtMiddleName->setText( parseName(txtFullName->text(), NAME_M) );
1060 txtLastName->setText( parseName(txtFullName->text(), NAME_L) ); 1067 txtLastName->setText( parseName(txtFullName->text(), NAME_L) );
1061 txtSuffix->setText( parseName(txtFullName->text(), NAME_S) ); 1068 // txtSuffix->setText( parseName(txtFullName->text(), NAME_S) );
1062 } 1069 }
1063 dlgName->showMaximized(); 1070 dlgName->showMaximized();
1064 if ( dlgName->exec() ) { 1071 if ( dlgName->exec() ) {
@@ -1102,153 +1109,58 @@ QString ContactEditor::parseName( const QString fullName, int type ) {
1102 QString strSuffix; 1109 QString strSuffix;
1103 QString strTitle; 1110 QString strTitle;
1104 int commapos; 1111 int commapos;
1105 int spCount; 1112 bool haveLastName = false;
1106 int spPos;
1107 int spPos2;
1108 1113
1114 qWarning("Fullname: %s", simplifiedName.latin1());
1109 1115
1110 commapos = simplifiedName.find( ',', 0, TRUE); 1116 commapos = simplifiedName.find( ',', 0, TRUE);
1111 spCount = simplifiedName.contains( ' ', TRUE ); 1117 if ( commapos >= 0 ) {
1118 qWarning(" Commapos: %d", commapos );
1112 1119
1113 if ( commapos == -1 ) { 1120 // A comma (",") separates the lastname from one or
1114 1121 // many first names. Thus, remove the lastname from the
1115 switch (spCount) { 1122 // String and parse the firstnames.
1116 case 0:
1117 //return simplifiedName;
1118 if (txtLastName->text() != "") {
1119 strLastName = simplifiedName;
1120 break;
1121 }
1122 if (txtMiddleName->text() != "") {
1123 strMiddleName = simplifiedName;
1124 break;
1125 }
1126 if (txtSuffix->text() != "") {
1127 strSuffix = simplifiedName;
1128 break;
1129 }
1130 strFirstName = simplifiedName;
1131 break;
1132 1123
1133 case 1: 1124 strLastName = simplifiedName.left( commapos );
1134 spPos = simplifiedName.find( ' ', 0, TRUE ); 1125 simplifiedName= simplifiedName.mid( commapos + 1 );
1135 strFirstName = simplifiedName.left( spPos ); 1126 haveLastName = true;
1136 strLastName = simplifiedName.mid( spPos + 1 ); 1127 qWarning("Fullname without ',': %s", simplifiedName.latin1());
1137 break;
1138 1128
1139 case 2: 1129 // If we have any lastname, we should now split all first names.
1140 spPos = simplifiedName.find( ' ', 0, TRUE ); 1130 // The first one will be the used as first, the rest as "middle names"
1141 strFirstName = simplifiedName.left( spPos );
1142 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE );
1143 strMiddleName = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos );
1144 strLastName = simplifiedName.mid( spPos2 + 1 );
1145 break;
1146 1131
1147 case 3: 1132 QStringList allFirstNames = QStringList::split(" ", simplifiedName);
1148 spPos = simplifiedName.find( ' ', 0, TRUE ); 1133 QStringList::Iterator it = allFirstNames.begin();
1149 strFirstName = simplifiedName.left( spPos ); 1134 strFirstName = *it++;
1150 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE ); 1135 QStringList allSecondNames;
1151 strMiddleName = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos ); 1136 for ( ; it != allFirstNames.end(); ++it )
1152 spPos = simplifiedName.find( ' ', spPos2 + 1, TRUE ); 1137 allSecondNames.append( *it );
1153 strLastName = simplifiedName.mid( spPos2 + 1, (spPos - 1) - spPos2 );
1154 strSuffix = simplifiedName.mid( spPos + 1 );
1155 break;
1156 1138
1157 case 4: 1139 strMiddleName = allSecondNames.join(" ");
1158 spPos = simplifiedName.find( ' ', 0, TRUE );
1159 strTitle = simplifiedName.left( spPos );
1160 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE );
1161 strFirstName = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos );
1162 spPos = simplifiedName.find( ' ', spPos2 + 1, TRUE );
1163 strMiddleName = simplifiedName.mid( spPos2 + 1, (spPos - 1) - spPos2 );
1164 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE );
1165 strLastName = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos );
1166 strSuffix = simplifiedName.mid( spPos2 + 1 );
1167 break;
1168 1140
1169 default:
1170 spPos = simplifiedName.find( ' ', 0, TRUE );
1171 strTitle = simplifiedName.left( spPos );
1172 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE );
1173 strFirstName = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos );
1174 spPos = simplifiedName.find( ' ', spPos2 + 1, TRUE );
1175 strMiddleName = simplifiedName.mid( spPos2 + 1, (spPos - 1) - spPos2 );
1176 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE );
1177 strLastName = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos );
1178 strSuffix = simplifiedName.mid( spPos2 + 1 );
1179 break;
1180 }
1181 } else { 1141 } else {
1182 simplifiedName.replace( commapos, 1, " " );
1183 simplifiedName = simplifiedName.simplifyWhiteSpace();
1184
1185 switch (spCount) {
1186 case 0:
1187 //return simplifiedName;
1188 if (txtLastName->text() != "") {
1189 strLastName = simplifiedName;
1190 break;
1191 }
1192 if (txtMiddleName->text() != "") {
1193 strMiddleName = simplifiedName;
1194 break;
1195 }
1196 if (txtSuffix->text() != "") {
1197 strSuffix = simplifiedName;
1198 break;
1199 }
1200 strFirstName = simplifiedName;
1201 break;
1202
1203 case 1:
1204 spPos = simplifiedName.find( ' ', 0, TRUE );
1205 strLastName = simplifiedName.left( spPos );
1206 strFirstName = simplifiedName.mid( spPos + 1 );
1207 break;
1208 1142
1209 case 2: 1143 // No comma separator used: We use the first word as firstname, the
1210 spPos = simplifiedName.find( ' ', 0, TRUE ); 1144 // last as second/lastname and everything in the middle as middlename
1211 strLastName = simplifiedName.left( spPos );
1212 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE );
1213 strFirstName = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos );
1214 strMiddleName = simplifiedName.mid( spPos2 + 1 );
1215 break;
1216 1145
1217 case 3: 1146 QStringList allNames = QStringList::split(" ", simplifiedName);
1218 spPos = simplifiedName.find( ' ', 0, TRUE ); 1147 QStringList::Iterator it = allNames.begin();
1219 strLastName = simplifiedName.left( spPos ); 1148 strFirstName = *it++;
1220 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE ); 1149 QStringList allSecondNames;
1221 strFirstName = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos ); 1150 for ( ; it != --allNames.end(); ++it )
1222 spPos = simplifiedName.find( ' ', spPos2 + 1, TRUE ); 1151 allSecondNames.append( *it );
1223 strMiddleName = simplifiedName.mid( spPos2 + 1, (spPos - 1) - spPos2 );
1224 strSuffix = simplifiedName.mid( spPos + 1 );
1225 break;
1226 1152
1227 case 4: 1153 strMiddleName = allSecondNames.join(" ");
1228 spPos = simplifiedName.find( ' ', 0, TRUE ); 1154 strLastName = *(--allNames.end());
1229 strLastName = simplifiedName.left( spPos );
1230 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE );
1231 strTitle = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos );
1232 spPos = simplifiedName.find( ' ', spPos2 + 1, TRUE );
1233 strFirstName = simplifiedName.mid( spPos2 + 1, (spPos - 1) - spPos2 );
1234 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE );
1235 strMiddleName = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos );
1236 strSuffix = simplifiedName.mid( spPos2 + 1 );
1237 break;
1238 1155
1239 default:
1240 spPos = simplifiedName.find( ' ', 0, TRUE );
1241 strLastName = simplifiedName.left( spPos );
1242 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE );
1243 strTitle = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos );
1244 spPos = simplifiedName.find( ' ', spPos2 + 1, TRUE );
1245 strFirstName = simplifiedName.mid( spPos2 + 1, (spPos - 1) - spPos );
1246 spPos2 = simplifiedName.find( ' ', spPos + 1, TRUE );
1247 strMiddleName = simplifiedName.mid( spPos + 1, (spPos2 - 1) - spPos );
1248 strSuffix = simplifiedName.mid( spPos2 + 1 );
1249 break;
1250 }
1251 } 1156 }
1157
1158 qWarning(" strFirstName: %s", strFirstName.latin1());
1159 qWarning(" strMiddleName: %s", strMiddleName.latin1());
1160 qWarning(" strLastName: %s", strLastName.latin1());
1161 qWarning(" strSuffix: %s", strSuffix.latin1());
1162 qWarning(" strTitle: %s", strTitle.latin1());
1163
1252 switch (type) { 1164 switch (type) {
1253 case NAME_FL: 1165 case NAME_FL:
1254 return strFirstName + " " + strLastName; 1166 return strFirstName + " " + strLastName;
@@ -1336,11 +1248,16 @@ void ContactEditor::setEntry( const OContact &entry ) {
1336 txtLastName->setText( ent.lastName() ); 1248 txtLastName->setText( ent.lastName() );
1337 txtSuffix->setText( ent.suffix() ); 1249 txtSuffix->setText( ent.suffix() );
1338 1250
1339 QString *tmpString = new QString; 1251 // QString *tmpString = new QString;
1340 *tmpString = ent.firstName() + " " + ent.middleName() + 1252 // *tmpString = ent.firstName() + " " + ent.middleName() +
1341 + " " + ent.lastName() + " " + ent.suffix(); 1253 // + " " + ent.lastName() + " " + ent.suffix();
1254 //txtFullName->setText( tmpString->simplifyWhiteSpace() );
1342 1255
1343 txtFullName->setText( tmpString->simplifyWhiteSpace() ); 1256 // Lastnames with multiple words need to be protected by a comma !
1257 if ( ent.lastName().contains( ' ', TRUE ) )
1258 txtFullName->setText( ent.lastName() + ", " + ent.firstName() + " " + ent.middleName() );
1259 else
1260 txtFullName->setText( ent.firstName() + " " + ent.middleName() + " " + ent.lastName() );
1344 1261
1345 cmbFileAs->setEditText( ent.fileAs() ); 1262 cmbFileAs->setEditText( ent.fileAs() );
1346 1263
@@ -1551,7 +1468,7 @@ void ContactEditor::saveEntry() {
1551 txtFirstName->setText( parseName( txtFullName->text(), NAME_F ) ); 1468 txtFirstName->setText( parseName( txtFullName->text(), NAME_F ) );
1552 txtMiddleName->setText( parseName( txtFullName->text(), NAME_M ) ); 1469 txtMiddleName->setText( parseName( txtFullName->text(), NAME_M ) );
1553 txtLastName->setText( parseName( txtFullName->text(), NAME_L ) ); 1470 txtLastName->setText( parseName( txtFullName->text(), NAME_L ) );
1554 txtSuffix->setText( parseName( txtFullName->text(), NAME_S ) ); 1471 // txtSuffix->setText( parseName( txtFullName->text(), NAME_S ) );
1555 1472
1556 useFullName = false; 1473 useFullName = false;
1557 } 1474 }
diff --git a/core/pim/addressbook/version.h b/core/pim/addressbook/version.h
index 3becfdc..c2ead05 100644
--- a/core/pim/addressbook/version.h
+++ b/core/pim/addressbook/version.h
@@ -2,8 +2,8 @@
2#define _VERSION_H_ 2#define _VERSION_H_
3 3
4#define MAINVERSION "0" 4#define MAINVERSION "0"
5#define SUBVERSION "2" 5#define SUBVERSION "3"
6#define PATCHVERSION "2" 6#define PATCHVERSION "0"
7 7
8#define APPNAME "OPIE_ADDRESSBOOK" 8#define APPNAME "OPIE_ADDRESSBOOK"
9 9