summaryrefslogtreecommitdiff
authorzecke <zecke>2002-06-19 17:38:11 (UTC)
committer zecke <zecke>2002-06-19 17:38:11 (UTC)
commit23ac56db3aa77b298f20b288aadf503fd09a23a9 (patch) (unidiff)
treefe820ec743bbf829d31ae3ab1436a41a69b1855c
parentdee5f6c5a3bd982913d0b234fb9392ce68d5df63 (diff)
downloadopie-23ac56db3aa77b298f20b288aadf503fd09a23a9.zip
opie-23ac56db3aa77b298f20b288aadf503fd09a23a9.tar.gz
opie-23ac56db3aa77b298f20b288aadf503fd09a23a9.tar.bz2
Tille ask Diana how she was able to trigger that bug?
I nominate her for the bug finding queen 2002. Ok I just fixed two possible crashes with the risk of losing data.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/pim/addressbook/abtable.cpp25
1 files changed, 17 insertions, 8 deletions
diff --git a/core/pim/addressbook/abtable.cpp b/core/pim/addressbook/abtable.cpp
index e9e6a0b..3fa1a7c 100644
--- a/core/pim/addressbook/abtable.cpp
+++ b/core/pim/addressbook/abtable.cpp
@@ -53,1149 +53,1158 @@ static QString journalFileName()
53 53
54/*! 54/*!
55 \class AbTableItem abtable.h 55 \class AbTableItem abtable.h
56 56
57 \brief QTableItem based class for showing a field of an entry 57 \brief QTableItem based class for showing a field of an entry
58*/ 58*/
59 59
60AbTableItem::AbTableItem( QTable *t, EditType et, const QString &s, 60AbTableItem::AbTableItem( QTable *t, EditType et, const QString &s,
61 const QString &secondSortKey) 61 const QString &secondSortKey)
62 : QTableItem( t, et, s ) 62 : QTableItem( t, et, s )
63{ 63{
64 // sortKey = s.lower() + QChar( '\0' ) + secondSortKey.lower(); 64 // sortKey = s.lower() + QChar( '\0' ) + secondSortKey.lower();
65 sortKey = Qtopia::buildSortKey( s, secondSortKey ); 65 sortKey = Qtopia::buildSortKey( s, secondSortKey );
66} 66}
67 67
68int AbTableItem::alignment() const 68int AbTableItem::alignment() const
69{ 69{
70 return AlignLeft|AlignVCenter; 70 return AlignLeft|AlignVCenter;
71} 71}
72 72
73QString AbTableItem::key() const 73QString AbTableItem::key() const
74{ 74{
75 return sortKey; 75 return sortKey;
76} 76}
77 77
78// A way to reset the item, without out doing a delete or a new... 78// A way to reset the item, without out doing a delete or a new...
79void AbTableItem::setItem( const QString &txt, const QString &secondKey ) 79void AbTableItem::setItem( const QString &txt, const QString &secondKey )
80{ 80{
81 setText( txt ); 81 setText( txt );
82 sortKey = Qtopia::buildSortKey( txt, secondKey ); 82 sortKey = Qtopia::buildSortKey( txt, secondKey );
83 83
84 // sortKey = txt.lower() + QChar( '\0' ) + secondKey.lower(); 84 // sortKey = txt.lower() + QChar( '\0' ) + secondKey.lower();
85} 85}
86 86
87/*! 87/*!
88 \class AbPickItem abtable.h 88 \class AbPickItem abtable.h
89 89
90 \brief QTableItem based class for showing slection of an entry 90 \brief QTableItem based class for showing slection of an entry
91*/ 91*/
92 92
93AbPickItem::AbPickItem( QTable *t ) : 93AbPickItem::AbPickItem( QTable *t ) :
94 QTableItem(t, WhenCurrent, "?") 94 QTableItem(t, WhenCurrent, "?")
95{ 95{
96} 96}
97 97
98QWidget *AbPickItem::createEditor() const 98QWidget *AbPickItem::createEditor() const
99{ 99{
100 QComboBox* combo = new QComboBox( table()->viewport() ); 100 QComboBox* combo = new QComboBox( table()->viewport() );
101 ( (AbPickItem*)this )->cb = combo; 101 ( (AbPickItem*)this )->cb = combo;
102 AbTable* t = static_cast<AbTable*>(table()); 102 AbTable* t = static_cast<AbTable*>(table());
103 QStringList c = t->choiceNames(); 103 QStringList c = t->choiceNames();
104 int cur = 0; 104 int cur = 0;
105 for (QStringList::ConstIterator it = c.begin(); it!=c.end(); ++it) { 105 for (QStringList::ConstIterator it = c.begin(); it!=c.end(); ++it) {
106 if ( *it == text() ) 106 if ( *it == text() )
107 cur = combo->count(); 107 cur = combo->count();
108 combo->insertItem(*it); 108 combo->insertItem(*it);
109 } 109 }
110 combo->setCurrentItem(cur); 110 combo->setCurrentItem(cur);
111 return combo; 111 return combo;
112} 112}
113 113
114void AbPickItem::setContentFromEditor( QWidget *w ) 114void AbPickItem::setContentFromEditor( QWidget *w )
115{ 115{
116 if ( w->inherits("QComboBox") ) 116 if ( w->inherits("QComboBox") )
117 setText( ( (QComboBox*)w )->currentText() ); 117 setText( ( (QComboBox*)w )->currentText() );
118 else 118 else
119 QTableItem::setContentFromEditor( w ); 119 QTableItem::setContentFromEditor( w );
120} 120}
121 121
122/*! 122/*!
123 \class AbTable abtable.h 123 \class AbTable abtable.h
124 124
125 \brief QTable based class for showing a list of entries 125 \brief QTable based class for showing a list of entries
126*/ 126*/
127 127
128AbTable::AbTable( const QValueList<int> *order, QWidget *parent, const char *name ) 128AbTable::AbTable( const QValueList<int> *order, QWidget *parent, const char *name )
129// #ifdef QT_QTABLE_NOHEADER_CONSTRUCTOR 129// #ifdef QT_QTABLE_NOHEADER_CONSTRUCTOR
130// : QTable( 0, 0, parent, name, TRUE ), 130// : QTable( 0, 0, parent, name, TRUE ),
131// #else 131// #else
132 : QTable( parent, name ), 132 : QTable( parent, name ),
133// #endif 133// #endif
134 lastSortCol( -1 ), 134 lastSortCol( -1 ),
135 asc( TRUE ), 135 asc( TRUE ),
136 intFields( order ), 136 intFields( order ),
137 currFindRow( -2 ), 137 currFindRow( -2 ),
138 mCat( 0 ) 138 mCat( 0 )
139{ 139{
140 mCat.load( categoryFileName() ); 140 mCat.load( categoryFileName() );
141 setSelectionMode( NoSelection ); 141 setSelectionMode( NoSelection );
142 init(); 142 init();
143 setSorting( TRUE ); 143 setSorting( TRUE );
144 connect( this, SIGNAL(clicked(int,int,int,const QPoint &)), 144 connect( this, SIGNAL(clicked(int,int,int,const QPoint &)),
145 this, SLOT(itemClicked(int,int)) ); 145 this, SLOT(itemClicked(int,int)) );
146} 146}
147 147
148AbTable::~AbTable() 148AbTable::~AbTable()
149{ 149{
150} 150}
151 151
152void AbTable::init() 152void AbTable::init()
153{ 153{
154 showChar = '\0'; 154 showChar = '\0';
155 setNumRows( 0 ); 155 setNumRows( 0 );
156 setNumCols( 2 ); 156 setNumCols( 2 );
157 157
158 horizontalHeader()->setLabel( 0, tr( "Full Name" )); 158 horizontalHeader()->setLabel( 0, tr( "Full Name" ));
159 horizontalHeader()->setLabel( 1, tr( "Contact" )); 159 horizontalHeader()->setLabel( 1, tr( "Contact" ));
160 setLeftMargin( 0 ); 160 setLeftMargin( 0 );
161 verticalHeader()->hide(); 161 verticalHeader()->hide();
162} 162}
163 163
164void AbTable::columnClicked( int col ) 164void AbTable::columnClicked( int col )
165{ 165{
166 if ( !sorting() ) 166 if ( !sorting() )
167 return; 167 return;
168 168
169 if ( lastSortCol == -1 ) 169 if ( lastSortCol == -1 )
170 lastSortCol = col; 170 lastSortCol = col;
171 171
172 if ( col == lastSortCol ) { 172 if ( col == lastSortCol ) {
173 asc = !asc; 173 asc = !asc;
174 } else { 174 } else {
175 lastSortCol = col; 175 lastSortCol = col;
176 asc = TRUE; 176 asc = TRUE;
177 } 177 }
178 resort(); 178 resort();
179} 179}
180 180
181void AbTable::resort() 181void AbTable::resort()
182{ 182{
183 if ( sorting() ) { 183 if ( sorting() ) {
184 if ( lastSortCol == -1 ) 184 if ( lastSortCol == -1 )
185 lastSortCol = 0; 185 lastSortCol = 0;
186 sortColumn( lastSortCol, asc, TRUE ); 186 sortColumn( lastSortCol, asc, TRUE );
187 updateVisible(); 187 updateVisible();
188 } 188 }
189} 189}
190 190
191Contact AbTable::currentEntry() 191Contact AbTable::currentEntry()
192{ 192{
193 Contact cnt; 193 Contact cnt;
194 AbTableItem *abItem; 194 AbTableItem *abItem;
195 abItem = static_cast<AbTableItem*>(item( currentRow(), 0 )); 195 abItem = static_cast<AbTableItem*>(item( currentRow(), 0 ));
196 if ( abItem ) { 196 if ( abItem ) {
197 cnt = contactList[abItem]; 197 cnt = contactList[abItem];
198 } 198 }
199 return cnt; 199 return cnt;
200} 200}
201 201
202void AbTable::replaceCurrentEntry( const Contact &newContact ) 202void AbTable::replaceCurrentEntry( const Contact &newContact )
203{ 203{
204 int row = currentRow(); 204 int row = currentRow();
205 updateJournal( newContact, Contact::ACTION_REPLACE, row ); 205 updateJournal( newContact, Contact::ACTION_REPLACE, row );
206 updateVisible(); 206 updateVisible();
207 207
208 journalFreeReplace( newContact, row ); 208 journalFreeReplace( newContact, row );
209} 209}
210 210
211void AbTable::deleteCurrentEntry() 211void AbTable::deleteCurrentEntry()
212{ 212{
213 int row = currentRow(); 213 int row = currentRow();
214 AbTableItem *abItem; 214 AbTableItem *abItem;
215 abItem = static_cast<AbTableItem*>(item( row, 0 )); 215 abItem = static_cast<AbTableItem*>(item( row, 0 ));
216 Contact oldContact; 216 Contact oldContact;
217 oldContact = contactList[abItem]; 217 oldContact = contactList[abItem];
218 updateJournal( oldContact, Contact::ACTION_REMOVE, row ); 218 updateJournal( oldContact, Contact::ACTION_REMOVE, row );
219 219
220 // a little wasteful, but it ensure's there is only one place 220 // a little wasteful, but it ensure's there is only one place
221 // where we delete. 221 // where we delete.
222 journalFreeRemove( row ); 222 journalFreeRemove( row );
223 updateVisible(); 223 updateVisible();
224 224
225 if ( numRows() == 0 ) 225 if ( numRows() == 0 )
226 emit empty( TRUE ); 226 emit empty( TRUE );
227} 227}
228 228
229void AbTable::clear() 229void AbTable::clear()
230{ 230{
231 contactList.clear(); 231 contactList.clear();
232 for ( int r = 0; r < numRows(); ++r ) { 232 for ( int r = 0; r < numRows(); ++r ) {
233 for ( int c = 0; c < numCols(); ++c ) { 233 for ( int c = 0; c < numCols(); ++c ) {
234 if ( cellWidget( r, c ) ) 234 if ( cellWidget( r, c ) )
235 clearCellWidget( r, c ); 235 clearCellWidget( r, c );
236 clearCell( r, c ); 236 clearCell( r, c );
237 } 237 }
238 } 238 }
239 setNumRows( 0 ); 239 setNumRows( 0 );
240} 240}
241 241
242void AbTable::refresh() 242void AbTable::refresh()
243{ 243{
244 int rows = numRows(); 244 int rows = numRows();
245 QString value; 245 QString value;
246 AbTableItem *abi; 246 AbTableItem *abi;
247 for ( int r = 0; r < rows; ++r ) { 247 for ( int r = 0; r < rows; ++r ) {
248 abi = static_cast<AbTableItem*>( item(r, 0) ); 248 abi = static_cast<AbTableItem*>( item(r, 0) );
249 value = findContactContact( contactList[abi] ); 249 value = findContactContact( contactList[abi] );
250 static_cast<AbTableItem*>( item(r, 1) )->setItem( value, abi->text() ); 250 static_cast<AbTableItem*>( item(r, 1) )->setItem( value, abi->text() );
251 } 251 }
252 resort(); 252 resort();
253} 253}
254 254
255void AbTable::keyPressEvent( QKeyEvent *e ) 255void AbTable::keyPressEvent( QKeyEvent *e )
256{ 256{
257 char key = toupper( e->ascii() ); 257 char key = toupper( e->ascii() );
258 258
259 if ( key >= 'A' && key <= 'Z' ) 259 if ( key >= 'A' && key <= 'Z' )
260 moveTo( key ); 260 moveTo( key );
261 261
262 switch( e->key() ) { 262 switch( e->key() ) {
263 case Qt::Key_Space: 263 case Qt::Key_Space:
264 case Qt::Key_Return: 264 case Qt::Key_Return:
265 case Qt::Key_Enter: 265 case Qt::Key_Enter:
266 emit details(); 266 emit details();
267 break; 267 break;
268 default: 268 default:
269 QTable::keyPressEvent( e ); 269 QTable::keyPressEvent( e );
270 } 270 }
271} 271}
272 272
273void AbTable::moveTo( char c ) 273void AbTable::moveTo( char c )
274{ 274{
275 275
276 int rows = numRows(); 276 int rows = numRows();
277 QString value; 277 QString value;
278 AbTableItem *abi; 278 AbTableItem *abi;
279 int r; 279 int r;
280 if ( asc ) { 280 if ( asc ) {
281 r = 0; 281 r = 0;
282 while ( r < rows-1) { 282 while ( r < rows-1) {
283 abi = static_cast<AbTableItem*>( item(r, 0) ); 283 abi = static_cast<AbTableItem*>( item(r, 0) );
284 QChar first = abi->key()[0]; 284 QChar first = abi->key()[0];
285 //### is there a bug in QChar to char comparison??? 285 //### is there a bug in QChar to char comparison???
286 if ( first.row() || first.cell() >= c ) 286 if ( first.row() || first.cell() >= c )
287 break; 287 break;
288 r++; 288 r++;
289 } 289 }
290 } else { 290 } else {
291 //### should probably disable reverse sorting instead 291 //### should probably disable reverse sorting instead
292 r = rows - 1; 292 r = rows - 1;
293 while ( r > 0 ) { 293 while ( r > 0 ) {
294 abi = static_cast<AbTableItem*>( item(r, 0) ); 294 abi = static_cast<AbTableItem*>( item(r, 0) );
295 QChar first = abi->key()[0]; 295 QChar first = abi->key()[0];
296 //### is there a bug in QChar to char comparison??? 296 //### is there a bug in QChar to char comparison???
297 if ( first.row() || first.cell() >= c ) 297 if ( first.row() || first.cell() >= c )
298 break; 298 break;
299 r--; 299 r--;
300 } 300 }
301 } 301 }
302 setCurrentCell( r, currentColumn() ); 302 setCurrentCell( r, currentColumn() );
303} 303}
304 304
305 305
306QString AbTable::findContactName( const Contact &entry ) 306QString AbTable::findContactName( const Contact &entry )
307{ 307{
308 // We use the fileAs, then company, defaultEmail 308 // We use the fileAs, then company, defaultEmail
309 QString str; 309 QString str;
310 str = entry.fileAs(); 310 str = entry.fileAs();
311 if ( str.isEmpty() ) { 311 if ( str.isEmpty() ) {
312 str = entry.company(); 312 str = entry.company();
313 if ( str.isEmpty() ) { 313 if ( str.isEmpty() ) {
314 str = entry.defaultEmail(); 314 str = entry.defaultEmail();
315 } 315 }
316 } 316 }
317 return str; 317 return str;
318} 318}
319 319
320QString AbTable::findContactContact( const Contact &entry ) 320QString AbTable::findContactContact( const Contact &entry )
321{ 321{
322 QString value; 322 QString value;
323 value = ""; 323 value = "";
324 for ( QValueList<int>::ConstIterator it = intFields->begin(); 324 for ( QValueList<int>::ConstIterator it = intFields->begin();
325 it != intFields->end(); ++it ) { 325 it != intFields->end(); ++it ) {
326 switch ( *it ) { 326 switch ( *it ) {
327 default: 327 default:
328 break; 328 break;
329 case Qtopia::Title: 329 case Qtopia::Title:
330 value = entry.title(); 330 value = entry.title();
331 break; 331 break;
332 case Qtopia::Suffix: 332 case Qtopia::Suffix:
333 value = entry.suffix(); 333 value = entry.suffix();
334 break; 334 break;
335 case Qtopia::FileAs: 335 case Qtopia::FileAs:
336 value = entry.fileAs(); 336 value = entry.fileAs();
337 break; 337 break;
338 case Qtopia::DefaultEmail: 338 case Qtopia::DefaultEmail:
339 value = entry.defaultEmail(); 339 value = entry.defaultEmail();
340 case Qtopia::Emails: 340 case Qtopia::Emails:
341 value = entry.emails(); 341 value = entry.emails();
342 break; 342 break;
343 case Qtopia::HomeStreet: 343 case Qtopia::HomeStreet:
344 value = entry.homeStreet(); 344 value = entry.homeStreet();
345 break; 345 break;
346 case Qtopia::HomeCity: 346 case Qtopia::HomeCity:
347 value = entry.homeCity(); 347 value = entry.homeCity();
348 break; 348 break;
349 case Qtopia::HomeState: 349 case Qtopia::HomeState:
350 value = entry.homeState(); 350 value = entry.homeState();
351 break; 351 break;
352 case Qtopia::HomeZip: 352 case Qtopia::HomeZip:
353 value = entry.homeZip(); 353 value = entry.homeZip();
354 break; 354 break;
355 case Qtopia::HomeCountry: 355 case Qtopia::HomeCountry:
356 value = entry.homeCountry(); 356 value = entry.homeCountry();
357 break; 357 break;
358 case Qtopia::HomePhone: 358 case Qtopia::HomePhone:
359 value = entry.homePhone(); 359 value = entry.homePhone();
360 break; 360 break;
361 case Qtopia::HomeFax: 361 case Qtopia::HomeFax:
362 value = entry.homeFax(); 362 value = entry.homeFax();
363 break; 363 break;
364 case Qtopia::HomeMobile: 364 case Qtopia::HomeMobile:
365 value = entry.homeMobile(); 365 value = entry.homeMobile();
366 break; 366 break;
367 case Qtopia::HomeWebPage: 367 case Qtopia::HomeWebPage:
368 value = entry.homeWebpage(); 368 value = entry.homeWebpage();
369 break; 369 break;
370 case Qtopia::Company: 370 case Qtopia::Company:
371 value = entry.company(); 371 value = entry.company();
372 break; 372 break;
373 case Qtopia::BusinessCity: 373 case Qtopia::BusinessCity:
374 value = entry.businessCity(); 374 value = entry.businessCity();
375 break; 375 break;
376 case Qtopia::BusinessStreet: 376 case Qtopia::BusinessStreet:
377 value = entry.businessStreet(); 377 value = entry.businessStreet();
378 break; 378 break;
379 case Qtopia::BusinessZip: 379 case Qtopia::BusinessZip:
380 value = entry.businessZip(); 380 value = entry.businessZip();
381 break; 381 break;
382 case Qtopia::BusinessCountry: 382 case Qtopia::BusinessCountry:
383 value = entry.businessCountry(); 383 value = entry.businessCountry();
384 break; 384 break;
385 case Qtopia::BusinessWebPage: 385 case Qtopia::BusinessWebPage:
386 value = entry.businessWebpage(); 386 value = entry.businessWebpage();
387 break; 387 break;
388 case Qtopia::JobTitle: 388 case Qtopia::JobTitle:
389 value = entry.jobTitle(); 389 value = entry.jobTitle();
390 break; 390 break;
391 case Qtopia::Department: 391 case Qtopia::Department:
392 value = entry.department(); 392 value = entry.department();
393 break; 393 break;
394 case Qtopia::Office: 394 case Qtopia::Office:
395 value = entry.office(); 395 value = entry.office();
396 break; 396 break;
397 case Qtopia::BusinessPhone: 397 case Qtopia::BusinessPhone:
398 value = entry.businessPhone(); 398 value = entry.businessPhone();
399 break; 399 break;
400 case Qtopia::BusinessFax: 400 case Qtopia::BusinessFax:
401 value = entry.businessFax(); 401 value = entry.businessFax();
402 break; 402 break;
403 case Qtopia::BusinessMobile: 403 case Qtopia::BusinessMobile:
404 value = entry.businessMobile(); 404 value = entry.businessMobile();
405 break; 405 break;
406 case Qtopia::BusinessPager: 406 case Qtopia::BusinessPager:
407 value = entry.businessPager(); 407 value = entry.businessPager();
408 break; 408 break;
409 case Qtopia::Profession: 409 case Qtopia::Profession:
410 value = entry.profession(); 410 value = entry.profession();
411 break; 411 break;
412 case Qtopia::Assistant: 412 case Qtopia::Assistant:
413 value = entry.assistant(); 413 value = entry.assistant();
414 break; 414 break;
415 case Qtopia::Manager: 415 case Qtopia::Manager:
416 value = entry.manager(); 416 value = entry.manager();
417 break; 417 break;
418 case Qtopia::Spouse: 418 case Qtopia::Spouse:
419 value = entry.spouse(); 419 value = entry.spouse();
420 break; 420 break;
421 case Qtopia::Gender: 421 case Qtopia::Gender:
422 value = entry.gender(); 422 value = entry.gender();
423 break; 423 break;
424 case Qtopia::Birthday: 424 case Qtopia::Birthday:
425 value = entry.birthday(); 425 value = entry.birthday();
426 break; 426 break;
427 case Qtopia::Anniversary: 427 case Qtopia::Anniversary:
428 value = entry.anniversary(); 428 value = entry.anniversary();
429 break; 429 break;
430 case Qtopia::Nickname: 430 case Qtopia::Nickname:
431 value = entry.nickname(); 431 value = entry.nickname();
432 break; 432 break;
433 case Qtopia::Children: 433 case Qtopia::Children:
434 value = entry.children(); 434 value = entry.children();
435 break; 435 break;
436 case Qtopia::Notes: 436 case Qtopia::Notes:
437 value = entry.notes(); 437 value = entry.notes();
438 break; 438 break;
439 } 439 }
440 if ( !value.isEmpty() ) 440 if ( !value.isEmpty() )
441 break; 441 break;
442 } 442 }
443 return value; 443 return value;
444} 444}
445 445
446void AbTable::addEntry( const Contact &newCnt ) 446void AbTable::addEntry( const Contact &newCnt )
447{ 447{
448 int row = numRows(); 448 int row = numRows();
449 setNumRows( row + 1 ); 449 setNumRows( row + 1 );
450 updateJournal( newCnt, Contact::ACTION_ADD ); 450 updateJournal( newCnt, Contact::ACTION_ADD );
451 insertIntoTable( newCnt, row ); 451 insertIntoTable( newCnt, row );
452 setCurrentCell( row, 0 ); 452 setCurrentCell( row, 0 );
453 updateVisible(); 453 updateVisible();
454} 454}
455 455
456void AbTable::resizeRows( int size ) { 456void AbTable::resizeRows( int size ) {
457/* 457/*
458 if (numRows()) { 458 if (numRows()) {
459 for (int i = 0; i < numRows(); i++) { 459 for (int i = 0; i < numRows(); i++) {
460 setRowHeight( i, size ); 460 setRowHeight( i, size );
461 } 461 }
462 }*/ 462 }*/
463 updateVisible(); 463 updateVisible();
464} 464}
465 465
466void AbTable::updateJournal( const Contact &cnt, 466void AbTable::updateJournal( const Contact &cnt,
467 Contact::journal_action action, int row ) 467 Contact::journal_action action, int row )
468{ 468{
469 QFile f( journalFileName() ); 469 QFile f( journalFileName() );
470 if ( !f.open(IO_WriteOnly|IO_Append) ) 470 if ( !f.open(IO_WriteOnly|IO_Append) )
471 return; 471 return;
472 QString buf; 472 QString buf;
473 QCString str; 473 QCString str;
474 buf = "<Contact "; 474 buf = "<Contact ";
475 cnt.save( buf ); 475 cnt.save( buf );
476 buf += " action=\"" + QString::number( (int)action ) + "\" "; 476 buf += " action=\"" + QString::number( (int)action ) + "\" ";
477 if ( action == Contact::ACTION_REMOVE || action == Contact::ACTION_REPLACE) 477 if ( action == Contact::ACTION_REMOVE || action == Contact::ACTION_REPLACE)
478 buf += " actionrow=\"" + QString::number(row) + "\" "; 478 buf += " actionrow=\"" + QString::number(row) + "\" ";
479 buf += "/>\n"; 479 buf += "/>\n";
480 QCString cstr = buf.utf8(); 480 QCString cstr = buf.utf8();
481 f.writeBlock( cstr.data(), cstr.length() ); 481 f.writeBlock( cstr.data(), cstr.length() );
482 QCopEnvelope( "QPE/PIM", "addressbookUpdated()" ); 482 QCopEnvelope( "QPE/PIM", "addressbookUpdated()" );
483} 483}
484 484
485bool AbTable::save( const QString &fn ) 485bool AbTable::save( const QString &fn )
486{ 486{
487// QTime t; 487// QTime t;
488// t.start(); 488// t.start();
489 489
490 QString strNewFile = fn + ".new"; 490 QString strNewFile = fn + ".new";
491 QFile f( strNewFile ); 491 QFile f( strNewFile );
492 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 492 if ( !f.open( IO_WriteOnly|IO_Raw ) )
493 return false; 493 return false;
494 494
495 int total_written; 495 int total_written;
496 QString out; 496 QString out;
497 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n" 497 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Addressbook ><AddressBook>\n"
498 " <Groups>\n" 498 " <Groups>\n"
499 " </Groups>\n" 499 " </Groups>\n"
500 " <Contacts>\n"; 500 " <Contacts>\n";
501 QMapIterator<AbTableItem*, Contact> it; 501 QMapIterator<AbTableItem*, Contact> it;
502 for ( it = contactList.begin(); it != contactList.end(); ++it ) { 502 for ( it = contactList.begin(); it != contactList.end(); ++it ) {
503 out += "<Contact "; 503 out += "<Contact ";
504 it.data().save( out ); 504 it.data().save( out );
505 out += "/>\n"; 505 out += "/>\n";
506 QCString cstr = out.utf8(); 506 QCString cstr = out.utf8();
507 total_written = f.writeBlock( cstr.data(), cstr.length() ); 507 total_written = f.writeBlock( cstr.data(), cstr.length() );
508 if ( total_written != int(cstr.length()) ) { 508 if ( total_written != int(cstr.length()) ) {
509 f.close(); 509 f.close();
510 QFile::remove( strNewFile ); 510 QFile::remove( strNewFile );
511 return false; 511 return false;
512 } 512 }
513 out = ""; 513 out = "";
514 } 514 }
515 out += " </Contacts>\n</AddressBook>\n"; 515 out += " </Contacts>\n</AddressBook>\n";
516 516
517 QCString cstr = out.utf8(); 517 QCString cstr = out.utf8();
518 total_written = f.writeBlock( cstr.data(), cstr.length() ); 518 total_written = f.writeBlock( cstr.data(), cstr.length() );
519 if ( total_written != int(cstr.length()) ) { 519 if ( total_written != int(cstr.length()) ) {
520 f.close(); 520 f.close();
521 QFile::remove( strNewFile ); 521 QFile::remove( strNewFile );
522 return false; 522 return false;
523 } 523 }
524 f.close(); 524 f.close();
525 525
526// qDebug("saving: %d", t.elapsed() ); 526// qDebug("saving: %d", t.elapsed() );
527 527
528 // move the file over, I'm just going to use the system call 528 // move the file over, I'm just going to use the system call
529 // because, I don't feel like using QDir. 529 // because, I don't feel like using QDir.
530 if ( ::rename( strNewFile.latin1(), fn.latin1() ) < 0 ) { 530 if ( ::rename( strNewFile.latin1(), fn.latin1() ) < 0 ) {
531 qWarning( "problem renaming file %s to %s, errno: %d", 531 qWarning( "problem renaming file %s to %s, errno: %d",
532 strNewFile.latin1(), fn.latin1(), errno ); 532 strNewFile.latin1(), fn.latin1(), errno );
533 // remove the tmp file... 533 // remove the tmp file...
534 QFile::remove( strNewFile ); 534 QFile::remove( strNewFile );
535 } 535 }
536 // remove the journal... 536 // remove the journal...
537 QFile::remove( journalFileName() ); 537 QFile::remove( journalFileName() );
538 return true; 538 return true;
539} 539}
540 540
541void AbTable::load( const QString &fn ) 541void AbTable::load( const QString &fn )
542{ 542{
543 setSorting( false ); 543 setSorting( false );
544 loadFile( fn, false ); 544 loadFile( fn, false );
545 // merge in the journal 545 // merge in the journal
546 if ( QFile::exists( journalFileName() ) ) { 546 if ( QFile::exists( journalFileName() ) ) {
547 loadFile( journalFileName(), true ); 547 loadFile( journalFileName(), true );
548 save( fn ); 548 save( fn );
549 } 549 }
550 setSorting( true ); 550 setSorting( true );
551 resort(); 551 resort();
552} 552}
553 553
554void AbTable::loadFile( const QString &strFile, bool journalFile ) 554void AbTable::loadFile( const QString &strFile, bool journalFile )
555{ 555{
556// QTime t; 556// QTime t;
557// t.start(); 557// t.start();
558 QFile f( strFile ); 558 QFile f( strFile );
559 if ( !f.open(IO_ReadOnly) ) 559 if ( !f.open(IO_ReadOnly) )
560 return; 560 return;
561 QList<Contact> list; 561 QList<Contact> list;
562 list.setAutoDelete( TRUE ); 562 list.setAutoDelete( TRUE );
563 QByteArray ba = f.readAll(); 563 QByteArray ba = f.readAll();
564 f.close(); 564 f.close();
565 if (ba.isEmpty() )
566 return;
565 char *uc = ba.data();//(QChar *)data.unicode(); 567 char *uc = ba.data();//(QChar *)data.unicode();
566 int len = ba.size();//data.length(); 568 int len = ba.size();//data.length();
567 bool foundAction = false; 569 bool foundAction = false;
568 Contact::journal_action action; 570 Contact::journal_action action;
569 bool foundKey = false; 571 bool foundKey = false;
570 int journalKey = 0; 572 int journalKey = 0;
571 573
572 const int JOURNALACTION = Qtopia::Notes + 1; 574 const int JOURNALACTION = Qtopia::Notes + 1;
573 const int JOURNALROW = JOURNALACTION + 1; 575 const int JOURNALROW = JOURNALACTION + 1;
574 576
575 // ********************************** 577 // **********************************
576 // CHANGE THE SIZE OF THE DICT IF YOU ADD ANY MORE FIELDS!!!! 578 // CHANGE THE SIZE OF THE DICT IF YOU ADD ANY MORE FIELDS!!!!
577 // ********************************** 579 // **********************************
578 QAsciiDict<int> dict( 47 ); 580 QAsciiDict<int> dict( 47 );
579 dict.setAutoDelete( TRUE ); 581 dict.setAutoDelete( TRUE );
580 dict.insert( "Uid", new int(Qtopia::AddressUid) ); 582 dict.insert( "Uid", new int(Qtopia::AddressUid) );
581 dict.insert( "Title", new int(Qtopia::Title) ); 583 dict.insert( "Title", new int(Qtopia::Title) );
582 dict.insert( "FirstName", new int(Qtopia::FirstName) ); 584 dict.insert( "FirstName", new int(Qtopia::FirstName) );
583 dict.insert( "MiddleName", new int(Qtopia::MiddleName) ); 585 dict.insert( "MiddleName", new int(Qtopia::MiddleName) );
584 dict.insert( "LastName", new int(Qtopia::LastName) ); 586 dict.insert( "LastName", new int(Qtopia::LastName) );
585 dict.insert( "Suffix", new int(Qtopia::Suffix) ); 587 dict.insert( "Suffix", new int(Qtopia::Suffix) );
586 dict.insert( "FileAs", new int(Qtopia::FileAs) ); 588 dict.insert( "FileAs", new int(Qtopia::FileAs) );
587 dict.insert( "Categories", new int(Qtopia::AddressCategory) ); 589 dict.insert( "Categories", new int(Qtopia::AddressCategory) );
588 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) ); 590 dict.insert( "DefaultEmail", new int(Qtopia::DefaultEmail) );
589 dict.insert( "Emails", new int(Qtopia::Emails) ); 591 dict.insert( "Emails", new int(Qtopia::Emails) );
590 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) ); 592 dict.insert( "HomeStreet", new int(Qtopia::HomeStreet) );
591 dict.insert( "HomeCity", new int(Qtopia::HomeCity) ); 593 dict.insert( "HomeCity", new int(Qtopia::HomeCity) );
592 dict.insert( "HomeState", new int(Qtopia::HomeState) ); 594 dict.insert( "HomeState", new int(Qtopia::HomeState) );
593 dict.insert( "HomeZip", new int(Qtopia::HomeZip) ); 595 dict.insert( "HomeZip", new int(Qtopia::HomeZip) );
594 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) ); 596 dict.insert( "HomeCountry", new int(Qtopia::HomeCountry) );
595 dict.insert( "HomePhone", new int(Qtopia::HomePhone) ); 597 dict.insert( "HomePhone", new int(Qtopia::HomePhone) );
596 dict.insert( "HomeFax", new int(Qtopia::HomeFax) ); 598 dict.insert( "HomeFax", new int(Qtopia::HomeFax) );
597 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) ); 599 dict.insert( "HomeMobile", new int(Qtopia::HomeMobile) );
598 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) ); 600 dict.insert( "HomeWebPage", new int(Qtopia::HomeWebPage) );
599 dict.insert( "Company", new int(Qtopia::Company) ); 601 dict.insert( "Company", new int(Qtopia::Company) );
600 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) ); 602 dict.insert( "BusinessStreet", new int(Qtopia::BusinessStreet) );
601 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) ); 603 dict.insert( "BusinessCity", new int(Qtopia::BusinessCity) );
602 dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); 604 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
603 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); 605 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
604 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); 606 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
605 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); 607 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
606 dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); 608 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
607 dict.insert( "Department", new int(Qtopia::Department) ); 609 dict.insert( "Department", new int(Qtopia::Department) );
608 dict.insert( "Office", new int(Qtopia::Office) ); 610 dict.insert( "Office", new int(Qtopia::Office) );
609 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); 611 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
610 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) ); 612 dict.insert( "BusinessFax", new int(Qtopia::BusinessFax) );
611 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) ); 613 dict.insert( "BusinessMobile", new int(Qtopia::BusinessMobile) );
612 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) ); 614 dict.insert( "BusinessPager", new int(Qtopia::BusinessPager) );
613 dict.insert( "Profession", new int(Qtopia::Profession) ); 615 dict.insert( "Profession", new int(Qtopia::Profession) );
614 dict.insert( "Assistant", new int(Qtopia::Assistant) ); 616 dict.insert( "Assistant", new int(Qtopia::Assistant) );
615 dict.insert( "Manager", new int(Qtopia::Manager) ); 617 dict.insert( "Manager", new int(Qtopia::Manager) );
616 dict.insert( "Spouse", new int(Qtopia::Spouse) ); 618 dict.insert( "Spouse", new int(Qtopia::Spouse) );
617 dict.insert( "Children", new int(Qtopia::Children) ); 619 dict.insert( "Children", new int(Qtopia::Children) );
618 dict.insert( "Gender", new int(Qtopia::Gender) ); 620 dict.insert( "Gender", new int(Qtopia::Gender) );
619 dict.insert( "Birthday", new int(Qtopia::Birthday) ); 621 dict.insert( "Birthday", new int(Qtopia::Birthday) );
620 dict.insert( "Anniversary", new int(Qtopia::Anniversary) ); 622 dict.insert( "Anniversary", new int(Qtopia::Anniversary) );
621 dict.insert( "Nickname", new int(Qtopia::Nickname) ); 623 dict.insert( "Nickname", new int(Qtopia::Nickname) );
622 dict.insert( "Notes", new int(Qtopia::Notes) ); 624 dict.insert( "Notes", new int(Qtopia::Notes) );
623 dict.insert( "action", new int(JOURNALACTION) ); 625 dict.insert( "action", new int(JOURNALACTION) );
624 dict.insert( "actionrow", new int(JOURNALROW) ); 626 dict.insert( "actionrow", new int(JOURNALROW) );
625 627
626 int i = 0; 628 int i = 0;
627 int num = 0; 629 int num = 0;
628 char *point; 630 char *point;
629 while ( (point = strstr( uc+i, "<Contact " ) ) != NULL ) { 631 while ( (point = strstr( uc+i, "<Contact " ) ) != NULL ) {
630 i = point - uc; 632 i = point - uc;
631 // if we are reading the standard file, we just need to 633 // if we are reading the standard file, we just need to
632 // insert info, so just say we'll do an insert... 634 // insert info, so just say we'll do an insert...
633 action = Contact::ACTION_ADD; 635 action = Contact::ACTION_ADD;
634 // new Contact 636 // new Contact
635 Contact *cnt = new Contact; 637 Contact *cnt = new Contact;
636 i += 9; 638 i += 9;
637 while ( 1 ) { 639 while ( 1 ) {
638 while ( i < len && (uc[i] == ' ' || uc[i] == '\n' || uc[i] == '\r') ) 640 while ( i < len && (uc[i] == ' ' || uc[i] == '\n' || uc[i] == '\r') )
639 i++; 641 i++;
640 if ( i >= len-2 || (uc[i] == '/' && uc[i+1] == '>') ) 642 if ( i >= len-2 || (uc[i] == '/' && uc[i+1] == '>') )
641 break; 643 break;
642 // we have another attribute read it. 644 // we have another attribute read it.
643 int j = i; 645 int j = i;
644 while ( j < len && uc[j] != '=' ) 646 while ( j < len && uc[j] != '=' )
645 j++; 647 j++;
646 char *attr = uc+i; 648 char *attr = uc+i;
647 uc[j] = '\0'; 649 uc[j] = '\0';
648 //qDebug("attr=%s", attr.latin1() ); 650 //qDebug("attr=%s", attr.latin1() );
649 i = ++j; // skip = 651 i = ++j; // skip =
650 while ( i < len && uc[i] != '"' ) 652 while ( i < len && uc[i] != '"' )
651 i++; 653 i++;
652 j = ++i; 654 j = ++i;
653 bool haveEnt = FALSE; 655 bool haveEnt = FALSE;
654 bool haveUtf = FALSE; 656 bool haveUtf = FALSE;
655 while ( j < len && uc[j] != '"' ) { 657 while ( j < len && uc[j] != '"' ) {
656 if ( uc[j] == '&' ) 658 if ( uc[j] == '&' )
657 haveEnt = TRUE; 659 haveEnt = TRUE;
658 if ( ((unsigned char)uc[j]) > 0x7f ) 660 if ( ((unsigned char)uc[j]) > 0x7f )
659 haveUtf = TRUE; 661 haveUtf = TRUE;
660 j++; 662 j++;
661 } 663 }
662 664
663 if ( j == i ) { 665 if ( j == i ) {
664 // empty value 666 // empty value
665 i = j + 1; 667 i = j + 1;
666 continue; 668 continue;
667 } 669 }
668 670
669 QString value = haveUtf ? QString::fromUtf8( uc+i, j-i ) 671 QString value = haveUtf ? QString::fromUtf8( uc+i, j-i )
670 : QString::fromLatin1( uc+i, j-i ); 672 : QString::fromLatin1( uc+i, j-i );
671 if ( haveEnt ) 673 if ( haveEnt )
672 value = Qtopia::plainString( value ); 674 value = Qtopia::plainString( value );
673 i = j + 1; 675 i = j + 1;
674 676
675 int *find = dict[ attr ]; 677 int *find = dict[ attr ];
676 if ( !find ) { 678 if ( !find ) {
677 cnt->setCustomField(attr, value); 679 cnt->setCustomField(attr, value);
678 continue; 680 continue;
679 } 681 }
680#if 1 682#if 1
681 switch( *find ) { 683 switch( *find ) {
682 case Qtopia::AddressUid: 684 case Qtopia::AddressUid:
683 cnt->setUid( value.toInt() ); 685 cnt->setUid( value.toInt() );
684 break; 686 break;
685 case Qtopia::AddressCategory: 687 case Qtopia::AddressCategory:
686 cnt->setCategories( Qtopia::Record::idsFromString( value )); 688 cnt->setCategories( Qtopia::Record::idsFromString( value ));
687 break; 689 break;
688 case JOURNALACTION: 690 case JOURNALACTION:
689 action = Contact::journal_action(value.toInt()); 691 action = Contact::journal_action(value.toInt());
690 break; 692 break;
691 case JOURNALROW: 693 case JOURNALROW:
692 journalKey = value.toInt(); 694 journalKey = value.toInt();
693 break; 695 break;
694 696
695 default: 697 default:
696 cnt->insert( *find, value ); 698 cnt->insert( *find, value );
697 break; 699 break;
698 } 700 }
699#endif 701#endif
700 } 702 }
701 703
702 // sadly we can't delay adding of items from the journal to get 704 // sadly we can't delay adding of items from the journal to get
703 // the proper effect, but then, the journal should _never_ be 705 // the proper effect, but then, the journal should _never_ be
704 // that huge, and recovering from a crash is not necessarily 706 // that huge, and recovering from a crash is not necessarily
705 // a *fast* thing. 707 // a *fast* thing.
706 switch ( action ) { 708 switch ( action ) {
707 case Contact::ACTION_ADD: 709 case Contact::ACTION_ADD:
708 if ( journalFile ) { 710 if ( journalFile ) {
709 int myrows = numRows(); 711 int myrows = numRows();
710 setNumRows( myrows + 1 ); 712 setNumRows( myrows + 1 );
711 insertIntoTable( *cnt, myrows ); 713 insertIntoTable( *cnt, myrows );
712 delete cnt; 714 delete cnt;
713 } 715 }
714 else 716 else
715 list.append( cnt ); 717 list.append( cnt );
716 break; 718 break;
717 case Contact::ACTION_REMOVE: 719 case Contact::ACTION_REMOVE:
718 // yup, we don't use the entry to remove the object... 720 // yup, we don't use the entry to remove the object...
719 journalFreeRemove( journalKey ); 721 journalFreeRemove( journalKey );
720 delete cnt; 722 delete cnt;
721 break; 723 break;
722 case Contact::ACTION_REPLACE: 724 case Contact::ACTION_REPLACE:
723 journalFreeReplace( *cnt, journalKey ); 725 journalFreeReplace( *cnt, journalKey );
724 delete cnt; 726 delete cnt;
725 break; 727 break;
726 default: 728 default:
727 break; 729 break;
728 } 730 }
729 num++; 731 num++;
730 foundAction = false; 732 foundAction = false;
731 foundKey = false; 733 foundKey = false;
732 // if ( num % 100 == 0 ) { 734 // if ( num % 100 == 0 ) {
733 // qDebug("loading file, num=%d, t=%d", num, t.elapsed() ); 735 // qDebug("loading file, num=%d, t=%d", num, t.elapsed() );
734 // } 736 // }
735 } 737 }
736 if ( list.count() > 0 ) { 738 if ( list.count() > 0 ) {
737 internalAddEntries( list ); 739 internalAddEntries( list );
738 } 740 }
739// qDebug("done loading %d, t=%d", num, t.elapsed() ); 741// qDebug("done loading %d, t=%d", num, t.elapsed() );
740 742
741} 743}
742 744
743void AbTable::realignTable( int row ) 745void AbTable::realignTable( int row )
744{ 746{
745 QTableItem *ti1, 747 QTableItem *ti1,
746 *ti2; 748 *ti2;
747 int totalRows = numRows(); 749 int totalRows = numRows();
748 for ( int curr = row; curr < totalRows - 1; curr++ ) { 750 for ( int curr = row; curr < totalRows - 1; curr++ ) {
749 // the same info from the todo list still applies, but I 751 // the same info from the todo list still applies, but I
750 // don't think it is _too_ bad. 752 // don't think it is _too_ bad.
751 ti1 = item( curr + 1, 0 ); 753 ti1 = item( curr + 1, 0 );
752 ti2 = item( curr + 1, 1 ); 754 ti2 = item( curr + 1, 1 );
753 takeItem( ti1 ); 755 takeItem( ti1 );
754 takeItem( ti2 ); 756 takeItem( ti2 );
755 setItem( curr, 0, ti1 ); 757 setItem( curr, 0, ti1 );
756 setItem( curr, 1, ti2 ); 758 setItem( curr, 1, ti2 );
757 } 759 }
758 setNumRows( totalRows - 1 ); 760 setNumRows( totalRows - 1 );
759 resort(); 761 resort();
760} 762}
761 763
762void AbTable::insertIntoTable( const Contact &cnt, int row ) 764void AbTable::insertIntoTable( const Contact &cnt, int row )
763{ 765{
764 QString strName, 766 QString strName,
765 strContact; 767 strContact;
766 768
767 strName = findContactName( cnt ); 769 strName = findContactName( cnt );
768 strContact = findContactContact( cnt ); 770 strContact = findContactContact( cnt );
769 771
770 AbTableItem *ati; 772 AbTableItem *ati;
771 ati = new AbTableItem( this, QTableItem::Never, strName, strContact); 773 ati = new AbTableItem( this, QTableItem::Never, strName, strContact);
772 contactList.insert( ati, cnt ); 774 contactList.insert( ati, cnt );
773 setItem( row, 0, ati ); 775 setItem( row, 0, ati );
774 ati = new AbTableItem( this, QTableItem::Never, strContact, strName); 776 ati = new AbTableItem( this, QTableItem::Never, strContact, strName);
775 setItem( row, 1, ati ); 777 setItem( row, 1, ati );
776 778
777 //### cannot do this; table only has two columns at this point 779 //### cannot do this; table only has two columns at this point
778 // setItem( row, 2, new AbPickItem( this ) ); 780 // setItem( row, 2, new AbPickItem( this ) );
779 781
780 // resort at some point? 782 // resort at some point?
781} 783}
782 784
783void AbTable::internalAddEntries( QList<Contact> &list ) 785void AbTable::internalAddEntries( QList<Contact> &list )
784{ 786{
785 setUpdatesEnabled( FALSE ); 787 setUpdatesEnabled( FALSE );
786 setNumRows( list.count() ); 788 setNumRows( list.count() );
787 int row = 0; 789 int row = 0;
788 Contact *it; 790 Contact *it;
789 for ( it = list.first(); it; it = list.next() ) 791 for ( it = list.first(); it; it = list.next() )
790 insertIntoTable( *it, row++ ); 792 insertIntoTable( *it, row++ );
791 resort(); 793 resort();
792 setUpdatesEnabled( TRUE ); 794 setUpdatesEnabled( TRUE );
793} 795}
794 796
795 797
796void AbTable::journalFreeReplace( const Contact &cnt, int row ) 798void AbTable::journalFreeReplace( const Contact &cnt, int row )
797{ 799{
798 QString strName, 800 QString strName,
799 strContact; 801 strContact;
800 AbTableItem *ati; 802 AbTableItem *ati = 0l;
801 803
802 strName = findContactName( cnt ); 804 strName = findContactName( cnt );
803 strContact = findContactContact( cnt ); 805 strContact = findContactContact( cnt );
804 ati = static_cast<AbTableItem*>(item(row, 0)); 806 ati = static_cast<AbTableItem*>(item(row, 0));
805 contactList.remove( ati ); 807 if ( ati != 0 ) {
806 ati->setItem( strName, strContact ); 808 contactList.remove( ati );
807 contactList.insert( ati, cnt ); 809 ati->setItem( strName, strContact );
808 810 contactList.insert( ati, cnt );
809 ati = static_cast<AbTableItem*>(item(row, 1)); 811
810 ati->setItem( strContact, strName ); 812 ati = static_cast<AbTableItem*>(item(row, 1));
813 ati->setItem( strContact, strName );
814 }else{
815 int myrows = numRows();
816 setNumRows( myrows + 1 );
817 insertIntoTable( cnt, myrows );
818 // gets deleted when returning
819 }
811} 820}
812 821
813void AbTable::journalFreeRemove( int row ) 822void AbTable::journalFreeRemove( int row )
814{ 823{
815 AbTableItem *ati; 824 AbTableItem *ati;
816 ati = static_cast<AbTableItem*>(item(row, 0)); 825 ati = static_cast<AbTableItem*>(item(row, 0));
817 if ( !ati ) 826 if ( !ati )
818 return; 827 return;
819 contactList.remove( ati ); 828 contactList.remove( ati );
820 realignTable( row ); 829 realignTable( row );
821} 830}
822 831
823#if QT_VERSION <= 230 832#if QT_VERSION <= 230
824#ifndef SINGLE_APP 833#ifndef SINGLE_APP
825void QTable::paintEmptyArea( QPainter *p, int cx, int cy, int cw, int ch ) 834void QTable::paintEmptyArea( QPainter *p, int cx, int cy, int cw, int ch )
826{ 835{
827 // Region of the rect we should draw 836 // Region of the rect we should draw
828 QRegion reg( QRect( cx, cy, cw, ch ) ); 837 QRegion reg( QRect( cx, cy, cw, ch ) );
829 // Subtract the table from it 838 // Subtract the table from it
830 reg = reg.subtract( QRect( QPoint( 0, 0 ), tableSize() ) ); 839 reg = reg.subtract( QRect( QPoint( 0, 0 ), tableSize() ) );
831 // And draw the rectangles (transformed as needed) 840 // And draw the rectangles (transformed as needed)
832 QArray<QRect> r = reg.rects(); 841 QArray<QRect> r = reg.rects();
833 for (unsigned int i=0; i<r.count(); i++) 842 for (unsigned int i=0; i<r.count(); i++)
834 p->fillRect( r[i], colorGroup().brush( QColorGroup::Base ) ); 843 p->fillRect( r[i], colorGroup().brush( QColorGroup::Base ) );
835} 844}
836#endif 845#endif
837#endif 846#endif
838 847
839 848
840// int AbTable::rowHeight( int ) const 849// int AbTable::rowHeight( int ) const
841// { 850// {
842// return 18; 851// return 18;
843// } 852// }
844 853
845// int AbTable::rowPos( int row ) const 854// int AbTable::rowPos( int row ) const
846// { 855// {
847// return 18*row; 856// return 18*row;
848// } 857// }
849 858
850// int AbTable::rowAt( int pos ) const 859// int AbTable::rowAt( int pos ) const
851// { 860// {
852// return QMIN( pos/18, numRows()-1 ); 861// return QMIN( pos/18, numRows()-1 );
853// } 862// }
854 863
855void AbTable::slotDoFind( const QString &findString, bool caseSensitive, 864void AbTable::slotDoFind( const QString &findString, bool caseSensitive,
856 bool backwards, int category ) 865 bool backwards, int category )
857{ 866{
858 if ( currFindRow < -1 ) 867 if ( currFindRow < -1 )
859 currFindRow = currentRow() - 1; 868 currFindRow = currentRow() - 1;
860 clearSelection( TRUE ); 869 clearSelection( TRUE );
861 int rows, 870 int rows,
862 row; 871 row;
863 AbTableItem *ati; 872 AbTableItem *ati;
864 QRegExp r( findString ); 873 QRegExp r( findString );
865 r.setCaseSensitive( caseSensitive ); 874 r.setCaseSensitive( caseSensitive );
866 rows = numRows(); 875 rows = numRows();
867 static bool wrapAround = true; 876 static bool wrapAround = true;
868 877
869 if ( !backwards ) { 878 if ( !backwards ) {
870 for ( row = currFindRow + 1; row < rows; row++ ) { 879 for ( row = currFindRow + 1; row < rows; row++ ) {
871 ati = static_cast<AbTableItem*>( item(row, 0) ); 880 ati = static_cast<AbTableItem*>( item(row, 0) );
872 if ( contactCompare( contactList[ati], r, category ) ) 881 if ( contactCompare( contactList[ati], r, category ) )
873 break; 882 break;
874 883
875 } 884 }
876 } else { 885 } else {
877 for ( row = currFindRow - 1; row > -1; row-- ) { 886 for ( row = currFindRow - 1; row > -1; row-- ) {
878 ati = static_cast<AbTableItem*>( item(row, 0) ); 887 ati = static_cast<AbTableItem*>( item(row, 0) );
879 if ( contactCompare( contactList[ati], r, category ) ) 888 if ( contactCompare( contactList[ati], r, category ) )
880 break; 889 break;
881 } 890 }
882 } 891 }
883 if ( row >= rows || row < 0 ) { 892 if ( row >= rows || row < 0 ) {
884 if ( row < 0 ) 893 if ( row < 0 )
885 currFindRow = rows; 894 currFindRow = rows;
886 else 895 else
887 currFindRow = -1; 896 currFindRow = -1;
888 897
889 if ( wrapAround ) 898 if ( wrapAround )
890 emit signalWrapAround(); 899 emit signalWrapAround();
891 else 900 else
892 emit signalNotFound(); 901 emit signalNotFound();
893 902
894 wrapAround = !wrapAround; 903 wrapAround = !wrapAround;
895 } else { 904 } else {
896 currFindRow = row; 905 currFindRow = row;
897 QTableSelection foundSelection; 906 QTableSelection foundSelection;
898 foundSelection.init( currFindRow, 0 ); 907 foundSelection.init( currFindRow, 0 );
899 foundSelection.expandTo( currFindRow, numCols() - 1 ); 908 foundSelection.expandTo( currFindRow, numCols() - 1 );
900 addSelection( foundSelection ); 909 addSelection( foundSelection );
901 setCurrentCell( currFindRow, numCols() - 1 ); 910 setCurrentCell( currFindRow, numCols() - 1 );
902 wrapAround = true; 911 wrapAround = true;
903 } 912 }
904} 913}
905 914
906static bool contactCompare( const Contact &cnt, const QRegExp &r, int category ) 915static bool contactCompare( const Contact &cnt, const QRegExp &r, int category )
907{ 916{
908 bool returnMe; 917 bool returnMe;
909 QArray<int> cats; 918 QArray<int> cats;
910 cats = cnt.categories(); 919 cats = cnt.categories();
911 920
912 returnMe = false; 921 returnMe = false;
913 if ( (category == -1 && cats.count() == 0) || category == -2 ) 922 if ( (category == -1 && cats.count() == 0) || category == -2 )
914 returnMe = cnt.match( r ); 923 returnMe = cnt.match( r );
915 else { 924 else {
916 int i; 925 int i;
917 for ( i = 0; i < int(cats.count()); i++ ) { 926 for ( i = 0; i < int(cats.count()); i++ ) {
918 if ( cats[i] == category ) { 927 if ( cats[i] == category ) {
919 returnMe = cnt.match( r ); 928 returnMe = cnt.match( r );
920 break; 929 break;
921 } 930 }
922 } 931 }
923 } 932 }
924 return returnMe; 933 return returnMe;
925} 934}
926 935
927void AbTable::fitColumns() 936void AbTable::fitColumns()
928{ 937{
929 int contentsWidth = visibleWidth(); 938 int contentsWidth = visibleWidth();
930 int n = numCols(); 939 int n = numCols();
931 int pw = n == 3 ? columnWidth(2) : 0; 940 int pw = n == 3 ? columnWidth(2) : 0;
932 setColumnWidth( 0, contentsWidth - contentsWidth / 2 ); 941 setColumnWidth( 0, contentsWidth - contentsWidth / 2 );
933 setColumnWidth( 1, contentsWidth / 2 - pw ); 942 setColumnWidth( 1, contentsWidth / 2 - pw );
934} 943}
935 944
936void AbTable::show() 945void AbTable::show()
937{ 946{
938 fitColumns(); 947 fitColumns();
939 QTable::show(); 948 QTable::show();
940} 949}
941 950
942void AbTable::setChoiceNames( const QStringList& list) 951void AbTable::setChoiceNames( const QStringList& list)
943{ 952{
944 choicenames = list; 953 choicenames = list;
945 if ( choicenames.isEmpty() ) { 954 if ( choicenames.isEmpty() ) {
946 // hide pick column 955 // hide pick column
947 setNumCols( 2 ); 956 setNumCols( 2 );
948 } else { 957 } else {
949 // show pick column 958 // show pick column
950 setNumCols( 3 ); 959 setNumCols( 3 );
951 setColumnWidth( 2, fontMetrics().width(tr( "Pick" ))+8 ); 960 setColumnWidth( 2, fontMetrics().width(tr( "Pick" ))+8 );
952 horizontalHeader()->setLabel( 2, tr( "Pick" )); 961 horizontalHeader()->setLabel( 2, tr( "Pick" ));
953 } 962 }
954 fitColumns(); 963 fitColumns();
955} 964}
956 965
957void AbTable::itemClicked(int,int col) 966void AbTable::itemClicked(int,int col)
958{ 967{
959 if ( col == 2 ) { 968 if ( col == 2 ) {
960 return; 969 return;
961 } else { 970 } else {
962 emit details(); 971 emit details();
963 } 972 }
964} 973}
965 974
966QStringList AbTable::choiceNames() const 975QStringList AbTable::choiceNames() const
967{ 976{
968 return choicenames; 977 return choicenames;
969} 978}
970 979
971void AbTable::setChoiceSelection(int /*index*/, const QStringList& /*list*/) 980void AbTable::setChoiceSelection(int /*index*/, const QStringList& /*list*/)
972{ 981{
973 /* ###### 982 /* ######
974 983
975 QString selname = choicenames.at(index); 984 QString selname = choicenames.at(index);
976 for (each row) { 985 for (each row) {
977 Contact *c = contactForRow(row); 986 Contact *c = contactForRow(row);
978 if ( list.contains(c->email) ) { 987 if ( list.contains(c->email) ) {
979 list.remove(c->email); 988 list.remove(c->email);
980 setText(row, 2, selname); 989 setText(row, 2, selname);
981 } 990 }
982 } 991 }
983 for (remaining list items) { 992 for (remaining list items) {
984 Contact *c = new contact(item); 993 Contact *c = new contact(item);
985 setText(newrow, 2, selname); 994 setText(newrow, 2, selname);
986 } 995 }
987 996
988 */ 997 */
989} 998}
990 999
991QStringList AbTable::choiceSelection(int /*index*/) const 1000QStringList AbTable::choiceSelection(int /*index*/) const
992{ 1001{
993 QStringList r; 1002 QStringList r;
994 /* ###### 1003 /* ######
995 1004
996 QString selname = choicenames.at(index); 1005 QString selname = choicenames.at(index);
997 for (each row) { 1006 for (each row) {
998 Contact *c = contactForRow(row); 1007 Contact *c = contactForRow(row);
999 if ( text(row,2) == selname ) { 1008 if ( text(row,2) == selname ) {
1000 r.append(c->email); 1009 r.append(c->email);
1001 } 1010 }
1002 } 1011 }
1003 1012
1004 */ 1013 */
1005 return r; 1014 return r;
1006} 1015}
1007 1016
1008void AbTable::setShowCategory( const QString &c ) 1017void AbTable::setShowCategory( const QString &c )
1009{ 1018{
1010 showCat = c; 1019 showCat = c;
1011 updateVisible(); 1020 updateVisible();
1012} 1021}
1013 1022
1014void AbTable::setShowByLetter( char c ) 1023void AbTable::setShowByLetter( char c )
1015{ 1024{
1016 showChar = tolower(c); 1025 showChar = tolower(c);
1017 updateVisible(); 1026 updateVisible();
1018} 1027}
1019 1028
1020QString AbTable::showCategory() const 1029QString AbTable::showCategory() const
1021{ 1030{
1022 return showCat; 1031 return showCat;
1023} 1032}
1024 1033
1025 1034
1026QStringList AbTable::categories() 1035QStringList AbTable::categories()
1027{ 1036{
1028 mCat.load( categoryFileName() ); 1037 mCat.load( categoryFileName() );
1029 QStringList categoryList = mCat.labels( "Contacts" ); 1038 QStringList categoryList = mCat.labels( "Contacts" );
1030 return categoryList; 1039 return categoryList;
1031} 1040}
1032 1041
1033void AbTable::updateVisible() 1042void AbTable::updateVisible()
1034{ 1043{
1035 int visible, 1044 int visible,
1036 totalRows, 1045 totalRows,
1037 id, 1046 id,
1038 totalCats, 1047 totalCats,
1039 it, 1048 it,
1040 row; 1049 row;
1041 bool hide; 1050 bool hide;
1042 AbTableItem *ati; 1051 AbTableItem *ati;
1043 Contact *cnt; 1052 Contact *cnt;
1044 QString fileAsName; 1053 QString fileAsName;
1045 QString tmpStr; 1054 QString tmpStr;
1046 visible = 0; 1055 visible = 0;
1047 1056
1048 setPaintingEnabled( FALSE ); 1057 setPaintingEnabled( FALSE );
1049 1058
1050 totalRows = numRows(); 1059 totalRows = numRows();
1051 id = mCat.id( "Contacts", showCat ); 1060 id = mCat.id( "Contacts", showCat );
1052 QArray<int> cats; 1061 QArray<int> cats;
1053 for ( row = 0; row < totalRows; row++ ) { 1062 for ( row = 0; row < totalRows; row++ ) {
1054 ati = static_cast<AbTableItem*>( item(row, 0) ); 1063 ati = static_cast<AbTableItem*>( item(row, 0) );
1055 cnt = &contactList[ati]; 1064 cnt = &contactList[ati];
1056 cats = cnt->categories(); 1065 cats = cnt->categories();
1057 fileAsName = cnt->fileAs(); 1066 fileAsName = cnt->fileAs();
1058 hide = false; 1067 hide = false;
1059 if ( !showCat.isEmpty() ) { 1068 if ( !showCat.isEmpty() ) {
1060 if ( showCat == tr( "Unfiled" ) ) { 1069 if ( showCat == tr( "Unfiled" ) ) {
1061 if ( cats.count() > 0 ) 1070 if ( cats.count() > 0 )
1062 hide = true; 1071 hide = true;
1063 } else { 1072 } else {
1064 // do some comparing 1073 // do some comparing
1065 if ( !hide ) { 1074 if ( !hide ) {
1066 hide = true; 1075 hide = true;
1067 totalCats = int(cats.count()); 1076 totalCats = int(cats.count());
1068 for ( it = 0; it < totalCats; it++ ) { 1077 for ( it = 0; it < totalCats; it++ ) {
1069 if ( cats[it] == id ) { 1078 if ( cats[it] == id ) {
1070 hide = false; 1079 hide = false;
1071 break; 1080 break;
1072 } 1081 }
1073 } 1082 }
1074 } 1083 }
1075 } 1084 }
1076 } 1085 }
1077 if ( showChar != '\0' ) { 1086 if ( showChar != '\0' ) {
1078 tmpStr = fileAsName.left(1); 1087 tmpStr = fileAsName.left(1);
1079 tmpStr = tmpStr.lower(); 1088 tmpStr = tmpStr.lower();
1080 if ( tmpStr != QString(QChar(showChar)) && showChar != '#' ) { 1089 if ( tmpStr != QString(QChar(showChar)) && showChar != '#' ) {
1081 hide = true; 1090 hide = true;
1082 } 1091 }
1083 if ( showChar == '#' ) { 1092 if ( showChar == '#' ) {
1084 if (tmpStr == "a") 1093 if (tmpStr == "a")
1085 hide = true; 1094 hide = true;
1086 1095
1087 if (tmpStr == "b") 1096 if (tmpStr == "b")
1088 hide = true; 1097 hide = true;
1089 1098
1090 if (tmpStr == "c") 1099 if (tmpStr == "c")
1091 hide = true; 1100 hide = true;
1092 1101
1093 if (tmpStr == "d") 1102 if (tmpStr == "d")
1094 hide = true; 1103 hide = true;
1095 1104
1096 if (tmpStr == "e") 1105 if (tmpStr == "e")
1097 hide = true; 1106 hide = true;
1098 1107
1099 if (tmpStr == "f") 1108 if (tmpStr == "f")
1100 hide = true; 1109 hide = true;
1101 1110
1102 if (tmpStr == "g") 1111 if (tmpStr == "g")
1103 hide = true; 1112 hide = true;
1104 1113
1105 if (tmpStr == "h") 1114 if (tmpStr == "h")
1106 hide = true; 1115 hide = true;
1107 1116
1108 if (tmpStr == "i") 1117 if (tmpStr == "i")
1109 hide = true; 1118 hide = true;
1110 1119
1111 if (tmpStr == "j") 1120 if (tmpStr == "j")
1112 hide = true; 1121 hide = true;
1113 1122
1114 if (tmpStr == "k") 1123 if (tmpStr == "k")
1115 hide = true; 1124 hide = true;
1116 1125
1117 if (tmpStr == "l") 1126 if (tmpStr == "l")
1118 hide = true; 1127 hide = true;
1119 1128
1120 if (tmpStr == "m") 1129 if (tmpStr == "m")
1121 hide = true; 1130 hide = true;
1122 1131
1123 if (tmpStr == "n") 1132 if (tmpStr == "n")
1124 hide = true; 1133 hide = true;
1125 1134
1126 if (tmpStr == "o") 1135 if (tmpStr == "o")
1127 hide = true; 1136 hide = true;
1128 1137
1129 if (tmpStr == "p") 1138 if (tmpStr == "p")
1130 hide = true; 1139 hide = true;
1131 1140
1132 if (tmpStr == "q") 1141 if (tmpStr == "q")
1133 hide = true; 1142 hide = true;
1134 1143
1135 if (tmpStr == "r") 1144 if (tmpStr == "r")
1136 hide = true; 1145 hide = true;
1137 1146
1138 if (tmpStr == "s") 1147 if (tmpStr == "s")
1139 hide = true; 1148 hide = true;
1140 1149
1141 if (tmpStr == "t") 1150 if (tmpStr == "t")
1142 hide = true; 1151 hide = true;
1143 1152
1144 if (tmpStr == "u") 1153 if (tmpStr == "u")
1145 hide = true; 1154 hide = true;
1146 1155
1147 if (tmpStr == "v") 1156 if (tmpStr == "v")
1148 hide = true; 1157 hide = true;
1149 1158
1150 if (tmpStr == "w") 1159 if (tmpStr == "w")
1151 hide = true; 1160 hide = true;
1152 1161
1153 if (tmpStr == "x") 1162 if (tmpStr == "x")
1154 hide = true; 1163 hide = true;
1155 1164
1156 if (tmpStr == "y") 1165 if (tmpStr == "y")
1157 hide = true; 1166 hide = true;
1158 1167
1159 if (tmpStr == "z") 1168 if (tmpStr == "z")
1160 hide = true; 1169 hide = true;
1161 } 1170 }
1162 1171
1163 } 1172 }
1164 if ( hide ) { 1173 if ( hide ) {
1165 if ( currentRow() == row ) 1174 if ( currentRow() == row )
1166 setCurrentCell( -1, 0 ); 1175 setCurrentCell( -1, 0 );
1167 if ( rowHeight(row) > 0 ) 1176 if ( rowHeight(row) > 0 )
1168 hideRow( row ); 1177 hideRow( row );
1169 } else { 1178 } else {
1170 if ( rowHeight(row) == 0 ) { 1179 if ( rowHeight(row) == 0 ) {
1171 showRow( row ); 1180 showRow( row );
1172 adjustRow( row ); 1181 adjustRow( row );
1173 } 1182 }
1174 visible++; 1183 visible++;
1175 } 1184 }
1176 } 1185 }
1177 if ( !visible ) 1186 if ( !visible )
1178 setCurrentCell( -1, 0 ); 1187 setCurrentCell( -1, 0 );
1179 1188
1180 setPaintingEnabled( TRUE ); 1189 setPaintingEnabled( TRUE );
1181} 1190}
1182 1191
1183 1192
1184void AbTable::setPaintingEnabled( bool e ) 1193void AbTable::setPaintingEnabled( bool e )
1185{ 1194{
1186 if ( e != enablePainting ) { 1195 if ( e != enablePainting ) {
1187 if ( !enablePainting ) { 1196 if ( !enablePainting ) {
1188 enablePainting = true; 1197 enablePainting = true;
1189 rowHeightChanged( 0 ); 1198 rowHeightChanged( 0 );
1190 viewport()->update(); 1199 viewport()->update();
1191 } else { 1200 } else {
1192 enablePainting = false; 1201 enablePainting = false;
1193 } 1202 }
1194 } 1203 }
1195} 1204}
1196 1205
1197void AbTable::rowHeightChanged( int row ) 1206void AbTable::rowHeightChanged( int row )
1198{ 1207{
1199 if ( enablePainting ) 1208 if ( enablePainting )
1200 QTable::rowHeightChanged( row ); 1209 QTable::rowHeightChanged( row );
1201} 1210}